first stabilization of editing a renkan.
authorymh <ymh.work@gmail.com>
Tue, 25 Dec 2012 21:29:11 +0100
changeset 47 267d67791e05
parent 46 7e132e2a48ca
child 48 01fb9167ad75
first stabilization of editing a renkan. No collaborative capacities yet.
.classpath
server/pom.xml
server/src/main/java/org/iri_research/renkan/controller/RenkanController.java
server/src/main/java/org/iri_research/renkan/coweb/RenkanSessionModerator.java
server/src/main/java/org/iri_research/renkan/coweb/event/AbstractSyncEventManager.java
server/src/main/java/org/iri_research/renkan/coweb/event/EdgeSyncEventManager.java
server/src/main/java/org/iri_research/renkan/coweb/event/ISyncEventManager.java
server/src/main/java/org/iri_research/renkan/coweb/event/NodeSyncEventManager.java
server/src/main/java/org/iri_research/renkan/coweb/event/ProjectSyncEventManager.java
server/src/main/java/org/iri_research/renkan/coweb/event/UserSyncEventManager.java
server/src/main/java/org/iri_research/renkan/models/Edge.java
server/src/main/java/org/iri_research/renkan/models/Node.java
server/src/main/java/org/iri_research/renkan/models/Project.java
server/src/main/java/org/iri_research/renkan/models/ProjectRevision.java
server/src/main/java/org/iri_research/renkan/models/Relation.java
server/src/main/java/org/iri_research/renkan/models/User.java
server/src/main/java/org/iri_research/renkan/repositories/EdgesRepository.java
server/src/main/java/org/iri_research/renkan/repositories/RelationsRepository.java
server/src/main/java/org/iri_research/renkan/repositories/UsersRepository.java
server/src/main/java/org/iri_research/renkan/rest/ProjectsResource.java
server/src/main/webapp/WEB-INF/jsp/projectPrompt.jsp
server/src/main/webapp/WEB-INF/spring-servlet.xml
server/src/main/webapp/WEB-INF/templates/renkanProjectEdit.html
server/src/main/webapp/WEB-INF/templates/renkanProjectRender.html
server/src/main/webapp/WEB-INF/web.xml
server/src/main/webapp/css/style.css
server/src/main/webapp/index.html
server/src/main/webapp/js/backbone-relational.js
server/src/main/webapp/js/backbone.js
server/src/main/webapp/js/config.js
server/src/main/webapp/js/corenkan.js
server/src/main/webapp/js/dojo.js
server/src/main/webapp/js/main_coweb.js
server/src/main/webapp/js/main_test_models.js
server/src/main/webapp/js/models.js
server/src/main/webapp/js/underscore.js
server/src/main/webapp/static/css/index.css
server/src/main/webapp/static/css/renkan-publish.css
server/src/main/webapp/static/css/renkan.css
server/src/main/webapp/static/css/style.css
server/src/main/webapp/static/data/simple-persist.php
server/src/main/webapp/static/data/test-data.json
server/src/main/webapp/static/img/edit.png
server/src/main/webapp/static/img/goto.png
server/src/main/webapp/static/img/ldt-point.png
server/src/main/webapp/static/img/ldt-segment.png
server/src/main/webapp/static/img/ldt-tag.png
server/src/main/webapp/static/img/link.png
server/src/main/webapp/static/img/more.png
server/src/main/webapp/static/img/refresh.png
server/src/main/webapp/static/img/remove.png
server/src/main/webapp/static/img/search-logos.png
server/src/main/webapp/static/img/search.png
server/src/main/webapp/static/img/tooltiparrow.png
server/src/main/webapp/static/img/topbarbuttons.png
server/src/main/webapp/static/img/wikipedia.png
server/src/main/webapp/static/img/zoombuttons.png
server/src/main/webapp/static/js/config.js
server/src/main/webapp/static/js/corenkan-json.js
server/src/main/webapp/static/js/corenkan.js
server/src/main/webapp/static/js/dojo.js
server/src/main/webapp/static/js/full-json.js
server/src/main/webapp/static/js/i18n.js
server/src/main/webapp/static/js/ldtjson-bin.js
server/src/main/webapp/static/js/main.js
server/src/main/webapp/static/js/main_coweb.js
server/src/main/webapp/static/js/main_test_models.js
server/src/main/webapp/static/js/models.js
server/src/main/webapp/static/js/paper-renderer.js
server/src/main/webapp/static/js/random-data.js
server/src/main/webapp/static/js/renkan-publish.js
server/src/main/webapp/static/js/twitter-bin.js
server/src/main/webapp/static/js/underscore.js
server/src/main/webapp/static/js/wikipedia-bin.js
server/src/main/webapp/static/lib/backbone-relational.js
server/src/main/webapp/static/lib/backbone.js
server/src/main/webapp/static/lib/jquery.min.js
server/src/main/webapp/static/lib/jquery.mousewheel.min.js
server/src/main/webapp/static/lib/paper.js
server/src/main/webapp/static/lib/underscore-min.js
--- a/.classpath	Tue Dec 11 00:01:41 2012 +0100
+++ b/.classpath	Tue Dec 25 21:29:11 2012 +0100
@@ -9,21 +9,21 @@
 	</classpathentry>
 	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.web.container"/>
 	<classpathentry kind="con" path="org.eclipse.jst.j2ee.internal.module.container"/>
-	<classpathentry kind="var" path="M2_REPO/org/opencoweb/coweb-bots/0.8.3/coweb-bots-0.8.3.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/opencoweb/coweb-server/0.8.3/coweb-server-0.8.3.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/opencoweb/coweb-operationengine/0.8.3/coweb-operationengine-0.8.3.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/opencoweb/coweb-bots/0.8.4/coweb-bots-0.8.4.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/opencoweb/coweb-server/0.8.4/coweb-server-0.8.4.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/opencoweb/coweb-operationengine/0.8.4/coweb-operationengine-0.8.4.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/cometd/java/bayeux-api/2.5.0/bayeux-api-2.5.0.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/cometd/java/cometd-java-common/2.5.0/cometd-java-common-2.5.0.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/eclipse/jetty/jetty-util/7.6.7.v20120910/jetty-util-7.6.7.v20120910.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/slf4j/slf4j-api/1.6.6/slf4j-api-1.6.6.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/eclipse/jetty/jetty-continuation/7.6.7.v20120910/jetty-continuation-7.6.7.v20120910.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/eclipse/jetty/jetty-jmx/7.6.7.v20120910/jetty-jmx-7.6.7.v20120910.jar"/>
-	<classpathentry kind="var" path="M2_REPO/com/sun/jersey/jersey-server/1.14/jersey-server-1.14.jar"/>
-	<classpathentry kind="var" path="M2_REPO/com/sun/jersey/jersey-core/1.14/jersey-core-1.14.jar"/>
+	<classpathentry kind="var" path="M2_REPO/com/sun/jersey/jersey-server/1.16/jersey-server-1.16.jar"/>
+	<classpathentry kind="var" path="M2_REPO/com/sun/jersey/jersey-core/1.16/jersey-core-1.16.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/mongodb/mongo-java-driver/2.9.0/mongo-java-driver-2.9.0.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-context/3.1.2.RELEASE/spring-context-3.1.2.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-context/3.1.3.RELEASE/spring-context-3.1.3.RELEASE.jar"/>
 	<classpathentry kind="var" path="M2_REPO"/>
-	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-beans/3.1.2.RELEASE/spring-beans-3.1.2.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-beans/3.1.3.RELEASE/spring-beans-3.1.3.RELEASE.jar"/>
 	<classpathentry kind="var" path="M2_REPO/javax/persistence/persistence-api/1.0.2/persistence-api-1.0.2.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/springframework/data/spring-data-mongodb/1.1.0.RELEASE/spring-data-mongodb-1.1.0.RELEASE.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/springframework/data/spring-data-commons-core/1.4.0.RELEASE/spring-data-commons-core-1.4.0.RELEASE.jar"/>
@@ -32,9 +32,11 @@
 	<classpathentry kind="var" path="M2_REPO/org/cometd/java/cometd-java-annotations/2.5.0/cometd-java-annotations-2.5.0.jar"/>
 	<classpathentry kind="var" path="M2_REPO/org/cometd/java/cometd-java-server/2.5.0/cometd-java-server-2.5.0.jar"/>
 	<classpathentry kind="var" path="M2_REPO/javax/servlet/servlet-api/2.5/servlet-api-2.5.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-core/3.1.2.RELEASE/spring-core-3.1.2.RELEASE.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-web/3.0.0.RC3/spring-web-3.0.0.RC3.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-core/3.1.3.RELEASE/spring-core-3.1.3.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-web/3.1.3.RELEASE/spring-web-3.1.3.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-webmvc/3.1.3.RELEASE/spring-webmvc-3.1.3.RELEASE.jar"/>
 	<classpathentry kind="var" path="M2_REPO/junit/junit/4.10/junit-4.10.jar"/>
-	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-test/3.1.2.RELEASE/spring-test-3.1.2.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/org/springframework/spring-test/3.1.3.RELEASE/spring-test-3.1.3.RELEASE.jar"/>
+	<classpathentry kind="var" path="M2_REPO/javax/servlet/jstl/1.2/jstl-1.2.jar"/>
 	<classpathentry kind="output" path="server/target/classes"/>
 </classpath>
--- a/server/pom.xml	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/pom.xml	Tue Dec 25 21:29:11 2012 +0100
@@ -8,10 +8,11 @@
     <packaging>war</packaging>
 
     <properties>
-        <coweb-version>0.8.3.1</coweb-version>
-        <jersey-version>1.14</jersey-version>
-        <spring-version>3.1.2.RELEASE</spring-version>
-        <junit.version>4.10</junit.version>
+        <coweb-version>0.8.4</coweb-version>
+        <jersey-version>1.16</jersey-version>
+        <spring-version>3.1.3.RELEASE</spring-version>
+        <junit-version>4.10</junit-version>
+        <thymeleaf-version>2.0.14</thymeleaf-version>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
     </properties>
 
@@ -154,6 +155,14 @@
                     <groupId>org.springframework</groupId>
                     <artifactId>spring-core</artifactId>
                 </exclusion>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-web</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.springframework</groupId>
+                    <artifactId>spring-aop</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
         <dependency>
@@ -187,6 +196,11 @@
             <version>${spring-version}</version>
         </dependency>        
         <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-webmvc</artifactId>
+            <version>${spring-version}</version>
+        </dependency>        
+        <dependency>
             <groupId>org.springframework.data</groupId>
             <artifactId>spring-data-commons-core</artifactId>
             <version>1.4.0.RELEASE</version>
@@ -209,9 +223,35 @@
         <dependency>                          
             <groupId>junit</groupId>           
             <artifactId>junit</artifactId>     
-            <version>${junit.version}</version>
+            <version>${junit-version}</version>
             <scope>test</scope>                
-        </dependency>         
+        </dependency>
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>jstl</artifactId>
+            <version>1.2</version>
+            <scope>runtime</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.thymeleaf</groupId>
+            <artifactId>thymeleaf</artifactId>
+            <version>${thymeleaf-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.thymeleaf</groupId>
+            <artifactId>thymeleaf-spring3</artifactId>
+            <version>${thymeleaf-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>net.sourceforge.nekohtml</groupId>
+            <artifactId>nekohtml</artifactId>
+            <version>1.9.16</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.jaxrs</groupId>
+            <artifactId>jackson-jaxrs-json-provider</artifactId>
+            <version>2.1.2</version>
+        </dependency>                 
     </dependencies>
     <organization>
     	<name>IRI</name>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/controller/RenkanController.java	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,64 @@
+package org.iri_research.renkan.controller;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.iri_research.renkan.models.Project;
+import org.iri_research.renkan.repositories.ProjectsRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.HttpMediaTypeNotAcceptableException;
+import org.springframework.web.HttpMediaTypeNotSupportedException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+
+@Controller
+@RequestMapping("/")
+public class RenkanController {
+
+	private final Logger logger = LoggerFactory.getLogger(RenkanController.class);
+	
+	@Autowired
+	private ProjectsRepository projectRepository;
+	
+	@RequestMapping(value="/{project_id}", method = RequestMethod.GET, produces={"text/html", "!image/*"})
+	public ModelAndView renkanProject(@PathVariable(value="project_id") String project_id, @RequestHeader(value="Accept") String accept_header) throws HttpMediaTypeNotSupportedException {
+
+		this.logger.debug("renkanProject : " + project_id + " Accept : " + accept_header!=null?accept_header:"");
+		
+		if(accept_header != null && accept_header.matches(".*image/.*")) {
+			throw new HttpMediaTypeNotSupportedException("Do not orduce image");
+		}
+		
+		if(project_id == null || project_id.length() == 0) {
+			throw new IllegalArgumentException("RenkanContoller.renkanProject: Project id is null or empty.");
+		}
+		
+		Project project = this.projectRepository.findOne(project_id);
+
+		if(project == null) {
+			project = new Project(project_id, "(New project)", "(Project Description)", "");
+			this.projectRepository.save(project);
+		}
+		
+		Map<String, Object> model = new HashMap<String, Object>();
+		model.put("project", project);
+		
+		return new ModelAndView("renkanProjectEdit", model);
+	}
+	
+	/*@RequestMapping("/test")
+	public ModelAndView projectPrompt() {
+		String message = "Hello world, Spring";
+		
+		return new ModelAndView("projectPrompt", "message", message);
+	}*/
+	
+}
--- a/server/src/main/java/org/iri_research/renkan/coweb/RenkanSessionModerator.java	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/coweb/RenkanSessionModerator.java	Tue Dec 25 21:29:11 2012 +0100
@@ -19,7 +19,7 @@
 		
 	@SuppressWarnings("unchecked")
 	@Override
-	public boolean onSync(Map<String, Object> data) {
+	public void onSync(Map<String, Object> data) {
 				
 		this.logger.debug("Debugging onSync : " + data.toString());
 		this.logger.debug("Debugging onSync channel: " + data.get("channel"));
@@ -35,28 +35,27 @@
 		
 		if(values == null) {
 			this.logger.warn("onSync : no values in message.");
-			return super.onSync(data);		
+			return;		
 		}
 		
-		String sync_type = (String) values.get("type");
+		String sync_type = (String) values.get("_type");
 		if(sync_type == null || sync_type.length() == 0) {
 			this.logger.warn("onSync : no type in value of message.");
-			return super.onSync(data);
+			return;
 		}
 		
 		ApplicationContext context = SpringConfigurer.getInstance().getApplicationContext();
 				
 		//String className = String.format("org.iri_research.renkan.coweb.event.%sSyncEventManager", sync_type.substring(0, 1).toUpperCase()+sync_type.substring(1));
 		String beanName = String.format("%sSyncEventManager", sync_type.toLowerCase());
-		boolean resDispatch = false; 
 		
 		try {
-			ISyncEventManager eventManager = (ISyncEventManager)context.getBean(beanName);
+			ISyncEventManager<?, ?> eventManager = (ISyncEventManager<?, ?>)context.getBean(beanName);
 			logger.debug("Debugging on Sync : dispatch to " + beanName);
-			resDispatch = eventManager.dispatchEvent(data);
+			eventManager.dispatchEvent(data);
 		}
 		catch(Throwable e) {
-			this.logger.error(String.format("onSync EventManagerClass %s not found : error : %s", sync_type, e.getMessage()));
+			this.logger.error(String.format("onSync EventManagerClass %s not found : error %s : %s", sync_type, e.toString(), e.getMessage()));
 		}
 		/*catch (ClassNotFoundException e) {
 			this.logger.error(String.format("onSync EventManagerClass %s not found : ClassNotFoundException : %s", sync_type, e.getMessage()));
@@ -66,7 +65,6 @@
 			this.logger.error(String.format("onSync EventManagerClass %s not found : IllegalAccessException : %s", sync_type, e.getMessage()));
 		}*/
 		
-		return super.onSync(data) && resDispatch;
 	}
 
 }
--- a/server/src/main/java/org/iri_research/renkan/coweb/event/AbstractSyncEventManager.java	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/coweb/event/AbstractSyncEventManager.java	Tue Dec 25 21:29:11 2012 +0100
@@ -1,19 +1,29 @@
 package org.iri_research.renkan.coweb.event;
 
+import java.io.Serializable;
+import java.util.List;
 import java.util.Map;
 
 import javax.inject.Inject;
 
+import org.coweb.CowebException;
 import org.iri_research.renkan.RenkanException;
+import org.iri_research.renkan.models.IRenkanModel;
 import org.iri_research.renkan.models.Project;
 import org.iri_research.renkan.models.ProjectSync;
+import org.iri_research.renkan.repositories.IRenkanRepository;
 import org.iri_research.renkan.repositories.ProjectSyncsRepository;
 import org.iri_research.renkan.repositories.ProjectsRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBCollection;
+import com.mongodb.DBObject;
+import com.mongodb.WriteResult;
 
-public abstract class AbstractSyncEventManager implements ISyncEventManager {
+
+public abstract class AbstractSyncEventManager<T extends IRenkanModel<ID>, ID extends Serializable> implements ISyncEventManager<T,ID> {
 
 	private final Logger logger = LoggerFactory.getLogger(AbstractSyncEventManager.class);
 	
@@ -27,29 +37,32 @@
 	public ProjectsRepository getProjectsRepository() {
 		return this.projectsRepository;
 	}
+	
+	@Override
+	public abstract IRenkanRepository<T, ID> getObjectRepository();
 		
 	@Override
-	public boolean dispatchEvent(Map<String, Object> data) {
+	public void dispatchEvent(Map<String, Object> data) {
 		
 		this.saveSyncEvent(data);
 
 		String eventType = (String) data.get("type");
 		
 		if("null".equalsIgnoreCase(eventType)) {
-			return this.nullOperation(data);
+			this.nullOperation(data);
 		}
 		else if ("update".equalsIgnoreCase(eventType)) {
-			return this.update(data);
+			this.update(data);
 		}
 		else if ("insert".equalsIgnoreCase(eventType)) {
-			return this.insert(data);
+			this.insert(data);
 		}
 		else if("delete".equalsIgnoreCase(eventType)) {
-			return this.delete(data);
+			this.delete(data);
 		}
-		
-		logger.warn(String.format("dispatchEvent : eventType unknown %s", eventType));
-		return false;
+		else {		
+			logger.warn(String.format("dispatchEvent : eventType unknown %s", eventType));
+		}
 	}
 
 	private void saveSyncEvent(Map<String, Object> data) {
@@ -60,7 +73,7 @@
 		Map<String, Object> values = (Map<String, Object>) data.get("value");
 		
 		if(values != null) {
-			project_id = (String) values.get("project_id");
+			project_id = (String) values.get("_project_id");
 		}
 		
 		if (project_id == null || "".equals(project_id)) {
@@ -85,16 +98,109 @@
 		
 	}
 
-	@Override
-	public abstract boolean update(Map<String, Object> data);
+	protected abstract List<T> getObjectList(Project project);
 
 	@Override
-	public abstract boolean insert(Map<String, Object> data);
+	public void update(Map<String, Object> data) {
+		
+		this.logger.debug("AbstractSyncEventManager: update " + this.getClass().getName());
+		
+		@SuppressWarnings("unchecked")
+		Map<String, Object> values = (Map<String, Object>) data.get("value");
+		String obj_id = (String) values.get("id");
+		
+		this.logger.debug(String.format("update %s %s", this.getClass().getName(), obj_id));
+		
+		DBCollection objCollection = this.getObjectRepository().getCollection();
+		DBObject obj = objCollection.findOne(obj_id);
+		
+		if (null == obj) {
+			throw new CowebException("Object update: object not found", String.format("Object %s not found in %s", obj_id, objCollection.getName()));
+		}
+		
+		boolean obj_changed = false;
+		// update object
+		for (String fieldname : values.keySet()) {
+			if(!"id".equalsIgnoreCase(fieldname) && !fieldname.startsWith("_"))
+			{
+				Object new_value = values.get(fieldname);
+				Object old_value = obj.get(fieldname);
+				if((new_value == null && old_value != null) || (new_value != null && !new_value.equals(old_value))) {
+					obj.put(fieldname, new_value);
+					obj_changed = true;
+				}
+			}
+		}
+		
+		if(obj_changed) {
+			obj.put("_id", obj_id);
+			WriteResult res = this.getObjectRepository().getCollection().update(new BasicDBObject("_id", obj_id), obj, true, false);
+			
+			if(!res.getLastError().ok()) {
+				throw new CowebException(String.format("Error when writing object %s in %s", obj_id, objCollection.getName()), res.getLastError().getErrorMessage()); 
+			}
+		}
+	}
+
+	@Override
+	public abstract void insert(Map<String, Object> data);
 
 	@Override
-	public abstract boolean delete(Map<String, Object> data);
+	public void delete(Map<String, Object> data) {
+		
+		@SuppressWarnings("unchecked")
+		Map<String, Object> values = (Map<String, Object>) data.get("value");
+		String project_id = (String) values.get("_project_id");		
+		Project project = this.getProjectsRepository().findOne(project_id); 
+		
+		if (null == project) {
+			throw new CowebException(this.getClass().getName() + " delete: project not found", String.format("Project %s not found", project_id));
+		}
+
+		Integer position = (Integer)data.get("position");
+		
+		if(position == null || position < 0) {
+			throw new CowebException("object delete: bad delete position", String.format("Bad position %s not found", position==null?"null":position.toString()));
+		}
+		int index = position.intValue();
+		
+		@SuppressWarnings("unchecked")
+		ID object_id = (ID) values.get("id");
+		
+		this.logger.debug(String.format("delete object %s in pos %d for project %s", object_id, index, project_id));
+		
+		IRenkanModel<ID> currentObject = null;
+		
+		List<T> objList = this.getObjectList(project);
+		
+		if(index < objList.size()) {
+			currentObject = objList.get(index);
+		}
+			
+		if(currentObject == null || !object_id.equals(currentObject.getId())) {
+			index = -1;
+			this.logger.warn(String.format("delete object %s in pos %d for project %s not current object", object_id, index, project_id));
+			for(int i=0;i<project.getNodes().size();i++) {
+				if(object_id.equals(objList.get(i).getId())) {
+					index = i;
+					break;
+				}
+			}
+		}
+		
+		if(index<0) {
+			this.logger.warn(String.format("delete object %s in pos %d for project %s not found", object_id, index, project_id));
+		}
+		else {
+			objList.remove(index);
+			this.getObjectRepository().delete(object_id);
+			this.getProjectsRepository().save(project);
+		}
+
+	}
 
 	@Override
-	public abstract boolean nullOperation(Map<String, Object> data);
-
+	public abstract void nullOperation(Map<String, Object> data);
+	
+	
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/coweb/event/EdgeSyncEventManager.java	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,118 @@
+package org.iri_research.renkan.coweb.event;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.coweb.CowebException;
+import org.iri_research.renkan.models.Edge;
+import org.iri_research.renkan.models.Node;
+import org.iri_research.renkan.models.Project;
+import org.iri_research.renkan.repositories.EdgesRepository;
+import org.iri_research.renkan.repositories.IRenkanRepository;
+import org.iri_research.renkan.repositories.NodesRepository;
+import org.iri_research.renkan.repositories.UsersRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Named
+public class EdgeSyncEventManager extends AbstractSyncEventManager<Edge, String> {
+
+	private final Logger logger = LoggerFactory.getLogger(EdgeSyncEventManager.class);
+
+	@Inject
+	private NodesRepository nodesRepository;
+
+	@Inject
+	private UsersRepository usersRepository;
+	
+	@Inject
+	private EdgesRepository edgesRepository;
+
+	
+	public NodesRepository getNodesRepository() {
+		return nodesRepository;
+	}
+
+	public UsersRepository getUsersRepository() {
+		return usersRepository;
+	}
+
+	public EdgesRepository getEdgesRepository() {
+		return edgesRepository;
+	}
+	
+	
+	@Override
+	public IRenkanRepository<Edge, String> getObjectRepository() {
+		return this.getEdgesRepository();
+	}
+	
+	
+	@Override
+	public void insert(Map<String, Object> data) {
+	
+		// get project
+		this.logger.debug("NodeSyncEventManager: insert Node");
+		
+		@SuppressWarnings("unchecked")
+		Map<String, Object> values = (Map<String, Object>) data.get("value");
+		String project_id = (String) values.get("_project_id");
+
+		Project project = this.getProjectsRepository().findOne(project_id);
+				
+		if (null == project) {
+			throw new CowebException("node insert: project not found", String.format("Project %s not found", project_id));
+		}
+
+		String creator_id = (String) values.get("created_by");
+								
+		String from_node_id = (String)values.get("from");
+		Node from_node = this.getNodesRepository().findOne(from_node_id);
+		
+		if(null == from_node) {
+			throw new CowebException("Edge insert: from not found", String.format("from %s not found", from_node_id));
+		}
+		
+		String to_node_id = (String)values.get("to");
+		Node to_node = this.getNodesRepository().findOne(to_node_id);
+		
+		if(null == to_node) {
+			throw new CowebException("Edge insert: to not found", String.format("to %s not found", to_node_id));
+		}
+		
+		String edge_id = (String)values.get("id");
+		
+		Edge edge = new Edge(edge_id, (String)values.get("title"), (String)values.get("description"), (String)values.get("uri"), from_node, to_node, creator_id, project_id);
+		
+		
+		Integer position = (Integer)data.get("position");
+		
+		if(position == null || position < 0) {
+			throw new CowebException("node insert: bad insert position", String.format("Bad position %s not found", position==null?"null":position.toString()));
+		}
+		int index = position.intValue();
+		List<Edge> edges = project.getEdges();
+		if(index > edges.size()) {
+			index = edges.size();
+		}
+		edges.add(index,edge);
+
+		this.getEdgesRepository().save(edge);
+		this.getProjectsRepository().save(project);
+		
+	}
+	
+	@Override
+	public void nullOperation(Map<String, Object> data) {
+		this.logger.debug("nullOperation: NOP");
+	}
+
+	@Override
+	protected List<Edge> getObjectList(Project project) {
+		return project.getEdges();
+	}
+
+}
--- a/server/src/main/java/org/iri_research/renkan/coweb/event/ISyncEventManager.java	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/coweb/event/ISyncEventManager.java	Tue Dec 25 21:29:11 2012 +0100
@@ -1,18 +1,21 @@
 package org.iri_research.renkan.coweb.event;
 
+import java.io.Serializable;
 import java.util.Map;
 
+import org.iri_research.renkan.repositories.IRenkanRepository;
 import org.iri_research.renkan.repositories.ProjectsRepository;
 
-public interface ISyncEventManager {
+public interface ISyncEventManager<T, ID extends Serializable> {
 	
-	public boolean dispatchEvent(Map<String, Object> data);
+	public void dispatchEvent(Map<String, Object> data);
 
-	public boolean update(Map<String, Object> data);
-	public boolean insert(Map<String, Object> data);
-	public boolean delete(Map<String, Object> data);
-	public boolean nullOperation(Map<String, Object> data);
+	public void update(Map<String, Object> data);
+	public void insert(Map<String, Object> data);
+	public void delete(Map<String, Object> data);
+	public void nullOperation(Map<String, Object> data);
 	
 	public ProjectsRepository getProjectsRepository();
+	public IRenkanRepository<T,ID> getObjectRepository();
 
 }
--- a/server/src/main/java/org/iri_research/renkan/coweb/event/NodeSyncEventManager.java	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/coweb/event/NodeSyncEventManager.java	Tue Dec 25 21:29:11 2012 +0100
@@ -9,92 +9,67 @@
 import org.coweb.CowebException;
 import org.iri_research.renkan.models.Node;
 import org.iri_research.renkan.models.Project;
-import org.iri_research.renkan.models.ProjectRevision;
+import org.iri_research.renkan.repositories.IRenkanRepository;
 import org.iri_research.renkan.repositories.NodesRepository;
+import org.iri_research.renkan.repositories.UsersRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBCollection;
-import com.mongodb.DBObject;
-import com.mongodb.WriteResult;
+import org.springframework.data.mongodb.core.geo.Point;
 
 @Named
-public class NodeSyncEventManager extends AbstractSyncEventManager {
+public class NodeSyncEventManager extends AbstractSyncEventManager<Node, String> {
 
-	private final Logger logger = LoggerFactory.getLogger(ProjectSyncEventManager.class);
+	private final Logger logger = LoggerFactory.getLogger(NodeSyncEventManager.class);
 
 	@Inject
 	private NodesRepository nodesRepository;
-	
+
+	@Inject
+	private UsersRepository usersRepository;
+
 	
 	public NodesRepository getNodesRepository() {
 		return nodesRepository;
 	}
-
+	
 	@Override
-	public boolean update(Map<String, Object> data) {
+	public IRenkanRepository<Node, String> getObjectRepository() {
+		return this.getNodesRepository();
+	}
+	
+	public UsersRepository getUsersRepository() {
+		return this.usersRepository;
+	}
 
-		this.logger.debug("ProjectSyncEventManager: update project");
+	
+	@Override
+	public void insert(Map<String, Object> data) {
+	
+		// get project
+		this.logger.debug("NodeSyncEventManager: insert Node");
 		
 		@SuppressWarnings("unchecked")
 		Map<String, Object> values = (Map<String, Object>) data.get("value");
-		String node_id = (String) values.get("id");
-		
-		this.logger.debug(String.format("update node %s", node_id));
-		
-		DBCollection projectCollection = this.getNodesRepository().getCollection();
-		DBObject node = projectCollection.findOne(node_id);
-		
-		if (null == node) {
-			throw new CowebException("Node update: node not found", String.format("Node %s not found", node_id));
-		}
-		
-		boolean node_changed = false;
-		// update project
-		for (String fieldname : values.keySet()) {
-			if(!"id".equalsIgnoreCase(fieldname) && node.containsField(fieldname))
-			{
-				Object new_value = values.get(fieldname);
-				Object old_value = node.get(fieldname);
-				if((new_value == null && old_value != null) || (new_value != null && !new_value.equals(old_value))) {
-					node.put(fieldname, new_value);
-					node_changed = true;
-				}
-			}
-		}
-		
-		if(node_changed) {
-			node.put("_id", node_id);
-			WriteResult res = this.getNodesRepository().getCollection().update(new BasicDBObject("_id", node_id), node, true, false);
-			
-			if(!res.getLastError().ok()) {
-				throw new CowebException(String.format("Error when writing node %s", node_id), res.getLastError().getErrorMessage()); 
-			}
-		}
+		String project_id = (String) values.get("_project_id");
 
-		return false;
-	}
-
-	@Override
-	public boolean insert(Map<String, Object> data) {
-	
-		// get project
-		this.logger.debug("ProjectSyncEventManager: update project");
-		
-		@SuppressWarnings("unchecked")
-		Map<String, Object> values = (Map<String, Object>) data.get("value");
-		String project_id = (String) values.get("project_id");
-
-		Project project = this.getProjectsRepository().findOne(project_id); 
-		
+		Project project = this.getProjectsRepository().findOne(project_id);
+				
 		if (null == project) {
 			throw new CowebException("node insert: project not found", String.format("Project %s not found", project_id));
 		}
 
+		String creator_id = (String) values.get("created_by");
+		
+		@SuppressWarnings("unchecked")
+		Map<String, Object> positionValues = (Map<String, Object>) values.get("position");
+		
+		Point nodePosition = new Point(((Number)positionValues.get("x")).doubleValue(), ((Number)positionValues.get("y")).doubleValue());
+		
+		String image = (String)values.get("image");
+		
 		String node_id = (String)values.get("id");
 		
-		Node node = new Node(node_id, (String)values.get("id"), (String)values.get("description"), (String)values.get("uri"), project);
+		Node node = new Node(node_id, (String)values.get("title"), (String)values.get("description"), (String)values.get("uri"), project_id, creator_id, nodePosition, image);
 		
 		Integer position = (Integer)data.get("position");
 		
@@ -111,20 +86,16 @@
 		this.getNodesRepository().save(node);
 		this.getProjectsRepository().save(project);
 		
-		return false;
+	}
+	
+	@Override
+	public void nullOperation(Map<String, Object> data) {
+		this.logger.debug("nullOperation: NOP");
 	}
 
 	@Override
-	public boolean delete(Map<String, Object> data) {
-		
-		
-		return false;
-	}
-
-	@Override
-	public boolean nullOperation(Map<String, Object> data) {
-		this.logger.debug("nullOperation: NOP");
-		return false;
+	protected List<Node> getObjectList(Project project) {
+		return project.getNodes();
 	}
 
 }
--- a/server/src/main/java/org/iri_research/renkan/coweb/event/ProjectSyncEventManager.java	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/coweb/event/ProjectSyncEventManager.java	Tue Dec 25 21:29:11 2012 +0100
@@ -3,105 +3,62 @@
  */
 package org.iri_research.renkan.coweb.event;
 
+import java.util.List;
 import java.util.Map;
 
 import javax.inject.Named;
 
-import org.coweb.CowebException;
+import org.iri_research.renkan.models.Project;
+import org.iri_research.renkan.repositories.IRenkanRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBCollection;
-import com.mongodb.DBObject;
-import com.mongodb.WriteResult;
-
 /**
  * @author ymh
  *
  */
 @Named
-public class ProjectSyncEventManager extends AbstractSyncEventManager {
+public class ProjectSyncEventManager extends AbstractSyncEventManager<Project, String> {
 
-	private final Logger logger = LoggerFactory.getLogger(ProjectSyncEventManager.class);
-			
-	private DBCollection getCollection() {		
-		return this.getProjectsRepository().getCollection();
+	private final Logger logger = LoggerFactory.getLogger(ProjectSyncEventManager.class);			
+	
+	@Override
+	public IRenkanRepository<Project, String> getObjectRepository() {
+		return this.getProjectsRepository();
 	}
 	
-	/* Update a project
-	 * @see org.iri_research.renkan.coweb.event.AbstractSyncEventManager#update(java.util.Map)
-	 */
-	@Override
-	public boolean update(Map<String, Object> data) {
-		
-		this.logger.debug("ProjectSyncEventManager: update project");
-		
-		@SuppressWarnings("unchecked")
-		Map<String, Object> values = (Map<String, Object>) data.get("value");
-		String project_id = (String) values.get("id");
-		
-		// get project
-		this.logger.debug(String.format("update project %s", project_id));
-		
-		DBCollection projectCollection = this.getCollection();
-		DBObject project = projectCollection.findOne(project_id);
-		
-		if (null == project) {
-			throw new CowebException("Project update: project not found", String.format("Project %s not found", project_id));
-		}
-		
-		boolean project_changed = false;
-		// update project
-		for (String fieldname : values.keySet()) {
-			if(!"id".equalsIgnoreCase(fieldname) && project.containsField(fieldname))
-			{
-				Object new_value = values.get(fieldname);
-				Object old_value = project.get(fieldname);
-				if((new_value == null && old_value != null) || (new_value != null && !new_value.equals(old_value))) {
-					project.put(fieldname, new_value);
-					project_changed = true;
-				}
-			}
-		}
-		
-		if(project_changed) {
-			project.put("_id", project_id);
-			WriteResult res = projectCollection.update(new BasicDBObject("_id", project_id), project, true, false);
-			
-			if(!res.getLastError().ok()) {
-				throw new CowebException(String.format("Error when writing project %s", project_id), res.getLastError().getErrorMessage()); 
-			}
-
-		}
-		return false;
-	}
-
 	/* (non-Javadoc)
 	 * @see org.iri_research.renkan.coweb.event.AbstractSyncEventManager#insert(java.util.Map)
 	 */
 	@Override
-	public boolean insert(Map<String, Object> data) {
+	public void insert(Map<String, Object> data) {
+		this.logger.debug("Insert called, do nothing");
 		// do nothing
-		return false;
 	}
 
 	/* (non-Javadoc)
 	 * @see org.iri_research.renkan.coweb.event.AbstractSyncEventManager#delete(java.util.Map)
 	 */
 	@Override
-	public boolean delete(Map<String, Object> data) {
+	public void delete(Map<String, Object> data) {
+		this.logger.debug("Delete called, do nothing");
 		// do nothing
-		return false;
 	}
 
 	/* (non-Javadoc)
 	 * @see org.iri_research.renkan.coweb.event.AbstractSyncEventManager#nullOperation(java.util.Map)
 	 */
 	@Override
-	public boolean nullOperation(Map<String, Object> data) {
+	public void nullOperation(Map<String, Object> data) {
+		this.logger.debug("Null called, do nothing");
 		// do nothing
-		return false;
 	}
 
+	@Override
+	protected List<Project> getObjectList(Project project) {
+		this.logger.error("Get object list called error");
+		throw new UnsupportedOperationException("Get object list called error");
+	}
+
+
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/coweb/event/UserSyncEventManager.java	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,88 @@
+package org.iri_research.renkan.coweb.event;
+
+import java.util.List;
+import java.util.Map;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import org.coweb.CowebException;
+import org.iri_research.renkan.models.Project;
+import org.iri_research.renkan.models.User;
+import org.iri_research.renkan.repositories.IRenkanRepository;
+import org.iri_research.renkan.repositories.UsersRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Named
+public class UserSyncEventManager extends AbstractSyncEventManager<User, String> {
+
+	private final Logger logger = LoggerFactory.getLogger(UserSyncEventManager.class);
+	
+	private final static String DEFAULT_COLOR = "#000080"; 
+
+	@Inject
+	private UsersRepository usersRepository;
+		
+	public UsersRepository getUsersRepository() {
+		return this.usersRepository;
+	}
+	
+	@Override
+	public IRenkanRepository<User, String> getObjectRepository() {
+		return this.getUsersRepository();
+	}
+
+
+	@Override
+	public void insert(Map<String, Object> data) {
+	
+		// get project
+		this.logger.debug("UserSyncEventManager: insert User");
+		
+		@SuppressWarnings("unchecked")
+		Map<String, Object> values = (Map<String, Object>) data.get("value");
+		String project_id = (String) values.get("_project_id");
+
+		Project project = this.getProjectsRepository().findOne(project_id);
+				
+		if (null == project) {
+			throw new CowebException("user insert: project not found", String.format("Project %s not found", project_id));
+		}
+		
+		String user_id = (String)values.get("id");
+		String color = (String)values.get("color");
+		if(color == null || color.length() == 0) {
+			color = UserSyncEventManager.DEFAULT_COLOR;
+		}
+		
+		User user = new User(user_id, (String)values.get("title"), (String)values.get("description"), (String)values.get("uri"), color, project_id);
+		
+		Integer position = (Integer)data.get("position");
+		
+		if(position == null || position < 0) {
+			throw new CowebException("node insert: bad insert position", String.format("Bad position %s not found", position==null?"null":position.toString()));
+		}
+		int index = position.intValue();
+		List<User> users = project.getUsers();
+		if(index > users.size()) {
+			index = users.size();
+		}
+		users.add(index,user);
+
+		this.getUsersRepository().save(user);
+		this.getProjectsRepository().save(project);
+		
+	}
+
+	@Override
+	public void nullOperation(Map<String, Object> data) {
+		this.logger.debug("nullOperation: NOP");
+	}
+
+	@Override
+	protected List<User> getObjectList(Project project) {
+		return project.getUsers();
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/models/Edge.java	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,57 @@
+package org.iri_research.renkan.models;
+
+import org.springframework.data.mongodb.core.mapping.DBRef;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+
+@Document(collection="edges")
+public class Edge extends AbstractRenkanModel<String> {
+
+	@DBRef
+	private Node from;
+	
+	@DBRef
+	private Node to;
+	
+	private String project_id;
+	
+	private String created_by;
+	
+
+	public Edge(String id, String title, String description, String uri, Node from, Node to, String created_by, String project_id) {
+		super(id,title, description, uri);
+		this.from = from;
+		this.to = to;
+		this.created_by = created_by;
+		this.project_id = project_id;
+	}
+
+
+	public String getProject_id() {
+		return project_id;
+	}
+
+
+	public String getCreated_by() {
+		return created_by;
+	}
+	
+	public String getFrom() {
+		if(this.from != null) {
+			return this.from.id;
+		}
+		else {
+			return null;
+		}
+	}
+
+	public String getTo() {
+		if(this.to != null) {
+			return this.to.id;
+		}
+		else {
+			return null;
+		}
+	}
+
+}
--- a/server/src/main/java/org/iri_research/renkan/models/Node.java	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/models/Node.java	Tue Dec 25 21:29:11 2012 +0100
@@ -1,19 +1,43 @@
 package org.iri_research.renkan.models;
 
-import org.springframework.data.mongodb.core.mapping.DBRef;
+import org.springframework.data.mongodb.core.geo.Point;
 import org.springframework.data.mongodb.core.mapping.Document;
 
 @Document(collection="nodes")
 public class Node extends AbstractRenkanModel<String> {
 
 
-	public Node(String id, String title, String description, String uri, Project project) {
+	public Node(String id, String title, String description, String uri, String project_id, String created_by, Point position, String image) {
 		super(id, title, description, uri);
 		
-		this.project = project;
+		this.project_id = project_id;
+		this.created_by = created_by;
+		this.position = position;
+		this.image = image;
 	}	
 	
-	@DBRef
-	private Project project = null;	
+	private String project_id = null;	
+
+	private String created_by = null;
+	
+	private Point position = null;
+
+	public Point getPosition() {
+		return position;
+	}
+
+	private String image;
+
+	public String getImage() {
+		return image;
+	}
+
+	public String getProject_id() {
+		return project_id;
+	}
+
+	public String getCreated_by() {
+		return created_by;
+	}
 
 }
--- a/server/src/main/java/org/iri_research/renkan/models/Project.java	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/models/Project.java	Tue Dec 25 21:29:11 2012 +0100
@@ -20,10 +20,15 @@
 	@DBRef
 	private List<Node> nodes = new ArrayList<Node>();
 	
-	// Relations
+	// edges
 	@DBRef
-	private List<Relation> relations = new ArrayList<Relation>();
+	private List<Edge> edges = new ArrayList<Edge>();
 
+	// Users
+	@DBRef
+	private List<User> users = new ArrayList<User>();
+
+	
 	
 	public Project(String id, String title, String description, String uri,
 			int revCounter) {
@@ -40,16 +45,19 @@
 	}
 	
 	public int getRevCounter() {
-		return revCounter;
+		return this.revCounter;
 	}
 	
 	public List<Node> getNodes() {
-		return nodes;
+		return this.nodes;
 	}
 
-	public List<Relation> getRelations() {
-		return relations;
-	}	
-
+	public List<Edge> getEdges() {
+		return this.edges;
+	}
+	
+	public List<User> getUsers() {
+		return this.users;
+	}
 
 }
--- a/server/src/main/java/org/iri_research/renkan/models/ProjectRevision.java	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/models/ProjectRevision.java	Tue Dec 25 21:29:11 2012 +0100
@@ -26,8 +26,8 @@
 	// Nodes
 	private List<Node> nodes = new ArrayList<Node>();
 	
-	// Relations
-	private List<Relation> relations = new ArrayList<Relation>();
+	// Edgess
+	private List<Edge> edges = new ArrayList<Edge>();
 
 
 	@SuppressWarnings("unused")
@@ -57,8 +57,8 @@
 		return nodes;
 	}
 
-	public List<Relation> getRelations() {
-		return relations;
+	public List<Edge> getEgdes() {
+		return edges;
 	}
 
 	public Date getCreated() {
--- a/server/src/main/java/org/iri_research/renkan/models/Relation.java	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,27 +0,0 @@
-package org.iri_research.renkan.models;
-
-import org.bson.types.ObjectId;
-import org.springframework.data.mongodb.core.mapping.DBRef;
-import org.springframework.data.mongodb.core.mapping.Document;
-
-
-@Document(collection="relations")
-public class Relation extends AbstractRenkanModel<ObjectId> {
-
-	@DBRef
-	private Node srcNode;
-	
-	@DBRef
-	private Node tgtNode;
-	
-	@DBRef
-	private Project project;
-
-	public Relation(ObjectId id, String title, String description, String uri, Node srcNode, Node tgtNode, Project project) {
-		super(id,title, description, uri);
-		this.srcNode = srcNode;
-		this.tgtNode = tgtNode;
-		this.project = project;
-	}
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/models/User.java	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,27 @@
+package org.iri_research.renkan.models;
+
+import org.springframework.data.mongodb.core.mapping.Document;
+
+@Document(collection="users")
+public class User extends AbstractRenkanModel<String> {
+	
+	private String color;
+	
+	private String project_id;
+
+	public User(String id, String title, String description, String uri, String color, String project_id) {
+		super(id, title, description, uri);
+		
+		this.project_id = project_id;
+		this.color = color;
+	}	
+	
+	public String getColor() {
+		return this.color;
+	}
+
+	public String getProject_id() {
+		return project_id;
+	}
+	
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/EdgesRepository.java	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,7 @@
+package org.iri_research.renkan.repositories;
+
+import org.iri_research.renkan.models.Edge;
+
+public interface EdgesRepository extends IRenkanRepository<Edge, String> {
+
+}
--- a/server/src/main/java/org/iri_research/renkan/repositories/RelationsRepository.java	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,7 +0,0 @@
-package org.iri_research.renkan.repositories;
-
-import org.iri_research.renkan.models.Relation;
-
-public interface RelationsRepository extends IRenkanRepository<Relation, String> {
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/java/org/iri_research/renkan/repositories/UsersRepository.java	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,7 @@
+package org.iri_research.renkan.repositories;
+
+import org.iri_research.renkan.models.User;
+
+public interface UsersRepository extends IRenkanRepository<User, String> {
+
+}
--- a/server/src/main/java/org/iri_research/renkan/rest/ProjectsResource.java	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/java/org/iri_research/renkan/rest/ProjectsResource.java	Tue Dec 25 21:29:11 2012 +0100
@@ -19,6 +19,7 @@
 import javax.ws.rs.core.Response.Status;
 import javax.ws.rs.core.UriInfo;
 
+import org.iri_research.renkan.models.Project;
 import org.iri_research.renkan.repositories.ProjectsRepository;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -54,18 +55,17 @@
 	@GET
 	@Path("{id : [a-zA-Z\\-0-9]+}")
 	@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
-	public String getProject(@PathParam("id") String projectId) {
+	public Project getProjectSd(@PathParam("id") String projectId) {
 		
-		this.logger.debug("GetProject : id " + projectId);
+		this.logger.debug("GetProject: " + projectId);
 				
-		DBCollection projectCollection = this.getCollection();
-		DBObject project = projectCollection.findOne(projectId);
+		Project project = this.projectRepository.findOne(projectId);
 		
 		if (null == project) {
 			throw new WebApplicationException(Status.NOT_FOUND);
 		}
 		
-		return project.toString();				
+		return project;				
 	}
 	
 	@DELETE
@@ -74,21 +74,10 @@
 	public Response deleteProject(@PathParam("id") String projectId) {
 		
 		this.logger.debug("DeleteProject : id " + projectId);
-		DBCollection projectCollection = this.getCollection();
-		BasicDBObject filter = new BasicDBObject("_id", projectId);
-		WriteResult res = projectCollection.remove(filter);
 		
-		if(res.getLastError().ok()) {
-			if(res.getN() == 0) {
-				return Response.noContent().build();
-			}
-			else {
-				return Response.ok(this.uriInfo.getAbsolutePathBuilder().segment(projectId).build().toString() + " deleted").build();
-			}
-		}
-		else {
-			throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(res.getError()).build());
-		}
+		this.projectRepository.delete(projectId);
+		return Response.ok(this.uriInfo.getAbsolutePathBuilder().segment(projectId).build().toString() + " deleted").build();
+		
 	}
 
 
@@ -113,6 +102,7 @@
 		
 	}
 	
+	//TODO: uses spring data
 	@GET
 	@Produces(MediaType.APPLICATION_JSON + ";charset=utf-8")
 	public String getProjectList() {
@@ -159,6 +149,7 @@
 		return JSON.serialize(res);
 	}
 	
+	//TODO: rewrite for recursive object and use spring data
 	private Response createOrUpdateProject(String projectId, String projectContent) {
 		
 		if(null == projectContent || projectContent.isEmpty()) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/jsp/projectPrompt.jsp	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,12 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8"
+    pageEncoding="UTF-8"%>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+<title>Project prompt</title>
+</head>
+<body>
+    ${message}
+</body>
+</html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/spring-servlet.xml	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xmlns:p="http://www.springframework.org/schema/p"
+    xmlns:context="http://www.springframework.org/schema/context"
+    xmlns:mvc="http://www.springframework.org/schema/mvc"
+    xsi:schemaLocation="http://www.springframework.org/schema/beans
+                        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+                        http://www.springframework.org/schema/context
+                        http://www.springframework.org/schema/context/spring-context-3.0.xsd
+                        http://www.springframework.org/schema/mvc
+                        http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
+
+    <!-- **************************************************************** -->
+    <!-- RESOURCE FOLDERS CONFIGURATION -->
+    <!-- Dispatcher configuration for serving static resources -->
+    <!-- **************************************************************** -->
+    <mvc:resources location="/images/" mapping="/images/**" />
+    <mvc:resources location="/css/" mapping="/css/**" />
+
+    <!-- **************************************************************** -->
+    <!-- SPRING ANNOTATION PROCESSING -->
+    <!-- **************************************************************** -->
+    <mvc:annotation-driven />
+    <context:component-scan
+        base-package="org.iri_research.renkan.controller" />
+         
+    <bean id="viewResolver"
+        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
+        <property name="viewClass"
+            value="org.springframework.web.servlet.view.JstlView" />
+        <property name="prefix" value="/WEB-INF/jsp/" />
+        <property name="suffix" value=".jsp" />
+        <property name="order" value="2" />
+    </bean>
+    
+    <bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
+        <property name="prefix" value="/WEB-INF/templates/" />
+        <property name="suffix" value=".html" />
+        <property name="templateMode" value="HTML5" />
+        <property name="cacheable" value="false"/>
+    </bean>
+    
+    <bean id="templateEngine" class="org.thymeleaf.spring3.SpringTemplateEngine">
+        <property name="templateResolver" ref="templateResolver" />
+    </bean>
+    
+    <bean class="org.thymeleaf.spring3.view.ThymeleafViewResolver">
+        <property name="templateEngine" ref="templateEngine" />
+        <property name="order" value="1" />
+        <!--property name="viewNames" value="*.html,*.xhtml" /-->
+        <property name="characterEncoding" value="UTF-8"/>
+    </bean>
+    
+</beans>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/templates/renkanProjectEdit.html	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,106 @@
+<!DOCTYPE html>
+<html lang="fr" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" >
+    <head>
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+        <title>Test de Rendu RENKAN</title>
+        <meta name="description" content="" />
+        <meta name="author" content="Institut de Recherche et d'Innovation" />
+        <script src="lib/jquery.min.js" th:src="@{/static/lib/jquery.min.js}" ></script>
+        <script src="lib/jquery.mousewheel.min.js" th:src="@{/static/lib/jquery.mousewheel.min.js}"></script>
+        <script src="lib/underscore-min.js" th:src="@{/static/lib/underscore-min.js}"></script>
+        <script src="lib/backbone.js" th:src="@{/static/lib/backbone.js}"></script>
+        <script src="lib/backbone-relational.js" th:src="@{/static/lib/backbone-relational.js}"></script>
+        <script src="lib/paper.js" th:src="@{/static/lib/paper.js}"></script>
+        <script src="js/main.js" th:src="@{/static/js/main.js}"></script>
+        <script src="js/i18n.js" th:src="@{/static/js/i18n.js}"></script>
+        <script src="js/models.js" th:src="@{/static/js/models.js}"></script>
+        <script src="js/corenkan-json.js" th:src="@{/static/js/corenkan-json.js}"></script>
+        <!--script src="js/random-data.js" th:src="@{/static/js/random-data.js}"></script-->
+        <script src="js/twitter-bin.js" th:src="@{/static/js/twitter-bin.js}"></script>
+        <script src="js/wikipedia-bin.js" th:src="@{/static/js/wikipedia-bin.js}"></script>
+        <script src="js/ldtjson-bin.js" th:src="@{/static/js/ldtjson-bin.js}"></script>
+        <script src="js/paper-renderer.js" th:src="@{/static/js/paper-renderer.js}"></script>
+        <script type="text/javascript" src="js/config.js" th:src="@{/static/js/config.js}"></script>
+        <script type="text/javascript" src="js/dojo.js" data-dojo-config="isDebug: true, parseOnLoad: true" th:src="@{/static/js/dojo.js}"></script>        
+        <script type="text/javascript" th:inline="javascript">
+            var _proj;
+            require(["corenkan"], function(corenkan) {            
+              $(function() {
+                _renkan = new Rkns.Renkan({
+                    url: /*[[@{/rest/projects/}+${project.id}]]*/ "data/simple-persist.php",
+                    static_url : /*[[@{/static/}]]*/ "",
+                    bins: [
+                        {
+                            bin: Rkns.Wikipedia.Bin,
+                            lang: "en",
+                            search: "Digital Humanities"
+                        },
+                        {
+                            bin: Rkns.Wikipedia.Bin,
+                            lang: "ja",
+                            search: "Digital Humanities"
+                        },
+                        {
+                            bin: Rkns.Twitter.Bin,
+                            search: "Digital Humanities"
+                        },
+                        {
+                            title: "LDT Project",
+                            bin: Rkns.Ldt.ProjectBin,
+                            project_id: "67280b1c-ff30-11e0-a82d-00145ea49a02",
+                            ldt_platform: "http://ldt.iri.centrepompidou.fr/"
+                        }
+                    ],
+                    search: [
+                        {
+                            type: Rkns.Wikipedia.Search,
+                            lang: "fr"
+                        }, 
+                        {
+                            type: Rkns.Wikipedia.Search,
+                            lang: "en"
+                        }, 
+                        {
+                            type: Rkns.Wikipedia.Search,
+                            lang: "ja"
+                        },
+                        {
+                            type: Rkns.Twitter.Search
+                        }
+                    ],
+                });
+                corenkan.app.onStatusChange = function(status) {
+                	if(status == "ready") {
+                        Rkns.jsonIO(_renkan, {
+                            url: /*[[@{/rest/projects/}+${project.id}]]*/ "data/simple-persist.php",
+                            callback: function(_proj, _renkan) {
+                            	corenkan.app.setProject(_proj);
+                            	var anon_users = _proj.get("users").where({title: "anonymous"});
+                            	if(anon_users.length == 0) {
+                                	_proj.current_user = _proj.addUser({
+                                        id: Rkns.Utils.getUID("u"),
+                                        title: "anonymous",
+                                        color: "#000080",
+                                    });
+                            	}
+                            	else {
+                            		_proj.current_user = anon_users[0];
+                            	}
+                            	_renkan.current_user = _proj.current_user.id;
+                            }
+                        });
+                	}
+                };
+              });
+            });
+        </script>
+        <link rel="stylesheet" href="css/renkan.css" th:href="@{/static/css/renkan.css}"/>
+        <style type="text/css">
+        </style>
+    </head>
+
+    <body>
+        <div id="renkan"></div>
+    </body>
+</html>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/WEB-INF/templates/renkanProjectRender.html	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="fr" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" >
+    <head>
+        <meta charset="utf-8" />
+        <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+        <title>Test de Rendu RENKAN</title>
+        <meta name="description" content="" />
+        <meta name="author" content="Institut de Recherche et d'Innovation" />
+        <script src="lib/jquery.min.js" th:src="@{/static/lib/jquery.min.js}"></script>
+        <script src="lib/jquery.mousewheel.min.js" th:src="@{/static/lib/jquery.mousewheel.min.js}"></script>
+        <script src="lib/underscore-min.js" th:src="@{/static/lib/underscore-min.js}"></script>
+        <script src="lib/backbone.js" th:src="@{/static/lib/backbone.js}"></script>
+        <script src="lib/backbone-relational.js" th:src="@{/static/lib/backbone-relational.js}"></script>
+        <script src="lib/paper.js" th:src="@{/static/lib/paper.js}"></script>
+        <script src="js/renkan-publish.js" th:src="@{/static/js/renkan-publish.js}"></script>
+        <script type="text/javascript" th:inline="javascript">
+        /*<![CDATA[*/
+            var _renkan;
+            $(function() {
+                _renkan = new Rkns.Renkan({static_url:/*[[@{/static/}]]*/ ""});
+                _renkan.addProject({
+                    url: /*[[@{/rest/projects/}+${project.id}]]*/ "../metadataplayer/json/renkan.json",
+                    callback: function(_proj) {
+                        if (_renkan.renderer) {
+                            _renkan.renderer.autoScale();
+                        }
+                    }
+                });
+                //_renkan.addProject({
+                //    url: "../metadataplayer/json/renkan.json"
+                //});
+                _renderer = _renkan.renderProjectAt(0);
+            });
+        /*]]>*/    
+        </script>
+        <link rel="stylesheet" href="css/renkan-publish.css" th:href="@{/static/css/renkan-publish.css}"/>
+        <style type="text/css">
+        </style>
+    </head>
+
+    <body>
+        <div id="renkan"></div>
+    </body>
+</html>
--- a/server/src/main/webapp/WEB-INF/web.xml	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/webapp/WEB-INF/web.xml	Tue Dec 25 21:29:11 2012 +0100
@@ -57,10 +57,23 @@
       <param-name>com.sun.jersey.config.property.packages</param-name>
       <param-value>org.iri_research.renkan.rest</param-value>
     </init-param>
+    <init-param>
+      <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
+      <param-value>true</param-value>
+    </init-param>
     <load-on-startup>1</load-on-startup>
   </servlet>
   <servlet-mapping>
     <servlet-name>rest Servlet</servlet-name>
     <url-pattern>/rest/*</url-pattern>
   </servlet-mapping>
+  <servlet>
+    <servlet-name>spring</servlet-name>
+    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+    <load-on-startup>1</load-on-startup>
+  </servlet>
+  <servlet-mapping>
+    <servlet-name>spring</servlet-name>
+    <url-pattern>/p/*</url-pattern>
+  </servlet-mapping>
 </web-app>
\ No newline at end of file
--- a/server/src/main/webapp/css/style.css	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,130 +0,0 @@
-/* =============================================================================
-   HTML5 Boilerplate CSS: h5bp.com/css
-   ========================================================================== */
-
-article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; }
-audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; }
-audio:not([controls]) { display: none; }
-[hidden] { display: none; }
-
-html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
-html, button, input, select, textarea { font-family: sans-serif; color: #222; }
-body { margin: 0; font-size: 1em; line-height: 1.4; }
-
-::-moz-selection { background: #fe57a1; color: #fff; text-shadow: none; }
-::selection { background: #fe57a1; color: #fff; text-shadow: none; }
-
-a { color: #00e; }
-a:visited { color: #551a8b; }
-a:hover { color: #06e; }
-a:focus { outline: thin dotted; }
-a:hover, a:active { outline: 0; }
-
-abbr[title] { border-bottom: 1px dotted; }
-b, strong { font-weight: bold; }
-blockquote { margin: 1em 40px; }
-dfn { font-style: italic; }
-hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
-ins { background: #ff9; color: #000; text-decoration: none; }
-mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
-pre, code, kbd, samp { font-family: monospace, serif; _font-family: 'courier new', monospace; font-size: 1em; }
-pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
-q { quotes: none; }
-q:before, q:after { content: ""; content: none; }
-small { font-size: 85%; }
-
-sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
-sup { top: -0.5em; }
-sub { bottom: -0.25em; }
-
-ul, ol { margin: 1em 0; padding: 0 0 0 40px; }
-dd { margin: 0 0 0 40px; }
-nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; }
-
-img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }
-
-svg:not(:root) { overflow: hidden; }
-
-figure { margin: 0; }
-
-form { margin: 0; }
-fieldset { border: 0; margin: 0; padding: 0; }
-label { cursor: pointer; }
-legend { border: 0; *margin-left: -7px; padding: 0; white-space: normal; }
-button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; }
-button, input { line-height: normal; }
-button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; }
-button[disabled], input[disabled] { cursor: default; }
-input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; *width: 13px; *height: 13px; }
-input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }
-input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
-button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
-textarea { overflow: auto; vertical-align: top; resize: vertical; }
-input:valid, textarea:valid {  }
-input:invalid, textarea:invalid { background-color: #f0dddd; }
-
-table { border-collapse: collapse; border-spacing: 0; }
-td { vertical-align: top; }
-
-.chromeframe { margin: 0.2em 0; background: #ccc; color: black; padding: 0.2em 0; }
-
-
-
-/* ===== Primary Styles ========================================================
-   Author:
-   ========================================================================== */
-.templates { display: none; }
-
-.project_desc_label { font-weight: bold; }
-
-#project_display {
-    background: #9cbc2c;
-    -moz-border-radius: 5px;
-    -webkit-border-radius: 5px;
-    border-radius: 5px;
-    padding: 20px;
-    width: 400px;
-}
-
-
-
-/* =============================================================================
-   Media Queries
-   ========================================================================== */
-
-@media only screen and (min-width: 35em) {
-	/* Style adjustments for viewports that meet the condition */
-}
-
-/* =============================================================================
-   Non-Semantic Helper Classes
-   ========================================================================== */
-
-.ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; *line-height: 0; }
-.ir br { display: none; }
-.hidden { display: none !important; visibility: hidden; }
-.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
-.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }
-.invisible { visibility: hidden; }
-.clearfix:before, .clearfix:after { content: ""; display: table; }
-.clearfix:after { clear: both; }
-.clearfix { *zoom: 1; }
-
-/* =============================================================================
-   Print Styles
-   ========================================================================== */
- 
-@media print {
-  * { background: transparent !important; color: black !important; box-shadow:none !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: h5bp.com/s */
-  a, a:visited { text-decoration: underline; }
-  a[href]:after { content: " (" attr(href) ")"; }
-  abbr[title]:after { content: " (" attr(title) ")"; }
-  .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }  /* Don't show links for images, or javascript/internal links */
-  pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
-  thead { display: table-header-group; } /* h5bp.com/t */
-  tr, img { page-break-inside: avoid; }
-  img { max-width: 100% !important; }
-  @page { margin: 0.5cm; }
-  p, h2, h3 { orphans: 3; widows: 3; }
-  h2, h3 { page-break-after: avoid; }
-}
--- a/server/src/main/webapp/index.html	Tue Dec 11 00:01:41 2012 +0100
+++ b/server/src/main/webapp/index.html	Tue Dec 25 21:29:11 2012 +0100
@@ -1,12 +1,161 @@
-<!DOCTYPE html>
+<!doctype html>
 <html>
-  <head>
-    <meta charset="utf-8" />
-    <title>My Cooperative Web Application</title>
-	<script type="text/javascript" src="js/config.js"></script>
-	<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/dojo/1.7.0/dojo/dojo.js" data-dojo-config="isDebug: true, parseOnLoad: true"></script>
-	<script data-main="main" src="js/main.js"></script>
-  </head>
-  <body>
-  </body>
+        <title>Renkan</title>
+
+        <meta charset="utf-8"> 
+        <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
+
+        <link rel="shortcut icon" href="favicon.ico">
+
+        <style>
+            body {
+              margin: 0;
+              height: 100%;
+              color: #333;
+              font: 14px helvetica, sans-serif;
+              background: #ddd;
+              background: -webkit-radial-gradient(circle,#aaa,#eee 60%) center fixed;
+              background: -moz-radial-gradient(circle,#aaa,#eee 60%) center fixed;
+              background: -ms-radial-gradient(circle,#aaa,#eee 60%) center fixed;
+              background: -o-radial-gradient(circle,#aaa,#eee 60%) center fixed;
+              border-top: 8px solid rgba(51,51,51,.8);
+            }
+            #wrapper {
+              border-top: 1px solid #999;
+              margin-top: 160px;
+              padding: 15px;
+              background: #eee;
+              background: -webkit-linear-gradient(#fff,#ccc);
+              background: -moz-linear-gradient(#fff,#ccc);
+              background: -ms-linear-gradient(#fff,#ccc);
+              background: -o-linear-gradient(#fff,#ccc);
+              opacity: .9;
+              box-shadow: 0px 1px 8px rgba(0,0,0,0.3);
+            }
+            #inner {
+              width: 300px;
+              margin: 0 auto;
+            }
+            #button {
+              margin: 0 auto;
+              border-radius: 3px;
+              text-align: center;
+              font: 36px verdana,arial,sans-serif;
+              color: white;
+              text-shadow: 0 -1px 0 rgba(0,0,0,.8);
+              height: 70px;
+              line-height: 70px;
+              background: #555;
+              background: -webkit-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
+              background: -moz-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
+              background: -ms-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
+              background: -o-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
+              box-shadow: inset 0 1px 3px rgba(0,0,0,0.9);
+            }
+            #button:hover {
+              cursor: pointer;
+              background: #666;
+              background: -webkit-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
+              background: -moz-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
+              background: -ms-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
+              background: -o-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
+            }
+            #button:active {
+              box-shadow: inset 0 1px 12px rgba(0,0,0,0.9);
+              background: #444;
+            }
+            #label {
+              text-align: left;
+              text-shadow: 0 1px 1px #fff;
+              margin: 16px auto 0;
+            }
+            form {
+              height: 38px;
+              background: #fff;
+              border: 1px solid #bbb;
+              border-radius: 3px;
+              position: relative;
+            }
+            button, input {
+              font-weight: bold;
+              font-size: 15px;
+            }
+            input[type="text"] {
+              border-radius: 3px;
+              box-sizing: border-box;
+              -moz-box-sizing: border-box;   
+              padding: 0 45px 0 10px;
+              *padding: 0; /* IE7 hack */
+              width: 100%;
+              height: 100%;
+              outline: none;
+              border: none;
+              position: absolute;
+            }
+            button[type="submit"] {
+              position: absolute;
+              right: 0;
+              width: 45px;
+              height: 38px;
+            }
+            @media only screen and (min-device-width: 320px) and (max-device-width: 720px) {
+              body {
+                background: #bbb;
+                background: -webkit-linear-gradient(#aaa,#eee 60%) center fixed;
+                background: -moz-linear-gradient(#aaa,#eee 60%) center fixed;
+                background: -ms-linear-gradient(#aaa,#eee 60%) center fixed;
+              }
+              #wrapper {
+                margin-top: 0;
+              }
+              #inner {
+                width: 95%;        
+              }
+              #label {
+                text-align: center;
+              }
+            }
+        </style>
+        <link href="static/css/index.css" rel="stylesheet"> 
+
+        <div id="wrapper">
+            <div id="inner">
+                <div id="button" onclick="go2Random()" class="translate">New Renkan</div>
+                <div id="label" class="translate">or create/open a Renkan with the name</div> 
+                <form action="#" onsubmit="go2Name();return false;"> 
+                    <input type="text" id="renkanname" autofocus x-webkit-speech> 
+                    <button type="submit">OK</button>
+                </form>
+            </div>
+        </div>
+        <script> 
+      
+            function go2Name() 
+            {
+                var renkanname = document.getElementById("renkanname").value;
+                renkanname.length > 0 ? window.location = "p/" + renkanname : alert("Please enter a name")
+            }
+ 
+            function go2Random() 
+            {
+                window.location = "p/" + randomRenkanName();
+            }
+ 
+            function randomRenkanName() 
+            {
+                var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+                var string_length = 10;
+                var randomstring = '';
+                for (var i = 0; i < string_length; i++) 
+                {
+                    var rnum = Math.floor(Math.random() * chars.length);
+                    randomstring += chars.substring(rnum, rnum + 1);
+                }
+                return randomstring;
+            }
+            
+            // start the custom js
+            if (typeof customStart == "function") customStart();
+        </script>
+
 </html>
--- a/server/src/main/webapp/js/backbone-relational.js	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1687 +0,0 @@
-/**
- * Backbone-relational.js 0.6.0
- * (c) 2011 Paul Uithol
- * 
- * Backbone-relational may be freely distributed under the MIT license; see the accompanying LICENSE.txt.
- * For details and documentation: https://github.com/PaulUithol/Backbone-relational.
- * Depends on Backbone (and thus on Underscore as well): https://github.com/documentcloud/backbone.
- */
-( function( undefined ) {
-	"use strict";
-	
-	/**
-	 * CommonJS shim
-	 **/
-	var _, Backbone, exports;
-	if ( typeof window === 'undefined' ) {
-		_ = require( 'underscore' );
-		Backbone = require( 'backbone' );
-		exports = module.exports = Backbone;
-	}
-	else {
-		_ = window._;
-		Backbone = window.Backbone;
-		exports = window;
-	}
-
-	Backbone.Relational = {
-		showWarnings: true
-	};
-
-	/**
-	 * Semaphore mixin; can be used as both binary and counting.
-	 **/
-	Backbone.Semaphore = {
-		_permitsAvailable: null,
-		_permitsUsed: 0,
-		
-		acquire: function() {
-			if ( this._permitsAvailable && this._permitsUsed >= this._permitsAvailable ) {
-				throw new Error( 'Max permits acquired' );
-			}
-			else {
-				this._permitsUsed++;
-			}
-		},
-		
-		release: function() {
-			if ( this._permitsUsed === 0 ) {
-				throw new Error( 'All permits released' );
-			}
-			else {
-				this._permitsUsed--;
-			}
-		},
-		
-		isLocked: function() {
-			return this._permitsUsed > 0;
-		},
-		
-		setAvailablePermits: function( amount ) {
-			if ( this._permitsUsed > amount ) {
-				throw new Error( 'Available permits cannot be less than used permits' );
-			}
-			this._permitsAvailable = amount;
-		}
-	};
-	
-	/**
-	 * A BlockingQueue that accumulates items while blocked (via 'block'),
-	 * and processes them when unblocked (via 'unblock').
-	 * Process can also be called manually (via 'process').
-	 */
-	Backbone.BlockingQueue = function() {
-		this._queue = [];
-	};
-	_.extend( Backbone.BlockingQueue.prototype, Backbone.Semaphore, {
-		_queue: null,
-		
-		add: function( func ) {
-			if ( this.isBlocked() ) {
-				this._queue.push( func );
-			}
-			else {
-				func();
-			}
-		},
-		
-		process: function() {
-			while ( this._queue && this._queue.length ) {
-				this._queue.shift()();
-			}
-		},
-		
-		block: function() {
-			this.acquire();
-		},
-		
-		unblock: function() {
-			this.release();
-			if ( !this.isBlocked() ) {
-				this.process();
-			}
-		},
-		
-		isBlocked: function() {
-			return this.isLocked();
-		}
-	});
-	/**
-	 * Global event queue. Accumulates external events ('add:<key>', 'remove:<key>' and 'update:<key>')
-	 * until the top-level object is fully initialized (see 'Backbone.RelationalModel').
-	 */
-	Backbone.Relational.eventQueue = new Backbone.BlockingQueue();
-	
-	/**
-	 * Backbone.Store keeps track of all created (and destruction of) Backbone.RelationalModel.
-	 * Handles lookup for relations.
-	 */
-	Backbone.Store = function() {
-		this._collections = [];
-		this._reverseRelations = [];
-		this._subModels = [];
-		this._modelScopes = [ exports ];
-	};
-	_.extend( Backbone.Store.prototype, Backbone.Events, {
-		addModelScope: function( scope ) {
-			this._modelScopes.push( scope );
-		},
-
-		/**
-		 * Add a set of subModelTypes to the store, that can be used to resolve the '_superModel'
-		 * for a model later in 'setupSuperModel'.
-		 *
-		 * @param {Backbone.RelationalModel} subModelTypes
-		 * @param {Backbone.RelationalModel} superModelType
-		 */
-		addSubModels: function( subModelTypes, superModelType ) {
-			this._subModels.push({
-				'superModelType': superModelType,
-				'subModels': subModelTypes
-			});
-		},
-
-		/**
-		 * Check if the given modelType is registered as another model's subModel. If so, add it to the super model's
-		 * '_subModels', and set the modelType's '_superModel', '_subModelTypeName', and '_subModelTypeAttribute'.
-		 *
-		 * @param {Backbone.RelationalModel} modelType
-		 */
-		setupSuperModel: function( modelType ) {
-			_.find( this._subModels, function( subModelDef ) {
-				return _.find( subModelDef.subModels, function( subModelTypeName, typeValue ) {
-					var subModelType = this.getObjectByName( subModelTypeName );
-
-					if ( modelType === subModelType ) {
-						// Set 'modelType' as a child of the found superModel
-						subModelDef.superModelType._subModels[ typeValue ] = modelType;
-
-						// Set '_superModel', '_subModelTypeValue', and '_subModelTypeAttribute' on 'modelType'.
-						modelType._superModel = subModelDef.superModelType;
-						modelType._subModelTypeValue = typeValue;
-						modelType._subModelTypeAttribute = subModelDef.superModelType.prototype.subModelTypeAttribute;
-						return true;
-					}
-				}, this );
-			}, this );
-		},
-		
-		/**
-		 * Add a reverse relation. Is added to the 'relations' property on model's prototype, and to
-		 * existing instances of 'model' in the store as well.
-		 * @param {Object} relation
-		 * @param {Backbone.RelationalModel} relation.model
-		 * @param {String} relation.type
-		 * @param {String} relation.key
-		 * @param {String|Object} relation.relatedModel
-		 */
-		addReverseRelation: function( relation ) {
-			var exists = _.any( this._reverseRelations, function( rel ) {
-					return _.all( relation, function( val, key ) {
-							return val === rel[ key ];
-						});
-				});
-			
-			if ( !exists && relation.model && relation.type ) {
-				this._reverseRelations.push( relation );
-				
-				var addRelation = function( model, relation ) {
-					if ( !model.prototype.relations ) {
-						model.prototype.relations = [];
-					}
-					model.prototype.relations.push( relation );
-					
-					_.each( model._subModels, function( subModel ) {
-							addRelation( subModel, relation );
-						}, this );
-				};
-				
-				addRelation( relation.model, relation );
-				
-				this.retroFitRelation( relation );
-			}
-		},
-		
-		/**
-		 * Add a 'relation' to all existing instances of 'relation.model' in the store
-		 * @param {Object} relation
-		 */
-		retroFitRelation: function( relation ) {
-			var coll = this.getCollection( relation.model );
-			coll.each( function( model ) {
-				if ( !( model instanceof relation.model ) ) {
-					return;
-				}
-
-				new relation.type( model, relation );
-			}, this);
-		},
-		
-		/**
-		 * Find the Store's collection for a certain type of model.
-		 * @param {Backbone.RelationalModel} model
-		 * @return {Backbone.Collection} A collection if found (or applicable for 'model'), or null
-		 */
-		getCollection: function( model ) {
-			if ( model instanceof Backbone.RelationalModel ) {
-				model = model.constructor;
-			}
-			
-			var rootModel = model;
-			while ( rootModel._superModel ) {
-				rootModel = rootModel._superModel;
-			}
-			
-			var coll = _.detect( this._collections, function( c ) {
-					return c.model === rootModel;
-				});
-			
-			if ( !coll ) {
-				coll = this._createCollection( rootModel );
-			}
-			
-			return coll;
-		},
-		
-		/**
-		 * Find a type on the global object by name. Splits name on dots.
-		 * @param {String} name
-		 * @return {Object}
-		 */
-		getObjectByName: function( name ) {
-			var parts = name.split( '.' ),
-				type = null;
-
-			_.find( this._modelScopes, function( scope ) {
-				type = _.reduce( parts, function( memo, val ) {
-					return memo[ val ];
-				}, scope );
-
-				if ( type && type !== scope ) {
-					return true;
-				}
-			}, this );
-
-			return type;
-		},
-		
-		_createCollection: function( type ) {
-			var coll;
-			
-			// If 'type' is an instance, take its constructor
-			if ( type instanceof Backbone.RelationalModel ) {
-				type = type.constructor;
-			}
-			
-			// Type should inherit from Backbone.RelationalModel.
-			if ( type.prototype instanceof Backbone.RelationalModel ) {
-				coll = new Backbone.Collection();
-				coll.model = type;
-				
-				this._collections.push( coll );
-			}
-			
-			return coll;
-		},
-
-		/**
-		 * Find the attribute that is to be used as the `id` on a given object
-		 * @param type
-		 * @param {String|Number|Object|Backbone.RelationalModel} item
-		 * @return {String|Number}
-		 */
-		resolveIdForItem: function( type, item ) {
-			var id = _.isString( item ) || _.isNumber( item ) ? item : null;
-
-			if ( id === null ) {
-				if ( item instanceof Backbone.RelationalModel ) {
-					id = item.id;
-				}
-				else if ( _.isObject( item ) ) {
-					id = item[ type.prototype.idAttribute ];
-				}
-			}
-
-			// Make all falsy values `null` (except for 0, which could be an id.. see '/issues/179')
-			if ( !id && id !== 0 ) {
-				id = null;
-			}
-
-			return id;
-		},
-
-		/**
-		 *
-		 * @param type
-		 * @param {String|Number|Object|Backbone.RelationalModel} item
-		 */
-		find: function( type, item ) {
-			var id = this.resolveIdForItem( type, item );
-			var coll = this.getCollection( type );
-			
-			// Because the found object could be of any of the type's superModel
-			// types, only return it if it's actually of the type asked for.
-			if ( coll ) {
-				var obj = coll.get( id );
-
-				if ( obj instanceof type ) {
-					return obj;
-				}
-			}
-
-			return null;
-		},
-		
-		/**
-		 * Add a 'model' to it's appropriate collection. Retain the original contents of 'model.collection'.
-		 * @param {Backbone.RelationalModel} model
-		 */
-		register: function( model ) {
-			var coll = this.getCollection( model );
-
-			if ( coll ) {
-				if ( coll.get( model ) ) {
-					throw new Error( "Cannot instantiate more than one Backbone.RelationalModel with the same id per type!" );
-				}
-
-				var modelColl = model.collection;
-				coll.add( model );
-				model.bind( 'destroy', this.unregister, this );
-				model.collection = modelColl;
-			}
-		},
-		
-		/**
-		 * Explicitly update a model's id in it's store collection
-		 * @param {Backbone.RelationalModel} model
-		 */
-		update: function( model ) {
-			var coll = this.getCollection( model );
-			coll._onModelEvent( 'change:' + model.idAttribute, model, coll );
-		},
-		
-		/**
-		 * Remove a 'model' from the store.
-		 * @param {Backbone.RelationalModel} model
-		 */
-		unregister: function( model ) {
-			model.unbind( 'destroy', this.unregister );
-			var coll = this.getCollection( model );
-			coll && coll.remove( model );
-		}
-	});
-	Backbone.Relational.store = new Backbone.Store();
-	
-	/**
-	 * The main Relation class, from which 'HasOne' and 'HasMany' inherit. Internally, 'relational:<key>' events
-	 * are used to regulate addition and removal of models from relations.
-	 *
-	 * @param {Backbone.RelationalModel} instance
-	 * @param {Object} options
-	 * @param {string} options.key
-	 * @param {Backbone.RelationalModel.constructor} options.relatedModel
-	 * @param {Boolean|String} [options.includeInJSON=true] Serialize the given attribute for related model(s)' in toJSON, or just their ids.
-	 * @param {Boolean} [options.createModels=true] Create objects from the contents of keys if the object is not found in Backbone.store.
-	 * @param {Object} [options.reverseRelation] Specify a bi-directional relation. If provided, Relation will reciprocate
-	 *    the relation to the 'relatedModel'. Required and optional properties match 'options', except that it also needs
-	 *    {Backbone.Relation|String} type ('HasOne' or 'HasMany').
-	 */
-	Backbone.Relation = function( instance, options ) {
-		this.instance = instance;
-		// Make sure 'options' is sane, and fill with defaults from subclasses and this object's prototype
-		options = _.isObject( options ) ? options : {};
-		this.reverseRelation = _.defaults( options.reverseRelation || {}, this.options.reverseRelation );
-		this.reverseRelation.type = !_.isString( this.reverseRelation.type ) ? this.reverseRelation.type :
-			Backbone[ this.reverseRelation.type ] || Backbone.Relational.store.getObjectByName( this.reverseRelation.type );
-		this.model = options.model || this.instance.constructor;
-		this.options = _.defaults( options, this.options, Backbone.Relation.prototype.options );
-		
-		this.key = this.options.key;
-		this.keySource = this.options.keySource || this.key;
-		this.keyDestination = this.options.keyDestination || this.keySource || this.key;
-
-		// 'exports' should be the global object where 'relatedModel' can be found on if given as a string.
-		this.relatedModel = this.options.relatedModel;
-		if ( _.isString( this.relatedModel ) ) {
-			this.relatedModel = Backbone.Relational.store.getObjectByName( this.relatedModel );
-		}
-
-		if ( !this.checkPreconditions() ) {
-			return false;
-		}
-
-		if ( instance ) {
-			this.keyContents = this.instance.get( this.keySource );
-
-			// Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'.
-			if ( this.key !== this.keySource ) {
-				this.instance.unset( this.keySource, { silent: true } );
-			}
-
-			// Add this Relation to instance._relations
-			this.instance._relations.push( this );
-		}
-
-		// Add the reverse relation on 'relatedModel' to the store's reverseRelations
-		if ( !this.options.isAutoRelation && this.reverseRelation.type && this.reverseRelation.key ) {
-			Backbone.Relational.store.addReverseRelation( _.defaults( {
-					isAutoRelation: true,
-					model: this.relatedModel,
-					relatedModel: this.model,
-					reverseRelation: this.options // current relation is the 'reverseRelation' for it's own reverseRelation
-				},
-				this.reverseRelation // Take further properties from this.reverseRelation (type, key, etc.)
-			) );
-		}
-
-		_.bindAll( this, '_modelRemovedFromCollection', '_relatedModelAdded', '_relatedModelRemoved' );
-
-		if ( instance ) {
-			this.initialize();
-
-			// When a model in the store is destroyed, check if it is 'this.instance'.
-			Backbone.Relational.store.getCollection( this.instance )
-				.bind( 'relational:remove', this._modelRemovedFromCollection );
-
-			// When 'relatedModel' are created or destroyed, check if it affects this relation.
-			Backbone.Relational.store.getCollection( this.relatedModel )
-				.bind( 'relational:add', this._relatedModelAdded )
-				.bind( 'relational:remove', this._relatedModelRemoved );
-		}
-	};
-	// Fix inheritance :\
-	Backbone.Relation.extend = Backbone.Model.extend;
-	// Set up all inheritable **Backbone.Relation** properties and methods.
-	_.extend( Backbone.Relation.prototype, Backbone.Events, Backbone.Semaphore, {
-		options: {
-			createModels: true,
-			includeInJSON: true,
-			isAutoRelation: false
-		},
-		
-		instance: null,
-		key: null,
-		keyContents: null,
-		relatedModel: null,
-		reverseRelation: null,
-		related: null,
-		
-		_relatedModelAdded: function( model, coll, options ) {
-			// Allow 'model' to set up it's relations, before calling 'tryAddRelated'
-			// (which can result in a call to 'addRelated' on a relation of 'model')
-			var dit = this;
-			model.queue( function() {
-				dit.tryAddRelated( model, options );
-			});
-		},
-		
-		_relatedModelRemoved: function( model, coll, options ) {
-			this.removeRelated( model, options );
-		},
-		
-		_modelRemovedFromCollection: function( model ) {
-			if ( model === this.instance ) {
-				this.destroy();
-			}
-		},
-		
-		/**
-		 * Check several pre-conditions.
-		 * @return {Boolean} True if pre-conditions are satisfied, false if they're not.
-		 */
-		checkPreconditions: function() {
-			var i = this.instance,
-				k = this.key,
-				m = this.model,
-				rm = this.relatedModel,
-				warn = Backbone.Relational.showWarnings && typeof console !== 'undefined';
-
-			if ( !m || !k || !rm ) {
-				warn && console.warn( 'Relation=%o; no model, key or relatedModel (%o, %o, %o)', this, m, k, rm );
-				return false;
-			}
-			// Check if the type in 'model' inherits from Backbone.RelationalModel
-			if ( !( m.prototype instanceof Backbone.RelationalModel ) ) {
-				warn && console.warn( 'Relation=%o; model does not inherit from Backbone.RelationalModel (%o)', this, i );
-				return false;
-			}
-			// Check if the type in 'relatedModel' inherits from Backbone.RelationalModel
-			if ( !( rm.prototype instanceof Backbone.RelationalModel ) ) {
-				warn && console.warn( 'Relation=%o; relatedModel does not inherit from Backbone.RelationalModel (%o)', this, rm );
-				return false;
-			}
-			// Check if this is not a HasMany, and the reverse relation is HasMany as well
-			if ( this instanceof Backbone.HasMany && this.reverseRelation.type === Backbone.HasMany ) {
-				warn && console.warn( 'Relation=%o; relation is a HasMany, and the reverseRelation is HasMany as well.', this );
-				return false;
-			}
-
-			// Check if we're not attempting to create a duplicate relationship
-			if ( i && i._relations.length ) {
-				var exists = _.any( i._relations, function( rel ) {
-						var hasReverseRelation = this.reverseRelation.key && rel.reverseRelation.key;
-						return rel.relatedModel === rm && rel.key === k &&
-							( !hasReverseRelation || this.reverseRelation.key === rel.reverseRelation.key );
-					}, this );
-
-				if ( exists ) {
-					warn && console.warn( 'Relation=%o between instance=%o.%s and relatedModel=%o.%s already exists',
-						this, i, k, rm, this.reverseRelation.key );
-					return false;
-				}
-			}
-
-			return true;
-		},
-
-		/**
-		 * Set the related model(s) for this relation
-		 * @param {Backbone.Mode|Backbone.Collection} related
-		 * @param {Object} [options]
-		 */
-		setRelated: function( related, options ) {
-			this.related = related;
-
-			this.instance.acquire();
-			this.instance.set( this.key, related, _.defaults( options || {}, { silent: true } ) );
-			this.instance.release();
-		},
-		
-		/**
-		 * Determine if a relation (on a different RelationalModel) is the reverse
-		 * relation of the current one.
-		 * @param {Backbone.Relation} relation
-		 * @return {Boolean}
-		 */
-		_isReverseRelation: function( relation ) {
-			if ( relation.instance instanceof this.relatedModel && this.reverseRelation.key === relation.key &&
-					this.key === relation.reverseRelation.key ) {
-				return true;
-			}
-			return false;
-		},
-		
-		/**
-		 * Get the reverse relations (pointing back to 'this.key' on 'this.instance') for the currently related model(s).
-		 * @param {Backbone.RelationalModel} [model] Get the reverse relations for a specific model.
-		 *    If not specified, 'this.related' is used.
-		 * @return {Backbone.Relation[]}
-		 */
-		getReverseRelations: function( model ) {
-			var reverseRelations = [];
-			// Iterate over 'model', 'this.related.models' (if this.related is a Backbone.Collection), or wrap 'this.related' in an array.
-			var models = !_.isUndefined( model ) ? [ model ] : this.related && ( this.related.models || [ this.related ] );
-			_.each( models , function( related ) {
-					_.each( related.getRelations(), function( relation ) {
-							if ( this._isReverseRelation( relation ) ) {
-								reverseRelations.push( relation );
-							}
-						}, this );
-				}, this );
-			
-			return reverseRelations;
-		},
-		
-		/**
-		 * Rename options.silent to options.silentChange, so events propagate properly.
-		 * (for example in HasMany, from 'addRelated'->'handleAddition')
-		 * @param {Object} [options]
-		 * @return {Object}
-		 */
-		sanitizeOptions: function( options ) {
-			options = options ? _.clone( options ) : {};
-			if ( options.silent ) {
-				options.silentChange = true;
-				delete options.silent;
-			}
-			return options;
-		},
-
-		/**
-		 * Rename options.silentChange to options.silent, so events are silenced as intended in Backbone's
-		 * original functions.
-		 * @param {Object} [options]
-		 * @return {Object}
-		 */
-		unsanitizeOptions: function( options ) {
-			options = options ? _.clone( options ) : {};
-			if ( options.silentChange ) {
-				options.silent = true;
-				delete options.silentChange;
-			}
-			return options;
-		},
-		
-		// Cleanup. Get reverse relation, call removeRelated on each.
-		destroy: function() {
-			Backbone.Relational.store.getCollection( this.instance )
-				.unbind( 'relational:remove', this._modelRemovedFromCollection );
-			
-			Backbone.Relational.store.getCollection( this.relatedModel )
-				.unbind( 'relational:add', this._relatedModelAdded )
-				.unbind( 'relational:remove', this._relatedModelRemoved );
-			
-			_.each( this.getReverseRelations(), function( relation ) {
-					relation.removeRelated( this.instance );
-				}, this );
-		}
-	});
-	
-	Backbone.HasOne = Backbone.Relation.extend({
-		options: {
-			reverseRelation: { type: 'HasMany' }
-		},
-		
-		initialize: function() {
-			_.bindAll( this, 'onChange' );
-
-			this.instance.bind( 'relational:change:' + this.key, this.onChange );
-
-			var model = this.findRelated( { silent: true } );
-			this.setRelated( model );
-
-			// Notify new 'related' object of the new relation.
-			_.each( this.getReverseRelations(), function( relation ) {
-					relation.addRelated( this.instance );
-				}, this );
-		},
-		
-		findRelated: function( options ) {
-			var item = this.keyContents;
-			var model = null;
-			
-			if ( item instanceof this.relatedModel ) {
-				model = item;
-			}
-			else if ( item || item === 0 ) { // since 0 can be a valid `id` as well
-				model = this.relatedModel.findOrCreate( item, { create: this.options.createModels } );
-			}
-			
-			return model;
-		},
-		
-		/**
-		 * If the key is changed, notify old & new reverse relations and initialize the new relation
-		 */
-		onChange: function( model, attr, options ) {
-			// Don't accept recursive calls to onChange (like onChange->findRelated->findOrCreate->initializeRelations->addRelated->onChange)
-			if ( this.isLocked() ) {
-				return;
-			}
-			this.acquire();
-			options = this.sanitizeOptions( options );
-			
-			// 'options._related' is set by 'addRelated'/'removeRelated'. If it is set, the change
-			// is the result of a call from a relation. If it's not, the change is the result of 
-			// a 'set' call on this.instance.
-			var changed = _.isUndefined( options._related );
-			var oldRelated = changed ? this.related : options._related;
-			
-			if ( changed ) {	
-				this.keyContents = attr;
-				
-				// Set new 'related'
-				if ( attr instanceof this.relatedModel ) {
-					this.related = attr;
-				}
-				else if ( attr ) {
-					var related = this.findRelated( options );
-					this.setRelated( related );
-				}
-				else {
-					this.setRelated( null );
-				}
-			}
-			
-			// Notify old 'related' object of the terminated relation
-			if ( oldRelated && this.related !== oldRelated ) {
-				_.each( this.getReverseRelations( oldRelated ), function( relation ) {
-						relation.removeRelated( this.instance, options );
-					}, this );
-			}
-			
-			// Notify new 'related' object of the new relation. Note we do re-apply even if this.related is oldRelated;
-			// that can be necessary for bi-directional relations if 'this.instance' was created after 'this.related'.
-			// In that case, 'this.instance' will already know 'this.related', but the reverse might not exist yet.
-			_.each( this.getReverseRelations(), function( relation ) {
-					relation.addRelated( this.instance, options );
-				}, this);
-			
-			// Fire the 'update:<key>' event if 'related' was updated
-			if ( !options.silentChange && this.related !== oldRelated ) {
-				var dit = this;
-				Backbone.Relational.eventQueue.add( function() {
-					dit.instance.trigger( 'update:' + dit.key, dit.instance, dit.related, options );
-				});
-			}
-			this.release();
-		},
-		
-		/**
-		 * If a new 'this.relatedModel' appears in the 'store', try to match it to the last set 'keyContents'
-		 */
-		tryAddRelated: function( model, options ) {
-			if ( this.related ) {
-				return;
-			}
-			options = this.sanitizeOptions( options );
-			
-			var item = this.keyContents;
-			if ( item || item === 0 ) { // since 0 can be a valid `id` as well
-				var id = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item );
-				if ( !_.isNull( id ) && model.id === id ) {
-					this.addRelated( model, options );
-				}
-			}
-		},
-		
-		addRelated: function( model, options ) {
-			if ( model !== this.related ) {
-				var oldRelated = this.related || null;
-				this.setRelated( model );
-				this.onChange( this.instance, model, { _related: oldRelated } );
-			}
-		},
-		
-		removeRelated: function( model, options ) {
-			if ( !this.related ) {
-				return;
-			}
-			
-			if ( model === this.related ) {
-				var oldRelated = this.related || null;
-				this.setRelated( null );
-				this.onChange( this.instance, model, { _related: oldRelated } );
-			}
-		}
-	});
-	
-	Backbone.HasMany = Backbone.Relation.extend({
-		collectionType: null,
-		
-		options: {
-			reverseRelation: { type: 'HasOne' },
-			collectionType: Backbone.Collection,
-			collectionKey: true,
-			collectionOptions: {}
-		},
-		
-		initialize: function() {
-			_.bindAll( this, 'onChange', 'handleAddition', 'handleRemoval', 'handleReset' );
-			this.instance.bind( 'relational:change:' + this.key, this.onChange );
-			
-			// Handle a custom 'collectionType'
-			this.collectionType = this.options.collectionType;
-			if ( _.isString( this.collectionType ) ) {
-				this.collectionType = Backbone.Relational.store.getObjectByName( this.collectionType );
-			}
-			if ( !this.collectionType.prototype instanceof Backbone.Collection ){
-				throw new Error( 'collectionType must inherit from Backbone.Collection' );
-			}
-
-			// Handle cases where a model/relation is created with a collection passed straight into 'attributes'
-			if ( this.keyContents instanceof Backbone.Collection ) {
-				this.setRelated( this._prepareCollection( this.keyContents ) );
-			}
-			else {
-				this.setRelated( this._prepareCollection() );
-			}
-
-			this.findRelated( { silent: true } );
-		},
-		
-		_getCollectionOptions: function() {
-			return _.isFunction( this.options.collectionOptions ) ?
-				this.options.collectionOptions( this.instance ) :
-				this.options.collectionOptions;
-		},
-
-		/**
-		 * Bind events and setup collectionKeys for a collection that is to be used as the backing store for a HasMany.
-		 * If no 'collection' is supplied, a new collection will be created of the specified 'collectionType' option.
-		 * @param {Backbone.Collection} [collection]
-		 */
-		_prepareCollection: function( collection ) {
-			if ( this.related ) {
-				this.related
-					.unbind( 'relational:add', this.handleAddition )
-					.unbind( 'relational:remove', this.handleRemoval )
-					.unbind( 'relational:reset', this.handleReset )
-			}
-
-			if ( !collection || !( collection instanceof Backbone.Collection ) ) {
-				collection = new this.collectionType( [], this._getCollectionOptions() );
-			}
-
-			collection.model = this.relatedModel;
-			
-			if ( this.options.collectionKey ) {
-				var key = this.options.collectionKey === true ? this.options.reverseRelation.key : this.options.collectionKey;
-				
-				if ( collection[ key ] && collection[ key ] !== this.instance ) {
-					if ( Backbone.Relational.showWarnings && typeof console !== 'undefined' ) {
-						console.warn( 'Relation=%o; collectionKey=%s already exists on collection=%o', this, key, this.options.collectionKey );
-					}
-				}
-				else if ( key ) {
-					collection[ key ] = this.instance;
-				}
-			}
-			
-			collection
-				.bind( 'relational:add', this.handleAddition )
-				.bind( 'relational:remove', this.handleRemoval )
-				.bind( 'relational:reset', this.handleReset );
-			
-			return collection;
-		},
-		
-		findRelated: function( options ) {
-			if ( this.keyContents ) {
-				var models = [];
-
-				if ( this.keyContents instanceof Backbone.Collection ) {
-					models = this.keyContents.models;
-				}
-				else {
-					// Handle cases the an API/user supplies just an Object/id instead of an Array
-					this.keyContents = _.isArray( this.keyContents ) ? this.keyContents : [ this.keyContents ];
-
-					// Try to find instances of the appropriate 'relatedModel' in the store
-					_.each( this.keyContents, function( item ) {
-							var model = null;
-							if ( item instanceof this.relatedModel ) {
-								model = item;
-							}
-							else if ( item || item === 0 ) { // since 0 can be a valid `id` as well
-								model = this.relatedModel.findOrCreate( item, { create: this.options.createModels } );
-							}
-
-							if ( model && !this.related.getByCid( model ) && !this.related.get( model ) ) {
-								models.push( model );
-							}
-						}, this );
-				}
-
-				// Add all found 'models' in on go, so 'add' will only be called once (and thus 'sort', etc.)
-				if ( models.length ) {
-					options = this.unsanitizeOptions( options );
-					this.related.add( models, options );
-				}
-			}
-		},
-		
-		/**
-		 * If the key is changed, notify old & new reverse relations and initialize the new relation
-		 */
-		onChange: function( model, attr, options ) {
-			options = this.sanitizeOptions( options );
-			this.keyContents = attr;
-			
-			// Notify old 'related' object of the terminated relation
-			_.each( this.getReverseRelations(), function( relation ) {
-					relation.removeRelated( this.instance, options );
-				}, this );
-			
-			// Replace 'this.related' by 'attr' if it is a Backbone.Collection
-			if ( attr instanceof Backbone.Collection ) {
-				this._prepareCollection( attr );
-				this.related = attr;
-			}
-			// Otherwise, 'attr' should be an array of related object ids.
-			// Re-use the current 'this.related' if it is a Backbone.Collection, and remove any current entries.
-			// Otherwise, create a new collection.
-			else {
-				var coll;
-
-				if ( this.related instanceof Backbone.Collection ) {
-					coll = this.related;
-					coll.remove( coll.models );
-				}
-				else {
-					coll = this._prepareCollection();
-				}
-
-				this.setRelated( coll );
-				this.findRelated( options );
-			}
-			
-			// Notify new 'related' object of the new relation
-			_.each( this.getReverseRelations(), function( relation ) {
-					relation.addRelated( this.instance, options );
-				}, this );
-			
-			var dit = this;
-			Backbone.Relational.eventQueue.add( function() {
-				!options.silentChange && dit.instance.trigger( 'update:' + dit.key, dit.instance, dit.related, options );
-			});
-		},
-		
-		tryAddRelated: function( model, options ) {
-			options = this.sanitizeOptions( options );
-			if ( !this.related.getByCid( model ) && !this.related.get( model ) ) {
-				// Check if this new model was specified in 'this.keyContents'
-				var item = _.any( this.keyContents, function( item ) {
-						var id = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item );
-						return !_.isNull( id ) && id === model.id;
-					}, this );
-				
-				if ( item ) {
-					this.related.add( model, options );
-				}
-			}
-		},
-		
-		/**
-		 * When a model is added to a 'HasMany', trigger 'add' on 'this.instance' and notify reverse relations.
-		 * (should be 'HasOne', must set 'this.instance' as their related).
-		 */
-		handleAddition: function( model, coll, options ) {
-			//console.debug('handleAddition called; args=%o', arguments);
-			// Make sure the model is in fact a valid model before continuing.
-			// (it can be invalid as a result of failing validation in Backbone.Collection._prepareModel)
-			if ( !( model instanceof Backbone.Model ) ) {
-				return;
-			}
-			
-			options = this.sanitizeOptions( options );
-			
-			_.each( this.getReverseRelations( model ), function( relation ) {
-					relation.addRelated( this.instance, options );
-				}, this );
-
-			// Only trigger 'add' once the newly added model is initialized (so, has it's relations set up)
-			var dit = this;
-			Backbone.Relational.eventQueue.add( function() {
-				!options.silentChange && dit.instance.trigger( 'add:' + dit.key, model, dit.related, options );
-			});
-		},
-		
-		/**
-		 * When a model is removed from a 'HasMany', trigger 'remove' on 'this.instance' and notify reverse relations.
-		 * (should be 'HasOne', which should be nullified)
-		 */
-		handleRemoval: function( model, coll, options ) {
-			//console.debug('handleRemoval called; args=%o', arguments);
-			if ( !( model instanceof Backbone.Model ) ) {
-				return;
-			}
-
-			options = this.sanitizeOptions( options );
-			
-			_.each( this.getReverseRelations( model ), function( relation ) {
-					relation.removeRelated( this.instance, options );
-				}, this );
-			
-			var dit = this;
-			Backbone.Relational.eventQueue.add( function() {
-				!options.silentChange && dit.instance.trigger( 'remove:' + dit.key, model, dit.related, options );
-			});
-		},
-
-		handleReset: function( coll, options ) {
-			options = this.sanitizeOptions( options );
-
-			var dit = this;
-			Backbone.Relational.eventQueue.add( function() {
-				!options.silentChange && dit.instance.trigger( 'reset:' + dit.key, dit.related, options );
-			});
-		},
-		
-		addRelated: function( model, options ) {
-			var dit = this;
-			options = this.unsanitizeOptions( options );
-			model.queue( function() { // Queued to avoid errors for adding 'model' to the 'this.related' set twice
-				if ( dit.related && !dit.related.getByCid( model ) && !dit.related.get( model ) ) {
-					dit.related.add( model, options );
-				}
-			});
-		},
-		
-		removeRelated: function( model, options ) {
-			options = this.unsanitizeOptions( options );
-			if ( this.related.getByCid( model ) || this.related.get( model ) ) {
-				this.related.remove( model, options );
-			}
-		}
-	});
-	
-	/**
-	 * A type of Backbone.Model that also maintains relations to other models and collections.
-	 * New events when compared to the original:
-	 *  - 'add:<key>' (model, related collection, options)
-	 *  - 'remove:<key>' (model, related collection, options)
-	 *  - 'update:<key>' (model, related model or collection, options)
-	 */
-	Backbone.RelationalModel = Backbone.Model.extend({
-		relations: null, // Relation descriptions on the prototype
-		_relations: null, // Relation instances
-		_isInitialized: false,
-		_deferProcessing: false,
-		_queue: null,
-		
-		subModelTypeAttribute: 'type',
-		subModelTypes: null,
-		
-		constructor: function( attributes, options ) {
-			// Nasty hack, for cases like 'model.get( <HasMany key> ).add( item )'.
-			// Defer 'processQueue', so that when 'Relation.createModels' is used we:
-			// a) Survive 'Backbone.Collection.add'; this takes care we won't error on "can't add model to a set twice"
-			//    (by creating a model from properties, having the model add itself to the collection via one of
-			//    it's relations, then trying to add it to the collection).
-			// b) Trigger 'HasMany' collection events only after the model is really fully set up.
-			// Example that triggers both a and b: "p.get('jobs').add( { company: c, person: p } )".
-			var dit = this;
-			if ( options && options.collection ) {
-				this._deferProcessing = true;
-				
-				var processQueue = function( model ) {
-					if ( model === dit ) {
-						dit._deferProcessing = false;
-						dit.processQueue();
-						options.collection.unbind( 'relational:add', processQueue );
-					}
-				};
-				options.collection.bind( 'relational:add', processQueue );
-				
-				// So we do process the queue eventually, regardless of whether this model really gets added to 'options.collection'.
-				_.defer( function() {
-					processQueue( dit );
-				});
-			}
-			
-			this._queue = new Backbone.BlockingQueue();
-			this._queue.block();
-			Backbone.Relational.eventQueue.block();
-			
-			Backbone.Model.apply( this, arguments );
-			
-			// Try to run the global queue holding external events
-			Backbone.Relational.eventQueue.unblock();
-		},
-		
-		/**
-		 * Override 'trigger' to queue 'change' and 'change:*' events
-		 */
-		trigger: function( eventName ) {
-			if ( eventName.length > 5 && 'change' === eventName.substr( 0, 6 ) ) {
-				var dit = this, args = arguments;
-				Backbone.Relational.eventQueue.add( function() {
-						Backbone.Model.prototype.trigger.apply( dit, args );
-					});
-			}
-			else {
-				Backbone.Model.prototype.trigger.apply( this, arguments );
-			}
-			
-			return this;
-		},
-		
-		/**
-		 * Initialize Relations present in this.relations; determine the type (HasOne/HasMany), then creates a new instance.
-		 * Invoked in the first call so 'set' (which is made from the Backbone.Model constructor).
-		 */
-		initializeRelations: function() {
-			this.acquire(); // Setting up relations often also involve calls to 'set', and we only want to enter this function once
-			this._relations = [];
-			
-			_.each( this.relations, function( rel ) {
-					var type = !_.isString( rel.type ) ? rel.type :	Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName( rel.type );
-					if ( type && type.prototype instanceof Backbone.Relation ) {
-						new type( this, rel ); // Also pushes the new Relation into _relations
-					}
-					else {
-						Backbone.Relational.showWarnings && typeof console !== 'undefined' && console.warn( 'Relation=%o; missing or invalid type!', rel );
-					}
-				}, this );
-			
-			this._isInitialized = true;
-			this.release();
-			this.processQueue();
-		},
-
-		/**
-		 * When new values are set, notify this model's relations (also if options.silent is set).
-		 * (Relation.setRelated locks this model before calling 'set' on it to prevent loops)
-		 */
-		updateRelations: function( options ) {
-			if ( this._isInitialized && !this.isLocked() ) {
-				_.each( this._relations, function( rel ) {
-					// Update from data in `rel.keySource` if set, or `rel.key` otherwise
-					var val = this.attributes[ rel.keySource ] || this.attributes[ rel.key ];
-					if ( rel.related !== val ) {
-						this.trigger( 'relational:change:' + rel.key, this, val, options || {} );
-					}
-				}, this );
-			}
-		},
-		
-		/**
-		 * Either add to the queue (if we're not initialized yet), or execute right away.
-		 */
-		queue: function( func ) {
-			this._queue.add( func );
-		},
-		
-		/**
-		 * Process _queue
-		 */
-		processQueue: function() {
-			if ( this._isInitialized && !this._deferProcessing && this._queue.isBlocked() ) {
-				this._queue.unblock();
-			}
-		},
-		
-		/**
-		 * Get a specific relation.
-		 * @param key {string} The relation key to look for.
-		 * @return {Backbone.Relation} An instance of 'Backbone.Relation', if a relation was found for 'key', or null.
-		 */
-		getRelation: function( key ) {
-			return _.detect( this._relations, function( rel ) {
-				if ( rel.key === key ) {
-					return true;
-				}
-			}, this );
-		},
-		
-		/**
-		 * Get all of the created relations.
-		 * @return {Backbone.Relation[]}
-		 */
-		getRelations: function() {
-			return this._relations;
-		},
-		
-		/**
-		 * Retrieve related objects.
-		 * @param key {string} The relation key to fetch models for.
-		 * @param [options] {Object} Options for 'Backbone.Model.fetch' and 'Backbone.sync'.
-		 * @param [update=false] {boolean} Whether to force a fetch from the server (updating existing models).
-		 * @return {jQuery.when[]} An array of request objects
-		 */
-		fetchRelated: function( key, options, update ) {
-			options || ( options = {} );
-			var setUrl,
-				requests = [],
-				rel = this.getRelation( key ),
-				keyContents = rel && rel.keyContents,
-				toFetch = keyContents && _.select( _.isArray( keyContents ) ? keyContents : [ keyContents ], function( item ) {
-					var id = Backbone.Relational.store.resolveIdForItem( rel.relatedModel, item );
-					return !_.isNull( id ) && ( update || !Backbone.Relational.store.find( rel.relatedModel, id ) );
-				}, this );
-			
-			if ( toFetch && toFetch.length ) {
-				// Create a model for each entry in 'keyContents' that is to be fetched
-				var models = _.map( toFetch, function( item ) {
-					var model;
-
-					if ( _.isObject( item ) ) {
-						model = rel.relatedModel.build( item );
-					}
-					else {
-						var attrs = {};
-						attrs[ rel.relatedModel.prototype.idAttribute ] = item;
-						model = rel.relatedModel.build( attrs );
-					}
-
-					return model;
-				}, this );
-				
-				// Try if the 'collection' can provide a url to fetch a set of models in one request.
-				if ( rel.related instanceof Backbone.Collection && _.isFunction( rel.related.url ) ) {
-					setUrl = rel.related.url( models );
-				}
-				
-				// An assumption is that when 'Backbone.Collection.url' is a function, it can handle building of set urls.
-				// To make sure it can, test if the url we got by supplying a list of models to fetch is different from
-				// the one supplied for the default fetch action (without args to 'url').
-				if ( setUrl && setUrl !== rel.related.url() ) {
-					var opts = _.defaults(
-						{
-							error: function() {
-								var args = arguments;
-								_.each( models, function( model ) {
-										model.trigger( 'destroy', model, model.collection, options );
-										options.error && options.error.apply( model, args );
-									});
-							},
-							url: setUrl
-						},
-						options,
-						{ add: true }
-					);
-
-					requests = [ rel.related.fetch( opts ) ];
-				}
-				else {
-					requests = _.map( models, function( model ) {
-						var opts = _.defaults(
-							{
-								error: function() {
-									model.trigger( 'destroy', model, model.collection, options );
-									options.error && options.error.apply( model, arguments );
-								}
-							},
-							options
-						);
-						return model.fetch( opts );
-					}, this );
-				}
-			}
-			
-			return requests;
-		},
-		
-		set: function( key, value, options ) {
-			Backbone.Relational.eventQueue.block();
-			
-			// Duplicate backbone's behavior to allow separate key/value parameters, instead of a single 'attributes' object
-			var attributes;
-			if ( _.isObject( key ) || key == null ) {
-				attributes = key;
-				options = value;
-			}
-			else {
-				attributes = {};
-				attributes[ key ] = value;
-			}
-			
-			var result = Backbone.Model.prototype.set.apply( this, arguments );
-			
-			// Ideal place to set up relations :)
-			if ( !this._isInitialized && !this.isLocked() ) {
-				this.constructor.initializeModelHierarchy();
-
-				Backbone.Relational.store.register( this );
-
-				this.initializeRelations();
-			}
-			// Update the 'idAttribute' in Backbone.store if; we don't want it to miss an 'id' update due to {silent:true}
-			else if ( attributes && this.idAttribute in attributes ) {
-				Backbone.Relational.store.update( this );
-			}
-			
-			if ( attributes ) {
-				this.updateRelations( options );
-			}
-			
-			// Try to run the global queue holding external events
-			Backbone.Relational.eventQueue.unblock();
-			
-			return result;
-		},
-		
-		unset: function( attribute, options ) {
-			Backbone.Relational.eventQueue.block();
-			
-			var result = Backbone.Model.prototype.unset.apply( this, arguments );
-			this.updateRelations( options );
-			
-			// Try to run the global queue holding external events
-			Backbone.Relational.eventQueue.unblock();
-			
-			return result;
-		},
-		
-		clear: function( options ) {
-			Backbone.Relational.eventQueue.block();
-			
-			var result = Backbone.Model.prototype.clear.apply( this, arguments );
-			this.updateRelations( options );
-			
-			// Try to run the global queue holding external events
-			Backbone.Relational.eventQueue.unblock();
-			
-			return result;
-		},
-		
-		/**
-		 * Override 'change', so the change will only execute after 'set' has finised (relations are updated),
-		 * and 'previousAttributes' will be available when the event is fired.
-		 */
-		change: function( options ) {
-			var dit = this, args = arguments;
-			Backbone.Relational.eventQueue.add( function() {
-					Backbone.Model.prototype.change.apply( dit, args );
-				});
-		},
-
-		clone: function() {
-			var attributes = _.clone( this.attributes );
-			if ( !_.isUndefined( attributes[ this.idAttribute ] ) ) {
-				attributes[ this.idAttribute ] = null;
-			}
-
-			_.each( this.getRelations(), function( rel ) {
-					delete attributes[ rel.key ];
-				});
-
-			return new this.constructor( attributes );
-		},
-		
-		/**
-		 * Convert relations to JSON, omits them when required
-		 */
-		toJSON: function() {
-			// If this Model has already been fully serialized in this branch once, return to avoid loops
-			if ( this.isLocked() ) {
-				return this.id;
-			}
-			
-			this.acquire();
-			var json = Backbone.Model.prototype.toJSON.call( this );
-			
-			if ( this.constructor._superModel && !( this.constructor._subModelTypeAttribute in json ) ) {
-				json[ this.constructor._subModelTypeAttribute ] = this.constructor._subModelTypeValue;
-			}
-			
-			_.each( this._relations, function( rel ) {
-					var value = json[ rel.key ];
-
-					if ( rel.options.includeInJSON === true) {
-						if ( value && _.isFunction( value.toJSON ) ) {
-							json[ rel.keyDestination ] = value.toJSON();
-						}
-						else {
-							json[ rel.keyDestination ] = null;
-						}
-					}
-					else if ( _.isString( rel.options.includeInJSON ) ) {
-						if ( value instanceof Backbone.Collection ) {
-							json[ rel.keyDestination ] = value.pluck( rel.options.includeInJSON );
-						}
-						else if ( value instanceof Backbone.Model ) {
-							json[ rel.keyDestination ] = value.get( rel.options.includeInJSON );
-						}	
-						else {
-							json[ rel.keyDestination ] = null;
-						}
-					}
-					else if ( _.isArray( rel.options.includeInJSON ) ) {
-						if ( value instanceof Backbone.Collection ) {
-							var valueSub = [];
-							value.each( function( model ) {
-								var curJson = {};
-								_.each( rel.options.includeInJSON, function( key ) {
-									curJson[ key ] = model.get( key );
-								});
-								valueSub.push( curJson );
-							});
-							json[ rel.keyDestination ] = valueSub;
-						}
-						else if ( value instanceof Backbone.Model ) {
-							var valueSub = {};
-							_.each( rel.options.includeInJSON, function( key ) {
-								valueSub[ key ] = value.get( key );
-							});
-							json[ rel.keyDestination ] = valueSub;
-						}
-						else {
-							json[ rel.keyDestination ] = null;
-						}
-					}
-					else {
-						delete json[ rel.key ];
-					}
-
-					if ( rel.keyDestination !== rel.key ) {
-						delete json[ rel.key ];
-					}
-				});
-			
-			this.release();
-			return json;
-		}
-	},
-	{
-		setup: function( superModel ) {
-			// We don't want to share a relations array with a parent, as this will cause problems with
-			// reverse relations.
-			this.prototype.relations = ( this.prototype.relations || [] ).slice( 0 );
-
-			this._subModels = {};
-			this._superModel = null;
-
-			// If this model has 'subModelTypes' itself, remember them in the store
-			if ( this.prototype.hasOwnProperty( 'subModelTypes' ) ) {
-				Backbone.Relational.store.addSubModels( this.prototype.subModelTypes, this );
-			}
-			// The 'subModelTypes' property should not be inherited, so reset it.
-			else {
-				this.prototype.subModelTypes = null;
-			}
-
-			// Initialize all reverseRelations that belong to this new model.
-			_.each( this.prototype.relations, function( rel ) {
-					if ( !rel.model ) {
-						rel.model = this;
-					}
-
-					if ( rel.reverseRelation && rel.model === this ) {				
-						var preInitialize = true;
-						if ( _.isString( rel.relatedModel ) ) {
-							/**
-							 * The related model might not be defined for two reasons
-							 *  1. it never gets defined, e.g. a typo
-							 *  2. it is related to itself
-							 * In neither of these cases do we need to pre-initialize reverse relations.
-							 */
-							var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
-							preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel );
-						}
-
-						var type = !_.isString( rel.type ) ? rel.type : Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName( rel.type );
-						if ( preInitialize && type && type.prototype instanceof Backbone.Relation ) {
-							new type( null, rel );
-						}
-					}
-				}, this );
-			
-			return this;
-		},
-
-		/**
-		 * Create a 'Backbone.Model' instance based on 'attributes'.
-		 * @param {Object} attributes
-		 * @param {Object} [options]
-		 * @return {Backbone.Model}
-		 */
-		build: function( attributes, options ) {
-			var model = this;
-
-			// 'build' is a possible entrypoint; it's possible no model hierarchy has been determined yet.
-			this.initializeModelHierarchy();
-
-			// Determine what type of (sub)model should be built if applicable.
-			// Lookup the proper subModelType in 'this._subModels'.
-			if ( this._subModels && this.prototype.subModelTypeAttribute in attributes ) {
-				var subModelTypeAttribute = attributes[ this.prototype.subModelTypeAttribute ];
-				var subModelType = this._subModels[ subModelTypeAttribute ];
-				if ( subModelType ) {
-					model = subModelType;
-				}
-			}
-			
-			return new model( attributes, options );
-		},
-
-		initializeModelHierarchy: function() {
-			// If we're here for the first time, try to determine if this modelType has a 'superModel'.
-			if ( _.isUndefined( this._superModel ) || _.isNull( this._superModel ) ) {
-				Backbone.Relational.store.setupSuperModel( this );
-
-				// If a superModel has been found, copy relations from the _superModel if they haven't been
-				// inherited automatically (due to a redefinition of 'relations').
-				// Otherwise, make sure we don't get here again for this type by making '_superModel' false so we fail
-				// the isUndefined/isNull check next time.
-				if ( this._superModel ) {
-					//
-					if ( this._superModel.prototype.relations ) {
-						var supermodelRelationsExist = _.any( this.prototype.relations, function( rel ) {
-							return rel.model && rel.model !== this;
-						}, this );
-
-						if ( !supermodelRelationsExist ) {
-							this.prototype.relations = this._superModel.prototype.relations.concat( this.prototype.relations );
-						}
-					}
-				}
-				else {
-					this._superModel = false;
-				}
-			}
-
-			// If we came here through 'build' for a model that has 'subModelTypes', and not all of them have been resolved yet, try to resolve each.
-			if ( this.prototype.subModelTypes && _.keys( this.prototype.subModelTypes ).length !== _.keys( this._subModels ).length ) {
-				_.each( this.prototype.subModelTypes, function( subModelTypeName ) {
-					var subModelType = Backbone.Relational.store.getObjectByName( subModelTypeName );
-					subModelType && subModelType.initializeModelHierarchy();
-				});
-			}
-		},
-
-		/**
-		 * Find an instance of `this` type in 'Backbone.Relational.store'.
-		 * - If `attributes` is a string or a number, `findOrCreate` will just query the `store` and return a model if found.
-		 * - If `attributes` is an object, the model will be updated with `attributes` if found.
-		 *   Otherwise, a new model is created with `attributes` (unless `options.create` is explicitly set to `false`).
-		 * @param {Object|String|Number} attributes Either a model's id, or the attributes used to create or update a model.
-		 * @param {Object} [options]
-		 * @param {Boolean} [options.create=true]
-		 * @return {Backbone.RelationalModel}
-		 */
-		findOrCreate: function( attributes, options ) {
-			// Try to find an instance of 'this' model type in the store
-			var model = Backbone.Relational.store.find( this, attributes );
-
-			// If we found an instance, update it with the data in 'item'; if not, create an instance
-			// (unless 'options.create' is false).
-			if ( _.isObject( attributes ) ) {
-				if ( model ) {
-					model.set( model.parse ? model.parse( attributes ) : attributes, options );
-				}
-				else if ( !options || ( options && options.create !== false ) ) {
-					model = this.build( attributes, options );
-				}
-			}
-
-			return model;
-		}
-	});
-	_.extend( Backbone.RelationalModel.prototype, Backbone.Semaphore );
-	
-	/**
-	 * Override Backbone.Collection._prepareModel, so objects will be built using the correct type
-	 * if the collection.model has subModels.
-	 */
-	Backbone.Collection.prototype.__prepareModel = Backbone.Collection.prototype._prepareModel;
-	Backbone.Collection.prototype._prepareModel = function ( model, options ) {
-		options || (options = {});
-		if ( !( model instanceof Backbone.Model ) ) {
-			var attrs = model;
-			options.collection = this;
-
-			if ( typeof this.model.findOrCreate !== 'undefined' ) {
-				model = this.model.findOrCreate( attrs, options );
-			}
-			else {
-				model = new this.model( attrs, options );
-			}
-			
-			if ( !model._validate( model.attributes, options ) ) {
-				model = false;
-			}
-		}
-		else if ( !model.collection ) {
-			model.collection = this;
-		}
-		
-		return model;
-	}
-	
-	/**
-	 * Override Backbone.Collection.add, so objects fetched from the server multiple times will
-	 * update the existing Model. Also, trigger 'relational:add'.
-	 */
-	var add = Backbone.Collection.prototype.__add = Backbone.Collection.prototype.add;
-	Backbone.Collection.prototype.add = function( models, options ) {
-		options || (options = {});
-		if ( !_.isArray( models ) ) {
-			models = [ models ];
-		}
-
-		var modelsToAdd = [];
-
-		//console.debug( 'calling add on coll=%o; model=%o, options=%o', this, models, options );
-		_.each( models, function( model ) {
-			if ( !( model instanceof Backbone.Model ) ) {
-				// `_prepareModel` attempts to find `model` in Backbone.store through `findOrCreate`,
-				// and sets the new properties on it if is found. Otherwise, a new model is instantiated.
-				model = Backbone.Collection.prototype._prepareModel.call( this, model, options );
-			}
-
-			if ( model instanceof Backbone.Model && !this.get( model ) && !this.getByCid( model ) ) {
-				modelsToAdd.push( model );
-			}
-		}, this );
-
-
-		// Add 'models' in a single batch, so the original add will only be called once (and thus 'sort', etc).
-		if ( modelsToAdd.length ) {
-			add.call( this, modelsToAdd, options );
-
-			_.each( modelsToAdd, function( model ) {
-				this.trigger( 'relational:add', model, this, options );
-			}, this );
-		}
-		
-		return this;
-	};
-	
-	/**
-	 * Override 'Backbone.Collection.remove' to trigger 'relational:remove'.
-	 */
-	var remove = Backbone.Collection.prototype.__remove = Backbone.Collection.prototype.remove;
-	Backbone.Collection.prototype.remove = function( models, options ) {
-		options || (options = {});
-		if ( !_.isArray( models ) ) {
-			models = [ models ];
-		}
-		else {
-			models = models.slice( 0 );
-		}
-
-		//console.debug('calling remove on coll=%o; models=%o, options=%o', this, models, options );
-		_.each( models, function( model ) {
-				model = this.getByCid( model ) || this.get( model );
-
-				if ( model instanceof Backbone.Model ) {
-					remove.call( this, model, options );
-					this.trigger('relational:remove', model, this, options);
-				}
-			}, this );
-		
-		return this;
-	};
-
-	/**
-	 * Override 'Backbone.Collection.reset' to trigger 'relational:reset'.
-	 */
-	var reset = Backbone.Collection.prototype.__reset = Backbone.Collection.prototype.reset;
-	Backbone.Collection.prototype.reset = function( models, options ) {
-		reset.call( this, models, options );
-		this.trigger( 'relational:reset', this, options );
-
-		return this;
-	};
-
-	/**
-	 * Override 'Backbone.Collection.sort' to trigger 'relational:reset'.
-	 */
-	var sort = Backbone.Collection.prototype.__sort = Backbone.Collection.prototype.sort;
-	Backbone.Collection.prototype.sort = function( options ) {
-		sort.call( this, options );
-		this.trigger( 'relational:reset', this, options );
-
-		return this;
-	};
-	
-	/**
-	 * Override 'Backbone.Collection.trigger' so 'add', 'remove' and 'reset' events are queued until relations
-	 * are ready.
-	 */
-	var trigger = Backbone.Collection.prototype.__trigger = Backbone.Collection.prototype.trigger;
-	Backbone.Collection.prototype.trigger = function( eventName ) {
-		if ( eventName === 'add' || eventName === 'remove' || eventName === 'reset' ) {
-			var dit = this, args = arguments;
-			
-			if (eventName === 'add') {
-				args = _.toArray(args);
-				// the fourth argument in case of a regular add is the option object.
-				// we need to clone it, as it could be modified while we wait on the eventQueue to be unblocked
-				if (_.isObject(args[3])) {
-					args[3] = _.clone(args[3]);
-				}
-			}
-			
-			Backbone.Relational.eventQueue.add( function() {
-					trigger.apply( dit, args );
-				});
-		}
-		else {
-			trigger.apply( this, arguments );
-		}
-		
-		return this;
-	};
-
-	// Override .extend() to automatically call .setup()
-	Backbone.RelationalModel.extend = function( protoProps, classProps ) {
-		var child = Backbone.Model.extend.apply( this, arguments );
-		
-		child.setup( this );
-
-		return child;
-	};
-})();
--- a/server/src/main/webapp/js/backbone.js	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1431 +0,0 @@
-//     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(){
-
-  // Initial Setup
-  // -------------
-
-  // Save a reference to the global object (`window` in the browser, `global`
-  // on the server).
-  var root = this;
-
-  // Save the previous value of the `Backbone` variable, so that it can be
-  // restored later on, if `noConflict` is used.
-  var previousBackbone = root.Backbone;
-
-  // Create a local reference to slice/splice.
-  var slice = Array.prototype.slice;
-  var splice = Array.prototype.splice;
-
-  // The top-level namespace. All public Backbone classes and modules will
-  // be attached to this. Exported for both CommonJS and the browser.
-  var Backbone;
-  if (typeof exports !== 'undefined') {
-    Backbone = exports;
-  } else {
-    Backbone = root.Backbone = {};
-  }
-
-  // Current version of the library. Keep in sync with `package.json`.
-  Backbone.VERSION = '0.9.2';
-
-  // Require Underscore, if we're on the server, and it's not already present.
-  var _ = root._;
-  if (!_ && (typeof require !== 'undefined')) _ = require('underscore');
-
-  // For Backbone's purposes, jQuery, Zepto, or Ender owns the `$` variable.
-  var $ = root.jQuery || root.Zepto || root.ender;
-
-  // Set the JavaScript library that will be used for DOM manipulation and
-  // Ajax calls (a.k.a. the `$` variable). By default Backbone will use: jQuery,
-  // Zepto, or Ender; but the `setDomLibrary()` method lets you inject an
-  // alternate JavaScript library (or a mock library for testing your views
-  // outside of a browser).
-  Backbone.setDomLibrary = function(lib) {
-    $ = lib;
-  };
-
-  // Runs Backbone.js in *noConflict* mode, returning the `Backbone` variable
-  // to its previous owner. Returns a reference to this Backbone object.
-  Backbone.noConflict = function() {
-    root.Backbone = previousBackbone;
-    return this;
-  };
-
-  // Turn on `emulateHTTP` to support legacy HTTP servers. Setting this option
-  // will fake `"PUT"` and `"DELETE"` requests via the `_method` parameter and
-  // set a `X-Http-Method-Override` header.
-  Backbone.emulateHTTP = false;
-
-  // Turn on `emulateJSON` to support legacy servers that can't deal with direct
-  // `application/json` requests ... will encode the body as
-  // `application/x-www-form-urlencoded` instead and will send the model in a
-  // form param named `model`.
-  Backbone.emulateJSON = false;
-
-  // Backbone.Events
-  // -----------------
-
-  // Regular expression used to split event strings
-  var eventSplitter = /\s+/;
-
-  // A module that can be mixed in to *any object* in order to provide it with
-  // custom events. You may bind with `on` or remove with `off` callback functions
-  // to an event; trigger`-ing an event fires all callbacks in succession.
-  //
-  //     var object = {};
-  //     _.extend(object, Backbone.Events);
-  //     object.on('expand', function(){ alert('expanded'); });
-  //     object.trigger('expand');
-  //
-  var Events = Backbone.Events = {
-
-    // Bind one or more space separated events, `events`, to a `callback`
-    // function. Passing `"all"` will bind the callback to all events fired.
-    on: function(events, callback, context) {
-
-      var calls, event, node, tail, list;
-      if (!callback) return this;
-      events = events.split(eventSplitter);
-      calls = this._callbacks || (this._callbacks = {});
-
-      // Create an immutable callback list, allowing traversal during
-      // modification.  The tail is an empty object that will always be used
-      // as the next node.
-      while (event = events.shift()) {
-        list = calls[event];
-        node = list ? list.tail : {};
-        node.next = tail = {};
-        node.context = context;
-        node.callback = callback;
-        calls[event] = {tail: tail, next: list ? list.next : node};
-      }
-
-      return this;
-    },
-
-    // Remove one or many callbacks. If `context` is null, removes all callbacks
-    // with that function. If `callback` is null, removes all callbacks for the
-    // event. If `events` is null, removes all bound callbacks for all events.
-    off: function(events, callback, context) {
-      var event, calls, node, tail, cb, ctx;
-
-      // No events, or removing *all* events.
-      if (!(calls = this._callbacks)) return;
-      if (!(events || callback || context)) {
-        delete this._callbacks;
-        return this;
-      }
-
-      // Loop through the listed events and contexts, splicing them out of the
-      // linked list of callbacks if appropriate.
-      events = events ? events.split(eventSplitter) : _.keys(calls);
-      while (event = events.shift()) {
-        node = calls[event];
-        delete calls[event];
-        if (!node || !(callback || context)) continue;
-        // Create a new list, omitting the indicated callbacks.
-        tail = node.tail;
-        while ((node = node.next) !== tail) {
-          cb = node.callback;
-          ctx = node.context;
-          if ((callback && cb !== callback) || (context && ctx !== context)) {
-            this.on(event, cb, ctx);
-          }
-        }
-      }
-
-      return this;
-    },
-
-    // Trigger one or many events, firing all bound callbacks. Callbacks are
-    // passed the same arguments as `trigger` is, apart from the event name
-    // (unless you're listening on `"all"`, which will cause your callback to
-    // receive the true name of the event as the first argument).
-    trigger: function(events) {
-      var event, node, calls, tail, args, all, rest;
-      if (!(calls = this._callbacks)) return this;
-      all = calls.all;
-      events = events.split(eventSplitter);
-      rest = slice.call(arguments, 1);
-
-      // For each event, walk through the linked list of callbacks twice,
-      // first to trigger the event, then to trigger any `"all"` callbacks.
-      while (event = events.shift()) {
-        if (node = calls[event]) {
-          tail = node.tail;
-          while ((node = node.next) !== tail) {
-            node.callback.apply(node.context || this, rest);
-          }
-        }
-        if (node = all) {
-          tail = node.tail;
-          args = [event].concat(rest);
-          while ((node = node.next) !== tail) {
-            node.callback.apply(node.context || this, args);
-          }
-        }
-      }
-
-      return this;
-    }
-
-  };
-
-  // Aliases for backwards compatibility.
-  Events.bind   = Events.on;
-  Events.unbind = Events.off;
-
-  // Backbone.Model
-  // --------------
-
-  // Create a new model, with defined attributes. A client id (`cid`)
-  // is automatically generated and assigned for you.
-  var Model = Backbone.Model = function(attributes, options) {
-    var defaults;
-    attributes || (attributes = {});
-    if (options && options.parse) attributes = this.parse(attributes);
-    if (defaults = getValue(this, 'defaults')) {
-      attributes = _.extend({}, defaults, attributes);
-    }
-    if (options && options.collection) this.collection = options.collection;
-    this.attributes = {};
-    this._escapedAttributes = {};
-    this.cid = _.uniqueId('c');
-    this.changed = {};
-    this._silent = {};
-    this._pending = {};
-    this.set(attributes, {silent: true});
-    // Reset change tracking.
-    this.changed = {};
-    this._silent = {};
-    this._pending = {};
-    this._previousAttributes = _.clone(this.attributes);
-    this.initialize.apply(this, arguments);
-  };
-
-  // Attach all inheritable methods to the Model prototype.
-  _.extend(Model.prototype, Events, {
-
-    // A hash of attributes whose current and previous value differ.
-    changed: null,
-
-    // A hash of attributes that have silently changed since the last time
-    // `change` was called.  Will become pending attributes on the next call.
-    _silent: null,
-
-    // A hash of attributes that have changed since the last `'change'` event
-    // began.
-    _pending: null,
-
-    // The default name for the JSON `id` attribute is `"id"`. MongoDB and
-    // CouchDB users may want to set this to `"_id"`.
-    idAttribute: 'id',
-
-    // Initialize is an empty function by default. Override it with your own
-    // initialization logic.
-    initialize: function(){},
-
-    // Return a copy of the model's `attributes` object.
-    toJSON: function(options) {
-      return _.clone(this.attributes);
-    },
-
-    // Get the value of an attribute.
-    get: function(attr) {
-      return this.attributes[attr];
-    },
-
-    // Get the HTML-escaped value of an attribute.
-    escape: function(attr) {
-      var html;
-      if (html = this._escapedAttributes[attr]) return html;
-      var val = this.get(attr);
-      return this._escapedAttributes[attr] = _.escape(val == null ? '' : '' + val);
-    },
-
-    // Returns `true` if the attribute contains a value that is not null
-    // or undefined.
-    has: function(attr) {
-      return this.get(attr) != null;
-    },
-
-    // Set a hash of model attributes on the object, firing `"change"` unless
-    // you choose to silence it.
-    set: function(key, value, options) {
-      var attrs, attr, val;
-
-      // Handle both `"key", value` and `{key: value}` -style arguments.
-      if (_.isObject(key) || key == null) {
-        attrs = key;
-        options = value;
-      } else {
-        attrs = {};
-        attrs[key] = value;
-      }
-
-      // Extract attributes and options.
-      options || (options = {});
-      if (!attrs) return this;
-      if (attrs instanceof Model) attrs = attrs.attributes;
-      if (options.unset) for (attr in attrs) attrs[attr] = void 0;
-
-      // Run validation.
-      if (!this._validate(attrs, options)) return false;
-
-      // Check for changes of `id`.
-      if (this.idAttribute in attrs) this.id = attrs[this.idAttribute];
-
-      var changes = options.changes = {};
-      var now = this.attributes;
-      var escaped = this._escapedAttributes;
-      var prev = this._previousAttributes || {};
-
-      // For each `set` attribute...
-      for (attr in attrs) {
-        val = attrs[attr];
-
-        // If the new and current value differ, record the change.
-        if (!_.isEqual(now[attr], val) || (options.unset && _.has(now, attr))) {
-          delete escaped[attr];
-          (options.silent ? this._silent : changes)[attr] = true;
-        }
-
-        // Update or delete the current value.
-        options.unset ? delete now[attr] : now[attr] = val;
-
-        // If the new and previous value differ, record the change.  If not,
-        // then remove changes for this attribute.
-        if (!_.isEqual(prev[attr], val) || (_.has(now, attr) != _.has(prev, attr))) {
-          this.changed[attr] = val;
-          if (!options.silent) this._pending[attr] = true;
-        } else {
-          delete this.changed[attr];
-          delete this._pending[attr];
-        }
-      }
-
-      // Fire the `"change"` events.
-      if (!options.silent) this.change(options);
-      return this;
-    },
-
-    // Remove an attribute from the model, firing `"change"` unless you choose
-    // to silence it. `unset` is a noop if the attribute doesn't exist.
-    unset: function(attr, options) {
-      (options || (options = {})).unset = true;
-      return this.set(attr, null, options);
-    },
-
-    // Clear all attributes on the model, firing `"change"` unless you choose
-    // to silence it.
-    clear: function(options) {
-      (options || (options = {})).unset = true;
-      return this.set(_.clone(this.attributes), options);
-    },
-
-    // Fetch the model from the server. If the server's representation of the
-    // model differs from its current attributes, they will be overriden,
-    // triggering a `"change"` event.
-    fetch: function(options) {
-      options = options ? _.clone(options) : {};
-      var model = this;
-      var success = options.success;
-      options.success = function(resp, status, xhr) {
-        if (!model.set(model.parse(resp, xhr), options)) return false;
-        if (success) success(model, resp);
-      };
-      options.error = Backbone.wrapError(options.error, model, options);
-      return (this.sync || Backbone.sync).call(this, 'read', this, options);
-    },
-
-    // Set a hash of model attributes, and sync the model to the server.
-    // If the server returns an attributes hash that differs, the model's
-    // state will be `set` again.
-    save: function(key, value, options) {
-      var attrs, current;
-
-      // Handle both `("key", value)` and `({key: value})` -style calls.
-      if (_.isObject(key) || key == null) {
-        attrs = key;
-        options = value;
-      } else {
-        attrs = {};
-        attrs[key] = value;
-      }
-      options = options ? _.clone(options) : {};
-
-      // If we're "wait"-ing to set changed attributes, validate early.
-      if (options.wait) {
-        if (!this._validate(attrs, options)) return false;
-        current = _.clone(this.attributes);
-      }
-
-      // Regular saves `set` attributes before persisting to the server.
-      var silentOptions = _.extend({}, options, {silent: true});
-      if (attrs && !this.set(attrs, options.wait ? silentOptions : options)) {
-        return false;
-      }
-
-      // After a successful server-side save, the client is (optionally)
-      // updated with the server-side state.
-      var model = this;
-      var success = options.success;
-      options.success = function(resp, status, xhr) {
-        var serverAttrs = model.parse(resp, xhr);
-        if (options.wait) {
-          delete options.wait;
-          serverAttrs = _.extend(attrs || {}, serverAttrs);
-        }
-        if (!model.set(serverAttrs, options)) return false;
-        if (success) {
-          success(model, resp);
-        } else {
-          model.trigger('sync', model, resp, options);
-        }
-      };
-
-      // Finish configuring and sending the Ajax request.
-      options.error = Backbone.wrapError(options.error, model, options);
-      var method = this.isNew() ? 'create' : 'update';
-      var xhr = (this.sync || Backbone.sync).call(this, method, this, options);
-      if (options.wait) this.set(current, silentOptions);
-      return xhr;
-    },
-
-    // Destroy this model on the server if it was already persisted.
-    // Optimistically removes the model from its collection, if it has one.
-    // If `wait: true` is passed, waits for the server to respond before removal.
-    destroy: function(options) {
-      options = options ? _.clone(options) : {};
-      var model = this;
-      var success = options.success;
-
-      var triggerDestroy = function() {
-        model.trigger('destroy', model, model.collection, options);
-      };
-
-      if (this.isNew()) {
-        triggerDestroy();
-        return false;
-      }
-
-      options.success = function(resp) {
-        if (options.wait) triggerDestroy();
-        if (success) {
-          success(model, resp);
-        } else {
-          model.trigger('sync', model, resp, options);
-        }
-      };
-
-      options.error = Backbone.wrapError(options.error, model, options);
-      var xhr = (this.sync || Backbone.sync).call(this, 'delete', this, options);
-      if (!options.wait) triggerDestroy();
-      return xhr;
-    },
-
-    // Default URL for the model's representation on the server -- if you're
-    // using Backbone's restful methods, override this to change the endpoint
-    // that will be called.
-    url: function() {
-      var base = getValue(this, 'urlRoot') || getValue(this.collection, 'url') || urlError();
-      if (this.isNew()) return base;
-      return base + (base.charAt(base.length - 1) == '/' ? '' : '/') + encodeURIComponent(this.id);
-    },
-
-    // **parse** converts a response into the hash of attributes to be `set` on
-    // the model. The default implementation is just to pass the response along.
-    parse: function(resp, xhr) {
-      return resp;
-    },
-
-    // Create a new model with identical attributes to this one.
-    clone: function() {
-      return new this.constructor(this.attributes);
-    },
-
-    // A model is new if it has never been saved to the server, and lacks an id.
-    isNew: function() {
-      return this.id == null;
-    },
-
-    // Call this method to manually fire a `"change"` event for this model and
-    // a `"change:attribute"` event for each changed attribute.
-    // Calling this will cause all objects observing the model to update.
-    change: function(options) {
-      options || (options = {});
-      var changing = this._changing;
-      this._changing = true;
-
-      // Silent changes become pending changes.
-      for (var attr in this._silent) this._pending[attr] = true;
-
-      // Silent changes are triggered.
-      var changes = _.extend({}, options.changes, this._silent);
-      this._silent = {};
-      for (var attr in changes) {
-        this.trigger('change:' + attr, this, this.get(attr), options);
-      }
-      if (changing) return this;
-
-      // Continue firing `"change"` events while there are pending changes.
-      while (!_.isEmpty(this._pending)) {
-        this._pending = {};
-        this.trigger('change', this, options);
-        // Pending and silent changes still remain.
-        for (var attr in this.changed) {
-          if (this._pending[attr] || this._silent[attr]) continue;
-          delete this.changed[attr];
-        }
-        this._previousAttributes = _.clone(this.attributes);
-      }
-
-      this._changing = false;
-      return this;
-    },
-
-    // Determine if the model has changed since the last `"change"` event.
-    // If you specify an attribute name, determine if that attribute has changed.
-    hasChanged: function(attr) {
-      if (!arguments.length) return !_.isEmpty(this.changed);
-      return _.has(this.changed, attr);
-    },
-
-    // Return an object containing all the attributes that have changed, or
-    // false if there are no changed attributes. Useful for determining what
-    // parts of a view need to be updated and/or what attributes need to be
-    // persisted to the server. Unset attributes will be set to undefined.
-    // You can also pass an attributes object to diff against the model,
-    // determining if there *would be* a change.
-    changedAttributes: function(diff) {
-      if (!diff) return this.hasChanged() ? _.clone(this.changed) : false;
-      var val, changed = false, old = this._previousAttributes;
-      for (var attr in diff) {
-        if (_.isEqual(old[attr], (val = diff[attr]))) continue;
-        (changed || (changed = {}))[attr] = val;
-      }
-      return changed;
-    },
-
-    // Get the previous value of an attribute, recorded at the time the last
-    // `"change"` event was fired.
-    previous: function(attr) {
-      if (!arguments.length || !this._previousAttributes) return null;
-      return this._previousAttributes[attr];
-    },
-
-    // Get all of the attributes of the model at the time of the previous
-    // `"change"` event.
-    previousAttributes: function() {
-      return _.clone(this._previousAttributes);
-    },
-
-    // Check if the model is currently in a valid state. It's only possible to
-    // get into an *invalid* state if you're using silent changes.
-    isValid: function() {
-      return !this.validate(this.attributes);
-    },
-
-    // Run validation against the next complete set of model attributes,
-    // returning `true` if all is well. If a specific `error` callback has
-    // been passed, call that instead of firing the general `"error"` event.
-    _validate: function(attrs, options) {
-      if (options.silent || !this.validate) return true;
-      attrs = _.extend({}, this.attributes, attrs);
-      var error = this.validate(attrs, options);
-      if (!error) return true;
-      if (options && options.error) {
-        options.error(this, error, options);
-      } else {
-        this.trigger('error', this, error, options);
-      }
-      return false;
-    }
-
-  });
-
-  // Backbone.Collection
-  // -------------------
-
-  // Provides a standard collection class for our sets of models, ordered
-  // or unordered. If a `comparator` is specified, the Collection will maintain
-  // its models in sort order, as they're added and removed.
-  var Collection = Backbone.Collection = function(models, options) {
-    options || (options = {});
-    if (options.model) this.model = options.model;
-    if (options.comparator) this.comparator = options.comparator;
-    this._reset();
-    this.initialize.apply(this, arguments);
-    if (models) this.reset(models, {silent: true, parse: options.parse});
-  };
-
-  // Define the Collection's inheritable methods.
-  _.extend(Collection.prototype, Events, {
-
-    // The default model for a collection is just a **Backbone.Model**.
-    // This should be overridden in most cases.
-    model: Model,
-
-    // Initialize is an empty function by default. Override it with your own
-    // initialization logic.
-    initialize: function(){},
-
-    // The JSON representation of a Collection is an array of the
-    // models' attributes.
-    toJSON: function(options) {
-      return this.map(function(model){ return model.toJSON(options); });
-    },
-
-    // Add a model, or list of models to the set. Pass **silent** to avoid
-    // firing the `add` event for every new model.
-    add: function(models, options) {
-      var i, index, length, model, cid, id, cids = {}, ids = {}, dups = [];
-      options || (options = {});
-      models = _.isArray(models) ? models.slice() : [models];
-
-      // Begin by turning bare objects into model references, and preventing
-      // invalid models or duplicate models from being added.
-      for (i = 0, length = models.length; i < length; i++) {
-        if (!(model = models[i] = this._prepareModel(models[i], options))) {
-          throw new Error("Can't add an invalid model to a collection");
-        }
-        cid = model.cid;
-        id = model.id;
-        if (cids[cid] || this._byCid[cid] || ((id != null) && (ids[id] || this._byId[id]))) {
-          dups.push(i);
-          continue;
-        }
-        cids[cid] = ids[id] = model;
-      }
-
-      // Remove duplicates.
-      i = dups.length;
-      while (i--) {
-        models.splice(dups[i], 1);
-      }
-
-      // Listen to added models' events, and index models for lookup by
-      // `id` and by `cid`.
-      for (i = 0, length = models.length; i < length; i++) {
-        (model = models[i]).on('all', this._onModelEvent, this);
-        this._byCid[model.cid] = model;
-        if (model.id != null) this._byId[model.id] = model;
-      }
-
-      // Insert models into the collection, re-sorting if needed, and triggering
-      // `add` events unless silenced.
-      this.length += length;
-      index = options.at != null ? options.at : this.models.length;
-      splice.apply(this.models, [index, 0].concat(models));
-      if (this.comparator) this.sort({silent: true});
-      if (options.silent) return this;
-      for (i = 0, length = this.models.length; i < length; i++) {
-        if (!cids[(model = this.models[i]).cid]) continue;
-        options.index = i;
-        model.trigger('add', model, this, options);
-      }
-      return this;
-    },
-
-    // Remove a model, or a list of models from the set. Pass silent to avoid
-    // firing the `remove` event for every model removed.
-    remove: function(models, options) {
-      var i, l, index, model;
-      options || (options = {});
-      models = _.isArray(models) ? models.slice() : [models];
-      for (i = 0, l = models.length; i < l; i++) {
-        model = this.getByCid(models[i]) || this.get(models[i]);
-        if (!model) continue;
-        delete this._byId[model.id];
-        delete this._byCid[model.cid];
-        index = this.indexOf(model);
-        this.models.splice(index, 1);
-        this.length--;
-        if (!options.silent) {
-          options.index = index;
-          model.trigger('remove', model, this, options);
-        }
-        this._removeReference(model);
-      }
-      return this;
-    },
-
-    // Add a model to the end of the collection.
-    push: function(model, options) {
-      model = this._prepareModel(model, options);
-      this.add(model, options);
-      return model;
-    },
-
-    // Remove a model from the end of the collection.
-    pop: function(options) {
-      var model = this.at(this.length - 1);
-      this.remove(model, options);
-      return model;
-    },
-
-    // Add a model to the beginning of the collection.
-    unshift: function(model, options) {
-      model = this._prepareModel(model, options);
-      this.add(model, _.extend({at: 0}, options));
-      return model;
-    },
-
-    // Remove a model from the beginning of the collection.
-    shift: function(options) {
-      var model = this.at(0);
-      this.remove(model, options);
-      return model;
-    },
-
-    // Get a model from the set by id.
-    get: function(id) {
-      if (id == null) return void 0;
-      return this._byId[id.id != null ? id.id : id];
-    },
-
-    // Get a model from the set by client id.
-    getByCid: function(cid) {
-      return cid && this._byCid[cid.cid || cid];
-    },
-
-    // Get the model at the given index.
-    at: function(index) {
-      return this.models[index];
-    },
-
-    // Return models with matching attributes. Useful for simple cases of `filter`.
-    where: function(attrs) {
-      if (_.isEmpty(attrs)) return [];
-      return this.filter(function(model) {
-        for (var key in attrs) {
-          if (attrs[key] !== model.get(key)) return false;
-        }
-        return true;
-      });
-    },
-
-    // Force the collection to re-sort itself. You don't need to call this under
-    // normal circumstances, as the set will maintain sort order as each item
-    // is added.
-    sort: function(options) {
-      options || (options = {});
-      if (!this.comparator) throw new Error('Cannot sort a set without a comparator');
-      var boundComparator = _.bind(this.comparator, this);
-      if (this.comparator.length == 1) {
-        this.models = this.sortBy(boundComparator);
-      } else {
-        this.models.sort(boundComparator);
-      }
-      if (!options.silent) this.trigger('reset', this, options);
-      return this;
-    },
-
-    // Pluck an attribute from each model in the collection.
-    pluck: function(attr) {
-      return _.map(this.models, function(model){ return model.get(attr); });
-    },
-
-    // When you have more items than you want to add or remove individually,
-    // you can reset the entire set with a new list of models, without firing
-    // any `add` or `remove` events. Fires `reset` when finished.
-    reset: function(models, options) {
-      models  || (models = []);
-      options || (options = {});
-      for (var i = 0, l = this.models.length; i < l; i++) {
-        this._removeReference(this.models[i]);
-      }
-      this._reset();
-      this.add(models, _.extend({silent: true}, options));
-      if (!options.silent) this.trigger('reset', this, options);
-      return this;
-    },
-
-    // Fetch the default set of models for this collection, resetting the
-    // collection when they arrive. If `add: true` is passed, appends the
-    // models to the collection instead of resetting.
-    fetch: function(options) {
-      options = options ? _.clone(options) : {};
-      if (options.parse === undefined) options.parse = true;
-      var collection = this;
-      var success = options.success;
-      options.success = function(resp, status, xhr) {
-        collection[options.add ? 'add' : 'reset'](collection.parse(resp, xhr), options);
-        if (success) success(collection, resp);
-      };
-      options.error = Backbone.wrapError(options.error, collection, options);
-      return (this.sync || Backbone.sync).call(this, 'read', this, options);
-    },
-
-    // Create a new instance of a model in this collection. Add the model to the
-    // collection immediately, unless `wait: true` is passed, in which case we
-    // wait for the server to agree.
-    create: function(model, options) {
-      var coll = this;
-      options = options ? _.clone(options) : {};
-      model = this._prepareModel(model, options);
-      if (!model) return false;
-      if (!options.wait) coll.add(model, options);
-      var success = options.success;
-      options.success = function(nextModel, resp, xhr) {
-        if (options.wait) coll.add(nextModel, options);
-        if (success) {
-          success(nextModel, resp);
-        } else {
-          nextModel.trigger('sync', model, resp, options);
-        }
-      };
-      model.save(null, options);
-      return model;
-    },
-
-    // **parse** converts a response into a list of models to be added to the
-    // collection. The default implementation is just to pass it through.
-    parse: function(resp, xhr) {
-      return resp;
-    },
-
-    // Proxy to _'s chain. Can't be proxied the same way the rest of the
-    // underscore methods are proxied because it relies on the underscore
-    // constructor.
-    chain: function () {
-      return _(this.models).chain();
-    },
-
-    // Reset all internal state. Called when the collection is reset.
-    _reset: function(options) {
-      this.length = 0;
-      this.models = [];
-      this._byId  = {};
-      this._byCid = {};
-    },
-
-    // Prepare a model or hash of attributes to be added to this collection.
-    _prepareModel: function(model, options) {
-      options || (options = {});
-      if (!(model instanceof Model)) {
-        var attrs = model;
-        options.collection = this;
-        model = new this.model(attrs, options);
-        if (!model._validate(model.attributes, options)) model = false;
-      } else if (!model.collection) {
-        model.collection = this;
-      }
-      return model;
-    },
-
-    // Internal method to remove a model's ties to a collection.
-    _removeReference: function(model) {
-      if (this == model.collection) {
-        delete model.collection;
-      }
-      model.off('all', this._onModelEvent, this);
-    },
-
-    // Internal method called every time a model in the set fires an event.
-    // Sets need to update their indexes when models change ids. All other
-    // events simply proxy through. "add" and "remove" events that originate
-    // in other collections are ignored.
-    _onModelEvent: function(event, model, collection, options) {
-      if ((event == 'add' || event == 'remove') && collection != this) return;
-      if (event == 'destroy') {
-        this.remove(model, options);
-      }
-      if (model && event === 'change:' + model.idAttribute) {
-        delete this._byId[model.previous(model.idAttribute)];
-        this._byId[model.id] = model;
-      }
-      this.trigger.apply(this, arguments);
-    }
-
-  });
-
-  // Underscore methods that we want to implement on the Collection.
-  var methods = ['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'];
-
-  // Mix in each Underscore method as a proxy to `Collection#models`.
-  _.each(methods, function(method) {
-    Collection.prototype[method] = function() {
-      return _[method].apply(_, [this.models].concat(_.toArray(arguments)));
-    };
-  });
-
-  // Backbone.Router
-  // -------------------
-
-  // Routers map faux-URLs to actions, and fire events when routes are
-  // matched. Creating a new one sets its `routes` hash, if not set statically.
-  var Router = Backbone.Router = function(options) {
-    options || (options = {});
-    if (options.routes) this.routes = options.routes;
-    this._bindRoutes();
-    this.initialize.apply(this, arguments);
-  };
-
-  // Cached regular expressions for matching named param parts and splatted
-  // parts of route strings.
-  var namedParam    = /:\w+/g;
-  var splatParam    = /\*\w+/g;
-  var escapeRegExp  = /[-[\]{}()+?.,\\^$|#\s]/g;
-
-  // Set up all inheritable **Backbone.Router** properties and methods.
-  _.extend(Router.prototype, Events, {
-
-    // Initialize is an empty function by default. Override it with your own
-    // initialization logic.
-    initialize: function(){},
-
-    // Manually bind a single named route to a callback. For example:
-    //
-    //     this.route('search/:query/p:num', 'search', function(query, num) {
-    //       ...
-    //     });
-    //
-    route: function(route, name, callback) {
-      Backbone.history || (Backbone.history = new History);
-      if (!_.isRegExp(route)) route = this._routeToRegExp(route);
-      if (!callback) callback = this[name];
-      Backbone.history.route(route, _.bind(function(fragment) {
-        var args = this._extractParameters(route, fragment);
-        callback && callback.apply(this, args);
-        this.trigger.apply(this, ['route:' + name].concat(args));
-        Backbone.history.trigger('route', this, name, args);
-      }, this));
-      return this;
-    },
-
-    // Simple proxy to `Backbone.history` to save a fragment into the history.
-    navigate: function(fragment, options) {
-      Backbone.history.navigate(fragment, options);
-    },
-
-    // Bind all defined routes to `Backbone.history`. We have to reverse the
-    // order of the routes here to support behavior where the most general
-    // routes can be defined at the bottom of the route map.
-    _bindRoutes: function() {
-      if (!this.routes) return;
-      var routes = [];
-      for (var route in this.routes) {
-        routes.unshift([route, this.routes[route]]);
-      }
-      for (var i = 0, l = routes.length; i < l; i++) {
-        this.route(routes[i][0], routes[i][1], this[routes[i][1]]);
-      }
-    },
-
-    // Convert a route string into a regular expression, suitable for matching
-    // against the current location hash.
-    _routeToRegExp: function(route) {
-      route = route.replace(escapeRegExp, '\\$&')
-                   .replace(namedParam, '([^\/]+)')
-                   .replace(splatParam, '(.*?)');
-      return new RegExp('^' + route + '$');
-    },
-
-    // Given a route, and a URL fragment that it matches, return the array of
-    // extracted parameters.
-    _extractParameters: function(route, fragment) {
-      return route.exec(fragment).slice(1);
-    }
-
-  });
-
-  // Backbone.History
-  // ----------------
-
-  // Handles cross-browser history management, based on URL fragments. If the
-  // browser does not support `onhashchange`, falls back to polling.
-  var History = Backbone.History = function() {
-    this.handlers = [];
-    _.bindAll(this, 'checkUrl');
-  };
-
-  // Cached regex for cleaning leading hashes and slashes .
-  var routeStripper = /^[#\/]/;
-
-  // Cached regex for detecting MSIE.
-  var isExplorer = /msie [\w.]+/;
-
-  // Has the history handling already been started?
-  History.started = false;
-
-  // Set up all inheritable **Backbone.History** properties and methods.
-  _.extend(History.prototype, Events, {
-
-    // The default interval to poll for hash changes, if necessary, is
-    // twenty times a second.
-    interval: 50,
-
-    // Gets the true hash value. Cannot use location.hash directly due to bug
-    // in Firefox where location.hash will always be decoded.
-    getHash: function(windowOverride) {
-      var loc = windowOverride ? windowOverride.location : window.location;
-      var match = loc.href.match(/#(.*)$/);
-      return match ? match[1] : '';
-    },
-
-    // Get the cross-browser normalized URL fragment, either from the URL,
-    // the hash, or the override.
-    getFragment: function(fragment, forcePushState) {
-      if (fragment == null) {
-        if (this._hasPushState || forcePushState) {
-          fragment = window.location.pathname;
-          var search = window.location.search;
-          if (search) fragment += search;
-        } else {
-          fragment = this.getHash();
-        }
-      }
-      if (!fragment.indexOf(this.options.root)) fragment = fragment.substr(this.options.root.length);
-      return fragment.replace(routeStripper, '');
-    },
-
-    // Start the hash change handling, returning `true` if the current URL matches
-    // an existing route, and `false` otherwise.
-    start: function(options) {
-      if (History.started) throw new Error("Backbone.history has already been started");
-      History.started = true;
-
-      // Figure out the initial configuration. Do we need an iframe?
-      // Is pushState desired ... is it available?
-      this.options          = _.extend({}, {root: '/'}, this.options, options);
-      this._wantsHashChange = this.options.hashChange !== false;
-      this._wantsPushState  = !!this.options.pushState;
-      this._hasPushState    = !!(this.options.pushState && window.history && window.history.pushState);
-      var fragment          = this.getFragment();
-      var docMode           = document.documentMode;
-      var oldIE             = (isExplorer.exec(navigator.userAgent.toLowerCase()) && (!docMode || docMode <= 7));
-
-      if (oldIE) {
-        this.iframe = $('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo('body')[0].contentWindow;
-        this.navigate(fragment);
-      }
-
-      // Depending on whether we're using pushState or hashes, and whether
-      // 'onhashchange' is supported, determine how we check the URL state.
-      if (this._hasPushState) {
-        $(window).bind('popstate', this.checkUrl);
-      } else if (this._wantsHashChange && ('onhashchange' in window) && !oldIE) {
-        $(window).bind('hashchange', this.checkUrl);
-      } else if (this._wantsHashChange) {
-        this._checkUrlInterval = setInterval(this.checkUrl, this.interval);
-      }
-
-      // Determine if we need to change the base url, for a pushState link
-      // opened by a non-pushState browser.
-      this.fragment = fragment;
-      var loc = window.location;
-      var atRoot  = loc.pathname == this.options.root;
-
-      // If we've started off with a route from a `pushState`-enabled browser,
-      // but we're currently in a browser that doesn't support it...
-      if (this._wantsHashChange && this._wantsPushState && !this._hasPushState && !atRoot) {
-        this.fragment = this.getFragment(null, true);
-        window.location.replace(this.options.root + '#' + this.fragment);
-        // Return immediately as browser will do redirect to new url
-        return true;
-
-      // Or if we've started out with a hash-based route, but we're currently
-      // in a browser where it could be `pushState`-based instead...
-      } else if (this._wantsPushState && this._hasPushState && atRoot && loc.hash) {
-        this.fragment = this.getHash().replace(routeStripper, '');
-        window.history.replaceState({}, document.title, loc.protocol + '//' + loc.host + this.options.root + this.fragment);
-      }
-
-      if (!this.options.silent) {
-        return this.loadUrl();
-      }
-    },
-
-    // Disable Backbone.history, perhaps temporarily. Not useful in a real app,
-    // but possibly useful for unit testing Routers.
-    stop: function() {
-      $(window).unbind('popstate', this.checkUrl).unbind('hashchange', this.checkUrl);
-      clearInterval(this._checkUrlInterval);
-      History.started = false;
-    },
-
-    // Add a route to be tested when the fragment changes. Routes added later
-    // may override previous routes.
-    route: function(route, callback) {
-      this.handlers.unshift({route: route, callback: callback});
-    },
-
-    // Checks the current URL to see if it has changed, and if it has,
-    // calls `loadUrl`, normalizing across the hidden iframe.
-    checkUrl: function(e) {
-      var current = this.getFragment();
-      if (current == this.fragment && this.iframe) current = this.getFragment(this.getHash(this.iframe));
-      if (current == this.fragment) return false;
-      if (this.iframe) this.navigate(current);
-      this.loadUrl() || this.loadUrl(this.getHash());
-    },
-
-    // Attempt to load the current URL fragment. If a route succeeds with a
-    // match, returns `true`. If no defined routes matches the fragment,
-    // returns `false`.
-    loadUrl: function(fragmentOverride) {
-      var fragment = this.fragment = this.getFragment(fragmentOverride);
-      var matched = _.any(this.handlers, function(handler) {
-        if (handler.route.test(fragment)) {
-          handler.callback(fragment);
-          return true;
-        }
-      });
-      return matched;
-    },
-
-    // Save a fragment into the hash history, or replace the URL state if the
-    // 'replace' option is passed. You are responsible for properly URL-encoding
-    // the fragment in advance.
-    //
-    // The options object can contain `trigger: true` if you wish to have the
-    // route callback be fired (not usually desirable), or `replace: true`, if
-    // you wish to modify the current URL without adding an entry to the history.
-    navigate: function(fragment, options) {
-      if (!History.started) return false;
-      if (!options || options === true) options = {trigger: options};
-      var frag = (fragment || '').replace(routeStripper, '');
-      if (this.fragment == frag) return;
-
-      // If pushState is available, we use it to set the fragment as a real URL.
-      if (this._hasPushState) {
-        if (frag.indexOf(this.options.root) != 0) frag = this.options.root + frag;
-        this.fragment = frag;
-        window.history[options.replace ? 'replaceState' : 'pushState']({}, document.title, frag);
-
-      // If hash changes haven't been explicitly disabled, update the hash
-      // fragment to store history.
-      } else if (this._wantsHashChange) {
-        this.fragment = frag;
-        this._updateHash(window.location, frag, options.replace);
-        if (this.iframe && (frag != this.getFragment(this.getHash(this.iframe)))) {
-          // Opening and closing the iframe tricks IE7 and earlier to push a history entry on hash-tag change.
-          // When replace is true, we don't want this.
-          if(!options.replace) this.iframe.document.open().close();
-          this._updateHash(this.iframe.location, frag, options.replace);
-        }
-
-      // If you've told us that you explicitly don't want fallback hashchange-
-      // based history, then `navigate` becomes a page refresh.
-      } else {
-        window.location.assign(this.options.root + fragment);
-      }
-      if (options.trigger) this.loadUrl(fragment);
-    },
-
-    // Update the hash location, either replacing the current entry, or adding
-    // a new one to the browser history.
-    _updateHash: function(location, fragment, replace) {
-      if (replace) {
-        location.replace(location.toString().replace(/(javascript:|#).*$/, '') + '#' + fragment);
-      } else {
-        location.hash = fragment;
-      }
-    }
-  });
-
-  // Backbone.View
-  // -------------
-
-  // Creating a Backbone.View creates its initial element outside of the DOM,
-  // if an existing element is not provided...
-  var View = Backbone.View = function(options) {
-    this.cid = _.uniqueId('view');
-    this._configure(options || {});
-    this._ensureElement();
-    this.initialize.apply(this, arguments);
-    this.delegateEvents();
-  };
-
-  // Cached regex to split keys for `delegate`.
-  var delegateEventSplitter = /^(\S+)\s*(.*)$/;
-
-  // List of view options to be merged as properties.
-  var viewOptions = ['model', 'collection', 'el', 'id', 'attributes', 'className', 'tagName'];
-
-  // Set up all inheritable **Backbone.View** properties and methods.
-  _.extend(View.prototype, Events, {
-
-    // The default `tagName` of a View's element is `"div"`.
-    tagName: 'div',
-
-    // jQuery delegate for element lookup, scoped to DOM elements within the
-    // current view. This should be prefered to global lookups where possible.
-    $: function(selector) {
-      return this.$el.find(selector);
-    },
-
-    // Initialize is an empty function by default. Override it with your own
-    // initialization logic.
-    initialize: function(){},
-
-    // **render** is the core function that your view should override, in order
-    // to populate its element (`this.el`), with the appropriate HTML. The
-    // convention is for **render** to always return `this`.
-    render: function() {
-      return this;
-    },
-
-    // Remove this view from the DOM. Note that the view isn't present in the
-    // DOM by default, so calling this method may be a no-op.
-    remove: function() {
-      this.$el.remove();
-      return this;
-    },
-
-    // For small amounts of DOM Elements, where a full-blown template isn't
-    // needed, use **make** to manufacture elements, one at a time.
-    //
-    //     var el = this.make('li', {'class': 'row'}, this.model.escape('title'));
-    //
-    make: function(tagName, attributes, content) {
-      var el = document.createElement(tagName);
-      if (attributes) $(el).attr(attributes);
-      if (content) $(el).html(content);
-      return el;
-    },
-
-    // Change the view's element (`this.el` property), including event
-    // re-delegation.
-    setElement: function(element, delegate) {
-      if (this.$el) this.undelegateEvents();
-      this.$el = (element instanceof $) ? element : $(element);
-      this.el = this.$el[0];
-      if (delegate !== false) this.delegateEvents();
-      return this;
-    },
-
-    // Set callbacks, where `this.events` is a hash of
-    //
-    // *{"event selector": "callback"}*
-    //
-    //     {
-    //       'mousedown .title':  'edit',
-    //       'click .button':     'save'
-    //       'click .open':       function(e) { ... }
-    //     }
-    //
-    // pairs. Callbacks will be bound to the view, with `this` set properly.
-    // Uses event delegation for efficiency.
-    // Omitting the selector binds the event to `this.el`.
-    // This only works for delegate-able events: not `focus`, `blur`, and
-    // not `change`, `submit`, and `reset` in Internet Explorer.
-    delegateEvents: function(events) {
-      if (!(events || (events = getValue(this, 'events')))) return;
-      this.undelegateEvents();
-      for (var key in events) {
-        var method = events[key];
-        if (!_.isFunction(method)) method = this[events[key]];
-        if (!method) throw new Error('Method "' + events[key] + '" does not exist');
-        var match = key.match(delegateEventSplitter);
-        var eventName = match[1], selector = match[2];
-        method = _.bind(method, this);
-        eventName += '.delegateEvents' + this.cid;
-        if (selector === '') {
-          this.$el.bind(eventName, method);
-        } else {
-          this.$el.delegate(selector, eventName, method);
-        }
-      }
-    },
-
-    // Clears all callbacks previously bound to the view with `delegateEvents`.
-    // You usually don't need to use this, but may wish to if you have multiple
-    // Backbone views attached to the same DOM element.
-    undelegateEvents: function() {
-      this.$el.unbind('.delegateEvents' + this.cid);
-    },
-
-    // Performs the initial configuration of a View with a set of options.
-    // Keys with special meaning *(model, collection, id, className)*, are
-    // attached directly to the view.
-    _configure: function(options) {
-      if (this.options) options = _.extend({}, this.options, options);
-      for (var i = 0, l = viewOptions.length; i < l; i++) {
-        var attr = viewOptions[i];
-        if (options[attr]) this[attr] = options[attr];
-      }
-      this.options = options;
-    },
-
-    // Ensure that the View has a DOM element to render into.
-    // If `this.el` is a string, pass it through `$()`, take the first
-    // matching element, and re-assign it to `el`. Otherwise, create
-    // an element from the `id`, `className` and `tagName` properties.
-    _ensureElement: function() {
-      if (!this.el) {
-        var attrs = getValue(this, 'attributes') || {};
-        if (this.id) attrs.id = this.id;
-        if (this.className) attrs['class'] = this.className;
-        this.setElement(this.make(this.tagName, attrs), false);
-      } else {
-        this.setElement(this.el, false);
-      }
-    }
-
-  });
-
-  // The self-propagating extend function that Backbone classes use.
-  var extend = function (protoProps, classProps) {
-    var child = inherits(this, protoProps, classProps);
-    child.extend = this.extend;
-    return child;
-  };
-
-  // Set up inheritance for the model, collection, and view.
-  Model.extend = Collection.extend = Router.extend = View.extend = extend;
-
-  // Backbone.sync
-  // -------------
-
-  // Map from CRUD to HTTP for our default `Backbone.sync` implementation.
-  var methodMap = {
-    'create': 'POST',
-    'update': 'PUT',
-    'delete': 'DELETE',
-    'read':   'GET'
-  };
-
-  // Override this function to change the manner in which Backbone persists
-  // models to the server. You will be passed the type of request, and the
-  // model in question. By default, makes a RESTful Ajax request
-  // to the model's `url()`. Some possible customizations could be:
-  //
-  // * Use `setTimeout` to batch rapid-fire updates into a single request.
-  // * Send up the models as XML instead of JSON.
-  // * Persist models via WebSockets instead of Ajax.
-  //
-  // Turn on `Backbone.emulateHTTP` in order to send `PUT` and `DELETE` requests
-  // as `POST`, with a `_method` parameter containing the true HTTP method,
-  // as well as all requests with the body as `application/x-www-form-urlencoded`
-  // instead of `application/json` with the model in a param named `model`.
-  // Useful when interfacing with server-side languages like **PHP** that make
-  // it difficult to read the body of `PUT` requests.
-  Backbone.sync = function(method, model, options) {
-    var type = methodMap[method];
-
-    // Default options, unless specified.
-    options || (options = {});
-
-    // Default JSON-request options.
-    var params = {type: type, dataType: 'json'};
-
-    // Ensure that we have a URL.
-    if (!options.url) {
-      params.url = getValue(model, 'url') || urlError();
-    }
-
-    // Ensure that we have the appropriate request data.
-    if (!options.data && model && (method == 'create' || method == 'update')) {
-      params.contentType = 'application/json';
-      params.data = JSON.stringify(model.toJSON());
-    }
-
-    // For older servers, emulate JSON by encoding the request into an HTML-form.
-    if (Backbone.emulateJSON) {
-      params.contentType = 'application/x-www-form-urlencoded';
-      params.data = params.data ? {model: params.data} : {};
-    }
-
-    // For older servers, emulate HTTP by mimicking the HTTP method with `_method`
-    // And an `X-HTTP-Method-Override` header.
-    if (Backbone.emulateHTTP) {
-      if (type === 'PUT' || type === 'DELETE') {
-        if (Backbone.emulateJSON) params.data._method = type;
-        params.type = 'POST';
-        params.beforeSend = function(xhr) {
-          xhr.setRequestHeader('X-HTTP-Method-Override', type);
-        };
-      }
-    }
-
-    // Don't process data on a non-GET request.
-    if (params.type !== 'GET' && !Backbone.emulateJSON) {
-      params.processData = false;
-    }
-
-    // Make the request, allowing the user to override any Ajax options.
-    return $.ajax(_.extend(params, options));
-  };
-
-  // Wrap an optional error callback with a fallback error event.
-  Backbone.wrapError = function(onError, originalModel, options) {
-    return function(model, resp) {
-      resp = model === originalModel ? resp : model;
-      if (onError) {
-        onError(originalModel, resp, options);
-      } else {
-        originalModel.trigger('error', originalModel, resp, options);
-      }
-    };
-  };
-
-  // Helpers
-  // -------
-
-  // Shared empty constructor function to aid in prototype-chain creation.
-  var ctor = function(){};
-
-  // Helper function to correctly set up the prototype chain, for subclasses.
-  // Similar to `goog.inherits`, but uses a hash of prototype properties and
-  // class properties to be extended.
-  var inherits = function(parent, protoProps, staticProps) {
-    var child;
-
-    // The constructor function for the new subclass is either defined by you
-    // (the "constructor" property in your `extend` definition), or defaulted
-    // by us to simply call the parent's constructor.
-    if (protoProps && protoProps.hasOwnProperty('constructor')) {
-      child = protoProps.constructor;
-    } else {
-      child = function(){ parent.apply(this, arguments); };
-    }
-
-    // Inherit class (static) properties from parent.
-    _.extend(child, parent);
-
-    // Set the prototype chain to inherit from `parent`, without calling
-    // `parent`'s constructor function.
-    ctor.prototype = parent.prototype;
-    child.prototype = new ctor();
-
-    // Add prototype properties (instance properties) to the subclass,
-    // if supplied.
-    if (protoProps) _.extend(child.prototype, protoProps);
-
-    // Add static properties to the constructor function, if supplied.
-    if (staticProps) _.extend(child, staticProps);
-
-    // Correctly set child's `prototype.constructor`.
-    child.prototype.constructor = child;
-
-    // Set a convenience property in case the parent's prototype is needed later.
-    child.__super__ = parent.prototype;
-
-    return child;
-  };
-
-  // Helper function to get a value from a Backbone object as a property
-  // or as a function.
-  var getValue = function(object, prop) {
-    if (!(object && object[prop])) return null;
-    return _.isFunction(object[prop]) ? object[prop]() : object[prop];
-  };
-
-  // Throw an error when a URL is needed, and none is supplied.
-  var urlError = function() {
-    throw new Error('A "url" property or function must be specified');
-  };
-
-}).call(this);
--- a/server/src/main/webapp/js/config.js	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-//
-// Config file. Split out from the app for ease of overlaying a new config
-// without affecting the app controller.
-//
-// Copyright (c) The Dojo Foundation 2011. All Rights Reserved.
-//
-var dojoConfig = {
-	baseUrl: '/renkan',
-	async:true,
-	paths : {
-	   coweb : 'lib/coweb',
-	   cowebx: 'lib/cowebx',
-	   org : 'lib/org',
-	   corenkan: 'js/corenkan',
-	},
-	/*packages:[{
-		name: 'dojo',
-		location:'lib/dojo',
-		main:'main'
-	},
-	{
-		name: 'dijit',
-		location:'lib/dijit',
-		main:'main'
-	},
-	{
-		name: 'dojox',
-		location:'lib/dojox',
-		main:'main'
-	}]*/
-};
-
--- a/server/src/main/webapp/js/corenkan.js	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,249 +0,0 @@
-define([
-    "dojo",
-    "coweb/main"
-], function(dojo, coweb) {
-
-    var CoRenkanApp = function() {
-    };
-
-    var proto = CoRenkanApp.prototype;
-
-    proto.init = function() {
-    	console.log("ready callback");
-    	
-    	//this.initCollab();
-    	
-    	var sess = coweb.initSession();
-    	sess.onStatusChange = function(status) {
-    	    console.log(status);
-    	};
-    	sess.prepare();
-    	this.project = null;
-                
-    };
-    
-    proto.initCollab = function(id) {    	
-    	this.collab = coweb.initCollab({id : id});
-    	this.collab.subscribeSync("project", this, "onRemoteProjectChange");    	
-    };
-    
-    function prepareValues(obj,c) {
-		values = {};
-		for(var fieldname in c.changes) {
-			if(c.changes[fieldname]) {
-				values[fieldname] = obj.get(fieldname);
-			}    			
-		}
-		return values;
-    }
-    
-    proto.setProject = function(project) {
-    	
-    	var projectFields = ["title", "description", "uri"];
-    	var that = this;
-    	for(var fieldIndex in projectFields) {
-    		(function(fi){
-	    		var field = projectFields[fi];
-	        	project.bind("change:"+field, function(obj, c) {
-	        		console.log(c);
-	        		values = {
-	        		    id: obj.id,
-	        		    type: "project",
-	        		    project_id: obj.id
-	        		};
-	        		values[field] = c;
-	        		that.collab.sendSync("project", values);
-	        	});
-    		})(fieldIndex);
-    	}
-    	project.get("nodes").bind("add", function(obj, c, options) {
-    		console.log("add nodes",obj, c, options);
-    		values = obj.toJSON();
-    		new_values = {
-    			id: obj.id,
-    			type: "node",
-    			index: options.index,
-    			project_id : obj.get("project").id
-    		};
-    		for(var k in new_values) {
-    			values[k] = new_values[k];
-    		}
-    		that.collab.sendSync("node", values, "insert", options.index);
-    	});
-    	project.get("nodes").bind("remove", function(obj, c, options) {
-    		console.log("delete nodes",obj, c, options);
-    		values = {
-        	    id: obj.id,
-        	    type: "node",
-        	    index: options.index,
-        	    project_id : obj.get("project").id
-        	};
-    		that.collab.sendSync("node", values, "delete", options.index);
-    	});
-    	project.get("nodes").bind("change", function(obj, c) {
-    		console.log("change nodes",obj, c);
-    		values = {
-    		    id: obj.id,
-        	    type: "node",
-        	    project_id : obj.get("project").id
-        	};
-    		for(var f in c) {
-    			if(c[f]) {
-    				values[f] = obj.get(f);
-    			}
-    		}
-        	that.collab.sendSync("node", values);
-    	});
-    	this.project = project;
-    	this.initCollab(project.id);
-    };
-    
-    
-    /**
-     * Called when a remote data store for project changes in some manner. Dispatches to
-     * local methods for insert, update, delete handling.
-     * TODO: manage project list change on server
-     * @param args Cooperative web event
-     */
-    proto.onRemoteProjectChange = function(args) {    	
-    	console.log(args);
-    	if (args.type === "update") {
-            this.onRemoteProjectUpdate(args.value, args.position);
-    	}
-        /*if (args.type === "insert") {
-            this.onRemoteInsert(value, args.position);
-        } else if (args.type === "update") {
-            this.onRemoteUpdate(value, args.position);
-        } else if (args.type === "delete") {
-            this.onRemoteDelete(args.position);
-        }*/
-    };
-    
-
-    /**
-     * Called when a remote data store for nodes changes in some manner. Dispatches to
-     * local methods for insert, update, delete handling.
-     * @param args Cooperative web event
-     */
-    proto.onRemoteNodeChange = function(args) {    	
-    	console.log(args);
-        if (args.type === "insert") {
-            this.onRemoteNodeInsert(value, args.position);
-        } else if (args.type === "update") {
-            this.onRemoteNodeUpdate(value, args.position);
-        } else if (args.type === "delete") {
-            this.onRemoteNodeDelete(args.position);
-        }
-    };
-
-    
-    
-    /**
-     * Called when a project attribute changes value in a remote data store.
-     * Updates the attribute value of the item with the same id in the local
-     * data store.
-     *
-     * @param value Item data sent by remote data store
-     * @param position Which item to update.
-     */
-    proto.onRemoteProjectUpdate = function(values, position) {
-    	var project_id = values['id'];
-    	if(typeof(project_id) === "undefined") {
-    		return;
-		}
-    	
-    	if(this.project != null && project_id == this.project.id) {
-    		for(var fieldname in values) {
-    			if(fieldname != "id" && fieldname != "type") {
-    				this.project.set(fieldname, values[fieldname]);
-    			}
-    		}
-    	}
-    	
-    };
-    
-
-    
-    /**
-     * Called when a node attribute changes value in a remote data store.
-     * Updates the attribute value of the item with the same id in the local
-     * data store.
-     *
-     * @param value Item data sent by remote data store
-     * @param position Which item to update.
-     */
-    proto.onRemoteNodeInsert = function(values, position) {
-    	var project_id = values['project_id'];
-    	if(typeof(project_id) === "undefined") {
-    		return;
-		}
-    	
-    	if(this.project != null && project_id == this.project.id) {
-    		for(var fieldname in values) {
-    			if(fieldname != "id" && fieldname != "type") {
-    				this.project.set(fieldname, values[fieldname]);
-    			}
-    		}
-    	}
-    	
-    };
-    
-    /**
-     * Called when a node attribute changes value in a remote data store.
-     * Updates the attribute value of the item with the same id in the local
-     * data store.
-     *
-     * @param value Item data sent by remote data store
-     * @param position Which item to update.
-     */
-    proto.onRemoteNodeUpdate = function(values, position) {
-    	var project_id = values['project_id'];
-    	if(typeof(project_id) === "undefined") {
-    		return;
-		}
-    	
-    	if(this.project != null && project_id == this.project.id) {
-    		for(var fieldname in values) {
-    			if(fieldname != "id" && fieldname != "type") {
-    				this.project.set(fieldname, values[fieldname]);
-    			}
-    		}
-    	}
-    	
-    };
-    
-    
-    /**
-     * Called when a node attribute changes value in a remote data store.
-     * Updates the attribute value of the item with the same id in the local
-     * data store.
-     *
-     * @param value Item data sent by remote data store
-     * @param position Which item to update.
-     */
-    proto.onRemoteNodeDelete = function(position) {
-    	var project_id = values['id'];
-    	if(typeof(project_id) === "undefined") {
-    		return;
-		}
-    	
-    	if(this.project != null && project_id == this.project.id) {
-    		for(var fieldname in values) {
-    			if(fieldname != "id" && fieldname != "type") {
-    				this.project.set(fieldname, values[fieldname]);
-    			}
-    		}
-    	}
-    	
-    };
-        
-    var app = new CoRenkanApp();
-    dojo.ready(function() {
-        app.init();
-    });
-    
-    
-    return {
-    	app: app
-    };
-});
\ No newline at end of file
--- a/server/src/main/webapp/js/dojo.js	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,15 +0,0 @@
-/*
-	Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
-	Available via Academic Free License >= 2.1 OR the modified BSD license.
-	see: http://dojotoolkit.org/license for details
-*/
-
-/*
-	This is an optimized version of Dojo, built for deployment and not for
-	development. To get sources and documentation, please visit:
-
-		http://dojotoolkit.org
-*/
-
-//>>built
-(function(_1,_2){var _3=function(){},_4=function(it){for(var p in it){return 0;}return 1;},_5={}.toString,_6=function(it){return _5.call(it)=="[object Function]";},_7=function(it){return _5.call(it)=="[object String]";},_8=function(it){return _5.call(it)=="[object Array]";},_9=function(_a,_b){if(_a){for(var i=0;i<_a.length;){_b(_a[i++]);}}},_c=function(_d,_e){for(var p in _e){_d[p]=_e[p];}return _d;},_f=function(_10,_11){return _c(new Error(_10),{src:"dojoLoader",info:_11});},_12=1,uid=function(){return "_"+_12++;},req=function(_13,_14,_15){return _16(_13,_14,_15,0,req);},_17=this,doc=_17.document,_18=doc&&doc.createElement("DiV"),has=req.has=function(_19){return _6(_1a[_19])?(_1a[_19]=_1a[_19](_17,doc,_18)):_1a[_19];},_1a=has.cache=_2.hasCache;has.add=function(_1b,_1c,now,_1d){(_1a[_1b]===undefined||_1d)&&(_1a[_1b]=_1c);return now&&has(_1b);};0&&has.add("host-node",_1.has&&"host-node" in _1.has?_1.has["host-node"]:(typeof process=="object"&&process.versions&&process.versions.node&&process.versions.v8));if(0){require("./_base/configNode.js").config(_2);_2.loaderPatch.nodeRequire=require;}0&&has.add("host-rhino",_1.has&&"host-rhino" in _1.has?_1.has["host-rhino"]:(typeof load=="function"&&(typeof Packages=="function"||typeof Packages=="object")));if(0){for(var _1e=_1.baseUrl||".",arg,_1f=this.arguments,i=0;i<_1f.length;){arg=(_1f[i++]+"").split("=");if(arg[0]=="baseUrl"){_1e=arg[1];break;}}load(_1e+"/_base/configRhino.js");rhinoDojoConfig(_2,_1e,_1f);}for(var p in _1.has){has.add(p,_1.has[p],0,1);}var _20=1,_21=2,_22=3,_23=4,_24=5;if(0){_20="requested";_21="arrived";_22="not-a-module";_23="executing";_24="executed";}var _25=0,_26="sync",xd="xd",_27=[],_28=0,_29=_3,_2a=_3,_2b;if(1){req.isXdUrl=_3;req.initSyncLoader=function(_2c,_2d,_2e){if(!_28){_28=_2c;_29=_2d;_2a=_2e;}return {sync:_26,requested:_20,arrived:_21,nonmodule:_22,executing:_23,executed:_24,syncExecStack:_27,modules:_2f,execQ:_30,getModule:_31,injectModule:_32,setArrived:_33,signal:_34,finishExec:_35,execModule:_36,dojoRequirePlugin:_28,getLegacyMode:function(){return _25;},guardCheckComplete:_37};};if(1){var _38=location.protocol,_39=location.host;req.isXdUrl=function(url){if(/^\./.test(url)){return false;}if(/^\/\//.test(url)){return true;}var _3a=url.match(/^([^\/\:]+\:)\/+([^\/]+)/);return _3a&&(_3a[1]!=_38||(_39&&_3a[2]!=_39));};1||has.add("dojo-xhr-factory",1);has.add("dojo-force-activex-xhr",1&&!doc.addEventListener&&window.location.protocol=="file:");has.add("native-xhr",typeof XMLHttpRequest!="undefined");if(has("native-xhr")&&!has("dojo-force-activex-xhr")){_2b=function(){return new XMLHttpRequest();};}else{for(var _3b=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"],_3c,i=0;i<3;){try{_3c=_3b[i++];if(new ActiveXObject(_3c)){break;}}catch(e){}}_2b=function(){return new ActiveXObject(_3c);};}req.getXhr=_2b;has.add("dojo-gettext-api",1);req.getText=function(url,_3d,_3e){var xhr=_2b();xhr.open("GET",_3f(url),false);xhr.send(null);if(xhr.status==200||(!location.host&&!xhr.status)){if(_3e){_3e(xhr.responseText,_3d);}}else{throw _f("xhrFailed",xhr.status);}return xhr.responseText;};}}else{req.async=1;}var _40=new Function("return eval(arguments[0]);");req.eval=function(_41,_42){return _40(_41+"\r\n////@ sourceURL="+_42);};var _43={},_44="error",_34=req.signal=function(_45,_46){var _47=_43[_45];_9(_47&&_47.slice(0),function(_48){_48.apply(null,_8(_46)?_46:[_46]);});},on=req.on=function(_49,_4a){var _4b=_43[_49]||(_43[_49]=[]);_4b.push(_4a);return {remove:function(){for(var i=0;i<_4b.length;i++){if(_4b[i]===_4a){_4b.splice(i,1);return;}}}};};var _4c=[],_4d={},_4e=[],_4f={},map=req.map={},_50=[],_2f={},_51="",_52={},_53="url:",_54={},_55={};if(1){var _56=function(_57){var p,_58,_59,now,m;for(p in _54){_58=_54[p];_59=p.match(/^url\:(.+)/);if(_59){_52[_53+_5a(_59[1],_57)]=_58;}else{if(p=="*now"){now=_58;}else{if(p!="*noref"){m=_5b(p,_57);_52[m.mid]=_52[_53+m.url]=_58;}}}}if(now){now(_5c(_57));}_54={};},_5d=function(s){return s.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g,function(c){return "\\"+c;});},_5e=function(map,_5f){_5f.splice(0,_5f.length);for(var p in map){_5f.push([p,map[p],new RegExp("^"+_5d(p)+"(/|$)"),p.length]);}_5f.sort(function(lhs,rhs){return rhs[3]-lhs[3];});return _5f;},_60=function(_61){var _62=_61.name;if(!_62){_62=_61;_61={name:_62};}_61=_c({main:"main"},_61);_61.location=_61.location?_61.location:_62;if(_61.packageMap){map[_62]=_61.packageMap;}if(!_61.main.indexOf("./")){_61.main=_61.main.substring(2);}_4f[_62]=_61;},_63=function(_64,_65,_66){for(var p in _64){if(p=="waitSeconds"){req.waitms=(_64[p]||0)*1000;}if(p=="cacheBust"){_51=_64[p]?(_7(_64[p])?_64[p]:(new Date()).getTime()+""):"";}if(p=="baseUrl"||p=="combo"){req[p]=_64[p];}if(1&&p=="async"){var _67=_64[p];req.legacyMode=_25=(_7(_67)&&/sync|legacyAsync/.test(_67)?_67:(!_67?_26:false));req.async=!_25;}if(_64[p]!==_1a){req.rawConfig[p]=_64[p];p!="has"&&has.add("config-"+p,_64[p],0,_65);}}if(!req.baseUrl){req.baseUrl="./";}if(!/\/$/.test(req.baseUrl)){req.baseUrl+="/";}for(p in _64.has){has.add(p,_64.has[p],0,_65);}_9(_64.packages,_60);for(_1e in _64.packagePaths){_9(_64.packagePaths[_1e],function(_68){var _69=_1e+"/"+_68;if(_7(_68)){_68={name:_68};}_68.location=_69;_60(_68);});}_5e(_c(map,_64.map),_50);_9(_50,function(_6a){_6a[1]=_5e(_6a[1],[]);if(_6a[0]=="*"){_50.star=_6a[1];}});_5e(_c(_4d,_64.paths),_4e);_9(_64.aliases,function(_6b){if(_7(_6b[0])){_6b[0]=new RegExp("^"+_5d(_6b[0])+"$");}_4c.push(_6b);});for(p in _64.config){var _6c=_31(p,_66);_6c.config=_c(_6c.config||{},_64.config[p]);}if(_64.cache){_56();_54=_64.cache;if(_64.cache["*noref"]){_56();}}_34("config",[_64,req.rawConfig]);};if(has("dojo-cdn")||1){var _6d=doc.getElementsByTagName("script"),i=0,_6e,_6f,src,_70;while(i<_6d.length){_6e=_6d[i++];if((src=_6e.getAttribute("src"))&&(_70=src.match(/(((.*)\/)|^)dojo\.js(\W|$)/i))){_6f=_70[3]||"";_2.baseUrl=_2.baseUrl||_6f;src=(_6e.getAttribute("data-dojo-config")||_6e.getAttribute("djConfig"));if(src){_55=req.eval("({ "+src+" })","data-dojo-config");}if(0){var _71=_6e.getAttribute("data-main");if(_71){_55.deps=_55.deps||[_71];}}break;}}}if(0){try{if(window.parent!=window&&window.parent.require){var doh=window.parent.require("doh");doh&&_c(_55,doh.testConfig);}}catch(e){}}req.rawConfig={};_63(_2,1);if(has("dojo-cdn")){_4f.dojo.location=_6f;if(_6f){_6f+="/";}_4f.dijit.location=_6f+"../dijit/";_4f.dojox.location=_6f+"../dojox/";}_63(_1,1);_63(_55,1);}else{_4d=_2.paths;_4e=_2.pathsMapProg;_4f=_2.packs;_4c=_2.aliases;_50=_2.mapProgs;_2f=_2.modules;_52=_2.cache;_51=_2.cacheBust;req.rawConfig=_2;}if(0){req.combo=req.combo||{add:_3};var _72=0,_73=[],_74=null;}var _75=function(_76){_37(function(){_9(_76.deps,_32);if(0&&_72&&!_74){_74=setTimeout(function(){_72=0;_74=null;req.combo.done(function(_77,url){var _78=function(){_79(0,_77);_7a();};_73.push(_77);_7b=_77;req.injectUrl(url,_78,_77);_7b=0;},req);},0);}});},_16=function(a1,a2,a3,_7c,_7d){var _7e,_7f;if(_7(a1)){_7e=_31(a1,_7c,true);if(_7e&&_7e.executed){return _7e.result;}throw _f("undefinedModule",a1);}if(!_8(a1)){_63(a1,0,_7c);a1=a2;a2=a3;}if(_8(a1)){if(!a1.length){a2&&a2();}else{_7f="require*"+uid();for(var mid,_80=[],i=0;i<a1.length;){mid=a1[i++];_80.push(_31(mid,_7c));}_7e=_c(_81("",_7f,0,""),{injected:_21,deps:_80,def:a2||_3,require:_7c?_7c.require:req,gc:1});_2f[_7e.mid]=_7e;_75(_7e);var _82=_83&&_25!=_26;_37(function(){_36(_7e,_82);});if(!_7e.executed){_30.push(_7e);}_7a();}}return _7d;},_5c=function(_84){if(!_84){return req;}var _85=_84.require;if(!_85){_85=function(a1,a2,a3){return _16(a1,a2,a3,_84,_85);};_84.require=_c(_85,req);_85.module=_84;_85.toUrl=function(_86){return _5a(_86,_84);};_85.toAbsMid=function(mid){return _b3(mid,_84);};if(0){_85.undef=function(mid){req.undef(mid,_84);};}if(1){_85.syncLoadNls=function(mid){var _87=_5b(mid,_84),_88=_2f[_87.mid];if(!_88||!_88.executed){_89=_52[_87.mid]||_52[_53+_87.url];if(_89){_8a(_89);_88=_2f[_87.mid];}}return _88&&_88.executed&&_88.result;};}}return _85;},_30=[],_8b=[],_8c={},_8d=function(_8e){_8e.injected=_20;_8c[_8e.mid]=1;if(_8e.url){_8c[_8e.url]=_8e.pack||1;}_8f();},_33=function(_90){_90.injected=_21;delete _8c[_90.mid];if(_90.url){delete _8c[_90.url];}if(_4(_8c)){_91();1&&_25==xd&&(_25=_26);}},_92=req.idle=function(){return !_8b.length&&_4(_8c)&&!_30.length&&!_83;},_93=function(_94,map){if(map){for(var i=0;i<map.length;i++){if(map[i][2].test(_94)){return map[i];}}}return 0;},_95=function(_96){var _97=[],_98,_99;_96=_96.replace(/\\/g,"/").split("/");while(_96.length){_98=_96.shift();if(_98==".."&&_97.length&&_99!=".."){_97.pop();_99=_97[_97.length-1];}else{if(_98!="."){_97.push(_99=_98);}}}return _97.join("/");},_81=function(pid,mid,_9a,url){if(1){var xd=req.isXdUrl(url);return {pid:pid,mid:mid,pack:_9a,url:url,executed:0,def:0,isXd:xd,isAmd:!!(xd||(_4f[pid]&&_4f[pid].isAmd))};}else{return {pid:pid,mid:mid,pack:_9a,url:url,executed:0,def:0};}},_9b=function(mid,_9c,_9d,_9e,_9f,_a0,_a1,_a2){var pid,_a3,_a4,_a5,_a6,url,_a7,_a8,_a9;_a9=mid;_a8=/^\./.test(mid);if(/(^\/)|(\:)|(\.js$)/.test(mid)||(_a8&&!_9c)){return _81(0,mid,0,mid);}else{mid=_95(_a8?(_9c.mid+"/../"+mid):mid);if(/^\./.test(mid)){throw _f("irrationalPath",mid);}if(_9c){_a6=_93(_9c.mid,_a0);}_a6=_a6||_a0.star;_a6=_a6&&_93(mid,_a6[1]);if(_a6){mid=_a6[1]+mid.substring(_a6[3]);}_70=mid.match(/^([^\/]+)(\/(.+))?$/);pid=_70?_70[1]:"";if((_a3=_9d[pid])){mid=pid+"/"+(_a4=(_70[3]||_a3.main));}else{pid="";}var _aa=0,_ab=0;_9(_4c,function(_ac){var _ad=mid.match(_ac[0]);if(_ad&&_ad.length>_aa){_ab=_6(_ac[1])?mid.replace(_ac[0],_ac[1]):_ac[1];}});if(_ab){return _9b(_ab,0,_9d,_9e,_9f,_a0,_a1,_a2);}_a7=_9e[mid];if(_a7){return _a2?_81(_a7.pid,_a7.mid,_a7.pack,_a7.url):_9e[mid];}}_a6=_93(mid,_a1);if(_a6){url=_a6[1]+mid.substring(_a6[3]);}else{if(pid){url=_a3.location+"/"+_a4;}else{if(has("config-tlmSiblingOfDojo")){url="../"+mid;}else{url=mid;}}}if(!(/(^\/)|(\:)/.test(url))){url=_9f+url;}url+=".js";return _81(pid,mid,_a3,_95(url));},_5b=function(mid,_ae){return _9b(mid,_ae,_4f,_2f,req.baseUrl,_50,_4e);},_af=function(_b0,_b1,_b2){return _b0.normalize?_b0.normalize(_b1,function(mid){return _b3(mid,_b2);}):_b3(_b1,_b2);},_b4=0,_31=function(mid,_b5,_b6){var _b7,_b8,_b9,_ba;_b7=mid.match(/^(.+?)\!(.*)$/);if(_b7){_b8=_31(_b7[1],_b5,_b6);if(1&&_25==_26&&!_b8.executed){_32(_b8);if(_b8.injected===_21&&!_b8.executed){_37(function(){_36(_b8);});}if(_b8.executed){_bb(_b8);}else{_30.unshift(_b8);}}if(_b8.executed===_24&&!_b8.load){_bb(_b8);}if(_b8.load){_b9=_af(_b8,_b7[2],_b5);mid=(_b8.mid+"!"+(_b8.dynamic?++_b4+"!":"")+_b9);}else{_b9=_b7[2];mid=_b8.mid+"!"+(++_b4)+"!waitingForPlugin";}_ba={plugin:_b8,mid:mid,req:_5c(_b5),prid:_b9};}else{_ba=_5b(mid,_b5);}return _2f[_ba.mid]||(!_b6&&(_2f[_ba.mid]=_ba));},_b3=req.toAbsMid=function(mid,_bc){return _5b(mid,_bc).mid;},_5a=req.toUrl=function(_bd,_be){var _bf=_5b(_bd+"/x",_be),url=_bf.url;return _3f(_bf.pid===0?_bd:url.substring(0,url.length-5));},_c0={injected:_21,executed:_24,def:_22,result:_22},_c1=function(mid){return _2f[mid]=_c({mid:mid},_c0);},_c2=_c1("require"),_c3=_c1("exports"),_c4=_c1("module"),_c5=function(_c6,_c7){req.trace("loader-run-factory",[_c6.mid]);var _c8=_c6.def,_c9;1&&_27.unshift(_c6);if(has("config-dojo-loader-catches")){try{_c9=_6(_c8)?_c8.apply(null,_c7):_c8;}catch(e){_34(_44,_c6.result=_f("factoryThrew",[_c6,e]));}}else{_c9=_6(_c8)?_c8.apply(null,_c7):_c8;}_c6.result=_c9===undefined&&_c6.cjs?_c6.cjs.exports:_c9;1&&_27.shift(_c6);},_ca={},_cb=0,_bb=function(_cc){var _cd=_cc.result;_cc.dynamic=_cd.dynamic;_cc.normalize=_cd.normalize;_cc.load=_cd.load;return _cc;},_ce=function(_cf){var map={};_9(_cf.loadQ,function(_d0){var _d1=_af(_cf,_d0.prid,_d0.req.module),mid=_cf.dynamic?_d0.mid.replace(/waitingForPlugin$/,_d1):(_cf.mid+"!"+_d1),_d2=_c(_c({},_d0),{mid:mid,prid:_d1,injected:0});if(!_2f[mid]){_e4(_2f[mid]=_d2);}map[_d0.mid]=_2f[mid];_33(_d0);delete _2f[_d0.mid];});_cf.loadQ=0;var _d3=function(_d4){for(var _d5,_d6=_d4.deps||[],i=0;i<_d6.length;i++){_d5=map[_d6[i].mid];if(_d5){_d6[i]=_d5;}}};for(var p in _2f){_d3(_2f[p]);}_9(_30,_d3);},_35=function(_d7){req.trace("loader-finish-exec",[_d7.mid]);_d7.executed=_24;_d7.defOrder=_cb++;1&&_9(_d7.provides,function(cb){cb();});if(_d7.loadQ){_bb(_d7);_ce(_d7);}for(i=0;i<_30.length;){if(_30[i]===_d7){_30.splice(i,1);}else{i++;}}if(/^require\*/.test(_d7.mid)){delete _2f[_d7.mid];}},_d8=[],_36=function(_d9,_da){if(_d9.executed===_23){req.trace("loader-circular-dependency",[_d8.concat(_d9.mid).join("->")]);return (!_d9.def||_da)?_ca:(_d9.cjs&&_d9.cjs.exports);}if(!_d9.executed){if(!_d9.def){return _ca;}var mid=_d9.mid,_db=_d9.deps||[],arg,_dc,_dd=[],i=0;if(0){_d8.push(mid);req.trace("loader-exec-module",["exec",_d8.length,mid]);}_d9.executed=_23;while(i<_db.length){arg=_db[i++];_dc=((arg===_c2)?_5c(_d9):((arg===_c3)?_d9.cjs.exports:((arg===_c4)?_d9.cjs:_36(arg,_da))));if(_dc===_ca){_d9.executed=0;req.trace("loader-exec-module",["abort",mid]);0&&_d8.pop();return _ca;}_dd.push(_dc);}_c5(_d9,_dd);_35(_d9);0&&_d8.pop();}return _d9.result;},_83=0,_37=function(_de){try{_83++;_de();}finally{_83--;}if(_92()){_34("idle",[]);}},_7a=function(){if(_83){return;}_37(function(){_29();for(var _df,_e0,i=0;i<_30.length;){_df=_cb;_e0=_30[i];_36(_e0);if(_df!=_cb){_29();i=0;}else{i++;}}});};if(0){req.undef=function(_e1,_e2){var _e3=_31(_e1,_e2);_33(_e3);delete _2f[_e3.mid];};}if(1){if(has("dojo-loader-eval-hint-url")===undefined){has.add("dojo-loader-eval-hint-url",1);}var _3f=function(url){url+="";return url+(_51?((/\?/.test(url)?"&":"?")+_51):"");},_e4=function(_e5){var _e6=_e5.plugin;if(_e6.executed===_24&&!_e6.load){_bb(_e6);}var _e7=function(def){_e5.result=def;_33(_e5);_35(_e5);_7a();};if(_e6.load){_e6.load(_e5.prid,_e5.req,_e7);}else{if(_e6.loadQ){_e6.loadQ.push(_e5);}else{_e6.loadQ=[_e5];_30.unshift(_e6);_32(_e6);}}},_89=0,_7b=0,_e8=0,_8a=function(_e9,_ea){if(has("config-stripStrict")){_e9=_e9.replace(/"use strict"/g,"");}_e8=1;if(has("config-dojo-loader-catches")){try{if(_e9===_89){_89.call(null);}else{req.eval(_e9,has("dojo-loader-eval-hint-url")?_ea.url:_ea.mid);}}catch(e){_34(_44,_f("evalModuleThrew",_ea));}}else{if(_e9===_89){_89.call(null);}else{req.eval(_e9,has("dojo-loader-eval-hint-url")?_ea.url:_ea.mid);}}_e8=0;},_32=function(_eb){var mid=_eb.mid,url=_eb.url;if(_eb.executed||_eb.injected||_8c[mid]||(_eb.url&&((_eb.pack&&_8c[_eb.url]===_eb.pack)||_8c[_eb.url]==1))){return;}_8d(_eb);if(0){var _ec=0;if(_eb.plugin&&_eb.plugin.isCombo){req.combo.add(_eb.plugin.mid,_eb.prid,0,req);_ec=1;}else{if(!_eb.plugin){_ec=req.combo.add(0,_eb.mid,_eb.url,req);}}if(_ec){_72=1;return;}}if(_eb.plugin){_e4(_eb);return;}var _ed=function(){_79(_eb);if(_eb.injected!==_21){_33(_eb);_c(_eb,_c0);req.trace("loader-define-nonmodule",[_eb.url]);}if(1&&_25){!_27.length&&_7a();}else{_7a();}};_89=_52[mid]||_52[_53+_eb.url];if(_89){req.trace("loader-inject",["cache",_eb.mid,url]);_8a(_89,_eb);_ed();return;}if(1&&_25){if(_eb.isXd){_25==_26&&(_25=xd);}else{if(_eb.isAmd&&_25!=_26){}else{var _ee=function(_ef){if(_25==_26){_27.unshift(_eb);_8a(_ef,_eb);_27.shift();_79(_eb);if(!_eb.cjs){_33(_eb);_35(_eb);}if(_eb.finish){var _f0=mid+"*finish",_f1=_eb.finish;delete _eb.finish;def(_f0,["dojo",("dojo/require!"+_f1.join(",")).replace(/\./g,"/")],function(_f2){_9(_f1,function(mid){_f2.require(mid);});});_30.unshift(_31(_f0));}_ed();}else{_ef=_2a(_eb,_ef);if(_ef){_8a(_ef,_eb);_ed();}else{_7b=_eb;req.injectUrl(_3f(url),_ed,_eb);_7b=0;}}};req.trace("loader-inject",["xhr",_eb.mid,url,_25!=_26]);if(has("config-dojo-loader-catches")){try{req.getText(url,_25!=_26,_ee);}catch(e){_34(_44,_f("xhrInjectFailed",[_eb,e]));}}else{req.getText(url,_25!=_26,_ee);}return;}}}req.trace("loader-inject",["script",_eb.mid,url]);_7b=_eb;req.injectUrl(_3f(url),_ed,_eb);_7b=0;},_f3=function(_f4,_f5,def){req.trace("loader-define-module",[_f4.mid,_f5]);if(0&&_f4.plugin&&_f4.plugin.isCombo){_f4.result=_6(def)?def():def;_33(_f4);_35(_f4);return _f4;}var mid=_f4.mid;if(_f4.injected===_21){_34(_44,_f("multipleDefine",_f4));return _f4;}_c(_f4,{deps:_f5,def:def,cjs:{id:_f4.mid,uri:_f4.url,exports:(_f4.result={}),setExports:function(_f6){_f4.cjs.exports=_f6;},config:function(){return _f4.config;}}});for(var i=0;i<_f5.length;i++){_f5[i]=_31(_f5[i],_f4);}if(1&&_25&&!_8c[mid]){_75(_f4);_30.push(_f4);_7a();}_33(_f4);if(!_6(def)&&!_f5.length){_f4.result=def;_35(_f4);}return _f4;},_79=function(_f7,_f8){var _f9=[],_fa,_fb;while(_8b.length){_fb=_8b.shift();_f8&&(_fb[0]=_f8.shift());_fa=(_fb[0]&&_31(_fb[0]))||_f7;_f9.push([_fa,_fb[1],_fb[2]]);}_56(_f7);_9(_f9,function(_fc){_75(_f3.apply(null,_fc));});};}var _fd=0,_91=_3,_8f=_3;if(1){_91=function(){_fd&&clearTimeout(_fd);_fd=0;},_8f=function(){_91();if(req.waitms){_fd=window.setTimeout(function(){_91();_34(_44,_f("timeout",_8c));},req.waitms);}};}if(1){has.add("ie-event-behavior",!!doc.attachEvent&&(typeof opera==="undefined"||opera.toString()!="[object Opera]"));}if(1&&(1||1)){var _fe=function(_ff,_100,_101,_102){if(!has("ie-event-behavior")){_ff.addEventListener(_100,_102,false);return function(){_ff.removeEventListener(_100,_102,false);};}else{_ff.attachEvent(_101,_102);return function(){_ff.detachEvent(_101,_102);};}},_103=_fe(window,"load","onload",function(){req.pageLoaded=1;doc.readyState!="complete"&&(doc.readyState="complete");_103();});if(1){var _104=doc.getElementsByTagName("script")[0],_105=_104.parentNode;req.injectUrl=function(url,_106,_107){var node=_107.node=doc.createElement("script"),_108=function(e){e=e||window.event;var node=e.target||e.srcElement;if(e.type==="load"||/complete|loaded/.test(node.readyState)){_109();_10a();_106&&_106();}},_109=_fe(node,"load","onreadystatechange",_108),_10a=_fe(node,"error","onerror",function(e){_109();_10a();_34(_44,_f("scriptError",[url,e]));});node.type="text/javascript";node.charset="utf-8";node.src=url;_105.insertBefore(node,_104);return node;};}}if(1){req.log=function(){try{for(var i=0;i<arguments.length;i++){}}catch(e){}};}else{req.log=_3;}if(0){var _10b=req.trace=function(_10c,args){if(_10b.on&&_10b.group[_10c]){_34("trace",[_10c,args]);for(var arg,dump=[],text="trace:"+_10c+(args.length?(":"+args[0]):""),i=1;i<args.length;){arg=args[i++];if(_7(arg)){text+=", "+arg;}else{dump.push(arg);}}req.log(text);dump.length&&dump.push(".");req.log.apply(req,dump);}};_c(_10b,{on:1,group:{},set:function(_10d,_10e){if(_7(_10d)){_10b.group[_10d]=_10e;}else{_c(_10b.group,_10d);}}});_10b.set(_c(_c(_c({},_2.trace),_1.trace),_55.trace));on("config",function(_10f){_10f.trace&&_10b.set(_10f.trace);});}else{req.trace=_3;}var def=function(mid,_110,_111){var _112=arguments.length,_113=["require","exports","module"],args=[0,mid,_110];if(_112==1){args=[0,(_6(mid)?_113:[]),mid];}else{if(_112==2&&_7(mid)){args=[mid,(_6(_110)?_113:[]),_110];}else{if(_112==3){args=[mid,_110,_111];}}}if(0&&args[1]===_113){args[2].toString().replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,"").replace(/require\(["']([\w\!\-_\.\/]+)["']\)/g,function(_114,dep){args[1].push(dep);});}req.trace("loader-define",args.slice(0,2));var _115=args[0]&&_31(args[0]),_116;if(_115&&!_8c[_115.mid]){_75(_f3(_115,args[1],args[2]));}else{if(!has("ie-event-behavior")||!1||_e8){_8b.push(args);}else{_115=_115||_7b;if(!_115){for(mid in _8c){_116=_2f[mid];if(_116&&_116.node&&_116.node.readyState==="interactive"){_115=_116;break;}}if(0&&!_115){for(var i=0;i<_73.length;i++){_115=_73[i];if(_115.node&&_115.node.readyState==="interactive"){break;}_115=0;}}}if(0&&_8(_115)){_75(_f3(_31(_115.shift()),args[1],args[2]));if(!_115.length){_73.splice(i,1);}}else{if(_115){_56(_115);_75(_f3(_115,args[1],args[2]));}else{_34(_44,_f("ieDefineFailed",args[0]));}}_7a();}}};def.amd={vendor:"dojotoolkit.org"};if(0){req.def=def;}_c(_c(req,_2.loaderPatch),_1.loaderPatch);on(_44,function(arg){try{console.error(arg);if(arg instanceof Error){for(var p in arg){}}}catch(e){}});_c(req,{uid:uid,cache:_52,packs:_4f});if(0){_c(req,{paths:_4d,aliases:_4c,modules:_2f,legacyMode:_25,execQ:_30,defQ:_8b,waiting:_8c,packs:_4f,mapProgs:_50,pathsMapProg:_4e,listenerQueues:_43,computeMapProg:_5e,runMapProg:_93,compactPath:_95,getModuleInfo:_9b});}if(_17.define){if(1){_34(_44,_f("defineAlreadyDefined",0));}return;}else{_17.define=def;_17.require=req;if(0){require=req;}}if(0&&req.combo&&req.combo.plugins){var _117=req.combo.plugins,_118;for(_118 in _117){_c(_c(_31(_118),_117[_118]),{isCombo:1,executed:"executed",load:1});}}if(1){var _119=_55.deps||_1.deps||_2.deps,_11a=_55.callback||_1.callback||_2.callback;req.boot=(_119||_11a)?[_119||[],_11a]:0;}if(!1){!req.async&&req(["dojo"]);req.boot&&req.apply(null,req.boot);}})(this.dojoConfig||this.djConfig||this.require||{},{async:0,hasCache:{"config-selectorEngine":"acme","config-tlmSiblingOfDojo":1,"dojo-built":1,"dojo-loader":1,dom:1,"host-browser":1},packages:[{location:"../dijit",name:"dijit"},{location:"../dojox",name:"dojox"},{location:".",name:"dojo"}]});require({cache:{"dojo/_base/fx":function(){define(["./kernel","./config","./lang","../Evented","./Color","./connect","./sniff","../dom","../dom-style"],function(dojo,_11b,lang,_11c,_11d,_11e,has,dom,_11f){var _120=lang.mixin;var _121={};var _122=_121._Line=function(_123,end){this.start=_123;this.end=end;};_122.prototype.getValue=function(n){return ((this.end-this.start)*n)+this.start;};var _124=_121.Animation=function(args){_120(this,args);if(lang.isArray(this.curve)){this.curve=new _122(this.curve[0],this.curve[1]);}};_124.prototype=new _11c();lang.extend(_124,{duration:350,repeat:0,rate:20,_percent:0,_startRepeatCount:0,_getStep:function(){var _125=this._percent,_126=this.easing;return _126?_126(_125):_125;},_fire:function(evt,args){var a=args||[];if(this[evt]){if(_11b.debugAtAllCosts){this[evt].apply(this,a);}else{try{this[evt].apply(this,a);}catch(e){console.error("exception in animation handler for:",evt);console.error(e);}}}return this;},play:function(_127,_128){var _129=this;if(_129._delayTimer){_129._clearTimer();}if(_128){_129._stopTimer();_129._active=_129._paused=false;_129._percent=0;}else{if(_129._active&&!_129._paused){return _129;}}_129._fire("beforeBegin",[_129.node]);var de=_127||_129.delay,_12a=lang.hitch(_129,"_play",_128);if(de>0){_129._delayTimer=setTimeout(_12a,de);return _129;}_12a();return _129;},_play:function(_12b){var _12c=this;if(_12c._delayTimer){_12c._clearTimer();}_12c._startTime=new Date().valueOf();if(_12c._paused){_12c._startTime-=_12c.duration*_12c._percent;}_12c._active=true;_12c._paused=false;var _12d=_12c.curve.getValue(_12c._getStep());if(!_12c._percent){if(!_12c._startRepeatCount){_12c._startRepeatCount=_12c.repeat;}_12c._fire("onBegin",[_12d]);}_12c._fire("onPlay",[_12d]);_12c._cycle();return _12c;},pause:function(){var _12e=this;if(_12e._delayTimer){_12e._clearTimer();}_12e._stopTimer();if(!_12e._active){return _12e;}_12e._paused=true;_12e._fire("onPause",[_12e.curve.getValue(_12e._getStep())]);return _12e;},gotoPercent:function(_12f,_130){var _131=this;_131._stopTimer();_131._active=_131._paused=true;_131._percent=_12f;if(_130){_131.play();}return _131;},stop:function(_132){var _133=this;if(_133._delayTimer){_133._clearTimer();}if(!_133._timer){return _133;}_133._stopTimer();if(_132){_133._percent=1;}_133._fire("onStop",[_133.curve.getValue(_133._getStep())]);_133._active=_133._paused=false;return _133;},status:function(){if(this._active){return this._paused?"paused":"playing";}return "stopped";},_cycle:function(){var _134=this;if(_134._active){var curr=new Date().valueOf();var step=_134.duration===0?1:(curr-_134._startTime)/(_134.duration);if(step>=1){step=1;}_134._percent=step;if(_134.easing){step=_134.easing(step);}_134._fire("onAnimate",[_134.curve.getValue(step)]);if(_134._percent<1){_134._startTimer();}else{_134._active=false;if(_134.repeat>0){_134.repeat--;_134.play(null,true);}else{if(_134.repeat==-1){_134.play(null,true);}else{if(_134._startRepeatCount){_134.repeat=_134._startRepeatCount;_134._startRepeatCount=0;}}}_134._percent=0;_134._fire("onEnd",[_134.node]);!_134.repeat&&_134._stopTimer();}}return _134;},_clearTimer:function(){clearTimeout(this._delayTimer);delete this._delayTimer;}});var ctr=0,_135=null,_136={run:function(){}};lang.extend(_124,{_startTimer:function(){if(!this._timer){this._timer=_11e.connect(_136,"run",this,"_cycle");ctr++;}if(!_135){_135=setInterval(lang.hitch(_136,"run"),this.rate);}},_stopTimer:function(){if(this._timer){_11e.disconnect(this._timer);this._timer=null;ctr--;}if(ctr<=0){clearInterval(_135);_135=null;ctr=0;}}});var _137=has("ie")?function(node){var ns=node.style;if(!ns.width.length&&_11f.get(node,"width")=="auto"){ns.width="auto";}}:function(){};_121._fade=function(args){args.node=dom.byId(args.node);var _138=_120({properties:{}},args),_139=(_138.properties.opacity={});_139.start=!("start" in _138)?function(){return +_11f.get(_138.node,"opacity")||0;}:_138.start;_139.end=_138.end;var anim=_121.animateProperty(_138);_11e.connect(anim,"beforeBegin",lang.partial(_137,_138.node));return anim;};_121.fadeIn=function(args){return _121._fade(_120({end:1},args));};_121.fadeOut=function(args){return _121._fade(_120({end:0},args));};_121._defaultEasing=function(n){return 0.5+((Math.sin((n+1.5)*Math.PI))/2);};var _13a=function(_13b){this._properties=_13b;for(var p in _13b){var prop=_13b[p];if(prop.start instanceof _11d){prop.tempColor=new _11d();}}};_13a.prototype.getValue=function(r){var ret={};for(var p in this._properties){var prop=this._properties[p],_13c=prop.start;if(_13c instanceof _11d){ret[p]=_11d.blendColors(_13c,prop.end,r,prop.tempColor).toCss();}else{if(!lang.isArray(_13c)){ret[p]=((prop.end-_13c)*r)+_13c+(p!="opacity"?prop.units||"px":0);}}}return ret;};_121.animateProperty=function(args){var n=args.node=dom.byId(args.node);if(!args.easing){args.easing=dojo._defaultEasing;}var anim=new _124(args);_11e.connect(anim,"beforeBegin",anim,function(){var pm={};for(var p in this.properties){if(p=="width"||p=="height"){this.node.display="block";}var prop=this.properties[p];if(lang.isFunction(prop)){prop=prop(n);}prop=pm[p]=_120({},(lang.isObject(prop)?prop:{end:prop}));if(lang.isFunction(prop.start)){prop.start=prop.start(n);}if(lang.isFunction(prop.end)){prop.end=prop.end(n);}var _13d=(p.toLowerCase().indexOf("color")>=0);function _13e(node,p){var v={height:node.offsetHeight,width:node.offsetWidth}[p];if(v!==undefined){return v;}v=_11f.get(node,p);return (p=="opacity")?+v:(_13d?v:parseFloat(v));};if(!("end" in prop)){prop.end=_13e(n,p);}else{if(!("start" in prop)){prop.start=_13e(n,p);}}if(_13d){prop.start=new _11d(prop.start);prop.end=new _11d(prop.end);}else{prop.start=(p=="opacity")?+prop.start:parseFloat(prop.start);}}this.curve=new _13a(pm);});_11e.connect(anim,"onAnimate",lang.hitch(_11f,"set",anim.node));return anim;};_121.anim=function(node,_13f,_140,_141,_142,_143){return _121.animateProperty({node:node,duration:_140||_124.prototype.duration,properties:_13f,easing:_141,onEnd:_142}).play(_143||0);};if(1){_120(dojo,_121);dojo._Animation=_124;}return _121;});},"dojo/dom-form":function(){define(["./_base/lang","./dom","./io-query","./json"],function(lang,dom,ioq,json){function _144(obj,name,_145){if(_145===null){return;}var val=obj[name];if(typeof val=="string"){obj[name]=[val,_145];}else{if(lang.isArray(val)){val.push(_145);}else{obj[name]=_145;}}};var _146="file|submit|image|reset|button";var form={fieldToObject:function fieldToObject(_147){var ret=null;_147=dom.byId(_147);if(_147){var _148=_147.name,type=(_147.type||"").toLowerCase();if(_148&&type&&!_147.disabled){if(type=="radio"||type=="checkbox"){if(_147.checked){ret=_147.value;}}else{if(_147.multiple){ret=[];var _149=[_147.firstChild];while(_149.length){for(var node=_149.pop();node;node=node.nextSibling){if(node.nodeType==1&&node.tagName.toLowerCase()=="option"){if(node.selected){ret.push(node.value);}}else{if(node.nextSibling){_149.push(node.nextSibling);}if(node.firstChild){_149.push(node.firstChild);}break;}}}}else{ret=_147.value;}}}}return ret;},toObject:function formToObject(_14a){var ret={},_14b=dom.byId(_14a).elements;for(var i=0,l=_14b.length;i<l;++i){var item=_14b[i],_14c=item.name,type=(item.type||"").toLowerCase();if(_14c&&type&&_146.indexOf(type)<0&&!item.disabled){_144(ret,_14c,form.fieldToObject(item));if(type=="image"){ret[_14c+".x"]=ret[_14c+".y"]=ret[_14c].x=ret[_14c].y=0;}}}return ret;},toQuery:function formToQuery(_14d){return ioq.objectToQuery(form.toObject(_14d));},toJson:function formToJson(_14e,_14f){return json.stringify(form.toObject(_14e),null,_14f?4:0);}};return form;});},"dojo/i18n":function(){define(["./_base/kernel","require","./has","./_base/array","./_base/config","./_base/lang","./_base/xhr","./json","module"],function(dojo,_150,has,_151,_152,lang,xhr,json,_153){has.add("dojo-preload-i18n-Api",1);1||has.add("dojo-v1x-i18n-Api",1);var _154=dojo.i18n={},_155=/(^.*(^|\/)nls)(\/|$)([^\/]*)\/?([^\/]*)/,_156=function(root,_157,_158,_159){for(var _15a=[_158+_159],_15b=_157.split("-"),_15c="",i=0;i<_15b.length;i++){_15c+=(_15c?"-":"")+_15b[i];if(!root||root[_15c]){_15a.push(_158+_15c+"/"+_159);}}return _15a;},_15d={},_15e=function(_15f,_160,_161){_161=_161?_161.toLowerCase():dojo.locale;_15f=_15f.replace(/\./g,"/");_160=_160.replace(/\./g,"/");return (/root/i.test(_161))?(_15f+"/nls/"+_160):(_15f+"/nls/"+_161+"/"+_160);},_162=dojo.getL10nName=function(_163,_164,_165){return _163=_153.id+"!"+_15e(_163,_164,_165);},_166=function(_167,_168,_169,_16a,_16b,load){_167([_168],function(root){var _16c=lang.clone(root.root),_16d=_156(!root._v1x&&root,_16b,_169,_16a);_167(_16d,function(){for(var i=1;i<_16d.length;i++){_16c=lang.mixin(lang.clone(_16c),arguments[i]);}var _16e=_168+"/"+_16b;_15d[_16e]=_16c;load();});});},_16f=function(id,_170){return /^\./.test(id)?_170(id):id;},_171=function(_172){var list=_152.extraLocale||[];list=lang.isArray(list)?list:[list];list.push(_172);return list;},load=function(id,_173,load){if(has("dojo-preload-i18n-Api")){var _174=id.split("*"),_175=_174[1]=="preload";if(_175){if(!_15d[id]){_15d[id]=1;_176(_174[2],json.parse(_174[3]),1,_173);}load(1);}if(_175||_177(id,_173,load)){return;}}var _178=_155.exec(id),_179=_178[1]+"/",_17a=_178[5]||_178[4],_17b=_179+_17a,_17c=(_178[5]&&_178[4]),_17d=_17c||dojo.locale,_17e=_17b+"/"+_17d,_17f=_17c?[_17d]:_171(_17d),_180=_17f.length,_181=function(){if(!--_180){load(lang.delegate(_15d[_17e]));}};_151.forEach(_17f,function(_182){var _183=_17b+"/"+_182;if(has("dojo-preload-i18n-Api")){_184(_183);}if(!_15d[_183]){_166(_173,_17b,_179,_17a,_182,_181);}else{_181();}});};if(has("dojo-unit-tests")){var _185=_154.unitTests=[];}if(has("dojo-preload-i18n-Api")||1){var _186=_154.normalizeLocale=function(_187){var _188=_187?_187.toLowerCase():dojo.locale;return _188=="root"?"ROOT":_188;},isXd=function(mid,_189){return (1&&1)?_189.isXdUrl(_150.toUrl(mid+".js")):true;},_18a=0,_18b=[],_176=_154._preloadLocalizations=function(_18c,_18d,_18e,_18f){_18f=_18f||_150;function _190(mid,_191){if(isXd(mid,_18f)||_18e){_18f([mid],_191);}else{_19b([mid],_191,_18f);}};function _192(_193,func){var _194=_193.split("-");while(_194.length){if(func(_194.join("-"))){return;}_194.pop();}func("ROOT");};function _195(_196){_196=_186(_196);_192(_196,function(loc){if(_151.indexOf(_18d,loc)>=0){var mid=_18c.replace(/\./g,"/")+"_"+loc;_18a++;_190(mid,function(_197){for(var p in _197){_15d[_150.toAbsMid(p)+"/"+loc]=_197[p];}--_18a;while(!_18a&&_18b.length){load.apply(null,_18b.shift());}});return true;}return false;});};_195();_151.forEach(dojo.config.extraLocale,_195);},_177=function(id,_198,load){if(_18a){_18b.push([id,_198,load]);}return _18a;},_184=function(){};}if(1){var _199={},_19a=new Function("__bundle","__checkForLegacyModules","__mid","__amdValue","var define = function(mid, factory){define.called = 1; __amdValue.result = factory || mid;},"+"\t   require = function(){define.called = 1;};"+"try{"+"define.called = 0;"+"eval(__bundle);"+"if(define.called==1)"+"return __amdValue;"+"if((__checkForLegacyModules = __checkForLegacyModules(__mid)))"+"return __checkForLegacyModules;"+"}catch(e){}"+"try{"+"return eval('('+__bundle+')');"+"}catch(e){"+"return e;"+"}"),_19b=function(deps,_19c,_19d){var _19e=[];_151.forEach(deps,function(mid){var url=_19d.toUrl(mid+".js");function load(text){var _19f=_19a(text,_184,mid,_199);if(_19f===_199){_19e.push(_15d[url]=_199.result);}else{if(_19f instanceof Error){console.error("failed to evaluate i18n bundle; url="+url,_19f);_19f={};}_19e.push(_15d[url]=(/nls\/[^\/]+\/[^\/]+$/.test(url)?_19f:{root:_19f,_v1x:1}));}};if(_15d[url]){_19e.push(_15d[url]);}else{var _1a0=_19d.syncLoadNls(mid);if(_1a0){_19e.push(_1a0);}else{if(!xhr){try{_19d.getText(url,true,load);}catch(e){_19e.push(_15d[url]={});}}else{xhr.get({url:url,sync:true,load:load,error:function(){_19e.push(_15d[url]={});}});}}}});_19c&&_19c.apply(null,_19e);};_184=function(_1a1){for(var _1a2,_1a3=_1a1.split("/"),_1a4=dojo.global[_1a3[0]],i=1;_1a4&&i<_1a3.length-1;_1a4=_1a4[_1a3[i++]]){}if(_1a4){_1a2=_1a4[_1a3[i]];if(!_1a2){_1a2=_1a4[_1a3[i].replace(/-/g,"_")];}if(_1a2){_15d[_1a1]=_1a2;}}return _1a2;};_154.getLocalization=function(_1a5,_1a6,_1a7){var _1a8,_1a9=_15e(_1a5,_1a6,_1a7);load(_1a9,(!isXd(_1a9,_150)?function(deps,_1aa){_19b(deps,_1aa,_150);}:_150),function(_1ab){_1a8=_1ab;});return _1a8;};if(has("dojo-unit-tests")){_185.push(function(doh){doh.register("tests.i18n.unit",function(t){var _1ac;_1ac=_19a("{prop:1}",_184,"nonsense",_199);t.is({prop:1},_1ac);t.is(undefined,_1ac[1]);_1ac=_19a("({prop:1})",_184,"nonsense",_199);t.is({prop:1},_1ac);t.is(undefined,_1ac[1]);_1ac=_19a("{'prop-x':1}",_184,"nonsense",_199);t.is({"prop-x":1},_1ac);t.is(undefined,_1ac[1]);_1ac=_19a("({'prop-x':1})",_184,"nonsense",_199);t.is({"prop-x":1},_1ac);t.is(undefined,_1ac[1]);_1ac=_19a("define({'prop-x':1})",_184,"nonsense",_199);t.is(_199,_1ac);t.is({"prop-x":1},_199.result);_1ac=_19a("define('some/module', {'prop-x':1})",_184,"nonsense",_199);t.is(_199,_1ac);t.is({"prop-x":1},_199.result);_1ac=_19a("this is total nonsense and should throw an error",_184,"nonsense",_199);t.is(_1ac instanceof Error,true);});});}}return lang.mixin(_154,{dynamic:true,normalize:_16f,load:load,cache:_15d});});},"dojo/promise/tracer":function(){define(["../_base/lang","./Promise","../Evented"],function(lang,_1ad,_1ae){"use strict";var _1af=new _1ae;var emit=_1af.emit;_1af.emit=null;function _1b0(args){setTimeout(function(){emit.apply(_1af,args);},0);};_1ad.prototype.trace=function(){var args=lang._toArray(arguments);this.then(function(_1b1){_1b0(["resolved",_1b1].concat(args));},function(_1b2){_1b0(["rejected",_1b2].concat(args));},function(_1b3){_1b0(["progress",_1b3].concat(args));});return this;};_1ad.prototype.traceRejected=function(){var args=lang._toArray(arguments);this.otherwise(function(_1b4){_1b0(["rejected",_1b4].concat(args));});return this;};return _1af;});},"dojo/errors/RequestError":function(){define(["./create"],function(_1b5){return _1b5("RequestError",function(_1b6,_1b7){this.response=_1b7;});});},"dojo/_base/html":function(){define("dojo/_base/html",["./kernel","../dom","../dom-style","../dom-attr","../dom-prop","../dom-class","../dom-construct","../dom-geometry"],function(dojo,dom,_1b8,attr,prop,cls,ctr,geom){dojo.byId=dom.byId;dojo.isDescendant=dom.isDescendant;dojo.setSelectable=dom.setSelectable;dojo.getAttr=attr.get;dojo.setAttr=attr.set;dojo.hasAttr=attr.has;dojo.removeAttr=attr.remove;dojo.getNodeProp=attr.getNodeProp;dojo.attr=function(node,name,_1b9){if(arguments.length==2){return attr[typeof name=="string"?"get":"set"](node,name);}return attr.set(node,name,_1b9);};dojo.hasClass=cls.contains;dojo.addClass=cls.add;dojo.removeClass=cls.remove;dojo.toggleClass=cls.toggle;dojo.replaceClass=cls.replace;dojo._toDom=dojo.toDom=ctr.toDom;dojo.place=ctr.place;dojo.create=ctr.create;dojo.empty=function(node){ctr.empty(node);};dojo._destroyElement=dojo.destroy=function(node){ctr.destroy(node);};dojo._getPadExtents=dojo.getPadExtents=geom.getPadExtents;dojo._getBorderExtents=dojo.getBorderExtents=geom.getBorderExtents;dojo._getPadBorderExtents=dojo.getPadBorderExtents=geom.getPadBorderExtents;dojo._getMarginExtents=dojo.getMarginExtents=geom.getMarginExtents;dojo._getMarginSize=dojo.getMarginSize=geom.getMarginSize;dojo._getMarginBox=dojo.getMarginBox=geom.getMarginBox;dojo.setMarginBox=geom.setMarginBox;dojo._getContentBox=dojo.getContentBox=geom.getContentBox;dojo.setContentSize=geom.setContentSize;dojo._isBodyLtr=dojo.isBodyLtr=geom.isBodyLtr;dojo._docScroll=dojo.docScroll=geom.docScroll;dojo._getIeDocumentElementOffset=dojo.getIeDocumentElementOffset=geom.getIeDocumentElementOffset;dojo._fixIeBiDiScrollLeft=dojo.fixIeBiDiScrollLeft=geom.fixIeBiDiScrollLeft;dojo.position=geom.position;dojo.marginBox=function marginBox(node,box){return box?geom.setMarginBox(node,box):geom.getMarginBox(node);};dojo.contentBox=function contentBox(node,box){return box?geom.setContentSize(node,box):geom.getContentBox(node);};dojo.coords=function(node,_1ba){dojo.deprecated("dojo.coords()","Use dojo.position() or dojo.marginBox().");node=dom.byId(node);var s=_1b8.getComputedStyle(node),mb=geom.getMarginBox(node,s);var abs=geom.position(node,_1ba);mb.x=abs.x;mb.y=abs.y;return mb;};dojo.getProp=prop.get;dojo.setProp=prop.set;dojo.prop=function(node,name,_1bb){if(arguments.length==2){return prop[typeof name=="string"?"get":"set"](node,name);}return prop.set(node,name,_1bb);};dojo.getStyle=_1b8.get;dojo.setStyle=_1b8.set;dojo.getComputedStyle=_1b8.getComputedStyle;dojo.__toPixelValue=dojo.toPixelValue=_1b8.toPixelValue;dojo.style=function(node,name,_1bc){switch(arguments.length){case 1:return _1b8.get(node);case 2:return _1b8[typeof name=="string"?"get":"set"](node,name);}return _1b8.set(node,name,_1bc);};return dojo;});},"dojo/_base/kernel":function(){define(["../has","./config","require","module"],function(has,_1bd,_1be,_1bf){var i,p,_1c0={},_1c1={},dojo={config:_1bd,global:this,dijit:_1c0,dojox:_1c1};var _1c2={dojo:["dojo",dojo],dijit:["dijit",_1c0],dojox:["dojox",_1c1]},_1c3=(_1be.map&&_1be.map[_1bf.id.match(/[^\/]+/)[0]]),item;for(p in _1c3){if(_1c2[p]){_1c2[p][0]=_1c3[p];}else{_1c2[p]=[_1c3[p],{}];}}for(p in _1c2){item=_1c2[p];item[1]._scopeName=item[0];if(!_1bd.noGlobals){this[item[0]]=item[1];}}dojo.scopeMap=_1c2;dojo.baseUrl=dojo.config.baseUrl=_1be.baseUrl;dojo.isAsync=!1||_1be.async;dojo.locale=_1bd.locale;var rev="$Rev: 29458 $".match(/\d+/);dojo.version={major:1,minor:8,patch:0,flag:"",revision:rev?+rev[0]:NaN,toString:function(){var v=dojo.version;return v.major+"."+v.minor+"."+v.patch+v.flag+" ("+v.revision+")";}};1||has.add("extend-dojo",1);(Function("d","d.eval = function(){return d.global.eval ? d.global.eval(arguments[0]) : eval(arguments[0]);}"))(dojo);if(0){dojo.exit=function(_1c4){quit(_1c4);};}else{dojo.exit=function(){};}1||has.add("dojo-guarantee-console",1);if(1){typeof console!="undefined"||(console={});var cn=["assert","count","debug","dir","dirxml","error","group","groupEnd","info","profile","profileEnd","time","timeEnd","trace","warn","log"];var tn;i=0;while((tn=cn[i++])){if(!console[tn]){(function(){var tcn=tn+"";console[tcn]=("log" in console)?function(){var a=Array.apply({},arguments);a.unshift(tcn+":");console["log"](a.join(" "));}:function(){};console[tcn]._fake=true;})();}}}has.add("dojo-debug-messages",!!_1bd.isDebug);dojo.deprecated=dojo.experimental=function(){};if(has("dojo-debug-messages")){dojo.deprecated=function(_1c5,_1c6,_1c7){var _1c8="DEPRECATED: "+_1c5;if(_1c6){_1c8+=" "+_1c6;}if(_1c7){_1c8+=" -- will be removed in version: "+_1c7;}console.warn(_1c8);};dojo.experimental=function(_1c9,_1ca){var _1cb="EXPERIMENTAL: "+_1c9+" -- APIs subject to change without notice.";if(_1ca){_1cb+=" "+_1ca;}console.warn(_1cb);};}1||has.add("dojo-modulePaths",1);if(1){if(_1bd.modulePaths){dojo.deprecated("dojo.modulePaths","use paths configuration");var _1cc={};for(p in _1bd.modulePaths){_1cc[p.replace(/\./g,"/")]=_1bd.modulePaths[p];}_1be({paths:_1cc});}}1||has.add("dojo-moduleUrl",1);if(1){dojo.moduleUrl=function(_1cd,url){dojo.deprecated("dojo.moduleUrl()","use require.toUrl","2.0");var _1ce=null;if(_1cd){_1ce=_1be.toUrl(_1cd.replace(/\./g,"/")+(url?("/"+url):"")+"/*.*").replace(/\/\*\.\*/,"")+(url?"":"/");}return _1ce;};}dojo._hasResource={};return dojo;});},"dojo/io-query":function(){define(["./_base/lang"],function(lang){var _1cf={};return {objectToQuery:function objectToQuery(map){var enc=encodeURIComponent,_1d0=[];for(var name in map){var _1d1=map[name];if(_1d1!=_1cf[name]){var _1d2=enc(name)+"=";if(lang.isArray(_1d1)){for(var i=0,l=_1d1.length;i<l;++i){_1d0.push(_1d2+enc(_1d1[i]));}}else{_1d0.push(_1d2+enc(_1d1));}}}return _1d0.join("&");},queryToObject:function queryToObject(str){var dec=decodeURIComponent,qp=str.split("&"),ret={},name,val;for(var i=0,l=qp.length,item;i<l;++i){item=qp[i];if(item.length){var s=item.indexOf("=");if(s<0){name=dec(item);val="";}else{name=dec(item.slice(0,s));val=dec(item.slice(s+1));}if(typeof ret[name]=="string"){ret[name]=[ret[name]];}if(lang.isArray(ret[name])){ret[name].push(val);}else{ret[name]=val;}}}return ret;}};});},"dojo/_base/Deferred":function(){define(["./kernel","../Deferred","../promise/Promise","../errors/CancelError","../has","./lang","../when"],function(dojo,_1d3,_1d4,_1d5,has,lang,when){var _1d6=function(){};var _1d7=Object.freeze||function(){};var _1d8=dojo.Deferred=function(_1d9){var _1da,_1db,_1dc,head,_1dd;var _1de=(this.promise=new _1d4());function _1df(_1e0){if(_1db){throw new Error("This deferred has already been resolved");}_1da=_1e0;_1db=true;_1e1();};function _1e1(){var _1e2;while(!_1e2&&_1dd){var _1e3=_1dd;_1dd=_1dd.next;if((_1e2=(_1e3.progress==_1d6))){_1db=false;}var func=(_1dc?_1e3.error:_1e3.resolved);if(has("config-useDeferredInstrumentation")){if(_1dc&&_1d3.instrumentRejected){_1d3.instrumentRejected(_1da,!!func);}}if(func){try{var _1e4=func(_1da);if(_1e4&&typeof _1e4.then==="function"){_1e4.then(lang.hitch(_1e3.deferred,"resolve"),lang.hitch(_1e3.deferred,"reject"),lang.hitch(_1e3.deferred,"progress"));continue;}var _1e5=_1e2&&_1e4===undefined;if(_1e2&&!_1e5){_1dc=_1e4 instanceof Error;}_1e3.deferred[_1e5&&_1dc?"reject":"resolve"](_1e5?_1da:_1e4);}catch(e){_1e3.deferred.reject(e);}}else{if(_1dc){_1e3.deferred.reject(_1da);}else{_1e3.deferred.resolve(_1da);}}}};this.resolve=this.callback=function(_1e6){this.fired=0;this.results=[_1e6,null];_1df(_1e6);};this.reject=this.errback=function(_1e7){_1dc=true;this.fired=1;if(has("config-useDeferredInstrumentation")){if(_1d3.instrumentRejected){_1d3.instrumentRejected(_1e7,!!_1dd);}}_1df(_1e7);this.results=[null,_1e7];};this.progress=function(_1e8){var _1e9=_1dd;while(_1e9){var _1ea=_1e9.progress;_1ea&&_1ea(_1e8);_1e9=_1e9.next;}};this.addCallbacks=function(_1eb,_1ec){this.then(_1eb,_1ec,_1d6);return this;};_1de.then=this.then=function(_1ed,_1ee,_1ef){var _1f0=_1ef==_1d6?this:new _1d8(_1de.cancel);var _1f1={resolved:_1ed,error:_1ee,progress:_1ef,deferred:_1f0};if(_1dd){head=head.next=_1f1;}else{_1dd=head=_1f1;}if(_1db){_1e1();}return _1f0.promise;};var _1f2=this;_1de.cancel=this.cancel=function(){if(!_1db){var _1f3=_1d9&&_1d9(_1f2);if(!_1db){if(!(_1f3 instanceof Error)){_1f3=new _1d5(_1f3);}_1f3.log=false;_1f2.reject(_1f3);}}};_1d7(_1de);};lang.extend(_1d8,{addCallback:function(_1f4){return this.addCallbacks(lang.hitch.apply(dojo,arguments));},addErrback:function(_1f5){return this.addCallbacks(null,lang.hitch.apply(dojo,arguments));},addBoth:function(_1f6){var _1f7=lang.hitch.apply(dojo,arguments);return this.addCallbacks(_1f7,_1f7);},fired:-1});_1d8.when=dojo.when=when;return _1d8;});},"dojo/NodeList-dom":function(){define(["./_base/kernel","./query","./_base/array","./_base/lang","./dom-class","./dom-construct","./dom-geometry","./dom-attr","./dom-style"],function(dojo,_1f8,_1f9,lang,_1fa,_1fb,_1fc,_1fd,_1fe){var _1ff=function(a){return a.length==1&&(typeof a[0]=="string");};var _200=function(node){var p=node.parentNode;if(p){p.removeChild(node);}};var _201=_1f8.NodeList,awc=_201._adaptWithCondition,aafe=_201._adaptAsForEach,aam=_201._adaptAsMap;function _202(_203){return function(node,name,_204){if(arguments.length==2){return _203[typeof name=="string"?"get":"set"](node,name);}return _203.set(node,name,_204);};};lang.extend(_201,{_normalize:function(_205,_206){var _207=_205.parse===true;if(typeof _205.template=="string"){var _208=_205.templateFunc||(dojo.string&&dojo.string.substitute);_205=_208?_208(_205.template,_205):_205;}var type=(typeof _205);if(type=="string"||type=="number"){_205=_1fb.toDom(_205,(_206&&_206.ownerDocument));if(_205.nodeType==11){_205=lang._toArray(_205.childNodes);}else{_205=[_205];}}else{if(!lang.isArrayLike(_205)){_205=[_205];}else{if(!lang.isArray(_205)){_205=lang._toArray(_205);}}}if(_207){_205._runParse=true;}return _205;},_cloneNode:function(node){return node.cloneNode(true);},_place:function(ary,_209,_20a,_20b){if(_209.nodeType!=1&&_20a=="only"){return;}var _20c=_209,_20d;var _20e=ary.length;for(var i=_20e-1;i>=0;i--){var node=(_20b?this._cloneNode(ary[i]):ary[i]);if(ary._runParse&&dojo.parser&&dojo.parser.parse){if(!_20d){_20d=_20c.ownerDocument.createElement("div");}_20d.appendChild(node);dojo.parser.parse(_20d);node=_20d.firstChild;while(_20d.firstChild){_20d.removeChild(_20d.firstChild);}}if(i==_20e-1){_1fb.place(node,_20c,_20a);}else{_20c.parentNode.insertBefore(node,_20c);}_20c=node;}},position:aam(_1fc.position),attr:awc(_202(_1fd),_1ff),style:awc(_202(_1fe),_1ff),addClass:aafe(_1fa.add),removeClass:aafe(_1fa.remove),toggleClass:aafe(_1fa.toggle),replaceClass:aafe(_1fa.replace),empty:aafe(_1fb.empty),removeAttr:aafe(_1fd.remove),marginBox:aam(_1fc.getMarginBox),place:function(_20f,_210){var item=_1f8(_20f)[0];return this.forEach(function(node){_1fb.place(node,item,_210);});},orphan:function(_211){return (_211?_1f8._filterResult(this,_211):this).forEach(_200);},adopt:function(_212,_213){return _1f8(_212).place(this[0],_213)._stash(this);},query:function(_214){if(!_214){return this;}var ret=new _201;this.map(function(node){_1f8(_214,node).forEach(function(_215){if(_215!==undefined){ret.push(_215);}});});return ret._stash(this);},filter:function(_216){var a=arguments,_217=this,_218=0;if(typeof _216=="string"){_217=_1f8._filterResult(this,a[0]);if(a.length==1){return _217._stash(this);}_218=1;}return this._wrap(_1f9.filter(_217,a[_218],a[_218+1]),this);},addContent:function(_219,_21a){_219=this._normalize(_219,this[0]);for(var i=0,node;(node=this[i]);i++){this._place(_219,node,_21a,i>0);}return this;}});return _201;});},"dojo/query":function(){define(["./_base/kernel","./has","./dom","./on","./_base/array","./_base/lang","./selector/_loader","./selector/_loader!default"],function(dojo,has,dom,on,_21b,lang,_21c,_21d){"use strict";has.add("array-extensible",function(){return lang.delegate([],{length:1}).length==1&&!has("bug-for-in-skips-shadowed");});var ap=Array.prototype,aps=ap.slice,apc=ap.concat,_21e=_21b.forEach;var tnl=function(a,_21f,_220){var _221=new (_220||this._NodeListCtor||nl)(a);return _21f?_221._stash(_21f):_221;};var _222=function(f,a,o){a=[0].concat(aps.call(a,0));o=o||dojo.global;return function(node){a[0]=node;return f.apply(o,a);};};var _223=function(f,o){return function(){this.forEach(_222(f,arguments,o));return this;};};var _224=function(f,o){return function(){return this.map(_222(f,arguments,o));};};var _225=function(f,o){return function(){return this.filter(_222(f,arguments,o));};};var _226=function(f,g,o){return function(){var a=arguments,body=_222(f,a,o);if(g.call(o||dojo.global,a)){return this.map(body);}this.forEach(body);return this;};};var _227=function(_228){var _229=this instanceof nl&&has("array-extensible");if(typeof _228=="number"){_228=Array(_228);}var _22a=(_228&&"length" in _228)?_228:arguments;if(_229||!_22a.sort){var _22b=_229?this:[],l=_22b.length=_22a.length;for(var i=0;i<l;i++){_22b[i]=_22a[i];}if(_229){return _22b;}_22a=_22b;}lang._mixin(_22a,nlp);_22a._NodeListCtor=function(_22c){return nl(_22c);};return _22a;};var nl=_227,nlp=nl.prototype=has("array-extensible")?[]:{};nl._wrap=nlp._wrap=tnl;nl._adaptAsMap=_224;nl._adaptAsForEach=_223;nl._adaptAsFilter=_225;nl._adaptWithCondition=_226;_21e(["slice","splice"],function(name){var f=ap[name];nlp[name]=function(){return this._wrap(f.apply(this,arguments),name=="slice"?this:null);};});_21e(["indexOf","lastIndexOf","every","some"],function(name){var f=_21b[name];nlp[name]=function(){return f.apply(dojo,[this].concat(aps.call(arguments,0)));};});lang.extend(_227,{constructor:nl,_NodeListCtor:nl,toString:function(){return this.join(",");},_stash:function(_22d){this._parent=_22d;return this;},on:function(_22e,_22f){var _230=this.map(function(node){return on(node,_22e,_22f);});_230.remove=function(){for(var i=0;i<_230.length;i++){_230[i].remove();}};return _230;},end:function(){if(this._parent){return this._parent;}else{return new this._NodeListCtor(0);}},concat:function(item){var t=aps.call(this,0),m=_21b.map(arguments,function(a){return aps.call(a,0);});return this._wrap(apc.apply(t,m),this);},map:function(func,obj){return this._wrap(_21b.map(this,func,obj),this);},forEach:function(_231,_232){_21e(this,_231,_232);return this;},filter:function(_233){var a=arguments,_234=this,_235=0;if(typeof _233=="string"){_234=_236._filterResult(this,a[0]);if(a.length==1){return _234._stash(this);}_235=1;}return this._wrap(_21b.filter(_234,a[_235],a[_235+1]),this);},instantiate:function(_237,_238){var c=lang.isFunction(_237)?_237:lang.getObject(_237);_238=_238||{};return this.forEach(function(node){new c(_238,node);});},at:function(){var t=new this._NodeListCtor(0);_21e(arguments,function(i){if(i<0){i=this.length+i;}if(this[i]){t.push(this[i]);}},this);return t._stash(this);}});function _239(_23a,_23b){var _23c=function(_23d,root){if(typeof root=="string"){root=dom.byId(root);if(!root){return new _23b([]);}}var _23e=typeof _23d=="string"?_23a(_23d,root):_23d?_23d.orphan?_23d:[_23d]:[];if(_23e.orphan){return _23e;}return new _23b(_23e);};_23c.matches=_23a.match||function(node,_23f,root){return _23c.filter([node],_23f,root).length>0;};_23c.filter=_23a.filter||function(_240,_241,root){return _23c(_241,root).filter(function(node){return _21b.indexOf(_240,node)>-1;});};if(typeof _23a!="function"){var _242=_23a.search;_23a=function(_243,root){return _242(root||document,_243);};}return _23c;};var _236=_239(_21d,_227);dojo.query=_239(_21d,function(_244){return _227(_244);});_236.load=function(id,_245,_246){_21c.load(id,_245,function(_247){_246(_239(_247,_227));});};dojo._filterQueryResult=_236._filterResult=function(_248,_249,root){return new _227(_236.filter(_248,_249,root));};dojo.NodeList=_236.NodeList=_227;return _236;});},"dojo/has":function(){define(["require","module"],function(_24a,_24b){var has=_24a.has||function(){};if(!1){var _24c=typeof window!="undefined"&&typeof location!="undefined"&&typeof document!="undefined"&&window.location==location&&window.document==document,_24d=this,doc=_24c&&document,_24e=doc&&doc.createElement("DiV"),_24f=(_24b.config&&_24b.config())||{};has=function(name){return typeof _24f[name]=="function"?(_24f[name]=_24f[name](_24d,doc,_24e)):_24f[name];};has.cache=_24f;has.add=function(name,test,now,_250){(typeof _24f[name]=="undefined"||_250)&&(_24f[name]=test);return now&&has(name);};1||has.add("host-browser",_24c);1||has.add("dom",_24c);1||has.add("dojo-dom-ready-api",1);1||has.add("dojo-sniff",1);}if(1){has.add("dom-addeventlistener",!!document.addEventListener);has.add("touch","ontouchstart" in document);has.add("device-width",screen.availWidth||innerWidth);var form=document.createElement("form");has.add("dom-attributes-explicit",form.attributes.length==0);has.add("dom-attributes-specified-flag",form.attributes.length>0&&form.attributes.length<40);}has.clearElement=function(_251){_251.innerHTML="";return _251;};has.normalize=function(id,_252){var _253=id.match(/[\?:]|[^:\?]*/g),i=0,get=function(skip){var term=_253[i++];if(term==":"){return 0;}else{if(_253[i++]=="?"){if(!skip&&has(term)){return get();}else{get(true);return get(skip);}}return term||0;}};id=get();return id&&_252(id);};has.load=function(id,_254,_255){if(id){_254([id],_255);}else{_255();}};return has;});},"dojo/_base/loader":function(){define(["./kernel","../has","require","module","./json","./lang","./array"],function(dojo,has,_256,_257,json,lang,_258){if(!1){console.error("cannot load the Dojo v1.x loader with a foreign loader");return 0;}1||has.add("dojo-fast-sync-require",1);var _259=function(id){return {src:_257.id,id:id};},_25a=function(name){return name.replace(/\./g,"/");},_25b=/\/\/>>built/,_25c=[],_25d=[],_25e=function(mid,_25f,_260){_25c.push(_260);_258.forEach(mid.split(","),function(mid){var _261=_262(mid,_25f.module);_25d.push(_261);_263(_261);});_264();},_264=(1?function(){var _265,mid;for(mid in _266){_265=_266[mid];if(_265.noReqPluginCheck===undefined){_265.noReqPluginCheck=/loadInit\!/.test(mid)||/require\!/.test(mid)?1:0;}if(!_265.executed&&!_265.noReqPluginCheck&&_265.injected==_267){return;}}_268(function(){var _269=_25c;_25c=[];_258.forEach(_269,function(cb){cb(1);});});}:(function(){var _26a,_26b=function(m){_26a[m.mid]=1;for(var t,_26c,deps=m.deps||[],i=0;i<deps.length;i++){_26c=deps[i];if(!(t=_26a[_26c.mid])){if(t===0||!_26b(_26c)){_26a[m.mid]=0;return false;}}}return true;};return function(){var _26d,mid;_26a={};for(mid in _266){_26d=_266[mid];if(_26d.executed||_26d.noReqPluginCheck){_26a[mid]=1;}else{if(_26d.noReqPluginCheck!==0){_26d.noReqPluginCheck=/loadInit\!/.test(mid)||/require\!/.test(mid)?1:0;}if(_26d.noReqPluginCheck){_26a[mid]=1;}else{if(_26d.injected!==_299){_26a[mid]=0;}}}}for(var t,i=0,end=_25d.length;i<end;i++){_26d=_25d[i];if(!(t=_26a[_26d.mid])){if(t===0||!_26b(_26d)){return;}}}_268(function(){var _26e=_25c;_25c=[];_258.forEach(_26e,function(cb){cb(1);});});};})()),_26f=function(mid,_270,_271){_270([mid],function(_272){_270(_272.names,function(){for(var _273="",args=[],i=0;i<arguments.length;i++){_273+="var "+_272.names[i]+"= arguments["+i+"]; ";args.push(arguments[i]);}eval(_273);var _274=_270.module,_275=[],_276,_277={provide:function(_278){_278=_25a(_278);var _279=_262(_278,_274);if(_279!==_274){_29f(_279);}},require:function(_27a,_27b){_27a=_25a(_27a);_27b&&(_262(_27a,_274).result=_29a);_275.push(_27a);},requireLocalization:function(_27c,_27d,_27e){if(!_276){_276=["dojo/i18n"];}_27e=(_27e||dojo.locale).toLowerCase();_27c=_25a(_27c)+"/nls/"+(/root/i.test(_27e)?"":_27e+"/")+_25a(_27d);if(_262(_27c,_274).isXd){_276.push("dojo/i18n!"+_27c);}},loadInit:function(f){f();}},hold={},p;try{for(p in _277){hold[p]=dojo[p];dojo[p]=_277[p];}_272.def.apply(null,args);}catch(e){_27f("error",[_259("failedDojoLoadInit"),e]);}finally{for(p in _277){dojo[p]=hold[p];}}if(_276){_275=_275.concat(_276);}if(_275.length){_25e(_275.join(","),_270,_271);}else{_271();}});});},_280=function(text,_281,_282){var _283=/\(|\)/g,_284=1,_285;_283.lastIndex=_281;while((_285=_283.exec(text))){if(_285[0]==")"){_284-=1;}else{_284+=1;}if(_284==0){break;}}if(_284!=0){throw "unmatched paren around character "+_283.lastIndex+" in: "+text;}return [dojo.trim(text.substring(_282,_283.lastIndex))+";\n",_283.lastIndex];},_286=/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,_287=/(^|\s)dojo\.(loadInit|require|provide|requireLocalization|requireIf|requireAfterIf|platformRequire)\s*\(/mg,_288=/(^|\s)(require|define)\s*\(/m,_289=function(text,_28a){var _28b,_28c,_28d,_28e,_28f=[],_290=[],_291=[];_28a=_28a||text.replace(_286,function(_292){_287.lastIndex=_288.lastIndex=0;return (_287.test(_292)||_288.test(_292))?"":_292;});while((_28b=_287.exec(_28a))){_28c=_287.lastIndex;_28d=_28c-_28b[0].length;_28e=_280(_28a,_28c,_28d);if(_28b[2]=="loadInit"){_28f.push(_28e[0]);}else{_290.push(_28e[0]);}_287.lastIndex=_28e[1];}_291=_28f.concat(_290);if(_291.length||!_288.test(_28a)){return [text.replace(/(^|\s)dojo\.loadInit\s*\(/g,"\n0 && dojo.loadInit("),_291.join(""),_291];}else{return 0;}},_293=function(_294,text){var _295,id,_296=[],_297=[];if(_25b.test(text)||!(_295=_289(text))){return 0;}id=_294.mid+"-*loadInit";for(var p in _262("dojo",_294).result.scopeMap){_296.push(p);_297.push("\""+p+"\"");}return "// xdomain rewrite of "+_294.mid+"\n"+"define('"+id+"',{\n"+"\tnames:"+dojo.toJson(_296)+",\n"+"\tdef:function("+_296.join(",")+"){"+_295[1]+"}"+"});\n\n"+"define("+dojo.toJson(_296.concat(["dojo/loadInit!"+id]))+", function("+_296.join(",")+"){\n"+_295[0]+"});";},_298=_256.initSyncLoader(_25e,_264,_293),sync=_298.sync,_267=_298.requested,_299=_298.arrived,_29a=_298.nonmodule,_29b=_298.executing,_29c=_298.executed,_29d=_298.syncExecStack,_266=_298.modules,_29e=_298.execQ,_262=_298.getModule,_263=_298.injectModule,_29f=_298.setArrived,_27f=_298.signal,_2a0=_298.finishExec,_2a1=_298.execModule,_2a2=_298.getLegacyMode,_268=_298.guardCheckComplete;_25e=_298.dojoRequirePlugin;dojo.provide=function(mid){var _2a3=_29d[0],_2a4=lang.mixin(_262(_25a(mid),_256.module),{executed:_29b,result:lang.getObject(mid,true)});_29f(_2a4);if(_2a3){(_2a3.provides||(_2a3.provides=[])).push(function(){_2a4.result=lang.getObject(mid);delete _2a4.provides;_2a4.executed!==_29c&&_2a0(_2a4);});}return _2a4.result;};has.add("config-publishRequireResult",1,0,0);dojo.require=function(_2a5,_2a6){function _2a7(mid,_2a8){var _2a9=_262(_25a(mid),_256.module);if(_29d.length&&_29d[0].finish){_29d[0].finish.push(mid);return undefined;}if(_2a9.executed){return _2a9.result;}_2a8&&(_2a9.result=_29a);var _2aa=_2a2();_263(_2a9);_2aa=_2a2();if(_2a9.executed!==_29c&&_2a9.injected===_299){_298.guardCheckComplete(function(){_2a1(_2a9);});}if(_2a9.executed){return _2a9.result;}if(_2aa==sync){if(_2a9.cjs){_29e.unshift(_2a9);}else{_29d.length&&(_29d[0].finish=[mid]);}}else{_29e.push(_2a9);}return undefined;};var _2ab=_2a7(_2a5,_2a6);if(has("config-publishRequireResult")&&!lang.exists(_2a5)&&_2ab!==undefined){lang.setObject(_2a5,_2ab);}return _2ab;};dojo.loadInit=function(f){f();};dojo.registerModulePath=function(_2ac,_2ad){var _2ae={};_2ae[_2ac.replace(/\./g,"/")]=_2ad;_256({paths:_2ae});};dojo.platformRequire=function(_2af){var _2b0=(_2af.common||[]).concat(_2af[dojo._name]||_2af["default"]||[]),temp;while(_2b0.length){if(lang.isArray(temp=_2b0.shift())){dojo.require.apply(dojo,temp);}else{dojo.require(temp);}}};dojo.requireIf=dojo.requireAfterIf=function(_2b1,_2b2,_2b3){if(_2b1){dojo.require(_2b2,_2b3);}};dojo.requireLocalization=function(_2b4,_2b5,_2b6){_256(["../i18n"],function(i18n){i18n.getLocalization(_2b4,_2b5,_2b6);});};return {extractLegacyApiApplications:_289,require:_25e,loadInit:_26f};});},"dojo/json":function(){define(["./has"],function(has){"use strict";var _2b7=typeof JSON!="undefined";has.add("json-parse",_2b7);has.add("json-stringify",_2b7&&JSON.stringify({a:0},function(k,v){return v||1;})=="{\"a\":1}");if(has("json-stringify")){return JSON;}else{var _2b8=function(str){return ("\""+str.replace(/(["\\])/g,"\\$1")+"\"").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r");};return {parse:has("json-parse")?JSON.parse:function(str,_2b9){if(_2b9&&!/^([\s\[\{]*(?:"(?:\\.|[^"])+"|-?\d[\d\.]*(?:[Ee][+-]?\d+)?|null|true|false|)[\s\]\}]*(?:,|:|$))+$/.test(str)){throw new SyntaxError("Invalid characters in JSON");}return eval("("+str+")");},stringify:function(_2ba,_2bb,_2bc){var _2bd;if(typeof _2bb=="string"){_2bc=_2bb;_2bb=null;}function _2be(it,_2bf,key){if(_2bb){it=_2bb(key,it);}var val,_2c0=typeof it;if(_2c0=="number"){return isFinite(it)?it+"":"null";}if(_2c0=="boolean"){return it+"";}if(it===null){return "null";}if(typeof it=="string"){return _2b8(it);}if(_2c0=="function"||_2c0=="undefined"){return _2bd;}if(typeof it.toJSON=="function"){return _2be(it.toJSON(key),_2bf,key);}if(it instanceof Date){return "\"{FullYear}-{Month+}-{Date}T{Hours}:{Minutes}:{Seconds}Z\"".replace(/\{(\w+)(\+)?\}/g,function(t,prop,plus){var num=it["getUTC"+prop]()+(plus?1:0);return num<10?"0"+num:num;});}if(it.valueOf()!==it){return _2be(it.valueOf(),_2bf,key);}var _2c1=_2bc?(_2bf+_2bc):"";var sep=_2bc?" ":"";var _2c2=_2bc?"\n":"";if(it instanceof Array){var itl=it.length,res=[];for(key=0;key<itl;key++){var obj=it[key];val=_2be(obj,_2c1,key);if(typeof val!="string"){val="null";}res.push(_2c2+_2c1+val);}return "["+res.join(",")+_2c2+_2bf+"]";}var _2c3=[];for(key in it){var _2c4;if(it.hasOwnProperty(key)){if(typeof key=="number"){_2c4="\""+key+"\"";}else{if(typeof key=="string"){_2c4=_2b8(key);}else{continue;}}val=_2be(it[key],_2c1,key);if(typeof val!="string"){continue;}_2c3.push(_2c2+_2c1+_2c4+":"+sep+val);}}return "{"+_2c3.join(",")+_2c2+_2bf+"}";};return _2be(_2ba,"","");}};}});},"dojo/_base/declare":function(){define(["./kernel","../has","./lang"],function(dojo,has,lang){var mix=lang.mixin,op=Object.prototype,opts=op.toString,xtor=new Function,_2c5=0,_2c6="constructor";function err(msg,cls){throw new Error("declare"+(cls?" "+cls:"")+": "+msg);};function _2c7(_2c8,_2c9){var _2ca=[],_2cb=[{cls:0,refs:[]}],_2cc={},_2cd=1,l=_2c8.length,i=0,j,lin,base,top,_2ce,rec,name,refs;for(;i<l;++i){base=_2c8[i];if(!base){err("mixin #"+i+" is unknown. Did you use dojo.require to pull it in?",_2c9);}else{if(opts.call(base)!="[object Function]"){err("mixin #"+i+" is not a callable constructor.",_2c9);}}lin=base._meta?base._meta.bases:[base];top=0;for(j=lin.length-1;j>=0;--j){_2ce=lin[j].prototype;if(!_2ce.hasOwnProperty("declaredClass")){_2ce.declaredClass="uniqName_"+(_2c5++);}name=_2ce.declaredClass;if(!_2cc.hasOwnProperty(name)){_2cc[name]={count:0,refs:[],cls:lin[j]};++_2cd;}rec=_2cc[name];if(top&&top!==rec){rec.refs.push(top);++top.count;}top=rec;}++top.count;_2cb[0].refs.push(top);}while(_2cb.length){top=_2cb.pop();_2ca.push(top.cls);--_2cd;while(refs=top.refs,refs.length==1){top=refs[0];if(!top||--top.count){top=0;break;}_2ca.push(top.cls);--_2cd;}if(top){for(i=0,l=refs.length;i<l;++i){top=refs[i];if(!--top.count){_2cb.push(top);}}}}if(_2cd){err("can't build consistent linearization",_2c9);}base=_2c8[0];_2ca[0]=base?base._meta&&base===_2ca[_2ca.length-base._meta.bases.length]?base._meta.bases.length:1:0;return _2ca;};function _2cf(args,a,f){var name,_2d0,_2d1,_2d2,meta,base,_2d3,opf,pos,_2d4=this._inherited=this._inherited||{};if(typeof args=="string"){name=args;args=a;a=f;}f=0;_2d2=args.callee;name=name||_2d2.nom;if(!name){err("can't deduce a name to call inherited()",this.declaredClass);}meta=this.constructor._meta;_2d1=meta.bases;pos=_2d4.p;if(name!=_2c6){if(_2d4.c!==_2d2){pos=0;base=_2d1[0];meta=base._meta;if(meta.hidden[name]!==_2d2){_2d0=meta.chains;if(_2d0&&typeof _2d0[name]=="string"){err("calling chained method with inherited: "+name,this.declaredClass);}do{meta=base._meta;_2d3=base.prototype;if(meta&&(_2d3[name]===_2d2&&_2d3.hasOwnProperty(name)||meta.hidden[name]===_2d2)){break;}}while(base=_2d1[++pos]);pos=base?pos:-1;}}base=_2d1[++pos];if(base){_2d3=base.prototype;if(base._meta&&_2d3.hasOwnProperty(name)){f=_2d3[name];}else{opf=op[name];do{_2d3=base.prototype;f=_2d3[name];if(f&&(base._meta?_2d3.hasOwnProperty(name):f!==opf)){break;}}while(base=_2d1[++pos]);}}f=base&&f||op[name];}else{if(_2d4.c!==_2d2){pos=0;meta=_2d1[0]._meta;if(meta&&meta.ctor!==_2d2){_2d0=meta.chains;if(!_2d0||_2d0.constructor!=="manual"){err("calling chained constructor with inherited",this.declaredClass);}while(base=_2d1[++pos]){meta=base._meta;if(meta&&meta.ctor===_2d2){break;}}pos=base?pos:-1;}}while(base=_2d1[++pos]){meta=base._meta;f=meta?meta.ctor:base;if(f){break;}}f=base&&f;}_2d4.c=f;_2d4.p=pos;if(f){return a===true?f:f.apply(this,a||args);}};function _2d5(name,args){if(typeof name=="string"){return this.__inherited(name,args,true);}return this.__inherited(name,true);};function _2d6(args,a1,a2){var f=this.getInherited(args,a1);if(f){return f.apply(this,a2||a1||args);}};var _2d7=dojo.config.isDebug?_2d6:_2cf;function _2d8(cls){var _2d9=this.constructor._meta.bases;for(var i=0,l=_2d9.length;i<l;++i){if(_2d9[i]===cls){return true;}}return this instanceof cls;};function _2da(_2db,_2dc){for(var name in _2dc){if(name!=_2c6&&_2dc.hasOwnProperty(name)){_2db[name]=_2dc[name];}}if(has("bug-for-in-skips-shadowed")){for(var _2dd=lang._extraNames,i=_2dd.length;i;){name=_2dd[--i];if(name!=_2c6&&_2dc.hasOwnProperty(name)){_2db[name]=_2dc[name];}}}};function _2de(_2df,_2e0){var name,t;for(name in _2e0){t=_2e0[name];if((t!==op[name]||!(name in op))&&name!=_2c6){if(opts.call(t)=="[object Function]"){t.nom=name;}_2df[name]=t;}}if(has("bug-for-in-skips-shadowed")){for(var _2e1=lang._extraNames,i=_2e1.length;i;){name=_2e1[--i];t=_2e0[name];if((t!==op[name]||!(name in op))&&name!=_2c6){if(opts.call(t)=="[object Function]"){t.nom=name;}_2df[name]=t;}}}return _2df;};function _2e2(_2e3){_2e4.safeMixin(this.prototype,_2e3);return this;};function _2e5(_2e6){return _2e4([this].concat(_2e6));};function _2e7(_2e8,_2e9){return function(){var a=arguments,args=a,a0=a[0],f,i,m,l=_2e8.length,_2ea;if(!(this instanceof a.callee)){return _2eb(a);}if(_2e9&&(a0&&a0.preamble||this.preamble)){_2ea=new Array(_2e8.length);_2ea[0]=a;for(i=0;;){a0=a[0];if(a0){f=a0.preamble;if(f){a=f.apply(this,a)||a;}}f=_2e8[i].prototype;f=f.hasOwnProperty("preamble")&&f.preamble;if(f){a=f.apply(this,a)||a;}if(++i==l){break;}_2ea[i]=a;}}for(i=l-1;i>=0;--i){f=_2e8[i];m=f._meta;f=m?m.ctor:f;if(f){f.apply(this,_2ea?_2ea[i]:a);}}f=this.postscript;if(f){f.apply(this,args);}};};function _2ec(ctor,_2ed){return function(){var a=arguments,t=a,a0=a[0],f;if(!(this instanceof a.callee)){return _2eb(a);}if(_2ed){if(a0){f=a0.preamble;if(f){t=f.apply(this,t)||t;}}f=this.preamble;if(f){f.apply(this,t);}}if(ctor){ctor.apply(this,a);}f=this.postscript;if(f){f.apply(this,a);}};};function _2ee(_2ef){return function(){var a=arguments,i=0,f,m;if(!(this instanceof a.callee)){return _2eb(a);}for(;f=_2ef[i];++i){m=f._meta;f=m?m.ctor:f;if(f){f.apply(this,a);break;}}f=this.postscript;if(f){f.apply(this,a);}};};function _2f0(name,_2f1,_2f2){return function(){var b,m,f,i=0,step=1;if(_2f2){i=_2f1.length-1;step=-1;}for(;b=_2f1[i];i+=step){m=b._meta;f=(m?m.hidden:b.prototype)[name];if(f){f.apply(this,arguments);}}};};function _2f3(ctor){xtor.prototype=ctor.prototype;var t=new xtor;xtor.prototype=null;return t;};function _2eb(args){var ctor=args.callee,t=_2f3(ctor);ctor.apply(t,args);return t;};function _2e4(_2f4,_2f5,_2f6){if(typeof _2f4!="string"){_2f6=_2f5;_2f5=_2f4;_2f4="";}_2f6=_2f6||{};var _2f7,i,t,ctor,name,_2f8,_2f9,_2fa=1,_2fb=_2f5;if(opts.call(_2f5)=="[object Array]"){_2f8=_2c7(_2f5,_2f4);t=_2f8[0];_2fa=_2f8.length-t;_2f5=_2f8[_2fa];}else{_2f8=[0];if(_2f5){if(opts.call(_2f5)=="[object Function]"){t=_2f5._meta;_2f8=_2f8.concat(t?t.bases:_2f5);}else{err("base class is not a callable constructor.",_2f4);}}else{if(_2f5!==null){err("unknown base class. Did you use dojo.require to pull it in?",_2f4);}}}if(_2f5){for(i=_2fa-1;;--i){_2f7=_2f3(_2f5);if(!i){break;}t=_2f8[i];(t._meta?_2da:mix)(_2f7,t.prototype);ctor=new Function;ctor.superclass=_2f5;ctor.prototype=_2f7;_2f5=_2f7.constructor=ctor;}}else{_2f7={};}_2e4.safeMixin(_2f7,_2f6);t=_2f6.constructor;if(t!==op.constructor){t.nom=_2c6;_2f7.constructor=t;}for(i=_2fa-1;i;--i){t=_2f8[i]._meta;if(t&&t.chains){_2f9=mix(_2f9||{},t.chains);}}if(_2f7["-chains-"]){_2f9=mix(_2f9||{},_2f7["-chains-"]);}t=!_2f9||!_2f9.hasOwnProperty(_2c6);_2f8[0]=ctor=(_2f9&&_2f9.constructor==="manual")?_2ee(_2f8):(_2f8.length==1?_2ec(_2f6.constructor,t):_2e7(_2f8,t));ctor._meta={bases:_2f8,hidden:_2f6,chains:_2f9,parents:_2fb,ctor:_2f6.constructor};ctor.superclass=_2f5&&_2f5.prototype;ctor.extend=_2e2;ctor.createSubclass=_2e5;ctor.prototype=_2f7;_2f7.constructor=ctor;_2f7.getInherited=_2d5;_2f7.isInstanceOf=_2d8;_2f7.inherited=_2d7;_2f7.__inherited=_2cf;if(_2f4){_2f7.declaredClass=_2f4;lang.setObject(_2f4,ctor);}if(_2f9){for(name in _2f9){if(_2f7[name]&&typeof _2f9[name]=="string"&&name!=_2c6){t=_2f7[name]=_2f0(name,_2f8,_2f9[name]==="after");t.nom=name;}}}return ctor;};dojo.safeMixin=_2e4.safeMixin=_2de;dojo.declare=_2e4;return _2e4;});},"dojo/dom":function(){define(["./sniff","./_base/lang","./_base/window"],function(has,lang,win){if(has("ie")<=7){try{document.execCommand("BackgroundImageCache",false,true);}catch(e){}}var dom={};if(has("ie")){dom.byId=function(id,doc){if(typeof id!="string"){return id;}var _2fc=doc||win.doc,te=id&&_2fc.getElementById(id);if(te&&(te.attributes.id.value==id||te.id==id)){return te;}else{var eles=_2fc.all[id];if(!eles||eles.nodeName){eles=[eles];}var i=0;while((te=eles[i++])){if((te.attributes&&te.attributes.id&&te.attributes.id.value==id)||te.id==id){return te;}}}};}else{dom.byId=function(id,doc){return ((typeof id=="string")?(doc||win.doc).getElementById(id):id)||null;};}dom.isDescendant=function(node,_2fd){try{node=dom.byId(node);_2fd=dom.byId(_2fd);while(node){if(node==_2fd){return true;}node=node.parentNode;}}catch(e){}return false;};dom.setSelectable=function(node,_2fe){node=dom.byId(node);if(has("mozilla")){node.style.MozUserSelect=_2fe?"":"none";}else{if(has("khtml")||has("webkit")){node.style.KhtmlUserSelect=_2fe?"auto":"none";}else{if(has("ie")){var v=(node.unselectable=_2fe?"":"on"),cs=node.getElementsByTagName("*"),i=0,l=cs.length;for(;i<l;++i){cs.item(i).unselectable=v;}}}}};return dom;});},"dojo/_base/browser":function(){if(require.has){require.has.add("config-selectorEngine","acme");}define(["../ready","./kernel","./connect","./unload","./window","./event","./html","./NodeList","../query","./xhr","./fx"],function(dojo){return dojo;});},"dojo/selector/acme":function(){define(["../dom","../sniff","../_base/array","../_base/lang","../_base/window"],function(dom,has,_2ff,lang,win){var trim=lang.trim;var each=_2ff.forEach;var _300=function(){return win.doc;};var _301=(_300().compatMode)=="BackCompat";var _302=">~+";var _303=false;var _304=function(){return true;};var _305=function(_306){if(_302.indexOf(_306.slice(-1))>=0){_306+=" * ";}else{_306+=" ";}var ts=function(s,e){return trim(_306.slice(s,e));};var _307=[];var _308=-1,_309=-1,_30a=-1,_30b=-1,_30c=-1,inId=-1,_30d=-1,_30e,lc="",cc="",_30f;var x=0,ql=_306.length,_310=null,_311=null;var _312=function(){if(_30d>=0){var tv=(_30d==x)?null:ts(_30d,x);_310[(_302.indexOf(tv)<0)?"tag":"oper"]=tv;_30d=-1;}};var _313=function(){if(inId>=0){_310.id=ts(inId,x).replace(/\\/g,"");inId=-1;}};var _314=function(){if(_30c>=0){_310.classes.push(ts(_30c+1,x).replace(/\\/g,""));_30c=-1;}};var _315=function(){_313();_312();_314();};var _316=function(){_315();if(_30b>=0){_310.pseudos.push({name:ts(_30b+1,x)});}_310.loops=(_310.pseudos.length||_310.attrs.length||_310.classes.length);_310.oquery=_310.query=ts(_30f,x);_310.otag=_310.tag=(_310["oper"])?null:(_310.tag||"*");if(_310.tag){_310.tag=_310.tag.toUpperCase();}if(_307.length&&(_307[_307.length-1].oper)){_310.infixOper=_307.pop();_310.query=_310.infixOper.query+" "+_310.query;}_307.push(_310);_310=null;};for(;lc=cc,cc=_306.charAt(x),x<ql;x++){if(lc=="\\"){continue;}if(!_310){_30f=x;_310={query:null,pseudos:[],attrs:[],classes:[],tag:null,oper:null,id:null,getTag:function(){return _303?this.otag:this.tag;}};_30d=x;}if(_30e){if(cc==_30e){_30e=null;}continue;}else{if(cc=="'"||cc=="\""){_30e=cc;continue;}}if(_308>=0){if(cc=="]"){if(!_311.attr){_311.attr=ts(_308+1,x);}else{_311.matchFor=ts((_30a||_308+1),x);}var cmf=_311.matchFor;if(cmf){if((cmf.charAt(0)=="\"")||(cmf.charAt(0)=="'")){_311.matchFor=cmf.slice(1,-1);}}if(_311.matchFor){_311.matchFor=_311.matchFor.replace(/\\/g,"");}_310.attrs.push(_311);_311=null;_308=_30a=-1;}else{if(cc=="="){var _317=("|~^$*".indexOf(lc)>=0)?lc:"";_311.type=_317+cc;_311.attr=ts(_308+1,x-_317.length);_30a=x+1;}}}else{if(_309>=0){if(cc==")"){if(_30b>=0){_311.value=ts(_309+1,x);}_30b=_309=-1;}}else{if(cc=="#"){_315();inId=x+1;}else{if(cc=="."){_315();_30c=x;}else{if(cc==":"){_315();_30b=x;}else{if(cc=="["){_315();_308=x;_311={};}else{if(cc=="("){if(_30b>=0){_311={name:ts(_30b+1,x),value:null};_310.pseudos.push(_311);}_309=x;}else{if((cc==" ")&&(lc!=cc)){_316();}}}}}}}}}return _307;};var _318=function(_319,_31a){if(!_319){return _31a;}if(!_31a){return _319;}return function(){return _319.apply(window,arguments)&&_31a.apply(window,arguments);};};var _31b=function(i,arr){var r=arr||[];if(i){r.push(i);}return r;};var _31c=function(n){return (1==n.nodeType);};var _31d="";var _31e=function(elem,attr){if(!elem){return _31d;}if(attr=="class"){return elem.className||_31d;}if(attr=="for"){return elem.htmlFor||_31d;}if(attr=="style"){return elem.style.cssText||_31d;}return (_303?elem.getAttribute(attr):elem.getAttribute(attr,2))||_31d;};var _31f={"*=":function(attr,_320){return function(elem){return (_31e(elem,attr).indexOf(_320)>=0);};},"^=":function(attr,_321){return function(elem){return (_31e(elem,attr).indexOf(_321)==0);};},"$=":function(attr,_322){return function(elem){var ea=" "+_31e(elem,attr);var _323=ea.lastIndexOf(_322);return _323>-1&&(_323==(ea.length-_322.length));};},"~=":function(attr,_324){var tval=" "+_324+" ";return function(elem){var ea=" "+_31e(elem,attr)+" ";return (ea.indexOf(tval)>=0);};},"|=":function(attr,_325){var _326=_325+"-";return function(elem){var ea=_31e(elem,attr);return ((ea==_325)||(ea.indexOf(_326)==0));};},"=":function(attr,_327){return function(elem){return (_31e(elem,attr)==_327);};}};var _328=(typeof _300().firstChild.nextElementSibling=="undefined");var _329=!_328?"nextElementSibling":"nextSibling";var _32a=!_328?"previousElementSibling":"previousSibling";var _32b=(_328?_31c:_304);var _32c=function(node){while(node=node[_32a]){if(_32b(node)){return false;}}return true;};var _32d=function(node){while(node=node[_329]){if(_32b(node)){return false;}}return true;};var _32e=function(node){var root=node.parentNode;root=root.nodeType!=7?root:root.nextSibling;var i=0,tret=root.children||root.childNodes,ci=(node["_i"]||node.getAttribute("_i")||-1),cl=(root["_l"]||(typeof root.getAttribute!=="undefined"?root.getAttribute("_l"):-1));if(!tret){return -1;}var l=tret.length;if(cl==l&&ci>=0&&cl>=0){return ci;}if(has("ie")&&typeof root.setAttribute!=="undefined"){root.setAttribute("_l",l);}else{root["_l"]=l;}ci=-1;for(var te=root["firstElementChild"]||root["firstChild"];te;te=te[_329]){if(_32b(te)){if(has("ie")){te.setAttribute("_i",++i);}else{te["_i"]=++i;}if(node===te){ci=i;}}}return ci;};var _32f=function(elem){return !((_32e(elem))%2);};var _330=function(elem){return ((_32e(elem))%2);};var _331={"checked":function(name,_332){return function(elem){return !!("checked" in elem?elem.checked:elem.selected);};},"disabled":function(name,_333){return function(elem){return elem.disabled;};},"enabled":function(name,_334){return function(elem){return !elem.disabled;};},"first-child":function(){return _32c;},"last-child":function(){return _32d;},"only-child":function(name,_335){return function(node){return _32c(node)&&_32d(node);};},"empty":function(name,_336){return function(elem){var cn=elem.childNodes;var cnl=elem.childNodes.length;for(var x=cnl-1;x>=0;x--){var nt=cn[x].nodeType;if((nt===1)||(nt==3)){return false;}}return true;};},"contains":function(name,_337){var cz=_337.charAt(0);if(cz=="\""||cz=="'"){_337=_337.slice(1,-1);}return function(elem){return (elem.innerHTML.indexOf(_337)>=0);};},"not":function(name,_338){var p=_305(_338)[0];var _339={el:1};if(p.tag!="*"){_339.tag=1;}if(!p.classes.length){_339.classes=1;}var ntf=_33a(p,_339);return function(elem){return (!ntf(elem));};},"nth-child":function(name,_33b){var pi=parseInt;if(_33b=="odd"){return _330;}else{if(_33b=="even"){return _32f;}}if(_33b.indexOf("n")!=-1){var _33c=_33b.split("n",2);var pred=_33c[0]?((_33c[0]=="-")?-1:pi(_33c[0])):1;var idx=_33c[1]?pi(_33c[1]):0;var lb=0,ub=-1;if(pred>0){if(idx<0){idx=(idx%pred)&&(pred+(idx%pred));}else{if(idx>0){if(idx>=pred){lb=idx-idx%pred;}idx=idx%pred;}}}else{if(pred<0){pred*=-1;if(idx>0){ub=idx;idx=idx%pred;}}}if(pred>0){return function(elem){var i=_32e(elem);return (i>=lb)&&(ub<0||i<=ub)&&((i%pred)==idx);};}else{_33b=idx;}}var _33d=pi(_33b);return function(elem){return (_32e(elem)==_33d);};}};var _33e=(has("ie")&&(has("ie")<9||has("quirks")))?function(cond){var clc=cond.toLowerCase();if(clc=="class"){cond="className";}return function(elem){return (_303?elem.getAttribute(cond):elem[cond]||elem[clc]);};}:function(cond){return function(elem){return (elem&&elem.getAttribute&&elem.hasAttribute(cond));};};var _33a=function(_33f,_340){if(!_33f){return _304;}_340=_340||{};var ff=null;if(!("el" in _340)){ff=_318(ff,_31c);}if(!("tag" in _340)){if(_33f.tag!="*"){ff=_318(ff,function(elem){return (elem&&((_303?elem.tagName:elem.tagName.toUpperCase())==_33f.getTag()));});}}if(!("classes" in _340)){each(_33f.classes,function(_341,idx,arr){var re=new RegExp("(?:^|\\s)"+_341+"(?:\\s|$)");ff=_318(ff,function(elem){return re.test(elem.className);});ff.count=idx;});}if(!("pseudos" in _340)){each(_33f.pseudos,function(_342){var pn=_342.name;if(_331[pn]){ff=_318(ff,_331[pn](pn,_342.value));}});}if(!("attrs" in _340)){each(_33f.attrs,function(attr){var _343;var a=attr.attr;if(attr.type&&_31f[attr.type]){_343=_31f[attr.type](a,attr.matchFor);}else{if(a.length){_343=_33e(a);}}if(_343){ff=_318(ff,_343);}});}if(!("id" in _340)){if(_33f.id){ff=_318(ff,function(elem){return (!!elem&&(elem.id==_33f.id));});}}if(!ff){if(!("default" in _340)){ff=_304;}}return ff;};var _344=function(_345){return function(node,ret,bag){while(node=node[_329]){if(_328&&(!_31c(node))){continue;}if((!bag||_346(node,bag))&&_345(node)){ret.push(node);}break;}return ret;};};var _347=function(_348){return function(root,ret,bag){var te=root[_329];while(te){if(_32b(te)){if(bag&&!_346(te,bag)){break;}if(_348(te)){ret.push(te);}}te=te[_329];}return ret;};};var _349=function(_34a){_34a=_34a||_304;return function(root,ret,bag){var te,x=0,tret=root.children||root.childNodes;while(te=tret[x++]){if(_32b(te)&&(!bag||_346(te,bag))&&(_34a(te,x))){ret.push(te);}}return ret;};};var _34b=function(node,root){var pn=node.parentNode;while(pn){if(pn==root){break;}pn=pn.parentNode;}return !!pn;};var _34c={};var _34d=function(_34e){var _34f=_34c[_34e.query];if(_34f){return _34f;}var io=_34e.infixOper;var oper=(io?io.oper:"");var _350=_33a(_34e,{el:1});var qt=_34e.tag;var _351=("*"==qt);var ecs=_300()["getElementsByClassName"];if(!oper){if(_34e.id){_350=(!_34e.loops&&_351)?_304:_33a(_34e,{el:1,id:1});_34f=function(root,arr){var te=dom.byId(_34e.id,(root.ownerDocument||root));if(!te||!_350(te)){return;}if(9==root.nodeType){return _31b(te,arr);}else{if(_34b(te,root)){return _31b(te,arr);}}};}else{if(ecs&&/\{\s*\[native code\]\s*\}/.test(String(ecs))&&_34e.classes.length&&!_301){_350=_33a(_34e,{el:1,classes:1,id:1});var _352=_34e.classes.join(" ");_34f=function(root,arr,bag){var ret=_31b(0,arr),te,x=0;var tret=root.getElementsByClassName(_352);while((te=tret[x++])){if(_350(te,root)&&_346(te,bag)){ret.push(te);}}return ret;};}else{if(!_351&&!_34e.loops){_34f=function(root,arr,bag){var ret=_31b(0,arr),te,x=0;var tag=_34e.getTag(),tret=tag?root.getElementsByTagName(tag):[];while((te=tret[x++])){if(_346(te,bag)){ret.push(te);}}return ret;};}else{_350=_33a(_34e,{el:1,tag:1,id:1});_34f=function(root,arr,bag){var ret=_31b(0,arr),te,x=0;var tag=_34e.getTag(),tret=tag?root.getElementsByTagName(tag):[];while((te=tret[x++])){if(_350(te,root)&&_346(te,bag)){ret.push(te);}}return ret;};}}}}else{var _353={el:1};if(_351){_353.tag=1;}_350=_33a(_34e,_353);if("+"==oper){_34f=_344(_350);}else{if("~"==oper){_34f=_347(_350);}else{if(">"==oper){_34f=_349(_350);}}}}return _34c[_34e.query]=_34f;};var _354=function(root,_355){var _356=_31b(root),qp,x,te,qpl=_355.length,bag,ret;for(var i=0;i<qpl;i++){ret=[];qp=_355[i];x=_356.length-1;if(x>0){bag={};ret.nozip=true;}var gef=_34d(qp);for(var j=0;(te=_356[j]);j++){gef(te,ret,bag);}if(!ret.length){break;}_356=ret;}return ret;};var _357={},_358={};var _359=function(_35a){var _35b=_305(trim(_35a));if(_35b.length==1){var tef=_34d(_35b[0]);return function(root){var r=tef(root,[]);if(r){r.nozip=true;}return r;};}return function(root){return _354(root,_35b);};};var _35c=has("ie")?"commentStrip":"nozip";var qsa="querySelectorAll";var _35d=!!_300()[qsa];var _35e=/\\[>~+]|n\+\d|([^ \\])?([>~+])([^ =])?/g;var _35f=function(_360,pre,ch,post){return ch?(pre?pre+" ":"")+ch+(post?" "+post:""):_360;};var _361=/([^[]*)([^\]]*])?/g;var _362=function(_363,_364,att){return _364.replace(_35e,_35f)+(att||"");};var _365=function(_366,_367){_366=_366.replace(_361,_362);if(_35d){var _368=_358[_366];if(_368&&!_367){return _368;}}var _369=_357[_366];if(_369){return _369;}var qcz=_366.charAt(0);var _36a=(-1==_366.indexOf(" "));if((_366.indexOf("#")>=0)&&(_36a)){_367=true;}var _36b=(_35d&&(!_367)&&(_302.indexOf(qcz)==-1)&&(!has("ie")||(_366.indexOf(":")==-1))&&(!(_301&&(_366.indexOf(".")>=0)))&&(_366.indexOf(":contains")==-1)&&(_366.indexOf(":checked")==-1)&&(_366.indexOf("|=")==-1));if(_36b){var tq=(_302.indexOf(_366.charAt(_366.length-1))>=0)?(_366+" *"):_366;return _358[_366]=function(root){try{if(!((9==root.nodeType)||_36a)){throw "";}var r=root[qsa](tq);r[_35c]=true;return r;}catch(e){return _365(_366,true)(root);}};}else{var _36c=_366.match(/([^\s,](?:"(?:\\.|[^"])+"|'(?:\\.|[^'])+'|[^,])*)/g);return _357[_366]=((_36c.length<2)?_359(_366):function(root){var _36d=0,ret=[],tp;while((tp=_36c[_36d++])){ret=ret.concat(_359(tp)(root));}return ret;});}};var _36e=0;var _36f=has("ie")?function(node){if(_303){return (node.getAttribute("_uid")||node.setAttribute("_uid",++_36e)||_36e);}else{return node.uniqueID;}}:function(node){return (node._uid||(node._uid=++_36e));};var _346=function(node,bag){if(!bag){return 1;}var id=_36f(node);if(!bag[id]){return bag[id]=1;}return 0;};var _370="_zipIdx";var _371=function(arr){if(arr&&arr.nozip){return arr;}var ret=[];if(!arr||!arr.length){return ret;}if(arr[0]){ret.push(arr[0]);}if(arr.length<2){return ret;}_36e++;var x,te;if(has("ie")&&_303){var _372=_36e+"";arr[0].setAttribute(_370,_372);for(x=1;te=arr[x];x++){if(arr[x].getAttribute(_370)!=_372){ret.push(te);}te.setAttribute(_370,_372);}}else{if(has("ie")&&arr.commentStrip){try{for(x=1;te=arr[x];x++){if(_31c(te)){ret.push(te);}}}catch(e){}}else{if(arr[0]){arr[0][_370]=_36e;}for(x=1;te=arr[x];x++){if(arr[x][_370]!=_36e){ret.push(te);}te[_370]=_36e;}}}return ret;};var _373=function(_374,root){root=root||_300();var od=root.ownerDocument||root;_303=(od.createElement("div").tagName==="div");var r=_365(_374)(root);if(r&&r.nozip){return r;}return _371(r);};_373.filter=function(_375,_376,root){var _377=[],_378=_305(_376),_379=(_378.length==1&&!/[^\w#\.]/.test(_376))?_33a(_378[0]):function(node){return _2ff.indexOf(_373(_376,dom.byId(root)),node)!=-1;};for(var x=0,te;te=_375[x];x++){if(_379(te)){_377.push(te);}}return _377;};return _373;});},"dojo/errors/RequestTimeoutError":function(){define("dojo/errors/RequestTimeoutError",["./create","./RequestError"],function(_37a,_37b){return _37a("RequestTimeoutError",null,_37b,{dojoType:"timeout"});});},"dojo/dom-geometry":function(){define(["./sniff","./_base/window","./dom","./dom-style"],function(has,win,dom,_37c){var geom={};geom.boxModel="content-box";if(has("ie")){geom.boxModel=document.compatMode=="BackCompat"?"border-box":"content-box";}geom.getPadExtents=function getPadExtents(node,_37d){node=dom.byId(node);var s=_37d||_37c.getComputedStyle(node),px=_37c.toPixelValue,l=px(node,s.paddingLeft),t=px(node,s.paddingTop),r=px(node,s.paddingRight),b=px(node,s.paddingBottom);return {l:l,t:t,r:r,b:b,w:l+r,h:t+b};};var none="none";geom.getBorderExtents=function getBorderExtents(node,_37e){node=dom.byId(node);var px=_37c.toPixelValue,s=_37e||_37c.getComputedStyle(node),l=s.borderLeftStyle!=none?px(node,s.borderLeftWidth):0,t=s.borderTopStyle!=none?px(node,s.borderTopWidth):0,r=s.borderRightStyle!=none?px(node,s.borderRightWidth):0,b=s.borderBottomStyle!=none?px(node,s.borderBottomWidth):0;return {l:l,t:t,r:r,b:b,w:l+r,h:t+b};};geom.getPadBorderExtents=function getPadBorderExtents(node,_37f){node=dom.byId(node);var s=_37f||_37c.getComputedStyle(node),p=geom.getPadExtents(node,s),b=geom.getBorderExtents(node,s);return {l:p.l+b.l,t:p.t+b.t,r:p.r+b.r,b:p.b+b.b,w:p.w+b.w,h:p.h+b.h};};geom.getMarginExtents=function getMarginExtents(node,_380){node=dom.byId(node);var s=_380||_37c.getComputedStyle(node),px=_37c.toPixelValue,l=px(node,s.marginLeft),t=px(node,s.marginTop),r=px(node,s.marginRight),b=px(node,s.marginBottom);return {l:l,t:t,r:r,b:b,w:l+r,h:t+b};};geom.getMarginBox=function getMarginBox(node,_381){node=dom.byId(node);var s=_381||_37c.getComputedStyle(node),me=geom.getMarginExtents(node,s),l=node.offsetLeft-me.l,t=node.offsetTop-me.t,p=node.parentNode,px=_37c.toPixelValue,pcs;if(has("mozilla")){var sl=parseFloat(s.left),st=parseFloat(s.top);if(!isNaN(sl)&&!isNaN(st)){l=sl;t=st;}else{if(p&&p.style){pcs=_37c.getComputedStyle(p);if(pcs.overflow!="visible"){l+=pcs.borderLeftStyle!=none?px(node,pcs.borderLeftWidth):0;t+=pcs.borderTopStyle!=none?px(node,pcs.borderTopWidth):0;}}}}else{if(has("opera")||(has("ie")==8&&!has("quirks"))){if(p){pcs=_37c.getComputedStyle(p);l-=pcs.borderLeftStyle!=none?px(node,pcs.borderLeftWidth):0;t-=pcs.borderTopStyle!=none?px(node,pcs.borderTopWidth):0;}}}return {l:l,t:t,w:node.offsetWidth+me.w,h:node.offsetHeight+me.h};};geom.getContentBox=function getContentBox(node,_382){node=dom.byId(node);var s=_382||_37c.getComputedStyle(node),w=node.clientWidth,h,pe=geom.getPadExtents(node,s),be=geom.getBorderExtents(node,s);if(!w){w=node.offsetWidth;h=node.offsetHeight;}else{h=node.clientHeight;be.w=be.h=0;}if(has("opera")){pe.l+=be.l;pe.t+=be.t;}return {l:pe.l,t:pe.t,w:w-pe.w-be.w,h:h-pe.h-be.h};};function _383(node,l,t,w,h,u){u=u||"px";var s=node.style;if(!isNaN(l)){s.left=l+u;}if(!isNaN(t)){s.top=t+u;}if(w>=0){s.width=w+u;}if(h>=0){s.height=h+u;}};function _384(node){return node.tagName.toLowerCase()=="button"||node.tagName.toLowerCase()=="input"&&(node.getAttribute("type")||"").toLowerCase()=="button";};function _385(node){return geom.boxModel=="border-box"||node.tagName.toLowerCase()=="table"||_384(node);};geom.setContentSize=function setContentSize(node,box,_386){node=dom.byId(node);var w=box.w,h=box.h;if(_385(node)){var pb=geom.getPadBorderExtents(node,_386);if(w>=0){w+=pb.w;}if(h>=0){h+=pb.h;}}_383(node,NaN,NaN,w,h);};var _387={l:0,t:0,w:0,h:0};geom.setMarginBox=function setMarginBox(node,box,_388){node=dom.byId(node);var s=_388||_37c.getComputedStyle(node),w=box.w,h=box.h,pb=_385(node)?_387:geom.getPadBorderExtents(node,s),mb=geom.getMarginExtents(node,s);if(has("webkit")){if(_384(node)){var ns=node.style;if(w>=0&&!ns.width){ns.width="4px";}if(h>=0&&!ns.height){ns.height="4px";}}}if(w>=0){w=Math.max(w-pb.w-mb.w,0);}if(h>=0){h=Math.max(h-pb.h-mb.h,0);}_383(node,box.l,box.t,w,h);};geom.isBodyLtr=function isBodyLtr(doc){doc=doc||win.doc;return (win.body(doc).dir||doc.documentElement.dir||"ltr").toLowerCase()=="ltr";};geom.docScroll=function docScroll(doc){doc=doc||win.doc;var node=win.doc.parentWindow||win.doc.defaultView;return "pageXOffset" in node?{x:node.pageXOffset,y:node.pageYOffset}:(node=has("quirks")?win.body(doc):doc.documentElement)&&{x:geom.fixIeBiDiScrollLeft(node.scrollLeft||0,doc),y:node.scrollTop||0};};if(has("ie")){geom.getIeDocumentElementOffset=function getIeDocumentElementOffset(doc){doc=doc||win.doc;var de=doc.documentElement;if(has("ie")<8){var r=de.getBoundingClientRect(),l=r.left,t=r.top;if(has("ie")<7){l+=de.clientLeft;t+=de.clientTop;}return {x:l<0?0:l,y:t<0?0:t};}else{return {x:0,y:0};}};}geom.fixIeBiDiScrollLeft=function fixIeBiDiScrollLeft(_389,doc){doc=doc||win.doc;var ie=has("ie");if(ie&&!geom.isBodyLtr(doc)){var qk=has("quirks"),de=qk?win.body(doc):doc.documentElement,pwin=win.global;if(ie==6&&!qk&&pwin.frameElement&&de.scrollHeight>de.clientHeight){_389+=de.clientLeft;}return (ie<8||qk)?(_389+de.clientWidth-de.scrollWidth):-_389;}return _389;};geom.position=function(node,_38a){node=dom.byId(node);var db=win.body(node.ownerDocument),ret=node.getBoundingClientRect();ret={x:ret.left,y:ret.top,w:ret.right-ret.left,h:ret.bottom-ret.top};if(has("ie")){var _38b=geom.getIeDocumentElementOffset(node.ownerDocument);ret.x-=_38b.x+(has("quirks")?db.clientLeft+db.offsetLeft:0);ret.y-=_38b.y+(has("quirks")?db.clientTop+db.offsetTop:0);}if(_38a){var _38c=geom.docScroll(node.ownerDocument);ret.x+=_38c.x;ret.y+=_38c.y;}return ret;};geom.getMarginSize=function getMarginSize(node,_38d){node=dom.byId(node);var me=geom.getMarginExtents(node,_38d||_37c.getComputedStyle(node));var size=node.getBoundingClientRect();return {w:(size.right-size.left)+me.w,h:(size.bottom-size.top)+me.h};};geom.normalizeEvent=function(_38e){if(!("layerX" in _38e)){_38e.layerX=_38e.offsetX;_38e.layerY=_38e.offsetY;}if(!has("dom-addeventlistener")){var se=_38e.target;var doc=(se&&se.ownerDocument)||document;var _38f=has("quirks")?doc.body:doc.documentElement;var _390=geom.getIeDocumentElementOffset(doc);_38e.pageX=_38e.clientX+geom.fixIeBiDiScrollLeft(_38f.scrollLeft||0,doc)-_390.x;_38e.pageY=_38e.clientY+(_38f.scrollTop||0)-_390.y;}};return geom;});},"dojo/dom-style":function(){define("dojo/dom-style",["./sniff","./dom"],function(has,dom){var _391,_392={};if(has("webkit")){_391=function(node){var s;if(node.nodeType==1){var dv=node.ownerDocument.defaultView;s=dv.getComputedStyle(node,null);if(!s&&node.style){node.style.display="";s=dv.getComputedStyle(node,null);}}return s||{};};}else{if(has("ie")&&(has("ie")<9||has("quirks"))){_391=function(node){return node.nodeType==1&&node.currentStyle?node.currentStyle:{};};}else{_391=function(node){return node.nodeType==1?node.ownerDocument.defaultView.getComputedStyle(node,null):{};};}}_392.getComputedStyle=_391;var _393;if(!has("ie")){_393=function(_394,_395){return parseFloat(_395)||0;};}else{_393=function(_396,_397){if(!_397){return 0;}if(_397=="medium"){return 4;}if(_397.slice&&_397.slice(-2)=="px"){return parseFloat(_397);}var s=_396.style,rs=_396.runtimeStyle,cs=_396.currentStyle,_398=s.left,_399=rs.left;rs.left=cs.left;try{s.left=_397;_397=s.pixelLeft;}catch(e){_397=0;}s.left=_398;rs.left=_399;return _397;};}_392.toPixelValue=_393;var astr="DXImageTransform.Microsoft.Alpha";var af=function(n,f){try{return n.filters.item(astr);}catch(e){return f?{}:null;}};var _39a=has("ie")<9||(has("ie")&&has("quirks"))?function(node){try{return af(node).Opacity/100;}catch(e){return 1;}}:function(node){return _391(node).opacity;};var _39b=has("ie")<9||(has("ie")&&has("quirks"))?function(node,_39c){var ov=_39c*100,_39d=_39c==1;node.style.zoom=_39d?"":1;if(!af(node)){if(_39d){return _39c;}node.style.filter+=" progid:"+astr+"(Opacity="+ov+")";}else{af(node,1).Opacity=ov;}af(node,1).Enabled=!_39d;if(node.tagName.toLowerCase()=="tr"){for(var td=node.firstChild;td;td=td.nextSibling){if(td.tagName.toLowerCase()=="td"){_39b(td,_39c);}}}return _39c;}:function(node,_39e){return node.style.opacity=_39e;};var _39f={left:true,top:true};var _3a0=/margin|padding|width|height|max|min|offset/;function _3a1(node,type,_3a2){type=type.toLowerCase();if(has("ie")){if(_3a2=="auto"){if(type=="height"){return node.offsetHeight;}if(type=="width"){return node.offsetWidth;}}if(type=="fontweight"){switch(_3a2){case 700:return "bold";case 400:default:return "normal";}}}if(!(type in _39f)){_39f[type]=_3a0.test(type);}return _39f[type]?_393(node,_3a2):_3a2;};var _3a3=has("ie")?"styleFloat":"cssFloat",_3a4={"cssFloat":_3a3,"styleFloat":_3a3,"float":_3a3};_392.get=function getStyle(node,name){var n=dom.byId(node),l=arguments.length,op=(name=="opacity");if(l==2&&op){return _39a(n);}name=_3a4[name]||name;var s=_392.getComputedStyle(n);return (l==1)?s:_3a1(n,name,s[name]||n.style[name]);};_392.set=function setStyle(node,name,_3a5){var n=dom.byId(node),l=arguments.length,op=(name=="opacity");name=_3a4[name]||name;if(l==3){return op?_39b(n,_3a5):n.style[name]=_3a5;}for(var x in name){_392.set(node,x,name[x]);}return _392.getComputedStyle(n);};return _392;});},"dojo/dom-prop":function(){define(["exports","./_base/kernel","./sniff","./_base/lang","./dom","./dom-style","./dom-construct","./_base/connect"],function(_3a6,dojo,has,lang,dom,_3a7,ctr,conn){var _3a8={},_3a9=0,_3aa=dojo._scopeName+"attrid";_3a6.names={"class":"className","for":"htmlFor",tabindex:"tabIndex",readonly:"readOnly",colspan:"colSpan",frameborder:"frameBorder",rowspan:"rowSpan",valuetype:"valueType"};_3a6.get=function getProp(node,name){node=dom.byId(node);var lc=name.toLowerCase(),_3ab=_3a6.names[lc]||name;return node[_3ab];};_3a6.set=function setProp(node,name,_3ac){node=dom.byId(node);var l=arguments.length;if(l==2&&typeof name!="string"){for(var x in name){_3a6.set(node,x,name[x]);}return node;}var lc=name.toLowerCase(),_3ad=_3a6.names[lc]||name;if(_3ad=="style"&&typeof _3ac!="string"){_3a7.set(node,_3ac);return node;}if(_3ad=="innerHTML"){if(has("ie")&&node.tagName.toLowerCase() in {col:1,colgroup:1,table:1,tbody:1,tfoot:1,thead:1,tr:1,title:1}){ctr.empty(node);node.appendChild(ctr.toDom(_3ac,node.ownerDocument));}else{node[_3ad]=_3ac;}return node;}if(lang.isFunction(_3ac)){var _3ae=node[_3aa];if(!_3ae){_3ae=_3a9++;node[_3aa]=_3ae;}if(!_3a8[_3ae]){_3a8[_3ae]={};}var h=_3a8[_3ae][_3ad];if(h){conn.disconnect(h);}else{try{delete node[_3ad];}catch(e){}}if(_3ac){_3a8[_3ae][_3ad]=conn.connect(node,_3ad,_3ac);}else{node[_3ad]=null;}return node;}node[_3ad]=_3ac;return node;};});},"dojo/when":function(){define(["./Deferred","./promise/Promise"],function(_3af,_3b0){"use strict";return function when(_3b1,_3b2,_3b3,_3b4){var _3b5=_3b1&&typeof _3b1.then==="function";var _3b6=_3b5&&_3b1 instanceof _3b0;if(!_3b5){if(_3b2){return _3b2(_3b1);}else{return new _3af().resolve(_3b1);}}else{if(!_3b6){var _3b7=new _3af(_3b1.cancel);_3b1.then(_3b7.resolve,_3b7.reject,_3b7.progress);_3b1=_3b7.promise;}}if(_3b2||_3b3||_3b4){return _3b1.then(_3b2,_3b3,_3b4);}return _3b1;};});},"dojo/dom-attr":function(){define(["exports","./sniff","./_base/lang","./dom","./dom-style","./dom-prop"],function(_3b8,has,lang,dom,_3b9,prop){var _3ba={innerHTML:1,className:1,htmlFor:has("ie"),value:1},_3bb={classname:"class",htmlfor:"for",tabindex:"tabIndex",readonly:"readOnly"};function _3bc(node,name){var attr=node.getAttributeNode&&node.getAttributeNode(name);return attr&&attr.specified;};_3b8.has=function hasAttr(node,name){var lc=name.toLowerCase();return _3ba[prop.names[lc]||name]||_3bc(dom.byId(node),_3bb[lc]||name);};_3b8.get=function getAttr(node,name){node=dom.byId(node);var lc=name.toLowerCase(),_3bd=prop.names[lc]||name,_3be=_3ba[_3bd],_3bf=node[_3bd];if(_3be&&typeof _3bf!="undefined"){return _3bf;}if(_3bd!="href"&&(typeof _3bf=="boolean"||lang.isFunction(_3bf))){return _3bf;}var _3c0=_3bb[lc]||name;return _3bc(node,_3c0)?node.getAttribute(_3c0):null;};_3b8.set=function setAttr(node,name,_3c1){node=dom.byId(node);if(arguments.length==2){for(var x in name){_3b8.set(node,x,name[x]);}return node;}var lc=name.toLowerCase(),_3c2=prop.names[lc]||name,_3c3=_3ba[_3c2];if(_3c2=="style"&&typeof _3c1!="string"){_3b9.set(node,_3c1);return node;}if(_3c3||typeof _3c1=="boolean"||lang.isFunction(_3c1)){return prop.set(node,name,_3c1);}node.setAttribute(_3bb[lc]||name,_3c1);return node;};_3b8.remove=function removeAttr(node,name){dom.byId(node).removeAttribute(_3bb[name.toLowerCase()]||name);};_3b8.getNodeProp=function getNodeProp(node,name){node=dom.byId(node);var lc=name.toLowerCase(),_3c4=prop.names[lc]||name;if((_3c4 in node)&&_3c4!="href"){return node[_3c4];}var _3c5=_3bb[lc]||name;return _3bc(node,_3c5)?node.getAttribute(_3c5):null;};});},"dojo/dom-construct":function(){define(["exports","./_base/kernel","./sniff","./_base/window","./dom","./dom-attr","./on"],function(_3c6,dojo,has,win,dom,attr,on){var _3c7={option:["select"],tbody:["table"],thead:["table"],tfoot:["table"],tr:["table","tbody"],td:["table","tbody","tr"],th:["table","thead","tr"],legend:["fieldset"],caption:["table"],colgroup:["table"],col:["table","colgroup"],li:["ul"]},_3c8=/<\s*([\w\:]+)/,_3c9={},_3ca=0,_3cb="__"+dojo._scopeName+"ToDomId";for(var _3cc in _3c7){if(_3c7.hasOwnProperty(_3cc)){var tw=_3c7[_3cc];tw.pre=_3cc=="option"?"<select multiple=\"multiple\">":"<"+tw.join("><")+">";tw.post="</"+tw.reverse().join("></")+">";}}function _3cd(node,ref){var _3ce=ref.parentNode;if(_3ce){_3ce.insertBefore(node,ref);}};function _3cf(node,ref){var _3d0=ref.parentNode;if(_3d0){if(_3d0.lastChild==ref){_3d0.appendChild(node);}else{_3d0.insertBefore(node,ref.nextSibling);}}};var _3d1=null,_3d2;on(window,"unload",function(){_3d1=null;});_3c6.toDom=function toDom(frag,doc){doc=doc||win.doc;var _3d3=doc[_3cb];if(!_3d3){doc[_3cb]=_3d3=++_3ca+"";_3c9[_3d3]=doc.createElement("div");}frag+="";var _3d4=frag.match(_3c8),tag=_3d4?_3d4[1].toLowerCase():"",_3d5=_3c9[_3d3],wrap,i,fc,df;if(_3d4&&_3c7[tag]){wrap=_3c7[tag];_3d5.innerHTML=wrap.pre+frag+wrap.post;for(i=wrap.length;i;--i){_3d5=_3d5.firstChild;}}else{_3d5.innerHTML=frag;}if(_3d5.childNodes.length==1){return _3d5.removeChild(_3d5.firstChild);}df=doc.createDocumentFragment();while(fc=_3d5.firstChild){df.appendChild(fc);}return df;};_3c6.place=function place(node,_3d6,_3d7){_3d6=dom.byId(_3d6);if(typeof node=="string"){node=/^\s*</.test(node)?_3c6.toDom(node,_3d6.ownerDocument):dom.byId(node);}if(typeof _3d7=="number"){var cn=_3d6.childNodes;if(!cn.length||cn.length<=_3d7){_3d6.appendChild(node);}else{_3cd(node,cn[_3d7<0?0:_3d7]);}}else{switch(_3d7){case "before":_3cd(node,_3d6);break;case "after":_3cf(node,_3d6);break;case "replace":_3d6.parentNode.replaceChild(node,_3d6);break;case "only":_3c6.empty(_3d6);_3d6.appendChild(node);break;case "first":if(_3d6.firstChild){_3cd(node,_3d6.firstChild);break;}default:_3d6.appendChild(node);}}return node;};_3c6.create=function create(tag,_3d8,_3d9,pos){var doc=win.doc;if(_3d9){_3d9=dom.byId(_3d9);doc=_3d9.ownerDocument;}if(typeof tag=="string"){tag=doc.createElement(tag);}if(_3d8){attr.set(tag,_3d8);}if(_3d9){_3c6.place(tag,_3d9,pos);}return tag;};_3c6.empty=has("ie")?function(node){node=dom.byId(node);for(var c;c=node.lastChild;){_3c6.destroy(c);}}:function(node){dom.byId(node).innerHTML="";};_3c6.destroy=function destroy(node){node=dom.byId(node);try{var doc=node.ownerDocument;if(!_3d1||_3d2!=doc){_3d1=doc.createElement("div");_3d2=doc;}_3d1.appendChild(node.parentNode?node.parentNode.removeChild(node):node);_3d1.innerHTML="";}catch(e){}};});},"dojo/request/xhr":function(){define("dojo/request/xhr",["../errors/RequestError","./watch","./handlers","./util","../has"],function(_3da,_3db,_3dc,util,has){has.add("native-xhr",function(){return typeof XMLHttpRequest!=="undefined";});has.add("dojo-force-activex-xhr",function(){return has("activex")&&!document.addEventListener&&window.location.protocol==="file:";});has.add("native-xhr2",function(){if(!has("native-xhr")){return;}var x=new XMLHttpRequest();return typeof x["addEventListener"]!=="undefined"&&(typeof opera==="undefined"||typeof x["upload"]!=="undefined");});has.add("native-formdata",function(){return typeof FormData==="function";});function _3dd(_3de,_3df){var _3e0=_3de.xhr;_3de.status=_3de.xhr.status;_3de.text=_3e0.responseText;if(_3de.options.handleAs==="xml"){_3de.data=_3e0.responseXML;}if(!_3df){try{_3dc(_3de);}catch(e){_3df=e;}}if(_3df){this.reject(_3df);}else{if(util.checkStatus(_3e0.status)){this.resolve(_3de);}else{_3df=new _3da("Unable to load "+_3de.url+" status: "+_3e0.status,_3de);this.reject(_3df);}}};var _3e1,_3e2,_3e3,_3e4;if(has("native-xhr2")){_3e1=function(_3e5){return !this.isFulfilled();};_3e4=function(dfd,_3e6){_3e6.xhr.abort();};_3e3=function(_3e7,dfd,_3e8){function _3e9(evt){dfd.handleResponse(_3e8);};function _3ea(evt){var _3eb=evt.target;var _3ec=new _3da("Unable to load "+_3e8.url+" status: "+_3eb.status,_3e8);dfd.handleResponse(_3e8,_3ec);};function _3ed(evt){if(evt.lengthComputable){_3e8.loaded=evt.loaded;_3e8.total=evt.total;dfd.progress(_3e8);}};_3e7.addEventListener("load",_3e9,false);_3e7.addEventListener("error",_3ea,false);_3e7.addEventListener("progress",_3ed,false);return function(){_3e7.removeEventListener("load",_3e9,false);_3e7.removeEventListener("error",_3ea,false);_3e7.removeEventListener("progress",_3ed,false);};};}else{_3e1=function(_3ee){return _3ee.xhr.readyState;};_3e2=function(_3ef){return 4===_3ef.xhr.readyState;};_3e4=function(dfd,_3f0){var xhr=_3f0.xhr;var _3f1=typeof xhr.abort;if(_3f1==="function"||_3f1==="object"||_3f1==="unknown"){xhr.abort();}};}var _3f2,_3f3={data:null,query:null,sync:false,method:"GET",headers:{"Content-Type":"application/x-www-form-urlencoded"}};function xhr(url,_3f4,_3f5){var _3f6=util.parseArgs(url,util.deepCreate(_3f3,_3f4),has("native-formdata")&&_3f4&&_3f4.data&&_3f4.data instanceof FormData);url=_3f6.url;_3f4=_3f6.options;var _3f7,last=function(){_3f7&&_3f7();};var dfd=util.deferred(_3f6,_3e4,_3e1,_3e2,_3dd,last);var _3f8=_3f6.xhr=xhr._create();if(!_3f8){dfd.cancel(new _3da("XHR was not created"));return _3f5?dfd:dfd.promise;}_3f6.getHeader=function(_3f9){return this.xhr.getResponseHeader(_3f9);};if(_3e3){_3f7=_3e3(_3f8,dfd,_3f6);}var data=_3f4.data,_3fa=!_3f4.sync,_3fb=_3f4.method;try{_3f8.open(_3fb,url,_3fa,_3f4.user||_3f2,_3f4.password||_3f2);if(_3f4.withCredentials){_3f8.withCredentials=_3f4.withCredentials;}var _3fc=_3f4.headers,_3fd;if(_3fc){for(var hdr in _3fc){if(hdr.toLowerCase()==="content-type"){_3fd=_3fc[hdr];}else{if(_3fc[hdr]){_3f8.setRequestHeader(hdr,_3fc[hdr]);}}}}if(_3fd&&_3fd!==false){_3f8.setRequestHeader("Content-Type",_3fd);}if(!_3fc||!("X-Requested-With" in _3fc)){_3f8.setRequestHeader("X-Requested-With","XMLHttpRequest");}if(util.notify){util.notify.emit("send",_3f6,dfd.promise.cancel);}_3f8.send(data);}catch(e){dfd.reject(e);}_3db(dfd);_3f8=null;return _3f5?dfd:dfd.promise;};xhr._create=function(){throw new Error("XMLHTTP not available");};if(has("native-xhr")&&!has("dojo-force-activex-xhr")){xhr._create=function(){return new XMLHttpRequest();};}else{if(has("activex")){try{new ActiveXObject("Msxml2.XMLHTTP");xhr._create=function(){return new ActiveXObject("Msxml2.XMLHTTP");};}catch(e){try{new ActiveXObject("Microsoft.XMLHTTP");xhr._create=function(){return new ActiveXObject("Microsoft.XMLHTTP");};}catch(e){}}}}util.addCommonMethods(xhr);return xhr;});},"dojo/text":function(){define(["./_base/kernel","require","./has","./_base/xhr"],function(dojo,_3fe,has,xhr){var _3ff;if(1){_3ff=function(url,sync,load){xhr("GET",{url:url,sync:!!sync,load:load,headers:dojo.config.textPluginHeaders||{}});};}else{if(_3fe.getText){_3ff=_3fe.getText;}else{console.error("dojo/text plugin failed to load because loader does not support getText");}}var _400={},_401=function(text){if(text){text=text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,"");var _402=text.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);if(_402){text=_402[1];}}else{text="";}return text;},_403={},_404={};dojo.cache=function(_405,url,_406){var key;if(typeof _405=="string"){if(/\//.test(_405)){key=_405;_406=url;}else{key=_3fe.toUrl(_405.replace(/\./g,"/")+(url?("/"+url):""));}}else{key=_405+"";_406=url;}var val=(_406!=undefined&&typeof _406!="string")?_406.value:_406,_407=_406&&_406.sanitize;if(typeof val=="string"){_400[key]=val;return _407?_401(val):val;}else{if(val===null){delete _400[key];return null;}else{if(!(key in _400)){_3ff(key,true,function(text){_400[key]=text;});}return _407?_401(_400[key]):_400[key];}}};return {dynamic:true,normalize:function(id,_408){var _409=id.split("!"),url=_409[0];return (/^\./.test(url)?_408(url):url)+(_409[1]?"!"+_409[1]:"");},load:function(id,_40a,load){var _40b=id.split("!"),_40c=_40b.length>1,_40d=_40b[0],url=_40a.toUrl(_40b[0]),_40e="url:"+url,text=_403,_40f=function(text){load(_40c?_401(text):text);};if(_40d in _400){text=_400[_40d];}else{if(_40e in _40a.cache){text=_40a.cache[_40e];}else{if(url in _400){text=_400[url];}}}if(text===_403){if(_404[url]){_404[url].push(_40f);}else{var _410=_404[url]=[_40f];_3ff(url,!_40a.async,function(text){_400[_40d]=_400[url]=text;for(var i=0;i<_410.length;){_410[i++](text);}delete _404[url];});}}else{_40f(text);}}};});},"dojo/keys":function(){define("dojo/keys",["./_base/kernel","./sniff"],function(dojo,has){return dojo.keys={BACKSPACE:8,TAB:9,CLEAR:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,META:has("webkit")?91:224,PAUSE:19,CAPS_LOCK:20,ESCAPE:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT_ARROW:37,UP_ARROW:38,RIGHT_ARROW:39,DOWN_ARROW:40,INSERT:45,DELETE:46,HELP:47,LEFT_WINDOW:91,RIGHT_WINDOW:92,SELECT:93,NUMPAD_0:96,NUMPAD_1:97,NUMPAD_2:98,NUMPAD_3:99,NUMPAD_4:100,NUMPAD_5:101,NUMPAD_6:102,NUMPAD_7:103,NUMPAD_8:104,NUMPAD_9:105,NUMPAD_MULTIPLY:106,NUMPAD_PLUS:107,NUMPAD_ENTER:108,NUMPAD_MINUS:109,NUMPAD_PERIOD:110,NUMPAD_DIVIDE:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,F13:124,F14:125,F15:126,NUM_LOCK:144,SCROLL_LOCK:145,UP_DPAD:175,DOWN_DPAD:176,LEFT_DPAD:177,RIGHT_DPAD:178,copyKey:has("mac")&&!has("air")?(has("safari")?91:224):17};});},"dojo/domReady":function(){define(["./has"],function(has){var _411=this,doc=document,_412={"loaded":1,"complete":1},_413=typeof doc.readyState!="string",_414=!!_412[doc.readyState];if(_413){doc.readyState="loading";}if(!_414){var _415=[],_416=[],_417=function(evt){evt=evt||_411.event;if(_414||(evt.type=="readystatechange"&&!_412[doc.readyState])){return;}_414=1;if(_413){doc.readyState="complete";}while(_415.length){(_415.shift())(doc);}},on=function(node,_418){node.addEventListener(_418,_417,false);_415.push(function(){node.removeEventListener(_418,_417,false);});};if(!has("dom-addeventlistener")){on=function(node,_419){_419="on"+_419;node.attachEvent(_419,_417);_415.push(function(){node.detachEvent(_419,_417);});};var div=doc.createElement("div");try{if(div.doScroll&&_411.frameElement===null){_416.push(function(){try{div.doScroll("left");return 1;}catch(e){}});}}catch(e){}}on(doc,"DOMContentLoaded");on(_411,"load");if("onreadystatechange" in doc){on(doc,"readystatechange");}else{if(!_413){_416.push(function(){return _412[doc.readyState];});}}if(_416.length){var _41a=function(){if(_414){return;}var i=_416.length;while(i--){if(_416[i]()){_417("poller");return;}}setTimeout(_41a,30);};_41a();}}function _41b(_41c){if(_414){_41c(doc);}else{_415.push(_41c);}};_41b.load=function(id,req,load){_41b(load);};return _41b;});},"dojo/_base/lang":function(){define("dojo/_base/lang",["./kernel","../has","../sniff"],function(dojo,has){has.add("bug-for-in-skips-shadowed",function(){for(var i in {toString:1}){return 0;}return 1;});var _41d=has("bug-for-in-skips-shadowed")?"hasOwnProperty.valueOf.isPrototypeOf.propertyIsEnumerable.toLocaleString.toString.constructor".split("."):[],_41e=_41d.length,_41f=function(_420,_421,_422){var p,i=0,_423=dojo.global;if(!_422){if(!_420.length){return _423;}else{p=_420[i++];try{_422=dojo.scopeMap[p]&&dojo.scopeMap[p][1];}catch(e){}_422=_422||(p in _423?_423[p]:(_421?_423[p]={}:undefined));}}while(_422&&(p=_420[i++])){_422=(p in _422?_422[p]:(_421?_422[p]={}:undefined));}return _422;},opts=Object.prototype.toString,_424=function(obj,_425,_426){return (_426||[]).concat(Array.prototype.slice.call(obj,_425||0));},_427=/\{([^\}]+)\}/g;var lang={_extraNames:_41d,_mixin:function(dest,_428,_429){var name,s,i,_42a={};for(name in _428){s=_428[name];if(!(name in dest)||(dest[name]!==s&&(!(name in _42a)||_42a[name]!==s))){dest[name]=_429?_429(s):s;}}if(has("bug-for-in-skips-shadowed")){if(_428){for(i=0;i<_41e;++i){name=_41d[i];s=_428[name];if(!(name in dest)||(dest[name]!==s&&(!(name in _42a)||_42a[name]!==s))){dest[name]=_429?_429(s):s;}}}}return dest;},mixin:function(dest,_42b){if(!dest){dest={};}for(var i=1,l=arguments.length;i<l;i++){lang._mixin(dest,arguments[i]);}return dest;},setObject:function(name,_42c,_42d){var _42e=name.split("."),p=_42e.pop(),obj=_41f(_42e,true,_42d);return obj&&p?(obj[p]=_42c):undefined;},getObject:function(name,_42f,_430){return _41f(name.split("."),_42f,_430);},exists:function(name,obj){return lang.getObject(name,false,obj)!==undefined;},isString:function(it){return (typeof it=="string"||it instanceof String);},isArray:function(it){return it&&(it instanceof Array||typeof it=="array");},isFunction:function(it){return opts.call(it)==="[object Function]";},isObject:function(it){return it!==undefined&&(it===null||typeof it=="object"||lang.isArray(it)||lang.isFunction(it));},isArrayLike:function(it){return it&&it!==undefined&&!lang.isString(it)&&!lang.isFunction(it)&&!(it.tagName&&it.tagName.toLowerCase()=="form")&&(lang.isArray(it)||isFinite(it.length));},isAlien:function(it){return it&&!lang.isFunction(it)&&/\{\s*\[native code\]\s*\}/.test(String(it));},extend:function(ctor,_431){for(var i=1,l=arguments.length;i<l;i++){lang._mixin(ctor.prototype,arguments[i]);}return ctor;},_hitchArgs:function(_432,_433){var pre=lang._toArray(arguments,2);var _434=lang.isString(_433);return function(){var args=lang._toArray(arguments);var f=_434?(_432||dojo.global)[_433]:_433;return f&&f.apply(_432||this,pre.concat(args));};},hitch:function(_435,_436){if(arguments.length>2){return lang._hitchArgs.apply(dojo,arguments);}if(!_436){_436=_435;_435=null;}if(lang.isString(_436)){_435=_435||dojo.global;if(!_435[_436]){throw (["lang.hitch: scope[\"",_436,"\"] is null (scope=\"",_435,"\")"].join(""));}return function(){return _435[_436].apply(_435,arguments||[]);};}return !_435?_436:function(){return _436.apply(_435,arguments||[]);};},delegate:(function(){function TMP(){};return function(obj,_437){TMP.prototype=obj;var tmp=new TMP();TMP.prototype=null;if(_437){lang._mixin(tmp,_437);}return tmp;};})(),_toArray:has("ie")?(function(){function slow(obj,_438,_439){var arr=_439||[];for(var x=_438||0;x<obj.length;x++){arr.push(obj[x]);}return arr;};return function(obj){return ((obj.item)?slow:_424).apply(this,arguments);};})():_424,partial:function(_43a){var arr=[null];return lang.hitch.apply(dojo,arr.concat(lang._toArray(arguments)));},clone:function(src){if(!src||typeof src!="object"||lang.isFunction(src)){return src;}if(src.nodeType&&"cloneNode" in src){return src.cloneNode(true);}if(src instanceof Date){return new Date(src.getTime());}if(src instanceof RegExp){return new RegExp(src);}var r,i,l;if(lang.isArray(src)){r=[];for(i=0,l=src.length;i<l;++i){if(i in src){r.push(lang.clone(src[i]));}}}else{r=src.constructor?new src.constructor():{};}return lang._mixin(r,src,lang.clone);},trim:String.prototype.trim?function(str){return str.trim();}:function(str){return str.replace(/^\s\s*/,"").replace(/\s\s*$/,"");},replace:function(tmpl,map,_43b){return tmpl.replace(_43b||_427,lang.isFunction(map)?map:function(_43c,k){return lang.getObject(k,false,map);});}};1&&lang.mixin(dojo,lang);return lang;});},"dojo/request/util":function(){define("dojo/request/util",["exports","../errors/RequestError","../errors/CancelError","../Deferred","../io-query","../_base/array","../_base/lang"],function(_43d,_43e,_43f,_440,_441,_442,lang){_43d.deepCopy=function deepCopy(_443,_444){for(var name in _444){var tval=_443[name],sval=_444[name];if(tval!==sval){if(tval&&typeof tval==="object"&&sval&&typeof sval==="object"){_43d.deepCopy(tval,sval);}else{_443[name]=sval;}}}return _443;};_43d.deepCreate=function deepCreate(_445,_446){_446=_446||{};var _447=lang.delegate(_445),name,_448;for(name in _445){_448=_445[name];if(_448&&typeof _448==="object"){_447[name]=_43d.deepCreate(_448,_446[name]);}}return _43d.deepCopy(_447,_446);};var _449=Object.freeze||function(obj){return obj;};function _44a(_44b){return _449(_44b);};_43d.deferred=function deferred(_44c,_44d,_44e,_44f,_450,last){var def=new _440(function(_451){_44d&&_44d(def,_44c);if(!_451||!(_451 instanceof _43e)&&!(_451 instanceof _43f)){return new _43f("Request canceled",_44c);}return _451;});def.response=_44c;def.isValid=_44e;def.isReady=_44f;def.handleResponse=_450;function _452(_453){_453.response=_44c;throw _453;};var _454=def.then(_44a).otherwise(_452);if(_43d.notify){_454.then(lang.hitch(_43d.notify,"emit","load"),lang.hitch(_43d.notify,"emit","error"));}var _455=_454.then(function(_456){return _456.data||_456.text;});var _457=_449(lang.delegate(_455,{response:_454}));if(last){def.then(function(_458){last.call(def,_458);},function(_459){last.call(def,_44c,_459);});}def.promise=_457;def.then=_457.then;return def;};_43d.addCommonMethods=function addCommonMethods(_45a,_45b){_442.forEach(_45b||["GET","POST","PUT","DELETE"],function(_45c){_45a[(_45c==="DELETE"?"DEL":_45c).toLowerCase()]=function(url,_45d){_45d=lang.delegate(_45d||{});_45d.method=_45c;return _45a(url,_45d);};});};_43d.parseArgs=function parseArgs(url,_45e,_45f){var data=_45e.data,_460=_45e.query;if(data&&!_45f){if(typeof data==="object"){_45e.data=_441.objectToQuery(data);}}if(_460){if(typeof _460==="object"){_460=_441.objectToQuery(_460);}if(_45e.preventCache){_460+=(_460?"&":"")+"request.preventCache="+(+(new Date));}}else{if(_45e.preventCache){_460="request.preventCache="+(+(new Date));}}if(url&&_460){url+=(~url.indexOf("?")?"&":"?")+_460;}return {url:url,options:_45e,getHeader:function(_461){return null;}};};_43d.checkStatus=function(stat){stat=stat||0;return (stat>=200&&stat<300)||stat===304||stat===1223||!stat;};});},"dojo/Evented":function(){define("dojo/Evented",["./aspect","./on"],function(_462,on){"use strict";var _463=_462.after;function _464(){};_464.prototype={on:function(type,_465){return on.parse(this,type,_465,function(_466,type){return _463(_466,"on"+type,_465,true);});},emit:function(type,_467){var args=[this];args.push.apply(args,arguments);return on.emit.apply(on,args);}};return _464;});},"dojo/mouse":function(){define("dojo/mouse",["./_base/kernel","./on","./has","./dom","./_base/window"],function(dojo,on,has,dom,win){has.add("dom-quirks",win.doc&&win.doc.compatMode=="BackCompat");has.add("events-mouseenter",win.doc&&"onmouseenter" in win.doc.createElement("div"));has.add("events-mousewheel",win.doc&&"onmousewheel" in win.doc);var _468;if(has("dom-quirks")||!has("dom-addeventlistener")){_468={LEFT:1,MIDDLE:4,RIGHT:2,isButton:function(e,_469){return e.button&_469;},isLeft:function(e){return e.button&1;},isMiddle:function(e){return e.button&4;},isRight:function(e){return e.button&2;}};}else{_468={LEFT:0,MIDDLE:1,RIGHT:2,isButton:function(e,_46a){return e.button==_46a;},isLeft:function(e){return e.button==0;},isMiddle:function(e){return e.button==1;},isRight:function(e){return e.button==2;}};}dojo.mouseButtons=_468;function _46b(type,_46c){var _46d=function(node,_46e){return on(node,type,function(evt){if(_46c){return _46c(evt,_46e);}if(!dom.isDescendant(evt.relatedTarget,node)){return _46e.call(this,evt);}});};_46d.bubble=function(_46f){return _46b(type,function(evt,_470){var _471=_46f(evt.target);var _472=evt.relatedTarget;if(_471&&(_471!=(_472&&_472.nodeType==1&&_46f(_472)))){return _470.call(_471,evt);}});};return _46d;};var _473;if(has("events-mousewheel")){_473="mousewheel";}else{_473=function(node,_474){return on(node,"DOMMouseScroll",function(evt){evt.wheelDelta=-evt.detail;_474.call(this,evt);});};}return {_eventHandler:_46b,enter:_46b("mouseover"),leave:_46b("mouseout"),wheel:_473,isLeft:_468.isLeft,isMiddle:_468.isMiddle,isRight:_468.isRight};});},"dojo/_base/xhr":function(){define("dojo/_base/xhr",["./kernel","./sniff","require","../io-query","../dom","../dom-form","./Deferred","./config","./json","./lang","./array","../on","../aspect","../request/watch","../request/xhr","../request/util"],function(dojo,has,_475,ioq,dom,_476,_477,_478,json,lang,_479,on,_47a,_47b,_47c,util){dojo._xhrObj=_47c._create;var cfg=dojo.config;dojo.objectToQuery=ioq.objectToQuery;dojo.queryToObject=ioq.queryToObject;dojo.fieldToObject=_476.fieldToObject;dojo.formToObject=_476.toObject;dojo.formToQuery=_476.toQuery;dojo.formToJson=_476.toJson;dojo._blockAsync=false;var _47d=dojo._contentHandlers=dojo.contentHandlers={"text":function(xhr){return xhr.responseText;},"json":function(xhr){return json.fromJson(xhr.responseText||null);},"json-comment-filtered":function(xhr){if(!_478.useCommentedJson){console.warn("Consider using the standard mimetype:application/json."+" json-commenting can introduce security issues. To"+" decrease the chances of hijacking, use the standard the 'json' handler and"+" prefix your json with: {}&&\n"+"Use djConfig.useCommentedJson=true to turn off this message.");}var _47e=xhr.responseText;var _47f=_47e.indexOf("/*");var _480=_47e.lastIndexOf("*/");if(_47f==-1||_480==-1){throw new Error("JSON was not comment filtered");}return json.fromJson(_47e.substring(_47f+2,_480));},"javascript":function(xhr){return dojo.eval(xhr.responseText);},"xml":function(xhr){var _481=xhr.responseXML;if(has("ie")){if((!_481||!_481.documentElement)){var ms=function(n){return "MSXML"+n+".DOMDocument";};var dp=["Microsoft.XMLDOM",ms(6),ms(4),ms(3),ms(2)];_479.some(dp,function(p){try{var dom=new ActiveXObject(p);dom.async=false;dom.loadXML(xhr.responseText);_481=dom;}catch(e){return false;}return true;});}}return _481;},"json-comment-optional":function(xhr){if(xhr.responseText&&/^[^{\[]*\/\*/.test(xhr.responseText)){return _47d["json-comment-filtered"](xhr);}else{return _47d["json"](xhr);}}};dojo._ioSetArgs=function(args,_482,_483,_484){var _485={args:args,url:args.url};var _486=null;if(args.form){var form=dom.byId(args.form);var _487=form.getAttributeNode("action");_485.url=_485.url||(_487?_487.value:null);_486=_476.toObject(form);}var _488=[{}];if(_486){_488.push(_486);}if(args.content){_488.push(args.content);}if(args.preventCache){_488.push({"dojo.preventCache":new Date().valueOf()});}_485.query=ioq.objectToQuery(lang.mixin.apply(null,_488));_485.handleAs=args.handleAs||"text";var d=new _477(function(dfd){dfd.canceled=true;_482&&_482(dfd);var err=dfd.ioArgs.error;if(!err){err=new Error("request cancelled");err.dojoType="cancel";dfd.ioArgs.error=err;}return err;});d.addCallback(_483);var ld=args.load;if(ld&&lang.isFunction(ld)){d.addCallback(function(_489){return ld.call(args,_489,_485);});}var err=args.error;if(err&&lang.isFunction(err)){d.addErrback(function(_48a){return err.call(args,_48a,_485);});}var _48b=args.handle;if(_48b&&lang.isFunction(_48b)){d.addBoth(function(_48c){return _48b.call(args,_48c,_485);});}d.addErrback(function(_48d){return _484(_48d,d);});if(cfg.ioPublish&&dojo.publish&&_485.args.ioPublish!==false){d.addCallbacks(function(res){dojo.publish("/dojo/io/load",[d,res]);return res;},function(res){dojo.publish("/dojo/io/error",[d,res]);return res;});d.addBoth(function(res){dojo.publish("/dojo/io/done",[d,res]);return res;});}d.ioArgs=_485;return d;};var _48e=function(dfd){var ret=_47d[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);return ret===undefined?null:ret;};var _48f=function(_490,dfd){if(!dfd.ioArgs.args.failOk){console.error(_490);}return _490;};var _491=function(dfd){if(_492<=0){_492=0;if(cfg.ioPublish&&dojo.publish&&(!dfd||dfd&&dfd.ioArgs.args.ioPublish!==false)){dojo.publish("/dojo/io/stop");}}};var _492=0;_47a.after(_47b,"_onAction",function(){_492-=1;});_47a.after(_47b,"_onInFlight",_491);dojo._ioCancelAll=_47b.cancelAll;dojo._ioNotifyStart=function(dfd){if(cfg.ioPublish&&dojo.publish&&dfd.ioArgs.args.ioPublish!==false){if(!_492){dojo.publish("/dojo/io/start");}_492+=1;dojo.publish("/dojo/io/send",[dfd]);}};dojo._ioWatch=function(dfd,_493,_494,_495){var args=dfd.ioArgs.options=dfd.ioArgs.args;lang.mixin(dfd,{response:dfd.ioArgs,isValid:function(_496){return _493(dfd);},isReady:function(_497){return _494(dfd);},handleResponse:function(_498){return _495(dfd);}});_47b(dfd);_491(dfd);};var _499="application/x-www-form-urlencoded";dojo._ioAddQueryToUrl=function(_49a){if(_49a.query.length){_49a.url+=(_49a.url.indexOf("?")==-1?"?":"&")+_49a.query;_49a.query=null;}};dojo.xhr=function(_49b,args,_49c){var rDfd;var dfd=dojo._ioSetArgs(args,function(dfd){rDfd&&rDfd.cancel();},_48e,_48f);var _49d=dfd.ioArgs;if("postData" in args){_49d.query=args.postData;}else{if("putData" in args){_49d.query=args.putData;}else{if("rawBody" in args){_49d.query=args.rawBody;}else{if((arguments.length>2&&!_49c)||"POST|PUT".indexOf(_49b.toUpperCase())===-1){dojo._ioAddQueryToUrl(_49d);}}}}var _49e={method:_49b,handleAs:"text",timeout:args.timeout,withCredentials:args.withCredentials,ioArgs:_49d};if(typeof args.headers!=="undefined"){_49e.headers=args.headers;}if(typeof args.contentType!=="undefined"){if(!_49e.headers){_49e.headers={};}_49e.headers["Content-Type"]=args.contentType;}if(typeof _49d.query!=="undefined"){_49e.data=_49d.query;}if(typeof args.sync!=="undefined"){_49e.sync=args.sync;}dojo._ioNotifyStart(dfd);try{rDfd=_47c(_49d.url,_49e,true);}catch(e){dfd.cancel();return dfd;}dfd.ioArgs.xhr=rDfd.response.xhr;rDfd.then(function(){dfd.resolve(dfd);}).otherwise(function(_49f){_49d.error=_49f;dfd.reject(_49f);});return dfd;};dojo.xhrGet=function(args){return dojo.xhr("GET",args);};dojo.rawXhrPost=dojo.xhrPost=function(args){return dojo.xhr("POST",args,true);};dojo.rawXhrPut=dojo.xhrPut=function(args){return dojo.xhr("PUT",args,true);};dojo.xhrDelete=function(args){return dojo.xhr("DELETE",args);};dojo._isDocumentOk=function(x){return util.checkStatus(x.status);};dojo._getText=function(url){var _4a0;dojo.xhrGet({url:url,sync:true,load:function(text){_4a0=text;}});return _4a0;};lang.mixin(dojo.xhr,{_xhrObj:dojo._xhrObj,fieldToObject:_476.fieldToObject,formToObject:_476.toObject,objectToQuery:ioq.objectToQuery,formToQuery:_476.toQuery,formToJson:_476.toJson,queryToObject:ioq.queryToObject,contentHandlers:_47d,_ioSetArgs:dojo._ioSetArgs,_ioCancelAll:dojo._ioCancelAll,_ioNotifyStart:dojo._ioNotifyStart,_ioWatch:dojo._ioWatch,_ioAddQueryToUrl:dojo._ioAddQueryToUrl,_isDocumentOk:dojo._isDocumentOk,_getText:dojo._getText,get:dojo.xhrGet,post:dojo.xhrPost,put:dojo.xhrPut,del:dojo.xhrDelete});return dojo.xhr;});},"dojo/topic":function(){define("dojo/topic",["./Evented"],function(_4a1){var hub=new _4a1;return {publish:function(_4a2,_4a3){return hub.emit.apply(hub,arguments);},subscribe:function(_4a4,_4a5){return hub.on.apply(hub,arguments);}};});},"dojo/loadInit":function(){define("dojo/loadInit",["./_base/loader"],function(_4a6){return {dynamic:0,normalize:function(id){return id;},load:_4a6.loadInit};});},"dojo/_base/unload":function(){define(["./kernel","./lang","../on"],function(dojo,lang,on){var win=window;var _4a7={addOnWindowUnload:function(obj,_4a8){if(!dojo.windowUnloaded){on(win,"unload",(dojo.windowUnloaded=function(){}));}on(win,"unload",lang.hitch(obj,_4a8));},addOnUnload:function(obj,_4a9){on(win,"beforeunload",lang.hitch(obj,_4a9));}};dojo.addOnWindowUnload=_4a7.addOnWindowUnload;dojo.addOnUnload=_4a7.addOnUnload;return _4a7;});},"dojo/Deferred":function(){define(["./has","./_base/lang","./errors/CancelError","./promise/Promise","./promise/instrumentation"],function(has,lang,_4aa,_4ab,_4ac){"use strict";var _4ad=0,_4ae=1,_4af=2;var _4b0="This deferred has already been fulfilled.";var _4b1=Object.freeze||function(){};var _4b2=function(_4b3,type,_4b4,_4b5,_4b6){if(1){if(type===_4af&&_4b7.instrumentRejected&&_4b3.length===0){_4b7.instrumentRejected(_4b4,false,_4b5,_4b6);}}for(var i=0;i<_4b3.length;i++){_4b8(_4b3[i],type,_4b4,_4b5);}};var _4b8=function(_4b9,type,_4ba,_4bb){var func=_4b9[type];var _4bc=_4b9.deferred;if(func){try{var _4bd=func(_4ba);if(_4bd&&typeof _4bd.then==="function"){_4b9.cancel=_4bd.cancel;_4bd.then(_4be(_4bc,_4ae),_4be(_4bc,_4af),_4be(_4bc,_4ad));return;}_4bf(_4bc,_4ae,_4bd);}catch(error){_4bf(_4bc,_4af,error);}}else{_4bf(_4bc,type,_4ba);}if(1){if(type===_4af&&_4b7.instrumentRejected){_4b7.instrumentRejected(_4ba,!!func,_4bb,_4bc.promise);}}};var _4be=function(_4c0,type){return function(_4c1){_4bf(_4c0,type,_4c1);};};var _4bf=function(_4c2,type,_4c3){if(!_4c2.isCanceled()){switch(type){case _4ad:_4c2.progress(_4c3);break;case _4ae:_4c2.resolve(_4c3);break;case _4af:_4c2.reject(_4c3);break;}}};var _4b7=function(_4c4){var _4c5=this.promise=new _4ab();var _4c6=this;var _4c7,_4c8,_4c9;var _4ca=false;var _4cb=[];if(1&&Error.captureStackTrace){Error.captureStackTrace(_4c6,_4b7);Error.captureStackTrace(_4c5,_4b7);}this.isResolved=_4c5.isResolved=function(){return _4c7===_4ae;};this.isRejected=_4c5.isRejected=function(){return _4c7===_4af;};this.isFulfilled=_4c5.isFulfilled=function(){return !!_4c7;};this.isCanceled=_4c5.isCanceled=function(){return _4ca;};this.progress=function(_4cc,_4cd){if(!_4c7){_4b2(_4cb,_4ad,_4cc,null,_4c6);return _4c5;}else{if(_4cd===true){throw new Error(_4b0);}else{return _4c5;}}};this.resolve=function(_4ce,_4cf){if(!_4c7){_4b2(_4cb,_4c7=_4ae,_4c8=_4ce,null,_4c6);_4cb=null;return _4c5;}else{if(_4cf===true){throw new Error(_4b0);}else{return _4c5;}}};var _4d0=this.reject=function(_4d1,_4d2){if(!_4c7){if(1&&Error.captureStackTrace){Error.captureStackTrace(_4c9={},_4d0);}_4b2(_4cb,_4c7=_4af,_4c8=_4d1,_4c9,_4c6);_4cb=null;return _4c5;}else{if(_4d2===true){throw new Error(_4b0);}else{return _4c5;}}};this.then=_4c5.then=function(_4d3,_4d4,_4d5){var _4d6=[_4d5,_4d3,_4d4];_4d6.cancel=_4c5.cancel;_4d6.deferred=new _4b7(function(_4d7){return _4d6.cancel&&_4d6.cancel(_4d7);});if(_4c7&&!_4cb){_4b8(_4d6,_4c7,_4c8,_4c9);}else{_4cb.push(_4d6);}return _4d6.deferred.promise;};this.cancel=_4c5.cancel=function(_4d8,_4d9){if(!_4c7){if(_4c4){var _4da=_4c4(_4d8);_4d8=typeof _4da==="undefined"?_4d8:_4da;}_4ca=true;if(!_4c7){if(typeof _4d8==="undefined"){_4d8=new _4aa();}_4d0(_4d8);return _4d8;}else{if(_4c7===_4af&&_4c8===_4d8){return _4d8;}}}else{if(_4d9===true){throw new Error(_4b0);}}};_4b1(_4c5);};_4b7.prototype.toString=function(){return "[object Deferred]";};if(_4ac){_4ac(_4b7);}return _4b7;});},"dojo/_base/NodeList":function(){define("dojo/_base/NodeList",["./kernel","../query","./array","./html","../NodeList-dom"],function(dojo,_4db,_4dc){var _4dd=_4db.NodeList,nlp=_4dd.prototype;nlp.connect=_4dd._adaptAsForEach(function(){return dojo.connect.apply(this,arguments);});nlp.coords=_4dd._adaptAsMap(dojo.coords);_4dd.events=["blur","focus","change","click","error","keydown","keypress","keyup","load","mousedown","mouseenter","mouseleave","mousemove","mouseout","mouseover","mouseup","submit"];_4dc.forEach(_4dd.events,function(evt){var _4de="on"+evt;nlp[_4de]=function(a,b){return this.connect(_4de,a,b);};});dojo.NodeList=_4dd;return _4dd;});},"dojo/_base/Color":function(){define(["./kernel","./lang","./array","./config"],function(dojo,lang,_4df,_4e0){var _4e1=dojo.Color=function(_4e2){if(_4e2){this.setColor(_4e2);}};_4e1.named={"black":[0,0,0],"silver":[192,192,192],"gray":[128,128,128],"white":[255,255,255],"maroon":[128,0,0],"red":[255,0,0],"purple":[128,0,128],"fuchsia":[255,0,255],"green":[0,128,0],"lime":[0,255,0],"olive":[128,128,0],"yellow":[255,255,0],"navy":[0,0,128],"blue":[0,0,255],"teal":[0,128,128],"aqua":[0,255,255],"transparent":_4e0.transparentColor||[0,0,0,0]};lang.extend(_4e1,{r:255,g:255,b:255,a:1,_set:function(r,g,b,a){var t=this;t.r=r;t.g=g;t.b=b;t.a=a;},setColor:function(_4e3){if(lang.isString(_4e3)){_4e1.fromString(_4e3,this);}else{if(lang.isArray(_4e3)){_4e1.fromArray(_4e3,this);}else{this._set(_4e3.r,_4e3.g,_4e3.b,_4e3.a);if(!(_4e3 instanceof _4e1)){this.sanitize();}}}return this;},sanitize:function(){return this;},toRgb:function(){var t=this;return [t.r,t.g,t.b];},toRgba:function(){var t=this;return [t.r,t.g,t.b,t.a];},toHex:function(){var arr=_4df.map(["r","g","b"],function(x){var s=this[x].toString(16);return s.length<2?"0"+s:s;},this);return "#"+arr.join("");},toCss:function(_4e4){var t=this,rgb=t.r+", "+t.g+", "+t.b;return (_4e4?"rgba("+rgb+", "+t.a:"rgb("+rgb)+")";},toString:function(){return this.toCss(true);}});_4e1.blendColors=dojo.blendColors=function(_4e5,end,_4e6,obj){var t=obj||new _4e1();_4df.forEach(["r","g","b","a"],function(x){t[x]=_4e5[x]+(end[x]-_4e5[x])*_4e6;if(x!="a"){t[x]=Math.round(t[x]);}});return t.sanitize();};_4e1.fromRgb=dojo.colorFromRgb=function(_4e7,obj){var m=_4e7.toLowerCase().match(/^rgba?\(([\s\.,0-9]+)\)/);return m&&_4e1.fromArray(m[1].split(/\s*,\s*/),obj);};_4e1.fromHex=dojo.colorFromHex=function(_4e8,obj){var t=obj||new _4e1(),bits=(_4e8.length==4)?4:8,mask=(1<<bits)-1;_4e8=Number("0x"+_4e8.substr(1));if(isNaN(_4e8)){return null;}_4df.forEach(["b","g","r"],function(x){var c=_4e8&mask;_4e8>>=bits;t[x]=bits==4?17*c:c;});t.a=1;return t;};_4e1.fromArray=dojo.colorFromArray=function(a,obj){var t=obj||new _4e1();t._set(Number(a[0]),Number(a[1]),Number(a[2]),Number(a[3]));if(isNaN(t.a)){t.a=1;}return t.sanitize();};_4e1.fromString=dojo.colorFromString=function(str,obj){var a=_4e1.named[str];return a&&_4e1.fromArray(a,obj)||_4e1.fromRgb(str,obj)||_4e1.fromHex(str,obj);};return _4e1;});},"dojo/promise/instrumentation":function(){define(["./tracer","../has","../_base/lang","../_base/array"],function(_4e9,has,lang,_4ea){function _4eb(_4ec,_4ed,_4ee){var _4ef="";if(_4ec&&_4ec.stack){_4ef+=_4ec.stack;}if(_4ed&&_4ed.stack){_4ef+="\n    ----------------------------------------\n    rejected"+_4ed.stack.split("\n").slice(1).join("\n").replace(/^\s+/," ");}if(_4ee&&_4ee.stack){_4ef+="\n    ----------------------------------------\n"+_4ee.stack;}console.error(_4ec,_4ef);};function _4f0(_4f1,_4f2,_4f3,_4f4){if(!_4f2){_4eb(_4f1,_4f3,_4f4);}};var _4f5=[];var _4f6=false;var _4f7=1000;function _4f8(_4f9,_4fa,_4fb,_4fc){if(_4fa){_4ea.some(_4f5,function(obj,ix){if(obj.error===_4f9){_4f5.splice(ix,1);return true;}});}else{if(!_4ea.some(_4f5,function(obj){return obj.error===_4f9;})){_4f5.push({error:_4f9,rejection:_4fb,deferred:_4fc,timestamp:new Date().getTime()});}}if(!_4f6){_4f6=setTimeout(_4fd,_4f7);}};function _4fd(){var now=new Date().getTime();var _4fe=now-_4f7;_4f5=_4ea.filter(_4f5,function(obj){if(obj.timestamp<_4fe){_4eb(obj.error,obj.rejection,obj.deferred);return false;}return true;});if(_4f5.length){_4f6=setTimeout(_4fd,_4f5[0].timestamp+_4f7-now);}};return function(_4ff){var _500=has("config-useDeferredInstrumentation");if(_500){_4e9.on("resolved",lang.hitch(console,"log","resolved"));_4e9.on("rejected",lang.hitch(console,"log","rejected"));_4e9.on("progress",lang.hitch(console,"log","progress"));var args=[];if(typeof _500==="string"){args=_500.split(",");_500=args.shift();}if(_500==="report-rejections"){_4ff.instrumentRejected=_4f0;}else{if(_500==="report-unhandled-rejections"||_500===true||_500===1){_4ff.instrumentRejected=_4f8;_4f7=parseInt(args[0],10)||_4f7;}else{throw new Error("Unsupported instrumentation usage <"+_500+">");}}}};});},"dojo/selector/_loader":function(){define(["../has","require"],function(has,_501){"use strict";var _502=document.createElement("div");has.add("dom-qsa2.1",!!_502.querySelectorAll);has.add("dom-qsa3",function(){try{_502.innerHTML="<p class='TEST'></p>";return _502.querySelectorAll(".TEST:empty").length==1;}catch(e){}});var _503;var acme="./acme",lite="./lite";return {load:function(id,_504,_505,_506){var req=_501;id=id=="default"?has("config-selectorEngine")||"css3":id;id=id=="css2"||id=="lite"?lite:id=="css2.1"?has("dom-qsa2.1")?lite:acme:id=="css3"?has("dom-qsa3")?lite:acme:id=="acme"?acme:(req=_504)&&id;if(id.charAt(id.length-1)=="?"){id=id.substring(0,id.length-1);var _507=true;}if(_507&&(has("dom-compliant-qsa")||_503)){return _505(_503);}req([id],function(_508){if(id!="./lite"){_503=_508;}_505(_508);});}};});},"dojo/promise/Promise":function(){define(["../_base/lang"],function(lang){"use strict";function _509(){throw new TypeError("abstract");};return lang.extend(function Promise(){},{then:function(_50a,_50b,_50c){_509();},cancel:function(_50d,_50e){_509();},isResolved:function(){_509();},isRejected:function(){_509();},isFulfilled:function(){_509();},isCanceled:function(){_509();},always:function(_50f){return this.then(_50f,_50f);},otherwise:function(_510){return this.then(null,_510);},trace:function(){return this;},traceRejected:function(){return this;},toString:function(){return "[object Promise]";}});});},"dojo/request/watch":function(){define(["./util","../errors/RequestTimeoutError","../errors/CancelError","../_base/array","../_base/window","../has!host-browser?dom-addeventlistener?:../on:"],function(util,_511,_512,_513,win,on){var _514=null,_515=[];function _516(){var now=+(new Date);for(var i=0,dfd;i<_515.length&&(dfd=_515[i]);i++){var _517=dfd.response,_518=_517.options;if((dfd.isCanceled&&dfd.isCanceled())||(dfd.isValid&&!dfd.isValid(_517))){_515.splice(i--,1);_519._onAction&&_519._onAction();}else{if(dfd.isReady&&dfd.isReady(_517)){_515.splice(i--,1);dfd.handleResponse(_517);_519._onAction&&_519._onAction();}else{if(dfd.startTime){if(dfd.startTime+(_518.timeout||0)<now){_515.splice(i--,1);dfd.cancel(new _511(_517));_519._onAction&&_519._onAction();}}}}}_519._onInFlight&&_519._onInFlight(dfd);if(!_515.length){clearInterval(_514);_514=null;}};function _519(dfd){if(dfd.response.options.timeout){dfd.startTime=+(new Date);}if(dfd.isFulfilled()){return;}_515.push(dfd);if(!_514){_514=setInterval(_516,50);}if(dfd.response.options.sync){_516();}};_519.cancelAll=function cancelAll(){try{_513.forEach(_515,function(dfd){try{dfd.cancel(new _512("All requests canceled."));}catch(e){}});}catch(e){}};if(win&&on&&win.doc.attachEvent){on(win.global,"unload",function(){_519.cancelAll();});}return _519;});},"dojo/on":function(){define(["./has!dom-addeventlistener?:./aspect","./_base/kernel","./has"],function(_51a,dojo,has){"use strict";if(1){var _51b=window.ScriptEngineMajorVersion;has.add("jscript",_51b&&(_51b()+ScriptEngineMinorVersion()/10));has.add("event-orientationchange",has("touch")&&!has("android"));has.add("event-stopimmediatepropagation",window.Event&&!!window.Event.prototype&&!!window.Event.prototype.stopImmediatePropagation);}var on=function(_51c,type,_51d,_51e){if(_51c.on&&typeof type!="function"){return _51c.on(type,_51d);}return on.parse(_51c,type,_51d,_51f,_51e,this);};on.pausable=function(_520,type,_521,_522){var _523;var _524=on(_520,type,function(){if(!_523){return _521.apply(this,arguments);}},_522);_524.pause=function(){_523=true;};_524.resume=function(){_523=false;};return _524;};on.once=function(_525,type,_526,_527){var _528=on(_525,type,function(){_528.remove();return _526.apply(this,arguments);});return _528;};on.parse=function(_529,type,_52a,_52b,_52c,_52d){if(type.call){return type.call(_52d,_529,_52a);}if(type.indexOf(",")>-1){var _52e=type.split(/\s*,\s*/);var _52f=[];var i=0;var _530;while(_530=_52e[i++]){_52f.push(_52b(_529,_530,_52a,_52c,_52d));}_52f.remove=function(){for(var i=0;i<_52f.length;i++){_52f[i].remove();}};return _52f;}return _52b(_529,type,_52a,_52c,_52d);};var _531=/^touch/;function _51f(_532,type,_533,_534,_535){var _536=type.match(/(.*):(.*)/);if(_536){type=_536[2];_536=_536[1];return on.selector(_536,type).call(_535,_532,_533);}if(has("touch")){if(_531.test(type)){_533=_537(_533);}if(!has("event-orientationchange")&&(type=="orientationchange")){type="resize";_532=window;_533=_537(_533);}}if(_538){_533=_538(_533);}if(_532.addEventListener){var _539=type in _53a,_53b=_539?_53a[type]:type;_532.addEventListener(_53b,_533,_539);return {remove:function(){_532.removeEventListener(_53b,_533,_539);}};}type="on"+type;if(_53c&&_532.attachEvent){return _53c(_532,type,_533);}throw new Error("Target must be an event emitter");};on.selector=function(_53d,_53e,_53f){return function(_540,_541){var _542=typeof _53d=="function"?{matches:_53d}:this,_543=_53e.bubble;function _544(_545){_542=_542&&_542.matches?_542:dojo.query;while(!_542.matches(_545,_53d,_540)){if(_545==_540||_53f===false||!(_545=_545.parentNode)||_545.nodeType!=1){return;}}return _545;};if(_543){return on(_540,_543(_544),_541);}return on(_540,_53e,function(_546){var _547=_544(_546.target);return _547&&_541.call(_547,_546);});};};function _548(){this.cancelable=false;};function _549(){this.bubbles=false;};var _54a=[].slice,_54b=on.emit=function(_54c,type,_54d){var args=_54a.call(arguments,2);var _54e="on"+type;if("parentNode" in _54c){var _54f=args[0]={};for(var i in _54d){_54f[i]=_54d[i];}_54f.preventDefault=_548;_54f.stopPropagation=_549;_54f.target=_54c;_54f.type=type;_54d=_54f;}do{_54c[_54e]&&_54c[_54e].apply(_54c,args);}while(_54d&&_54d.bubbles&&(_54c=_54c.parentNode));return _54d&&_54d.cancelable&&_54d;};var _53a={};if(!has("event-stopimmediatepropagation")){var _550=function(){this.immediatelyStopped=true;this.modified=true;};var _538=function(_551){return function(_552){if(!_552.immediatelyStopped){_552.stopImmediatePropagation=_550;return _551.apply(this,arguments);}};};}if(has("dom-addeventlistener")){_53a={focusin:"focus",focusout:"blur"};if(has("opera")){_53a.keydown="keypress";}on.emit=function(_553,type,_554){if(_553.dispatchEvent&&document.createEvent){var _555=_553.ownerDocument.createEvent("HTMLEvents");_555.initEvent(type,!!_554.bubbles,!!_554.cancelable);for(var i in _554){var _556=_554[i];if(!(i in _555)){_555[i]=_554[i];}}return _553.dispatchEvent(_555)&&_555;}return _54b.apply(on,arguments);};}else{on._fixEvent=function(evt,_557){if(!evt){var w=_557&&(_557.ownerDocument||_557.document||_557).parentWindow||window;evt=w.event;}if(!evt){return evt;}if(_558&&evt.type==_558.type){evt=_558;}if(!evt.target){evt.target=evt.srcElement;evt.currentTarget=(_557||evt.srcElement);if(evt.type=="mouseover"){evt.relatedTarget=evt.fromElement;}if(evt.type=="mouseout"){evt.relatedTarget=evt.toElement;}if(!evt.stopPropagation){evt.stopPropagation=_559;evt.preventDefault=_55a;}switch(evt.type){case "keypress":var c=("charCode" in evt?evt.charCode:evt.keyCode);if(c==10){c=0;evt.keyCode=13;}else{if(c==13||c==27){c=0;}else{if(c==3){c=99;}}}evt.charCode=c;_55b(evt);break;}}return evt;};var _558,_55c=function(_55d){this.handle=_55d;};_55c.prototype.remove=function(){delete _dojoIEListeners_[this.handle];};var _55e=function(_55f){return function(evt){evt=on._fixEvent(evt,this);var _560=_55f.call(this,evt);if(evt.modified){if(!_558){setTimeout(function(){_558=null;});}_558=evt;}return _560;};};var _53c=function(_561,type,_562){_562=_55e(_562);if(((_561.ownerDocument?_561.ownerDocument.parentWindow:_561.parentWindow||_561.window||window)!=top||has("jscript")<5.8)&&!has("config-_allow_leaks")){if(typeof _dojoIEListeners_=="undefined"){_dojoIEListeners_=[];}var _563=_561[type];if(!_563||!_563.listeners){var _564=_563;_563=Function("event","var callee = arguments.callee; for(var i = 0; i<callee.listeners.length; i++){var listener = _dojoIEListeners_[callee.listeners[i]]; if(listener){listener.call(this,event);}}");_563.listeners=[];_561[type]=_563;_563.global=this;if(_564){_563.listeners.push(_dojoIEListeners_.push(_564)-1);}}var _565;_563.listeners.push(_565=(_563.global._dojoIEListeners_.push(_562)-1));return new _55c(_565);}return _51a.after(_561,type,_562,true);};var _55b=function(evt){evt.keyChar=evt.charCode?String.fromCharCode(evt.charCode):"";evt.charOrCode=evt.keyChar||evt.keyCode;};var _559=function(){this.cancelBubble=true;};var _55a=on._preventDefault=function(){this.bubbledKeyCode=this.keyCode;if(this.ctrlKey){try{this.keyCode=0;}catch(e){}}this.defaultPrevented=true;this.returnValue=false;};}if(has("touch")){var _566=function(){};var _567=window.orientation;var _537=function(_568){return function(_569){var _56a=_569.corrected;if(!_56a){var type=_569.type;try{delete _569.type;}catch(e){}if(_569.type){_566.prototype=_569;var _56a=new _566;_56a.preventDefault=function(){_569.preventDefault();};_56a.stopPropagation=function(){_569.stopPropagation();};}else{_56a=_569;_56a.type=type;}_569.corrected=_56a;if(type=="resize"){if(_567==window.orientation){return null;}_567=window.orientation;_56a.type="orientationchange";return _568.call(this,_56a);}if(!("rotation" in _56a)){_56a.rotation=0;_56a.scale=1;}var _56b=_56a.changedTouches[0];for(var i in _56b){delete _56a[i];_56a[i]=_56b[i];}}return _568.call(this,_56a);};};}return on;});},"dojo/_base/sniff":function(){define(["./kernel","./lang","../sniff"],function(dojo,lang,has){if(!1){return has;}dojo._name="browser";lang.mixin(dojo,{isBrowser:true,isFF:has("ff"),isIE:has("ie"),isKhtml:has("khtml"),isWebKit:has("webkit"),isMozilla:has("mozilla"),isMoz:has("mozilla"),isOpera:has("opera"),isSafari:has("safari"),isChrome:has("chrome"),isMac:has("mac"),isIos:has("ios"),isAndroid:has("android"),isWii:has("wii"),isQuirks:has("quirks"),isAir:has("air")});dojo.locale=dojo.locale||(has("ie")?navigator.userLanguage:navigator.language).toLowerCase();return has;});},"dojo/errors/create":function(){define(["../_base/lang"],function(lang){return function(name,ctor,base,_56c){base=base||Error;var _56d=function(_56e){if(base===Error){if(Error.captureStackTrace){Error.captureStackTrace(this,_56d);}var err=Error.call(this,_56e),prop;for(prop in err){if(err.hasOwnProperty(prop)){this[prop]=err[prop];}}this.message=_56e;this.stack=err.stack;}else{base.apply(this,arguments);}if(ctor){ctor.apply(this,arguments);}};_56d.prototype=lang.delegate(base.prototype,_56c);_56d.prototype.name=name;_56d.prototype.constructor=_56d;return _56d;};});},"dojo/_base/array":function(){define(["./kernel","../has","./lang"],function(dojo,has,lang){var _56f={},u;function _570(fn){return _56f[fn]=new Function("item","index","array",fn);};function _571(some){var _572=!some;return function(a,fn,o){var i=0,l=a&&a.length||0,_573;if(l&&typeof a=="string"){a=a.split("");}if(typeof fn=="string"){fn=_56f[fn]||_570(fn);}if(o){for(;i<l;++i){_573=!fn.call(o,a[i],i,a);if(some^_573){return !_573;}}}else{for(;i<l;++i){_573=!fn(a[i],i,a);if(some^_573){return !_573;}}}return _572;};};function _574(up){var _575=1,_576=0,_577=0;if(!up){_575=_576=_577=-1;}return function(a,x,from,last){if(last&&_575>0){return _578.lastIndexOf(a,x,from);}var l=a&&a.length||0,end=up?l+_577:_576,i;if(from===u){i=up?_576:l+_577;}else{if(from<0){i=l+from;if(i<0){i=_576;}}else{i=from>=l?l+_577:from;}}if(l&&typeof a=="string"){a=a.split("");}for(;i!=end;i+=_575){if(a[i]==x){return i;}}return -1;};};var _578={every:_571(false),some:_571(true),indexOf:_574(true),lastIndexOf:_574(false),forEach:function(arr,_579,_57a){var i=0,l=arr&&arr.length||0;if(l&&typeof arr=="string"){arr=arr.split("");}if(typeof _579=="string"){_579=_56f[_579]||_570(_579);}if(_57a){for(;i<l;++i){_579.call(_57a,arr[i],i,arr);}}else{for(;i<l;++i){_579(arr[i],i,arr);}}},map:function(arr,_57b,_57c,Ctr){var i=0,l=arr&&arr.length||0,out=new (Ctr||Array)(l);if(l&&typeof arr=="string"){arr=arr.split("");}if(typeof _57b=="string"){_57b=_56f[_57b]||_570(_57b);}if(_57c){for(;i<l;++i){out[i]=_57b.call(_57c,arr[i],i,arr);}}else{for(;i<l;++i){out[i]=_57b(arr[i],i,arr);}}return out;},filter:function(arr,_57d,_57e){var i=0,l=arr&&arr.length||0,out=[],_57f;if(l&&typeof arr=="string"){arr=arr.split("");}if(typeof _57d=="string"){_57d=_56f[_57d]||_570(_57d);}if(_57e){for(;i<l;++i){_57f=arr[i];if(_57d.call(_57e,_57f,i,arr)){out.push(_57f);}}}else{for(;i<l;++i){_57f=arr[i];if(_57d(_57f,i,arr)){out.push(_57f);}}}return out;},clearCache:function(){_56f={};}};1&&lang.mixin(dojo,_578);return _578;});},"dojo/_base/json":function(){define(["./kernel","../json"],function(dojo,json){dojo.fromJson=function(js){return eval("("+js+")");};dojo._escapeString=json.stringify;dojo.toJsonIndentStr="\t";dojo.toJson=function(it,_580){return json.stringify(it,function(key,_581){if(_581){var tf=_581.__json__||_581.json;if(typeof tf=="function"){return tf.call(_581);}}return _581;},_580&&dojo.toJsonIndentStr);};return dojo;});},"dojo/_base/window":function(){define("dojo/_base/window",["./kernel","./lang","../sniff"],function(dojo,lang,has){var ret={global:dojo.global,doc:this["document"]||null,body:function(doc){doc=doc||dojo.doc;return doc.body||doc.getElementsByTagName("body")[0];},setContext:function(_582,_583){dojo.global=ret.global=_582;dojo.doc=ret.doc=_583;},withGlobal:function(_584,_585,_586,_587){var _588=dojo.global;try{dojo.global=ret.global=_584;return ret.withDoc.call(null,_584.document,_585,_586,_587);}finally{dojo.global=ret.global=_588;}},withDoc:function(_589,_58a,_58b,_58c){var _58d=ret.doc,oldQ=has("quirks"),_58e=has("ie"),isIE,mode,pwin;try{dojo.doc=ret.doc=_589;dojo.isQuirks=has.add("quirks",dojo.doc.compatMode=="BackCompat",true,true);if(has("ie")){if((pwin=_589.parentWindow)&&pwin.navigator){isIE=parseFloat(pwin.navigator.appVersion.split("MSIE ")[1])||undefined;mode=_589.documentMode;if(mode&&mode!=5&&Math.floor(isIE)!=mode){isIE=mode;}dojo.isIE=has.add("ie",isIE,true,true);}}if(_58b&&typeof _58a=="string"){_58a=_58b[_58a];}return _58a.apply(_58b,_58c||[]);}finally{dojo.doc=ret.doc=_58d;dojo.isQuirks=has.add("quirks",oldQ,true,true);dojo.isIE=has.add("ie",_58e,true,true);}}};1&&lang.mixin(dojo,ret);return ret;});},"dojo/dom-class":function(){define(["./_base/lang","./_base/array","./dom"],function(lang,_58f,dom){var _590="className";var cls,_591=/\s+/,a1=[""];function _592(s){if(typeof s=="string"||s instanceof String){if(s&&!_591.test(s)){a1[0]=s;return a1;}var a=s.split(_591);if(a.length&&!a[0]){a.shift();}if(a.length&&!a[a.length-1]){a.pop();}return a;}if(!s){return [];}return _58f.filter(s,function(x){return x;});};var _593={};cls={contains:function containsClass(node,_594){return ((" "+dom.byId(node)[_590]+" ").indexOf(" "+_594+" ")>=0);},add:function addClass(node,_595){node=dom.byId(node);_595=_592(_595);var cls=node[_590],_596;cls=cls?" "+cls+" ":" ";_596=cls.length;for(var i=0,len=_595.length,c;i<len;++i){c=_595[i];if(c&&cls.indexOf(" "+c+" ")<0){cls+=c+" ";}}if(_596<cls.length){node[_590]=cls.substr(1,cls.length-2);}},remove:function removeClass(node,_597){node=dom.byId(node);var cls;if(_597!==undefined){_597=_592(_597);cls=" "+node[_590]+" ";for(var i=0,len=_597.length;i<len;++i){cls=cls.replace(" "+_597[i]+" "," ");}cls=lang.trim(cls);}else{cls="";}if(node[_590]!=cls){node[_590]=cls;}},replace:function replaceClass(node,_598,_599){node=dom.byId(node);_593[_590]=node[_590];cls.remove(_593,_599);cls.add(_593,_598);if(node[_590]!==_593[_590]){node[_590]=_593[_590];}},toggle:function toggleClass(node,_59a,_59b){node=dom.byId(node);if(_59b===undefined){_59a=_592(_59a);for(var i=0,len=_59a.length,c;i<len;++i){c=_59a[i];cls[cls.contains(node,c)?"remove":"add"](node,c);}}else{cls[_59b?"add":"remove"](node,_59a);}return _59b;}};return cls;});},"dojo/_base/config":function(){define(["../has","require"],function(has,_59c){var _59d={};if(1){var src=_59c.rawConfig,p;for(p in src){_59d[p]=src[p];}}else{var _59e=function(_59f,_5a0,_5a1){for(p in _59f){p!="has"&&has.add(_5a0+p,_59f[p],0,_5a1);}};_59d=1?_59c.rawConfig:this.dojoConfig||this.djConfig||{};_59e(_59d,"config",1);_59e(_59d.has,"",1);}return _59d;});},"dojo/main":function(){define(["./_base/kernel","./has","require","./sniff","./_base/lang","./_base/array","./_base/config","./ready","./_base/declare","./_base/connect","./_base/Deferred","./_base/json","./_base/Color","./has!dojo-firebug?./_firebug/firebug","./_base/browser","./_base/loader"],function(_5a2,has,_5a3,_5a4,lang,_5a5,_5a6,_5a7){if(_5a6.isDebug){_5a3(["./_firebug/firebug"]);}1||has.add("dojo-config-require",1);if(1){var deps=_5a6.require;if(deps){deps=_5a5.map(lang.isArray(deps)?deps:[deps],function(item){return item.replace(/\./g,"/");});if(_5a2.isAsync){_5a3(deps);}else{_5a7(1,function(){_5a3(deps);});}}}return _5a2;});},"dojo/_base/event":function(){define("dojo/_base/event",["./kernel","../on","../has","../dom-geometry"],function(dojo,on,has,dom){if(on._fixEvent){var _5a8=on._fixEvent;on._fixEvent=function(evt,se){evt=_5a8(evt,se);if(evt){dom.normalizeEvent(evt);}return evt;};}var ret={fix:function(evt,_5a9){if(on._fixEvent){return on._fixEvent(evt,_5a9);}return evt;},stop:function(evt){if(has("dom-addeventlistener")||(evt&&evt.preventDefault)){evt.preventDefault();evt.stopPropagation();}else{evt=evt||window.event;evt.cancelBubble=true;on._preventDefault.call(evt);}}};if(1){dojo.fixEvent=ret.fix;dojo.stopEvent=ret.stop;}return ret;});},"dojo/sniff":function(){define(["./has"],function(has){if(1){var n=navigator,dua=n.userAgent,dav=n.appVersion,tv=parseFloat(dav);has.add("air",dua.indexOf("AdobeAIR")>=0),has.add("khtml",dav.indexOf("Konqueror")>=0?tv:undefined);has.add("webkit",parseFloat(dua.split("WebKit/")[1])||undefined);has.add("chrome",parseFloat(dua.split("Chrome/")[1])||undefined);has.add("safari",dav.indexOf("Safari")>=0&&!has("chrome")?parseFloat(dav.split("Version/")[1]):undefined);has.add("mac",dav.indexOf("Macintosh")>=0);has.add("quirks",document.compatMode=="BackCompat");has.add("ios",/iPhone|iPod|iPad/.test(dua));has.add("android",parseFloat(dua.split("Android ")[1])||undefined);if(!has("webkit")){if(dua.indexOf("Opera")>=0){has.add("opera",tv>=9.8?parseFloat(dua.split("Version/")[1])||tv:tv);}if(dua.indexOf("Gecko")>=0&&!has("khtml")&&!has("webkit")){has.add("mozilla",tv);}if(has("mozilla")){has.add("ff",parseFloat(dua.split("Firefox/")[1]||dua.split("Minefield/")[1])||undefined);}if(document.all&&!has("opera")){var isIE=parseFloat(dav.split("MSIE ")[1])||undefined;var mode=document.documentMode;if(mode&&mode!=5&&Math.floor(isIE)!=mode){isIE=mode;}has.add("ie",isIE);}has.add("wii",typeof opera!="undefined"&&opera.wiiremote);}}return has;});},"dojo/request/handlers":function(){define(["../json","../_base/kernel","../_base/array","../has"],function(JSON,_5aa,_5ab,has){has.add("activex",typeof ActiveXObject!=="undefined");var _5ac;if(has("activex")){var dp=["Msxml2.DOMDocument.6.0","Msxml2.DOMDocument.4.0","MSXML2.DOMDocument.3.0","MSXML.DOMDocument"];_5ac=function(_5ad){var _5ae=_5ad.data;if(!_5ae||!_5ae.documentElement){var text=_5ad.text;_5ab.some(dp,function(p){try{var dom=new ActiveXObject(p);dom.async=false;dom.loadXML(text);_5ae=dom;}catch(e){return false;}return true;});}return _5ae;};}var _5af={"javascript":function(_5b0){return _5aa.eval(_5b0.text||"");},"json":function(_5b1){return JSON.parse(_5b1.text||null);},"xml":_5ac};function _5b2(_5b3){var _5b4=_5af[_5b3.options.handleAs];_5b3.data=_5b4?_5b4(_5b3):(_5b3.data||_5b3.text);return _5b3;};_5b2.register=function(name,_5b5){_5af[name]=_5b5;};return _5b2;});},"dojo/aspect":function(){define("dojo/aspect",[],function(){"use strict";var _5b6,_5b7=0;function _5b8(_5b9,type,_5ba,_5bb){var _5bc=_5b9[type];var _5bd=type=="around";var _5be;if(_5bd){var _5bf=_5ba(function(){return _5bc.advice(this,arguments);});_5be={remove:function(){_5be.cancelled=true;},advice:function(_5c0,args){return _5be.cancelled?_5bc.advice(_5c0,args):_5bf.apply(_5c0,args);}};}else{_5be={remove:function(){var _5c1=_5be.previous;var next=_5be.next;if(!next&&!_5c1){delete _5b9[type];}else{if(_5c1){_5c1.next=next;}else{_5b9[type]=next;}if(next){next.previous=_5c1;}}},id:_5b7++,advice:_5ba,receiveArguments:_5bb};}if(_5bc&&!_5bd){if(type=="after"){var next=_5bc;while(next){_5bc=next;next=next.next;}_5bc.next=_5be;_5be.previous=_5bc;}else{if(type=="before"){_5b9[type]=_5be;_5be.next=_5bc;_5bc.previous=_5be;}}}else{_5b9[type]=_5be;}return _5be;};function _5c2(type){return function(_5c3,_5c4,_5c5,_5c6){var _5c7=_5c3[_5c4],_5c8;if(!_5c7||_5c7.target!=_5c3){_5c3[_5c4]=_5c8=function(){var _5c9=_5b7;var args=arguments;var _5ca=_5c8.before;while(_5ca){args=_5ca.advice.apply(this,args)||args;_5ca=_5ca.next;}if(_5c8.around){var _5cb=_5c8.around.advice(this,args);}var _5cc=_5c8.after;while(_5cc&&_5cc.id<_5c9){if(_5cc.receiveArguments){var _5cd=_5cc.advice.apply(this,args);_5cb=_5cd===_5b6?_5cb:_5cd;}else{_5cb=_5cc.advice.call(this,_5cb,args);}_5cc=_5cc.next;}return _5cb;};if(_5c7){_5c8.around={advice:function(_5ce,args){return _5c7.apply(_5ce,args);}};}_5c8.target=_5c3;}var _5cf=_5b8((_5c8||_5c7),type,_5c5,_5c6);_5c5=null;return _5cf;};};var _5d0=_5c2("after");var _5d1=_5c2("before");var _5d2=_5c2("around");return {before:_5d1,around:_5d2,after:_5d0};});},"dojo/ready":function(){define("dojo/ready",["./_base/kernel","./has","require","./domReady","./_base/lang"],function(dojo,has,_5d3,_5d4,lang){var _5d5=0,_5d6,_5d7=[],_5d8=0,_5d9=function(){_5d5=1;dojo._postLoad=dojo.config.afterOnLoad=true;if(_5d7.length){_5d6(_5da);}},_5da=function(){if(_5d5&&!_5d8&&_5d7.length){_5d8=1;var f=_5d7.shift();try{f();}finally{_5d8=0;}_5d8=0;if(_5d7.length){_5d6(_5da);}}};_5d3.on("idle",_5da);_5d6=function(){if(_5d3.idle()){_5da();}};var _5db=dojo.ready=dojo.addOnLoad=function(_5dc,_5dd,_5de){var _5df=lang._toArray(arguments);if(typeof _5dc!="number"){_5de=_5dd;_5dd=_5dc;_5dc=1000;}else{_5df.shift();}_5de=_5de?lang.hitch.apply(dojo,_5df):function(){_5dd();};_5de.priority=_5dc;for(var i=0;i<_5d7.length&&_5dc>=_5d7[i].priority;i++){}_5d7.splice(i,0,_5de);_5d6();};1||has.add("dojo-config-addOnLoad",1);if(1){var dca=dojo.config.addOnLoad;if(dca){_5db[(lang.isArray(dca)?"apply":"call")](dojo,dca);}}if(1&&dojo.config.parseOnLoad&&!dojo.isAsync){_5db(99,function(){if(!dojo.parser){dojo.deprecated("Add explicit require(['dojo/parser']);","","2.0");_5d3(["dojo/parser"]);}});}if(1){_5d4(_5d9);}else{_5d9();}return _5db;});},"dojo/_base/connect":function(){define(["./kernel","../on","../topic","../aspect","./event","../mouse","./sniff","./lang","../keys"],function(dojo,on,hub,_5e0,_5e1,_5e2,has,lang){has.add("events-keypress-typed",function(){var _5e3={charCode:0};try{_5e3=document.createEvent("KeyboardEvent");(_5e3.initKeyboardEvent||_5e3.initKeyEvent).call(_5e3,"keypress",true,true,null,false,false,false,false,9,3);}catch(e){}return _5e3.charCode==0&&!has("opera");});function _5e4(obj,_5e5,_5e6,_5e7,_5e8){_5e7=lang.hitch(_5e6,_5e7);if(!obj||!(obj.addEventListener||obj.attachEvent)){return _5e0.after(obj||dojo.global,_5e5,_5e7,true);}if(typeof _5e5=="string"&&_5e5.substring(0,2)=="on"){_5e5=_5e5.substring(2);}if(!obj){obj=dojo.global;}if(!_5e8){switch(_5e5){case "keypress":_5e5=_5e9;break;case "mouseenter":_5e5=_5e2.enter;break;case "mouseleave":_5e5=_5e2.leave;break;}}return on(obj,_5e5,_5e7,_5e8);};var _5ea={106:42,111:47,186:59,187:43,188:44,189:45,190:46,191:47,192:96,219:91,220:92,221:93,222:39,229:113};var _5eb=has("mac")?"metaKey":"ctrlKey";var _5ec=function(evt,_5ed){var faux=lang.mixin({},evt,_5ed);_5ee(faux);faux.preventDefault=function(){evt.preventDefault();};faux.stopPropagation=function(){evt.stopPropagation();};return faux;};function _5ee(evt){evt.keyChar=evt.charCode?String.fromCharCode(evt.charCode):"";evt.charOrCode=evt.keyChar||evt.keyCode;};var _5e9;if(has("events-keypress-typed")){var _5ef=function(e,code){try{return (e.keyCode=code);}catch(e){return 0;}};_5e9=function(_5f0,_5f1){var _5f2=on(_5f0,"keydown",function(evt){var k=evt.keyCode;var _5f3=(k!=13)&&k!=32&&(k!=27||!has("ie"))&&(k<48||k>90)&&(k<96||k>111)&&(k<186||k>192)&&(k<219||k>222)&&k!=229;if(_5f3||evt.ctrlKey){var c=_5f3?0:k;if(evt.ctrlKey){if(k==3||k==13){return _5f1.call(evt.currentTarget,evt);}else{if(c>95&&c<106){c-=48;}else{if((!evt.shiftKey)&&(c>=65&&c<=90)){c+=32;}else{c=_5ea[c]||c;}}}}var faux=_5ec(evt,{type:"keypress",faux:true,charCode:c});_5f1.call(evt.currentTarget,faux);if(has("ie")){_5ef(evt,faux.keyCode);}}});var _5f4=on(_5f0,"keypress",function(evt){var c=evt.charCode;c=c>=32?c:0;evt=_5ec(evt,{charCode:c,faux:true});return _5f1.call(this,evt);});return {remove:function(){_5f2.remove();_5f4.remove();}};};}else{if(has("opera")){_5e9=function(_5f5,_5f6){return on(_5f5,"keypress",function(evt){var c=evt.which;if(c==3){c=99;}c=c<32&&!evt.shiftKey?0:c;if(evt.ctrlKey&&!evt.shiftKey&&c>=65&&c<=90){c+=32;}return _5f6.call(this,_5ec(evt,{charCode:c}));});};}else{_5e9=function(_5f7,_5f8){return on(_5f7,"keypress",function(evt){_5ee(evt);return _5f8.call(this,evt);});};}}var _5f9={_keypress:_5e9,connect:function(obj,_5fa,_5fb,_5fc,_5fd){var a=arguments,args=[],i=0;args.push(typeof a[0]=="string"?null:a[i++],a[i++]);var a1=a[i+1];args.push(typeof a1=="string"||typeof a1=="function"?a[i++]:null,a[i++]);for(var l=a.length;i<l;i++){args.push(a[i]);}return _5e4.apply(this,args);},disconnect:function(_5fe){if(_5fe){_5fe.remove();}},subscribe:function(_5ff,_600,_601){return hub.subscribe(_5ff,lang.hitch(_600,_601));},publish:function(_602,args){return hub.publish.apply(hub,[_602].concat(args));},connectPublisher:function(_603,obj,_604){var pf=function(){_5f9.publish(_603,arguments);};return _604?_5f9.connect(obj,_604,pf):_5f9.connect(obj,pf);},isCopyKey:function(e){return e[_5eb];}};_5f9.unsubscribe=_5f9.disconnect;1&&lang.mixin(dojo,_5f9);return _5f9;});},"dojo/errors/CancelError":function(){define(["./create"],function(_605){return _605("CancelError",null,null,{dojoType:"cancel"});});}}});(function(){var _606=this.require;_606({cache:{}});!_606.async&&_606(["dojo"]);_606.boot&&_606.apply(null,_606.boot);})();
\ No newline at end of file
--- a/server/src/main/webapp/js/main_coweb.js	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,24 +0,0 @@
-//
-// Cooperative web application template.
-//
-// Copyright (c) The Dojo Foundation 2011. All Rights Reserved.
-//
-
-// assumes admin servlet deployed with the application 
-var cowebConfig = {
-    adminUrl : './admin'
-};
-
-//require(['corenkan']);
-
-require({moduleUrl : 'lib'},
-        ['coweb/main','dojo', 'corenkan'],
-function(coweb, dojo, corenkan) {
-    // do application setup here
-    
-	dojo.ready(function() {
-        //this.collab = corenkan.app.collab;
-    });
-    
-});
-
--- a/server/src/main/webapp/js/main_test_models.js	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,305 +0,0 @@
-(function() {
-	
-	var root = this;
-		
-	var Backbone = root.Backbone;
-	
-	var Rkns = root.Rkns = {};
-
-	root.ModelView = Backbone.View.extend({
-		
-		events : {
-			"click .show_form" : "show_form",
-			"click .remove_button" : "remove_click",
-		},
-		
-		initialize: function(options) {
-			_.bindAll(this);
-			this.template = _.template(options.template);
-			this.model.bind("change", this.render);
-			this.form_view = options.form_view;
-			this.form_el = options.form_el;
-			if(typeof options.getJSON === "function") {
-				this.getJSON = options.getJSON;
-			}
-		},
-		render: function() {
-			$(this.el).html(this.template(this.getJSON()));
-			return this;
-		},
-		show_form: function(evt) {
-			if(typeof this.form_view !== "undefined") {
-				this.form_view.render();
-				$(this.form_el).empty();
-				$(this.form_el).append(this.form_view.el);
-			}
-		},
-		getJSON : function() {
-			return this.model.toJSON();			
-		},
-		remove_click : function(evt) {
-			var obj_id = $(evt.currentTarget).attr("value");
-			if(typeof this.model.collection !== "undefined") {
-				this.model.collection.remove(this.model);
-			}
-		},
-
-	});
-	
-	root.ColView = Backbone.View.extend({
-		initialize: function(options) {
-			
-			_.bindAll(this);
-			this.element = options.element;
-			this.element_form = options.element_form;
-			this.element_form_el = options.element_form_el;
-			this.rendered = false;
-			
-			var that = this;
-			this.element_views = [];
-			
-			this.collection.each(function(elt) { 
-				this.add(elt); 
-			});
-			
-			this.collection.bind('add', this.add);
-			this.collection.bind('remove', this.remove);
-		},
-		
-		render : function() {
-			this.rendered = true;
-			var that = this;
-			this.$el.empty();
-			_(this.element_views).each(function(dvs){
-				that.$el.append(dvs.disp.render().el);				
-			});
-			
-			return this;
-		},
-		
-		add : function(elt) {
-			
-			var fv_args = _.extend({}, this.element_form, {model: elt});			
-			var fv = new FormView(fv_args);
-			
-			var dv_args = _.extend({}, this.element, {model: elt, tagName: 'li', form_view: fv, form_el: this.element_form_el});			
-			var dv = new ModelView(dv_args);
-			
-			this.element_views.push({disp:dv, form:fv});
-			
-			if(this.rendered) {
-				this.$el.append(dv.render().el);
-			}
-		},
-			
-		
-		remove : function(elt) {
-			var viewsToRemove = _(this.element_views).select(function(cvs) { return cvs.disp.model === elt; })[0];
-			this.element_views = _(this.element_views).without(viewsToRemove);
-			
-			if(this.rendered) {
-				viewsToRemove.disp.$el.remove();
-				viewsToRemove.form.$el.remove();
-			}
-		},
-		
-		remove_click : function(evt) {
-			var obj_id = $(evt.currentTarget).attr("value");
-			this.collection.remove(this.collection.get(obj_id));
-		}
-		
-	});
-	
-	root.FormView = Backbone.View.extend({
-		events : {
-			"change .form_field": "changed"
-		},
-		initialize: function(options) {
-			_.bindAll(this);
-			this.template = _.template(options.template);
-			this.model.bind("change", this.render);
-			if(typeof options.getJSON === "function") {
-				this.getJSON = options.getJSON;
-			}
-		},
-		render: function() {
-			this.$el.html(this.template(this.getJSON()));
-			return this;
-		},
-		changed: function(evt) {
-			var value = $(evt.currentTarget).val();
-			var field_name = $(evt.currentTarget).attr("name");
-			if(this.model.get(field_name) != value) {
-				this.model.set(field_name, value);
-			}
-		},
-		getJSON : function() {
-			return this.model.toJSON(); 
-		}
-	});
-	
-	
-	root.SelectCurrentUserView = Backbone.View.extend({
-		initialize: function(options) {
-			_.bindAll(this);
-			this.rendered = false;
-			
-			this.child_view_constructor = options.child_view_constructor;
-			this.child_tag_name = options.child_tag_name;
-			
-			this.children_views = [];
-			this.collection.each(this.add);
-			
-			this.collection.bind('add', this.add);
-			this.collection.bind('remove', this.remove);
-		},
-		add: function(elt) {
-			var child_view = new this.child_view_constructor({
-				model: elt,
-				tagName : this.child_tag_name
-			});
-			this.children_views.push(child_view);
-			
-			if (this.rendered) {
-				this.$el.append(child_view.render().el);
-			}
-		},
-		remove: function(elt) {
-			var view_to_remove = _(this.children_views).select(function(cv) { return cv.model === elt; })[0];
-			this.children_views = _(this.children_views).without(view_to_remove);
-			if (this.rendered) {
-				view_to_remove.$el.remove();
-			}
-		},
-		render: function() {
-			this.rendered = true;
-			var that = this;
-			
-			this.$el.empty().html("<option value=\"\">Unknown</option>");
-			
-			_(this.children_views).each(function(cv){
-				that.$el.append(cv.render().el);
-			});
-			
-			return this;
-		}
-		
-	});
-	
-	root.SelectUserView = Backbone.View.extend({
-		initialize: function(options) {
-			_.bindAll(this);
-			this.model.bind("change", this.render);
-		},		
-		render: function() {
-			this.$el.val(this.model.id).text(this.model.get("title"));
-			return this;
-		}
-	});
-	
-	root.CurrentUserView = Backbone.View.extend({
-		initialize : function() {
-			this._select_view = new SelectCurrentUserView({
-				el : this.el,
-				collection : this.model.get("users"),
-				child_view_constructor: SelectUserView,
-				child_tag_name: "option",
-			});
-		},
-		render: function() {
-			this.$el.empty();
-			this._select_view.render();
-			return this;
-		}
-		
-	});
-	
-	
-	root.BasicListView = Backbone.View.extend({
-		
-		initialize: function(options) {
-			_.bindAll(this);
-			
-			this.element_view_constructor = options.element_view_constructor;
-			if(typeof options.template !== "undefined") {
-				this.template = _.template(options.template);
-			}
-			
-			this.rendered = false;
-			this.element_views = [];
-			this.collection.each(this.add);
-			
-			this.collection.bind('add', this.add);
-			this.collection.bind('remove', this.remove);
-			this.collection.bind('reset', this.reset);
-			this.collection.bind('destroy', this.destroy);
-		},
-	
-		render: function() {
-			this.rendered = true;
-			var that = this;
-			this.$el.empty();
-			if(typeof this.template !== "undefined") {
-				var data = {};
-				if(typeof this.model !== "undefined") {
-					data = this.$el.model.toJSON();
-				}
-				this.$el.html(this.template(data));
-			}
-			_(this.element_views).each(function(dvs){
-				that.$el.append(dvs.render().el);
-			});
-
-			return this;
-		},
-		
-		add: function(elt) {
-			var element_view = new this.element_view_constructor({model: elt});
-			this.element_views.push(element_view);
-			if(this.rendered) {
-				this.$el.append(element_view.render().el);
-			}
-		},
-		
-		remove: function(elt) {
-			var element_view = _(this.element_views).select(function(cv) {return cv.model === elt;})[0];
-			this.element_views = _(this.element_views).without(element_view);
-			if(this.rendered) {
-				element_view.$el.remove();
-			}
-			
-		},
-
-		reset: function() {
-			_(this.element_views).each(function(cv) {
-				cv.$el.remove();
-			});
-			this.element_views = [];
-			this.collection.each(this.add);	
-		}
-	
-	});
-	
-	
-	root.BasicModelView = Backbone.View.extend({
-				
-		initialize: function(options) {
-			_.bindAll(this);
-			if(typeof options.template !== "undefined") {
-				this.template = _.template(options.template);
-			}
-			if(typeof options.getJSON === "function") {
-				this.getJSON = options.getJSON;
-			}
-			this.model.bind("change", this.render);
-		},
-		render: function() {
-			$(this.el).html(this.template(this.getJSON()));
-			return this;
-		},
-		getJSON : function() {
-			return this.model.toJSON();			
-		}
-	});
-	
-}).call(this);
--- a/server/src/main/webapp/js/models.js	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,160 +0,0 @@
-(function() {
-	
-	var root = this;
-		
-	var Backbone = root.Backbone;
-	
-	var Models = root.Rkns.Models = {};
-	
-	
-	Models.getUID = function(obj) {
-		var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
-		    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
-		    return v.toString(16);
-		});
-		return obj.type + "-" + guid; 
-	};
-	
-	
-	var RenkanModel = Backbone.RelationalModel.extend({
-		idAttribute : "_id",
-		constructor: function(options) {
-			
-			if (typeof options !== "undefined") {
-	            options._id = options._id || options.id || Models.getUID(this);
-	            options.title = options.title || "(untitled " + this.type + ")";
-	            options.description = options.description || "";
-	            options.uri = options.uri || "";
-	            
-	            if(typeof this.prepare === "function") {
-	            	options = this.prepare(options);
-	            }
-			}
-			Backbone.RelationalModel.prototype.constructor.call(this, options);
-		},
-		validate: function() {
-			if(!this.type) {
-				return "object has no type";
-			}
-		},
-		addReference : function(_options, _propName, _list, _id, _default) {
-		    var _element = _list.get(_id);
-		    if (typeof _element === "undefined" && typeof _default !== "undefined") {
-		        _options[_propName ] = _default;
-		    }
-		    else {
-		    	_options[_propName ] = _element;
-		    }
-		}
-	});
-	
-		
-	// USER
-	var User = Models.User = root.Rkns.Models.User = RenkanModel.extend({
-		type: "user",
-		prepare: function(options) {
-			options.color = options.color || "#666666";
-			return options;
-		}	
-	
-	});
-	
-	// NODE
-	var Node = Models.Node = root.Rkns.Models.Node = RenkanModel.extend({
-		type: "node",
-		relations: [{
-			type: Backbone.HasOne,
-			key: "created_by",
-			relatedModel: User,
-			reverseRelation : {
-				includeInJSON: '_id'
-			}
-		}],
-		prepare: function(options) {
-			project = options.project;
-			delete options["project"];
-			this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user);
-			options.description = options.description || "";			
-			return options;
-		}
-	
-	});
-	
-	// EDGE
-	var Edge = Models.Edge = root.Rkns.Models.Edge = RenkanModel.extend({
-		type: "edge",
-		relations: [
-		  {
-			type: Backbone.HasOne,
-			key: "created_by",
-			relatedModel: User,
-			reverseRelation : {
-				includeInJSON: '_id'
-			}
-		  },
-		  {
-		    type: Backbone.HasOne,
-			key: "from",
-			relatedModel: Node
-		  },
-		  {
-		    type: Backbone.HasOne,
-			key: "to",
-			relatedModel: Node
-		  },
-		],
-		prepare: function(options) {
-			project = options.project;
-			delete options.project;
-			this.addReference(options, "created_by", options.created_by, project.get("users"), project.current_user);
-			this.addReference(options, "from", options.from, project.get("nodes"));
-			this.addReference(options, "to", options.to, project.get("nodes"));
-			return options;
-		}
-	});
-		
-	// PROJECT
-	var Project = Models.Project = root.Rkns.Models.Project = RenkanModel.extend({
-		type: "project",
-		current_user : null,
-		relations: [
-		  {
-		    type: Backbone.HasMany,
-		    key: "users",
-		    relatedModel: User,
-		    reverseRelation: {
-	            key: 'project',
-	            includeInJSON: '_id'
-	        },
-		  },
-		  {
-		    type: Backbone.HasMany,
-		    key: "nodes",
-		    relatedModel: Node,
-		    reverseRelation: {
-	            key: 'project',
-	            includeInJSON: '_id'
-	        },
-		  },
-		  {
-		    type: Backbone.HasMany,
-		    key: "edges",
-		    relatedModel: Edge,
-		    reverseRelation: {
-	            key: 'project',
-	            includeInJSON: '_id'
-	        },
-		  }
-		],
-		addNode: function(_props) {
-			_props.project = this;
-			this.get("nodes").push(_props);
-		},
-		addUser: function(_props) {
-			this.get("users").push(_props);
-		}
-	});
-
-	
-}).call(this);
-
--- a/server/src/main/webapp/js/underscore.js	Tue Dec 11 00:01:41 2012 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-// 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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/css/index.css	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,107 @@
+ body {
+   margin: 0;
+   height: 100%;
+   color: #333;
+   font: 14px helvetica, sans-serif;
+   background: #ddd;
+   background: -webkit-radial-gradient(circle,#aaa,#eee 60%) center fixed;
+   background: -moz-radial-gradient(circle,#aaa,#eee 60%) center fixed;
+   background: -ms-radial-gradient(circle,#aaa,#eee 60%) center fixed;
+   background: -o-radial-gradient(circle,#aaa,#eee 60%) center fixed;
+   border-top: 8px solid rgba(51,51,51,.8);
+ }
+ #wrapper {
+   border-top: 1px solid #999;
+   margin-top: 160px;
+   padding: 15px;
+   background: #eee;
+   background: -webkit-linear-gradient(#fff,#ccc);
+   background: -moz-linear-gradient(#fff,#ccc);
+   background: -ms-linear-gradient(#fff,#ccc);
+   background: -o-linear-gradient(#fff,#ccc);
+   opacity: .9;
+   box-shadow: 0px 1px 8px rgba(0,0,0,0.3);
+ }
+ #inner {
+   width: 300px;
+   margin: 0 auto;
+ }
+ #button {
+   margin: 0 auto;
+   border-radius: 3px;
+   text-align: center;
+   font: 36px verdana,arial,sans-serif;
+   color: white;
+   text-shadow: 0 -1px 0 rgba(0,0,0,.8);
+   height: 70px;
+   line-height: 70px;
+   background: #555;
+   background: -webkit-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
+   background: -moz-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
+   background: -ms-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
+   background: -o-linear-gradient(#5F5F5F,#565656 50%,#4C4C4C 51%,#373737);
+   box-shadow: inset 0 1px 3px rgba(0,0,0,0.9);
+ }
+ #button:hover {
+   cursor: pointer;
+   background: #666;
+   background: -webkit-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
+   background: -moz-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
+   background: -ms-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
+   background: -o-linear-gradient(#707070,#666666 50%,#5B5B5B 51%,#474747);
+ }
+ #button:active {
+   box-shadow: inset 0 1px 12px rgba(0,0,0,0.9);
+   background: #444;
+ }
+ #label {
+   text-align: left;
+   text-shadow: 0 1px 1px #fff;
+   margin: 16px auto 0;
+ }
+ form {
+   height: 38px;
+   background: #fff;
+   border: 1px solid #bbb;
+   border-radius: 3px;
+   position: relative;
+ }
+ button, input {
+   font-weight: bold;
+   font-size: 15px;
+ }
+ input[type="text"] {
+   border-radius: 3px;
+   box-sizing: border-box;
+   -moz-box-sizing: border-box;   
+   padding: 0 45px 0 10px;
+   *padding: 0; /* IE7 hack */
+   width: 100%;
+   height: 100%;
+   outline: none;
+   border: none;
+   position: absolute;
+ }
+ button[type="submit"] {
+   position: absolute;
+   right: 0;
+   width: 45px;
+   height: 38px;
+ }
+ @media only screen and (min-device-width: 320px) and (max-device-width: 720px) {
+   body {
+     background: #bbb;
+     background: -webkit-linear-gradient(#aaa,#eee 60%) center fixed;
+     background: -moz-linear-gradient(#aaa,#eee 60%) center fixed;
+     background: -ms-linear-gradient(#aaa,#eee 60%) center fixed;
+   }
+   #wrapper {
+     margin-top: 0;
+   }
+   #inner {
+     width: 95%;        
+   }
+   #label {
+     text-align: center;
+   }
+ }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/css/renkan-publish.css	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,134 @@
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed, 
+figure, figcaption, footer, header, hgroup, 
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+    margin: 0;
+    padding: 0;
+    border: 0;
+    font-size: 100%;
+    font: inherit;
+    vertical-align: baseline;
+}
+
+ul, li {
+    list-style: none;
+}
+
+input::-moz-focus-inner /*Remove button padding in FF*/
+{ 
+    border: 0;
+    padding: 0;
+}
+
+table {
+    border-collapse: separate; border-spacing: 0;
+}
+
+th, td {
+    vertical-align: top;
+}
+
+img a {
+    border: none;
+}
+
+body {
+    font-size: 10px; font-family: Arial, Helvetica, sans-serif;
+    background: #ffffff; color: #000000;
+}
+
+a {
+    color: #303080;
+}
+
+.Rk-ProjectList {
+    position: absolute; left: 0; top: 0; list-style: none; padding: 0; margin: 0;
+}
+
+.Rk-Project {
+    list-style: none; margin-right: 5px; padding: 5px; height: 15px; font-size: 13px; font-weight: bold;
+    float: left; border-top-left-radius: 8px; border-top-right-radius: 8px;
+    background: #505050; color: #E0E0E0; cursor: pointer;
+    background: -moz-linear-gradient(top, #333333 20%, #666666 80%);
+}
+
+.Rk-Project:hover {
+    background: -moz-linear-gradient(bottom, #333333 20%, #666666 80%);
+}
+
+.Rk-Project.active {
+    background: #505080;
+    color: #ffffc0;
+    background: -moz-linear-gradient(bottom, #333366 20%, #666699 80%);
+}
+
+.Rk-Render {
+    position: absolute; left: 0; top: 25px; right: 0; bottom: 0;
+    background: -moz-linear-gradient(top, rgba(180,180,180,.2) 0, rgba(255,255,255,.2) 30%, rgba(255,255,255,.2) 70%, rgba(180,180,180,.2) 100%);
+}
+
+.Rk-Canvas {
+    background: -moz-linear-gradient(left, rgba(180,180,180,.2) 0, rgba(255,255,255,.2) 30%, rgba(255,255,255,.2) 70%, rgba(180,180,180,.2) 100%);
+    position: absolute; left: 0; top: 0; right: 0; bottom: 0;
+}
+
+.Rk-Editor {
+    position: absolute; left: 0; top: 0;
+}
+
+.Rk-CloseX {
+    float: right; cursor: pointer;
+}
+
+.Rk-Editor h2 {
+    font-size: 14px; font-weight: bold;
+}
+
+.Rk-Editor p {
+    margin: 5px 0; font-size: 11px;
+}
+
+.Rk-RelatedList {
+    list-style: none;
+}
+
+.Rk-Related {
+    color: #a000c0; cursor: pointer; margin: 5px 0;
+}
+
+.Rk-Related b {
+    font-weight: bolder;
+}
+
+.Rk-Related:hover {
+    text-decoration: underline;
+}
+
+.Rk-ZoomButtons {
+    position: absolute; left: 0; top: 0; cursor: pointer;
+}
+
+.Rk-ZoomIn, .Rk-ZoomOut {
+    width: 21px; height: 20px; background: url(../img/zoombuttons.png); margin: 5px;
+}
+
+.Rk-ZoomIn:hover {
+    background-position: 0 -20px;
+}
+
+.Rk-ZoomOut {
+    background-position: -21px 0;
+}
+
+.Rk-ZoomOut:hover {
+    background-position: -21px -20px;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/css/renkan.css	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,468 @@
+html, body, div, span, applet, object, iframe,
+h1, h2, h3, h4, h5, h6, p, blockquote, pre,
+a, abbr, acronym, address, big, cite, code,
+del, dfn, em, img, ins, kbd, q, s, samp,
+small, strike, strong, sub, sup, tt, var,
+b, u, i, center,
+dl, dt, dd, ol, ul, li,
+fieldset, form, label, legend,
+table, caption, tbody, tfoot, thead, tr, th, td,
+article, aside, canvas, details, embed, 
+figure, figcaption, footer, header, hgroup, 
+menu, nav, output, ruby, section, summary,
+time, mark, audio, video {
+    margin: 0;
+    padding: 0;
+    border: 0;
+    font-size: 100%;
+    font: inherit;
+    vertical-align: baseline;
+}
+
+ul, li {
+    list-style: none;
+}
+
+input::-moz-focus-inner /*Remove button padding in FF*/
+{ 
+    border: 0;
+    padding: 0;
+}
+
+table {
+    border-collapse: separate; border-spacing: 0;
+}
+
+th, td {
+    vertical-align: top;
+}
+
+img a {
+    border: none;
+}
+
+body {
+    font-size: 10px; font-family: Arial, Helvetica, sans-serif;
+    background: #ffffff; color: #000000;
+}
+
+a {
+    color: #6060c0;
+}
+
+.Rk-Main {
+    position: absolute; left: 0; top: 0; right: 0; bottom: 0;
+}
+
+.Rk-Render {
+    position: absolute; left: 300px; top: 0; right: 0; bottom: 0;
+    background: #ffffff;
+    background: -moz-linear-gradient(left, #f3f3f3 0, #ffffff 30%, #ffffff 70%, #f3f3f3 100%);
+    background: -webkit-linear-gradient(left, #f3f3f3 0, #ffffff 30%, #ffffff 70%, #f3f3f3 100%);
+}
+
+/* Top Bar */
+
+.Rk-TopBar {
+    position: absolute; left: 0; top: 0; right: 0; height: 35px;
+    background: #333333;
+    background: -moz-linear-gradient(top, #505050 5px, #1e1e1e 30px);
+    background: -webkit-linear-gradient(top, #505050 5px, #1e1e1e 30px);
+}
+
+.Rk-PadTitle {
+    float: left; font-size: 14px; height: 16px; margin: 4px 5px; width: 130px; background: #666666; padding: 4px; border: 1px solid #333333;
+    border-radius: 3px; box-shadow: 0 1px 0 #505050; color: #ffffff; font-weight: bold;
+}
+
+.Rk-Users {
+    float: right; width: 130px; margin: 4px 5px;
+}
+
+.Rk-CurrentUser {
+    font-size: 13px; background: #666666; padding: 4px; border: 1px solid #333333; border-radius: 3px; box-shadow: 0 1px 0 #505050; color: #ffffff;
+}
+
+.Rk-CurrentUser-Color {
+    display: inline-block; width: 12px; height: 12px; border: 1px solid #333333; margin: -2px 2px;
+}   
+
+.Rk-UserList {
+    box-shadow: 0 2px 2px #999999;
+    position: relative; z-index: 3; display: none; padding-top: 8px;
+}
+
+.Rk-User {
+    background: #ffffff; padding: 3px; font-size: 12px; border-style: solid solid none; border-color: #cccccc; border-width: 1px;
+}
+
+.Rk-TopBar-Button {
+    float: right; background: url(../img/topbarbuttons.png) no-repeat; height: 35px; cursor: pointer;
+    position: relative;
+}
+
+.Rk-TopBar-Separator {
+    background: #666666;
+    background: -moz-linear-gradient(top, #666666 20%, #333333 80%);
+    background: -webkit-linear-gradient(top, #666666 20%, #333333 80%);
+    content: ""; display: block; height: 35px; float: right; width: 1px; border-left: 1px solid #111111;
+    margin: 0 3px;
+}
+
+.Rk-TopBar-Tooltip {
+    position: absolute; top: 31px; left: 50%; margin-left: -60px; width: 120px; z-index: 3; display: none;
+}
+
+.Rk-TopBar-Tooltip-Contents {
+    background: #ffffff;
+    font-size: 13px; font-weight: bold; color: #6060c0; text-align: center; padding: 2px;
+    border-style: none solid solid; border-width: 1px; border-color: #cccccc; border-bottom-left-radius: 2px; border-bottom-right-radius: 2px;
+}
+
+.Rk-TopBar-Tooltip-Tip {
+    height: 7px; background: url(../img/tooltiparrow.png) center no-repeat; margin: 0 1px;
+}
+
+.Rk-AddNode-Button {
+    width: 34px;
+}
+
+.Rk-AddNode-Button:hover {
+    background-position: 0 -35px;
+}
+
+.Rk-FullScreen-Button {
+    width: 34px; background-position: -34px 0;
+}
+
+.Rk-FullScreen-Button:hover {
+    background-position: -34px -35px;
+}
+
+.Rk-AddEdge-Button {
+    width: 34px; background-position: -68px 0;
+}
+
+.Rk-AddEdge-Button:hover {
+    background-position: -68px -35px;
+}
+/* Canvas */
+
+.Rk-Canvas {
+    background: -moz-linear-gradient(top, rgba(180,180,180,.2) 0, rgba(255,255,255,.2) 30%, rgba(255,255,255,.2) 70%, rgba(180,180,180,.2) 100%);
+    background: -webkit-linear-gradient(top, rgba(180,180,180,.2) 0, rgba(255,255,255,.2) 30%, rgba(255,255,255,.2) 70%, rgba(180,180,180,.2) 100%);
+    position: absolute; left: 0; top: 35px; right: 0; bottom: 0; z-index: 1;
+}
+
+/* Editors */
+
+.Rk-Editor {
+    position: absolute; left: 0; top: 35px; right: 0; z-index: 2;
+}
+
+.Rk-Notifications {
+    position: absolute; right: 15px; top: 15px; width: 200px;
+    padding: 10px; border-radius: 8px; display: none;
+    color: #ffffff; font-size: 13px; text-align: center; font-weight: bold;
+    background: rgba(20,20,20,.7);
+    background: -moz-linear-gradient(top, rgba(40,40,40,.7) 20%, rgba(0,0,0,.7) 80%);
+    background: -webkit-linear-gradient(top, rgba(40,40,40,.7) 20%, rgba(0,0,0,.7) 80%);
+}
+
+.Rk-CloseX {
+    float: right; cursor: pointer;
+}
+
+.Rk-Editor h2 {
+    font-size: 16px; font-weight: bold;
+}
+
+.Rk-Editor p {
+    margin: 5px 0; font-size: 12px;
+}
+
+.Rk-Editor label {
+    display: inline-block; width: 70px;
+}
+
+a.Rk-Edit-Goto {
+    display: block; float: right; width: 18px; height: 17px; margin: 1px 0; border: none; background: url(../img/goto.png);
+}
+
+.Rk-Edit-Title, .Rk-Edit-URI, .Rk-Edit-Image {
+    font-size: 12px; width: 225px;
+}
+
+.Rk-Edit-URI {
+    font-size: 12px; width: 205px;
+}
+
+.Rk-Edit-ImgPreview {
+    border: 1px solid #666; margin: 5px 0; min-height: 10px; display: block;
+    max-width: 100% !important; max-height: 100px !important;
+}
+
+.Rk-Editor textarea {
+    width: 225px; height: 120px; resize: none;
+}
+
+.Rk-UserColor {
+    display: inline-block; width: 1em; height: 1em; border: 1px solid #666666; margin: -2px 2px;
+}
+
+.Rk-ZoomButtons {
+    position: absolute; left: 0; top: 0; cursor: pointer;
+}
+
+.Rk-ZoomIn, .Rk-ZoomOut {
+    width: 21px; height: 20px; background: url(../img/zoombuttons.png); margin: 5px;
+}
+
+.Rk-ZoomIn:hover {
+    background-position: 0 -20px;
+}
+
+.Rk-ZoomOut {
+    background-position: -21px 0;
+}
+
+.Rk-ZoomOut:hover {
+    background-position: -21px -20px;
+}
+
+/* Bins */
+
+.Rk-Title {
+    position: absolute; left: 0; top: 0; width: 300px; height: 35px;
+    background: #333333;
+    background: -moz-linear-gradient(top, #505050 5px, #1e1e1e 30px);
+    background: -webkit-linear-gradient(top, #505050 5px, #1e1e1e 30px);
+}
+
+.Rk-Title h1 {
+    font-size: 18px; color: #ffffff; margin: 5px;
+}
+
+
+.Rk-Title:after {
+    background: #666666;
+    background: -moz-linear-gradient(top, #666666 20%, #333333 80%);
+    background: -webkit-linear-gradient(top, #666666 20%, #333333 80%);
+    content: ""; display: block; height: 35px;
+    left: 298px; position: absolute; top: 0; width: 1px; border-left: 1px solid #111111;
+}
+
+.Rk-Bins {
+    background: #ffffff; position: absolute; left: 0; top: 35px; width: 299px; bottom: 0;
+    overflow: hidden; border-right: 1px solid #252525;
+}
+
+/* Bin Search Field */
+
+.Rk-Search-Form {
+    padding: 10px; height: 27px;
+    background: #666666;
+    background: -moz-linear-gradient(top, #606060 20%, #909090 80%);
+    background: -webkit-linear-gradient(top, #606060 20%, #909090 80%);
+}
+
+.Rk-Search-Input, .Rk-Search-Select {
+    float: left; border-width: 1px; border-color: #003050;
+}
+
+.Rk-Search-Input {
+    border-top-left-radius: 5px; border-bottom-left-radius: 5px; border-style: solid;
+    font-size: 13px; width: 190px; background: #ffffff; height: 15px; padding: 5px;
+}
+
+.Rk-Search-Select {
+    display: inline-block; position: relative; width: 45px;
+    border-style: solid none; cursor: pointer;
+    height: 25px; background: #ffffff url(../img/more.png) 30px 10px no-repeat;
+}
+
+.Rk-Search-Select:hover {
+    background-color: #3030FF;
+}
+
+.Rk-Search-Current {
+    width: 40px; height: 20px; margin: 2px; background-repeat: no-repeat;
+}
+
+.Rk-Search-List {
+    width: 180px; margin-left: 15px; font-size: 13px;
+    position: absolute; right: 0; top: 25px; background: #ffffff;
+    box-shadow: 1px 1px 2px #505050; display: none;
+    border: 1px solid #cccccc;
+}
+
+.Rk-Search-List li {
+    padding: 2px 2px 2px 30px; border-top: 1px solid #cccccc; height: 16px;
+    background-color: #ffffff; background-repeat: no-repeat; cursor: pointer;
+}
+
+.Rk-Search-List li:hover {
+    background-color: #3030ff; color: #ffffff;
+}
+
+.Rk-Search-Submit {
+    border: 1px solid #003050; height: 27px; width: 30px; border-top-right-radius: 5px; border-bottom-right-radius: 5px;
+    background: #333333 center no-repeat url(../img/search.png); cursor: pointer;
+}
+
+.Rk-Search-Submit:hover {
+    background-color: #999999;
+}
+
+/* Individual Bins */
+
+
+.Rk-Bin-Title {
+    background: #333333;
+    background: -moz-linear-gradient(top, #505050 20%, #1e1e1e 80%);
+    background: -webkit-linear-gradient(top, #505050 20%, #1e1e1e 80%);
+    border-bottom: 1px solid #666666; font-weight: bold;
+    font-size: 14px; padding: 5px 5px 5px 30px; cursor: pointer; color: #f0f0f0;
+}
+
+.Rk-Bin-Close {
+    float: right; display: block; font-size: 16px; font-weight: bold; margin: 2px 3px 0; color: #f0f0f0; cursor: pointer;
+    text-shadow: -1px -1px 1px #999999, 1px 1px 1px #000000; text-decoration: none;
+}
+
+.Rk-Bin-Close:hover {
+    color: #ffff80;
+}
+
+.Rk-Bin-Title:hover {
+    color: #ffffe0;
+    background: -moz-linear-gradient(top, rgb(20,20,20) 20%, rgb(60,60,60) 80%);
+    background: -webkit-linear-gradient(top, rgb(20,20,20) 20%, rgb(60,60,60) 80%);
+}
+
+.Rk-Bin-Refresh {
+    width: 18px; height: 17px; background: url(../img/refresh.png); display: block; float: right; margin-top: 4px;
+}
+
+.Rk-Bin-Refresh:hover {
+    background-position: -18px 0;
+}
+
+.Rk-Bin-Title-Icon {
+    float: left; width: 25px; margin: 2px;
+}
+
+.Rk-Bin-Main {
+    overflow: auto;
+    background: #ffffff;
+    background: -moz-linear-gradient(top, #e0e0e0 0, #FFFFFF 2%, #FFFFFF 98%, #e0e0e0 100%);
+    background: -webkit-linear-gradient(top, #e0e0e0 0, #FFFFFF 2%, #FFFFFF 98%, #e0e0e0 100%);
+}
+
+.Rk-Bin-Item {
+    cursor: move;
+}
+
+.Rk-Bin-Item:hover {
+    background: -moz-linear-gradient(top, rgba(0,0,0,.1) 20%, rgba(128,128,128,.1) 80%);
+    background: -webkit-linear-gradient(top, rgba(0,0,0,.1) 20%, rgba(128,128,128,.1) 80%);
+}
+
+.Rk-Bin-Item.dragging {
+    background: -moz-linear-gradient(top, rgba(128,0,0,.1) 20%, rgba(255,128,128,.1) 80%);
+    background: -webkit-linear-gradient(top, rgba(128,0,0,.1) 20%, rgba(255,128,128,.1) 80%);
+    color: #660000;
+}
+
+.Rk-Bin-Item.selected {
+    background: #ffffc0;
+}
+
+.Rk-Bin-Main li {
+    padding: 2px; border-bottom: 1px solid #cccccc;
+    clear: both;
+}
+
+.Rk-Bin-Main h3 {
+    font-size: 14px; font-style: italic; font-weight: bold; text-align: center;
+}
+
+.Rk-Bin-Main h4 {
+    font-size: 12px; font-weight: bold;
+}
+
+.Rk-Bin-Main p {
+    font-size: 11px;
+}
+
+.Rk-Twitter-Icon {
+    background-image: url(../img/search-logos.png); background-position: 0 -80px;
+}
+
+.Rk-Twitter-Title-Icon {
+    height: 20px; background: url(../img/search-logos.png); background-position: 0 -80px;
+}
+
+.Rk-Twitter-TwImage {
+    float: left; width: 48px; height: 48px; margin: 2px 0;
+}
+
+.Rk-Twitter-TwTitle, .Rk-Twitter-TwDate, .Rk-Twitter-TwText, .Rk-Twitter-TwActions {
+    margin: 2px 0 2px 50px;
+}
+
+p.Rk-Twitter-TwDate {
+    font-size: 11px; font-style: italic;
+}
+
+p.Rk-Twitter-TwActions {
+    font-size: 11px;
+}
+
+.Rk-Bin-Main .searchmatch {
+    background: #ffff80;
+}
+
+.Rk-Wikipedia-Search-Icon {
+    background-image: url(../img/search-logos.png);
+}
+
+.Rk-Wikipedia-Icon {
+    float: left; margin: 3px;
+}
+
+.Rk-Wikipedia-Title-Icon {
+    height: 20px; background: url(../img/search-logos.png);
+}
+
+.Rk-Wikipedia-Lang-en {
+    background-position: 0 -20px;
+}
+
+.Rk-Wikipedia-Lang-fr {
+    background-position: 0 -40px;
+}
+
+.Rk-Wikipedia-Lang-ja {
+    background-position: 0 -60px;
+}
+
+.Rk-Wikipedia-Result {
+    min-height: 51px;
+}
+
+.Rk-Wikipedia-Result p, .Rk-Wikipedia-Result h4 {
+    margin-left: 54px;
+}
+
+.Rk-Ldt-Tag-Icon {
+    float: left; margin: 0 2px 0 0;
+}
+
+.Rk-Ldt-Annotation-Icon {
+    float: left; margin: 3px;
+}
+
+.Rk-Clear {
+    clear: both;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/css/style.css	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,130 @@
+/* =============================================================================
+   HTML5 Boilerplate CSS: h5bp.com/css
+   ========================================================================== */
+
+article, aside, details, figcaption, figure, footer, header, hgroup, nav, section { display: block; }
+audio, canvas, video { display: inline-block; *display: inline; *zoom: 1; }
+audio:not([controls]) { display: none; }
+[hidden] { display: none; }
+
+html { font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
+html, button, input, select, textarea { font-family: sans-serif; color: #222; }
+body { margin: 0; font-size: 1em; line-height: 1.4; }
+
+::-moz-selection { background: #fe57a1; color: #fff; text-shadow: none; }
+::selection { background: #fe57a1; color: #fff; text-shadow: none; }
+
+a { color: #00e; }
+a:visited { color: #551a8b; }
+a:hover { color: #06e; }
+a:focus { outline: thin dotted; }
+a:hover, a:active { outline: 0; }
+
+abbr[title] { border-bottom: 1px dotted; }
+b, strong { font-weight: bold; }
+blockquote { margin: 1em 40px; }
+dfn { font-style: italic; }
+hr { display: block; height: 1px; border: 0; border-top: 1px solid #ccc; margin: 1em 0; padding: 0; }
+ins { background: #ff9; color: #000; text-decoration: none; }
+mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }
+pre, code, kbd, samp { font-family: monospace, serif; _font-family: 'courier new', monospace; font-size: 1em; }
+pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }
+q { quotes: none; }
+q:before, q:after { content: ""; content: none; }
+small { font-size: 85%; }
+
+sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }
+sup { top: -0.5em; }
+sub { bottom: -0.25em; }
+
+ul, ol { margin: 1em 0; padding: 0 0 0 40px; }
+dd { margin: 0 0 0 40px; }
+nav ul, nav ol { list-style: none; list-style-image: none; margin: 0; padding: 0; }
+
+img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }
+
+svg:not(:root) { overflow: hidden; }
+
+figure { margin: 0; }
+
+form { margin: 0; }
+fieldset { border: 0; margin: 0; padding: 0; }
+label { cursor: pointer; }
+legend { border: 0; *margin-left: -7px; padding: 0; white-space: normal; }
+button, input, select, textarea { font-size: 100%; margin: 0; vertical-align: baseline; *vertical-align: middle; }
+button, input { line-height: normal; }
+button, input[type="button"], input[type="reset"], input[type="submit"] { cursor: pointer; -webkit-appearance: button; *overflow: visible; }
+button[disabled], input[disabled] { cursor: default; }
+input[type="checkbox"], input[type="radio"] { box-sizing: border-box; padding: 0; *width: 13px; *height: 13px; }
+input[type="search"] { -webkit-appearance: textfield; -moz-box-sizing: content-box; -webkit-box-sizing: content-box; box-sizing: content-box; }
+input[type="search"]::-webkit-search-decoration, input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; }
+button::-moz-focus-inner, input::-moz-focus-inner { border: 0; padding: 0; }
+textarea { overflow: auto; vertical-align: top; resize: vertical; }
+input:valid, textarea:valid {  }
+input:invalid, textarea:invalid { background-color: #f0dddd; }
+
+table { border-collapse: collapse; border-spacing: 0; }
+td { vertical-align: top; }
+
+.chromeframe { margin: 0.2em 0; background: #ccc; color: black; padding: 0.2em 0; }
+
+
+
+/* ===== Primary Styles ========================================================
+   Author:
+   ========================================================================== */
+.templates { display: none; }
+
+.project_desc_label { font-weight: bold; }
+
+#project_display {
+    background: #9cbc2c;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    border-radius: 5px;
+    padding: 20px;
+    width: 400px;
+}
+
+
+
+/* =============================================================================
+   Media Queries
+   ========================================================================== */
+
+@media only screen and (min-width: 35em) {
+	/* Style adjustments for viewports that meet the condition */
+}
+
+/* =============================================================================
+   Non-Semantic Helper Classes
+   ========================================================================== */
+
+.ir { display: block; border: 0; text-indent: -999em; overflow: hidden; background-color: transparent; background-repeat: no-repeat; text-align: left; direction: ltr; *line-height: 0; }
+.ir br { display: none; }
+.hidden { display: none !important; visibility: hidden; }
+.visuallyhidden { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
+.visuallyhidden.focusable:active, .visuallyhidden.focusable:focus { clip: auto; height: auto; margin: 0; overflow: visible; position: static; width: auto; }
+.invisible { visibility: hidden; }
+.clearfix:before, .clearfix:after { content: ""; display: table; }
+.clearfix:after { clear: both; }
+.clearfix { *zoom: 1; }
+
+/* =============================================================================
+   Print Styles
+   ========================================================================== */
+ 
+@media print {
+  * { background: transparent !important; color: black !important; box-shadow:none !important; text-shadow: none !important; filter:none !important; -ms-filter: none !important; } /* Black prints faster: h5bp.com/s */
+  a, a:visited { text-decoration: underline; }
+  a[href]:after { content: " (" attr(href) ")"; }
+  abbr[title]:after { content: " (" attr(title) ")"; }
+  .ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }  /* Don't show links for images, or javascript/internal links */
+  pre, blockquote { border: 1px solid #999; page-break-inside: avoid; }
+  thead { display: table-header-group; } /* h5bp.com/t */
+  tr, img { page-break-inside: avoid; }
+  img { max-width: 100% !important; }
+  @page { margin: 0.5cm; }
+  p, h2, h3 { orphans: 3; widows: 3; }
+  h2, h3 { page-break-after: avoid; }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/data/simple-persist.php	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,14 @@
+<?php
+    header('Content-Type: application/json; charset=utf-8');
+    $file = "dynamic-data.json";
+    if (isset($_GET['reset']) && $_GET['reset']) {
+        $resetfile = "test-data.json";
+        file_put_contents($file, file_get_contents($resetfile));
+    }
+    if ($_SERVER['REQUEST_METHOD'] == 'PUT') {
+        file_put_contents($file, file_get_contents("php://input"));
+        echo json_encode(array("result" => "OK"));
+    } else {
+        echo file_get_contents($file);
+    }
+?>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/data/test-data.json	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,298 @@
+{
+    "users": [
+        {
+            "_id": "u-anonymous",
+            "title": "anonymous",
+            "uri": "",
+            "description": "",
+            "color": "#dd00dd"
+        }, {
+            "_id": "u-cybunk",
+            "title": "Samuel",
+            "uri": "http://twitter.com/cybunk",
+            "description": "",
+            "color": "#e00000"
+        }, {
+            "_id": "u-raphv",
+            "title": "Raphael",
+            "uri": "http://twitter.com/raphv",
+            "description": "",
+            "color": "#00a000"
+        }
+    ],
+    "nodes": [
+        {
+            "_id": "node-2012-08-22-9da6eef6c6391d05-0001",
+            "title": "Chocs technologiques et tâches de l’université...",
+            "uri": "http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/e328e188-ff2f-11e0-b9e1-00145ea49a02/#id=s_6C326EED-B91A-AEDF-032D-40D9A60AAD7E",
+            "description": "Bernard Stiegler:\nChocs technologiques et tâches de l’université. L'époque des digital studies\nベルナール・スティグレールによるプレゼンテーション『テクノロジーの衝撃と大学の諸課題――デジタル・スタディーズの時代』 (langue française フランス語)",
+            "position": {
+                "x": 35.50145330596697,
+                "y": -79.8809523809524
+            },
+            "image": "http://www.iri.centrepompidou.fr/dev/~veltr/hitachi-tests/img/ldt-segment.png",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "node-2012-08-22-9da6eef6c6391d05-0002",
+            "title": "Wiki: ベルナール・スティグレール",
+            "uri": "http://ja.wikipedia.org/wiki/%E3%83%99%E3%83%AB%E3%83%8A%E3%83%BC%E3%83%AB%E3%83%BB%E3%82%B9%E3%83%86%E3%82%A3%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%AB",
+            "description": "|image_name = Bernard-Stiegler.jpg\n'''ベルナール・スティグレール'''('''Bernard Stiegler''',[[1952年]][[4月1日]] - )は、[[フランス]]の[[哲学者]]。\n",
+            "position": {
+                "x": -212.89325104742056,
+                "y": -142.05921029473706
+            },
+            "image": "http://www.iri.centrepompidou.fr/dev/~veltr/hitachi-tests/img/wikipedia.png",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "node-2012-08-22-9da6eef6c6391d05-0003",
+            "title": "Wiki: Bernard Stiegler",
+            "uri": "http://fr.wikipedia.org/wiki/Bernard_Stiegler",
+            "description": "Bernard Stiegler, né le 1 | avril | 1952, est un philosophe  français  qui axe sa réflexion sur les enjeux des mutations actuelles —  ... ",
+            "position": {
+                "x": -199.613212880364,
+                "y": -297.6715155910511
+            },
+            "image": "http://www.iri.centrepompidou.fr/dev/~veltr/hitachi-tests/img/wikipedia.png",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "node-2012-08-22-9da6eef6c6391d05-0004",
+            "title": "Tag: Stiegler",
+            "uri": "http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/search/?search=Stiegler&field=all",
+            "description": "Tag 'Stiegler'",
+            "position": {
+                "x": -68.40773762286169,
+                "y": -205.76155213199334
+            },
+            "image": "http://www.iri.centrepompidou.fr/dev/~veltr/hitachi-tests/img/ldt-tag.png",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "node-2012-08-22-9da6eef6c6391d05-0009",
+            "title": "Wiki: Humanités numériques",
+            "uri": "http://fr.wikipedia.org/wiki/Humanit%C3%A9s_num%C3%A9riques",
+            "description": "une proposition de définition a été élaborée lors du THATCamp des 18 et 19 mai 2010 sous la forme d'un « Manifeste des digital humanities : ... ",
+            "position": {
+                "x": -227.84295519248332,
+                "y": 91.1816115015538
+            },
+            "image": "http://www.iri.centrepompidou.fr/dev/~veltr/hitachi-tests/img/wikipedia.png",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "node-2012-08-22-9da6eef6c6391d05-000a",
+            "title": "Wiki: デジタル・ヒューマニティーズ",
+            "uri": "http://ja.wikipedia.org/wiki/%E3%83%87%E3%82%B8%E3%82%BF%E3%83%AB%E3%83%BB%E3%83%92%E3%83%A5%E3%83%BC%E3%83%9E%E3%83%8B%E3%83%86%E3%82%A3%E3%83%BC%E3%82%BA",
+            "description": "...(digital humanities)は、コンピューティングと人文科学(humanities)諸分野と間の接点に関して調査、研究、教育、および�\n* Centre for Computing in the Humanities\n",
+            "position": {
+                "x": -221.48701615763574,
+                "y": 242.80740052545508
+            },
+            "image": "http://www.iri.centrepompidou.fr/dev/~veltr/hitachi-tests/img/wikipedia.png",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "node-2012-08-22-9da6eef6c6391d05-000b",
+            "title": "Digital studies",
+            "uri": "",
+            "description": "",
+            "position": {
+                "x": -62.798895620242085,
+                "y": 32.09820725365255
+            },
+            "created_by": "u-raphv"
+        }, {
+            "_id": "node-2012-08-22-9da6eef6c6391d05-000c",
+            "title": "Digital Humanities",
+            "uri": "",
+            "description": "",
+            "position": {
+                "x": -110.57020731070799,
+                "y": 160.92139209086253
+            },
+            "created_by": "u-raphv"
+        }, {
+            "_id": "node-2012-08-22-b778a9fc31296d6b-0008",
+            "title": "Les rétentions (Tweet)",
+            "uri": "http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/e328e188-ff2f-11e0-b9e1-00145ea49a02/#id=a924b90c-46a1-4f0a-9e13-bcf69f7b5de0-127750274034049024",
+            "description": "Tweet by Vincent Puig: #tfcem Les rétentions primaires (perception) s'aggrégent et forment des rétentions secondaires (mémoire), gravées sur rétentions tertiaires",
+            "position": {
+                "x": 186.15055288633457,
+                "y": -184.66836073709257
+            },
+            "image": "http://a1.twimg.com/profile_images/379424006/PortaitVP120Ko_normal.jpg",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "node-2012-08-22-b778a9fc31296d6b-0009",
+            "title": "L'origine de la géométrie (Tweet)",
+            "uri": "http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/e328e188-ff2f-11e0-b9e1-00145ea49a02/#id=5b34ae61-ffb1-4535-a479-007cb0ef57e8-127752118743474177",
+            "description": "Tweet by Vincent Puig: #tfcem L'origine de la géométrie: l'écriture est processus long de transindividuation. Nos tweets quasi temps réel sont de même nature++",
+            "position": {
+                "x": 87.82365160023906,
+                "y": -280.3591650733953
+            },
+            "image": "http://a1.twimg.com/profile_images/379424006/PortaitVP120Ko_normal.jpg",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "node-2012-08-22-b778a9fc31296d6b-000a",
+            "title": "Polemictweet : un outil Digital Studies (Tweet)",
+            "uri": "http://ldt.iri.centrepompidou.fr/ldtplatform/ldt/front/player/e328e188-ff2f-11e0-b9e1-00145ea49a02/#id=4b34e895-221b-467b-a0f2-8ff4ae87cae4-127758736415666177",
+            "description": "Tweet by Vincent Puig:\n#tfcem Polemictweet : un outil Digital Studies pensé à l'IRI comme rétention tertiaire numérique avec les même armes que l'industrie",
+            "position": {
+                "x": 168.59118089416432,
+                "y": 57.97933221077804
+            },
+            "image": "http://a1.twimg.com/profile_images/379424006/PortaitVP120Ko_normal.jpg",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "node-2012-08-22-b778a9fc31296d6b-000f",
+            "title": "Rétention (Définition AI)",
+            "uri": "http://arsindustrialis.org/vocabulaire-ars-industrialis/r%C3%A9tention",
+            "description": "Les rétentions sont ce qui est retenu ou recueilli par la conscience. Ce terme est emprunté à Husserl ; mais les rétentions tertiaires sont propres à la philosophie de Bernard Stiegler.\n\nLes rétentions sont des sélections : dans le flux de conscience que vous êtes vous ne pouvez pas tout retenir, ce que vous retenez est ce que vous êtes, mais ce que vous retenez dépend ce que vous avez déjà retenu.\n\nL’espèce humaine, étant originairement constituée par sa prothéticité, dispose d’une troisième mémoire, ni génétique, ni épigénétique : le milieu épiphylogénétique, comme ensemble des rétentions tertiaires formant des dispositifs rétentionels.",
+            "position": {
+                "x": 276.41820932461013,
+                "y": -62.82646518900019
+            },
+            "image": "http://www.arsindustrialis.org/sites/default/files/userfiles/user3/Logovocabulairenoir.JPG",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "node-2012-08-22-5b349e49066c1b01-0001",
+            "title": "Polemic Tweet",
+            "uri": "http://polemictweet.com/",
+            "description": "Polemic Tweet Web Site",
+            "position": {
+                "x": 220.96817493563964,
+                "y": 196.75746750735607
+            },
+            "image": "http://www.polemictweet.com/images/ENMI_2010_logo.gif",
+            "created_by": "u-cybunk"
+        }
+    ],
+    "edges": [
+        {
+            "_id": "edge-2012-08-22-9da6eef6c6391d05-0005",
+            "title": "is about",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-9da6eef6c6391d05-0002",
+            "to": "node-2012-08-22-9da6eef6c6391d05-0004",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "edge-2012-08-22-9da6eef6c6391d05-0006",
+            "title": "is about",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-9da6eef6c6391d05-0003",
+            "to": "node-2012-08-22-9da6eef6c6391d05-0004",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "edge-2012-08-22-9da6eef6c6391d05-0007",
+            "title": "speech by",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-9da6eef6c6391d05-0001",
+            "to": "node-2012-08-22-9da6eef6c6391d05-0004",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "edge-2012-08-22-b778a9fc31296d6b-0001",
+            "title": "is about",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-9da6eef6c6391d05-0001",
+            "to": "node-2012-08-22-9da6eef6c6391d05-000b",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "edge-2012-08-22-b778a9fc31296d6b-0002",
+            "title": "Are related to",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-9da6eef6c6391d05-000b",
+            "to": "node-2012-08-22-9da6eef6c6391d05-000c",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "edge-2012-08-22-b778a9fc31296d6b-0003",
+            "title": "is about",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-9da6eef6c6391d05-0009",
+            "to": "node-2012-08-22-9da6eef6c6391d05-000c",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "edge-2012-08-22-b778a9fc31296d6b-0004",
+            "title": "is about",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-9da6eef6c6391d05-000a",
+            "to": "node-2012-08-22-9da6eef6c6391d05-000c",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "edge-2012-08-22-b778a9fc31296d6b-000b",
+            "title": "is about",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-b778a9fc31296d6b-000a",
+            "to": "node-2012-08-22-9da6eef6c6391d05-000b",
+            "created_by": "u-raphv"
+        }, {
+            "_id": "edge-2012-08-22-b778a9fc31296d6b-000c",
+            "title": "tweeted during",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-b778a9fc31296d6b-0009",
+            "to": "node-2012-08-22-9da6eef6c6391d05-0001",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "edge-2012-08-22-b778a9fc31296d6b-000d",
+            "title": "tweeted during",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-b778a9fc31296d6b-0008",
+            "to": "node-2012-08-22-9da6eef6c6391d05-0001",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "edge-2012-08-22-b778a9fc31296d6b-000e",
+            "title": "tweeted during",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-b778a9fc31296d6b-000a",
+            "to": "node-2012-08-22-9da6eef6c6391d05-0001",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "edge-2012-08-22-b778a9fc31296d6b-0011",
+            "title": "is about",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-b778a9fc31296d6b-0008",
+            "to": "node-2012-08-22-b778a9fc31296d6b-000f",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "edge-2012-08-22-b778a9fc31296d6b-0012",
+            "title": "is about",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-b778a9fc31296d6b-000a",
+            "to": "node-2012-08-22-b778a9fc31296d6b-000f",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "edge-2012-08-22-5b349e49066c1b01-0002",
+            "title": "is about",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-b778a9fc31296d6b-000a",
+            "to": "node-2012-08-22-5b349e49066c1b01-0001",
+            "created_by": "u-cybunk"
+        }, {
+            "_id": "edge-2012-09-06-70cc0c2d5e1112d3-0001",
+            "title": "is an example of",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-b778a9fc31296d6b-000a",
+            "to": "node-2012-08-22-9da6eef6c6391d05-000b",
+            "created_by": "u-anonymous"
+        }, {
+            "_id": "edge-2012-09-06-70cc0c2d5e1112d3-0002",
+            "title": "tool used",
+            "uri": "",
+            "description": "",
+            "from": "node-2012-08-22-5b349e49066c1b01-0001",
+            "to": "node-2012-08-22-b778a9fc31296d6b-000a",
+            "created_by": "u-anonymous"
+        }
+    ]
+}
\ No newline at end of file
Binary file server/src/main/webapp/static/img/edit.png has changed
Binary file server/src/main/webapp/static/img/goto.png has changed
Binary file server/src/main/webapp/static/img/ldt-point.png has changed
Binary file server/src/main/webapp/static/img/ldt-segment.png has changed
Binary file server/src/main/webapp/static/img/ldt-tag.png has changed
Binary file server/src/main/webapp/static/img/link.png has changed
Binary file server/src/main/webapp/static/img/more.png has changed
Binary file server/src/main/webapp/static/img/refresh.png has changed
Binary file server/src/main/webapp/static/img/remove.png has changed
Binary file server/src/main/webapp/static/img/search-logos.png has changed
Binary file server/src/main/webapp/static/img/search.png has changed
Binary file server/src/main/webapp/static/img/tooltiparrow.png has changed
Binary file server/src/main/webapp/static/img/topbarbuttons.png has changed
Binary file server/src/main/webapp/static/img/wikipedia.png has changed
Binary file server/src/main/webapp/static/img/zoombuttons.png has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/config.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,38 @@
+//
+// Config file. Split out from the app for ease of overlaying a new config
+// without affecting the app controller.
+//
+// Copyright (c) The Dojo Foundation 2011. All Rights Reserved.
+//
+var dojoConfig = {
+	baseUrl: '/renkan',
+	async:true,
+	paths : {
+	   coweb : 'lib/coweb',
+	   cowebx: 'lib/cowebx',
+	   org : 'lib/org',
+	   corenkan: 'static/js/corenkan',
+	   underscore: 'static/lib/underscore-min',
+	},
+	/*packages:[{
+		name: 'dojo',
+		location:'lib/dojo',
+		main:'main'
+	},
+	{
+		name: 'dijit',
+		location:'lib/dijit',
+		main:'main'
+	},
+	{
+		name: 'dojox',
+		location:'lib/dojox',
+		main:'main'
+	}]*/
+};
+
+var cowebConfig = {
+	    adminUrl : '/renkan/admin'
+};
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/corenkan-json.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,19 @@
+
+Rkns.jsonIO = function(_renkan, _opts) {
+    var _proj = _renkan.project;
+    if (typeof _opts.http_method == "undefined") {
+        _opts.http_method = 'PUT';
+    }
+    var _load = function() {
+        Rkns.$.getJSON(_opts.url, function(_data) {
+        	_data['_id'] = _data['id'];
+        	_proj.set(_data, {silent: true});
+            _renkan.renderer.autoScale();
+            if(typeof _opts.callback !== "undefined") {
+            	console.log("Corenkan json: project loaded, calling callback fro project id " + _proj.id, _data, _proj);
+            	_opts.callback(_proj, _renkan);
+            }
+        });
+    };
+    _load();
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/corenkan.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,306 @@
+define([
+    "dojo",
+    "coweb/main"
+], function(dojo, coweb) {
+	
+    var CoRenkan = function() {
+    };
+
+    var proto = CoRenkan.prototype;
+
+    proto.init = function() {
+    	console.log("ready callback");
+    	
+    	//this.initCollab();
+    	
+    	var sess = coweb.initSession();
+    	var that = this;
+    	sess.onStatusChange = function(status) {
+    	    console.log(status);
+    	    if(typeof that.onStatusChange === "function") {
+    	    	that.onStatusChange(status);
+    	    }
+    	};
+    	sess.prepare();
+    	this.project = null;
+                
+    };
+    
+    proto.initCollab = function(id) {    	
+    	this.collab = coweb.initCollab({id : id});
+    	this.collab.subscribeSync("project", this, "onRemoteProjectChange");    	
+    };
+    
+    function prepareValues(obj,c) {
+		values = {};
+		for(var fieldname in c.changes) {
+			if(c.changes[fieldname]) {
+				values[fieldname] = obj.get(fieldname);
+			}    			
+		}
+		return values;
+    }
+    
+    proto.addObjectBind = function(type, obj, c, options) {
+		console.log("add " + type,obj, c, options, this.project.toJSON());
+		var values = obj.toJSON();
+		var new_values = {
+			id: obj.id,
+			_type: type,
+			_index: options.index,
+			_project_id : obj.get("project").get("_id")
+		};
+		for(var k in new_values) {
+			values[k] = new_values[k];
+		}
+		console.log("add values : ", values);
+		this.collab.sendSync(type, values, "insert", options.index);
+    };
+    
+    proto.removeObjectBind = function(type, obj, c, options) {
+		console.log("delete " + type,obj, c, options);
+		var values = {
+    	    id: obj.id,
+    	    _type: type,
+    	    _index: options.index,
+    	    _project_id : obj.get("project").id
+    	};
+		this.collab.sendSync(type, values, "delete", options.index);    	
+    };
+    
+    proto.updateObjectBind = function(type, obj, options) {
+		console.log("change " + type,obj, options);
+		if(obj.hasChanged()) {
+			var values = {
+			    id: obj.id,
+	    	    _type: type,
+	    	    _project_id : obj.get("project").id
+	    	};
+			_.extend(values,obj.changed);		
+	    	this.collab.sendSync(type, values);
+		}
+    };
+    
+    proto.setProject = function(project) {
+    	
+    	console.log("project", project);
+    	
+    	var projectFields = ["title", "description", "uri"];    	
+    	var that = this;
+    	for(var fieldIndex in projectFields) {
+    		(function(fi){
+	    		var field = projectFields[fi];
+	        	project.bind("change:"+field, function(obj, c) {
+	        		console.log(c);
+	        		values = {
+	        		    id: obj.id,
+	        		    type: "project",
+	        		    project_id: obj.id
+	        		};
+	        		values[field] = c;
+	        		that.collab.sendSync("project", values);
+	        	});
+    		})(fieldIndex);
+    	}
+    	
+    	project.get("nodes").bind("add", function(obj, c, options) {    		
+    		that.addObjectBind("node", obj, c, options);
+    	});
+    	
+    	project.get("nodes").bind("remove", function(obj, c, options) {
+    		that.removeObjectBind("node", obj, c, options);
+    	});
+    	
+    	project.get("nodes").bind("change", function(obj, options) {
+    		that.updateObjectBind("node", obj, options);
+    	});
+
+    	project.get("users").bind("add", function(obj, c, options) {    		
+    		that.addObjectBind("user", obj, c, options);
+    	});
+    	
+    	project.get("users").bind("remove", function(obj, c, options) {
+    		that.removeObjectBind("user", obj, c, options);
+    	});
+    	
+    	project.get("users").bind("change", function(obj, options) {
+    		that.updateObjectBind("user", obj, options);
+    	});
+
+    	project.get("edges").bind("add", function(obj, c, options) {    		
+    		that.addObjectBind("edge", obj, c, options);
+    	});
+    	
+    	project.get("edges").bind("remove", function(obj, c, options) {
+    		that.removeObjectBind("edge", obj, c, options);
+    	});
+    	
+    	project.get("edges").bind("change", function(obj, options) {
+    		that.updateObjectBind("edge", obj, options);
+    	});
+
+    	
+    	this.project = project;
+    	this.initCollab("renkan_" + project.id);
+    };
+    
+    
+    /**
+     * Called when a remote data store for project changes in some manner. Dispatches to
+     * local methods for insert, update, delete handling.
+     * TODO: manage project list change on server
+     * @param args Cooperative web event
+     */
+    proto.onRemoteProjectChange = function(args) {    	
+    	console.log("Remote project change", args);
+    	if (args.type === "update") {
+            this.onRemoteProjectUpdate(args.value, args.position);
+    	}
+        /*if (args.type === "insert") {
+            this.onRemoteInsert(value, args.position);
+        } else if (args.type === "update") {
+            this.onRemoteUpdate(value, args.position);
+        } else if (args.type === "delete") {
+            this.onRemoteDelete(args.position);
+        }*/
+    };
+    
+
+    /**
+     * Called when a remote data store for nodes changes in some manner. Dispatches to
+     * local methods for insert, update, delete handling.
+     * @param args Cooperative web event
+     */
+    proto.onRemoteObjectChange = function(field, args) {    	
+    	console.log("Remote "+ field +" change",args);
+        if (args.type === "insert") {
+            this.onRemoteObjectInsert(field, args.value, args.position);
+        } else if (args.type === "update") {
+            this.onRemoteNodeUpdate(field, args.value, args.position);
+        } else if (args.type === "delete") {
+            this.onRemoteNodeDelete(field, args.position);
+        }
+    };
+
+    
+    /**
+     * Called when a remote data store for nodes changes in some manner. Dispatches to
+     * local methods for insert, update, delete handling.
+     * @param args Cooperative web event
+     */
+    proto.onRemoteNodeChange = function(args) {
+    	this.onRemoteObjectChange("nodes", args);
+    };
+
+
+    /**
+     * Called when a remote data store for nodes changes in some manner. Dispatches to
+     * local methods for insert, update, delete handling.
+     * @param args Cooperative web event
+     */
+    proto.onRemoteUserChange = function(args) {    	
+    	this.onRemoteObjectChange("users", args);
+    };
+
+    /**
+     * Called when a remote data store for nodes changes in some manner. Dispatches to
+     * local methods for insert, update, delete handling.
+     * @param args Cooperative web event
+     */
+    proto.onRemoteUserChange = function(args) {    	
+    	this.onRemoteObjectChange("edges", args);
+    };
+
+        
+    /**
+     * Called when a project attribute changes value in a remote data store.
+     * Updates the attribute value of the item with the same id in the local
+     * data store.
+     *
+     * @param value Item data sent by remote data store
+     * @param position Which item to update.
+     */
+    proto.onRemoteProjectUpdate = function(values, position) {
+    	var project_id = values['id'];
+    	if(typeof(project_id) === "undefined") {
+    		return;
+		}
+    	
+    	if(this.project != null && project_id == this.project.id) {
+    		for(var fieldname in values) {
+    			if(fieldname != "id" && fieldname != "type") {
+    				this.project.set(fieldname, values[fieldname]);
+    			}
+    		}
+    	}
+    	
+    };    
+
+    /**
+     * Called when an object is inserted in a remote data store.
+     *
+     * @param value Item data sent by remote data store
+     * @param position Which item to update.
+     */
+    proto.onRemoteObjectInsert = function(field, values, position) {
+    	
+    	var coll = this.project.get(field);    	
+    	var object_id = values['id'];    	
+    	
+    	var obj = coll.get(object_id);
+    	
+    	if(obj != null) {
+    		this.onRemoteObjectUpdate(field, values, coll.indexOf(obj));
+    	}
+    	else {
+    		this.project.get(field).add(values, {at:position});
+    	}
+    	
+    };
+    
+    /**
+     * Called when a object attribute changes value in a remote data store.
+     * Updates the attribute value of the item with the same id in the local
+     * data store.
+     *
+     * @param field The collection field
+     * @param value Item data sent by remote data store
+     * @param position Which item to update.
+     */
+    proto.onRemoteObjectUpdate = function(field, values, position) {
+
+    	var object_id = values['id'];
+    	
+    	if(this.project != null) {
+    		for(var obj in this.project.get(field)) {
+    			if(obj.id == object_id) {
+    	    		for(var fieldname in values) {
+    	    			if(fieldname != "id" && fieldname != "type") {
+    	    				obj.set(fieldname, values[fieldname]);
+    	    			}
+    	    		}
+    			}
+    		}
+    	}
+    };
+    
+    /**
+     * Called when a object is deleted in a remote data store.
+     *
+     * @param position Which item to update.
+     */
+    proto.onRemoteObjectDelete = function(field, position) {
+    	this.project.get(field).remove(this.project.get(field).at(position));
+    };
+    
+        
+    var app = new CoRenkan();
+    dojo.ready(function() {
+        app.init();
+    });
+    
+    
+    return {
+    	app: app
+    };
+});
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/dojo.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,15 @@
+/*
+	Copyright (c) 2004-2011, The Dojo Foundation All Rights Reserved.
+	Available via Academic Free License >= 2.1 OR the modified BSD license.
+	see: http://dojotoolkit.org/license for details
+*/
+
+/*
+	This is an optimized version of Dojo, built for deployment and not for
+	development. To get sources and documentation, please visit:
+
+		http://dojotoolkit.org
+*/
+
+//>>built
+(function(_1,_2){var _3=function(){},_4=function(it){for(var p in it){return 0;}return 1;},_5={}.toString,_6=function(it){return _5.call(it)=="[object Function]";},_7=function(it){return _5.call(it)=="[object String]";},_8=function(it){return _5.call(it)=="[object Array]";},_9=function(_a,_b){if(_a){for(var i=0;i<_a.length;){_b(_a[i++]);}}},_c=function(_d,_e){for(var p in _e){_d[p]=_e[p];}return _d;},_f=function(_10,_11){return _c(new Error(_10),{src:"dojoLoader",info:_11});},_12=1,uid=function(){return "_"+_12++;},req=function(_13,_14,_15){return _16(_13,_14,_15,0,req);},_17=this,doc=_17.document,_18=doc&&doc.createElement("DiV"),has=req.has=function(_19){return _6(_1a[_19])?(_1a[_19]=_1a[_19](_17,doc,_18)):_1a[_19];},_1a=has.cache=_2.hasCache;has.add=function(_1b,_1c,now,_1d){(_1a[_1b]===undefined||_1d)&&(_1a[_1b]=_1c);return now&&has(_1b);};0&&has.add("host-node",_1.has&&"host-node" in _1.has?_1.has["host-node"]:(typeof process=="object"&&process.versions&&process.versions.node&&process.versions.v8));if(0){require("./_base/configNode.js").config(_2);_2.loaderPatch.nodeRequire=require;}0&&has.add("host-rhino",_1.has&&"host-rhino" in _1.has?_1.has["host-rhino"]:(typeof load=="function"&&(typeof Packages=="function"||typeof Packages=="object")));if(0){for(var _1e=_1.baseUrl||".",arg,_1f=this.arguments,i=0;i<_1f.length;){arg=(_1f[i++]+"").split("=");if(arg[0]=="baseUrl"){_1e=arg[1];break;}}load(_1e+"/_base/configRhino.js");rhinoDojoConfig(_2,_1e,_1f);}for(var p in _1.has){has.add(p,_1.has[p],0,1);}var _20=1,_21=2,_22=3,_23=4,_24=5;if(0){_20="requested";_21="arrived";_22="not-a-module";_23="executing";_24="executed";}var _25=0,_26="sync",xd="xd",_27=[],_28=0,_29=_3,_2a=_3,_2b;if(1){req.isXdUrl=_3;req.initSyncLoader=function(_2c,_2d,_2e){if(!_28){_28=_2c;_29=_2d;_2a=_2e;}return {sync:_26,requested:_20,arrived:_21,nonmodule:_22,executing:_23,executed:_24,syncExecStack:_27,modules:_2f,execQ:_30,getModule:_31,injectModule:_32,setArrived:_33,signal:_34,finishExec:_35,execModule:_36,dojoRequirePlugin:_28,getLegacyMode:function(){return _25;},guardCheckComplete:_37};};if(1){var _38=location.protocol,_39=location.host;req.isXdUrl=function(url){if(/^\./.test(url)){return false;}if(/^\/\//.test(url)){return true;}var _3a=url.match(/^([^\/\:]+\:)\/+([^\/]+)/);return _3a&&(_3a[1]!=_38||(_39&&_3a[2]!=_39));};1||has.add("dojo-xhr-factory",1);has.add("dojo-force-activex-xhr",1&&!doc.addEventListener&&window.location.protocol=="file:");has.add("native-xhr",typeof XMLHttpRequest!="undefined");if(has("native-xhr")&&!has("dojo-force-activex-xhr")){_2b=function(){return new XMLHttpRequest();};}else{for(var _3b=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"],_3c,i=0;i<3;){try{_3c=_3b[i++];if(new ActiveXObject(_3c)){break;}}catch(e){}}_2b=function(){return new ActiveXObject(_3c);};}req.getXhr=_2b;has.add("dojo-gettext-api",1);req.getText=function(url,_3d,_3e){var xhr=_2b();xhr.open("GET",_3f(url),false);xhr.send(null);if(xhr.status==200||(!location.host&&!xhr.status)){if(_3e){_3e(xhr.responseText,_3d);}}else{throw _f("xhrFailed",xhr.status);}return xhr.responseText;};}}else{req.async=1;}var _40=new Function("return eval(arguments[0]);");req.eval=function(_41,_42){return _40(_41+"\r\n////@ sourceURL="+_42);};var _43={},_44="error",_34=req.signal=function(_45,_46){var _47=_43[_45];_9(_47&&_47.slice(0),function(_48){_48.apply(null,_8(_46)?_46:[_46]);});},on=req.on=function(_49,_4a){var _4b=_43[_49]||(_43[_49]=[]);_4b.push(_4a);return {remove:function(){for(var i=0;i<_4b.length;i++){if(_4b[i]===_4a){_4b.splice(i,1);return;}}}};};var _4c=[],_4d={},_4e=[],_4f={},map=req.map={},_50=[],_2f={},_51="",_52={},_53="url:",_54={},_55={};if(1){var _56=function(_57){var p,_58,_59,now,m;for(p in _54){_58=_54[p];_59=p.match(/^url\:(.+)/);if(_59){_52[_53+_5a(_59[1],_57)]=_58;}else{if(p=="*now"){now=_58;}else{if(p!="*noref"){m=_5b(p,_57);_52[m.mid]=_52[_53+m.url]=_58;}}}}if(now){now(_5c(_57));}_54={};},_5d=function(s){return s.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g,function(c){return "\\"+c;});},_5e=function(map,_5f){_5f.splice(0,_5f.length);for(var p in map){_5f.push([p,map[p],new RegExp("^"+_5d(p)+"(/|$)"),p.length]);}_5f.sort(function(lhs,rhs){return rhs[3]-lhs[3];});return _5f;},_60=function(_61){var _62=_61.name;if(!_62){_62=_61;_61={name:_62};}_61=_c({main:"main"},_61);_61.location=_61.location?_61.location:_62;if(_61.packageMap){map[_62]=_61.packageMap;}if(!_61.main.indexOf("./")){_61.main=_61.main.substring(2);}_4f[_62]=_61;},_63=function(_64,_65,_66){for(var p in _64){if(p=="waitSeconds"){req.waitms=(_64[p]||0)*1000;}if(p=="cacheBust"){_51=_64[p]?(_7(_64[p])?_64[p]:(new Date()).getTime()+""):"";}if(p=="baseUrl"||p=="combo"){req[p]=_64[p];}if(1&&p=="async"){var _67=_64[p];req.legacyMode=_25=(_7(_67)&&/sync|legacyAsync/.test(_67)?_67:(!_67?_26:false));req.async=!_25;}if(_64[p]!==_1a){req.rawConfig[p]=_64[p];p!="has"&&has.add("config-"+p,_64[p],0,_65);}}if(!req.baseUrl){req.baseUrl="./";}if(!/\/$/.test(req.baseUrl)){req.baseUrl+="/";}for(p in _64.has){has.add(p,_64.has[p],0,_65);}_9(_64.packages,_60);for(_1e in _64.packagePaths){_9(_64.packagePaths[_1e],function(_68){var _69=_1e+"/"+_68;if(_7(_68)){_68={name:_68};}_68.location=_69;_60(_68);});}_5e(_c(map,_64.map),_50);_9(_50,function(_6a){_6a[1]=_5e(_6a[1],[]);if(_6a[0]=="*"){_50.star=_6a[1];}});_5e(_c(_4d,_64.paths),_4e);_9(_64.aliases,function(_6b){if(_7(_6b[0])){_6b[0]=new RegExp("^"+_5d(_6b[0])+"$");}_4c.push(_6b);});for(p in _64.config){var _6c=_31(p,_66);_6c.config=_c(_6c.config||{},_64.config[p]);}if(_64.cache){_56();_54=_64.cache;if(_64.cache["*noref"]){_56();}}_34("config",[_64,req.rawConfig]);};if(has("dojo-cdn")||1){var _6d=doc.getElementsByTagName("script"),i=0,_6e,_6f,src,_70;while(i<_6d.length){_6e=_6d[i++];if((src=_6e.getAttribute("src"))&&(_70=src.match(/(((.*)\/)|^)dojo\.js(\W|$)/i))){_6f=_70[3]||"";_2.baseUrl=_2.baseUrl||_6f;src=(_6e.getAttribute("data-dojo-config")||_6e.getAttribute("djConfig"));if(src){_55=req.eval("({ "+src+" })","data-dojo-config");}if(0){var _71=_6e.getAttribute("data-main");if(_71){_55.deps=_55.deps||[_71];}}break;}}}if(0){try{if(window.parent!=window&&window.parent.require){var doh=window.parent.require("doh");doh&&_c(_55,doh.testConfig);}}catch(e){}}req.rawConfig={};_63(_2,1);if(has("dojo-cdn")){_4f.dojo.location=_6f;if(_6f){_6f+="/";}_4f.dijit.location=_6f+"../dijit/";_4f.dojox.location=_6f+"../dojox/";}_63(_1,1);_63(_55,1);}else{_4d=_2.paths;_4e=_2.pathsMapProg;_4f=_2.packs;_4c=_2.aliases;_50=_2.mapProgs;_2f=_2.modules;_52=_2.cache;_51=_2.cacheBust;req.rawConfig=_2;}if(0){req.combo=req.combo||{add:_3};var _72=0,_73=[],_74=null;}var _75=function(_76){_37(function(){_9(_76.deps,_32);if(0&&_72&&!_74){_74=setTimeout(function(){_72=0;_74=null;req.combo.done(function(_77,url){var _78=function(){_79(0,_77);_7a();};_73.push(_77);_7b=_77;req.injectUrl(url,_78,_77);_7b=0;},req);},0);}});},_16=function(a1,a2,a3,_7c,_7d){var _7e,_7f;if(_7(a1)){_7e=_31(a1,_7c,true);if(_7e&&_7e.executed){return _7e.result;}throw _f("undefinedModule",a1);}if(!_8(a1)){_63(a1,0,_7c);a1=a2;a2=a3;}if(_8(a1)){if(!a1.length){a2&&a2();}else{_7f="require*"+uid();for(var mid,_80=[],i=0;i<a1.length;){mid=a1[i++];_80.push(_31(mid,_7c));}_7e=_c(_81("",_7f,0,""),{injected:_21,deps:_80,def:a2||_3,require:_7c?_7c.require:req,gc:1});_2f[_7e.mid]=_7e;_75(_7e);var _82=_83&&_25!=_26;_37(function(){_36(_7e,_82);});if(!_7e.executed){_30.push(_7e);}_7a();}}return _7d;},_5c=function(_84){if(!_84){return req;}var _85=_84.require;if(!_85){_85=function(a1,a2,a3){return _16(a1,a2,a3,_84,_85);};_84.require=_c(_85,req);_85.module=_84;_85.toUrl=function(_86){return _5a(_86,_84);};_85.toAbsMid=function(mid){return _b3(mid,_84);};if(0){_85.undef=function(mid){req.undef(mid,_84);};}if(1){_85.syncLoadNls=function(mid){var _87=_5b(mid,_84),_88=_2f[_87.mid];if(!_88||!_88.executed){_89=_52[_87.mid]||_52[_53+_87.url];if(_89){_8a(_89);_88=_2f[_87.mid];}}return _88&&_88.executed&&_88.result;};}}return _85;},_30=[],_8b=[],_8c={},_8d=function(_8e){_8e.injected=_20;_8c[_8e.mid]=1;if(_8e.url){_8c[_8e.url]=_8e.pack||1;}_8f();},_33=function(_90){_90.injected=_21;delete _8c[_90.mid];if(_90.url){delete _8c[_90.url];}if(_4(_8c)){_91();1&&_25==xd&&(_25=_26);}},_92=req.idle=function(){return !_8b.length&&_4(_8c)&&!_30.length&&!_83;},_93=function(_94,map){if(map){for(var i=0;i<map.length;i++){if(map[i][2].test(_94)){return map[i];}}}return 0;},_95=function(_96){var _97=[],_98,_99;_96=_96.replace(/\\/g,"/").split("/");while(_96.length){_98=_96.shift();if(_98==".."&&_97.length&&_99!=".."){_97.pop();_99=_97[_97.length-1];}else{if(_98!="."){_97.push(_99=_98);}}}return _97.join("/");},_81=function(pid,mid,_9a,url){if(1){var xd=req.isXdUrl(url);return {pid:pid,mid:mid,pack:_9a,url:url,executed:0,def:0,isXd:xd,isAmd:!!(xd||(_4f[pid]&&_4f[pid].isAmd))};}else{return {pid:pid,mid:mid,pack:_9a,url:url,executed:0,def:0};}},_9b=function(mid,_9c,_9d,_9e,_9f,_a0,_a1,_a2){var pid,_a3,_a4,_a5,_a6,url,_a7,_a8,_a9;_a9=mid;_a8=/^\./.test(mid);if(/(^\/)|(\:)|(\.js$)/.test(mid)||(_a8&&!_9c)){return _81(0,mid,0,mid);}else{mid=_95(_a8?(_9c.mid+"/../"+mid):mid);if(/^\./.test(mid)){throw _f("irrationalPath",mid);}if(_9c){_a6=_93(_9c.mid,_a0);}_a6=_a6||_a0.star;_a6=_a6&&_93(mid,_a6[1]);if(_a6){mid=_a6[1]+mid.substring(_a6[3]);}_70=mid.match(/^([^\/]+)(\/(.+))?$/);pid=_70?_70[1]:"";if((_a3=_9d[pid])){mid=pid+"/"+(_a4=(_70[3]||_a3.main));}else{pid="";}var _aa=0,_ab=0;_9(_4c,function(_ac){var _ad=mid.match(_ac[0]);if(_ad&&_ad.length>_aa){_ab=_6(_ac[1])?mid.replace(_ac[0],_ac[1]):_ac[1];}});if(_ab){return _9b(_ab,0,_9d,_9e,_9f,_a0,_a1,_a2);}_a7=_9e[mid];if(_a7){return _a2?_81(_a7.pid,_a7.mid,_a7.pack,_a7.url):_9e[mid];}}_a6=_93(mid,_a1);if(_a6){url=_a6[1]+mid.substring(_a6[3]);}else{if(pid){url=_a3.location+"/"+_a4;}else{if(has("config-tlmSiblingOfDojo")){url="../"+mid;}else{url=mid;}}}if(!(/(^\/)|(\:)/.test(url))){url=_9f+url;}url+=".js";return _81(pid,mid,_a3,_95(url));},_5b=function(mid,_ae){return _9b(mid,_ae,_4f,_2f,req.baseUrl,_50,_4e);},_af=function(_b0,_b1,_b2){return _b0.normalize?_b0.normalize(_b1,function(mid){return _b3(mid,_b2);}):_b3(_b1,_b2);},_b4=0,_31=function(mid,_b5,_b6){var _b7,_b8,_b9,_ba;_b7=mid.match(/^(.+?)\!(.*)$/);if(_b7){_b8=_31(_b7[1],_b5,_b6);if(1&&_25==_26&&!_b8.executed){_32(_b8);if(_b8.injected===_21&&!_b8.executed){_37(function(){_36(_b8);});}if(_b8.executed){_bb(_b8);}else{_30.unshift(_b8);}}if(_b8.executed===_24&&!_b8.load){_bb(_b8);}if(_b8.load){_b9=_af(_b8,_b7[2],_b5);mid=(_b8.mid+"!"+(_b8.dynamic?++_b4+"!":"")+_b9);}else{_b9=_b7[2];mid=_b8.mid+"!"+(++_b4)+"!waitingForPlugin";}_ba={plugin:_b8,mid:mid,req:_5c(_b5),prid:_b9};}else{_ba=_5b(mid,_b5);}return _2f[_ba.mid]||(!_b6&&(_2f[_ba.mid]=_ba));},_b3=req.toAbsMid=function(mid,_bc){return _5b(mid,_bc).mid;},_5a=req.toUrl=function(_bd,_be){var _bf=_5b(_bd+"/x",_be),url=_bf.url;return _3f(_bf.pid===0?_bd:url.substring(0,url.length-5));},_c0={injected:_21,executed:_24,def:_22,result:_22},_c1=function(mid){return _2f[mid]=_c({mid:mid},_c0);},_c2=_c1("require"),_c3=_c1("exports"),_c4=_c1("module"),_c5=function(_c6,_c7){req.trace("loader-run-factory",[_c6.mid]);var _c8=_c6.def,_c9;1&&_27.unshift(_c6);if(has("config-dojo-loader-catches")){try{_c9=_6(_c8)?_c8.apply(null,_c7):_c8;}catch(e){_34(_44,_c6.result=_f("factoryThrew",[_c6,e]));}}else{_c9=_6(_c8)?_c8.apply(null,_c7):_c8;}_c6.result=_c9===undefined&&_c6.cjs?_c6.cjs.exports:_c9;1&&_27.shift(_c6);},_ca={},_cb=0,_bb=function(_cc){var _cd=_cc.result;_cc.dynamic=_cd.dynamic;_cc.normalize=_cd.normalize;_cc.load=_cd.load;return _cc;},_ce=function(_cf){var map={};_9(_cf.loadQ,function(_d0){var _d1=_af(_cf,_d0.prid,_d0.req.module),mid=_cf.dynamic?_d0.mid.replace(/waitingForPlugin$/,_d1):(_cf.mid+"!"+_d1),_d2=_c(_c({},_d0),{mid:mid,prid:_d1,injected:0});if(!_2f[mid]){_e4(_2f[mid]=_d2);}map[_d0.mid]=_2f[mid];_33(_d0);delete _2f[_d0.mid];});_cf.loadQ=0;var _d3=function(_d4){for(var _d5,_d6=_d4.deps||[],i=0;i<_d6.length;i++){_d5=map[_d6[i].mid];if(_d5){_d6[i]=_d5;}}};for(var p in _2f){_d3(_2f[p]);}_9(_30,_d3);},_35=function(_d7){req.trace("loader-finish-exec",[_d7.mid]);_d7.executed=_24;_d7.defOrder=_cb++;1&&_9(_d7.provides,function(cb){cb();});if(_d7.loadQ){_bb(_d7);_ce(_d7);}for(i=0;i<_30.length;){if(_30[i]===_d7){_30.splice(i,1);}else{i++;}}if(/^require\*/.test(_d7.mid)){delete _2f[_d7.mid];}},_d8=[],_36=function(_d9,_da){if(_d9.executed===_23){req.trace("loader-circular-dependency",[_d8.concat(_d9.mid).join("->")]);return (!_d9.def||_da)?_ca:(_d9.cjs&&_d9.cjs.exports);}if(!_d9.executed){if(!_d9.def){return _ca;}var mid=_d9.mid,_db=_d9.deps||[],arg,_dc,_dd=[],i=0;if(0){_d8.push(mid);req.trace("loader-exec-module",["exec",_d8.length,mid]);}_d9.executed=_23;while(i<_db.length){arg=_db[i++];_dc=((arg===_c2)?_5c(_d9):((arg===_c3)?_d9.cjs.exports:((arg===_c4)?_d9.cjs:_36(arg,_da))));if(_dc===_ca){_d9.executed=0;req.trace("loader-exec-module",["abort",mid]);0&&_d8.pop();return _ca;}_dd.push(_dc);}_c5(_d9,_dd);_35(_d9);0&&_d8.pop();}return _d9.result;},_83=0,_37=function(_de){try{_83++;_de();}finally{_83--;}if(_92()){_34("idle",[]);}},_7a=function(){if(_83){return;}_37(function(){_29();for(var _df,_e0,i=0;i<_30.length;){_df=_cb;_e0=_30[i];_36(_e0);if(_df!=_cb){_29();i=0;}else{i++;}}});};if(0){req.undef=function(_e1,_e2){var _e3=_31(_e1,_e2);_33(_e3);delete _2f[_e3.mid];};}if(1){if(has("dojo-loader-eval-hint-url")===undefined){has.add("dojo-loader-eval-hint-url",1);}var _3f=function(url){url+="";return url+(_51?((/\?/.test(url)?"&":"?")+_51):"");},_e4=function(_e5){var _e6=_e5.plugin;if(_e6.executed===_24&&!_e6.load){_bb(_e6);}var _e7=function(def){_e5.result=def;_33(_e5);_35(_e5);_7a();};if(_e6.load){_e6.load(_e5.prid,_e5.req,_e7);}else{if(_e6.loadQ){_e6.loadQ.push(_e5);}else{_e6.loadQ=[_e5];_30.unshift(_e6);_32(_e6);}}},_89=0,_7b=0,_e8=0,_8a=function(_e9,_ea){if(has("config-stripStrict")){_e9=_e9.replace(/"use strict"/g,"");}_e8=1;if(has("config-dojo-loader-catches")){try{if(_e9===_89){_89.call(null);}else{req.eval(_e9,has("dojo-loader-eval-hint-url")?_ea.url:_ea.mid);}}catch(e){_34(_44,_f("evalModuleThrew",_ea));}}else{if(_e9===_89){_89.call(null);}else{req.eval(_e9,has("dojo-loader-eval-hint-url")?_ea.url:_ea.mid);}}_e8=0;},_32=function(_eb){var mid=_eb.mid,url=_eb.url;if(_eb.executed||_eb.injected||_8c[mid]||(_eb.url&&((_eb.pack&&_8c[_eb.url]===_eb.pack)||_8c[_eb.url]==1))){return;}_8d(_eb);if(0){var _ec=0;if(_eb.plugin&&_eb.plugin.isCombo){req.combo.add(_eb.plugin.mid,_eb.prid,0,req);_ec=1;}else{if(!_eb.plugin){_ec=req.combo.add(0,_eb.mid,_eb.url,req);}}if(_ec){_72=1;return;}}if(_eb.plugin){_e4(_eb);return;}var _ed=function(){_79(_eb);if(_eb.injected!==_21){_33(_eb);_c(_eb,_c0);req.trace("loader-define-nonmodule",[_eb.url]);}if(1&&_25){!_27.length&&_7a();}else{_7a();}};_89=_52[mid]||_52[_53+_eb.url];if(_89){req.trace("loader-inject",["cache",_eb.mid,url]);_8a(_89,_eb);_ed();return;}if(1&&_25){if(_eb.isXd){_25==_26&&(_25=xd);}else{if(_eb.isAmd&&_25!=_26){}else{var _ee=function(_ef){if(_25==_26){_27.unshift(_eb);_8a(_ef,_eb);_27.shift();_79(_eb);if(!_eb.cjs){_33(_eb);_35(_eb);}if(_eb.finish){var _f0=mid+"*finish",_f1=_eb.finish;delete _eb.finish;def(_f0,["dojo",("dojo/require!"+_f1.join(",")).replace(/\./g,"/")],function(_f2){_9(_f1,function(mid){_f2.require(mid);});});_30.unshift(_31(_f0));}_ed();}else{_ef=_2a(_eb,_ef);if(_ef){_8a(_ef,_eb);_ed();}else{_7b=_eb;req.injectUrl(_3f(url),_ed,_eb);_7b=0;}}};req.trace("loader-inject",["xhr",_eb.mid,url,_25!=_26]);if(has("config-dojo-loader-catches")){try{req.getText(url,_25!=_26,_ee);}catch(e){_34(_44,_f("xhrInjectFailed",[_eb,e]));}}else{req.getText(url,_25!=_26,_ee);}return;}}}req.trace("loader-inject",["script",_eb.mid,url]);_7b=_eb;req.injectUrl(_3f(url),_ed,_eb);_7b=0;},_f3=function(_f4,_f5,def){req.trace("loader-define-module",[_f4.mid,_f5]);if(0&&_f4.plugin&&_f4.plugin.isCombo){_f4.result=_6(def)?def():def;_33(_f4);_35(_f4);return _f4;}var mid=_f4.mid;if(_f4.injected===_21){_34(_44,_f("multipleDefine",_f4));return _f4;}_c(_f4,{deps:_f5,def:def,cjs:{id:_f4.mid,uri:_f4.url,exports:(_f4.result={}),setExports:function(_f6){_f4.cjs.exports=_f6;},config:function(){return _f4.config;}}});for(var i=0;i<_f5.length;i++){_f5[i]=_31(_f5[i],_f4);}if(1&&_25&&!_8c[mid]){_75(_f4);_30.push(_f4);_7a();}_33(_f4);if(!_6(def)&&!_f5.length){_f4.result=def;_35(_f4);}return _f4;},_79=function(_f7,_f8){var _f9=[],_fa,_fb;while(_8b.length){_fb=_8b.shift();_f8&&(_fb[0]=_f8.shift());_fa=(_fb[0]&&_31(_fb[0]))||_f7;_f9.push([_fa,_fb[1],_fb[2]]);}_56(_f7);_9(_f9,function(_fc){_75(_f3.apply(null,_fc));});};}var _fd=0,_91=_3,_8f=_3;if(1){_91=function(){_fd&&clearTimeout(_fd);_fd=0;},_8f=function(){_91();if(req.waitms){_fd=window.setTimeout(function(){_91();_34(_44,_f("timeout",_8c));},req.waitms);}};}if(1){has.add("ie-event-behavior",!!doc.attachEvent&&(typeof opera==="undefined"||opera.toString()!="[object Opera]"));}if(1&&(1||1)){var _fe=function(_ff,_100,_101,_102){if(!has("ie-event-behavior")){_ff.addEventListener(_100,_102,false);return function(){_ff.removeEventListener(_100,_102,false);};}else{_ff.attachEvent(_101,_102);return function(){_ff.detachEvent(_101,_102);};}},_103=_fe(window,"load","onload",function(){req.pageLoaded=1;doc.readyState!="complete"&&(doc.readyState="complete");_103();});if(1){var _104=doc.getElementsByTagName("script")[0],_105=_104.parentNode;req.injectUrl=function(url,_106,_107){var node=_107.node=doc.createElement("script"),_108=function(e){e=e||window.event;var node=e.target||e.srcElement;if(e.type==="load"||/complete|loaded/.test(node.readyState)){_109();_10a();_106&&_106();}},_109=_fe(node,"load","onreadystatechange",_108),_10a=_fe(node,"error","onerror",function(e){_109();_10a();_34(_44,_f("scriptError",[url,e]));});node.type="text/javascript";node.charset="utf-8";node.src=url;_105.insertBefore(node,_104);return node;};}}if(1){req.log=function(){try{for(var i=0;i<arguments.length;i++){}}catch(e){}};}else{req.log=_3;}if(0){var _10b=req.trace=function(_10c,args){if(_10b.on&&_10b.group[_10c]){_34("trace",[_10c,args]);for(var arg,dump=[],text="trace:"+_10c+(args.length?(":"+args[0]):""),i=1;i<args.length;){arg=args[i++];if(_7(arg)){text+=", "+arg;}else{dump.push(arg);}}req.log(text);dump.length&&dump.push(".");req.log.apply(req,dump);}};_c(_10b,{on:1,group:{},set:function(_10d,_10e){if(_7(_10d)){_10b.group[_10d]=_10e;}else{_c(_10b.group,_10d);}}});_10b.set(_c(_c(_c({},_2.trace),_1.trace),_55.trace));on("config",function(_10f){_10f.trace&&_10b.set(_10f.trace);});}else{req.trace=_3;}var def=function(mid,_110,_111){var _112=arguments.length,_113=["require","exports","module"],args=[0,mid,_110];if(_112==1){args=[0,(_6(mid)?_113:[]),mid];}else{if(_112==2&&_7(mid)){args=[mid,(_6(_110)?_113:[]),_110];}else{if(_112==3){args=[mid,_110,_111];}}}if(0&&args[1]===_113){args[2].toString().replace(/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,"").replace(/require\(["']([\w\!\-_\.\/]+)["']\)/g,function(_114,dep){args[1].push(dep);});}req.trace("loader-define",args.slice(0,2));var _115=args[0]&&_31(args[0]),_116;if(_115&&!_8c[_115.mid]){_75(_f3(_115,args[1],args[2]));}else{if(!has("ie-event-behavior")||!1||_e8){_8b.push(args);}else{_115=_115||_7b;if(!_115){for(mid in _8c){_116=_2f[mid];if(_116&&_116.node&&_116.node.readyState==="interactive"){_115=_116;break;}}if(0&&!_115){for(var i=0;i<_73.length;i++){_115=_73[i];if(_115.node&&_115.node.readyState==="interactive"){break;}_115=0;}}}if(0&&_8(_115)){_75(_f3(_31(_115.shift()),args[1],args[2]));if(!_115.length){_73.splice(i,1);}}else{if(_115){_56(_115);_75(_f3(_115,args[1],args[2]));}else{_34(_44,_f("ieDefineFailed",args[0]));}}_7a();}}};def.amd={vendor:"dojotoolkit.org"};if(0){req.def=def;}_c(_c(req,_2.loaderPatch),_1.loaderPatch);on(_44,function(arg){try{console.error(arg);if(arg instanceof Error){for(var p in arg){}}}catch(e){}});_c(req,{uid:uid,cache:_52,packs:_4f});if(0){_c(req,{paths:_4d,aliases:_4c,modules:_2f,legacyMode:_25,execQ:_30,defQ:_8b,waiting:_8c,packs:_4f,mapProgs:_50,pathsMapProg:_4e,listenerQueues:_43,computeMapProg:_5e,runMapProg:_93,compactPath:_95,getModuleInfo:_9b});}if(_17.define){if(1){_34(_44,_f("defineAlreadyDefined",0));}return;}else{_17.define=def;_17.require=req;if(0){require=req;}}if(0&&req.combo&&req.combo.plugins){var _117=req.combo.plugins,_118;for(_118 in _117){_c(_c(_31(_118),_117[_118]),{isCombo:1,executed:"executed",load:1});}}if(1){var _119=_55.deps||_1.deps||_2.deps,_11a=_55.callback||_1.callback||_2.callback;req.boot=(_119||_11a)?[_119||[],_11a]:0;}if(!1){!req.async&&req(["dojo"]);req.boot&&req.apply(null,req.boot);}})(this.dojoConfig||this.djConfig||this.require||{},{async:0,hasCache:{"config-selectorEngine":"acme","config-tlmSiblingOfDojo":1,"dojo-built":1,"dojo-loader":1,dom:1,"host-browser":1},packages:[{location:"../dijit",name:"dijit"},{location:"../dojox",name:"dojox"},{location:".",name:"dojo"}]});require({cache:{"dojo/_base/fx":function(){define(["./kernel","./config","./lang","../Evented","./Color","./connect","./sniff","../dom","../dom-style"],function(dojo,_11b,lang,_11c,_11d,_11e,has,dom,_11f){var _120=lang.mixin;var _121={};var _122=_121._Line=function(_123,end){this.start=_123;this.end=end;};_122.prototype.getValue=function(n){return ((this.end-this.start)*n)+this.start;};var _124=_121.Animation=function(args){_120(this,args);if(lang.isArray(this.curve)){this.curve=new _122(this.curve[0],this.curve[1]);}};_124.prototype=new _11c();lang.extend(_124,{duration:350,repeat:0,rate:20,_percent:0,_startRepeatCount:0,_getStep:function(){var _125=this._percent,_126=this.easing;return _126?_126(_125):_125;},_fire:function(evt,args){var a=args||[];if(this[evt]){if(_11b.debugAtAllCosts){this[evt].apply(this,a);}else{try{this[evt].apply(this,a);}catch(e){console.error("exception in animation handler for:",evt);console.error(e);}}}return this;},play:function(_127,_128){var _129=this;if(_129._delayTimer){_129._clearTimer();}if(_128){_129._stopTimer();_129._active=_129._paused=false;_129._percent=0;}else{if(_129._active&&!_129._paused){return _129;}}_129._fire("beforeBegin",[_129.node]);var de=_127||_129.delay,_12a=lang.hitch(_129,"_play",_128);if(de>0){_129._delayTimer=setTimeout(_12a,de);return _129;}_12a();return _129;},_play:function(_12b){var _12c=this;if(_12c._delayTimer){_12c._clearTimer();}_12c._startTime=new Date().valueOf();if(_12c._paused){_12c._startTime-=_12c.duration*_12c._percent;}_12c._active=true;_12c._paused=false;var _12d=_12c.curve.getValue(_12c._getStep());if(!_12c._percent){if(!_12c._startRepeatCount){_12c._startRepeatCount=_12c.repeat;}_12c._fire("onBegin",[_12d]);}_12c._fire("onPlay",[_12d]);_12c._cycle();return _12c;},pause:function(){var _12e=this;if(_12e._delayTimer){_12e._clearTimer();}_12e._stopTimer();if(!_12e._active){return _12e;}_12e._paused=true;_12e._fire("onPause",[_12e.curve.getValue(_12e._getStep())]);return _12e;},gotoPercent:function(_12f,_130){var _131=this;_131._stopTimer();_131._active=_131._paused=true;_131._percent=_12f;if(_130){_131.play();}return _131;},stop:function(_132){var _133=this;if(_133._delayTimer){_133._clearTimer();}if(!_133._timer){return _133;}_133._stopTimer();if(_132){_133._percent=1;}_133._fire("onStop",[_133.curve.getValue(_133._getStep())]);_133._active=_133._paused=false;return _133;},status:function(){if(this._active){return this._paused?"paused":"playing";}return "stopped";},_cycle:function(){var _134=this;if(_134._active){var curr=new Date().valueOf();var step=_134.duration===0?1:(curr-_134._startTime)/(_134.duration);if(step>=1){step=1;}_134._percent=step;if(_134.easing){step=_134.easing(step);}_134._fire("onAnimate",[_134.curve.getValue(step)]);if(_134._percent<1){_134._startTimer();}else{_134._active=false;if(_134.repeat>0){_134.repeat--;_134.play(null,true);}else{if(_134.repeat==-1){_134.play(null,true);}else{if(_134._startRepeatCount){_134.repeat=_134._startRepeatCount;_134._startRepeatCount=0;}}}_134._percent=0;_134._fire("onEnd",[_134.node]);!_134.repeat&&_134._stopTimer();}}return _134;},_clearTimer:function(){clearTimeout(this._delayTimer);delete this._delayTimer;}});var ctr=0,_135=null,_136={run:function(){}};lang.extend(_124,{_startTimer:function(){if(!this._timer){this._timer=_11e.connect(_136,"run",this,"_cycle");ctr++;}if(!_135){_135=setInterval(lang.hitch(_136,"run"),this.rate);}},_stopTimer:function(){if(this._timer){_11e.disconnect(this._timer);this._timer=null;ctr--;}if(ctr<=0){clearInterval(_135);_135=null;ctr=0;}}});var _137=has("ie")?function(node){var ns=node.style;if(!ns.width.length&&_11f.get(node,"width")=="auto"){ns.width="auto";}}:function(){};_121._fade=function(args){args.node=dom.byId(args.node);var _138=_120({properties:{}},args),_139=(_138.properties.opacity={});_139.start=!("start" in _138)?function(){return +_11f.get(_138.node,"opacity")||0;}:_138.start;_139.end=_138.end;var anim=_121.animateProperty(_138);_11e.connect(anim,"beforeBegin",lang.partial(_137,_138.node));return anim;};_121.fadeIn=function(args){return _121._fade(_120({end:1},args));};_121.fadeOut=function(args){return _121._fade(_120({end:0},args));};_121._defaultEasing=function(n){return 0.5+((Math.sin((n+1.5)*Math.PI))/2);};var _13a=function(_13b){this._properties=_13b;for(var p in _13b){var prop=_13b[p];if(prop.start instanceof _11d){prop.tempColor=new _11d();}}};_13a.prototype.getValue=function(r){var ret={};for(var p in this._properties){var prop=this._properties[p],_13c=prop.start;if(_13c instanceof _11d){ret[p]=_11d.blendColors(_13c,prop.end,r,prop.tempColor).toCss();}else{if(!lang.isArray(_13c)){ret[p]=((prop.end-_13c)*r)+_13c+(p!="opacity"?prop.units||"px":0);}}}return ret;};_121.animateProperty=function(args){var n=args.node=dom.byId(args.node);if(!args.easing){args.easing=dojo._defaultEasing;}var anim=new _124(args);_11e.connect(anim,"beforeBegin",anim,function(){var pm={};for(var p in this.properties){if(p=="width"||p=="height"){this.node.display="block";}var prop=this.properties[p];if(lang.isFunction(prop)){prop=prop(n);}prop=pm[p]=_120({},(lang.isObject(prop)?prop:{end:prop}));if(lang.isFunction(prop.start)){prop.start=prop.start(n);}if(lang.isFunction(prop.end)){prop.end=prop.end(n);}var _13d=(p.toLowerCase().indexOf("color")>=0);function _13e(node,p){var v={height:node.offsetHeight,width:node.offsetWidth}[p];if(v!==undefined){return v;}v=_11f.get(node,p);return (p=="opacity")?+v:(_13d?v:parseFloat(v));};if(!("end" in prop)){prop.end=_13e(n,p);}else{if(!("start" in prop)){prop.start=_13e(n,p);}}if(_13d){prop.start=new _11d(prop.start);prop.end=new _11d(prop.end);}else{prop.start=(p=="opacity")?+prop.start:parseFloat(prop.start);}}this.curve=new _13a(pm);});_11e.connect(anim,"onAnimate",lang.hitch(_11f,"set",anim.node));return anim;};_121.anim=function(node,_13f,_140,_141,_142,_143){return _121.animateProperty({node:node,duration:_140||_124.prototype.duration,properties:_13f,easing:_141,onEnd:_142}).play(_143||0);};if(1){_120(dojo,_121);dojo._Animation=_124;}return _121;});},"dojo/dom-form":function(){define(["./_base/lang","./dom","./io-query","./json"],function(lang,dom,ioq,json){function _144(obj,name,_145){if(_145===null){return;}var val=obj[name];if(typeof val=="string"){obj[name]=[val,_145];}else{if(lang.isArray(val)){val.push(_145);}else{obj[name]=_145;}}};var _146="file|submit|image|reset|button";var form={fieldToObject:function fieldToObject(_147){var ret=null;_147=dom.byId(_147);if(_147){var _148=_147.name,type=(_147.type||"").toLowerCase();if(_148&&type&&!_147.disabled){if(type=="radio"||type=="checkbox"){if(_147.checked){ret=_147.value;}}else{if(_147.multiple){ret=[];var _149=[_147.firstChild];while(_149.length){for(var node=_149.pop();node;node=node.nextSibling){if(node.nodeType==1&&node.tagName.toLowerCase()=="option"){if(node.selected){ret.push(node.value);}}else{if(node.nextSibling){_149.push(node.nextSibling);}if(node.firstChild){_149.push(node.firstChild);}break;}}}}else{ret=_147.value;}}}}return ret;},toObject:function formToObject(_14a){var ret={},_14b=dom.byId(_14a).elements;for(var i=0,l=_14b.length;i<l;++i){var item=_14b[i],_14c=item.name,type=(item.type||"").toLowerCase();if(_14c&&type&&_146.indexOf(type)<0&&!item.disabled){_144(ret,_14c,form.fieldToObject(item));if(type=="image"){ret[_14c+".x"]=ret[_14c+".y"]=ret[_14c].x=ret[_14c].y=0;}}}return ret;},toQuery:function formToQuery(_14d){return ioq.objectToQuery(form.toObject(_14d));},toJson:function formToJson(_14e,_14f){return json.stringify(form.toObject(_14e),null,_14f?4:0);}};return form;});},"dojo/i18n":function(){define(["./_base/kernel","require","./has","./_base/array","./_base/config","./_base/lang","./_base/xhr","./json","module"],function(dojo,_150,has,_151,_152,lang,xhr,json,_153){has.add("dojo-preload-i18n-Api",1);1||has.add("dojo-v1x-i18n-Api",1);var _154=dojo.i18n={},_155=/(^.*(^|\/)nls)(\/|$)([^\/]*)\/?([^\/]*)/,_156=function(root,_157,_158,_159){for(var _15a=[_158+_159],_15b=_157.split("-"),_15c="",i=0;i<_15b.length;i++){_15c+=(_15c?"-":"")+_15b[i];if(!root||root[_15c]){_15a.push(_158+_15c+"/"+_159);}}return _15a;},_15d={},_15e=function(_15f,_160,_161){_161=_161?_161.toLowerCase():dojo.locale;_15f=_15f.replace(/\./g,"/");_160=_160.replace(/\./g,"/");return (/root/i.test(_161))?(_15f+"/nls/"+_160):(_15f+"/nls/"+_161+"/"+_160);},_162=dojo.getL10nName=function(_163,_164,_165){return _163=_153.id+"!"+_15e(_163,_164,_165);},_166=function(_167,_168,_169,_16a,_16b,load){_167([_168],function(root){var _16c=lang.clone(root.root),_16d=_156(!root._v1x&&root,_16b,_169,_16a);_167(_16d,function(){for(var i=1;i<_16d.length;i++){_16c=lang.mixin(lang.clone(_16c),arguments[i]);}var _16e=_168+"/"+_16b;_15d[_16e]=_16c;load();});});},_16f=function(id,_170){return /^\./.test(id)?_170(id):id;},_171=function(_172){var list=_152.extraLocale||[];list=lang.isArray(list)?list:[list];list.push(_172);return list;},load=function(id,_173,load){if(has("dojo-preload-i18n-Api")){var _174=id.split("*"),_175=_174[1]=="preload";if(_175){if(!_15d[id]){_15d[id]=1;_176(_174[2],json.parse(_174[3]),1,_173);}load(1);}if(_175||_177(id,_173,load)){return;}}var _178=_155.exec(id),_179=_178[1]+"/",_17a=_178[5]||_178[4],_17b=_179+_17a,_17c=(_178[5]&&_178[4]),_17d=_17c||dojo.locale,_17e=_17b+"/"+_17d,_17f=_17c?[_17d]:_171(_17d),_180=_17f.length,_181=function(){if(!--_180){load(lang.delegate(_15d[_17e]));}};_151.forEach(_17f,function(_182){var _183=_17b+"/"+_182;if(has("dojo-preload-i18n-Api")){_184(_183);}if(!_15d[_183]){_166(_173,_17b,_179,_17a,_182,_181);}else{_181();}});};if(has("dojo-unit-tests")){var _185=_154.unitTests=[];}if(has("dojo-preload-i18n-Api")||1){var _186=_154.normalizeLocale=function(_187){var _188=_187?_187.toLowerCase():dojo.locale;return _188=="root"?"ROOT":_188;},isXd=function(mid,_189){return (1&&1)?_189.isXdUrl(_150.toUrl(mid+".js")):true;},_18a=0,_18b=[],_176=_154._preloadLocalizations=function(_18c,_18d,_18e,_18f){_18f=_18f||_150;function _190(mid,_191){if(isXd(mid,_18f)||_18e){_18f([mid],_191);}else{_19b([mid],_191,_18f);}};function _192(_193,func){var _194=_193.split("-");while(_194.length){if(func(_194.join("-"))){return;}_194.pop();}func("ROOT");};function _195(_196){_196=_186(_196);_192(_196,function(loc){if(_151.indexOf(_18d,loc)>=0){var mid=_18c.replace(/\./g,"/")+"_"+loc;_18a++;_190(mid,function(_197){for(var p in _197){_15d[_150.toAbsMid(p)+"/"+loc]=_197[p];}--_18a;while(!_18a&&_18b.length){load.apply(null,_18b.shift());}});return true;}return false;});};_195();_151.forEach(dojo.config.extraLocale,_195);},_177=function(id,_198,load){if(_18a){_18b.push([id,_198,load]);}return _18a;},_184=function(){};}if(1){var _199={},_19a=new Function("__bundle","__checkForLegacyModules","__mid","__amdValue","var define = function(mid, factory){define.called = 1; __amdValue.result = factory || mid;},"+"\t   require = function(){define.called = 1;};"+"try{"+"define.called = 0;"+"eval(__bundle);"+"if(define.called==1)"+"return __amdValue;"+"if((__checkForLegacyModules = __checkForLegacyModules(__mid)))"+"return __checkForLegacyModules;"+"}catch(e){}"+"try{"+"return eval('('+__bundle+')');"+"}catch(e){"+"return e;"+"}"),_19b=function(deps,_19c,_19d){var _19e=[];_151.forEach(deps,function(mid){var url=_19d.toUrl(mid+".js");function load(text){var _19f=_19a(text,_184,mid,_199);if(_19f===_199){_19e.push(_15d[url]=_199.result);}else{if(_19f instanceof Error){console.error("failed to evaluate i18n bundle; url="+url,_19f);_19f={};}_19e.push(_15d[url]=(/nls\/[^\/]+\/[^\/]+$/.test(url)?_19f:{root:_19f,_v1x:1}));}};if(_15d[url]){_19e.push(_15d[url]);}else{var _1a0=_19d.syncLoadNls(mid);if(_1a0){_19e.push(_1a0);}else{if(!xhr){try{_19d.getText(url,true,load);}catch(e){_19e.push(_15d[url]={});}}else{xhr.get({url:url,sync:true,load:load,error:function(){_19e.push(_15d[url]={});}});}}}});_19c&&_19c.apply(null,_19e);};_184=function(_1a1){for(var _1a2,_1a3=_1a1.split("/"),_1a4=dojo.global[_1a3[0]],i=1;_1a4&&i<_1a3.length-1;_1a4=_1a4[_1a3[i++]]){}if(_1a4){_1a2=_1a4[_1a3[i]];if(!_1a2){_1a2=_1a4[_1a3[i].replace(/-/g,"_")];}if(_1a2){_15d[_1a1]=_1a2;}}return _1a2;};_154.getLocalization=function(_1a5,_1a6,_1a7){var _1a8,_1a9=_15e(_1a5,_1a6,_1a7);load(_1a9,(!isXd(_1a9,_150)?function(deps,_1aa){_19b(deps,_1aa,_150);}:_150),function(_1ab){_1a8=_1ab;});return _1a8;};if(has("dojo-unit-tests")){_185.push(function(doh){doh.register("tests.i18n.unit",function(t){var _1ac;_1ac=_19a("{prop:1}",_184,"nonsense",_199);t.is({prop:1},_1ac);t.is(undefined,_1ac[1]);_1ac=_19a("({prop:1})",_184,"nonsense",_199);t.is({prop:1},_1ac);t.is(undefined,_1ac[1]);_1ac=_19a("{'prop-x':1}",_184,"nonsense",_199);t.is({"prop-x":1},_1ac);t.is(undefined,_1ac[1]);_1ac=_19a("({'prop-x':1})",_184,"nonsense",_199);t.is({"prop-x":1},_1ac);t.is(undefined,_1ac[1]);_1ac=_19a("define({'prop-x':1})",_184,"nonsense",_199);t.is(_199,_1ac);t.is({"prop-x":1},_199.result);_1ac=_19a("define('some/module', {'prop-x':1})",_184,"nonsense",_199);t.is(_199,_1ac);t.is({"prop-x":1},_199.result);_1ac=_19a("this is total nonsense and should throw an error",_184,"nonsense",_199);t.is(_1ac instanceof Error,true);});});}}return lang.mixin(_154,{dynamic:true,normalize:_16f,load:load,cache:_15d});});},"dojo/promise/tracer":function(){define(["../_base/lang","./Promise","../Evented"],function(lang,_1ad,_1ae){"use strict";var _1af=new _1ae;var emit=_1af.emit;_1af.emit=null;function _1b0(args){setTimeout(function(){emit.apply(_1af,args);},0);};_1ad.prototype.trace=function(){var args=lang._toArray(arguments);this.then(function(_1b1){_1b0(["resolved",_1b1].concat(args));},function(_1b2){_1b0(["rejected",_1b2].concat(args));},function(_1b3){_1b0(["progress",_1b3].concat(args));});return this;};_1ad.prototype.traceRejected=function(){var args=lang._toArray(arguments);this.otherwise(function(_1b4){_1b0(["rejected",_1b4].concat(args));});return this;};return _1af;});},"dojo/errors/RequestError":function(){define(["./create"],function(_1b5){return _1b5("RequestError",function(_1b6,_1b7){this.response=_1b7;});});},"dojo/_base/html":function(){define("dojo/_base/html",["./kernel","../dom","../dom-style","../dom-attr","../dom-prop","../dom-class","../dom-construct","../dom-geometry"],function(dojo,dom,_1b8,attr,prop,cls,ctr,geom){dojo.byId=dom.byId;dojo.isDescendant=dom.isDescendant;dojo.setSelectable=dom.setSelectable;dojo.getAttr=attr.get;dojo.setAttr=attr.set;dojo.hasAttr=attr.has;dojo.removeAttr=attr.remove;dojo.getNodeProp=attr.getNodeProp;dojo.attr=function(node,name,_1b9){if(arguments.length==2){return attr[typeof name=="string"?"get":"set"](node,name);}return attr.set(node,name,_1b9);};dojo.hasClass=cls.contains;dojo.addClass=cls.add;dojo.removeClass=cls.remove;dojo.toggleClass=cls.toggle;dojo.replaceClass=cls.replace;dojo._toDom=dojo.toDom=ctr.toDom;dojo.place=ctr.place;dojo.create=ctr.create;dojo.empty=function(node){ctr.empty(node);};dojo._destroyElement=dojo.destroy=function(node){ctr.destroy(node);};dojo._getPadExtents=dojo.getPadExtents=geom.getPadExtents;dojo._getBorderExtents=dojo.getBorderExtents=geom.getBorderExtents;dojo._getPadBorderExtents=dojo.getPadBorderExtents=geom.getPadBorderExtents;dojo._getMarginExtents=dojo.getMarginExtents=geom.getMarginExtents;dojo._getMarginSize=dojo.getMarginSize=geom.getMarginSize;dojo._getMarginBox=dojo.getMarginBox=geom.getMarginBox;dojo.setMarginBox=geom.setMarginBox;dojo._getContentBox=dojo.getContentBox=geom.getContentBox;dojo.setContentSize=geom.setContentSize;dojo._isBodyLtr=dojo.isBodyLtr=geom.isBodyLtr;dojo._docScroll=dojo.docScroll=geom.docScroll;dojo._getIeDocumentElementOffset=dojo.getIeDocumentElementOffset=geom.getIeDocumentElementOffset;dojo._fixIeBiDiScrollLeft=dojo.fixIeBiDiScrollLeft=geom.fixIeBiDiScrollLeft;dojo.position=geom.position;dojo.marginBox=function marginBox(node,box){return box?geom.setMarginBox(node,box):geom.getMarginBox(node);};dojo.contentBox=function contentBox(node,box){return box?geom.setContentSize(node,box):geom.getContentBox(node);};dojo.coords=function(node,_1ba){dojo.deprecated("dojo.coords()","Use dojo.position() or dojo.marginBox().");node=dom.byId(node);var s=_1b8.getComputedStyle(node),mb=geom.getMarginBox(node,s);var abs=geom.position(node,_1ba);mb.x=abs.x;mb.y=abs.y;return mb;};dojo.getProp=prop.get;dojo.setProp=prop.set;dojo.prop=function(node,name,_1bb){if(arguments.length==2){return prop[typeof name=="string"?"get":"set"](node,name);}return prop.set(node,name,_1bb);};dojo.getStyle=_1b8.get;dojo.setStyle=_1b8.set;dojo.getComputedStyle=_1b8.getComputedStyle;dojo.__toPixelValue=dojo.toPixelValue=_1b8.toPixelValue;dojo.style=function(node,name,_1bc){switch(arguments.length){case 1:return _1b8.get(node);case 2:return _1b8[typeof name=="string"?"get":"set"](node,name);}return _1b8.set(node,name,_1bc);};return dojo;});},"dojo/_base/kernel":function(){define(["../has","./config","require","module"],function(has,_1bd,_1be,_1bf){var i,p,_1c0={},_1c1={},dojo={config:_1bd,global:this,dijit:_1c0,dojox:_1c1};var _1c2={dojo:["dojo",dojo],dijit:["dijit",_1c0],dojox:["dojox",_1c1]},_1c3=(_1be.map&&_1be.map[_1bf.id.match(/[^\/]+/)[0]]),item;for(p in _1c3){if(_1c2[p]){_1c2[p][0]=_1c3[p];}else{_1c2[p]=[_1c3[p],{}];}}for(p in _1c2){item=_1c2[p];item[1]._scopeName=item[0];if(!_1bd.noGlobals){this[item[0]]=item[1];}}dojo.scopeMap=_1c2;dojo.baseUrl=dojo.config.baseUrl=_1be.baseUrl;dojo.isAsync=!1||_1be.async;dojo.locale=_1bd.locale;var rev="$Rev: 29458 $".match(/\d+/);dojo.version={major:1,minor:8,patch:0,flag:"",revision:rev?+rev[0]:NaN,toString:function(){var v=dojo.version;return v.major+"."+v.minor+"."+v.patch+v.flag+" ("+v.revision+")";}};1||has.add("extend-dojo",1);(Function("d","d.eval = function(){return d.global.eval ? d.global.eval(arguments[0]) : eval(arguments[0]);}"))(dojo);if(0){dojo.exit=function(_1c4){quit(_1c4);};}else{dojo.exit=function(){};}1||has.add("dojo-guarantee-console",1);if(1){typeof console!="undefined"||(console={});var cn=["assert","count","debug","dir","dirxml","error","group","groupEnd","info","profile","profileEnd","time","timeEnd","trace","warn","log"];var tn;i=0;while((tn=cn[i++])){if(!console[tn]){(function(){var tcn=tn+"";console[tcn]=("log" in console)?function(){var a=Array.apply({},arguments);a.unshift(tcn+":");console["log"](a.join(" "));}:function(){};console[tcn]._fake=true;})();}}}has.add("dojo-debug-messages",!!_1bd.isDebug);dojo.deprecated=dojo.experimental=function(){};if(has("dojo-debug-messages")){dojo.deprecated=function(_1c5,_1c6,_1c7){var _1c8="DEPRECATED: "+_1c5;if(_1c6){_1c8+=" "+_1c6;}if(_1c7){_1c8+=" -- will be removed in version: "+_1c7;}console.warn(_1c8);};dojo.experimental=function(_1c9,_1ca){var _1cb="EXPERIMENTAL: "+_1c9+" -- APIs subject to change without notice.";if(_1ca){_1cb+=" "+_1ca;}console.warn(_1cb);};}1||has.add("dojo-modulePaths",1);if(1){if(_1bd.modulePaths){dojo.deprecated("dojo.modulePaths","use paths configuration");var _1cc={};for(p in _1bd.modulePaths){_1cc[p.replace(/\./g,"/")]=_1bd.modulePaths[p];}_1be({paths:_1cc});}}1||has.add("dojo-moduleUrl",1);if(1){dojo.moduleUrl=function(_1cd,url){dojo.deprecated("dojo.moduleUrl()","use require.toUrl","2.0");var _1ce=null;if(_1cd){_1ce=_1be.toUrl(_1cd.replace(/\./g,"/")+(url?("/"+url):"")+"/*.*").replace(/\/\*\.\*/,"")+(url?"":"/");}return _1ce;};}dojo._hasResource={};return dojo;});},"dojo/io-query":function(){define(["./_base/lang"],function(lang){var _1cf={};return {objectToQuery:function objectToQuery(map){var enc=encodeURIComponent,_1d0=[];for(var name in map){var _1d1=map[name];if(_1d1!=_1cf[name]){var _1d2=enc(name)+"=";if(lang.isArray(_1d1)){for(var i=0,l=_1d1.length;i<l;++i){_1d0.push(_1d2+enc(_1d1[i]));}}else{_1d0.push(_1d2+enc(_1d1));}}}return _1d0.join("&");},queryToObject:function queryToObject(str){var dec=decodeURIComponent,qp=str.split("&"),ret={},name,val;for(var i=0,l=qp.length,item;i<l;++i){item=qp[i];if(item.length){var s=item.indexOf("=");if(s<0){name=dec(item);val="";}else{name=dec(item.slice(0,s));val=dec(item.slice(s+1));}if(typeof ret[name]=="string"){ret[name]=[ret[name]];}if(lang.isArray(ret[name])){ret[name].push(val);}else{ret[name]=val;}}}return ret;}};});},"dojo/_base/Deferred":function(){define(["./kernel","../Deferred","../promise/Promise","../errors/CancelError","../has","./lang","../when"],function(dojo,_1d3,_1d4,_1d5,has,lang,when){var _1d6=function(){};var _1d7=Object.freeze||function(){};var _1d8=dojo.Deferred=function(_1d9){var _1da,_1db,_1dc,head,_1dd;var _1de=(this.promise=new _1d4());function _1df(_1e0){if(_1db){throw new Error("This deferred has already been resolved");}_1da=_1e0;_1db=true;_1e1();};function _1e1(){var _1e2;while(!_1e2&&_1dd){var _1e3=_1dd;_1dd=_1dd.next;if((_1e2=(_1e3.progress==_1d6))){_1db=false;}var func=(_1dc?_1e3.error:_1e3.resolved);if(has("config-useDeferredInstrumentation")){if(_1dc&&_1d3.instrumentRejected){_1d3.instrumentRejected(_1da,!!func);}}if(func){try{var _1e4=func(_1da);if(_1e4&&typeof _1e4.then==="function"){_1e4.then(lang.hitch(_1e3.deferred,"resolve"),lang.hitch(_1e3.deferred,"reject"),lang.hitch(_1e3.deferred,"progress"));continue;}var _1e5=_1e2&&_1e4===undefined;if(_1e2&&!_1e5){_1dc=_1e4 instanceof Error;}_1e3.deferred[_1e5&&_1dc?"reject":"resolve"](_1e5?_1da:_1e4);}catch(e){_1e3.deferred.reject(e);}}else{if(_1dc){_1e3.deferred.reject(_1da);}else{_1e3.deferred.resolve(_1da);}}}};this.resolve=this.callback=function(_1e6){this.fired=0;this.results=[_1e6,null];_1df(_1e6);};this.reject=this.errback=function(_1e7){_1dc=true;this.fired=1;if(has("config-useDeferredInstrumentation")){if(_1d3.instrumentRejected){_1d3.instrumentRejected(_1e7,!!_1dd);}}_1df(_1e7);this.results=[null,_1e7];};this.progress=function(_1e8){var _1e9=_1dd;while(_1e9){var _1ea=_1e9.progress;_1ea&&_1ea(_1e8);_1e9=_1e9.next;}};this.addCallbacks=function(_1eb,_1ec){this.then(_1eb,_1ec,_1d6);return this;};_1de.then=this.then=function(_1ed,_1ee,_1ef){var _1f0=_1ef==_1d6?this:new _1d8(_1de.cancel);var _1f1={resolved:_1ed,error:_1ee,progress:_1ef,deferred:_1f0};if(_1dd){head=head.next=_1f1;}else{_1dd=head=_1f1;}if(_1db){_1e1();}return _1f0.promise;};var _1f2=this;_1de.cancel=this.cancel=function(){if(!_1db){var _1f3=_1d9&&_1d9(_1f2);if(!_1db){if(!(_1f3 instanceof Error)){_1f3=new _1d5(_1f3);}_1f3.log=false;_1f2.reject(_1f3);}}};_1d7(_1de);};lang.extend(_1d8,{addCallback:function(_1f4){return this.addCallbacks(lang.hitch.apply(dojo,arguments));},addErrback:function(_1f5){return this.addCallbacks(null,lang.hitch.apply(dojo,arguments));},addBoth:function(_1f6){var _1f7=lang.hitch.apply(dojo,arguments);return this.addCallbacks(_1f7,_1f7);},fired:-1});_1d8.when=dojo.when=when;return _1d8;});},"dojo/NodeList-dom":function(){define(["./_base/kernel","./query","./_base/array","./_base/lang","./dom-class","./dom-construct","./dom-geometry","./dom-attr","./dom-style"],function(dojo,_1f8,_1f9,lang,_1fa,_1fb,_1fc,_1fd,_1fe){var _1ff=function(a){return a.length==1&&(typeof a[0]=="string");};var _200=function(node){var p=node.parentNode;if(p){p.removeChild(node);}};var _201=_1f8.NodeList,awc=_201._adaptWithCondition,aafe=_201._adaptAsForEach,aam=_201._adaptAsMap;function _202(_203){return function(node,name,_204){if(arguments.length==2){return _203[typeof name=="string"?"get":"set"](node,name);}return _203.set(node,name,_204);};};lang.extend(_201,{_normalize:function(_205,_206){var _207=_205.parse===true;if(typeof _205.template=="string"){var _208=_205.templateFunc||(dojo.string&&dojo.string.substitute);_205=_208?_208(_205.template,_205):_205;}var type=(typeof _205);if(type=="string"||type=="number"){_205=_1fb.toDom(_205,(_206&&_206.ownerDocument));if(_205.nodeType==11){_205=lang._toArray(_205.childNodes);}else{_205=[_205];}}else{if(!lang.isArrayLike(_205)){_205=[_205];}else{if(!lang.isArray(_205)){_205=lang._toArray(_205);}}}if(_207){_205._runParse=true;}return _205;},_cloneNode:function(node){return node.cloneNode(true);},_place:function(ary,_209,_20a,_20b){if(_209.nodeType!=1&&_20a=="only"){return;}var _20c=_209,_20d;var _20e=ary.length;for(var i=_20e-1;i>=0;i--){var node=(_20b?this._cloneNode(ary[i]):ary[i]);if(ary._runParse&&dojo.parser&&dojo.parser.parse){if(!_20d){_20d=_20c.ownerDocument.createElement("div");}_20d.appendChild(node);dojo.parser.parse(_20d);node=_20d.firstChild;while(_20d.firstChild){_20d.removeChild(_20d.firstChild);}}if(i==_20e-1){_1fb.place(node,_20c,_20a);}else{_20c.parentNode.insertBefore(node,_20c);}_20c=node;}},position:aam(_1fc.position),attr:awc(_202(_1fd),_1ff),style:awc(_202(_1fe),_1ff),addClass:aafe(_1fa.add),removeClass:aafe(_1fa.remove),toggleClass:aafe(_1fa.toggle),replaceClass:aafe(_1fa.replace),empty:aafe(_1fb.empty),removeAttr:aafe(_1fd.remove),marginBox:aam(_1fc.getMarginBox),place:function(_20f,_210){var item=_1f8(_20f)[0];return this.forEach(function(node){_1fb.place(node,item,_210);});},orphan:function(_211){return (_211?_1f8._filterResult(this,_211):this).forEach(_200);},adopt:function(_212,_213){return _1f8(_212).place(this[0],_213)._stash(this);},query:function(_214){if(!_214){return this;}var ret=new _201;this.map(function(node){_1f8(_214,node).forEach(function(_215){if(_215!==undefined){ret.push(_215);}});});return ret._stash(this);},filter:function(_216){var a=arguments,_217=this,_218=0;if(typeof _216=="string"){_217=_1f8._filterResult(this,a[0]);if(a.length==1){return _217._stash(this);}_218=1;}return this._wrap(_1f9.filter(_217,a[_218],a[_218+1]),this);},addContent:function(_219,_21a){_219=this._normalize(_219,this[0]);for(var i=0,node;(node=this[i]);i++){this._place(_219,node,_21a,i>0);}return this;}});return _201;});},"dojo/query":function(){define(["./_base/kernel","./has","./dom","./on","./_base/array","./_base/lang","./selector/_loader","./selector/_loader!default"],function(dojo,has,dom,on,_21b,lang,_21c,_21d){"use strict";has.add("array-extensible",function(){return lang.delegate([],{length:1}).length==1&&!has("bug-for-in-skips-shadowed");});var ap=Array.prototype,aps=ap.slice,apc=ap.concat,_21e=_21b.forEach;var tnl=function(a,_21f,_220){var _221=new (_220||this._NodeListCtor||nl)(a);return _21f?_221._stash(_21f):_221;};var _222=function(f,a,o){a=[0].concat(aps.call(a,0));o=o||dojo.global;return function(node){a[0]=node;return f.apply(o,a);};};var _223=function(f,o){return function(){this.forEach(_222(f,arguments,o));return this;};};var _224=function(f,o){return function(){return this.map(_222(f,arguments,o));};};var _225=function(f,o){return function(){return this.filter(_222(f,arguments,o));};};var _226=function(f,g,o){return function(){var a=arguments,body=_222(f,a,o);if(g.call(o||dojo.global,a)){return this.map(body);}this.forEach(body);return this;};};var _227=function(_228){var _229=this instanceof nl&&has("array-extensible");if(typeof _228=="number"){_228=Array(_228);}var _22a=(_228&&"length" in _228)?_228:arguments;if(_229||!_22a.sort){var _22b=_229?this:[],l=_22b.length=_22a.length;for(var i=0;i<l;i++){_22b[i]=_22a[i];}if(_229){return _22b;}_22a=_22b;}lang._mixin(_22a,nlp);_22a._NodeListCtor=function(_22c){return nl(_22c);};return _22a;};var nl=_227,nlp=nl.prototype=has("array-extensible")?[]:{};nl._wrap=nlp._wrap=tnl;nl._adaptAsMap=_224;nl._adaptAsForEach=_223;nl._adaptAsFilter=_225;nl._adaptWithCondition=_226;_21e(["slice","splice"],function(name){var f=ap[name];nlp[name]=function(){return this._wrap(f.apply(this,arguments),name=="slice"?this:null);};});_21e(["indexOf","lastIndexOf","every","some"],function(name){var f=_21b[name];nlp[name]=function(){return f.apply(dojo,[this].concat(aps.call(arguments,0)));};});lang.extend(_227,{constructor:nl,_NodeListCtor:nl,toString:function(){return this.join(",");},_stash:function(_22d){this._parent=_22d;return this;},on:function(_22e,_22f){var _230=this.map(function(node){return on(node,_22e,_22f);});_230.remove=function(){for(var i=0;i<_230.length;i++){_230[i].remove();}};return _230;},end:function(){if(this._parent){return this._parent;}else{return new this._NodeListCtor(0);}},concat:function(item){var t=aps.call(this,0),m=_21b.map(arguments,function(a){return aps.call(a,0);});return this._wrap(apc.apply(t,m),this);},map:function(func,obj){return this._wrap(_21b.map(this,func,obj),this);},forEach:function(_231,_232){_21e(this,_231,_232);return this;},filter:function(_233){var a=arguments,_234=this,_235=0;if(typeof _233=="string"){_234=_236._filterResult(this,a[0]);if(a.length==1){return _234._stash(this);}_235=1;}return this._wrap(_21b.filter(_234,a[_235],a[_235+1]),this);},instantiate:function(_237,_238){var c=lang.isFunction(_237)?_237:lang.getObject(_237);_238=_238||{};return this.forEach(function(node){new c(_238,node);});},at:function(){var t=new this._NodeListCtor(0);_21e(arguments,function(i){if(i<0){i=this.length+i;}if(this[i]){t.push(this[i]);}},this);return t._stash(this);}});function _239(_23a,_23b){var _23c=function(_23d,root){if(typeof root=="string"){root=dom.byId(root);if(!root){return new _23b([]);}}var _23e=typeof _23d=="string"?_23a(_23d,root):_23d?_23d.orphan?_23d:[_23d]:[];if(_23e.orphan){return _23e;}return new _23b(_23e);};_23c.matches=_23a.match||function(node,_23f,root){return _23c.filter([node],_23f,root).length>0;};_23c.filter=_23a.filter||function(_240,_241,root){return _23c(_241,root).filter(function(node){return _21b.indexOf(_240,node)>-1;});};if(typeof _23a!="function"){var _242=_23a.search;_23a=function(_243,root){return _242(root||document,_243);};}return _23c;};var _236=_239(_21d,_227);dojo.query=_239(_21d,function(_244){return _227(_244);});_236.load=function(id,_245,_246){_21c.load(id,_245,function(_247){_246(_239(_247,_227));});};dojo._filterQueryResult=_236._filterResult=function(_248,_249,root){return new _227(_236.filter(_248,_249,root));};dojo.NodeList=_236.NodeList=_227;return _236;});},"dojo/has":function(){define(["require","module"],function(_24a,_24b){var has=_24a.has||function(){};if(!1){var _24c=typeof window!="undefined"&&typeof location!="undefined"&&typeof document!="undefined"&&window.location==location&&window.document==document,_24d=this,doc=_24c&&document,_24e=doc&&doc.createElement("DiV"),_24f=(_24b.config&&_24b.config())||{};has=function(name){return typeof _24f[name]=="function"?(_24f[name]=_24f[name](_24d,doc,_24e)):_24f[name];};has.cache=_24f;has.add=function(name,test,now,_250){(typeof _24f[name]=="undefined"||_250)&&(_24f[name]=test);return now&&has(name);};1||has.add("host-browser",_24c);1||has.add("dom",_24c);1||has.add("dojo-dom-ready-api",1);1||has.add("dojo-sniff",1);}if(1){has.add("dom-addeventlistener",!!document.addEventListener);has.add("touch","ontouchstart" in document);has.add("device-width",screen.availWidth||innerWidth);var form=document.createElement("form");has.add("dom-attributes-explicit",form.attributes.length==0);has.add("dom-attributes-specified-flag",form.attributes.length>0&&form.attributes.length<40);}has.clearElement=function(_251){_251.innerHTML="";return _251;};has.normalize=function(id,_252){var _253=id.match(/[\?:]|[^:\?]*/g),i=0,get=function(skip){var term=_253[i++];if(term==":"){return 0;}else{if(_253[i++]=="?"){if(!skip&&has(term)){return get();}else{get(true);return get(skip);}}return term||0;}};id=get();return id&&_252(id);};has.load=function(id,_254,_255){if(id){_254([id],_255);}else{_255();}};return has;});},"dojo/_base/loader":function(){define(["./kernel","../has","require","module","./json","./lang","./array"],function(dojo,has,_256,_257,json,lang,_258){if(!1){console.error("cannot load the Dojo v1.x loader with a foreign loader");return 0;}1||has.add("dojo-fast-sync-require",1);var _259=function(id){return {src:_257.id,id:id};},_25a=function(name){return name.replace(/\./g,"/");},_25b=/\/\/>>built/,_25c=[],_25d=[],_25e=function(mid,_25f,_260){_25c.push(_260);_258.forEach(mid.split(","),function(mid){var _261=_262(mid,_25f.module);_25d.push(_261);_263(_261);});_264();},_264=(1?function(){var _265,mid;for(mid in _266){_265=_266[mid];if(_265.noReqPluginCheck===undefined){_265.noReqPluginCheck=/loadInit\!/.test(mid)||/require\!/.test(mid)?1:0;}if(!_265.executed&&!_265.noReqPluginCheck&&_265.injected==_267){return;}}_268(function(){var _269=_25c;_25c=[];_258.forEach(_269,function(cb){cb(1);});});}:(function(){var _26a,_26b=function(m){_26a[m.mid]=1;for(var t,_26c,deps=m.deps||[],i=0;i<deps.length;i++){_26c=deps[i];if(!(t=_26a[_26c.mid])){if(t===0||!_26b(_26c)){_26a[m.mid]=0;return false;}}}return true;};return function(){var _26d,mid;_26a={};for(mid in _266){_26d=_266[mid];if(_26d.executed||_26d.noReqPluginCheck){_26a[mid]=1;}else{if(_26d.noReqPluginCheck!==0){_26d.noReqPluginCheck=/loadInit\!/.test(mid)||/require\!/.test(mid)?1:0;}if(_26d.noReqPluginCheck){_26a[mid]=1;}else{if(_26d.injected!==_299){_26a[mid]=0;}}}}for(var t,i=0,end=_25d.length;i<end;i++){_26d=_25d[i];if(!(t=_26a[_26d.mid])){if(t===0||!_26b(_26d)){return;}}}_268(function(){var _26e=_25c;_25c=[];_258.forEach(_26e,function(cb){cb(1);});});};})()),_26f=function(mid,_270,_271){_270([mid],function(_272){_270(_272.names,function(){for(var _273="",args=[],i=0;i<arguments.length;i++){_273+="var "+_272.names[i]+"= arguments["+i+"]; ";args.push(arguments[i]);}eval(_273);var _274=_270.module,_275=[],_276,_277={provide:function(_278){_278=_25a(_278);var _279=_262(_278,_274);if(_279!==_274){_29f(_279);}},require:function(_27a,_27b){_27a=_25a(_27a);_27b&&(_262(_27a,_274).result=_29a);_275.push(_27a);},requireLocalization:function(_27c,_27d,_27e){if(!_276){_276=["dojo/i18n"];}_27e=(_27e||dojo.locale).toLowerCase();_27c=_25a(_27c)+"/nls/"+(/root/i.test(_27e)?"":_27e+"/")+_25a(_27d);if(_262(_27c,_274).isXd){_276.push("dojo/i18n!"+_27c);}},loadInit:function(f){f();}},hold={},p;try{for(p in _277){hold[p]=dojo[p];dojo[p]=_277[p];}_272.def.apply(null,args);}catch(e){_27f("error",[_259("failedDojoLoadInit"),e]);}finally{for(p in _277){dojo[p]=hold[p];}}if(_276){_275=_275.concat(_276);}if(_275.length){_25e(_275.join(","),_270,_271);}else{_271();}});});},_280=function(text,_281,_282){var _283=/\(|\)/g,_284=1,_285;_283.lastIndex=_281;while((_285=_283.exec(text))){if(_285[0]==")"){_284-=1;}else{_284+=1;}if(_284==0){break;}}if(_284!=0){throw "unmatched paren around character "+_283.lastIndex+" in: "+text;}return [dojo.trim(text.substring(_282,_283.lastIndex))+";\n",_283.lastIndex];},_286=/(\/\*([\s\S]*?)\*\/|\/\/(.*)$)/mg,_287=/(^|\s)dojo\.(loadInit|require|provide|requireLocalization|requireIf|requireAfterIf|platformRequire)\s*\(/mg,_288=/(^|\s)(require|define)\s*\(/m,_289=function(text,_28a){var _28b,_28c,_28d,_28e,_28f=[],_290=[],_291=[];_28a=_28a||text.replace(_286,function(_292){_287.lastIndex=_288.lastIndex=0;return (_287.test(_292)||_288.test(_292))?"":_292;});while((_28b=_287.exec(_28a))){_28c=_287.lastIndex;_28d=_28c-_28b[0].length;_28e=_280(_28a,_28c,_28d);if(_28b[2]=="loadInit"){_28f.push(_28e[0]);}else{_290.push(_28e[0]);}_287.lastIndex=_28e[1];}_291=_28f.concat(_290);if(_291.length||!_288.test(_28a)){return [text.replace(/(^|\s)dojo\.loadInit\s*\(/g,"\n0 && dojo.loadInit("),_291.join(""),_291];}else{return 0;}},_293=function(_294,text){var _295,id,_296=[],_297=[];if(_25b.test(text)||!(_295=_289(text))){return 0;}id=_294.mid+"-*loadInit";for(var p in _262("dojo",_294).result.scopeMap){_296.push(p);_297.push("\""+p+"\"");}return "// xdomain rewrite of "+_294.mid+"\n"+"define('"+id+"',{\n"+"\tnames:"+dojo.toJson(_296)+",\n"+"\tdef:function("+_296.join(",")+"){"+_295[1]+"}"+"});\n\n"+"define("+dojo.toJson(_296.concat(["dojo/loadInit!"+id]))+", function("+_296.join(",")+"){\n"+_295[0]+"});";},_298=_256.initSyncLoader(_25e,_264,_293),sync=_298.sync,_267=_298.requested,_299=_298.arrived,_29a=_298.nonmodule,_29b=_298.executing,_29c=_298.executed,_29d=_298.syncExecStack,_266=_298.modules,_29e=_298.execQ,_262=_298.getModule,_263=_298.injectModule,_29f=_298.setArrived,_27f=_298.signal,_2a0=_298.finishExec,_2a1=_298.execModule,_2a2=_298.getLegacyMode,_268=_298.guardCheckComplete;_25e=_298.dojoRequirePlugin;dojo.provide=function(mid){var _2a3=_29d[0],_2a4=lang.mixin(_262(_25a(mid),_256.module),{executed:_29b,result:lang.getObject(mid,true)});_29f(_2a4);if(_2a3){(_2a3.provides||(_2a3.provides=[])).push(function(){_2a4.result=lang.getObject(mid);delete _2a4.provides;_2a4.executed!==_29c&&_2a0(_2a4);});}return _2a4.result;};has.add("config-publishRequireResult",1,0,0);dojo.require=function(_2a5,_2a6){function _2a7(mid,_2a8){var _2a9=_262(_25a(mid),_256.module);if(_29d.length&&_29d[0].finish){_29d[0].finish.push(mid);return undefined;}if(_2a9.executed){return _2a9.result;}_2a8&&(_2a9.result=_29a);var _2aa=_2a2();_263(_2a9);_2aa=_2a2();if(_2a9.executed!==_29c&&_2a9.injected===_299){_298.guardCheckComplete(function(){_2a1(_2a9);});}if(_2a9.executed){return _2a9.result;}if(_2aa==sync){if(_2a9.cjs){_29e.unshift(_2a9);}else{_29d.length&&(_29d[0].finish=[mid]);}}else{_29e.push(_2a9);}return undefined;};var _2ab=_2a7(_2a5,_2a6);if(has("config-publishRequireResult")&&!lang.exists(_2a5)&&_2ab!==undefined){lang.setObject(_2a5,_2ab);}return _2ab;};dojo.loadInit=function(f){f();};dojo.registerModulePath=function(_2ac,_2ad){var _2ae={};_2ae[_2ac.replace(/\./g,"/")]=_2ad;_256({paths:_2ae});};dojo.platformRequire=function(_2af){var _2b0=(_2af.common||[]).concat(_2af[dojo._name]||_2af["default"]||[]),temp;while(_2b0.length){if(lang.isArray(temp=_2b0.shift())){dojo.require.apply(dojo,temp);}else{dojo.require(temp);}}};dojo.requireIf=dojo.requireAfterIf=function(_2b1,_2b2,_2b3){if(_2b1){dojo.require(_2b2,_2b3);}};dojo.requireLocalization=function(_2b4,_2b5,_2b6){_256(["../i18n"],function(i18n){i18n.getLocalization(_2b4,_2b5,_2b6);});};return {extractLegacyApiApplications:_289,require:_25e,loadInit:_26f};});},"dojo/json":function(){define(["./has"],function(has){"use strict";var _2b7=typeof JSON!="undefined";has.add("json-parse",_2b7);has.add("json-stringify",_2b7&&JSON.stringify({a:0},function(k,v){return v||1;})=="{\"a\":1}");if(has("json-stringify")){return JSON;}else{var _2b8=function(str){return ("\""+str.replace(/(["\\])/g,"\\$1")+"\"").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\r]/g,"\\r");};return {parse:has("json-parse")?JSON.parse:function(str,_2b9){if(_2b9&&!/^([\s\[\{]*(?:"(?:\\.|[^"])+"|-?\d[\d\.]*(?:[Ee][+-]?\d+)?|null|true|false|)[\s\]\}]*(?:,|:|$))+$/.test(str)){throw new SyntaxError("Invalid characters in JSON");}return eval("("+str+")");},stringify:function(_2ba,_2bb,_2bc){var _2bd;if(typeof _2bb=="string"){_2bc=_2bb;_2bb=null;}function _2be(it,_2bf,key){if(_2bb){it=_2bb(key,it);}var val,_2c0=typeof it;if(_2c0=="number"){return isFinite(it)?it+"":"null";}if(_2c0=="boolean"){return it+"";}if(it===null){return "null";}if(typeof it=="string"){return _2b8(it);}if(_2c0=="function"||_2c0=="undefined"){return _2bd;}if(typeof it.toJSON=="function"){return _2be(it.toJSON(key),_2bf,key);}if(it instanceof Date){return "\"{FullYear}-{Month+}-{Date}T{Hours}:{Minutes}:{Seconds}Z\"".replace(/\{(\w+)(\+)?\}/g,function(t,prop,plus){var num=it["getUTC"+prop]()+(plus?1:0);return num<10?"0"+num:num;});}if(it.valueOf()!==it){return _2be(it.valueOf(),_2bf,key);}var _2c1=_2bc?(_2bf+_2bc):"";var sep=_2bc?" ":"";var _2c2=_2bc?"\n":"";if(it instanceof Array){var itl=it.length,res=[];for(key=0;key<itl;key++){var obj=it[key];val=_2be(obj,_2c1,key);if(typeof val!="string"){val="null";}res.push(_2c2+_2c1+val);}return "["+res.join(",")+_2c2+_2bf+"]";}var _2c3=[];for(key in it){var _2c4;if(it.hasOwnProperty(key)){if(typeof key=="number"){_2c4="\""+key+"\"";}else{if(typeof key=="string"){_2c4=_2b8(key);}else{continue;}}val=_2be(it[key],_2c1,key);if(typeof val!="string"){continue;}_2c3.push(_2c2+_2c1+_2c4+":"+sep+val);}}return "{"+_2c3.join(",")+_2c2+_2bf+"}";};return _2be(_2ba,"","");}};}});},"dojo/_base/declare":function(){define(["./kernel","../has","./lang"],function(dojo,has,lang){var mix=lang.mixin,op=Object.prototype,opts=op.toString,xtor=new Function,_2c5=0,_2c6="constructor";function err(msg,cls){throw new Error("declare"+(cls?" "+cls:"")+": "+msg);};function _2c7(_2c8,_2c9){var _2ca=[],_2cb=[{cls:0,refs:[]}],_2cc={},_2cd=1,l=_2c8.length,i=0,j,lin,base,top,_2ce,rec,name,refs;for(;i<l;++i){base=_2c8[i];if(!base){err("mixin #"+i+" is unknown. Did you use dojo.require to pull it in?",_2c9);}else{if(opts.call(base)!="[object Function]"){err("mixin #"+i+" is not a callable constructor.",_2c9);}}lin=base._meta?base._meta.bases:[base];top=0;for(j=lin.length-1;j>=0;--j){_2ce=lin[j].prototype;if(!_2ce.hasOwnProperty("declaredClass")){_2ce.declaredClass="uniqName_"+(_2c5++);}name=_2ce.declaredClass;if(!_2cc.hasOwnProperty(name)){_2cc[name]={count:0,refs:[],cls:lin[j]};++_2cd;}rec=_2cc[name];if(top&&top!==rec){rec.refs.push(top);++top.count;}top=rec;}++top.count;_2cb[0].refs.push(top);}while(_2cb.length){top=_2cb.pop();_2ca.push(top.cls);--_2cd;while(refs=top.refs,refs.length==1){top=refs[0];if(!top||--top.count){top=0;break;}_2ca.push(top.cls);--_2cd;}if(top){for(i=0,l=refs.length;i<l;++i){top=refs[i];if(!--top.count){_2cb.push(top);}}}}if(_2cd){err("can't build consistent linearization",_2c9);}base=_2c8[0];_2ca[0]=base?base._meta&&base===_2ca[_2ca.length-base._meta.bases.length]?base._meta.bases.length:1:0;return _2ca;};function _2cf(args,a,f){var name,_2d0,_2d1,_2d2,meta,base,_2d3,opf,pos,_2d4=this._inherited=this._inherited||{};if(typeof args=="string"){name=args;args=a;a=f;}f=0;_2d2=args.callee;name=name||_2d2.nom;if(!name){err("can't deduce a name to call inherited()",this.declaredClass);}meta=this.constructor._meta;_2d1=meta.bases;pos=_2d4.p;if(name!=_2c6){if(_2d4.c!==_2d2){pos=0;base=_2d1[0];meta=base._meta;if(meta.hidden[name]!==_2d2){_2d0=meta.chains;if(_2d0&&typeof _2d0[name]=="string"){err("calling chained method with inherited: "+name,this.declaredClass);}do{meta=base._meta;_2d3=base.prototype;if(meta&&(_2d3[name]===_2d2&&_2d3.hasOwnProperty(name)||meta.hidden[name]===_2d2)){break;}}while(base=_2d1[++pos]);pos=base?pos:-1;}}base=_2d1[++pos];if(base){_2d3=base.prototype;if(base._meta&&_2d3.hasOwnProperty(name)){f=_2d3[name];}else{opf=op[name];do{_2d3=base.prototype;f=_2d3[name];if(f&&(base._meta?_2d3.hasOwnProperty(name):f!==opf)){break;}}while(base=_2d1[++pos]);}}f=base&&f||op[name];}else{if(_2d4.c!==_2d2){pos=0;meta=_2d1[0]._meta;if(meta&&meta.ctor!==_2d2){_2d0=meta.chains;if(!_2d0||_2d0.constructor!=="manual"){err("calling chained constructor with inherited",this.declaredClass);}while(base=_2d1[++pos]){meta=base._meta;if(meta&&meta.ctor===_2d2){break;}}pos=base?pos:-1;}}while(base=_2d1[++pos]){meta=base._meta;f=meta?meta.ctor:base;if(f){break;}}f=base&&f;}_2d4.c=f;_2d4.p=pos;if(f){return a===true?f:f.apply(this,a||args);}};function _2d5(name,args){if(typeof name=="string"){return this.__inherited(name,args,true);}return this.__inherited(name,true);};function _2d6(args,a1,a2){var f=this.getInherited(args,a1);if(f){return f.apply(this,a2||a1||args);}};var _2d7=dojo.config.isDebug?_2d6:_2cf;function _2d8(cls){var _2d9=this.constructor._meta.bases;for(var i=0,l=_2d9.length;i<l;++i){if(_2d9[i]===cls){return true;}}return this instanceof cls;};function _2da(_2db,_2dc){for(var name in _2dc){if(name!=_2c6&&_2dc.hasOwnProperty(name)){_2db[name]=_2dc[name];}}if(has("bug-for-in-skips-shadowed")){for(var _2dd=lang._extraNames,i=_2dd.length;i;){name=_2dd[--i];if(name!=_2c6&&_2dc.hasOwnProperty(name)){_2db[name]=_2dc[name];}}}};function _2de(_2df,_2e0){var name,t;for(name in _2e0){t=_2e0[name];if((t!==op[name]||!(name in op))&&name!=_2c6){if(opts.call(t)=="[object Function]"){t.nom=name;}_2df[name]=t;}}if(has("bug-for-in-skips-shadowed")){for(var _2e1=lang._extraNames,i=_2e1.length;i;){name=_2e1[--i];t=_2e0[name];if((t!==op[name]||!(name in op))&&name!=_2c6){if(opts.call(t)=="[object Function]"){t.nom=name;}_2df[name]=t;}}}return _2df;};function _2e2(_2e3){_2e4.safeMixin(this.prototype,_2e3);return this;};function _2e5(_2e6){return _2e4([this].concat(_2e6));};function _2e7(_2e8,_2e9){return function(){var a=arguments,args=a,a0=a[0],f,i,m,l=_2e8.length,_2ea;if(!(this instanceof a.callee)){return _2eb(a);}if(_2e9&&(a0&&a0.preamble||this.preamble)){_2ea=new Array(_2e8.length);_2ea[0]=a;for(i=0;;){a0=a[0];if(a0){f=a0.preamble;if(f){a=f.apply(this,a)||a;}}f=_2e8[i].prototype;f=f.hasOwnProperty("preamble")&&f.preamble;if(f){a=f.apply(this,a)||a;}if(++i==l){break;}_2ea[i]=a;}}for(i=l-1;i>=0;--i){f=_2e8[i];m=f._meta;f=m?m.ctor:f;if(f){f.apply(this,_2ea?_2ea[i]:a);}}f=this.postscript;if(f){f.apply(this,args);}};};function _2ec(ctor,_2ed){return function(){var a=arguments,t=a,a0=a[0],f;if(!(this instanceof a.callee)){return _2eb(a);}if(_2ed){if(a0){f=a0.preamble;if(f){t=f.apply(this,t)||t;}}f=this.preamble;if(f){f.apply(this,t);}}if(ctor){ctor.apply(this,a);}f=this.postscript;if(f){f.apply(this,a);}};};function _2ee(_2ef){return function(){var a=arguments,i=0,f,m;if(!(this instanceof a.callee)){return _2eb(a);}for(;f=_2ef[i];++i){m=f._meta;f=m?m.ctor:f;if(f){f.apply(this,a);break;}}f=this.postscript;if(f){f.apply(this,a);}};};function _2f0(name,_2f1,_2f2){return function(){var b,m,f,i=0,step=1;if(_2f2){i=_2f1.length-1;step=-1;}for(;b=_2f1[i];i+=step){m=b._meta;f=(m?m.hidden:b.prototype)[name];if(f){f.apply(this,arguments);}}};};function _2f3(ctor){xtor.prototype=ctor.prototype;var t=new xtor;xtor.prototype=null;return t;};function _2eb(args){var ctor=args.callee,t=_2f3(ctor);ctor.apply(t,args);return t;};function _2e4(_2f4,_2f5,_2f6){if(typeof _2f4!="string"){_2f6=_2f5;_2f5=_2f4;_2f4="";}_2f6=_2f6||{};var _2f7,i,t,ctor,name,_2f8,_2f9,_2fa=1,_2fb=_2f5;if(opts.call(_2f5)=="[object Array]"){_2f8=_2c7(_2f5,_2f4);t=_2f8[0];_2fa=_2f8.length-t;_2f5=_2f8[_2fa];}else{_2f8=[0];if(_2f5){if(opts.call(_2f5)=="[object Function]"){t=_2f5._meta;_2f8=_2f8.concat(t?t.bases:_2f5);}else{err("base class is not a callable constructor.",_2f4);}}else{if(_2f5!==null){err("unknown base class. Did you use dojo.require to pull it in?",_2f4);}}}if(_2f5){for(i=_2fa-1;;--i){_2f7=_2f3(_2f5);if(!i){break;}t=_2f8[i];(t._meta?_2da:mix)(_2f7,t.prototype);ctor=new Function;ctor.superclass=_2f5;ctor.prototype=_2f7;_2f5=_2f7.constructor=ctor;}}else{_2f7={};}_2e4.safeMixin(_2f7,_2f6);t=_2f6.constructor;if(t!==op.constructor){t.nom=_2c6;_2f7.constructor=t;}for(i=_2fa-1;i;--i){t=_2f8[i]._meta;if(t&&t.chains){_2f9=mix(_2f9||{},t.chains);}}if(_2f7["-chains-"]){_2f9=mix(_2f9||{},_2f7["-chains-"]);}t=!_2f9||!_2f9.hasOwnProperty(_2c6);_2f8[0]=ctor=(_2f9&&_2f9.constructor==="manual")?_2ee(_2f8):(_2f8.length==1?_2ec(_2f6.constructor,t):_2e7(_2f8,t));ctor._meta={bases:_2f8,hidden:_2f6,chains:_2f9,parents:_2fb,ctor:_2f6.constructor};ctor.superclass=_2f5&&_2f5.prototype;ctor.extend=_2e2;ctor.createSubclass=_2e5;ctor.prototype=_2f7;_2f7.constructor=ctor;_2f7.getInherited=_2d5;_2f7.isInstanceOf=_2d8;_2f7.inherited=_2d7;_2f7.__inherited=_2cf;if(_2f4){_2f7.declaredClass=_2f4;lang.setObject(_2f4,ctor);}if(_2f9){for(name in _2f9){if(_2f7[name]&&typeof _2f9[name]=="string"&&name!=_2c6){t=_2f7[name]=_2f0(name,_2f8,_2f9[name]==="after");t.nom=name;}}}return ctor;};dojo.safeMixin=_2e4.safeMixin=_2de;dojo.declare=_2e4;return _2e4;});},"dojo/dom":function(){define(["./sniff","./_base/lang","./_base/window"],function(has,lang,win){if(has("ie")<=7){try{document.execCommand("BackgroundImageCache",false,true);}catch(e){}}var dom={};if(has("ie")){dom.byId=function(id,doc){if(typeof id!="string"){return id;}var _2fc=doc||win.doc,te=id&&_2fc.getElementById(id);if(te&&(te.attributes.id.value==id||te.id==id)){return te;}else{var eles=_2fc.all[id];if(!eles||eles.nodeName){eles=[eles];}var i=0;while((te=eles[i++])){if((te.attributes&&te.attributes.id&&te.attributes.id.value==id)||te.id==id){return te;}}}};}else{dom.byId=function(id,doc){return ((typeof id=="string")?(doc||win.doc).getElementById(id):id)||null;};}dom.isDescendant=function(node,_2fd){try{node=dom.byId(node);_2fd=dom.byId(_2fd);while(node){if(node==_2fd){return true;}node=node.parentNode;}}catch(e){}return false;};dom.setSelectable=function(node,_2fe){node=dom.byId(node);if(has("mozilla")){node.style.MozUserSelect=_2fe?"":"none";}else{if(has("khtml")||has("webkit")){node.style.KhtmlUserSelect=_2fe?"auto":"none";}else{if(has("ie")){var v=(node.unselectable=_2fe?"":"on"),cs=node.getElementsByTagName("*"),i=0,l=cs.length;for(;i<l;++i){cs.item(i).unselectable=v;}}}}};return dom;});},"dojo/_base/browser":function(){if(require.has){require.has.add("config-selectorEngine","acme");}define(["../ready","./kernel","./connect","./unload","./window","./event","./html","./NodeList","../query","./xhr","./fx"],function(dojo){return dojo;});},"dojo/selector/acme":function(){define(["../dom","../sniff","../_base/array","../_base/lang","../_base/window"],function(dom,has,_2ff,lang,win){var trim=lang.trim;var each=_2ff.forEach;var _300=function(){return win.doc;};var _301=(_300().compatMode)=="BackCompat";var _302=">~+";var _303=false;var _304=function(){return true;};var _305=function(_306){if(_302.indexOf(_306.slice(-1))>=0){_306+=" * ";}else{_306+=" ";}var ts=function(s,e){return trim(_306.slice(s,e));};var _307=[];var _308=-1,_309=-1,_30a=-1,_30b=-1,_30c=-1,inId=-1,_30d=-1,_30e,lc="",cc="",_30f;var x=0,ql=_306.length,_310=null,_311=null;var _312=function(){if(_30d>=0){var tv=(_30d==x)?null:ts(_30d,x);_310[(_302.indexOf(tv)<0)?"tag":"oper"]=tv;_30d=-1;}};var _313=function(){if(inId>=0){_310.id=ts(inId,x).replace(/\\/g,"");inId=-1;}};var _314=function(){if(_30c>=0){_310.classes.push(ts(_30c+1,x).replace(/\\/g,""));_30c=-1;}};var _315=function(){_313();_312();_314();};var _316=function(){_315();if(_30b>=0){_310.pseudos.push({name:ts(_30b+1,x)});}_310.loops=(_310.pseudos.length||_310.attrs.length||_310.classes.length);_310.oquery=_310.query=ts(_30f,x);_310.otag=_310.tag=(_310["oper"])?null:(_310.tag||"*");if(_310.tag){_310.tag=_310.tag.toUpperCase();}if(_307.length&&(_307[_307.length-1].oper)){_310.infixOper=_307.pop();_310.query=_310.infixOper.query+" "+_310.query;}_307.push(_310);_310=null;};for(;lc=cc,cc=_306.charAt(x),x<ql;x++){if(lc=="\\"){continue;}if(!_310){_30f=x;_310={query:null,pseudos:[],attrs:[],classes:[],tag:null,oper:null,id:null,getTag:function(){return _303?this.otag:this.tag;}};_30d=x;}if(_30e){if(cc==_30e){_30e=null;}continue;}else{if(cc=="'"||cc=="\""){_30e=cc;continue;}}if(_308>=0){if(cc=="]"){if(!_311.attr){_311.attr=ts(_308+1,x);}else{_311.matchFor=ts((_30a||_308+1),x);}var cmf=_311.matchFor;if(cmf){if((cmf.charAt(0)=="\"")||(cmf.charAt(0)=="'")){_311.matchFor=cmf.slice(1,-1);}}if(_311.matchFor){_311.matchFor=_311.matchFor.replace(/\\/g,"");}_310.attrs.push(_311);_311=null;_308=_30a=-1;}else{if(cc=="="){var _317=("|~^$*".indexOf(lc)>=0)?lc:"";_311.type=_317+cc;_311.attr=ts(_308+1,x-_317.length);_30a=x+1;}}}else{if(_309>=0){if(cc==")"){if(_30b>=0){_311.value=ts(_309+1,x);}_30b=_309=-1;}}else{if(cc=="#"){_315();inId=x+1;}else{if(cc=="."){_315();_30c=x;}else{if(cc==":"){_315();_30b=x;}else{if(cc=="["){_315();_308=x;_311={};}else{if(cc=="("){if(_30b>=0){_311={name:ts(_30b+1,x),value:null};_310.pseudos.push(_311);}_309=x;}else{if((cc==" ")&&(lc!=cc)){_316();}}}}}}}}}return _307;};var _318=function(_319,_31a){if(!_319){return _31a;}if(!_31a){return _319;}return function(){return _319.apply(window,arguments)&&_31a.apply(window,arguments);};};var _31b=function(i,arr){var r=arr||[];if(i){r.push(i);}return r;};var _31c=function(n){return (1==n.nodeType);};var _31d="";var _31e=function(elem,attr){if(!elem){return _31d;}if(attr=="class"){return elem.className||_31d;}if(attr=="for"){return elem.htmlFor||_31d;}if(attr=="style"){return elem.style.cssText||_31d;}return (_303?elem.getAttribute(attr):elem.getAttribute(attr,2))||_31d;};var _31f={"*=":function(attr,_320){return function(elem){return (_31e(elem,attr).indexOf(_320)>=0);};},"^=":function(attr,_321){return function(elem){return (_31e(elem,attr).indexOf(_321)==0);};},"$=":function(attr,_322){return function(elem){var ea=" "+_31e(elem,attr);var _323=ea.lastIndexOf(_322);return _323>-1&&(_323==(ea.length-_322.length));};},"~=":function(attr,_324){var tval=" "+_324+" ";return function(elem){var ea=" "+_31e(elem,attr)+" ";return (ea.indexOf(tval)>=0);};},"|=":function(attr,_325){var _326=_325+"-";return function(elem){var ea=_31e(elem,attr);return ((ea==_325)||(ea.indexOf(_326)==0));};},"=":function(attr,_327){return function(elem){return (_31e(elem,attr)==_327);};}};var _328=(typeof _300().firstChild.nextElementSibling=="undefined");var _329=!_328?"nextElementSibling":"nextSibling";var _32a=!_328?"previousElementSibling":"previousSibling";var _32b=(_328?_31c:_304);var _32c=function(node){while(node=node[_32a]){if(_32b(node)){return false;}}return true;};var _32d=function(node){while(node=node[_329]){if(_32b(node)){return false;}}return true;};var _32e=function(node){var root=node.parentNode;root=root.nodeType!=7?root:root.nextSibling;var i=0,tret=root.children||root.childNodes,ci=(node["_i"]||node.getAttribute("_i")||-1),cl=(root["_l"]||(typeof root.getAttribute!=="undefined"?root.getAttribute("_l"):-1));if(!tret){return -1;}var l=tret.length;if(cl==l&&ci>=0&&cl>=0){return ci;}if(has("ie")&&typeof root.setAttribute!=="undefined"){root.setAttribute("_l",l);}else{root["_l"]=l;}ci=-1;for(var te=root["firstElementChild"]||root["firstChild"];te;te=te[_329]){if(_32b(te)){if(has("ie")){te.setAttribute("_i",++i);}else{te["_i"]=++i;}if(node===te){ci=i;}}}return ci;};var _32f=function(elem){return !((_32e(elem))%2);};var _330=function(elem){return ((_32e(elem))%2);};var _331={"checked":function(name,_332){return function(elem){return !!("checked" in elem?elem.checked:elem.selected);};},"disabled":function(name,_333){return function(elem){return elem.disabled;};},"enabled":function(name,_334){return function(elem){return !elem.disabled;};},"first-child":function(){return _32c;},"last-child":function(){return _32d;},"only-child":function(name,_335){return function(node){return _32c(node)&&_32d(node);};},"empty":function(name,_336){return function(elem){var cn=elem.childNodes;var cnl=elem.childNodes.length;for(var x=cnl-1;x>=0;x--){var nt=cn[x].nodeType;if((nt===1)||(nt==3)){return false;}}return true;};},"contains":function(name,_337){var cz=_337.charAt(0);if(cz=="\""||cz=="'"){_337=_337.slice(1,-1);}return function(elem){return (elem.innerHTML.indexOf(_337)>=0);};},"not":function(name,_338){var p=_305(_338)[0];var _339={el:1};if(p.tag!="*"){_339.tag=1;}if(!p.classes.length){_339.classes=1;}var ntf=_33a(p,_339);return function(elem){return (!ntf(elem));};},"nth-child":function(name,_33b){var pi=parseInt;if(_33b=="odd"){return _330;}else{if(_33b=="even"){return _32f;}}if(_33b.indexOf("n")!=-1){var _33c=_33b.split("n",2);var pred=_33c[0]?((_33c[0]=="-")?-1:pi(_33c[0])):1;var idx=_33c[1]?pi(_33c[1]):0;var lb=0,ub=-1;if(pred>0){if(idx<0){idx=(idx%pred)&&(pred+(idx%pred));}else{if(idx>0){if(idx>=pred){lb=idx-idx%pred;}idx=idx%pred;}}}else{if(pred<0){pred*=-1;if(idx>0){ub=idx;idx=idx%pred;}}}if(pred>0){return function(elem){var i=_32e(elem);return (i>=lb)&&(ub<0||i<=ub)&&((i%pred)==idx);};}else{_33b=idx;}}var _33d=pi(_33b);return function(elem){return (_32e(elem)==_33d);};}};var _33e=(has("ie")&&(has("ie")<9||has("quirks")))?function(cond){var clc=cond.toLowerCase();if(clc=="class"){cond="className";}return function(elem){return (_303?elem.getAttribute(cond):elem[cond]||elem[clc]);};}:function(cond){return function(elem){return (elem&&elem.getAttribute&&elem.hasAttribute(cond));};};var _33a=function(_33f,_340){if(!_33f){return _304;}_340=_340||{};var ff=null;if(!("el" in _340)){ff=_318(ff,_31c);}if(!("tag" in _340)){if(_33f.tag!="*"){ff=_318(ff,function(elem){return (elem&&((_303?elem.tagName:elem.tagName.toUpperCase())==_33f.getTag()));});}}if(!("classes" in _340)){each(_33f.classes,function(_341,idx,arr){var re=new RegExp("(?:^|\\s)"+_341+"(?:\\s|$)");ff=_318(ff,function(elem){return re.test(elem.className);});ff.count=idx;});}if(!("pseudos" in _340)){each(_33f.pseudos,function(_342){var pn=_342.name;if(_331[pn]){ff=_318(ff,_331[pn](pn,_342.value));}});}if(!("attrs" in _340)){each(_33f.attrs,function(attr){var _343;var a=attr.attr;if(attr.type&&_31f[attr.type]){_343=_31f[attr.type](a,attr.matchFor);}else{if(a.length){_343=_33e(a);}}if(_343){ff=_318(ff,_343);}});}if(!("id" in _340)){if(_33f.id){ff=_318(ff,function(elem){return (!!elem&&(elem.id==_33f.id));});}}if(!ff){if(!("default" in _340)){ff=_304;}}return ff;};var _344=function(_345){return function(node,ret,bag){while(node=node[_329]){if(_328&&(!_31c(node))){continue;}if((!bag||_346(node,bag))&&_345(node)){ret.push(node);}break;}return ret;};};var _347=function(_348){return function(root,ret,bag){var te=root[_329];while(te){if(_32b(te)){if(bag&&!_346(te,bag)){break;}if(_348(te)){ret.push(te);}}te=te[_329];}return ret;};};var _349=function(_34a){_34a=_34a||_304;return function(root,ret,bag){var te,x=0,tret=root.children||root.childNodes;while(te=tret[x++]){if(_32b(te)&&(!bag||_346(te,bag))&&(_34a(te,x))){ret.push(te);}}return ret;};};var _34b=function(node,root){var pn=node.parentNode;while(pn){if(pn==root){break;}pn=pn.parentNode;}return !!pn;};var _34c={};var _34d=function(_34e){var _34f=_34c[_34e.query];if(_34f){return _34f;}var io=_34e.infixOper;var oper=(io?io.oper:"");var _350=_33a(_34e,{el:1});var qt=_34e.tag;var _351=("*"==qt);var ecs=_300()["getElementsByClassName"];if(!oper){if(_34e.id){_350=(!_34e.loops&&_351)?_304:_33a(_34e,{el:1,id:1});_34f=function(root,arr){var te=dom.byId(_34e.id,(root.ownerDocument||root));if(!te||!_350(te)){return;}if(9==root.nodeType){return _31b(te,arr);}else{if(_34b(te,root)){return _31b(te,arr);}}};}else{if(ecs&&/\{\s*\[native code\]\s*\}/.test(String(ecs))&&_34e.classes.length&&!_301){_350=_33a(_34e,{el:1,classes:1,id:1});var _352=_34e.classes.join(" ");_34f=function(root,arr,bag){var ret=_31b(0,arr),te,x=0;var tret=root.getElementsByClassName(_352);while((te=tret[x++])){if(_350(te,root)&&_346(te,bag)){ret.push(te);}}return ret;};}else{if(!_351&&!_34e.loops){_34f=function(root,arr,bag){var ret=_31b(0,arr),te,x=0;var tag=_34e.getTag(),tret=tag?root.getElementsByTagName(tag):[];while((te=tret[x++])){if(_346(te,bag)){ret.push(te);}}return ret;};}else{_350=_33a(_34e,{el:1,tag:1,id:1});_34f=function(root,arr,bag){var ret=_31b(0,arr),te,x=0;var tag=_34e.getTag(),tret=tag?root.getElementsByTagName(tag):[];while((te=tret[x++])){if(_350(te,root)&&_346(te,bag)){ret.push(te);}}return ret;};}}}}else{var _353={el:1};if(_351){_353.tag=1;}_350=_33a(_34e,_353);if("+"==oper){_34f=_344(_350);}else{if("~"==oper){_34f=_347(_350);}else{if(">"==oper){_34f=_349(_350);}}}}return _34c[_34e.query]=_34f;};var _354=function(root,_355){var _356=_31b(root),qp,x,te,qpl=_355.length,bag,ret;for(var i=0;i<qpl;i++){ret=[];qp=_355[i];x=_356.length-1;if(x>0){bag={};ret.nozip=true;}var gef=_34d(qp);for(var j=0;(te=_356[j]);j++){gef(te,ret,bag);}if(!ret.length){break;}_356=ret;}return ret;};var _357={},_358={};var _359=function(_35a){var _35b=_305(trim(_35a));if(_35b.length==1){var tef=_34d(_35b[0]);return function(root){var r=tef(root,[]);if(r){r.nozip=true;}return r;};}return function(root){return _354(root,_35b);};};var _35c=has("ie")?"commentStrip":"nozip";var qsa="querySelectorAll";var _35d=!!_300()[qsa];var _35e=/\\[>~+]|n\+\d|([^ \\])?([>~+])([^ =])?/g;var _35f=function(_360,pre,ch,post){return ch?(pre?pre+" ":"")+ch+(post?" "+post:""):_360;};var _361=/([^[]*)([^\]]*])?/g;var _362=function(_363,_364,att){return _364.replace(_35e,_35f)+(att||"");};var _365=function(_366,_367){_366=_366.replace(_361,_362);if(_35d){var _368=_358[_366];if(_368&&!_367){return _368;}}var _369=_357[_366];if(_369){return _369;}var qcz=_366.charAt(0);var _36a=(-1==_366.indexOf(" "));if((_366.indexOf("#")>=0)&&(_36a)){_367=true;}var _36b=(_35d&&(!_367)&&(_302.indexOf(qcz)==-1)&&(!has("ie")||(_366.indexOf(":")==-1))&&(!(_301&&(_366.indexOf(".")>=0)))&&(_366.indexOf(":contains")==-1)&&(_366.indexOf(":checked")==-1)&&(_366.indexOf("|=")==-1));if(_36b){var tq=(_302.indexOf(_366.charAt(_366.length-1))>=0)?(_366+" *"):_366;return _358[_366]=function(root){try{if(!((9==root.nodeType)||_36a)){throw "";}var r=root[qsa](tq);r[_35c]=true;return r;}catch(e){return _365(_366,true)(root);}};}else{var _36c=_366.match(/([^\s,](?:"(?:\\.|[^"])+"|'(?:\\.|[^'])+'|[^,])*)/g);return _357[_366]=((_36c.length<2)?_359(_366):function(root){var _36d=0,ret=[],tp;while((tp=_36c[_36d++])){ret=ret.concat(_359(tp)(root));}return ret;});}};var _36e=0;var _36f=has("ie")?function(node){if(_303){return (node.getAttribute("_uid")||node.setAttribute("_uid",++_36e)||_36e);}else{return node.uniqueID;}}:function(node){return (node._uid||(node._uid=++_36e));};var _346=function(node,bag){if(!bag){return 1;}var id=_36f(node);if(!bag[id]){return bag[id]=1;}return 0;};var _370="_zipIdx";var _371=function(arr){if(arr&&arr.nozip){return arr;}var ret=[];if(!arr||!arr.length){return ret;}if(arr[0]){ret.push(arr[0]);}if(arr.length<2){return ret;}_36e++;var x,te;if(has("ie")&&_303){var _372=_36e+"";arr[0].setAttribute(_370,_372);for(x=1;te=arr[x];x++){if(arr[x].getAttribute(_370)!=_372){ret.push(te);}te.setAttribute(_370,_372);}}else{if(has("ie")&&arr.commentStrip){try{for(x=1;te=arr[x];x++){if(_31c(te)){ret.push(te);}}}catch(e){}}else{if(arr[0]){arr[0][_370]=_36e;}for(x=1;te=arr[x];x++){if(arr[x][_370]!=_36e){ret.push(te);}te[_370]=_36e;}}}return ret;};var _373=function(_374,root){root=root||_300();var od=root.ownerDocument||root;_303=(od.createElement("div").tagName==="div");var r=_365(_374)(root);if(r&&r.nozip){return r;}return _371(r);};_373.filter=function(_375,_376,root){var _377=[],_378=_305(_376),_379=(_378.length==1&&!/[^\w#\.]/.test(_376))?_33a(_378[0]):function(node){return _2ff.indexOf(_373(_376,dom.byId(root)),node)!=-1;};for(var x=0,te;te=_375[x];x++){if(_379(te)){_377.push(te);}}return _377;};return _373;});},"dojo/errors/RequestTimeoutError":function(){define("dojo/errors/RequestTimeoutError",["./create","./RequestError"],function(_37a,_37b){return _37a("RequestTimeoutError",null,_37b,{dojoType:"timeout"});});},"dojo/dom-geometry":function(){define(["./sniff","./_base/window","./dom","./dom-style"],function(has,win,dom,_37c){var geom={};geom.boxModel="content-box";if(has("ie")){geom.boxModel=document.compatMode=="BackCompat"?"border-box":"content-box";}geom.getPadExtents=function getPadExtents(node,_37d){node=dom.byId(node);var s=_37d||_37c.getComputedStyle(node),px=_37c.toPixelValue,l=px(node,s.paddingLeft),t=px(node,s.paddingTop),r=px(node,s.paddingRight),b=px(node,s.paddingBottom);return {l:l,t:t,r:r,b:b,w:l+r,h:t+b};};var none="none";geom.getBorderExtents=function getBorderExtents(node,_37e){node=dom.byId(node);var px=_37c.toPixelValue,s=_37e||_37c.getComputedStyle(node),l=s.borderLeftStyle!=none?px(node,s.borderLeftWidth):0,t=s.borderTopStyle!=none?px(node,s.borderTopWidth):0,r=s.borderRightStyle!=none?px(node,s.borderRightWidth):0,b=s.borderBottomStyle!=none?px(node,s.borderBottomWidth):0;return {l:l,t:t,r:r,b:b,w:l+r,h:t+b};};geom.getPadBorderExtents=function getPadBorderExtents(node,_37f){node=dom.byId(node);var s=_37f||_37c.getComputedStyle(node),p=geom.getPadExtents(node,s),b=geom.getBorderExtents(node,s);return {l:p.l+b.l,t:p.t+b.t,r:p.r+b.r,b:p.b+b.b,w:p.w+b.w,h:p.h+b.h};};geom.getMarginExtents=function getMarginExtents(node,_380){node=dom.byId(node);var s=_380||_37c.getComputedStyle(node),px=_37c.toPixelValue,l=px(node,s.marginLeft),t=px(node,s.marginTop),r=px(node,s.marginRight),b=px(node,s.marginBottom);return {l:l,t:t,r:r,b:b,w:l+r,h:t+b};};geom.getMarginBox=function getMarginBox(node,_381){node=dom.byId(node);var s=_381||_37c.getComputedStyle(node),me=geom.getMarginExtents(node,s),l=node.offsetLeft-me.l,t=node.offsetTop-me.t,p=node.parentNode,px=_37c.toPixelValue,pcs;if(has("mozilla")){var sl=parseFloat(s.left),st=parseFloat(s.top);if(!isNaN(sl)&&!isNaN(st)){l=sl;t=st;}else{if(p&&p.style){pcs=_37c.getComputedStyle(p);if(pcs.overflow!="visible"){l+=pcs.borderLeftStyle!=none?px(node,pcs.borderLeftWidth):0;t+=pcs.borderTopStyle!=none?px(node,pcs.borderTopWidth):0;}}}}else{if(has("opera")||(has("ie")==8&&!has("quirks"))){if(p){pcs=_37c.getComputedStyle(p);l-=pcs.borderLeftStyle!=none?px(node,pcs.borderLeftWidth):0;t-=pcs.borderTopStyle!=none?px(node,pcs.borderTopWidth):0;}}}return {l:l,t:t,w:node.offsetWidth+me.w,h:node.offsetHeight+me.h};};geom.getContentBox=function getContentBox(node,_382){node=dom.byId(node);var s=_382||_37c.getComputedStyle(node),w=node.clientWidth,h,pe=geom.getPadExtents(node,s),be=geom.getBorderExtents(node,s);if(!w){w=node.offsetWidth;h=node.offsetHeight;}else{h=node.clientHeight;be.w=be.h=0;}if(has("opera")){pe.l+=be.l;pe.t+=be.t;}return {l:pe.l,t:pe.t,w:w-pe.w-be.w,h:h-pe.h-be.h};};function _383(node,l,t,w,h,u){u=u||"px";var s=node.style;if(!isNaN(l)){s.left=l+u;}if(!isNaN(t)){s.top=t+u;}if(w>=0){s.width=w+u;}if(h>=0){s.height=h+u;}};function _384(node){return node.tagName.toLowerCase()=="button"||node.tagName.toLowerCase()=="input"&&(node.getAttribute("type")||"").toLowerCase()=="button";};function _385(node){return geom.boxModel=="border-box"||node.tagName.toLowerCase()=="table"||_384(node);};geom.setContentSize=function setContentSize(node,box,_386){node=dom.byId(node);var w=box.w,h=box.h;if(_385(node)){var pb=geom.getPadBorderExtents(node,_386);if(w>=0){w+=pb.w;}if(h>=0){h+=pb.h;}}_383(node,NaN,NaN,w,h);};var _387={l:0,t:0,w:0,h:0};geom.setMarginBox=function setMarginBox(node,box,_388){node=dom.byId(node);var s=_388||_37c.getComputedStyle(node),w=box.w,h=box.h,pb=_385(node)?_387:geom.getPadBorderExtents(node,s),mb=geom.getMarginExtents(node,s);if(has("webkit")){if(_384(node)){var ns=node.style;if(w>=0&&!ns.width){ns.width="4px";}if(h>=0&&!ns.height){ns.height="4px";}}}if(w>=0){w=Math.max(w-pb.w-mb.w,0);}if(h>=0){h=Math.max(h-pb.h-mb.h,0);}_383(node,box.l,box.t,w,h);};geom.isBodyLtr=function isBodyLtr(doc){doc=doc||win.doc;return (win.body(doc).dir||doc.documentElement.dir||"ltr").toLowerCase()=="ltr";};geom.docScroll=function docScroll(doc){doc=doc||win.doc;var node=win.doc.parentWindow||win.doc.defaultView;return "pageXOffset" in node?{x:node.pageXOffset,y:node.pageYOffset}:(node=has("quirks")?win.body(doc):doc.documentElement)&&{x:geom.fixIeBiDiScrollLeft(node.scrollLeft||0,doc),y:node.scrollTop||0};};if(has("ie")){geom.getIeDocumentElementOffset=function getIeDocumentElementOffset(doc){doc=doc||win.doc;var de=doc.documentElement;if(has("ie")<8){var r=de.getBoundingClientRect(),l=r.left,t=r.top;if(has("ie")<7){l+=de.clientLeft;t+=de.clientTop;}return {x:l<0?0:l,y:t<0?0:t};}else{return {x:0,y:0};}};}geom.fixIeBiDiScrollLeft=function fixIeBiDiScrollLeft(_389,doc){doc=doc||win.doc;var ie=has("ie");if(ie&&!geom.isBodyLtr(doc)){var qk=has("quirks"),de=qk?win.body(doc):doc.documentElement,pwin=win.global;if(ie==6&&!qk&&pwin.frameElement&&de.scrollHeight>de.clientHeight){_389+=de.clientLeft;}return (ie<8||qk)?(_389+de.clientWidth-de.scrollWidth):-_389;}return _389;};geom.position=function(node,_38a){node=dom.byId(node);var db=win.body(node.ownerDocument),ret=node.getBoundingClientRect();ret={x:ret.left,y:ret.top,w:ret.right-ret.left,h:ret.bottom-ret.top};if(has("ie")){var _38b=geom.getIeDocumentElementOffset(node.ownerDocument);ret.x-=_38b.x+(has("quirks")?db.clientLeft+db.offsetLeft:0);ret.y-=_38b.y+(has("quirks")?db.clientTop+db.offsetTop:0);}if(_38a){var _38c=geom.docScroll(node.ownerDocument);ret.x+=_38c.x;ret.y+=_38c.y;}return ret;};geom.getMarginSize=function getMarginSize(node,_38d){node=dom.byId(node);var me=geom.getMarginExtents(node,_38d||_37c.getComputedStyle(node));var size=node.getBoundingClientRect();return {w:(size.right-size.left)+me.w,h:(size.bottom-size.top)+me.h};};geom.normalizeEvent=function(_38e){if(!("layerX" in _38e)){_38e.layerX=_38e.offsetX;_38e.layerY=_38e.offsetY;}if(!has("dom-addeventlistener")){var se=_38e.target;var doc=(se&&se.ownerDocument)||document;var _38f=has("quirks")?doc.body:doc.documentElement;var _390=geom.getIeDocumentElementOffset(doc);_38e.pageX=_38e.clientX+geom.fixIeBiDiScrollLeft(_38f.scrollLeft||0,doc)-_390.x;_38e.pageY=_38e.clientY+(_38f.scrollTop||0)-_390.y;}};return geom;});},"dojo/dom-style":function(){define("dojo/dom-style",["./sniff","./dom"],function(has,dom){var _391,_392={};if(has("webkit")){_391=function(node){var s;if(node.nodeType==1){var dv=node.ownerDocument.defaultView;s=dv.getComputedStyle(node,null);if(!s&&node.style){node.style.display="";s=dv.getComputedStyle(node,null);}}return s||{};};}else{if(has("ie")&&(has("ie")<9||has("quirks"))){_391=function(node){return node.nodeType==1&&node.currentStyle?node.currentStyle:{};};}else{_391=function(node){return node.nodeType==1?node.ownerDocument.defaultView.getComputedStyle(node,null):{};};}}_392.getComputedStyle=_391;var _393;if(!has("ie")){_393=function(_394,_395){return parseFloat(_395)||0;};}else{_393=function(_396,_397){if(!_397){return 0;}if(_397=="medium"){return 4;}if(_397.slice&&_397.slice(-2)=="px"){return parseFloat(_397);}var s=_396.style,rs=_396.runtimeStyle,cs=_396.currentStyle,_398=s.left,_399=rs.left;rs.left=cs.left;try{s.left=_397;_397=s.pixelLeft;}catch(e){_397=0;}s.left=_398;rs.left=_399;return _397;};}_392.toPixelValue=_393;var astr="DXImageTransform.Microsoft.Alpha";var af=function(n,f){try{return n.filters.item(astr);}catch(e){return f?{}:null;}};var _39a=has("ie")<9||(has("ie")&&has("quirks"))?function(node){try{return af(node).Opacity/100;}catch(e){return 1;}}:function(node){return _391(node).opacity;};var _39b=has("ie")<9||(has("ie")&&has("quirks"))?function(node,_39c){var ov=_39c*100,_39d=_39c==1;node.style.zoom=_39d?"":1;if(!af(node)){if(_39d){return _39c;}node.style.filter+=" progid:"+astr+"(Opacity="+ov+")";}else{af(node,1).Opacity=ov;}af(node,1).Enabled=!_39d;if(node.tagName.toLowerCase()=="tr"){for(var td=node.firstChild;td;td=td.nextSibling){if(td.tagName.toLowerCase()=="td"){_39b(td,_39c);}}}return _39c;}:function(node,_39e){return node.style.opacity=_39e;};var _39f={left:true,top:true};var _3a0=/margin|padding|width|height|max|min|offset/;function _3a1(node,type,_3a2){type=type.toLowerCase();if(has("ie")){if(_3a2=="auto"){if(type=="height"){return node.offsetHeight;}if(type=="width"){return node.offsetWidth;}}if(type=="fontweight"){switch(_3a2){case 700:return "bold";case 400:default:return "normal";}}}if(!(type in _39f)){_39f[type]=_3a0.test(type);}return _39f[type]?_393(node,_3a2):_3a2;};var _3a3=has("ie")?"styleFloat":"cssFloat",_3a4={"cssFloat":_3a3,"styleFloat":_3a3,"float":_3a3};_392.get=function getStyle(node,name){var n=dom.byId(node),l=arguments.length,op=(name=="opacity");if(l==2&&op){return _39a(n);}name=_3a4[name]||name;var s=_392.getComputedStyle(n);return (l==1)?s:_3a1(n,name,s[name]||n.style[name]);};_392.set=function setStyle(node,name,_3a5){var n=dom.byId(node),l=arguments.length,op=(name=="opacity");name=_3a4[name]||name;if(l==3){return op?_39b(n,_3a5):n.style[name]=_3a5;}for(var x in name){_392.set(node,x,name[x]);}return _392.getComputedStyle(n);};return _392;});},"dojo/dom-prop":function(){define(["exports","./_base/kernel","./sniff","./_base/lang","./dom","./dom-style","./dom-construct","./_base/connect"],function(_3a6,dojo,has,lang,dom,_3a7,ctr,conn){var _3a8={},_3a9=0,_3aa=dojo._scopeName+"attrid";_3a6.names={"class":"className","for":"htmlFor",tabindex:"tabIndex",readonly:"readOnly",colspan:"colSpan",frameborder:"frameBorder",rowspan:"rowSpan",valuetype:"valueType"};_3a6.get=function getProp(node,name){node=dom.byId(node);var lc=name.toLowerCase(),_3ab=_3a6.names[lc]||name;return node[_3ab];};_3a6.set=function setProp(node,name,_3ac){node=dom.byId(node);var l=arguments.length;if(l==2&&typeof name!="string"){for(var x in name){_3a6.set(node,x,name[x]);}return node;}var lc=name.toLowerCase(),_3ad=_3a6.names[lc]||name;if(_3ad=="style"&&typeof _3ac!="string"){_3a7.set(node,_3ac);return node;}if(_3ad=="innerHTML"){if(has("ie")&&node.tagName.toLowerCase() in {col:1,colgroup:1,table:1,tbody:1,tfoot:1,thead:1,tr:1,title:1}){ctr.empty(node);node.appendChild(ctr.toDom(_3ac,node.ownerDocument));}else{node[_3ad]=_3ac;}return node;}if(lang.isFunction(_3ac)){var _3ae=node[_3aa];if(!_3ae){_3ae=_3a9++;node[_3aa]=_3ae;}if(!_3a8[_3ae]){_3a8[_3ae]={};}var h=_3a8[_3ae][_3ad];if(h){conn.disconnect(h);}else{try{delete node[_3ad];}catch(e){}}if(_3ac){_3a8[_3ae][_3ad]=conn.connect(node,_3ad,_3ac);}else{node[_3ad]=null;}return node;}node[_3ad]=_3ac;return node;};});},"dojo/when":function(){define(["./Deferred","./promise/Promise"],function(_3af,_3b0){"use strict";return function when(_3b1,_3b2,_3b3,_3b4){var _3b5=_3b1&&typeof _3b1.then==="function";var _3b6=_3b5&&_3b1 instanceof _3b0;if(!_3b5){if(_3b2){return _3b2(_3b1);}else{return new _3af().resolve(_3b1);}}else{if(!_3b6){var _3b7=new _3af(_3b1.cancel);_3b1.then(_3b7.resolve,_3b7.reject,_3b7.progress);_3b1=_3b7.promise;}}if(_3b2||_3b3||_3b4){return _3b1.then(_3b2,_3b3,_3b4);}return _3b1;};});},"dojo/dom-attr":function(){define(["exports","./sniff","./_base/lang","./dom","./dom-style","./dom-prop"],function(_3b8,has,lang,dom,_3b9,prop){var _3ba={innerHTML:1,className:1,htmlFor:has("ie"),value:1},_3bb={classname:"class",htmlfor:"for",tabindex:"tabIndex",readonly:"readOnly"};function _3bc(node,name){var attr=node.getAttributeNode&&node.getAttributeNode(name);return attr&&attr.specified;};_3b8.has=function hasAttr(node,name){var lc=name.toLowerCase();return _3ba[prop.names[lc]||name]||_3bc(dom.byId(node),_3bb[lc]||name);};_3b8.get=function getAttr(node,name){node=dom.byId(node);var lc=name.toLowerCase(),_3bd=prop.names[lc]||name,_3be=_3ba[_3bd],_3bf=node[_3bd];if(_3be&&typeof _3bf!="undefined"){return _3bf;}if(_3bd!="href"&&(typeof _3bf=="boolean"||lang.isFunction(_3bf))){return _3bf;}var _3c0=_3bb[lc]||name;return _3bc(node,_3c0)?node.getAttribute(_3c0):null;};_3b8.set=function setAttr(node,name,_3c1){node=dom.byId(node);if(arguments.length==2){for(var x in name){_3b8.set(node,x,name[x]);}return node;}var lc=name.toLowerCase(),_3c2=prop.names[lc]||name,_3c3=_3ba[_3c2];if(_3c2=="style"&&typeof _3c1!="string"){_3b9.set(node,_3c1);return node;}if(_3c3||typeof _3c1=="boolean"||lang.isFunction(_3c1)){return prop.set(node,name,_3c1);}node.setAttribute(_3bb[lc]||name,_3c1);return node;};_3b8.remove=function removeAttr(node,name){dom.byId(node).removeAttribute(_3bb[name.toLowerCase()]||name);};_3b8.getNodeProp=function getNodeProp(node,name){node=dom.byId(node);var lc=name.toLowerCase(),_3c4=prop.names[lc]||name;if((_3c4 in node)&&_3c4!="href"){return node[_3c4];}var _3c5=_3bb[lc]||name;return _3bc(node,_3c5)?node.getAttribute(_3c5):null;};});},"dojo/dom-construct":function(){define(["exports","./_base/kernel","./sniff","./_base/window","./dom","./dom-attr","./on"],function(_3c6,dojo,has,win,dom,attr,on){var _3c7={option:["select"],tbody:["table"],thead:["table"],tfoot:["table"],tr:["table","tbody"],td:["table","tbody","tr"],th:["table","thead","tr"],legend:["fieldset"],caption:["table"],colgroup:["table"],col:["table","colgroup"],li:["ul"]},_3c8=/<\s*([\w\:]+)/,_3c9={},_3ca=0,_3cb="__"+dojo._scopeName+"ToDomId";for(var _3cc in _3c7){if(_3c7.hasOwnProperty(_3cc)){var tw=_3c7[_3cc];tw.pre=_3cc=="option"?"<select multiple=\"multiple\">":"<"+tw.join("><")+">";tw.post="</"+tw.reverse().join("></")+">";}}function _3cd(node,ref){var _3ce=ref.parentNode;if(_3ce){_3ce.insertBefore(node,ref);}};function _3cf(node,ref){var _3d0=ref.parentNode;if(_3d0){if(_3d0.lastChild==ref){_3d0.appendChild(node);}else{_3d0.insertBefore(node,ref.nextSibling);}}};var _3d1=null,_3d2;on(window,"unload",function(){_3d1=null;});_3c6.toDom=function toDom(frag,doc){doc=doc||win.doc;var _3d3=doc[_3cb];if(!_3d3){doc[_3cb]=_3d3=++_3ca+"";_3c9[_3d3]=doc.createElement("div");}frag+="";var _3d4=frag.match(_3c8),tag=_3d4?_3d4[1].toLowerCase():"",_3d5=_3c9[_3d3],wrap,i,fc,df;if(_3d4&&_3c7[tag]){wrap=_3c7[tag];_3d5.innerHTML=wrap.pre+frag+wrap.post;for(i=wrap.length;i;--i){_3d5=_3d5.firstChild;}}else{_3d5.innerHTML=frag;}if(_3d5.childNodes.length==1){return _3d5.removeChild(_3d5.firstChild);}df=doc.createDocumentFragment();while(fc=_3d5.firstChild){df.appendChild(fc);}return df;};_3c6.place=function place(node,_3d6,_3d7){_3d6=dom.byId(_3d6);if(typeof node=="string"){node=/^\s*</.test(node)?_3c6.toDom(node,_3d6.ownerDocument):dom.byId(node);}if(typeof _3d7=="number"){var cn=_3d6.childNodes;if(!cn.length||cn.length<=_3d7){_3d6.appendChild(node);}else{_3cd(node,cn[_3d7<0?0:_3d7]);}}else{switch(_3d7){case "before":_3cd(node,_3d6);break;case "after":_3cf(node,_3d6);break;case "replace":_3d6.parentNode.replaceChild(node,_3d6);break;case "only":_3c6.empty(_3d6);_3d6.appendChild(node);break;case "first":if(_3d6.firstChild){_3cd(node,_3d6.firstChild);break;}default:_3d6.appendChild(node);}}return node;};_3c6.create=function create(tag,_3d8,_3d9,pos){var doc=win.doc;if(_3d9){_3d9=dom.byId(_3d9);doc=_3d9.ownerDocument;}if(typeof tag=="string"){tag=doc.createElement(tag);}if(_3d8){attr.set(tag,_3d8);}if(_3d9){_3c6.place(tag,_3d9,pos);}return tag;};_3c6.empty=has("ie")?function(node){node=dom.byId(node);for(var c;c=node.lastChild;){_3c6.destroy(c);}}:function(node){dom.byId(node).innerHTML="";};_3c6.destroy=function destroy(node){node=dom.byId(node);try{var doc=node.ownerDocument;if(!_3d1||_3d2!=doc){_3d1=doc.createElement("div");_3d2=doc;}_3d1.appendChild(node.parentNode?node.parentNode.removeChild(node):node);_3d1.innerHTML="";}catch(e){}};});},"dojo/request/xhr":function(){define("dojo/request/xhr",["../errors/RequestError","./watch","./handlers","./util","../has"],function(_3da,_3db,_3dc,util,has){has.add("native-xhr",function(){return typeof XMLHttpRequest!=="undefined";});has.add("dojo-force-activex-xhr",function(){return has("activex")&&!document.addEventListener&&window.location.protocol==="file:";});has.add("native-xhr2",function(){if(!has("native-xhr")){return;}var x=new XMLHttpRequest();return typeof x["addEventListener"]!=="undefined"&&(typeof opera==="undefined"||typeof x["upload"]!=="undefined");});has.add("native-formdata",function(){return typeof FormData==="function";});function _3dd(_3de,_3df){var _3e0=_3de.xhr;_3de.status=_3de.xhr.status;_3de.text=_3e0.responseText;if(_3de.options.handleAs==="xml"){_3de.data=_3e0.responseXML;}if(!_3df){try{_3dc(_3de);}catch(e){_3df=e;}}if(_3df){this.reject(_3df);}else{if(util.checkStatus(_3e0.status)){this.resolve(_3de);}else{_3df=new _3da("Unable to load "+_3de.url+" status: "+_3e0.status,_3de);this.reject(_3df);}}};var _3e1,_3e2,_3e3,_3e4;if(has("native-xhr2")){_3e1=function(_3e5){return !this.isFulfilled();};_3e4=function(dfd,_3e6){_3e6.xhr.abort();};_3e3=function(_3e7,dfd,_3e8){function _3e9(evt){dfd.handleResponse(_3e8);};function _3ea(evt){var _3eb=evt.target;var _3ec=new _3da("Unable to load "+_3e8.url+" status: "+_3eb.status,_3e8);dfd.handleResponse(_3e8,_3ec);};function _3ed(evt){if(evt.lengthComputable){_3e8.loaded=evt.loaded;_3e8.total=evt.total;dfd.progress(_3e8);}};_3e7.addEventListener("load",_3e9,false);_3e7.addEventListener("error",_3ea,false);_3e7.addEventListener("progress",_3ed,false);return function(){_3e7.removeEventListener("load",_3e9,false);_3e7.removeEventListener("error",_3ea,false);_3e7.removeEventListener("progress",_3ed,false);};};}else{_3e1=function(_3ee){return _3ee.xhr.readyState;};_3e2=function(_3ef){return 4===_3ef.xhr.readyState;};_3e4=function(dfd,_3f0){var xhr=_3f0.xhr;var _3f1=typeof xhr.abort;if(_3f1==="function"||_3f1==="object"||_3f1==="unknown"){xhr.abort();}};}var _3f2,_3f3={data:null,query:null,sync:false,method:"GET",headers:{"Content-Type":"application/x-www-form-urlencoded"}};function xhr(url,_3f4,_3f5){var _3f6=util.parseArgs(url,util.deepCreate(_3f3,_3f4),has("native-formdata")&&_3f4&&_3f4.data&&_3f4.data instanceof FormData);url=_3f6.url;_3f4=_3f6.options;var _3f7,last=function(){_3f7&&_3f7();};var dfd=util.deferred(_3f6,_3e4,_3e1,_3e2,_3dd,last);var _3f8=_3f6.xhr=xhr._create();if(!_3f8){dfd.cancel(new _3da("XHR was not created"));return _3f5?dfd:dfd.promise;}_3f6.getHeader=function(_3f9){return this.xhr.getResponseHeader(_3f9);};if(_3e3){_3f7=_3e3(_3f8,dfd,_3f6);}var data=_3f4.data,_3fa=!_3f4.sync,_3fb=_3f4.method;try{_3f8.open(_3fb,url,_3fa,_3f4.user||_3f2,_3f4.password||_3f2);if(_3f4.withCredentials){_3f8.withCredentials=_3f4.withCredentials;}var _3fc=_3f4.headers,_3fd;if(_3fc){for(var hdr in _3fc){if(hdr.toLowerCase()==="content-type"){_3fd=_3fc[hdr];}else{if(_3fc[hdr]){_3f8.setRequestHeader(hdr,_3fc[hdr]);}}}}if(_3fd&&_3fd!==false){_3f8.setRequestHeader("Content-Type",_3fd);}if(!_3fc||!("X-Requested-With" in _3fc)){_3f8.setRequestHeader("X-Requested-With","XMLHttpRequest");}if(util.notify){util.notify.emit("send",_3f6,dfd.promise.cancel);}_3f8.send(data);}catch(e){dfd.reject(e);}_3db(dfd);_3f8=null;return _3f5?dfd:dfd.promise;};xhr._create=function(){throw new Error("XMLHTTP not available");};if(has("native-xhr")&&!has("dojo-force-activex-xhr")){xhr._create=function(){return new XMLHttpRequest();};}else{if(has("activex")){try{new ActiveXObject("Msxml2.XMLHTTP");xhr._create=function(){return new ActiveXObject("Msxml2.XMLHTTP");};}catch(e){try{new ActiveXObject("Microsoft.XMLHTTP");xhr._create=function(){return new ActiveXObject("Microsoft.XMLHTTP");};}catch(e){}}}}util.addCommonMethods(xhr);return xhr;});},"dojo/text":function(){define(["./_base/kernel","require","./has","./_base/xhr"],function(dojo,_3fe,has,xhr){var _3ff;if(1){_3ff=function(url,sync,load){xhr("GET",{url:url,sync:!!sync,load:load,headers:dojo.config.textPluginHeaders||{}});};}else{if(_3fe.getText){_3ff=_3fe.getText;}else{console.error("dojo/text plugin failed to load because loader does not support getText");}}var _400={},_401=function(text){if(text){text=text.replace(/^\s*<\?xml(\s)+version=[\'\"](\d)*.(\d)*[\'\"](\s)*\?>/im,"");var _402=text.match(/<body[^>]*>\s*([\s\S]+)\s*<\/body>/im);if(_402){text=_402[1];}}else{text="";}return text;},_403={},_404={};dojo.cache=function(_405,url,_406){var key;if(typeof _405=="string"){if(/\//.test(_405)){key=_405;_406=url;}else{key=_3fe.toUrl(_405.replace(/\./g,"/")+(url?("/"+url):""));}}else{key=_405+"";_406=url;}var val=(_406!=undefined&&typeof _406!="string")?_406.value:_406,_407=_406&&_406.sanitize;if(typeof val=="string"){_400[key]=val;return _407?_401(val):val;}else{if(val===null){delete _400[key];return null;}else{if(!(key in _400)){_3ff(key,true,function(text){_400[key]=text;});}return _407?_401(_400[key]):_400[key];}}};return {dynamic:true,normalize:function(id,_408){var _409=id.split("!"),url=_409[0];return (/^\./.test(url)?_408(url):url)+(_409[1]?"!"+_409[1]:"");},load:function(id,_40a,load){var _40b=id.split("!"),_40c=_40b.length>1,_40d=_40b[0],url=_40a.toUrl(_40b[0]),_40e="url:"+url,text=_403,_40f=function(text){load(_40c?_401(text):text);};if(_40d in _400){text=_400[_40d];}else{if(_40e in _40a.cache){text=_40a.cache[_40e];}else{if(url in _400){text=_400[url];}}}if(text===_403){if(_404[url]){_404[url].push(_40f);}else{var _410=_404[url]=[_40f];_3ff(url,!_40a.async,function(text){_400[_40d]=_400[url]=text;for(var i=0;i<_410.length;){_410[i++](text);}delete _404[url];});}}else{_40f(text);}}};});},"dojo/keys":function(){define("dojo/keys",["./_base/kernel","./sniff"],function(dojo,has){return dojo.keys={BACKSPACE:8,TAB:9,CLEAR:12,ENTER:13,SHIFT:16,CTRL:17,ALT:18,META:has("webkit")?91:224,PAUSE:19,CAPS_LOCK:20,ESCAPE:27,SPACE:32,PAGE_UP:33,PAGE_DOWN:34,END:35,HOME:36,LEFT_ARROW:37,UP_ARROW:38,RIGHT_ARROW:39,DOWN_ARROW:40,INSERT:45,DELETE:46,HELP:47,LEFT_WINDOW:91,RIGHT_WINDOW:92,SELECT:93,NUMPAD_0:96,NUMPAD_1:97,NUMPAD_2:98,NUMPAD_3:99,NUMPAD_4:100,NUMPAD_5:101,NUMPAD_6:102,NUMPAD_7:103,NUMPAD_8:104,NUMPAD_9:105,NUMPAD_MULTIPLY:106,NUMPAD_PLUS:107,NUMPAD_ENTER:108,NUMPAD_MINUS:109,NUMPAD_PERIOD:110,NUMPAD_DIVIDE:111,F1:112,F2:113,F3:114,F4:115,F5:116,F6:117,F7:118,F8:119,F9:120,F10:121,F11:122,F12:123,F13:124,F14:125,F15:126,NUM_LOCK:144,SCROLL_LOCK:145,UP_DPAD:175,DOWN_DPAD:176,LEFT_DPAD:177,RIGHT_DPAD:178,copyKey:has("mac")&&!has("air")?(has("safari")?91:224):17};});},"dojo/domReady":function(){define(["./has"],function(has){var _411=this,doc=document,_412={"loaded":1,"complete":1},_413=typeof doc.readyState!="string",_414=!!_412[doc.readyState];if(_413){doc.readyState="loading";}if(!_414){var _415=[],_416=[],_417=function(evt){evt=evt||_411.event;if(_414||(evt.type=="readystatechange"&&!_412[doc.readyState])){return;}_414=1;if(_413){doc.readyState="complete";}while(_415.length){(_415.shift())(doc);}},on=function(node,_418){node.addEventListener(_418,_417,false);_415.push(function(){node.removeEventListener(_418,_417,false);});};if(!has("dom-addeventlistener")){on=function(node,_419){_419="on"+_419;node.attachEvent(_419,_417);_415.push(function(){node.detachEvent(_419,_417);});};var div=doc.createElement("div");try{if(div.doScroll&&_411.frameElement===null){_416.push(function(){try{div.doScroll("left");return 1;}catch(e){}});}}catch(e){}}on(doc,"DOMContentLoaded");on(_411,"load");if("onreadystatechange" in doc){on(doc,"readystatechange");}else{if(!_413){_416.push(function(){return _412[doc.readyState];});}}if(_416.length){var _41a=function(){if(_414){return;}var i=_416.length;while(i--){if(_416[i]()){_417("poller");return;}}setTimeout(_41a,30);};_41a();}}function _41b(_41c){if(_414){_41c(doc);}else{_415.push(_41c);}};_41b.load=function(id,req,load){_41b(load);};return _41b;});},"dojo/_base/lang":function(){define("dojo/_base/lang",["./kernel","../has","../sniff"],function(dojo,has){has.add("bug-for-in-skips-shadowed",function(){for(var i in {toString:1}){return 0;}return 1;});var _41d=has("bug-for-in-skips-shadowed")?"hasOwnProperty.valueOf.isPrototypeOf.propertyIsEnumerable.toLocaleString.toString.constructor".split("."):[],_41e=_41d.length,_41f=function(_420,_421,_422){var p,i=0,_423=dojo.global;if(!_422){if(!_420.length){return _423;}else{p=_420[i++];try{_422=dojo.scopeMap[p]&&dojo.scopeMap[p][1];}catch(e){}_422=_422||(p in _423?_423[p]:(_421?_423[p]={}:undefined));}}while(_422&&(p=_420[i++])){_422=(p in _422?_422[p]:(_421?_422[p]={}:undefined));}return _422;},opts=Object.prototype.toString,_424=function(obj,_425,_426){return (_426||[]).concat(Array.prototype.slice.call(obj,_425||0));},_427=/\{([^\}]+)\}/g;var lang={_extraNames:_41d,_mixin:function(dest,_428,_429){var name,s,i,_42a={};for(name in _428){s=_428[name];if(!(name in dest)||(dest[name]!==s&&(!(name in _42a)||_42a[name]!==s))){dest[name]=_429?_429(s):s;}}if(has("bug-for-in-skips-shadowed")){if(_428){for(i=0;i<_41e;++i){name=_41d[i];s=_428[name];if(!(name in dest)||(dest[name]!==s&&(!(name in _42a)||_42a[name]!==s))){dest[name]=_429?_429(s):s;}}}}return dest;},mixin:function(dest,_42b){if(!dest){dest={};}for(var i=1,l=arguments.length;i<l;i++){lang._mixin(dest,arguments[i]);}return dest;},setObject:function(name,_42c,_42d){var _42e=name.split("."),p=_42e.pop(),obj=_41f(_42e,true,_42d);return obj&&p?(obj[p]=_42c):undefined;},getObject:function(name,_42f,_430){return _41f(name.split("."),_42f,_430);},exists:function(name,obj){return lang.getObject(name,false,obj)!==undefined;},isString:function(it){return (typeof it=="string"||it instanceof String);},isArray:function(it){return it&&(it instanceof Array||typeof it=="array");},isFunction:function(it){return opts.call(it)==="[object Function]";},isObject:function(it){return it!==undefined&&(it===null||typeof it=="object"||lang.isArray(it)||lang.isFunction(it));},isArrayLike:function(it){return it&&it!==undefined&&!lang.isString(it)&&!lang.isFunction(it)&&!(it.tagName&&it.tagName.toLowerCase()=="form")&&(lang.isArray(it)||isFinite(it.length));},isAlien:function(it){return it&&!lang.isFunction(it)&&/\{\s*\[native code\]\s*\}/.test(String(it));},extend:function(ctor,_431){for(var i=1,l=arguments.length;i<l;i++){lang._mixin(ctor.prototype,arguments[i]);}return ctor;},_hitchArgs:function(_432,_433){var pre=lang._toArray(arguments,2);var _434=lang.isString(_433);return function(){var args=lang._toArray(arguments);var f=_434?(_432||dojo.global)[_433]:_433;return f&&f.apply(_432||this,pre.concat(args));};},hitch:function(_435,_436){if(arguments.length>2){return lang._hitchArgs.apply(dojo,arguments);}if(!_436){_436=_435;_435=null;}if(lang.isString(_436)){_435=_435||dojo.global;if(!_435[_436]){throw (["lang.hitch: scope[\"",_436,"\"] is null (scope=\"",_435,"\")"].join(""));}return function(){return _435[_436].apply(_435,arguments||[]);};}return !_435?_436:function(){return _436.apply(_435,arguments||[]);};},delegate:(function(){function TMP(){};return function(obj,_437){TMP.prototype=obj;var tmp=new TMP();TMP.prototype=null;if(_437){lang._mixin(tmp,_437);}return tmp;};})(),_toArray:has("ie")?(function(){function slow(obj,_438,_439){var arr=_439||[];for(var x=_438||0;x<obj.length;x++){arr.push(obj[x]);}return arr;};return function(obj){return ((obj.item)?slow:_424).apply(this,arguments);};})():_424,partial:function(_43a){var arr=[null];return lang.hitch.apply(dojo,arr.concat(lang._toArray(arguments)));},clone:function(src){if(!src||typeof src!="object"||lang.isFunction(src)){return src;}if(src.nodeType&&"cloneNode" in src){return src.cloneNode(true);}if(src instanceof Date){return new Date(src.getTime());}if(src instanceof RegExp){return new RegExp(src);}var r,i,l;if(lang.isArray(src)){r=[];for(i=0,l=src.length;i<l;++i){if(i in src){r.push(lang.clone(src[i]));}}}else{r=src.constructor?new src.constructor():{};}return lang._mixin(r,src,lang.clone);},trim:String.prototype.trim?function(str){return str.trim();}:function(str){return str.replace(/^\s\s*/,"").replace(/\s\s*$/,"");},replace:function(tmpl,map,_43b){return tmpl.replace(_43b||_427,lang.isFunction(map)?map:function(_43c,k){return lang.getObject(k,false,map);});}};1&&lang.mixin(dojo,lang);return lang;});},"dojo/request/util":function(){define("dojo/request/util",["exports","../errors/RequestError","../errors/CancelError","../Deferred","../io-query","../_base/array","../_base/lang"],function(_43d,_43e,_43f,_440,_441,_442,lang){_43d.deepCopy=function deepCopy(_443,_444){for(var name in _444){var tval=_443[name],sval=_444[name];if(tval!==sval){if(tval&&typeof tval==="object"&&sval&&typeof sval==="object"){_43d.deepCopy(tval,sval);}else{_443[name]=sval;}}}return _443;};_43d.deepCreate=function deepCreate(_445,_446){_446=_446||{};var _447=lang.delegate(_445),name,_448;for(name in _445){_448=_445[name];if(_448&&typeof _448==="object"){_447[name]=_43d.deepCreate(_448,_446[name]);}}return _43d.deepCopy(_447,_446);};var _449=Object.freeze||function(obj){return obj;};function _44a(_44b){return _449(_44b);};_43d.deferred=function deferred(_44c,_44d,_44e,_44f,_450,last){var def=new _440(function(_451){_44d&&_44d(def,_44c);if(!_451||!(_451 instanceof _43e)&&!(_451 instanceof _43f)){return new _43f("Request canceled",_44c);}return _451;});def.response=_44c;def.isValid=_44e;def.isReady=_44f;def.handleResponse=_450;function _452(_453){_453.response=_44c;throw _453;};var _454=def.then(_44a).otherwise(_452);if(_43d.notify){_454.then(lang.hitch(_43d.notify,"emit","load"),lang.hitch(_43d.notify,"emit","error"));}var _455=_454.then(function(_456){return _456.data||_456.text;});var _457=_449(lang.delegate(_455,{response:_454}));if(last){def.then(function(_458){last.call(def,_458);},function(_459){last.call(def,_44c,_459);});}def.promise=_457;def.then=_457.then;return def;};_43d.addCommonMethods=function addCommonMethods(_45a,_45b){_442.forEach(_45b||["GET","POST","PUT","DELETE"],function(_45c){_45a[(_45c==="DELETE"?"DEL":_45c).toLowerCase()]=function(url,_45d){_45d=lang.delegate(_45d||{});_45d.method=_45c;return _45a(url,_45d);};});};_43d.parseArgs=function parseArgs(url,_45e,_45f){var data=_45e.data,_460=_45e.query;if(data&&!_45f){if(typeof data==="object"){_45e.data=_441.objectToQuery(data);}}if(_460){if(typeof _460==="object"){_460=_441.objectToQuery(_460);}if(_45e.preventCache){_460+=(_460?"&":"")+"request.preventCache="+(+(new Date));}}else{if(_45e.preventCache){_460="request.preventCache="+(+(new Date));}}if(url&&_460){url+=(~url.indexOf("?")?"&":"?")+_460;}return {url:url,options:_45e,getHeader:function(_461){return null;}};};_43d.checkStatus=function(stat){stat=stat||0;return (stat>=200&&stat<300)||stat===304||stat===1223||!stat;};});},"dojo/Evented":function(){define("dojo/Evented",["./aspect","./on"],function(_462,on){"use strict";var _463=_462.after;function _464(){};_464.prototype={on:function(type,_465){return on.parse(this,type,_465,function(_466,type){return _463(_466,"on"+type,_465,true);});},emit:function(type,_467){var args=[this];args.push.apply(args,arguments);return on.emit.apply(on,args);}};return _464;});},"dojo/mouse":function(){define("dojo/mouse",["./_base/kernel","./on","./has","./dom","./_base/window"],function(dojo,on,has,dom,win){has.add("dom-quirks",win.doc&&win.doc.compatMode=="BackCompat");has.add("events-mouseenter",win.doc&&"onmouseenter" in win.doc.createElement("div"));has.add("events-mousewheel",win.doc&&"onmousewheel" in win.doc);var _468;if(has("dom-quirks")||!has("dom-addeventlistener")){_468={LEFT:1,MIDDLE:4,RIGHT:2,isButton:function(e,_469){return e.button&_469;},isLeft:function(e){return e.button&1;},isMiddle:function(e){return e.button&4;},isRight:function(e){return e.button&2;}};}else{_468={LEFT:0,MIDDLE:1,RIGHT:2,isButton:function(e,_46a){return e.button==_46a;},isLeft:function(e){return e.button==0;},isMiddle:function(e){return e.button==1;},isRight:function(e){return e.button==2;}};}dojo.mouseButtons=_468;function _46b(type,_46c){var _46d=function(node,_46e){return on(node,type,function(evt){if(_46c){return _46c(evt,_46e);}if(!dom.isDescendant(evt.relatedTarget,node)){return _46e.call(this,evt);}});};_46d.bubble=function(_46f){return _46b(type,function(evt,_470){var _471=_46f(evt.target);var _472=evt.relatedTarget;if(_471&&(_471!=(_472&&_472.nodeType==1&&_46f(_472)))){return _470.call(_471,evt);}});};return _46d;};var _473;if(has("events-mousewheel")){_473="mousewheel";}else{_473=function(node,_474){return on(node,"DOMMouseScroll",function(evt){evt.wheelDelta=-evt.detail;_474.call(this,evt);});};}return {_eventHandler:_46b,enter:_46b("mouseover"),leave:_46b("mouseout"),wheel:_473,isLeft:_468.isLeft,isMiddle:_468.isMiddle,isRight:_468.isRight};});},"dojo/_base/xhr":function(){define("dojo/_base/xhr",["./kernel","./sniff","require","../io-query","../dom","../dom-form","./Deferred","./config","./json","./lang","./array","../on","../aspect","../request/watch","../request/xhr","../request/util"],function(dojo,has,_475,ioq,dom,_476,_477,_478,json,lang,_479,on,_47a,_47b,_47c,util){dojo._xhrObj=_47c._create;var cfg=dojo.config;dojo.objectToQuery=ioq.objectToQuery;dojo.queryToObject=ioq.queryToObject;dojo.fieldToObject=_476.fieldToObject;dojo.formToObject=_476.toObject;dojo.formToQuery=_476.toQuery;dojo.formToJson=_476.toJson;dojo._blockAsync=false;var _47d=dojo._contentHandlers=dojo.contentHandlers={"text":function(xhr){return xhr.responseText;},"json":function(xhr){return json.fromJson(xhr.responseText||null);},"json-comment-filtered":function(xhr){if(!_478.useCommentedJson){console.warn("Consider using the standard mimetype:application/json."+" json-commenting can introduce security issues. To"+" decrease the chances of hijacking, use the standard the 'json' handler and"+" prefix your json with: {}&&\n"+"Use djConfig.useCommentedJson=true to turn off this message.");}var _47e=xhr.responseText;var _47f=_47e.indexOf("/*");var _480=_47e.lastIndexOf("*/");if(_47f==-1||_480==-1){throw new Error("JSON was not comment filtered");}return json.fromJson(_47e.substring(_47f+2,_480));},"javascript":function(xhr){return dojo.eval(xhr.responseText);},"xml":function(xhr){var _481=xhr.responseXML;if(has("ie")){if((!_481||!_481.documentElement)){var ms=function(n){return "MSXML"+n+".DOMDocument";};var dp=["Microsoft.XMLDOM",ms(6),ms(4),ms(3),ms(2)];_479.some(dp,function(p){try{var dom=new ActiveXObject(p);dom.async=false;dom.loadXML(xhr.responseText);_481=dom;}catch(e){return false;}return true;});}}return _481;},"json-comment-optional":function(xhr){if(xhr.responseText&&/^[^{\[]*\/\*/.test(xhr.responseText)){return _47d["json-comment-filtered"](xhr);}else{return _47d["json"](xhr);}}};dojo._ioSetArgs=function(args,_482,_483,_484){var _485={args:args,url:args.url};var _486=null;if(args.form){var form=dom.byId(args.form);var _487=form.getAttributeNode("action");_485.url=_485.url||(_487?_487.value:null);_486=_476.toObject(form);}var _488=[{}];if(_486){_488.push(_486);}if(args.content){_488.push(args.content);}if(args.preventCache){_488.push({"dojo.preventCache":new Date().valueOf()});}_485.query=ioq.objectToQuery(lang.mixin.apply(null,_488));_485.handleAs=args.handleAs||"text";var d=new _477(function(dfd){dfd.canceled=true;_482&&_482(dfd);var err=dfd.ioArgs.error;if(!err){err=new Error("request cancelled");err.dojoType="cancel";dfd.ioArgs.error=err;}return err;});d.addCallback(_483);var ld=args.load;if(ld&&lang.isFunction(ld)){d.addCallback(function(_489){return ld.call(args,_489,_485);});}var err=args.error;if(err&&lang.isFunction(err)){d.addErrback(function(_48a){return err.call(args,_48a,_485);});}var _48b=args.handle;if(_48b&&lang.isFunction(_48b)){d.addBoth(function(_48c){return _48b.call(args,_48c,_485);});}d.addErrback(function(_48d){return _484(_48d,d);});if(cfg.ioPublish&&dojo.publish&&_485.args.ioPublish!==false){d.addCallbacks(function(res){dojo.publish("/dojo/io/load",[d,res]);return res;},function(res){dojo.publish("/dojo/io/error",[d,res]);return res;});d.addBoth(function(res){dojo.publish("/dojo/io/done",[d,res]);return res;});}d.ioArgs=_485;return d;};var _48e=function(dfd){var ret=_47d[dfd.ioArgs.handleAs](dfd.ioArgs.xhr);return ret===undefined?null:ret;};var _48f=function(_490,dfd){if(!dfd.ioArgs.args.failOk){console.error(_490);}return _490;};var _491=function(dfd){if(_492<=0){_492=0;if(cfg.ioPublish&&dojo.publish&&(!dfd||dfd&&dfd.ioArgs.args.ioPublish!==false)){dojo.publish("/dojo/io/stop");}}};var _492=0;_47a.after(_47b,"_onAction",function(){_492-=1;});_47a.after(_47b,"_onInFlight",_491);dojo._ioCancelAll=_47b.cancelAll;dojo._ioNotifyStart=function(dfd){if(cfg.ioPublish&&dojo.publish&&dfd.ioArgs.args.ioPublish!==false){if(!_492){dojo.publish("/dojo/io/start");}_492+=1;dojo.publish("/dojo/io/send",[dfd]);}};dojo._ioWatch=function(dfd,_493,_494,_495){var args=dfd.ioArgs.options=dfd.ioArgs.args;lang.mixin(dfd,{response:dfd.ioArgs,isValid:function(_496){return _493(dfd);},isReady:function(_497){return _494(dfd);},handleResponse:function(_498){return _495(dfd);}});_47b(dfd);_491(dfd);};var _499="application/x-www-form-urlencoded";dojo._ioAddQueryToUrl=function(_49a){if(_49a.query.length){_49a.url+=(_49a.url.indexOf("?")==-1?"?":"&")+_49a.query;_49a.query=null;}};dojo.xhr=function(_49b,args,_49c){var rDfd;var dfd=dojo._ioSetArgs(args,function(dfd){rDfd&&rDfd.cancel();},_48e,_48f);var _49d=dfd.ioArgs;if("postData" in args){_49d.query=args.postData;}else{if("putData" in args){_49d.query=args.putData;}else{if("rawBody" in args){_49d.query=args.rawBody;}else{if((arguments.length>2&&!_49c)||"POST|PUT".indexOf(_49b.toUpperCase())===-1){dojo._ioAddQueryToUrl(_49d);}}}}var _49e={method:_49b,handleAs:"text",timeout:args.timeout,withCredentials:args.withCredentials,ioArgs:_49d};if(typeof args.headers!=="undefined"){_49e.headers=args.headers;}if(typeof args.contentType!=="undefined"){if(!_49e.headers){_49e.headers={};}_49e.headers["Content-Type"]=args.contentType;}if(typeof _49d.query!=="undefined"){_49e.data=_49d.query;}if(typeof args.sync!=="undefined"){_49e.sync=args.sync;}dojo._ioNotifyStart(dfd);try{rDfd=_47c(_49d.url,_49e,true);}catch(e){dfd.cancel();return dfd;}dfd.ioArgs.xhr=rDfd.response.xhr;rDfd.then(function(){dfd.resolve(dfd);}).otherwise(function(_49f){_49d.error=_49f;dfd.reject(_49f);});return dfd;};dojo.xhrGet=function(args){return dojo.xhr("GET",args);};dojo.rawXhrPost=dojo.xhrPost=function(args){return dojo.xhr("POST",args,true);};dojo.rawXhrPut=dojo.xhrPut=function(args){return dojo.xhr("PUT",args,true);};dojo.xhrDelete=function(args){return dojo.xhr("DELETE",args);};dojo._isDocumentOk=function(x){return util.checkStatus(x.status);};dojo._getText=function(url){var _4a0;dojo.xhrGet({url:url,sync:true,load:function(text){_4a0=text;}});return _4a0;};lang.mixin(dojo.xhr,{_xhrObj:dojo._xhrObj,fieldToObject:_476.fieldToObject,formToObject:_476.toObject,objectToQuery:ioq.objectToQuery,formToQuery:_476.toQuery,formToJson:_476.toJson,queryToObject:ioq.queryToObject,contentHandlers:_47d,_ioSetArgs:dojo._ioSetArgs,_ioCancelAll:dojo._ioCancelAll,_ioNotifyStart:dojo._ioNotifyStart,_ioWatch:dojo._ioWatch,_ioAddQueryToUrl:dojo._ioAddQueryToUrl,_isDocumentOk:dojo._isDocumentOk,_getText:dojo._getText,get:dojo.xhrGet,post:dojo.xhrPost,put:dojo.xhrPut,del:dojo.xhrDelete});return dojo.xhr;});},"dojo/topic":function(){define("dojo/topic",["./Evented"],function(_4a1){var hub=new _4a1;return {publish:function(_4a2,_4a3){return hub.emit.apply(hub,arguments);},subscribe:function(_4a4,_4a5){return hub.on.apply(hub,arguments);}};});},"dojo/loadInit":function(){define("dojo/loadInit",["./_base/loader"],function(_4a6){return {dynamic:0,normalize:function(id){return id;},load:_4a6.loadInit};});},"dojo/_base/unload":function(){define(["./kernel","./lang","../on"],function(dojo,lang,on){var win=window;var _4a7={addOnWindowUnload:function(obj,_4a8){if(!dojo.windowUnloaded){on(win,"unload",(dojo.windowUnloaded=function(){}));}on(win,"unload",lang.hitch(obj,_4a8));},addOnUnload:function(obj,_4a9){on(win,"beforeunload",lang.hitch(obj,_4a9));}};dojo.addOnWindowUnload=_4a7.addOnWindowUnload;dojo.addOnUnload=_4a7.addOnUnload;return _4a7;});},"dojo/Deferred":function(){define(["./has","./_base/lang","./errors/CancelError","./promise/Promise","./promise/instrumentation"],function(has,lang,_4aa,_4ab,_4ac){"use strict";var _4ad=0,_4ae=1,_4af=2;var _4b0="This deferred has already been fulfilled.";var _4b1=Object.freeze||function(){};var _4b2=function(_4b3,type,_4b4,_4b5,_4b6){if(1){if(type===_4af&&_4b7.instrumentRejected&&_4b3.length===0){_4b7.instrumentRejected(_4b4,false,_4b5,_4b6);}}for(var i=0;i<_4b3.length;i++){_4b8(_4b3[i],type,_4b4,_4b5);}};var _4b8=function(_4b9,type,_4ba,_4bb){var func=_4b9[type];var _4bc=_4b9.deferred;if(func){try{var _4bd=func(_4ba);if(_4bd&&typeof _4bd.then==="function"){_4b9.cancel=_4bd.cancel;_4bd.then(_4be(_4bc,_4ae),_4be(_4bc,_4af),_4be(_4bc,_4ad));return;}_4bf(_4bc,_4ae,_4bd);}catch(error){_4bf(_4bc,_4af,error);}}else{_4bf(_4bc,type,_4ba);}if(1){if(type===_4af&&_4b7.instrumentRejected){_4b7.instrumentRejected(_4ba,!!func,_4bb,_4bc.promise);}}};var _4be=function(_4c0,type){return function(_4c1){_4bf(_4c0,type,_4c1);};};var _4bf=function(_4c2,type,_4c3){if(!_4c2.isCanceled()){switch(type){case _4ad:_4c2.progress(_4c3);break;case _4ae:_4c2.resolve(_4c3);break;case _4af:_4c2.reject(_4c3);break;}}};var _4b7=function(_4c4){var _4c5=this.promise=new _4ab();var _4c6=this;var _4c7,_4c8,_4c9;var _4ca=false;var _4cb=[];if(1&&Error.captureStackTrace){Error.captureStackTrace(_4c6,_4b7);Error.captureStackTrace(_4c5,_4b7);}this.isResolved=_4c5.isResolved=function(){return _4c7===_4ae;};this.isRejected=_4c5.isRejected=function(){return _4c7===_4af;};this.isFulfilled=_4c5.isFulfilled=function(){return !!_4c7;};this.isCanceled=_4c5.isCanceled=function(){return _4ca;};this.progress=function(_4cc,_4cd){if(!_4c7){_4b2(_4cb,_4ad,_4cc,null,_4c6);return _4c5;}else{if(_4cd===true){throw new Error(_4b0);}else{return _4c5;}}};this.resolve=function(_4ce,_4cf){if(!_4c7){_4b2(_4cb,_4c7=_4ae,_4c8=_4ce,null,_4c6);_4cb=null;return _4c5;}else{if(_4cf===true){throw new Error(_4b0);}else{return _4c5;}}};var _4d0=this.reject=function(_4d1,_4d2){if(!_4c7){if(1&&Error.captureStackTrace){Error.captureStackTrace(_4c9={},_4d0);}_4b2(_4cb,_4c7=_4af,_4c8=_4d1,_4c9,_4c6);_4cb=null;return _4c5;}else{if(_4d2===true){throw new Error(_4b0);}else{return _4c5;}}};this.then=_4c5.then=function(_4d3,_4d4,_4d5){var _4d6=[_4d5,_4d3,_4d4];_4d6.cancel=_4c5.cancel;_4d6.deferred=new _4b7(function(_4d7){return _4d6.cancel&&_4d6.cancel(_4d7);});if(_4c7&&!_4cb){_4b8(_4d6,_4c7,_4c8,_4c9);}else{_4cb.push(_4d6);}return _4d6.deferred.promise;};this.cancel=_4c5.cancel=function(_4d8,_4d9){if(!_4c7){if(_4c4){var _4da=_4c4(_4d8);_4d8=typeof _4da==="undefined"?_4d8:_4da;}_4ca=true;if(!_4c7){if(typeof _4d8==="undefined"){_4d8=new _4aa();}_4d0(_4d8);return _4d8;}else{if(_4c7===_4af&&_4c8===_4d8){return _4d8;}}}else{if(_4d9===true){throw new Error(_4b0);}}};_4b1(_4c5);};_4b7.prototype.toString=function(){return "[object Deferred]";};if(_4ac){_4ac(_4b7);}return _4b7;});},"dojo/_base/NodeList":function(){define("dojo/_base/NodeList",["./kernel","../query","./array","./html","../NodeList-dom"],function(dojo,_4db,_4dc){var _4dd=_4db.NodeList,nlp=_4dd.prototype;nlp.connect=_4dd._adaptAsForEach(function(){return dojo.connect.apply(this,arguments);});nlp.coords=_4dd._adaptAsMap(dojo.coords);_4dd.events=["blur","focus","change","click","error","keydown","keypress","keyup","load","mousedown","mouseenter","mouseleave","mousemove","mouseout","mouseover","mouseup","submit"];_4dc.forEach(_4dd.events,function(evt){var _4de="on"+evt;nlp[_4de]=function(a,b){return this.connect(_4de,a,b);};});dojo.NodeList=_4dd;return _4dd;});},"dojo/_base/Color":function(){define(["./kernel","./lang","./array","./config"],function(dojo,lang,_4df,_4e0){var _4e1=dojo.Color=function(_4e2){if(_4e2){this.setColor(_4e2);}};_4e1.named={"black":[0,0,0],"silver":[192,192,192],"gray":[128,128,128],"white":[255,255,255],"maroon":[128,0,0],"red":[255,0,0],"purple":[128,0,128],"fuchsia":[255,0,255],"green":[0,128,0],"lime":[0,255,0],"olive":[128,128,0],"yellow":[255,255,0],"navy":[0,0,128],"blue":[0,0,255],"teal":[0,128,128],"aqua":[0,255,255],"transparent":_4e0.transparentColor||[0,0,0,0]};lang.extend(_4e1,{r:255,g:255,b:255,a:1,_set:function(r,g,b,a){var t=this;t.r=r;t.g=g;t.b=b;t.a=a;},setColor:function(_4e3){if(lang.isString(_4e3)){_4e1.fromString(_4e3,this);}else{if(lang.isArray(_4e3)){_4e1.fromArray(_4e3,this);}else{this._set(_4e3.r,_4e3.g,_4e3.b,_4e3.a);if(!(_4e3 instanceof _4e1)){this.sanitize();}}}return this;},sanitize:function(){return this;},toRgb:function(){var t=this;return [t.r,t.g,t.b];},toRgba:function(){var t=this;return [t.r,t.g,t.b,t.a];},toHex:function(){var arr=_4df.map(["r","g","b"],function(x){var s=this[x].toString(16);return s.length<2?"0"+s:s;},this);return "#"+arr.join("");},toCss:function(_4e4){var t=this,rgb=t.r+", "+t.g+", "+t.b;return (_4e4?"rgba("+rgb+", "+t.a:"rgb("+rgb)+")";},toString:function(){return this.toCss(true);}});_4e1.blendColors=dojo.blendColors=function(_4e5,end,_4e6,obj){var t=obj||new _4e1();_4df.forEach(["r","g","b","a"],function(x){t[x]=_4e5[x]+(end[x]-_4e5[x])*_4e6;if(x!="a"){t[x]=Math.round(t[x]);}});return t.sanitize();};_4e1.fromRgb=dojo.colorFromRgb=function(_4e7,obj){var m=_4e7.toLowerCase().match(/^rgba?\(([\s\.,0-9]+)\)/);return m&&_4e1.fromArray(m[1].split(/\s*,\s*/),obj);};_4e1.fromHex=dojo.colorFromHex=function(_4e8,obj){var t=obj||new _4e1(),bits=(_4e8.length==4)?4:8,mask=(1<<bits)-1;_4e8=Number("0x"+_4e8.substr(1));if(isNaN(_4e8)){return null;}_4df.forEach(["b","g","r"],function(x){var c=_4e8&mask;_4e8>>=bits;t[x]=bits==4?17*c:c;});t.a=1;return t;};_4e1.fromArray=dojo.colorFromArray=function(a,obj){var t=obj||new _4e1();t._set(Number(a[0]),Number(a[1]),Number(a[2]),Number(a[3]));if(isNaN(t.a)){t.a=1;}return t.sanitize();};_4e1.fromString=dojo.colorFromString=function(str,obj){var a=_4e1.named[str];return a&&_4e1.fromArray(a,obj)||_4e1.fromRgb(str,obj)||_4e1.fromHex(str,obj);};return _4e1;});},"dojo/promise/instrumentation":function(){define(["./tracer","../has","../_base/lang","../_base/array"],function(_4e9,has,lang,_4ea){function _4eb(_4ec,_4ed,_4ee){var _4ef="";if(_4ec&&_4ec.stack){_4ef+=_4ec.stack;}if(_4ed&&_4ed.stack){_4ef+="\n    ----------------------------------------\n    rejected"+_4ed.stack.split("\n").slice(1).join("\n").replace(/^\s+/," ");}if(_4ee&&_4ee.stack){_4ef+="\n    ----------------------------------------\n"+_4ee.stack;}console.error(_4ec,_4ef);};function _4f0(_4f1,_4f2,_4f3,_4f4){if(!_4f2){_4eb(_4f1,_4f3,_4f4);}};var _4f5=[];var _4f6=false;var _4f7=1000;function _4f8(_4f9,_4fa,_4fb,_4fc){if(_4fa){_4ea.some(_4f5,function(obj,ix){if(obj.error===_4f9){_4f5.splice(ix,1);return true;}});}else{if(!_4ea.some(_4f5,function(obj){return obj.error===_4f9;})){_4f5.push({error:_4f9,rejection:_4fb,deferred:_4fc,timestamp:new Date().getTime()});}}if(!_4f6){_4f6=setTimeout(_4fd,_4f7);}};function _4fd(){var now=new Date().getTime();var _4fe=now-_4f7;_4f5=_4ea.filter(_4f5,function(obj){if(obj.timestamp<_4fe){_4eb(obj.error,obj.rejection,obj.deferred);return false;}return true;});if(_4f5.length){_4f6=setTimeout(_4fd,_4f5[0].timestamp+_4f7-now);}};return function(_4ff){var _500=has("config-useDeferredInstrumentation");if(_500){_4e9.on("resolved",lang.hitch(console,"log","resolved"));_4e9.on("rejected",lang.hitch(console,"log","rejected"));_4e9.on("progress",lang.hitch(console,"log","progress"));var args=[];if(typeof _500==="string"){args=_500.split(",");_500=args.shift();}if(_500==="report-rejections"){_4ff.instrumentRejected=_4f0;}else{if(_500==="report-unhandled-rejections"||_500===true||_500===1){_4ff.instrumentRejected=_4f8;_4f7=parseInt(args[0],10)||_4f7;}else{throw new Error("Unsupported instrumentation usage <"+_500+">");}}}};});},"dojo/selector/_loader":function(){define(["../has","require"],function(has,_501){"use strict";var _502=document.createElement("div");has.add("dom-qsa2.1",!!_502.querySelectorAll);has.add("dom-qsa3",function(){try{_502.innerHTML="<p class='TEST'></p>";return _502.querySelectorAll(".TEST:empty").length==1;}catch(e){}});var _503;var acme="./acme",lite="./lite";return {load:function(id,_504,_505,_506){var req=_501;id=id=="default"?has("config-selectorEngine")||"css3":id;id=id=="css2"||id=="lite"?lite:id=="css2.1"?has("dom-qsa2.1")?lite:acme:id=="css3"?has("dom-qsa3")?lite:acme:id=="acme"?acme:(req=_504)&&id;if(id.charAt(id.length-1)=="?"){id=id.substring(0,id.length-1);var _507=true;}if(_507&&(has("dom-compliant-qsa")||_503)){return _505(_503);}req([id],function(_508){if(id!="./lite"){_503=_508;}_505(_508);});}};});},"dojo/promise/Promise":function(){define(["../_base/lang"],function(lang){"use strict";function _509(){throw new TypeError("abstract");};return lang.extend(function Promise(){},{then:function(_50a,_50b,_50c){_509();},cancel:function(_50d,_50e){_509();},isResolved:function(){_509();},isRejected:function(){_509();},isFulfilled:function(){_509();},isCanceled:function(){_509();},always:function(_50f){return this.then(_50f,_50f);},otherwise:function(_510){return this.then(null,_510);},trace:function(){return this;},traceRejected:function(){return this;},toString:function(){return "[object Promise]";}});});},"dojo/request/watch":function(){define(["./util","../errors/RequestTimeoutError","../errors/CancelError","../_base/array","../_base/window","../has!host-browser?dom-addeventlistener?:../on:"],function(util,_511,_512,_513,win,on){var _514=null,_515=[];function _516(){var now=+(new Date);for(var i=0,dfd;i<_515.length&&(dfd=_515[i]);i++){var _517=dfd.response,_518=_517.options;if((dfd.isCanceled&&dfd.isCanceled())||(dfd.isValid&&!dfd.isValid(_517))){_515.splice(i--,1);_519._onAction&&_519._onAction();}else{if(dfd.isReady&&dfd.isReady(_517)){_515.splice(i--,1);dfd.handleResponse(_517);_519._onAction&&_519._onAction();}else{if(dfd.startTime){if(dfd.startTime+(_518.timeout||0)<now){_515.splice(i--,1);dfd.cancel(new _511(_517));_519._onAction&&_519._onAction();}}}}}_519._onInFlight&&_519._onInFlight(dfd);if(!_515.length){clearInterval(_514);_514=null;}};function _519(dfd){if(dfd.response.options.timeout){dfd.startTime=+(new Date);}if(dfd.isFulfilled()){return;}_515.push(dfd);if(!_514){_514=setInterval(_516,50);}if(dfd.response.options.sync){_516();}};_519.cancelAll=function cancelAll(){try{_513.forEach(_515,function(dfd){try{dfd.cancel(new _512("All requests canceled."));}catch(e){}});}catch(e){}};if(win&&on&&win.doc.attachEvent){on(win.global,"unload",function(){_519.cancelAll();});}return _519;});},"dojo/on":function(){define(["./has!dom-addeventlistener?:./aspect","./_base/kernel","./has"],function(_51a,dojo,has){"use strict";if(1){var _51b=window.ScriptEngineMajorVersion;has.add("jscript",_51b&&(_51b()+ScriptEngineMinorVersion()/10));has.add("event-orientationchange",has("touch")&&!has("android"));has.add("event-stopimmediatepropagation",window.Event&&!!window.Event.prototype&&!!window.Event.prototype.stopImmediatePropagation);}var on=function(_51c,type,_51d,_51e){if(_51c.on&&typeof type!="function"){return _51c.on(type,_51d);}return on.parse(_51c,type,_51d,_51f,_51e,this);};on.pausable=function(_520,type,_521,_522){var _523;var _524=on(_520,type,function(){if(!_523){return _521.apply(this,arguments);}},_522);_524.pause=function(){_523=true;};_524.resume=function(){_523=false;};return _524;};on.once=function(_525,type,_526,_527){var _528=on(_525,type,function(){_528.remove();return _526.apply(this,arguments);});return _528;};on.parse=function(_529,type,_52a,_52b,_52c,_52d){if(type.call){return type.call(_52d,_529,_52a);}if(type.indexOf(",")>-1){var _52e=type.split(/\s*,\s*/);var _52f=[];var i=0;var _530;while(_530=_52e[i++]){_52f.push(_52b(_529,_530,_52a,_52c,_52d));}_52f.remove=function(){for(var i=0;i<_52f.length;i++){_52f[i].remove();}};return _52f;}return _52b(_529,type,_52a,_52c,_52d);};var _531=/^touch/;function _51f(_532,type,_533,_534,_535){var _536=type.match(/(.*):(.*)/);if(_536){type=_536[2];_536=_536[1];return on.selector(_536,type).call(_535,_532,_533);}if(has("touch")){if(_531.test(type)){_533=_537(_533);}if(!has("event-orientationchange")&&(type=="orientationchange")){type="resize";_532=window;_533=_537(_533);}}if(_538){_533=_538(_533);}if(_532.addEventListener){var _539=type in _53a,_53b=_539?_53a[type]:type;_532.addEventListener(_53b,_533,_539);return {remove:function(){_532.removeEventListener(_53b,_533,_539);}};}type="on"+type;if(_53c&&_532.attachEvent){return _53c(_532,type,_533);}throw new Error("Target must be an event emitter");};on.selector=function(_53d,_53e,_53f){return function(_540,_541){var _542=typeof _53d=="function"?{matches:_53d}:this,_543=_53e.bubble;function _544(_545){_542=_542&&_542.matches?_542:dojo.query;while(!_542.matches(_545,_53d,_540)){if(_545==_540||_53f===false||!(_545=_545.parentNode)||_545.nodeType!=1){return;}}return _545;};if(_543){return on(_540,_543(_544),_541);}return on(_540,_53e,function(_546){var _547=_544(_546.target);return _547&&_541.call(_547,_546);});};};function _548(){this.cancelable=false;};function _549(){this.bubbles=false;};var _54a=[].slice,_54b=on.emit=function(_54c,type,_54d){var args=_54a.call(arguments,2);var _54e="on"+type;if("parentNode" in _54c){var _54f=args[0]={};for(var i in _54d){_54f[i]=_54d[i];}_54f.preventDefault=_548;_54f.stopPropagation=_549;_54f.target=_54c;_54f.type=type;_54d=_54f;}do{_54c[_54e]&&_54c[_54e].apply(_54c,args);}while(_54d&&_54d.bubbles&&(_54c=_54c.parentNode));return _54d&&_54d.cancelable&&_54d;};var _53a={};if(!has("event-stopimmediatepropagation")){var _550=function(){this.immediatelyStopped=true;this.modified=true;};var _538=function(_551){return function(_552){if(!_552.immediatelyStopped){_552.stopImmediatePropagation=_550;return _551.apply(this,arguments);}};};}if(has("dom-addeventlistener")){_53a={focusin:"focus",focusout:"blur"};if(has("opera")){_53a.keydown="keypress";}on.emit=function(_553,type,_554){if(_553.dispatchEvent&&document.createEvent){var _555=_553.ownerDocument.createEvent("HTMLEvents");_555.initEvent(type,!!_554.bubbles,!!_554.cancelable);for(var i in _554){var _556=_554[i];if(!(i in _555)){_555[i]=_554[i];}}return _553.dispatchEvent(_555)&&_555;}return _54b.apply(on,arguments);};}else{on._fixEvent=function(evt,_557){if(!evt){var w=_557&&(_557.ownerDocument||_557.document||_557).parentWindow||window;evt=w.event;}if(!evt){return evt;}if(_558&&evt.type==_558.type){evt=_558;}if(!evt.target){evt.target=evt.srcElement;evt.currentTarget=(_557||evt.srcElement);if(evt.type=="mouseover"){evt.relatedTarget=evt.fromElement;}if(evt.type=="mouseout"){evt.relatedTarget=evt.toElement;}if(!evt.stopPropagation){evt.stopPropagation=_559;evt.preventDefault=_55a;}switch(evt.type){case "keypress":var c=("charCode" in evt?evt.charCode:evt.keyCode);if(c==10){c=0;evt.keyCode=13;}else{if(c==13||c==27){c=0;}else{if(c==3){c=99;}}}evt.charCode=c;_55b(evt);break;}}return evt;};var _558,_55c=function(_55d){this.handle=_55d;};_55c.prototype.remove=function(){delete _dojoIEListeners_[this.handle];};var _55e=function(_55f){return function(evt){evt=on._fixEvent(evt,this);var _560=_55f.call(this,evt);if(evt.modified){if(!_558){setTimeout(function(){_558=null;});}_558=evt;}return _560;};};var _53c=function(_561,type,_562){_562=_55e(_562);if(((_561.ownerDocument?_561.ownerDocument.parentWindow:_561.parentWindow||_561.window||window)!=top||has("jscript")<5.8)&&!has("config-_allow_leaks")){if(typeof _dojoIEListeners_=="undefined"){_dojoIEListeners_=[];}var _563=_561[type];if(!_563||!_563.listeners){var _564=_563;_563=Function("event","var callee = arguments.callee; for(var i = 0; i<callee.listeners.length; i++){var listener = _dojoIEListeners_[callee.listeners[i]]; if(listener){listener.call(this,event);}}");_563.listeners=[];_561[type]=_563;_563.global=this;if(_564){_563.listeners.push(_dojoIEListeners_.push(_564)-1);}}var _565;_563.listeners.push(_565=(_563.global._dojoIEListeners_.push(_562)-1));return new _55c(_565);}return _51a.after(_561,type,_562,true);};var _55b=function(evt){evt.keyChar=evt.charCode?String.fromCharCode(evt.charCode):"";evt.charOrCode=evt.keyChar||evt.keyCode;};var _559=function(){this.cancelBubble=true;};var _55a=on._preventDefault=function(){this.bubbledKeyCode=this.keyCode;if(this.ctrlKey){try{this.keyCode=0;}catch(e){}}this.defaultPrevented=true;this.returnValue=false;};}if(has("touch")){var _566=function(){};var _567=window.orientation;var _537=function(_568){return function(_569){var _56a=_569.corrected;if(!_56a){var type=_569.type;try{delete _569.type;}catch(e){}if(_569.type){_566.prototype=_569;var _56a=new _566;_56a.preventDefault=function(){_569.preventDefault();};_56a.stopPropagation=function(){_569.stopPropagation();};}else{_56a=_569;_56a.type=type;}_569.corrected=_56a;if(type=="resize"){if(_567==window.orientation){return null;}_567=window.orientation;_56a.type="orientationchange";return _568.call(this,_56a);}if(!("rotation" in _56a)){_56a.rotation=0;_56a.scale=1;}var _56b=_56a.changedTouches[0];for(var i in _56b){delete _56a[i];_56a[i]=_56b[i];}}return _568.call(this,_56a);};};}return on;});},"dojo/_base/sniff":function(){define(["./kernel","./lang","../sniff"],function(dojo,lang,has){if(!1){return has;}dojo._name="browser";lang.mixin(dojo,{isBrowser:true,isFF:has("ff"),isIE:has("ie"),isKhtml:has("khtml"),isWebKit:has("webkit"),isMozilla:has("mozilla"),isMoz:has("mozilla"),isOpera:has("opera"),isSafari:has("safari"),isChrome:has("chrome"),isMac:has("mac"),isIos:has("ios"),isAndroid:has("android"),isWii:has("wii"),isQuirks:has("quirks"),isAir:has("air")});dojo.locale=dojo.locale||(has("ie")?navigator.userLanguage:navigator.language).toLowerCase();return has;});},"dojo/errors/create":function(){define(["../_base/lang"],function(lang){return function(name,ctor,base,_56c){base=base||Error;var _56d=function(_56e){if(base===Error){if(Error.captureStackTrace){Error.captureStackTrace(this,_56d);}var err=Error.call(this,_56e),prop;for(prop in err){if(err.hasOwnProperty(prop)){this[prop]=err[prop];}}this.message=_56e;this.stack=err.stack;}else{base.apply(this,arguments);}if(ctor){ctor.apply(this,arguments);}};_56d.prototype=lang.delegate(base.prototype,_56c);_56d.prototype.name=name;_56d.prototype.constructor=_56d;return _56d;};});},"dojo/_base/array":function(){define(["./kernel","../has","./lang"],function(dojo,has,lang){var _56f={},u;function _570(fn){return _56f[fn]=new Function("item","index","array",fn);};function _571(some){var _572=!some;return function(a,fn,o){var i=0,l=a&&a.length||0,_573;if(l&&typeof a=="string"){a=a.split("");}if(typeof fn=="string"){fn=_56f[fn]||_570(fn);}if(o){for(;i<l;++i){_573=!fn.call(o,a[i],i,a);if(some^_573){return !_573;}}}else{for(;i<l;++i){_573=!fn(a[i],i,a);if(some^_573){return !_573;}}}return _572;};};function _574(up){var _575=1,_576=0,_577=0;if(!up){_575=_576=_577=-1;}return function(a,x,from,last){if(last&&_575>0){return _578.lastIndexOf(a,x,from);}var l=a&&a.length||0,end=up?l+_577:_576,i;if(from===u){i=up?_576:l+_577;}else{if(from<0){i=l+from;if(i<0){i=_576;}}else{i=from>=l?l+_577:from;}}if(l&&typeof a=="string"){a=a.split("");}for(;i!=end;i+=_575){if(a[i]==x){return i;}}return -1;};};var _578={every:_571(false),some:_571(true),indexOf:_574(true),lastIndexOf:_574(false),forEach:function(arr,_579,_57a){var i=0,l=arr&&arr.length||0;if(l&&typeof arr=="string"){arr=arr.split("");}if(typeof _579=="string"){_579=_56f[_579]||_570(_579);}if(_57a){for(;i<l;++i){_579.call(_57a,arr[i],i,arr);}}else{for(;i<l;++i){_579(arr[i],i,arr);}}},map:function(arr,_57b,_57c,Ctr){var i=0,l=arr&&arr.length||0,out=new (Ctr||Array)(l);if(l&&typeof arr=="string"){arr=arr.split("");}if(typeof _57b=="string"){_57b=_56f[_57b]||_570(_57b);}if(_57c){for(;i<l;++i){out[i]=_57b.call(_57c,arr[i],i,arr);}}else{for(;i<l;++i){out[i]=_57b(arr[i],i,arr);}}return out;},filter:function(arr,_57d,_57e){var i=0,l=arr&&arr.length||0,out=[],_57f;if(l&&typeof arr=="string"){arr=arr.split("");}if(typeof _57d=="string"){_57d=_56f[_57d]||_570(_57d);}if(_57e){for(;i<l;++i){_57f=arr[i];if(_57d.call(_57e,_57f,i,arr)){out.push(_57f);}}}else{for(;i<l;++i){_57f=arr[i];if(_57d(_57f,i,arr)){out.push(_57f);}}}return out;},clearCache:function(){_56f={};}};1&&lang.mixin(dojo,_578);return _578;});},"dojo/_base/json":function(){define(["./kernel","../json"],function(dojo,json){dojo.fromJson=function(js){return eval("("+js+")");};dojo._escapeString=json.stringify;dojo.toJsonIndentStr="\t";dojo.toJson=function(it,_580){return json.stringify(it,function(key,_581){if(_581){var tf=_581.__json__||_581.json;if(typeof tf=="function"){return tf.call(_581);}}return _581;},_580&&dojo.toJsonIndentStr);};return dojo;});},"dojo/_base/window":function(){define("dojo/_base/window",["./kernel","./lang","../sniff"],function(dojo,lang,has){var ret={global:dojo.global,doc:this["document"]||null,body:function(doc){doc=doc||dojo.doc;return doc.body||doc.getElementsByTagName("body")[0];},setContext:function(_582,_583){dojo.global=ret.global=_582;dojo.doc=ret.doc=_583;},withGlobal:function(_584,_585,_586,_587){var _588=dojo.global;try{dojo.global=ret.global=_584;return ret.withDoc.call(null,_584.document,_585,_586,_587);}finally{dojo.global=ret.global=_588;}},withDoc:function(_589,_58a,_58b,_58c){var _58d=ret.doc,oldQ=has("quirks"),_58e=has("ie"),isIE,mode,pwin;try{dojo.doc=ret.doc=_589;dojo.isQuirks=has.add("quirks",dojo.doc.compatMode=="BackCompat",true,true);if(has("ie")){if((pwin=_589.parentWindow)&&pwin.navigator){isIE=parseFloat(pwin.navigator.appVersion.split("MSIE ")[1])||undefined;mode=_589.documentMode;if(mode&&mode!=5&&Math.floor(isIE)!=mode){isIE=mode;}dojo.isIE=has.add("ie",isIE,true,true);}}if(_58b&&typeof _58a=="string"){_58a=_58b[_58a];}return _58a.apply(_58b,_58c||[]);}finally{dojo.doc=ret.doc=_58d;dojo.isQuirks=has.add("quirks",oldQ,true,true);dojo.isIE=has.add("ie",_58e,true,true);}}};1&&lang.mixin(dojo,ret);return ret;});},"dojo/dom-class":function(){define(["./_base/lang","./_base/array","./dom"],function(lang,_58f,dom){var _590="className";var cls,_591=/\s+/,a1=[""];function _592(s){if(typeof s=="string"||s instanceof String){if(s&&!_591.test(s)){a1[0]=s;return a1;}var a=s.split(_591);if(a.length&&!a[0]){a.shift();}if(a.length&&!a[a.length-1]){a.pop();}return a;}if(!s){return [];}return _58f.filter(s,function(x){return x;});};var _593={};cls={contains:function containsClass(node,_594){return ((" "+dom.byId(node)[_590]+" ").indexOf(" "+_594+" ")>=0);},add:function addClass(node,_595){node=dom.byId(node);_595=_592(_595);var cls=node[_590],_596;cls=cls?" "+cls+" ":" ";_596=cls.length;for(var i=0,len=_595.length,c;i<len;++i){c=_595[i];if(c&&cls.indexOf(" "+c+" ")<0){cls+=c+" ";}}if(_596<cls.length){node[_590]=cls.substr(1,cls.length-2);}},remove:function removeClass(node,_597){node=dom.byId(node);var cls;if(_597!==undefined){_597=_592(_597);cls=" "+node[_590]+" ";for(var i=0,len=_597.length;i<len;++i){cls=cls.replace(" "+_597[i]+" "," ");}cls=lang.trim(cls);}else{cls="";}if(node[_590]!=cls){node[_590]=cls;}},replace:function replaceClass(node,_598,_599){node=dom.byId(node);_593[_590]=node[_590];cls.remove(_593,_599);cls.add(_593,_598);if(node[_590]!==_593[_590]){node[_590]=_593[_590];}},toggle:function toggleClass(node,_59a,_59b){node=dom.byId(node);if(_59b===undefined){_59a=_592(_59a);for(var i=0,len=_59a.length,c;i<len;++i){c=_59a[i];cls[cls.contains(node,c)?"remove":"add"](node,c);}}else{cls[_59b?"add":"remove"](node,_59a);}return _59b;}};return cls;});},"dojo/_base/config":function(){define(["../has","require"],function(has,_59c){var _59d={};if(1){var src=_59c.rawConfig,p;for(p in src){_59d[p]=src[p];}}else{var _59e=function(_59f,_5a0,_5a1){for(p in _59f){p!="has"&&has.add(_5a0+p,_59f[p],0,_5a1);}};_59d=1?_59c.rawConfig:this.dojoConfig||this.djConfig||{};_59e(_59d,"config",1);_59e(_59d.has,"",1);}return _59d;});},"dojo/main":function(){define(["./_base/kernel","./has","require","./sniff","./_base/lang","./_base/array","./_base/config","./ready","./_base/declare","./_base/connect","./_base/Deferred","./_base/json","./_base/Color","./has!dojo-firebug?./_firebug/firebug","./_base/browser","./_base/loader"],function(_5a2,has,_5a3,_5a4,lang,_5a5,_5a6,_5a7){if(_5a6.isDebug){_5a3(["./_firebug/firebug"]);}1||has.add("dojo-config-require",1);if(1){var deps=_5a6.require;if(deps){deps=_5a5.map(lang.isArray(deps)?deps:[deps],function(item){return item.replace(/\./g,"/");});if(_5a2.isAsync){_5a3(deps);}else{_5a7(1,function(){_5a3(deps);});}}}return _5a2;});},"dojo/_base/event":function(){define("dojo/_base/event",["./kernel","../on","../has","../dom-geometry"],function(dojo,on,has,dom){if(on._fixEvent){var _5a8=on._fixEvent;on._fixEvent=function(evt,se){evt=_5a8(evt,se);if(evt){dom.normalizeEvent(evt);}return evt;};}var ret={fix:function(evt,_5a9){if(on._fixEvent){return on._fixEvent(evt,_5a9);}return evt;},stop:function(evt){if(has("dom-addeventlistener")||(evt&&evt.preventDefault)){evt.preventDefault();evt.stopPropagation();}else{evt=evt||window.event;evt.cancelBubble=true;on._preventDefault.call(evt);}}};if(1){dojo.fixEvent=ret.fix;dojo.stopEvent=ret.stop;}return ret;});},"dojo/sniff":function(){define(["./has"],function(has){if(1){var n=navigator,dua=n.userAgent,dav=n.appVersion,tv=parseFloat(dav);has.add("air",dua.indexOf("AdobeAIR")>=0),has.add("khtml",dav.indexOf("Konqueror")>=0?tv:undefined);has.add("webkit",parseFloat(dua.split("WebKit/")[1])||undefined);has.add("chrome",parseFloat(dua.split("Chrome/")[1])||undefined);has.add("safari",dav.indexOf("Safari")>=0&&!has("chrome")?parseFloat(dav.split("Version/")[1]):undefined);has.add("mac",dav.indexOf("Macintosh")>=0);has.add("quirks",document.compatMode=="BackCompat");has.add("ios",/iPhone|iPod|iPad/.test(dua));has.add("android",parseFloat(dua.split("Android ")[1])||undefined);if(!has("webkit")){if(dua.indexOf("Opera")>=0){has.add("opera",tv>=9.8?parseFloat(dua.split("Version/")[1])||tv:tv);}if(dua.indexOf("Gecko")>=0&&!has("khtml")&&!has("webkit")){has.add("mozilla",tv);}if(has("mozilla")){has.add("ff",parseFloat(dua.split("Firefox/")[1]||dua.split("Minefield/")[1])||undefined);}if(document.all&&!has("opera")){var isIE=parseFloat(dav.split("MSIE ")[1])||undefined;var mode=document.documentMode;if(mode&&mode!=5&&Math.floor(isIE)!=mode){isIE=mode;}has.add("ie",isIE);}has.add("wii",typeof opera!="undefined"&&opera.wiiremote);}}return has;});},"dojo/request/handlers":function(){define(["../json","../_base/kernel","../_base/array","../has"],function(JSON,_5aa,_5ab,has){has.add("activex",typeof ActiveXObject!=="undefined");var _5ac;if(has("activex")){var dp=["Msxml2.DOMDocument.6.0","Msxml2.DOMDocument.4.0","MSXML2.DOMDocument.3.0","MSXML.DOMDocument"];_5ac=function(_5ad){var _5ae=_5ad.data;if(!_5ae||!_5ae.documentElement){var text=_5ad.text;_5ab.some(dp,function(p){try{var dom=new ActiveXObject(p);dom.async=false;dom.loadXML(text);_5ae=dom;}catch(e){return false;}return true;});}return _5ae;};}var _5af={"javascript":function(_5b0){return _5aa.eval(_5b0.text||"");},"json":function(_5b1){return JSON.parse(_5b1.text||null);},"xml":_5ac};function _5b2(_5b3){var _5b4=_5af[_5b3.options.handleAs];_5b3.data=_5b4?_5b4(_5b3):(_5b3.data||_5b3.text);return _5b3;};_5b2.register=function(name,_5b5){_5af[name]=_5b5;};return _5b2;});},"dojo/aspect":function(){define("dojo/aspect",[],function(){"use strict";var _5b6,_5b7=0;function _5b8(_5b9,type,_5ba,_5bb){var _5bc=_5b9[type];var _5bd=type=="around";var _5be;if(_5bd){var _5bf=_5ba(function(){return _5bc.advice(this,arguments);});_5be={remove:function(){_5be.cancelled=true;},advice:function(_5c0,args){return _5be.cancelled?_5bc.advice(_5c0,args):_5bf.apply(_5c0,args);}};}else{_5be={remove:function(){var _5c1=_5be.previous;var next=_5be.next;if(!next&&!_5c1){delete _5b9[type];}else{if(_5c1){_5c1.next=next;}else{_5b9[type]=next;}if(next){next.previous=_5c1;}}},id:_5b7++,advice:_5ba,receiveArguments:_5bb};}if(_5bc&&!_5bd){if(type=="after"){var next=_5bc;while(next){_5bc=next;next=next.next;}_5bc.next=_5be;_5be.previous=_5bc;}else{if(type=="before"){_5b9[type]=_5be;_5be.next=_5bc;_5bc.previous=_5be;}}}else{_5b9[type]=_5be;}return _5be;};function _5c2(type){return function(_5c3,_5c4,_5c5,_5c6){var _5c7=_5c3[_5c4],_5c8;if(!_5c7||_5c7.target!=_5c3){_5c3[_5c4]=_5c8=function(){var _5c9=_5b7;var args=arguments;var _5ca=_5c8.before;while(_5ca){args=_5ca.advice.apply(this,args)||args;_5ca=_5ca.next;}if(_5c8.around){var _5cb=_5c8.around.advice(this,args);}var _5cc=_5c8.after;while(_5cc&&_5cc.id<_5c9){if(_5cc.receiveArguments){var _5cd=_5cc.advice.apply(this,args);_5cb=_5cd===_5b6?_5cb:_5cd;}else{_5cb=_5cc.advice.call(this,_5cb,args);}_5cc=_5cc.next;}return _5cb;};if(_5c7){_5c8.around={advice:function(_5ce,args){return _5c7.apply(_5ce,args);}};}_5c8.target=_5c3;}var _5cf=_5b8((_5c8||_5c7),type,_5c5,_5c6);_5c5=null;return _5cf;};};var _5d0=_5c2("after");var _5d1=_5c2("before");var _5d2=_5c2("around");return {before:_5d1,around:_5d2,after:_5d0};});},"dojo/ready":function(){define("dojo/ready",["./_base/kernel","./has","require","./domReady","./_base/lang"],function(dojo,has,_5d3,_5d4,lang){var _5d5=0,_5d6,_5d7=[],_5d8=0,_5d9=function(){_5d5=1;dojo._postLoad=dojo.config.afterOnLoad=true;if(_5d7.length){_5d6(_5da);}},_5da=function(){if(_5d5&&!_5d8&&_5d7.length){_5d8=1;var f=_5d7.shift();try{f();}finally{_5d8=0;}_5d8=0;if(_5d7.length){_5d6(_5da);}}};_5d3.on("idle",_5da);_5d6=function(){if(_5d3.idle()){_5da();}};var _5db=dojo.ready=dojo.addOnLoad=function(_5dc,_5dd,_5de){var _5df=lang._toArray(arguments);if(typeof _5dc!="number"){_5de=_5dd;_5dd=_5dc;_5dc=1000;}else{_5df.shift();}_5de=_5de?lang.hitch.apply(dojo,_5df):function(){_5dd();};_5de.priority=_5dc;for(var i=0;i<_5d7.length&&_5dc>=_5d7[i].priority;i++){}_5d7.splice(i,0,_5de);_5d6();};1||has.add("dojo-config-addOnLoad",1);if(1){var dca=dojo.config.addOnLoad;if(dca){_5db[(lang.isArray(dca)?"apply":"call")](dojo,dca);}}if(1&&dojo.config.parseOnLoad&&!dojo.isAsync){_5db(99,function(){if(!dojo.parser){dojo.deprecated("Add explicit require(['dojo/parser']);","","2.0");_5d3(["dojo/parser"]);}});}if(1){_5d4(_5d9);}else{_5d9();}return _5db;});},"dojo/_base/connect":function(){define(["./kernel","../on","../topic","../aspect","./event","../mouse","./sniff","./lang","../keys"],function(dojo,on,hub,_5e0,_5e1,_5e2,has,lang){has.add("events-keypress-typed",function(){var _5e3={charCode:0};try{_5e3=document.createEvent("KeyboardEvent");(_5e3.initKeyboardEvent||_5e3.initKeyEvent).call(_5e3,"keypress",true,true,null,false,false,false,false,9,3);}catch(e){}return _5e3.charCode==0&&!has("opera");});function _5e4(obj,_5e5,_5e6,_5e7,_5e8){_5e7=lang.hitch(_5e6,_5e7);if(!obj||!(obj.addEventListener||obj.attachEvent)){return _5e0.after(obj||dojo.global,_5e5,_5e7,true);}if(typeof _5e5=="string"&&_5e5.substring(0,2)=="on"){_5e5=_5e5.substring(2);}if(!obj){obj=dojo.global;}if(!_5e8){switch(_5e5){case "keypress":_5e5=_5e9;break;case "mouseenter":_5e5=_5e2.enter;break;case "mouseleave":_5e5=_5e2.leave;break;}}return on(obj,_5e5,_5e7,_5e8);};var _5ea={106:42,111:47,186:59,187:43,188:44,189:45,190:46,191:47,192:96,219:91,220:92,221:93,222:39,229:113};var _5eb=has("mac")?"metaKey":"ctrlKey";var _5ec=function(evt,_5ed){var faux=lang.mixin({},evt,_5ed);_5ee(faux);faux.preventDefault=function(){evt.preventDefault();};faux.stopPropagation=function(){evt.stopPropagation();};return faux;};function _5ee(evt){evt.keyChar=evt.charCode?String.fromCharCode(evt.charCode):"";evt.charOrCode=evt.keyChar||evt.keyCode;};var _5e9;if(has("events-keypress-typed")){var _5ef=function(e,code){try{return (e.keyCode=code);}catch(e){return 0;}};_5e9=function(_5f0,_5f1){var _5f2=on(_5f0,"keydown",function(evt){var k=evt.keyCode;var _5f3=(k!=13)&&k!=32&&(k!=27||!has("ie"))&&(k<48||k>90)&&(k<96||k>111)&&(k<186||k>192)&&(k<219||k>222)&&k!=229;if(_5f3||evt.ctrlKey){var c=_5f3?0:k;if(evt.ctrlKey){if(k==3||k==13){return _5f1.call(evt.currentTarget,evt);}else{if(c>95&&c<106){c-=48;}else{if((!evt.shiftKey)&&(c>=65&&c<=90)){c+=32;}else{c=_5ea[c]||c;}}}}var faux=_5ec(evt,{type:"keypress",faux:true,charCode:c});_5f1.call(evt.currentTarget,faux);if(has("ie")){_5ef(evt,faux.keyCode);}}});var _5f4=on(_5f0,"keypress",function(evt){var c=evt.charCode;c=c>=32?c:0;evt=_5ec(evt,{charCode:c,faux:true});return _5f1.call(this,evt);});return {remove:function(){_5f2.remove();_5f4.remove();}};};}else{if(has("opera")){_5e9=function(_5f5,_5f6){return on(_5f5,"keypress",function(evt){var c=evt.which;if(c==3){c=99;}c=c<32&&!evt.shiftKey?0:c;if(evt.ctrlKey&&!evt.shiftKey&&c>=65&&c<=90){c+=32;}return _5f6.call(this,_5ec(evt,{charCode:c}));});};}else{_5e9=function(_5f7,_5f8){return on(_5f7,"keypress",function(evt){_5ee(evt);return _5f8.call(this,evt);});};}}var _5f9={_keypress:_5e9,connect:function(obj,_5fa,_5fb,_5fc,_5fd){var a=arguments,args=[],i=0;args.push(typeof a[0]=="string"?null:a[i++],a[i++]);var a1=a[i+1];args.push(typeof a1=="string"||typeof a1=="function"?a[i++]:null,a[i++]);for(var l=a.length;i<l;i++){args.push(a[i]);}return _5e4.apply(this,args);},disconnect:function(_5fe){if(_5fe){_5fe.remove();}},subscribe:function(_5ff,_600,_601){return hub.subscribe(_5ff,lang.hitch(_600,_601));},publish:function(_602,args){return hub.publish.apply(hub,[_602].concat(args));},connectPublisher:function(_603,obj,_604){var pf=function(){_5f9.publish(_603,arguments);};return _604?_5f9.connect(obj,_604,pf):_5f9.connect(obj,pf);},isCopyKey:function(e){return e[_5eb];}};_5f9.unsubscribe=_5f9.disconnect;1&&lang.mixin(dojo,_5f9);return _5f9;});},"dojo/errors/CancelError":function(){define(["./create"],function(_605){return _605("CancelError",null,null,{dojoType:"cancel"});});}}});(function(){var _606=this.require;_606({cache:{}});!_606.async&&_606(["dojo"]);_606.boot&&_606.apply(null,_606.boot);})();
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/full-json.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,38 @@
+/* Saves the Full JSON at each modification */
+
+
+Rkns.jsonIO = function(_renkan, _opts) {
+    var _proj = _renkan.project;
+    if (typeof _opts.http_method == "undefined") {
+        _opts.http_method = 'PUT';
+    }
+    var _load = function() {
+        Rkns.$.getJSON(_opts.url, function(_data) {
+            _proj.set(_data);
+            _renkan.renderer.autoScale();
+        });
+    }
+    var _save = function() {
+        var _data = _proj.toJSON();
+        Rkns.$.ajax({
+            type: _opts.http_method,
+            url: _opts.url,
+            contentType: "application/json",
+            data: JSON.stringify(_data),
+            success: function(data, textStatus, jqXHR) {
+            }
+        });
+        
+    }
+    var _thrSave = Rkns._.throttle(
+        function() {
+            setTimeout(_save, 100)
+        }, 1000);
+    _load();
+    _proj.on("add:nodes add:edges add:users", function(_model) {
+        _model.on("change remove", function(_model) {
+            _thrSave();
+        });
+        _thrSave();
+    });
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/i18n.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,58 @@
+Rkns.i18n = {
+    en: {
+        edit_node: "Edit Node",
+        edit_edge: "Edit Edge",
+        edit_title: "Title:",
+        edit_uri: "URI:",
+        edit_description: "Description:",
+        edit_from: "From:",
+        edit_to: "To:",
+        edit_image: "Image:",
+        full_screen: "Full Screen",
+        add_node: "Add Node",
+        add_edge: "Add Edge",
+        created_by: "Created by:",
+        zoom_in: "Zoom In",
+        zoom_out: "Zoom Out",
+        caption_edit: "Edit",
+        caption_remove: "Remove",
+        caption_link: "Link to another node",
+        notif_add_node: "Click on the background canvas to add a node",
+        notif_start_edge: "Click on a first node to start the edge",
+        notif_end_edge: "Click on a second node to complete the edge",
+        search_on_twitter: "Twitter",
+        wiki_fr: "French Wikipedia",
+        wiki_en: "English Wikipedia",
+        wiki_ja: "Japanese Wikipedia",
+        wiki_: "Wikipedia (Other Language)",
+        untitled_project: "Untitled project"
+    },
+    fr: {
+        edit_node: "Édition d’un nœud",
+        edit_edge: "Édition d’un lien",
+        edit_title: "Titre :",
+        edit_uri: "URI :",
+        edit_description: "Description :",
+        edit_from: "De :",
+        edit_to: "Vers :",
+        edit_image: "Image :",
+        full_screen: "Mode plein écran",
+        add_node: "Ajouter un nœud",
+        add_edge: "Ajouter un lien",
+        created_by: "Créé par :",
+        zoom_in: "Agrandir l’échelle",
+        zoom_out: "Rapetisser l’échelle",
+        caption_edit: "Éditer",
+        caption_remove: "Supprimer",
+        caption_link: "Créer un lien",
+        notif_add_node: "Cliquer sur le fond du graphe pour rajouter un nœud",
+        notif_start_edge: "Cliquer sur un premier nœud pour commencer le lien",
+        notif_end_edge: "Cliquer sur un second nœud pour terminer le lien",
+        search_on_twitter: "Twitter",
+        wiki_fr: "Wikipedia en Français",
+        wiki_en: "Wikipedia en Anglais",
+        wiki_ja: "Wikipedia en Japonais",
+        wiki_: "Wikipedia (Autre langue)",
+        untitled_project: "Projet sans titre"
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/ldtjson-bin.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,87 @@
+Rkns.Ldt = {}
+
+Rkns.Ldt.ProjectBin = Rkns.Utils.inherit(Rkns._BaseBin);
+
+Rkns.Ldt.ProjectBin.prototype.tagTemplate = Rkns._.template(
+    '<li class="Rk-Bin-Item" data-image="<%=static_url%>img/ldt-tag.png" data-uri="<%=ldt_platform%>ldtplatform/ldt/front/search/?search=<%=encodedtitle%>&field=all" data-title="<%-title%>" data-description="Tag \'<%-title%>\'">'
+    + '<img class="Rk-Ldt-Tag-Icon" src="<%=static_url%>img/ldt-tag.png" /><h4><%-title%></h4><div class="Rk-Clear"></div></li>'
+);
+
+Rkns.Ldt.ProjectBin.prototype.annotationTemplate = Rkns._.template(
+    '<li class="Rk-Bin-Item" data-image="<%=image%>" data-uri="<%=ldt_platform%>ldtplatform/ldt/front/player/<%=mediaid%>/#id=<%=annotationid%>" data-title="<%-title%>" data-description="<%-description%>">'
+    + '<img class="Rk-Ldt-Annotation-Icon" src="<%=image%>"/><h4><%-title%></h4><p><%-description%></p><p>Start: <%=start%>, End: <%=end%>, Duration: <%=duration%></p><div class="Rk-Clear"></div></li>'
+);
+
+Rkns.Ldt.ProjectBin.prototype._init = function(_renkan, _opts) {
+    this.proj_id = _opts.project_id;
+    this.ldt_platform = _opts.ldt_platform || "http://ldt.iri.centrepompidou.fr/";
+    this.title_$.html(_opts.title);
+    this.refresh();
+}
+
+Rkns.Ldt.ProjectBin.prototype.refresh = function() {
+    var _this = this;
+    function convertTC(_ms) {
+        function pad(_n) {
+            var _res = _n.toString();
+            while (_res.length < 2) {
+                _res = '0' + _res;
+            }
+            return _res;
+        }
+        var _totalSeconds = Math.abs(Math.floor(_ms/1000)),
+            _hours = Math.floor(_totalSeconds / 3600),
+            _minutes = (Math.floor(_totalSeconds / 60) % 60),
+            _seconds = _totalSeconds % 60,
+            _res = '';
+        if (_hours) {
+            _res += pad(_hours) + ':'
+        }
+        _res += pad(_minutes) + ':' + pad(_seconds);
+        return _res;
+    }
+    Rkns.$.ajax({
+        url: this.ldt_platform + 'ldtplatform/ldt/cljson/id/' + this.proj_id,
+        dataType: "jsonp",
+        success: function(_data) {
+            var _html = '<li><h3>Tags</h3></li>',
+                _projtitle = _data.meta["dc:title"];
+            _this.title_$.html('LDT Project: "' + _projtitle + '"');
+            _html += Rkns._(_data.tags).map(function(_tag) {
+                var _title = _tag.meta["dc:title"]
+                return _this.tagTemplate({
+                    ldt_platform: _this.ldt_platform,
+                    title: _title,
+                    encodedtitle : encodeURIComponent(_title),
+                    static_url: _this.renkan.static_url
+                })
+            }).join("");
+            _html += '<li><h3>Annotations</h3></li>';
+            _html += Rkns._(_data.annotations).map(function(_annotation) {
+                var _description = _annotation.content.description,
+                    _title = _annotation.content.title.replace(_description,""),
+                    _duration = _annotation.end - _annotation.begin,
+                    _img = (
+                        (_annotation.content && _annotation.content.img && _annotation.content.img.src)
+                        ? _annotation.content.img.src
+                        : _this.renkan.static_url + ( _duration ? "img/ldt-segment.png" : "img/ldt-point.png" )
+                    );
+                return _this.annotationTemplate({
+                    ldt_platform: _this.ldt_platform,
+                    title: _title,
+                    description: _description,
+                    start: convertTC(_annotation.begin),
+                    end: convertTC(_annotation.end),
+                    duration: convertTC(_duration),
+                    mediaid: _annotation.media,
+                    annotationid: _annotation.id,
+                    image: _img,
+                    static_url: _this.renkan.static_url
+                });
+            }).join("");
+            
+            _this.main_$.html(_html);
+            _renkan.resizeBins();
+        }
+    });
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/main.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,258 @@
+/* 
+ *  Copyright 2012 Institut de recherche et d'innovation 
+ *  contributor(s) : Yves-Marie Haussonne, Raphael Velt, Samuel Huron
+ *   
+ *  contact@iri.centrepompidou.fr
+ *  http://www.iri.centrepompidou.fr 
+ *   
+ *  This software is a computer program whose purpose is to show and add annotations on a video .
+ *  This software is governed by the CeCILL-C license under French law and
+ *  abiding by the rules of distribution of free software. You can  use, 
+ *  modify and/ or redistribute the software under the terms of the CeCILL-C
+ *  license as circulated by CEA, CNRS and INRIA at the following URL
+ *  "http://www.cecill.info". 
+ *  
+ *  The fact that you are presently reading this means that you have had
+ *  knowledge of the CeCILL-C license and that you accept its terms.
+*/
+
+/* Declaring the Renkan Namespace Rkns and Default values */
+
+if (typeof Rkns !== "object") {
+    Rkns = {}
+}
+
+Rkns.$ = jQuery;
+
+Rkns._ = _;
+
+Rkns._BaseBin = function(_renkan, _opts) {
+    if (typeof _renkan !== "undefined") {
+        this.renkan = _renkan;
+        this.renkan.$.find(".Rk-Bin-Main").hide();
+        this.$ = Rkns.$('<li>')
+            .addClass("Rk-Bin")
+            .appendTo(_renkan.$.find(".Rk-Bin-List"));
+        this.title_icon_$ = Rkns.$('<span>')
+            .addClass("Rk-Bin-Title-Icon")
+            .appendTo(this.$);
+            
+        var _this = this;
+        
+        Rkns.$('<a>')
+            .attr("href","#")
+            .addClass("Rk-Bin-Close")
+            .html('&times;')
+            .appendTo(this.$)
+            .click(function() {
+                _this.destroy();
+                return false;
+            });
+        Rkns.$('<a>')
+            .attr("href","#")
+            .addClass("Rk-Bin-Refresh")
+            .appendTo(this.$)
+            .click(function() {
+                _this.refresh();
+                return false;
+            });
+        this.title_$ = Rkns.$('<h2>')
+            .addClass("Rk-Bin-Title")
+            .appendTo(this.$);
+        this.main_$ = Rkns.$('<div>')
+            .addClass("Rk-Bin-Main")
+            .appendTo(this.$);
+        this.title_$.html(_opts.title || '(new bin)');
+        this.renkan.resizeBins();
+        
+        if (_opts.auto_refresh) {
+            window.setInterval(function() {
+                _this.refresh();
+            },_opts.auto_refresh)
+        }
+    }
+}
+
+Rkns._BaseBin.prototype.destroy = function() {
+    this.$.detach();
+    this.renkan.resizeBins();
+}
+
+/* Point of entry */
+
+Rkns.Renkan = function(_opts) {
+    if (typeof _opts.language !== "string" || typeof Rkns.i18n[_opts.language] == "undefined") {
+        _opts.language = "en";
+    }
+    if (typeof _opts.container !== "string") {
+        _opts.container = "renkan";
+    }
+    if (typeof _opts.search !== "object" || !_opts.search) {
+        _opts.search = [];
+    }
+    if (typeof _opts.static_url !== "string") {
+        _opts.static_url = "";
+    }
+    this.project = new Rkns.Models.Project();
+    this.language = _opts.language;
+    this.static_url = _opts.static_url;
+    this.l10n = Rkns.i18n[_opts.language];
+    if (typeof _opts.user_id !== "undefined") {
+        this.current_user = _opts.user_id;
+    }
+    this.$ = Rkns.$("#" + _opts.container);
+    this.$
+        .addClass("Rk-Main")
+        .html(this.template());
+    this.renderer = new Rkns.Renderer.Scene(this);
+    this.tabs = [];
+    this.search_engines = [];
+    this.selected_bin_item = undefined;
+    var _this = this;
+    this.$.mouseup(function() {
+        _this.selected_bin_item = undefined;
+        _this.$.find(".Rk-Bin-Item.dragging").removeClass("dragging");
+    });
+    if (!_opts.search.length) {
+        this.$.find(".Rk-Search-Form").detach();
+    } else {
+        var _tmpl = Rkns._.template('<li class="<%= className %>" data-key="<%= key %>"><%= title %></li>'),
+            _select = this.$.find(".Rk-Search-List"),
+            _input = this.$.find(".Rk-Search-Input"),
+            _form = this.$.find(".Rk-Search-Form");
+        Rkns._(_opts.search).each(function(_search, _key) {
+            var _searchObj = new _search.type(_this, _search);
+            _this.search_engines.push(_searchObj);
+        });
+        _select.html(
+            Rkns._(this.search_engines).map(function(_search, _key) {
+                return _tmpl({
+                    key: _key,
+                    title: _search.getSearchTitle(),
+                    className: _search.getBgClass()
+                });
+            }).join("")
+        );
+        _select.find("li").click(function() {
+            var _el = Rkns.$(this);
+            _this.setSearchEngine(_el.attr("data-key"));
+            _form.submit();
+        });
+        _form.submit(function() {
+            if (_input.val()) {
+                var _search = _this.search_engine;
+                _search.search(_input.val());
+            }
+            return false;
+        });
+        this.$.find(".Rk-Search-Current").mouseenter(
+            function() { _select.slideDown(); }
+        );
+        this.$.find(".Rk-Search-Select").mouseleave(
+            function() { _select.slideUp(); }
+        );
+        this.setSearchEngine(0);
+    }
+    Rkns._(_opts.bins).each(function(_bin) {
+        _this.tabs.push(new _bin.bin(_this, _bin));
+    });
+    
+    this.$.find(".Rk-Bins")
+        .on("click",".Rk-Bin-Title,.Rk-Bin-Title-Icon", function() {
+            var _mainDiv = Rkns.$(this).siblings(".Rk-Bin-Main");
+            if (_mainDiv.is(":hidden")) {
+                _this.$.find(".Rk-Bin-Main").slideUp();
+                _mainDiv.slideDown();
+            }
+        }).on("mousedown", ".Rk-Bin-Item", function() {
+            var _t = Rkns.$(this);
+            _t.addClass("dragging");
+            _this.selected_bin_item = {
+                uri : $(_t).attr("data-uri"),
+                title : $(_t).attr("data-title"),
+                description : $(_t).attr("data-description"),
+                image: $(_t).attr("data-image")
+            }
+            return false;
+        }).on("mouseover", ".Rk-Bin-Item", function(_e) {
+            var _t = Rkns.$(this);
+            if (_t && $(_t).attr("data-uri")) {
+                var _models = _this.project.get("nodes").where({
+                    uri: $(_t).attr("data-uri")
+                });
+                Rkns._(_models).each(function(_model) {
+                    _this.renderer.highlightModel(_model);
+                });
+            }
+        }).mouseout(function() {
+            _this.renderer.unhighlightAll();
+        });
+    Rkns.$(window).resize(function() {
+        _this.resizeBins();
+    });
+}
+
+Rkns.Renkan.prototype.template = Rkns._.template(
+    '<div class="Rk-Title"><h1>Hyper Plateau</h1></div><div class="Rk-Bins">'
+    + '<form class="Rk-Search-Form"><input class="Rk-Search-Input" type="text" placeholder="Search" />'
+    + '<div class="Rk-Search-Select"><div class="Rk-Search-Current"></div><ul class="Rk-Search-List"></ul></div>'
+    + '<input type="submit" value="" class="Rk-Search-Submit" /></form>'
+    + '<ul class="Rk-Bin-List"></ul></div><div class="Rk-Render Rk-Render-Panel"></div>'
+);
+
+
+Rkns.Renkan.prototype.setSearchEngine = function(_key) {
+    this.search_engine = this.search_engines[_key];
+    this.$.find(".Rk-Search-Current").attr("class","Rk-Search-Current " + this.search_engine.getBgClass());
+}
+
+Rkns.Renkan.prototype.resizeBins = function() {
+    var _d = + this.$.find(".Rk-Search-Form").outerHeight();
+    this.$.find(".Rk-Bin-Title").each(function() {
+        _d += Rkns.$(this).outerHeight();
+    });
+    this.$.find(".Rk-Bin-Main").css({
+        height: this.$.find(".Rk-Bins").height() - _d
+    });
+}
+
+/* Utility functions */
+
+Rkns.Utils = {
+    _ID_AUTO_INCREMENT : 0,
+    _ID_BASE : (function(_d) {
+        function pad(n){return n<10 ? '0'+n : n}
+        function fillrand(n) {
+            var _res = ''
+            for (var i=0; i<n; i++) {
+                _res += Math.floor(16*Math.random()).toString(16);
+            }
+            return _res;
+        }
+        return _d.getUTCFullYear() + '-'  
+            + pad(_d.getUTCMonth()+1) + '-'  
+            + pad(_d.getUTCDate()) + '-'
+            + fillrand(16);
+    })(new Date()),
+    getUID : function(_base) {
+        var _n = (++this._ID_AUTO_INCREMENT).toString(16),
+            _base = (typeof _base === "undefined" ? "" : _base + "-" );
+        while (_n.length < 4) {
+            _n = '0' + _n
+        }
+        return _base + this._ID_BASE + '-' + _n;
+    },
+    inherit : function(_baseClass, _callbefore) {
+        var _class = function() {
+            if (typeof _callbefore === "function") {
+                _callbefore.apply(this, Array.prototype.slice.call(arguments, 0));
+            }
+            _baseClass.apply(this, Array.prototype.slice.call(arguments, 0));
+            if (typeof this._init == "function") {
+                this._init.apply(this, Array.prototype.slice.call(arguments, 0));
+            }
+        }
+        _class.prototype = new _baseClass();
+        return _class;
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/main_coweb.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,24 @@
+//
+// Cooperative web application template.
+//
+// Copyright (c) The Dojo Foundation 2011. All Rights Reserved.
+//
+
+// assumes admin servlet deployed with the application 
+var cowebConfig = {
+    adminUrl : './admin'
+};
+
+//require(['corenkan']);
+
+require({moduleUrl : 'lib'},
+        ['coweb/main','dojo', 'corenkan'],
+function(coweb, dojo, corenkan) {
+    // do application setup here
+    
+	dojo.ready(function() {
+        //this.collab = corenkan.app.collab;
+    });
+    
+});
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/main_test_models.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,306 @@
+(function() {
+	
+	var root = this;
+		
+	var Backbone = root.Backbone;
+	
+	var Rkns = root.Rkns = {};
+
+	root.ModelView = Backbone.View.extend({
+		
+		events : {
+			"click .show_form" : "show_form",
+			"click .remove_button" : "remove_click",
+		},
+		
+		initialize: function(options) {
+			_.bindAll(this);
+			this.template = _.template(options.template);
+			this.model.bind("change", this.render);
+			this.form_view = options.form_view;
+			this.form_el = options.form_el;
+			if(typeof options.getJSON === "function") {
+				this.getJSON = options.getJSON;
+			}
+		},
+		render: function() {
+			$(this.el).html(this.template(this.getJSON()));
+			return this;
+		},
+		show_form: function(evt) {
+			if(typeof this.form_view !== "undefined") {
+				this.form_view.render();
+				$(this.form_el).empty();
+				$(this.form_el).append(this.form_view.el);
+			}
+		},
+		getJSON : function() {
+			return this.model.toJSON();			
+		},
+		remove_click : function(evt) {
+			var obj_id = $(evt.currentTarget).attr("value");
+			if(typeof this.model.collection !== "undefined") {
+				this.model.collection.remove(this.model);
+			}
+		},
+
+	});
+	
+	root.ColView = Backbone.View.extend({
+		initialize: function(options) {
+			
+			_.bindAll(this);
+			this.element = options.element;
+			this.element_form = options.element_form;
+			this.element_form_el = options.element_form_el;
+			this.rendered = false;
+			
+			var that = this;
+			this.element_views = [];
+			
+			var that = this;
+			this.collection.each(function(elt) { 
+				that.add(elt); 
+			});
+			
+			this.collection.bind('add', this.add);
+			this.collection.bind('remove', this.remove);
+		},
+		
+		render : function() {
+			this.rendered = true;
+			var that = this;
+			this.$el.empty();
+			_(this.element_views).each(function(dvs){
+				that.$el.append(dvs.disp.render().el);				
+			});
+			
+			return this;
+		},
+		
+		add : function(elt) {
+			
+			var fv_args = _.extend({}, this.element_form, {model: elt});			
+			var fv = new FormView(fv_args);
+			
+			var dv_args = _.extend({}, this.element, {model: elt, tagName: 'li', form_view: fv, form_el: this.element_form_el});			
+			var dv = new ModelView(dv_args);
+			
+			this.element_views.push({disp:dv, form:fv});
+			
+			if(this.rendered) {
+				this.$el.append(dv.render().el);
+			}
+		},
+			
+		
+		remove : function(elt) {
+			var viewsToRemove = _(this.element_views).select(function(cvs) { return cvs.disp.model === elt; })[0];
+			this.element_views = _(this.element_views).without(viewsToRemove);
+			
+			if(this.rendered) {
+				viewsToRemove.disp.$el.remove();
+				viewsToRemove.form.$el.remove();
+			}
+		},
+		
+		remove_click : function(evt) {
+			var obj_id = $(evt.currentTarget).attr("value");
+			this.collection.remove(this.collection.get(obj_id));
+		}
+		
+	});
+	
+	root.FormView = Backbone.View.extend({
+		events : {
+			"change .form_field": "changed"
+		},
+		initialize: function(options) {
+			_.bindAll(this);
+			this.template = _.template(options.template);
+			this.model.bind("change", this.render);
+			if(typeof options.getJSON === "function") {
+				this.getJSON = options.getJSON;
+			}
+		},
+		render: function() {
+			this.$el.html(this.template(this.getJSON()));
+			return this;
+		},
+		changed: function(evt) {
+			var value = $(evt.currentTarget).val();
+			var field_name = $(evt.currentTarget).attr("name");
+			if(this.model.get(field_name) != value) {
+				this.model.set(field_name, value);
+			}
+		},
+		getJSON : function() {
+			return this.model.toJSON(); 
+		}
+	});
+	
+	
+	root.SelectCurrentUserView = Backbone.View.extend({
+		initialize: function(options) {
+			_.bindAll(this);
+			this.rendered = false;
+			
+			this.child_view_constructor = options.child_view_constructor;
+			this.child_tag_name = options.child_tag_name;
+			
+			this.children_views = [];
+			this.collection.each(this.add);
+			
+			this.collection.bind('add', this.add);
+			this.collection.bind('remove', this.remove);
+		},
+		add: function(elt) {
+			var child_view = new this.child_view_constructor({
+				model: elt,
+				tagName : this.child_tag_name
+			});
+			this.children_views.push(child_view);
+			
+			if (this.rendered) {
+				this.$el.append(child_view.render().el);
+			}
+		},
+		remove: function(elt) {
+			var view_to_remove = _(this.children_views).select(function(cv) { return cv.model === elt; })[0];
+			this.children_views = _(this.children_views).without(view_to_remove);
+			if (this.rendered) {
+				view_to_remove.$el.remove();
+			}
+		},
+		render: function() {
+			this.rendered = true;
+			var that = this;
+			
+			this.$el.empty().html("<option value=\"\">Unknown</option>");
+			
+			_(this.children_views).each(function(cv){
+				that.$el.append(cv.render().el);
+			});
+			
+			return this;
+		}
+		
+	});
+	
+	root.SelectUserView = Backbone.View.extend({
+		initialize: function(options) {
+			_.bindAll(this);
+			this.model.bind("change", this.render);
+		},		
+		render: function() {
+			this.$el.val(this.model.id).text(this.model.get("title"));
+			return this;
+		}
+	});
+	
+	root.CurrentUserView = Backbone.View.extend({
+		initialize : function() {
+			this._select_view = new SelectCurrentUserView({
+				el : this.el,
+				collection : this.model.get("users"),
+				child_view_constructor: SelectUserView,
+				child_tag_name: "option",
+			});
+		},
+		render: function() {
+			this.$el.empty();
+			this._select_view.render();
+			return this;
+		}
+		
+	});
+	
+	
+	root.BasicListView = Backbone.View.extend({
+		
+		initialize: function(options) {
+			_.bindAll(this);
+			
+			this.element_view_constructor = options.element_view_constructor;
+			if(typeof options.template !== "undefined") {
+				this.template = _.template(options.template);
+			}
+			
+			this.rendered = false;
+			this.element_views = [];
+			this.collection.each(this.add);
+			
+			this.collection.bind('add', this.add);
+			this.collection.bind('remove', this.remove);
+			this.collection.bind('reset', this.reset);
+			this.collection.bind('destroy', this.destroy);
+		},
+	
+		render: function() {
+			this.rendered = true;
+			var that = this;
+			this.$el.empty();
+			if(typeof this.template !== "undefined") {
+				var data = {};
+				if(typeof this.model !== "undefined") {
+					data = this.$el.model.toJSON();
+				}
+				this.$el.html(this.template(data));
+			}
+			_(this.element_views).each(function(dvs){
+				that.$el.append(dvs.render().el);
+			});
+
+			return this;
+		},
+		
+		add: function(elt) {
+			var element_view = new this.element_view_constructor({model: elt});
+			this.element_views.push(element_view);
+			if(this.rendered) {
+				this.$el.append(element_view.render().el);
+			}
+		},
+		
+		remove: function(elt) {
+			var element_view = _(this.element_views).select(function(cv) {return cv.model === elt;})[0];
+			this.element_views = _(this.element_views).without(element_view);
+			if(this.rendered) {
+				element_view.$el.remove();
+			}
+			
+		},
+
+		reset: function() {
+			_(this.element_views).each(function(cv) {
+				cv.$el.remove();
+			});
+			this.element_views = [];
+			this.collection.each(this.add);	
+		}
+	
+	});
+	
+	
+	root.BasicModelView = Backbone.View.extend({
+				
+		initialize: function(options) {
+			_.bindAll(this);
+			if(typeof options.template !== "undefined") {
+				this.template = _.template(options.template);
+			}
+			if(typeof options.getJSON === "function") {
+				this.getJSON = options.getJSON;
+			}
+			this.model.bind("change", this.render);
+		},
+		render: function() {
+			$(this.el).html(this.template(this.getJSON()));
+			return this;
+		},
+		getJSON : function() {
+			return this.model.toJSON();			
+		}
+	});
+	
+}).call(this);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/models.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,219 @@
+(function() {
+    
+    var root = this;
+        
+    var Backbone = root.Backbone;
+    
+    var Models = root.Rkns.Models = {};
+    
+    
+    Models.getUID = function(obj) {
+        var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+            var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
+            return v.toString(16);
+        });
+        return obj.type + "-" + guid; 
+    };
+    
+    
+    var RenkanModel = Backbone.RelationalModel.extend({
+        idAttribute : "_id",
+        constructor: function(options) {
+            
+            if (typeof options !== "undefined") {
+                options._id = options._id || options.id || Models.getUID(this);
+                options.title = options.title || "(untitled " + this.type + ")";
+                options.description = options.description || "";
+                options.uri = options.uri || "";
+                
+                if(typeof this.prepare === "function") {
+                    options = this.prepare(options);
+                }
+            }
+            Backbone.RelationalModel.prototype.constructor.call(this, options);
+        },
+        validate: function() {
+            if(!this.type) {
+                return "object has no type";
+            }
+        },
+        addReference : function(_options, _propName, _list, _id, _default) {
+            var _element = _list.get(_id);
+            if (typeof _element === "undefined" && typeof _default !== "undefined") {
+                _options[_propName ] = _default;
+            }
+            else {
+                _options[_propName ] = _element;
+            }
+        }
+    });
+        
+    // USER
+    var User = Models.User = RenkanModel.extend({
+        type: "user",
+        prepare: function(options) {
+            options.color = options.color || "#666666";
+            return options;
+        },
+        toJSON: function() {
+            return {
+                _id: this.get("_id"),
+                title: this.get("title"),
+                uri: this.get("uri"),
+                description: this.get("description"),
+                color: this.get("color"),
+            };
+        },
+    });
+    
+    // NODE
+    var Node = Models.Node = RenkanModel.extend({
+        type: "node",
+        relations: [{
+            type: Backbone.HasOne,
+            key: "created_by",
+            relatedModel: User
+        }],
+        prepare: function(options) {
+            project = options.project;
+            this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user);
+            options.description = options.description || "";
+            return options;
+        },
+        toJSON: function() {
+            return {
+                _id: this.get("_id"),
+                title: this.get("title"),
+                uri: this.get("uri"),
+                description: this.get("description"),
+                position: this.get("position"),
+                image: this.get("image"),
+                created_by: this.get("created_by") ? this.get("created_by").get("_id") : null
+            };
+        },
+    });
+    
+    // EDGE
+    var Edge = Models.Edge = RenkanModel.extend({
+        type: "edge",
+        relations: [
+          {
+            type: Backbone.HasOne,
+            key: "created_by",
+            relatedModel: User
+          },
+          {
+            type: Backbone.HasOne,
+            key: "from",
+            relatedModel: Node
+          },
+          {
+            type: Backbone.HasOne,
+            key: "to",
+            relatedModel: Node
+          },
+        ],
+        prepare: function(options) {
+            project = options.project;
+            this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user);
+            this.addReference(options, "from", project.get("nodes"), options.from);
+            this.addReference(options, "to", project.get("nodes"), options.to);
+            return options;
+        },
+        toJSON: function() {
+            return {
+                _id: this.get("_id"),
+                title: this.get("title"),
+                uri: this.get("uri"),
+                description: this.get("description"),
+                from: this.get("from") ? this.get("from").get("_id") : null,
+                to: this.get("to") ? this.get("to").get("_id") : null,
+                created_by: this.get("created_by") ? this.get("created_by").get("_id") : null
+            };
+        },
+    });
+        
+    // PROJECT
+    var Project = Models.Project = RenkanModel.extend({
+        type: "project",
+        relations: [
+          {
+            type: Backbone.HasMany,
+            key: "users",
+            relatedModel: User,
+            reverseRelation: {
+                key: 'project',
+                includeInJSON: '_id'
+            },
+          },
+          {
+            type: Backbone.HasMany,
+            key: "nodes",
+            relatedModel: Node,
+            reverseRelation: {
+                key: 'project',
+                includeInJSON: '_id'
+            },
+          },
+          {
+            type: Backbone.HasMany,
+            key: "edges",
+            relatedModel: Edge,
+            reverseRelation: {
+                key: 'project',
+                includeInJSON: '_id'
+            },
+          }
+        ],
+        addUser: function(_props) {
+            _props.project = this;
+            var _user = new User(_props);
+            this.get("users").push(_user);
+            return _user;
+        },
+        addNode: function(_props) {
+            _props.project = this;
+            var _node = new Node(_props);
+            this.get("nodes").push(_node);
+            return _node;
+        },
+        addEdge: function(_props) {
+            _props.project = this;
+            var _edge = new Edge(_props);
+            this.get("edges").push(_edge);
+            return _edge;
+        },
+        removeNode: function(_model) {
+            this.get("nodes").remove(_model);
+        },
+        removeEdge: function(_model) {
+            this.get("edges").remove(_model);
+        },
+        validate: function(options) {
+            var _project = this;
+            _(options.users).each(function(_item) {
+                _item.project = _project;
+            });
+            _(options.nodes).each(function(_item) {
+                _item.project = _project;
+            });
+            _(options.edges).each(function(_item) {
+                _item.project = _project;
+            });
+        },
+        // Add event handler to remove edges when a node is removed
+        initialize: function() {
+            var _this = this;
+            this.on("remove:nodes", function(_node) {
+                _this.get("edges").remove(
+                    _this.get("edges").filter(function(_edge) {
+                        return _edge.get("from") == _node || _edge.get("to") == _node;
+                    })
+                );
+            });
+        }
+    });
+    
+
+}).call(window);
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/paper-renderer.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,1400 @@
+Rkns.Renderer = {
+    _MARGIN_X: 80,
+    _MARGIN_Y: 50,
+    _MIN_DRAG_DISTANCE: 2,
+    _NODE_RADIUS: 25,
+    _NODE_BUTTON_INNER: 26,
+    _NODE_BUTTON_OUTER: 60,
+    _EDGE_BUTTON_INNER: 1,
+    _EDGE_BUTTON_OUTER: 40,
+    _NODE_FONT_SIZE: 10,
+    _EDGE_FONT_SIZE: 9,
+    _NODE_MAX_CHAR: 50,
+    _EDGE_MAX_CHAR: 40,
+    _ARROW_LENGTH: 16,
+    _ARROW_WIDTH: 8,
+    _EDITOR_ARROW_LENGTH : 20,
+    _EDITOR_ARROW_WIDTH : 40,
+    _EDITOR_MARGIN : 15,
+    _EDITOR_PADDING : 10,
+    _EDITOR_GRADIENT : new paper.Gradient(['#f0f0f0', '#d0d0d0']),
+    _CLICKMODE_ADDNODE : 1,
+    _CLICKMODE_STARTEDGE : 2,
+    _CLICKMODE_ENDEDGE : 3
+}
+
+Rkns.Renderer.Utils = {
+    drawEditBox : function(_coords, _path, _width, _xmargin, _selector) {
+        _selector.css({
+            width: (_width - 2* Rkns.Renderer._EDITOR_PADDING),
+        })
+        var _height = _selector.outerHeight() + 2* Rkns.Renderer._EDITOR_PADDING,
+            _isLeft = (_coords.x < paper.view.center.x ? 1 : -1),
+            _left = _coords.x + _isLeft * ( _xmargin + Rkns.Renderer._EDITOR_ARROW_LENGTH ),
+            _right = _coords.x + _isLeft * ( _xmargin + Rkns.Renderer._EDITOR_ARROW_LENGTH + _width ),
+            _top = _coords.y - _height / 2;
+        if (_top < Rkns.Renderer._EDITOR_MARGIN) {
+            _top = Math.min( Rkns.Renderer._EDITOR_MARGIN, _coords.y - Rkns.Renderer._EDITOR_ARROW_WIDTH / 2 );
+        }
+        var _bottom = _top + _height;
+        if (_bottom > (paper.view.size.height - Rkns.Renderer._EDITOR_MARGIN)) {
+            _bottom = Math.max( paper.view.size.height - Rkns.Renderer._EDITOR_MARGIN, _coords.y + Rkns.Renderer._EDITOR_ARROW_WIDTH / 2 );
+            _top = _bottom - _height;
+        }
+        _path.segments[0].point
+            = _path.segments[7].point
+            = _coords.add([_isLeft * _xmargin, 0]);
+        _path.segments[1].point.x
+            = _path.segments[2].point.x
+            = _path.segments[5].point.x
+            = _path.segments[6].point.x
+            = _left;
+        _path.segments[3].point.x
+            = _path.segments[4].point.x
+            = _right;
+        _path.segments[2].point.y
+            = _path.segments[3].point.y
+            = _top;
+        _path.segments[4].point.y
+            = _path.segments[5].point.y
+            = _bottom;
+        _path.segments[1].point.y = _coords.y - Rkns.Renderer._EDITOR_ARROW_WIDTH / 2;
+        _path.segments[6].point.y = _coords.y + Rkns.Renderer._EDITOR_ARROW_WIDTH / 2;
+        _path.closed = true;
+        _path.fillColor = new paper.GradientColor(Rkns.Renderer._EDITOR_GRADIENT, [0,_top], [0, _bottom]);
+        _selector.css({
+            left: (Rkns.Renderer._EDITOR_PADDING + Math.min(_left, _right)),
+            top: (Rkns.Renderer._EDITOR_PADDING + _top)
+        });
+    },
+    sector : function(_repr, _inR, _outR, _startAngle, _endAngle, _padding, _imgsrc, _caption) {
+        var _startRads = _startAngle * Math.PI / 180,
+            _endRads = _endAngle * Math.PI / 180,
+            _img = new Image(),
+            _span = _endRads - _startRads,
+            _k = .0879 * _span,
+            _kin = _k * _inR,
+            _kout = _k * _outR,
+            _startdx = - Math.sin(_startRads),
+            _startdy = Math.cos(_startRads),
+            _startXIn = Math.cos(_startRads) * _inR + _padding * _startdx,
+            _startYIn = Math.sin(_startRads) * _inR + _padding * _startdy,
+            _startXOut = Math.cos(_startRads) * _outR + _padding * _startdx,
+            _startYOut = Math.sin(_startRads) * _outR + _padding * _startdy,
+            _enddx = - Math.sin(_endRads),
+            _enddy = Math.cos(_endRads),
+            _endXIn = Math.cos(_endRads) * _inR - _padding * _enddx,
+            _endYIn = Math.sin(_endRads) * _inR - _padding * _enddy,
+            _endXOut = Math.cos(_endRads) * _outR - _padding * _enddx,
+            _endYOut = Math.sin(_endRads) * _outR - _padding * _enddy,
+            _centerR = (_inR + _outR)/2,
+            _centerRads = (_startRads + _endRads) / 2,
+            _centerX = Math.cos(_centerRads) * _centerR,
+            _centerY = Math.sin(_centerRads) * _centerR,
+            _textX = Math.cos(_centerRads) * (_outR + 3),
+            _textY = Math.sin(_centerRads) * (_outR + 3),
+            _segments = [];
+        _segments.push([[_startXIn, _startYIn], [0, 0], [ _kin * _startdx, _kin * _startdy ]]);
+        for (var i = 1; i < 4; i++) {
+            var _rads = i * _span / 4 + _startRads,
+                _dx = - Math.sin(_rads),
+                _dy = Math.cos(_rads),
+                _x = Math.cos(_rads) * _inR,
+                _y = Math.sin(_rads) * _inR;
+            _segments.push([[_x, _y], [ - _kin * _dx, - _kin * _dy], [ _kin * _dx, _kin * _dy ]]);
+        }
+        _segments.push([[_endXIn, _endYIn], [ - _kin * _enddx, - _kin * _enddy ], [0,0]]);
+        _segments.push([[_endXOut, _endYOut], [ 0,0 ], [ - _kout * _enddx, - _kout * _enddy ]]);
+        for (var i = 3; i > 0; i--) {
+            var _rads = i * _span / 4 + _startRads,
+                _dx = - Math.sin(_rads),
+                _dy = Math.cos(_rads),
+                _x = Math.cos(_rads) * _outR,
+                _y = Math.sin(_rads) * _outR;
+            _segments.push([[_x, _y], [ _kout * _dx, _kout * _dy], [ - _kout * _dx, - _kout * _dy ]]);
+        }
+        _segments.push([[_startXOut, _startYOut], [ _kout * _startdx, _kout * _startdy ], [0, 0]]);
+        var _path = new paper.Path();
+        _path.add.apply(_path, _segments);
+        _path.fillColor = "#333333";
+        _path.opacity = .5;
+        _path.closed = true;
+        _path.__representation = _repr;
+        if (_textX >= -2 && _textX <= 2) {
+            if (_textY > 0) {
+                _textY += 6;
+            }
+        }
+        var _text = new paper.PointText(_textX,_textY);
+        _text.characterStyle = {
+            fontSize: 9,
+            fillColor: '#c000c0'
+        };
+        if (_textX > 2) {
+            _text.paragraphStyle.justification = 'left';
+        } else if (_textX < -2) {
+            _text.paragraphStyle.justification = 'right';
+        } else {
+            _text.paragraphStyle.justification = 'center';
+        }
+        _text.visible = false;
+        var _visible = false,
+            _restPos = new paper.Point(-200, -200),
+            _grp = new paper.Group([_path, _text]),
+            _delta = _grp.position,
+            _imgdelta = new paper.Point([_centerX, _centerY]),
+            _currentPos = new paper.Point(0,0);
+        _text.content = _caption;
+        _grp.visible = false;
+        _grp.position = _restPos;
+        var _res = {
+            show: function() {
+                _visible = true;
+                _grp.position = _currentPos.add(_delta);
+                _grp.visible = true;
+            },
+            moveTo: function(_point) {
+                _currentPos = _point;
+                if (_visible) {
+                    _grp.position = _point.add(_delta);
+                }
+            },
+            hide: function() {
+                _visible = false;
+                _grp.visible = false;
+                _grp.position = _restPos;
+            },
+            select: function() {
+                _path.opacity = .8;
+                _text.visible = true;
+            },
+            unselect: function() {
+                _path.opacity = .5;
+                _text.visible = false;
+            },
+            destroy: function() {
+                _grp.remove();
+            }
+        }
+        _img.onload = function() {
+            var _h = _img.height;
+            var _raster = new paper.Raster(_img);
+            _raster.position = _imgdelta.add(_grp.position).subtract(_delta);
+            _grp.addChild(_raster);
+        }
+        _img.src = _imgsrc;
+        return _res
+    }
+}
+
+Rkns.Renderer._BaseRepresentation = function(_renderer, _model) {
+    if (typeof _renderer !== "undefined") {
+        this.renderer = _renderer;
+        this.project = _renderer.renkan.project;
+        this.model = _model;
+        if (this.model) {
+            var _this = this;
+            this._changeBinding = function() {
+                _this.redraw();
+            }
+            this._removeBinding = function() {
+                _renderer.removeRepresentation(_this);
+                _renderer.redraw();
+            }
+            this.model.on("change", this._changeBinding );
+            this.model.on("remove", this._removeBinding );
+        }
+    }
+}
+
+Rkns.Renderer._BaseRepresentation.prototype.super = function(_func) {
+    Rkns.Renderer._BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));
+}
+
+Rkns.Renderer._BaseRepresentation.prototype.select = function() {}
+
+Rkns.Renderer._BaseRepresentation.prototype.unselect = function() {}
+
+Rkns.Renderer._BaseRepresentation.prototype.highlight = function() {}
+
+Rkns.Renderer._BaseRepresentation.prototype.unhighlight = function() {}
+
+Rkns.Renderer._BaseRepresentation.prototype.mouseup = function() {}
+
+Rkns.Renderer._BaseRepresentation.prototype.destroy = function() {
+    if (this.model) {
+        this.model.off("change", this._changeBinding );
+        this.model.off("remove", this._removeBinding );
+    }
+}
+
+Rkns.Renderer.Node = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.Node.prototype._init = function() {
+    this.renderer.node_layer.activate();
+    this.type = "Node";
+    this.circle = new paper.Path.Circle([0, 0], Rkns.Renderer._NODE_RADIUS);
+    this.circle.fillColor = '#ffffff';
+    this.circle.__representation = this;
+    this.title = new paper.PointText([0,0]);
+    this.title.characterStyle = {
+        fontSize: Rkns.Renderer._NODE_FONT_SIZE,
+        fillColor: 'black'
+    };
+    this.edit_button = new Rkns.Renderer.NodeEditButton(this.renderer, null);
+    this.edit_button.node_representation = this;
+    this.remove_button = new Rkns.Renderer.NodeRemoveButton(this.renderer, null);
+    this.remove_button.node_representation = this;
+    this.link_button = new Rkns.Renderer.NodeLinkButton(this.renderer, null);
+    this.link_button.node_representation = this;
+    this.title.paragraphStyle.justification = 'center';
+}
+
+Rkns.Renderer.Node.prototype.redraw = function() {
+    var _model_coords = new paper.Point(this.model.get("position"));
+    this.paper_coords = this.renderer.toPaperCoords(_model_coords);
+    this.circle.position = this.paper_coords;
+    this.title.content = this.model.get("title");
+    this.title.position = this.paper_coords.add([0, Rkns.Renderer._NODE_RADIUS + 1.5 *Rkns.Renderer._NODE_FONT_SIZE]);
+    this.circle.strokeColor = this.model.get("created_by").get("color");
+    this.edit_button.moveTo(this.paper_coords);
+    this.remove_button.moveTo(this.paper_coords);
+    this.link_button.moveTo(this.paper_coords);
+    var _img = this.model.get("image");
+    if (_img && _img !== this.img) {
+        var _image = new Image(),
+            _this = this;
+        _image.onload = function() {
+            if (_this.node_image) {
+                _this.node_image.remove();
+            }
+            _this.renderer.node_layer.activate();
+            var _ratio = Math.min(1, 2 * Rkns.Renderer._NODE_RADIUS / _image.width, 2 * Rkns.Renderer._NODE_RADIUS / _image.height );
+            var _raster = new paper.Raster(_image);
+            var _clip = new paper.Path.Circle([0, 0], Rkns.Renderer._NODE_RADIUS);
+            _raster.scale(_ratio);
+            _this.node_image = new paper.Group(_clip, _raster);
+            _this.node_image.opacity = .9;
+            /* This is a workaround to allow clipping at group level
+             * If opacity was set to 1, paper.js would merge all clipping groups in one (known bug).
+            */
+            _this.node_image.clipped = true;
+            _this.node_image.position = _this.paper_coords;
+            _this.node_image.__representation = _this;
+            _clip.__representation = _this;
+            paper.view.draw();
+        }
+        _image.src = _img;
+    }
+    this.img = _img;
+    if (this.node_image) {
+        if (!this.img) {
+            this.node_image.remove();
+            delete this.node_image;
+        } else {
+            this.node_image.position = this.paper_coords;
+        }
+    }
+}
+
+Rkns.Renderer.Node.prototype.paperShift = function(_delta) {
+    var _coords = this.renderer.toModelCoords(this.paper_coords.add(_delta)),
+        _data = {
+            position: {
+                x: _coords.x,
+                y: _coords.y
+            }
+        };
+    this.model.set(_data);
+    this.renderer.redraw();
+}
+
+Rkns.Renderer.Node.prototype.openEditor = function() {
+    this.renderer.removeRepresentationsOfType("editor");
+    var _editor = this.renderer.addRepresentation("NodeEditor",null);
+    _editor.node_representation = this;
+    _editor.draw();
+}
+
+Rkns.Renderer.Node.prototype.select = function() {
+    this.circle.strokeWidth = 3;
+    this.edit_button.show();
+    this.remove_button.show();
+    this.link_button.show();
+    var _uri = this.model.get("uri");
+    Rkns.$('.Rk-Bin-Item').each(function() {
+        var _el = Rkns.$(this);
+        if (_el.attr("data-uri") == _uri) {
+            _el.addClass("selected");
+        }
+    });
+}
+
+Rkns.Renderer.Node.prototype.unselect = function(_newTarget) {
+    if (!_newTarget || _newTarget.node_representation !== this) {
+        this.edit_button.hide();
+        this.remove_button.hide();
+        this.link_button.hide();
+        this.circle.strokeWidth = 1;
+        Rkns.$('.Rk-Bin-Item').removeClass("selected");
+    }
+}
+
+Rkns.Renderer.Node.prototype.highlight = function() {
+    this.circle.fillColor = "#ffff80";
+    if (this.node_image) {
+        this.node_image.opacity = .5;
+    }
+}
+
+Rkns.Renderer.Node.prototype.unhighlight = function(_newTarget) {
+    this.circle.fillColor = "#ffffff";
+    if (this.node_image) {
+        this.node_image.opacity = .9;
+    }
+}
+
+Rkns.Renderer.Node.prototype.mouseup = function(_event) {
+    if (!this.renderer.is_dragging) {
+        this.openEditor();
+    }
+    this.renderer.click_target = null;
+    this.renderer.is_dragging = false;
+}
+
+Rkns.Renderer.Node.prototype.destroy = function(_event) {
+    this.super("destroy");
+    this.edit_button.destroy();
+    this.remove_button.destroy();
+    this.link_button.destroy();
+    this.circle.remove();
+    this.title.remove();
+    if (this.node_image) {
+        this.node_image.remove();
+    }
+}
+
+/* */
+
+Rkns.Renderer.Edge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.Edge.prototype._init = function() {
+    this.renderer.edge_layer.activate();
+    this.type = "Edge";
+    this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
+    this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
+    this.bundle = this.renderer.addToBundles(this);
+    this.line = new paper.Path();
+    this.line.add([0,0],[0,0],[0,0]);
+    this.line.__representation = this;
+    this.arrow = new paper.Path();
+    this.arrow.add([0,0],[Rkns.Renderer._ARROW_LENGTH,Rkns.Renderer._ARROW_WIDTH / 2],[0,Rkns.Renderer._ARROW_WIDTH]);
+    this.arrow.__representation = this;
+    this.text = new paper.PointText();
+    this.text.characterStyle = {
+        fontSize: Rkns.Renderer._EDGE_FONT_SIZE,
+        fillColor: 'black'
+    };
+    this.text.paragraphStyle.justification = 'center';
+    this.text_angle = 0;
+    this.arrow_angle = 0;
+    this.edit_button = new Rkns.Renderer.EdgeEditButton(this.renderer, null);
+    this.edit_button.edge_representation = this;
+    this.remove_button = new Rkns.Renderer.EdgeRemoveButton(this.renderer, null);
+    this.remove_button.edge_representation = this;
+}
+
+Rkns.Renderer.Edge.prototype.redraw = function() {
+    var _p0a = this.from_representation.paper_coords,
+        _p1a = this.to_representation.paper_coords,
+        _v = _p1a.subtract(_p0a),
+        _r = _v.length,
+        _u = _v.divide(_r),
+        _group_pos = this.bundle.getPosition(this),
+        _delta = new paper.Point([- _u.y, _u.x]).multiply( 12 * _group_pos ),
+        _p0b = _p0a.add(_delta), /* Adding a 4 px difference */
+        _p1b = _p1a.add(_delta), /* to differentiate inbound and outbound links */
+        _a = _v.angle,
+        _handle = _v.divide(3),
+        _color = this.model.get("created_by").get("color");
+    this.paper_coords = _p0b.add(_p1b).divide(2);
+    this.line.strokeColor = _color;
+    this.line.segments[0].point = _p0a;
+    this.line.segments[1].point = this.paper_coords;
+    this.line.segments[1].handleIn = _handle.multiply(-1);
+    this.line.segments[1].handleOut = _handle;
+    this.line.segments[2].point = _p1a;
+    this.arrow.rotate(_a - this.arrow_angle);
+    this.arrow.fillColor = _color;
+    this.arrow.position = this.paper_coords.subtract(_u.multiply(4));
+    this.arrow_angle = _a;
+    if (_a > 90) {
+        _a -= 180;
+    }
+    if (_a < -90) {
+        _a += 180;
+    }
+    this.text.rotate(_a - this.text_angle);
+    this.text.content = this.model.get("title");
+    this.text.position = this.paper_coords;
+    this.text_angle = _a;
+    this.edit_button.moveTo(this.paper_coords);
+    this.remove_button.moveTo(this.paper_coords);
+}
+
+Rkns.Renderer.Edge.prototype.openEditor = function() {
+    this.renderer.removeRepresentationsOfType("editor");
+    var _editor = this.renderer.addRepresentation("EdgeEditor",null);
+    _editor.edge_representation = this;
+    _editor.draw();
+}
+
+Rkns.Renderer.Edge.prototype.select = function() {
+    this.line.strokeWidth = 3;
+    this.edit_button.show();
+    this.remove_button.show();
+}
+
+Rkns.Renderer.Edge.prototype.unselect = function(_newTarget) {
+    if (!_newTarget || _newTarget.edge_representation !== this) {
+        this.edit_button.hide();
+        this.remove_button.hide();
+        this.line.strokeWidth = 1;
+    }
+}
+
+Rkns.Renderer.Edge.prototype.mouseup = function(_event) {
+    if (!this.renderer.is_dragging) {
+        this.openEditor();
+    }
+    this.renderer.click_target = null;
+    this.renderer.is_dragging = false;
+}
+
+Rkns.Renderer.Edge.prototype.paperShift = function(_delta) {
+    this.from_representation.paperShift(_delta);
+    this.to_representation.paperShift(_delta);
+    this.renderer.redraw();
+}
+
+Rkns.Renderer.Edge.prototype.destroy = function() {
+    this.super("destroy");
+    this.line.remove();
+    this.arrow.remove();
+    this.text.remove();
+    this.edit_button.destroy();
+    this.remove_button.destroy();
+    var _this = this;
+    this.bundle.edges = Rkns._(this.bundle.edges).reject(function(_edge) {
+        return _edge === _this;
+    });
+}
+
+/* */
+
+Rkns.Renderer.TempEdge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.TempEdge.prototype._init = function() {
+    this.renderer.edge_layer.activate();
+    this.type = "temp-edge";
+    
+    var _color = this.project.get("users").get(this.renderer.renkan.current_user).get("color");
+    this.line = new paper.Path();
+    this.line.strokeColor = _color;
+    this.line.add([0,0],[0,0]);
+    this.line.__representation = this;
+    this.arrow = new paper.Path();
+    this.arrow.fillColor = _color;
+    this.arrow.add([0,0],[Rkns.Renderer._ARROW_LENGTH,Rkns.Renderer._ARROW_WIDTH / 2],[0,Rkns.Renderer._ARROW_WIDTH]);
+    this.arrow.__representation = this;
+    this.arrow_angle = 0;
+}
+
+Rkns.Renderer.TempEdge.prototype.redraw = function() {
+    var _p0 = this.from_representation.paper_coords,
+        _p1 = this.end_pos,
+        _a = _p1.subtract(_p0).angle,
+        _c = _p0.add(_p1).divide(2);
+    this.line.segments[0].point = _p0;
+    this.line.segments[1].point = _p1;
+    this.arrow.rotate(_a - this.arrow_angle);
+    this.arrow.position = _c;
+    this.arrow_angle = _a;
+}
+
+Rkns.Renderer.TempEdge.prototype.paperShift = function(_delta) {
+    this.end_pos = this.end_pos.add(_delta);
+    var _hitResult = paper.project.hitTest(this.end_pos);
+    this.renderer.findTarget(_hitResult);
+    this.redraw();
+}
+
+Rkns.Renderer.TempEdge.prototype.mouseup = function(_event) {
+    var _hitResult = paper.project.hitTest(_event.point),
+        _model = this.from_representation.model,
+        _endDrag = true;
+    if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+        var _target = _hitResult.item.__representation;
+        if (_target.type === "Node" && _model !== _target.model) {
+            var _data = {
+                id: Rkns.Utils.getUID('edge'),
+                created_by: this.renderer.renkan.current_user,
+                from: _model.get("_id"),
+                to: _target.model.get("_id")
+            };
+            this.project.addEdge(_data);
+        }
+        if (_model === _target.model || (_target.node_representation && _target.node_representation.model === _model)) {
+            _endDrag = false;
+            this.renderer.is_dragging = true;
+        }
+    }
+    if (_endDrag) {
+        this.renderer.click_target = null;
+        this.renderer.is_dragging = false;
+        this.renderer.removeRepresentation(this);
+        paper.view.draw();
+    }
+}
+
+Rkns.Renderer.TempEdge.prototype.destroy = function() {
+    this.arrow.remove();
+    this.line.remove();
+}
+
+/* */
+
+Rkns.Renderer.NodeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.NodeEditor.prototype._init = function() {
+    this.renderer.overlay_layer.activate();
+    this.type = "editor";
+    this.editor_block = new paper.Path();
+    var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
+    this.editor_block.add.apply(this.editor_block, _pts);
+    this.editor_block.strokeWidth = 2;
+    this.editor_block.strokeColor = "#999999";
+    this.editor_block.fillColor = "#e0e0e0";
+    this.editor_block.opacity = .8;
+    this.editor_$ = Rkns.$('<div>')
+        .appendTo(this.renderer.editor_$)
+        .css({
+            position: "absolute",
+            opacity: .8
+        })
+        .hide();
+}
+
+Rkns.Renderer.NodeEditor.prototype.template = Rkns._.template(
+    '<h2><span class="Rk-CloseX">&times;</span><%=l10n.edit_node%></span></h2>'
+    + '<p><label><%=l10n.edit_title%></label><input class="Rk-Edit-Title" type="text" value="<%=node.title%>"/></p>'
+    + '<p><label><%=l10n.edit_uri%></label><input class="Rk-Edit-URI" type="text" value="<%=node.uri%>"/><a class="Rk-Edit-Goto" href="<%=node.uri%>" target="_blank"></a></p>'
+    + '<p><label><%=l10n.edit_description%></label><textarea class="Rk-Edit-Description"><%=node.description%></textarea></p>'
+    + '<p><label><%=l10n.edit_image%></label><input class="Rk-Edit-Image" type="text" value="<%=node.image%>"/><img class="Rk-Edit-ImgPreview" src="<%=node.image%>" /></p>'
+    + '<p><label><%=l10n.created_by%></label> <span class="Rk-UserColor" style="background:<%=node.created_by_color%>;"></span><%=node.created_by_title%></p>'
+);
+
+Rkns.Renderer.NodeEditor.prototype.draw = function() {
+    var _model = this.node_representation.model;
+    this.editor_$
+        .html(this.template({
+            node: {
+                title: _model.get("title"),
+                uri: _model.get("uri"),
+                description: _model.get("description"),
+                image: _model.get("image") || "",
+                created_by_color: _model.get("created_by").get("color"),
+                created_by_title: _model.get("created_by").get("title")
+            },
+            l10n: this.renderer.renkan.l10n
+        }));
+    this.redraw();
+    var _this = this;
+    this.editor_$.find(".Rk-CloseX").click(function() {
+        _this.renderer.removeRepresentation(_this);
+        paper.view.draw();
+    });
+    this.editor_$.find("input, textarea").bind("keyup change", function() {
+        var _uri = _this.editor_$.find(".Rk-Edit-URI").val(),
+            _image = _this.editor_$.find(".Rk-Edit-Image").val();
+        _this.editor_$.find(".Rk-Edit-ImgPreview").attr("src", _image);
+        _this.editor_$.find(".Rk-Edit-Goto").attr("href",_uri);
+        var _data = {
+            title: _this.editor_$.find(".Rk-Edit-Title").val(),
+            description: _this.editor_$.find(".Rk-Edit-Description").val(),
+            uri: _uri,
+            image: _image
+        }
+        _model.set(_data);
+        _this.redraw();
+    });
+    this.editor_$.find("img").load(function() {
+        _this.redraw();
+    })
+    this.editor_$.find(".Rk-Edit-Title")[0].focus();
+}
+
+Rkns.Renderer.NodeEditor.prototype.redraw = function() {
+    var _coords = this.node_representation.paper_coords;
+    Rkns.Renderer.Utils.drawEditBox(_coords, this.editor_block, 250, 20, this.editor_$);
+    this.editor_$.show();
+    paper.view.draw();
+}
+
+Rkns.Renderer.NodeEditor.prototype.destroy = function() {
+    this.editor_block.remove();
+    this.editor_$.detach();
+}
+
+/* */
+
+Rkns.Renderer.EdgeEditor = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.EdgeEditor.prototype._init = function() {
+    this.renderer.overlay_layer.activate();
+    this.type = "editor";
+    this.editor_block = new paper.Path();
+    var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
+    this.editor_block.add.apply(this.editor_block, _pts);
+    this.editor_block.strokeWidth = 2;
+    this.editor_block.strokeColor = "#999999";
+    this.editor_block.fillColor = "#e0e0e0";
+    this.editor_block.opacity = .8;
+    this.editor_$ = Rkns.$('<div>')
+        .appendTo(this.renderer.editor_$)
+        .css({
+            position: "absolute",
+            opacity: .8
+        })
+        .hide();
+}
+
+Rkns.Renderer.EdgeEditor.prototype.template = Rkns._.template(
+    '<h2><span class="Rk-CloseX">&times;</span><%=l10n.edit_edge%></span></h2>'
+    + '<p><label><%=l10n.edit_title%></label><input class="Rk-Edit-Title" type="text" value="<%=edge.title%>"/></p>'
+    + '<p><label><%=l10n.edit_uri%></label><input class="Rk-Edit-URI" type="text" value="<%=edge.uri%>"/><a class="Rk-Edit-Goto" href="<%=edge.uri%>" target="_blank"></a></p>'
+    + '<p><label><%=l10n.edit_from%></label><span class="Rk-UserColor" style="background:<%=edge.from_created_by_color%>;"></span><%=edge.from_title%></p>'
+    + '<p><label><%=l10n.edit_to%></label><span class="Rk-UserColor" style="background:<%=edge.to_created_by_color%>;"></span><%=edge.to_title%></p>'
+    + '<p><label><%=l10n.created_by%> </label><span class="Rk-UserColor" style="background:<%=edge.created_by_color%>;"></span><%=edge.created_by_title%></p>'
+);
+
+Rkns.Renderer.EdgeEditor.prototype.draw = function() {
+    var _model = this.edge_representation.model;
+    this.editor_$
+        .html(this.template({
+            edge: {
+                title: _model.get("title"),
+                uri: _model.get("uri"),
+                description: _model.get("description"),
+                from_title: _model.get("from").get("title"),
+                to_title: _model.get("to").get("title"),
+                from_created_by_color: _model.get("from").get("created_by").get("color"),
+                to_created_by_color: _model.get("to").get("created_by").get("color"),
+                created_by_color: _model.get("created_by").get("color"),
+                created_by_title: _model.get("created_by").get("title")
+            },
+            l10n: this.renderer.renkan.l10n
+        }));
+    this.redraw();
+    var _this = this;
+    this.editor_$.find(".Rk-CloseX").click(function() {
+        _this.renderer.removeRepresentation(_this);
+        paper.view.draw();
+    });
+    this.editor_$.find("input, textarea").bind("keyup change", function() {
+        _this.editor_$.find(".Rk-Edit-Goto").attr("href",_this.editor_$.find(".Rk-Edit-URI").val());
+        var _data = {
+            title: _this.editor_$.find(".Rk-Edit-Title").val(),
+            uri: _this.editor_$.find(".Rk-Edit-URI").val()
+        }
+        _model.set(_data);
+        _this.redraw();
+    });
+}
+Rkns.Renderer.EdgeEditor.prototype.redraw = function() {
+    var _coords = this.edge_representation.paper_coords;
+    Rkns.Renderer.Utils.drawEditBox(_coords, this.editor_block, 250, 5, this.editor_$);
+    this.editor_$.show();
+    paper.view.draw();
+}
+
+Rkns.Renderer.EdgeEditor.prototype.destroy = function() {
+    this.editor_block.remove();
+    this.editor_$.detach();
+}
+
+/* */
+
+Rkns.Renderer.NodeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.NodeEditButton.prototype._init = function() {
+    this.renderer.overlay_layer.activate();
+    this.type = "Node-edit-button";
+    this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._NODE_BUTTON_INNER, Rkns.Renderer._NODE_BUTTON_OUTER, - 90, 30, 1, this.renderer.renkan.static_url+'img/edit.png', this.renderer.renkan.l10n.caption_edit);
+}
+
+Rkns.Renderer.NodeEditButton.prototype.moveTo = function(_pos) {
+    this.sector.moveTo(_pos);
+}
+
+Rkns.Renderer.NodeEditButton.prototype.show = function() {
+    this.sector.show();
+}
+
+Rkns.Renderer.NodeEditButton.prototype.hide = function() {
+    this.sector.hide();
+}
+
+Rkns.Renderer.NodeEditButton.prototype.select = function() {
+    this.sector.select();
+}
+
+Rkns.Renderer.NodeEditButton.prototype.unselect = function(_newTarget) {
+    this.sector.unselect();
+    if (!_newTarget || (_newTarget !== this.node_representation && _newTarget.node_representation !== this.node_representation)) {
+        this.node_representation.unselect();
+    }
+}
+
+Rkns.Renderer.NodeEditButton.prototype.mouseup = function() {
+    if (!this.renderer.is_dragging) {
+        this.node_representation.openEditor();
+    }
+}
+
+Rkns.Renderer.NodeEditButton.prototype.destroy = function() {
+    this.sector.destroy();
+}
+
+/* */
+
+Rkns.Renderer.NodeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.NodeRemoveButton.prototype._init = function() {
+    this.renderer.overlay_layer.activate();
+    this.type = "Node-remove-button";
+    this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._NODE_BUTTON_INNER, Rkns.Renderer._NODE_BUTTON_OUTER, -210, -90, 1, this.renderer.renkan.static_url+'img/remove.png', this.renderer.renkan.l10n.caption_remove);
+}
+
+Rkns.Renderer.NodeRemoveButton.prototype.moveTo = function(_pos) {
+    this.sector.moveTo(_pos);
+}
+
+Rkns.Renderer.NodeRemoveButton.prototype.show = function() {
+    this.sector.show();
+}
+
+Rkns.Renderer.NodeRemoveButton.prototype.hide = function() {
+    this.sector.hide();
+}
+
+Rkns.Renderer.NodeRemoveButton.prototype.select = function() {
+    this.sector.select();
+}
+
+Rkns.Renderer.NodeRemoveButton.prototype.unselect = function(_newTarget) {
+    this.sector.unselect();
+    if (!_newTarget || (_newTarget !== this.node_representation && _newTarget.node_representation !== this.node_representation)) {
+        this.node_representation.unselect();
+    }
+}
+
+Rkns.Renderer.NodeRemoveButton.prototype.mouseup = function() {
+    this.renderer.removeRepresentationsOfType("editor");
+    if (confirm('Do you really wish to remove node "' + this.node_representation.model.get("title") + '"?')) {
+        this.project.removeNode(this.node_representation.model);
+    }
+}
+
+Rkns.Renderer.NodeRemoveButton.prototype.destroy = function() {
+    this.sector.destroy();
+}
+
+/* */
+
+Rkns.Renderer.NodeLinkButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.NodeLinkButton.prototype._init = function() {
+    this.renderer.overlay_layer.activate();
+    this.type = "Node-link-button";
+    this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._NODE_BUTTON_INNER, Rkns.Renderer._NODE_BUTTON_OUTER, 30, 150, 1, this.renderer.renkan.static_url+'img/link.png', this.renderer.renkan.l10n.caption_link);
+}
+
+Rkns.Renderer.NodeLinkButton.prototype.moveTo = function(_pos) {
+    this.sector.moveTo(_pos);
+}
+
+Rkns.Renderer.NodeLinkButton.prototype.show = function() {
+    this.sector.show();
+}
+
+Rkns.Renderer.NodeLinkButton.prototype.hide = function() {
+    this.sector.hide();
+}
+
+Rkns.Renderer.NodeLinkButton.prototype.select = function() {
+    this.sector.select();
+}
+
+Rkns.Renderer.NodeLinkButton.prototype.unselect = function(_newTarget) {
+    this.sector.unselect();
+    if (!_newTarget || (_newTarget !== this.node_representation && _newTarget.node_representation !== this.node_representation)) {
+        this.node_representation.unselect();
+    }
+}
+
+Rkns.Renderer.NodeLinkButton.prototype.destroy = function() {
+    this.sector.destroy();
+}
+
+/* */
+
+Rkns.Renderer.EdgeEditButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.EdgeEditButton.prototype._init = function() {
+    this.renderer.overlay_layer.activate();
+    this.type = "Edge-edit-button";
+    this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, - 90, 90, 1, this.renderer.renkan.static_url+'img/edit.png', this.renderer.renkan.l10n.caption_edit);
+}
+
+Rkns.Renderer.EdgeEditButton.prototype.moveTo = function(_pos) {
+    this.sector.moveTo(_pos);
+}
+
+Rkns.Renderer.EdgeEditButton.prototype.show = function() {
+    this.sector.show();
+}
+
+Rkns.Renderer.EdgeEditButton.prototype.hide = function() {
+    this.sector.hide();
+}
+
+Rkns.Renderer.EdgeEditButton.prototype.select = function() {
+    this.sector.select();
+}
+
+Rkns.Renderer.EdgeEditButton.prototype.unselect = function(_newTarget) {
+    this.sector.unselect();
+    if (!_newTarget || (_newTarget !== this.edge_representation && _newTarget.edge_representation !== this.edge_representation)) {
+        this.edge_representation.unselect();
+    }
+}
+
+Rkns.Renderer.EdgeEditButton.prototype.mouseup = function() {
+    if (!this.renderer.is_dragging) {
+        this.edge_representation.openEditor();
+    }
+}
+
+Rkns.Renderer.EdgeEditButton.prototype.destroy = function() {
+    this.sector.destroy();
+}
+
+/* */
+
+Rkns.Renderer.EdgeRemoveButton = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.EdgeRemoveButton.prototype._init = function() {
+    this.renderer.overlay_layer.activate();
+    this.type = "Edge-remove-button";
+    this.sector = Rkns.Renderer.Utils.sector(this, Rkns.Renderer._EDGE_BUTTON_INNER, Rkns.Renderer._EDGE_BUTTON_OUTER, - 270, -90, 1, this.renderer.renkan.static_url+'img/remove.png', this.renderer.renkan.l10n.caption_remove);
+}
+Rkns.Renderer.EdgeRemoveButton.prototype.moveTo = function(_pos) {
+    this.sector.moveTo(_pos);
+}
+
+Rkns.Renderer.EdgeRemoveButton.prototype.show = function() {
+    this.sector.show();
+}
+
+Rkns.Renderer.EdgeRemoveButton.prototype.hide = function() {
+    this.sector.hide();
+}
+
+Rkns.Renderer.EdgeRemoveButton.prototype.select = function() {
+    this.sector.select();
+}
+
+Rkns.Renderer.EdgeRemoveButton.prototype.unselect = function(_newTarget) {
+    this.sector.unselect();
+    if (!_newTarget || (_newTarget !== this.edge_representation && _newTarget.edge_representation !== this.edge_representation)) {
+        this.edge_representation.unselect();
+    }
+}
+
+Rkns.Renderer.EdgeRemoveButton.prototype.mouseup = function() {
+    this.renderer.removeRepresentationsOfType("editor");
+    if (confirm('Do you really wish to remove edge "' + this.edge_representation.model.get("title") + '"?')) {
+        this.project.removeEdge(this.edge_representation.model);
+    }
+}
+
+Rkns.Renderer.EdgeRemoveButton.prototype.destroy = function() {
+    this.sector.destroy();
+}
+
+/* */
+
+Rkns.Renderer.Scene = function(_renkan) {
+    this.renkan = _renkan;
+    this.$ = Rkns.$(".Rk-Render");
+    this.representations = [];
+    this.$.html(this.template({
+        l10n: _renkan.l10n
+    }))
+    this.canvas_$ = this.$.find(".Rk-Canvas");
+    this.editor_$ = this.$.find(".Rk-Editor");
+    this.notif_$ = this.$.find(".Rk-Notifications");
+    paper.setup(this.canvas_$[0]);
+    this.scale = 1;
+    this.offset = paper.view.center;
+    this.totalScroll = 0;
+    this.click_target = null;
+    this.selected_target = null;
+    this.edge_layer = new paper.Layer();
+    this.node_layer = new paper.Layer();
+    this.overlay_layer = new paper.Layer();
+    this.bundles = [];
+    this.click_mode = false;
+    var _tool = new paper.Tool(),
+        _this = this;
+    _tool.minDistance = Rkns.Renderer._MIN_DRAG_DISTANCE;
+    _tool.onMouseMove = function(_event) {
+        _this.onMouseMove(_event);
+    }
+    _tool.onMouseDown = function(_event) {
+        _this.onMouseDown(_event);
+    }
+    _tool.onMouseDrag = function(_event) {
+        _this.onMouseDrag(_event);
+    }
+    this.canvas_$.mouseup(function(_event) {
+        _this.onMouseUp(_event);
+    });
+    this.canvas_$.mousewheel(function(_event, _delta) {
+        _this.onScroll(_event, _delta);
+    });
+    this.canvas_$.dblclick(function(_event) {
+        _this.onDoubleClick(_event);
+    });
+    this.canvas_$.mouseenter(function(_event) {
+        _this.onMouseEnter(_event);
+    });
+    this.editor_$.find(".Rk-ZoomOut").click(function() {
+        _this.offset = new paper.Point([
+            _this.canvas_$.width(),
+            _this.canvas_$.height()
+        ]).multiply( .5 * ( 1 - Math.SQRT1_2 ) ).add(_this.offset.multiply( Math.SQRT1_2 ));
+        _this.setScale( _this.scale * Math.SQRT1_2 );
+        _this.redraw();
+    });
+    this.editor_$.find(".Rk-ZoomIn").click(function() {
+        _this.offset = new paper.Point([
+            _this.canvas_$.width(),
+            _this.canvas_$.height()
+        ]).multiply( .5 * ( 1 - Math.SQRT2 ) ).add(_this.offset.multiply( Math.SQRT2 ));
+        _this.setScale( _this.scale * Math.SQRT2 );
+        _this.redraw();
+    });
+    this.$.find(".Rk-CurrentUser").mouseenter(
+        function() { _this.$.find(".Rk-UserList").slideDown() }
+    );
+    this.$.find(".Rk-Users").mouseleave(
+        function() { _this.$.find(".Rk-UserList").slideUp(); }
+    );
+    this.$.find(".Rk-FullScreen-Button").click(function() {
+        var _isFull = document.fullScreen || document.mozFullScreen || document.webkitIsFullScreen,
+            _el = _this.renkan.$[0],
+            _requestMethods = ["requestFullScreen","mozRequestFullScreen","webkitRequestFullScreen"],
+            _cancelMethods = ["cancelFullScreen","mozCancelFullScreen","webkitCancelFullScreen"];
+        if (_isFull) {
+            for (var i = 0; i < _cancelMethods.length; i++) {
+                if (typeof document[_cancelMethods[i]] === "function") {
+                    document[_cancelMethods[i]]();
+                    break;
+                }
+            }
+        } else {
+            for (var i = 0; i < _requestMethods.length; i++) {
+                if (typeof _el[_requestMethods[i]] === "function") {
+                    _el[_requestMethods[i]]();
+                    break;
+                }
+            }
+        }
+    });
+    this.$.find(".Rk-AddNode-Button").click(function() {
+        if (_this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) {
+            _this.click_mode = false;
+            _this.notif_$.hide();
+        } else {
+            _this.click_mode = Rkns.Renderer._CLICKMODE_ADDNODE;
+            _this.notif_$.html(_renkan.l10n.notif_add_node).fadeIn();
+        }
+    });
+    this.$.find(".Rk-AddEdge-Button").click(function() {
+        if (_this.click_mode === Rkns.Renderer._CLICKMODE_STARTEDGE || _this.click_mode === Rkns.Renderer._CLICKMODE_ENDEDGE) {
+            _this.click_mode = false;
+            _this.notif_$.hide();
+        } else {
+            _this.click_mode = Rkns.Renderer._CLICKMODE_STARTEDGE;
+            _this.notif_$.html(_renkan.l10n.notif_start_edge).fadeIn();
+        }
+    });
+    this.$.find(".Rk-TopBar-Button").mouseover(function() {
+        Rkns.$(this).find(".Rk-TopBar-Tooltip").show();
+    }).mouseout(function() {
+        Rkns.$(this).find(".Rk-TopBar-Tooltip").hide();
+    });
+    
+    paper.view.onResize = function(_event) {
+        _this.offset = _this.offset.add(_event.delta.divide(2));
+        _this.redraw();
+    }
+    
+    var _thRedraw = Rkns._.throttle(function() {
+        _this.redraw();
+    },50);
+    
+    this.addRepresentations("Node", this.renkan.project.get("nodes"));
+    this.addRepresentations("Edge", this.renkan.project.get("edges"));
+    this.renkan.project.get("users").each(function(_user) {
+        _this.addUser(_user);
+    })
+    
+    this.renkan.project.on("add:users", function(_user) {
+        _this.addUser(_user);
+    });
+    this.renkan.project.on("add:nodes", function(_node) {
+        _this.addRepresentation("Node", _node);
+        _thRedraw();
+    });
+    this.renkan.project.on("add:edges", function(_edge) {
+        _this.addRepresentation("Edge", _edge);
+        _thRedraw();
+    });
+    
+    this.redraw();
+}
+
+Rkns.Renderer.Scene.prototype.template = Rkns._.template(
+    '<div class="Rk-TopBar"><h3 class="Rk-PadTitle"><%=l10n.untitled_project%></h3>'
+    + '<div class="Rk-Users"><div class="Rk-CurrentUser"><span class="Rk-CurrentUser-Color"></span><span class="Rk-CurrentUser-Name">&lt;unknown user&gt;</span></div><ul class="Rk-UserList"></ul></div>'
+    + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-FullScreen-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%=l10n.full_screen%></div></div></div>'
+    + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddNode-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%=l10n.add_node%></div></div></div>'
+    + '<div class="Rk-TopBar-Separator"></div><div class="Rk-TopBar-Button Rk-AddEdge-Button"><div class="Rk-TopBar-Tooltip"><div class="Rk-TopBar-Tooltip-Tip"></div><div class="Rk-TopBar-Tooltip-Contents"><%=l10n.add_edge%></div></div></div>'
+    + '<div class="Rk-TopBar-Separator"></div></div>'
+    + '<canvas class="Rk-Canvas" resize></canvas><div class="Rk-Editor"><div class="Rk-Notifications"></div>'
+    + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%=l10n.zoom_in%>"></div><div class="Rk-ZoomOut" title="<%=l10n.zoom_out%>"></div></div>'
+    + '</div>'
+);
+
+Rkns.Renderer.Scene.prototype.addToBundles = function(_edgeRepr) {
+    var _bundle = Rkns._(this.bundles).find(function(_bundle) {
+        return ( 
+            ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation )
+            || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )
+        );
+    });
+    if (typeof _bundle !== "undefined") {
+        _bundle.edges.push(_edgeRepr)
+    } else {
+        _bundle = {
+            from: _edgeRepr.from_representation,
+            to: _edgeRepr.to_representation,
+            edges: [ _edgeRepr ],
+            getPosition: function(_er) {
+                var _dir = (_er.from_representation === this.from) ? 1 : -1;
+                return _dir * ( Rkns._(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 );
+            }
+        }
+        this.bundles.push(_bundle);
+    }
+    return _bundle;
+}
+
+Rkns.Renderer.Scene.prototype.setScale = function(_newScale) {
+    this.scale = _newScale;
+    this.redraw();
+}
+
+Rkns.Renderer.Scene.prototype.autoScale = function() {
+    var nodes = this.renkan.project.get("nodes")
+    if (nodes.length > 1) {
+        var _xx = nodes.map(function(_node) { return _node.get("position").x }),
+            _yy = nodes.map(function(_node) { return _node.get("position").y }),
+            _minx = Math.min.apply(Math, _xx),
+            _miny = Math.min.apply(Math, _yy),
+            _maxx = Math.max.apply(Math, _xx),
+            _maxy = Math.max.apply(Math, _yy);
+        var _scale = Math.min((paper.view.size.width - 2 * Rkns.Renderer._MARGIN_X) / (_maxx - _minx), (paper.view.size.height - 2 * Rkns.Renderer._MARGIN_Y) / (_maxy - _miny));
+        this.offset = paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(_scale));
+        this.setScale(_scale);
+    }
+    if (nodes.length === 1) {
+        this.offset = paper.view.center.subtract(new paper.Point([nodes.at(0).get("position").x, nodes.at(0).get("position").y]));
+        this.setScale(1);
+    }
+}
+
+Rkns.Renderer.Scene.prototype.toPaperCoords = function(_point) {
+    return _point.multiply(this.scale).add(this.offset);
+}
+
+
+Rkns.Renderer.Scene.prototype.toModelCoords = function(_point) {
+    return _point.subtract(this.offset).divide(this.scale);
+}
+
+Rkns.Renderer.Scene.prototype.addRepresentation = function(_type, _model) {
+    var _repr = new Rkns.Renderer[_type](this, _model);
+    this.representations.push(_repr);
+    return _repr;
+}
+
+Rkns.Renderer.Scene.prototype.addRepresentations = function(_type, _collection) {
+    var _this = this;
+    _collection.forEach(function(_model) {
+        _this.addRepresentation(_type, _model);
+    });
+}
+
+Rkns.Renderer.Scene.prototype.userTemplate = Rkns._.template(
+    '<li class="Rk-User"><span class="Rk-UserColor" style="background:<%=background%>;"></span><%=name%></li>'
+);
+
+Rkns.Renderer.Scene.prototype.addUser = function(_user) {
+    if (_user.get("_id") === this.renkan.current_user) {
+        this.$.find(".Rk-CurrentUser-Name").text(_user.get("title"));
+        this.$.find(".Rk-CurrentUser-Color").css("background", _user.get("color"));
+    } else {
+        this.$.find(".Rk-UserList").append(
+            Rkns.$(
+                this.userTemplate({
+                    name: _user.get("title"),
+                    background: _user.get("color")
+                })
+            )
+        );
+    }
+}
+
+Rkns.Renderer.Scene.prototype.removeRepresentation = function(_representation) {
+    _representation.destroy();
+    this.representations = Rkns._(this.representations).reject(
+        function(_repr) {
+            return _repr == _representation
+        }
+    );
+}
+
+Rkns.Renderer.Scene.prototype.getRepresentationByModel = function(_model) {
+    return Rkns._(this.representations).find(function(_repr) {
+        return _repr.model === _model;
+    });
+}
+
+Rkns.Renderer.Scene.prototype.removeRepresentationsOfType = function(_type) {
+    var _representations = Rkns._(this.representations).filter(function(_repr) {
+            return _repr.type == _type;
+        }),
+        _this = this;
+    Rkns._(_representations).each(function(_repr) {
+        _this.removeRepresentation(_repr);
+    });
+}
+
+Rkns.Renderer.Scene.prototype.highlightModel = function(_model) {
+    var _repr = this.getRepresentationByModel(_model);
+    if (_repr) {
+        _repr.highlight();
+    }
+}
+
+Rkns.Renderer.Scene.prototype.unhighlightAll = function(_model) {
+    Rkns._(this.representations).each(function(_repr) {
+        _repr.unhighlight();
+    });
+}
+
+Rkns.Renderer.Scene.prototype.redraw = function() {
+    Rkns._(this.representations).each(function(_representation) {
+        _representation.redraw();
+    });
+    paper.view.draw();
+}
+
+Rkns.Renderer.Scene.prototype.addTempEdge = function(_from, _point) {
+    var _tmpEdge = this.addRepresentation("TempEdge",null);
+    _tmpEdge.end_pos = _point;
+    _tmpEdge.from_representation = _from;
+    _tmpEdge.redraw();
+    this.click_target = _tmpEdge;
+}
+
+Rkns.Renderer.Scene.prototype.findTarget = function(_hitResult) {
+    if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+        var _newTarget = _hitResult.item.__representation;
+        if (this.selected_target !== _hitResult.item.__representation) {
+            if (this.selected_target) {
+                this.selected_target.unselect(_newTarget);
+            }
+            _newTarget.select(this.selected_target);
+            this.selected_target = _newTarget;
+        }
+    } else {
+        if (this.selected_target) {
+            this.selected_target.unselect(null);
+        }
+        this.selected_target = null;
+    }
+}
+
+Rkns.Renderer.Scene.prototype.onMouseMove = function(_event) {
+    var _hitResult = paper.project.hitTest(_event.point);
+    if (this.is_dragging) {
+        if (this.click_target && typeof this.click_target.paperShift === "function") {
+            this.click_target.paperShift(_event.delta);
+        } else {
+            this.offset = this.offset.add(_event.delta);
+            this.redraw();
+        }
+    } else {
+        this.findTarget(_hitResult);
+    }
+}
+
+Rkns.Renderer.Scene.prototype.onMouseDown = function(_event) {
+    if (!this.click_target || this.click_target.type !== "temp-edge") {
+        this.is_dragging = false;
+        var _hitResult = paper.project.hitTest(_event.point);
+        if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+            this.click_target = _hitResult.item.__representation;
+            if (this.click_target.type === "Node-link-button") {
+                this.removeRepresentationsOfType("editor");
+                this.addTempEdge(this.click_target.node_representation, _event.point);
+            }
+        } else {
+            this.click_target = null;
+            if (this.click_mode === Rkns.Renderer._CLICKMODE_ADDNODE) {
+                var _coords = this.toModelCoords(_event.point),
+                    _data = {
+                        id: Rkns.Utils.getUID('node'),
+                        created_by: this.renkan.current_user,
+                        position: {
+                            x: _coords.x,
+                            y: _coords.y
+                        }
+                    };
+                    _node = this.renkan.project.addNode(_data);
+                this.getRepresentationByModel(_node).openEditor();
+            }
+        }
+    }
+    if (this.click_mode) {
+        if (this.click_mode === Rkns.Renderer._CLICKMODE_STARTEDGE && this.click_target && this.click_target.type === "Node") {
+            this.removeRepresentationsOfType("editor");
+            this.addTempEdge(this.click_target, _event.point);
+            this.click_mode = Rkns.Renderer._CLICKMODE_ENDEDGE;
+            this.notif_$.fadeOut(function() {
+                Rkns.$(this).html(_renkan.l10n.notif_end_edge).fadeIn();
+            });
+        } else {
+            this.notif_$.hide();
+            this.click_mode = false;
+        }
+    }
+}
+
+Rkns.Renderer.Scene.prototype.onMouseDrag = function(_event) {
+    this.is_dragging = true;
+    this.onMouseMove(_event);
+}
+
+Rkns.Renderer.Scene.prototype.onMouseUp = function(_event) {
+    if (this.click_target) {
+        var _off = this.canvas_$.offset();
+        this.click_target.mouseup(
+            {
+                point: new paper.Point([
+                    _event.pageX - _off.left,
+                    _event.pageY - _off.top
+                ])
+            }
+        );
+    } else {
+        this.click_target = null;
+        this.is_dragging = false;
+    }
+}
+
+Rkns.Renderer.Scene.prototype.onScroll = function(_event, _scrolldelta) {
+    this.totalScroll += _scrolldelta;
+    if (Math.abs(this.totalScroll) >= 1) {
+        var _off = this.canvas_$.offset(),
+            _delta = new paper.Point([
+                _event.pageX - _off.left,
+                _event.pageY - _off.top
+            ]).subtract(this.offset).multiply( Math.SQRT2 - 1 );
+        if (this.totalScroll > 0) {
+            this.offset = this.offset.subtract(_delta);
+            this.setScale( this.scale * Math.SQRT2 );
+        } else {
+            this.offset = this.offset.add(_delta.divide( Math.SQRT2 ));
+            this.setScale( this.scale * Math.SQRT1_2);
+        }
+        this.totalScroll = 0;
+        this.redraw();
+    }
+}
+
+Rkns.Renderer.Scene.prototype.onDoubleClick = function(_event) {
+    var _off = this.canvas_$.offset(),
+        _point = new paper.Point([
+            _event.pageX - _off.left,
+            _event.pageY - _off.top
+        ]);
+    var _hitResult = paper.project.hitTest(_point);
+    if (!_hitResult || typeof _hitResult.item.__representation === "undefined") {
+        var _coords = this.toModelCoords(_point),
+            _data = {
+                id: Rkns.Utils.getUID('node'),
+                created_by: this.renkan.current_user,
+                position: {
+                    x: _coords.x,
+                    y: _coords.y
+                }
+            };
+            _node = this.renkan.project.addNode(_data);
+            this.getRepresentationByModel(_node).openEditor();
+    }
+    paper.view.draw();
+}
+
+Rkns.Renderer.Scene.prototype.onMouseEnter = function(_event) {
+    var _newEl = this.renkan.selected_bin_item;
+    if (_newEl) {
+        var _off = this.canvas_$.offset(),
+            _point = new paper.Point([
+                _event.pageX - _off.left,
+                _event.pageY - _off.top
+            ]),
+            _coords = this.toModelCoords(_point),
+            _data = {
+                id: Rkns.Utils.getUID('node'),
+                created_by: this.renkan.current_user,
+                uri: _newEl.uri,
+                title: _newEl.title,
+                description: _newEl.description,
+                image: _newEl.image,
+                position: {
+                    x: _coords.x,
+                    y: _coords.y
+                }
+            };
+        var _node = this.renkan.project.addNode(_data);
+        this.renkan.selected_bin_item = null;
+        this.is_dragging = true;
+        this.click_target = this.getRepresentationByModel(_node);
+    }
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/random-data.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,42 @@
+Rkns.randomData = function(_renkan, _opts) {
+    _opts = _opts || {};
+    _opts.user_count = _opts.user_count || 5;
+    _opts.node_count = _opts.node_count || 20;
+    _opts.edge_count = _opts.edge_count || 2 * _opts.node_count;
+    _opts.user_colors = _opts.user_colors || ["#ff0000", "#008000", "#0000ff", "#808000", "#808080", "#c000c0", "#00c0c0"];
+    var _proj = _renkan.project
+    for (var i = 0; i < _opts.user_count; i++) {
+        _proj.addUser({
+            id: "user-"+i,
+            title: "User #"+(1+i),
+            color: _opts.user_colors[i]
+        });
+    }
+    for (var i = 0; i < _opts.node_count; i++) {
+        _proj.addNode({
+            id: "node-"+i,
+            title: "Node #"+(1+i),
+            created_by: "user-" + Math.floor(_opts.user_count*Math.random()),
+            position: {
+                x: 300 * Math.cos(2 * Math.PI * i / _opts.node_count),
+                y: 300 * Math.sin(2 * Math.PI * i / _opts.node_count)
+            }
+        });
+    }
+    for (var i = 0; i < _opts.node_count; i++) {
+        var _from, _to;
+        _from = _to = Math.floor(_opts.node_count*Math.random());
+        while(_from === _to) {
+            _to = Math.floor(_opts.node_count*Math.random());
+        }
+        _proj.addEdge({
+            id: "edge-"+i,
+            title: "Edge #"+(1+i),
+            created_by: "user-" + Math.floor(_opts.user_count*Math.random()),
+            from: "node-" + _from,
+            to: "node-" + _to
+        });
+    }
+    _renkan.current_user = "user-0";
+    _renkan.renderer.autoScale();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/renkan-publish.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,1079 @@
+/* 
+ *  Copyright 2012 Institut de recherche et d'innovation 
+ *  contributor(s) : Yves-Marie Haussonne, Raphael Velt, Samuel Huron
+ *   
+ *  contact@iri.centrepompidou.fr
+ *  http://www.iri.centrepompidou.fr 
+ *   
+ *  This software is a computer program whose purpose is to show and add annotations on a video .
+ *  This software is governed by the CeCILL-C license under French law and
+ *  abiding by the rules of distribution of free software. You can  use, 
+ *  modify and/ or redistribute the software under the terms of the CeCILL-C
+ *  license as circulated by CEA, CNRS and INRIA at the following URL
+ *  "http://www.cecill.info". 
+ *  
+ *  The fact that you are presently reading this means that you have had
+ *  knowledge of the CeCILL-C license and that you accept its terms.
+*/
+
+if (typeof Rkns !== "object") {
+    Rkns = {}
+}
+
+Rkns.$ = jQuery;
+
+Rkns._ = _;
+
+Rkns.i18n = {
+    en: {
+        zoom_in: "Zoom In",
+        zoom_out: "Zoom Out",
+        see_in_project: 'See also <b>"{node}"</b> in <b>"{project}"</b>'
+    }
+}
+
+Rkns.Utils = {
+    inherit : function(_baseClass) {
+        var _class = function() {
+            _baseClass.apply(this, Array.prototype.slice.call(arguments, 0));
+            if (typeof this._init == "function") {
+                this._init.apply(this, Array.prototype.slice.call(arguments, 0));
+            }
+        }
+        _class.prototype = new _baseClass();
+        return _class;
+    }
+}
+
+Rkns.Models = {};
+
+Rkns.Models.getUID = function(obj) {
+    var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
+        var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
+        return v.toString(16);
+    });
+    return obj.type + "-" + guid; 
+};
+
+Rkns.Models.RenkanModel = Backbone.RelationalModel.extend({
+    idAttribute : "_id",
+    constructor: function(options) {
+
+        if (typeof options !== "undefined") {
+            options._id = options._id || options.id || Rkns.Models.getUID(this);
+            options.title = options.title || "(untitled " + this.type + ")";
+            options.description = options.description || "";
+            options.uri = options.uri || "";
+
+            if(typeof this.prepare === "function") {
+                options = this.prepare(options);
+            }
+        }
+        Backbone.RelationalModel.prototype.constructor.call(this, options);
+    },
+    validate: function() {
+        if(!this.type) {
+            return "object has no type";
+        }
+    },
+    addReference : function(_options, _propName, _list, _id, _default) {
+        var _element = _list.get(_id);
+        if (typeof _element === "undefined" && typeof _default !== "undefined") {
+            _options[_propName ] = _default;
+        }
+        else {
+            _options[_propName ] = _element;
+        }
+    }
+});
+    
+// USER
+Rkns.Models.User = Rkns.Models.RenkanModel.extend({
+    type: "user",
+    prepare: function(options) {
+        options.color = options.color || "#666666";
+        return options;
+    },
+    toJSON: function() {
+        return {
+            id: this.get("_id"),
+            title: this.get("title"),
+            uri: this.get("uri"),
+            description: this.get("description"),
+            color: this.get("color"),
+        }
+    },
+});
+
+// NODE
+Rkns.Models.Node = Rkns.Models.RenkanModel.extend({
+    type: "node",
+    relations: [{
+        type: Backbone.HasOne,
+        key: "created_by",
+        relatedModel: Rkns.Models.User
+    }],
+    prepare: function(options) {
+        project = options.project;
+        this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user);
+        options.description = options.description || "";
+        return options;
+    },
+    toJSON: function() {
+        return {
+            id: this.get("_id"),
+            title: this.get("title"),
+            uri: this.get("uri"),
+            description: this.get("description"),
+            position: this.get("position"),
+            image: this.get("image"),
+            created_by: this.get("created_by").get("_id")
+        }
+    },
+});
+
+// EDGE
+Rkns.Models.Edge = Rkns.Models.RenkanModel.extend({
+    type: "edge",
+    relations: [
+      {
+        type: Backbone.HasOne,
+        key: "created_by",
+        relatedModel: Rkns.Models.User
+      },
+      {
+        type: Backbone.HasOne,
+        key: "from",
+        relatedModel: Rkns.Models.Node
+      },
+      {
+        type: Backbone.HasOne,
+        key: "to",
+        relatedModel: Rkns.Models.Node
+      },
+    ],
+    prepare: function(options) {
+        project = options.project;
+        this.addReference(options, "created_by", project.get("users"), options.created_by, project.current_user);
+        this.addReference(options, "from", project.get("nodes"), options.from);
+        this.addReference(options, "to", project.get("nodes"), options.to);
+        return options;
+    },
+    toJSON: function() {
+        return {
+            id: this.get("_id"),
+            title: this.get("title"),
+            uri: this.get("uri"),
+            description: this.get("description"),
+            from: this.get("from").get("_id"),
+            to: this.get("to").get("_id"),
+            created_by: this.get("created_by").get("_id"),
+        }
+    },
+});
+    
+// PROJECT
+Rkns.Models.Project = Rkns.Models.RenkanModel.extend({
+    type: "project",
+    relations: [
+      {
+        type: Backbone.HasMany,
+        key: "users",
+        relatedModel: Rkns.Models.User,
+        reverseRelation: {
+            key: 'project',
+            includeInJSON: '_id'
+        },
+      },
+      {
+        type: Backbone.HasMany,
+        key: "nodes",
+        relatedModel: Rkns.Models.Node,
+        reverseRelation: {
+            key: 'project',
+            includeInJSON: '_id'
+        },
+      },
+      {
+        type: Backbone.HasMany,
+        key: "edges",
+        relatedModel: Rkns.Models.Edge,
+        reverseRelation: {
+            key: 'project',
+            includeInJSON: '_id'
+        },
+      }
+    ],
+    addUser: function(_props) {
+        _props.project = this;
+        var _user = new Rkns.Models.User(_props);
+        this.get("users").push(_user);
+        return _user;
+    },
+    addNode: function(_props) {
+        _props.project = this;
+        var _node = new Rkns.Models.Node(_props);
+        this.get("nodes").push(_node);
+        return _node;
+    },
+    addEdge: function(_props) {
+        _props.project = this;
+        var _edge = new Rkns.Models.Edge(_props);
+        this.get("edges").push(_edge);
+        return _edge;
+    },
+    removeNode: function(_model) {
+        this.get("nodes").remove(_model);
+    },
+    removeEdge: function(_model) {
+        this.get("edges").remove(_model);
+    },
+    validate: function(options) {
+        var _project = this;
+        Rkns._(options.users).each(function(_item) {
+            _item.project = _project;
+        });
+        Rkns._(options.nodes).each(function(_item) {
+            _item.project = _project;
+        });
+        Rkns._(options.edges).each(function(_item) {
+            _item.project = _project;
+        });
+    },
+    // Add event handler to remove edges when a node is removed
+    initialize: function() {
+        var _this = this;
+        this.on("remove:nodes", function(_node) {
+            _this.get("edges").remove(
+                _this.get("edges").filter(function(_edge) {
+                    return _edge.get("from") == _node || _edge.get("to") == _node;
+                })
+            );
+        });
+    }
+});
+
+/* Point of entry */
+
+Rkns.Renkan = function(_opts) {
+    if (typeof _opts.language !== "string" || typeof Rkns.i18n[_opts.language] == "undefined") {
+        _opts.language = "en";
+    }
+    if (typeof _opts.container !== "string") {
+        _opts.container = "renkan";
+    }
+    if (typeof _opts.search !== "object" || !_opts.search) {
+        _opts.search = [];
+    }
+    this.projects = [];
+    this.l10n = Rkns.i18n[_opts.language];
+    this.$ = Rkns.$("#" + _opts.container);
+    this.$.html(this.template());
+    this.uris = {};
+    this.active_project = null;
+    this.renderer = null;
+}
+
+Rkns.Renkan.prototype.template = Rkns._.template(
+    '<div class="Rk-Render"></div><ul class="Rk-Project-List"></ul>'
+);
+
+Rkns.Renkan.prototype.addProject = function(_opts) {
+    var _proj = new Rkns.Models.Project(),
+        _li = Rkns.$("<li>").addClass("Rk-Project").text("Untitled #" + (1+this.projects.length));
+    this.$.find(".Rk-Project-List").append(_li);
+    Rkns.loadJson(_proj, _opts);
+    var _this = this;
+    _li.click(function() {
+        _this.renderProject(_proj);
+    });
+    _proj.on("change:title", function() {
+        _li.html(_proj.get("title"));
+    });
+    _proj.on("select", function() {
+        _this.$.find(".Rk-Project").removeClass("active");
+        _li.addClass("active");
+    });
+    _proj.on("add:nodes", function(_node) {
+        var _uri = _node.get("uri");
+        if (_uri) {
+            if (typeof _this.uris[_uri] === "undefined") {
+                _this.uris[_uri] = [];
+            }
+            _this.uris[_uri].push(_node);
+        }
+    });
+    this.projects.push(_proj);
+    return _proj;
+}
+
+Rkns.Renkan.prototype.renderProject = function(_project) {
+    if (_project) {
+        if (this.renderer) {
+            this.renderer.destroy();
+        }
+        this.active_project = _project;
+        this.renderer = new Rkns.Renderer.Scene(this, _project);
+        this.renderer.autoScale();
+        _project.trigger("select");
+    }
+}
+
+Rkns.Renkan.prototype.renderProjectAt = function(_index) {
+    this.renderProject(this.projects[_index]);
+}
+
+Rkns.loadJson = function(_proj, _opts) {
+    if (typeof _opts.http_method == "undefined") {
+        _opts.http_method = 'PUT';
+    }
+    var _load = function() {
+        Rkns.$.getJSON(_opts.url, function(_data) {
+            _proj.set(_data);
+            if (typeof _opts.callback === "function") {
+                _opts.callback(_proj);
+            }
+        });
+    }
+    _load();
+}
+
+Rkns.Renderer = {
+    _MARGIN_X: 80,
+    _MARGIN_Y: 50,
+    _MIN_DRAG_DISTANCE: 2,
+    _NODE_RADIUS: 20,
+    _NODE_FONT_SIZE: 10,
+    _EDGE_FONT_SIZE: 9,
+    _NODE_MAX_CHAR: 30,
+    _EDGE_MAX_CHAR: 20,
+    _ARROW_LENGTH: 16,
+    _ARROW_WIDTH: 8,
+    _TOOLTIP_ARROW_LENGTH : 15,
+    _TOOLTIP_ARROW_WIDTH : 26,
+    _TOOLTIP_MARGIN : 10,
+    _TOOLTIP_PADDING : 8,
+    _TOOLTIP_GRADIENT : new paper.Gradient(['#f0f0f0', '#d0d0d0'])
+}
+
+Rkns.Renderer.Utils = {
+    shortenText : function(_text,_length) {
+        var _rgxp = new RegExp('^(.{' + _length + '}).+$');
+        return _text.replace(/(\n|\r|\r\n)/mg,' ').replace(_rgxp,'$1…');
+    },
+    drawTooltip : function(_coords, _path, _width, _xmargin, _selector) {
+        _selector.css({
+            width: (_width - 2* Rkns.Renderer._TOOLTIP_PADDING),
+        });
+        var _height = _selector.outerHeight() + 2* Rkns.Renderer._TOOLTIP_PADDING,
+            _isLeft = (_coords.x < paper.view.center.x ? 1 : -1),
+            _left = _coords.x + _isLeft * ( _xmargin + Rkns.Renderer._TOOLTIP_ARROW_LENGTH ),
+            _right = _coords.x + _isLeft * ( _xmargin + Rkns.Renderer._TOOLTIP_ARROW_LENGTH + _width ),
+            _top = _coords.y - _height / 2;
+        if (_top < Rkns.Renderer._TOOLTIP_MARGIN) {
+            _top = Math.min( Rkns.Renderer._TOOLTIP_MARGIN, _coords.y - Rkns.Renderer._TOOLTIP_ARROW_WIDTH / 2 );
+        }
+        var _bottom = _top + _height;
+        if (_bottom > (paper.view.size.height - Rkns.Renderer._TOOLTIP_MARGIN)) {
+            _bottom = Math.max( paper.view.size.height - Rkns.Renderer._TOOLTIP_MARGIN, _coords.y + Rkns.Renderer._TOOLTIP_ARROW_WIDTH / 2 );
+            _top = _bottom - _height;
+        }
+        _path.segments[0].point
+            = _path.segments[7].point
+            = _coords.add([_isLeft * _xmargin, 0]);
+        _path.segments[1].point.x
+            = _path.segments[2].point.x
+            = _path.segments[5].point.x
+            = _path.segments[6].point.x
+            = _left;
+        _path.segments[3].point.x
+            = _path.segments[4].point.x
+            = _right;
+        _path.segments[2].point.y
+            = _path.segments[3].point.y
+            = _top;
+        _path.segments[4].point.y
+            = _path.segments[5].point.y
+            = _bottom;
+        _path.segments[1].point.y = _coords.y - Rkns.Renderer._TOOLTIP_ARROW_WIDTH / 2;
+        _path.segments[6].point.y = _coords.y + Rkns.Renderer._TOOLTIP_ARROW_WIDTH / 2;
+        _path.closed = true;
+        _path.fillColor = new paper.GradientColor(Rkns.Renderer._TOOLTIP_GRADIENT, [0,_top], [0, _bottom]);
+        _selector.css({
+            left: (Rkns.Renderer._TOOLTIP_PADDING + Math.min(_left, _right)),
+            top: (Rkns.Renderer._TOOLTIP_PADDING + _top)
+        });
+    }
+}
+
+Rkns.Renderer._BaseRepresentation = function(_renderer, _model) {
+    if (typeof _renderer !== "undefined") {
+        this.renderer = _renderer;
+        this.project = _renderer.project;
+        this.model = _model;
+        if (this.model) {
+            var _this = this;
+            this._selectBinding = function() {
+                _this.select();
+            };
+            this._unselectBinding = function() {
+                _this.unselect();
+            }
+            this._changeBinding = function() {
+                _this.redraw();
+            }
+            this._removeBinding = function() {
+                _renderer.removeRepresentation(_this);
+                _renderer.redraw();
+            }
+            this.model.on("change", this._changeBinding );
+            this.model.on("remove", this._removeBinding );
+            this.model.on("select", this._selectBinding );
+            this.model.on("unselect", this._unselectBinding );
+        }
+    }
+}
+
+Rkns.Renderer._BaseRepresentation.prototype.super = function(_func) {
+    Rkns.Renderer._BaseRepresentation.prototype[_func].apply(this, Array.prototype.slice.call(arguments, 1));
+}
+
+Rkns.Renderer._BaseRepresentation.prototype.select = function() {}
+
+Rkns.Renderer._BaseRepresentation.prototype.unselect = function() {}
+
+Rkns.Renderer._BaseRepresentation.prototype.mouseup = function() {}
+
+Rkns.Renderer._BaseRepresentation.prototype.destroy = function() {
+    if (this.model) {
+        this.model.off("change", this._changeBinding );
+        this.model.off("remove", this._removeBinding );
+        this.model.off("select", this._selectBinding);
+        this.model.off("unselect", this._unselectBinding);
+    }
+}
+
+Rkns.Renderer.Node = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.Node.prototype._init = function() {
+    this.renderer.node_layer.activate();
+    this.type = "Node";
+    this.circle = new paper.Path.Circle([0, 0], Rkns.Renderer._NODE_RADIUS);
+    this.circle.fillColor = '#ffffff';
+    this.circle.__representation = this;
+    this.title = new paper.PointText([0,0]);
+    this.title.characterStyle = {
+        fontSize: Rkns.Renderer._NODE_FONT_SIZE,
+        fillColor: 'black'
+    };
+    this.title.paragraphStyle.justification = 'center';
+    this.title.__representation = this;
+    this.model_coords = new paper.Point(this.model.get("position"));
+}
+
+Rkns.Renderer.Node.prototype.redraw = function() {
+    this.paper_coords = this.renderer.toPaperCoords(this.model_coords);
+    this.circle.position = this.paper_coords;
+    this.title.content = Rkns.Renderer.Utils.shortenText(this.model.get("title"), Rkns.Renderer._NODE_MAX_CHAR);
+    this.title.position = this.paper_coords.add([0, 2 * Rkns.Renderer._NODE_RADIUS]);
+    this.circle.strokeColor = this.model.get("created_by").get("color");
+    var _img = this.model.get("image");
+    if (_img && _img !== this.img) {
+        var _image = new Image(),
+            _this = this;
+        _image.onload = function() {
+            if (_this.node_image) {
+                _this.node_image.remove();
+            }
+            _this.renderer.node_layer.activate();
+            var _ratio = Math.min(1, 2 * Rkns.Renderer._NODE_RADIUS / _image.width, 2 * Rkns.Renderer._NODE_RADIUS / _image.height );
+            var _raster = new paper.Raster(_image);
+            var _clip = new paper.Path.Circle([0, 0], Rkns.Renderer._NODE_RADIUS);
+            _raster.scale(_ratio);
+            _this.node_image = new paper.Group(_clip, _raster);
+            _this.node_image.opacity = _this.selected ? .5 : .9;
+            /* This is a workaround to allow clipping at group level */
+            _this.node_image.clipped = true;
+            _this.node_image.position = _this.paper_coords;
+            _this.node_image.__representation = _this;
+            paper.view.draw();
+        }
+        _image.src = _img;
+    }
+    this.img = _img;
+    if (this.node_image) {
+        if (!this.img) {
+            this.node_image.remove();
+            delete this.node_image;
+        } else {
+            this.node_image.position = this.paper_coords;
+        }
+    }
+}
+
+Rkns.Renderer.Node.prototype.paperShift = function(_delta) {
+    this.paper_coords = this.paper_coords.add(_delta);
+    this.model_coords = this.renderer.toModelCoords(this.paper_coords);
+    this.renderer.redraw();
+}
+
+Rkns.Renderer.Node.prototype.openTooltip = function() {
+    this.renderer.removeRepresentationsOfType("tooltip");
+    var _tooltip = this.renderer.addRepresentation("NodeTooltip",null);
+    _tooltip.node_representation = this;
+    _tooltip.draw();
+}
+
+Rkns.Renderer.Node.prototype.select = function() {
+    this.selected = true;
+    this.circle.strokeWidth = 3;
+    this.openTooltip();
+    this.circle.fillColor = "#ffff80";
+    if (this.node_image) {
+        this.node_image.opacity = .5;
+    }
+    paper.view.draw();
+}
+
+Rkns.Renderer.Node.prototype.unselect = function() {
+    this.selected = false;
+    this.circle.strokeWidth = 1;
+    this.circle.fillColor = "#ffffff";
+    if (this.node_image) {
+        this.node_image.opacity = .9;
+    }
+    paper.view.draw();
+}
+
+Rkns.Renderer.Node.prototype.mouseup = function(_event) {
+}
+
+Rkns.Renderer.Node.prototype.destroy = function(_event) {
+    this.super("destroy");
+    this.circle.remove();
+    this.title.remove();
+    if (this.node_image) {
+        this.node_image.remove();
+    }
+}
+
+/* */
+
+Rkns.Renderer.Edge = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.Edge.prototype._init = function() {
+    this.renderer.edge_layer.activate();
+    this.type = "Edge";
+    this.from_representation = this.renderer.getRepresentationByModel(this.model.get("from"));
+    this.to_representation = this.renderer.getRepresentationByModel(this.model.get("to"));
+    this.bundle = this.renderer.addToBundles(this);
+    this.line = new paper.Path();
+    this.line.add([0,0],[0,0],[0,0]);
+    this.line.__representation = this;
+    this.arrow = new paper.Path();
+    this.arrow.add([0,0],[Rkns.Renderer._ARROW_LENGTH,Rkns.Renderer._ARROW_WIDTH / 2],[0,Rkns.Renderer._ARROW_WIDTH]);
+    this.arrow.__representation = this;
+    this.text = new paper.PointText();
+    this.text.characterStyle = {
+        fontSize: Rkns.Renderer._EDGE_FONT_SIZE,
+        fillColor: 'black'
+    };
+    this.text.paragraphStyle.justification = 'center';
+    this.text.__representation = this;
+    this.text_angle = 0;
+    this.arrow_angle = 0;
+}
+
+Rkns.Renderer.Edge.prototype.redraw = function() {
+    var _p0a = this.from_representation.paper_coords,
+        _p1a = this.to_representation.paper_coords,
+        _v = _p1a.subtract(_p0a),
+        _r = _v.length,
+        _u = _v.divide(_r),
+        _group_pos = this.bundle.getPosition(this),
+        _delta = new paper.Point([- _u.y, _u.x]).multiply( 12 * _group_pos ),
+        _p0b = _p0a.add(_delta), /* Adding a 4 px difference */
+        _p1b = _p1a.add(_delta), /* to differentiate inbound and outbound links */
+        _a = _v.angle,
+        _handle = _v.divide(3),
+        _color = this.model.get("created_by").get("color");
+    this.paper_coords = _p0b.add(_p1b).divide(2);
+    this.line.strokeColor = _color;
+    this.line.segments[0].point = _p0a;
+    this.line.segments[1].point = this.paper_coords;
+    this.line.segments[1].handleIn = _handle.multiply(-1);
+    this.line.segments[1].handleOut = _handle;
+    this.line.segments[2].point = _p1a;
+    this.arrow.rotate(_a - this.arrow_angle);
+    this.arrow.fillColor = _color;
+    this.arrow.position = this.paper_coords.subtract(_u.multiply(4));
+    this.arrow_angle = _a;
+    if (_a > 90) {
+        _a -= 180;
+    }
+    if (_a < -90) {
+        _a += 180;
+    }
+    this.text.rotate(_a - this.text_angle);
+    this.text.content = Rkns.Renderer.Utils.shortenText(this.model.get("title"), Rkns.Renderer._EDGE_MAX_CHAR);
+    this.text.position = this.paper_coords;
+    this.text_angle = _a;
+}
+
+Rkns.Renderer.Edge.prototype.openTooltip = function() {
+    this.renderer.removeRepresentationsOfType("tooltip");
+    var _tooltip = this.renderer.addRepresentation("EdgeTooltip",null);
+    _tooltip.edge_representation = this;
+    _tooltip.draw();
+}
+
+Rkns.Renderer.Edge.prototype.select = function() {
+    this.line.strokeWidth = 3;
+    this.openTooltip();
+    paper.view.draw();
+}
+
+Rkns.Renderer.Edge.prototype.unselect = function() {
+    this.line.strokeWidth = 1;
+    paper.view.draw();
+}
+
+Rkns.Renderer.Edge.prototype.mouseup = function(_event) {
+}
+
+Rkns.Renderer.Edge.prototype.paperShift = function(_delta) {
+    this.from_representation.paperShift(_delta);
+    this.to_representation.paperShift(_delta);
+    this.renderer.redraw();
+}
+
+Rkns.Renderer.Edge.prototype.destroy = function() {
+    this.super("destroy");
+    this.line.remove();
+    this.arrow.remove();
+    this.text.remove();
+    var _this = this;
+    this.bundle.edges = Rkns._(this.bundle.edges).reject(function(_edge) {
+        return _edge === _this;
+    });
+}
+
+/* */
+
+Rkns.Renderer.NodeTooltip = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.NodeTooltip.prototype._init = function() {
+    this.renderer.overlay_layer.activate();
+    this.type = "tooltip";
+    this.tooltip_block = new paper.Path();
+    var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
+    this.tooltip_block.add.apply(this.tooltip_block, _pts);
+    this.tooltip_block.strokeWidth = 2;
+    this.tooltip_block.strokeColor = "#999999";
+    this.tooltip_block.fillColor = "#e0e0e0";
+    this.tooltip_block.opacity = .8;
+    this.tooltip_$ = Rkns.$('<div>')
+        .appendTo(this.renderer.tooltip_$)
+        .css({
+            position: "absolute",
+            opacity: .8
+        })
+        .hide();
+}
+
+Rkns.Renderer.NodeTooltip.prototype.template = Rkns._.template(
+    '<h2><span class="Rk-CloseX">&times;</span><%=a%></h2>'
+    + '<p><%-description%></p>'
+    + '<ul class="Rk-Related-List"></ul>'
+);
+
+Rkns.Renderer.NodeTooltip.prototype.draw = function() {
+    var _model = this.node_representation.model,
+        _title = _model.get("title"),
+        _uri = _model.get("uri");
+    this.tooltip_$
+        .html(this.template({
+            a: (_uri ? '<a href="' + _uri + '" target="_blank">' : '' ) + _title + (_uri ? '</a>' : '' ),
+            description: _model.get("description").replace(/(\n|\r|\r\n)/mg,' ').substr(0,180).replace(/(^.{150,179})[\s].+$/m,'$1&hellip;')
+        }))
+    var _this = this,
+        _renkan = this.renderer.renkan,
+        _uris = _renkan.uris[_uri];
+    Rkns._(_uris).each(function(_othernode) {
+        if (_othernode !== _model && _othernode.get("project") !== _this.project) {
+            var _otherproj = _othernode.get("project"),
+                _nodetitle = _othernode.get("title") || "Untitled node"
+                _projtitle = _otherproj.get("title") || "Untitled node",
+                _html = _renkan.l10n.see_in_project.replace('{node}',Rkns._.escape(_nodetitle)).replace('{project}',Rkns._.escape(_projtitle)),
+                _li = Rkns.$("<li>").addClass("Rk-Related").html(_html);
+            _li.click(function() {
+                _renkan.renderProject(_otherproj);
+                Rkns._.defer(function() {
+                    _othernode.trigger("select");
+                });
+            });
+            _this.tooltip_$.append(_li);
+        }
+    });
+    this.tooltip_$.find(".Rk-CloseX").click(function() {
+        _this.renderer.removeRepresentation(_this);
+        paper.view.draw();
+    });
+    this.redraw();
+}
+
+Rkns.Renderer.NodeTooltip.prototype.redraw = function() {
+    var _coords = this.node_representation.paper_coords;
+    Rkns.Renderer.Utils.drawTooltip(_coords, this.tooltip_block, 250, 15, this.tooltip_$);
+    this.tooltip_$.show();
+}
+
+Rkns.Renderer.NodeTooltip.prototype.destroy = function() {
+    this.tooltip_block.remove();
+    this.tooltip_$.detach();
+}
+
+/* */
+
+Rkns.Renderer.EdgeTooltip = Rkns.Utils.inherit(Rkns.Renderer._BaseRepresentation);
+
+Rkns.Renderer.EdgeTooltip.prototype._init = function() {
+    this.renderer.overlay_layer.activate();
+    this.type = "tooltip";
+    this.tooltip_block = new paper.Path();
+    var _pts = Rkns._(Rkns._.range(8)).map(function() {return [0,0]});
+    this.tooltip_block.add.apply(this.tooltip_block, _pts);
+    this.tooltip_block.strokeWidth = 2;
+    this.tooltip_block.strokeColor = "#999999";
+    this.tooltip_block.fillColor = "#e0e0e0";
+    this.tooltip_block.opacity = .8;
+    this.tooltip_$ = Rkns.$('<div>')
+        .appendTo(this.renderer.tooltip_$)
+        .css({
+            position: "absolute",
+            opacity: .8
+        })
+        .hide();
+}
+
+Rkns.Renderer.EdgeTooltip.prototype.template = Rkns._.template(
+    '<h2><span class="Rk-CloseX">&times;</span><%=a%></h2>'
+    + '<p><%-description%></p>'
+);
+
+Rkns.Renderer.EdgeTooltip.prototype.draw = function() {
+    var _model = this.edge_representation.model,
+        _title = _model.get("title"),
+        _uri = _model.get("uri");
+    this.tooltip_$
+        .html(this.template({
+            a: (_uri ? '<a href="' + _uri + '" target="_blank">' : '' ) + _title + (_uri ? '</a>' : '' ),
+            description: _model.get("description").replace(/(\n|\r|\r\n)/mg,' ').substr(0,180).replace(/(^.{150,179})[\s].+$/m,'$1&hellip;')
+        }));
+    this.redraw();
+    var _this = this;
+    this.tooltip_$.find(".Rk-CloseX").click(function() {
+        _this.renderer.removeRepresentation(_this);
+        paper.view.draw();
+    });
+}
+
+Rkns.Renderer.EdgeTooltip.prototype.redraw = function() {
+    var _coords = this.edge_representation.paper_coords;
+    Rkns.Renderer.Utils.drawTooltip(_coords, this.tooltip_block, 250, 5, this.tooltip_$);
+    this.tooltip_$.show();
+    paper.view.draw();
+}
+
+Rkns.Renderer.EdgeTooltip.prototype.destroy = function() {
+    this.tooltip_block.remove();
+    this.tooltip_$.detach();
+}
+
+/* */
+
+Rkns.Renderer.Scene = function(_renkan, _project) {
+    this.renkan = _renkan;
+    this.project = _project;
+    this.$ = Rkns.$(".Rk-Render");
+    this.representations = [];
+    this.$.html(this.template({
+        width: this.$.width(),
+        height: this.$.height(),
+        l10n: _renkan.l10n
+    }))
+    this.canvas_$ = this.$.find(".Rk-Canvas");
+    this.tooltip_$ = this.$.find(".Rk-Editor");
+    paper.setup(this.canvas_$[0]);
+    this.scale = 1;
+    this.offset = paper.view.center;
+    this.totalScroll = 0;
+    this.click_target = null;
+    this.selected_target = null;
+    this.edge_layer = new paper.Layer();
+    this.node_layer = new paper.Layer();
+    this.overlay_layer = new paper.Layer();
+    this.bundles = [];
+    var _tool = new paper.Tool(),
+        _this = this;
+    _tool.minDistance = Rkns.Renderer._MIN_DRAG_DISTANCE;
+    _tool.onMouseMove = function(_event) {
+        _this.onMouseMove(_event);
+    }
+    _tool.onMouseDown = function(_event) {
+        _this.onMouseDown(_event);
+    }
+    _tool.onMouseDrag = function(_event) {
+        _this.onMouseDrag(_event);
+    }
+    this.canvas_$.mouseup(function(_event) {
+        _this.onMouseUp(_event);
+    });
+    this.canvas_$.mousewheel(function(_event, _delta) {
+        _this.onScroll(_event, _delta);
+    });
+    this.tooltip_$.find(".Rk-ZoomOut").click(function() {
+        _this.offset = new paper.Point([
+            _this.canvas_$.width(),
+            _this.canvas_$.height()
+        ]).multiply( .5 * ( 1 - Math.SQRT1_2 ) ).add(_this.offset.multiply( Math.SQRT1_2 ));
+        _this.scale *= Math.SQRT1_2;
+        _this.redraw();
+    });
+    this.tooltip_$.find(".Rk-ZoomIn").click(function() {
+        _this.offset = new paper.Point([
+            _this.canvas_$.width(),
+            _this.canvas_$.height()
+        ]).multiply( .5 * ( 1 - Math.SQRT2 ) ).add(_this.offset.multiply( Math.SQRT2 ));
+        _this.scale *= Math.SQRT2;
+        _this.redraw();
+    });
+    paper.view.onResize = function(_event) {
+        _this.offset = _this.offset.add(_event.delta.divide(2));
+        _this.redraw();
+    }
+    
+    var _thRedraw = Rkns._.throttle(function() {
+        _this.redraw();
+    },50);
+    
+    this.addRepresentations("Node", this.project.get("nodes"));
+    this.addRepresentations("Edge", this.project.get("edges"));
+    
+    this._addNodesBinding = function(_node) {
+        _this.addRepresentation("Node", _node);
+        _thRedraw();
+    }
+    this._addEdgesBinding = function(_edge) {
+        _this.addRepresentation("Edge", _edge);
+        _thRedraw();
+    }
+    
+    this.project.on("add:nodes", this._addNodesBinding );
+    this.project.on("add:edges", this._addEdgesBinding );
+    this.redraw();
+}
+
+Rkns.Renderer.Scene.prototype.template = Rkns._.template(
+    '<canvas class="Rk-Canvas" width="<%-width%>" height="<%-height%>"></canvas><div class="Rk-Editor">'
+    + '<div class="Rk-ZoomButtons"><div class="Rk-ZoomIn" title="<%-l10n.zoom_in%>"></div><div class="Rk-ZoomOut" title="<%-l10n.zoom_out%>"></div></div>'
+    + '</div>'
+);
+
+Rkns.Renderer.Scene.prototype.addToBundles = function(_edgeRepr) {
+    var _bundle = Rkns._(this.bundles).find(function(_bundle) {
+        return ( 
+            ( _bundle.from === _edgeRepr.from_representation && _bundle.to === _edgeRepr.to_representation )
+            || ( _bundle.from === _edgeRepr.to_representation && _bundle.to === _edgeRepr.from_representation )
+        );
+    });
+    if (typeof _bundle !== "undefined") {
+        _bundle.edges.push(_edgeRepr)
+    } else {
+        _bundle = {
+            from: _edgeRepr.from_representation,
+            to: _edgeRepr.to_representation,
+            edges: [ _edgeRepr ],
+            getPosition: function(_er) {
+                var _dir = (_er.from_representation === this.from) ? 1 : -1;
+                return _dir * ( Rkns._(this.edges).indexOf(_er) - (this.edges.length - 1) / 2 );
+            }
+        }
+        this.bundles.push(_bundle);
+    }
+    return _bundle;
+}
+
+Rkns.Renderer.Scene.prototype.autoScale = function() {
+    if (this.project.get("nodes").length) {
+        var _xx = this.project.get("nodes").map(function(_node) { return _node.get("position").x }),
+            _yy = this.project.get("nodes").map(function(_node) { return _node.get("position").y }),
+            _minx = Math.min.apply(Math, _xx),
+            _miny = Math.min.apply(Math, _yy),
+            _maxx = Math.max.apply(Math, _xx),
+            _maxy = Math.max.apply(Math, _yy);
+        this.scale = Math.min((paper.view.size.width - 2 * Rkns.Renderer._MARGIN_X) / (_maxx - _minx), (paper.view.size.height - 2 * Rkns.Renderer._MARGIN_Y) / (_maxy - _miny));
+        this.offset = paper.view.center.subtract(new paper.Point([(_maxx + _minx) / 2, (_maxy + _miny) / 2]).multiply(this.scale));
+        this.redraw();
+    }
+}
+
+Rkns.Renderer.Scene.prototype.toPaperCoords = function(_point) {
+    return _point.multiply(this.scale).add(this.offset);
+}
+
+
+Rkns.Renderer.Scene.prototype.toModelCoords = function(_point) {
+    return _point.subtract(this.offset).divide(this.scale);
+}
+
+Rkns.Renderer.Scene.prototype.addRepresentation = function(_type, _model) {
+    var _repr = new Rkns.Renderer[_type](this, _model);
+    this.representations.push(_repr);
+    return _repr;
+}
+
+Rkns.Renderer.Scene.prototype.addRepresentations = function(_type, _collection) {
+    var _this = this;
+    _collection.forEach(function(_model) {
+        _this.addRepresentation(_type, _model);
+    });
+}
+
+Rkns.Renderer.Scene.prototype.removeRepresentation = function(_representation) {
+    _representation.destroy();
+    this.representations = Rkns._(this.representations).reject(
+        function(_repr) {
+            return _repr == _representation
+        }
+    );
+}
+
+Rkns.Renderer.Scene.prototype.getRepresentationByModel = function(_model) {
+    return Rkns._(this.representations).find(function(_repr) {
+        return _repr.model === _model;
+    });
+}
+
+Rkns.Renderer.Scene.prototype.removeRepresentationsOfType = function(_type) {
+    var _representations = Rkns._(this.representations).filter(function(_repr) {
+            return _repr.type == _type;
+        }),
+        _this = this;
+    Rkns._(_representations).each(function(_repr) {
+        _this.removeRepresentation(_repr);
+    });
+}
+
+Rkns.Renderer.Scene.prototype.unselectAll = function() {
+    Rkns._(this.representations).each(function(_repr) {
+        _repr.model.trigger("unselect");
+    });
+}
+
+Rkns.Renderer.Scene.prototype.redraw = function() {
+    Rkns._(this.representations).each(function(_representation) {
+        _representation.redraw();
+    });
+    paper.view.draw();
+}
+
+Rkns.Renderer.Scene.prototype.addTempEdge = function(_from, _point) {
+    var _tmpEdge = this.addRepresentation("TempEdge",null);
+    _tmpEdge.end_pos = _point;
+    _tmpEdge.from_representation = _from;
+    _tmpEdge.redraw();
+    this.click_target = _tmpEdge;
+}
+
+Rkns.Renderer.Scene.prototype.findTarget = function(_hitResult) {
+    if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+        var _newTarget = _hitResult.item.__representation;
+        if (this.selected_target !== _newTarget && _newTarget.model) {
+            if (this.selected_target) {
+                this.selected_target.model.trigger("unselect");
+            }
+            _newTarget.model.trigger("select");
+            this.selected_target = _newTarget;
+        }
+    } else {
+        if (!_hitResult) {
+            this.removeRepresentationsOfType("tooltip");
+        }
+        if (this.selected_target) {
+            this.selected_target.model.trigger("unselect");
+        }
+        this.selected_target = null;
+    }
+}
+
+Rkns.Renderer.Scene.prototype.onMouseMove = function(_event) {
+    var _hitResult = paper.project.hitTest(_event.point);
+    if (this.is_dragging) {
+        if (this.click_target && typeof this.click_target.paperShift === "function") {
+            this.click_target.paperShift(_event.delta);
+        } else {
+            this.offset = this.offset.add(_event.delta);
+            this.redraw();
+        }
+    } else {
+        this.findTarget(_hitResult);
+    }
+}
+
+Rkns.Renderer.Scene.prototype.onMouseDown = function(_event) {
+    this.is_dragging = false;
+    var _hitResult = paper.project.hitTest(_event.point);
+    if (_hitResult && typeof _hitResult.item.__representation !== "undefined") {
+        this.click_target = _hitResult.item.__representation;
+    } else {
+        this.click_target = null;
+    }
+}
+
+Rkns.Renderer.Scene.prototype.onMouseDrag = function(_event) {
+    this.is_dragging = true;
+    this.onMouseMove(_event);
+}
+
+Rkns.Renderer.Scene.prototype.onMouseUp = function(_event) {
+    if (this.click_target) {
+        var _off = this.canvas_$.offset();
+        if (this.click_target.model) {
+            this.click_target.model.trigger("click");
+        }
+    }
+    this.is_dragging = false;
+    this.click_target = null;
+}
+
+Rkns.Renderer.Scene.prototype.onScroll = function(_event, _scrolldelta) {
+    this.totalScroll += _scrolldelta;
+    if (Math.abs(this.totalScroll) >= 1) {
+        var _off = this.canvas_$.offset(),
+            _delta = new paper.Point([
+                _event.pageX - _off.left,
+                _event.pageY - _off.top
+            ]).subtract(this.offset).multiply( Math.SQRT2 - 1 );
+        if (this.totalScroll > 0) {
+            this.offset = this.offset.subtract(_delta);
+            this.scale *= Math.SQRT2;
+        } else {
+            this.offset = this.offset.add(_delta.divide( Math.SQRT2 ));
+            this.scale *= Math.SQRT1_2;
+        }
+        this.totalScroll = 0;
+        this.redraw();
+    }
+}
+
+Rkns.Renderer.Scene.prototype.destroy = function() {
+    this.project.off("add:nodes", this._addNodesBinding );
+    this.project.off("add:edges", this._addEdgesBinding );
+    Rkns._(this.representations).each(function(_repr) {
+        _repr.destroy();
+    });
+    this.$.html("");
+    paper.remove();
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/twitter-bin.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,124 @@
+Rkns.Twitter = {
+}
+
+Rkns.Twitter.Search = function(_renkan, _opts) {
+	this.renkan = _renkan;
+	this.opts = _opts;
+}
+
+Rkns.Twitter.Search.prototype.getBgClass = function() {
+	return "Rk-Twitter-Icon";
+}
+
+Rkns.Twitter.Search.prototype.getSearchTitle = function() {
+	return this.renkan.l10n.search_on_twitter;
+}
+
+Rkns.Twitter.Search.prototype.search = function(_q) {
+    this.renkan.tabs.push(
+        new Rkns.Twitter.Bin(this.renkan, {
+            search: _q
+        })
+    );
+}
+
+Rkns.Twitter.Bin = Rkns.Utils.inherit(Rkns._BaseBin);
+
+Rkns.Twitter.Bin.prototype.tweetTemplate = Rkns._.template(
+    '<li class="Rk-Twitter-Tweet Rk-Bin-Item" data-uri="http://twitter.com/<%=tweet.from_user%>/status/<%=tweet.id_str%>" '
+    + 'data-title="Tweet by @<%=tweet.from_user%>" data-description="<%-tweet.text%>" data-image="<%=tweet.profile_image_url%>">'
+    + '<img class="Rk-Twitter-TwImage" src="<%=tweet.profile_image_url%>" />'
+    + '<h4 class="Rk-Twitter-TwTitle"><a href="http://twitter.com/<%=tweet.from_user%>" target="_blank">@<%=tweet.from_user%></a> (<%=tweet.from_user_name%>)</h4>'
+    + '<p class="Rk-Twitter-TwDate"><%=date%></p>'
+    + '<p class="Rk-Twitter-TwText"><%=text%></p>'
+    + '<p class="Rk-Twitter-TwActions"><a class="Rk-Twitter-TwAction" href="http://twitter.com/<%=tweet.from_user%>/status/<%=tweet.id_str%>" target="_blank">show original</a> · '
+    + '<a href="http://twitter.com/intent/tweet?in_reply_to=<%=tweet.id_str%>" target="_blank">reply</a> · '
+    + '<a href="http://twitter.com/intent/retweet?tweet_id=<%=tweet.id_str%>" target="_blank">retweet</a> · '
+    + '<a href="http://twitter.com/intent/favorite?tweet_id=<%=tweet.id_str%>" target="_blank">favorite</a></p></li>'
+);
+
+Rkns.Twitter.Bin.prototype._init = function(_renkan, _opts) {
+    this.search = _opts.search;
+    this.title_icon_$.addClass('Rk-Twitter-Title-Icon');
+    this.title_$.html(this.search).addClass("Rk-Twitter-Title");
+    this.refresh();
+}
+
+Rkns.Twitter.Bin.prototype.refresh = function() {
+    var _this = this;
+    Rkns.$.ajax({
+        url: "http://search.twitter.com/search.json?q=" + encodeURIComponent(this.search),
+        dataType: "jsonp",
+        success: function(_data) {
+            var _rgxp = new RegExp('('+_this.search.replace(/(\W)/g,'\\$1')+')','gi');
+            function highlight(_text) {
+                return _text.replace(_rgxp, "<span class='searchmatch'>$1</span>");
+            }
+            var _html = Rkns._(_data.results).map(function(_result) {
+                var _entities = [],
+                    _users = _result.text.match(/@[\w_]+/gm),
+                    _lastpos = 0;
+                if (_users) {
+                    for (var _i = 0; _i < _users.length; _i++) {
+                        var _m = _users[_i],
+                            _start = _lastpos + _result.text.substr(_lastpos).search(_m),
+                            _lastpos = _start + _m.length;
+                        _entities.push({
+                            "text" : _m,
+                            "start" : _start,
+                            "end" : _lastpos,
+                            "link" :'<a href="http://twitter.com/' + _m.substr(1) + '" onclick="filtrerTexte(\'' + _m + '\'); return false;" target="_blank">',
+                        });
+                    }
+                }
+                var _hashes = _result.text.match(/([^&]|^)#[^\s,.!?=#@&;()]+/gm),
+                    _lastpos = 0;
+                if (_hashes) {
+                    for (var _i = 0; _i < _hashes.length; _i++) {
+                        var _m = _hashes[_i],
+                            _h = ( _m[0] == '#' ? _m : _m.substr(1) ),
+                            _start = _lastpos + _result.text.substr(_lastpos).search(_h),
+                            _lastpos = _start + _h.length;
+                        _entities.push({
+                            "text" : _h,
+                            "start" : _start,
+                            "end" : _lastpos,
+                            "link" :'<a href="http://twitter.com/search?q=' + encodeURIComponent(_h) + '" onclick="filtrerTexte(\'' + _.escape(_h) + '\'); return false;" target="_blank">',
+                        });
+                    }
+                }
+                
+                var _urls = _result.text.match(/(www\.|https?:\/\/)[\w./_\-]+/gim),
+                    _lastpos = 0;
+                if (_urls) {
+                    for (var _i = 0; _i < _urls.length; _i++) {
+                        var _m = _urls[_i],
+                            _start = _lastpos + _result.text.substr(_lastpos).search(_m),
+                            _lastpos = _start + _m.length;
+                        _entities.push({
+                            "text" : _m,
+                            "start" : _start,
+                            "end" : _lastpos,
+                            "link" :'<a href="' + _m + '" target="_blank">',
+                        });
+                    }
+                }
+                _entities = Rkns._(_entities).sortBy(function(a) { return a.start });
+                var _lastend = 0,
+                    _text = Rkns._(_entities).map(function(_e) {
+                        var _txt = highlight(_result.text.substring(_lastend, _e.start)) + _e.link + highlight(_e.text) + '</a>';
+                        _lastend = _e.end;
+                        return _txt;
+                    }).join("") + highlight(_result.text.substring(_lastend));
+                
+                return _this.tweetTemplate({
+                    tweet: _result,
+                    date: new Date(_result.created_at.replace(/(\+|-)/,'UTC$1')).toLocaleString(),
+                    text: _text
+                });
+            }).join("");
+            _this.main_$.html(_html);
+            _renkan.resizeBins();
+        }
+    });
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/underscore.js	Tue Dec 25 21:29:11 2012 +0100
@@ -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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/js/wikipedia-bin.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,63 @@
+Rkns.Wikipedia = {
+}
+
+Rkns.Wikipedia.Search = function(_renkan, _opts) {
+    this.renkan = _renkan;
+    this.lang = _opts.lang || "en";
+}
+
+Rkns.Wikipedia.Search.prototype.getBgClass = function() {
+    return "Rk-Wikipedia-Search-Icon Rk-Wikipedia-Lang-" + this.lang;
+}
+
+Rkns.Wikipedia.Search.prototype.getSearchTitle = function() {
+    return ( this.renkan.l10n["wiki_" + this.lang] || this.renkan.l10n.wiki_) ;
+}
+
+Rkns.Wikipedia.Search.prototype.search = function(_q) {
+    this.renkan.tabs.push(
+        new Rkns.Wikipedia.Bin(this.renkan, {
+            lang: this.lang,
+            search: _q
+        })
+    );
+}
+
+Rkns.Wikipedia.Bin = Rkns.Utils.inherit(Rkns._BaseBin);
+
+Rkns.Wikipedia.Bin.prototype.resultTemplate = Rkns._.template(
+    '<li class="Rk-Wikipedia-Result Rk-Bin-Item" data-uri="<%=wpurl%>" '
+    + 'data-title="Wikipedia: <%=result.title%>" data-description="<%=wpdesc%>" data-image="<%=static_url%>img/wikipedia.png">'
+    + '<img class="Rk-Wikipedia-Icon" src="<%=static_url%>img/wikipedia.png"></div><h4 class="Rk-Wikipedia-Title"><a href="<%=wpurl%>" target="_blank"><%=highlightedtitle%></a></h4>'
+    + '<p class="Rk-Wikipedia-Snippet"><%=result.snippet%></p></li>'
+);
+
+Rkns.Wikipedia.Bin.prototype._init = function(_renkan, _opts) {
+    this.search = _opts.search;
+    this.lang = _opts.lang || "en";
+    this.title_icon_$.addClass('Rk-Wikipedia-Title-Icon Rk-Wikipedia-Lang-' + this.lang);
+    this.title_$.html(this.search).addClass("Rk-Wikipedia-Title");
+    this.refresh();
+}
+
+Rkns.Wikipedia.Bin.prototype.refresh = function() {
+    var _this = this;
+    Rkns.$.ajax({
+        url: "http://" + _this.lang + ".wikipedia.org/w/api.php?action=query&list=search&srsearch=" + encodeURIComponent(this.search) + "&format=json",
+        dataType: "jsonp",
+        success: function(_data) {
+            var _rgxp = new RegExp('('+_this.search.replace(/(\W)/g,'\\$1')+')','gi'),
+                _html = Rkns._(_data.query.search).map(function(_result) {
+                return _this.resultTemplate({
+                    result: _result,
+                    wpurl: "http://" + _this.lang + ".wikipedia.org/wiki/" + encodeURI(_result.title.replace(/ /g,"_")),
+                    highlightedtitle: _result.title.replace(_rgxp, "<span class='searchmatch'>$1</span>"),
+                    wpdesc: Rkns.$('<div>').html(_result.snippet).text(),
+                    static_url: _this.renkan.static_url
+                });
+            }).join("");
+            _this.main_$.html(_html);
+            _renkan.resizeBins();
+        }
+    });
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/lib/backbone-relational.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,1715 @@
+/* vim: set tabstop=4:softtabstop=4:shiftwidth=4:noexpandtab */
+/**
+ * Backbone-relational.js 0.7.0
+ * (c) 2011-2013 Paul Uithol
+ * 
+ * Backbone-relational may be freely distributed under the MIT license; see the accompanying LICENSE.txt.
+ * For details and documentation: https://github.com/PaulUithol/Backbone-relational.
+ * Depends on Backbone (and thus on Underscore as well): https://github.com/documentcloud/backbone.
+ */
+( function( undefined ) {
+	"use strict";
+	
+	/**
+	 * CommonJS shim
+	 **/
+	var _, Backbone, exports;
+	if ( typeof window === 'undefined' ) {
+		_ = require( 'underscore' );
+		Backbone = require( 'backbone' );
+		exports = module.exports = Backbone;
+	}
+	else {
+		_ = window._;
+		Backbone = window.Backbone;
+		exports = window;
+	}
+
+	Backbone.Relational = {
+		showWarnings: true
+	};
+
+	/**
+	 * Semaphore mixin; can be used as both binary and counting.
+	 **/
+	Backbone.Semaphore = {
+		_permitsAvailable: null,
+		_permitsUsed: 0,
+		
+		acquire: function() {
+			if ( this._permitsAvailable && this._permitsUsed >= this._permitsAvailable ) {
+				throw new Error( 'Max permits acquired' );
+			}
+			else {
+				this._permitsUsed++;
+			}
+		},
+		
+		release: function() {
+			if ( this._permitsUsed === 0 ) {
+				throw new Error( 'All permits released' );
+			}
+			else {
+				this._permitsUsed--;
+			}
+		},
+		
+		isLocked: function() {
+			return this._permitsUsed > 0;
+		},
+		
+		setAvailablePermits: function( amount ) {
+			if ( this._permitsUsed > amount ) {
+				throw new Error( 'Available permits cannot be less than used permits' );
+			}
+			this._permitsAvailable = amount;
+		}
+	};
+	
+	/**
+	 * A BlockingQueue that accumulates items while blocked (via 'block'),
+	 * and processes them when unblocked (via 'unblock').
+	 * Process can also be called manually (via 'process').
+	 */
+	Backbone.BlockingQueue = function() {
+		this._queue = [];
+	};
+	_.extend( Backbone.BlockingQueue.prototype, Backbone.Semaphore, {
+		_queue: null,
+		
+		add: function( func ) {
+			if ( this.isBlocked() ) {
+				this._queue.push( func );
+			}
+			else {
+				func();
+			}
+		},
+		
+		process: function() {
+			while ( this._queue && this._queue.length ) {
+				this._queue.shift()();
+			}
+		},
+		
+		block: function() {
+			this.acquire();
+		},
+		
+		unblock: function() {
+			this.release();
+			if ( !this.isBlocked() ) {
+				this.process();
+			}
+		},
+		
+		isBlocked: function() {
+			return this.isLocked();
+		}
+	});
+	/**
+	 * Global event queue. Accumulates external events ('add:<key>', 'remove:<key>' and 'update:<key>')
+	 * until the top-level object is fully initialized (see 'Backbone.RelationalModel').
+	 */
+	Backbone.Relational.eventQueue = new Backbone.BlockingQueue();
+	
+	/**
+	 * Backbone.Store keeps track of all created (and destruction of) Backbone.RelationalModel.
+	 * Handles lookup for relations.
+	 */
+	Backbone.Store = function() {
+		this._collections = [];
+		this._reverseRelations = [];
+		this._subModels = [];
+		this._modelScopes = [ exports ];
+	};
+	_.extend( Backbone.Store.prototype, Backbone.Events, {
+		addModelScope: function( scope ) {
+			this._modelScopes.push( scope );
+		},
+
+		/**
+		 * Add a set of subModelTypes to the store, that can be used to resolve the '_superModel'
+		 * for a model later in 'setupSuperModel'.
+		 *
+		 * @param {Backbone.RelationalModel} subModelTypes
+		 * @param {Backbone.RelationalModel} superModelType
+		 */
+		addSubModels: function( subModelTypes, superModelType ) {
+			this._subModels.push({
+				'superModelType': superModelType,
+				'subModels': subModelTypes
+			});
+		},
+
+		/**
+		 * Check if the given modelType is registered as another model's subModel. If so, add it to the super model's
+		 * '_subModels', and set the modelType's '_superModel', '_subModelTypeName', and '_subModelTypeAttribute'.
+		 *
+		 * @param {Backbone.RelationalModel} modelType
+		 */
+		setupSuperModel: function( modelType ) {
+			_.find( this._subModels || [], function( subModelDef ) {
+				return _.find( subModelDef.subModels || [], function( subModelTypeName, typeValue ) {
+					var subModelType = this.getObjectByName( subModelTypeName );
+
+					if ( modelType === subModelType ) {
+						// Set 'modelType' as a child of the found superModel
+						subModelDef.superModelType._subModels[ typeValue ] = modelType;
+
+						// Set '_superModel', '_subModelTypeValue', and '_subModelTypeAttribute' on 'modelType'.
+						modelType._superModel = subModelDef.superModelType;
+						modelType._subModelTypeValue = typeValue;
+						modelType._subModelTypeAttribute = subModelDef.superModelType.prototype.subModelTypeAttribute;
+						return true;
+					}
+				}, this );
+			}, this );
+		},
+		
+		/**
+		 * Add a reverse relation. Is added to the 'relations' property on model's prototype, and to
+		 * existing instances of 'model' in the store as well.
+		 * @param {Object} relation
+		 * @param {Backbone.RelationalModel} relation.model
+		 * @param {String} relation.type
+		 * @param {String} relation.key
+		 * @param {String|Object} relation.relatedModel
+		 */
+		addReverseRelation: function( relation ) {
+			var exists = _.any( this._reverseRelations || [], function( rel ) {
+					return _.all( relation || [], function( val, key ) {
+							return val === rel[ key ];
+						});
+				});
+			
+			if ( !exists && relation.model && relation.type ) {
+				this._reverseRelations.push( relation );
+				
+				var addRelation = function( model, relation ) {
+					if ( !model.prototype.relations ) {
+						model.prototype.relations = [];
+					}
+					model.prototype.relations.push( relation );
+					
+					_.each( model._subModels || [], function( subModel ) {
+							addRelation( subModel, relation );
+						}, this );
+				};
+				
+				addRelation( relation.model, relation );
+				
+				this.retroFitRelation( relation );
+			}
+		},
+		
+		/**
+		 * Add a 'relation' to all existing instances of 'relation.model' in the store
+		 * @param {Object} relation
+		 */
+		retroFitRelation: function( relation ) {
+			var coll = this.getCollection( relation.model );
+			coll.each( function( model ) {
+				if ( !( model instanceof relation.model ) ) {
+					return;
+				}
+
+				new relation.type( model, relation );
+			}, this);
+		},
+		
+		/**
+		 * Find the Store's collection for a certain type of model.
+		 * @param {Backbone.RelationalModel} model
+		 * @return {Backbone.Collection} A collection if found (or applicable for 'model'), or null
+		 */
+		getCollection: function( model ) {
+			if ( model instanceof Backbone.RelationalModel ) {
+				model = model.constructor;
+			}
+			
+			var rootModel = model;
+			while ( rootModel._superModel ) {
+				rootModel = rootModel._superModel;
+			}
+			
+			var coll = _.detect( this._collections, function( c ) {
+					return c.model === rootModel;
+				});
+			
+			if ( !coll ) {
+				coll = this._createCollection( rootModel );
+			}
+			
+			return coll;
+		},
+		
+		/**
+		 * Find a type on the global object by name. Splits name on dots.
+		 * @param {String} name
+		 * @return {Object}
+		 */
+		getObjectByName: function( name ) {
+			var parts = name.split( '.' ),
+				type = null;
+
+			_.find( this._modelScopes || [], function( scope ) {
+				type = _.reduce( parts || [], function( memo, val ) {
+					return memo ? memo[ val ] : undefined;
+				}, scope );
+
+				if ( type && type !== scope ) {
+					return true;
+				}
+			}, this );
+
+			return type;
+		},
+		
+		_createCollection: function( type ) {
+			var coll;
+			
+			// If 'type' is an instance, take its constructor
+			if ( type instanceof Backbone.RelationalModel ) {
+				type = type.constructor;
+			}
+			
+			// Type should inherit from Backbone.RelationalModel.
+			if ( type.prototype instanceof Backbone.RelationalModel ) {
+				coll = new Backbone.Collection();
+				coll.model = type;
+				
+				this._collections.push( coll );
+			}
+			
+			return coll;
+		},
+
+		/**
+		 * Find the attribute that is to be used as the `id` on a given object
+		 * @param type
+		 * @param {String|Number|Object|Backbone.RelationalModel} item
+		 * @return {String|Number}
+		 */
+		resolveIdForItem: function( type, item ) {
+			var id = _.isString( item ) || _.isNumber( item ) ? item : null;
+
+			if ( id === null ) {
+				if ( item instanceof Backbone.RelationalModel ) {
+					id = item.id;
+				}
+				else if ( _.isObject( item ) ) {
+					id = item[ type.prototype.idAttribute ];
+				}
+			}
+
+			// Make all falsy values `null` (except for 0, which could be an id.. see '/issues/179')
+			if ( !id && id !== 0 ) {
+				id = null;
+			}
+
+			return id;
+		},
+
+		/**
+		 *
+		 * @param type
+		 * @param {String|Number|Object|Backbone.RelationalModel} item
+		 */
+		find: function( type, item ) {
+			var id = this.resolveIdForItem( type, item );
+			var coll = this.getCollection( type );
+			
+			// Because the found object could be of any of the type's superModel
+			// types, only return it if it's actually of the type asked for.
+			if ( coll ) {
+				var obj = coll.get( id );
+
+				if ( obj instanceof type ) {
+					return obj;
+				}
+			}
+
+			return null;
+		},
+		
+		/**
+		 * Add a 'model' to it's appropriate collection. Retain the original contents of 'model.collection'.
+		 * @param {Backbone.RelationalModel} model
+		 */
+		register: function( model ) {
+			var coll = this.getCollection( model );
+
+			if ( coll ) {
+				if ( coll.get( model ) ) {
+					throw new Error( "Cannot instantiate more than one Backbone.RelationalModel with the same id per type!" );
+				}
+
+				var modelColl = model.collection;
+				coll.add( model );
+				model.bind( 'destroy', this.unregister, this );
+				model.collection = modelColl;
+			}
+		},
+		
+		/**
+		 * Explicitly update a model's id in it's store collection
+		 * @param {Backbone.RelationalModel} model
+		 */
+		update: function( model ) {
+			var coll = this.getCollection( model );
+			coll._onModelEvent( 'change:' + model.idAttribute, model, coll );
+		},
+		
+		/**
+		 * Remove a 'model' from the store.
+		 * @param {Backbone.RelationalModel} model
+		 */
+		unregister: function( model ) {
+			model.unbind( 'destroy', this.unregister );
+			var coll = this.getCollection( model );
+			coll && coll.remove( model );
+		}
+	});
+	Backbone.Relational.store = new Backbone.Store();
+	
+	/**
+	 * The main Relation class, from which 'HasOne' and 'HasMany' inherit. Internally, 'relational:<key>' events
+	 * are used to regulate addition and removal of models from relations.
+	 *
+	 * @param {Backbone.RelationalModel} instance
+	 * @param {Object} options
+	 * @param {string} options.key
+	 * @param {Backbone.RelationalModel.constructor} options.relatedModel
+	 * @param {Boolean|String} [options.includeInJSON=true] Serialize the given attribute for related model(s)' in toJSON, or just their ids.
+	 * @param {Boolean} [options.createModels=true] Create objects from the contents of keys if the object is not found in Backbone.store.
+	 * @param {Object} [options.reverseRelation] Specify a bi-directional relation. If provided, Relation will reciprocate
+	 *    the relation to the 'relatedModel'. Required and optional properties match 'options', except that it also needs
+	 *    {Backbone.Relation|String} type ('HasOne' or 'HasMany').
+	 */
+	Backbone.Relation = function( instance, options ) {
+		this.instance = instance;
+		// Make sure 'options' is sane, and fill with defaults from subclasses and this object's prototype
+		options = _.isObject( options ) ? options : {};
+		this.reverseRelation = _.defaults( options.reverseRelation || {}, this.options.reverseRelation );
+		this.reverseRelation.type = !_.isString( this.reverseRelation.type ) ? this.reverseRelation.type :
+			Backbone[ this.reverseRelation.type ] || Backbone.Relational.store.getObjectByName( this.reverseRelation.type );
+		this.model = options.model || this.instance.constructor;
+		this.options = _.defaults( options, this.options, Backbone.Relation.prototype.options );
+		
+		this.key = this.options.key;
+		this.keySource = this.options.keySource || this.key;
+		this.keyDestination = this.options.keyDestination || this.keySource || this.key;
+
+		// 'exports' should be the global object where 'relatedModel' can be found on if given as a string.
+		this.relatedModel = this.options.relatedModel;
+		if ( _.isString( this.relatedModel ) ) {
+			this.relatedModel = Backbone.Relational.store.getObjectByName( this.relatedModel );
+		}
+
+		if ( !this.checkPreconditions() ) {
+			return;
+		}
+
+		if ( instance ) {
+			var contentKey = this.keySource;
+			if ( contentKey !== this.key && typeof this.instance.get( this.key ) === 'object' ) {
+				contentKey = this.key;
+			}
+
+			this.keyContents = this.instance.get( contentKey );
+
+			// Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'.
+			if ( this.keySource !== this.key ) {
+				this.instance.unset( this.keySource, { silent: true } );
+			}
+
+			// Add this Relation to instance._relations
+			this.instance._relations.push( this );
+		}
+
+		// Add the reverse relation on 'relatedModel' to the store's reverseRelations
+		if ( !this.options.isAutoRelation && this.reverseRelation.type && this.reverseRelation.key ) {
+			Backbone.Relational.store.addReverseRelation( _.defaults( {
+					isAutoRelation: true,
+					model: this.relatedModel,
+					relatedModel: this.model,
+					reverseRelation: this.options // current relation is the 'reverseRelation' for it's own reverseRelation
+				},
+				this.reverseRelation // Take further properties from this.reverseRelation (type, key, etc.)
+			) );
+		}
+
+		_.bindAll( this, '_modelRemovedFromCollection', '_relatedModelAdded', '_relatedModelRemoved' );
+
+		if ( instance ) {
+			this.initialize();
+
+			if ( options.autoFetch ) {
+				this.instance.fetchRelated( options.key, _.isObject( options.autoFetch ) ? options.autoFetch : {} );
+			}
+
+			// When a model in the store is destroyed, check if it is 'this.instance'.
+			Backbone.Relational.store.getCollection( this.instance )
+				.bind( 'relational:remove', this._modelRemovedFromCollection );
+
+			// When 'relatedModel' are created or destroyed, check if it affects this relation.
+			Backbone.Relational.store.getCollection( this.relatedModel )
+				.bind( 'relational:add', this._relatedModelAdded )
+				.bind( 'relational:remove', this._relatedModelRemoved );
+		}
+	};
+	// Fix inheritance :\
+	Backbone.Relation.extend = Backbone.Model.extend;
+	// Set up all inheritable **Backbone.Relation** properties and methods.
+	_.extend( Backbone.Relation.prototype, Backbone.Events, Backbone.Semaphore, {
+		options: {
+			createModels: true,
+			includeInJSON: true,
+			isAutoRelation: false,
+			autoFetch: false
+		},
+		
+		instance: null,
+		key: null,
+		keyContents: null,
+		relatedModel: null,
+		reverseRelation: null,
+		related: null,
+		
+		_relatedModelAdded: function( model, coll, options ) {
+			// Allow 'model' to set up it's relations, before calling 'tryAddRelated'
+			// (which can result in a call to 'addRelated' on a relation of 'model')
+			var dit = this;
+			model.queue( function() {
+				dit.tryAddRelated( model, options );
+			});
+		},
+		
+		_relatedModelRemoved: function( model, coll, options ) {
+			this.removeRelated( model, options );
+		},
+		
+		_modelRemovedFromCollection: function( model ) {
+			if ( model === this.instance ) {
+				this.destroy();
+			}
+		},
+		
+		/**
+		 * Check several pre-conditions.
+		 * @return {Boolean} True if pre-conditions are satisfied, false if they're not.
+		 */
+		checkPreconditions: function() {
+			var i = this.instance,
+				k = this.key,
+				m = this.model,
+				rm = this.relatedModel,
+				warn = Backbone.Relational.showWarnings && typeof console !== 'undefined';
+
+			if ( !m || !k || !rm ) {
+				warn && console.warn( 'Relation=%o; no model, key or relatedModel (%o, %o, %o)', this, m, k, rm );
+				return false;
+			}
+			// Check if the type in 'model' inherits from Backbone.RelationalModel
+			if ( !( m.prototype instanceof Backbone.RelationalModel ) ) {
+				warn && console.warn( 'Relation=%o; model does not inherit from Backbone.RelationalModel (%o)', this, i );
+				return false;
+			}
+			// Check if the type in 'relatedModel' inherits from Backbone.RelationalModel
+			if ( !( rm.prototype instanceof Backbone.RelationalModel ) ) {
+				warn && console.warn( 'Relation=%o; relatedModel does not inherit from Backbone.RelationalModel (%o)', this, rm );
+				return false;
+			}
+			// Check if this is not a HasMany, and the reverse relation is HasMany as well
+			if ( this instanceof Backbone.HasMany && this.reverseRelation.type === Backbone.HasMany ) {
+				warn && console.warn( 'Relation=%o; relation is a HasMany, and the reverseRelation is HasMany as well.', this );
+				return false;
+			}
+
+			// Check if we're not attempting to create a duplicate relationship
+			if ( i && i._relations.length ) {
+				var exists = _.any( i._relations || [], function( rel ) {
+						var hasReverseRelation = this.reverseRelation.key && rel.reverseRelation.key;
+						return rel.relatedModel === rm && rel.key === k &&
+							( !hasReverseRelation || this.reverseRelation.key === rel.reverseRelation.key );
+					}, this );
+
+				if ( exists ) {
+					warn && console.warn( 'Relation=%o between instance=%o.%s and relatedModel=%o.%s already exists',
+						this, i, k, rm, this.reverseRelation.key );
+					return false;
+				}
+			}
+
+			return true;
+		},
+
+		/**
+		 * Set the related model(s) for this relation
+		 * @param {Backbone.Model|Backbone.Collection} related
+		 * @param {Object} [options]
+		 */
+		setRelated: function( related, options ) {
+			this.related = related;
+
+			this.instance.acquire();
+			this.instance.set( this.key, related, _.defaults( options || {}, { silent: true } ) );
+			this.instance.release();
+		},
+		
+		/**
+		 * Determine if a relation (on a different RelationalModel) is the reverse
+		 * relation of the current one.
+		 * @param {Backbone.Relation} relation
+		 * @return {Boolean}
+		 */
+		_isReverseRelation: function( relation ) {
+			if ( relation.instance instanceof this.relatedModel && this.reverseRelation.key === relation.key &&
+					this.key === relation.reverseRelation.key ) {
+				return true;
+			}
+			return false;
+		},
+		
+		/**
+		 * Get the reverse relations (pointing back to 'this.key' on 'this.instance') for the currently related model(s).
+		 * @param {Backbone.RelationalModel} [model] Get the reverse relations for a specific model.
+		 *    If not specified, 'this.related' is used.
+		 * @return {Backbone.Relation[]}
+		 */
+		getReverseRelations: function( model ) {
+			var reverseRelations = [];
+			// Iterate over 'model', 'this.related.models' (if this.related is a Backbone.Collection), or wrap 'this.related' in an array.
+			var models = !_.isUndefined( model ) ? [ model ] : this.related && ( this.related.models || [ this.related ] );
+			_.each( models || [], function( related ) {
+					_.each( related.getRelations() || [], function( relation ) {
+							if ( this._isReverseRelation( relation ) ) {
+								reverseRelations.push( relation );
+							}
+						}, this );
+				}, this );
+			
+			return reverseRelations;
+		},
+		
+		/**
+		 * Rename options.silent to options.silentChange, so events propagate properly.
+		 * (for example in HasMany, from 'addRelated'->'handleAddition')
+		 * @param {Object} [options]
+		 * @return {Object}
+		 */
+		sanitizeOptions: function( options ) {
+			options = options ? _.clone( options ) : {};
+			if ( options.silent ) {
+				options.silentChange = true;
+				delete options.silent;
+			}
+			return options;
+		},
+
+		/**
+		 * Rename options.silentChange to options.silent, so events are silenced as intended in Backbone's
+		 * original functions.
+		 * @param {Object} [options]
+		 * @return {Object}
+		 */
+		unsanitizeOptions: function( options ) {
+			options = options ? _.clone( options ) : {};
+			if ( options.silentChange ) {
+				options.silent = true;
+				delete options.silentChange;
+			}
+			return options;
+		},
+		
+		// Cleanup. Get reverse relation, call removeRelated on each.
+		destroy: function() {
+			Backbone.Relational.store.getCollection( this.instance )
+				.unbind( 'relational:remove', this._modelRemovedFromCollection );
+			
+			Backbone.Relational.store.getCollection( this.relatedModel )
+				.unbind( 'relational:add', this._relatedModelAdded )
+				.unbind( 'relational:remove', this._relatedModelRemoved );
+			
+			_.each( this.getReverseRelations() || [], function( relation ) {
+					relation.removeRelated( this.instance );
+				}, this );
+		}
+	});
+	
+	Backbone.HasOne = Backbone.Relation.extend({
+		options: {
+			reverseRelation: { type: 'HasMany' }
+		},
+		
+		initialize: function() {
+			_.bindAll( this, 'onChange' );
+
+			this.instance.bind( 'relational:change:' + this.key, this.onChange );
+
+			var model = this.findRelated( { silent: true } );
+			this.setRelated( model );
+
+			// Notify new 'related' object of the new relation.
+			_.each( this.getReverseRelations() || [], function( relation ) {
+					relation.addRelated( this.instance );
+				}, this );
+		},
+		
+		findRelated: function( options ) {
+			var item = this.keyContents;
+			var model = null;
+			
+			if ( item instanceof this.relatedModel ) {
+				model = item;
+			}
+			else if ( item || item === 0 ) { // since 0 can be a valid `id` as well
+				model = this.relatedModel.findOrCreate( item, { create: this.options.createModels } );
+			}
+			
+			return model;
+		},
+		
+		/**
+		 * If the key is changed, notify old & new reverse relations and initialize the new relation
+		 */
+		onChange: function( model, attr, options ) {
+			// Don't accept recursive calls to onChange (like onChange->findRelated->findOrCreate->initializeRelations->addRelated->onChange)
+			if ( this.isLocked() ) {
+				return;
+			}
+			this.acquire();
+			options = this.sanitizeOptions( options );
+			
+			// 'options._related' is set by 'addRelated'/'removeRelated'. If it is set, the change
+			// is the result of a call from a relation. If it's not, the change is the result of 
+			// a 'set' call on this.instance.
+			var changed = _.isUndefined( options._related );
+			var oldRelated = changed ? this.related : options._related;
+			
+			if ( changed ) {	
+				this.keyContents = attr;
+				
+				// Set new 'related'
+				if ( attr instanceof this.relatedModel ) {
+					this.related = attr;
+				}
+				else if ( attr ) {
+					var related = this.findRelated( options );
+					this.setRelated( related );
+				}
+				else {
+					this.setRelated( null );
+				}
+			}
+			
+			// Notify old 'related' object of the terminated relation
+			if ( oldRelated && this.related !== oldRelated ) {
+				_.each( this.getReverseRelations( oldRelated ) || [], function( relation ) {
+						relation.removeRelated( this.instance, options );
+					}, this );
+			}
+			
+			// Notify new 'related' object of the new relation. Note we do re-apply even if this.related is oldRelated;
+			// that can be necessary for bi-directional relations if 'this.instance' was created after 'this.related'.
+			// In that case, 'this.instance' will already know 'this.related', but the reverse might not exist yet.
+			_.each( this.getReverseRelations() || [], function( relation ) {
+					relation.addRelated( this.instance, options );
+				}, this);
+			
+			// Fire the 'update:<key>' event if 'related' was updated
+			if ( !options.silentChange && this.related !== oldRelated ) {
+				var dit = this;
+				Backbone.Relational.eventQueue.add( function() {
+					dit.instance.trigger( 'update:' + dit.key, dit.instance, dit.related, options );
+				});
+			}
+			this.release();
+		},
+		
+		/**
+		 * If a new 'this.relatedModel' appears in the 'store', try to match it to the last set 'keyContents'
+		 */
+		tryAddRelated: function( model, options ) {
+			if ( this.related ) {
+				return;
+			}
+			options = this.sanitizeOptions( options );
+			
+			var item = this.keyContents;
+			if ( item || item === 0 ) { // since 0 can be a valid `id` as well
+				var id = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item );
+				if ( !_.isNull( id ) && model.id === id ) {
+					this.addRelated( model, options );
+				}
+			}
+		},
+		
+		addRelated: function( model, options ) {
+			if ( model !== this.related ) {
+				var oldRelated = this.related || null;
+				this.setRelated( model );
+				this.onChange( this.instance, model, { _related: oldRelated } );
+			}
+		},
+		
+		removeRelated: function( model, options ) {
+			if ( !this.related ) {
+				return;
+			}
+			
+			if ( model === this.related ) {
+				var oldRelated = this.related || null;
+				this.setRelated( null );
+				this.onChange( this.instance, model, { _related: oldRelated } );
+			}
+		}
+	});
+	
+	Backbone.HasMany = Backbone.Relation.extend({
+		collectionType: null,
+		
+		options: {
+			reverseRelation: { type: 'HasOne' },
+			collectionType: Backbone.Collection,
+			collectionKey: true,
+			collectionOptions: {}
+		},
+		
+		initialize: function() {
+			_.bindAll( this, 'onChange', 'handleAddition', 'handleRemoval', 'handleReset' );
+			this.instance.bind( 'relational:change:' + this.key, this.onChange );
+			
+			// Handle a custom 'collectionType'
+			this.collectionType = this.options.collectionType;
+			if ( _.isString( this.collectionType ) ) {
+				this.collectionType = Backbone.Relational.store.getObjectByName( this.collectionType );
+			}
+			if ( !this.collectionType.prototype instanceof Backbone.Collection ){
+				throw new Error( 'collectionType must inherit from Backbone.Collection' );
+			}
+
+			// Handle cases where a model/relation is created with a collection passed straight into 'attributes'
+			if ( this.keyContents instanceof Backbone.Collection ) {
+				this.setRelated( this._prepareCollection( this.keyContents ) );
+			}
+			else {
+				this.setRelated( this._prepareCollection() );
+			}
+
+			this.findRelated( { silent: true } );
+		},
+		
+		_getCollectionOptions: function() {
+			return _.isFunction( this.options.collectionOptions ) ?
+				this.options.collectionOptions( this.instance ) :
+				this.options.collectionOptions;
+		},
+
+		/**
+		 * Bind events and setup collectionKeys for a collection that is to be used as the backing store for a HasMany.
+		 * If no 'collection' is supplied, a new collection will be created of the specified 'collectionType' option.
+		 * @param {Backbone.Collection} [collection]
+		 */
+		_prepareCollection: function( collection ) {
+			if ( this.related ) {
+				this.related
+					.unbind( 'relational:add', this.handleAddition )
+					.unbind( 'relational:remove', this.handleRemoval )
+					.unbind( 'relational:reset', this.handleReset )
+			}
+
+			if ( !collection || !( collection instanceof Backbone.Collection ) ) {
+				collection = new this.collectionType( [], this._getCollectionOptions() );
+			}
+
+			collection.model = this.relatedModel;
+			
+			if ( this.options.collectionKey ) {
+				var key = this.options.collectionKey === true ? this.options.reverseRelation.key : this.options.collectionKey;
+				
+				if ( collection[ key ] && collection[ key ] !== this.instance ) {
+					if ( Backbone.Relational.showWarnings && typeof console !== 'undefined' ) {
+						console.warn( 'Relation=%o; collectionKey=%s already exists on collection=%o', this, key, this.options.collectionKey );
+					}
+				}
+				else if ( key ) {
+					collection[ key ] = this.instance;
+				}
+			}
+			
+			collection
+				.bind( 'relational:add', this.handleAddition )
+				.bind( 'relational:remove', this.handleRemoval )
+				.bind( 'relational:reset', this.handleReset );
+			
+			return collection;
+		},
+		
+		findRelated: function( options ) {
+			if ( this.keyContents ) {
+				var models = [];
+
+				if ( this.keyContents instanceof Backbone.Collection ) {
+					models = this.keyContents.models;
+				}
+				else {
+					// Handle cases the an API/user supplies just an Object/id instead of an Array
+					this.keyContents = _.isArray( this.keyContents ) ? this.keyContents : [ this.keyContents ];
+
+					// Try to find instances of the appropriate 'relatedModel' in the store
+					_.each( this.keyContents || [], function( item ) {
+							var model = null;
+							if ( item instanceof this.relatedModel ) {
+								model = item;
+							}
+							else if ( item || item === 0 ) { // since 0 can be a valid `id` as well
+								model = this.relatedModel.findOrCreate( item, { create: this.options.createModels } );
+							}
+
+							if ( model && !this.related.get( model ) ) {
+								models.push( model );
+							}
+						}, this );
+				}
+
+				// Add all found 'models' in on go, so 'add' will only be called once (and thus 'sort', etc.)
+				if ( models.length ) {
+					options = this.unsanitizeOptions( options );
+					this.related.add( models, options );
+				}
+			}
+		},
+		
+		/**
+		 * If the key is changed, notify old & new reverse relations and initialize the new relation
+		 */
+		onChange: function( model, attr, options ) {
+			options = this.sanitizeOptions( options );
+			this.keyContents = attr;
+			
+			// Replace 'this.related' by 'attr' if it is a Backbone.Collection
+			if ( attr instanceof Backbone.Collection ) {
+				this._prepareCollection( attr );
+				this.related = attr;
+			}
+			// Otherwise, 'attr' should be an array of related object ids.
+			// Re-use the current 'this.related' if it is a Backbone.Collection, and remove any current entries.
+			// Otherwise, create a new collection.
+			else {
+				var oldIds = {}, newIds = {};
+
+				if (!_.isArray( attr ) && attr !== undefined) {
+					attr = [ attr ];
+				}
+
+				_.each( attr, function( attributes ) {
+					newIds[ attributes.id ] = true;
+				});
+
+				var coll = this.related;
+				if ( coll instanceof Backbone.Collection ) {
+					// Make sure to operate on a copy since we're removing while iterating
+					_.each( coll.models.slice(0) , function( model ) {
+						// When fetch is called with the 'keepNewModels' option, we don't want to remove
+						// client-created new models when the fetch is completed.
+						if ( !options.keepNewModels || !model.isNew() ) {
+							oldIds[ model.id ] = true;
+							coll.remove( model, { silent: (model.id in newIds) } );
+						}
+					});
+				} else {
+					coll = this._prepareCollection();
+				}
+
+				_.each( attr, function( attributes ) {
+					var model = this.relatedModel.findOrCreate( attributes, { create: this.options.createModels } );
+					if (model) {
+						coll.add( model, { silent: (attributes.id in oldIds)} );
+					}
+				}, this);
+
+				this.setRelated( coll );
+
+			}
+			
+			var dit = this;
+			Backbone.Relational.eventQueue.add( function() {
+				!options.silentChange && dit.instance.trigger( 'update:' + dit.key, dit.instance, dit.related, options );
+			});
+		},
+		
+		tryAddRelated: function( model, options ) {
+			options = this.sanitizeOptions( options );
+			if ( !this.related.get( model ) ) {
+				// Check if this new model was specified in 'this.keyContents'
+				var item = _.any( this.keyContents || [], function( item ) {
+						var id = Backbone.Relational.store.resolveIdForItem( this.relatedModel, item );
+						return !_.isNull( id ) && id === model.id;
+					}, this );
+				
+				if ( item ) {
+					this.related.add( model, options );
+				}
+			}
+		},
+		
+		/**
+		 * When a model is added to a 'HasMany', trigger 'add' on 'this.instance' and notify reverse relations.
+		 * (should be 'HasOne', must set 'this.instance' as their related).
+		 */
+		handleAddition: function( model, coll, options ) {
+			//console.debug('handleAddition called; args=%o', arguments);
+			// Make sure the model is in fact a valid model before continuing.
+			// (it can be invalid as a result of failing validation in Backbone.Collection._prepareModel)
+			if ( !( model instanceof Backbone.Model ) ) {
+				return;
+			}
+			
+			options = this.sanitizeOptions( options );
+			
+			_.each( this.getReverseRelations( model ) || [], function( relation ) {
+					relation.addRelated( this.instance, options );
+				}, this );
+
+			// Only trigger 'add' once the newly added model is initialized (so, has it's relations set up)
+			var dit = this;
+			Backbone.Relational.eventQueue.add( function() {
+				!options.silentChange && dit.instance.trigger( 'add:' + dit.key, model, dit.related, options );
+			});
+		},
+		
+		/**
+		 * When a model is removed from a 'HasMany', trigger 'remove' on 'this.instance' and notify reverse relations.
+		 * (should be 'HasOne', which should be nullified)
+		 */
+		handleRemoval: function( model, coll, options ) {
+			//console.debug('handleRemoval called; args=%o', arguments);
+			if ( !( model instanceof Backbone.Model ) ) {
+				return;
+			}
+
+			options = this.sanitizeOptions( options );
+			
+			_.each( this.getReverseRelations( model ) || [], function( relation ) {
+					relation.removeRelated( this.instance, options );
+				}, this );
+			
+			var dit = this;
+			Backbone.Relational.eventQueue.add( function() {
+				!options.silentChange && dit.instance.trigger( 'remove:' + dit.key, model, dit.related, options );
+			});
+		},
+
+		handleReset: function( coll, options ) {
+			options = this.sanitizeOptions( options );
+
+			var dit = this;
+			Backbone.Relational.eventQueue.add( function() {
+				!options.silentChange && dit.instance.trigger( 'reset:' + dit.key, dit.related, options );
+			});
+		},
+		
+		addRelated: function( model, options ) {
+			var dit = this;
+			options = this.unsanitizeOptions( options );
+			model.queue( function() { // Queued to avoid errors for adding 'model' to the 'this.related' set twice
+				if ( dit.related && !dit.related.get( model ) ) {
+					dit.related.add( model, options );
+				}
+			});
+		},
+		
+		removeRelated: function( model, options ) {
+			options = this.unsanitizeOptions( options );
+			if ( this.related.get( model ) ) {
+				this.related.remove( model, options );
+			}
+		}
+	});
+	
+	/**
+	 * A type of Backbone.Model that also maintains relations to other models and collections.
+	 * New events when compared to the original:
+	 *  - 'add:<key>' (model, related collection, options)
+	 *  - 'remove:<key>' (model, related collection, options)
+	 *  - 'update:<key>' (model, related model or collection, options)
+	 */
+	Backbone.RelationalModel = Backbone.Model.extend({
+		relations: null, // Relation descriptions on the prototype
+		_relations: null, // Relation instances
+		_isInitialized: false,
+		_deferProcessing: false,
+		_queue: null,
+		
+		subModelTypeAttribute: 'type',
+		subModelTypes: null,
+		
+		constructor: function( attributes, options ) {
+			// Nasty hack, for cases like 'model.get( <HasMany key> ).add( item )'.
+			// Defer 'processQueue', so that when 'Relation.createModels' is used we:
+			// a) Survive 'Backbone.Collection.add'; this takes care we won't error on "can't add model to a set twice"
+			//    (by creating a model from properties, having the model add itself to the collection via one of
+			//    it's relations, then trying to add it to the collection).
+			// b) Trigger 'HasMany' collection events only after the model is really fully set up.
+			// Example that triggers both a and b: "p.get('jobs').add( { company: c, person: p } )".
+			var dit = this;
+			if ( options && options.collection ) {
+				this._deferProcessing = true;
+				
+				var processQueue = function( model ) {
+					if ( model === dit ) {
+						dit._deferProcessing = false;
+						dit.processQueue();
+						options.collection.unbind( 'relational:add', processQueue );
+					}
+				};
+				options.collection.bind( 'relational:add', processQueue );
+				
+				// So we do process the queue eventually, regardless of whether this model really gets added to 'options.collection'.
+				_.defer( function() {
+					processQueue( dit );
+				});
+			}
+			
+			this._queue = new Backbone.BlockingQueue();
+			this._queue.block();
+			Backbone.Relational.eventQueue.block();
+			
+			Backbone.Model.apply( this, arguments );
+			
+			// Try to run the global queue holding external events
+			Backbone.Relational.eventQueue.unblock();
+		},
+		
+		/**
+		 * Override 'trigger' to queue 'change' and 'change:*' events
+		 */
+		trigger: function( eventName ) {
+			if ( eventName.length > 5 && 'change' === eventName.substr( 0, 6 ) ) {
+				var dit = this, args = arguments;
+				Backbone.Relational.eventQueue.add( function() {
+						Backbone.Model.prototype.trigger.apply( dit, args );
+					});
+			}
+			else {
+				Backbone.Model.prototype.trigger.apply( this, arguments );
+			}
+			
+			return this;
+		},
+		
+		/**
+		 * Initialize Relations present in this.relations; determine the type (HasOne/HasMany), then creates a new instance.
+		 * Invoked in the first call so 'set' (which is made from the Backbone.Model constructor).
+		 */
+		initializeRelations: function() {
+			this.acquire(); // Setting up relations often also involve calls to 'set', and we only want to enter this function once
+			this._relations = [];
+			
+			_.each( this.relations || [], function( rel ) {
+					var type = !_.isString( rel.type ) ? rel.type :	Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName( rel.type );
+					if ( type && type.prototype instanceof Backbone.Relation ) {
+						new type( this, rel ); // Also pushes the new Relation into _relations
+					}
+					else {
+						Backbone.Relational.showWarnings && typeof console !== 'undefined' && console.warn( 'Relation=%o; missing or invalid type!', rel );
+					}
+				}, this );
+			
+			this._isInitialized = true;
+			this.release();
+			this.processQueue();
+		},
+
+		/**
+		 * When new values are set, notify this model's relations (also if options.silent is set).
+		 * (Relation.setRelated locks this model before calling 'set' on it to prevent loops)
+		 */
+		updateRelations: function( options ) {
+			if ( this._isInitialized && !this.isLocked() ) {
+				_.each( this._relations || [], function( rel ) {
+					// Update from data in `rel.keySource` if set, or `rel.key` otherwise
+					var val = this.attributes[ rel.keySource ] || this.attributes[ rel.key ];
+					if ( rel.related !== val ) {
+						this.trigger( 'relational:change:' + rel.key, this, val, options || {} );
+					}
+				}, this );
+			}
+		},
+		
+		/**
+		 * Either add to the queue (if we're not initialized yet), or execute right away.
+		 */
+		queue: function( func ) {
+			this._queue.add( func );
+		},
+		
+		/**
+		 * Process _queue
+		 */
+		processQueue: function() {
+			if ( this._isInitialized && !this._deferProcessing && this._queue.isBlocked() ) {
+				this._queue.unblock();
+			}
+		},
+		
+		/**
+		 * Get a specific relation.
+		 * @param key {string} The relation key to look for.
+		 * @return {Backbone.Relation} An instance of 'Backbone.Relation', if a relation was found for 'key', or null.
+		 */
+		getRelation: function( key ) {
+			return _.detect( this._relations, function( rel ) {
+				if ( rel.key === key ) {
+					return true;
+				}
+			}, this );
+		},
+		
+		/**
+		 * Get all of the created relations.
+		 * @return {Backbone.Relation[]}
+		 */
+		getRelations: function() {
+			return this._relations;
+		},
+		
+		/**
+		 * Retrieve related objects.
+		 * @param key {string} The relation key to fetch models for.
+		 * @param [options] {Object} Options for 'Backbone.Model.fetch' and 'Backbone.sync'.
+		 * @param [update=false] {boolean} Whether to force a fetch from the server (updating existing models).
+		 * @return {jQuery.when[]} An array of request objects
+		 */
+		fetchRelated: function( key, options, update ) {
+			options || ( options = {} );
+			var setUrl,
+				requests = [],
+				rel = this.getRelation( key ),
+				keyContents = rel && rel.keyContents,
+				toFetch = keyContents && _.select( _.isArray( keyContents ) ? keyContents : [ keyContents ], function( item ) {
+					var id = Backbone.Relational.store.resolveIdForItem( rel.relatedModel, item );
+					return !_.isNull( id ) && ( update || !Backbone.Relational.store.find( rel.relatedModel, id ) );
+				}, this );
+			
+			if ( toFetch && toFetch.length ) {
+				// Create a model for each entry in 'keyContents' that is to be fetched
+				var models = _.map( toFetch, function( item ) {
+					var model;
+
+					if ( _.isObject( item ) ) {
+						model = rel.relatedModel.findOrCreate( item );
+					}
+					else {
+						var attrs = {};
+						attrs[ rel.relatedModel.prototype.idAttribute ] = item;
+						model = rel.relatedModel.findOrCreate( attrs );
+					}
+
+					return model;
+				}, this );
+				
+				// Try if the 'collection' can provide a url to fetch a set of models in one request.
+				if ( rel.related instanceof Backbone.Collection && _.isFunction( rel.related.url ) ) {
+					setUrl = rel.related.url( models );
+				}
+				
+				// An assumption is that when 'Backbone.Collection.url' is a function, it can handle building of set urls.
+				// To make sure it can, test if the url we got by supplying a list of models to fetch is different from
+				// the one supplied for the default fetch action (without args to 'url').
+				if ( setUrl && setUrl !== rel.related.url() ) {
+					var opts = _.defaults(
+						{
+							error: function() {
+								var args = arguments;
+								_.each( models || [], function( model ) {
+										model.trigger( 'destroy', model, model.collection, options );
+										options.error && options.error.apply( model, args );
+									});
+							},
+							url: setUrl
+						},
+						options,
+						{ add: true }
+					);
+
+					requests = [ rel.related.fetch( opts ) ];
+				}
+				else {
+					requests = _.map( models || [], function( model ) {
+						var opts = _.defaults(
+							{
+								error: function() {
+									model.trigger( 'destroy', model, model.collection, options );
+									options.error && options.error.apply( model, arguments );
+								}
+							},
+							options
+						);
+						return model.fetch( opts );
+					}, this );
+				}
+			}
+			
+			return requests;
+		},
+		
+		set: function( key, value, options ) {
+			Backbone.Relational.eventQueue.block();
+			
+			// Duplicate backbone's behavior to allow separate key/value parameters, instead of a single 'attributes' object
+			var attributes;
+			if ( _.isObject( key ) || key == null ) {
+				attributes = key;
+				options = value;
+			}
+			else {
+				attributes = {};
+				attributes[ key ] = value;
+			}
+			
+			var result = Backbone.Model.prototype.set.apply( this, arguments );
+			
+			// Ideal place to set up relations :)
+			if ( !this._isInitialized && !this.isLocked() ) {
+				this.constructor.initializeModelHierarchy();
+
+				Backbone.Relational.store.register( this );
+
+				this.initializeRelations();
+			}
+			// Update the 'idAttribute' in Backbone.store if; we don't want it to miss an 'id' update due to {silent:true}
+			else if ( attributes && this.idAttribute in attributes ) {
+				Backbone.Relational.store.update( this );
+			}
+			
+			if ( attributes ) {
+				this.updateRelations( options );
+			}
+			
+			// Try to run the global queue holding external events
+			Backbone.Relational.eventQueue.unblock();
+			
+			return result;
+		},
+		
+		unset: function( attribute, options ) {
+			Backbone.Relational.eventQueue.block();
+			
+			var result = Backbone.Model.prototype.unset.apply( this, arguments );
+			this.updateRelations( options );
+			
+			// Try to run the global queue holding external events
+			Backbone.Relational.eventQueue.unblock();
+			
+			return result;
+		},
+		
+		clear: function( options ) {
+			Backbone.Relational.eventQueue.block();
+			
+			var result = Backbone.Model.prototype.clear.apply( this, arguments );
+			this.updateRelations( options );
+			
+			// Try to run the global queue holding external events
+			Backbone.Relational.eventQueue.unblock();
+			
+			return result;
+		},
+		
+		/**
+		 * Override 'change', so the change will only execute after 'set' has finised (relations are updated),
+		 * and 'previousAttributes' will be available when the event is fired.
+		 */
+		change: function( options ) {
+			var dit = this, args = arguments;
+			Backbone.Relational.eventQueue.add( function() {
+					Backbone.Model.prototype.change.apply( dit, args );
+				});
+		},
+
+		clone: function() {
+			var attributes = _.clone( this.attributes );
+			if ( !_.isUndefined( attributes[ this.idAttribute ] ) ) {
+				attributes[ this.idAttribute ] = null;
+			}
+
+			_.each( this.getRelations() || [], function( rel ) {
+					delete attributes[ rel.key ];
+				});
+
+			return new this.constructor( attributes );
+		},
+		
+		/**
+		 * Convert relations to JSON, omits them when required
+		 */
+		toJSON: function(options) {
+			// If this Model has already been fully serialized in this branch once, return to avoid loops
+			if ( this.isLocked() ) {
+				return this.id;
+			}
+			
+			this.acquire();
+			var json = Backbone.Model.prototype.toJSON.call( this, options );
+			
+			if ( this.constructor._superModel && !( this.constructor._subModelTypeAttribute in json ) ) {
+				json[ this.constructor._subModelTypeAttribute ] = this.constructor._subModelTypeValue;
+			}
+			
+			_.each( this._relations || [], function( rel ) {
+					var value = json[ rel.key ];
+
+					if ( rel.options.includeInJSON === true) {
+						if ( value && _.isFunction( value.toJSON ) ) {
+							json[ rel.keyDestination ] = value.toJSON( options );
+						}
+						else {
+							json[ rel.keyDestination ] = null;
+						}
+					}
+					else if ( _.isString( rel.options.includeInJSON ) ) {
+						if ( value instanceof Backbone.Collection ) {
+							json[ rel.keyDestination ] = value.pluck( rel.options.includeInJSON );
+						}
+						else if ( value instanceof Backbone.Model ) {
+							json[ rel.keyDestination ] = value.get( rel.options.includeInJSON );
+						}	
+						else {
+							json[ rel.keyDestination ] = null;
+						}
+					}
+					else if ( _.isArray( rel.options.includeInJSON ) ) {
+						if ( value instanceof Backbone.Collection ) {
+							var valueSub = [];
+							value.each( function( model ) {
+								var curJson = {};
+								_.each( rel.options.includeInJSON, function( key ) {
+									curJson[ key ] = model.get( key );
+								});
+								valueSub.push( curJson );
+							});
+							json[ rel.keyDestination ] = valueSub;
+						}
+						else if ( value instanceof Backbone.Model ) {
+							var valueSub = {};
+							_.each( rel.options.includeInJSON, function( key ) {
+								valueSub[ key ] = value.get( key );
+							});
+							json[ rel.keyDestination ] = valueSub;
+						}
+						else {
+							json[ rel.keyDestination ] = null;
+						}
+					}
+					else {
+						delete json[ rel.key ];
+					}
+
+					if ( rel.keyDestination !== rel.key ) {
+						delete json[ rel.key ];
+					}
+				});
+			
+			this.release();
+			return json;
+		}
+	},
+	{
+		setup: function( superModel ) {
+			// We don't want to share a relations array with a parent, as this will cause problems with
+			// reverse relations.
+			this.prototype.relations = ( this.prototype.relations || [] ).slice( 0 );
+
+			this._subModels = {};
+			this._superModel = null;
+
+			// If this model has 'subModelTypes' itself, remember them in the store
+			if ( this.prototype.hasOwnProperty( 'subModelTypes' ) ) {
+				Backbone.Relational.store.addSubModels( this.prototype.subModelTypes, this );
+			}
+			// The 'subModelTypes' property should not be inherited, so reset it.
+			else {
+				this.prototype.subModelTypes = null;
+			}
+
+			// Initialize all reverseRelations that belong to this new model.
+			_.each( this.prototype.relations || [], function( rel ) {
+					if ( !rel.model ) {
+						rel.model = this;
+					}
+
+					if ( rel.reverseRelation && rel.model === this ) {				
+						var preInitialize = true;
+						if ( _.isString( rel.relatedModel ) ) {
+							/**
+							 * The related model might not be defined for two reasons
+							 *  1. it never gets defined, e.g. a typo
+							 *  2. it is related to itself
+							 * In neither of these cases do we need to pre-initialize reverse relations.
+							 */
+							var relatedModel = Backbone.Relational.store.getObjectByName( rel.relatedModel );
+							preInitialize = relatedModel && ( relatedModel.prototype instanceof Backbone.RelationalModel );
+						}
+
+						var type = !_.isString( rel.type ) ? rel.type : Backbone[ rel.type ] || Backbone.Relational.store.getObjectByName( rel.type );
+						if ( preInitialize && type && type.prototype instanceof Backbone.Relation ) {
+							new type( null, rel );
+						}
+					}
+				}, this );
+			
+			return this;
+		},
+
+		/**
+		 * Create a 'Backbone.Model' instance based on 'attributes'.
+		 * @param {Object} attributes
+		 * @param {Object} [options]
+		 * @return {Backbone.Model}
+		 */
+		build: function( attributes, options ) {
+			var model = this;
+
+			// 'build' is a possible entrypoint; it's possible no model hierarchy has been determined yet.
+			this.initializeModelHierarchy();
+
+			// Determine what type of (sub)model should be built if applicable.
+			// Lookup the proper subModelType in 'this._subModels'.
+			if ( this._subModels && this.prototype.subModelTypeAttribute in attributes ) {
+				var subModelTypeAttribute = attributes[ this.prototype.subModelTypeAttribute ];
+				var subModelType = this._subModels[ subModelTypeAttribute ];
+				if ( subModelType ) {
+					model = subModelType;
+				}
+			}
+			
+			return new model( attributes, options );
+		},
+
+		initializeModelHierarchy: function() {
+			// If we're here for the first time, try to determine if this modelType has a 'superModel'.
+			if ( _.isUndefined( this._superModel ) || _.isNull( this._superModel ) ) {
+				Backbone.Relational.store.setupSuperModel( this );
+
+				// If a superModel has been found, copy relations from the _superModel if they haven't been
+				// inherited automatically (due to a redefinition of 'relations').
+				// Otherwise, make sure we don't get here again for this type by making '_superModel' false so we fail
+				// the isUndefined/isNull check next time.
+				if ( this._superModel ) {
+					//
+					if ( this._superModel.prototype.relations ) {
+						var supermodelRelationsExist = _.any( this.prototype.relations || [], function( rel ) {
+							return rel.model && rel.model !== this;
+						}, this );
+
+						if ( !supermodelRelationsExist ) {
+							this.prototype.relations = this._superModel.prototype.relations.concat( this.prototype.relations );
+						}
+					}
+				}
+				else {
+					this._superModel = false;
+				}
+			}
+
+			// If we came here through 'build' for a model that has 'subModelTypes', and not all of them have been resolved yet, try to resolve each.
+			if ( this.prototype.subModelTypes && _.keys( this.prototype.subModelTypes ).length !== _.keys( this._subModels ).length ) {
+				_.each( this.prototype.subModelTypes || [], function( subModelTypeName ) {
+					var subModelType = Backbone.Relational.store.getObjectByName( subModelTypeName );
+					subModelType && subModelType.initializeModelHierarchy();
+				});
+			}
+		},
+
+		/**
+		 * Find an instance of `this` type in 'Backbone.Relational.store'.
+		 * - If `attributes` is a string or a number, `findOrCreate` will just query the `store` and return a model if found.
+		 * - If `attributes` is an object, the model will be updated with `attributes` if found.
+		 *   Otherwise, a new model is created with `attributes` (unless `options.create` is explicitly set to `false`).
+		 * @param {Object|String|Number} attributes Either a model's id, or the attributes used to create or update a model.
+		 * @param {Object} [options]
+		 * @param {Boolean} [options.create=true]
+		 * @return {Backbone.RelationalModel}
+		 */
+		findOrCreate: function( attributes, options ) {
+			var parsedAttributes = (_.isObject( attributes ) && this.prototype.parse) ? this.prototype.parse( attributes ) : attributes;
+			// Try to find an instance of 'this' model type in the store
+			var model = Backbone.Relational.store.find( this, parsedAttributes );
+
+			// If we found an instance, update it with the data in 'item'; if not, create an instance
+			// (unless 'options.create' is false).
+			if ( _.isObject( attributes ) ) {
+				if ( model ) {
+					model.set( parsedAttributes, options );
+				}
+				else if ( !options || ( options && options.create !== false ) ) {
+					model = this.build( attributes, options );
+				}
+			}
+
+			return model;
+		}
+	});
+	_.extend( Backbone.RelationalModel.prototype, Backbone.Semaphore );
+	
+	/**
+	 * Override Backbone.Collection._prepareModel, so objects will be built using the correct type
+	 * if the collection.model has subModels.
+	 */
+	Backbone.Collection.prototype.__prepareModel = Backbone.Collection.prototype._prepareModel;
+	Backbone.Collection.prototype._prepareModel = function ( attrs, options ) {
+		var model;
+		
+		if ( attrs instanceof Backbone.Model ) {
+			if ( !attrs.collection ) {
+				attrs.collection = this;
+			}
+			model = attrs;
+		}
+		else {
+			options || (options = {});
+			options.collection = this;
+			
+			if ( typeof this.model.findOrCreate !== 'undefined' ) {
+				model = this.model.findOrCreate( attrs, options );
+			}
+			else {
+				model = new this.model( attrs, options );
+			}
+			
+			if ( !model._validate( attrs, options ) ) {
+				model = false;
+			}
+		}
+		
+		return model;
+	};
+
+	
+	/**
+	 * Override Backbone.Collection.add, so objects fetched from the server multiple times will
+	 * update the existing Model. Also, trigger 'relational:add'.
+	 */
+	var add = Backbone.Collection.prototype.__add = Backbone.Collection.prototype.add;
+	Backbone.Collection.prototype.add = function( models, options ) {
+		options || (options = {});
+		if ( !_.isArray( models ) ) {
+			models = [ models ];
+		}
+
+		var modelsToAdd = [];
+
+		//console.debug( 'calling add on coll=%o; model=%o, options=%o', this, models, options );
+		_.each( models || [], function( model ) {
+			if ( !( model instanceof Backbone.Model ) ) {
+				// `_prepareModel` attempts to find `model` in Backbone.store through `findOrCreate`,
+				// and sets the new properties on it if is found. Otherwise, a new model is instantiated.
+				model = Backbone.Collection.prototype._prepareModel.call( this, model, options );
+			}
+
+				if ( model instanceof Backbone.Model && !this.get( model ) ) {
+					modelsToAdd.push( model );
+				}
+			}, this );
+
+		// Add 'models' in a single batch, so the original add will only be called once (and thus 'sort', etc).
+		if ( modelsToAdd.length ) {
+			add.call( this, modelsToAdd, options );
+
+			_.each( modelsToAdd || [], function( model ) {
+				this.trigger( 'relational:add', model, this, options );
+			}, this );
+		}
+		
+		return this;
+	};
+	
+	/**
+	 * Override 'Backbone.Collection.remove' to trigger 'relational:remove'.
+	 */
+	var remove = Backbone.Collection.prototype.__remove = Backbone.Collection.prototype.remove;
+	Backbone.Collection.prototype.remove = function( models, options ) {
+		options || (options = {});
+		if ( !_.isArray( models ) ) {
+			models = [ models ];
+		}
+		else {
+			models = models.slice( 0 );
+		}
+
+		//console.debug('calling remove on coll=%o; models=%o, options=%o', this, models, options );
+		_.each( models || [], function( model ) {
+				model = this.get( model );
+
+				if ( model instanceof Backbone.Model ) {
+					remove.call( this, model, options );
+					this.trigger('relational:remove', model, this, options);
+				}
+			}, this );
+		
+		return this;
+	};
+
+	/**
+	 * Override 'Backbone.Collection.reset' to trigger 'relational:reset'.
+	 */
+	var reset = Backbone.Collection.prototype.__reset = Backbone.Collection.prototype.reset;
+	Backbone.Collection.prototype.reset = function( models, options ) {
+		reset.call( this, models, options );
+		this.trigger( 'relational:reset', this, options );
+
+		return this;
+	};
+
+	/**
+	 * Override 'Backbone.Collection.sort' to trigger 'relational:reset'.
+	 */
+	var sort = Backbone.Collection.prototype.__sort = Backbone.Collection.prototype.sort;
+	Backbone.Collection.prototype.sort = function( options ) {
+		sort.call( this, options );
+		this.trigger( 'relational:reset', this, options );
+
+		return this;
+	};
+	
+	/**
+	 * Override 'Backbone.Collection.trigger' so 'add', 'remove' and 'reset' events are queued until relations
+	 * are ready.
+	 */
+	var trigger = Backbone.Collection.prototype.__trigger = Backbone.Collection.prototype.trigger;
+	Backbone.Collection.prototype.trigger = function( eventName ) {
+		if ( eventName === 'add' || eventName === 'remove' || eventName === 'reset' ) {
+			var dit = this, args = arguments;
+			
+			if (eventName === 'add') {
+				args = _.toArray( args );
+				// the fourth argument in case of a regular add is the option object.
+				// we need to clone it, as it could be modified while we wait on the eventQueue to be unblocked
+				if (_.isObject( args[3] ) ) {
+					args[3] = _.clone( args[3] );
+				}
+			}
+			
+			Backbone.Relational.eventQueue.add( function() {
+					trigger.apply( dit, args );
+				});
+		}
+		else {
+			trigger.apply( this, arguments );
+		}
+		
+		return this;
+	};
+
+	// Override .extend() to automatically call .setup()
+	Backbone.RelationalModel.extend = function( protoProps, classProps ) {
+		var child = Backbone.Model.extend.apply( this, arguments );
+		
+		child.setup( this );
+
+		return child;
+	};
+})();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/lib/backbone.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,42 @@
+// Backbone.js 0.9.9
+
+// (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 k=this,y=k.Backbone,h=[],z=h.push,r=h.slice,A=h.splice,g;g="undefined"!==typeof exports?exports:k.Backbone={};g.VERSION="0.9.9";var e=k._;!e&&"undefined"!==typeof require&&(e=require("underscore"));g.$=k.jQuery||k.Zepto||k.ender;g.noConflict=function(){k.Backbone=y;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var s=/\s+/,n=function(a,b,c,d){if(!c)return!0;if("object"===typeof c)for(var f in c)a[b].apply(a,[f,c[f]].concat(d));else if(s.test(c)){c=c.split(s);f=0;for(var e=c.length;f<
+e;f++)a[b].apply(a,[c[f]].concat(d))}else return!0},t=function(a,b,c){var d,a=-1,f=b.length;switch(c.length){case 0:for(;++a<f;)(d=b[a]).callback.call(d.ctx);break;case 1:for(;++a<f;)(d=b[a]).callback.call(d.ctx,c[0]);break;case 2:for(;++a<f;)(d=b[a]).callback.call(d.ctx,c[0],c[1]);break;case 3:for(;++a<f;)(d=b[a]).callback.call(d.ctx,c[0],c[1],c[2]);break;default:for(;++a<f;)(d=b[a]).callback.apply(d.ctx,c)}},h=g.Events={on:function(a,b,c){if(!n(this,"on",a,[b,c])||!b)return this;this._events||(this._events=
+{});(this._events[a]||(this._events[a]=[])).push({callback:b,context:c,ctx:c||this});return this},once:function(a,b,c){if(!n(this,"once",a,[b,c])||!b)return this;var d=this,f=e.once(function(){d.off(a,f);b.apply(this,arguments)});f._callback=b;this.on(a,f,c);return this},off:function(a,b,c){var d,f,l,g,i,m,h,j;if(!this._events||!n(this,"off",a,[b,c]))return this;if(!a&&!b&&!c)return this._events={},this;g=a?[a]:e.keys(this._events);i=0;for(m=g.length;i<m;i++)if(a=g[i],d=this._events[a]){l=[];if(b||
+c){h=0;for(j=d.length;h<j;h++)f=d[h],(b&&b!==(f.callback._callback||f.callback)||c&&c!==f.context)&&l.push(f)}this._events[a]=l}return this},trigger:function(a){if(!this._events)return this;var b=r.call(arguments,1);if(!n(this,"trigger",a,b))return this;var c=this._events[a],d=this._events.all;c&&t(this,c,b);d&&t(this,d,arguments);return this},listenTo:function(a,b,c){var d=this._listeners||(this._listeners={}),f=a._listenerId||(a._listenerId=e.uniqueId("l"));d[f]=a;a.on(b,c||this,this);return this},
+stopListening:function(a,b,c){var d=this._listeners;if(d){if(a)a.off(b,c,this),!b&&!c&&delete d[a._listenerId];else{for(var f in d)d[f].off(null,null,this);this._listeners={}}return this}}};h.bind=h.on;h.unbind=h.off;e.extend(g,h);var o=g.Model=function(a,b){var c,d=a||{};this.cid=e.uniqueId("c");this.changed={};this.attributes={};this._changes=[];b&&b.collection&&(this.collection=b.collection);b&&b.parse&&(d=this.parse(d));(c=e.result(this,"defaults"))&&e.defaults(d,c);this.set(d,{silent:!0});this._currentAttributes=
+e.clone(this.attributes);this._previousAttributes=e.clone(this.attributes);this.initialize.apply(this,arguments)};e.extend(o.prototype,h,{changed:null,idAttribute:"id",initialize:function(){},toJSON:function(){return e.clone(this.attributes)},sync:function(){return g.sync.apply(this,arguments)},get:function(a){return this.attributes[a]},escape:function(a){return e.escape(this.get(a))},has:function(a){return null!=this.get(a)},set:function(a,b,c){var d,f;if(null==a)return this;e.isObject(a)?(f=a,c=
+b):(f={})[a]=b;var a=c&&c.silent,l=c&&c.unset;if(!this._validate(f,c))return!1;this.idAttribute in f&&(this.id=f[this.idAttribute]);var g=this.attributes;for(d in f)b=f[d],l?delete g[d]:g[d]=b,this._changes.push(d,b);this._hasComputed=!1;a||this.change(c);return this},unset:function(a,b){return this.set(a,void 0,e.extend({},b,{unset:!0}))},clear:function(a){var b={},c;for(c in this.attributes)b[c]=void 0;return this.set(b,e.extend({},a,{unset:!0}))},fetch:function(a){a=a?e.clone(a):{};void 0===a.parse&&
+(a.parse=!0);var b=this,c=a.success;a.success=function(d){if(!b.set(b.parse(d),a))return false;c&&c(b,d,a)};return this.sync("read",this,a)},save:function(a,b,c){var d,f,g;null==a||e.isObject(a)?(d=a,c=b):null!=a&&((d={})[a]=b);c=c?e.clone(c):{};if(c.wait){if(d&&!this._validate(d,c))return!1;f=e.clone(this.attributes)}a=e.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c)||!d&&!this._validate(null,c))return!1;var q=this,i=c.success;c.success=function(a){g=true;var b=q.parse(a);c.wait&&(b=e.extend(d||
+{},b));if(!q.set(b,c))return false;i&&i(q,a,c)};b=this.isNew()?"create":c.patch?"patch":"update";"patch"==b&&(c.attrs=d);b=this.sync(b,this,c);!g&&c.wait&&(this.clear(a),this.set(f,a));return b},destroy:function(a){var a=a?e.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};a.success=function(f){(a.wait||b.isNew())&&d();c&&c(b,f,a)};if(this.isNew())return a.success(),!1;var f=this.sync("delete",this,a);a.wait||d();return f},url:function(){var a=e.result(this,"urlRoot")||
+e.result(this.collection,"url")||u();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){var b=this._changing;this._changing=!0;var c=this._computeChanges(!0);this._pending=!!c.length;for(var d=c.length-2;0<=d;d-=2)this.trigger("change:"+c[d],this,c[d+1],a);if(b)return this;for(;this._pending;)this._pending=!1,this.trigger("change",
+this,a),this._previousAttributes=e.clone(this.attributes);this._changing=!1;return this},hasChanged:function(a){this._hasComputed||this._computeChanges();return null==a?!e.isEmpty(this.changed):e.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?e.clone(this.changed):!1;var b,c=!1,d=this._previousAttributes,f;for(f in a)if(!e.isEqual(d[f],b=a[f]))(c||(c={}))[f]=b;return c},_computeChanges:function(a){this.changed={};for(var b={},c=[],d=this._currentAttributes,f=this._changes,
+e=f.length-2;0<=e;e-=2){var g=f[e],i=f[e+1];b[g]||(b[g]=!0,d[g]!==i&&(this.changed[g]=i,a&&(c.push(g,i),d[g]=i)))}a&&(this._changes=[]);this._hasComputed=!0;return c},previous:function(a){return null==a||!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return e.clone(this._previousAttributes)},_validate:function(a,b){if(!this.validate)return!0;var a=e.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 p=g.Collection=function(a,b){b||(b={});b.model&&(this.model=b.model);void 0!==b.comparator&&(this.comparator=b.comparator);this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,e.extend({silent:!0},b))};e.extend(p.prototype,h,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},sync:function(){return g.sync.apply(this,arguments)},add:function(a,b){var c,d,f,g,h=b&&b.at,i=null==(b&&b.sort)?!0:b.sort,a=e.isArray(a)?
+a.slice():[a];for(c=a.length-1;0<=c;c--)(d=this._prepareModel(a[c],b))?(a[c]=d,(f=null!=d.id&&this._byId[d.id])||this._byCid[d.cid]?(b&&(b.merge&&f)&&(f.set(d.attributes,b),g=i),a.splice(c,1)):(d.on("all",this._onModelEvent,this),this._byCid[d.cid]=d,null!=d.id&&(this._byId[d.id]=d))):(this.trigger("error",this,a[c],b),a.splice(c,1));a.length&&(g=i);this.length+=a.length;c=[null!=h?h:this.models.length,0];z.apply(c,a);A.apply(this.models,c);g&&(this.comparator&&null==h)&&this.sort({silent:!0});if(b&&
+b.silent)return this;for(;d=a.shift();)d.trigger("add",d,this,b);return this},remove:function(a,b){var c,d,f,g;b||(b={});a=e.isArray(a)?a.slice():[a];c=0;for(d=a.length;c<d;c++)if(g=this.get(a[c]))delete this._byId[g.id],delete this._byCid[g.cid],f=this.indexOf(g),this.models.splice(f,1),this.length--,b.silent||(b.index=f,g.trigger("remove",g,this,b)),this._removeReference(g);return this},push:function(a,b){a=this._prepareModel(a,b);this.add(a,e.extend({at:this.length},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,e.extend({at:0},b));return a},shift:function(a){var b=this.at(0);this.remove(b,a);return b},slice:function(a,b){return this.models.slice(a,b)},get:function(a){return null==a?void 0:this._byId[null!=a.id?a.id:a]||this._byCid[a.cid||a]},at:function(a){return this.models[a]},where:function(a){return e.isEmpty(a)?[]:this.filter(function(b){for(var c in a)if(a[c]!==b.get(c))return!1;return!0})},
+sort:function(a){if(!this.comparator)throw Error("Cannot sort a set without a comparator");e.isString(this.comparator)||1===this.comparator.length?this.models=this.sortBy(this.comparator,this):this.models.sort(e.bind(this.comparator,this));(!a||!a.silent)&&this.trigger("sort",this,a);return this},pluck:function(a){return e.invoke(this.models,"get",a)},update:function(a,b){var c,d,f,g,h=[],i=[],m={},j=this.model.prototype.idAttribute,b=e.extend({add:!0,merge:!0,remove:!0},b);b.parse&&(a=this.parse(a));
+e.isArray(a)||(a=a?[a]:[]);if(b.add&&!b.remove)return this.add(a,b);d=0;for(f=a.length;d<f;d++)c=a[d],g=this.get(c.id||c.cid||c[j]),b.remove&&g&&(m[g.cid]=!0),(b.add&&!g||b.merge&&g)&&h.push(c);if(b.remove){d=0;for(f=this.models.length;d<f;d++)c=this.models[d],m[c.cid]||i.push(c)}i.length&&this.remove(i,b);h.length&&this.add(h,b);return this},reset:function(a,b){b||(b={});b.parse&&(a=this.parse(a));for(var c=0,d=this.models.length;c<d;c++)this._removeReference(this.models[c]);b.previousModels=this.models;
+this._reset();a&&this.add(a,e.extend({silent:!0},b));b.silent||this.trigger("reset",this,b);return this},fetch:function(a){a=a?e.clone(a):{};void 0===a.parse&&(a.parse=!0);var b=this,c=a.success;a.success=function(d){b[a.update?"update":"reset"](d,a);c&&c(b,d,a)};return this.sync("read",this,a)},create:function(a,b){var c=this,b=b?e.clone(b):{},a=this._prepareModel(a,b);if(!a)return!1;b.wait||c.add(a,b);var d=b.success;b.success=function(a,b,e){e.wait&&c.add(a,e);d&&d(a,b,e)};a.save(null,b);return a},
+parse:function(a){return a},clone:function(){return new this.constructor(this.models)},chain:function(){return e(this.models).chain()},_reset:function(){this.length=0;this.models=[];this._byId={};this._byCid={}},_prepareModel:function(a,b){if(a instanceof o)return a.collection||(a.collection=this),a;b||(b={});b.collection=this;var c=new this.model(a,b);return!c._validate(a,b)?!1:c},_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)],null!=b.id&&(this._byId[b.id]=b)),this.trigger.apply(this,arguments))}});e.each("forEach each map collect reduce foldl inject reduceRight foldr find detect filter select reject every all some any include contains invoke max min sortedIndex toArray size first head take initial rest tail last without indexOf shuffle lastIndexOf isEmpty".split(" "),
+function(a){p.prototype[a]=function(){var b=r.call(arguments);b.unshift(this.models);return e[a].apply(e,b)}});e.each(["groupBy","countBy","sortBy"],function(a){p.prototype[a]=function(b,c){var d=e.isFunction(b)?b:function(a){return a.get(b)};return e[a](this.models,d,c)}});var v=g.Router=function(a){a||(a={});a.routes&&(this.routes=a.routes);this._bindRoutes();this.initialize.apply(this,arguments)},B=/\((.*?)\)/g,C=/:\w+/g,D=/\*\w+/g,E=/[\-{}\[\]+?.,\\\^$|#\s]/g;e.extend(v.prototype,h,{initialize:function(){},
+route:function(a,b,c){e.isRegExp(a)||(a=this._routeToRegExp(a));c||(c=this[b]);g.history.route(a,e.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);return this},_bindRoutes:function(){if(this.routes)for(var a,b=e.keys(this.routes);null!=(a=b.pop());)this.route(a,this.routes[a])},_routeToRegExp:function(a){a=a.replace(E,"\\$&").replace(B,
+"(?:$1)?").replace(C,"([^/]+)").replace(D,"(.*?)");return RegExp("^"+a+"$")},_extractParameters:function(a,b){return a.exec(b).slice(1)}});var j=g.History=function(){this.handlers=[];e.bindAll(this,"checkUrl");"undefined"!==typeof window&&(this.location=window.location,this.history=window.history)},w=/^[#\/]|\s+$/g,F=/^\/+|\/+$/g,G=/msie [\w.]+/,H=/\/$/;j.started=!1;e.extend(j.prototype,h,{interval:50,getHash:function(a){return(a=(a||this).location.href.match(/#(.*)$/))?a[1]:""},getFragment:function(a,
+b){if(null==a)if(this._hasPushState||!this._wantsHashChange||b){var a=this.location.pathname,c=this.root.replace(H,"");a.indexOf(c)||(a=a.substr(c.length))}else a=this.getHash();return a.replace(w,"")},start:function(a){if(j.started)throw Error("Backbone.history has already been started");j.started=!0;this.options=e.extend({},{root:"/"},this.options,a);this.root=this.options.root;this._wantsHashChange=!1!==this.options.hashChange;this._wantsPushState=!!this.options.pushState;this._hasPushState=!(!this.options.pushState||
+!this.history||!this.history.pushState);var a=this.getFragment(),b=document.documentMode,b=G.exec(navigator.userAgent.toLowerCase())&&(!b||7>=b);this.root=("/"+this.root+"/").replace(F,"/");b&&this._wantsHashChange&&(this.iframe=g.$('<iframe src="javascript:0" tabindex="-1" />').hide().appendTo("body")[0].contentWindow,this.navigate(a));this._hasPushState?g.$(window).bind("popstate",this.checkUrl):this._wantsHashChange&&"onhashchange"in window&&!b?g.$(window).bind("hashchange",this.checkUrl):this._wantsHashChange&&
+(this._checkUrlInterval=setInterval(this.checkUrl,this.interval));this.fragment=a;a=this.location;b=a.pathname.replace(/[^\/]$/,"$&/")===this.root;if(this._wantsHashChange&&this._wantsPushState&&!this._hasPushState&&!b)return this.fragment=this.getFragment(null,!0),this.location.replace(this.root+this.location.search+"#"+this.fragment),!0;this._wantsPushState&&(this._hasPushState&&b&&a.hash)&&(this.fragment=this.getHash().replace(w,""),this.history.replaceState({},document.title,this.root+this.fragment+
+a.search));if(!this.options.silent)return this.loadUrl()},stop:function(){g.$(window).unbind("popstate",this.checkUrl).unbind("hashchange",this.checkUrl);clearInterval(this._checkUrlInterval);j.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 e.any(this.handlers,function(a){if(a.route.test(b))return a.callback(b),!0})},navigate:function(a,b){if(!j.started)return!1;if(!b||!0===b)b={trigger:b};a=this.getFragment(a||"");if(this.fragment!==a){this.fragment=a;var c=this.root+a;if(this._hasPushState)this.history[b.replace?"replaceState":"pushState"]({},document.title,c);else if(this._wantsHashChange)this._updateHash(this.location,a,b.replace),this.iframe&&a!==this.getFragment(this.getHash(this.iframe))&&
+(b.replace||this.iframe.document.open().close(),this._updateHash(this.iframe.location,a,b.replace));else return this.location.assign(c);b.trigger&&this.loadUrl(a)}},_updateHash:function(a,b,c){c?(c=a.href.replace(/(javascript:|#).*$/,""),a.replace(c+"#"+b)):a.hash="#"+b}});g.history=new j;var x=g.View=function(a){this.cid=e.uniqueId("view");this._configure(a||{});this._ensureElement();this.initialize.apply(this,arguments);this.delegateEvents()},I=/^(\S+)\s*(.*)$/,J="model collection el id attributes className tagName events".split(" ");
+e.extend(x.prototype,h,{tagName:"div",$:function(a){return this.$el.find(a)},initialize:function(){},render:function(){return this},remove:function(){this.$el.remove();this.stopListening();return this},make:function(a,b,c){a=document.createElement(a);b&&g.$(a).attr(b);null!=c&&g.$(a).html(c);return a},setElement:function(a,b){this.$el&&this.undelegateEvents();this.$el=a instanceof g.$?a:g.$(a);this.el=this.$el[0];!1!==b&&this.delegateEvents();return this},delegateEvents:function(a){if(a||(a=e.result(this,
+"events"))){this.undelegateEvents();for(var b in a){var c=a[b];e.isFunction(c)||(c=this[a[b]]);if(!c)throw Error('Method "'+a[b]+'" does not exist');var d=b.match(I),f=d[1],d=d[2],c=e.bind(c,this),f=f+(".delegateEvents"+this.cid);""===d?this.$el.bind(f,c):this.$el.delegate(d,f,c)}}},undelegateEvents:function(){this.$el.unbind(".delegateEvents"+this.cid)},_configure:function(a){this.options&&(a=e.extend({},e.result(this,"options"),a));e.extend(this,e.pick(a,J));this.options=a},_ensureElement:function(){if(this.el)this.setElement(e.result(this,
+"el"),!1);else{var a=e.extend({},e.result(this,"attributes"));this.id&&(a.id=e.result(this,"id"));this.className&&(a["class"]=e.result(this,"className"));this.setElement(this.make(e.result(this,"tagName"),a),!1)}}});var K={create:"POST",update:"PUT",patch:"PATCH","delete":"DELETE",read:"GET"};g.sync=function(a,b,c){var d=K[a];e.defaults(c||(c={}),{emulateHTTP:g.emulateHTTP,emulateJSON:g.emulateJSON});var f={type:d,dataType:"json"};c.url||(f.url=e.result(b,"url")||u());if(null==c.data&&b&&("create"===
+a||"update"===a||"patch"===a))f.contentType="application/json",f.data=JSON.stringify(c.attrs||b.toJSON(c));c.emulateJSON&&(f.contentType="application/x-www-form-urlencoded",f.data=f.data?{model:f.data}:{});if(c.emulateHTTP&&("PUT"===d||"DELETE"===d||"PATCH"===d)){f.type="POST";c.emulateJSON&&(f.data._method=d);var h=c.beforeSend;c.beforeSend=function(a){a.setRequestHeader("X-HTTP-Method-Override",d);if(h)return h.apply(this,arguments)}}"GET"!==f.type&&!c.emulateJSON&&(f.processData=!1);var j=c.success;
+c.success=function(a,d,e){j&&j(a,d,e);b.trigger("sync",b,a,c)};var i=c.error;c.error=function(a){i&&i(b,a,c);b.trigger("error",b,a,c)};a=g.ajax(e.extend(f,c));b.trigger("request",b,a,c);return a};g.ajax=function(){return g.$.ajax.apply(g.$,arguments)};o.extend=p.extend=v.extend=x.extend=j.extend=function(a,b){var c=this,d;d=a&&e.has(a,"constructor")?a.constructor:function(){c.apply(this,arguments)};e.extend(d,c,b);var f=function(){this.constructor=d};f.prototype=c.prototype;d.prototype=new f;a&&e.extend(d.prototype,
+a);d.__super__=c.prototype;return d};var u=function(){throw Error('A "url" property or function must be specified');}}).call(this);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/lib/jquery.min.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,4 @@
+/*! jQuery v1.7.2 jquery.com | jquery.org/license */
+(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cu(a){if(!cj[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){ck||(ck=c.createElement("iframe"),ck.frameBorder=ck.width=ck.height=0),b.appendChild(ck);if(!cl||!ck.createElement)cl=(ck.contentWindow||ck.contentDocument).document,cl.write((f.support.boxModel?"<!doctype html>":"")+"<html><body>"),cl.close();d=cl.createElement(a),cl.body.appendChild(d),e=f.css(d,"display"),b.removeChild(ck)}cj[a]=e}return cj[a]}function ct(a,b){var c={};f.each(cp.concat.apply([],cp.slice(0,b)),function(){c[this]=a});return c}function cs(){cq=b}function cr(){setTimeout(cs,0);return cq=f.now()}function ci(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ch(){try{return new a.XMLHttpRequest}catch(b){}}function cb(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g<i;g++){if(g===1)for(h in a.converters)typeof h=="string"&&(e[h.toLowerCase()]=a.converters[h]);l=k,k=d[g];if(k==="*")k=l;else if(l!=="*"&&l!==k){m=l+" "+k,n=e[m]||e["* "+k];if(!n){p=b;for(o in e){j=o.split(" ");if(j[0]===l||j[0]==="*"){p=e[j[1]+" "+k];if(p){o=e[o],o===!0?n=p:p===!0&&(n=o);break}}}}!n&&!p&&f.error("No conversion from "+m.replace(" "," to ")),n!==!0&&(c=n?n(c):p(o(c)))}}return c}function ca(a,c,d){var e=a.contents,f=a.dataTypes,g=a.responseFields,h,i,j,k;for(i in g)i in d&&(c[g[i]]=d[i]);while(f[0]==="*")f.shift(),h===b&&(h=a.mimeType||c.getResponseHeader("content-type"));if(h)for(i in e)if(e[i]&&e[i].test(h)){f.unshift(i);break}if(f[0]in d)j=f[0];else{for(i in d){if(!f[0]||a.converters[i+" "+f[0]]){j=i;break}k||(k=i)}j=j||k}if(j){j!==f[0]&&f.unshift(j);return d[j]}}function b_(a,b,c,d){if(f.isArray(b))f.each(b,function(b,e){c||bD.test(a)?d(a,e):b_(a+"["+(typeof e=="object"?b:"")+"]",e,c,d)});else if(!c&&f.type(b)==="object")for(var e in b)b_(a+"["+e+"]",b[e],c,d);else d(a,b)}function b$(a,c){var d,e,g=f.ajaxSettings.flatOptions||{};for(d in c)c[d]!==b&&((g[d]?a:e||(e={}))[d]=c[d]);e&&f.extend(!0,a,e)}function bZ(a,c,d,e,f,g){f=f||c.dataTypes[0],g=g||{},g[f]=!0;var h=a[f],i=0,j=h?h.length:0,k=a===bS,l;for(;i<j&&(k||!l);i++)l=h[i](c,d,e),typeof l=="string"&&(!k||g[l]?l=b:(c.dataTypes.unshift(l),l=bZ(a,c,d,e,l,g)));(k||!l)&&!g["*"]&&(l=bZ(a,c,d,e,"*",g));return l}function bY(a){return function(b,c){typeof b!="string"&&(c=b,b="*");if(f.isFunction(c)){var d=b.toLowerCase().split(bO),e=0,g=d.length,h,i,j;for(;e<g;e++)h=d[e],j=/^\+/.test(h),j&&(h=h.substr(1)||"*"),i=a[h]=a[h]||[],i[j?"unshift":"push"](c)}}}function bB(a,b,c){var d=b==="width"?a.offsetWidth:a.offsetHeight,e=b==="width"?1:0,g=4;if(d>0){if(c!=="border")for(;e<g;e+=2)c||(d-=parseFloat(f.css(a,"padding"+bx[e]))||0),c==="margin"?d+=parseFloat(f.css(a,c+bx[e]))||0:d-=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0;return d+"px"}d=by(a,b);if(d<0||d==null)d=a.style[b];if(bt.test(d))return d;d=parseFloat(d)||0;if(c)for(;e<g;e+=2)d+=parseFloat(f.css(a,"padding"+bx[e]))||0,c!=="padding"&&(d+=parseFloat(f.css(a,"border"+bx[e]+"Width"))||0),c==="margin"&&(d+=parseFloat(f.css(a,c+bx[e]))||0);return d+"px"}function bo(a){var b=c.createElement("div");bh.appendChild(b),b.innerHTML=a.outerHTML;return b.firstChild}function bn(a){var b=(a.nodeName||"").toLowerCase();b==="input"?bm(a):b!=="script"&&typeof a.getElementsByTagName!="undefined"&&f.grep(a.getElementsByTagName("input"),bm)}function bm(a){if(a.type==="checkbox"||a.type==="radio")a.defaultChecked=a.checked}function bl(a){return typeof a.getElementsByTagName!="undefined"?a.getElementsByTagName("*"):typeof a.querySelectorAll!="undefined"?a.querySelectorAll("*"):[]}function bk(a,b){var c;b.nodeType===1&&(b.clearAttributes&&b.clearAttributes(),b.mergeAttributes&&b.mergeAttributes(a),c=b.nodeName.toLowerCase(),c==="object"?b.outerHTML=a.outerHTML:c!=="input"||a.type!=="checkbox"&&a.type!=="radio"?c==="option"?b.selected=a.defaultSelected:c==="input"||c==="textarea"?b.defaultValue=a.defaultValue:c==="script"&&b.text!==a.text&&(b.text=a.text):(a.checked&&(b.defaultChecked=b.checked=a.checked),b.value!==a.value&&(b.value=a.value)),b.removeAttribute(f.expando),b.removeAttribute("_submit_attached"),b.removeAttribute("_change_attached"))}function bj(a,b){if(b.nodeType===1&&!!f.hasData(a)){var c,d,e,g=f._data(a),h=f._data(b,g),i=g.events;if(i){delete h.handle,h.events={};for(c in i)for(d=0,e=i[c].length;d<e;d++)f.event.add(b,c,i[c][d])}h.data&&(h.data=f.extend({},h.data))}}function bi(a,b){return f.nodeName(a,"table")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function U(a){var b=V.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}function T(a,b,c){b=b||0;if(f.isFunction(b))return f.grep(a,function(a,d){var e=!!b.call(a,d,a);return e===c});if(b.nodeType)return f.grep(a,function(a,d){return a===b===c});if(typeof b=="string"){var d=f.grep(a,function(a){return a.nodeType===1});if(O.test(b))return f.filter(b,d,!c);b=f.filter(b,d)}return f.grep(a,function(a,d){return f.inArray(a,b)>=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?+d:j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c<d;c++)b[a[c]]=!0;return b}var c=a.document,d=a.navigator,e=a.location,f=function(){function J(){if(!e.isReady){try{c.documentElement.doScroll("left")}catch(a){setTimeout(J,1);return}e.ready()}}var e=function(a,b){return new e.fn.init(a,b,h)},f=a.jQuery,g=a.$,h,i=/^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.2",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j<k;j++)if((a=arguments[j])!=null)for(c in a){d=i[c],f=a[c];if(i===f)continue;l&&f&&(e.isPlainObject(f)||(g=e.isArray(f)))?(g?(g=!1,h=d&&e.isArray(d)?d:[]):h=d&&e.isPlainObject(d)?d:{},i[c]=e.extend(l,h,f)):f!==b&&(i[c]=f)}return i},e.extend({noConflict:function(b){a.$===e&&(a.$=g),b&&a.jQuery===e&&(a.jQuery=f);return e},isReady:!1,readyWait:1,holdReady:function(a){a?e.readyWait++:e.ready(!0)},ready:function(a){if(a===!0&&!--e.readyWait||a!==!0&&!e.isReady){if(!c.body)return setTimeout(e.ready,1);e.isReady=!0;if(a!==!0&&--e.readyWait>0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a!=null&&a==a.window},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){if(typeof c!="string"||!c)return null;var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g<h;)if(c.apply(a[g++],d)===!1)break}else if(i){for(f in a)if(c.call(a[f],f,a[f])===!1)break}else for(;g<h;)if(c.call(a[g],g,a[g++])===!1)break;return a},trim:G?function(a){return a==null?"":G.call(a)}:function(a){return a==null?"":(a+"").replace(k,"").replace(l,"")},makeArray:function(a,b){var c=b||[];if(a!=null){var d=e.type(a);a.length==null||d==="string"||d==="function"||d==="regexp"||e.isWindow(a)?E.call(c,a):e.merge(c,a)}return c},inArray:function(a,b,c){var d;if(b){if(H)return H.call(b,a,c);d=b.length,c=c?c<0?Math.max(0,d+c):c:0;for(;c<d;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,c){var d=a.length,e=0;if(typeof c.length=="number")for(var f=c.length;e<f;e++)a[d++]=c[e];else while(c[e]!==b)a[d++]=c[e++];a.length=d;return a},grep:function(a,b,c){var d=[],e;c=!!c;for(var f=0,g=a.length;f<g;f++)e=!!b(a[f],f),c!==e&&d.push(a[f]);return d},map:function(a,c,d){var f,g,h=[],i=0,j=a.length,k=a instanceof e||j!==b&&typeof j=="number"&&(j>0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i<j;i++)f=c(a[i],i,d),f!=null&&(h[h.length]=f);else for(g in a)f=c(a[g],g,d),f!=null&&(h[h.length]=f);return h.concat.apply([],h)},guid:1,proxy:function(a,c){if(typeof c=="string"){var d=a[c];c=a,a=d}if(!e.isFunction(a))return b;var f=F.call(arguments,2),g=function(){return a.apply(c,f.concat(F.call(arguments)))};g.guid=a.guid=a.guid||g.guid||e.guid++;return g},access:function(a,c,d,f,g,h,i){var j,k=d==null,l=0,m=a.length;if(d&&typeof d=="object"){for(l in d)e.access(a,c,l,d[l],1,h,f);g=1}else if(f!==b){j=i===b&&e.isFunction(f),k&&(j?(j=c,c=function(a,b,c){return j.call(e(a),c)}):(c.call(a,f),c=null));if(c)for(;l<m;l++)c(a[l],d,j?f.call(a[l],l,c(a[l],d)):f,i);g=1}return g?a:k?c.call(a):m?c(a[0],d):h},now:function(){return(new Date).getTime()},uaMatch:function(a){a=a.toLowerCase();var b=r.exec(a)||s.exec(a)||t.exec(a)||a.indexOf("compatible")<0&&u.exec(a)||[];return{browser:b[1]||"",version:b[2]||"0"}},sub:function(){function a(b,c){return new a.fn.init(b,c)}e.extend(!0,a,this),a.superclass=this,a.fn=a.prototype=this(),a.fn.constructor=a,a.sub=this.sub,a.fn.init=function(d,f){f&&f instanceof e&&!(f instanceof a)&&(f=a(f));return e.fn.init.call(this,d,f,b)},a.fn.init.prototype=a.fn;var b=a(c);return a},browser:{}}),e.each("Boolean Number String Function Array Date RegExp Object".split(" "),function(a,b){I["[object "+b+"]"]=b.toLowerCase()}),z=e.uaMatch(y),z.browser&&(e.browser[z.browser]=!0,e.browser.version=z.version),e.browser.webkit&&(e.browser.safari=!0),j.test(" ")&&(k=/^[\s\xA0]+/,l=/[\s\xA0]+$/),h=e(c),c.addEventListener?B=function(){c.removeEventListener("DOMContentLoaded",B,!1),e.ready()}:c.attachEvent&&(B=function(){c.readyState==="complete"&&(c.detachEvent("onreadystatechange",B),e.ready())});return e}(),g={};f.Callbacks=function(a){a=a?g[a]||h(a):{};var c=[],d=[],e,i,j,k,l,m,n=function(b){var d,e,g,h,i;for(d=0,e=b.length;d<e;d++)g=b[d],h=f.type(g),h==="array"?n(g):h==="function"&&(!a.unique||!p.has(g))&&c.push(g)},o=function(b,f){f=f||[],e=!a.memory||[b,f],i=!0,j=!0,m=k||0,k=0,l=c.length;for(;c&&m<l;m++)if(c[m].apply(b,f)===!1&&a.stopOnFalse){e=!0;break}j=!1,c&&(a.once?e===!0?p.disable():c=[]:d&&d.length&&(e=d.shift(),p.fireWith(e[0],e[1])))},p={add:function(){if(c){var a=c.length;n(arguments),j?l=c.length:e&&e!==!0&&(k=a,o(e[0],e[1]))}return this},remove:function(){if(c){var b=arguments,d=0,e=b.length;for(;d<e;d++)for(var f=0;f<c.length;f++)if(b[d]===c[f]){j&&f<=l&&(l--,f<=m&&m--),c.splice(f--,1);if(a.unique)break}}return this},has:function(a){if(c){var b=0,d=c.length;for(;b<d;b++)if(a===c[b])return!0}return!1},empty:function(){c=[];return this},disable:function(){c=d=e=b;return this},disabled:function(){return!c},lock:function(){d=b,(!e||e===!0)&&p.disable();return this},locked:function(){return!d},fireWith:function(b,c){d&&(j?a.once||d.push([b,c]):(!a.once||!e)&&o(b,c));return this},fire:function(){p.fireWith(this,arguments);return this},fired:function(){return!!i}};return p};var i=[].slice;f.extend({Deferred:function(a){var b=f.Callbacks("once memory"),c=f.Callbacks("once memory"),d=f.Callbacks("memory"),e="pending",g={resolve:b,reject:c,notify:d},h={done:b.add,fail:c.add,progress:d.add,state:function(){return e},isResolved:b.fired,isRejected:c.fired,then:function(a,b,c){i.done(a).fail(b).progress(c);return this},always:function(){i.done.apply(i,arguments).fail.apply(i,arguments);return this},pipe:function(a,b,c){return f.Deferred(function(d){f.each({done:[a,"resolve"],fail:[b,"reject"],progress:[c,"notify"]},function(a,b){var c=b[0],e=b[1],g;f.isFunction(c)?i[a](function(){g=c.apply(this,arguments),g&&f.isFunction(g.promise)?g.promise().then(d.resolve,d.reject,d.notify):d[e+"With"](this===i?d:this,[g])}):i[a](d[e])})}).promise()},promise:function(a){if(a==null)a=h;else for(var b in h)a[b]=h[b];return a}},i=h.promise({}),j;for(j in g)i[j]=g[j].fire,i[j+"With"]=g[j].fireWith;i.done(function(){e="resolved"},c.disable,d.lock).fail(function(){e="rejected"},b.disable,d.lock),a&&a.call(i,i);return i},when:function(a){function m(a){return function(b){e[a]=arguments.length>1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c<d;c++)b[c]&&b[c].promise&&f.isFunction(b[c].promise)?b[c].promise().then(l(c),j.reject,m(c)):--g;g||j.resolveWith(j,b)}else j!==a&&j.resolveWith(j,d?[a]:[]);return k}}),f.support=function(){var b,d,e,g,h,i,j,k,l,m,n,o,p=c.createElement("div"),q=c.documentElement;p.setAttribute("className","t"),p.innerHTML="   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>",d=p.getElementsByTagName("*"),e=p.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=p.getElementsByTagName("input")[0],b={leadingWhitespace:p.firstChild.nodeType===3,tbody:!p.getElementsByTagName("tbody").length,htmlSerialize:!!p.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:p.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav></:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0,pixelMargin:!0},f.boxModel=b.boxModel=c.compatMode==="CSS1Compat",i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete p.test}catch(r){b.deleteExpando=!1}!p.addEventListener&&p.attachEvent&&p.fireEvent&&(p.attachEvent("onclick",function(){b.noCloneEvent=!1}),p.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),i.setAttribute("name","t"),p.appendChild(i),j=c.createDocumentFragment(),j.appendChild(p.lastChild),b.checkClone=j.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,j.removeChild(i),j.appendChild(p);if(p.attachEvent)for(n in{submit:1,change:1,focusin:1})m="on"+n,o=m in p,o||(p.setAttribute(m,"return;"),o=typeof p[m]=="function"),b[n+"Bubbles"]=o;j.removeChild(p),j=g=h=p=i=null,f(function(){var d,e,g,h,i,j,l,m,n,q,r,s,t,u=c.getElementsByTagName("body")[0];!u||(m=1,t="padding:0;margin:0;border:",r="position:absolute;top:0;left:0;width:1px;height:1px;",s=t+"0;visibility:hidden;",n="style='"+r+t+"5px solid #000;",q="<div "+n+"display:block;'><div style='"+t+"0;display:block;overflow:hidden;'></div></div>"+"<table "+n+"' cellpadding='0' cellspacing='0'>"+"<tr><td></td></tr></table>",d=c.createElement("div"),d.style.cssText=s+"width:0;height:0;position:static;top:0;margin-top:"+m+"px",u.insertBefore(d,u.firstChild),p=c.createElement("div"),d.appendChild(p),p.innerHTML="<table><tr><td style='"+t+"0;display:none'></td><td>t</td></tr></table>",k=p.getElementsByTagName("td"),o=k[0].offsetHeight===0,k[0].style.display="",k[1].style.display="none",b.reliableHiddenOffsets=o&&k[0].offsetHeight===0,a.getComputedStyle&&(p.innerHTML="",l=c.createElement("div"),l.style.width="0",l.style.marginRight="0",p.style.width="2px",p.appendChild(l),b.reliableMarginRight=(parseInt((a.getComputedStyle(l,null)||{marginRight:0}).marginRight,10)||0)===0),typeof p.style.zoom!="undefined"&&(p.innerHTML="",p.style.width=p.style.padding="1px",p.style.border=0,p.style.overflow="hidden",p.style.display="inline",p.style.zoom=1,b.inlineBlockNeedsLayout=p.offsetWidth===3,p.style.display="block",p.style.overflow="visible",p.innerHTML="<div style='width:5px;'></div>",b.shrinkWrapBlocks=p.offsetWidth!==3),p.style.cssText=r+s,p.innerHTML=q,e=p.firstChild,g=e.firstChild,i=e.nextSibling.firstChild.firstChild,j={doesNotAddBorder:g.offsetTop!==5,doesAddBorderForTableAndCells:i.offsetTop===5},g.style.position="fixed",g.style.top="20px",j.fixedPosition=g.offsetTop===20||g.offsetTop===15,g.style.position=g.style.top="",e.style.overflow="hidden",e.style.position="relative",j.subtractsBorderForOverflowNotVisible=g.offsetTop===-5,j.doesNotIncludeMarginInBodyOffset=u.offsetTop!==m,a.getComputedStyle&&(p.style.marginTop="1%",b.pixelMargin=(a.getComputedStyle(p,null)||{marginTop:0}).marginTop!=="1%"),typeof d.style.zoom!="undefined"&&(d.style.zoom=1),u.removeChild(d),l=p=d=null,f.extend(b,j))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e<g;e++)delete d[b[e]];if(!(c?m:f.isEmptyObject)(d))return}}if(!c){delete j[k].data;if(!m(j[k]))return}f.support.deleteExpando||!j.setInterval?delete j[k]:j[k]=null,i&&(f.support.deleteExpando?delete a[h]:a.removeAttribute?a.removeAttribute(h):a[h]=null)}},_data:function(a,b,c){return f.data(a,b,c,!0)},acceptData:function(a){if(a.nodeName){var b=f.noData[a.nodeName.toLowerCase()];if(b)return b!==!0&&a.getAttribute("classid")===b}return!0}}),f.fn.extend({data:function(a,c){var d,e,g,h,i,j=this[0],k=0,m=null;if(a===b){if(this.length){m=f.data(j);if(j.nodeType===1&&!f._data(j,"parsedAttrs")){g=j.attributes;for(i=g.length;k<i;k++)h=g[k].name,h.indexOf("data-")===0&&(h=f.camelCase(h.substring(5)),l(j,h,m[h]));f._data(j,"parsedAttrs",!0)}}return m}if(typeof a=="object")return this.each(function(){f.data(this,a)});d=a.split(".",2),d[1]=d[1]?"."+d[1]:"",e=d[1]+"!";return f.access(this,function(c){if(c===b){m=this.triggerHandler("getData"+e,[d[0]]),m===b&&j&&(m=f.data(j,a),m=l(j,a,m));return m===b&&d[1]?this.data(d[0]):m}d[1]=c,this.each(function(){var b=f(this);b.triggerHandler("setData"+e,d),f.data(this,a,c),b.triggerHandler("changeData"+e,d)})},null,c,arguments.length>1,null,!1)},removeData:function(a){return this.each(function(){f.removeData(this,a)})}}),f.extend({_mark:function(a,b){a&&(b=(b||"fx")+"mark",f._data(a,b,(f._data(a,b)||0)+1))},_unmark:function(a,b,c){a!==!0&&(c=b,b=a,a=!1);if(b){c=c||"fx";var d=c+"mark",e=a?0:(f._data(b,d)||1)-1;e?f._data(b,d,e):(f.removeData(b,d,!0),n(b,c,"mark"))}},queue:function(a,b,c){var d;if(a){b=(b||"fx")+"queue",d=f._data(a,b),c&&(!d||f.isArray(c)?d=f._data(a,b,f.makeArray(c)):d.push(c));return d||[]}},dequeue:function(a,b){b=b||"fx";var c=f.queue(a,b),d=c.shift(),e={};d==="inprogress"&&(d=c.shift()),d&&(b==="fx"&&c.unshift("inprogress"),f._data(a,b+".run",e),d.call(a,function(){f.dequeue(a,b)},e)),c.length||(f.removeData(a,b+"queue "+b+".run",!0),n(a,b,"queue"))}}),f.fn.extend({queue:function(a,c){var d=2;typeof a!="string"&&(c=a,a="fx",d--);if(arguments.length<d)return f.queue(this[0],a);return c===b?this:this.each(function(){var b=f.queue(this,a,c);a==="fx"&&b[0]!=="inprogress"&&f.dequeue(this,a)})},dequeue:function(a){return this.each(function(){f.dequeue(this,a)})},delay:function(a,b){a=f.fx?f.fx.speeds[a]||a:a,b=b||"fx";return this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,c){function m(){--h||d.resolveWith(e,[e])}typeof a!="string"&&(c=a,a=b),a=a||"fx";var d=f.Deferred(),e=this,g=e.length,h=1,i=a+"defer",j=a+"queue",k=a+"mark",l;while(g--)if(l=f.data(e[g],i,b,!0)||(f.data(e[g],j,b,!0)||f.data(e[g],k,b,!0))&&f.data(e[g],i,f.Callbacks("once memory"),!0))h++,l.add(m);m();return d.promise(c)}});var o=/[\n\t\r]/g,p=/\s+/,q=/\r/g,r=/^(?:button|input)$/i,s=/^(?:button|input|object|select|textarea)$/i,t=/^a(?:rea)?$/i,u=/^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,v=f.support.getSetAttribute,w,x,y;f.fn.extend({attr:function(a,b){return f.access(this,f.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){f.removeAttr(this,a)})},prop:function(a,b){return f.access(this,f.prop,a,b,arguments.length>1)},removeProp:function(a){a=f.propFix[a]||a;return this.each(function(){try{this[a]=b,delete this[a]}catch(c){}})},addClass:function(a){var b,c,d,e,g,h,i;if(f.isFunction(a))return this.each(function(b){f(this).addClass(a.call(this,b,this.className))});if(a&&typeof a=="string"){b=a.split(p);for(c=0,d=this.length;c<d;c++){e=this[c];if(e.nodeType===1)if(!e.className&&b.length===1)e.className=a;else{g=" "+e.className+" ";for(h=0,i=b.length;h<i;h++)~g.indexOf(" "+b[h]+" ")||(g+=b[h]+" ");e.className=f.trim(g)}}}return this},removeClass:function(a){var c,d,e,g,h,i,j;if(f.isFunction(a))return this.each(function(b){f(this).removeClass(a.call(this,b,this.className))});if(a&&typeof a=="string"||a===b){c=(a||"").split(p);for(d=0,e=this.length;d<e;d++){g=this[d];if(g.nodeType===1&&g.className)if(a){h=(" "+g.className+" ").replace(o," ");for(i=0,j=c.length;i<j;i++)h=h.replace(" "+c[i]+" "," ");g.className=f.trim(h)}else g.className=""}}return this},toggleClass:function(a,b){var c=typeof a,d=typeof b=="boolean";if(f.isFunction(a))return this.each(function(c){f(this).toggleClass(a.call(this,c,this.className,b),b)});return this.each(function(){if(c==="string"){var e,g=0,h=f(this),i=b,j=a.split(p);while(e=j[g++])i=d?i:!h.hasClass(e),h[i?"addClass":"removeClass"](e)}else if(c==="undefined"||c==="boolean")this.className&&f._data(this,"__className__",this.className),this.className=this.className||a===!1?"":f._data(this,"__className__")||""})},hasClass:function(a){var b=" "+a+" ",c=0,d=this.length;for(;c<d;c++)if(this[c].nodeType===1&&(" "+this[c].className+" ").replace(o," ").indexOf(b)>-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.type]||f.valHooks[this.nodeName.toLowerCase()];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.type]||f.valHooks[g.nodeName.toLowerCase()];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c<d;c++){e=i[c];if(e.selected&&(f.support.optDisabled?!e.disabled:e.getAttribute("disabled")===null)&&(!e.parentNode.disabled||!f.nodeName(e.parentNode,"optgroup"))){b=f(e).val();if(j)return b;h.push(b)}}if(j&&!h.length&&i.length)return f(i[g]).val();return h},set:function(a,b){var c=f.makeArray(b);f(a).find("option").each(function(){this.selected=f.inArray(f(this).val(),c)>=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h,i=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;i<g;i++)e=d[i],e&&(c=f.propFix[e]||e,h=u.test(e),h||f.attr(a,e,""),a.removeAttribute(v?e:c),h&&c in a&&(a[c]=!1))}},attrHooks:{type:{set:function(a,b){if(r.test(a.nodeName)&&a.parentNode)f.error("type property can't be changed");else if(!f.support.radioValue&&b==="radio"&&f.nodeName(a,"input")){var c=a.value;a.setAttribute("type",b),c&&(a.value=c);return b}}},value:{get:function(a,b){if(w&&f.nodeName(a,"button"))return w.get(a,b);return b in a?a.value:null},set:function(a,b,c){if(w&&f.nodeName(a,"button"))return w.set(a,b,c);a.value=b}}},propFix:{tabindex:"tabIndex",readonly:"readOnly","for":"htmlFor","class":"className",maxlength:"maxLength",cellspacing:"cellSpacing",cellpadding:"cellPadding",rowspan:"rowSpan",colspan:"colSpan",usemap:"useMap",frameborder:"frameBorder",contenteditable:"contentEditable"},prop:function(a,c,d){var e,g,h,i=a.nodeType;if(!!a&&i!==3&&i!==8&&i!==2){h=i!==1||!f.isXMLDoc(a),h&&(c=f.propFix[c]||c,g=f.propHooks[c]);return d!==b?g&&"set"in g&&(e=g.set(a,d,c))!==b?e:a[c]=d:g&&"get"in g&&(e=g.get(a,c))!==null?e:a[c]}},propHooks:{tabIndex:{get:function(a){var c=a.getAttributeNode("tabindex");return c&&c.specified?parseInt(c.value,10):s.test(a.nodeName)||t.test(a.nodeName)&&a.href?0:b}}}}),f.attrHooks.tabindex=f.propHooks.tabIndex,x={get:function(a,c){var d,e=f.prop(a,c);return e===!0||typeof e!="boolean"&&(d=a.getAttributeNode(c))&&d.nodeValue!==!1?c.toLowerCase():b},set:function(a,b,c){var d;b===!1?f.removeAttr(a,c):(d=f.propFix[c]||c,d in a&&(a[d]=!0),a.setAttribute(c,c.toLowerCase()));return c}},v||(y={name:!0,id:!0,coords:!0},w=f.valHooks.button={get:function(a,c){var d;d=a.getAttributeNode(c);return d&&(y[c]?d.nodeValue!=="":d.specified)?d.nodeValue:b},set:function(a,b,d){var e=a.getAttributeNode(d);e||(e=c.createAttribute(d),a.setAttributeNode(e));return e.nodeValue=b+""}},f.attrHooks.tabindex.set=w.set,f.each(["width","height"],function(a,b){f.attrHooks[b]=f.extend(f.attrHooks[b],{set:function(a,c){if(c===""){a.setAttribute(b,"auto");return c}}})}),f.attrHooks.contenteditable={get:w.get,set:function(a,b,c){b===""&&(b="false"),w.set(a,b,c)}}),f.support.hrefNormalized||f.each(["href","src","width","height"],function(a,c){f.attrHooks[c]=f.extend(f.attrHooks[c],{get:function(a){var d=a.getAttribute(c,2);return d===null?b:d}})}),f.support.style||(f.attrHooks.style={get:function(a){return a.style.cssText.toLowerCase()||b},set:function(a,b){return a.style.cssText=""+b}}),f.support.optSelected||(f.propHooks.selected=f.extend(f.propHooks.selected,{get:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex);return null}})),f.support.enctype||(f.propFix.enctype="encoding"),f.support.checkOn||f.each(["radio","checkbox"],function(){f.valHooks[this]={get:function(a){return a.getAttribute("value")===null?"on":a.value}}}),f.each(["radio","checkbox"],function(){f.valHooks[this]=f.extend(f.valHooks[this],{set:function(a,b){if(f.isArray(b))return a.checked=f.inArray(f(a).val(),b)>=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/(?:^|\s)hover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(
+a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")};f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler,g=p.selector),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k<c.length;k++){l=A.exec(c[k])||[],m=l[1],n=(l[2]||"").split(".").sort(),s=f.event.special[m]||{},m=(g?s.delegateType:s.bindType)||m,s=f.event.special[m]||{},o=f.extend({type:m,origType:l[1],data:e,handler:d,guid:d.guid,selector:g,quick:g&&G(g),namespace:n.join(".")},p),r=j[m];if(!r){r=j[m]=[],r.delegateCount=0;if(!s.setup||s.setup.call(a,e,n,i)===!1)a.addEventListener?a.addEventListener(m,i,!1):a.attachEvent&&a.attachEvent("on"+m,i)}s.add&&(s.add.call(a,o),o.handler.guid||(o.handler.guid=d.guid)),g?r.splice(r.delegateCount++,0,o):r.push(o),f.event.global[m]=!0}a=null}},global:{},remove:function(a,b,c,d,e){var g=f.hasData(a)&&f._data(a),h,i,j,k,l,m,n,o,p,q,r,s;if(!!g&&!!(o=g.events)){b=f.trim(I(b||"")).split(" ");for(h=0;h<b.length;h++){i=A.exec(b[h])||[],j=k=i[1],l=i[2];if(!j){for(j in o)f.event.remove(a,j+b[h],c,d,!0);continue}p=f.event.special[j]||{},j=(d?p.delegateType:p.bindType)||j,r=o[j]||[],m=r.length,l=l?new RegExp("(^|\\.)"+l.split(".").sort().join("\\.(?:.*\\.)?")+"(\\.|$)"):null;for(n=0;n<r.length;n++)s=r[n],(e||k===s.origType)&&(!c||c.guid===s.guid)&&(!l||l.test(s.namespace))&&(!d||d===s.selector||d==="**"&&s.selector)&&(r.splice(n--,1),s.selector&&r.delegateCount--,p.remove&&p.remove.call(a,s));r.length===0&&m!==r.length&&((!p.teardown||p.teardown.call(a,l)===!1)&&f.removeEvent(a,j,g.handle),delete o[j])}f.isEmptyObject(o)&&(q=g.handle,q&&(q.elem=null),f.removeData(a,["events","handle"],!0))}},customEvent:{getData:!0,setData:!0,changeData:!0},trigger:function(c,d,e,g){if(!e||e.nodeType!==3&&e.nodeType!==8){var h=c.type||c,i=[],j,k,l,m,n,o,p,q,r,s;if(E.test(h+f.event.triggered))return;h.indexOf("!")>=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;l<r.length&&!c.isPropagationStopped();l++)m=r[l][0],c.type=r[l][1],q=(f._data(m,"events")||{})[c.type]&&f._data(m,"handle"),q&&q.apply(m,d),q=o&&m[o],q&&f.acceptData(m)&&q.apply(m,d)===!1&&c.preventDefault();c.type=h,!g&&!c.isDefaultPrevented()&&(!p._default||p._default.apply(e.ownerDocument,d)===!1)&&(h!=="click"||!f.nodeName(e,"a"))&&f.acceptData(e)&&o&&e[h]&&(h!=="focus"&&h!=="blur"||c.target.offsetWidth!==0)&&!f.isWindow(e)&&(n=e[o],n&&(e[o]=null),f.event.triggered=h,e[h](),f.event.triggered=b,n&&(e[o]=n));return c.result}},dispatch:function(c){c=f.event.fix(c||a.event);var d=(f._data(this,"events")||{})[c.type]||[],e=d.delegateCount,g=[].slice.call(arguments,0),h=!c.exclusive&&!c.namespace,i=f.event.special[c.type]||{},j=[],k,l,m,n,o,p,q,r,s,t,u;g[0]=c,c.delegateTarget=this;if(!i.preDispatch||i.preDispatch.call(this,c)!==!1){if(e&&(!c.button||c.type!=="click")){n=f(this),n.context=this.ownerDocument||this;for(m=c.target;m!=this;m=m.parentNode||this)if(m.disabled!==!0){p={},r=[],n[0]=m;for(k=0;k<e;k++)s=d[k],t=s.selector,p[t]===b&&(p[t]=s.quick?H(m,s.quick):n.is(t)),p[t]&&r.push(s);r.length&&j.push({elem:m,matches:r})}}d.length>e&&j.push({elem:this,matches:d.slice(e)});for(k=0;k<j.length&&!c.isPropagationStopped();k++){q=j[k],c.currentTarget=q.elem;for(l=0;l<q.matches.length&&!c.isImmediatePropagationStopped();l++){s=q.matches[l];if(h||!c.namespace&&!s.namespace||c.namespace_re&&c.namespace_re.test(s.namespace))c.data=s.data,c.handleObj=s,o=((f.event.special[s.origType]||{}).handle||s.handler).apply(q.elem,g),o!==b&&(c.result=o,o===!1&&(c.preventDefault(),c.stopPropagation()))}}i.postDispatch&&i.postDispatch.call(this,c);return c.result}},props:"attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){a.which==null&&(a.which=b.charCode!=null?b.charCode:b.keyCode);return a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,d){var e,f,g,h=d.button,i=d.fromElement;a.pageX==null&&d.clientX!=null&&(e=a.target.ownerDocument||c,f=e.documentElement,g=e.body,a.pageX=d.clientX+(f&&f.scrollLeft||g&&g.scrollLeft||0)-(f&&f.clientLeft||g&&g.clientLeft||0),a.pageY=d.clientY+(f&&f.scrollTop||g&&g.scrollTop||0)-(f&&f.clientTop||g&&g.clientTop||0)),!a.relatedTarget&&i&&(a.relatedTarget=i===a.target?d.toElement:i),!a.which&&h!==b&&(a.which=h&1?1:h&2?3:h&4?2:0);return a}},fix:function(a){if(a[f.expando])return a;var d,e,g=a,h=f.event.fixHooks[a.type]||{},i=h.props?this.props.concat(h.props):this.props;a=f.Event(g);for(d=i.length;d;)e=i[--d],a[e]=g[e];a.target||(a.target=g.srcElement||c),a.target.nodeType===3&&(a.target=a.target.parentNode),a.metaKey===b&&(a.metaKey=a.ctrlKey);return h.filter?h.filter(a,g):a},special:{ready:{setup:f.bindReady},load:{noBubble:!0},focus:{delegateType:"focusin"},blur:{delegateType:"focusout"},beforeunload:{setup:function(a,b,c){f.isWindow(this)&&(this.onbeforeunload=c)},teardown:function(a,b){this.onbeforeunload===b&&(this.onbeforeunload=null)}}},simulate:function(a,b,c,d){var e=f.extend(new f.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?f.event.trigger(e,null,b):f.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},f.event.handle=f.event.dispatch,f.removeEvent=c.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){a.detachEvent&&a.detachEvent("on"+b,c)},f.Event=function(a,b){if(!(this instanceof f.Event))return new f.Event(a,b);a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||a.returnValue===!1||a.getPreventDefault&&a.getPreventDefault()?K:J):this.type=a,b&&f.extend(this,b),this.timeStamp=a&&a.timeStamp||f.now(),this[f.expando]=!0},f.Event.prototype={preventDefault:function(){this.isDefaultPrevented=K;var a=this.originalEvent;!a||(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){this.isPropagationStopped=K;var a=this.originalEvent;!a||(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=K,this.stopPropagation()},isDefaultPrevented:J,isPropagationStopped:J,isImmediatePropagationStopped:J},f.each({mouseenter:"mouseover",mouseleave:"mouseout"},function(a,b){f.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c=this,d=a.relatedTarget,e=a.handleObj,g=e.selector,h;if(!d||d!==c&&!f.contains(c,d))a.type=e.origType,h=e.handler.apply(this,arguments),a.type=b;return h}}}),f.support.submitBubbles||(f.event.special.submit={setup:function(){if(f.nodeName(this,"form"))return!1;f.event.add(this,"click._submit keypress._submit",function(a){var c=a.target,d=f.nodeName(c,"input")||f.nodeName(c,"button")?c.form:b;d&&!d._submit_attached&&(f.event.add(d,"submit._submit",function(a){a._submit_bubble=!0}),d._submit_attached=!0)})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&f.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){if(f.nodeName(this,"form"))return!1;f.event.remove(this,"._submit")}}),f.support.changeBubbles||(f.event.special.change={setup:function(){if(z.test(this.nodeName)){if(this.type==="checkbox"||this.type==="radio")f.event.add(this,"propertychange._change",function(a){a.originalEvent.propertyName==="checked"&&(this._just_changed=!0)}),f.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1,f.event.simulate("change",this,a,!0))});return!1}f.event.add(this,"beforeactivate._change",function(a){var b=a.target;z.test(b.nodeName)&&!b._change_attached&&(f.event.add(b,"change._change",function(a){this.parentNode&&!a.isSimulated&&!a.isTrigger&&f.event.simulate("change",this.parentNode,a,!0)}),b._change_attached=!0)})},handle:function(a){var b=a.target;if(this!==b||a.isSimulated||a.isTrigger||b.type!=="radio"&&b.type!=="checkbox")return a.handleObj.handler.apply(this,arguments)},teardown:function(){f.event.remove(this,"._change");return z.test(this.nodeName)}}),f.support.focusinBubbles||f.each({focus:"focusin",blur:"focusout"},function(a,b){var d=0,e=function(a){f.event.simulate(b,a.target,f.event.fix(a),!0)};f.event.special[b]={setup:function(){d++===0&&c.addEventListener(a,e,!0)},teardown:function(){--d===0&&c.removeEventListener(a,e,!0)}}}),f.fn.extend({on:function(a,c,d,e,g){var h,i;if(typeof a=="object"){typeof c!="string"&&(d=d||c,c=b);for(i in a)this.on(i,c,d,a[i],g);return this}d==null&&e==null?(e=c,d=c=b):e==null&&(typeof c=="string"?(e=d,d=b):(e=d,d=c,c=b));if(e===!1)e=J;else if(!e)return this;g===1&&(h=e,e=function(a){f().off(a);return h.apply(this,arguments)},e.guid=h.guid||(h.guid=f.guid++));return this.each(function(){f.event.add(this,a,e,d,c)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,c,d){if(a&&a.preventDefault&&a.handleObj){var e=a.handleObj;f(a.delegateTarget).off(e.namespace?e.origType+"."+e.namespace:e.origType,e.selector,e.handler);return this}if(typeof a=="object"){for(var g in a)this.off(g,c,a[g]);return this}if(c===!1||typeof c=="function")d=c,c=b;d===!1&&(d=J);return this.each(function(){f.event.remove(this,a,d,c)})},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},live:function(a,b,c){f(this.context).on(a,this.selector,b,c);return this},die:function(a,b){f(this.context).off(a,this.selector||"**",b);return this},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return arguments.length==1?this.off(a,"**"):this.off(b,a,c)},trigger:function(a,b){return this.each(function(){f.event.trigger(a,b,this)})},triggerHandler:function(a,b){if(this[0])return f.event.trigger(a,b,this[0],!0)},toggle:function(a){var b=arguments,c=a.guid||f.guid++,d=0,e=function(c){var e=(f._data(this,"lastToggle"+a.guid)||0)%d;f._data(this,"lastToggle"+a.guid,e+1),c.preventDefault();return b[e].apply(this,arguments)||!1};e.guid=c;while(d<b.length)b[d++].guid=c;return this.click(e)},hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)}}),f.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){f.fn[b]=function(a,c){c==null&&(c=a,a=null);return arguments.length>0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}if(j.nodeType===1){g||(j[d]=c,j.sizset=h);if(typeof b!="string"){if(j===b){k=!0;break}}else if(m.filter(b,[j]).length>0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h<i;h++){var j=e[h];if(j){var k=!1;j=j[a];while(j){if(j[d]===c){k=e[j.sizset];break}j.nodeType===1&&!g&&(j[d]=c,j.sizset=h);if(j.nodeName.toLowerCase()===b){k=j;break}j=j[a]}e[h]=k}}}var a=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b<a.length;b++)a[b]===a[b-1]&&a.splice(b--,1)}return a},m.matches=function(a,b){return m(a,null,null,b)},m.matchesSelector=function(a,b){return m(b,null,null,[a]).length>0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e<f;e++){h=o.order[e];if(g=o.leftMatch[h].exec(a)){i=g[1],g.splice(1,1);if(i.substr(i.length-1)!=="\\"){g[1]=(g[1]||"").replace(j,""),d=o.find[h](g,b,c);if(d!=null){a=a.replace(o.match[h],"");break}}}}d||(d=typeof b.getElementsByTagName!="undefined"?b.getElementsByTagName("*"):[]);return{set:d,expr:a}},m.filter=function(a,c,d,e){var f,g,h,i,j,k,l,n,p,q=a,r=[],s=c,t=c&&c[0]&&m.isXML(c[0]);while(a&&c.length){for(h in o.filter)if((f=o.leftMatch[h].exec(a))!=null&&f[2]){k=o.filter[h],l=f[1],g=!1,f.splice(1,1);if(l.substr(l.length-1)==="\\")continue;s===r&&(r=[]);if(o.preFilter[h]){f=o.preFilter[h](f,s,d,r,e,t);if(!f)g=i=!0;else if(f===!0)continue}if(f)for(n=0;(j=s[n])!=null;n++)j&&(i=k(j,f,n,s),p=e^i,d&&i!=null?p?g=!0:s[n]=!1:p&&(r.push(j),g=!0));if(i!==b){d||(s=r),a=a.replace(o.match[h],"");if(!g)return[];break}}if(a===q)if(g==null)m.error(a);else break;q=a}return s},m.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)};var n=m.getText=function(a){var b,c,d=a.nodeType,e="";if(d){if(d===1||d===9||d===11){if(typeof a.textContent=="string")return a.textContent;if(typeof a.innerText=="string")return a.innerText.replace(k,"");for(a=a.firstChild;a;a=a.nextSibling)e+=n(a)}else if(d===3||d===4)return a.nodeValue}else for(b=0;c=a[b];b++)c.nodeType!==8&&(e+=n(c));return e},o=m.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/},leftMatch:{},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(a){return a.getAttribute("href")},type:function(a){return a.getAttribute("type")}},relative:{"+":function(a,b){var c=typeof b=="string",d=c&&!l.test(b),e=c&&!d;d&&(b=b.toLowerCase());for(var f=0,g=a.length,h;f<g;f++)if(h=a[f]){while((h=h.previousSibling)&&h.nodeType!==1);a[f]=e||h&&h.nodeName.toLowerCase()===b?h||!1:h===b}e&&m.filter(b,a,!0)},">":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e<f;e++){c=a[e];if(c){var g=c.parentNode;a[e]=g.nodeName.toLowerCase()===b?g:!1}}}else{for(;e<f;e++)c=a[e],c&&(a[e]=d?c.parentNode:c.parentNode===b);d&&m.filter(b,a,!0)}},"":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("parentNode",b,f,a,d,c)},"~":function(a,b,c){var d,f=e++,g=x;typeof b=="string"&&!l.test(b)&&(b=b.toLowerCase(),d=b,g=w),g("previousSibling",b,f,a,d,c)}},find:{ID:function(a,b,c){if(typeof b.getElementById!="undefined"&&!c){var d=b.getElementById(a[1]);return d&&d.parentNode?[d]:[]}},NAME:function(a,b){if(typeof b.getElementsByName!="undefined"){var c=[],d=b.getElementsByName(a[1]);for(var e=0,f=d.length;e<f;e++)d[e].getAttribute("name")===a[1]&&c.push(d[e]);return c.length===0?null:c}},TAG:function(a,b){if(typeof b.getElementsByTagName!="undefined")return b.getElementsByTagName(a[1])}},preFilter:{CLASS:function(a,b,c,d,e,f){a=" "+a[1].replace(j,"")+" ";if(f)return a;for(var g=0,h;(h=b[g])!=null;g++)h&&(e^(h.className&&(" "+h.className+" ").replace(/[\t\n\r]/g," ").indexOf(a)>=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return b<c[3]-0},gt:function(a,b,c){return b>c[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h<i;h++)if(g[h]===a)return!1;return!0}m.error(e)},CHILD:function(a,b){var c,e,f,g,h,i,j,k=b[1],l=a;switch(k){case"only":case"first":while(l=l.previousSibling)if(l.nodeType===1)return!1;if(k==="first")return!0;l=a;case"last":while(l=l.nextSibling)if(l.nodeType===1)return!1;return!0;case"nth":c=b[2],e=b[3];if(c===1&&e===0)return!0;f=b[0],g=a.parentNode;if(g&&(g[d]!==f||!a.nodeIndex)){i=0;for(l=g.firstChild;l;l=l.nextSibling)l.nodeType===1&&(l.nodeIndex=++i);g[d]=f}j=a.nodeIndex-e;return c===0?j===0:j%c===0&&j/c>=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));o.match.globalPOS=p;var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c<e;c++)d.push(a[c]);else for(;a[c];c++)d.push(a[c]);return d}}var u,v;c.documentElement.compareDocumentPosition?u=function(a,b){if(a===b){h=!0;return 0}if(!a.compareDocumentPosition||!b.compareDocumentPosition)return a.compareDocumentPosition?-1:1;return a.compareDocumentPosition(b)&4?-1:1}:(u=function(a,b){if(a===b){h=!0;return 0}if(a.sourceIndex&&b.sourceIndex)return a.sourceIndex-b.sourceIndex;var c,d,e=[],f=[],g=a.parentNode,i=b.parentNode,j=g;if(g===i)return v(a,b);if(!g)return-1;if(!i)return 1;while(j)e.unshift(j),j=j.parentNode;j=i;while(j)f.unshift(j),j=j.parentNode;c=e.length,d=f.length;for(var k=0;k<c&&k<d;k++)if(e[k]!==f[k])return v(e[k],f[k]);return k===c?v(a,f[k],-1):v(e[k],b,1)},v=function(a,b,c){if(a===b)return c;var d=a.nextSibling;while(d){if(d===b)return-1;d=d.nextSibling}return 1}),function(){var a=c.createElement("div"),d="script"+(new Date).getTime(),e=c.documentElement;a.innerHTML="<a name='"+d+"'/>",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="<a href='#'></a>",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="<p class='TEST'></p>";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="<div class='test e'></div><div class='test'></div>";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h<i;h++)m(a,g[h],e,c);return m.filter(f,e)};m.attr=f.attr,m.selectors.attrMap={},f.find=m,f.expr=m.selectors,f.expr[":"]=f.expr.filters,f.unique=m.uniqueSort,f.text=m.getText,f.isXMLDoc=m.isXML,f.contains=m.contains}();var L=/Until$/,M=/^(?:parents|prevUntil|prevAll)/,N=/,/,O=/^.[^:#\[\.,]*$/,P=Array.prototype.slice,Q=f.expr.match.globalPOS,R={children:!0,contents:!0,next:!0,prev:!0};f.fn.extend({find:function(a){var b=this,c,d;if(typeof a!="string")return f(a).filter(function(){for(c=0,d=b.length;c<d;c++)if(f.contains(b[c],this))return!0});var e=this.pushStack("","find",a),g,h,i;for(c=0,d=this.length;c<d;c++){g=e.length,f.find(a,this[c],e);if(c>0)for(h=g;h<e.length;h++)for(i=0;i<g;i++)if(e[i]===e[h]){e.splice(h--,1);break}}return e},has:function(a){var b=f(a);return this.filter(function(){for(var a=0,c=b.length;a<c;a++)if(f.contains(this,b[a]))return!0})},not:function(a){return this.pushStack(T(this,a,!1),"not",a)},filter:function(a){return this.pushStack(T(this,a,!0),"filter",a)},is:function(a){return!!a&&(typeof a=="string"?Q.test(a)?f(a,this.context).index(this[0])>=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d<a.length;d++)f(g).is(a[d])&&c.push({selector:a[d],elem:g,level:h});g=g.parentNode,h++}return c}var i=Q.test(a)||typeof a!="string"?f(a,b||this.context):0;for(d=0,e=this.length;d<e;d++){g=this[d];while(g){if(i?i.index(g)>-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/<tbody/i,_=/<|&#?\w+;/,ba=/<(?:script|style)/i,bb=/<(?:script|object|embed|option|style)/i,bc=new RegExp("<(?:"+V+")[\\s/>]","i"),bd=/checked\s*(?:[^=]|=\s*.checked.)/i,be=/\/(java|ecma)script/i,bf=/^\s*<!(?:\[CDATA\[|\-\-)/,bg={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],area:[1,"<map>","</map>"],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div<div>","</div>"]),f.fn.extend({text:function(a){return f.access(this,function(a){return a===b?f.text(this):this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a))},null,a,arguments.length)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f
+.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function(){for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){return f.access(this,function(a){var c=this[0]||{},d=0,e=this.length;if(a===b)return c.nodeType===1?c.innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1></$2>");try{for(;d<e;d++)c=this[d]||{},c.nodeType===1&&(f.cleanData(c.getElementsByTagName("*")),c.innerHTML=a);c=0}catch(g){}}c&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(a){if(this[0]&&this[0].parentNode){if(f.isFunction(a))return this.each(function(b){var c=f(this),d=c.html();c.replaceWith(a.call(this,b,d))});typeof a!="string"&&(a=f(a).detach());return this.each(function(){var b=this.nextSibling,c=this.parentNode;f(this).remove(),b?f(b).before(a):f(c).append(a)})}return this.length?this.pushStack(f(f.isFunction(a)?a():a),"replaceWith",a):this},detach:function(a){return this.remove(a,!0)},domManip:function(a,c,d){var e,g,h,i,j=a[0],k=[];if(!f.support.checkClone&&arguments.length===3&&typeof j=="string"&&bd.test(j))return this.each(function(){f(this).domManip(a,c,d,!0)});if(f.isFunction(j))return this.each(function(e){var g=f(this);a[0]=j.call(this,e,c?g.html():b),g.domManip(a,c,d)});if(this[0]){i=j&&j.parentNode,f.support.parentNode&&i&&i.nodeType===11&&i.childNodes.length===this.length?e={fragment:i}:e=f.buildFragment(a,this,k),h=e.fragment,h.childNodes.length===1?g=h=h.firstChild:g=h.firstChild;if(g){c=c&&f.nodeName(g,"tr");for(var l=0,m=this.length,n=m-1;l<m;l++)d.call(c?bi(this[l],g):this[l],e.cacheable||m>1&&l<n?f.clone(h,!0,!0):h)}k.length&&f.each(k,function(a,b){b.src?f.ajax({type:"GET",global:!1,url:b.src,async:!1,dataType:"script"}):f.globalEval((b.text||b.textContent||b.innerHTML||"").replace(bf,"/*$0*/")),b.parentNode&&b.parentNode.removeChild(b)})}return this}}),f.buildFragment=function(a,b,d){var e,g,h,i,j=a[0];b&&b[0]&&(i=b[0].ownerDocument||b[0]),i.createDocumentFragment||(i=c),a.length===1&&typeof j=="string"&&j.length<512&&i===c&&j.charAt(0)==="<"&&!bb.test(j)&&(f.support.checkClone||!bd.test(j))&&(f.support.html5Clone||!bc.test(j))&&(g=!0,h=f.fragments[j],h&&h!==1&&(e=h)),e||(e=i.createDocumentFragment(),f.clean(a,i,e,d)),g&&(f.fragments[j]=h?e:1);return{fragment:e,cacheable:g}},f.fragments={},f.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){f.fn[a]=function(c){var d=[],e=f(c),g=this.length===1&&this[0].parentNode;if(g&&g.nodeType===11&&g.childNodes.length===1&&e.length===1){e[b](this[0]);return this}for(var h=0,i=e.length;h<i;h++){var j=(h>0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||f.isXMLDoc(a)||!bc.test("<"+a.nodeName+">")?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g,h,i,j=[];b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);for(var k=0,l;(l=a[k])!=null;k++){typeof l=="number"&&(l+="");if(!l)continue;if(typeof l=="string")if(!_.test(l))l=b.createTextNode(l);else{l=l.replace(Y,"<$1></$2>");var m=(Z.exec(l)||["",""])[1].toLowerCase(),n=bg[m]||bg._default,o=n[0],p=b.createElement("div"),q=bh.childNodes,r;b===c?bh.appendChild(p):U(b).appendChild(p),p.innerHTML=n[1]+l+n[2];while(o--)p=p.lastChild;if(!f.support.tbody){var s=$.test(l),t=m==="table"&&!s?p.firstChild&&p.firstChild.childNodes:n[1]==="<table>"&&!s?p.childNodes:[];for(i=t.length-1;i>=0;--i)f.nodeName(t[i],"tbody")&&!t[i].childNodes.length&&t[i].parentNode.removeChild(t[i])}!f.support.leadingWhitespace&&X.test(l)&&p.insertBefore(b.createTextNode(X.exec(l)[0]),p.firstChild),l=p.childNodes,p&&(p.parentNode.removeChild(p),q.length>0&&(r=q[q.length-1],r&&r.parentNode&&r.parentNode.removeChild(r)))}var u;if(!f.support.appendChecked)if(l[0]&&typeof (u=l.length)=="number")for(i=0;i<u;i++)bn(l[i]);else bn(l);l.nodeType?j.push(l):j=f.merge(j,l)}if(d){g=function(a){return!a.type||be.test(a.type)};for(k=0;j[k];k++){h=j[k];if(e&&f.nodeName(h,"script")&&(!h.type||be.test(h.type)))e.push(h.parentNode?h.parentNode.removeChild(h):h);else{if(h.nodeType===1){var v=f.grep(h.getElementsByTagName("script"),g);j.splice.apply(j,[k+1,0].concat(v))}d.appendChild(h)}}}return j},cleanData:function(a){var b,c,d=f.cache,e=f.event.special,g=f.support.deleteExpando;for(var h=0,i;(i=a[h])!=null;h++){if(i.nodeName&&f.noData[i.nodeName.toLowerCase()])continue;c=i[f.expando];if(c){b=d[c];if(b&&b.events){for(var j in b.events)e[j]?f.event.remove(i,j):f.removeEvent(i,j,b.handle);b.handle&&(b.handle.elem=null)}g?delete i[f.expando]:i.removeAttribute&&i.removeAttribute(f.expando),delete d[c]}}}});var bp=/alpha\([^)]*\)/i,bq=/opacity=([^)]*)/,br=/([A-Z]|^ms)/g,bs=/^[\-+]?(?:\d*\.)?\d+$/i,bt=/^-?(?:\d*\.)?\d+(?!px)[^\d\s]+$/i,bu=/^([\-+])=([\-+.\de]+)/,bv=/^margin/,bw={position:"absolute",visibility:"hidden",display:"block"},bx=["Top","Right","Bottom","Left"],by,bz,bA;f.fn.css=function(a,c){return f.access(this,function(a,c,d){return d!==b?f.style(a,c,d):f.css(a,c)},a,c,arguments.length>1)},f.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=by(a,"opacity");return c===""?"1":c}return a.style.opacity}}},cssNumber:{fillOpacity:!0,fontWeight:!0,lineHeight:!0,opacity:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":f.support.cssFloat?"cssFloat":"styleFloat"},style:function(a,c,d,e){if(!!a&&a.nodeType!==3&&a.nodeType!==8&&!!a.style){var g,h,i=f.camelCase(c),j=a.style,k=f.cssHooks[i];c=f.cssProps[i]||i;if(d===b){if(k&&"get"in k&&(g=k.get(a,!1,e))!==b)return g;return j[c]}h=typeof d,h==="string"&&(g=bu.exec(d))&&(d=+(g[1]+1)*+g[2]+parseFloat(f.css(a,c)),h="number");if(d==null||h==="number"&&isNaN(d))return;h==="number"&&!f.cssNumber[i]&&(d+="px");if(!k||!("set"in k)||(d=k.set(a,d))!==b)try{j[c]=d}catch(l){}}},css:function(a,c,d){var e,g;c=f.camelCase(c),g=f.cssHooks[c],c=f.cssProps[c]||c,c==="cssFloat"&&(c="float");if(g&&"get"in g&&(e=g.get(a,!0,d))!==b)return e;if(by)return by(a,c)},swap:function(a,b,c){var d={},e,f;for(f in b)d[f]=a.style[f],a.style[f]=b[f];e=c.call(a);for(f in b)a.style[f]=d[f];return e}}),f.curCSS=f.css,c.defaultView&&c.defaultView.getComputedStyle&&(bz=function(a,b){var c,d,e,g,h=a.style;b=b.replace(br,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b))),!f.support.pixelMargin&&e&&bv.test(b)&&bt.test(c)&&(g=h.width,h.width=c,c=e.width,h.width=g);return c}),c.documentElement.currentStyle&&(bA=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f==null&&g&&(e=g[b])&&(f=e),bt.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),by=bz||bA,f.each(["height","width"],function(a,b){f.cssHooks[b]={get:function(a,c,d){if(c)return a.offsetWidth!==0?bB(a,b,d):f.swap(a,bw,function(){return bB(a,b,d)})},set:function(a,b){return bs.test(b)?b+"px":b}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return bq.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bp,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bp.test(g)?g.replace(bp,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){return f.swap(a,{display:"inline-block"},function(){return b?by(a,"margin-right"):a.style.marginRight})}})}),f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)}),f.each({margin:"",padding:"",border:"Width"},function(a,b){f.cssHooks[a+b]={expand:function(c){var d,e=typeof c=="string"?c.split(" "):[c],f={};for(d=0;d<4;d++)f[a+bx[d]+b]=e[d]||e[d-2]||e[0];return f}}});var bC=/%20/g,bD=/\[\]$/,bE=/\r?\n/g,bF=/#.*$/,bG=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bH=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bI=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bJ=/^(?:GET|HEAD)$/,bK=/^\/\//,bL=/\?/,bM=/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,bN=/^(?:select|textarea)/i,bO=/\s+/,bP=/([?&])_=[^&]*/,bQ=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bR=f.fn.load,bS={},bT={},bU,bV,bW=["*/"]+["*"];try{bU=e.href}catch(bX){bU=c.createElement("a"),bU.href="",bU=bU.href}bV=bQ.exec(bU.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bR)return bR.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("<div>").append(c.replace(bM,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bN.test(this.nodeName)||bH.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bE,"\r\n")}}):{name:b.name,value:c.replace(bE,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b$(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b$(a,b);return a},ajaxSettings:{url:bU,isLocal:bI.test(bV[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded; charset=UTF-8",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bW},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bY(bS),ajaxTransport:bY(bT),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?ca(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cb(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bG.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bF,"").replace(bK,bV[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bO),d.crossDomain==null&&(r=bQ.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bV[1]&&r[2]==bV[2]&&(r[3]||(r[1]==="http:"?80:443))==(bV[3]||(bV[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),bZ(bS,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bJ.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bL.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bP,"$1_="+x);d.url=y+(y===d.url?(bL.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bW+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=bZ(bT,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)b_(g,a[g],c,e);return d.join("&").replace(bC,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cc=f.now(),cd=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cc++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=typeof b.data=="string"&&/^application\/x\-www\-form\-urlencoded/.test(b.contentType);if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(cd.test(b.url)||e&&cd.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(cd,l),b.url===j&&(e&&(k=k.replace(cd,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var ce=a.ActiveXObject?function(){for(var a in cg)cg[a](0,1)}:!1,cf=0,cg;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ch()||ci()}:ch,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,ce&&delete cg[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n);try{m.text=h.responseText}catch(a){}try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cf,ce&&(cg||(cg={},f(a).unload(ce)),cg[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var cj={},ck,cl,cm=/^(?:toggle|show|hide)$/,cn=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,co,cp=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cq;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(ct("show",3),a,b,c);for(var g=0,h=this.length;g<h;g++)d=this[g],d.style&&(e=d.style.display,!f._data(d,"olddisplay")&&e==="none"&&(e=d.style.display=""),(e===""&&f.css(d,"display")==="none"||!f.contains(d.ownerDocument.documentElement,d))&&f._data(d,"olddisplay",cu(d.nodeName)));for(g=0;g<h;g++){d=this[g];if(d.style){e=d.style.display;if(e===""||e==="none")d.style.display=f._data(d,"olddisplay")||""}}return this},hide:function(a,b,c){if(a||a===0)return this.animate(ct("hide",3),a,b,c);var d,e,g=0,h=this.length;for(;g<h;g++)d=this[g],d.style&&(e=f.css(d,"display"),e!=="none"&&!f._data(d,"olddisplay")&&f._data(d,"olddisplay",e));for(g=0;g<h;g++)this[g].style&&(this[g].style.display="none");return this},_toggle:f.fn.toggle,toggle:function(a,b,c){var d=typeof a=="boolean";f.isFunction(a)&&f.isFunction(b)?this._toggle.apply(this,arguments):a==null||d?this.each(function(){var b=d?a:f(this).is(":hidden");f(this)[b?"show":"hide"]()}):this.animate(ct("toggle",3),a,b,c);return this},fadeTo:function(a,b,c,d){return this.filter(":hidden").css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){function g(){e.queue===!1&&f._mark(this);var b=f.extend({},e),c=this.nodeType===1,d=c&&f(this).is(":hidden"),g,h,i,j,k,l,m,n,o,p,q;b.animatedProperties={};for(i in a){g=f.camelCase(i),i!==g&&(a[g]=a[i],delete a[i]);if((k=f.cssHooks[g])&&"expand"in k){l=k.expand(a[g]),delete a[g];for(i in l)i in a||(a[i]=l[i])}}for(g in a){h=a[g],f.isArray(h)?(b.animatedProperties[g]=h[1],h=a[g]=h[0]):b.animatedProperties[g]=b.specialEasing&&b.specialEasing[g]||b.easing||"swing";if(h==="hide"&&d||h==="show"&&!d)return b.complete.call(this);c&&(g==="height"||g==="width")&&(b.overflow=[this.style.overflow,this.style.overflowX,this.style.overflowY],f.css(this,"display")==="inline"&&f.css(this,"float")==="none"&&(!f.support.inlineBlockNeedsLayout||cu(this.nodeName)==="inline"?this.style.display="inline-block":this.style.zoom=1))}b.overflow!=null&&(this.style.overflow="hidden");for(i in a)j=new f.fx(this,b,i),h=a[i],cm.test(h)?(q=f._data(this,"toggle"+i)||(h==="toggle"?d?"show":"hide":0),q?(f._data(this,"toggle"+i,q==="show"?"hide":"show"),j[q]()):j[h]()):(m=cn.exec(h),n=j.cur(),m?(o=parseFloat(m[2]),p=m[3]||(f.cssNumber[i]?"":"px"),p!=="px"&&(f.style(this,i,(o||1)+p),n=(o||1)/j.cur()*n,f.style(this,i,n+p)),m[1]&&(o=(m[1]==="-="?-1:1)*o+n),j.custom(n,o,p)):j.custom(n,h,""));return!0}var e=f.speed(b,c,d);if(f.isEmptyObject(a))return this.each(e.complete,[!1]);a=f.extend({},a);return e.queue===!1?this.each(g):this.queue(e.queue,g)},stop:function(a,c,d){typeof a!="string"&&(d=c,c=a,a=b),c&&a!==!1&&this.queue(a||"fx",[]);return this.each(function(){function h(a,b,c){var e=b[c];f.removeData(a,c,!0),e.stop(d)}var b,c=!1,e=f.timers,g=f._data(this);d||f._unmark(!0,this);if(a==null)for(b in g)g[b]&&g[b].stop&&b.indexOf(".run")===b.length-4&&h(this,g,b);else g[b=a+".run"]&&g[b].stop&&h(this,g,b);for(b=e.length;b--;)e[b].elem===this&&(a==null||e[b].queue===a)&&(d?e[b](!0):e[b].saveState(),c=!0,e.splice(b,1));(!d||!c)&&f.dequeue(this,a)})}}),f.each({slideDown:ct("show",1),slideUp:ct("hide",1),slideToggle:ct("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){f.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),f.extend({speed:function(a,b,c){var d=a&&typeof a=="object"?f.extend({},a):{complete:c||!c&&b||f.isFunction(a)&&a,duration:a,easing:c&&b||b&&!f.isFunction(b)&&b};d.duration=f.fx.off?0:typeof d.duration=="number"?d.duration:d.duration in f.fx.speeds?f.fx.speeds[d.duration]:f.fx.speeds._default;if(d.queue==null||d.queue===!0)d.queue="fx";d.old=d.complete,d.complete=function(a){f.isFunction(d.old)&&d.old.call(this),d.queue?f.dequeue(this,d.queue):a!==!1&&f._unmark(this)};return d},easing:{linear:function(a){return a},swing:function(a){return-Math.cos(a*Math.PI)/2+.5}},timers:[],fx:function(a,b,c){this.options=b,this.elem=a,this.prop=c,b.orig=b.orig||{}}}),f.fx.prototype={update:function(){this.options.step&&this.options.step.call(this.elem,this.now,this),(f.fx.step[this.prop]||f.fx.step._default)(this)},cur:function(){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null))return this.elem[this.prop];var a,b=f.css(this.elem,this.prop);return isNaN(a=parseFloat(b))?!b||b==="auto"?0:b:a},custom:function(a,c,d){function h(a){return e.step(a)}var e=this,g=f.fx;this.startTime=cq||cr(),this.end=c,this.now=this.start=a,this.pos=this.state=0,this.unit=d||this.unit||(f.cssNumber[this.prop]?"":"px"),h.queue=this.options.queue,h.elem=this.elem,h.saveState=function(){f._data(e.elem,"fxshow"+e.prop)===b&&(e.options.hide?f._data(e.elem,"fxshow"+e.prop,e.start):e.options.show&&f._data(e.elem,"fxshow"+e.prop,e.end))},h()&&f.timers.push(h)&&!co&&(co=setInterval(g.tick,g.interval))},show:function(){var a=f._data(this.elem,"fxshow"+this.prop);this.options.orig[this.prop]=a||f.style(this.elem,this.prop),this.options.show=!0,a!==b?this.custom(this.cur(),a):this.custom(this.prop==="width"||this.prop==="height"?1:0,this.cur()),f(this.elem).show()},hide:function(){this.options.orig[this.prop]=f._data(this.elem,"fxshow"+this.prop)||f.style(this.elem,this.prop),this.options.hide=!0,this.custom(this.cur(),0)},step:function(a){var b,c,d,e=cq||cr(),g=!0,h=this.elem,i=this.options;if(a||e>=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c<b.length;c++)a=b[c],!a()&&b[c]===a&&b.splice(c--,1);b.length||f.fx.stop()},interval:13,stop:function(){clearInterval(co),co=null},speeds:{slow:600,fast:200,_default:400},step:{opacity:function(a){f.style(a.elem,"opacity",a.now)},_default:function(a){a.elem.style&&a.elem.style[a.prop]!=null?a.elem.style[a.prop]=a.now+a.unit:a.elem[a.prop]=a.now}}}),f.each(cp.concat.apply([],cp),function(a,b){b.indexOf("margin")&&(f.fx.step[b]=function(a){f.style(a.elem,b,Math.max(0,a.now)+a.unit)})}),f.expr&&f.expr.filters&&(f.expr.filters.animated=function(a){return f.grep(f.timers,function(b){return a===b.elem}).length});var cv,cw=/^t(?:able|d|h)$/i,cx=/^(?:body|html)$/i;"getBoundingClientRect"in c.documentElement?cv=function(a,b,c,d){try{d=a.getBoundingClientRect()}catch(e){}if(!d||!f.contains(c,a))return d?{top:d.top,left:d.left}:{top:0,left:0};var g=b.body,h=cy(b),i=c.clientTop||g.clientTop||0,j=c.clientLeft||g.clientLeft||0,k=h.pageYOffset||f.support.boxModel&&c.scrollTop||g.scrollTop,l=h.pageXOffset||f.support.boxModel&&c.scrollLeft||g.scrollLeft,m=d.top+k-i,n=d.left+l-j;return{top:m,left:n}}:cv=function(a,b,c){var d,e=a.offsetParent,g=a,h=b.body,i=b.defaultView,j=i?i.getComputedStyle(a,null):a.currentStyle,k=a.offsetTop,l=a.offsetLeft;while((a=a.parentNode)&&a!==h&&a!==c){if(f.support.fixedPosition&&j.position==="fixed")break;d=i?i.getComputedStyle(a,null):a.currentStyle,k-=a.scrollTop,l-=a.scrollLeft,a===e&&(k+=a.offsetTop,l+=a.offsetLeft,f.support.doesNotAddBorder&&(!f.support.doesAddBorderForTableAndCells||!cw.test(a.nodeName))&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),g=e,e=a.offsetParent),f.support.subtractsBorderForOverflowNotVisible&&d.overflow!=="visible"&&(k+=parseFloat(d.borderTopWidth)||0,l+=parseFloat(d.borderLeftWidth)||0),j=d}if(j.position==="relative"||j.position==="static")k+=h.offsetTop,l+=h.offsetLeft;f.support.fixedPosition&&j.position==="fixed"&&(k+=Math.max(c.scrollTop,h.scrollTop),l+=Math.max(c.scrollLeft,h.scrollLeft));return{top:k,left:l}},f.fn.offset=function(a){if(arguments.length)return a===b?this:this.each(function(b){f.offset.setOffset(this,a,b)});var c=this[0],d=c&&c.ownerDocument;if(!d)return null;if(c===d.body)return f.offset.bodyOffset(c);return cv(c,d,d.documentElement)},f.offset={bodyOffset:function(a){var b=a.offsetTop,c=a.offsetLeft;f.support.doesNotIncludeMarginInBodyOffset&&(b+=parseFloat(f.css(a,"marginTop"))||0,c+=parseFloat(f.css(a,"marginLeft"))||0);return{top:b,left:c}},setOffset:function(a,b,c){var d=f.css(a,"position");d==="static"&&(a.style.position="relative");var e=f(a),g=e.offset(),h=f.css(a,"top"),i=f.css(a,"left"),j=(d==="absolute"||d==="fixed")&&f.inArray("auto",[h,i])>-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,c){var d=/Y/.test(c);f.fn[a]=function(e){return f.access(this,function(a,e,g){var h=cy(a);if(g===b)return h?c in h?h[c]:f.support.boxModel&&h.document.documentElement[e]||h.document.body[e]:a[e];h?h.scrollTo(d?f(h).scrollLeft():g,d?g:f(h).scrollTop()):a[e]=g},a,e,arguments.length,null)}}),f.each({Height:"height",Width:"width"},function(a,c){var d="client"+a,e="scroll"+a,g="offset"+a;f.fn["inner"+a]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,c,"padding")):this[c]():null},f.fn["outer"+a]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,c,a?"margin":"border")):this[c]():null},f.fn[c]=function(a){return f.access(this,function(a,c,h){var i,j,k,l;if(f.isWindow(a)){i=a.document,j=i.documentElement[d];return f.support.boxModel&&j||i.body&&i.body[d]||j}if(a.nodeType===9){i=a.documentElement;if(i[d]>=i[e])return i[d];return Math.max(a.body[e],i[e],a.body[g],i[g])}if(h===b){k=f.css(a,c),l=parseFloat(k);return f.isNumeric(l)?l:k}f(a).css(c,h)},c,a,arguments.length,null)}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window);
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/lib/jquery.mousewheel.min.js	Tue Dec 25 21:29:11 2012 +0100
@@ -0,0 +1,12 @@
+/*! Copyright (c) 2011 Brandon Aaron (http://brandonaaron.net)
+ * Licensed under the MIT License (LICENSE.txt).
+ *
+ * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
+ * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
+ * Thanks to: Seamus Leahy for adding deltaX and deltaY
+ *
+ * Version: 3.0.6
+ * 
+ * Requires: 1.2.2+
+ */
+(function(a){function d(b){var c=b||window.event,d=[].slice.call(arguments,1),e=0,f=!0,g=0,h=0;return b=a.event.fix(c),b.type="mousewheel",c.wheelDelta&&(e=c.wheelDelta/120),c.detail&&(e=-c.detail/3),h=e,c.axis!==undefined&&c.axis===c.HORIZONTAL_AXIS&&(h=0,g=-1*e),c.wheelDeltaY!==undefined&&(h=c.wheelDeltaY/120),c.wheelDeltaX!==undefined&&(g=-1*c.wheelDeltaX/120),d.unshift(b,e,g,h),(a.event.dispatch||a.event.handle).apply(this,d)}var b=["DOMMouseScroll","mousewheel"];if(a.event.fixHooks)for(var c=b.length;c;)a.event.fixHooks[b[--c]]=a.event.mouseHooks;a.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=b.length;a;)this.addEventListener(b[--a],d,!1);else this.onmousewheel=d},teardown:function(){if(this.removeEventListener)for(var a=b.length;a;)this.removeEventListener(b[--a],d,!1);else this.onmousewheel=null}},a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery)
Binary file server/src/main/webapp/static/lib/paper.js has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/server/src/main/webapp/static/lib/underscore-min.js	Tue Dec 25 21:29:11 2012 +0100
@@ -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);