├── project
├── build.properties
├── build.sbt
└── Build.scala
├── samples
└── play2
│ └── todolist
│ ├── public
│ ├── stylesheets
│ │ └── main.css
│ ├── images
│ │ └── favicon.png
│ └── swagger-ui
│ │ ├── javascripts
│ │ ├── jquery.slideto.min.js
│ │ ├── jquery.wiggle.min.js
│ │ ├── swagger-service-sample.js
│ │ ├── jquery.ba-bbq.min.js
│ │ ├── doc.js
│ │ ├── underscore-min.js
│ │ ├── swagger-ui.js
│ │ ├── spine.js
│ │ ├── swagger-service.js
│ │ ├── jquery.tmpl.js
│ │ └── chosen.jquery.js
│ │ ├── index.html
│ │ └── stylesheets
│ │ └── screen.css
│ ├── project
│ ├── build.properties
│ ├── plugins.sbt
│ └── Build.scala
│ ├── .gitignore
│ ├── app
│ ├── api
│ │ └── sorting
│ │ │ └── OrderDirection.scala
│ ├── db
│ │ └── TodoSchema.scala
│ ├── util
│ │ └── binding
│ │ │ ├── binders.scala
│ │ │ └── EnumerationBindable.scala
│ ├── models
│ │ ├── formats.scala
│ │ └── Todo.scala
│ ├── Global.scala
│ └── controllers
│ │ ├── Swagger.scala
│ │ └── Todos.scala
│ └── conf
│ ├── routes
│ └── application.conf
├── .gitignore
├── core
└── src
│ ├── main
│ └── scala
│ │ └── net
│ │ └── eamelink
│ │ └── swaggerkit
│ │ ├── SchemaBuilder.scala
│ │ └── domain.scala
│ └── test
│ └── scala
│ └── net
│ └── eamelink
│ └── swaggerkit
│ └── ModelSpec.scala
├── README.textile
└── play2
└── src
├── test
└── scala
│ └── net
│ └── eamelink
│ └── swaggerkit
│ └── play2
│ └── WritersSpec.scala
└── main
└── scala
└── net
└── eamelink
└── swaggerkit
└── play2
└── Writers.scala
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.5
2 |
--------------------------------------------------------------------------------
/samples/play2/todolist/public/stylesheets/main.css:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/project/build.sbt:
--------------------------------------------------------------------------------
1 | scalacOptions ++= Seq("-feature", "-deprecation")
2 |
--------------------------------------------------------------------------------
/samples/play2/todolist/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=0.13.5
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | .project
3 | .classpath
4 | .settings
5 | .cache
6 |
--------------------------------------------------------------------------------
/samples/play2/todolist/.gitignore:
--------------------------------------------------------------------------------
1 | logs
2 | project/project
3 | project/target
4 | target
5 | tmp
6 | .history
7 | dist
--------------------------------------------------------------------------------
/samples/play2/todolist/public/images/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/eamelink/swaggerkit/HEAD/samples/play2/todolist/public/images/favicon.png
--------------------------------------------------------------------------------
/samples/play2/todolist/app/api/sorting/OrderDirection.scala:
--------------------------------------------------------------------------------
1 | package api.sorting
2 |
3 | object OrderDirection extends Enumeration {
4 | val asc = Value("asc")
5 | val desc = Value("desc")
6 | }
7 |
--------------------------------------------------------------------------------
/core/src/main/scala/net/eamelink/swaggerkit/SchemaBuilder.scala:
--------------------------------------------------------------------------------
1 | package net.eamelink.swaggerkit
2 |
3 | /**
4 | * Trait with methods for building Schemas
5 | */
6 | trait SchemaBuilder {
7 | implicit def typeToProperty(st: Type): Property = Property(st)
8 | }
--------------------------------------------------------------------------------
/samples/play2/todolist/app/db/TodoSchema.scala:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import org.squeryl.PrimitiveTypeMode._
4 | import org.squeryl.Schema
5 | import models.Todo
6 |
7 | object TodoSchema extends Schema {
8 | val todosTable = table[Todo]
9 |
10 | on(todosTable) (t => declare(
11 | t.id is(primaryKey, autoIncremented)
12 | ))
13 | }
--------------------------------------------------------------------------------
/samples/play2/todolist/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | // Comment to get more information during initialization
2 | logLevel := Level.Warn
3 |
4 | // The Typesafe repository
5 | resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
6 |
7 | // Use the Play sbt plugin for Play projects
8 | addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.3.6")
9 |
--------------------------------------------------------------------------------
/samples/play2/todolist/app/util/binding/binders.scala:
--------------------------------------------------------------------------------
1 | package util.binding
2 |
3 | import models.Todo
4 | import api.sorting.OrderDirection
5 |
6 | object binders {
7 | implicit object OrderDirectionBindable extends EnumerationBindable[OrderDirection.Value](OrderDirection)
8 | implicit object TodoOrderBindable extends EnumerationBindable[Todo.Order.Value](Todo.Order)
9 | }
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/jquery.slideto.min.js:
--------------------------------------------------------------------------------
1 | (function(b){b.fn.slideto=function(a){a=b.extend({slide_duration:"slow",highlight_duration:3E3,highlight:true,highlight_color:"#FFFF99"},a);return this.each(function(){obj=b(this);b("body").animate({scrollTop:obj.offset().top},a.slide_duration,function(){a.highlight&&b.ui.version&&obj.effect("highlight",{color:a.highlight_color},a.highlight_duration)})})}})(jQuery);
2 |
--------------------------------------------------------------------------------
/samples/play2/todolist/project/Build.scala:
--------------------------------------------------------------------------------
1 | import sbt._
2 | import Keys._
3 | import PlayProject._
4 |
5 | object ApplicationBuild extends Build {
6 |
7 | val appName = "todolist"
8 | val appVersion = "1.1"
9 |
10 | val appDependencies = Seq(
11 | "org.squeryl" %% "squeryl" % "0.9.5-7"
12 | )
13 |
14 | val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
15 | routesImport ++= Seq("models._", "util.binding.binders._", "api.sorting._")) dependsOn (swaggerkitPlay2)
16 |
17 | lazy val swaggerkitPlay2 = ProjectRef(file("../../.."), "swaggerkit-play2")
18 | }
19 |
--------------------------------------------------------------------------------
/samples/play2/todolist/app/util/binding/EnumerationBindable.scala:
--------------------------------------------------------------------------------
1 | package util.binding
2 |
3 | import play.api.mvc.QueryStringBindable
4 |
5 | class EnumerationBindable[A](enum: Enumeration) extends QueryStringBindable[A] {
6 | override def bind(key: String, params: Map[String, Seq[String]]): Option[Either[String, A]] = {
7 | params.get(key).map {
8 | passedValueSeq => enum.values.find { value =>
9 | value.toString == passedValueSeq.mkString
10 | }.map {
11 | value => Right(value.asInstanceOf[A])
12 | }.getOrElse {
13 | Left("Invalid " + key + ", allowed are one of " + enum.values.mkString(", "))
14 | }
15 | }
16 | }
17 |
18 | override def unbind(key: String, value: A): String = key + "=" + value
19 | }
20 |
21 |
--------------------------------------------------------------------------------
/samples/play2/todolist/app/models/formats.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import play.api.libs.json._
4 | import net.eamelink.swaggerkit._
5 | import net.eamelink.swaggerkit.SimpleTypes._
6 | import org.joda.time.format.ISODateTimeFormat
7 |
8 | object formats {
9 | val dateTimeFormatter = ISODateTimeFormat.dateTime
10 |
11 | implicit object DefaultTodo extends Writes[Todo] with SchemaBuilder {
12 | def writes(todo: Todo): JsValue = JsObject(List(
13 | "id" -> JsNumber(todo.id),
14 | "text" -> JsString(todo.text),
15 | "due" -> JsString(dateTimeFormatter.print(todo.due)),
16 | "done" -> JsBoolean(todo.done)))
17 |
18 | lazy val schema = Schema("Todo") has (
19 | "id" -> Integer,
20 | "text" -> String,
21 | "due" -> String,
22 | "done" -> Boolean)
23 | }
24 |
25 | }
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/jquery.wiggle.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | jQuery Wiggle
3 | Author: WonderGroup, Jordan Thomas
4 | URL: http://labs.wondergroup.com/demos/mini-ui/index.html
5 | License: MIT (http://en.wikipedia.org/wiki/MIT_License)
6 | */
7 |
8 | jQuery.fn.wiggle=function(o){var d={speed:50,wiggles:3,travel:5,callback:null};var o=jQuery.extend(d,o);return this.each(function(){var cache=this;var wrap=jQuery(this).wrap('
').css("position","relative");var calls=0;for(i=1;i<=o.wiggles;i++){jQuery(this).animate({left:"-="+o.travel},o.speed).animate({left:"+="+o.travel*2},o.speed*2).animate({left:"-="+o.travel},o.speed,function(){calls++;if(jQuery(cache).parent().hasClass('wiggle-wrap')){jQuery(cache).parent().replaceWith(cache);}
9 | if(calls==o.wiggles&&jQuery.isFunction(o.callback)){o.callback();}});}});};
10 |
--------------------------------------------------------------------------------
/samples/play2/todolist/conf/routes:
--------------------------------------------------------------------------------
1 | # Routes
2 | # This file defines all application routes (Higher priority routes first)
3 | # ~~~~
4 |
5 | # Home page
6 | GET / controllers.Swagger.ui
7 |
8 | GET /api/todos controllers.Todos.list(search: Option[String], withDone: Option[Boolean], orderBy: Option[Todo.Order.Value], direction: Option[OrderDirection.Value])
9 | POST /api/todos controllers.Todos.create
10 | GET /api/todos/:todoId controllers.Todos.show(todoId: Long)
11 | PUT /api/tools/:todoId controllers.Todos.update(todoId: Long)
12 |
13 | # Swagger routes
14 | GET /api/resources.json controllers.Swagger.discover()
15 | GET /api/:id.json controllers.Swagger.resource(id)
16 |
17 | # Map static resources from the /public folder to the /assets URL path
18 | GET /assets/*file controllers.Assets.at(path="/public", file)
19 |
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/swagger-service-sample.js:
--------------------------------------------------------------------------------
1 | jQuery(function($) {
2 | // create and initialize SwaggerService
3 | var swaggerService = new SwaggerService("http://swagr.api.wordnik.com/v4/list.json");
4 | swaggerService.init();
5 |
6 | // Create convenience references to Spine models
7 | var ApiResource = swaggerService.ApiResource();
8 |
9 | // Register a callback for when apis are loaded
10 | ApiResource.bind("refresh", apisLoaded);
11 |
12 | function apisLoaded() {
13 | for(var i = 0; i < ApiResource.all().length; i++) {
14 | var apiResource = ApiResource.all()[i];
15 | log("---------------------------------------------");
16 | log("------------- apiResource : " + apiResource.name);
17 | apiResource.apiList.logAll();
18 | apiResource.modelList.logAll();
19 | }
20 |
21 | if (window.console) console.log("apis loaded");
22 | }
23 |
24 | });
25 |
--------------------------------------------------------------------------------
/samples/play2/todolist/app/Global.scala:
--------------------------------------------------------------------------------
1 | import db.TodoSchema
2 | import play.api.GlobalSettings
3 | import org.squeryl.SessionFactory
4 | import org.squeryl.Session
5 | import org.squeryl.adapters.H2Adapter
6 | import org.squeryl.PrimitiveTypeMode._
7 | import play.api.db.DB
8 | import play.api.Application
9 | import models.Todo
10 | import org.joda.time.DateTime
11 |
12 | object Global extends GlobalSettings {
13 | override def onStart(app: Application) {
14 | SessionFactory.concreteFactory = Some(() =>
15 | Session.create(DB.getConnection()(app), new H2Adapter))
16 |
17 | inTransaction {
18 | TodoSchema.create
19 | }
20 |
21 | // Load sample Todo's
22 | inTransaction {
23 | Todo.insert(Todo("Create sample app for swaggerkit-play2", new DateTime(2012, 5, 5, 14, 9), true))
24 | Todo.insert(Todo("Write more documentation", (new DateTime()).plusHours(4), false))
25 | Todo.insert(Todo("Fix bugs in swaggerkit-play", (new DateTime()).plusDays(1), false))
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/samples/play2/todolist/conf/application.conf:
--------------------------------------------------------------------------------
1 | # This is the main configuration file for the application.
2 | # ~~~~~
3 |
4 | # Secret key
5 | # ~~~~~
6 | # The secret key is used to secure cryptographics functions.
7 | # If you deploy your application to several instances be sure to use the same key!
8 | application.secret="F@O^L@`NaM8:_BUylP>qY=?UXp@ models.formats.DefaultTodo.schema))))
27 |
28 | def ui() = Action {
29 | Redirect("/assets/swagger-ui/index.html")
30 | }
31 |
32 | def discover() = Action { request =>
33 | Ok(Json.toJson(apiDocumentation(request.host)))
34 | }
35 |
36 | def resource(id: String) = Action { request =>
37 | val path = "/%s.{format}" format id
38 | apiDocumentation(request.host).apis.filter(_.path == path).headOption.map { doc =>
39 | Ok(Json.toJson(doc))
40 | }.getOrElse(NotFound)
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/project/Build.scala:
--------------------------------------------------------------------------------
1 | import sbt._
2 | import Keys._
3 |
4 | object Settings {
5 | val name = "swaggerkit"
6 |
7 | val buildSettings = Defaults.coreDefaultSettings ++ Seq(
8 | version := "0.4-SNAPSHOT",
9 | crossScalaVersions := Seq("2.10.4", "2.11.4"),
10 | organization := "net.eamelink"
11 | )
12 | }
13 |
14 | object Resolvers {
15 | val typesafeRepo = "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"
16 | }
17 |
18 | object Dependencies {
19 | lazy val play = "com.typesafe.play" %% "play" % "2.3.6"
20 | lazy val specs = "org.specs2" %% "specs2" % "2.4.11" % "test"
21 | }
22 |
23 | object ApplicationBuild extends Build {
24 | import Settings._
25 | import Resolvers._
26 | import Dependencies._
27 |
28 | lazy val root = Project(name, file("."), settings = buildSettings ++ Seq(
29 | publish := {})
30 | ) aggregate (core, play2)
31 |
32 | lazy val core = Project(name + "-core", file("core"), settings = buildSettings ++ Seq(
33 | publishTo <<= version { (v: String) =>
34 | val path = if(v.trim.endsWith("SNAPSHOT")) "snapshots-public" else "releases-public"
35 | Some(Resolver.url("Lunatech Artifactory", new URL("http://artifactory.lunatech.com/artifactory/%s/" format path)))
36 | },
37 | resolvers := Seq(typesafeRepo),
38 | libraryDependencies ++= Seq(specs)))
39 |
40 | lazy val play2 = Project(name + "-play2", file("play2"), settings = buildSettings ++ Seq(
41 | publishTo <<= version { (v: String) =>
42 | val path = if(v.trim.endsWith("SNAPSHOT")) "snapshots-public" else "releases-public"
43 | Some(Resolver.url("Lunatech Artifactory", new URL("http://artifactory.lunatech.com/artifactory/%s/" format path)))
44 | },
45 | resolvers := Seq(typesafeRepo),
46 | libraryDependencies ++= Seq(play, specs))) dependsOn (core)
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/samples/play2/todolist/app/models/Todo.scala:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import org.squeryl.PrimitiveTypeMode._
4 | import db.TodoSchema
5 | import api.sorting.OrderDirection
6 | import org.squeryl.dsl.ast.ExpressionNode
7 | import org.squeryl.KeyedEntity
8 | import org.joda.time.DateTime
9 |
10 | case class Todo private (
11 | id: Long,
12 | text: String,
13 | due: DateTime,
14 | done: Boolean) extends KeyedEntity[Long]
15 |
16 | object Todo {
17 | import TodoSchema._
18 |
19 | object Order extends Enumeration {
20 | val id = Value("id")
21 | val text = Value("text")
22 | val done = Value("done")
23 |
24 | def buildOrder(todo: Todo, order: Order.Value, od: OrderDirection.Value): ExpressionNode = order match {
25 | // We use backticks to avoid declaring a new variable
26 | case `id` => if (od == OrderDirection.asc) todo.id else todo.id desc
27 | case `text` => if (od == OrderDirection.asc) todo.text else todo.text desc
28 | case `done` => if (od == OrderDirection.asc) todo.id else todo.done desc
29 | }
30 | }
31 |
32 | def apply(text: String, due: DateTime, done: Boolean) = {
33 | new Todo(0, text, due, done)
34 | }
35 | def findById(id: Long): Option[Todo] = inTransaction {
36 | from(todosTable)(t => where(t.id === id) select (t)).headOption
37 | }
38 |
39 | def find(search: Option[String], withDone: Boolean, order: Order.Value, direction: OrderDirection.Value): Seq[Todo] = inTransaction {
40 | val doneFilter = if(withDone) None else Some(false)
41 | from(todosTable)((todo) =>
42 | where(
43 | todo.text like search.? and
44 | todo.done === doneFilter.?
45 | )
46 | select (todo)
47 | orderBy Order.buildOrder(todo, order, direction)).toList
48 | }
49 |
50 | def insert(todo: Todo): Todo = inTransaction {
51 | todosTable.insert(todo.copy())
52 | }
53 |
54 | def delete(id: Long) = inTransaction {
55 | todosTable.delete(id)
56 | }
57 | }
--------------------------------------------------------------------------------
/README.textile:
--------------------------------------------------------------------------------
1 | h1. Swaggerkit
2 |
3 | Swaggerkit is a Scala toolkit that helps you generate the Swagger JSON for your REST API, that allows Swagger-aware tools to automatically discover and use your API, and the Swagger-UI tool to show documentation and a sandbox for your API.
4 |
5 | The Swagger project itself consists of the Swagger Specification and some implementations for servers and clients. There is a Scala implementation, but it relies on JaxRS, which is often not the technology of choice in your Scala REST API.
6 |
7 | Swaggerkit is an alternative implementation that has no dependencies on JaxRS, or any other technology for that matter (except for Scala...). It is basically an set of case classes that form the data structures as described in the Swagger Specification.
8 |
9 | From these case classes, the JSON must be generated. This project currently contains an implementation that uses the Play 2.0 JSON library for that.
10 |
11 | h2. Versions
12 |
13 | Version 0.3 is the latest for Play 2.3.x, built for both Scala 2.10 and 2.11
14 |
15 |
16 | h2. Design considerations
17 |
18 | * There is no magic. There are case classes and a small DSL to help you construct the entire documentation structure, but nothing is inferred or automatically generated.
19 |
20 | h2. Current Limitations
21 |
22 | * JSON only, there is no XML output supported. This limitation can be lifted in the future.
23 | * JSON generation currently depends on Play 2 library, because that's where I use it for. This limitation can be lifted in the future.
24 | * Swagger specification version not very stable. This is mainly build around a Swagger-1.1-SNAPSHOT version of the spec.
25 | * It has been built for Swagger-UI commit b659da04, which is from February.
26 |
27 | h2. Getting started
28 |
29 | There is no Maven repo yet, so you'll have to build this yourself with SBT. Then, there is no real documentation or examples yet, so you're on your own. For now, you can take a look at the sample Play 2 application in samples/play2/todolist and in the SampleApiDocumentation trait in the source (src/test/scala/net/eamelink/swaggerkit/play2/WritersSpec.scala).
30 |
31 | h2. License
32 |
33 | This software is licensed under the Apache 2 license, quoted below.
34 |
35 | Copyright 2012 Erik Bakker (http://eamelink.net).
36 |
37 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
38 |
39 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
40 |
--------------------------------------------------------------------------------
/play2/src/test/scala/net/eamelink/swaggerkit/play2/WritersSpec.scala:
--------------------------------------------------------------------------------
1 | package net.eamelink.swaggerkit.play2
2 |
3 | import net.eamelink.swaggerkit._
4 | import net.eamelink.swaggerkit.SimpleTypes._
5 | import org.specs2.mutable.Specification
6 | import org.specs2.specification.Scope
7 | import play.api.libs.json._
8 |
9 | class WritersSpec extends Specification with SampleApiDocumentation {
10 | "The JSON output for a resource discovery page" should {
11 |
12 | val json = Writers.ApiDocumentationWriter.writes(apiDoc)
13 |
14 | "contain the base path" in {
15 | (json \ "basePath").as[String] must_== apiDoc.basePath
16 | }
17 |
18 | "contain the swagger version" in {
19 | (json \ "swaggerVersion").as[String] must_== apiDoc.swaggerVersion
20 | }
21 |
22 | "contain the api version" in {
23 | (json \ "apiVersion").as[String] must_== apiDoc.apiVersion
24 | }
25 |
26 | "list the proper number of apis" in {
27 | (json \ "apis").as[List[JsValue]] must have size (1)
28 | }
29 |
30 | "list the resource declaration path for a resource" in {
31 | ((json \ "apis")(0) \ "path").as[String] must_== apiDoc.apis(0).path
32 | }
33 |
34 | "list the description for a resource" in {
35 | ((json \ "apis")(0) \ "description").as[String] must_== apiDoc.apis(0).description
36 | }
37 | }
38 | }
39 |
40 | trait SampleApiDocumentation extends Scope with SchemaBuilder {
41 | lazy val apiDoc = ApiDocumentation(
42 | basePath = "http://api.example.com/",
43 | swaggerVersion = "1.1-SNAPSHOT",
44 | apiVersion = "1",
45 | apis = List(ResourceDeclaration(
46 | path = "/albums.{format}",
47 | description = "Operations on Albums",
48 | resourcePath = "/albums",
49 | basePath = "http://api.example.com/",
50 | swaggerVersion = "1.1-SNAPSHOT",
51 | apiVersion = "1",
52 | apis = List(
53 | albumsApi, albumApi),
54 | models = Map("Album" -> albumSchema))))
55 |
56 | lazy val albumsApi = Api("/albums") describedBy "An albums API" withOperations (listAlbums, createAlbum)
57 | lazy val albumApi = Api("/album/{albumId}") describedBy "An album API" withOperations (showAlbum, updateAlbum, deleteAlbum)
58 |
59 | lazy val listAlbums = Operation("listAlbums", GET, "List albums") takes (
60 | QueryParam("query", String) is "Filter by name",
61 | QueryParam("orderBy", String) is "The sort field. Defaults to 'id'" withValues ("id", "title")) // TODO: Maybe add sample data where this is populated by an Enumeration?
62 |
63 | lazy val createAlbum = Operation("createAlbum", POST, "Create a new album") takes (
64 | BodyParam(albumSchema))
65 |
66 | lazy val showAlbum = Operation("showAlbum", GET, "Show an album") takes (
67 | PathParam("albumId", String) is "The album id") note
68 | "This is just a sample note"
69 |
70 | lazy val updateAlbum = Operation("updateAlbum", PUT, "Update an album") takes () // TODO
71 |
72 | lazy val deleteAlbum = Operation("deleteAlbum", DELETE, "Delete an album") takes () // TODO
73 |
74 | lazy val albumSchema = Schema("Album") has (
75 | "id" -> Integer,
76 | "title" -> String,
77 | "photos" -> Array(photoSchema))
78 |
79 | lazy val photoSchema = Schema("Photo") has (
80 | "id" -> Integer,
81 | "title" -> String)
82 | }
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/jquery.ba-bbq.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010
3 | * http://benalman.com/projects/jquery-bbq-plugin/
4 | *
5 | * Copyright (c) 2010 "Cowboy" Ben Alman
6 | * Dual licensed under the MIT and GPL licenses.
7 | * http://benalman.com/about/license/
8 | */
9 |
10 | (function($,p){var i,m=Array.prototype.slice,r=decodeURIComponent,a=$.param,c,l,v,b=$.bbq=$.bbq||{},q,u,j,e=$.event.special,d="hashchange",A="querystring",D="fragment",y="elemUrlAttr",g="location",k="href",t="src",x=/^.*\?|#.*$/g,w=/^.*\#/,h,C={};function E(F){return typeof F==="string"}function B(G){var F=m.call(arguments,1);return function(){return G.apply(this,F.concat(m.call(arguments)))}}function n(F){return F.replace(/^[^#]*#?(.*)$/,"$1")}function o(F){return F.replace(/(?:^[^?#]*\?([^#]*).*$)?.*/,"$1")}function f(H,M,F,I,G){var O,L,K,N,J;if(I!==i){K=F.match(H?/^([^#]*)\#?(.*)$/:/^([^#?]*)\??([^#]*)(#?.*)/);J=K[3]||"";if(G===2&&E(I)){L=I.replace(H?w:x,"")}else{N=l(K[2]);I=E(I)?l[H?D:A](I):I;L=G===2?I:G===1?$.extend({},I,N):$.extend({},N,I);L=a(L);if(H){L=L.replace(h,r)}}O=K[1]+(H?"#":L||!K[1]?"?":"")+L+J}else{O=M(F!==i?F:p[g][k])}return O}a[A]=B(f,0,o);a[D]=c=B(f,1,n);c.noEscape=function(G){G=G||"";var F=$.map(G.split(""),encodeURIComponent);h=new RegExp(F.join("|"),"g")};c.noEscape(",/");$.deparam=l=function(I,F){var H={},G={"true":!0,"false":!1,"null":null};$.each(I.replace(/\+/g," ").split("&"),function(L,Q){var K=Q.split("="),P=r(K[0]),J,O=H,M=0,R=P.split("]["),N=R.length-1;if(/\[/.test(R[0])&&/\]$/.test(R[N])){R[N]=R[N].replace(/\]$/,"");R=R.shift().split("[").concat(R);N=R.length-1}else{N=0}if(K.length===2){J=r(K[1]);if(F){J=J&&!isNaN(J)?+J:J==="undefined"?i:G[J]!==i?G[J]:J}if(N){for(;M<=N;M++){P=R[M]===""?O.length:R[M];O=O[P]=M').hide().insertAfter("body")[0].contentWindow;q=function(){return a(n.document[c][l])};o=function(u,s){if(u!==s){var t=n.document;t.open().close();t[c].hash="#"+u}};o(a())}}m.start=function(){if(r){return}var t=a();o||p();(function s(){var v=a(),u=q(t);if(v!==t){o(t=v,u);$(i).trigger(d)}else{if(u!==t){i[c][l]=i[c][l].replace(/#.*/,"")+"#"+u}}r=setTimeout(s,$[d+"Delay"])})()};m.stop=function(){if(!n){r&&clearTimeout(r);r=0}};return m})()})(jQuery,this);
20 |
--------------------------------------------------------------------------------
/core/src/test/scala/net/eamelink/swaggerkit/ModelSpec.scala:
--------------------------------------------------------------------------------
1 | package net.eamelink.swaggerkit
2 |
3 | import SimpleTypes._
4 | import org.specs2.mutable.Specification
5 | import org.specs2.specification.Scope
6 |
7 | class ModelSpec extends Specification {
8 |
9 | "The SchemaBuilder trait" should {
10 | "provide an implicit conversion from Type to Property" in {
11 | object t extends SchemaBuilder {
12 | val p: Property = Number
13 | }
14 | success
15 | }
16 | }
17 |
18 | "A Type" should {
19 | "have a name" in {
20 | val t: Type = Number
21 | t.name
22 | success
23 | }
24 | }
25 |
26 | "SimpleTypes" should {
27 | "contain all primitives from draft-zyp-json-schema-03" in {
28 | val primitives: Seq[Type] = Seq(String, Number, Integer, Boolean, Object, Any)
29 | success
30 | }
31 |
32 | "have an Array Type constructor that takes a Type as parameter" in {
33 | val primitive: Type = Array(String)
34 | success
35 | }
36 | }
37 |
38 | "A Property" should {
39 | "take a description with 'is'" in {
40 | val p = Property(String) is "Real name"
41 | p.description must_== Some("Real name")
42 | }
43 |
44 | "take allowed values with 'allows'" in {
45 | val p = Property(String) allows ("Mr", "Dr", "Mrs", "Prof")
46 | p.allowableValues must beSome
47 | }
48 | }
49 |
50 | "The HttpMethod trait" should {
51 | "be extended by GET, POST, PUT and DELETE" in {
52 | val methods: Seq[HttpMethod] = List(GET, POST, PUT, DELETE)
53 | success
54 | }
55 | }
56 |
57 | "A Parameter" should {
58 | "have a factory QueryParam" in {
59 | QueryParam("foo", Number).paramType must_== "query"
60 | }
61 |
62 | "have a factory PathParam" in {
63 | PathParam("foo", Number).paramType must_== "path"
64 | }
65 |
66 | "have a factory BodyParam" in {
67 | BodyParam(Number).paramType must_== "body"
68 | }
69 |
70 | "take a description with 'is'" in new SampleParam {
71 | (param is "bar").description must beSome.which(_ == "bar")
72 | }
73 |
74 | "have a switch 'isRequired'" in new SampleParam {
75 | (param isRequired).required must_== true
76 | }
77 |
78 | "have a switch 'isOptional'" in new SampleParam {
79 | (param isOptional).required must_== false
80 | }
81 |
82 | "have a switch 'allowsMultiple'" in new SampleParam {
83 | (param allowsMultiple).allowMultiple must_== true
84 | }
85 |
86 | "have a switch 'noMultiple'" in new SampleParam {
87 | (param noMultiple).allowMultiple must_== false
88 | }
89 |
90 | "take a vararg values in 'withValues'" in new SampleParam {
91 | (param withValues ("a", "b", "c")).allowableValues must beSome
92 | }
93 |
94 | "take an enum with values in 'withValues'" in new SampleParam {
95 | object WeekDay extends Enumeration {
96 | type WeekDay = Value
97 | val Mon, Tue, Wed, Thu, Fri, Sat, Sun = Value
98 | }
99 | (param withValues (WeekDay)).allowableValues must beSome
100 | }
101 |
102 | }
103 |
104 | "An Operation" should {
105 | "take a vararg parameters with 'takes'" in new SampleOperation with SampleParam {
106 | (operation takes param).parameters must contain(param)
107 | }
108 |
109 | "take a note with 'note'" in new SampleOperation {
110 | (operation note "foobar").notes must beSome.which(_ == "foobar")
111 | }
112 | }
113 |
114 | "An Api" should {
115 | "take a description with 'describedBy'" in new SampleApi {
116 | (api describedBy "foobar").description must beSome.which(_ == "foobar")
117 | }
118 |
119 | "take a vararg operations in 'withOperations'" in new SampleApi with SampleOperation {
120 | (api withOperations operation).operations must contain(operation)
121 | }
122 | }
123 | }
124 |
125 | trait SampleParam extends Scope {
126 | val param = QueryParam("foo", Number)
127 | }
128 |
129 | trait SampleOperation extends Scope {
130 | val operation = Operation("foo", GET, "bar")
131 | }
132 |
133 | trait SampleApi extends Scope {
134 | val api = Api("foo")
135 | }
--------------------------------------------------------------------------------
/play2/src/main/scala/net/eamelink/swaggerkit/play2/Writers.scala:
--------------------------------------------------------------------------------
1 | package net.eamelink.swaggerkit.play2
2 |
3 | import net.eamelink.swaggerkit._
4 | import play.api.libs.json._
5 | import scala.collection.mutable.ListBuffer
6 |
7 | object Writers {
8 |
9 | implicit object ApiDocumentationWriter extends Writes[ApiDocumentation] {
10 | def writes(rl: ApiDocumentation): JsValue = JsObject(List(
11 | "basePath" -> JsString(rl.basePath),
12 | "swaggerVersion" -> JsString(rl.swaggerVersion),
13 | "apiVersion" -> JsString(rl.apiVersion),
14 | "apis" -> JsArray(rl.apis.map(resourceDeclaration => JsObject(List(
15 | "path" -> JsString(resourceDeclaration.path),
16 | "description" -> JsString(resourceDeclaration.description)))).toList)))
17 | }
18 |
19 | implicit object ResourceDeclarationWriter extends Writes[ResourceDeclaration] {
20 | def writes(ad: ResourceDeclaration): JsValue = JsObject(List(
21 | "resourcePath" -> JsString(ad.resourcePath),
22 | "basePath" -> JsString(ad.basePath),
23 | "apiVersion" -> JsString(ad.apiVersion),
24 | "swaggerVersion" -> JsString(ad.swaggerVersion),
25 | "apis" -> JsArray(ad.apis.map(api => ApiWriter.writes(api))),
26 | "models" -> JsObject(ad.models.map(pair => pair._1 -> SchemaWriter.writes(pair._2)).toList)))
27 | }
28 |
29 | object ParameterWriter extends Writes[Parameter] {
30 |
31 | def writes(param: Parameter): JsValue = {
32 | var properties = new ListBuffer[(String, JsValue)]
33 |
34 | param.name.map(n => properties += "name" -> JsString(n))
35 | param.description.map(d => properties += "description" -> JsString(d))
36 |
37 | // A boolean is represented by type string, and a list of allowable values
38 | param.dataType.name match {
39 | case "boolean" => {
40 | properties += "dataType" -> JsString("string")
41 | properties += booleanValues
42 | }
43 | case _ => {
44 | properties += "dataType" -> JsString(param.dataType.name)
45 | }
46 | }
47 |
48 | properties += "required" -> JsBoolean(param.required)
49 | properties += "allowMultiple" -> JsBoolean(param.allowMultiple)
50 | properties += "paramType" -> JsString(param.paramType)
51 | if (param.allowableValues.isDefined) {
52 | properties += "allowableValues" -> JsObject(List(
53 | "values" -> JsArray(param.allowableValues.get.map(JsString(_)).toList),
54 | "valueType" -> JsString("LIST")))
55 | }
56 | param.valueTypeInternal.map(vti => properties += "valueTypeInternal" -> JsString(vti))
57 |
58 | JsObject(properties)
59 | }
60 |
61 | private val booleanValues = "allowableValues" -> JsObject(List(
62 | "values" -> JsArray(List(JsString("0"), JsString("1"))),
63 | "valueType" -> JsString("LIST")))
64 | }
65 |
66 | object OperationWriter extends Writes[Operation] {
67 | def writes(op: Operation): JsValue = JsObject(List(
68 | "parameters" -> JsArray(op.parameters.map(param => ParameterWriter.writes(param))),
69 | "httpMethod" -> JsString(op.httpMethod.toString),
70 | "notes" -> JsString(op.notes.getOrElse("")),
71 | "responseTypeInternal" -> JsString(op.responseTypeInternal.getOrElse("")),
72 | "nickname" -> JsString(op.nickName),
73 | "responseClass" -> JsString(op.responseClass.getOrElse("")),
74 | "summary" -> JsString(op.summary)))
75 | }
76 |
77 | object ApiWriter extends Writes[Api] {
78 | def writes(api: Api): JsValue = JsObject(List(
79 | "path" -> JsString(api.path),
80 | "description" -> JsString(api.description.getOrElse("")),
81 | "operations" -> JsArray(api.operations.map(op => OperationWriter.writes(op)))))
82 | }
83 |
84 | object PropertyWriter extends Writes[Property] {
85 | def writes(p: Property): JsValue = JsObject(List(
86 | "type" -> JsString(p.typ.name)))
87 | }
88 |
89 | object SchemaWriter extends Writes[Schema] {
90 | def writes(s: Schema): JsValue = JsObject(List(
91 | "properties" -> {
92 | s.properties match {
93 | case None => JsNull
94 | case Some(properties) => JsObject(properties.map(p => p._1 -> PropertyWriter.writes(p._2)).toList)
95 | }
96 | }))
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/samples/play2/todolist/app/controllers/Todos.scala:
--------------------------------------------------------------------------------
1 | package controllers
2 |
3 | import play.api.mvc._
4 | import play.api.libs.json._
5 | import play.api.data.Form
6 | import play.api.data.Form._
7 | import play.api.data.Forms._
8 | import net.eamelink.swaggerkit._
9 | import net.eamelink.swaggerkit.SimpleTypes._
10 | import models.Todo
11 | import models.formats.DefaultTodo
12 | import api.sorting.OrderDirection
13 | import org.joda.time.DateTime
14 |
15 | object Todos extends Controller {
16 | val dateFormat = "yyyy-MM-dd hh:mm";
17 |
18 | lazy val todosApi = Api("/todos") describedBy "A todos API" withOperations (listOperation, createOperation)
19 | lazy val todoApi = Api("/todos/{todoId}") describedBy "A todo API" withOperations (showOperation, updateOperation, deleteOperation)
20 |
21 | lazy val listOperation = Operation("listTodos", GET, "Get a list of todos") takes (
22 | QueryParam("search", String) is "A search query. Searches in the todo text.",
23 | QueryParam("withDone", Boolean) is "Show completed todos as well. Defaults to '0'",
24 | QueryParam("orderBy", String) is "The sort field. Defaults to 'due'" withValues Todo.Order,
25 | QueryParam("direction", String) is "The order direction. Defaults to 'asc'" withValues OrderDirection) note
26 | "This is just a sample note."
27 |
28 | def list(search: Option[String], withDone: Option[Boolean], orderBy: Option[Todo.Order.Value], direction: Option[OrderDirection.Value]) = Action {
29 | Ok(Json.toJson(Todo.find(search.map("%" + _ + "%"), withDone.getOrElse(false), orderBy.getOrElse(Todo.Order.id), direction.getOrElse(OrderDirection.asc))))
30 | }
31 |
32 | val showOperation = Operation("showTodo", GET, "Get a todo") takes (
33 | PathParam("todoId", String) is "The todo id") note
34 | "And this is another sample note."
35 |
36 | def show(todoId: Long) = Action { implicit request =>
37 | Todo.findById(todoId).map { todo =>
38 | Ok(Json.toJson(todo))
39 | }.getOrElse[Result](NotFound)
40 | }
41 |
42 | val createOperation = Operation("createTodo", POST, "Create a todo") takes (
43 | BodyParam(DefaultTodo.schema) is "The Todo item you want to create") note
44 | "This method returns the created todo item, and a Location header pointing to its url."
45 |
46 | def create() = Action { implicit request =>
47 | val createForm = Form(
48 | tuple(
49 | "text" -> text,
50 | "due" -> date(dateFormat),
51 | "done" -> boolean))
52 | createForm.bindFromRequest.fold(
53 | formWithErrors => Forbidden(formWithErrors.errorsAsJson),
54 | value => {
55 | val createdTodo = Todo.insert(
56 | Todo(value._1, new DateTime(value._2.getTime), value._3))
57 | Created(Json.toJson(createdTodo)).withHeaders(
58 | LOCATION -> routes.Todos.show(createdTodo.id).toString())
59 | })
60 | }
61 |
62 | val updateOperation = Operation("updateTodo", PUT, "Update a todo") takes (
63 | PathParam("todoId", String) is "The id of the todo to update",
64 | BodyParam(DefaultTodo.schema)) note
65 | "This operation returns the updated todo item, and a Location header pointing to its url."
66 |
67 | def update(todoId: Long) = Action { implicit request =>
68 |
69 | Todo.findById(todoId).map { existingTodo =>
70 | val updateForm = Form(
71 | tuple(
72 | "text" -> text,
73 | "done" -> boolean,
74 | "due" -> date(dateFormat)))
75 |
76 | val json = request.body.asJson.get.asInstanceOf[JsObject]
77 |
78 | updateForm.bindFromRequest.fold(
79 | formWithErrors => Forbidden(formWithErrors.errorsAsJson),
80 | value => {
81 | val updatedTodo = existingTodo.copy(
82 | text = value._1)
83 | Ok(Json.toJson(updatedTodo)).withHeaders(
84 | LOCATION -> routes.Todos.show(updatedTodo.id).toString())
85 | })
86 | }.getOrElse(NotFound)
87 | }
88 |
89 | lazy val deleteOperation = Operation("deleteTodo", DELETE, "Delete a todo item") takes (
90 | PathParam("todoId", String) is "The id of the todo to delete") note
91 | "This method returns a 204 when successful, a 404 when the todo item was not found."
92 |
93 | def delete(todoId: Long) = Action {
94 | Todo.findById(todoId).map{ todo =>
95 | Todo.delete(todo.id)
96 | NoContent
97 | }.getOrElse(NotFound)
98 | }
99 | }
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/doc.js:
--------------------------------------------------------------------------------
1 | $(function() {
2 |
3 | // Helper function for vertically aligning DOM elements
4 | // http://www.seodenver.com/simple-vertical-align-plugin-for-jquery/
5 | $.fn.vAlign = function() {
6 | return this.each(function(i){
7 | var ah = $(this).height();
8 | var ph = $(this).parent().height();
9 | var mh = (ph - ah) / 2;
10 | $(this).css('margin-top', mh);
11 | });
12 | };
13 |
14 | $.fn.stretchFormtasticInputWidthToParent = function() {
15 | return this.each(function(i){
16 | var p_width = $(this).closest("form").innerWidth();
17 | var p_padding = parseInt($(this).closest("form").css('padding-left') ,10) + parseInt($(this).closest("form").css('padding-right'), 10);
18 | var this_padding = parseInt($(this).css('padding-left'), 10) + parseInt($(this).css('padding-right'), 10);
19 | $(this).css('width', p_width - p_padding - this_padding);
20 | });
21 | };
22 |
23 | $('form.formtastic li.string input, form.formtastic textarea').stretchFormtasticInputWidthToParent();
24 |
25 | // Vertically center these paragraphs
26 | // Parent may need a min-height for this to work..
27 | $('ul.downplayed li div.content p').vAlign();
28 |
29 | // When a sandbox form is submitted..
30 | $("form.sandbox").submit(function(){
31 |
32 | var error_free = true;
33 |
34 | // Cycle through the forms required inputs
35 | $(this).find("input.required").each(function() {
36 |
37 | // Remove any existing error styles from the input
38 | $(this).removeClass('error');
39 |
40 | // Tack the error style on if the input is empty..
41 | if ($(this).val() == '') {
42 | $(this).addClass('error');
43 | $(this).wiggle();
44 | error_free = false;
45 | }
46 |
47 | });
48 |
49 | return error_free;
50 | });
51 |
52 | });
53 |
54 | function clippyCopiedCallback(a) {
55 | $('#api_key_copied').fadeIn().delay(1000).fadeOut();
56 |
57 | // var b = $("#clippy_tooltip_" + a);
58 | // b.length != 0 && (b.attr("title", "copied!").trigger("tipsy.reload"), setTimeout(function() {
59 | // b.attr("title", "copy to clipboard")
60 | // },
61 | // 500))
62 | }
63 |
64 | // Logging function that accounts for browsers that don't have window.console
65 | function log() {
66 | if (window.console) console.log.apply(console,arguments);
67 | }
68 |
69 | var Docs = {
70 |
71 | shebang: function() {
72 |
73 | // If shebang has an operation nickname in it..
74 | // e.g. /docs/#!/words/get_search
75 | var fragments = $.param.fragment().split('/');
76 | fragments.shift(); // get rid of the bang
77 |
78 | switch (fragments.length) {
79 | case 1:
80 | // Expand all operations for the resource and scroll to it
81 | log('shebang resource:' + fragments[0]);
82 | var dom_id = 'resource_' + fragments[0];
83 |
84 | Docs.expandEndpointListForResource(fragments[0]);
85 | $("#"+dom_id).slideto({highlight: false});
86 | break;
87 | case 2:
88 | // Refer to the endpoint DOM element, e.g. #words_get_search
89 | log('shebang endpoint: ' + fragments.join('_'));
90 |
91 | // Expand Resource
92 | Docs.expandEndpointListForResource(fragments[0]);
93 | $("#"+dom_id).slideto({highlight: false});
94 |
95 | // Expand operation
96 | var li_dom_id = fragments.join('_');
97 | var li_content_dom_id = li_dom_id + "_content";
98 |
99 | log("li_dom_id " + li_dom_id);
100 | log("li_content_dom_id " + li_content_dom_id);
101 |
102 | Docs.expandOperation($('#'+li_content_dom_id));
103 | $('#'+li_dom_id).slideto({highlight: false});
104 | break;
105 | }
106 |
107 | },
108 |
109 | toggleEndpointListForResource: function(resource) {
110 | var elem = $('li#resource_' + resource + ' ul.endpoints');
111 | if (elem.is(':visible')) {
112 | Docs.collapseEndpointListForResource(resource);
113 | } else {
114 | Docs.expandEndpointListForResource(resource);
115 | }
116 | },
117 |
118 | // Expand resource
119 | expandEndpointListForResource: function(resource) {
120 | $('#resource_' + resource).addClass('active');
121 |
122 | var elem = $('li#resource_' + resource + ' ul.endpoints');
123 | elem.slideDown();
124 | },
125 |
126 | // Collapse resource and mark as explicitly closed
127 | collapseEndpointListForResource: function(resource) {
128 | $('#resource_' + resource).removeClass('active');
129 |
130 | var elem = $('li#resource_' + resource + ' ul.endpoints');
131 | elem.slideUp();
132 | },
133 |
134 | expandOperationsForResource: function(resource) {
135 | // Make sure the resource container is open..
136 | Docs.expandEndpointListForResource(resource);
137 | $('li#resource_' + resource + ' li.operation div.content').each(function() {
138 | Docs.expandOperation($(this));
139 | });
140 | },
141 |
142 | collapseOperationsForResource: function(resource) {
143 | // Make sure the resource container is open..
144 | Docs.expandEndpointListForResource(resource);
145 | $('li#resource_' + resource + ' li.operation div.content').each(function() {
146 | Docs.collapseOperation($(this));
147 | });
148 | },
149 |
150 | expandOperation: function(elem) {
151 | elem.slideDown();
152 | },
153 |
154 | collapseOperation: function(elem) {
155 | elem.slideUp();
156 | },
157 |
158 | toggleOperationContent: function(dom_id) {
159 | var elem = $('#' + dom_id);
160 | (elem.is(':visible')) ? Docs.collapseOperation(elem) : Docs.expandOperation(elem);
161 | }
162 |
163 | };
164 |
--------------------------------------------------------------------------------
/core/src/main/scala/net/eamelink/swaggerkit/domain.scala:
--------------------------------------------------------------------------------
1 | package net.eamelink.swaggerkit
2 |
3 | /**
4 | * Container for the entire API documentation.
5 | *
6 | * This is a model for the resource discovery page.
7 | */
8 | case class ApiDocumentation(
9 | basePath: String,
10 | swaggerVersion: String,
11 | apiVersion: String,
12 | apis: List[ResourceDeclaration])
13 |
14 | /**
15 | * Resource declaration, lists api's and model's for a given resource.
16 | */
17 | case class ResourceDeclaration(
18 | // Properties shown on the resource discovery page.
19 | path: String,
20 | description: String,
21 |
22 | // Properties shown on the page for the given resource.
23 | resourcePath: String,
24 | basePath: String,
25 | swaggerVersion: String,
26 | apiVersion: String,
27 | apis: List[Api],
28 | models: Map[String, Schema])
29 |
30 | object ResourceDeclaration {
31 | /**
32 | * Resource declaration constructor that finds all models in operations.
33 | */
34 | def apply(path: String, description: String, resourcePath: String, basePath: String, swaggerVersion: String, apiVersion: String, apis: List[Api]): ResourceDeclaration =
35 | ResourceDeclaration(path, description, resourcePath, basePath, swaggerVersion, apiVersion, apis, findModels(apis))
36 |
37 | /**
38 | * Find models that are references by the list of Api.
39 | *
40 | * Currently only looks for parameters, not operation return types.
41 | */
42 | private def findModels(apis: List[Api]): Map[String, Schema] = {
43 | apis.flatMap { api =>
44 | api.operations.flatMap { operation =>
45 | operation.parameters.map(_.dataType).collect {
46 | case schema: Schema => (schema.name -> schema)
47 | }
48 | }
49 | }.toMap
50 | }
51 | }
52 |
53 | /**
54 | * API, collection of operations on the same URL
55 | */
56 | case class Api(
57 | path: String,
58 | description: Option[String] = None,
59 | operations: List[Operation] = Nil) {
60 |
61 | def describedBy(description: String) = copy(description = Some(description))
62 | def withOperations(ops: Operation*) = copy(operations = ops.toList)
63 | }
64 |
65 | /**
66 | * Http operation on a given url
67 | */
68 | case class Operation(
69 | nickName: String,
70 | httpMethod: HttpMethod,
71 | summary: String,
72 | parameters: List[Parameter] = Nil,
73 | notes: Option[String] = None,
74 | responseTypeInternal: Option[String] = None,
75 | responseClass: Option[String] = None) {
76 |
77 | def takes(params: Parameter*) = copy(parameters = params.toList)
78 | def note(note: String) = copy(notes = Some(note))
79 | }
80 |
81 | /**
82 | * Http request parameter
83 | */
84 | case class Parameter(
85 | name: Option[String],
86 | description: Option[String] = None,
87 | dataType: Type,
88 | required: Boolean = false,
89 | valueTypeInternal: Option[String] = None,
90 | allowMultiple: Boolean = false,
91 | allowableValues: Option[Seq[String]] = None,
92 | paramType: String) {
93 |
94 | def is(description: String) = copy(description = Some(description))
95 | def isRequired() = copy(required = true)
96 | def isOptional() = copy(required = false)
97 | def allowsMultiple() = copy(allowMultiple = true)
98 | def noMultiple() = copy(allowMultiple = false)
99 | def withValues(values: String*) = copy(allowableValues = Some(values))
100 | def withValues(enum: Enumeration) = copy(allowableValues = Some(enum.values.map(_.toString).toList))
101 | }
102 |
103 | /**
104 | * Factory for 'query' request parameters
105 | */
106 | object QueryParam {
107 | def apply(name: String, dataType: Type) = Parameter(name = Some(name), dataType = dataType, paramType = "query", allowableValues = None)
108 | }
109 |
110 | /**
111 | * Factory for 'path' request parameters
112 | */
113 | object PathParam {
114 | def apply(name: String, dataType: Type) = Parameter(name = Some(name), dataType = dataType, paramType = "path", required = true, allowableValues = None)
115 | }
116 |
117 | /**
118 | * Factory for 'body' request parameters
119 | */
120 | object BodyParam {
121 | def apply(dataType: Type) = Parameter(None, dataType = dataType, paramType = "body", required = true)
122 | }
123 |
124 | /**
125 | * Http methods: GET, POST etc.
126 | */
127 | sealed trait HttpMethod
128 | case object GET extends HttpMethod
129 | case object POST extends HttpMethod
130 | case object PUT extends HttpMethod
131 | case object DELETE extends HttpMethod
132 |
133 | /**
134 | * A description of a complex type.
135 | */
136 | case class Schema(name: String, properties: Option[Map[String, Property]] = None) extends Type {
137 | def has(props: (String, Property)*) = copy(properties = Some(props.toMap))
138 | }
139 |
140 | /**
141 | * A property of a Schema.
142 | */
143 | case class Property(
144 | typ: Type,
145 | description: Option[String] = None,
146 | allowableValues: Option[Seq[String]] = None) {
147 |
148 | def is(description: String) = copy(description = Some(description))
149 | def allows(vals: String*) = copy(allowableValues = Some(vals.toSeq))
150 | }
151 |
152 | /**
153 | * A property type from a 'model' in the Swagger output.
154 | *
155 | * This can be a Simple type, or a Schema. In Swagger, for a Schema just the name is outputted.
156 | */
157 | trait Type {
158 | def name: String
159 | }
160 |
161 | /**
162 | * Predefined primitives, or "Simple Types" as the spec calls them
163 | *
164 | * @see http://tools.ietf.org/html/draft-zyp-json-schema-03 section 5.1
165 | */
166 | object SimpleTypes {
167 | object String extends Type { val name = "string" }
168 | object Number extends Type { val name = "number" }
169 | object Integer extends Type { val name = "integer" }
170 | object Boolean extends Type { val name = "boolean" }
171 | object Object extends Type { val name = "object" }
172 | object Any extends Type { val name = "any" }
173 | case class Array(innerType: Type) extends Type { def name = "Array[" + innerType.name + "]" }
174 | }
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Swagger API Explorer
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
24 |
27 |
54 |
58 |
111 |
119 |
138 |
148 |
154 |
160 |
161 | Enter the base URL of the API that you wish to explore, or try
162 |
localhost:9000/api
163 |
164 |
165 | Sexy API documentation from
166 | Swagger.
167 |
168 |
169 |
170 |
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/underscore-min.js:
--------------------------------------------------------------------------------
1 | // Underscore.js 1.1.7
2 | // (c) 2011 Jeremy Ashkenas, DocumentCloud Inc.
3 | // Underscore is freely distributable under the MIT license.
4 | // Portions of Underscore are inspired or borrowed from Prototype,
5 | // Oliver Steele's Functional, and John Resig's Micro-Templating.
6 | // For all details and documentation:
7 | // http://documentcloud.github.com/underscore
8 | (function(){var p=this,C=p._,m={},i=Array.prototype,n=Object.prototype,f=i.slice,D=i.unshift,E=n.toString,l=n.hasOwnProperty,s=i.forEach,t=i.map,u=i.reduce,v=i.reduceRight,w=i.filter,x=i.every,y=i.some,o=i.indexOf,z=i.lastIndexOf;n=Array.isArray;var F=Object.keys,q=Function.prototype.bind,b=function(a){return new j(a)};typeof module!=="undefined"&&module.exports?(module.exports=b,b._=b):p._=b;b.VERSION="1.1.7";var h=b.each=b.forEach=function(a,c,b){if(a!=null)if(s&&a.forEach===s)a.forEach(c,b);else if(a.length===
9 | +a.length)for(var e=0,k=a.length;e=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,
13 | c,d){if(!c&&b.isArray(a))return Math.min.apply(Math,a);var e={computed:Infinity};h(a,function(a,b,f){b=c?c.call(d,a,b,f):a;bd?1:0}),"value")};b.groupBy=function(a,b){var d={};h(a,function(a,f){var g=b(a,f);(d[g]||(d[g]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||
14 | (d=b.identity);for(var e=0,f=a.length;e>1;d(a[g])=0})})};b.difference=function(a,c){return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=f.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=
20 | function(a,b){return function(){if(--a<1)return b.apply(this,arguments)}};b.keys=F||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var b=[],d;for(d in a)l.call(a,d)&&(b[b.length]=d);return b};b.values=function(a){return b.map(a,b.identity)};b.functions=b.methods=function(a){var c=[],d;for(d in a)b.isFunction(a[d])&&c.push(d);return c.sort()};b.extend=function(a){h(f.call(arguments,1),function(b){for(var d in b)b[d]!==void 0&&(a[d]=b[d])});return a};b.defaults=function(a){h(f.call(arguments,
21 | 1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,c){if(a===c)return!0;var d=typeof a;if(d!=typeof c)return!1;if(a==c)return!0;if(!a&&c||a&&!c)return!1;if(a._chain)a=a._wrapped;if(c._chain)c=c._wrapped;if(a.isEqual)return a.isEqual(c);if(c.isEqual)return c.isEqual(a);if(b.isDate(a)&&b.isDate(c))return a.getTime()===c.getTime();if(b.isNaN(a)&&b.isNaN(c))return!1;
22 | if(b.isRegExp(a)&&b.isRegExp(c))return a.source===c.source&&a.global===c.global&&a.ignoreCase===c.ignoreCase&&a.multiline===c.multiline;if(d!=="object")return!1;if(a.length&&a.length!==c.length)return!1;d=b.keys(a);var e=b.keys(c);if(d.length!=e.length)return!1;for(var f in a)if(!(f in c)||!b.isEqual(a[f],c[f]))return!1;return!0};b.isEmpty=function(a){if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(l.call(a,c))return!1;return!0};b.isElement=function(a){return!!(a&&a.nodeType==
23 | 1)};b.isArray=n||function(a){return E.call(a)==="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return!(!a||!l.call(a,"callee"))};b.isFunction=function(a){return!(!a||!a.constructor||!a.call||!a.apply)};b.isString=function(a){return!!(a===""||a&&a.charCodeAt&&a.substr)};b.isNumber=function(a){return!!(a===0||a&&a.toExponential&&a.toFixed)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===!0||a===!1};b.isDate=function(a){return!(!a||!a.getTimezoneOffset||
24 | !a.setUTCFullYear)};b.isRegExp=function(a){return!(!a||!a.test||!a.exec||!(a.ignoreCase||a.ignoreCase===!1))};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.noConflict=function(){p._=C;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e/g,interpolate:/<%=([\s\S]+?)%>/g};
25 | b.template=function(a,c){var d=b.templateSettings;d="var __p=[],print=function(){__p.push.apply(__p,arguments);};with(obj||{}){__p.push('"+a.replace(/\\/g,"\\\\").replace(/'/g,"\\'").replace(d.interpolate,function(a,b){return"',"+b.replace(/\\'/g,"'")+",'"}).replace(d.evaluate||null,function(a,b){return"');"+b.replace(/\\'/g,"'").replace(/[\r\n\t]/g," ")+"__p.push('"}).replace(/\r/g,"\\r").replace(/\n/g,"\\n").replace(/\t/g,"\\t")+"');}return __p.join('');";d=new Function("obj",d);return c?d(c):d};
26 | var j=function(a){this._wrapped=a};b.prototype=j.prototype;var r=function(a,c){return c?b(a).chain():a},H=function(a,c){j.prototype[a]=function(){var a=f.call(arguments);D.call(a,this._wrapped);return r(c.apply(b,a),this._chain)}};b.mixin(b);h(["pop","push","reverse","shift","sort","splice","unshift"],function(a){var b=i[a];j.prototype[a]=function(){b.apply(this._wrapped,arguments);return r(this._wrapped,this._chain)}});h(["concat","join","slice"],function(a){var b=i[a];j.prototype[a]=function(){return r(b.apply(this._wrapped,
27 | arguments),this._chain)}});j.prototype.chain=function(){this._chain=!0;return this};j.prototype.value=function(){return this._wrapped}})();
28 |
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/swagger-ui.js:
--------------------------------------------------------------------------------
1 | jQuery(function($) {
2 |
3 | // this.baseUrl = "http://petstore.swagger.wordnik.com/api/resources.json";
4 | // this.apiKey = "special-key";
5 |
6 | var ApiSelectionController = Spine.Controller.create({
7 | proxied: ["showApi"],
8 |
9 | baseUrlList: new Array(),
10 |
11 | init: function() {
12 | if (this.supportsLocalStorage()) {
13 | var baseUrl = localStorage.getItem("com.wordnik.swagger.ui.baseUrl");
14 | var apiKey = localStorage.getItem("com.wordnik.swagger.ui.apiKey");
15 |
16 | if (baseUrl && baseUrl.length > 0)
17 | $("#input_baseUrl").val(baseUrl);
18 |
19 | if (apiKey && apiKey.length > 0)
20 | $("#input_apiKey").val(apiKey);
21 |
22 | } else {
23 | log("localStorage not supported, user will need to specifiy the api url");
24 | }
25 |
26 | $("a#explore").click(this.showApi);
27 |
28 | this.adaptToScale();
29 | $(window).resize(function() {
30 | apiSelectionController.adaptToScale();
31 | });
32 |
33 | this.handleEnter();
34 | },
35 |
36 | handleEnter: function(){
37 | var self = this;
38 | var submit = function() {
39 | self.showApi();
40 | };
41 | $('#input_baseUrl').keydown(function(e) {
42 | if(e.which != 13) return;
43 | submit();
44 | });
45 | $('#input_apiKey').keydown(function(e) {
46 | if(e.which != 13) return;
47 | submit();
48 | });
49 | },
50 |
51 | adaptToScale: function() {
52 | // var form_width = $('form#api_selector').width();
53 | // var inputs_width = 0;
54 | // $('form#api_selector div.input').each( function(){ inputs_width += $(this).outerWidth(); });
55 | //
56 | // // Update with of baseUrl input
57 | // var free_width = form_width - inputs_width;
58 | // $('#input_baseUrl').width($('#input_baseUrl').width() + free_width - 50);
59 | },
60 |
61 |
62 | slapOn: function() {
63 | // messageController.showMessage("Please enter the base URL of the API that you wish to explore.");
64 | $("#content_message").show();
65 | $("#resources_container").hide();
66 | this.showApi();
67 | },
68 |
69 | supportsLocalStorage: function() {
70 | try {
71 | return 'localStorage' in window && window['localStorage'] !== null;
72 | } catch(e) {
73 | return false;
74 | }
75 | },
76 |
77 | showApi: function() {
78 | var baseUrl = jQuery.trim($("#input_baseUrl").val());
79 | var apiKey = jQuery.trim($("#input_apiKey").val());
80 | if (baseUrl.length == 0) {
81 | $("#input_baseUrl").wiggle();
82 | } else {
83 | if (this.supportsLocalStorage()) {
84 | localStorage.setItem("com.wordnik.swagger.ui.apiKey", apiKey);
85 | localStorage.setItem("com.wordnik.swagger.ui.baseUrl", baseUrl);
86 | }
87 | var resourceListController = ResourceListController.init({
88 | baseUrl: baseUrl,
89 | apiKey: apiKey
90 | });
91 | }
92 | }
93 | });
94 |
95 | var MessageController = Spine.Controller.create({
96 | showMessage: function(msg) {
97 | if (msg) {
98 | $("#content_message").html(msg);
99 | $("#content_message").show();
100 | } else {
101 | $("#content_message").html("");
102 | $("#content_message").hide();
103 | }
104 |
105 | },
106 |
107 | clearMessage: function() {
108 | this.showMessage();
109 | }
110 | });
111 | var messageController = MessageController.init();
112 |
113 | // The following heirarchy is followed by these view controllers
114 | // ResourceListController
115 | // >>> ResourceController
116 | // >>> ApiController
117 | // >>> OperationController
118 | var ResourceListController = Spine.Controller.create({
119 | proxied: ["addAll", "addOne"],
120 |
121 | ApiResource: null,
122 |
123 | init: function() {
124 | if (this.baseUrl == null) {
125 | throw new Error("A baseUrl must be passed to ResourceListController");
126 | }
127 |
128 | $("#content_message").hide();
129 | $("#resources_container").hide();
130 | $("#resources").html("");
131 |
132 | // create and initialize SwaggerService
133 | var swaggerService = new SwaggerService(this.baseUrl, this.apiKey,
134 | function(msg) {
135 | if (msg)
136 | messageController.showMessage(msg);
137 | else
138 | messageController.showMessage("Fetching remote JSON...");
139 | });
140 |
141 | // $("#api_host_url").html(swaggerService.apiHost());
142 |
143 | swaggerService.init();
144 |
145 | // Create convenience references to Spine models
146 | this.ApiResource = swaggerService.ApiResource();
147 |
148 | this.ApiResource.bind("refresh", this.addAll);
149 | },
150 |
151 | addAll: function() {
152 | this.ApiResource.each(this.addOne);
153 | messageController.clearMessage();
154 | $("#resources_container").slideDown(function() {
155 | setTimeout(function() {
156 | Docs.shebang();
157 | },
158 | 400);
159 | });
160 | },
161 |
162 | addOne: function(apiResource) {
163 | ResourceController.init({
164 | item: apiResource,
165 | container: "#resources"
166 | });
167 | }
168 | });
169 |
170 | var ResourceController = Spine.Controller.create({
171 | proxied: ["renderApi", "renderOperation"],
172 |
173 | templateName: "#resourceTemplate",
174 | apiResource: null,
175 | apiList: null,
176 | modelList: null,
177 |
178 | init: function() {
179 | this.render();
180 | this.apiResource = this.item;
181 | this.apiList = this.apiResource.apiList;
182 | this.modelList = this.apiResource.modelList;
183 | this.apiList.each(this.renderApi);
184 | },
185 |
186 | render: function() {
187 | $(this.templateName).tmpl(this.item).appendTo(this.container);
188 | $('#colophon').fadeIn();
189 | },
190 |
191 | renderApi: function(api) {
192 | var resourceApisContainer = "#" + this.apiResource.name + "_endpoint_list";
193 | ApiController.init({
194 | item: api,
195 | container: resourceApisContainer
196 | });
197 |
198 | }
199 |
200 | });
201 |
202 |
203 | var ApiController = Spine.Controller.create({
204 | proxied: ["renderOperation"],
205 |
206 | api: null,
207 | templateName: "#apiTemplate",
208 |
209 | init: function() {
210 | this.render();
211 |
212 | this.api = this.item;
213 |
214 | this.api.operations.each(this.renderOperation);
215 | },
216 |
217 | render: function() {
218 | $(this.templateName).tmpl(this.item).appendTo(this.container);
219 | },
220 |
221 | renderOperation: function(operation) {
222 | var operationsContainer = "#" + this.api.name + "_endpoint_operations";
223 | OperationController.init({
224 | item: operation,
225 | container: operationsContainer
226 | });
227 | }
228 | });
229 |
230 |
231 | // Param Model
232 | // ----------------------------------------------------------------------------------------------
233 | var Param = Spine.Model.setup(
234 | "Param",
235 | ["name", "defaultValue", 'description', 'required', 'dataType', 'allowableValues', 'paramType', 'allowMultiple', "readOnly"]
236 | );
237 |
238 | Param.include({
239 |
240 | cleanup: function() {
241 | this.defaultValue = this.defaultValue || '';
242 | },
243 |
244 | templateName: function(){
245 | var n = "#paramTemplate";
246 |
247 | if (this.allowableValues && this.allowableValues.valueType == "LIST") {
248 | n += "Select";
249 | } else {
250 | if (this.required) n += "Required";
251 | if (this.readOnly) n += "ReadOnly";
252 | }
253 |
254 | return(n);
255 | }
256 |
257 | });
258 |
259 |
260 | var OperationController = Spine.Controller.create({
261 | proxied: ["submitOperation", "showResponse", "showErrorStatus", "showCompleteStatus"],
262 |
263 | operation: null,
264 | templateName: "#operationTemplate",
265 | elementScope: "#operationTemplate",
266 |
267 | init: function() {
268 | this.render();
269 |
270 | this.operation = this.item;
271 | this.isGetOperation = (this.operation.httpMethodLowercase == "get");
272 | this.elementScope = "#" + this.operation.apiName + "_" + this.operation.nickname + "_" + this.operation.httpMethod;
273 |
274 | this.renderParams();
275 | },
276 |
277 | render: function() {
278 | $(this.templateName).tmpl(this.item).appendTo(this.container);
279 | },
280 |
281 | renderParams: function() {
282 | if (this.operation.parameters && this.operation.parameters.count() > 0) {
283 | var operationParamsContainer = this.elementScope + "_params";
284 |
285 | for (var p = 0; p < this.operation.parameters.count(); p++) {
286 | var param = Param.init(this.operation.parameters.all()[p]);
287 | // Only GET operations display forms..
288 | param.readOnly = !this.isGetOperation;
289 | param.cleanup();
290 |
291 | $(param.templateName()).tmpl(param).appendTo(operationParamsContainer);
292 | }
293 | }
294 |
295 | var submitButtonId = this.elementScope + "_content_sandbox_response_button";
296 | if (this.isGetOperation) {
297 | $(submitButtonId).click(this.submitOperation);
298 | } else {
299 | $(submitButtonId).hide();
300 |
301 | var valueHeader = this.elementScope + "_value_header";
302 | $(valueHeader).html("Default Value");
303 | }
304 |
305 | },
306 |
307 | submitOperation: function() {
308 | var form = $(this.elementScope + "_form");
309 | var error_free = true;
310 | var missing_input = null;
311 |
312 | // Cycle through the form's required inputs
313 | form.find("input.required").each(function() {
314 |
315 | // Remove any existing error styles from the input
316 | $(this).removeClass('error');
317 |
318 | // Tack the error style on if the input is empty..
319 | if ($(this).val() == '') {
320 | if (missing_input == null)
321 | missing_input = $(this);
322 | $(this).addClass('error');
323 | $(this).wiggle();
324 | error_free = false;
325 | }
326 |
327 | });
328 |
329 | if (error_free) {
330 | var invocationUrl = this.operation.invocationUrl(form.serializeArray());
331 | $(".request_url", this.elementScope + "_content_sandbox_response").html("" + invocationUrl + "
");
332 | $.getJSON(invocationUrl, this.showResponse).complete(this.showCompleteStatus).error(this.showErrorStatus);
333 | }
334 |
335 | },
336 |
337 | showResponse: function(response) {
338 | // log(response);
339 | var prettyJson = JSON.stringify(response, null, "\t").replace(/\n/g, "
");
340 | // log(prettyJson);
341 | $(".response_body", this.elementScope + "_content_sandbox_response").html(prettyJson);
342 |
343 | $(this.elementScope + "_content_sandbox_response").slideDown();
344 | },
345 |
346 | showErrorStatus: function(data) {
347 | // log("error " + data.status);
348 | this.showStatus(data);
349 | $(this.elementScope + "_content_sandbox_response").slideDown();
350 | },
351 |
352 | showCompleteStatus: function(data) {
353 | // log("complete " + data.status);
354 | this.showStatus(data);
355 | },
356 |
357 | showStatus: function(data) {
358 | // log(data);
359 | // log(data.getAllResponseHeaders());
360 | var response_body = "" + JSON.stringify(JSON.parse(data.responseText), null, 2).replace(/\n/g, "
") + "
";
361 | $(".response_code", this.elementScope + "_content_sandbox_response").html("" + data.status + "
");
362 | $(".response_body", this.elementScope + "_content_sandbox_response").html(response_body);
363 | $(".response_headers", this.elementScope + "_content_sandbox_response").html("" + data.getAllResponseHeaders() + "
");
364 | }
365 |
366 | });
367 |
368 | // Attach controller to window*
369 | window.apiSelectionController = ApiSelectionController.init();
370 |
371 | if (this.baseUrl) {
372 | window.resourceListController = ResourceListController.init({
373 | baseUrl: this.baseUrl,
374 | apiKey: this.apiKey
375 | });
376 | } else {
377 | apiSelectionController.slapOn();
378 | }
379 |
380 | });
381 |
382 |
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/spine.js:
--------------------------------------------------------------------------------
1 | (function(){
2 |
3 | var Spine;
4 | if (typeof exports !== "undefined") {
5 | Spine = exports;
6 | } else {
7 | Spine = this.Spine = {};
8 | }
9 |
10 | Spine.version = "0.0.4";
11 |
12 | var $ = Spine.$ = this.jQuery || this.Zepto || function(){ return arguments[0]; };
13 |
14 | var makeArray = Spine.makeArray = function(args){
15 | return Array.prototype.slice.call(args, 0);
16 | };
17 |
18 | var isArray = Spine.isArray = function(value){
19 | return Object.prototype.toString.call(value) == "[object Array]";
20 | };
21 |
22 | // Shim Array, as these functions aren't in IE
23 | if (typeof Array.prototype.indexOf === "undefined")
24 | Array.prototype.indexOf = function(value){
25 | for ( var i = 0; i < this.length; i++ )
26 | if ( this[ i ] === value )
27 | return i;
28 | return -1;
29 | };
30 |
31 | var Events = Spine.Events = {
32 | bind: function(ev, callback) {
33 | var evs = ev.split(" ");
34 | var calls = this._callbacks || (this._callbacks = {});
35 |
36 | for (var i=0; i < evs.length; i++)
37 | (this._callbacks[evs[i]] || (this._callbacks[evs[i]] = [])).push(callback);
38 |
39 | return this;
40 | },
41 |
42 | trigger: function() {
43 | var args = makeArray(arguments);
44 | var ev = args.shift();
45 |
46 | var list, calls, i, l;
47 | if (!(calls = this._callbacks)) return false;
48 | if (!(list = this._callbacks[ev])) return false;
49 |
50 | for (i = 0, l = list.length; i < l; i++)
51 | if (list[i].apply(this, args) === false)
52 | break;
53 |
54 | return true;
55 | },
56 |
57 | unbind: function(ev, callback){
58 | if ( !ev ) {
59 | this._callbacks = {};
60 | return this;
61 | }
62 |
63 | var list, calls, i, l;
64 | if (!(calls = this._callbacks)) return this;
65 | if (!(list = this._callbacks[ev])) return this;
66 |
67 | if ( !callback ) {
68 | delete this._callbacks[ev];
69 | return this;
70 | }
71 |
72 | for (i = 0, l = list.length; i < l; i++)
73 | if (callback === list[i]) {
74 | list.splice(i, 1);
75 | break;
76 | }
77 |
78 | return this;
79 | }
80 | };
81 |
82 | var Log = Spine.Log = {
83 | trace: true,
84 |
85 | logPrefix: "(App)",
86 |
87 | log: function(){
88 | if ( !this.trace ) return;
89 | if (typeof console == "undefined") return;
90 | var args = makeArray(arguments);
91 | if (this.logPrefix) args.unshift(this.logPrefix);
92 | console.log.apply(console, args);
93 | return this;
94 | }
95 | };
96 |
97 | // Classes (or prototypial inheritors)
98 |
99 | if (typeof Object.create !== "function")
100 | Object.create = function(o) {
101 | function F() {}
102 | F.prototype = o;
103 | return new F();
104 | };
105 |
106 | var moduleKeywords = ["included", "extended"];
107 |
108 | var Class = Spine.Class = {
109 | inherited: function(){},
110 | created: function(){},
111 |
112 | prototype: {
113 | initialize: function(){},
114 | init: function(){}
115 | },
116 |
117 | create: function(include, extend){
118 | var object = Object.create(this);
119 | object.parent = this;
120 | object.prototype = object.fn = Object.create(this.prototype);
121 |
122 | if (include) object.include(include);
123 | if (extend) object.extend(extend);
124 |
125 | object.created();
126 | this.inherited(object);
127 | return object;
128 | },
129 |
130 | init: function(){
131 | var instance = Object.create(this.prototype);
132 | instance.parent = this;
133 |
134 | instance.initialize.apply(instance, arguments);
135 | instance.init.apply(instance, arguments);
136 | return instance;
137 | },
138 |
139 | proxy: function(func){
140 | var thisObject = this;
141 | return(function(){
142 | return func.apply(thisObject, arguments);
143 | });
144 | },
145 |
146 | proxyAll: function(){
147 | var functions = makeArray(arguments);
148 | for (var i=0; i < functions.length; i++)
149 | this[functions[i]] = this.proxy(this[functions[i]]);
150 | },
151 |
152 | include: function(obj){
153 | for(var key in obj)
154 | if (moduleKeywords.indexOf(key) == -1)
155 | this.fn[key] = obj[key];
156 |
157 | var included = obj.included;
158 | if (included) included.apply(this);
159 | return this;
160 | },
161 |
162 | extend: function(obj){
163 | for(var key in obj)
164 | if (moduleKeywords.indexOf(key) == -1)
165 | this[key] = obj[key];
166 |
167 | var extended = obj.extended;
168 | if (extended) extended.apply(this);
169 | return this;
170 | }
171 | };
172 |
173 | Class.prototype.proxy = Class.proxy;
174 | Class.prototype.proxyAll = Class.proxyAll;
175 | Class.instancet = Class.init;
176 | Class.sub = Class.create;
177 |
178 | // Models
179 |
180 | Spine.guid = function(){
181 | return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
182 | var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
183 | return v.toString(16);
184 | }).toUpperCase();
185 | };
186 |
187 | var Model = Spine.Model = Class.create();
188 |
189 | Model.extend(Events);
190 |
191 | Model.extend({
192 | setup: function(name, atts){
193 | var model = Model.sub();
194 | if (name) model.name = name;
195 | if (atts) model.attributes = atts;
196 | return model;
197 | },
198 |
199 | created: function(sub){
200 | this.records = {};
201 | this.attributes = this.attributes ?
202 | makeArray(this.attributes) : [];
203 | },
204 |
205 | find: function(id){
206 | var record = this.records[id];
207 | if ( !record ) throw("Unknown record");
208 | return record.clone();
209 | },
210 |
211 | exists: function(id){
212 | try {
213 | return this.find(id);
214 | } catch (e) {
215 | return false;
216 | }
217 | },
218 |
219 | refresh: function(values){
220 | values = this.fromJSON(values);
221 | this.records = {};
222 |
223 | for (var i=0, il = values.length; i < il; i++) {
224 | var record = values[i];
225 | record.newRecord = false;
226 | record.id = record.id || Spine.guid();
227 | this.records[record.id] = record;
228 | }
229 |
230 | this.trigger("refresh");
231 | return this;
232 | },
233 |
234 | // adeed by ayush
235 | createAll: function(values){
236 | values = this.fromJSON(values);
237 | for (var i=0, il = values.length; i < il; i++) {
238 | var record = values[i];
239 | record.newRecord = false;
240 | record.id = record.id || Spine.guid();
241 | this.records[record.id] = record;
242 | }
243 |
244 | return this;
245 | },
246 |
247 | select: function(callback){
248 | var result = [];
249 |
250 | for (var key in this.records)
251 | if (callback(this.records[key]))
252 | result.push(this.records[key]);
253 |
254 | return this.cloneArray(result);
255 | },
256 |
257 | findByAttribute: function(name, value){
258 | for (var key in this.records)
259 | if (this.records[key][name] == value)
260 | return this.records[key].clone();
261 | },
262 |
263 | findAllByAttribute: function(name, value){
264 | return(this.select(function(item){
265 | return(item[name] == value);
266 | }));
267 | },
268 |
269 | each: function(callback){
270 | for (var key in this.records)
271 | callback(this.records[key]);
272 | },
273 |
274 | all: function(){
275 | return this.cloneArray(this.recordsValues());
276 | },
277 |
278 | first: function(){
279 | var record = this.recordsValues()[0];
280 | return(record && record.clone());
281 | },
282 |
283 | last: function(){
284 | var values = this.recordsValues();
285 | var record = values[values.length - 1];
286 | return(record && record.clone());
287 | },
288 |
289 | count: function(){
290 | return this.recordsValues().length;
291 | },
292 |
293 | deleteAll: function(){
294 | for (var key in this.records)
295 | delete this.records[key];
296 | },
297 |
298 | destroyAll: function(){
299 | for (var key in this.records)
300 | this.records[key].destroy();
301 | },
302 |
303 | update: function(id, atts){
304 | this.find(id).updateAttributes(atts);
305 | },
306 |
307 | create: function(atts){
308 | var record = this.init(atts);
309 | return record.save();
310 | },
311 |
312 | destroy: function(id){
313 | this.find(id).destroy();
314 | },
315 |
316 | sync: function(callback){
317 | this.bind("change", callback);
318 | },
319 |
320 | fetch: function(callbackOrParams){
321 | typeof(callbackOrParams) == "function" ?
322 | this.bind("fetch", callbackOrParams) :
323 | this.trigger("fetch", callbackOrParams);
324 | },
325 |
326 | toJSON: function(){
327 | return this.recordsValues();
328 | },
329 |
330 | fromJSON: function(objects){
331 | if ( !objects ) return;
332 | if ( typeof objects == "string" )
333 | objects = JSON.parse(objects);
334 | if ( isArray(objects) ) {
335 | var results = [];
336 | for (var i=0; i < objects.length; i++)
337 | results.push(this.init(objects[i]));
338 | return results;
339 | } else {
340 | return this.init(objects);
341 | }
342 | },
343 |
344 | // Private
345 |
346 | recordsValues: function(){
347 | var result = [];
348 | for (var key in this.records)
349 | result.push(this.records[key]);
350 | return result;
351 | },
352 |
353 | cloneArray: function(array){
354 | var result = [];
355 | for (var i=0; i < array.length; i++)
356 | result.push(array[i].clone());
357 | return result;
358 | },
359 |
360 | // added by ayush
361 | logAll: function() {
362 | for(var i = 0; i < this.all().length; i++) {
363 | var e = this.all()[i];
364 | if(window.console) console.log(e.toString());
365 | }
366 | }
367 |
368 | });
369 |
370 | Model.include({
371 | model: true,
372 | newRecord: true,
373 |
374 | init: function(atts){
375 | if (atts) this.load(atts);
376 | this.trigger("init", this);
377 | },
378 |
379 | isNew: function(){
380 | return this.newRecord;
381 | },
382 |
383 | isValid: function(){
384 | return(!this.validate());
385 | },
386 |
387 | validate: function(){ },
388 |
389 | load: function(atts){
390 | for(var name in atts)
391 | this[name] = atts[name];
392 | },
393 |
394 | attributes: function(){
395 | var result = {};
396 | for (var i=0; i < this.parent.attributes.length; i++) {
397 | var attr = this.parent.attributes[i];
398 | result[attr] = this[attr];
399 | }
400 | result.id = this.id;
401 | return result;
402 | },
403 |
404 | eql: function(rec){
405 | return(rec && rec.id === this.id &&
406 | rec.parent === this.parent);
407 | },
408 |
409 | save: function(){
410 | var error = this.validate();
411 | if ( error ) {
412 | this.trigger("error", this, error);
413 | return false;
414 | }
415 |
416 | this.trigger("beforeSave", this);
417 | this.newRecord ? this.create() : this.update();
418 | this.trigger("save", this);
419 | return this;
420 | },
421 |
422 | updateAttribute: function(name, value){
423 | this[name] = value;
424 | return this.save();
425 | },
426 |
427 | updateAttributes: function(atts){
428 | this.load(atts);
429 | return this.save();
430 | },
431 |
432 | destroy: function(){
433 | this.trigger("beforeDestroy", this);
434 | delete this.parent.records[this.id];
435 | this.destroyed = true;
436 | this.trigger("destroy", this);
437 | this.trigger("change", this, "destroy");
438 | },
439 |
440 | dup: function(){
441 | var result = this.parent.init(this.attributes());
442 | result.newRecord = this.newRecord;
443 | return result;
444 | },
445 |
446 | clone: function(){
447 | return Object.create(this);
448 | },
449 |
450 | reload: function(){
451 | if ( this.newRecord ) return this;
452 | var original = this.parent.find(this.id);
453 | this.load(original.attributes());
454 | return original;
455 | },
456 |
457 | toJSON: function(){
458 | return(this.attributes());
459 | },
460 |
461 | exists: function(){
462 | return(this.id && this.id in this.parent.records);
463 | },
464 |
465 | // Private
466 |
467 | update: function(){
468 | this.trigger("beforeUpdate", this);
469 | var records = this.parent.records;
470 | records[this.id].load(this.attributes());
471 | var clone = records[this.id].clone();
472 | this.trigger("update", clone);
473 | this.trigger("change", clone, "update");
474 | },
475 |
476 | create: function(){
477 | this.trigger("beforeCreate", this);
478 | if ( !this.id ) this.id = Spine.guid();
479 | this.newRecord = false;
480 | var records = this.parent.records;
481 | records[this.id] = this.dup();
482 | var clone = records[this.id].clone();
483 | this.trigger("create", clone);
484 | this.trigger("change", clone, "create");
485 | },
486 |
487 | bind: function(events, callback){
488 | return this.parent.bind(events, this.proxy(function(record){
489 | if ( record && this.eql(record) )
490 | callback.apply(this, arguments);
491 | }));
492 | },
493 |
494 | trigger: function(){
495 | return this.parent.trigger.apply(this.parent, arguments);
496 | }
497 | });
498 |
499 | // Controllers
500 |
501 | var eventSplitter = /^(\w+)\s*(.*)$/;
502 |
503 | var Controller = Spine.Controller = Class.create({
504 | tag: "div",
505 |
506 | initialize: function(options){
507 | this.options = options;
508 |
509 | for (var key in this.options)
510 | this[key] = this.options[key];
511 |
512 | if (!this.el) this.el = document.createElement(this.tag);
513 | this.el = $(this.el);
514 |
515 | if ( !this.events ) this.events = this.parent.events;
516 | if ( !this.elements ) this.elements = this.parent.elements;
517 |
518 | if (this.events) this.delegateEvents();
519 | if (this.elements) this.refreshElements();
520 | if (this.proxied) this.proxyAll.apply(this, this.proxied);
521 | },
522 |
523 | $: function(selector){
524 | return $(selector, this.el);
525 | },
526 |
527 | delegateEvents: function(){
528 | for (var key in this.events) {
529 | var methodName = this.events[key];
530 | var method = this.proxy(this[methodName]);
531 |
532 | var match = key.match(eventSplitter);
533 | var eventName = match[1], selector = match[2];
534 |
535 | if (selector === '') {
536 | this.el.bind(eventName, method);
537 | } else {
538 | this.el.delegate(selector, eventName, method);
539 | }
540 | }
541 | },
542 |
543 | refreshElements: function(){
544 | for (var key in this.elements) {
545 | this[this.elements[key]] = this.$(key);
546 | }
547 | },
548 |
549 | delay: function(func, timeout){
550 | setTimeout(this.proxy(func), timeout || 0);
551 | }
552 | });
553 |
554 | Controller.include(Events);
555 | Controller.include(Log);
556 |
557 | Spine.App = Class.create();
558 | Spine.App.extend(Events);
559 | Controller.fn.App = Spine.App;
560 | })();
561 |
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/swagger-service.js:
--------------------------------------------------------------------------------
1 | function SwaggerService(discoveryUrl, _apiKey, statusCallback) {
2 | if (!discoveryUrl)
3 | throw new Error("discoveryUrl must be passed while creating SwaggerService");
4 |
5 | // constants
6 | discoveryUrl = jQuery.trim(discoveryUrl);
7 | if (discoveryUrl.length == 0)
8 | throw new Error("discoveryUrl must be passed while creating SwaggerService");
9 |
10 | if (! (discoveryUrl.toLowerCase().indexOf("http:") == 0 || discoveryUrl.toLowerCase().indexOf("https:") == 0)) {
11 | discoveryUrl = ("http://" + discoveryUrl);
12 | }
13 |
14 | var globalBasePath = null;
15 | var formatString = ".{format}";
16 | var statusListener = statusCallback;
17 | var apiKey = _apiKey;
18 |
19 | var apiKeySuffix = "";
20 | if (apiKey) {
21 | apiKey = jQuery.trim(apiKey);
22 | if (apiKey.length > 0)
23 | apiKeySuffix = "?api_key=" + apiKey;
24 | }
25 |
26 | function log() {
27 | if (window.console) console.log.apply(console,arguments);
28 | }
29 |
30 | function error(m) {
31 | log("ERROR: " + m);
32 | }
33 |
34 | function updateStatus(status) {
35 | statusListener(status);
36 | }
37 |
38 | function endsWith(str, suffix) {
39 | return str.indexOf(suffix, str.length - suffix.length) !== -1;
40 | }
41 |
42 | // make some models public
43 | this.ApiResource = function() {
44 | return ApiResource;
45 | };
46 |
47 | this.apiHost = function() {
48 | return globalBasePath;
49 | };
50 |
51 | this.formatString = function() {
52 | return formatString;
53 | };
54 |
55 | // Model: ApiResource
56 | var ApiResource = Spine.Model.setup("ApiResource", ["name", "baseUrl", "path", "path_json", "path_xml", "description", "apiLists", "modelList"]);
57 | ApiResource.include({
58 | path_json: null,
59 | path_xml: null,
60 |
61 | init: function(atts) {
62 | if (atts) this.load(atts);
63 | this.path_json = this.path.replace("{format}", "json");
64 | this.path_xml = this.path.replace("{format}", "xml");
65 | this.baseUrl = globalBasePath;
66 | //execluded 9 letters to remove .{format} from name
67 | this.name = this.path.split("/");
68 | this.name = this.name[this.name.length - 1];
69 | this.name = this.name.replace(".{format}",'').replace(/\//g, "_");
70 | // this.name = this.path.substr(1, this.path.length - formatString.length - 1).replace(/\//g, "_");
71 | this.apiList = Api.sub();
72 | this.modelList = ApiModel.sub();
73 | },
74 |
75 | addApis: function(apiObjects, basePath) {
76 | // log("apiObjects: %o", apiObjects);
77 | this.apiList.createAll(apiObjects);
78 | this.apiList.each(function(api) {
79 | api.setBaseUrl(basePath);
80 | });
81 | },
82 |
83 | addModel: function(modelObject) {
84 | this.modelList.create(modelObject);
85 | },
86 |
87 | toString: function() {
88 | return this.path_json + ": " + this.description;
89 | }
90 | });
91 |
92 | // Model: Api
93 | var Api = Spine.Model.setup("Api", ["baseUrl", "path", "path_json", "path_xml", "name", "description", "operations", "path_json", "path_xml"]);
94 | Api.include({
95 | init: function(atts) {
96 | if (atts) this.load(atts);
97 |
98 | var secondPathSeperatorIndex = this.path.indexOf("/", 1);
99 | if (secondPathSeperatorIndex > 0) {
100 | var prefix = this.path.substr(0, secondPathSeperatorIndex);
101 | var suffix = this.path.substr(secondPathSeperatorIndex, this.path.length);
102 | // log(this.path + ":: " + prefix + "..." + suffix);
103 | this.path_json = prefix.replace("{format}", "json") + suffix;
104 | this.path_xml = prefix.replace("{format}", "xml") + suffix;;
105 |
106 | if (this.path.indexOf("/") == 0) {
107 | this.name = this.path.substr(1, secondPathSeperatorIndex - formatString.length - 1);
108 | } else {
109 | this.name = this.path.substr(0, secondPathSeperatorIndex - formatString.length - 1);
110 | }
111 | } else {
112 | this.path_json = this.path.replace("{format}", "json");
113 | this.path_xml = this.path.replace("{format}", "xml");
114 |
115 | if (this.path.indexOf("/") == 0) {
116 | this.name = this.path.substr(1, this.path.length - formatString.length - 1);
117 | } else {
118 | this.name = this.path.substr(0, this.path.length - formatString.length - 1);
119 | }
120 | }
121 |
122 | var value = this.operations;
123 |
124 | this.operations = ApiOperation.sub();
125 | if (value) {
126 | for (var i = 0; i < value.length; i++) {
127 | var obj = value[i];
128 | obj.apiName = this.name;
129 | obj.path = this.path;
130 | obj.path_json = this.path_json;
131 | obj.path_xml = this.path_xml;
132 |
133 | }
134 |
135 | this.operations.refresh(value);
136 | }
137 |
138 | updateStatus("Loading " + this.path + "...");
139 |
140 | },
141 |
142 | setBaseUrl: function(u) {
143 | this.baseUrl = u;
144 | this.operations.each(function(o) {
145 | o.baseUrl = u;
146 | });
147 | },
148 |
149 | toString: function() {
150 | var opsString = "";
151 | for (var i = 0; i < this.operations.all().length; i++) {
152 | var e = this.operations.all()[i];
153 |
154 | if (opsString.length > 0)
155 | opsString += ", ";
156 |
157 | opsString += e.toString();
158 | }
159 | return this.path_json + "- " + this.operations.all().length + " operations: " + opsString;
160 | }
161 |
162 | });
163 |
164 | // Model: ApiOperation
165 | var ApiOperation = Spine.Model.setup("ApiOperation", ["baseUrl", "path", "path_json", "path_xml", "summary", "notes", "deprecated", "open", "httpMethod", "httpMethodLowercase", "nickname", "responseClass", "parameters", "apiName"]);
166 | ApiOperation.include({
167 | init: function(atts) {
168 | if (atts) this.load(atts);
169 |
170 | this.httpMethodLowercase = this.httpMethod.toLowerCase();
171 |
172 | var value = this.parameters;
173 | this.parameters = ApiParameter.sub();
174 | if (value) this.parameters.refresh(value);
175 | },
176 |
177 | toString: function() {
178 | var paramsString = "(";
179 | for (var i = 0; i < this.parameters.all().length; i++) {
180 | var e = this.parameters.all()[i];
181 |
182 | if (paramsString.length > 1)
183 | paramsString += ", ";
184 |
185 | paramsString += e.toString();
186 | }
187 | paramsString += ")";
188 |
189 | return "{" + this.path_json + "| " + this.nickname + paramsString + ": " + this.summary + "}";
190 | },
191 |
192 | invocationUrl: function(formValues) {
193 | var formValuesMap = new Object();
194 | for (var i = 0; i < formValues.length; i++) {
195 | var formValue = formValues[i];
196 | if (formValue.value && jQuery.trim(formValue.value).length > 0)
197 | formValuesMap[formValue.name] = formValue.value;
198 | }
199 |
200 | var urlTemplateText = this.path_json.split("{").join("${");
201 | // log("url template = " + urlTemplateText);
202 | var urlTemplate = $.template(null, urlTemplateText);
203 | var url = $.tmpl(urlTemplate, formValuesMap)[0].data;
204 | // log("url with path params = " + url);
205 |
206 | var queryParams = apiKeySuffix;
207 | this.parameters.each(function(param) {
208 | var paramValue = jQuery.trim(formValuesMap[param.name]);
209 | if (param.paramType == "query" && paramValue.length > 0) {
210 | queryParams += queryParams.length > 0 ? "&": "?";
211 | queryParams += param.name;
212 | queryParams += "=";
213 | queryParams += formValuesMap[param.name];
214 | }
215 | });
216 |
217 | url = this.baseUrl + url + queryParams;
218 | // log("final url with query params and base url = " + url);
219 |
220 | return url;
221 | }
222 |
223 | });
224 |
225 | // Model: ApiParameter
226 | var ApiParameter = Spine.Model.setup("ApiParameter", ["name", "description", "required", "dataType", "allowableValues", "paramType", "allowMultiple"]);
227 | ApiParameter.include({
228 | init: function(atts) {
229 | if (atts) this.load(atts);
230 |
231 | this.name = this.name || this.dataType;
232 |
233 | if(this.allowableValues){
234 | var value = this.allowableValues;
235 | if(value.valueType == "LIST"){
236 | this.allowableValues = AllowableListValues.sub();
237 | } else if (value.valueType == "RANGE"){
238 | this.allowableValues = AllowableRangeValues.sub();
239 | }
240 | if (value) this.allowableValues = this.allowableValues.create(value);
241 | }
242 | },
243 |
244 | toString: function() {
245 | if (this.allowableValues)
246 | return this.name + ": " + this.dataType + " " + this.allowableValues;
247 | else
248 | return this.name + ": " + this.dataType;
249 | }
250 |
251 | });
252 |
253 | var AllowableListValues = Spine.Model.setup("AllowableListValues", ["valueType", "values"]);
254 | AllowableListValues.include({
255 | init: function(atts) {
256 | if (atts) this.load(atts);
257 | this.name = "allowableValues";
258 | },
259 | toString: function() {
260 | if (this.values)
261 | return "["+this.values+"]";
262 | else
263 | return "";
264 | }
265 | });
266 |
267 | var AllowableRangeValues = Spine.Model.setup("AllowableRangeValues", ["valueType", "inclusive", "min", "max"]);
268 | AllowableRangeValues.include({
269 | init: function(atts) {
270 | if (atts) this.load(atts);
271 | this.name = "allowableValues";
272 | },
273 |
274 | toString: function() {
275 | if (this.min && this.max)
276 | return "[" + min + "," + max + "]";
277 | else
278 | return "";
279 | }
280 | });
281 |
282 |
283 | // Model: ApiModel
284 | var ApiModel = Spine.Model.setup("ApiModel", ["id", "fields"]);
285 | ApiModel.include({
286 | init: function(atts) {
287 | if (atts) this.load(atts);
288 |
289 | if (!this.fields) {
290 | var propertiesListObject = this.properties;
291 | this.fields = ApiModelProperty.sub();
292 |
293 | for (var propName in propertiesListObject) {
294 | if (propName != "parent") {
295 | var p = propertiesListObject[propName];
296 | p.name = propName;
297 | p.id = Spine.guid();
298 | // log(p);
299 | this.fields.create(p);
300 | }
301 | }
302 | //log("got " + this.fields.count() + " fields for " + this.id);
303 | }
304 | },
305 |
306 | toString: function() {
307 | var propsString = "";
308 |
309 | propsString += "(";
310 | for (var i = 0; i < this.fields.all().length; i++) {
311 | var e = this.fields.all()[i];
312 |
313 | if (propsString.length > 1)
314 | propsString += ", ";
315 |
316 | propsString += e.toString();
317 | }
318 | propsString += ")";
319 |
320 | if (this.required)
321 | return this.id + " (required): " + propsString;
322 | else
323 | return this.id + ": " + propsString;
324 | }
325 |
326 | });
327 |
328 |
329 | // Model: ApiModelProperty
330 | var ApiModelProperty = Spine.Model.setup("ApiModelProperty", ["name", "required", "dataType"]);
331 | ApiModelProperty.include({
332 | init: function(atts) {
333 | if (atts) this.load(atts);
334 |
335 | if (!this.dataType) {
336 | if (atts.type == "any")
337 | this.dataType = "object";
338 | else if (atts.type == "array") {
339 | if (atts.items) {
340 | if (atts.items.$ref) {
341 | this.dataType = "array[" + atts.items.$ref + "]";
342 | } else {
343 | this.dataType = "array[" + atts.items.type + "]";
344 | }
345 | } else {
346 | this.dataType = "array";
347 | }
348 | } else
349 | this.dataType = atts.type;
350 |
351 | }
352 | },
353 |
354 | toString: function() {
355 | if (this.required)
356 | return this.name + ": " + this.dataType + " (required)";
357 | else
358 | return this.name + ": " + this.dataType;
359 | }
360 |
361 | });
362 |
363 | // Controller
364 | var ModelController = Spine.Controller.create({
365 | countLoaded: 0,
366 | proxied: ["fetchResources", "loadResources", "apisLoaded", "modelsLoaded"],
367 | discoveryUrlList: [],
368 | discoveryUrlListCursor: 0,
369 |
370 | init: function() {
371 | // log("ModelController.init");
372 |
373 | this.fetchEndpoints();
374 | },
375 |
376 | fetchEndpoints: function() {
377 | updateStatus("Fetching API List...");
378 | var baseDiscoveryUrl = endsWith(discoveryUrl, "/") ? discoveryUrl.substr(0, discoveryUrl.length - 1) : discoveryUrl;
379 | if(endsWith(baseDiscoveryUrl, "/resources.json"))
380 | baseDiscoveryUrl = baseDiscoveryUrl.substr(0, baseDiscoveryUrl.length - "/resources.json".length);
381 | else if(endsWith(baseDiscoveryUrl, "/resources"))
382 | baseDiscoveryUrl = baseDiscoveryUrl.substr(0, baseDiscoveryUrl.length - "/resources".length);
383 |
384 | this.discoveryUrlList.push(discoveryUrl);
385 | this.discoveryUrlList.push(baseDiscoveryUrl);
386 | this.discoveryUrlList.push(baseDiscoveryUrl + "/resources.json");
387 | this.discoveryUrlList.push(baseDiscoveryUrl + "/resources");
388 |
389 | log("Will try the following urls to discover api endpoints:")
390 | for(var i = 0; i < this.discoveryUrlList.length; i++)
391 | log(" > " + this.discoveryUrlList[i]);
392 |
393 | this.fetchEndpointsSeq();
394 | },
395 |
396 | fetchEndpointsSeq: function() {
397 | var controller = this;
398 |
399 | if(this.discoveryUrlListCursor < this.discoveryUrlList.length) {
400 | var url = this.discoveryUrlList[this.discoveryUrlListCursor++]
401 | updateStatus("Fetching API List from " + url);
402 | log("Trying url " + url);
403 | $.getJSON(url + apiKeySuffix, function(response) {
404 | })
405 | .success(function(response) {
406 | log("Setting globalBasePath to " + response.basePath);
407 | globalBasePath = response.basePath;
408 | ApiResource.createAll(response.apis);
409 | controller.fetchResources(response.basePath);
410 | })
411 | .error(function(response) {
412 | controller.fetchEndpointsSeq();
413 | });
414 | } else {
415 | log ('Error with resource discovery. Exhaused all possible endpoint urls');
416 |
417 | var urlsTried = "";
418 | for(var i = 0; i < this.discoveryUrlList.length; i++) {
419 | urlsTried = urlsTried + "
" + this.discoveryUrlList[i];
420 | }
421 |
422 | updateStatus("Unable to fetch API Listing. Tried the following urls:" + urlsTried);
423 | }
424 | },
425 |
426 | fetchResources: function(basePath) {
427 | log("fetchResources: basePath = " + basePath);
428 | //ApiResource.logAll();
429 | for (var i = 0; i < ApiResource.all().length; i++) {
430 | var apiResource = ApiResource.all()[i];
431 | this.fetchResource(apiResource);
432 | }
433 | },
434 |
435 | fetchResource: function(apiResource) {
436 | var controller = this;
437 | updateStatus("Fetching " + apiResource.name + "...");
438 | var resourceUrl = globalBasePath + apiResource.path_json + apiKeySuffix;
439 | log("resourceUrl: %o", resourceUrl);
440 | $.getJSON(resourceUrl,
441 | function(response) {
442 | controller.loadResources(response, apiResource);
443 | });
444 | },
445 |
446 | loadResources: function(response, apiResource) {
447 | try {
448 | this.countLoaded++;
449 | // log(response);
450 | if (response.apis) {
451 | apiResource.addApis(response.apis, response.basePath);
452 | }
453 | // updateStatus("Parsed Apis");
454 | //log(response.models);
455 | if (response.models) {
456 | // log("response.models.length = " + response.models.length);
457 | for (var modeName in response.models) {
458 | var m = response.models[modeName];
459 | // log("creating " + m.id);
460 | apiResource.addModel(m);
461 | // apiResource.modelList.create(m);
462 | }
463 | }
464 |
465 | updateStatus();
466 | } finally {
467 | if (this.countLoaded == ApiResource.count()) {
468 | // log("all models/api loaded");
469 | ApiResource.trigger("refresh");
470 | }
471 | }
472 | }
473 |
474 | });
475 |
476 | this.init = function() {
477 | this.modelController = ModelController.init();
478 | };
479 | };
480 |
481 |
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/jquery.tmpl.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery Templating Plugin
3 | * Copyright 2010, John Resig
4 | * Dual licensed under the MIT or GPL Version 2 licenses.
5 | */
6 |
7 | (function(jQuery, undefined) {
8 | var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
9 | newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];
10 |
11 | function newTmplItem(options, parentItem, fn, data) {
12 | // Returns a template item data structure for a new rendered instance of a template (a 'template item').
13 | // The content field is a hierarchical array of strings and nested items (to be
14 | // removed and replaced by nodes field of dom elements, once inserted in DOM).
15 | var newItem = {
16 | data: data || (parentItem ? parentItem.data : {}),
17 | _wrap: parentItem ? parentItem._wrap : null,
18 | tmpl: null,
19 | parent: parentItem || null,
20 | nodes: [],
21 | calls: tiCalls,
22 | nest: tiNest,
23 | wrap: tiWrap,
24 | html: tiHtml,
25 | update: tiUpdate
26 | };
27 | if (options) {
28 | jQuery.extend(newItem, options, { nodes: [], parent: parentItem });
29 | }
30 | if (fn) {
31 | // Build the hierarchical content to be used during insertion into DOM
32 | newItem.tmpl = fn;
33 | newItem._ctnt = newItem._ctnt || newItem.tmpl(jQuery, newItem);
34 | newItem.key = ++itemKey;
35 | // Keep track of new template item, until it is stored as jQuery Data on DOM element
36 | (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
37 | }
38 | return newItem;
39 | }
40 |
41 | // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
42 | jQuery.each({
43 | appendTo: "append",
44 | prependTo: "prepend",
45 | insertBefore: "before",
46 | insertAfter: "after",
47 | replaceAll: "replaceWith"
48 | }, function(name, original) {
49 | jQuery.fn[ name ] = function(selector) {
50 | var ret = [], insert = jQuery(selector), elems, i, l, tmplItems,
51 | parent = this.length === 1 && this[0].parentNode;
52 |
53 | appendToTmplItems = newTmplItems || {};
54 | if (parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1) {
55 | insert[ original ](this[0]);
56 | ret = this;
57 | } else {
58 | for (i = 0,l = insert.length; i < l; i++) {
59 | cloneIndex = i;
60 | elems = (i > 0 ? this.clone(true) : this).get();
61 | jQuery.fn[ original ].apply(jQuery(insert[i]), elems);
62 | ret = ret.concat(elems);
63 | }
64 | cloneIndex = 0;
65 | ret = this.pushStack(ret, name, insert.selector);
66 | }
67 | tmplItems = appendToTmplItems;
68 | appendToTmplItems = null;
69 | jQuery.tmpl.complete(tmplItems);
70 | return ret;
71 | };
72 | });
73 |
74 | jQuery.fn.extend({
75 | // Use first wrapped element as template markup.
76 | // Return wrapped set of template items, obtained by rendering template against data.
77 | tmpl: function(data, options, parentItem) {
78 | return jQuery.tmpl(this[0], data, options, parentItem);
79 | },
80 |
81 | // Find which rendered template item the first wrapped DOM element belongs to
82 | tmplItem: function() {
83 | return jQuery.tmplItem(this[0]);
84 | },
85 |
86 | // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
87 | template: function(name) {
88 | return jQuery.template(name, this[0]);
89 | },
90 |
91 | domManip: function(args, table, callback, options) {
92 | // This appears to be a bug in the appendTo, etc. implementation
93 | // it should be doing .call() instead of .apply(). See #6227
94 | if (args[0] && args[0].nodeType) {
95 | var dmArgs = jQuery.makeArray(arguments), argsLength = args.length, i = 0, tmplItem;
96 | while (i < argsLength && !(tmplItem = jQuery.data(args[i++], "tmplItem"))) {
97 | }
98 | if (argsLength > 1) {
99 | dmArgs[0] = [jQuery.makeArray(args)];
100 | }
101 | if (tmplItem && cloneIndex) {
102 | dmArgs[2] = function(fragClone) {
103 | // Handler called by oldManip when rendered template has been inserted into DOM.
104 | jQuery.tmpl.afterManip(this, fragClone, callback);
105 | };
106 | }
107 | oldManip.apply(this, dmArgs);
108 | } else {
109 | oldManip.apply(this, arguments);
110 | }
111 | cloneIndex = 0;
112 | if (!appendToTmplItems) {
113 | jQuery.tmpl.complete(newTmplItems);
114 | }
115 | return this;
116 | }
117 | });
118 |
119 | jQuery.extend({
120 | // Return wrapped set of template items, obtained by rendering template against data.
121 | tmpl: function(tmpl, data, options, parentItem) {
122 | var ret, topLevel = !parentItem;
123 | if (topLevel) {
124 | // This is a top-level tmpl call (not from a nested template using {{tmpl}})
125 | parentItem = topTmplItem;
126 | tmpl = jQuery.template[tmpl] || jQuery.template(null, tmpl);
127 | wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
128 | } else if (!tmpl) {
129 | // The template item is already associated with DOM - this is a refresh.
130 | // Re-evaluate rendered template for the parentItem
131 | tmpl = parentItem.tmpl;
132 | newTmplItems[parentItem.key] = parentItem;
133 | parentItem.nodes = [];
134 | if (parentItem.wrapped) {
135 | updateWrapped(parentItem, parentItem.wrapped);
136 | }
137 | // Rebuild, without creating a new template item
138 | return jQuery(build(parentItem, null, parentItem.tmpl(jQuery, parentItem)));
139 | }
140 | if (!tmpl) {
141 | return []; // Could throw...
142 | }
143 | if (typeof data === "function") {
144 | data = data.call(parentItem || {});
145 | }
146 | if (options && options.wrapped) {
147 | updateWrapped(options, options.wrapped);
148 | }
149 | ret = jQuery.isArray(data) ?
150 | jQuery.map(data, function(dataItem) {
151 | return dataItem ? newTmplItem(options, parentItem, tmpl, dataItem) : null;
152 | }) :
153 | [ newTmplItem(options, parentItem, tmpl, data) ];
154 | return topLevel ? jQuery(build(parentItem, null, ret)) : ret;
155 | },
156 |
157 | // Return rendered template item for an element.
158 | tmplItem: function(elem) {
159 | var tmplItem;
160 | if (elem instanceof jQuery) {
161 | elem = elem[0];
162 | }
163 | while (elem && elem.nodeType === 1 && !(tmplItem = jQuery.data(elem, "tmplItem")) && (elem = elem.parentNode)) {
164 | }
165 | return tmplItem || topTmplItem;
166 | },
167 |
168 | // Set:
169 | // Use $.template( name, tmpl ) to cache a named template,
170 | // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
171 | // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.
172 |
173 | // Get:
174 | // Use $.template( name ) to access a cached template.
175 | // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
176 | // will return the compiled template, without adding a name reference.
177 | // If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
178 | // to $.template( null, templateString )
179 | template: function(name, tmpl) {
180 | if (tmpl) {
181 | // Compile template and associate with name
182 | if (typeof tmpl === "string") {
183 | // This is an HTML string being passed directly in.
184 | tmpl = buildTmplFn(tmpl)
185 | } else if (tmpl instanceof jQuery) {
186 | tmpl = tmpl[0] || {};
187 | }
188 | if (tmpl.nodeType) {
189 | // If this is a template block, use cached copy, or generate tmpl function and cache.
190 | tmpl = jQuery.data(tmpl, "tmpl") || jQuery.data(tmpl, "tmpl", buildTmplFn(tmpl.innerHTML));
191 | }
192 | return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
193 | }
194 | // Return named compiled template
195 | return name ? (typeof name !== "string" ? jQuery.template(null, name) :
196 | (jQuery.template[name] ||
197 | // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec)
198 | jQuery.template(null, htmlExpr.test(name) ? name : jQuery(name)))) : null;
199 | },
200 |
201 | encode: function(text) {
202 | // Do HTML encoding replacing < > & and ' and " by corresponding entities.
203 | return ("" + text).split("<").join("<").split(">").join(">").split('"').join(""").split("'").join("'");
204 | }
205 | });
206 |
207 | jQuery.extend(jQuery.tmpl, {
208 | tag: {
209 | "tmpl": {
210 | _default: { $2: "null" },
211 | open: "if($notnull_1){_=_.concat($item.nest($1,$2));}"
212 | // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
213 | // This means that {{tmpl foo}} treats foo as a template (which IS a function).
214 | // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
215 | },
216 | "wrap": {
217 | _default: { $2: "null" },
218 | open: "$item.calls(_,$1,$2);_=[];",
219 | close: "call=$item.calls();_=call._.concat($item.wrap(call,_));"
220 | },
221 | "each": {
222 | _default: { $2: "$index, $value" },
223 | open: "if($notnull_1){$.each($1a,function($2){with(this){",
224 | close: "}});}"
225 | },
226 | "if": {
227 | open: "if(($notnull_1) && $1a){",
228 | close: "}"
229 | },
230 | "else": {
231 | _default: { $1: "true" },
232 | open: "}else if(($notnull_1) && $1a){"
233 | },
234 | "html": {
235 | // Unecoded expression evaluation.
236 | open: "if($notnull_1){_.push($1a);}"
237 | },
238 | "=": {
239 | // Encoded expression evaluation. Abbreviated form is ${}.
240 | _default: { $1: "$data" },
241 | open: "if($notnull_1){_.push($.encode($1a));}"
242 | },
243 | "!": {
244 | // Comment tag. Skipped by parser
245 | open: ""
246 | }
247 | },
248 |
249 | // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
250 | complete: function(items) {
251 | newTmplItems = {};
252 | },
253 |
254 | // Call this from code which overrides domManip, or equivalent
255 | // Manage cloning/storing template items etc.
256 | afterManip: function afterManip(elem, fragClone, callback) {
257 | // Provides cloned fragment ready for fixup prior to and after insertion into DOM
258 | var content = fragClone.nodeType === 11 ?
259 | jQuery.makeArray(fragClone.childNodes) :
260 | fragClone.nodeType === 1 ? [fragClone] : [];
261 |
262 | // Return fragment to original caller (e.g. append) for DOM insertion
263 | callback.call(elem, fragClone);
264 |
265 | // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
266 | storeTmplItems(content);
267 | cloneIndex++;
268 | }
269 | });
270 |
271 | //========================== Private helper functions, used by code above ==========================
272 |
273 | function build(tmplItem, nested, content) {
274 | // Convert hierarchical content into flat string array
275 | // and finally return array of fragments ready for DOM insertion
276 | var frag, ret = content ? jQuery.map(content, function(item) {
277 | return (typeof item === "string") ?
278 | // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
279 | (tmplItem.key ? item.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2") : item) :
280 | // This is a child template item. Build nested template.
281 | build(item, tmplItem, item._ctnt);
282 | }) :
283 | // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}.
284 | tmplItem;
285 | if (nested) {
286 | return ret;
287 | }
288 |
289 | // top-level template
290 | ret = ret.join("");
291 |
292 | // Support templates which have initial or final text nodes, or consist only of text
293 | // Also support HTML entities within the HTML markup.
294 | ret.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function(all, before, middle, after) {
295 | frag = jQuery(middle).get();
296 |
297 | storeTmplItems(frag);
298 | if (before) {
299 | frag = unencode(before).concat(frag);
300 | }
301 | if (after) {
302 | frag = frag.concat(unencode(after));
303 | }
304 | });
305 | return frag ? frag : unencode(ret);
306 | }
307 |
308 | function unencode(text) {
309 | // Use createElement, since createTextNode will not render HTML entities correctly
310 | var el = document.createElement("div");
311 | el.innerHTML = text;
312 | return jQuery.makeArray(el.childNodes);
313 | }
314 |
315 | // Generate a reusable function that will serve to render a template against data
316 | function buildTmplFn(markup) {
317 | return new Function("jQuery", "$item",
318 | "var $=jQuery,call,_=[],$data=$item.data;" +
319 |
320 | // Introduce the data as local variables using with(){}
321 | "with($data){_.push('" +
322 |
323 | // Convert the template into pure JavaScript
324 | jQuery.trim(markup)
325 | .replace(/([\\'])/g, "\\$1")
326 | .replace(/[\r\t\n]/g, " ")
327 | .replace(/\$\{([^\}]*)\}/g, "{{= $1}}")
328 | .replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
329 | function(all, slash, type, fnargs, target, parens, args) {
330 | var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
331 | if (!tag) {
332 | throw "Template command not found: " + type;
333 | }
334 | def = tag._default || [];
335 | if (parens && !/\w$/.test(target)) {
336 | target += parens;
337 | parens = "";
338 | }
339 | if (target) {
340 | target = unescape(target);
341 | args = args ? ("," + unescape(args) + ")") : (parens ? ")" : "");
342 | // Support for target being things like a.toLowerCase();
343 | // In that case don't call with template item as 'this' pointer. Just evaluate...
344 | expr = parens ? (target.indexOf(".") > -1 ? target + parens : ("(" + target + ").call($item" + args)) : target;
345 | exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
346 | } else {
347 | exprAutoFnDetect = expr = def.$1 || "null";
348 | }
349 | fnargs = unescape(fnargs);
350 | return "');" +
351 | tag[ slash ? "close" : "open" ]
352 | .split("$notnull_1").join(target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true")
353 | .split("$1a").join(exprAutoFnDetect)
354 | .split("$1").join(expr)
355 | .split("$2").join(fnargs ?
356 | fnargs.replace(/\s*([^\(]+)\s*(\((.*?)\))?/g, function(all, name, parens, params) {
357 | params = params ? ("," + params + ")") : (parens ? ")" : "");
358 | return params ? ("(" + name + ").call($item" + params) : all;
359 | })
360 | : (def.$2 || "")
361 | ) +
362 | "_.push('";
363 | }) +
364 | "');}return _;"
365 | );
366 | }
367 |
368 | function updateWrapped(options, wrapped) {
369 | // Build the wrapped content.
370 | options._wrap = build(options, true,
371 | // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
372 | jQuery.isArray(wrapped) ? wrapped : [htmlExpr.test(wrapped) ? wrapped : jQuery(wrapped).html()]
373 | ).join("");
374 | }
375 |
376 | function unescape(args) {
377 | return args ? args.replace(/\\'/g, "'").replace(/\\\\/g, "\\") : null;
378 | }
379 |
380 | function outerHtml(elem) {
381 | var div = document.createElement("div");
382 | div.appendChild(elem.cloneNode(true));
383 | return div.innerHTML;
384 | }
385 |
386 | // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
387 | function storeTmplItems(content) {
388 | var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
389 | for (i = 0,l = content.length; i < l; i++) {
390 | if ((elem = content[i]).nodeType !== 1) {
391 | continue;
392 | }
393 | elems = elem.getElementsByTagName("*");
394 | for (m = elems.length - 1; m >= 0; m--) {
395 | processItemKey(elems[m]);
396 | }
397 | processItemKey(elem);
398 | }
399 | function processItemKey(el) {
400 | var pntKey, pntNode = el, pntItem, tmplItem, key;
401 | // Ensure that each rendered template inserted into the DOM has its own template item,
402 | if ((key = el.getAttribute(tmplItmAtt))) {
403 | while (pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute(tmplItmAtt))) {
404 | }
405 | if (pntKey !== key) {
406 | // The next ancestor with a _tmplitem expando is on a different key than this one.
407 | // So this is a top-level element within this template item
408 | // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
409 | pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute(tmplItmAtt) || 0)) : 0;
410 | if (!(tmplItem = newTmplItems[key])) {
411 | // The item is for wrapped content, and was copied from the temporary parent wrappedItem.
412 | tmplItem = wrappedItems[key];
413 | tmplItem = newTmplItem(tmplItem, newTmplItems[pntNode] || wrappedItems[pntNode], null, true);
414 | tmplItem.key = ++itemKey;
415 | newTmplItems[itemKey] = tmplItem;
416 | }
417 | if (cloneIndex) {
418 | cloneTmplItem(key);
419 | }
420 | }
421 | el.removeAttribute(tmplItmAtt);
422 | } else if (cloneIndex && (tmplItem = jQuery.data(el, "tmplItem"))) {
423 | // This was a rendered element, cloned during append or appendTo etc.
424 | // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
425 | cloneTmplItem(tmplItem.key);
426 | newTmplItems[tmplItem.key] = tmplItem;
427 | pntNode = jQuery.data(el.parentNode, "tmplItem");
428 | pntNode = pntNode ? pntNode.key : 0;
429 | }
430 | if (tmplItem) {
431 | pntItem = tmplItem;
432 | // Find the template item of the parent element.
433 | // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
434 | while (pntItem && pntItem.key != pntNode) {
435 | // Add this element as a top-level node for this rendered template item, as well as for any
436 | // ancestor items between this item and the item of its parent element
437 | pntItem.nodes.push(el);
438 | pntItem = pntItem.parent;
439 | }
440 | // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
441 | delete tmplItem._ctnt;
442 | delete tmplItem._wrap;
443 | // Store template item as jQuery data on the element
444 | jQuery.data(el, "tmplItem", tmplItem);
445 | }
446 | function cloneTmplItem(key) {
447 | key = key + keySuffix;
448 | tmplItem = newClonedItems[key] =
449 | (newClonedItems[key] || newTmplItem(tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent, null, true));
450 | }
451 | }
452 | }
453 |
454 | //---- Helper functions for template item ----
455 |
456 | function tiCalls(content, tmpl, data, options) {
457 | if (!content) {
458 | return stack.pop();
459 | }
460 | stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options });
461 | }
462 |
463 | function tiNest(tmpl, data, options) {
464 | // nested template, using {{tmpl}} tag
465 | return jQuery.tmpl(jQuery.template(tmpl), data, options, this);
466 | }
467 |
468 | function tiWrap(call, wrapped) {
469 | // nested template, using {{wrap}} tag
470 | var options = call.options || {};
471 | options.wrapped = wrapped;
472 | // Apply the template, which may incorporate wrapped content,
473 | return jQuery.tmpl(jQuery.template(call.tmpl), call.data, options, call.item);
474 | }
475 |
476 | function tiHtml(filter, textOnly) {
477 | var wrapped = this._wrap;
478 | return jQuery.map(
479 | jQuery(jQuery.isArray(wrapped) ? wrapped.join("") : wrapped).filter(filter || "*"),
480 | function(e) {
481 | return textOnly ?
482 | e.innerText || e.textContent :
483 | e.outerHTML || outerHtml(e);
484 | });
485 | }
486 |
487 | function tiUpdate() {
488 | var coll = this.nodes;
489 | jQuery.tmpl(null, null, null, this).insertBefore(coll[0]);
490 | jQuery(coll).remove();
491 | }
492 | })(jQuery);
493 |
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/javascripts/chosen.jquery.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | /*
3 | Chosen, a Select Box Enhancer for jQuery and Protoype
4 | by Patrick Filler for Harvest, http://getharvest.com
5 |
6 | Available for use under the MIT License, http://en.wikipedia.org/wiki/MIT_License
7 |
8 | Copyright (c) 2011 by Harvest
9 | */ var $, Chosen, SelectParser, get_side_border_padding, root;
10 | var __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
11 | root = typeof exports !== "undefined" && exports !== null ? exports : this;
12 | $ = jQuery;
13 | $.fn.extend({
14 | chosen: function(data, options) {
15 | return $(this).each(function(input_field) {
16 | if (!($(this)).hasClass("chzn-done")) {
17 | return new Chosen(this, data, options);
18 | }
19 | });
20 | }
21 | });
22 | Chosen = (function() {
23 | function Chosen(elmn) {
24 | this.set_default_values();
25 | this.form_field = elmn;
26 | this.form_field_jq = $(this.form_field);
27 | this.is_multiple = this.form_field.multiple;
28 | this.default_text_default = this.form_field.multiple ? "Select Some Options" : "Select an Option";
29 | this.set_up_html();
30 | this.register_observers();
31 | this.form_field_jq.addClass("chzn-done");
32 | }
33 | Chosen.prototype.set_default_values = function() {
34 | this.click_test_action = __bind(function(evt) {
35 | return this.test_active_click(evt);
36 | }, this);
37 | this.active_field = false;
38 | this.mouse_on_container = false;
39 | this.results_showing = false;
40 | this.result_highlighted = null;
41 | this.result_single_selected = null;
42 | return this.choices = 0;
43 | };
44 | Chosen.prototype.set_up_html = function() {
45 | var container_div, dd_top, dd_width, sf_width;
46 | this.container_id = this.form_field.id.length ? this.form_field.id.replace('.', '_') : this.generate_field_id();
47 | this.container_id += "_chzn";
48 | this.f_width = this.form_field_jq.width();
49 | this.default_text = this.form_field_jq.attr('title') ? this.form_field_jq.attr('title') : this.default_text_default;
50 | container_div = $("", {
51 | id: this.container_id,
52 | "class": 'chzn-container',
53 | style: 'width: ' + this.f_width + 'px;'
54 | });
55 | if (this.is_multiple) {
56 | container_div.html('');
57 | } else {
58 | container_div.html('' + this.default_text + '
');
59 | }
60 | this.form_field_jq.hide().after(container_div);
61 | this.container = $('#' + this.container_id);
62 | this.container.addClass("chzn-container-" + (this.is_multiple ? "multi" : "single"));
63 | this.dropdown = this.container.find('div.chzn-drop').first();
64 | dd_top = this.container.height();
65 | dd_width = this.f_width - get_side_border_padding(this.dropdown);
66 | this.dropdown.css({
67 | "width": dd_width + "px",
68 | "top": dd_top + "px"
69 | });
70 | this.search_field = this.container.find('input').first();
71 | this.search_results = this.container.find('ul.chzn-results').first();
72 | this.search_field_scale();
73 | this.search_no_results = this.container.find('li.no-results').first();
74 | if (this.is_multiple) {
75 | this.search_choices = this.container.find('ul.chzn-choices').first();
76 | this.search_container = this.container.find('li.search-field').first();
77 | } else {
78 | this.search_container = this.container.find('div.chzn-search').first();
79 | this.selected_item = this.container.find('.chzn-single').first();
80 | sf_width = dd_width - get_side_border_padding(this.search_container) - get_side_border_padding(this.search_field);
81 | this.search_field.css({
82 | "width": sf_width + "px"
83 | });
84 | }
85 | this.results_build();
86 | return this.set_tab_index();
87 | };
88 | Chosen.prototype.register_observers = function() {
89 | this.container.click(__bind(function(evt) {
90 | return this.container_click(evt);
91 | }, this));
92 | this.container.mouseenter(__bind(function(evt) {
93 | return this.mouse_enter(evt);
94 | }, this));
95 | this.container.mouseleave(__bind(function(evt) {
96 | return this.mouse_leave(evt);
97 | }, this));
98 | this.search_results.click(__bind(function(evt) {
99 | return this.search_results_click(evt);
100 | }, this));
101 | this.search_results.mouseover(__bind(function(evt) {
102 | return this.search_results_mouseover(evt);
103 | }, this));
104 | this.search_results.mouseout(__bind(function(evt) {
105 | return this.search_results_mouseout(evt);
106 | }, this));
107 | this.form_field_jq.bind("liszt:updated", __bind(function(evt) {
108 | return this.results_update_field(evt);
109 | }, this));
110 | this.search_field.blur(__bind(function(evt) {
111 | return this.input_blur(evt);
112 | }, this));
113 | this.search_field.keyup(__bind(function(evt) {
114 | return this.keyup_checker(evt);
115 | }, this));
116 | this.search_field.keydown(__bind(function(evt) {
117 | return this.keydown_checker(evt);
118 | }, this));
119 | if (this.is_multiple) {
120 | this.search_choices.click(__bind(function(evt) {
121 | return this.choices_click(evt);
122 | }, this));
123 | return this.search_field.focus(__bind(function(evt) {
124 | return this.input_focus(evt);
125 | }, this));
126 | } else {
127 | return this.selected_item.focus(__bind(function(evt) {
128 | return this.activate_field(evt);
129 | }, this));
130 | }
131 | };
132 | Chosen.prototype.container_click = function(evt) {
133 | if (evt && evt.type === "click") {
134 | evt.stopPropagation();
135 | }
136 | if (!this.pending_destroy_click) {
137 | if (!this.active_field) {
138 | if (this.is_multiple) {
139 | this.search_field.val("");
140 | }
141 | $(document).click(this.click_test_action);
142 | this.results_show();
143 | } else if (!this.is_multiple && evt && ($(evt.target) === this.selected_item || $(evt.target).parents("a.chzn-single").length)) {
144 | evt.preventDefault();
145 | this.results_toggle();
146 | }
147 | return this.activate_field();
148 | } else {
149 | return this.pending_destroy_click = false;
150 | }
151 | };
152 | Chosen.prototype.mouse_enter = function() {
153 | return this.mouse_on_container = true;
154 | };
155 | Chosen.prototype.mouse_leave = function() {
156 | return this.mouse_on_container = false;
157 | };
158 | Chosen.prototype.input_focus = function(evt) {
159 | if (!this.active_field) {
160 | return setTimeout((__bind(function() {
161 | return this.container_click();
162 | }, this)), 50);
163 | }
164 | };
165 | Chosen.prototype.input_blur = function(evt) {
166 | if (!this.mouse_on_container) {
167 | this.active_field = false;
168 | return setTimeout((__bind(function() {
169 | return this.blur_test();
170 | }, this)), 100);
171 | }
172 | };
173 | Chosen.prototype.blur_test = function(evt) {
174 | if (!this.active_field && this.container.hasClass("chzn-container-active")) {
175 | return this.close_field();
176 | }
177 | };
178 | Chosen.prototype.close_field = function() {
179 | $(document).unbind("click", this.click_test_action);
180 | if (!this.is_multiple) {
181 | this.selected_item.attr("tabindex", this.search_field.attr("tabindex"));
182 | this.search_field.attr("tabindex", -1);
183 | }
184 | this.active_field = false;
185 | this.results_hide();
186 | this.container.removeClass("chzn-container-active");
187 | this.winnow_results_clear();
188 | this.clear_backstroke();
189 | this.show_search_field_default();
190 | return this.search_field_scale();
191 | };
192 | Chosen.prototype.activate_field = function() {
193 | if (!this.is_multiple && !this.active_field) {
194 | this.search_field.attr("tabindex", this.selected_item.attr("tabindex"));
195 | this.selected_item.attr("tabindex", -1);
196 | }
197 | this.container.addClass("chzn-container-active");
198 | this.active_field = true;
199 | this.search_field.val(this.search_field.val());
200 | return this.search_field.focus();
201 | };
202 | Chosen.prototype.test_active_click = function(evt) {
203 | if ($(evt.target).parents('#' + this.container_id).length) {
204 | return this.active_field = true;
205 | } else {
206 | return this.close_field();
207 | }
208 | };
209 | Chosen.prototype.results_build = function() {
210 | var content, data, startTime, _i, _len, _ref;
211 | startTime = new Date();
212 | this.parsing = true;
213 | this.results_data = SelectParser.select_to_array(this.form_field);
214 | if (this.is_multiple && this.choices > 0) {
215 | this.search_choices.find("li.search-choice").remove();
216 | this.choices = 0;
217 | } else if (!this.is_multiple) {
218 | this.selected_item.find("span").text(this.default_text);
219 | }
220 | content = '';
221 | _ref = this.results_data;
222 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
223 | data = _ref[_i];
224 | if (data.group) {
225 | content += this.result_add_group(data);
226 | } else if (!data.empty) {
227 | content += this.result_add_option(data);
228 | if (data.selected && this.is_multiple) {
229 | this.choice_build(data);
230 | } else if (data.selected && !this.is_multiple) {
231 | this.selected_item.find("span").text(data.text);
232 | }
233 | }
234 | }
235 | this.show_search_field_default();
236 | this.search_field_scale();
237 | this.search_results.html(content);
238 | return this.parsing = false;
239 | };
240 | Chosen.prototype.result_add_group = function(group) {
241 | if (!group.disabled) {
242 | group.dom_id = this.container_id + "_g_" + group.array_index;
243 | return '' + $("").text(group.label).html() + '';
244 | } else {
245 | return "";
246 | }
247 | };
248 | Chosen.prototype.result_add_option = function(option) {
249 | var classes;
250 | if (!option.disabled) {
251 | option.dom_id = this.container_id + "_o_" + option.array_index;
252 | classes = option.selected && this.is_multiple ? [] : ["active-result"];
253 | if (option.selected) {
254 | classes.push("result-selected");
255 | }
256 | if (option.group_array_index != null) {
257 | classes.push("group-option");
258 | }
259 | return '' + $("").text(option.text).html() + '';
260 | } else {
261 | return "";
262 | }
263 | };
264 | Chosen.prototype.results_update_field = function() {
265 | this.result_clear_highlight();
266 | this.result_single_selected = null;
267 | return this.results_build();
268 | };
269 | Chosen.prototype.result_do_highlight = function(el) {
270 | var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
271 | if (el.length) {
272 | this.result_clear_highlight();
273 | this.result_highlight = el;
274 | this.result_highlight.addClass("highlighted");
275 | maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
276 | visible_top = this.search_results.scrollTop();
277 | visible_bottom = maxHeight + visible_top;
278 | high_top = this.result_highlight.position().top + this.search_results.scrollTop();
279 | high_bottom = high_top + this.result_highlight.outerHeight();
280 | if (high_bottom >= visible_bottom) {
281 | return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
282 | } else if (high_top < visible_top) {
283 | return this.search_results.scrollTop(high_top);
284 | }
285 | }
286 | };
287 | Chosen.prototype.result_clear_highlight = function() {
288 | if (this.result_highlight) {
289 | this.result_highlight.removeClass("highlighted");
290 | }
291 | return this.result_highlight = null;
292 | };
293 | Chosen.prototype.results_toggle = function() {
294 | if (this.results_showing) {
295 | return this.results_hide();
296 | } else {
297 | return this.results_show();
298 | }
299 | };
300 | Chosen.prototype.results_show = function() {
301 | var dd_top;
302 | if (!this.is_multiple) {
303 | this.selected_item.addClass("chzn-single-with-drop");
304 | if (this.result_single_selected) {
305 | this.result_do_highlight(this.result_single_selected);
306 | }
307 | }
308 | dd_top = this.is_multiple ? this.container.height() : this.container.height() - 1;
309 | this.dropdown.css({
310 | "top": dd_top + "px",
311 | "left": 0
312 | });
313 | this.results_showing = true;
314 | this.search_field.focus();
315 | this.search_field.val(this.search_field.val());
316 | return this.winnow_results();
317 | };
318 | Chosen.prototype.results_hide = function() {
319 | if (!this.is_multiple) {
320 | this.selected_item.removeClass("chzn-single-with-drop");
321 | }
322 | this.result_clear_highlight();
323 | this.dropdown.css({
324 | "left": "-9000px"
325 | });
326 | return this.results_showing = false;
327 | };
328 | Chosen.prototype.set_tab_index = function(el) {
329 | var ti;
330 | if (this.form_field_jq.attr("tabindex")) {
331 | ti = this.form_field_jq.attr("tabindex");
332 | this.form_field_jq.attr("tabindex", -1);
333 | if (this.is_multiple) {
334 | return this.search_field.attr("tabindex", ti);
335 | } else {
336 | this.selected_item.attr("tabindex", ti);
337 | return this.search_field.attr("tabindex", -1);
338 | }
339 | }
340 | };
341 | Chosen.prototype.show_search_field_default = function() {
342 | if (this.is_multiple && this.choices < 1 && !this.active_field) {
343 | this.search_field.val(this.default_text);
344 | return this.search_field.addClass("default");
345 | } else {
346 | this.search_field.val("");
347 | return this.search_field.removeClass("default");
348 | }
349 | };
350 | Chosen.prototype.search_results_click = function(evt) {
351 | var target;
352 | target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
353 | if (target.length) {
354 | this.result_highlight = target;
355 | return this.result_select();
356 | }
357 | };
358 | Chosen.prototype.search_results_mouseover = function(evt) {
359 | var target;
360 | target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
361 | if (target) {
362 | return this.result_do_highlight(target);
363 | }
364 | };
365 | Chosen.prototype.search_results_mouseout = function(evt) {
366 | if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
367 | return this.result_clear_highlight();
368 | }
369 | };
370 | Chosen.prototype.choices_click = function(evt) {
371 | evt.preventDefault();
372 | if (this.active_field && !($(evt.target).hasClass("search-choice" || $(evt.target).parents('.search-choice').first)) && !this.results_showing) {
373 | return this.results_show();
374 | }
375 | };
376 | Chosen.prototype.choice_build = function(item) {
377 | var choice_id, link;
378 | choice_id = this.container_id + "_c_" + item.array_index;
379 | this.choices += 1;
380 | this.search_container.before('' + item.text + '');
381 | link = $('#' + choice_id).find("a").first();
382 | return link.click(__bind(function(evt) {
383 | return this.choice_destroy_link_click(evt);
384 | }, this));
385 | };
386 | Chosen.prototype.choice_destroy_link_click = function(evt) {
387 | evt.preventDefault();
388 | this.pending_destroy_click = true;
389 | return this.choice_destroy($(evt.target));
390 | };
391 | Chosen.prototype.choice_destroy = function(link) {
392 | this.choices -= 1;
393 | this.show_search_field_default();
394 | if (this.is_multiple && this.choices > 0 && this.search_field.val().length < 1) {
395 | this.results_hide();
396 | }
397 | this.result_deselect(link.attr("rel"));
398 | return link.parents('li').first().remove();
399 | };
400 | Chosen.prototype.result_select = function() {
401 | var high, high_id, item, position;
402 | if (this.result_highlight) {
403 | high = this.result_highlight;
404 | high_id = high.attr("id");
405 | this.result_clear_highlight();
406 | high.addClass("result-selected");
407 | if (this.is_multiple) {
408 | this.result_deactivate(high);
409 | } else {
410 | this.result_single_selected = high;
411 | }
412 | position = high_id.substr(high_id.lastIndexOf("_") + 1);
413 | item = this.results_data[position];
414 | item.selected = true;
415 | this.form_field.options[item.options_index].selected = true;
416 | if (this.is_multiple) {
417 | this.choice_build(item);
418 | } else {
419 | this.selected_item.find("span").first().text(item.text);
420 | }
421 | this.results_hide();
422 | this.search_field.val("");
423 | this.form_field_jq.trigger("change");
424 | return this.search_field_scale();
425 | }
426 | };
427 | Chosen.prototype.result_activate = function(el) {
428 | return el.addClass("active-result").show();
429 | };
430 | Chosen.prototype.result_deactivate = function(el) {
431 | return el.removeClass("active-result").hide();
432 | };
433 | Chosen.prototype.result_deselect = function(pos) {
434 | var result, result_data;
435 | result_data = this.results_data[pos];
436 | result_data.selected = false;
437 | this.form_field.options[result_data.options_index].selected = false;
438 | result = $("#" + this.container_id + "_o_" + pos);
439 | result.removeClass("result-selected").addClass("active-result").show();
440 | this.result_clear_highlight();
441 | this.winnow_results();
442 | this.form_field_jq.trigger("change");
443 | return this.search_field_scale();
444 | };
445 | Chosen.prototype.results_search = function(evt) {
446 | if (this.results_showing) {
447 | return this.winnow_results();
448 | } else {
449 | return this.results_show();
450 | }
451 | };
452 | Chosen.prototype.winnow_results = function() {
453 | var found, option, part, parts, regex, result_id, results, searchText, startTime, startpos, text, zregex, _i, _j, _len, _len2, _ref;
454 | startTime = new Date();
455 | this.no_results_clear();
456 | results = 0;
457 | searchText = this.search_field.val() === this.default_text ? "" : $.trim(this.search_field.val());
458 | regex = new RegExp('^' + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
459 | zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
460 | _ref = this.results_data;
461 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
462 | option = _ref[_i];
463 | if (!option.disabled && !option.empty) {
464 | if (option.group) {
465 | $('#' + option.dom_id).hide();
466 | } else if (!(this.is_multiple && option.selected)) {
467 | found = false;
468 | result_id = option.dom_id;
469 | if (regex.test(option.text)) {
470 | found = true;
471 | results += 1;
472 | } else if (option.text.indexOf(" ") >= 0 || option.text.indexOf("[") === 0) {
473 | parts = option.text.replace(/\[|\]/g, "").split(" ");
474 | if (parts.length) {
475 | for (_j = 0, _len2 = parts.length; _j < _len2; _j++) {
476 | part = parts[_j];
477 | if (regex.test(part)) {
478 | found = true;
479 | results += 1;
480 | }
481 | }
482 | }
483 | }
484 | if (found) {
485 | if (searchText.length) {
486 | startpos = option.text.search(zregex);
487 | text = option.text.substr(0, startpos + searchText.length) + '' + option.text.substr(startpos + searchText.length);
488 | text = text.substr(0, startpos) + '' + text.substr(startpos);
489 | } else {
490 | text = option.text;
491 | }
492 | if ($("#" + result_id).html !== text) {
493 | $("#" + result_id).html(text);
494 | }
495 | this.result_activate($("#" + result_id));
496 | if (option.group_array_index != null) {
497 | $("#" + this.results_data[option.group_array_index].dom_id).show();
498 | }
499 | } else {
500 | if (this.result_highlight && result_id === this.result_highlight.attr('id')) {
501 | this.result_clear_highlight();
502 | }
503 | this.result_deactivate($("#" + result_id));
504 | }
505 | }
506 | }
507 | }
508 | if (results < 1 && searchText.length) {
509 | return this.no_results(searchText);
510 | } else {
511 | return this.winnow_results_set_highlight();
512 | }
513 | };
514 | Chosen.prototype.winnow_results_clear = function() {
515 | var li, lis, _i, _len, _results;
516 | this.search_field.val("");
517 | lis = this.search_results.find("li");
518 | _results = [];
519 | for (_i = 0, _len = lis.length; _i < _len; _i++) {
520 | li = lis[_i];
521 | li = $(li);
522 | _results.push(li.hasClass("group-result") ? li.show() : !this.is_multiple || !li.hasClass("result-selected") ? this.result_activate(li) : void 0);
523 | }
524 | return _results;
525 | };
526 | Chosen.prototype.winnow_results_set_highlight = function() {
527 | var do_high;
528 | if (!this.result_highlight) {
529 | do_high = this.search_results.find(".active-result").first();
530 | if (do_high) {
531 | return this.result_do_highlight(do_high);
532 | }
533 | }
534 | };
535 | Chosen.prototype.no_results = function(terms) {
536 | var no_results_html;
537 | no_results_html = $('No results match ""');
538 | no_results_html.find("span").first().text(terms);
539 | return this.search_results.append(no_results_html);
540 | };
541 | Chosen.prototype.no_results_clear = function() {
542 | return this.search_results.find(".no-results").remove();
543 | };
544 | Chosen.prototype.keydown_arrow = function() {
545 | var first_active, next_sib;
546 | if (!this.result_highlight) {
547 | first_active = this.search_results.find("li.active-result").first();
548 | if (first_active) {
549 | this.result_do_highlight($(first_active));
550 | }
551 | } else if (this.results_showing) {
552 | next_sib = this.result_highlight.nextAll("li.active-result").first();
553 | if (next_sib) {
554 | this.result_do_highlight(next_sib);
555 | }
556 | }
557 | if (!this.results_showing) {
558 | return this.results_show();
559 | }
560 | };
561 | Chosen.prototype.keyup_arrow = function() {
562 | var prev_sibs;
563 | if (!this.results_showing && !this.is_multiple) {
564 | return this.results_show();
565 | } else if (this.result_highlight) {
566 | prev_sibs = this.result_highlight.prevAll("li.active-result");
567 | if (prev_sibs.length) {
568 | return this.result_do_highlight(prev_sibs.first());
569 | } else {
570 | if (this.choices > 0) {
571 | this.results_hide();
572 | }
573 | return this.result_clear_highlight();
574 | }
575 | }
576 | };
577 | Chosen.prototype.keydown_backstroke = function() {
578 | if (this.pending_backstroke) {
579 | this.choice_destroy(this.pending_backstroke.find("a").first());
580 | return this.clear_backstroke();
581 | } else {
582 | this.pending_backstroke = this.search_container.siblings("li.search-choice").last();
583 | return this.pending_backstroke.addClass("search-choice-focus");
584 | }
585 | };
586 | Chosen.prototype.clear_backstroke = function() {
587 | if (this.pending_backstroke) {
588 | this.pending_backstroke.removeClass("search-choice-focus");
589 | }
590 | return this.pending_backstroke = null;
591 | };
592 | Chosen.prototype.keyup_checker = function(evt) {
593 | var stroke, _ref;
594 | stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
595 | this.search_field_scale();
596 | switch (stroke) {
597 | case 8:
598 | if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) {
599 | return this.keydown_backstroke();
600 | } else if (!this.pending_backstroke) {
601 | this.result_clear_highlight();
602 | return this.results_search();
603 | }
604 | break;
605 | case 13:
606 | evt.preventDefault();
607 | if (this.results_showing) {
608 | return this.result_select();
609 | }
610 | break;
611 | case 27:
612 | if (this.results_showing) {
613 | return this.results_hide();
614 | }
615 | break;
616 | case 9:
617 | case 38:
618 | case 40:
619 | case 16:
620 | break;
621 | default:
622 | return this.results_search();
623 | }
624 | };
625 | Chosen.prototype.keydown_checker = function(evt) {
626 | var stroke, _ref;
627 | stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
628 | this.search_field_scale();
629 | if (stroke !== 8 && this.pending_backstroke) {
630 | this.clear_backstroke();
631 | }
632 | switch (stroke) {
633 | case 8:
634 | this.backstroke_length = this.search_field.val().length;
635 | break;
636 | case 9:
637 | this.mouse_on_container = false;
638 | break;
639 | case 13:
640 | evt.preventDefault();
641 | break;
642 | case 38:
643 | evt.preventDefault();
644 | this.keyup_arrow();
645 | break;
646 | case 40:
647 | this.keydown_arrow();
648 | break;
649 | }
650 | };
651 | Chosen.prototype.search_field_scale = function() {
652 | var dd_top, div, h, style, style_block, styles, w, _i, _len;
653 | if (this.is_multiple) {
654 | h = 0;
655 | w = 0;
656 | style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
657 | styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
658 | for (_i = 0, _len = styles.length; _i < _len; _i++) {
659 | style = styles[_i];
660 | style_block += style + ":" + this.search_field.css(style) + ";";
661 | }
662 | div = $('', {
663 | 'style': style_block
664 | });
665 | div.text(this.search_field.val());
666 | $('body').append(div);
667 | w = div.width() + 25;
668 | div.remove();
669 | if (w > this.f_width - 10) {
670 | w = this.f_width - 10;
671 | }
672 | this.search_field.css({
673 | 'width': w + 'px'
674 | });
675 | dd_top = this.container.height();
676 | return this.dropdown.css({
677 | "top": dd_top + "px"
678 | });
679 | }
680 | };
681 | Chosen.prototype.generate_field_id = function() {
682 | var new_id;
683 | new_id = this.generate_random_id();
684 | this.form_field.id = new_id;
685 | return new_id;
686 | };
687 | Chosen.prototype.generate_random_id = function() {
688 | var string;
689 | string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char();
690 | while ($("#" + string).length > 0) {
691 | string += this.generate_random_char();
692 | }
693 | return string;
694 | };
695 | Chosen.prototype.generate_random_char = function() {
696 | var chars, newchar, rand;
697 | chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZ";
698 | rand = Math.floor(Math.random() * chars.length);
699 | return newchar = chars.substring(rand, rand + 1);
700 | };
701 | return Chosen;
702 | })();
703 | get_side_border_padding = function(elmt) {
704 | var side_border_padding;
705 | return side_border_padding = elmt.outerWidth() - elmt.width();
706 | };
707 | root.get_side_border_padding = get_side_border_padding;
708 | SelectParser = (function() {
709 | function SelectParser() {
710 | this.options_index = 0;
711 | this.parsed = [];
712 | }
713 | SelectParser.prototype.add_node = function(child) {
714 | if (child.nodeName === "OPTGROUP") {
715 | return this.add_group(child);
716 | } else {
717 | return this.add_option(child);
718 | }
719 | };
720 | SelectParser.prototype.add_group = function(group) {
721 | var group_position, option, _i, _len, _ref, _results;
722 | group_position = this.parsed.length;
723 | this.parsed.push({
724 | array_index: group_position,
725 | group: true,
726 | label: group.label,
727 | children: 0,
728 | disabled: group.disabled
729 | });
730 | _ref = group.childNodes;
731 | _results = [];
732 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
733 | option = _ref[_i];
734 | _results.push(this.add_option(option, group_position, group.disabled));
735 | }
736 | return _results;
737 | };
738 | SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
739 | if (option.nodeName === "OPTION") {
740 | if (option.text !== "") {
741 | if (group_position != null) {
742 | this.parsed[group_position].children += 1;
743 | }
744 | this.parsed.push({
745 | array_index: this.parsed.length,
746 | options_index: this.options_index,
747 | value: option.value,
748 | text: option.text,
749 | selected: option.selected,
750 | disabled: group_disabled === true ? group_disabled : option.disabled,
751 | group_array_index: group_position
752 | });
753 | } else {
754 | this.parsed.push({
755 | array_index: this.parsed.length,
756 | options_index: this.options_index,
757 | empty: true
758 | });
759 | }
760 | return this.options_index += 1;
761 | }
762 | };
763 | return SelectParser;
764 | })();
765 | SelectParser.select_to_array = function(select) {
766 | var child, parser, _i, _len, _ref;
767 | parser = new SelectParser();
768 | _ref = select.childNodes;
769 | for (_i = 0, _len = _ref.length; _i < _len; _i++) {
770 | child = _ref[_i];
771 | parser.add_node(child);
772 | }
773 | return parser.parsed;
774 | };
775 | root.SelectParser = SelectParser;
776 | }).call(this);
777 |
--------------------------------------------------------------------------------
/samples/play2/todolist/public/swagger-ui/stylesheets/screen.css:
--------------------------------------------------------------------------------
1 | html, body, div, span, applet, object, iframe,
2 | h1, h2, h3, h4, h5, h6, p, blockquote, pre,
3 | a, abbr, acronym, address, big, cite, code,
4 | del, dfn, em, img, ins, kbd, q, s, samp,
5 | small, strike, strong, sub, sup, tt, var,
6 | b, u, i, center,
7 | dl, dt, dd, ol, ul, li,
8 | fieldset, form, label, legend,
9 | table, caption, tbody, tfoot, thead, tr, th, td,
10 | article, aside, canvas, details, embed,
11 | figure, figcaption, footer, header, hgroup,
12 | menu, nav, output, ruby, section, summary,
13 | time, mark, audio, video {
14 | margin: 0;
15 | padding: 0;
16 | border: 0;
17 | font-size: 100%;
18 | font: inherit;
19 | vertical-align: baseline; }
20 |
21 | body {
22 | line-height: 1; }
23 |
24 | ol, ul {
25 | list-style: none; }
26 |
27 | table {
28 | border-collapse: collapse;
29 | border-spacing: 0; }
30 |
31 | caption, th, td {
32 | text-align: left;
33 | font-weight: normal;
34 | vertical-align: middle; }
35 |
36 | q, blockquote {
37 | quotes: none; }
38 | q:before, q:after, blockquote:before, blockquote:after {
39 | content: "";
40 | content: none; }
41 |
42 | a img {
43 | border: none; }
44 |
45 | article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary {
46 | display: block; }
47 |
48 | h1 a, h2 a, h3 a, h4 a, h5 a, h6 a {
49 | text-decoration: none; }
50 | h1 a:hover, h2 a:hover, h3 a:hover, h4 a:hover, h5 a:hover, h6 a:hover {
51 | text-decoration: underline; }
52 | h1 span.divider, h2 span.divider, h3 span.divider, h4 span.divider, h5 span.divider, h6 span.divider {
53 | color: #aaaaaa; }
54 |
55 | h1 {
56 | color: #547f00;
57 | color: black;
58 | font-size: 1.5em;
59 | line-height: 1.3em;
60 | padding: 10px 0 10px 0;
61 | font-family: "Droid Sans", sans-serif;
62 | font-weight: bold; }
63 |
64 | h2 {
65 | color: #89bf04;
66 | color: black;
67 | font-size: 1.3em;
68 | padding: 10px 0 10px 0; }
69 | h2 a {
70 | color: black; }
71 | h2 span.sub {
72 | font-size: 0.7em;
73 | color: #999999;
74 | font-style: italic; }
75 | h2 span.sub a {
76 | color: #777777; }
77 |
78 | h3 {
79 | color: black;
80 | font-size: 1.1em;
81 | padding: 10px 0 10px 0; }
82 |
83 | div.heading_with_menu {
84 | float: none;
85 | clear: both;
86 | overflow: hidden;
87 | display: block; }
88 | div.heading_with_menu h1, div.heading_with_menu h2, div.heading_with_menu h3, div.heading_with_menu h4, div.heading_with_menu h5, div.heading_with_menu h6 {
89 | display: block;
90 | clear: none;
91 | float: left;
92 | -moz-box-sizing: border-box;
93 | -webkit-box-sizing: border-box;
94 | -ms-box-sizing: border-box;
95 | box-sizing: border-box;
96 | width: 60%; }
97 | div.heading_with_menu ul {
98 | display: block;
99 | clear: none;
100 | float: right;
101 | -moz-box-sizing: border-box;
102 | -webkit-box-sizing: border-box;
103 | -ms-box-sizing: border-box;
104 | box-sizing: border-box;
105 | margin-top: 10px; }
106 |
107 | p {
108 | line-height: 1.4em;
109 | padding: 0 0 10px 0;
110 | color: #333333; }
111 |
112 | ol {
113 | margin: 0px 0 10px 0;
114 | padding: 0 0 0 18px;
115 | list-style-type: decimal; }
116 | ol li {
117 | padding: 5px 0px;
118 | font-size: 0.9em;
119 | color: #333333; }
120 |
121 | .markdown h3 {
122 | color: #547f00; }
123 | .markdown h4 {
124 | color: #666666; }
125 | .markdown pre {
126 | font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace;
127 | background-color: #fcf6db;
128 | border: 1px solid black;
129 | border-color: #e5e0c6;
130 | padding: 10px;
131 | margin: 0 0 10px 0; }
132 | .markdown pre code {
133 | line-height: 1.6em; }
134 | .markdown p code, .markdown li code {
135 | font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace;
136 | background-color: #f0f0f0;
137 | color: black;
138 | padding: 1px 3px; }
139 | .markdown ol, .markdown ul {
140 | font-family: "Droid Sans", sans-serif;
141 | margin: 5px 0 10px 0;
142 | padding: 0 0 0 18px;
143 | list-style-type: disc; }
144 | .markdown ol li, .markdown ul li {
145 | padding: 3px 0px;
146 | line-height: 1.4em;
147 | color: #333333; }
148 |
149 | div.gist {
150 | margin: 20px 0 25px 0 !important; }
151 |
152 | p.big, div.big p {
153 | font-size: 1 em;
154 | margin-bottom: 10px; }
155 |
156 | span.weak {
157 | color: #666666; }
158 | span.blank, span.empty {
159 | color: #888888;
160 | font-style: italic; }
161 |
162 | a {
163 | color: #547f00; }
164 |
165 | strong {
166 | font-family: "Droid Sans", sans-serif;
167 | font-weight: bold;
168 | font-weight: bold; }
169 |
170 | .code {
171 | font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; }
172 |
173 | pre {
174 | font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace;
175 | background-color: #fcf6db;
176 | border: 1px solid black;
177 | border-color: #e5e0c6;
178 | padding: 10px;
179 | /* white-space: pre-line */ }
180 | pre code {
181 | line-height: 1.6em; }
182 |
183 | .required {
184 | font-weight: bold; }
185 |
186 | table.fullwidth {
187 | width: 100%; }
188 | table thead tr th {
189 | padding: 5px;
190 | font-size: 0.9em;
191 | color: #666666;
192 | border-bottom: 1px solid #999999; }
193 | table tbody tr.offset {
194 | background-color: #f5f5f5; }
195 | table tbody tr td {
196 | padding: 6px;
197 | font-size: 0.9em;
198 | border-bottom: 1px solid #cccccc;
199 | vertical-align: top;
200 | line-height: 1.3em; }
201 | table tbody tr:last-child td {
202 | border-bottom: none; }
203 | table tbody tr.offset {
204 | background-color: #f0f0f0; }
205 |
206 | form.form_box {
207 | background-color: #ebf3f9;
208 | border: 1px solid black;
209 | border-color: #c3d9ec;
210 | padding: 10px; }
211 | form.form_box label {
212 | color: #0f6ab4 !important; }
213 | form.form_box input[type=submit] {
214 | display: block;
215 | padding: 10px; }
216 | form.form_box p {
217 | font-size: 0.9em;
218 | padding: 0 0 15px 0;
219 | color: #7e7b6d; }
220 | form.form_box p a {
221 | color: #646257; }
222 | form.form_box p strong {
223 | color: black; }
224 | form.form_box p.weak {
225 | font-size: 0.8em; }
226 | form.formtastic fieldset.inputs ol li p.inline-hints {
227 | margin-left: 0;
228 | font-style: italic;
229 | font-size: 0.9em;
230 | margin: 0; }
231 | form.formtastic fieldset.inputs ol li label {
232 | display: block;
233 | clear: both;
234 | width: auto;
235 | padding: 0 0 3px 0;
236 | color: #666666; }
237 | form.formtastic fieldset.inputs ol li label abbr {
238 | padding-left: 3px;
239 | color: #888888; }
240 | form.formtastic fieldset.inputs ol li.required label {
241 | color: black; }
242 | form.formtastic fieldset.inputs ol li.string input, form.formtastic fieldset.inputs ol li.url input, form.formtastic fieldset.inputs ol li.numeric input {
243 | display: block;
244 | padding: 4px;
245 | width: auto;
246 | clear: both; }
247 | form.formtastic fieldset.inputs ol li.string input.title, form.formtastic fieldset.inputs ol li.url input.title, form.formtastic fieldset.inputs ol li.numeric input.title {
248 | font-size: 1.3em; }
249 | form.formtastic fieldset.inputs ol li.text textarea {
250 | font-family: "Droid Sans", sans-serif;
251 | height: 250px;
252 | padding: 4px;
253 | display: block;
254 | clear: both; }
255 | form.formtastic fieldset.inputs ol li.select select {
256 | display: block;
257 | clear: both; }
258 | form.formtastic fieldset.inputs ol li.boolean {
259 | float: none;
260 | clear: both;
261 | overflow: hidden;
262 | display: block; }
263 | form.formtastic fieldset.inputs ol li.boolean input {
264 | display: block;
265 | float: left;
266 | clear: none;
267 | margin: 0 5px 0 0; }
268 | form.formtastic fieldset.inputs ol li.boolean label {
269 | display: block;
270 | float: left;
271 | clear: none;
272 | margin: 0;
273 | padding: 0; }
274 | form.formtastic fieldset.buttons {
275 | margin: 0;
276 | padding: 0; }
277 | form.fullwidth ol li.string input, form.fullwidth ol li.url input, form.fullwidth ol li.text textarea, form.fullwidth ol li.numeric input {
278 | width: 500px !important; }
279 |
280 | body {
281 | font-family: "Droid Sans", sans-serif; }
282 | body #content_message {
283 | margin: 10px 15px;
284 | font-style: italic;
285 | color: #999999; }
286 | body #header {
287 | background-color: #89bf04;
288 | padding: 14px; }
289 | body #header a#logo {
290 | font-size: 1.5em;
291 | font-weight: bold;
292 | text-decoration: none;
293 | background: transparent url(http://swagger.wordnik.com/images/logo_small.png) no-repeat left center;
294 | padding: 20px 0 20px 40px;
295 | color: white; }
296 | body #header form#api_selector {
297 | display: block;
298 | clear: none;
299 | float: right; }
300 | body #header form#api_selector .input {
301 | display: block;
302 | clear: none;
303 | float: left;
304 | margin: 0 10px 0 0; }
305 | body #header form#api_selector .input input {
306 | font-size: 0.9em;
307 | padding: 3px;
308 | margin: 0; }
309 | body #header form#api_selector .input input#input_baseUrl {
310 | width: 400px; }
311 | body #header form#api_selector .input input#input_apiKey {
312 | width: 200px; }
313 | body #header form#api_selector .input a#explore {
314 | display: block;
315 | text-decoration: none;
316 | font-weight: bold;
317 | padding: 6px 8px;
318 | font-size: 0.9em;
319 | color: white;
320 | background-color: #547f00;
321 | -moz-border-radius: 4px;
322 | -webkit-border-radius: 4px;
323 | -o-border-radius: 4px;
324 | -ms-border-radius: 4px;
325 | -khtml-border-radius: 4px;
326 | border-radius: 4px; }
327 | body #header form#api_selector .input a#explore:hover {
328 | background-color: #547f00; }
329 | body p#colophon {
330 | margin: 0 15px 40px 15px;
331 | padding: 10px 0;
332 | font-size: 0.8em;
333 | border-top: 1px solid #dddddd;
334 | font-family: "Droid Sans", sans-serif;
335 | color: #999999;
336 | font-style: italic; }
337 | body p#colophon a {
338 | text-decoration: none;
339 | color: #547f00; }
340 | body ul#resources {
341 | padding: 0 15px;
342 | font-family: "Droid Sans", sans-serif;
343 | font-size: 0.9em; }
344 | body ul#resources li.resource {
345 | border-bottom: 1px solid #dddddd; }
346 | body ul#resources li.resource:last-child {
347 | border-bottom: none; }
348 | body ul#resources li.resource div.heading {
349 | border: 1px solid transparent;
350 | float: none;
351 | clear: both;
352 | overflow: hidden;
353 | display: block; }
354 | body ul#resources li.resource div.heading h2 {
355 | color: #999999;
356 | padding-left: 0px;
357 | display: block;
358 | clear: none;
359 | float: left;
360 | font-family: "Droid Sans", sans-serif;
361 | font-weight: bold; }
362 | body ul#resources li.resource div.heading h2 a {
363 | color: #999999; }
364 | body ul#resources li.resource div.heading h2 a:hover {
365 | color: black; }
366 | body ul#resources li.resource div.heading ul.options {
367 | float: none;
368 | clear: both;
369 | overflow: hidden;
370 | margin: 0;
371 | padding: 0;
372 | display: block;
373 | clear: none;
374 | float: right;
375 | margin: 14px 10px 0 0; }
376 | body ul#resources li.resource div.heading ul.options li {
377 | float: left;
378 | clear: none;
379 | margin: 0;
380 | padding: 2px 10px;
381 | border-right: 1px solid #dddddd; }
382 | body ul#resources li.resource div.heading ul.options li:first-child, body ul#resources li.resource div.heading ul.options li.first {
383 | padding-left: 0; }
384 | body ul#resources li.resource div.heading ul.options li:last-child, body ul#resources li.resource div.heading ul.options li.last {
385 | padding-right: 0;
386 | border-right: none; }
387 | body ul#resources li.resource div.heading ul.options li {
388 | color: #666666;
389 | font-size: 0.9em; }
390 | body ul#resources li.resource div.heading ul.options li a {
391 | color: #aaaaaa;
392 | text-decoration: none; }
393 | body ul#resources li.resource div.heading ul.options li a:hover {
394 | text-decoration: underline;
395 | color: black; }
396 | body ul#resources li.resource:hover div.heading h2 a, body ul#resources li.resource.active div.heading h2 a {
397 | color: black; }
398 | body ul#resources li.resource:hover div.heading ul.options li a, body ul#resources li.resource.active div.heading ul.options li a {
399 | color: #555555; }
400 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get {
401 | float: none;
402 | clear: both;
403 | overflow: hidden;
404 | display: block;
405 | margin: 0 0 10px 0;
406 | padding: 0 0 0 0px; }
407 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading {
408 | float: none;
409 | clear: both;
410 | overflow: hidden;
411 | display: block;
412 | margin: 0 0 0 0;
413 | padding: 0;
414 | background-color: #e7f0f7;
415 | border: 1px solid black;
416 | border-color: #c3d9ec; }
417 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 {
418 | display: block;
419 | clear: none;
420 | float: left;
421 | width: auto;
422 | margin: 0;
423 | padding: 0;
424 | line-height: 1.1em;
425 | color: black; }
426 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span {
427 | margin: 0;
428 | padding: 0; }
429 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.http_method a {
430 | text-transform: uppercase;
431 | background-color: #0f6ab4;
432 | text-decoration: none;
433 | color: white;
434 | display: inline-block;
435 | width: 50px;
436 | font-size: 0.7em;
437 | text-align: center;
438 | padding: 7px 0 4px 0;
439 | -moz-border-radius: 2px;
440 | -webkit-border-radius: 2px;
441 | -o-border-radius: 2px;
442 | -ms-border-radius: 2px;
443 | -khtml-border-radius: 2px;
444 | border-radius: 2px; }
445 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.path {
446 | padding-left: 10px; }
447 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.path a {
448 | color: black;
449 | text-decoration: none; }
450 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.path a:hover {
451 | text-decoration: underline; }
452 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options {
453 | float: none;
454 | clear: both;
455 | overflow: hidden;
456 | margin: 0;
457 | padding: 0;
458 | display: block;
459 | clear: none;
460 | float: right;
461 | margin: 6px 10px 0 0; }
462 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li {
463 | float: left;
464 | clear: none;
465 | margin: 0;
466 | padding: 2px 10px;
467 | border-right: 1px solid #dddddd; }
468 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:first-child, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.first {
469 | padding-left: 0; }
470 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:last-child, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.last {
471 | padding-right: 0;
472 | border-right: none; }
473 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li {
474 | border-right-color: #c3d9ec;
475 | color: #0f6ab4;
476 | font-size: 0.9em; }
477 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a {
478 | color: #0f6ab4;
479 | text-decoration: none; }
480 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a:hover, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a:active, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a.active {
481 | text-decoration: underline; }
482 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content {
483 | background-color: #ebf3f9;
484 | border: 1px solid black;
485 | border-color: #c3d9ec;
486 | border-top: none;
487 | padding: 10px;
488 | -moz-border-radius-bottomleft: 6px;
489 | -webkit-border-bottom-left-radius: 6px;
490 | -o-border-bottom-left-radius: 6px;
491 | -ms-border-bottom-left-radius: 6px;
492 | -khtml-border-bottom-left-radius: 6px;
493 | border-bottom-left-radius: 6px;
494 | -moz-border-radius-bottomright: 6px;
495 | -webkit-border-bottom-right-radius: 6px;
496 | -o-border-bottom-right-radius: 6px;
497 | -ms-border-bottom-right-radius: 6px;
498 | -khtml-border-bottom-right-radius: 6px;
499 | border-bottom-right-radius: 6px;
500 | margin: 0 0 20px 0; }
501 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content h4 {
502 | color: #0f6ab4;
503 | font-size: 1.1em;
504 | margin: 0;
505 | padding: 15px 0 5px 0px; }
506 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content form input[type='text'].error {
507 | outline: 2px solid black;
508 | outline-color: #cc0000; }
509 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header {
510 | float: none;
511 | clear: both;
512 | overflow: hidden;
513 | display: block; }
514 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header input.submit {
515 | display: block;
516 | clear: none;
517 | float: left;
518 | padding: 6px 8px; }
519 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header img {
520 | display: block;
521 | display: block;
522 | clear: none;
523 | float: right; }
524 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header a {
525 | padding: 4px 0 0 10px;
526 | color: #6fa5d2;
527 | display: inline-block;
528 | font-size: 0.9em; }
529 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.response div.block {
530 | background-color: #fcf6db;
531 | border: 1px solid black;
532 | border-color: #e5e0c6; }
533 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.response div.block pre {
534 | font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace;
535 | padding: 10px;
536 | font-size: 0.9em;
537 | max-height: 400px;
538 | overflow-y: auto; }
539 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post {
540 | float: none;
541 | clear: both;
542 | overflow: hidden;
543 | display: block;
544 | margin: 0 0 10px 0;
545 | padding: 0 0 0 0px; }
546 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading {
547 | float: none;
548 | clear: both;
549 | overflow: hidden;
550 | display: block;
551 | margin: 0 0 0 0;
552 | padding: 0;
553 | background-color: #e7f6ec;
554 | border: 1px solid black;
555 | border-color: #c3e8d1; }
556 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 {
557 | display: block;
558 | clear: none;
559 | float: left;
560 | width: auto;
561 | margin: 0;
562 | padding: 0;
563 | line-height: 1.1em;
564 | color: black; }
565 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span {
566 | margin: 0;
567 | padding: 0; }
568 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.http_method a {
569 | text-transform: uppercase;
570 | background-color: #10a54a;
571 | text-decoration: none;
572 | color: white;
573 | display: inline-block;
574 | width: 50px;
575 | font-size: 0.7em;
576 | text-align: center;
577 | padding: 7px 0 4px 0;
578 | -moz-border-radius: 2px;
579 | -webkit-border-radius: 2px;
580 | -o-border-radius: 2px;
581 | -ms-border-radius: 2px;
582 | -khtml-border-radius: 2px;
583 | border-radius: 2px; }
584 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.path {
585 | padding-left: 10px; }
586 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.path a {
587 | color: black;
588 | text-decoration: none; }
589 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.path a:hover {
590 | text-decoration: underline; }
591 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options {
592 | float: none;
593 | clear: both;
594 | overflow: hidden;
595 | margin: 0;
596 | padding: 0;
597 | display: block;
598 | clear: none;
599 | float: right;
600 | margin: 6px 10px 0 0; }
601 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li {
602 | float: left;
603 | clear: none;
604 | margin: 0;
605 | padding: 2px 10px;
606 | border-right: 1px solid #dddddd; }
607 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:first-child, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.first {
608 | padding-left: 0; }
609 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:last-child, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.last {
610 | padding-right: 0;
611 | border-right: none; }
612 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li {
613 | border-right-color: #c3e8d1;
614 | color: #10a54a;
615 | font-size: 0.9em; }
616 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a {
617 | color: #10a54a;
618 | text-decoration: none; }
619 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a:hover, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a:active, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a.active {
620 | text-decoration: underline; }
621 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content {
622 | background-color: #ebf7f0;
623 | border: 1px solid black;
624 | border-color: #c3e8d1;
625 | border-top: none;
626 | padding: 10px;
627 | -moz-border-radius-bottomleft: 6px;
628 | -webkit-border-bottom-left-radius: 6px;
629 | -o-border-bottom-left-radius: 6px;
630 | -ms-border-bottom-left-radius: 6px;
631 | -khtml-border-bottom-left-radius: 6px;
632 | border-bottom-left-radius: 6px;
633 | -moz-border-radius-bottomright: 6px;
634 | -webkit-border-bottom-right-radius: 6px;
635 | -o-border-bottom-right-radius: 6px;
636 | -ms-border-bottom-right-radius: 6px;
637 | -khtml-border-bottom-right-radius: 6px;
638 | border-bottom-right-radius: 6px;
639 | margin: 0 0 20px 0; }
640 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content h4 {
641 | color: #10a54a;
642 | font-size: 1.1em;
643 | margin: 0;
644 | padding: 15px 0 5px 0px; }
645 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content form input[type='text'].error {
646 | outline: 2px solid black;
647 | outline-color: #cc0000; }
648 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header {
649 | float: none;
650 | clear: both;
651 | overflow: hidden;
652 | display: block; }
653 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header input.submit {
654 | display: block;
655 | clear: none;
656 | float: left;
657 | padding: 6px 8px; }
658 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header img {
659 | display: block;
660 | display: block;
661 | clear: none;
662 | float: right; }
663 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header a {
664 | padding: 4px 0 0 10px;
665 | color: #6fc992;
666 | display: inline-block;
667 | font-size: 0.9em; }
668 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.response div.block {
669 | background-color: #fcf6db;
670 | border: 1px solid black;
671 | border-color: #e5e0c6; }
672 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.response div.block pre {
673 | font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace;
674 | padding: 10px;
675 | font-size: 0.9em;
676 | max-height: 400px;
677 | overflow-y: auto; }
678 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put {
679 | float: none;
680 | clear: both;
681 | overflow: hidden;
682 | display: block;
683 | margin: 0 0 10px 0;
684 | padding: 0 0 0 0px; }
685 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading {
686 | float: none;
687 | clear: both;
688 | overflow: hidden;
689 | display: block;
690 | margin: 0 0 0 0;
691 | padding: 0;
692 | background-color: #f9f2e9;
693 | border: 1px solid black;
694 | border-color: #f0e0ca; }
695 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 {
696 | display: block;
697 | clear: none;
698 | float: left;
699 | width: auto;
700 | margin: 0;
701 | padding: 0;
702 | line-height: 1.1em;
703 | color: black; }
704 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span {
705 | margin: 0;
706 | padding: 0; }
707 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.http_method a {
708 | text-transform: uppercase;
709 | background-color: #c5862b;
710 | text-decoration: none;
711 | color: white;
712 | display: inline-block;
713 | width: 50px;
714 | font-size: 0.7em;
715 | text-align: center;
716 | padding: 7px 0 4px 0;
717 | -moz-border-radius: 2px;
718 | -webkit-border-radius: 2px;
719 | -o-border-radius: 2px;
720 | -ms-border-radius: 2px;
721 | -khtml-border-radius: 2px;
722 | border-radius: 2px; }
723 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.path {
724 | padding-left: 10px; }
725 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.path a {
726 | color: black;
727 | text-decoration: none; }
728 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.path a:hover {
729 | text-decoration: underline; }
730 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options {
731 | float: none;
732 | clear: both;
733 | overflow: hidden;
734 | margin: 0;
735 | padding: 0;
736 | display: block;
737 | clear: none;
738 | float: right;
739 | margin: 6px 10px 0 0; }
740 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li {
741 | float: left;
742 | clear: none;
743 | margin: 0;
744 | padding: 2px 10px;
745 | border-right: 1px solid #dddddd; }
746 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:first-child, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.first {
747 | padding-left: 0; }
748 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:last-child, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.last {
749 | padding-right: 0;
750 | border-right: none; }
751 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li {
752 | border-right-color: #f0e0ca;
753 | color: #c5862b;
754 | font-size: 0.9em; }
755 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a {
756 | color: #c5862b;
757 | text-decoration: none; }
758 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a:hover, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a:active, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a.active {
759 | text-decoration: underline; }
760 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content {
761 | background-color: #faf5ee;
762 | border: 1px solid black;
763 | border-color: #f0e0ca;
764 | border-top: none;
765 | padding: 10px;
766 | -moz-border-radius-bottomleft: 6px;
767 | -webkit-border-bottom-left-radius: 6px;
768 | -o-border-bottom-left-radius: 6px;
769 | -ms-border-bottom-left-radius: 6px;
770 | -khtml-border-bottom-left-radius: 6px;
771 | border-bottom-left-radius: 6px;
772 | -moz-border-radius-bottomright: 6px;
773 | -webkit-border-bottom-right-radius: 6px;
774 | -o-border-bottom-right-radius: 6px;
775 | -ms-border-bottom-right-radius: 6px;
776 | -khtml-border-bottom-right-radius: 6px;
777 | border-bottom-right-radius: 6px;
778 | margin: 0 0 20px 0; }
779 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content h4 {
780 | color: #c5862b;
781 | font-size: 1.1em;
782 | margin: 0;
783 | padding: 15px 0 5px 0px; }
784 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content form input[type='text'].error {
785 | outline: 2px solid black;
786 | outline-color: #cc0000; }
787 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header {
788 | float: none;
789 | clear: both;
790 | overflow: hidden;
791 | display: block; }
792 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header input.submit {
793 | display: block;
794 | clear: none;
795 | float: left;
796 | padding: 6px 8px; }
797 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header img {
798 | display: block;
799 | display: block;
800 | clear: none;
801 | float: right; }
802 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header a {
803 | padding: 4px 0 0 10px;
804 | color: #dcb67f;
805 | display: inline-block;
806 | font-size: 0.9em; }
807 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.response div.block {
808 | background-color: #fcf6db;
809 | border: 1px solid black;
810 | border-color: #e5e0c6; }
811 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.response div.block pre {
812 | font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace;
813 | padding: 10px;
814 | font-size: 0.9em;
815 | max-height: 400px;
816 | overflow-y: auto; }
817 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete {
818 | float: none;
819 | clear: both;
820 | overflow: hidden;
821 | display: block;
822 | margin: 0 0 10px 0;
823 | padding: 0 0 0 0px; }
824 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading {
825 | float: none;
826 | clear: both;
827 | overflow: hidden;
828 | display: block;
829 | margin: 0 0 0 0;
830 | padding: 0;
831 | background-color: #f5e8e8;
832 | border: 1px solid black;
833 | border-color: #e8c6c7; }
834 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 {
835 | display: block;
836 | clear: none;
837 | float: left;
838 | width: auto;
839 | margin: 0;
840 | padding: 0;
841 | line-height: 1.1em;
842 | color: black; }
843 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span {
844 | margin: 0;
845 | padding: 0; }
846 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.http_method a {
847 | text-transform: uppercase;
848 | background-color: #a41e22;
849 | text-decoration: none;
850 | color: white;
851 | display: inline-block;
852 | width: 50px;
853 | font-size: 0.7em;
854 | text-align: center;
855 | padding: 7px 0 4px 0;
856 | -moz-border-radius: 2px;
857 | -webkit-border-radius: 2px;
858 | -o-border-radius: 2px;
859 | -ms-border-radius: 2px;
860 | -khtml-border-radius: 2px;
861 | border-radius: 2px; }
862 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.path {
863 | padding-left: 10px; }
864 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.path a {
865 | color: black;
866 | text-decoration: none; }
867 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.path a:hover {
868 | text-decoration: underline; }
869 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options {
870 | float: none;
871 | clear: both;
872 | overflow: hidden;
873 | margin: 0;
874 | padding: 0;
875 | display: block;
876 | clear: none;
877 | float: right;
878 | margin: 6px 10px 0 0; }
879 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li {
880 | float: left;
881 | clear: none;
882 | margin: 0;
883 | padding: 2px 10px;
884 | border-right: 1px solid #dddddd; }
885 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:first-child, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.first {
886 | padding-left: 0; }
887 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:last-child, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.last {
888 | padding-right: 0;
889 | border-right: none; }
890 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li {
891 | border-right-color: #e8c6c7;
892 | color: #a41e22;
893 | font-size: 0.9em; }
894 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a {
895 | color: #a41e22;
896 | text-decoration: none; }
897 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a:hover, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a:active, body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a.active {
898 | text-decoration: underline; }
899 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content {
900 | background-color: #f7eded;
901 | border: 1px solid black;
902 | border-color: #e8c6c7;
903 | border-top: none;
904 | padding: 10px;
905 | -moz-border-radius-bottomleft: 6px;
906 | -webkit-border-bottom-left-radius: 6px;
907 | -o-border-bottom-left-radius: 6px;
908 | -ms-border-bottom-left-radius: 6px;
909 | -khtml-border-bottom-left-radius: 6px;
910 | border-bottom-left-radius: 6px;
911 | -moz-border-radius-bottomright: 6px;
912 | -webkit-border-bottom-right-radius: 6px;
913 | -o-border-bottom-right-radius: 6px;
914 | -ms-border-bottom-right-radius: 6px;
915 | -khtml-border-bottom-right-radius: 6px;
916 | border-bottom-right-radius: 6px;
917 | margin: 0 0 20px 0; }
918 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content h4 {
919 | color: #a41e22;
920 | font-size: 1.1em;
921 | margin: 0;
922 | padding: 15px 0 5px 0px; }
923 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content form input[type='text'].error {
924 | outline: 2px solid black;
925 | outline-color: #cc0000; }
926 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header {
927 | float: none;
928 | clear: both;
929 | overflow: hidden;
930 | display: block; }
931 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header input.submit {
932 | display: block;
933 | clear: none;
934 | float: left;
935 | padding: 6px 8px; }
936 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header img {
937 | display: block;
938 | display: block;
939 | clear: none;
940 | float: right; }
941 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header a {
942 | padding: 4px 0 0 10px;
943 | color: #c8787a;
944 | display: inline-block;
945 | font-size: 0.9em; }
946 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.response div.block {
947 | background-color: #fcf6db;
948 | border: 1px solid black;
949 | border-color: #e5e0c6; }
950 | body ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.response div.block pre {
951 | font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace;
952 | padding: 10px;
953 | font-size: 0.9em;
954 | max-height: 400px;
955 | overflow-y: auto; }
956 |
--------------------------------------------------------------------------------