use swagger instead of enunciate

This commit is contained in:
Athou
2013-04-15 21:50:36 +02:00
parent 2152e93086
commit a9eb2595fe
31 changed files with 6895 additions and 169 deletions

28
pom.xml
View File

@@ -138,22 +138,6 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.enunciate</groupId>
<artifactId>maven-enunciate-plugin</artifactId>
<version>1.26.2</version>
<executions>
<execution>
<id>package</id>
<goals>
<goal>assemble</goal>
</goals>
<configuration>
<configFile>${project.basedir}/src/main/enunciate/enunciate.xml</configFile>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.github.searls</groupId>
<artifactId>jasmine-maven-plugin</artifactId>
@@ -278,9 +262,9 @@
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.2.2</version>
<groupId>com.fasterxml.jackson.jaxrs</groupId>
<artifactId>jackson-jaxrs-json-provider</artifactId>
<version>2.1.4</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
@@ -305,9 +289,9 @@
</dependency>
<dependency>
<groupId>org.codehaus.enunciate</groupId>
<artifactId>enunciate-core-annotations</artifactId>
<version>1.26.2</version>
<groupId>com.wordnik</groupId>
<artifactId>swagger-jaxrs_2.9.1</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>

View File

@@ -15,9 +15,10 @@ import com.commafeed.backend.model.UserRole.Role;
import com.commafeed.backend.services.UserService;
import com.google.common.collect.Sets;
@SuppressWarnings("serial")
public class CommaFeedSession extends AuthenticatedWebSession {
private static final long serialVersionUID = 1L;
@Inject
UserService userService;

View File

@@ -0,0 +1,101 @@
package com.commafeed.frontend.rest;
import java.util.Enumeration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import com.commafeed.frontend.model.Entries;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.core.SwaggerSpec;
import com.wordnik.swagger.jaxrs.ConfigReader;
import com.wordnik.swagger.jaxrs.JavaApiListing;
@Path("/resources")
@Api("/resources")
@Produces({ "application/json" })
public class ApiListingResource extends JavaApiListing {
@Override
@GET
@ApiOperation(value = "Returns list of all available api endpoints", responseClass = "List[DocumentationEndPoint]")
public Response getAllApis(@Context final ServletConfig sc,
@Context Application app, @Context HttpHeaders headers,
@Context UriInfo uriInfo) {
return super.getAllApis(new ServletConfigProxy(sc), app, headers,
uriInfo);
}
public static class ServletConfigProxy implements ServletConfig {
private ServletConfig sc;
public ServletConfigProxy(ServletConfig sc) {
this.sc = sc;
}
@Override
public String getServletName() {
return sc.getServletName();
}
@Override
public ServletContext getServletContext() {
return sc.getServletContext();
}
@Override
public String getInitParameter(String name) {
if ("swagger.config.reader".equals(name)) {
return CustomConfigReader.class.getName();
}
return sc.getInitParameter(name);
}
@Override
public Enumeration<String> getInitParameterNames() {
return sc.getInitParameterNames();
}
}
public static class CustomConfigReader extends ConfigReader {
public CustomConfigReader(ServletConfig config) {
}
@Override
public String basePath() {
return "http://localhost:8082/commafeed/rest";
}
@Override
public String swaggerVersion() {
return SwaggerSpec.version();
}
@Override
public String apiVersion() {
return "1.0";
}
@Override
public String modelPackages() {
return Entries.class.getPackage().getName();
}
@Override
public String apiFilterClassName() {
return null;
}
}
}

View File

@@ -1,124 +0,0 @@
package com.commafeed.frontend.rest;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import org.apache.commons.lang.time.DateUtils;
import com.commafeed.frontend.CommaFeedSession;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
@Provider
@Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN })
@Consumes(MediaType.APPLICATION_JSON)
public class JSONMessageBodyReaderWriter implements MessageBodyWriter<Object>,
MessageBodyReader<Object> {
private static final String UTF_8 = "UTF-8";
private Gson gson;
@Override
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public long getSize(Object t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return -1;
}
@Override
public void writeTo(Object t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException {
httpHeaders.putSingle(HttpHeaders.CONTENT_TYPE, mediaType.toString()
+ ";charset=" + UTF_8);
httpHeaders.putSingle(HttpHeaders.CACHE_CONTROL, "no-cache");
httpHeaders.putSingle("Pragma", "no-cache");
if (type == String.class) {
entityStream.write(t.toString().getBytes(UTF_8));
} else {
OutputStreamWriter writer = new OutputStreamWriter(entityStream,
UTF_8);
getGson().toJson(t, type, writer);
writer.flush();
}
}
@Override
public Object readFrom(Class<Object> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
InputStreamReader reader = new InputStreamReader(
new BufferedInputStream(entityStream), UTF_8);
return getGson().fromJson(reader, type);
}
private Gson getGson() {
if (gson == null) {
gson = new GsonBuilder().registerTypeAdapter(Date.class,
new DateSerializer()).create();
}
return gson;
}
private static class DateSerializer implements JsonSerializer<Date> {
private static final String DAY_FORMAT = "yyyy-MM-dd";
private static final String TIME_FORMAT = "HH:mm";
public JsonElement serialize(Date src, Type typeOfSrc,
JsonSerializationContext context) {
Date now = Calendar.getInstance().getTime();
String format = DateUtils.isSameDay(now, src) ? TIME_FORMAT
: DAY_FORMAT;
Locale locale = CommaFeedSession.get().getLocale();
Calendar calendar = Calendar.getInstance(locale);
TimeZone timeZone = calendar.getTimeZone();
SimpleDateFormat dateFormat = new SimpleDateFormat(format);
dateFormat.setTimeZone(timeZone);
return new JsonPrimitive(dateFormat.format(src));
}
}
}

View File

@@ -11,15 +11,22 @@ import com.commafeed.frontend.rest.resources.EntriesREST;
import com.commafeed.frontend.rest.resources.SessionREST;
import com.commafeed.frontend.rest.resources.SettingsREST;
import com.commafeed.frontend.rest.resources.SubscriptionsREST;
import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider;
import com.google.common.collect.Sets;
import com.wordnik.swagger.jaxrs.JaxrsApiReader;
@ApplicationPath("/rest")
public class RESTApplication extends Application {
static {
JaxrsApiReader.setFormatString("");
}
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> set = Sets.newHashSet();
set.add(JSONMessageBodyReaderWriter.class);
set.add(ApiListingResource.class);
set.add(JacksonJsonProvider.class);
set.add(SubscriptionsREST.class);
set.add(EntriesREST.class);

View File

@@ -6,15 +6,19 @@ import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.InvocationContext;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriInfo;
import org.apache.wicket.ThreadContext;
import org.apache.wicket.authentication.IAuthenticationStrategy;
@@ -41,11 +45,14 @@ import com.commafeed.backend.services.UserService;
import com.commafeed.frontend.CommaFeedApplication;
import com.commafeed.frontend.CommaFeedSession;
import com.commafeed.frontend.SecurityCheck;
import com.commafeed.frontend.rest.ApiListingResource.ServletConfigProxy;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.jaxrs.JavaHelp;
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@SecurityCheck(Role.USER)
public abstract class AbstractREST {
public abstract class AbstractREST extends JavaHelp {
@Context
HttpServletRequest request;
@@ -126,7 +133,7 @@ public abstract class AbstractREST {
.entity("You need to be authenticated to do this.").build());
}
boolean allowed = false;
boolean allowed = true;
Method method = context.getMethod();
if (method.isAnnotationPresent(SecurityCheck.class)) {
@@ -153,4 +160,12 @@ public abstract class AbstractREST {
return authorized;
}
@Override
@GET
@ApiOperation(value = "Returns information about API parameters", responseClass = "com.wordnik.swagger.core.Documentation")
public Response getHelp(@Context ServletConfig sc,
@Context HttpHeaders headers, @Context UriInfo uriInfo) {
return super.getHelp(new ServletConfigProxy(sc), headers, uriInfo);
}
}

View File

@@ -5,8 +5,6 @@ import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import org.codehaus.enunciate.doc.DocumentationGroup;
import com.commafeed.backend.model.ApplicationSettings;
import com.commafeed.backend.model.UserRole.Role;
import com.commafeed.backend.services.ApplicationSettingsService;
@@ -14,7 +12,6 @@ import com.commafeed.frontend.SecurityCheck;
@SecurityCheck(Role.ADMIN)
@Path("admin/settings")
@DocumentationGroup("Application Settings")
public class AdminSettingsREST {
@Inject

View File

@@ -12,7 +12,6 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang.StringUtils;
import org.codehaus.enunciate.doc.DocumentationGroup;
import com.commafeed.backend.StartupBean;
import com.commafeed.backend.model.User;
@@ -27,7 +26,6 @@ import com.google.common.collect.Sets;
@SecurityCheck(Role.ADMIN)
@Path("admin/users")
@DocumentationGroup("User Management")
public class AdminUsersREST extends AbstractREST {
@Path("save")

View File

@@ -13,7 +13,6 @@ import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.lang.StringUtils;
import org.codehaus.enunciate.doc.DocumentationGroup;
import com.commafeed.backend.model.FeedCategory;
import com.commafeed.backend.model.FeedEntry;
@@ -24,9 +23,12 @@ import com.commafeed.frontend.model.Entries;
import com.commafeed.frontend.model.Entry;
import com.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import com.wordnik.swagger.annotations.Api;
import com.wordnik.swagger.annotations.ApiOperation;
import com.wordnik.swagger.annotations.ApiParam;
@Path("entries")
@DocumentationGroup("Entries")
@Path("/entries/")
@Api(value = "/entries", description = "Operations about entries")
public class EntriesREST extends AbstractREST {
public static final String ALL = "all";
@@ -39,9 +41,11 @@ public class EntriesREST extends AbstractREST {
all, unread;
}
@Path("get")
@Path("/get")
@GET
public Entries getEntries(@QueryParam("type") Type type,
@ApiOperation(value = "Find entry by ID", notes = "Add extra notes here", responseClass = "com.commafeed.frontend.model.Entries")
public Entries getEntries(
@ApiParam(value = "ID of entry that needs to be fetched", allowableValues = "range[1,5]", required = true) @QueryParam("type") Type type,
@QueryParam("id") String id,
@QueryParam("readType") ReadType readType,
@DefaultValue("0") @QueryParam("offset") int offset,

View File

@@ -6,7 +6,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import org.apache.commons.lang.StringUtils;
import org.codehaus.enunciate.doc.DocumentationGroup;
import com.commafeed.backend.model.User;
import com.commafeed.backend.model.UserRole;
@@ -15,7 +14,6 @@ import com.commafeed.frontend.model.ProfileModificationRequest;
import com.commafeed.frontend.model.UserModel;
@Path("session")
@DocumentationGroup("User settings")
public class SessionREST extends AbstractREST {
@Path("get")

View File

@@ -6,8 +6,6 @@ import javax.ws.rs.Path;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import org.codehaus.enunciate.doc.DocumentationGroup;
import com.commafeed.backend.model.UserSettings;
import com.commafeed.backend.model.UserSettings.ReadingMode;
import com.commafeed.backend.model.UserSettings.ReadingOrder;
@@ -15,7 +13,6 @@ import com.commafeed.frontend.model.Settings;
import com.google.common.base.Preconditions;
@Path("settings")
@DocumentationGroup("User settings")
public class SettingsREST extends AbstractREST {
@Path("get")

View File

@@ -21,7 +21,6 @@ import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ObjectUtils;
import org.codehaus.enunciate.doc.DocumentationGroup;
import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedCategory;
@@ -33,7 +32,6 @@ import com.commafeed.frontend.rest.resources.EntriesREST.Type;
import com.google.common.base.Preconditions;
@Path("subscriptions")
@DocumentationGroup("Subscriptions")
public class SubscriptionsREST extends AbstractREST {
@GET

View File

@@ -11,8 +11,8 @@
<param-value>com.commafeed.frontend.CommaFeedApplication</param-value>
</init-param>
<init-param>
<param-name>configuration</param-name>
<param-value>deployment</param-value>
<param-name>configuration</param-name>
<param-value>deployment</param-value>
</init-param>
</filter>
<filter-mapping>

View File

@@ -0,0 +1,135 @@
/*
Original style from softwaremaniacs.org (c) Ivan Sagalaev <Maniac@SoftwareManiacs.Org>
*/
pre code {
display: block; padding: 0.5em;
background: #F0F0F0;
}
pre code,
pre .subst,
pre .tag .title,
pre .lisp .title,
pre .clojure .built_in,
pre .nginx .title {
color: black;
}
pre .string,
pre .title,
pre .constant,
pre .parent,
pre .tag .value,
pre .rules .value,
pre .rules .value .number,
pre .preprocessor,
pre .ruby .symbol,
pre .ruby .symbol .string,
pre .aggregate,
pre .template_tag,
pre .django .variable,
pre .smalltalk .class,
pre .addition,
pre .flow,
pre .stream,
pre .bash .variable,
pre .apache .tag,
pre .apache .cbracket,
pre .tex .command,
pre .tex .special,
pre .erlang_repl .function_or_atom,
pre .markdown .header {
color: #800;
}
pre .comment,
pre .annotation,
pre .template_comment,
pre .diff .header,
pre .chunk,
pre .markdown .blockquote {
color: #888;
}
pre .number,
pre .date,
pre .regexp,
pre .literal,
pre .smalltalk .symbol,
pre .smalltalk .char,
pre .go .constant,
pre .change,
pre .markdown .bullet,
pre .markdown .link_url {
color: #080;
}
pre .label,
pre .javadoc,
pre .ruby .string,
pre .decorator,
pre .filter .argument,
pre .localvars,
pre .array,
pre .attr_selector,
pre .important,
pre .pseudo,
pre .pi,
pre .doctype,
pre .deletion,
pre .envvar,
pre .shebang,
pre .apache .sqbracket,
pre .nginx .built_in,
pre .tex .formula,
pre .erlang_repl .reserved,
pre .prompt,
pre .markdown .link_label,
pre .vhdl .attribute,
pre .clojure .attribute,
pre .coffeescript .property {
color: #88F
}
pre .keyword,
pre .id,
pre .phpdoc,
pre .title,
pre .built_in,
pre .aggregate,
pre .css .tag,
pre .javadoctag,
pre .phpdoc,
pre .yardoctag,
pre .smalltalk .class,
pre .winutils,
pre .bash .variable,
pre .apache .tag,
pre .go .typename,
pre .tex .command,
pre .markdown .strong,
pre .request,
pre .status {
font-weight: bold;
}
pre .markdown .emphasis {
font-style: italic;
}
pre .nginx .built_in {
font-weight: normal;
}
pre .coffeescript .javascript,
pre .javascript .xml,
pre .tex .formula,
pre .xml .javascript,
pre .xml .vbscript,
pre .xml .css,
pre .xml .cdata {
opacity: 0.5;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 770 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 824 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 980 B

View File

@@ -0,0 +1,80 @@
<!DOCTYPE html>
<html>
<head>
<title>Swagger UI</title>
<link href='//fonts.googleapis.com/css?family=Droid+Sans:400,700' rel='stylesheet' type='text/css'/>
<link href='css/hightlight.default.css' media='screen' rel='stylesheet' type='text/css'/>
<link href='css/screen.css' media='screen' rel='stylesheet' type='text/css'/>
<script src='lib/jquery-1.8.0.min.js' type='text/javascript'></script>
<script src='lib/jquery.slideto.min.js' type='text/javascript'></script>
<script src='lib/jquery.wiggle.min.js' type='text/javascript'></script>
<script src='lib/jquery.ba-bbq.min.js' type='text/javascript'></script>
<script src='lib/handlebars-1.0.rc.1.js' type='text/javascript'></script>
<script src='lib/underscore-min.js' type='text/javascript'></script>
<script src='lib/backbone-min.js' type='text/javascript'></script>
<script src='lib/swagger.js' type='text/javascript'></script>
<script src='swagger-ui.js' type='text/javascript'></script>
<script src='lib/highlight.7.3.pack.js' type='text/javascript'></script>
<script type="text/javascript">
$(function () {
window.swaggerUi = new SwaggerUi({
discoveryUrl:"http://petstore.swagger.wordnik.com/api/api-docs.json",
apiKey:"special-key",
dom_id:"swagger-ui-container",
supportHeaderParams: false,
supportedSubmitMethods: ['get', 'post', 'put'],
onComplete: function(swaggerApi, swaggerUi){
if(console) {
console.log("Loaded SwaggerUI")
console.log(swaggerApi);
console.log(swaggerUi);
}
$('pre code').each(function(i, e) {hljs.highlightBlock(e)});
},
onFailure: function(data) {
if(console) {
console.log("Unable to Load SwaggerUI");
console.log(data);
}
},
docExpansion: "none"
});
window.swaggerUi.load();
});
</script>
</head>
<body>
<div id='header'>
<div class="swagger-ui-wrap">
<a id="logo" href="http://swagger.wordnik.com">swagger</a>
<form id='api_selector'>
<div class='input icon-btn'>
<img id="show-pet-store-icon" src="images/pet_store_api.png" title="Show Swagger Petstore Example Apis">
</div>
<div class='input icon-btn'>
<img id="show-wordnik-dev-icon" src="images/wordnik_api.png" title="Show Wordnik Developer Apis">
</div>
<div class='input'><input placeholder="http://example.com/api" id="input_baseUrl" name="baseUrl"
type="text"/></div>
<div class='input'><input placeholder="api_key" id="input_apiKey" name="apiKey" type="text"/></div>
<div class='input'><a id="explore" href="#">Explore</a></div>
</form>
</div>
</div>
<div id="message-bar" class="swagger-ui-wrap">
&nbsp;
</div>
<div id="swagger-ui-container" class="swagger-ui-wrap">
</div>
</body>
</html>

View File

@@ -0,0 +1,38 @@
// Backbone.js 0.9.2
// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Backbone may be freely distributed under the MIT license.
// For all details and documentation:
// http://backbonejs.org
(function(){var l=this,y=l.Backbone,z=Array.prototype.slice,A=Array.prototype.splice,g;g="undefined"!==typeof exports?exports:l.Backbone={};g.VERSION="0.9.2";var f=l._;!f&&"undefined"!==typeof require&&(f=require("underscore"));var i=l.jQuery||l.Zepto||l.ender;g.setDomLibrary=function(a){i=a};g.noConflict=function(){l.Backbone=y;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var p=/\s+/,k=g.Events={on:function(a,b,c){var d,e,f,g,j;if(!b)return this;a=a.split(p);for(d=this._callbacks||(this._callbacks=
{});e=a.shift();)f=(j=d[e])?j.tail:{},f.next=g={},f.context=c,f.callback=b,d[e]={tail:g,next:j?j.next:f};return this},off:function(a,b,c){var d,e,h,g,j,q;if(e=this._callbacks){if(!a&&!b&&!c)return delete this._callbacks,this;for(a=a?a.split(p):f.keys(e);d=a.shift();)if(h=e[d],delete e[d],h&&(b||c))for(g=h.tail;(h=h.next)!==g;)if(j=h.callback,q=h.context,b&&j!==b||c&&q!==c)this.on(d,j,q);return this}},trigger:function(a){var b,c,d,e,f,g;if(!(d=this._callbacks))return this;f=d.all;a=a.split(p);for(g=
z.call(arguments,1);b=a.shift();){if(c=d[b])for(e=c.tail;(c=c.next)!==e;)c.callback.apply(c.context||this,g);if(c=f){e=c.tail;for(b=[b].concat(g);(c=c.next)!==e;)c.callback.apply(c.context||this,b)}}return this}};k.bind=k.on;k.unbind=k.off;var o=g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=n(this,"defaults"))a=f.extend({},c,a);b&&b.collection&&(this.collection=b.collection);this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId("c");this.changed={};this._silent=
{};this._pending={};this.set(a,{silent:!0});this.changed={};this._silent={};this._pending={};this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(o.prototype,k,{changed:null,_silent:null,_pending:null,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.get(a);return this._escapedAttributes[a]=f.escape(null==
b?"":""+b)},has:function(a){return null!=this.get(a)},set:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;d instanceof o&&(d=d.attributes);if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return!1;this.idAttribute in d&&(this.id=d[this.idAttribute]);var b=c.changes={},h=this.attributes,g=this._escapedAttributes,j=this._previousAttributes||{};for(e in d){a=d[e];if(!f.isEqual(h[e],a)||c.unset&&f.has(h,e))delete g[e],(c.silent?this._silent:
b)[e]=!0;c.unset?delete h[e]:h[e]=a;!f.isEqual(j[e],a)||f.has(h,e)!=f.has(j,e)?(this.changed[e]=a,c.silent||(this._pending[e]=!0)):(delete this.changed[e],delete this._pending[e])}c.silent||this.change(c);return this},unset:function(a,b){(b||(b={})).unset=!0;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=!0;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a=a?f.clone(a):{},b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return!1;c&&c(b,d)};
a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};if(c.wait){if(!this._validate(d,c))return!1;e=f.clone(this.attributes)}a=f.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c))return!1;var h=this,i=c.success;c.success=function(a,b,e){b=h.parse(a,e);if(c.wait){delete c.wait;b=f.extend(d||{},b)}if(!h.set(b,c))return false;i?i(h,a):h.trigger("sync",h,a,c)};c.error=g.wrapError(c.error,
h,c);b=this.isNew()?"create":"update";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};if(this.isNew())return d(),!1;a.success=function(e){a.wait&&d();c?c(b,e):b.trigger("sync",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync||g.sync).call(this,"delete",this,a);a.wait||d();return e},url:function(){var a=n(this,"urlRoot")||n(this.collection,"url")||t();
return this.isNew()?a:a+("/"==a.charAt(a.length-1)?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return null==this.id},change:function(a){a||(a={});var b=this._changing;this._changing=!0;for(var c in this._silent)this._pending[c]=!0;var d=f.extend({},a.changes,this._silent);this._silent={};for(c in d)this.trigger("change:"+c,this,this.get(c),a);if(b)return this;for(;!f.isEmpty(this._pending);){this._pending=
{};this.trigger("change",this,a);for(c in this.changed)!this._pending[c]&&!this._silent[c]&&delete this.changed[c];this._previousAttributes=f.clone(this.attributes)}this._changing=!1;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this.changed):f.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this.changed):!1;var b,c=!1,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length||
!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return!0;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return!0;b&&b.error?b.error(this,c,b):this.trigger("error",this,c,b);return!1}});var r=g.Collection=function(a,b){b||(b={});b.model&&(this.model=b.model);b.comparator&&(this.comparator=b.comparator);
this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:!0,parse:b.parse})};f.extend(r.prototype,k,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},add:function(a,b){var c,d,e,g,i,j={},k={},l=[];b||(b={});a=f.isArray(a)?a.slice():[a];c=0;for(d=a.length;c<d;c++){if(!(e=a[c]=this._prepareModel(a[c],b)))throw Error("Can't add an invalid model to a collection");g=e.cid;i=e.id;j[g]||this._byCid[g]||null!=i&&(k[i]||this._byId[i])?
l.push(c):j[g]=k[i]=e}for(c=l.length;c--;)a.splice(l[c],1);c=0;for(d=a.length;c<d;c++)(e=a[c]).on("all",this._onModelEvent,this),this._byCid[e.cid]=e,null!=e.id&&(this._byId[e.id]=e);this.length+=d;A.apply(this.models,[null!=b.at?b.at:this.models.length,0].concat(a));this.comparator&&this.sort({silent:!0});if(b.silent)return this;c=0;for(d=this.models.length;c<d;c++)if(j[(e=this.models[c]).cid])b.index=c,e.trigger("add",e,this,b);return this},remove:function(a,b){var c,d,e,g;b||(b={});a=f.isArray(a)?
a.slice():[a];c=0;for(d=a.length;c<d;c++)if(g=this.getByCid(a[c])||this.get(a[c]))delete this._byId[g.id],delete this._byCid[g.cid],e=this.indexOf(g),this.models.splice(e,1),this.length--,b.silent||(b.index=e,g.trigger("remove",g,this,b)),this._removeReference(g);return this},push:function(a,b){a=this._prepareModel(a,b);this.add(a,b);return a},pop:function(a){var b=this.at(this.length-1);this.remove(b,a);return b},unshift:function(a,b){a=this._prepareModel(a,b);this.add(a,f.extend({at:0},b));return a},
shift:function(a){var b=this.at(0);this.remove(b,a);return b},get:function(a){return null==a?void 0:this._byId[null!=a.id?a.id:a]},getByCid:function(a){return a&&this._byCid[a.cid||a]},at:function(a){return this.models[a]},where:function(a){return f.isEmpty(a)?[]:this.filter(function(b){for(var c in a)if(a[c]!==b.get(c))return!1;return!0})},sort:function(a){a||(a={});if(!this.comparator)throw Error("Cannot sort a set without a comparator");var b=f.bind(this.comparator,this);1==this.comparator.length?
this.models=this.sortBy(b):this.models.sort(b);a.silent||this.trigger("reset",this,a);return this},pluck:function(a){return f.map(this.models,function(b){return b.get(a)})},reset:function(a,b){a||(a=[]);b||(b={});for(var c=0,d=this.models.length;c<d;c++)this._removeReference(this.models[c]);this._reset();this.add(a,f.extend({silent:!0},b));b.silent||this.trigger("reset",this,b);return this},fetch:function(a){a=a?f.clone(a):{};void 0===a.parse&&(a.parse=!0);var b=this,c=a.success;a.success=function(d,
e,f){b[a.add?"add":"reset"](b.parse(d,f),a);c&&c(b,d)};a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},create:function(a,b){var c=this,b=b?f.clone(b):{},a=this._prepareModel(a,b);if(!a)return!1;b.wait||c.add(a,b);var d=b.success;b.success=function(e,f){b.wait&&c.add(e,b);d?d(e,f):e.trigger("sync",a,f,b)};a.save(null,b);return a},parse:function(a){return a},chain:function(){return f(this.models).chain()},_reset:function(){this.length=0;this.models=[];this._byId=
{};this._byCid={}},_prepareModel:function(a,b){b||(b={});a instanceof o?a.collection||(a.collection=this):(b.collection=this,a=new this.model(a,b),a._validate(a.attributes,b)||(a=!1));return a},_removeReference:function(a){this==a.collection&&delete a.collection;a.off("all",this._onModelEvent,this)},_onModelEvent:function(a,b,c,d){("add"==a||"remove"==a)&&c!=this||("destroy"==a&&this.remove(b,d),b&&a==="change:"+b.idAttribute&&(delete this._byId[b.previous(b.idAttribute)],this._byId[b.id]=b),this.trigger.apply(this,
arguments))}});f.each("forEach,each,map,reduce,reduceRight,find,detect,filter,select,reject,every,all,some,any,include,contains,invoke,max,min,sortBy,sortedIndex,toArray,size,first,initial,rest,last,without,indexOf,shuffle,lastIndexOf,isEmpty,groupBy".split(","),function(a){r.prototype[a]=function(){return f[a].apply(f,[this.models].concat(f.toArray(arguments)))}});var u=g.Router=function(a){a||(a={});a.routes&&(this.routes=a.routes);this._bindRoutes();this.initialize.apply(this,arguments)},B=/:\w+/g,
C=/\*\w+/g,D=/[-[\]{}()+?.,\\^$|#\s]/g;f.extend(u.prototype,k,{initialize:function(){},route:function(a,b,c){g.history||(g.history=new m);f.isRegExp(a)||(a=this._routeToRegExp(a));c||(c=this[b]);g.history.route(a,f.bind(function(d){d=this._extractParameters(a,d);c&&c.apply(this,d);this.trigger.apply(this,["route:"+b].concat(d));g.history.trigger("route",this,b,d)},this));return this},navigate:function(a,b){g.history.navigate(a,b)},_bindRoutes:function(){if(this.routes){var a=[],b;for(b in this.routes)a.unshift([b,
this.routes[b]]);b=0;for(var c=a.length;b<c;b++)this.route(a[b][0],a[b][1],this[a[b][1]])}},_routeToRegExp:function(a){a=a.replace(D,"\\$&").replace(B,"([^/]+)").replace(C,"(.*?)");return RegExp("^"+a+"$")},_extractParameters:function(a,b){return a.exec(b).slice(1)}});var m=g.History=function(){this.handlers=[];f.bindAll(this,"checkUrl")},s=/^[#\/]/,E=/msie [\w.]+/;m.started=!1;f.extend(m.prototype,k,{interval:50,getHash:function(a){return(a=(a?a.location:window.location).href.match(/#(.*)$/))?a[1]:
""},getFragment:function(a,b){if(null==a)if(this._hasPushState||b){var a=window.location.pathname,c=window.location.search;c&&(a+=c)}else a=this.getHash();a.indexOf(this.options.root)||(a=a.substr(this.options.root.length));return a.replace(s,"")},start:function(a){if(m.started)throw Error("Backbone.history has already been started");m.started=!0;this.options=f.extend({},{root:"/"},this.options,a);this._wantsHashChange=!1!==this.options.hashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=
!(!this.options.pushState||!window.history||!window.history.pushState);var a=this.getFragment(),b=document.documentMode;if(b=E.exec(navigator.userAgent.toLowerCase())&&(!b||7>=b))this.iframe=i('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow,this.navigate(a);this._hasPushState?i(window).bind("popstate",this.checkUrl):this._wantsHashChange&&"onhashchange"in window&&!b?i(window).bind("hashchange",this.checkUrl):this._wantsHashChange&&(this._checkUrlInterval=setInterval(this.checkUrl,
this.interval));this.fragment=a;a=window.location;b=a.pathname==this.options.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,!0),window.location.replace(this.options.root+"#"+this.fragment),!0;this._wantsPushState&&this._hasPushState&&b&&a.hash&&(this.fragment=this.getHash().replace(s,""),window.history.replaceState({},document.title,a.protocol+"//"+a.host+this.options.root+this.fragment));if(!this.options.silent)return this.loadUrl()},
stop:function(){i(window).unbind("popstate",this.checkUrl).unbind("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);m.started=!1},route:function(a,b){this.handlers.unshift({route:a,callback:b})},checkUrl:function(){var a=this.getFragment();a==this.fragment&&this.iframe&&(a=this.getFragment(this.getHash(this.iframe)));if(a==this.fragment)return!1;this.iframe&&this.navigate(a);this.loadUrl()||this.loadUrl(this.getHash())},loadUrl:function(a){var b=this.fragment=this.getFragment(a);return f.any(this.handlers,
function(a){if(a.route.test(b))return a.callback(b),!0})},navigate:function(a,b){if(!m.started)return!1;if(!b||!0===b)b={trigger:b};var c=(a||"").replace(s,"");this.fragment!=c&&(this._hasPushState?(0!=c.indexOf(this.options.root)&&(c=this.options.root+c),this.fragment=c,window.history[b.replace?"replaceState":"pushState"]({},document.title,c)):this._wantsHashChange?(this.fragment=c,this._updateHash(window.location,c,b.replace),this.iframe&&c!=this.getFragment(this.getHash(this.iframe))&&(b.replace||
this.iframe.document.open().close(),this._updateHash(this.iframe.location,c,b.replace))):window.location.assign(this.options.root+a),b.trigger&&this.loadUrl(a))},_updateHash:function(a,b,c){c?a.replace(a.toString().replace(/(javascript:|#).*$/,"")+"#"+b):a.hash=b}});var v=g.View=function(a){this.cid=f.uniqueId("view");this._configure(a||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()},F=/^(\S+)\s*(.*)$/,w="model,collection,el,id,attributes,className,tagName".split(",");
f.extend(v.prototype,k,{tagName:"div",$:function(a){return this.$el.find(a)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();return this},make:function(a,b,c){a=document.createElement(a);b&&i(a).attr(b);c&&i(a).html(c);return a},setElement:function(a,b){this.$el&&this.undelegateEvents();this.$el=a instanceof i?a:i(a);this.el=this.$el[0];!1!==b&&this.delegateEvents();return this},delegateEvents:function(a){if(a||(a=n(this,"events"))){this.undelegateEvents();
for(var b in a){var c=a[b];f.isFunction(c)||(c=this[a[b]]);if(!c)throw Error('Method "'+a[b]+'" does not exist');var d=b.match(F),e=d[1],d=d[2],c=f.bind(c,this),e=e+(".delegateEvents"+this.cid);""===d?this.$el.bind(e,c):this.$el.delegate(d,e,c)}}},undelegateEvents:function(){this.$el.unbind(".delegateEvents"+this.cid)},_configure:function(a){this.options&&(a=f.extend({},this.options,a));for(var b=0,c=w.length;b<c;b++){var d=w[b];a[d]&&(this[d]=a[d])}this.options=a},_ensureElement:function(){if(this.el)this.setElement(this.el,
!1);else{var a=n(this,"attributes")||{};this.id&&(a.id=this.id);this.className&&(a["class"]=this.className);this.setElement(this.make(this.tagName,a),!1)}}});o.extend=r.extend=u.extend=v.extend=function(a,b){var c=G(this,a,b);c.extend=this.extend;return c};var H={create:"POST",update:"PUT","delete":"DELETE",read:"GET"};g.sync=function(a,b,c){var d=H[a];c||(c={});var e={type:d,dataType:"json"};c.url||(e.url=n(b,"url")||t());if(!c.data&&b&&("create"==a||"update"==a))e.contentType="application/json",
e.data=JSON.stringify(b.toJSON());g.emulateJSON&&(e.contentType="application/x-www-form-urlencoded",e.data=e.data?{model:e.data}:{});if(g.emulateHTTP&&("PUT"===d||"DELETE"===d))g.emulateJSON&&(e.data._method=d),e.type="POST",e.beforeSend=function(a){a.setRequestHeader("X-HTTP-Method-Override",d)};"GET"!==e.type&&!g.emulateJSON&&(e.processData=!1);return i.ajax(f.extend(e,c))};g.wrapError=function(a,b,c){return function(d,e){e=d===b?e:d;a?a(b,e,c):b.trigger("error",b,e,c)}};var x=function(){},G=function(a,
b,c){var d;d=b&&b.hasOwnProperty("constructor")?b.constructor:function(){a.apply(this,arguments)};f.extend(d,a);x.prototype=a.prototype;d.prototype=new x;b&&f.extend(d.prototype,b);c&&f.extend(d,c);d.prototype.constructor=d;d.__super__=a.prototype;return d},n=function(a,b){return!a||!a[b]?null:f.isFunction(a[b])?a[b]():a[b]},t=function(){throw Error('A "url" property or function must be specified');}}).call(this);

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,18 @@
/*
* jQuery BBQ: Back Button & Query Library - v1.2.1 - 2/17/2010
* http://benalman.com/projects/jquery-bbq-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(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<N?O[P]||(R[M+1]&&isNaN(R[M+1])?{}:[]):J}}else{if($.isArray(H[P])){H[P].push(J)}else{if(H[P]!==i){H[P]=[H[P],J]}else{H[P]=J}}}}else{if(P){H[P]=F?i:""}}});return H};function z(H,F,G){if(F===i||typeof F==="boolean"){G=F;F=a[H?D:A]()}else{F=E(F)?F.replace(H?w:x,""):F}return l(F,G)}l[A]=B(z,0);l[D]=v=B(z,1);$[y]||($[y]=function(F){return $.extend(C,F)})({a:k,base:k,iframe:t,img:t,input:t,form:"action",link:k,script:t});j=$[y];function s(I,G,H,F){if(!E(H)&&typeof H!=="object"){F=H;H=G;G=i}return this.each(function(){var L=$(this),J=G||j()[(this.nodeName||"").toLowerCase()]||"",K=J&&L.attr(J)||"";L.attr(J,a[I](K,H,F))})}$.fn[A]=B(s,A);$.fn[D]=B(s,D);b.pushState=q=function(I,F){if(E(I)&&/^#/.test(I)&&F===i){F=2}var H=I!==i,G=c(p[g][k],H?I:{},H?F:2);p[g][k]=G+(/#/.test(G)?"":"#")};b.getState=u=function(F,G){return F===i||typeof F==="boolean"?v(F):v(G)[F]};b.removeState=function(F){var G={};if(F!==i){G=u();$.each($.isArray(F)?F:arguments,function(I,H){delete G[H]})}q(G,2)};e[d]=$.extend(e[d],{add:function(F){var H;function G(J){var I=J[D]=c();J.getState=function(K,L){return K===i||typeof K==="boolean"?l(I,K):l(I,L)[K]};H.apply(this,arguments)}if($.isFunction(F)){H=F;return G}else{H=F.handler;F.handler=G}}})})(jQuery,this);
/*
* jQuery hashchange event - v1.2 - 2/11/2010
* http://benalman.com/projects/jquery-hashchange-plugin/
*
* Copyright (c) 2010 "Cowboy" Ben Alman
* Dual licensed under the MIT and GPL licenses.
* http://benalman.com/about/license/
*/
(function($,i,b){var j,k=$.event.special,c="location",d="hashchange",l="href",f=$.browser,g=document.documentMode,h=f.msie&&(g===b||g<8),e="on"+d in i&&!h;function a(m){m=m||i[c][l];return m.replace(/^[^#]*#?(.*)$/,"$1")}$[d+"Delay"]=100;k[d]=$.extend(k[d],{setup:function(){if(e){return false}$(j.start)},teardown:function(){if(e){return false}$(j.stop)}});j=(function(){var m={},r,n,o,q;function p(){o=q=function(s){return s};if(h){n=$('<iframe src="javascript:0"/>').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);

View File

@@ -0,0 +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);

View File

@@ -0,0 +1,8 @@
/*
jQuery Wiggle
Author: WonderGroup, Jordan Thomas
URL: http://labs.wondergroup.com/demos/mini-ui/index.html
License: MIT (http://en.wikipedia.org/wiki/MIT_License)
*/
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('<div class="wiggle-wrap"></div>').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);}
if(calls==o.wiggles&&jQuery.isFunction(o.callback)){o.callback();}});}});};

View File

@@ -0,0 +1,765 @@
// Generated by CoffeeScript 1.4.0
(function() {
var SwaggerApi, SwaggerModel, SwaggerModelProperty, SwaggerOperation, SwaggerRequest, SwaggerResource,
__bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
SwaggerApi = (function() {
SwaggerApi.prototype.discoveryUrl = "http://api.wordnik.com/v4/resources.json";
SwaggerApi.prototype.debug = false;
SwaggerApi.prototype.api_key = null;
SwaggerApi.prototype.basePath = null;
function SwaggerApi(options) {
if (options == null) {
options = {};
}
if (options.discoveryUrl != null) {
this.discoveryUrl = options.discoveryUrl;
}
if (options.debug != null) {
this.debug = options.debug;
}
this.apiKeyName = options.apiKeyName != null ? options.apiKeyName : 'api_key';
if (options.apiKey != null) {
this.api_key = options.apiKey;
}
if (options.api_key != null) {
this.api_key = options.api_key;
}
if (options.verbose != null) {
this.verbose = options.verbose;
}
this.supportHeaderParams = options.supportHeaderParams != null ? options.supportHeaderParams : false;
this.supportedSubmitMethods = options.supportedSubmitMethods != null ? options.supportedSubmitMethods : ['get'];
if (options.success != null) {
this.success = options.success;
}
this.failure = options.failure != null ? options.failure : function() {};
this.progress = options.progress != null ? options.progress : function() {};
this.headers = options.headers != null ? options.headers : {};
this.booleanValues = options.booleanValues != null ? options.booleanValues : new Array('true', 'false');
this.discoveryUrl = this.suffixApiKey(this.discoveryUrl);
if (options.success != null) {
this.build();
}
}
SwaggerApi.prototype.build = function() {
var _this = this;
this.progress('fetching resource list: ' + this.discoveryUrl);
return jQuery.getJSON(this.discoveryUrl, function(response) {
var res, resource, _i, _j, _len, _len1, _ref, _ref1;
if (response.apiVersion != null) {
_this.apiVersion = response.apiVersion;
}
if ((response.basePath != null) && jQuery.trim(response.basePath).length > 0) {
_this.basePath = response.basePath;
if (_this.basePath.match(/^HTTP/i) == null) {
_this.fail("discoveryUrl basePath must be a URL.");
}
_this.basePath = _this.basePath.replace(/\/$/, '');
} else {
_this.basePath = _this.discoveryUrl.substring(0, _this.discoveryUrl.lastIndexOf('/'));
log('derived basepath from discoveryUrl as ' + _this.basePath);
}
_this.apis = {};
_this.apisArray = [];
if (response.resourcePath != null) {
_this.resourcePath = response.resourcePath;
res = null;
_ref = response.apis;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
resource = _ref[_i];
if (res === null) {
res = new SwaggerResource(resource, _this);
} else {
res.addOperations(resource.path, resource.operations);
}
}
if (res != null) {
_this.apis[res.name] = res;
_this.apisArray.push(res);
res.ready = true;
_this.selfReflect();
}
} else {
_ref1 = response.apis;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
resource = _ref1[_j];
res = new SwaggerResource(resource, _this);
_this.apis[res.name] = res;
_this.apisArray.push(res);
}
}
return _this;
}).error(function(error) {
if (_this.discoveryUrl.substring(0, 4) !== 'http') {
return _this.fail('Please specify the protocol for ' + _this.discoveryUrl);
} else if (error.status === 0) {
return _this.fail('Can\'t read from server. It may not have the appropriate access-control-origin settings.');
} else if (error.status === 404) {
return _this.fail('Can\'t read swagger JSON from ' + _this.discoveryUrl);
} else {
return _this.fail(error.status + ' : ' + error.statusText + ' ' + _this.discoveryUrl);
}
});
};
SwaggerApi.prototype.selfReflect = function() {
var resource, resource_name, _ref;
if (this.apis == null) {
return false;
}
_ref = this.apis;
for (resource_name in _ref) {
resource = _ref[resource_name];
if (resource.ready == null) {
return false;
}
}
this.setConsolidatedModels();
this.ready = true;
if (this.success != null) {
return this.success();
}
};
SwaggerApi.prototype.fail = function(message) {
this.failure(message);
throw message;
};
SwaggerApi.prototype.setConsolidatedModels = function() {
var model, modelName, resource, resource_name, _i, _len, _ref, _ref1, _results;
this.modelsArray = [];
this.models = {};
_ref = this.apis;
for (resource_name in _ref) {
resource = _ref[resource_name];
for (modelName in resource.models) {
if (!(this.models[modelName] != null)) {
this.models[modelName] = resource.models[modelName];
this.modelsArray.push(resource.models[modelName]);
}
}
}
_ref1 = this.modelsArray;
_results = [];
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
model = _ref1[_i];
_results.push(model.setReferencedModels(this.models));
}
return _results;
};
SwaggerApi.prototype.suffixApiKey = function(url) {
var sep;
if ((this.api_key != null) && jQuery.trim(this.api_key).length > 0 && (url != null)) {
sep = url.indexOf('?') > 0 ? '&' : '?';
return url + sep + this.apiKeyName + '=' + this.api_key;
} else {
return url;
}
};
SwaggerApi.prototype.help = function() {
var operation, operation_name, parameter, resource, resource_name, _i, _len, _ref, _ref1, _ref2;
_ref = this.apis;
for (resource_name in _ref) {
resource = _ref[resource_name];
console.log(resource_name);
_ref1 = resource.operations;
for (operation_name in _ref1) {
operation = _ref1[operation_name];
console.log(" " + operation.nickname);
_ref2 = operation.parameters;
for (_i = 0, _len = _ref2.length; _i < _len; _i++) {
parameter = _ref2[_i];
console.log(" " + parameter.name + (parameter.required ? ' (required)' : '') + " - " + parameter.description);
}
}
}
return this;
};
return SwaggerApi;
})();
SwaggerResource = (function() {
function SwaggerResource(resourceObj, api) {
var parts,
_this = this;
this.api = api;
this.path = this.api.resourcePath != null ? this.api.resourcePath : resourceObj.path;
this.description = resourceObj.description;
parts = this.path.split("/");
this.name = parts[parts.length - 1].replace('.{format}', '');
this.basePath = this.api.basePath;
this.operations = {};
this.operationsArray = [];
this.modelsArray = [];
this.models = {};
if ((resourceObj.operations != null) && (this.api.resourcePath != null)) {
this.api.progress('reading resource ' + this.name + ' models and operations');
this.addModels(resourceObj.models);
this.addOperations(resourceObj.path, resourceObj.operations);
this.api[this.name] = this;
} else {
if (this.path == null) {
this.api.fail("SwaggerResources must have a path.");
}
this.url = this.api.suffixApiKey(this.api.basePath + this.path.replace('{format}', 'json'));
this.api.progress('fetching resource ' + this.name + ': ' + this.url);
jQuery.getJSON(this.url, function(response) {
var endpoint, _i, _len, _ref;
if ((response.basePath != null) && jQuery.trim(response.basePath).length > 0) {
_this.basePath = response.basePath;
_this.basePath = _this.basePath.replace(/\/$/, '');
}
_this.addModels(response.models);
if (response.apis) {
_ref = response.apis;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
endpoint = _ref[_i];
_this.addOperations(endpoint.path, endpoint.operations);
}
}
_this.api[_this.name] = _this;
_this.ready = true;
return _this.api.selfReflect();
}).error(function(error) {
return _this.api.fail("Unable to read api '" + _this.name + "' from path " + _this.url + " (server returned " + error.statusText + ")");
});
}
}
SwaggerResource.prototype.addModels = function(models) {
var model, modelName, swaggerModel, _i, _len, _ref, _results;
if (models != null) {
for (modelName in models) {
if (!(this.models[modelName] != null)) {
swaggerModel = new SwaggerModel(modelName, models[modelName]);
this.modelsArray.push(swaggerModel);
this.models[modelName] = swaggerModel;
}
}
_ref = this.modelsArray;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
model = _ref[_i];
_results.push(model.setReferencedModels(this.models));
}
return _results;
}
};
SwaggerResource.prototype.addOperations = function(resource_path, ops) {
var consumes, o, op, _i, _len, _results;
if (ops) {
_results = [];
for (_i = 0, _len = ops.length; _i < _len; _i++) {
o = ops[_i];
consumes = o.consumes;
if (o.supportedContentTypes) {
consumes = o.supportedContentTypes;
}
op = new SwaggerOperation(o.nickname, resource_path, o.httpMethod, o.parameters, o.summary, o.notes, o.responseClass, o.errorResponses, this, o.consumes, o.produces);
this.operations[op.nickname] = op;
_results.push(this.operationsArray.push(op));
}
return _results;
}
};
SwaggerResource.prototype.help = function() {
var operation, operation_name, parameter, _i, _len, _ref, _ref1;
_ref = this.operations;
for (operation_name in _ref) {
operation = _ref[operation_name];
console.log(" " + operation.nickname);
_ref1 = operation.parameters;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
parameter = _ref1[_i];
console.log(" " + parameter.name + (parameter.required ? ' (required)' : '') + " - " + parameter.description);
}
}
return this;
};
return SwaggerResource;
})();
SwaggerModel = (function() {
function SwaggerModel(modelName, obj) {
var propertyName;
this.name = obj.id != null ? obj.id : modelName;
this.properties = [];
for (propertyName in obj.properties) {
this.properties.push(new SwaggerModelProperty(propertyName, obj.properties[propertyName]));
}
}
SwaggerModel.prototype.setReferencedModels = function(allModels) {
var prop, _i, _len, _ref, _results;
_ref = this.properties;
_results = [];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
prop = _ref[_i];
if (allModels[prop.dataType] != null) {
_results.push(prop.refModel = allModels[prop.dataType]);
} else if ((prop.refDataType != null) && (allModels[prop.refDataType] != null)) {
_results.push(prop.refModel = allModels[prop.refDataType]);
} else {
_results.push(void 0);
}
}
return _results;
};
SwaggerModel.prototype.getMockSignature = function(prefix, modelsToIgnore) {
var classClose, classOpen, prop, propertiesStr, returnVal, strong, strongClose, stronger, _i, _j, _len, _len1, _ref, _ref1;
propertiesStr = [];
_ref = this.properties;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
prop = _ref[_i];
propertiesStr.push(prop.toString());
}
strong = '<span style="font-weight: bold; color: #000; font-size: 1.0em">';
stronger = '<span style="font-weight: bold; color: #000; font-size: 1.1em">';
strongClose = '</span>';
classOpen = strong + 'class ' + this.name + '(' + strongClose;
classClose = strong + ')' + strongClose;
returnVal = classOpen + '<span>' + propertiesStr.join('</span>, <span>') + '</span>' + classClose;
if (prefix != null) {
returnVal = stronger + prefix + strongClose + '<br/>' + returnVal;
}
if (!modelsToIgnore) {
modelsToIgnore = [];
}
modelsToIgnore.push(this);
_ref1 = this.properties;
for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) {
prop = _ref1[_j];
if ((prop.refModel != null) && (modelsToIgnore.indexOf(prop.refModel)) === -1) {
returnVal = returnVal + ('<br>' + prop.refModel.getMockSignature(void 0, modelsToIgnore));
}
}
return returnVal;
};
SwaggerModel.prototype.createJSONSample = function(modelToIgnore) {
var prop, result, _i, _len, _ref;
result = {};
_ref = this.properties;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
prop = _ref[_i];
result[prop.name] = prop.getSampleValue(modelToIgnore);
}
return result;
};
return SwaggerModel;
})();
SwaggerModelProperty = (function() {
function SwaggerModelProperty(name, obj) {
this.name = name;
this.dataType = obj.type;
this.isArray = this.dataType.toLowerCase() === 'array';
this.descr = obj.description;
if (obj.items != null) {
if (obj.items.type != null) {
this.refDataType = obj.items.type;
}
if (obj.items.$ref != null) {
this.refDataType = obj.items.$ref;
}
}
this.dataTypeWithRef = this.refDataType != null ? this.dataType + '[' + this.refDataType + ']' : this.dataType;
if (obj.allowableValues != null) {
this.valueType = obj.allowableValues.valueType;
this.values = obj.allowableValues.values;
if (this.values != null) {
this.valuesString = "'" + this.values.join("' or '") + "'";
}
}
}
SwaggerModelProperty.prototype.getSampleValue = function(modelToIgnore) {
var result;
if ((this.refModel != null) && (!(this.refModel === modelToIgnore))) {
result = this.refModel.createJSONSample(this.refModel);
} else {
if (this.isArray) {
result = this.refDataType;
} else {
result = this.dataType;
}
}
if (this.isArray) {
return [result];
} else {
return result;
}
};
SwaggerModelProperty.prototype.toString = function() {
var str;
str = this.name + ': ' + this.dataTypeWithRef;
if (this.values != null) {
str += " = ['" + this.values.join("' or '") + "']";
}
if (this.descr != null) {
str += ' {' + this.descr + '}';
}
return str;
};
return SwaggerModelProperty;
})();
SwaggerOperation = (function() {
function SwaggerOperation(nickname, path, httpMethod, parameters, summary, notes, responseClass, errorResponses, resource, consumes, produces) {
var parameter, v, _i, _j, _len, _len1, _ref, _ref1, _ref2,
_this = this;
this.nickname = nickname;
this.path = path;
this.httpMethod = httpMethod;
this.parameters = parameters != null ? parameters : [];
this.summary = summary;
this.notes = notes;
this.responseClass = responseClass;
this.errorResponses = errorResponses;
this.resource = resource;
this.consumes = consumes;
this.produces = produces;
this["do"] = __bind(this["do"], this);
if (this.nickname == null) {
this.resource.api.fail("SwaggerOperations must have a nickname.");
}
if (this.path == null) {
this.resource.api.fail("SwaggerOperation " + nickname + " is missing path.");
}
if (this.httpMethod == null) {
this.resource.api.fail("SwaggerOperation " + nickname + " is missing httpMethod.");
}
this.path = this.path.replace('{format}', 'json');
this.httpMethod = this.httpMethod.toLowerCase();
this.isGetMethod = this.httpMethod === "get";
this.resourceName = this.resource.name;
if (((_ref = this.responseClass) != null ? _ref.toLowerCase() : void 0) === 'void') {
this.responseClass = void 0;
}
if (this.responseClass != null) {
this.responseClassSignature = this.getSignature(this.responseClass, this.resource.models);
this.responseSampleJSON = this.getSampleJSON(this.responseClass, this.resource.models);
}
this.errorResponses = this.errorResponses || [];
_ref1 = this.parameters;
for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
parameter = _ref1[_i];
parameter.name = parameter.name || parameter.dataType;
if (parameter.dataType.toLowerCase() === 'boolean') {
parameter.allowableValues = {};
parameter.allowableValues.values = this.resource.api.booleanValues;
}
parameter.signature = this.getSignature(parameter.dataType, this.resource.models);
parameter.sampleJSON = this.getSampleJSON(parameter.dataType, this.resource.models);
if (parameter.allowableValues != null) {
if (parameter.allowableValues.valueType === "RANGE") {
parameter.isRange = true;
} else {
parameter.isList = true;
}
if (parameter.allowableValues.values != null) {
parameter.allowableValues.descriptiveValues = [];
_ref2 = parameter.allowableValues.values;
for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) {
v = _ref2[_j];
if ((parameter.defaultValue != null) && parameter.defaultValue === v) {
parameter.allowableValues.descriptiveValues.push({
value: v,
isDefault: true
});
} else {
parameter.allowableValues.descriptiveValues.push({
value: v,
isDefault: false
});
}
}
}
}
}
this.resource[this.nickname] = function(args, callback, error) {
return _this["do"](args, callback, error);
};
}
SwaggerOperation.prototype.isListType = function(dataType) {
if (dataType.indexOf('[') >= 0) {
return dataType.substring(dataType.indexOf('[') + 1, dataType.indexOf(']'));
} else {
return void 0;
}
};
SwaggerOperation.prototype.getSignature = function(dataType, models) {
var isPrimitive, listType;
listType = this.isListType(dataType);
isPrimitive = ((listType != null) && models[listType]) || (models[dataType] != null) ? false : true;
if (isPrimitive) {
return dataType;
} else {
if (listType != null) {
return models[listType].getMockSignature(dataType);
} else {
return models[dataType].getMockSignature(dataType);
}
}
};
SwaggerOperation.prototype.getSampleJSON = function(dataType, models) {
var isPrimitive, listType, val;
listType = this.isListType(dataType);
isPrimitive = ((listType != null) && models[listType]) || (models[dataType] != null) ? false : true;
val = isPrimitive ? void 0 : (listType != null ? models[listType].createJSONSample() : models[dataType].createJSONSample());
if (val) {
val = listType ? [val] : val;
return JSON.stringify(val, null, 2);
}
};
SwaggerOperation.prototype["do"] = function(args, callback, error) {
var body, headers;
if (args == null) {
args = {};
}
if ((typeof args) === "function") {
error = callback;
callback = args;
args = {};
}
if (error == null) {
error = function(xhr, textStatus, error) {
return console.log(xhr, textStatus, error);
};
}
if (callback == null) {
callback = function(data) {
return console.log(data);
};
}
if (args.headers != null) {
headers = args.headers;
delete args.headers;
}
if (args.body != null) {
body = args.body;
delete args.body;
}
return new SwaggerRequest(this.httpMethod, this.urlify(args), headers, body, callback, error, this);
};
SwaggerOperation.prototype.pathJson = function() {
return this.path.replace("{format}", "json");
};
SwaggerOperation.prototype.pathXml = function() {
return this.path.replace("{format}", "xml");
};
SwaggerOperation.prototype.urlify = function(args, includeApiKey) {
var param, queryParams, reg, url, _i, _len, _ref;
if (includeApiKey == null) {
includeApiKey = true;
}
url = this.resource.basePath + this.pathJson();
_ref = this.parameters;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
param = _ref[_i];
if (param.paramType === 'path') {
if (args[param.name]) {
reg = new RegExp('\{' + param.name + '[^\}]*\}', 'gi');
url = url.replace(reg, encodeURIComponent(args[param.name]));
delete args[param.name];
} else {
throw "" + param.name + " is a required path param.";
}
}
}
if (includeApiKey && (this.resource.api.api_key != null) && this.resource.api.api_key.length > 0) {
args[this.apiKeyName] = this.resource.api.api_key;
}
if (this.supportHeaderParams()) {
queryParams = jQuery.param(this.getQueryParams(args, includeApiKey));
} else {
queryParams = jQuery.param(this.getQueryAndHeaderParams(args, includeApiKey));
}
if ((queryParams != null) && queryParams.length > 0) {
url += "?" + queryParams;
}
return url;
};
SwaggerOperation.prototype.supportHeaderParams = function() {
return this.resource.api.supportHeaderParams;
};
SwaggerOperation.prototype.supportedSubmitMethods = function() {
return this.resource.api.supportedSubmitMethods;
};
SwaggerOperation.prototype.getQueryAndHeaderParams = function(args, includeApiKey) {
if (includeApiKey == null) {
includeApiKey = true;
}
return this.getMatchingParams(['query', 'header'], args, includeApiKey);
};
SwaggerOperation.prototype.getQueryParams = function(args, includeApiKey) {
if (includeApiKey == null) {
includeApiKey = true;
}
return this.getMatchingParams(['query'], args, includeApiKey);
};
SwaggerOperation.prototype.getHeaderParams = function(args, includeApiKey) {
if (includeApiKey == null) {
includeApiKey = true;
}
return this.getMatchingParams(['header'], args, includeApiKey);
};
SwaggerOperation.prototype.getMatchingParams = function(paramTypes, args, includeApiKey) {
var matchingParams, name, param, value, _i, _len, _ref, _ref1;
matchingParams = {};
_ref = this.parameters;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
param = _ref[_i];
if ((jQuery.inArray(param.paramType, paramTypes) >= 0) && args[param.name]) {
matchingParams[param.name] = args[param.name];
}
}
if (includeApiKey && (this.resource.api.api_key != null) && this.resource.api.api_key.length > 0) {
matchingParams[this.resource.api.apiKeyName] = this.resource.api.api_key;
}
if (jQuery.inArray('header', paramTypes) >= 0) {
_ref1 = this.resource.api.headers;
for (name in _ref1) {
value = _ref1[name];
matchingParams[name] = value;
}
}
return matchingParams;
};
SwaggerOperation.prototype.help = function() {
var parameter, _i, _len, _ref;
_ref = this.parameters;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
parameter = _ref[_i];
console.log(" " + parameter.name + (parameter.required ? ' (required)' : '') + " - " + parameter.description);
}
return this;
};
return SwaggerOperation;
})();
SwaggerRequest = (function() {
function SwaggerRequest(type, url, headers, body, successCallback, errorCallback, operation) {
var obj,
_this = this;
this.type = type;
this.url = url;
this.headers = headers;
this.body = body;
this.successCallback = successCallback;
this.errorCallback = errorCallback;
this.operation = operation;
if (this.type == null) {
throw "SwaggerRequest type is required (get/post/put/delete).";
}
if (this.url == null) {
throw "SwaggerRequest url is required.";
}
if (this.successCallback == null) {
throw "SwaggerRequest successCallback is required.";
}
if (this.errorCallback == null) {
throw "SwaggerRequest error callback is required.";
}
if (this.operation == null) {
throw "SwaggerRequest operation is required.";
}
if (this.operation.resource.api.verbose) {
console.log(this.asCurl());
}
this.headers || (this.headers = {});
if (this.operation.resource.api.api_key != null) {
this.headers[this.apiKeyName] = this.operation.resource.api.api_key;
}
if (this.headers.mock == null) {
obj = {
type: this.type,
url: this.url,
data: JSON.stringify(this.body),
dataType: 'json',
error: function(xhr, textStatus, error) {
return _this.errorCallback(xhr, textStatus, error);
},
success: function(data) {
return _this.successCallback(data);
}
};
if (obj.type.toLowerCase() === "post" || obj.type.toLowerCase() === "put") {
obj.contentType = "application/json";
}
jQuery.ajax(obj);
}
}
SwaggerRequest.prototype.asCurl = function() {
var header_args, k, v;
header_args = (function() {
var _ref, _results;
_ref = this.headers;
_results = [];
for (k in _ref) {
v = _ref[k];
_results.push("--header \"" + k + ": " + v + "\"");
}
return _results;
}).call(this);
return "curl " + (header_args.join(" ")) + " " + this.url;
};
return SwaggerRequest;
})();
window.SwaggerApi = SwaggerApi;
window.SwaggerResource = SwaggerResource;
window.SwaggerOperation = SwaggerOperation;
window.SwaggerRequest = SwaggerRequest;
}).call(this);

View File

@@ -0,0 +1,32 @@
// Underscore.js 1.3.3
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore is freely distributable under the MIT license.
// Portions of Underscore are inspired or borrowed from Prototype,
// Oliver Steele's Functional, and John Resig's Micro-Templating.
// For all details and documentation:
// http://documentcloud.github.com/underscore
(function(){function r(a,c,d){if(a===c)return 0!==a||1/a==1/c;if(null==a||null==c)return a===c;a._chain&&(a=a._wrapped);c._chain&&(c=c._wrapped);if(a.isEqual&&b.isFunction(a.isEqual))return a.isEqual(c);if(c.isEqual&&b.isFunction(c.isEqual))return c.isEqual(a);var e=l.call(a);if(e!=l.call(c))return!1;switch(e){case "[object String]":return a==""+c;case "[object Number]":return a!=+a?c!=+c:0==a?1/a==1/c:a==+c;case "[object Date]":case "[object Boolean]":return+a==+c;case "[object RegExp]":return a.source==
c.source&&a.global==c.global&&a.multiline==c.multiline&&a.ignoreCase==c.ignoreCase}if("object"!=typeof a||"object"!=typeof c)return!1;for(var f=d.length;f--;)if(d[f]==a)return!0;d.push(a);var f=0,g=!0;if("[object Array]"==e){if(f=a.length,g=f==c.length)for(;f--&&(g=f in a==f in c&&r(a[f],c[f],d)););}else{if("constructor"in a!="constructor"in c||a.constructor!=c.constructor)return!1;for(var h in a)if(b.has(a,h)&&(f++,!(g=b.has(c,h)&&r(a[h],c[h],d))))break;if(g){for(h in c)if(b.has(c,h)&&!f--)break;
g=!f}}d.pop();return g}var s=this,I=s._,o={},k=Array.prototype,p=Object.prototype,i=k.slice,J=k.unshift,l=p.toString,K=p.hasOwnProperty,y=k.forEach,z=k.map,A=k.reduce,B=k.reduceRight,C=k.filter,D=k.every,E=k.some,q=k.indexOf,F=k.lastIndexOf,p=Array.isArray,L=Object.keys,t=Function.prototype.bind,b=function(a){return new m(a)};"undefined"!==typeof exports?("undefined"!==typeof module&&module.exports&&(exports=module.exports=b),exports._=b):s._=b;b.VERSION="1.3.3";var j=b.each=b.forEach=function(a,
c,d){if(a!=null)if(y&&a.forEach===y)a.forEach(c,d);else if(a.length===+a.length)for(var e=0,f=a.length;e<f;e++){if(e in a&&c.call(d,a[e],e,a)===o)break}else for(e in a)if(b.has(a,e)&&c.call(d,a[e],e,a)===o)break};b.map=b.collect=function(a,c,b){var e=[];if(a==null)return e;if(z&&a.map===z)return a.map(c,b);j(a,function(a,g,h){e[e.length]=c.call(b,a,g,h)});if(a.length===+a.length)e.length=a.length;return e};b.reduce=b.foldl=b.inject=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(A&&
a.reduce===A){e&&(c=b.bind(c,e));return f?a.reduce(c,d):a.reduce(c)}j(a,function(a,b,i){if(f)d=c.call(e,d,a,b,i);else{d=a;f=true}});if(!f)throw new TypeError("Reduce of empty array with no initial value");return d};b.reduceRight=b.foldr=function(a,c,d,e){var f=arguments.length>2;a==null&&(a=[]);if(B&&a.reduceRight===B){e&&(c=b.bind(c,e));return f?a.reduceRight(c,d):a.reduceRight(c)}var g=b.toArray(a).reverse();e&&!f&&(c=b.bind(c,e));return f?b.reduce(g,c,d,e):b.reduce(g,c)};b.find=b.detect=function(a,
c,b){var e;G(a,function(a,g,h){if(c.call(b,a,g,h)){e=a;return true}});return e};b.filter=b.select=function(a,c,b){var e=[];if(a==null)return e;if(C&&a.filter===C)return a.filter(c,b);j(a,function(a,g,h){c.call(b,a,g,h)&&(e[e.length]=a)});return e};b.reject=function(a,c,b){var e=[];if(a==null)return e;j(a,function(a,g,h){c.call(b,a,g,h)||(e[e.length]=a)});return e};b.every=b.all=function(a,c,b){var e=true;if(a==null)return e;if(D&&a.every===D)return a.every(c,b);j(a,function(a,g,h){if(!(e=e&&c.call(b,
a,g,h)))return o});return!!e};var G=b.some=b.any=function(a,c,d){c||(c=b.identity);var e=false;if(a==null)return e;if(E&&a.some===E)return a.some(c,d);j(a,function(a,b,h){if(e||(e=c.call(d,a,b,h)))return o});return!!e};b.include=b.contains=function(a,c){var b=false;if(a==null)return b;if(q&&a.indexOf===q)return a.indexOf(c)!=-1;return b=G(a,function(a){return a===c})};b.invoke=function(a,c){var d=i.call(arguments,2);return b.map(a,function(a){return(b.isFunction(c)?c||a:a[c]).apply(a,d)})};b.pluck=
function(a,c){return b.map(a,function(a){return a[c]})};b.max=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.max.apply(Math,a);if(!c&&b.isEmpty(a))return-Infinity;var e={computed:-Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b>=e.computed&&(e={value:a,computed:b})});return e.value};b.min=function(a,c,d){if(!c&&b.isArray(a)&&a[0]===+a[0])return Math.min.apply(Math,a);if(!c&&b.isEmpty(a))return Infinity;var e={computed:Infinity};j(a,function(a,b,h){b=c?c.call(d,a,b,h):a;b<e.computed&&
(e={value:a,computed:b})});return e.value};b.shuffle=function(a){var b=[],d;j(a,function(a,f){d=Math.floor(Math.random()*(f+1));b[f]=b[d];b[d]=a});return b};b.sortBy=function(a,c,d){var e=b.isFunction(c)?c:function(a){return a[c]};return b.pluck(b.map(a,function(a,b,c){return{value:a,criteria:e.call(d,a,b,c)}}).sort(function(a,b){var c=a.criteria,d=b.criteria;return c===void 0?1:d===void 0?-1:c<d?-1:c>d?1:0}),"value")};b.groupBy=function(a,c){var d={},e=b.isFunction(c)?c:function(a){return a[c]};
j(a,function(a,b){var c=e(a,b);(d[c]||(d[c]=[])).push(a)});return d};b.sortedIndex=function(a,c,d){d||(d=b.identity);for(var e=0,f=a.length;e<f;){var g=e+f>>1;d(a[g])<d(c)?e=g+1:f=g}return e};b.toArray=function(a){return!a?[]:b.isArray(a)||b.isArguments(a)?i.call(a):a.toArray&&b.isFunction(a.toArray)?a.toArray():b.values(a)};b.size=function(a){return b.isArray(a)?a.length:b.keys(a).length};b.first=b.head=b.take=function(a,b,d){return b!=null&&!d?i.call(a,0,b):a[0]};b.initial=function(a,b,d){return i.call(a,
0,a.length-(b==null||d?1:b))};b.last=function(a,b,d){return b!=null&&!d?i.call(a,Math.max(a.length-b,0)):a[a.length-1]};b.rest=b.tail=function(a,b,d){return i.call(a,b==null||d?1:b)};b.compact=function(a){return b.filter(a,function(a){return!!a})};b.flatten=function(a,c){return b.reduce(a,function(a,e){if(b.isArray(e))return a.concat(c?e:b.flatten(e));a[a.length]=e;return a},[])};b.without=function(a){return b.difference(a,i.call(arguments,1))};b.uniq=b.unique=function(a,c,d){var d=d?b.map(a,d):a,
e=[];a.length<3&&(c=true);b.reduce(d,function(d,g,h){if(c?b.last(d)!==g||!d.length:!b.include(d,g)){d.push(g);e.push(a[h])}return d},[]);return e};b.union=function(){return b.uniq(b.flatten(arguments,true))};b.intersection=b.intersect=function(a){var c=i.call(arguments,1);return b.filter(b.uniq(a),function(a){return b.every(c,function(c){return b.indexOf(c,a)>=0})})};b.difference=function(a){var c=b.flatten(i.call(arguments,1),true);return b.filter(a,function(a){return!b.include(c,a)})};b.zip=function(){for(var a=
i.call(arguments),c=b.max(b.pluck(a,"length")),d=Array(c),e=0;e<c;e++)d[e]=b.pluck(a,""+e);return d};b.indexOf=function(a,c,d){if(a==null)return-1;var e;if(d){d=b.sortedIndex(a,c);return a[d]===c?d:-1}if(q&&a.indexOf===q)return a.indexOf(c);d=0;for(e=a.length;d<e;d++)if(d in a&&a[d]===c)return d;return-1};b.lastIndexOf=function(a,b){if(a==null)return-1;if(F&&a.lastIndexOf===F)return a.lastIndexOf(b);for(var d=a.length;d--;)if(d in a&&a[d]===b)return d;return-1};b.range=function(a,b,d){if(arguments.length<=
1){b=a||0;a=0}for(var d=arguments[2]||1,e=Math.max(Math.ceil((b-a)/d),0),f=0,g=Array(e);f<e;){g[f++]=a;a=a+d}return g};var H=function(){};b.bind=function(a,c){var d,e;if(a.bind===t&&t)return t.apply(a,i.call(arguments,1));if(!b.isFunction(a))throw new TypeError;e=i.call(arguments,2);return d=function(){if(!(this instanceof d))return a.apply(c,e.concat(i.call(arguments)));H.prototype=a.prototype;var b=new H,g=a.apply(b,e.concat(i.call(arguments)));return Object(g)===g?g:b}};b.bindAll=function(a){var c=
i.call(arguments,1);c.length==0&&(c=b.functions(a));j(c,function(c){a[c]=b.bind(a[c],a)});return a};b.memoize=function(a,c){var d={};c||(c=b.identity);return function(){var e=c.apply(this,arguments);return b.has(d,e)?d[e]:d[e]=a.apply(this,arguments)}};b.delay=function(a,b){var d=i.call(arguments,2);return setTimeout(function(){return a.apply(null,d)},b)};b.defer=function(a){return b.delay.apply(b,[a,1].concat(i.call(arguments,1)))};b.throttle=function(a,c){var d,e,f,g,h,i,j=b.debounce(function(){h=
g=false},c);return function(){d=this;e=arguments;f||(f=setTimeout(function(){f=null;h&&a.apply(d,e);j()},c));g?h=true:i=a.apply(d,e);j();g=true;return i}};b.debounce=function(a,b,d){var e;return function(){var f=this,g=arguments;d&&!e&&a.apply(f,g);clearTimeout(e);e=setTimeout(function(){e=null;d||a.apply(f,g)},b)}};b.once=function(a){var b=false,d;return function(){if(b)return d;b=true;return d=a.apply(this,arguments)}};b.wrap=function(a,b){return function(){var d=[a].concat(i.call(arguments,0));
return b.apply(this,d)}};b.compose=function(){var a=arguments;return function(){for(var b=arguments,d=a.length-1;d>=0;d--)b=[a[d].apply(this,b)];return b[0]}};b.after=function(a,b){return a<=0?b():function(){if(--a<1)return b.apply(this,arguments)}};b.keys=L||function(a){if(a!==Object(a))throw new TypeError("Invalid object");var c=[],d;for(d in a)b.has(a,d)&&(c[c.length]=d);return c};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){j(i.call(arguments,1),function(b){for(var d in b)a[d]=b[d]});return a};b.pick=function(a){var c={};j(b.flatten(i.call(arguments,1)),function(b){b in a&&(c[b]=a[b])});return c};b.defaults=function(a){j(i.call(arguments,1),function(b){for(var d in b)a[d]==null&&(a[d]=b[d])});return a};b.clone=function(a){return!b.isObject(a)?a:b.isArray(a)?a.slice():b.extend({},a)};b.tap=function(a,b){b(a);return a};b.isEqual=function(a,b){return r(a,b,[])};b.isEmpty=
function(a){if(a==null)return true;if(b.isArray(a)||b.isString(a))return a.length===0;for(var c in a)if(b.has(a,c))return false;return true};b.isElement=function(a){return!!(a&&a.nodeType==1)};b.isArray=p||function(a){return l.call(a)=="[object Array]"};b.isObject=function(a){return a===Object(a)};b.isArguments=function(a){return l.call(a)=="[object Arguments]"};b.isArguments(arguments)||(b.isArguments=function(a){return!(!a||!b.has(a,"callee"))});b.isFunction=function(a){return l.call(a)=="[object Function]"};
b.isString=function(a){return l.call(a)=="[object String]"};b.isNumber=function(a){return l.call(a)=="[object Number]"};b.isFinite=function(a){return b.isNumber(a)&&isFinite(a)};b.isNaN=function(a){return a!==a};b.isBoolean=function(a){return a===true||a===false||l.call(a)=="[object Boolean]"};b.isDate=function(a){return l.call(a)=="[object Date]"};b.isRegExp=function(a){return l.call(a)=="[object RegExp]"};b.isNull=function(a){return a===null};b.isUndefined=function(a){return a===void 0};b.has=function(a,
b){return K.call(a,b)};b.noConflict=function(){s._=I;return this};b.identity=function(a){return a};b.times=function(a,b,d){for(var e=0;e<a;e++)b.call(d,e)};b.escape=function(a){return(""+a).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;").replace(/\//g,"&#x2F;")};b.result=function(a,c){if(a==null)return null;var d=a[c];return b.isFunction(d)?d.call(a):d};b.mixin=function(a){j(b.functions(a),function(c){M(c,b[c]=a[c])})};var N=0;b.uniqueId=
function(a){var b=N++;return a?a+b:b};b.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var u=/.^/,n={"\\":"\\","'":"'",r:"\r",n:"\n",t:"\t",u2028:"\u2028",u2029:"\u2029"},v;for(v in n)n[n[v]]=v;var O=/\\|'|\r|\n|\t|\u2028|\u2029/g,P=/\\(\\|'|r|n|t|u2028|u2029)/g,w=function(a){return a.replace(P,function(a,b){return n[b]})};b.template=function(a,c,d){d=b.defaults(d||{},b.templateSettings);a="__p+='"+a.replace(O,function(a){return"\\"+n[a]}).replace(d.escape||
u,function(a,b){return"'+\n_.escape("+w(b)+")+\n'"}).replace(d.interpolate||u,function(a,b){return"'+\n("+w(b)+")+\n'"}).replace(d.evaluate||u,function(a,b){return"';\n"+w(b)+"\n;__p+='"})+"';\n";d.variable||(a="with(obj||{}){\n"+a+"}\n");var a="var __p='';var print=function(){__p+=Array.prototype.join.call(arguments, '')};\n"+a+"return __p;\n",e=new Function(d.variable||"obj","_",a);if(c)return e(c,b);c=function(a){return e.call(this,a,b)};c.source="function("+(d.variable||"obj")+"){\n"+a+"}";return c};
b.chain=function(a){return b(a).chain()};var m=function(a){this._wrapped=a};b.prototype=m.prototype;var x=function(a,c){return c?b(a).chain():a},M=function(a,c){m.prototype[a]=function(){var a=i.call(arguments);J.call(a,this._wrapped);return x(c.apply(b,a),this._chain)}};b.mixin(b);j("pop,push,reverse,shift,sort,splice,unshift".split(","),function(a){var b=k[a];m.prototype[a]=function(){var d=this._wrapped;b.apply(d,arguments);var e=d.length;(a=="shift"||a=="splice")&&e===0&&delete d[0];return x(d,
this._chain)}});j(["concat","join","slice"],function(a){var b=k[a];m.prototype[a]=function(){return x(b.apply(this._wrapped,arguments),this._chain)}});m.prototype.chain=function(){this._chain=true;return this};m.prototype.value=function(){return this._wrapped}}).call(this);

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long