diff --git a/source/java/org/alfresco/web/templating/TemplateInputMethod.java b/source/java/org/alfresco/web/templating/TemplateInputMethod.java
index 75c31f833d..ae76e9605a 100644
--- a/source/java/org/alfresco/web/templating/TemplateInputMethod.java
+++ b/source/java/org/alfresco/web/templating/TemplateInputMethod.java
@@ -23,5 +23,5 @@ public interface TemplateInputMethod
public String getInputURL(final Document xmlContent,
final TemplateType tt);
- public String getSchemaInputURL(final TemplateType tt);
+ // public String getSchemaInputURL(final TemplateType tt);
}
diff --git a/source/java/org/alfresco/web/templating/TemplatingService.java b/source/java/org/alfresco/web/templating/TemplatingService.java
index 01fe985cb6..921878acc2 100644
--- a/source/java/org/alfresco/web/templating/TemplatingService.java
+++ b/source/java/org/alfresco/web/templating/TemplatingService.java
@@ -76,15 +76,27 @@ public class TemplatingService
return new TemplateTypeImpl(name, schema);
}
- public void writeXML(final Node d, final File output)
+ public Document newDocument()
+ throws ParserConfigurationException,
+ SAXException,
+ IOException
+ {
+ final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setNamespaceAware(true);
+ dbf.setValidating(false);
+ final DocumentBuilder db = dbf.newDocumentBuilder();
+ return db.newDocument();
+ }
+
+ public void writeXML(final Node n, final Writer output)
{
try
{
- System.out.println("writing out a document for " + d.getNodeName() +
+ System.out.println("writing out a document for " + n.getNodeName() +
" to " + output);
final TransformerFactory tf = TransformerFactory.newInstance();
final Transformer t = tf.newTransformer();
- t.transform(new DOMSource(d), new StreamResult(output));
+ t.transform(new DOMSource(n), new StreamResult(output));
}
catch (TransformerException te)
{
@@ -93,6 +105,13 @@ public class TemplatingService
}
}
+ public void writeXML(final Node n, final File output)
+ throws IOException
+ {
+
+ this.writeXML(n, new FileWriter(output));
+ }
+
public Document parseXML(final String source)
throws ParserConfigurationException,
SAXException,
diff --git a/source/java/org/alfresco/web/templating/xforms/DojoGenerator.java b/source/java/org/alfresco/web/templating/xforms/DojoGenerator.java
new file mode 100644
index 0000000000..a90edebddd
--- /dev/null
+++ b/source/java/org/alfresco/web/templating/xforms/DojoGenerator.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2005 Alfresco, Inc.
+ *
+ * Licensed under the Mozilla Public License version 1.1
+ * with a permitted attribution clause. You may obtain a
+ * copy of the License at
+ *
+ * http://www.alfresco.org/legal/license.txt
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied. See the License for the specific
+ * language governing permissions and limitations under the
+ * License.
+ */
+package org.alfresco.web.templating.xforms;
+
+import org.chiba.tools.xslt.UIGenerator;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Iterator;
+import javax.servlet.*;
+import javax.servlet.http.*;
+import java.io.*;
+import org.chiba.xml.xforms.exception.XFormsException;
+
+public class DojoGenerator
+ implements UIGenerator
+{
+
+ private Node inputNode;
+ private final HashMap parameters = new HashMap();
+ private final HttpServletRequest request;
+ private final HttpServletResponse response;
+
+ public DojoGenerator(HttpServletRequest request,
+ HttpServletResponse response)
+ {
+ this.request = request;
+ this.response = response;
+ }
+
+ public void setInputNode(final Node inputNode)
+ {
+ this.inputNode = inputNode;
+ }
+
+ public void setParameter(final String key, final Object value)
+ {
+ this.parameters.put(key, value);
+ }
+
+ public void setOutput(Object output)
+ {
+ // this.output = output;
+ }
+
+ public void generate()
+ throws XFormsException
+ {
+ try
+ {
+ request.setAttribute("xform", this.inputNode);
+ final RequestDispatcher rd = request.getRequestDispatcher("/jsp/content/xforms/dojo-generator.jsp");
+ rd.include(request, response);
+ }
+ catch (Exception e)
+ {
+ throw new XFormsException(e);
+ }
+ }
+}
+
\ No newline at end of file
diff --git a/source/java/org/alfresco/web/templating/xforms/XFormsInputMethod.java b/source/java/org/alfresco/web/templating/xforms/XFormsInputMethod.java
index a3065c46bd..4a081fcda6 100644
--- a/source/java/org/alfresco/web/templating/xforms/XFormsInputMethod.java
+++ b/source/java/org/alfresco/web/templating/xforms/XFormsInputMethod.java
@@ -24,6 +24,8 @@ import org.alfresco.util.TempFileProvider;
import org.alfresco.web.templating.*;
import org.alfresco.web.templating.xforms.schemabuilder.*;
import org.chiba.xml.util.DOMUtil;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
@@ -31,6 +33,7 @@ import org.w3c.dom.Node;
public class XFormsInputMethod
implements TemplateInputMethod
{
+ private static final Log LOGGER = LogFactory.getLog(XFormsInputMethod.class);
public XFormsInputMethod()
{
@@ -122,8 +125,15 @@ public class XFormsInputMethod
{
final TemplatingService ts = TemplatingService.getInstance();
final File schemaFile = TempFileProvider.createTempFile("alfresco", ".schema");
- ts.writeXML(tt.getSchema(), schemaFile);
-
+ try
+ {
+ ts.writeXML(tt.getSchema(), schemaFile);
+ }
+ catch (IOException ioe)
+ {
+ assert false : ioe.getMessage();
+ LOGGER.error(ioe);
+ }
final FacesContext fc = FacesContext.getCurrentInstance();
final String cp =
fc.getExternalContext().getRequestContextPath();
diff --git a/source/java/org/alfresco/web/templating/xforms/servlet/ChibaServlet.java b/source/java/org/alfresco/web/templating/xforms/servlet/ChibaServlet.java
index b4fab79e6b..f132155abf 100644
--- a/source/java/org/alfresco/web/templating/xforms/servlet/ChibaServlet.java
+++ b/source/java/org/alfresco/web/templating/xforms/servlet/ChibaServlet.java
@@ -1,11 +1,13 @@
package org.alfresco.web.templating.xforms.servlet;
import org.alfresco.web.app.Application;
+import org.alfresco.web.templating.xforms.DojoGenerator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.httpclient.Cookie;
import org.chiba.adapter.ChibaAdapter;
import org.alfresco.web.templating.xforms.flux.FluxAdapter;
+import org.alfresco.web.templating.TemplatingService;
import org.chiba.tools.xslt.StylesheetLoader;
import org.chiba.tools.xslt.UIGenerator;
import org.chiba.tools.xslt.XSLTGenerator;
@@ -44,7 +46,6 @@ public class ChibaServlet extends HttpServlet {
//init-params
private static Log logger = LogFactory.getLog(ChibaServlet.class);
-
private static final String FORM_PARAM_NAME = "form";
private static final String XSL_PARAM_NAME = "xslt";
private static final String CSS_PARAM_NAME = "css";
@@ -164,54 +165,68 @@ public class ChibaServlet extends HttpServlet {
*/
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
- throws ServletException, IOException {
+ throws ServletException, IOException {
ChibaAdapter adapter = null;
HttpSession session = request.getSession(true);
+ try {
+ if (request.getParameter("xxx") != null)
+ {
+ response.setContentType("text/xml");
+ Writer out = response.getWriter();
+ adapter = (ChibaAdapter)session.getAttribute(CHIBA_ADAPTER);
+ TemplatingService.getInstance().writeXML(adapter.getXForms(), out);
+ out.close();
+ }
+ else
+ {
+ logger.info("--------------- new XForms session ---------------");
+ //kill everything that may have lived before
+ session.removeAttribute(CHIBA_ADAPTER);
+ session.removeAttribute(CHIBA_UI_GENERATOR);
- logger.info("--------------- new XForms session ---------------");
- try {
- //kill everything that may have lived before
- session.removeAttribute(CHIBA_ADAPTER);
- session.removeAttribute(CHIBA_UI_GENERATOR);
+ // determine Form to load
+ String formURI = /*getRequestURI(request) +*/ request.getParameter(FORM_PARAM_NAME);
+ logger.info("formURI: " + formURI);
+ String xslFile = request.getParameter(XSL_PARAM_NAME);
+ String css = request.getParameter(CSS_PARAM_NAME);
+ String actionURL = getActionURL(request, response,true);
+ logger.info("setting up adapeter");
- // determine Form to load
- String formURI = /*getRequestURI(request) +*/ request.getParameter(FORM_PARAM_NAME);
- logger.info("formURI: " + formURI);
- String xslFile = request.getParameter(XSL_PARAM_NAME);
- String css = request.getParameter(CSS_PARAM_NAME);
- String actionURL = getActionURL(request, response,true);
- logger.info("setting up adapeter");
+ //setup Adapter
+ adapter = setupAdapter(new FluxAdapter(session), session, formURI);
+ setContextParams(request, adapter);
+ storeCookies(request, adapter);
+ adapter.init();
- //setup Adapter
- adapter = setupAdapter(new FluxAdapter(session), session, formURI);
- setContextParams(request, adapter);
- storeCookies(request, adapter);
- adapter.init();
+ if (load(adapter, response)) return;
+ if (replaceAll(adapter, response)) return;
- if (load(adapter, response)) return;
- if (replaceAll(adapter, response)) return;
+ // response.setContentType("text/html");
+ // PrintWriter out = response.getWriter();
- response.setContentType("text/html");
- PrintWriter out = response.getWriter();
+ logger.info("generating ui");
- logger.info("generating ui");
+ UIGenerator uiGenerator = createUIGenerator(request,
+ response,
+ actionURL,
+ xslFile,
+ css);
+ uiGenerator.setInputNode(adapter.getXForms());
+ // uiGenerator.setOutput(out);
+ uiGenerator.generate();
- UIGenerator uiGenerator = createUIGenerator(request, actionURL, xslFile, css);
- uiGenerator.setInputNode(adapter.getXForms());
- uiGenerator.setOutput(out);
- uiGenerator.generate();
+ //store adapter in session
+ session.setAttribute(CHIBA_ADAPTER, adapter);
+ session.setAttribute(CHIBA_UI_GENERATOR,uiGenerator);
- //store adapter in session
- session.setAttribute(CHIBA_ADAPTER, adapter);
- session.setAttribute(CHIBA_UI_GENERATOR,uiGenerator);
-
- out.close();
- logger.info("done!");
- } catch (Exception e) {
+ // out.close();
+ logger.info("done!");
+ }
+ } catch (Exception e) {
e.printStackTrace();
- shutdown(adapter, session, e, response, request);
- }
+ shutdown(adapter, session, e, response, request);
+ }
}
/**
@@ -228,24 +243,24 @@ public class ChibaServlet extends HttpServlet {
* @return ServletAdapter
*/
protected ChibaAdapter setupAdapter(ChibaAdapter adapter,
- HttpSession session,
- String formPath)
+ HttpSession session,
+ String formPath)
throws XFormsException, URISyntaxException {
- adapter.createXFormsProcessor();
+ adapter.createXFormsProcessor();
- if ((configPath != null) && !(configPath.equals(""))) {
- adapter.setConfigPath(configPath);
- }
- adapter.setXForms(new URI(formPath));
- adapter.setBaseURI(formPath);
- adapter.setUploadDestination(uploadDir);
+ if ((configPath != null) && !(configPath.equals(""))) {
+ adapter.setConfigPath(configPath);
+ }
+ adapter.setXForms(new URI(formPath));
+ adapter.setBaseURI(formPath);
+ adapter.setUploadDestination(uploadDir);
- Map servletMap = new HashMap();
- servletMap.put(ChibaAdapter.SESSION_ID, session.getId());
- adapter.setContextParam(ChibaAdapter.SUBMISSION_RESPONSE, servletMap);
+ Map servletMap = new HashMap();
+ servletMap.put(ChibaAdapter.SESSION_ID, session.getId());
+ adapter.setContextParam(ChibaAdapter.SUBMISSION_RESPONSE, servletMap);
- return adapter;
+ return adapter;
}
/**
@@ -257,21 +272,21 @@ public class ChibaServlet extends HttpServlet {
* @param adapter the Chiba adapter instance
*/
protected void storeCookies(HttpServletRequest request,ChibaAdapter adapter){
- javax.servlet.http.Cookie[] cookiesIn = request.getCookies();
- if (cookiesIn != null) {
- Cookie[] commonsCookies = new org.apache.commons.httpclient.Cookie[cookiesIn.length];
- for (int i = 0; i < cookiesIn.length; i += 1) {
- javax.servlet.http.Cookie c = cookiesIn[i];
- Cookie newCookie = new Cookie(c.getDomain(),
- c.getName(),
- c.getValue(),
- c.getPath(),
- c.getMaxAge(),
- c.getSecure());
- commonsCookies[i] = newCookie;
- }
- adapter.setContextParam(AbstractHTTPConnector.REQUEST_COOKIE,commonsCookies);
- }
+ javax.servlet.http.Cookie[] cookiesIn = request.getCookies();
+ if (cookiesIn != null) {
+ Cookie[] commonsCookies = new org.apache.commons.httpclient.Cookie[cookiesIn.length];
+ for (int i = 0; i < cookiesIn.length; i += 1) {
+ javax.servlet.http.Cookie c = cookiesIn[i];
+ Cookie newCookie = new Cookie(c.getDomain(),
+ c.getName(),
+ c.getValue(),
+ c.getPath(),
+ c.getMaxAge(),
+ c.getSecure());
+ commonsCookies[i] = newCookie;
+ }
+ adapter.setContextParam(AbstractHTTPConnector.REQUEST_COOKIE,commonsCookies);
+ }
}
/**
@@ -285,41 +300,42 @@ public class ChibaServlet extends HttpServlet {
* @throws XFormsException
*/
protected UIGenerator createUIGenerator(HttpServletRequest request,
- String actionURL,
- String xslFile,
- String css)
+ HttpServletResponse response,
+ String actionURL,
+ String xslFile,
+ String css)
throws XFormsException {
- StylesheetLoader stylesheetLoader = new StylesheetLoader(stylesPath);
- if (xslFile != null){
- stylesheetLoader.setStylesheetFile(xslFile);
- }
- UIGenerator uiGenerator = new XSLTGenerator(stylesheetLoader);
+// StylesheetLoader stylesheetLoader = new StylesheetLoader(stylesPath);
+// if (xslFile != null){
+// stylesheetLoader.setStylesheetFile(xslFile);
+// }
+ UIGenerator uiGenerator = new DojoGenerator(request, response);
- //set parameters
- uiGenerator.setParameter("contextroot",request.getContextPath());
- uiGenerator.setParameter("action-url",actionURL);
- uiGenerator.setParameter("debug-enabled", String.valueOf(logger.isDebugEnabled()));
- String selectorPrefix =
+ //set parameters
+ uiGenerator.setParameter("contextroot",request.getContextPath());
+ uiGenerator.setParameter("action-url",actionURL);
+ uiGenerator.setParameter("debug-enabled", String.valueOf(logger.isDebugEnabled()));
+ String selectorPrefix =
Config.getInstance().getProperty(HttpRequestHandler.SELECTOR_PREFIX_PROPERTY,
HttpRequestHandler.SELECTOR_PREFIX_DEFAULT);
- uiGenerator.setParameter("selector-prefix", selectorPrefix);
- String removeUploadPrefix =
+ uiGenerator.setParameter("selector-prefix", selectorPrefix);
+ String removeUploadPrefix =
Config.getInstance().getProperty(HttpRequestHandler.REMOVE_UPLOAD_PREFIX_PROPERTY,
HttpRequestHandler.REMOVE_UPLOAD_PREFIX_DEFAULT);
- uiGenerator.setParameter("remove-upload-prefix", removeUploadPrefix);
- if (css != null)
- uiGenerator.setParameter("css-file", css);
- String dataPrefix = Config.getInstance().getProperty("chiba.web.dataPrefix");
- uiGenerator.setParameter("data-prefix", dataPrefix);
+ uiGenerator.setParameter("remove-upload-prefix", removeUploadPrefix);
+ if (css != null)
+ uiGenerator.setParameter("css-file", css);
+ String dataPrefix = Config.getInstance().getProperty("chiba.web.dataPrefix");
+ uiGenerator.setParameter("data-prefix", dataPrefix);
- String triggerPrefix = Config.getInstance().getProperty("chiba.web.triggerPrefix");
- uiGenerator.setParameter("trigger-prefix", triggerPrefix);
+ String triggerPrefix = Config.getInstance().getProperty("chiba.web.triggerPrefix");
+ uiGenerator.setParameter("trigger-prefix", triggerPrefix);
- uiGenerator.setParameter("user-agent", request.getHeader("User-Agent"));
+ uiGenerator.setParameter("user-agent", request.getHeader("User-Agent"));
- uiGenerator.setParameter("scripted","true");
+ // uiGenerator.setParameter("scripted","true");
- return uiGenerator;
+ return uiGenerator;
}
/**
@@ -331,39 +347,39 @@ public class ChibaServlet extends HttpServlet {
*/
protected void setContextParams(HttpServletRequest request, ChibaAdapter chibaAdapter) {
- //[1] pass user-agent to Adapter for UI-building
- chibaAdapter.setContextParam(ServletAdapter.USERAGENT, request.getHeader("User-Agent"));
+ //[1] pass user-agent to Adapter for UI-building
+ chibaAdapter.setContextParam(ServletAdapter.USERAGENT, request.getHeader("User-Agent"));
- //[2] read any request params that are *not* Chiba params and pass them into the context map
- Enumeration params = request.getParameterNames();
- while (params.hasMoreElements()) {
- String s = (String) params.nextElement();
- //store all request-params we don't use in the context map of ChibaBean
- if (!(s.equals(FORM_PARAM_NAME) ||
- s.equals(XSL_PARAM_NAME) ||
- s.equals(CSS_PARAM_NAME) ||
- s.equals(ACTIONURL_PARAM_NAME))) {
- String value = request.getParameter(s);
- //servletAdapter.setContextProperty(s, value);
- chibaAdapter.setContextParam(s, value);
- if (logger.isDebugEnabled()) {
- logger.debug("added request param '" + s + "' added to context");
- }
- }
- }
+ //[2] read any request params that are *not* Chiba params and pass them into the context map
+ Enumeration params = request.getParameterNames();
+ while (params.hasMoreElements()) {
+ String s = (String) params.nextElement();
+ //store all request-params we don't use in the context map of ChibaBean
+ if (!(s.equals(FORM_PARAM_NAME) ||
+ s.equals(XSL_PARAM_NAME) ||
+ s.equals(CSS_PARAM_NAME) ||
+ s.equals(ACTIONURL_PARAM_NAME))) {
+ String value = request.getParameter(s);
+ //servletAdapter.setContextProperty(s, value);
+ chibaAdapter.setContextParam(s, value);
+ if (logger.isDebugEnabled()) {
+ logger.debug("added request param '" + s + "' added to context");
+ }
+ }
+ }
}
/**
* @deprecated should be re-implemented using chiba events on adapter
*/
protected boolean load(ChibaAdapter adapter, HttpServletResponse response) throws XFormsException, IOException {
- if (adapter.getContextParam(ChibaAdapter.LOAD_URI) != null) {
- String redirectTo = (String) adapter.removeContextParam(ChibaAdapter.LOAD_URI);
- adapter.shutdown();
- response.sendRedirect(response.encodeRedirectURL(redirectTo));
- return true;
- }
- return false;
+ if (adapter.getContextParam(ChibaAdapter.LOAD_URI) != null) {
+ String redirectTo = (String) adapter.removeContextParam(ChibaAdapter.LOAD_URI);
+ adapter.shutdown();
+ response.sendRedirect(response.encodeRedirectURL(redirectTo));
+ return true;
+ }
+ return false;
}
/**
@@ -371,79 +387,79 @@ public class ChibaServlet extends HttpServlet {
*/
protected boolean replaceAll(ChibaAdapter chibaAdapter, HttpServletResponse response)
throws XFormsException, IOException {
- if (chibaAdapter.getContextParam(ChibaAdapter.SUBMISSION_RESPONSE) != null) {
- Map forwardMap = (Map) chibaAdapter.removeContextParam(ChibaAdapter.SUBMISSION_RESPONSE);
- if (forwardMap.containsKey(ChibaAdapter.SUBMISSION_RESPONSE_STREAM)) {
- forwardResponse(forwardMap, response);
- chibaAdapter.shutdown();
- return true;
- }
- }
- return false;
+ if (chibaAdapter.getContextParam(ChibaAdapter.SUBMISSION_RESPONSE) != null) {
+ Map forwardMap = (Map) chibaAdapter.removeContextParam(ChibaAdapter.SUBMISSION_RESPONSE);
+ if (forwardMap.containsKey(ChibaAdapter.SUBMISSION_RESPONSE_STREAM)) {
+ forwardResponse(forwardMap, response);
+ chibaAdapter.shutdown();
+ return true;
+ }
+ }
+ return false;
}
private String getActionURL(HttpServletRequest request, HttpServletResponse response, boolean scripted) {
- String defaultActionURL = getRequestURI(request) + agent;
- String encodedDefaultActionURL = response.encodeURL(defaultActionURL);
- int sessIdx = encodedDefaultActionURL.indexOf(";jsession");
- String sessionId = null;
- if (sessIdx > -1) {
- sessionId = encodedDefaultActionURL.substring(sessIdx);
- }
- String actionURL = request.getParameter(ACTIONURL_PARAM_NAME);
- if (null == actionURL) {
- actionURL = encodedDefaultActionURL;
- } else if (null != sessionId) {
- actionURL += sessionId;
- }
+ String defaultActionURL = getRequestURI(request) + agent;
+ String encodedDefaultActionURL = response.encodeURL(defaultActionURL);
+ int sessIdx = encodedDefaultActionURL.indexOf(";jsession");
+ String sessionId = null;
+ if (sessIdx > -1) {
+ sessionId = encodedDefaultActionURL.substring(sessIdx);
+ }
+ String actionURL = request.getParameter(ACTIONURL_PARAM_NAME);
+ if (null == actionURL) {
+ actionURL = encodedDefaultActionURL;
+ } else if (null != sessionId) {
+ actionURL += sessionId;
+ }
- logger.info("actionURL: " + actionURL);
- // encode the URL to allow for session id rewriting
- return response.encodeURL(actionURL);
+ logger.info("actionURL: " + actionURL);
+ // encode the URL to allow for session id rewriting
+ return response.encodeURL(actionURL);
}
private String getRequestURI(HttpServletRequest request){
- StringBuffer buffer = new StringBuffer(request.getScheme());
- buffer.append("://");
- buffer.append(request.getServerName());
- buffer.append(":");
- buffer.append(request.getServerPort()) ;
- buffer.append(request.getContextPath());
- return buffer.toString();
+ StringBuffer buffer = new StringBuffer(request.getScheme());
+ buffer.append("://");
+ buffer.append(request.getServerName());
+ buffer.append(":");
+ buffer.append(request.getServerPort()) ;
+ buffer.append(request.getContextPath());
+ return buffer.toString();
}
private void forwardResponse(Map forwardMap, HttpServletResponse response) throws IOException {
- // fetch response stream
- InputStream responseStream = (InputStream) forwardMap.remove(ChibaAdapter.SUBMISSION_RESPONSE_STREAM);
+ // fetch response stream
+ InputStream responseStream = (InputStream) forwardMap.remove(ChibaAdapter.SUBMISSION_RESPONSE_STREAM);
- // copy header information
- Iterator iterator = forwardMap.keySet().iterator();
- while (iterator.hasNext()) {
+ // copy header information
+ Iterator iterator = forwardMap.keySet().iterator();
+ while (iterator.hasNext()) {
- String name = (String) iterator.next();
+ String name = (String) iterator.next();
- if ("Transfer-Encoding".equalsIgnoreCase(name)) {
- // Some servers (e.g. WebSphere) may set a "Transfer-Encoding"
- // with the value "chunked". This may confuse the client since
- // ChibaServlet output is not encoded as "chunked", so this
- // header is ignored.
- continue;
- }
- String value = (String) forwardMap.get(name);
- response.setHeader(name, value);
- }
+ if ("Transfer-Encoding".equalsIgnoreCase(name)) {
+ // Some servers (e.g. WebSphere) may set a "Transfer-Encoding"
+ // with the value "chunked". This may confuse the client since
+ // ChibaServlet output is not encoded as "chunked", so this
+ // header is ignored.
+ continue;
+ }
+ String value = (String) forwardMap.get(name);
+ response.setHeader(name, value);
+ }
- // copy stream content
- OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
- for (int b = responseStream.read();
- b > -1;
- b = responseStream.read()) {
- outputStream.write(b);
- }
+ // copy stream content
+ OutputStream outputStream = new BufferedOutputStream(response.getOutputStream());
+ for (int b = responseStream.read();
+ b > -1;
+ b = responseStream.read()) {
+ outputStream.write(b);
+ }
- // close streams
- responseStream.close();
- outputStream.close();
+ // close streams
+ responseStream.close();
+ outputStream.close();
}
protected void shutdown(ChibaAdapter chibaAdapter,
@@ -452,15 +468,15 @@ public class ChibaServlet extends HttpServlet {
HttpServletResponse response,
HttpServletRequest request)
throws IOException,
- ServletException {
- // attempt to shutdown processor
- if (chibaAdapter != null) {
- try {
- chibaAdapter.shutdown();
- } catch (XFormsException xfe) {
- xfe.printStackTrace();
- }
- }
+ ServletException {
+ // attempt to shutdown processor
+ if (chibaAdapter != null) {
+ try {
+ chibaAdapter.shutdown();
+ } catch (XFormsException xfe) {
+ xfe.printStackTrace();
+ }
+ }
Application.handleServletError(this.getServletContext(),
request,
response,
diff --git a/source/web/jsp/content/xforms/dojo-generator.jsp b/source/web/jsp/content/xforms/dojo-generator.jsp
new file mode 100644
index 0000000000..7d57eaf492
--- /dev/null
+++ b/source/web/jsp/content/xforms/dojo-generator.jsp
@@ -0,0 +1,31 @@
+<%@ page import="java.io.*,
+ java.util.Enumeration,
+ java.text.DateFormat,
+ java.util.Date,
+ org.alfresco.web.bean.content.*,
+ org.alfresco.web.templating.*,
+ org.w3c.dom.*"%>
+<%@ page session="true" %>
+<%@ page errorPage="error.jsp" %>
+<%
+String url = request.getContextPath() + request.getServletPath() + '?' + request.getQueryString() + "&xxx=bla";
+%>
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/source/web/jsp/content/xforms/xforms.js b/source/web/jsp/content/xforms/xforms.js
new file mode 100644
index 0000000000..81bd1ca281
--- /dev/null
+++ b/source/web/jsp/content/xforms/xforms.js
@@ -0,0 +1,269 @@
+dojo.require("dojo.widget.DebugConsole");
+dojo.require("dojo.widget.Button");
+dojo.require("dojo.widget.validate");
+dojo.require("dojo.widget.ComboBox");
+dojo.require("dojo.widget.Checkbox");
+dojo.require("dojo.widget.Editor");
+dojo.require("dojo.widget.Spinner");
+dojo.require("dojo.html.style");
+dojo.hostenv.writeIncludes();
+dojo.addOnLoad(xforms_init);
+
+var bindings = {};
+var xform = null;
+function xforms_init()
+{
+ dojo.io.bind({
+ url: xforms_url,
+ mimetype: "text/xml",
+ load: function(type, data, evt)
+ {
+ xform = data.documentElement;
+ var model = xform.getElementsByTagName("model");
+ load_bindings(model[0]);
+ for (var i in bindings)
+ {
+ dojo.debug("bindings["+i+"]="+bindings[i].id+", parent = "+ (bindings[i].parent ? bindings[i].parent.id : 'null'));
+ }
+
+ var body = xform.getElementsByTagName("body");
+ load_body(body[0], [ document.getElementById("alf-ui") ]);
+ },
+ error: function(type, e)
+ {
+ alert("error " + type + " e = " + e);
+ }
+ });
+}
+
+function get_instance()
+{
+ var model = xform.getElementsByTagName("model")[0];
+ return model.getElementsByTagName("instance")[0];
+}
+
+function load_bindings(bind, parent)
+{
+ dojo.lang.forEach(bind.childNodes, function(b)
+ {
+ if (b.nodeName.toLowerCase() == "xforms:bind")
+ {
+ var id = b.getAttribute("id");
+ bindings[id] = {
+ id: b.getAttribute("id"),
+ required: b.getAttribute("xforms:required"),
+ nodeset: b.getAttribute("xforms:nodeset"),
+ type: b.getAttribute("xforms:type"),
+ parent: parent
+ }
+ load_bindings(b, bindings[id]);
+ }
+ });
+}
+
+function load_body(body, ui_element_stack)
+{
+ dojo.lang.forEach(body.childNodes, function(o)
+ {
+ dojo.debug(o + " nn " + o.nodeName);
+ switch (o.nodeName.toLowerCase())
+ {
+ case "xforms:group":
+ var table = document.createElement("table");
+ table.setAttribute("style", "width:100%");
+ ui_element_stack[ui_element_stack.length - 1].appendChild(table);
+ ui_element_stack.push(table);
+ load_body(o, ui_element_stack);
+ ui_element_stack.pop();
+ break;
+// case "xforms:label":
+// var label = document.createElement("span");
+// label.appendChild(document.createTextNode(dojo.dom.textContent(o)));
+// ui_element_stack.last().appendChild(label);
+// break;
+ case "xforms:textarea":
+ var row = document.createElement("tr");
+ ui_element_stack[ui_element_stack.length - 1].appendChild(row);
+ var label = get_label_node(o);
+ var cell = document.createElement("td");
+ row.appendChild(cell);
+ if (label)
+ cell.appendChild(document.createTextNode(dojo.dom.textContent(label)));
+ cell = document.createElement("td");
+ row.appendChild(cell);
+ var nodeRef = document.createElement("div");
+ nodeRef.setAttribute("style", "height: 200px");
+ cell.appendChild(nodeRef);
+ var w = dojo.widget.createWidget("Editor", { items: ["|", "bold", "italic", "underline", "strikethrough", "|", "colorGroup", "|", "createLink", "insertImage" ] }, nodeRef);
+ break;
+ case "xforms:input":
+ var binding = bindings[o.getAttribute("xforms:bind")];
+ var row = document.createElement("tr");
+ ui_element_stack[ui_element_stack.length - 1].appendChild(row);
+ var label = get_label_node(o);
+ var cell = document.createElement("td");
+ row.appendChild(cell);
+ var required = binding.required == "true()";
+ if (label)
+ {
+ if (required)
+ {
+ var req = document.createElement("img");
+ req.setAttribute("src", contextPath + "/images/icons/required_field.gif");
+ req.setAttribute("style", "margin:5px");
+ cell.appendChild(req);
+ }
+ cell.appendChild(document.createTextNode(dojo.dom.textContent(label)));
+ }
+ cell = document.createElement("td");
+ row.appendChild(cell);
+ var nodeRef = document.createElement("div");
+ cell.appendChild(nodeRef);
+ var value = get_initial_value(binding);
+ switch (binding.type)
+ {
+ case "date":
+ var dateTextBoxDiv = document.createElement("div");
+ nodeRef.appendChild(dateTextBoxDiv);
+ var dateTextBox = dojo.widget.createWidget("DateTextBox", { format: "YYYY-MM-DD", value: value }, dateTextBoxDiv);
+ dateTextBox.onfocus = function(o) {
+ dateTextBox.hide(); dojo.debug("hiding " + o);
+ dateTextBox.picker.show();
+
+ };
+ var datePickerDiv = document.createElement("div");
+ nodeRef.appendChild(datePickerDiv);
+ dateTextBox.picker = dojo.widget.createWidget("DatePicker", { isHidden: true, value : value }, datePickerDiv);
+ dateTextBox.picker.hide();
+ dojo.event.connect(dateTextBox.picker,
+ "onSetDate",
+ function(event)
+ {
+ dateTextBox.picker.hide();
+ dateTextBox.show();
+ dateTextBox.setValue(dojo.widget.DatePicker.util.toRfcDate(dateTextBox.picker.date));
+ });
+ break;
+ case "integer":
+ case "positiveInteger":
+ case "negativeInteger":
+ var w = dojo.widget.createWidget("SpinnerIntegerTextBox", { value: value }, nodeRef);
+ break;
+ case "double":
+ var w = dojo.widget.createWidget("SpinnerRealNumberTextBox", { value: value }, nodeRef);
+ break;
+ case "string":
+ default:
+ var w = dojo.widget.createWidget("ValidationTextBox", { required: required, value: value }, nodeRef);
+ }
+ break;
+ case "xforms:select1":
+ var binding = bindings[o.getAttribute("xforms:bind")];
+ var row = document.createElement("tr");
+ ui_element_stack[ui_element_stack.length - 1].appendChild(row);
+ var cell = document.createElement("td");
+ row.appendChild(cell);
+ var label = get_label_node(o);
+ if (label)
+ cell.appendChild(document.createTextNode(dojo.dom.textContent(label)));
+ var nodeRef = document.createElement("div");
+ cell = document.createElement("td");
+ row.appendChild(cell);
+ var nodeRef = document.createElement("div");
+ cell.appendChild(nodeRef);
+ var values = get_select_values(o);
+ for (var i in values)
+ {
+ dojo.debug("values["+ i + "] = " + values[i].id + ", " + values[i].label + ", " + values[i].value);
+ }
+ if (binding.type == "boolean")
+ {
+ var w = dojo.widget.createWidget("CheckBox", { value: "value" }, nodeRef);
+ }
+ else if (values.length <= 5)
+ {
+ for (var i in values)
+ {
+ var radio = document.createElement("input");
+ radio.setAttribute("name", o.getAttribute("id"));
+ radio.setAttribute("type", "radio");
+ radio.setAttribute("value", values[i].value);
+ nodeRef.appendChild(radio);
+ nodeRef.appendChild(document.createTextNode(values[i].label));
+ }
+ }
+ else
+ {
+ var combobox = document.createElement("select");
+ nodeRef.appendChild(combobox);
+ for (var i in values)
+ {
+ var option = document.createElement("option");
+ option.appendChild(document.createTextNode(values[i].label));
+ option.setAttribute("value", values[i].value);
+ combobox.appendChild(option);
+ }
+ }
+ break;
+ default:
+ load_body(o, ui_element_stack);
+ }
+ });
+}
+
+function get_label_node(o)
+{
+ var labels = o.getElementsByTagName("label");
+ for (var i = 0; i < labels.length; i++)
+ {
+ dojo.debug("parent " + labels[i].parentNode.nodeName +
+" o " + o.nodeName);
+ if (labels[i].parentNode == o)
+ return labels[i];
+ }
+ return null;
+}
+
+function get_initial_value(binding)
+{
+ var b = binding;
+ var a = [];
+ do
+ {
+ a.push(b);
+ b = b.parent
+ }
+ while (b);
+ var node = get_instance();
+ for (var i = a.length - 1; i >= 0; i--)
+ {
+ var element_name = (a[i].nodeset.match(/^\//)
+ ? a[i].nodeset.replace(/^\/(.+)/, "$1")
+ : a[i].nodeset);
+ dojo.debug("locating " + a[i].nodeset + "(" + element_name + ")" +
+ " in " + node.nodeName);
+ node = node.getElementsByTagName(element_name)[0];
+ dojo.debug("got node " + node.nodeName);
+ }
+ return dojo.dom.textContent(node);
+}
+
+function get_select_values(o)
+{
+ var values = o.getElementsByTagName("item");
+ var result = [];
+ for (var v in values)
+ {
+ if (values[v].getElementsByTagName)
+ {
+ var label = values[v].getElementsByTagName("label")[0];
+ var value = values[v].getElementsByTagName("value")[0];
+ result.push({
+ id: value.getAttribute("id"),
+ label: dojo.dom.textContent(label),
+ value: dojo.dom.textContent(value)
+ });
+ }
+ }
+ return result;
+}
diff --git a/source/web/scripts/ajax/dojo.js b/source/web/scripts/ajax/dojo.js
index 038afe584f..68364bf877 100644
--- a/source/web/scripts/ajax/dojo.js
+++ b/source/web/scripts/ajax/dojo.js
@@ -1,5593 +1,97 @@
-/*
- Copyright (c) 2004-2006, The Dojo Foundation
- All Rights Reserved.
-
- Licensed under the Academic Free License version 2.1 or above OR the
- modified BSD license. For more information on Dojo licensing, see:
-
- http://dojotoolkit.org/community/licensing.shtml
-*/
-
-/*
- This is a compiled version of Dojo, built for deployment and not for
- development. To get an editable version, please visit:
-
- http://dojotoolkit.org
-
- for documentation and information on getting the source.
-*/
-
-if(typeof dojo=="undefined"){
-var dj_global=this;
-function dj_undef(_1,_2){
-if(_2==null){
-_2=dj_global;
-}
-return (typeof _2[_1]=="undefined");
-}
-if(dj_undef("djConfig")){
-var djConfig={};
-}
-if(dj_undef("dojo")){
-var dojo={};
-}
-dojo.version={major:0,minor:3,patch:1,flag:"",revision:Number("$Rev: 4342 $".match(/[0-9]+/)[0]),toString:function(){
-with(dojo.version){
-return major+"."+minor+"."+patch+flag+" ("+revision+")";
-}
-}};
-dojo.evalProp=function(_3,_4,_5){
-return (_4&&!dj_undef(_3,_4)?_4[_3]:(_5?(_4[_3]={}):undefined));
+if(typeof dojo == "undefined"){
+ dj_usingBootstrap = true; //Needed for bootstrap2.js to work properly.
+ (function(){
+ var hostEnv = "browser";
+ var isRhino = false;
+ var isSpidermonkey = false;
+ var isDashboard = false;
+ if((typeof this["load"] == "function")&&((typeof this["Packages"] == "function")||(typeof this["Packages"] == "object"))){
+ var isRhino = true;
+ hostEnv = "rhino";
+ }else if(typeof this["load"] == "function"){
+ isSpidermonkey = true;
+ hostEnv = "spidermonkey";
+ }else if(window.widget){
+ isDashboard = true;
+ hostEnv = "dashboard";
+ }
+ var tmps = ["bootstrap1.js", "loader.js", "hostenv_"+hostEnv+".js"];
+
+ if((this["djConfig"])&&((djConfig["forceXDomain"])||(djConfig["useXDomain"]))){
+ tmps.push("loader_xd.js");
+ }
+
+ if(hostEnv == "dashboard"){
+ tmps.splice(1, 0, "hostenv_browser.js");
+ }
+
+ tmps.push("bootstrap2.js");
+
+ if((this["djConfig"])&&(djConfig["baseScriptUri"])){
+ var root = djConfig["baseScriptUri"];
+ }else if((this["djConfig"])&&(djConfig["baseRelativePath"])){
+ var root = djConfig["baseRelativePath"];
+ }else{
+ var root = "./";
+ if(isSpidermonkey){
+ // auto-detect the base path via an exception. Hack!
+ try{ throw new Error(""); }catch(e){ root = e.fileName.split("dojo.js")[0]; };
+ }
+ if(!this["djConfig"]){
+ djConfig = { baseRelativePath: root };
+ }
+
+ // attempt to figure out the path to dojo if it isn't set in the config
+ if((this["document"])&&(this["document"]["getElementsByTagName"])){
+ var scripts = document.getElementsByTagName("script");
+ var rePkg = /(__package__|dojo)\.js([\?\.]|$)/i;
+ for(var i = 0; i < scripts.length; i++) {
+ var src = scripts[i].getAttribute("src");
+ if(!src) { continue; }
+ var m = src.match(rePkg);
+ if(m) {
+ root = src.substring(0, m.index);
+ if(!this["djConfig"]) { djConfig = {}; }
+ djConfig["baseScriptUri"] = djConfig["baseRelativePath"] = root;
+ break;
+ }
+ }
+ }
+ }
+
+ if((this["djConfig"])&&((djConfig["isDebug"])||(djConfig["debugAtAllCosts"]))){
+ tmps.push("debug.js");
+ }
+
+ if((this["djConfig"])&&(djConfig["debugAtAllCosts"])&&(!isRhino)&&(!isDashboard)){
+ tmps.push("browser_debug.js");
+ }
+
+ //Support compatibility packages. Right now this only allows setting one
+ //compatibility package. Might need to revisit later down the line to support
+ //more than one.
+ if((this["djConfig"])&&(djConfig["compat"])){
+ tmps.push("compat/" + djConfig["compat"] + ".js");
+ }
+
+ var loaderRoot = root;
+ if((this["djConfig"])&&(djConfig["baseLoaderUri"])){
+ loaderRoot = djConfig["baseLoaderUri"];
+ }
+
+ for(var x=0; x < tmps.length; x++){
+ var spath = loaderRoot+"src/"+tmps[x];
+ if(isRhino||isSpidermonkey){
+ load(spath);
+ } else {
+ try {
+ document.write("");
+ } catch (e) {
+ var script = document.createElement("script");
+ script.src = spath;
+ document.getElementsByTagName("head")[0].appendChild(script);
+ }
+ }
+ }
+ })();
};
-dojo.parseObjPath=function(_6,_7,_8){
-var _9=(_7!=null?_7:dj_global);
-var _a=_6.split(".");
-var _b=_a.pop();
-for(var i=0,l=_a.length;i1){
-dh.modulesLoadedListeners.push(function(){
-obj[_3d]();
-});
-}
-}
-if(dh.post_load_&&dh.inFlightCount==0&&!dh.loadNotifying){
-dh.callLoaded();
-}
-};
-dojo.addOnUnload=function(obj,_40){
-var dh=dojo.hostenv;
-if(arguments.length==1){
-dh.unloadListeners.push(obj);
-}else{
-if(arguments.length>1){
-dh.unloadListeners.push(function(){
-obj[_40]();
-});
-}
-}
-};
-dojo.hostenv.modulesLoaded=function(){
-if(this.post_load_){
-return;
-}
-if((this.loadUriStack.length==0)&&(this.getTextStack.length==0)){
-if(this.inFlightCount>0){
-dojo.debug("files still in flight!");
-return;
-}
-dojo.hostenv.callLoaded();
-}
-};
-dojo.hostenv.callLoaded=function(){
-if(typeof setTimeout=="object"){
-setTimeout("dojo.hostenv.loaded();",0);
-}else{
-dojo.hostenv.loaded();
-}
-};
-dojo.hostenv.getModuleSymbols=function(_42){
-var _43=_42.split(".");
-for(var i=_43.length-1;i>0;i--){
-var _45=_43.slice(0,i).join(".");
-var _46=this.getModulePrefix(_45);
-if(_46!=_45){
-_43.splice(0,i,_46);
-break;
-}
-}
-return _43;
-};
-dojo.hostenv._global_omit_module_check=false;
-dojo.hostenv.loadModule=function(_47,_48,_49){
-if(!_47){
-return;
-}
-_49=this._global_omit_module_check||_49;
-var _4a=this.findModule(_47,false);
-if(_4a){
-return _4a;
-}
-if(dj_undef(_47,this.loading_modules_)){
-this.addedToLoadingCount.push(_47);
-}
-this.loading_modules_[_47]=1;
-var _4b=_47.replace(/\./g,"/")+".js";
-var _4c=this.getModuleSymbols(_47);
-var _4d=((_4c[0].charAt(0)!="/")&&(!_4c[0].match(/^\w+:/)));
-var _4e=_4c[_4c.length-1];
-var _4f=_47.split(".");
-if(_4e=="*"){
-_47=(_4f.slice(0,-1)).join(".");
-while(_4c.length){
-_4c.pop();
-_4c.push(this.pkgFileName);
-_4b=_4c.join("/")+".js";
-if(_4d&&(_4b.charAt(0)=="/")){
-_4b=_4b.slice(1);
-}
-ok=this.loadPath(_4b,((!_49)?_47:null));
-if(ok){
-break;
-}
-_4c.pop();
-}
-}else{
-_4b=_4c.join("/")+".js";
-_47=_4f.join(".");
-var ok=this.loadPath(_4b,((!_49)?_47:null));
-if((!ok)&&(!_48)){
-_4c.pop();
-while(_4c.length){
-_4b=_4c.join("/")+".js";
-ok=this.loadPath(_4b,((!_49)?_47:null));
-if(ok){
-break;
-}
-_4c.pop();
-_4b=_4c.join("/")+"/"+this.pkgFileName+".js";
-if(_4d&&(_4b.charAt(0)=="/")){
-_4b=_4b.slice(1);
-}
-ok=this.loadPath(_4b,((!_49)?_47:null));
-if(ok){
-break;
-}
-}
-}
-if((!ok)&&(!_49)){
-dojo.raise("Could not load '"+_47+"'; last tried '"+_4b+"'");
-}
-}
-if(!_49&&!this["isXDomain"]){
-_4a=this.findModule(_47,false);
-if(!_4a){
-dojo.raise("symbol '"+_47+"' is not defined after loading '"+_4b+"'");
-}
-}
-return _4a;
-};
-dojo.hostenv.startPackage=function(_51){
-var _52=dojo.evalObjPath((_51.split(".").slice(0,-1)).join("."));
-this.loaded_modules_[(new String(_51)).toLowerCase()]=_52;
-var _53=_51.split(/\./);
-if(_53[_53.length-1]=="*"){
-_53.pop();
-}
-return dojo.evalObjPath(_53.join("."),true);
-};
-dojo.hostenv.findModule=function(_54,_55){
-var lmn=(new String(_54)).toLowerCase();
-if(this.loaded_modules_[lmn]){
-return this.loaded_modules_[lmn];
-}
-var _57=dojo.evalObjPath(_54);
-if((_54)&&(typeof _57!="undefined")&&(_57)){
-this.loaded_modules_[lmn]=_57;
-return _57;
-}
-if(_55){
-dojo.raise("no loaded module named '"+_54+"'");
-}
-return null;
-};
-dojo.kwCompoundRequire=function(_58){
-var _59=_58["common"]||[];
-var _5a=(_58[dojo.hostenv.name_])?_59.concat(_58[dojo.hostenv.name_]||[]):_59.concat(_58["default"]||[]);
-for(var x=0;x<_5a.length;x++){
-var _5c=_5a[x];
-if(_5c.constructor==Array){
-dojo.hostenv.loadModule.apply(dojo.hostenv,_5c);
-}else{
-dojo.hostenv.loadModule(_5c);
-}
-}
-};
-dojo.require=function(){
-dojo.hostenv.loadModule.apply(dojo.hostenv,arguments);
-};
-dojo.requireIf=function(){
-if((arguments[0]===true)||(arguments[0]=="common")||(arguments[0]&&dojo.render[arguments[0]].capable)){
-var _5d=[];
-for(var i=1;i1){
-var _67=_66[1];
-var _68=_67.split("&");
-for(var x in _68){
-var sp=_68[x].split("=");
-if((sp[0].length>9)&&(sp[0].substr(0,9)=="djConfig.")){
-var opt=sp[0].substr(9);
-try{
-djConfig[opt]=eval(sp[1]);
-}
-catch(e){
-djConfig[opt]=sp[1];
-}
-}
-}
-}
-}
-if(((djConfig["baseScriptUri"]=="")||(djConfig["baseRelativePath"]==""))&&(document&&document.getElementsByTagName)){
-var _6c=document.getElementsByTagName("script");
-var _6d=/(__package__|dojo|bootstrap1)\.js([\?\.]|$)/i;
-for(var i=0;i<_6c.length;i++){
-var src=_6c[i].getAttribute("src");
-if(!src){
-continue;
-}
-var m=src.match(_6d);
-if(m){
-var _71=src.substring(0,m.index);
-if(src.indexOf("bootstrap1")>-1){
-_71+="../";
-}
-if(!this["djConfig"]){
-djConfig={};
-}
-if(djConfig["baseScriptUri"]==""){
-djConfig["baseScriptUri"]=_71;
-}
-if(djConfig["baseRelativePath"]==""){
-djConfig["baseRelativePath"]=_71;
-}
-break;
-}
-}
-}
-var dr=dojo.render;
-var drh=dojo.render.html;
-var drs=dojo.render.svg;
-var dua=drh.UA=navigator.userAgent;
-var dav=drh.AV=navigator.appVersion;
-var t=true;
-var f=false;
-drh.capable=t;
-drh.support.builtin=t;
-dr.ver=parseFloat(drh.AV);
-dr.os.mac=dav.indexOf("Macintosh")>=0;
-dr.os.win=dav.indexOf("Windows")>=0;
-dr.os.linux=dav.indexOf("X11")>=0;
-drh.opera=dua.indexOf("Opera")>=0;
-drh.khtml=(dav.indexOf("Konqueror")>=0)||(dav.indexOf("Safari")>=0);
-drh.safari=dav.indexOf("Safari")>=0;
-var _79=dua.indexOf("Gecko");
-drh.mozilla=drh.moz=(_79>=0)&&(!drh.khtml);
-if(drh.mozilla){
-drh.geckoVersion=dua.substring(_79+6,_79+14);
-}
-drh.ie=(document.all)&&(!drh.opera);
-drh.ie50=drh.ie&&dav.indexOf("MSIE 5.0")>=0;
-drh.ie55=drh.ie&&dav.indexOf("MSIE 5.5")>=0;
-drh.ie60=drh.ie&&dav.indexOf("MSIE 6.0")>=0;
-drh.ie70=drh.ie&&dav.indexOf("MSIE 7.0")>=0;
-dojo.locale=(drh.ie?navigator.userLanguage:navigator.language).toLowerCase();
-dr.vml.capable=drh.ie;
-drs.capable=f;
-drs.support.plugin=f;
-drs.support.builtin=f;
-if(document.implementation&&document.implementation.hasFeature&&document.implementation.hasFeature("org.w3c.dom.svg","1.0")){
-drs.capable=t;
-drs.support.builtin=t;
-drs.support.plugin=f;
-}
-})();
-dojo.hostenv.startPackage("dojo.hostenv");
-dojo.render.name=dojo.hostenv.name_="browser";
-dojo.hostenv.searchIds=[];
-dojo.hostenv._XMLHTTP_PROGIDS=["Msxml2.XMLHTTP","Microsoft.XMLHTTP","Msxml2.XMLHTTP.4.0"];
-dojo.hostenv.getXmlhttpObject=function(){
-var _7a=null;
-var _7b=null;
-try{
-_7a=new XMLHttpRequest();
-}
-catch(e){
-}
-if(!_7a){
-for(var i=0;i<3;++i){
-var _7d=dojo.hostenv._XMLHTTP_PROGIDS[i];
-try{
-_7a=new ActiveXObject(_7d);
-}
-catch(e){
-_7b=e;
-}
-if(_7a){
-dojo.hostenv._XMLHTTP_PROGIDS=[_7d];
-break;
-}
-}
-}
-if(!_7a){
-return dojo.raise("XMLHTTP not available",_7b);
-}
-return _7a;
-};
-dojo.hostenv.getText=function(uri,_7f,_80){
-var _81=this.getXmlhttpObject();
-if(_7f){
-_81.onreadystatechange=function(){
-if(4==_81.readyState){
-if((!_81["status"])||((200<=_81.status)&&(300>_81.status))){
-_7f(_81.responseText);
-}
-}
-};
-}
-_81.open("GET",uri,_7f?true:false);
-try{
-_81.send(null);
-if(_7f){
-return null;
-}
-if((_81["status"])&&((200>_81.status)||(300<=_81.status))){
-throw Error("Unable to load "+uri+" status:"+_81.status);
-}
-}
-catch(e){
-if((_80)&&(!_7f)){
-return null;
-}else{
-throw e;
-}
-}
-return _81.responseText;
-};
-dojo.hostenv.defaultDebugContainerId="dojoDebug";
-dojo.hostenv._println_buffer=[];
-dojo.hostenv._println_safe=false;
-dojo.hostenv.println=function(_82){
-if(!dojo.hostenv._println_safe){
-dojo.hostenv._println_buffer.push(_82);
-}else{
-try{
-var _83=document.getElementById(djConfig.debugContainerId?djConfig.debugContainerId:dojo.hostenv.defaultDebugContainerId);
-if(!_83){
-_83=document.getElementsByTagName("body")[0]||document.body;
-}
-var div=document.createElement("div");
-div.appendChild(document.createTextNode(_82));
-_83.appendChild(div);
-}
-catch(e){
-try{
-document.write("
"+_82+"
");
-}
-catch(e2){
-window.status=_82;
-}
-}
-}
-};
-dojo.addOnLoad(function(){
-dojo.hostenv._println_safe=true;
-while(dojo.hostenv._println_buffer.length>0){
-dojo.hostenv.println(dojo.hostenv._println_buffer.shift());
-}
-});
-function dj_addNodeEvtHdlr(_85,_86,fp,_88){
-var _89=_85["on"+_86]||function(){
-};
-_85["on"+_86]=function(){
-fp.apply(_85,arguments);
-_89.apply(_85,arguments);
-};
-return true;
-}
-dj_addNodeEvtHdlr(window,"load",function(){
-if(arguments.callee.initialized){
-return;
-}
-arguments.callee.initialized=true;
-var _8a=function(){
-if(dojo.render.html.ie){
-dojo.hostenv.makeWidgets();
-}
-};
-if(dojo.hostenv.inFlightCount==0){
-_8a();
-dojo.hostenv.modulesLoaded();
-}else{
-dojo.addOnLoad(_8a);
-}
-});
-dj_addNodeEvtHdlr(window,"unload",function(){
-dojo.hostenv.unloaded();
-});
-dojo.hostenv.makeWidgets=function(){
-var _8b=[];
-if(djConfig.searchIds&&djConfig.searchIds.length>0){
-_8b=_8b.concat(djConfig.searchIds);
-}
-if(dojo.hostenv.searchIds&&dojo.hostenv.searchIds.length>0){
-_8b=_8b.concat(dojo.hostenv.searchIds);
-}
-if((djConfig.parseWidgets)||(_8b.length>0)){
-if(dojo.evalObjPath("dojo.widget.Parse")){
-var _8c=new dojo.xml.Parse();
-if(_8b.length>0){
-for(var x=0;x<_8b.length;x++){
-var _8e=document.getElementById(_8b[x]);
-if(!_8e){
-continue;
-}
-var _8f=_8c.parseElement(_8e,null,true);
-dojo.widget.getParser().createComponents(_8f);
-}
-}else{
-if(djConfig.parseWidgets){
-var _8f=_8c.parseElement(document.getElementsByTagName("body")[0]||document.body,null,true);
-dojo.widget.getParser().createComponents(_8f);
-}
-}
-}
-}
-};
-dojo.addOnLoad(function(){
-if(!dojo.render.html.ie){
-dojo.hostenv.makeWidgets();
-}
-});
-try{
-if(dojo.render.html.ie){
-document.write("");
-document.write("");
-}
-}
-catch(e){
-}
-dojo.hostenv.writeIncludes=function(){
-};
-dojo.byId=function(id,doc){
-if(id&&(typeof id=="string"||id instanceof String)){
-if(!doc){
-doc=document;
-}
-return doc.getElementById(id);
-}
-return id;
-};
-(function(){
-if(typeof dj_usingBootstrap!="undefined"){
-return;
-}
-var _92=false;
-var _93=false;
-var _94=false;
-if((typeof this["load"]=="function")&&((typeof this["Packages"]=="function")||(typeof this["Packages"]=="object"))){
-_92=true;
-}else{
-if(typeof this["load"]=="function"){
-_93=true;
-}else{
-if(window.widget){
-_94=true;
-}
-}
-}
-var _95=[];
-if((this["djConfig"])&&((djConfig["isDebug"])||(djConfig["debugAtAllCosts"]))){
-_95.push("debug.js");
-}
-if((this["djConfig"])&&(djConfig["debugAtAllCosts"])&&(!_92)&&(!_94)){
-_95.push("browser_debug.js");
-}
-if((this["djConfig"])&&(djConfig["compat"])){
-_95.push("compat/"+djConfig["compat"]+".js");
-}
-var _96=djConfig["baseScriptUri"];
-if((this["djConfig"])&&(djConfig["baseLoaderUri"])){
-_96=djConfig["baseLoaderUri"];
-}
-for(var x=0;x<_95.length;x++){
-var _98=_96+"src/"+_95[x];
-if(_92||_93){
-load(_98);
-}else{
-try{
-document.write("");
-}
-catch(e){
-var _99=document.createElement("script");
-_99.src=_98;
-document.getElementsByTagName("head")[0].appendChild(_99);
-}
-}
-}
-})();
-dojo.fallback_locale="en";
-dojo.normalizeLocale=function(_9a){
-return _9a?_9a.toLowerCase():dojo.locale;
-};
-dojo.requireLocalization=function(_9b,_9c,_9d){
-dojo.debug("EXPERIMENTAL: dojo.requireLocalization");
-var _9e=dojo.hostenv.getModuleSymbols(_9b);
-var _9f=_9e.concat("nls").join("/");
-_9d=dojo.normalizeLocale(_9d);
-var _a0=_9d.split("-");
-var _a1=[];
-for(var i=_a0.length;i>0;i--){
-_a1.push(_a0.slice(0,i).join("-"));
-}
-if(_a1[_a1.length-1]!=dojo.fallback_locale){
-_a1.push(dojo.fallback_locale);
-}
-var _a3=[_9b,"_nls",_9c].join(".");
-var _a4=dojo.hostenv.startPackage(_a3);
-dojo.hostenv.loaded_modules_[_a3]=_a4;
-var _a5=false;
-for(var i=_a1.length-1;i>=0;i--){
-var loc=_a1[i];
-var pkg=[_a3,loc].join(".");
-var _a8=false;
-if(!dojo.hostenv.findModule(pkg)){
-dojo.hostenv.loaded_modules_[pkg]=null;
-var _a9=[_9f,loc,_9c].join("/")+".js";
-_a8=dojo.hostenv.loadPath(_a9,null,function(_aa){
-_a4[loc]=_aa;
-if(_a5){
-for(var x in _a5){
-if(!_a4[loc][x]){
-_a4[loc][x]=_a5[x];
-}
-}
-}
-});
-}else{
-_a8=true;
-}
-if(_a8&&_a4[loc]){
-_a5=_a4[loc];
-}
-}
-};
-dojo.provide("dojo.string.common");
-dojo.require("dojo.string");
-dojo.string.trim=function(str,wh){
-if(!str.replace){
-return str;
-}
-if(!str.length){
-return str;
-}
-var re=(wh>0)?(/^\s+/):(wh<0)?(/\s+$/):(/^\s+|\s+$/g);
-return str.replace(re,"");
-};
-dojo.string.trimStart=function(str){
-return dojo.string.trim(str,1);
-};
-dojo.string.trimEnd=function(str){
-return dojo.string.trim(str,-1);
-};
-dojo.string.repeat=function(str,_b2,_b3){
-var out="";
-for(var i=0;i<_b2;i++){
-out+=str;
-if(_b3&&i<_b2-1){
-out+=_b3;
-}
-}
-return out;
-};
-dojo.string.pad=function(str,len,c,dir){
-var out=String(str);
-if(!c){
-c="0";
-}
-if(!dir){
-dir=1;
-}
-while(out.length0){
-out=c+out;
-}else{
-out+=c;
-}
-}
-return out;
-};
-dojo.string.padLeft=function(str,len,c){
-return dojo.string.pad(str,len,c,1);
-};
-dojo.string.padRight=function(str,len,c){
-return dojo.string.pad(str,len,c,-1);
-};
-dojo.provide("dojo.string");
-dojo.require("dojo.string.common");
-dojo.provide("dojo.lang.common");
-dojo.require("dojo.lang");
-dojo.lang._mixin=function(obj,_c2){
-var _c3={};
-for(var x in _c2){
-if(typeof _c3[x]=="undefined"||_c3[x]!=_c2[x]){
-obj[x]=_c2[x];
-}
-}
-if(dojo.render.html.ie&&dojo.lang.isFunction(_c2["toString"])&&_c2["toString"]!=obj["toString"]){
-obj.toString=_c2.toString;
-}
-return obj;
-};
-dojo.lang.mixin=function(obj,_c6){
-for(var i=1,l=arguments.length;i-1;
-};
-dojo.lang.isObject=function(wh){
-if(typeof wh=="undefined"){
-return false;
-}
-return (typeof wh=="object"||wh===null||dojo.lang.isArray(wh)||dojo.lang.isFunction(wh));
-};
-dojo.lang.isArray=function(wh){
-return (wh instanceof Array||typeof wh=="array");
-};
-dojo.lang.isArrayLike=function(wh){
-if(dojo.lang.isString(wh)){
-return false;
-}
-if(dojo.lang.isFunction(wh)){
-return false;
-}
-if(dojo.lang.isArray(wh)){
-return true;
-}
-if(typeof wh!="undefined"&&wh&&dojo.lang.isNumber(wh.length)&&isFinite(wh.length)){
-return true;
-}
-return false;
-};
-dojo.lang.isFunction=function(wh){
-if(!wh){
-return false;
-}
-return (wh instanceof Function||typeof wh=="function");
-};
-dojo.lang.isString=function(wh){
-return (wh instanceof String||typeof wh=="string");
-};
-dojo.lang.isAlien=function(wh){
-if(!wh){
-return false;
-}
-return !dojo.lang.isFunction()&&/\{\s*\[native code\]\s*\}/.test(String(wh));
-};
-dojo.lang.isBoolean=function(wh){
-return (wh instanceof Boolean||typeof wh=="boolean");
-};
-dojo.lang.isNumber=function(wh){
-return (wh instanceof Number||typeof wh=="number");
-};
-dojo.lang.isUndefined=function(wh){
-return ((wh==undefined)&&(typeof wh=="undefined"));
-};
-dojo.provide("dojo.lang.extras");
-dojo.require("dojo.lang.common");
-dojo.lang.setTimeout=function(_e2,_e3){
-var _e4=window,argsStart=2;
-if(!dojo.lang.isFunction(_e2)){
-_e4=_e2;
-_e2=_e3;
-_e3=arguments[2];
-argsStart++;
-}
-if(dojo.lang.isString(_e2)){
-_e2=_e4[_e2];
-}
-var _e5=[];
-for(var i=argsStart;i=4){
-this.changeUrl=_f7;
-}
-}
-};
-dojo.lang.extend(dojo.io.Request,{url:"",mimetype:"text/plain",method:"GET",content:undefined,transport:undefined,changeUrl:undefined,formNode:undefined,sync:false,bindSuccess:false,useCache:false,preventCache:false,load:function(_f8,_f9,evt){
-},error:function(_fb,_fc){
-},timeout:function(_fd){
-},handle:function(){
-},timeoutSeconds:0,abort:function(){
-},fromKwArgs:function(_fe){
-if(_fe["url"]){
-_fe.url=_fe.url.toString();
-}
-if(_fe["formNode"]){
-_fe.formNode=dojo.byId(_fe.formNode);
-}
-if(!_fe["method"]&&_fe["formNode"]&&_fe["formNode"].method){
-_fe.method=_fe["formNode"].method;
-}
-if(!_fe["handle"]&&_fe["handler"]){
-_fe.handle=_fe.handler;
-}
-if(!_fe["load"]&&_fe["loaded"]){
-_fe.load=_fe.loaded;
-}
-if(!_fe["changeUrl"]&&_fe["changeURL"]){
-_fe.changeUrl=_fe.changeURL;
-}
-_fe.encoding=dojo.lang.firstValued(_fe["encoding"],djConfig["bindEncoding"],"");
-_fe.sendTransport=dojo.lang.firstValued(_fe["sendTransport"],djConfig["ioSendTransport"],false);
-var _ff=dojo.lang.isFunction;
-for(var x=0;x0){
-dojo.io.bind(dojo.io._bindQueue.shift());
-}else{
-dojo.io._queueBindInFlight=false;
-}
-}
-};
-dojo.io._bindQueue=[];
-dojo.io._queueBindInFlight=false;
-dojo.io.argsFromMap=function(map,_110,last){
-var enc=/utf/i.test(_110||"")?encodeURIComponent:dojo.string.encodeAscii;
-var _113=[];
-var _114=new Object();
-for(var name in map){
-var _116=function(elt){
-var val=enc(name)+"="+enc(elt);
-_113[(last==name)?"push":"unshift"](val);
-};
-if(!_114[name]){
-var _119=map[name];
-if(dojo.lang.isArray(_119)){
-dojo.lang.forEach(_119,_116);
-}else{
-_116(_119);
-}
-}
-}
-return _113.join("&");
-};
-dojo.io.setIFrameSrc=function(_11a,src,_11c){
-try{
-var r=dojo.render.html;
-if(!_11c){
-if(r.safari){
-_11a.location=src;
-}else{
-frames[_11a.name].location=src;
-}
-}else{
-var idoc;
-if(r.ie){
-idoc=_11a.contentWindow.document;
-}else{
-if(r.safari){
-idoc=_11a.document;
-}else{
-idoc=_11a.contentWindow;
-}
-}
-if(!idoc){
-_11a.location=src;
-return;
-}else{
-idoc.location.replace(src);
-}
-}
-}
-catch(e){
-dojo.debug(e);
-dojo.debug("setIFrameSrc: "+e);
-}
-};
-dojo.provide("dojo.lang.array");
-dojo.require("dojo.lang.common");
-dojo.lang.has=function(obj,name){
-try{
-return (typeof obj[name]!="undefined");
-}
-catch(e){
-return false;
-}
-};
-dojo.lang.isEmpty=function(obj){
-if(dojo.lang.isObject(obj)){
-var tmp={};
-var _123=0;
-for(var x in obj){
-if(obj[x]&&(!tmp[x])){
-_123++;
-break;
-}
-}
-return (_123==0);
-}else{
-if(dojo.lang.isArrayLike(obj)||dojo.lang.isString(obj)){
-return obj.length==0;
-}
-}
-};
-dojo.lang.map=function(arr,obj,_127){
-var _128=dojo.lang.isString(arr);
-if(_128){
-arr=arr.split("");
-}
-if(dojo.lang.isFunction(obj)&&(!_127)){
-_127=obj;
-obj=dj_global;
-}else{
-if(dojo.lang.isFunction(obj)&&_127){
-var _129=obj;
-obj=_127;
-_127=_129;
-}
-}
-if(Array.map){
-var _12a=Array.map(arr,_127,obj);
-}else{
-var _12a=[];
-for(var i=0;i=3){
-dojo.raise("thisObject doesn't exist!");
-}
-_13e=dj_global;
-}
-var _140=[];
-for(var i=0;i/gm,">").replace(/"/gm,""");
-if(!_183){
-str=str.replace(/'/gm,"'");
-}
-return str;
-};
-dojo.string.escapeSql=function(str){
-return str.replace(/'/gm,"''");
-};
-dojo.string.escapeRegExp=function(str){
-return str.replace(/\\/gm,"\\\\").replace(/([\f\b\n\t\r[\^$|?*+(){}])/gm,"\\$1");
-};
-dojo.string.escapeJavaScript=function(str){
-return str.replace(/(["'\f\b\n\t\r])/gm,"\\$1");
-};
-dojo.string.escapeString=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");
-};
-dojo.string.summary=function(str,len){
-if(!len||str.length<=len){
-return str;
-}else{
-return str.substring(0,len).replace(/\.+$/,"")+"...";
-}
-};
-dojo.string.endsWith=function(str,end,_18c){
-if(_18c){
-str=str.toLowerCase();
-end=end.toLowerCase();
-}
-if((str.length-end.length)<0){
-return false;
-}
-return str.lastIndexOf(end)==str.length-end.length;
-};
-dojo.string.endsWithAny=function(str){
-for(var i=1;i-1){
-return true;
-}
-}
-return false;
-};
-dojo.string.normalizeNewlines=function(text,_197){
-if(_197=="\n"){
-text=text.replace(/\r\n/g,"\n");
-text=text.replace(/\r/g,"\n");
-}else{
-if(_197=="\r"){
-text=text.replace(/\r\n/g,"\r");
-text=text.replace(/\n/g,"\r");
-}else{
-text=text.replace(/([^\r])\n/g,"$1\r\n");
-text=text.replace(/\r([^\n])/g,"\r\n$1");
-}
-}
-return text;
-};
-dojo.string.splitEscaped=function(str,_199){
-var _19a=[];
-for(var i=0,prevcomma=0;i5)&&(_1a1[x].indexOf("dojo-")>=0)){
-return "dojo:"+_1a1[x].substr(5).toLowerCase();
-}
-}
-}
-}
-}
-return _19e.toLowerCase();
-};
-dojo.dom.getUniqueId=function(){
-do{
-var id="dj_unique_"+(++arguments.callee._idIncrement);
-}while(document.getElementById(id));
-return id;
-};
-dojo.dom.getUniqueId._idIncrement=0;
-dojo.dom.firstElement=dojo.dom.getFirstChildElement=function(_1a4,_1a5){
-var node=_1a4.firstChild;
-while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE){
-node=node.nextSibling;
-}
-if(_1a5&&node&&node.tagName&&node.tagName.toLowerCase()!=_1a5.toLowerCase()){
-node=dojo.dom.nextElement(node,_1a5);
-}
-return node;
-};
-dojo.dom.lastElement=dojo.dom.getLastChildElement=function(_1a7,_1a8){
-var node=_1a7.lastChild;
-while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE){
-node=node.previousSibling;
-}
-if(_1a8&&node&&node.tagName&&node.tagName.toLowerCase()!=_1a8.toLowerCase()){
-node=dojo.dom.prevElement(node,_1a8);
-}
-return node;
-};
-dojo.dom.nextElement=dojo.dom.getNextSiblingElement=function(node,_1ab){
-if(!node){
-return null;
-}
-do{
-node=node.nextSibling;
-}while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE);
-if(node&&_1ab&&_1ab.toLowerCase()!=node.tagName.toLowerCase()){
-return dojo.dom.nextElement(node,_1ab);
-}
-return node;
-};
-dojo.dom.prevElement=dojo.dom.getPreviousSiblingElement=function(node,_1ad){
-if(!node){
-return null;
-}
-if(_1ad){
-_1ad=_1ad.toLowerCase();
-}
-do{
-node=node.previousSibling;
-}while(node&&node.nodeType!=dojo.dom.ELEMENT_NODE);
-if(node&&_1ad&&_1ad.toLowerCase()!=node.tagName.toLowerCase()){
-return dojo.dom.prevElement(node,_1ad);
-}
-return node;
-};
-dojo.dom.moveChildren=function(_1ae,_1af,trim){
-var _1b1=0;
-if(trim){
-while(_1ae.hasChildNodes()&&_1ae.firstChild.nodeType==dojo.dom.TEXT_NODE){
-_1ae.removeChild(_1ae.firstChild);
-}
-while(_1ae.hasChildNodes()&&_1ae.lastChild.nodeType==dojo.dom.TEXT_NODE){
-_1ae.removeChild(_1ae.lastChild);
-}
-}
-while(_1ae.hasChildNodes()){
-_1af.appendChild(_1ae.firstChild);
-_1b1++;
-}
-return _1b1;
-};
-dojo.dom.copyChildren=function(_1b2,_1b3,trim){
-var _1b5=_1b2.cloneNode(true);
-return this.moveChildren(_1b5,_1b3,trim);
-};
-dojo.dom.removeChildren=function(node){
-var _1b7=node.childNodes.length;
-while(node.hasChildNodes()){
-node.removeChild(node.firstChild);
-}
-return _1b7;
-};
-dojo.dom.replaceChildren=function(node,_1b9){
-dojo.dom.removeChildren(node);
-node.appendChild(_1b9);
-};
-dojo.dom.removeNode=function(node){
-if(node&&node.parentNode){
-return node.parentNode.removeChild(node);
-}
-};
-dojo.dom.getAncestors=function(node,_1bc,_1bd){
-var _1be=[];
-var _1bf=dojo.lang.isFunction(_1bc);
-while(node){
-if(!_1bf||_1bc(node)){
-_1be.push(node);
-}
-if(_1bd&&_1be.length>0){
-return _1be[0];
-}
-node=node.parentNode;
-}
-if(_1bd){
-return null;
-}
-return _1be;
-};
-dojo.dom.getAncestorsByTag=function(node,tag,_1c2){
-tag=tag.toLowerCase();
-return dojo.dom.getAncestors(node,function(el){
-return ((el.tagName)&&(el.tagName.toLowerCase()==tag));
-},_1c2);
-};
-dojo.dom.getFirstAncestorByTag=function(node,tag){
-return dojo.dom.getAncestorsByTag(node,tag,true);
-};
-dojo.dom.isDescendantOf=function(node,_1c7,_1c8){
-if(_1c8&&node){
-node=node.parentNode;
-}
-while(node){
-if(node==_1c7){
-return true;
-}
-node=node.parentNode;
-}
-return false;
-};
-dojo.dom.innerXML=function(node){
-if(node.innerXML){
-return node.innerXML;
-}else{
-if(node.xml){
-return node.xml;
-}else{
-if(typeof XMLSerializer!="undefined"){
-return (new XMLSerializer()).serializeToString(node);
-}
-}
-}
-};
-dojo.dom.createDocument=function(){
-var doc=null;
-if(!dj_undef("ActiveXObject")){
-var _1cb=["MSXML2","Microsoft","MSXML","MSXML3"];
-for(var i=0;i<_1cb.length;i++){
-try{
-doc=new ActiveXObject(_1cb[i]+".XMLDOM");
-}
-catch(e){
-}
-if(doc){
-break;
-}
-}
-}else{
-if((document.implementation)&&(document.implementation.createDocument)){
-doc=document.implementation.createDocument("","",null);
-}
-}
-return doc;
-};
-dojo.dom.createDocumentFromText=function(str,_1ce){
-if(!_1ce){
-_1ce="text/xml";
-}
-if(!dj_undef("DOMParser")){
-var _1cf=new DOMParser();
-return _1cf.parseFromString(str,_1ce);
-}else{
-if(!dj_undef("ActiveXObject")){
-var _1d0=dojo.dom.createDocument();
-if(_1d0){
-_1d0.async=false;
-_1d0.loadXML(str);
-return _1d0;
-}else{
-dojo.debug("toXml didn't work?");
-}
-}else{
-if(document.createElement){
-var tmp=document.createElement("xml");
-tmp.innerHTML=str;
-if(document.implementation&&document.implementation.createDocument){
-var _1d2=document.implementation.createDocument("foo","",null);
-for(var i=0;i");
-}
-}
-catch(e){
-}
-if(dojo.render.html.opera){
-dojo.debug("Opera is not supported with dojo.undo.browser, so back/forward detection will not work.");
-}
-dojo.undo.browser={initialHref:window.location.href,initialHash:window.location.hash,moveForward:false,historyStack:[],forwardStack:[],historyIframe:null,bookmarkAnchor:null,locationTimer:null,setInitialState:function(args){
-this.initialState={"url":this.initialHref,"kwArgs":args,"urlHash":this.initialHash};
-},addToHistory:function(args){
-var hash=null;
-if(!this.historyIframe){
-this.historyIframe=window.frames["djhistory"];
-}
-if(!this.bookmarkAnchor){
-this.bookmarkAnchor=document.createElement("a");
-(document.body||document.getElementsByTagName("body")[0]).appendChild(this.bookmarkAnchor);
-this.bookmarkAnchor.style.display="none";
-}
-if((!args["changeUrl"])||(dojo.render.html.ie)){
-var url=dojo.hostenv.getBaseScriptUri()+"iframe_history.html?"+(new Date()).getTime();
-this.moveForward=true;
-dojo.io.setIFrameSrc(this.historyIframe,url,false);
-}
-if(args["changeUrl"]){
-this.changingUrl=true;
-hash="#"+((args["changeUrl"]!==true)?args["changeUrl"]:(new Date()).getTime());
-setTimeout("window.location.href = '"+hash+"'; dojo.undo.browser.changingUrl = false;",1);
-this.bookmarkAnchor.href=hash;
-if(dojo.render.html.ie){
-var _1f4=args["back"]||args["backButton"]||args["handle"];
-var tcb=function(_1f6){
-if(window.location.hash!=""){
-setTimeout("window.location.href = '"+hash+"';",1);
-}
-_1f4.apply(this,[_1f6]);
-};
-if(args["back"]){
-args.back=tcb;
-}else{
-if(args["backButton"]){
-args.backButton=tcb;
-}else{
-if(args["handle"]){
-args.handle=tcb;
-}
-}
-}
-this.forwardStack=[];
-var _1f7=args["forward"]||args["forwardButton"]||args["handle"];
-var tfw=function(_1f9){
-if(window.location.hash!=""){
-window.location.href=hash;
-}
-if(_1f7){
-_1f7.apply(this,[_1f9]);
-}
-};
-if(args["forward"]){
-args.forward=tfw;
-}else{
-if(args["forwardButton"]){
-args.forwardButton=tfw;
-}else{
-if(args["handle"]){
-args.handle=tfw;
-}
-}
-}
-}else{
-if(dojo.render.html.moz){
-if(!this.locationTimer){
-this.locationTimer=setInterval("dojo.undo.browser.checkLocation();",200);
-}
-}
-}
-}
-this.historyStack.push({"url":url,"kwArgs":args,"urlHash":hash});
-},checkLocation:function(){
-if(!this.changingUrl){
-var hsl=this.historyStack.length;
-if((window.location.hash==this.initialHash||window.location.href==this.initialHref)&&(hsl==1)){
-this.handleBackButton();
-return;
-}
-if(this.forwardStack.length>0){
-if(this.forwardStack[this.forwardStack.length-1].urlHash==window.location.hash){
-this.handleForwardButton();
-return;
-}
-}
-if((hsl>=2)&&(this.historyStack[hsl-2])){
-if(this.historyStack[hsl-2].urlHash==window.location.hash){
-this.handleBackButton();
-return;
-}
-}
-}
-},iframeLoaded:function(evt,_1fc){
-if(!dojo.render.html.opera){
-var _1fd=this._getUrlQuery(_1fc.href);
-if(_1fd==null){
-if(this.historyStack.length==1){
-this.handleBackButton();
-}
-return;
-}
-if(this.moveForward){
-this.moveForward=false;
-return;
-}
-if(this.historyStack.length>=2&&_1fd==this._getUrlQuery(this.historyStack[this.historyStack.length-2].url)){
-this.handleBackButton();
-}else{
-if(this.forwardStack.length>0&&_1fd==this._getUrlQuery(this.forwardStack[this.forwardStack.length-1].url)){
-this.handleForwardButton();
-}
-}
-}
-},handleBackButton:function(){
-var _1fe=this.historyStack.pop();
-if(!_1fe){
-return;
-}
-var last=this.historyStack[this.historyStack.length-1];
-if(!last&&this.historyStack.length==0){
-last=this.initialState;
-}
-if(last){
-if(last.kwArgs["back"]){
-last.kwArgs["back"]();
-}else{
-if(last.kwArgs["backButton"]){
-last.kwArgs["backButton"]();
-}else{
-if(last.kwArgs["handle"]){
-last.kwArgs.handle("back");
-}
-}
-}
-}
-this.forwardStack.push(_1fe);
-},handleForwardButton:function(){
-var last=this.forwardStack.pop();
-if(!last){
-return;
-}
-if(last.kwArgs["forward"]){
-last.kwArgs.forward();
-}else{
-if(last.kwArgs["forwardButton"]){
-last.kwArgs.forwardButton();
-}else{
-if(last.kwArgs["handle"]){
-last.kwArgs.handle("forward");
-}
-}
-}
-this.historyStack.push(last);
-},_getUrlQuery:function(url){
-var _202=url.split("?");
-if(_202.length<2){
-return null;
-}else{
-return _202[1];
-}
-}};
-dojo.provide("dojo.io.BrowserIO");
-dojo.require("dojo.io");
-dojo.require("dojo.lang.array");
-dojo.require("dojo.lang.func");
-dojo.require("dojo.string.extras");
-dojo.require("dojo.dom");
-dojo.require("dojo.undo.browser");
-dojo.io.checkChildrenForFile=function(node){
-var _204=false;
-var _205=node.getElementsByTagName("input");
-dojo.lang.forEach(_205,function(_206){
-if(_204){
-return;
-}
-if(_206.getAttribute("type")=="file"){
-_204=true;
-}
-});
-return _204;
-};
-dojo.io.formHasFile=function(_207){
-return dojo.io.checkChildrenForFile(_207);
-};
-dojo.io.updateNode=function(node,_209){
-node=dojo.byId(node);
-var args=_209;
-if(dojo.lang.isString(_209)){
-args={url:_209};
-}
-args.mimetype="text/html";
-args.load=function(t,d,e){
-while(node.firstChild){
-if(dojo["event"]){
-try{
-dojo.event.browser.clean(node.firstChild);
-}
-catch(e){
-}
-}
-node.removeChild(node.firstChild);
-}
-node.innerHTML=d;
-};
-dojo.io.bind(args);
-};
-dojo.io.formFilter=function(node){
-var type=(node.type||"").toLowerCase();
-return !node.disabled&&node.name&&!dojo.lang.inArray(type,["file","submit","image","reset","button"]);
-};
-dojo.io.encodeForm=function(_210,_211,_212){
-if((!_210)||(!_210.tagName)||(!_210.tagName.toLowerCase()=="form")){
-dojo.raise("Attempted to encode a non-form element.");
-}
-if(!_212){
-_212=dojo.io.formFilter;
-}
-var enc=/utf/i.test(_211||"")?encodeURIComponent:dojo.string.encodeAscii;
-var _214=[];
-for(var i=0;i<_210.elements.length;i++){
-var elm=_210.elements[i];
-if(!elm||elm.tagName.toLowerCase()=="fieldset"||!_212(elm)){
-continue;
-}
-var name=enc(elm.name);
-var type=elm.type.toLowerCase();
-if(type=="select-multiple"){
-for(var j=0;j=200)&&(http.status<300))||(http.status==304)||(location.protocol=="file:"&&(http.status==0||http.status==undefined))||(location.protocol=="chrome:"&&(http.status==0||http.status==undefined))){
-var ret;
-if(_23b.method.toLowerCase()=="head"){
-var _241=http.getAllResponseHeaders();
-ret={};
-ret.toString=function(){
-return _241;
-};
-var _242=_241.split(/[\r\n]+/g);
-for(var i=0;i<_242.length;i++){
-var pair=_242[i].match(/^([^:]+)\s*:\s*(.+)$/i);
-if(pair){
-ret[pair[1]]=pair[2];
-}
-}
-}else{
-if(_23b.mimetype=="text/javascript"){
-try{
-ret=dj_eval(http.responseText);
-}
-catch(e){
-dojo.debug(e);
-dojo.debug(http.responseText);
-ret=null;
-}
-}else{
-if(_23b.mimetype=="text/json"){
-try{
-ret=dj_eval("("+http.responseText+")");
-}
-catch(e){
-dojo.debug(e);
-dojo.debug(http.responseText);
-ret=false;
-}
-}else{
-if((_23b.mimetype=="application/xml")||(_23b.mimetype=="text/xml")){
-ret=http.responseXML;
-if(!ret||typeof ret=="string"||!http.getResponseHeader("Content-Type")){
-ret=dojo.dom.createDocumentFromText(http.responseText);
-}
-}else{
-ret=http.responseText;
-}
-}
-}
-}
-if(_23f){
-addToCache(url,_23e,_23b.method,http);
-}
-_23b[(typeof _23b.load=="function")?"load":"handle"]("load",ret,http,_23b);
-}else{
-var _245=new dojo.io.Error("XMLHttpTransport Error: "+http.status+" "+http.statusText);
-_23b[(typeof _23b.error=="function")?"error":"handle"]("error",_245,http,_23b);
-}
-}
-function setHeaders(http,_247){
-if(_247["headers"]){
-for(var _248 in _247["headers"]){
-if(_248.toLowerCase()=="content-type"&&!_247["contentType"]){
-_247["contentType"]=_247["headers"][_248];
-}else{
-http.setRequestHeader(_248,_247["headers"][_248]);
-}
-}
-}
-}
-this.inFlight=[];
-this.inFlightTimer=null;
-this.startWatchingInFlight=function(){
-if(!this.inFlightTimer){
-this.inFlightTimer=setInterval("dojo.io.XMLHTTPTransport.watchInFlight();",10);
-}
-};
-this.watchInFlight=function(){
-var now=null;
-for(var x=this.inFlight.length-1;x>=0;x--){
-var tif=this.inFlight[x];
-if(!tif){
-this.inFlight.splice(x,1);
-continue;
-}
-if(4==tif.http.readyState){
-this.inFlight.splice(x,1);
-doLoad(tif.req,tif.http,tif.url,tif.query,tif.useCache);
-}else{
-if(tif.startTime){
-if(!now){
-now=(new Date()).getTime();
-}
-if(tif.startTime+(tif.req.timeoutSeconds*1000)-1){
-dojo.debug("Warning: dojo.io.bind: stripping hash values from url:",url);
-url=url.split("#")[0];
-}
-if(_24e["file"]){
-_24e.method="post";
-}
-if(!_24e["method"]){
-_24e.method="get";
-}
-if(_24e.method.toLowerCase()=="get"){
-_24e.multipart=false;
-}else{
-if(_24e["file"]){
-_24e.multipart=true;
-}else{
-if(!_24e["multipart"]){
-_24e.multipart=false;
-}
-}
-}
-if(_24e["backButton"]||_24e["back"]||_24e["changeUrl"]){
-dojo.undo.browser.addToHistory(_24e);
-}
-var _253=_24e["content"]||{};
-if(_24e.sendTransport){
-_253["dojo.transport"]="xmlhttp";
-}
-do{
-if(_24e.postContent){
-_250=_24e.postContent;
-break;
-}
-if(_253){
-_250+=dojo.io.argsFromMap(_253,_24e.encoding);
-}
-if(_24e.method.toLowerCase()=="get"||!_24e.multipart){
-break;
-}
-var t=[];
-if(_250.length){
-var q=_250.split("&");
-for(var i=0;i-1?"&":"?")+_250;
-}
-if(_25a){
-_260+=(dojo.string.endsWithAny(_260,"?","&")?"":(_260.indexOf("?")>-1?"&":"?"))+"dojo.preventCache="+new Date().valueOf();
-}
-http.open(_24e.method.toUpperCase(),_260,_259);
-setHeaders(http,_24e);
-try{
-http.send(null);
-}
-catch(e){
-if(typeof http.abort=="function"){
-http.abort();
-}
-doLoad(_24e,{status:404},url,_250,_25b);
-}
-}
-if(!_259){
-doLoad(_24e,http,url,_250,_25b);
-}
-_24e.abort=function(){
-return http.abort();
-};
-return;
-};
-dojo.io.transports.addTransport("XMLHTTPTransport");
-};
-dojo.provide("dojo.event");
-dojo.require("dojo.lang.array");
-dojo.require("dojo.lang.extras");
-dojo.require("dojo.lang.func");
-dojo.event=new function(){
-this.canTimeout=dojo.lang.isFunction(dj_global["setTimeout"])||dojo.lang.isAlien(dj_global["setTimeout"]);
-function interpolateArgs(args,_262){
-var dl=dojo.lang;
-var ao={srcObj:dj_global,srcFunc:null,adviceObj:dj_global,adviceFunc:null,aroundObj:null,aroundFunc:null,adviceType:(args.length>2)?args[0]:"after",precedence:"last",once:false,delay:null,rate:0,adviceMsg:false};
-switch(args.length){
-case 0:
-return;
-case 1:
-return;
-case 2:
-ao.srcFunc=args[0];
-ao.adviceFunc=args[1];
-break;
-case 3:
-if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){
-ao.adviceType="after";
-ao.srcObj=args[0];
-ao.srcFunc=args[1];
-ao.adviceFunc=args[2];
-}else{
-if((dl.isString(args[1]))&&(dl.isString(args[2]))){
-ao.srcFunc=args[1];
-ao.adviceFunc=args[2];
-}else{
-if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){
-ao.adviceType="after";
-ao.srcObj=args[0];
-ao.srcFunc=args[1];
-var _265=dl.nameAnonFunc(args[2],ao.adviceObj,_262);
-ao.adviceFunc=_265;
-}else{
-if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){
-ao.adviceType="after";
-ao.srcObj=dj_global;
-var _265=dl.nameAnonFunc(args[0],ao.srcObj,_262);
-ao.srcFunc=_265;
-ao.adviceObj=args[1];
-ao.adviceFunc=args[2];
-}
-}
-}
-}
-break;
-case 4:
-if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){
-ao.adviceType="after";
-ao.srcObj=args[0];
-ao.srcFunc=args[1];
-ao.adviceObj=args[2];
-ao.adviceFunc=args[3];
-}else{
-if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){
-ao.adviceType=args[0];
-ao.srcObj=dj_global;
-ao.srcFunc=args[1];
-ao.adviceObj=args[2];
-ao.adviceFunc=args[3];
-}else{
-if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){
-ao.adviceType=args[0];
-ao.srcObj=dj_global;
-var _265=dl.nameAnonFunc(args[1],dj_global,_262);
-ao.srcFunc=_265;
-ao.adviceObj=args[2];
-ao.adviceFunc=args[3];
-}else{
-if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){
-ao.srcObj=args[1];
-ao.srcFunc=args[2];
-var _265=dl.nameAnonFunc(args[3],dj_global,_262);
-ao.adviceObj=dj_global;
-ao.adviceFunc=_265;
-}else{
-if(dl.isObject(args[1])){
-ao.srcObj=args[1];
-ao.srcFunc=args[2];
-ao.adviceObj=dj_global;
-ao.adviceFunc=args[3];
-}else{
-if(dl.isObject(args[2])){
-ao.srcObj=dj_global;
-ao.srcFunc=args[1];
-ao.adviceObj=args[2];
-ao.adviceFunc=args[3];
-}else{
-ao.srcObj=ao.adviceObj=ao.aroundObj=dj_global;
-ao.srcFunc=args[1];
-ao.adviceFunc=args[2];
-ao.aroundFunc=args[3];
-}
-}
-}
-}
-}
-}
-break;
-case 6:
-ao.srcObj=args[1];
-ao.srcFunc=args[2];
-ao.adviceObj=args[3];
-ao.adviceFunc=args[4];
-ao.aroundFunc=args[5];
-ao.aroundObj=dj_global;
-break;
-default:
-ao.srcObj=args[1];
-ao.srcFunc=args[2];
-ao.adviceObj=args[3];
-ao.adviceFunc=args[4];
-ao.aroundObj=args[5];
-ao.aroundFunc=args[6];
-ao.once=args[7];
-ao.delay=args[8];
-ao.rate=args[9];
-ao.adviceMsg=args[10];
-break;
-}
-if(dl.isFunction(ao.aroundFunc)){
-var _265=dl.nameAnonFunc(ao.aroundFunc,ao.aroundObj,_262);
-ao.aroundFunc=_265;
-}
-if(dl.isFunction(ao.srcFunc)){
-ao.srcFunc=dl.getNameInObj(ao.srcObj,ao.srcFunc);
-}
-if(dl.isFunction(ao.adviceFunc)){
-ao.adviceFunc=dl.getNameInObj(ao.adviceObj,ao.adviceFunc);
-}
-if((ao.aroundObj)&&(dl.isFunction(ao.aroundFunc))){
-ao.aroundFunc=dl.getNameInObj(ao.aroundObj,ao.aroundFunc);
-}
-if(!ao.srcObj){
-dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
-}
-if(!ao.adviceObj){
-dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
-}
-return ao;
-}
-this.connect=function(){
-if(arguments.length==1){
-var ao=arguments[0];
-}else{
-var ao=interpolateArgs(arguments,true);
-}
-if(dojo.lang.isArray(ao.srcObj)&&ao.srcObj!=""){
-var _267={};
-for(var x in ao){
-_267[x]=ao[x];
-}
-var mjps=[];
-dojo.lang.forEach(ao.srcObj,function(src){
-if((dojo.render.html.capable)&&(dojo.lang.isString(src))){
-src=dojo.byId(src);
-}
-_267.srcObj=src;
-mjps.push(dojo.event.connect.call(dojo.event,_267));
-});
-return mjps;
-}
-var mjp=dojo.event.MethodJoinPoint.getForMethod(ao.srcObj,ao.srcFunc);
-if(ao.adviceFunc){
-var mjp2=dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj,ao.adviceFunc);
-}
-mjp.kwAddAdvice(ao);
-return mjp;
-};
-this.log=function(a1,a2){
-var _26f;
-if((arguments.length==1)&&(typeof a1=="object")){
-_26f=a1;
-}else{
-_26f={srcObj:a1,srcFunc:a2};
-}
-_26f.adviceFunc=function(){
-var _270=[];
-for(var x=0;x=this.jp_.around.length){
-return this.jp_.object[this.jp_.methodname].apply(this.jp_.object,this.args);
-}else{
-var ti=this.jp_.around[this.around_index];
-var mobj=ti[0]||dj_global;
-var meth=ti[1];
-return mobj[meth].call(mobj,this);
-}
-};
-dojo.event.MethodJoinPoint=function(obj,_287){
-this.object=obj||dj_global;
-this.methodname=_287;
-this.methodfunc=this.object[_287];
-this.before=[];
-this.after=[];
-this.around=[];
-};
-dojo.event.MethodJoinPoint.getForMethod=function(obj,_289){
-if(!obj){
-obj=dj_global;
-}
-if(!obj[_289]){
-obj[_289]=function(){
-};
-if(!obj[_289]){
-dojo.raise("Cannot set do-nothing method on that object "+_289);
-}
-}else{
-if((!dojo.lang.isFunction(obj[_289]))&&(!dojo.lang.isAlien(obj[_289]))){
-return null;
-}
-}
-var _28a=_289+"$joinpoint";
-var _28b=_289+"$joinpoint$method";
-var _28c=obj[_28a];
-if(!_28c){
-var _28d=false;
-if(dojo.event["browser"]){
-if((obj["attachEvent"])||(obj["nodeType"])||(obj["addEventListener"])){
-_28d=true;
-dojo.event.browser.addClobberNodeAttrs(obj,[_28a,_28b,_289]);
-}
-}
-var _28e=obj[_289].length;
-obj[_28b]=obj[_289];
-_28c=obj[_28a]=new dojo.event.MethodJoinPoint(obj,_28b);
-obj[_289]=function(){
-var args=[];
-if((_28d)&&(!arguments.length)){
-var evt=null;
-try{
-if(obj.ownerDocument){
-evt=obj.ownerDocument.parentWindow.event;
-}else{
-if(obj.documentElement){
-evt=obj.documentElement.ownerDocument.parentWindow.event;
-}else{
-evt=window.event;
-}
-}
-}
-catch(e){
-evt=window.event;
-}
-if(evt){
-args.push(dojo.event.browser.fixEvent(evt,this));
-}
-}else{
-for(var x=0;x0){
-dojo.lang.forEach(this.before,_296);
-}
-var _2a6;
-if(this.around.length>0){
-var mi=new dojo.event.MethodInvocation(this,obj,args);
-_2a6=mi.proceed();
-}else{
-if(this.methodfunc){
-_2a6=this.object[this.methodname].apply(this.object,args);
-}
-}
-if(this.after.length>0){
-dojo.lang.forEach(this.after,_296);
-}
-return (this.methodfunc)?_2a6:null;
-},getArr:function(kind){
-var arr=this.after;
-if((typeof kind=="string")&&(kind.indexOf("before")!=-1)){
-arr=this.before;
-}else{
-if(kind=="around"){
-arr=this.around;
-}
-}
-return arr;
-},kwAddAdvice:function(args){
-this.addAdvice(args["adviceObj"],args["adviceFunc"],args["aroundObj"],args["aroundFunc"],args["adviceType"],args["precedence"],args["once"],args["delay"],args["rate"],args["adviceMsg"]);
-},addAdvice:function(_2ab,_2ac,_2ad,_2ae,_2af,_2b0,once,_2b2,rate,_2b4){
-var arr=this.getArr(_2af);
-if(!arr){
-dojo.raise("bad this: "+this);
-}
-var ao=[_2ab,_2ac,_2ad,_2ae,_2b2,rate,_2b4];
-if(once){
-if(this.hasAdvice(_2ab,_2ac,_2af,arr)>=0){
-return;
-}
-}
-if(_2b0=="first"){
-arr.unshift(ao);
-}else{
-arr.push(ao);
-}
-},hasAdvice:function(_2b7,_2b8,_2b9,arr){
-if(!arr){
-arr=this.getArr(_2b9);
-}
-var ind=-1;
-for(var x=0;x=0;i=i-1){
-var el=na[i];
-if(el["__clobberAttrs__"]){
-for(var j=0;j0){
-this.duration=_319;
-}
-if(_31c){
-this.repeatCount=_31c;
-}
-if(rate){
-this.rate=rate;
-}
-if(_318){
-this.handler=_318.handler;
-this.beforeBegin=_318.beforeBegin;
-this.onBegin=_318.onBegin;
-this.onEnd=_318.onEnd;
-this.onPlay=_318.onPlay;
-this.onPause=_318.onPause;
-this.onStop=_318.onStop;
-this.onAnimate=_318.onAnimate;
-}
-if(_31b&&dojo.lang.isFunction(_31b)){
-this.easing=_31b;
-}
-};
-dojo.inherits(dojo.lfx.Animation,dojo.lfx.IAnimation);
-dojo.lang.extend(dojo.lfx.Animation,{_startTime:null,_endTime:null,_timer:null,_percent:0,_startRepeatCount:0,play:function(_31e,_31f){
-if(_31f){
-clearTimeout(this._timer);
-this._active=false;
-this._paused=false;
-this._percent=0;
-}else{
-if(this._active&&!this._paused){
-return this;
-}
-}
-this.fire("handler",["beforeBegin"]);
-this.fire("beforeBegin");
-if(_31e>0){
-setTimeout(dojo.lang.hitch(this,function(){
-this.play(null,_31f);
-}),_31e);
-return this;
-}
-this._startTime=new Date().valueOf();
-if(this._paused){
-this._startTime-=(this.duration*this._percent/100);
-}
-this._endTime=this._startTime+this.duration;
-this._active=true;
-this._paused=false;
-var step=this._percent/100;
-var _321=this.curve.getValue(step);
-if(this._percent==0){
-if(!this._startRepeatCount){
-this._startRepeatCount=this.repeatCount;
-}
-this.fire("handler",["begin",_321]);
-this.fire("onBegin",[_321]);
-}
-this.fire("handler",["play",_321]);
-this.fire("onPlay",[_321]);
-this._cycle();
-return this;
-},pause:function(){
-clearTimeout(this._timer);
-if(!this._active){
-return this;
-}
-this._paused=true;
-var _322=this.curve.getValue(this._percent/100);
-this.fire("handler",["pause",_322]);
-this.fire("onPause",[_322]);
-return this;
-},gotoPercent:function(pct,_324){
-clearTimeout(this._timer);
-this._active=true;
-this._paused=true;
-this._percent=pct;
-if(_324){
-this.play();
-}
-},stop:function(_325){
-clearTimeout(this._timer);
-var step=this._percent/100;
-if(_325){
-step=1;
-}
-var _327=this.curve.getValue(step);
-this.fire("handler",["stop",_327]);
-this.fire("onStop",[_327]);
-this._active=false;
-this._paused=false;
-return this;
-},status:function(){
-if(this._active){
-return this._paused?"paused":"playing";
-}else{
-return "stopped";
-}
-},_cycle:function(){
-clearTimeout(this._timer);
-if(this._active){
-var curr=new Date().valueOf();
-var step=(curr-this._startTime)/(this._endTime-this._startTime);
-if(step>=1){
-step=1;
-this._percent=100;
-}else{
-this._percent=step*100;
-}
-if((this.easing)&&(dojo.lang.isFunction(this.easing))){
-step=this.easing(step);
-}
-var _32a=this.curve.getValue(step);
-this.fire("handler",["animate",_32a]);
-this.fire("onAnimate",[_32a]);
-if(step<1){
-this._timer=setTimeout(dojo.lang.hitch(this,"_cycle"),this.rate);
-}else{
-this._active=false;
-this.fire("handler",["end"]);
-this.fire("onEnd");
-if(this.repeatCount>0){
-this.repeatCount--;
-this.play(null,true);
-}else{
-if(this.repeatCount==-1){
-this.play(null,true);
-}else{
-if(this._startRepeatCount){
-this.repeatCount=this._startRepeatCount;
-this._startRepeatCount=0;
-}
-}
-}
-}
-}
-return this;
-}});
-dojo.lfx.Combine=function(){
-dojo.lfx.IAnimation.call(this);
-this._anims=[];
-this._animsEnded=0;
-var _32b=arguments;
-if(_32b.length==1&&(dojo.lang.isArray(_32b[0])||dojo.lang.isArrayLike(_32b[0]))){
-_32b=_32b[0];
-}
-var _32c=this;
-dojo.lang.forEach(_32b,function(anim){
-_32c._anims.push(anim);
-var _32e=(anim["onEnd"])?dojo.lang.hitch(anim,"onEnd"):function(){
-};
-anim.onEnd=function(){
-_32e();
-_32c._onAnimsEnded();
-};
-});
-};
-dojo.inherits(dojo.lfx.Combine,dojo.lfx.IAnimation);
-dojo.lang.extend(dojo.lfx.Combine,{_animsEnded:0,play:function(_32f,_330){
-if(!this._anims.length){
-return this;
-}
-this.fire("beforeBegin");
-if(_32f>0){
-setTimeout(dojo.lang.hitch(this,function(){
-this.play(null,_330);
-}),_32f);
-return this;
-}
-if(_330||this._anims[0].percent==0){
-this.fire("onBegin");
-}
-this.fire("onPlay");
-this._animsCall("play",null,_330);
-return this;
-},pause:function(){
-this.fire("onPause");
-this._animsCall("pause");
-return this;
-},stop:function(_331){
-this.fire("onStop");
-this._animsCall("stop",_331);
-return this;
-},_onAnimsEnded:function(){
-this._animsEnded++;
-if(this._animsEnded>=this._anims.length){
-this.fire("onEnd");
-}
-return this;
-},_animsCall:function(_332){
-var args=[];
-if(arguments.length>1){
-for(var i=1;i0){
-setTimeout(dojo.lang.hitch(this,function(){
-this.play(null,_33e);
-}),_33d);
-return this;
-}
-if(_33f){
-if(this._currAnim==0){
-this.fire("handler",["begin",this._currAnim]);
-this.fire("onBegin",[this._currAnim]);
-}
-this.fire("onPlay",[this._currAnim]);
-_33f.play(null,_33e);
-}
-return this;
-},pause:function(){
-if(this._anims[this._currAnim]){
-this._anims[this._currAnim].pause();
-this.fire("onPause",[this._currAnim]);
-}
-return this;
-},playPause:function(){
-if(this._anims.length==0){
-return this;
-}
-if(this._currAnim==-1){
-this._currAnim=0;
-}
-var _340=this._anims[this._currAnim];
-if(_340){
-if(!_340._active||_340._paused){
-this.play();
-}else{
-this.pause();
-}
-}
-return this;
-},stop:function(){
-var _341=this._anims[this._currAnim];
-if(_341){
-_341.stop();
-this.fire("onStop",[this._currAnim]);
-}
-return _341;
-},_playNext:function(){
-if(this._currAnim==-1||this._anims.length==0){
-return this;
-}
-this._currAnim++;
-if(this._anims[this._currAnim]){
-this._anims[this._currAnim].play(null,true);
-}
-return this;
-}});
-dojo.lfx.combine=function(){
-var _342=arguments;
-if(dojo.lang.isArray(arguments[0])){
-_342=arguments[0];
-}
-return new dojo.lfx.Combine(_342);
-};
-dojo.lfx.chain=function(){
-var _343=arguments;
-if(dojo.lang.isArray(arguments[0])){
-_343=arguments[0];
-}
-return new dojo.lfx.Chain(_343);
-};
-dojo.provide("dojo.graphics.color");
-dojo.require("dojo.lang.array");
-dojo.graphics.color.Color=function(r,g,b,a){
-if(dojo.lang.isArray(r)){
-this.r=r[0];
-this.g=r[1];
-this.b=r[2];
-this.a=r[3]||1;
-}else{
-if(dojo.lang.isString(r)){
-var rgb=dojo.graphics.color.extractRGB(r);
-this.r=rgb[0];
-this.g=rgb[1];
-this.b=rgb[2];
-this.a=g||1;
-}else{
-if(r instanceof dojo.graphics.color.Color){
-this.r=r.r;
-this.b=r.b;
-this.g=r.g;
-this.a=r.a;
-}else{
-this.r=r;
-this.g=g;
-this.b=b;
-this.a=a;
-}
-}
-}
-};
-dojo.graphics.color.Color.fromArray=function(arr){
-return new dojo.graphics.color.Color(arr[0],arr[1],arr[2],arr[3]);
-};
-dojo.lang.extend(dojo.graphics.color.Color,{toRgb:function(_34a){
-if(_34a){
-return this.toRgba();
-}else{
-return [this.r,this.g,this.b];
-}
-},toRgba:function(){
-return [this.r,this.g,this.b,this.a];
-},toHex:function(){
-return dojo.graphics.color.rgb2hex(this.toRgb());
-},toCss:function(){
-return "rgb("+this.toRgb().join()+")";
-},toString:function(){
-return this.toHex();
-},blend:function(_34b,_34c){
-return dojo.graphics.color.blend(this.toRgb(),new dojo.graphics.color.Color(_34b).toRgb(),_34c);
-}});
-dojo.graphics.color.named={white:[255,255,255],black:[0,0,0],red:[255,0,0],green:[0,255,0],blue:[0,0,255],navy:[0,0,128],gray:[128,128,128],silver:[192,192,192]};
-dojo.graphics.color.blend=function(a,b,_34f){
-if(typeof a=="string"){
-return dojo.graphics.color.blendHex(a,b,_34f);
-}
-if(!_34f){
-_34f=0;
-}else{
-if(_34f>1){
-_34f=1;
-}else{
-if(_34f<-1){
-_34f=-1;
-}
-}
-}
-var c=new Array(3);
-for(var i=0;i<3;i++){
-var half=Math.abs(a[i]-b[i])/2;
-c[i]=Math.floor(Math.min(a[i],b[i])+half+(half*_34f));
-}
-return c;
-};
-dojo.graphics.color.blendHex=function(a,b,_355){
-return dojo.graphics.color.rgb2hex(dojo.graphics.color.blend(dojo.graphics.color.hex2rgb(a),dojo.graphics.color.hex2rgb(b),_355));
-};
-dojo.graphics.color.extractRGB=function(_356){
-var hex="0123456789abcdef";
-_356=_356.toLowerCase();
-if(_356.indexOf("rgb")==0){
-var _358=_356.match(/rgba*\((\d+), *(\d+), *(\d+)/i);
-var ret=_358.splice(1,3);
-return ret;
-}else{
-var _35a=dojo.graphics.color.hex2rgb(_356);
-if(_35a){
-return _35a;
-}else{
-return dojo.graphics.color.named[_356]||[255,255,255];
-}
-}
-};
-dojo.graphics.color.hex2rgb=function(hex){
-var _35c="0123456789ABCDEF";
-var rgb=new Array(3);
-if(hex.indexOf("#")==0){
-hex=hex.substring(1);
-}
-hex=hex.toUpperCase();
-if(hex.replace(new RegExp("["+_35c+"]","g"),"")!=""){
-return null;
-}
-if(hex.length==3){
-rgb[0]=hex.charAt(0)+hex.charAt(0);
-rgb[1]=hex.charAt(1)+hex.charAt(1);
-rgb[2]=hex.charAt(2)+hex.charAt(2);
-}else{
-rgb[0]=hex.substring(0,2);
-rgb[1]=hex.substring(2,4);
-rgb[2]=hex.substring(4);
-}
-for(var i=0;i0&&!(j==1&&segs[0]=="")&&segs[j]==".."&&segs[j-1]!=".."){
-if(j==segs.length-1){
-segs.splice(j,1);
-segs[j-1]="";
-}else{
-segs.splice(j-1,2);
-j-=2;
-}
-}
-}
-}
-_36a.path=segs.join("/");
-}
-}
-}
-}
-uri="";
-if(_36a.scheme!=null){
-uri+=_36a.scheme+":";
-}
-if(_36a.authority!=null){
-uri+="//"+_36a.authority;
-}
-uri+=_36a.path;
-if(_36a.query!=null){
-uri+="?"+_36a.query;
-}
-if(_36a.fragment!=null){
-uri+="#"+_36a.fragment;
-}
-}
-this.uri=uri.toString();
-var _36f="^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?$";
-var r=this.uri.match(new RegExp(_36f));
-this.scheme=r[2]||(r[1]?"":null);
-this.authority=r[4]||(r[3]?"":null);
-this.path=r[5];
-this.query=r[7]||(r[6]?"":null);
-this.fragment=r[9]||(r[8]?"":null);
-if(this.authority!=null){
-_36f="^((([^:]+:)?([^@]+))@)?([^:]*)(:([0-9]+))?$";
-r=this.authority.match(new RegExp(_36f));
-this.user=r[3]||null;
-this.password=r[4]||null;
-this.host=r[5];
-this.port=r[7]||null;
-}
-this.toString=function(){
-return this.uri;
-};
-};
-};
-dojo.provide("dojo.style");
-dojo.require("dojo.graphics.color");
-dojo.require("dojo.uri.Uri");
-dojo.require("dojo.lang.common");
-(function(){
-var h=dojo.render.html;
-var ds=dojo.style;
-var db=document["body"]||document["documentElement"];
-ds.boxSizing={MARGIN_BOX:"margin-box",BORDER_BOX:"border-box",PADDING_BOX:"padding-box",CONTENT_BOX:"content-box"};
-var bs=ds.boxSizing;
-ds.getBoxSizing=function(node){
-if((h.ie)||(h.opera)){
-var cm=document["compatMode"];
-if((cm=="BackCompat")||(cm=="QuirksMode")){
-return bs.BORDER_BOX;
-}else{
-return bs.CONTENT_BOX;
-}
-}else{
-if(arguments.length==0){
-node=document.documentElement;
-}
-var _377=ds.getStyle(node,"-moz-box-sizing");
-if(!_377){
-_377=ds.getStyle(node,"box-sizing");
-}
-return (_377?_377:bs.CONTENT_BOX);
-}
-};
-ds.isBorderBox=function(node){
-return (ds.getBoxSizing(node)==bs.BORDER_BOX);
-};
-ds.getUnitValue=function(node,_37a,_37b){
-var s=ds.getComputedStyle(node,_37a);
-if((!s)||((s=="auto")&&(_37b))){
-return {value:0,units:"px"};
-}
-if(dojo.lang.isUndefined(s)){
-return ds.getUnitValue.bad;
-}
-var _37d=s.match(/(\-?[\d.]+)([a-z%]*)/i);
-if(!_37d){
-return ds.getUnitValue.bad;
-}
-return {value:Number(_37d[1]),units:_37d[2].toLowerCase()};
-};
-ds.getUnitValue.bad={value:NaN,units:""};
-ds.getPixelValue=function(node,_37f,_380){
-var _381=ds.getUnitValue(node,_37f,_380);
-if(isNaN(_381.value)){
-return 0;
-}
-if((_381.value)&&(_381.units!="px")){
-return NaN;
-}
-return _381.value;
-};
-ds.getNumericStyle=function(){
-dojo.deprecated("dojo.(style|html).getNumericStyle","in favor of dojo.(style|html).getPixelValue","0.4");
-return ds.getPixelValue.apply(this,arguments);
-};
-ds.setPositivePixelValue=function(node,_383,_384){
-if(isNaN(_384)){
-return false;
-}
-node.style[_383]=Math.max(0,_384)+"px";
-return true;
-};
-ds._sumPixelValues=function(node,_386,_387){
-var _388=0;
-for(var x=0;x<_386.length;x++){
-_388+=ds.getPixelValue(node,_386[x],_387);
-}
-return _388;
-};
-ds.isPositionAbsolute=function(node){
-return (ds.getComputedStyle(node,"position")=="absolute");
-};
-ds.getBorderExtent=function(node,side){
-return (ds.getStyle(node,"border-"+side+"-style")=="none"?0:ds.getPixelValue(node,"border-"+side+"-width"));
-};
-ds.getMarginWidth=function(node){
-return ds._sumPixelValues(node,["margin-left","margin-right"],ds.isPositionAbsolute(node));
-};
-ds.getBorderWidth=function(node){
-return ds.getBorderExtent(node,"left")+ds.getBorderExtent(node,"right");
-};
-ds.getPaddingWidth=function(node){
-return ds._sumPixelValues(node,["padding-left","padding-right"],true);
-};
-ds.getPadBorderWidth=function(node){
-return ds.getPaddingWidth(node)+ds.getBorderWidth(node);
-};
-ds.getContentBoxWidth=function(node){
-node=dojo.byId(node);
-return node.offsetWidth-ds.getPadBorderWidth(node);
-};
-ds.getBorderBoxWidth=function(node){
-node=dojo.byId(node);
-return node.offsetWidth;
-};
-ds.getMarginBoxWidth=function(node){
-return ds.getInnerWidth(node)+ds.getMarginWidth(node);
-};
-ds.setContentBoxWidth=function(node,_395){
-node=dojo.byId(node);
-if(ds.isBorderBox(node)){
-_395+=ds.getPadBorderWidth(node);
-}
-return ds.setPositivePixelValue(node,"width",_395);
-};
-ds.setMarginBoxWidth=function(node,_397){
-node=dojo.byId(node);
-if(!ds.isBorderBox(node)){
-_397-=ds.getPadBorderWidth(node);
-}
-_397-=ds.getMarginWidth(node);
-return ds.setPositivePixelValue(node,"width",_397);
-};
-ds.getContentWidth=ds.getContentBoxWidth;
-ds.getInnerWidth=ds.getBorderBoxWidth;
-ds.getOuterWidth=ds.getMarginBoxWidth;
-ds.setContentWidth=ds.setContentBoxWidth;
-ds.setOuterWidth=ds.setMarginBoxWidth;
-ds.getMarginHeight=function(node){
-return ds._sumPixelValues(node,["margin-top","margin-bottom"],ds.isPositionAbsolute(node));
-};
-ds.getBorderHeight=function(node){
-return ds.getBorderExtent(node,"top")+ds.getBorderExtent(node,"bottom");
-};
-ds.getPaddingHeight=function(node){
-return ds._sumPixelValues(node,["padding-top","padding-bottom"],true);
-};
-ds.getPadBorderHeight=function(node){
-return ds.getPaddingHeight(node)+ds.getBorderHeight(node);
-};
-ds.getContentBoxHeight=function(node){
-node=dojo.byId(node);
-return node.offsetHeight-ds.getPadBorderHeight(node);
-};
-ds.getBorderBoxHeight=function(node){
-node=dojo.byId(node);
-return node.offsetHeight;
-};
-ds.getMarginBoxHeight=function(node){
-return ds.getInnerHeight(node)+ds.getMarginHeight(node);
-};
-ds.setContentBoxHeight=function(node,_3a0){
-node=dojo.byId(node);
-if(ds.isBorderBox(node)){
-_3a0+=ds.getPadBorderHeight(node);
-}
-return ds.setPositivePixelValue(node,"height",_3a0);
-};
-ds.setMarginBoxHeight=function(node,_3a2){
-node=dojo.byId(node);
-if(!ds.isBorderBox(node)){
-_3a2-=ds.getPadBorderHeight(node);
-}
-_3a2-=ds.getMarginHeight(node);
-return ds.setPositivePixelValue(node,"height",_3a2);
-};
-ds.getContentHeight=ds.getContentBoxHeight;
-ds.getInnerHeight=ds.getBorderBoxHeight;
-ds.getOuterHeight=ds.getMarginBoxHeight;
-ds.setContentHeight=ds.setContentBoxHeight;
-ds.setOuterHeight=ds.setMarginBoxHeight;
-ds.getAbsolutePosition=ds.abs=function(node,_3a4){
-node=dojo.byId(node);
-var ret=[];
-ret.x=ret.y=0;
-var st=dojo.html.getScrollTop();
-var sl=dojo.html.getScrollLeft();
-if(h.ie){
-with(node.getBoundingClientRect()){
-ret.x=left-2;
-ret.y=top-2;
-}
-}else{
-if(document.getBoxObjectFor){
-var bo=document.getBoxObjectFor(node);
-ret.x=bo.x-ds.sumAncestorProperties(node,"scrollLeft");
-ret.y=bo.y-ds.sumAncestorProperties(node,"scrollTop");
-}else{
-if(node["offsetParent"]){
-var _3a9;
-if((h.safari)&&(node.style.getPropertyValue("position")=="absolute")&&(node.parentNode==db)){
-_3a9=db;
-}else{
-_3a9=db.parentNode;
-}
-if(node.parentNode!=db){
-var nd=node;
-if(window.opera){
-nd=db;
-}
-ret.x-=ds.sumAncestorProperties(nd,"scrollLeft");
-ret.y-=ds.sumAncestorProperties(nd,"scrollTop");
-}
-do{
-var n=node["offsetLeft"];
-ret.x+=isNaN(n)?0:n;
-var m=node["offsetTop"];
-ret.y+=isNaN(m)?0:m;
-node=node.offsetParent;
-}while((node!=_3a9)&&(node!=null));
-}else{
-if(node["x"]&&node["y"]){
-ret.x+=isNaN(node.x)?0:node.x;
-ret.y+=isNaN(node.y)?0:node.y;
-}
-}
-}
-}
-if(_3a4){
-ret.y+=st;
-ret.x+=sl;
-}
-ret[0]=ret.x;
-ret[1]=ret.y;
-return ret;
-};
-ds.sumAncestorProperties=function(node,prop){
-node=dojo.byId(node);
-if(!node){
-return 0;
-}
-var _3af=0;
-while(node){
-var val=node[prop];
-if(val){
-_3af+=val-0;
-if(node==document.body){
-break;
-}
-}
-node=node.parentNode;
-}
-return _3af;
-};
-ds.getTotalOffset=function(node,type,_3b3){
-return ds.abs(node,_3b3)[(type=="top")?"y":"x"];
-};
-ds.getAbsoluteX=ds.totalOffsetLeft=function(node,_3b5){
-return ds.getTotalOffset(node,"left",_3b5);
-};
-ds.getAbsoluteY=ds.totalOffsetTop=function(node,_3b7){
-return ds.getTotalOffset(node,"top",_3b7);
-};
-ds.styleSheet=null;
-ds.insertCssRule=function(_3b8,_3b9,_3ba){
-if(!ds.styleSheet){
-if(document.createStyleSheet){
-ds.styleSheet=document.createStyleSheet();
-}else{
-if(document.styleSheets[0]){
-ds.styleSheet=document.styleSheets[0];
-}else{
-return null;
-}
-}
-}
-if(arguments.length<3){
-if(ds.styleSheet.cssRules){
-_3ba=ds.styleSheet.cssRules.length;
-}else{
-if(ds.styleSheet.rules){
-_3ba=ds.styleSheet.rules.length;
-}else{
-return null;
-}
-}
-}
-if(ds.styleSheet.insertRule){
-var rule=_3b8+" { "+_3b9+" }";
-return ds.styleSheet.insertRule(rule,_3ba);
-}else{
-if(ds.styleSheet.addRule){
-return ds.styleSheet.addRule(_3b8,_3b9,_3ba);
-}else{
-return null;
-}
-}
-};
-ds.removeCssRule=function(_3bc){
-if(!ds.styleSheet){
-dojo.debug("no stylesheet defined for removing rules");
-return false;
-}
-if(h.ie){
-if(!_3bc){
-_3bc=ds.styleSheet.rules.length;
-ds.styleSheet.removeRule(_3bc);
-}
-}else{
-if(document.styleSheets[0]){
-if(!_3bc){
-_3bc=ds.styleSheet.cssRules.length;
-}
-ds.styleSheet.deleteRule(_3bc);
-}
-}
-return true;
-};
-ds.insertCssFile=function(URI,doc,_3bf){
-if(!URI){
-return;
-}
-if(!doc){
-doc=document;
-}
-var _3c0=dojo.hostenv.getText(URI);
-_3c0=ds.fixPathsInCssText(_3c0,URI);
-if(_3bf){
-var _3c1=doc.getElementsByTagName("style");
-var _3c2="";
-for(var i=0;i<_3c1.length;i++){
-_3c2=(_3c1[i].styleSheet&&_3c1[i].styleSheet.cssText)?_3c1[i].styleSheet.cssText:_3c1[i].innerHTML;
-if(_3c0==_3c2){
-return;
-}
-}
-}
-var _3c4=ds.insertCssText(_3c0);
-if(_3c4&&djConfig.isDebug){
-_3c4.setAttribute("dbgHref",URI);
-}
-return _3c4;
-};
-ds.insertCssText=function(_3c5,doc,URI){
-if(!_3c5){
-return;
-}
-if(!doc){
-doc=document;
-}
-if(URI){
-_3c5=ds.fixPathsInCssText(_3c5,URI);
-}
-var _3c8=doc.createElement("style");
-_3c8.setAttribute("type","text/css");
-var head=doc.getElementsByTagName("head")[0];
-if(!head){
-dojo.debug("No head tag in document, aborting styles");
-return;
-}else{
-head.appendChild(_3c8);
-}
-if(_3c8.styleSheet){
-_3c8.styleSheet.cssText=_3c5;
-}else{
-var _3ca=doc.createTextNode(_3c5);
-_3c8.appendChild(_3ca);
-}
-return _3c8;
-};
-ds.fixPathsInCssText=function(_3cb,URI){
-if(!_3cb||!URI){
-return;
-}
-var pos=0;
-var str="";
-var url="";
-while(pos!=-1){
-pos=0;
-url="";
-pos=_3cb.indexOf("url(",pos);
-if(pos<0){
-break;
-}
-str+=_3cb.slice(0,pos+4);
-_3cb=_3cb.substring(pos+4,_3cb.length);
-url+=_3cb.match(/^[\t\s\w()\/.\\'"-:#=&?]*\)/)[0];
-_3cb=_3cb.substring(url.length-1,_3cb.length);
-url=url.replace(/^[\s\t]*(['"]?)([\w()\/.\\'"-:#=&?]*)\1[\s\t]*?\)/,"$2");
-if(url.search(/(file|https?|ftps?):\/\//)==-1){
-url=(new dojo.uri.Uri(URI,url).toString());
-}
-str+=url;
-}
-return str+_3cb;
-};
-ds.getBackgroundColor=function(node){
-node=dojo.byId(node);
-var _3d1;
-do{
-_3d1=ds.getStyle(node,"background-color");
-if(_3d1.toLowerCase()=="rgba(0, 0, 0, 0)"){
-_3d1="transparent";
-}
-if(node==document.getElementsByTagName("body")[0]){
-node=null;
-break;
-}
-node=node.parentNode;
-}while(node&&dojo.lang.inArray(_3d1,["transparent",""]));
-if(_3d1=="transparent"){
-_3d1=[255,255,255,0];
-}else{
-_3d1=dojo.graphics.color.extractRGB(_3d1);
-}
-return _3d1;
-};
-ds.getComputedStyle=function(node,_3d3,_3d4){
-node=dojo.byId(node);
-var _3d3=ds.toSelectorCase(_3d3);
-var _3d5=ds.toCamelCase(_3d3);
-if(!node||!node.style){
-return _3d4;
-}else{
-if(document.defaultView){
-try{
-var cs=document.defaultView.getComputedStyle(node,"");
-if(cs){
-return cs.getPropertyValue(_3d3);
-}
-}
-catch(e){
-if(node.style.getPropertyValue){
-return node.style.getPropertyValue(_3d3);
-}else{
-return _3d4;
-}
-}
-}else{
-if(node.currentStyle){
-return node.currentStyle[_3d5];
-}
-}
-}
-if(node.style.getPropertyValue){
-return node.style.getPropertyValue(_3d3);
-}else{
-return _3d4;
-}
-};
-ds.getStyleProperty=function(node,_3d8){
-node=dojo.byId(node);
-return (node&&node.style?node.style[ds.toCamelCase(_3d8)]:undefined);
-};
-ds.getStyle=function(node,_3da){
-var _3db=ds.getStyleProperty(node,_3da);
-return (_3db?_3db:ds.getComputedStyle(node,_3da));
-};
-ds.setStyle=function(node,_3dd,_3de){
-node=dojo.byId(node);
-if(node&&node.style){
-var _3df=ds.toCamelCase(_3dd);
-node.style[_3df]=_3de;
-}
-};
-ds.toCamelCase=function(_3e0){
-var arr=_3e0.split("-"),cc=arr[0];
-for(var i=1;i=1){
-if(h.ie){
-ds.clearOpacity(node);
-return;
-}else{
-_3e5=0.999999;
-}
-}else{
-if(_3e5<0){
-_3e5=0;
-}
-}
-}
-if(h.ie){
-if(node.nodeName.toLowerCase()=="tr"){
-var tds=node.getElementsByTagName("td");
-for(var x=0;x=0.999999?1:Number(opac);
-};
-ds.clearOpacity=function clearOpacity(node){
-node=dojo.byId(node);
-var ns=node.style;
-if(h.ie){
-try{
-if(node.filters&&node.filters.alpha){
-ns.filter="";
-}
-}
-catch(e){
-}
-}else{
-if(h.moz){
-ns.opacity=1;
-ns.MozOpacity=1;
-}else{
-if(h.safari){
-ns.opacity=1;
-ns.KhtmlOpacity=1;
-}else{
-ns.opacity=1;
-}
-}
-}
-};
-ds.setStyleAttributes=function(node,_3ee){
-var _3ef={"opacity":dojo.style.setOpacity,"content-height":dojo.style.setContentHeight,"content-width":dojo.style.setContentWidth,"outer-height":dojo.style.setOuterHeight,"outer-width":dojo.style.setOuterWidth};
-var _3f0=_3ee.replace(/(;)?\s*$/,"").split(";");
-for(var i=0;i<_3f0.length;i++){
-var _3f2=_3f0[i].split(":");
-var name=_3f2[0].replace(/\s*$/,"").replace(/^\s*/,"").toLowerCase();
-var _3f4=_3f2[1].replace(/\s*$/,"").replace(/^\s*/,"");
-if(dojo.lang.has(_3ef,name)){
-_3ef[name](node,_3f4);
-}else{
-node.style[dojo.style.toCamelCase(name)]=_3f4;
-}
-}
-};
-ds._toggle=function(node,_3f6,_3f7){
-node=dojo.byId(node);
-_3f7(node,!_3f6(node));
-return _3f6(node);
-};
-ds.show=function(node){
-node=dojo.byId(node);
-if(ds.getStyleProperty(node,"display")=="none"){
-ds.setStyle(node,"display",(node.dojoDisplayCache||""));
-node.dojoDisplayCache=undefined;
-}
-};
-ds.hide=function(node){
-node=dojo.byId(node);
-if(typeof node["dojoDisplayCache"]=="undefined"){
-var d=ds.getStyleProperty(node,"display");
-if(d!="none"){
-node.dojoDisplayCache=d;
-}
-}
-ds.setStyle(node,"display","none");
-};
-ds.setShowing=function(node,_3fc){
-ds[(_3fc?"show":"hide")](node);
-};
-ds.isShowing=function(node){
-return (ds.getStyleProperty(node,"display")!="none");
-};
-ds.toggleShowing=function(node){
-return ds._toggle(node,ds.isShowing,ds.setShowing);
-};
-ds.displayMap={tr:"",td:"",th:"",img:"inline",span:"inline",input:"inline",button:"inline"};
-ds.suggestDisplayByTagName=function(node){
-node=dojo.byId(node);
-if(node&&node.tagName){
-var tag=node.tagName.toLowerCase();
-return (tag in ds.displayMap?ds.displayMap[tag]:"block");
-}
-};
-ds.setDisplay=function(node,_402){
-ds.setStyle(node,"display",(dojo.lang.isString(_402)?_402:(_402?ds.suggestDisplayByTagName(node):"none")));
-};
-ds.isDisplayed=function(node){
-return (ds.getComputedStyle(node,"display")!="none");
-};
-ds.toggleDisplay=function(node){
-return ds._toggle(node,ds.isDisplayed,ds.setDisplay);
-};
-ds.setVisibility=function(node,_406){
-ds.setStyle(node,"visibility",(dojo.lang.isString(_406)?_406:(_406?"visible":"hidden")));
-};
-ds.isVisible=function(node){
-return (ds.getComputedStyle(node,"visibility")!="hidden");
-};
-ds.toggleVisibility=function(node){
-return ds._toggle(node,ds.isVisible,ds.setVisibility);
-};
-ds.toCoordinateArray=function(_409,_40a){
-if(dojo.lang.isArray(_409)){
-while(_409.length<4){
-_409.push(0);
-}
-while(_409.length>4){
-_409.pop();
-}
-var ret=_409;
-}else{
-var node=dojo.byId(_409);
-var pos=ds.getAbsolutePosition(node,_40a);
-var ret=[pos.x,pos.y,ds.getBorderBoxWidth(node),ds.getBorderBoxHeight(node)];
-}
-ret.x=ret[0];
-ret.y=ret[1];
-ret.w=ret[2];
-ret.h=ret[3];
-return ret;
-};
-})();
-dojo.provide("dojo.html");
-dojo.require("dojo.lang.func");
-dojo.require("dojo.dom");
-dojo.require("dojo.style");
-dojo.require("dojo.string");
-dojo.lang.mixin(dojo.html,dojo.dom);
-dojo.lang.mixin(dojo.html,dojo.style);
-dojo.html.clearSelection=function(){
-try{
-if(window["getSelection"]){
-if(dojo.render.html.safari){
-window.getSelection().collapse();
-}else{
-window.getSelection().removeAllRanges();
-}
-}else{
-if(document.selection){
-if(document.selection.empty){
-document.selection.empty();
-}else{
-if(document.selection.clear){
-document.selection.clear();
-}
-}
-}
-}
-return true;
-}
-catch(e){
-dojo.debug(e);
-return false;
-}
-};
-dojo.html.disableSelection=function(_40e){
-_40e=dojo.byId(_40e)||document.body;
-var h=dojo.render.html;
-if(h.mozilla){
-_40e.style.MozUserSelect="none";
-}else{
-if(h.safari){
-_40e.style.KhtmlUserSelect="none";
-}else{
-if(h.ie){
-_40e.unselectable="on";
-}else{
-return false;
-}
-}
-}
-return true;
-};
-dojo.html.enableSelection=function(_410){
-_410=dojo.byId(_410)||document.body;
-var h=dojo.render.html;
-if(h.mozilla){
-_410.style.MozUserSelect="";
-}else{
-if(h.safari){
-_410.style.KhtmlUserSelect="";
-}else{
-if(h.ie){
-_410.unselectable="off";
-}else{
-return false;
-}
-}
-}
-return true;
-};
-dojo.html.selectElement=function(_412){
-_412=dojo.byId(_412);
-if(document.selection&&document.body.createTextRange){
-var _413=document.body.createTextRange();
-_413.moveToElementText(_412);
-_413.select();
-}else{
-if(window["getSelection"]){
-var _414=window.getSelection();
-if(_414["selectAllChildren"]){
-_414.selectAllChildren(_412);
-}
-}
-}
-};
-dojo.html.selectInputText=function(_415){
-_415=dojo.byId(_415);
-if(document.selection&&document.body.createTextRange){
-var _416=_415.createTextRange();
-_416.moveStart("character",0);
-_416.moveEnd("character",_415.value.length);
-_416.select();
-}else{
-if(window["getSelection"]){
-var _417=window.getSelection();
-_415.setSelectionRange(0,_415.value.length);
-}
-}
-_415.focus();
-};
-dojo.html.isSelectionCollapsed=function(){
-if(document["selection"]){
-return document.selection.createRange().text=="";
-}else{
-if(window["getSelection"]){
-var _418=window.getSelection();
-if(dojo.lang.isString(_418)){
-return _418=="";
-}else{
-return _418.isCollapsed;
-}
-}
-}
-};
-dojo.html.getEventTarget=function(evt){
-if(!evt){
-evt=window.event||{};
-}
-var t=(evt.srcElement?evt.srcElement:(evt.target?evt.target:null));
-while((t)&&(t.nodeType!=1)){
-t=t.parentNode;
-}
-return t;
-};
-dojo.html.getDocumentWidth=function(){
-dojo.deprecated("dojo.html.getDocument*","replaced by dojo.html.getViewport*","0.4");
-return dojo.html.getViewportWidth();
-};
-dojo.html.getDocumentHeight=function(){
-dojo.deprecated("dojo.html.getDocument*","replaced by dojo.html.getViewport*","0.4");
-return dojo.html.getViewportHeight();
-};
-dojo.html.getDocumentSize=function(){
-dojo.deprecated("dojo.html.getDocument*","replaced of dojo.html.getViewport*","0.4");
-return dojo.html.getViewportSize();
-};
-dojo.html.getViewportWidth=function(){
-var w=0;
-if(window.innerWidth){
-w=window.innerWidth;
-}
-if(dojo.exists(document,"documentElement.clientWidth")){
-var w2=document.documentElement.clientWidth;
-if(!w||w2&&w2=left&&_456.x<=_45a&&_456.y>=top&&_456.y<=_458);
-};
-dojo.html.setActiveStyleSheet=function(_45b){
-var i=0,a,els=document.getElementsByTagName("link");
-while(a=els[i++]){
-if(a.getAttribute("rel").indexOf("style")!=-1&&a.getAttribute("title")){
-a.disabled=true;
-if(a.getAttribute("title")==_45b){
-a.disabled=false;
-}
-}
-}
-};
-dojo.html.getActiveStyleSheet=function(){
-var i=0,a,els=document.getElementsByTagName("link");
-while(a=els[i++]){
-if(a.getAttribute("rel").indexOf("style")!=-1&&a.getAttribute("title")&&!a.disabled){
-return a.getAttribute("title");
-}
-}
-return null;
-};
-dojo.html.getPreferredStyleSheet=function(){
-var i=0,a,els=document.getElementsByTagName("link");
-while(a=els[i++]){
-if(a.getAttribute("rel").indexOf("style")!=-1&&a.getAttribute("rel").indexOf("alt")==-1&&a.getAttribute("title")){
-return a.getAttribute("title");
-}
-}
-return null;
-};
-dojo.html.body=function(){
-return document.body||document.getElementsByTagName("body")[0];
-};
-dojo.html.isTag=function(node){
-node=dojo.byId(node);
-if(node&&node.tagName){
-var arr=dojo.lang.map(dojo.lang.toArray(arguments,1),function(a){
-return String(a).toLowerCase();
-});
-return arr[dojo.lang.find(node.tagName.toLowerCase(),arr)]||"";
-}
-return "";
-};
-dojo.html.copyStyle=function(_462,_463){
-if(dojo.lang.isUndefined(_463.style.cssText)){
-_462.setAttribute("style",_463.getAttribute("style"));
-}else{
-_462.style.cssText=_463.style.cssText;
-}
-dojo.html.addClass(_462,dojo.html.getClass(_463));
-};
-dojo.html._callExtrasDeprecated=function(_464,args){
-var _466="dojo.html.extras";
-dojo.deprecated("dojo.html."+_464,"moved to "+_466,"0.4");
-dojo["require"](_466);
-return dojo.html[_464].apply(dojo.html,args);
-};
-dojo.html.createNodesFromText=function(){
-return dojo.html._callExtrasDeprecated("createNodesFromText",arguments);
-};
-dojo.html.gravity=function(){
-return dojo.html._callExtrasDeprecated("gravity",arguments);
-};
-dojo.html.placeOnScreen=function(){
-return dojo.html._callExtrasDeprecated("placeOnScreen",arguments);
-};
-dojo.html.placeOnScreenPoint=function(){
-return dojo.html._callExtrasDeprecated("placeOnScreenPoint",arguments);
-};
-dojo.html.renderedTextContent=function(){
-return dojo.html._callExtrasDeprecated("renderedTextContent",arguments);
-};
-dojo.html.BackgroundIframe=function(){
-return dojo.html._callExtrasDeprecated("BackgroundIframe",arguments);
-};
-dojo.provide("dojo.lfx.html");
-dojo.require("dojo.lfx.Animation");
-dojo.require("dojo.html");
-dojo.lfx.html._byId=function(_467){
-if(!_467){
-return [];
-}
-if(dojo.lang.isArray(_467)){
-if(!_467.alreadyChecked){
-var n=[];
-dojo.lang.forEach(_467,function(node){
-n.push(dojo.byId(node));
-});
-n.alreadyChecked=true;
-return n;
-}else{
-return _467;
-}
-}else{
-var n=[];
-n.push(dojo.byId(_467));
-n.alreadyChecked=true;
-return n;
-}
-};
-dojo.lfx.html.propertyAnimation=function(_46a,_46b,_46c,_46d){
-_46a=dojo.lfx.html._byId(_46a);
-if(_46a.length==1){
-dojo.lang.forEach(_46b,function(prop){
-if(typeof prop["start"]=="undefined"){
-if(prop.property!="opacity"){
-prop.start=parseInt(dojo.style.getComputedStyle(_46a[0],prop.property));
-}else{
-prop.start=dojo.style.getOpacity(_46a[0]);
-}
-}
-});
-}
-var _46f=function(_470){
-var _471=new Array(_470.length);
-for(var i=0;i<_470.length;i++){
-_471[i]=Math.round(_470[i]);
-}
-return _471;
-};
-var _473=function(n,_475){
-n=dojo.byId(n);
-if(!n||!n.style){
-return;
-}
-for(var s in _475){
-if(s=="opacity"){
-dojo.style.setOpacity(n,_475[s]);
-}else{
-n.style[s]=_475[s];
-}
-}
-};
-var _477=function(_478){
-this._properties=_478;
-this.diffs=new Array(_478.length);
-dojo.lang.forEach(_478,function(prop,i){
-if(dojo.lang.isArray(prop.start)){
-this.diffs[i]=null;
-}else{
-if(prop.start instanceof dojo.graphics.color.Color){
-prop.startRgb=prop.start.toRgb();
-prop.endRgb=prop.end.toRgb();
-}else{
-this.diffs[i]=prop.end-prop.start;
-}
-}
-},this);
-this.getValue=function(n){
-var ret={};
-dojo.lang.forEach(this._properties,function(prop,i){
-var _47f=null;
-if(dojo.lang.isArray(prop.start)){
-}else{
-if(prop.start instanceof dojo.graphics.color.Color){
-_47f=(prop.units||"rgb")+"(";
-for(var j=0;j1){
-return dojo.lfx.combine(_4a2);
-}else{
-return _4a2[0];
-}
-};
-dojo.lfx.html.wipeOut=function(_4a7,_4a8,_4a9,_4aa){
-_4a7=dojo.lfx.html._byId(_4a7);
-var _4ab=[];
-dojo.lang.forEach(_4a7,function(node){
-var _4ad=dojo.style.getStyle(node,"overflow");
-if(_4ad=="visible"){
-node.style.overflow="hidden";
-}
-dojo.style.show(node);
-var anim=dojo.lfx.propertyAnimation(node,[{property:"height",start:dojo.style.getContentBoxHeight(node),end:0}],_4a8,_4a9);
-var _4af=(anim["onEnd"])?dojo.lang.hitch(anim,"onEnd"):function(){
-};
-anim.onEnd=function(){
-_4af();
-dojo.style.hide(node);
-node.style.overflow=_4ad;
-if(_4aa){
-_4aa(node,anim);
-}
-};
-_4ab.push(anim);
-});
-if(_4a7.length>1){
-return dojo.lfx.combine(_4ab);
-}else{
-return _4ab[0];
-}
-};
-dojo.lfx.html.slideTo=function(_4b0,_4b1,_4b2,_4b3,_4b4){
-_4b0=dojo.lfx.html._byId(_4b0);
-var _4b5=[];
-dojo.lang.forEach(_4b0,function(node){
-var top=null;
-var left=null;
-var init=(function(){
-var _4ba=node;
-return function(){
-top=_4ba.offsetTop;
-left=_4ba.offsetLeft;
-if(!dojo.style.isPositionAbsolute(_4ba)){
-var ret=dojo.style.abs(_4ba,true);
-dojo.style.setStyleAttributes(_4ba,"position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
-top=ret.y;
-left=ret.x;
-}
-};
-})();
-init();
-var anim=dojo.lfx.propertyAnimation(node,[{property:"top",start:top,end:_4b1[0]},{property:"left",start:left,end:_4b1[1]}],_4b2,_4b3);
-var _4bd=(anim["beforeBegin"])?dojo.lang.hitch(anim,"beforeBegin"):function(){
-};
-anim.beforeBegin=function(){
-_4bd();
-init();
-};
-if(_4b4){
-var _4be=(anim["onEnd"])?dojo.lang.hitch(anim,"onEnd"):function(){
-};
-anim.onEnd=function(){
-_4be();
-_4b4(_4b0,anim);
-};
-}
-_4b5.push(anim);
-});
-if(_4b0.length>1){
-return dojo.lfx.combine(_4b5);
-}else{
-return _4b5[0];
-}
-};
-dojo.lfx.html.slideBy=function(_4bf,_4c0,_4c1,_4c2,_4c3){
-_4bf=dojo.lfx.html._byId(_4bf);
-var _4c4=[];
-dojo.lang.forEach(_4bf,function(node){
-var top=null;
-var left=null;
-var init=(function(){
-var _4c9=node;
-return function(){
-top=node.offsetTop;
-left=node.offsetLeft;
-if(!dojo.style.isPositionAbsolute(_4c9)){
-var ret=dojo.style.abs(_4c9);
-dojo.style.setStyleAttributes(_4c9,"position:absolute;top:"+ret.y+"px;left:"+ret.x+"px;");
-top=ret.y;
-left=ret.x;
-}
-};
-})();
-init();
-var anim=dojo.lfx.propertyAnimation(node,[{property:"top",start:top,end:top+_4c0[0]},{property:"left",start:left,end:left+_4c0[1]}],_4c1,_4c2);
-var _4cc=(anim["beforeBegin"])?dojo.lang.hitch(anim,"beforeBegin"):function(){
-};
-anim.beforeBegin=function(){
-_4cc();
-init();
-};
-if(_4c3){
-var _4cd=(anim["onEnd"])?dojo.lang.hitch(anim,"onEnd"):function(){
-};
-anim.onEnd=function(){
-_4cd();
-_4c3(_4bf,anim);
-};
-}
-_4c4.push(anim);
-});
-if(_4bf.length>1){
-return dojo.lfx.combine(_4c4);
-}else{
-return _4c4[0];
-}
-};
-dojo.lfx.html.explode=function(_4ce,_4cf,_4d0,_4d1,_4d2){
-_4ce=dojo.byId(_4ce);
-_4cf=dojo.byId(_4cf);
-var _4d3=dojo.style.toCoordinateArray(_4ce,true);
-var _4d4=document.createElement("div");
-dojo.html.copyStyle(_4d4,_4cf);
-with(_4d4.style){
-position="absolute";
-display="none";
-}
-document.body.appendChild(_4d4);
-with(_4cf.style){
-visibility="hidden";
-display="block";
-}
-var _4d5=dojo.style.toCoordinateArray(_4cf,true);
-with(_4cf.style){
-display="none";
-visibility="visible";
-}
-var anim=new dojo.lfx.propertyAnimation(_4d4,[{property:"height",start:_4d3[3],end:_4d5[3]},{property:"width",start:_4d3[2],end:_4d5[2]},{property:"top",start:_4d3[1],end:_4d5[1]},{property:"left",start:_4d3[0],end:_4d5[0]},{property:"opacity",start:0.3,end:1}],_4d0,_4d1);
-anim.beforeBegin=function(){
-dojo.style.setDisplay(_4d4,"block");
-};
-anim.onEnd=function(){
-dojo.style.setDisplay(_4cf,"block");
-_4d4.parentNode.removeChild(_4d4);
-};
-if(_4d2){
-var _4d7=(anim["onEnd"])?dojo.lang.hitch(anim,"onEnd"):function(){
-};
-anim.onEnd=function(){
-_4d7();
-_4d2(_4cf,anim);
-};
-}
-return anim;
-};
-dojo.lfx.html.implode=function(_4d8,end,_4da,_4db,_4dc){
-_4d8=dojo.byId(_4d8);
-end=dojo.byId(end);
-var _4dd=dojo.style.toCoordinateArray(_4d8,true);
-var _4de=dojo.style.toCoordinateArray(end,true);
-var _4df=document.createElement("div");
-dojo.html.copyStyle(_4df,_4d8);
-dojo.style.setOpacity(_4df,0.3);
-with(_4df.style){
-position="absolute";
-display="none";
-}
-document.body.appendChild(_4df);
-var anim=new dojo.lfx.propertyAnimation(_4df,[{property:"height",start:_4dd[3],end:_4de[3]},{property:"width",start:_4dd[2],end:_4de[2]},{property:"top",start:_4dd[1],end:_4de[1]},{property:"left",start:_4dd[0],end:_4de[0]},{property:"opacity",start:1,end:0.3}],_4da,_4db);
-anim.beforeBegin=function(){
-dojo.style.hide(_4d8);
-dojo.style.show(_4df);
-};
-anim.onEnd=function(){
-_4df.parentNode.removeChild(_4df);
-};
-if(_4dc){
-var _4e1=(anim["onEnd"])?dojo.lang.hitch(anim,"onEnd"):function(){
-};
-anim.onEnd=function(){
-_4e1();
-_4dc(_4d8,anim);
-};
-}
-return anim;
-};
-dojo.lfx.html.highlight=function(_4e2,_4e3,_4e4,_4e5,_4e6){
-_4e2=dojo.lfx.html._byId(_4e2);
-var _4e7=[];
-dojo.lang.forEach(_4e2,function(node){
-var _4e9=dojo.style.getBackgroundColor(node);
-var bg=dojo.style.getStyle(node,"background-color").toLowerCase();
-var _4eb=dojo.style.getStyle(node,"background-image");
-var _4ec=(bg=="transparent"||bg=="rgba(0, 0, 0, 0)");
-while(_4e9.length>3){
-_4e9.pop();
-}
-var rgb=new dojo.graphics.color.Color(_4e3);
-var _4ee=new dojo.graphics.color.Color(_4e9);
-var anim=dojo.lfx.propertyAnimation(node,[{property:"background-color",start:rgb,end:_4ee}],_4e4,_4e5);
-var _4f0=(anim["beforeBegin"])?dojo.lang.hitch(anim,"beforeBegin"):function(){
-};
-anim.beforeBegin=function(){
-_4f0();
-if(_4eb){
-node.style.backgroundImage="none";
-}
-node.style.backgroundColor="rgb("+rgb.toRgb().join(",")+")";
-};
-var _4f1=(anim["onEnd"])?dojo.lang.hitch(anim,"onEnd"):function(){
-};
-anim.onEnd=function(){
-_4f1();
-if(_4eb){
-node.style.backgroundImage=_4eb;
-}
-if(_4ec){
-node.style.backgroundColor="transparent";
-}
-if(_4e6){
-_4e6(node,anim);
-}
-};
-_4e7.push(anim);
-});
-if(_4e2.length>1){
-return dojo.lfx.combine(_4e7);
-}else{
-return _4e7[0];
-}
-};
-dojo.lfx.html.unhighlight=function(_4f2,_4f3,_4f4,_4f5,_4f6){
-_4f2=dojo.lfx.html._byId(_4f2);
-var _4f7=[];
-dojo.lang.forEach(_4f2,function(node){
-var _4f9=new dojo.graphics.color.Color(dojo.style.getBackgroundColor(node));
-var rgb=new dojo.graphics.color.Color(_4f3);
-var _4fb=dojo.style.getStyle(node,"background-image");
-var anim=dojo.lfx.propertyAnimation(node,[{property:"background-color",start:_4f9,end:rgb}],_4f4,_4f5);
-var _4fd=(anim["beforeBegin"])?dojo.lang.hitch(anim,"beforeBegin"):function(){
-};
-anim.beforeBegin=function(){
-_4fd();
-if(_4fb){
-node.style.backgroundImage="none";
-}
-node.style.backgroundColor="rgb("+_4f9.toRgb().join(",")+")";
-};
-var _4fe=(anim["onEnd"])?dojo.lang.hitch(anim,"onEnd"):function(){
-};
-anim.onEnd=function(){
-_4fe();
-if(_4f6){
-_4f6(node,anim);
-}
-};
-_4f7.push(anim);
-});
-if(_4f2.length>1){
-return dojo.lfx.combine(_4f7);
-}else{
-return _4f7[0];
-}
-};
-dojo.lang.mixin(dojo.lfx,dojo.lfx.html);
-dojo.kwCompoundRequire({browser:["dojo.lfx.html"],dashboard:["dojo.lfx.html"]});
-dojo.provide("dojo.lfx.*");
-
diff --git a/source/web/scripts/ajax/src/AdapterRegistry.js b/source/web/scripts/ajax/src/AdapterRegistry.js
new file mode 100644
index 0000000000..8e1e281724
--- /dev/null
+++ b/source/web/scripts/ajax/src/AdapterRegistry.js
@@ -0,0 +1,79 @@
+dojo.provide("dojo.AdapterRegistry");
+dojo.require("dojo.lang.func");
+
+dojo.AdapterRegistry = function(/*boolean, optional*/returnWrappers){
+ // summary:
+ // A registry to make contextual calling/searching easier.
+ // description:
+ // Objects of this class keep list of arrays in the form [name, check,
+ // wrap, directReturn] that are used to determine what the contextual
+ // result of a set of checked arguments is. All check/wrap functions
+ // in this registry should be of the same arity.
+ this.pairs = [];
+ this.returnWrappers = returnWrappers || false;
+}
+
+dojo.lang.extend(dojo.AdapterRegistry, {
+ register: function( /*string*/ name, /*function*/ check, /*function*/ wrap,
+ /*boolean, optional*/ directReturn,
+ /*boolean, optional*/ override){
+ // summary:
+ // register a check function to determine if the wrap function or
+ // object gets selected
+ // name: a way to identify this matcher.
+ // check:
+ // a function that arguments are passed to from the adapter's
+ // match() function. The check function should return true if the
+ // given arguments are appropriate for the wrap function.
+ // directReturn:
+ // If directReturn is true, the value passed in for wrap will be
+ // returned instead of being called. Alternately, the
+ // AdapterRegistry can be set globally to "return not call" using
+ // the returnWrappers property. Either way, this behavior allows
+ // the registry to act as a "search" function instead of a
+ // function interception library.
+ // override:
+ // If override is given and true, the check function will be given
+ // highest priority. Otherwise, it will be the lowest priority
+ // adapter.
+
+ var type = (override) ? "unshift" : "push";
+ this.pairs[type]([name, check, wrap, directReturn]);
+ },
+
+ match: function(/* ... */){
+ // summary:
+ // Find an adapter for the given arguments. If no suitable adapter
+ // is found, throws an exception. match() accepts any number of
+ // arguments, all of which are passed to all matching functions
+ // from the registered pairs.
+ for(var i = 0; i < this.pairs.length; i++){
+ var pair = this.pairs[i];
+ if(pair[1].apply(this, arguments)){
+ if((pair[3])||(this.returnWrappers)){
+ return pair[2];
+ }else{
+ return pair[2].apply(this, arguments);
+ }
+ }
+ }
+ throw new Error("No match found");
+ // dojo.raise("No match found");
+ },
+
+ unregister: function(name){
+ // summary: Remove a named adapter from the registry
+
+ // FIXME: this is kind of a dumb way to handle this. On a large
+ // registry this will be slow-ish and we can use the name as a lookup
+ // should we choose to trade memory for speed.
+ for(var i = 0; i < this.pairs.length; i++){
+ var pair = this.pairs[i];
+ if(pair[0] == name){
+ this.pairs.splice(i, 1);
+ return true;
+ }
+ }
+ return false;
+ }
+});
diff --git a/source/web/scripts/ajax/src/Deferred.js b/source/web/scripts/ajax/src/Deferred.js
new file mode 100644
index 0000000000..6f99fe8767
--- /dev/null
+++ b/source/web/scripts/ajax/src/Deferred.js
@@ -0,0 +1,305 @@
+dojo.provide("dojo.Deferred");
+dojo.require("dojo.lang.func");
+
+dojo.Deferred = function(/* optional */ canceller){
+ /*
+ NOTE: this namespace and documentation are imported wholesale
+ from MochiKit
+
+ Encapsulates a sequence of callbacks in response to a value that
+ may not yet be available. This is modeled after the Deferred class
+ from Twisted .
+
+ Why do we want this? JavaScript has no threads, and even if it did,
+ threads are hard. Deferreds are a way of abstracting non-blocking
+ events, such as the final response to an XMLHttpRequest.
+
+ The sequence of callbacks is internally represented as a list
+ of 2-tuples containing the callback/errback pair. For example,
+ the following call sequence::
+
+ var d = new Deferred();
+ d.addCallback(myCallback);
+ d.addErrback(myErrback);
+ d.addBoth(myBoth);
+ d.addCallbacks(myCallback, myErrback);
+
+ is translated into a Deferred with the following internal
+ representation::
+
+ [
+ [myCallback, null],
+ [null, myErrback],
+ [myBoth, myBoth],
+ [myCallback, myErrback]
+ ]
+
+ The Deferred also keeps track of its current status (fired).
+ Its status may be one of three things:
+
+ -1: no value yet (initial condition)
+ 0: success
+ 1: error
+
+ A Deferred will be in the error state if one of the following
+ three conditions are met:
+
+ 1. The result given to callback or errback is "instanceof" Error
+ 2. The previous callback or errback raised an exception while
+ executing
+ 3. The previous callback or errback returned a value "instanceof"
+ Error
+
+ Otherwise, the Deferred will be in the success state. The state of
+ the Deferred determines the next element in the callback sequence to
+ run.
+
+ When a callback or errback occurs with the example deferred chain,
+ something equivalent to the following will happen (imagine that
+ exceptions are caught and returned)::
+
+ // d.callback(result) or d.errback(result)
+ if(!(result instanceof Error)){
+ result = myCallback(result);
+ }
+ if(result instanceof Error){
+ result = myErrback(result);
+ }
+ result = myBoth(result);
+ if(result instanceof Error){
+ result = myErrback(result);
+ }else{
+ result = myCallback(result);
+ }
+
+ The result is then stored away in case another step is added to the
+ callback sequence. Since the Deferred already has a value available,
+ any new callbacks added will be called immediately.
+
+ There are two other "advanced" details about this implementation that
+ are useful:
+
+ Callbacks are allowed to return Deferred instances themselves, so you
+ can build complicated sequences of events with ease.
+
+ The creator of the Deferred may specify a canceller. The canceller
+ is a function that will be called if Deferred.cancel is called before
+ the Deferred fires. You can use this to implement clean aborting of
+ an XMLHttpRequest, etc. Note that cancel will fire the deferred with
+ a CancelledError (unless your canceller returns another kind of
+ error), so the errbacks should be prepared to handle that error for
+ cancellable Deferreds.
+
+ */
+
+ this.chain = [];
+ this.id = this._nextId();
+ this.fired = -1;
+ this.paused = 0;
+ this.results = [null, null];
+ this.canceller = canceller;
+ this.silentlyCancelled = false;
+};
+
+dojo.lang.extend(dojo.Deferred, {
+ getFunctionFromArgs: function(){
+ var a = arguments;
+ if((a[0])&&(!a[1])){
+ if(dojo.lang.isFunction(a[0])){
+ return a[0];
+ }else if(dojo.lang.isString(a[0])){
+ return dj_global[a[0]];
+ }
+ }else if((a[0])&&(a[1])){
+ return dojo.lang.hitch(a[0], a[1]);
+ }
+ return null;
+ },
+
+ makeCalled: function() {
+ var deferred = new dojo.Deferred();
+ deferred.callback();
+ return deferred;
+ },
+
+ repr: function(){
+ var state;
+ if(this.fired == -1){
+ state = 'unfired';
+ }else if(this.fired == 0){
+ state = 'success';
+ } else {
+ state = 'error';
+ }
+ return 'Deferred(' + this.id + ', ' + state + ')';
+ },
+
+ toString: dojo.lang.forward("repr"),
+
+ _nextId: (function(){
+ var n = 1;
+ return function(){ return n++; };
+ })(),
+
+ cancel: function(){
+ /***
+ Cancels a Deferred that has not yet received a value, or is
+ waiting on another Deferred as its value.
+
+ If a canceller is defined, the canceller is called. If the
+ canceller did not return an error, or there was no canceller,
+ then the errback chain is started with CancelledError.
+ ***/
+ if(this.fired == -1){
+ if (this.canceller){
+ this.canceller(this);
+ }else{
+ this.silentlyCancelled = true;
+ }
+ if(this.fired == -1){
+ this.errback(new Error(this.repr()));
+ }
+ }else if( (this.fired == 0)&&
+ (this.results[0] instanceof dojo.Deferred)){
+ this.results[0].cancel();
+ }
+ },
+
+
+ _pause: function(){
+ // Used internally to signal that it's waiting on another Deferred
+ this.paused++;
+ },
+
+ _unpause: function(){
+ // Used internally to signal that it's no longer waiting on
+ // another Deferred.
+ this.paused--;
+ if ((this.paused == 0) && (this.fired >= 0)) {
+ this._fire();
+ }
+ },
+
+ _continue: function(res){
+ // Used internally when a dependent deferred fires.
+ this._resback(res);
+ this._unpause();
+ },
+
+ _resback: function(res){
+ // The primitive that means either callback or errback
+ this.fired = ((res instanceof Error) ? 1 : 0);
+ this.results[this.fired] = res;
+ this._fire();
+ },
+
+ _check: function(){
+ if(this.fired != -1){
+ if(!this.silentlyCancelled){
+ dojo.raise("already called!");
+ }
+ this.silentlyCancelled = false;
+ return;
+ }
+ },
+
+ callback: function(res){
+ /*
+ Begin the callback sequence with a non-error value.
+
+ callback or errback should only be called once on a given
+ Deferred.
+ */
+ this._check();
+ this._resback(res);
+ },
+
+ errback: function(res){
+ // Begin the callback sequence with an error result.
+ this._check();
+ if(!(res instanceof Error)){
+ res = new Error(res);
+ }
+ this._resback(res);
+ },
+
+ addBoth: function(cb, cbfn){
+ /*
+ Add the same function as both a callback and an errback as the
+ next element on the callback sequence. This is useful for code
+ that you want to guarantee to run, e.g. a finalizer.
+ */
+ var enclosed = this.getFunctionFromArgs(cb, cbfn);
+ if(arguments.length > 2){
+ enclosed = dojo.lang.curryArguments(null, enclosed, arguments, 2);
+ }
+ return this.addCallbacks(enclosed, enclosed);
+ },
+
+ addCallback: function(cb, cbfn){
+ // Add a single callback to the end of the callback sequence.
+ var enclosed = this.getFunctionFromArgs(cb, cbfn);
+ if(arguments.length > 2){
+ enclosed = dojo.lang.curryArguments(null, enclosed, arguments, 2);
+ }
+ return this.addCallbacks(enclosed, null);
+ },
+
+ addErrback: function(cb, cbfn){
+ // Add a single callback to the end of the callback sequence.
+ var enclosed = this.getFunctionFromArgs(cb, cbfn);
+ if(arguments.length > 2){
+ enclosed = dojo.lang.curryArguments(null, enclosed, arguments, 2);
+ }
+ return this.addCallbacks(null, enclosed);
+ return this.addCallbacks(null, cbfn);
+ },
+
+ addCallbacks: function (cb, eb) {
+ // Add separate callback and errback to the end of the callback
+ // sequence.
+ this.chain.push([cb, eb])
+ if (this.fired >= 0) {
+ this._fire();
+ }
+ return this;
+ },
+
+ _fire: function(){
+ // Used internally to exhaust the callback sequence when a result
+ // is available.
+ var chain = this.chain;
+ var fired = this.fired;
+ var res = this.results[fired];
+ var self = this;
+ var cb = null;
+ while (chain.length > 0 && this.paused == 0) {
+ // Array
+ var pair = chain.shift();
+ var f = pair[fired];
+ if (f == null) {
+ continue;
+ }
+ try {
+ res = f(res);
+ fired = ((res instanceof Error) ? 1 : 0);
+ if(res instanceof dojo.Deferred) {
+ cb = function(res){
+ self._continue(res);
+ }
+ this._pause();
+ }
+ }catch(err){
+ fired = 1;
+ res = err;
+ }
+ }
+ this.fired = fired;
+ this.results[fired] = res;
+ if((cb)&&(this.paused)){
+ // this is for "tail recursion" in case the dependent
+ // deferred is already fired
+ res.addBoth(cb);
+ }
+ }
+});
diff --git a/source/web/scripts/ajax/src/DeferredList.js b/source/web/scripts/ajax/src/DeferredList.js
new file mode 100644
index 0000000000..0905e53bfb
--- /dev/null
+++ b/source/web/scripts/ajax/src/DeferredList.js
@@ -0,0 +1,78 @@
+dojo.require("dojo.Deferred");
+
+dojo.provide("dojo.DeferredList");
+
+
+dojo.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) {
+ this.list = list;
+ this.resultList = new Array(this.list.length);
+
+ // Deferred init
+ this.chain = [];
+ this.id = this._nextId();
+ this.fired = -1;
+ this.paused = 0;
+ this.results = [null, null];
+ this.canceller = canceller;
+ this.silentlyCancelled = false;
+
+ if (this.list.length === 0 && !fireOnOneCallback) {
+ this.callback(this.resultList);
+ }
+
+ this.finishedCount = 0;
+ this.fireOnOneCallback = fireOnOneCallback;
+ this.fireOnOneErrback = fireOnOneErrback;
+ this.consumeErrors = consumeErrors;
+
+ var index = 0;
+
+ var _this = this;
+
+ dojo.lang.forEach(this.list, function(d) {
+ var _index = index;
+ //dojo.debug("add cb/errb index "+_index);
+ d.addCallback(function(r) { _this._cbDeferred(_index, true, r) });
+ d.addErrback(function(r) { _this._cbDeferred(_index, false, r) });
+ index++;
+ });
+
+};
+
+
+dojo.inherits(dojo.DeferredList, dojo.Deferred);
+
+dojo.lang.extend(dojo.DeferredList, {
+
+ _cbDeferred: function (index, succeeded, result) {
+ //dojo.debug("Fire "+index+" succ "+succeeded+" res "+result);
+ this.resultList[index] = [succeeded, result];
+ this.finishedCount += 1;
+ if (this.fired !== 0) {
+ if (succeeded && this.fireOnOneCallback) {
+ this.callback([index, result]);
+ } else if (!succeeded && this.fireOnOneErrback) {
+ this.errback(result);
+ } else if (this.finishedCount == this.list.length) {
+ this.callback(this.resultList);
+ }
+ }
+ if (!succeeded && this.consumeErrors) {
+ result = null;
+ }
+ return result;
+ },
+
+ gatherResults: function (deferredList) {
+ var d = new dojo.DeferredList(deferredList, false, true, false);
+ d.addCallback(function (results) {
+ var ret = [];
+ for (var i = 0; i < results.length; i++) {
+ ret.push(results[i][1]);
+ }
+ return ret;
+ });
+ return d;
+ }
+});
+
diff --git a/source/web/scripts/ajax/src/animation.js b/source/web/scripts/ajax/src/animation.js
new file mode 100644
index 0000000000..5755dc8f0a
--- /dev/null
+++ b/source/web/scripts/ajax/src/animation.js
@@ -0,0 +1,2 @@
+dojo.provide("dojo.animation");
+dojo.require("dojo.animation.Animation");
diff --git a/source/web/scripts/ajax/src/animation/Animation.js b/source/web/scripts/ajax/src/animation/Animation.js
new file mode 100644
index 0000000000..278bb6f4ba
--- /dev/null
+++ b/source/web/scripts/ajax/src/animation/Animation.js
@@ -0,0 +1,233 @@
+dojo.provide("dojo.animation.Animation");
+dojo.require("dojo.animation.AnimationEvent");
+
+dojo.require("dojo.lang.func");
+dojo.require("dojo.math");
+dojo.require("dojo.math.curves");
+
+/*
+Animation package based off of Dan Pupius' work on Animations:
+http://pupius.co.uk/js/Toolkit.Drawing.js
+*/
+
+dojo.animation.Animation = function(/*dojo.math.curves.* */ curve, /*int*/ duration, /*Decimal?*/ accel, /*int?*/ repeatCount, /*int?*/ rate) {
+ // summary: Animation object iterates a set of numbers over a curve for a given amount of time, calling 'onAnimate' at each step.
+ // curve: Curve to animate over.
+ // duration: Duration of the animation, in milliseconds.
+ // accel: Either an integer or curve representing amount of acceleration. (?) Default is linear acceleration.
+ // repeatCount: Number of times to repeat the animation. Default is 0.
+ // rate: Time between animation steps, in milliseconds. Default is 25.
+ // description: Calls the following events: "onBegin", "onAnimate", "onEnd", "onPlay", "onPause", "onStop"
+ // If the animation implements a "handler" function, that will be called before each event is called.
+
+ if(dojo.lang.isArray(curve)) {
+ // curve: Array
+ // id: i
+ curve = new dojo.math.curves.Line(curve[0], curve[1]);
+ }
+ this.curve = curve;
+ this.duration = duration;
+ this.repeatCount = repeatCount || 0;
+ this.rate = rate || 25;
+ if(accel) {
+ // accel: Decimal
+ // id: j
+ if(dojo.lang.isFunction(accel.getValue)) {
+ // accel: dojo.math.curves.CatmullRom
+ // id: k
+ this.accel = accel;
+ } else {
+ var i = 0.35*accel+0.5; // 0.15 <= i <= 0.85
+ this.accel = new dojo.math.curves.CatmullRom([[0], [i], [1]], 0.45);
+ }
+ }
+}
+
+dojo.lang.extend(dojo.animation.Animation, {
+ // public properties
+ curve: null,
+ duration: 0,
+ repeatCount: 0,
+ accel: null,
+
+ // events
+ onBegin: null,
+ onAnimate: null,
+ onEnd: null,
+ onPlay: null,
+ onPause: null,
+ onStop: null,
+ handler: null,
+
+ // "private" properties
+ _animSequence: null,
+ _startTime: null,
+ _endTime: null,
+ _lastFrame: null,
+ _timer: null,
+ _percent: 0,
+ _active: false,
+ _paused: false,
+ _startRepeatCount: 0,
+
+ // public methods
+ play: function(/*Boolean?*/ gotoStart) {
+ // summary: Play the animation.
+ // goToStart: If true, will restart the animation from the beginning.
+ // Otherwise, starts from current play counter.
+ // description: Sends an "onPlay" event to any observers.
+ // Also sends an "onBegin" event if starting from the beginning.
+ if( gotoStart ) {
+ clearTimeout(this._timer);
+ this._active = false;
+ this._paused = false;
+ this._percent = 0;
+ } else if( this._active && !this._paused ) {
+ return;
+ }
+
+ this._startTime = new Date().valueOf();
+ if( this._paused ) {
+ this._startTime -= (this.duration * this._percent / 100);
+ }
+ this._endTime = this._startTime + this.duration;
+ this._lastFrame = this._startTime;
+
+ var e = new dojo.animation.AnimationEvent(this, null, this.curve.getValue(this._percent),
+ this._startTime, this._startTime, this._endTime, this.duration, this._percent, 0);
+
+ this._active = true;
+ this._paused = false;
+
+ if( this._percent == 0 ) {
+ if(!this._startRepeatCount) {
+ this._startRepeatCount = this.repeatCount;
+ }
+ e.type = "begin";
+ if(typeof this.handler == "function") { this.handler(e); }
+ if(typeof this.onBegin == "function") { this.onBegin(e); }
+ }
+
+ e.type = "play";
+ if(typeof this.handler == "function") { this.handler(e); }
+ if(typeof this.onPlay == "function") { this.onPlay(e); }
+
+ if(this._animSequence) { this._animSequence._setCurrent(this); }
+
+ this._cycle();
+ },
+
+ pause: function() {
+ // summary: Temporarily stop the animation, leaving the play counter at the current location.
+ // Resume later with sequence.play()
+ // description: Sends an "onPause" AnimationEvent to any observers.
+ clearTimeout(this._timer);
+ if( !this._active ) { return; }
+ this._paused = true;
+ var e = new dojo.animation.AnimationEvent(this, "pause", this.curve.getValue(this._percent),
+ this._startTime, new Date().valueOf(), this._endTime, this.duration, this._percent, 0);
+ if(typeof this.handler == "function") { this.handler(e); }
+ if(typeof this.onPause == "function") { this.onPause(e); }
+ },
+
+ playPause: function() {
+ // summary: Toggle between play and paused states.
+ if( !this._active || this._paused ) {
+ this.play();
+ } else {
+ this.pause();
+ }
+ },
+
+ gotoPercent: function(/*int*/ pct, /*Boolean*/ andPlay) {
+ // summary: Set the play counter at a certain point in the animation.
+ // pct: Point to set the play counter to, expressed as a percentage (0 to 100).
+ // andPlay: If true, will start the animation at the counter automatically.
+ clearTimeout(this._timer);
+ this._active = true;
+ this._paused = true;
+ this._percent = pct;
+ if( andPlay ) { this.play(); }
+ },
+
+ stop: function(/*Boolean?*/ gotoEnd) {
+ // summary: Stop the animation.
+ // gotoEnd: If true, will advance play counter to the end before sending the event.
+ // description: Sends an "onStop" AnimationEvent to any observers.
+ clearTimeout(this._timer);
+ var step = this._percent / 100;
+ if( gotoEnd ) {
+ step = 1;
+ }
+ var e = new dojo.animation.AnimationEvent(this, "stop", this.curve.getValue(step),
+ this._startTime, new Date().valueOf(), this._endTime, this.duration, this._percent);
+ if(typeof this.handler == "function") { this.handler(e); }
+ if(typeof this.onStop == "function") { this.onStop(e); }
+ this._active = false;
+ this._paused = false;
+ },
+
+ status: function() {
+ // summary: Return the status of the animation.
+ // description: Returns one of "playing", "paused" or "stopped".
+ if( this._active ) {
+ return this._paused ? "paused" : "playing"; /* String */
+ } else {
+ return "stopped"; /* String */
+ }
+ },
+
+ // "private" methods
+ _cycle: function() {
+ // summary: Perform once 'cycle' or step of the animation.
+ clearTimeout(this._timer);
+ if( this._active ) {
+ var curr = new Date().valueOf();
+ var step = (curr - this._startTime) / (this._endTime - this._startTime);
+ var fps = 1000 / (curr - this._lastFrame);
+ this._lastFrame = curr;
+
+ if( step >= 1 ) {
+ step = 1;
+ this._percent = 100;
+ } else {
+ this._percent = step * 100;
+ }
+
+ // Perform accelleration
+ if(this.accel && this.accel.getValue) {
+ step = this.accel.getValue(step);
+ }
+
+ var e = new dojo.animation.AnimationEvent(this, "animate", this.curve.getValue(step),
+ this._startTime, curr, this._endTime, this.duration, this._percent, Math.round(fps));
+
+ if(typeof this.handler == "function") { this.handler(e); }
+ if(typeof this.onAnimate == "function") { this.onAnimate(e); }
+
+ if( step < 1 ) {
+ this._timer = setTimeout(dojo.lang.hitch(this, "_cycle"), this.rate);
+ } else {
+ e.type = "end";
+ this._active = false;
+ if(typeof this.handler == "function") { this.handler(e); }
+ if(typeof this.onEnd == "function") { this.onEnd(e); }
+
+ if( this.repeatCount > 0 ) {
+ this.repeatCount--;
+ this.play(true);
+ } else if( this.repeatCount == -1 ) {
+ this.play(true);
+ } else {
+ if(this._startRepeatCount) {
+ this.repeatCount = this._startRepeatCount;
+ this._startRepeatCount = 0;
+ }
+ if( this._animSequence ) {
+ this._animSequence._playNext();
+ }
+ }
+ }
+ }
+ }
+});
diff --git a/source/web/scripts/ajax/src/animation/AnimationEvent.js b/source/web/scripts/ajax/src/animation/AnimationEvent.js
new file mode 100644
index 0000000000..fa8086da89
--- /dev/null
+++ b/source/web/scripts/ajax/src/animation/AnimationEvent.js
@@ -0,0 +1,53 @@
+dojo.provide("dojo.animation.AnimationEvent");
+
+dojo.require("dojo.lang");
+
+dojo.animation.AnimationEvent = function(
+ /*dojo.animation.Animation*/ animation,
+ /*String*/type,
+ /*int[] */ coords,
+ /*int*/ startTime,
+ /*int*/ currentTime,
+ /*int*/ endTime,
+ /*int*/ duration,
+ /*int*/ percent,
+ /*int?*/ fps) {
+ // summary: Event sent at various points during an Animation.
+ // animation: Animation throwing the event.
+ // type: One of: "animate", "begin", "end", "play", "pause" or "stop".
+ // coords: Current coordinates of the animation.
+ // startTime: Time the animation was started, as milliseconds.
+ // currentTime: Time the event was thrown, as milliseconds.
+ // endTime: Time the animation is expected to complete, as milliseconds.
+ // duration: Duration of the animation, in milliseconds.
+ // percent: Percent of the animation that has completed, between 0 and 100.
+ // fps: Frames currently shown per second. (Only sent for "animate" event).
+ // description: The AnimationEvent has public properties of the same name as
+ // all constructor arguments, plus "x", "y" and "z".
+
+ this.type = type; // "animate", "begin", "end", "play", "pause", "stop"
+ this.animation = animation;
+
+ this.coords = coords;
+ this.x = coords[0];
+ this.y = coords[1];
+ this.z = coords[2];
+
+ this.startTime = startTime;
+ this.currentTime = currentTime;
+ this.endTime = endTime;
+
+ this.duration = duration;
+ this.percent = percent;
+ this.fps = fps;
+};
+dojo.lang.extend(dojo.animation.AnimationEvent, {
+ coordsAsInts: function() {
+ // summary: Coerce the coordinates into integers.
+ var cints = new Array(this.coords.length);
+ for(var i = 0; i < this.coords.length; i++) {
+ cints[i] = Math.round(this.coords[i]);
+ }
+ return cints;
+ }
+});
diff --git a/source/web/scripts/ajax/src/animation/AnimationSequence.js b/source/web/scripts/ajax/src/animation/AnimationSequence.js
new file mode 100644
index 0000000000..7ca352f63b
--- /dev/null
+++ b/source/web/scripts/ajax/src/animation/AnimationSequence.js
@@ -0,0 +1,150 @@
+dojo.provide("dojo.animation.AnimationSequence");
+dojo.require("dojo.animation.AnimationEvent");
+dojo.require("dojo.animation.Animation");
+
+dojo.animation.AnimationSequence = function(/*int?*/ repeatCount){
+ // summary: Sequence of Animations, played one after the other.
+ // repeatCount: Number of times to repeat the entire sequence. Default is 0 (play once only).
+ // description: Calls the following events: "onBegin", "onEnd", "onNext"
+ // If the animation implements a "handler" function, that will be called before each event is called.
+ this._anims = [];
+ this.repeatCount = repeatCount || 0;
+}
+
+dojo.lang.extend(dojo.animation.AnimationSequence, {
+ repeatCount: 0,
+
+ _anims: [],
+ _currAnim: -1,
+
+ onBegin: null,
+ onEnd: null,
+ onNext: null,
+ handler: null,
+
+ add: function() {
+ // summary: Add one or more Animations to the sequence.
+ // description: args: Animations (dojo.animation.Animation) to add to the sequence.
+ for(var i = 0; i < arguments.length; i++) {
+ this._anims.push(arguments[i]);
+ arguments[i]._animSequence = this;
+ }
+ },
+
+ remove: function(/*dojo.animation.Animation*/ anim) {
+ // summary: Remove one particular animation from the sequence.
+ // amim: Animation to remove.
+ for(var i = 0; i < this._anims.length; i++) {
+ if( this._anims[i] == anim ) {
+ this._anims[i]._animSequence = null;
+ this._anims.splice(i, 1);
+ break;
+ }
+ }
+ },
+
+ removeAll: function() {
+ // summary: Remove all animations from the sequence.
+ for(var i = 0; i < this._anims.length; i++) {
+ this._anims[i]._animSequence = null;
+ }
+ this._anims = [];
+ this._currAnim = -1;
+ },
+
+ clear: function() {
+ // summary: Remove all animations from the sequence.
+ this.removeAll();
+ },
+
+ play: function(/*Boolean?*/ gotoStart) {
+ // summary: Play the animation sequence.
+ // gotoStart: If true, will start at the beginning of the first sequence.
+ // Otherwise, starts at the current play counter of the current animation.
+ // description: Sends an "onBegin" event to any observers.
+ if( this._anims.length == 0 ) { return; }
+ if( gotoStart || !this._anims[this._currAnim] ) {
+ this._currAnim = 0;
+ }
+ if( this._anims[this._currAnim] ) {
+ if( this._currAnim == 0 ) {
+ var e = {type: "begin", animation: this._anims[this._currAnim]};
+ if(typeof this.handler == "function") { this.handler(e); }
+ if(typeof this.onBegin == "function") { this.onBegin(e); }
+ }
+ this._anims[this._currAnim].play(gotoStart);
+ }
+ },
+
+ pause: function() {
+ // summary: temporarily stop the current animation. Resume later with sequence.play()
+ if( this._anims[this._currAnim] ) {
+ this._anims[this._currAnim].pause();
+ }
+ },
+
+ playPause: function() {
+ // summary: Toggle between play and paused states.
+ if( this._anims.length == 0 ) { return; }
+ if( this._currAnim == -1 ) { this._currAnim = 0; }
+ if( this._anims[this._currAnim] ) {
+ this._anims[this._currAnim].playPause();
+ }
+ },
+
+ stop: function() {
+ // summary: Stop the current animation.
+ if( this._anims[this._currAnim] ) {
+ this._anims[this._currAnim].stop();
+ }
+ },
+
+ status: function() {
+ // summary: Return the status of the current animation.
+ // description: Returns one of "playing", "paused" or "stopped".
+ if( this._anims[this._currAnim] ) {
+ return this._anims[this._currAnim].status();
+ } else {
+ return "stopped";
+ }
+ },
+
+ _setCurrent: function(/*dojo.animation.Animation*/ anim) {
+ // summary: Set the current animation.
+ // anim: Animation to make current, must have already been added to the sequence.
+ for(var i = 0; i < this._anims.length; i++) {
+ if( this._anims[i] == anim ) {
+ this._currAnim = i;
+ break;
+ }
+ }
+ },
+
+ _playNext: function() {
+ // summary: Play the next animation in the sequence.
+ // description: Sends an "onNext" event to any observers.
+ // Also sends "onEnd" if the last animation is finished.
+ if( this._currAnim == -1 || this._anims.length == 0 ) { return; }
+ this._currAnim++;
+ if( this._anims[this._currAnim] ) {
+ var e = {type: "next", animation: this._anims[this._currAnim]};
+ if(typeof this.handler == "function") { this.handler(e); }
+ if(typeof this.onNext == "function") { this.onNext(e); }
+ this._anims[this._currAnim].play(true);
+ } else {
+ var e = {type: "end", animation: this._anims[this._anims.length-1]};
+ if(typeof this.handler == "function") { this.handler(e); }
+ if(typeof this.onEnd == "function") { this.onEnd(e); }
+ if(this.repeatCount > 0) {
+ this._currAnim = 0;
+ this.repeatCount--;
+ this._anims[this._currAnim].play(true);
+ } else if(this.repeatCount == -1) {
+ this._currAnim = 0;
+ this._anims[this._currAnim].play(true);
+ } else {
+ this._currAnim = -1;
+ }
+ }
+ }
+});
diff --git a/source/web/scripts/ajax/src/animation/Timer.js b/source/web/scripts/ajax/src/animation/Timer.js
new file mode 100644
index 0000000000..e0d9330e7e
--- /dev/null
+++ b/source/web/scripts/ajax/src/animation/Timer.js
@@ -0,0 +1,46 @@
+dojo.provide("dojo.animation.Timer");
+dojo.require("dojo.lang.func");
+
+dojo.animation.Timer = function(/*int*/ interval){
+ // summary: Timer object executes an "onTick()" method repeatedly at a specified interval.
+ // repeatedly at a given interval.
+ // interval: Interval between function calls, in milliseconds.
+ this.timer = null;
+ this.isRunning = false;
+ this.interval = interval;
+
+ this.onStart = null;
+ this.onStop = null;
+};
+
+dojo.lang.extend(dojo.animation.Timer, {
+ onTick : function(){
+ // summary: Method called every time the interval passes. Override to do something useful.
+ },
+
+ setInterval : function(interval){
+ // summary: Reset the interval of a timer, whether running or not.
+ // interval: New interval, in milliseconds.
+ if (this.isRunning) dj_global.clearInterval(this.timer);
+ this.interval = interval;
+ if (this.isRunning) this.timer = dj_global.setInterval(dojo.lang.hitch(this, "onTick"), this.interval);
+ },
+
+ start : function(){
+ // summary: Start the timer ticking.
+ // description: Calls the "onStart()" handler, if defined.
+ // Note that the onTick() function is not called right away,
+ // only after first interval passes.
+ if (typeof this.onStart == "function") this.onStart();
+ this.isRunning = true;
+ this.timer = dj_global.setInterval(this.onTick, this.interval);
+ },
+
+ stop : function(){
+ // summary: Stop the timer.
+ // description: Calls the "onStop()" handler, if defined.
+ if (typeof this.onStop == "function") this.onStop();
+ this.isRunning = false;
+ dj_global.clearInterval(this.timer);
+ }
+});
diff --git a/source/web/scripts/ajax/src/animation/__package__.js b/source/web/scripts/ajax/src/animation/__package__.js
new file mode 100644
index 0000000000..de7aeb2404
--- /dev/null
+++ b/source/web/scripts/ajax/src/animation/__package__.js
@@ -0,0 +1,8 @@
+dojo.kwCompoundRequire({
+ common: [
+ "dojo.animation.AnimationEvent",
+ "dojo.animation.Animation",
+ "dojo.animation.AnimationSequence"
+ ]
+});
+dojo.provide("dojo.animation.*");
diff --git a/source/web/scripts/ajax/src/behavior.js b/source/web/scripts/ajax/src/behavior.js
new file mode 100644
index 0000000000..d32435f54a
--- /dev/null
+++ b/source/web/scripts/ajax/src/behavior.js
@@ -0,0 +1,238 @@
+dojo.provide("dojo.behavior");
+dojo.require("dojo.event.*");
+
+dojo.require("dojo.experimental");
+dojo.experimental("dojo.behavior");
+
+dojo.behavior = new function(){
+ function arrIn(obj, name){
+ if(!obj[name]){ obj[name] = []; }
+ return obj[name];
+ }
+
+ function forIn(obj, scope, func){
+ var tmpObj = {};
+ for(var x in obj){
+ if(typeof tmpObj[x] == "undefined"){
+ if(!func){
+ scope(obj[x], x);
+ }else{
+ func.call(scope, obj[x], x);
+ }
+ }
+ }
+ }
+
+ // FIXME: need a better test so we don't exclude nightly Safari's!
+ this.behaviors = {};
+ this.add = function(behaviorObj){
+ /* behavior objects are specified in the following format:
+ *
+ * {
+ * "#id": {
+ * "found": function(element){
+ * // ...
+ * },
+ *
+ * "onblah": {targetObj: foo, targetFunc: "bar"},
+ *
+ * "onblarg": "/foo/bar/baz/blarg",
+ *
+ * "onevent": function(evt){
+ * },
+ *
+ * "onotherevent: function(evt){
+ * // ...
+ * }
+ * },
+ *
+ * "#id2": {
+ * // ...
+ * },
+ *
+ * "#id3": function(element){
+ * // ...
+ * },
+ *
+ * // publish the match on a topic
+ * "#id4": "/found/topic/name",
+ *
+ * // match all direct descendants
+ * "#id4 > *": function(element){
+ * // ...
+ * },
+ *
+ * // match the first child node that's an element
+ * "#id4 > @firstElement": { ... },
+ *
+ * // match the last child node that's an element
+ * "#id4 > @lastElement": { ... },
+ *
+ * // all elements of type tagname
+ * "tagname": {
+ * // ...
+ * },
+ *
+ * // maps to roughly:
+ * // dojo.lang.forEach(body.getElementsByTagName("tagname1"), function(node){
+ * // dojo.lang.forEach(node.getElementsByTagName("tagname2"), function(node2){
+ * // dojo.lang.forEach(node2.getElementsByTagName("tagname3", function(node3){
+ * // // apply rules
+ * // });
+ * // });
+ * // });
+ * "tagname1 tagname2 tagname3": {
+ * // ...
+ * },
+ *
+ * ".classname": {
+ * // ...
+ * },
+ *
+ * "tagname.classname": {
+ * // ...
+ * },
+ * }
+ *
+ * The "found" method is a generalized handler that's called as soon
+ * as the node matches the selector. Rules for values that follow also
+ * apply to the "found" key.
+ *
+ * The "on*" handlers are attached with dojo.event.connect(). If the
+ * value is not a function but is rather an object, it's assumed to be
+ * the "other half" of a dojo.event.kwConnect() argument object. It
+ * may contain any/all properties of such a connection modifier save
+ * for the sourceObj and sourceFunc properties which are filled in by
+ * the system automatically. If a string is instead encountered, the
+ * node publishes the specified event on the topic contained in the
+ * string value.
+ *
+ * If the value corresponding to the ID key is a function and not a
+ * list, it's treated as though it was the value of "found".
+ *
+ */
+
+ var tmpObj = {};
+ forIn(behaviorObj, this, function(behavior, name){
+ var tBehavior = arrIn(this.behaviors, name);
+ if((dojo.lang.isString(behavior))||(dojo.lang.isFunction(behavior))){
+ behavior = { found: behavior };
+ }
+ forIn(behavior, function(rule, ruleName){
+ arrIn(tBehavior, ruleName).push(rule);
+ });
+ });
+ }
+
+ this.apply = function(){
+ dojo.profile.start("dojo.behavior.apply");
+ var r = dojo.render.html;
+ // note, we apply one way for fast queries and one way for slow
+ // iteration. So be it.
+ var safariGoodEnough = (!r.safari);
+ if(r.safari){
+ // Anything over release #420 should work the fast way
+ var uas = r.UA.split("AppleWebKit/")[1];
+ if(parseInt(uas.match(/[0-9.]{3,}/)) >= 420){
+ safariGoodEnough = true;
+ }
+ }
+ if((dj_undef("behaviorFastParse", djConfig) ? (safariGoodEnough) : djConfig["behaviorFastParse"])){
+ this.applyFast();
+ }else{
+ this.applySlow();
+ }
+ dojo.profile.end("dojo.behavior.apply");
+ }
+
+ this.matchCache = {};
+
+ this.elementsById = function(id, handleRemoved){
+ var removed = [];
+ var added = [];
+ arrIn(this.matchCache, id);
+ if(handleRemoved){
+ var nodes = this.matchCache[id];
+ for(var x=0; x");
+ } catch (e) {
+ var script = document.createElement("script");
+ script.src = spath;
+ document.getElementsByTagName("head")[0].appendChild(script);
+ }
+ }
+ }
+})();
+
+// Localization routines
+
+/**
+ * Returns canonical form of locale, as used by Dojo. All variants are case-insensitive and are separated by '-'
+ * as specified in RFC 3066
+ */
+dojo.normalizeLocale = function(locale) {
+ return locale ? locale.toLowerCase() : dojo.locale;
+};
+
+dojo.searchLocalePath = function(locale, down, searchFunc){
+ locale = dojo.normalizeLocale(locale);
+
+ var elements = locale.split('-');
+ var searchlist = [];
+ for(var i = elements.length; i > 0; i--){
+ searchlist.push(elements.slice(0, i).join('-'));
+ }
+ searchlist.push(false);
+ if(down){searchlist.reverse();}
+
+ for(var j = searchlist.length - 1; j >= 0; j--){
+ var loc = searchlist[j] || "ROOT";
+ var stop = searchFunc(loc);
+ if(stop){ break; }
+ }
+}
+
+/**
+ * requireLocalization() is for loading translated bundles provided within a package in the namespace.
+ * Contents are typically strings, but may be any name/value pair, represented in JSON format.
+ * A bundle is structured in a program as follows, where modulename is mycode.mywidget and
+ * bundlename is mybundle:
+ *
+ * mycode/
+ * mywidget/
+ * nls/
+ * mybundle.js (the fallback translation, English in this example)
+ * de/
+ * mybundle.js
+ * de-at/
+ * mybundle.js
+ * en/
+ * (empty; use the fallback translation)
+ * en-us/
+ * mybundle.js
+ * en-gb/
+ * mybundle.js
+ * es/
+ * mybundle.js
+ * ...etc
+ *
+ * Each directory is named for a locale as specified by RFC 3066, (http://www.ietf.org/rfc/rfc3066.txt),
+ * normalized in lowercase.
+ *
+ * For a given locale, bundles will be loaded for that locale and all less-specific locales above it, as well
+ * as a fallback at the root. For example, a search for the "de-at" locale will first load nls/de-at/mybundle.js,
+ * then nls/de/mybundle.js and finally nls/mybundle.js. Lookups will traverse the locales in this same order
+ * and flatten all the values into a JS object (see dojo.i18n.getLocalization). A build step can preload the
+ * bundles to avoid data redundancy and extra network hits.
+ *
+ * @param modulename package in which the bundle is found
+ * @param bundlename bundle name, typically the filename without the '.js' suffix
+ * @param locale the locale to load (optional) By default, the browser's user locale as defined
+ * in dojo.locale
+ */
+dojo.requireLocalization = function(modulename, bundlename, locale /*optional*/){
+ var bundlepackage = [modulename, "_nls", bundlename].join(".");
+ var bundle = dojo.hostenv.startPackage(bundlepackage);
+ dojo.hostenv.loaded_modules_[bundlepackage] = bundle; // this seems to be necessary. why?
+
+ if(!dj_undef("dj_localesBuilt", dj_global) && dojo.hostenv.loaded_modules_[bundlepackage]){
+ locale = dojo.normalizeLocale(locale);
+ for(var i=0; i=0; x--){
+ dojo.clobberLastObject(removals[x]);
+ }
+ var depList = [];
+ var seen = dojo.hostenv._writtenIncludes;
+ for(var x=0; x");
+ }
+ document.write("");
+ dojo.hostenv._loadedUrisListStart = 0;
+ if (!willCallAgain) {
+ // turn off debugAtAllCosts, so that dojo.require() calls inside of ContentPane hrefs
+ // work correctly
+ dj_eval = old_dj_eval;
+ dojo.hostenv.loadUri = dojo.hostenv.oldLoadUri;
+ }
+}
diff --git a/source/web/scripts/ajax/src/collections/ArrayList.js b/source/web/scripts/ajax/src/collections/ArrayList.js
new file mode 100644
index 0000000000..7248722395
--- /dev/null
+++ b/source/web/scripts/ajax/src/collections/ArrayList.js
@@ -0,0 +1,136 @@
+dojo.provide("dojo.collections.ArrayList");
+dojo.require("dojo.collections.Collections");
+
+dojo.collections.ArrayList=function(/* array? */arr){
+ // summary
+ // Returns a new object of type dojo.collections.ArrayList
+ var items=[];
+ if(arr) items=items.concat(arr);
+ this.count=items.length;
+ this.add=function(/* object */obj){
+ // summary
+ // Add an element to the collection.
+ items.push(obj);
+ this.count=items.length;
+ };
+ this.addRange=function(/* array */a){
+ // summary
+ // Add a range of objects to the ArrayList
+ if(a.getIterator){
+ var e=a.getIterator();
+ while(!e.atEnd()){
+ this.add(e.get());
+ }
+ this.count=items.length;
+ }else{
+ for(var i=0; i=0) {
+ items.splice(i,1);
+ }
+ this.count=items.length;
+ };
+ this.removeAt=function(/* int */ i){
+ // summary
+ // return an array with function applied to all elements
+ items.splice(i,1);
+ this.count=items.length;
+ };
+ this.reverse=function(){
+ // summary
+ // Reverse the internal array
+ items.reverse();
+ };
+ this.sort=function(/* function? */ fn){
+ // summary
+ // sort the internal array
+ if(fn){
+ items.sort(fn);
+ }else{
+ items.sort();
+ }
+ };
+ this.setByIndex=function(/* int */ i, /* object */ obj){
+ // summary
+ // Set an element in the array by the passed index.
+ items[i]=obj;
+ this.count=items.length;
+ };
+ this.toArray=function(){
+ // summary
+ // Return a new array with all of the items of the internal array concatenated.
+ return [].concat(items);
+ }
+ this.toString=function(/* string */ delim){
+ // summary
+ // implementation of toString, follows [].toString();
+ return items.join((delim||","));
+ };
+};
diff --git a/source/web/scripts/ajax/src/collections/BinaryTree.js b/source/web/scripts/ajax/src/collections/BinaryTree.js
new file mode 100644
index 0000000000..83f3f7647b
--- /dev/null
+++ b/source/web/scripts/ajax/src/collections/BinaryTree.js
@@ -0,0 +1,193 @@
+dojo.provide("dojo.collections.BinaryTree");
+dojo.require("dojo.collections.Collections");
+dojo.require("dojo.experimental");
+
+dojo.experimental("dojo.collections.BinaryTree");
+
+dojo.collections.BinaryTree=function(data){
+ function node(data, rnode, lnode){
+ this.value=data||null;
+ this.right=rnode||null;
+ this.left=lnode||null;
+ this.clone=function(){
+ var c=new node();
+ if (this.value.value) c.value=this.value.clone();
+ else c.value=this.value;
+ if (this.left) c.left=this.left.clone();
+ if (this.right) c.right=this.right.clone();
+ }
+ this.compare=function(n){
+ if (this.value > n.value) return 1;
+ if (this.value < n.value) return -1;
+ return 0;
+ }
+ this.compareData=function(d){
+ if (this.value > d) return 1;
+ if (this.value < d) return -1;
+ return 0;
+ }
+ }
+
+ function inorderTraversalBuildup(current, a){
+ if (current){
+ inorderTraversalBuildup(current.left, a);
+ a.add(current);
+ inorderTraversalBuildup(current.right, a);
+ }
+ }
+
+ function preorderTraversal(current, sep){
+ var s="";
+ if (current){
+ s=current.value.toString() + sep;
+ s += preorderTraversal(current.left, sep);
+ s += preorderTraversal(current.right, sep);
+ }
+ return s;
+ }
+ function inorderTraversal(current, sep){
+ var s="";
+ if (current){
+ s=inorderTraversal(current.left, sep);
+ s += current.value.toString() + sep;
+ s += inorderTraversal(current.right, sep);
+ }
+ return s;
+ }
+ function postorderTraversal(current, sep){
+ var s="";
+ if (current){
+ s=postorderTraversal(current.left, sep);
+ s += postorderTraversal(current.right, sep);
+ s += current.value.toString() + sep;
+ }
+ return s;
+ }
+
+ function searchHelper(current, data){
+ if (!current) return null;
+ var i=current.compareData(data);
+ if (i==0) return current;
+ if (i>0) return searchHelper(current.left, data);
+ else return searchHelper(current.right, data);
+ }
+
+ this.add=function(data){
+ var n=new node(data);
+ var i;
+ var current=root;
+ var parent=null;
+ while (current){
+ i=current.compare(n);
+ if (i == 0) return;
+ parent=current;
+ if (i > 0) current=current.left;
+ else current=current.right;
+ }
+ this.count++;
+ if (!parent) root=n;
+ else {
+ i=parent.compare(n);
+ if (i > 0) parent.left=n;
+ else parent.right=n;
+ }
+ };
+ this.clear=function(){
+ root=null;
+ this.count=0;
+ };
+ this.clone=function(){
+ var c=new dojo.collections.BinaryTree();
+ c.root=root.clone();
+ c.count=this.count;
+ return c;
+ };
+ this.contains=function(data){
+ return this.search(data) != null;
+ };
+ this.deleteData=function(data){
+ var current=root;
+ var parent=null;
+ var i=current.compareData(data);
+ while (i != 0 && current != null){
+ if (i > 0){
+ parent=current;
+ current=current.left;
+ } else if (i < 0) {
+ parent=current;
+ current=current.right;
+ }
+ i=current.compareData(data);
+ }
+ if (!current) return;
+ this.count--;
+ if (!current.right) {
+ if (!parent) root=current.left;
+ else {
+ i=parent.compare(current);
+ if (i > 0) parent.left=current.left;
+ else if (i < 0) parent.right=current.left;
+ }
+ } else if (!current.right.left){
+ if (!parent) root=current.right;
+ else {
+ i=parent.compare(current);
+ if (i > 0) parent.left=current.right;
+ else if (i < 0) parent.right=current.right;
+ }
+ } else {
+ var leftmost=current.right.left;
+ var lmParent=current.right;
+ while (leftmost.left != null){
+ lmParent=leftmost;
+ leftmost=leftmost.left;
+ }
+ lmParent.left=leftmost.right;
+ leftmost.left=current.left;
+ leftmost.right=current.right;
+ if (!parent) root=leftmost;
+ else {
+ i=parent.compare(current);
+ if (i > 0) parent.left=leftmost;
+ else if (i < 0) parent.right=leftmost;
+ }
+ }
+ };
+ this.getIterator=function(){
+ var a=[];
+ inorderTraversalBuildup(root, a);
+ return new dojo.collections.Iterator(a);
+ };
+ this.search=function(data){
+ return searchHelper(root, data);
+ };
+ this.toString=function(order, sep){
+ if (!order) var order=dojo.collections.BinaryTree.TraversalMethods.Inorder;
+ if (!sep) var sep=" ";
+ var s="";
+ switch (order){
+ case dojo.collections.BinaryTree.TraversalMethods.Preorder:
+ s=preorderTraversal(root, sep);
+ break;
+ case dojo.collections.BinaryTree.TraversalMethods.Inorder:
+ s=inorderTraversal(root, sep);
+ break;
+ case dojo.collections.BinaryTree.TraversalMethods.Postorder:
+ s=postorderTraversal(root, sep);
+ break;
+ };
+ if (s.length == 0) return "";
+ else return s.substring(0, s.length - sep.length);
+ };
+
+ this.count=0;
+ var root=this.root=null;
+ if (data) {
+ this.add(data);
+ }
+}
+dojo.collections.BinaryTree.TraversalMethods={
+ Preorder : 0,
+ Inorder : 1,
+ Postorder : 2
+};
diff --git a/source/web/scripts/ajax/src/collections/Collections.js b/source/web/scripts/ajax/src/collections/Collections.js
new file mode 100644
index 0000000000..3e4d1436a0
--- /dev/null
+++ b/source/web/scripts/ajax/src/collections/Collections.js
@@ -0,0 +1,115 @@
+dojo.provide("dojo.collections.Collections");
+
+dojo.collections={Collections:true};
+dojo.collections.DictionaryEntry=function(/* string */k, /* object */v){
+ // summary
+ // return an object of type dojo.collections.DictionaryEntry
+ this.key=k;
+ this.value=v;
+ this.valueOf=function(){
+ return this.value; // object
+ };
+ this.toString=function(){
+ return String(this.value); // string
+ };
+}
+
+/* Iterators
+ * The collections.Iterators (Iterator and DictionaryIterator) are built to
+ * work with the Collections included in this namespace. However, they *can*
+ * be used with arrays and objects, respectively, should one choose to do so.
+ */
+dojo.collections.Iterator=function(/* array */arr){
+ // summary
+ // return an object of type dojo.collections.Iterator
+ var a=arr;
+ var position=0;
+ this.element=a[position]||null;
+ this.atEnd=function(){
+ // summary
+ // Test to see if the internal cursor has reached the end of the internal collection.
+ return (position>=a.length); // bool
+ };
+ this.get=function(){
+ // summary
+ // Test to see if the internal cursor has reached the end of the internal collection.
+ if(this.atEnd()){
+ return null; // object
+ }
+ this.element=a[position++];
+ return this.element; // object
+ };
+ this.map=function(/* function */fn, /* object? */scope){
+ // summary
+ // Functional iteration with optional scope.
+ var s=scope||dj_global;
+ if(Array.map){
+ return Array.map(a,fn,s); // array
+ }else{
+ var arr=[];
+ for(var i=0; i=a.length); // bool
+ };
+ this.get=function(){
+ // summary
+ // Test to see if the internal cursor has reached the end of the internal collection.
+ if(this.atEnd()){
+ return null; // object
+ }
+ this.element=a[position++];
+ return this.element; // object
+ };
+ this.map=function(/* function */fn, /* object? */scope){
+ // summary
+ // Functional iteration with optional scope.
+ var s=scope||dj_global;
+ if(Array.map){
+ return Array.map(a,fn,s); // array
+ }else{
+ var arr=[];
+ for(var i=0; i=o.length);
+ }
+ this.get=function(){
+ if(this.atEnd()){
+ return null; // object
+ }
+ this.element=o[position++];
+ return this.element; // object
+ };
+ this.map=function(/* function */fn, /* object? */scope){
+ var s=scope||dj_global;
+ if(Array.map){
+ return Array.map(o,fn,s); // array
+ }else{
+ var arr=[];
+ for(var i=0; i 1){
+ n=new node(arguments[0],arguments[1]);
+ }
+ if(!this.nodes.containsKey(n.key)){
+ this.nodes.add(n);
+ this.count++;
+ }
+ };
+ this.addDirectedEdge=function(uKey, vKey, cost){
+ var uNode,vNode;
+ if(uKey.constructor!= node){
+ uNode=this.nodes.item(uKey);
+ vNode=this.nodes.item(vKey);
+ }else{
+ uNode=uKey;
+ vNode=vKey;
+ }
+ var c=cost||0;
+ uNode.addDirected(vNode,c);
+ };
+ this.addUndirectedEdge=function(uKey, vKey, cost){
+ var uNode, vNode;
+ if(uKey.constructor!=node){
+ uNode=this.nodes.item(uKey);
+ vNode=this.nodes.item(vKey);
+ }else{
+ uNode=uKey;
+ vNode=vKey;
+ }
+ var c=cost||0;
+ uNode.addDirected(vNode,c);
+ vNode.addDirected(uNode,c);
+ };
+ this.contains=function(n){
+ return this.nodes.containsKey(n.key);
+ };
+ this.containsKey=function(k){
+ return this.nodes.containsKey(k);
+ };
+}
diff --git a/source/web/scripts/ajax/src/collections/Queue.js b/source/web/scripts/ajax/src/collections/Queue.js
new file mode 100644
index 0000000000..47fbf82983
--- /dev/null
+++ b/source/web/scripts/ajax/src/collections/Queue.js
@@ -0,0 +1,77 @@
+dojo.provide("dojo.collections.Queue");
+dojo.require("dojo.collections.Collections");
+
+dojo.collections.Queue=function(/* array? */arr){
+ // summary
+ // return an object of type dojo.collections.Queue
+ var q=[];
+ if (arr){
+ q=q.concat(arr);
+ }
+ this.count=q.length;
+ this.clear=function(){
+ // summary
+ // clears the internal collection
+ q=[];
+ this.count=q.length;
+ };
+ this.clone=function(){
+ // summary
+ // creates a new Queue based on this one
+ return new dojo.collections.Queue(q); // dojo.collections.Queue
+ };
+ this.contains=function(/* object */ o){
+ // summary
+ // Check to see if the passed object is an element in this queue
+ for(var i=0; i val) return 1;
+ if (this.value < val) return -1;
+ return 0;
+ }
+ this.incrementHeight = function(){
+ this.nodes.incrementHeight();
+ this.height++;
+ };
+ this.decrementHeight = function(){
+ this.nodes.decrementHeight();
+ this.height--;
+ };
+ }
+ function nodeList(height){
+ var arr = [];
+ this.height = height;
+ for (var i = 0; i < height; i++) arr[i] = null;
+ this.item = function(i){
+ return arr[i];
+ };
+ this.incrementHeight = function(){
+ this.height++;
+ arr[this.height] = null;
+ };
+ this.decrementHeight = function(){
+ arr.splice(arr.length - 1, 1);
+ this.height--;
+ };
+ }
+ function iterator(list){
+ this.element = list.head;
+ this.atEnd = function(){
+ return (this.element==null);
+ }
+ this.get = function(){
+ if(this.atEnd()){
+ return null;
+ }
+ this.element=this.element.nodes[0];
+ return this.element;
+ }
+ this.reset = function(){
+ this.element = list.head;
+ }
+ }
+
+ function chooseRandomHeight(max){
+ var level = 1;
+ while (Math.random() < PROB && level < max) level++;
+ return level;
+ }
+
+ var PROB = 0.5;
+ var comparisons = 0;
+
+ this.head = new node(1);
+ this.count = 0;
+ this.add = function(val){
+ var updates = [];
+ var current = this.head;
+ for (var i = this.head.height; i >= 0; i--){
+ if (!(current.nodes[i] != null && current.nodes[i].compare(val) < 0)) comparisons++;
+ while (current.nodes[i] != null && current.nodes[i].compare(val) < 0){
+ current = current.nodes[i];
+ comparisons++;
+ }
+ updates[i] = current;
+ }
+ if (current.nodes[0] != null && current.nodes[0].compare(val) == 0) return;
+ var n = new node(val, chooseRandomHeight(this.head.height + 1));
+ this.count++;
+ if (n.height > this.head.height){
+ this.head.incrementHeight();
+ this.head.nodes[this.head.height - 1] = n;
+ }
+ for (i = 0; i < n.height; i++){
+ if (i < updates.length) {
+ n.nodes[i] = updates[i].nodes[i];
+ updates[i].nodes[i] = n;
+ }
+ }
+ };
+
+ this.contains = function(val){
+ var current = this.head;
+ var i;
+ for (i = this.head.height - 1; i >= 0; i--) {
+ while (current.item(i) != null) {
+ comparisons++;
+ var result = current.nodes[i].compare(val);
+ if (result == 0) return true;
+ else if (result < 0) current = current.nodes[i];
+ else break;
+ }
+ }
+ return false;
+ };
+ this.getIterator = function(){
+ return new iterator(this);
+ };
+
+ this.remove = function(val){
+ var updates = [];
+ var current = this.head;
+ for (var i = this.head.height - 1; i >= 0; i--){
+ if (!(current.nodes[i] != null && current.nodes[i].compare(val) < 0)) comparisons++;
+ while (current.nodes[i] != null && current.nodes[i].compare(val) < 0) {
+ current = current.nodes[i];
+ comparisons++;
+ }
+ updates[i] = current;
+ }
+
+ current = current.nodes[0];
+ if (current != null && current.compare(val) == 0){
+ this.count--;
+ for (var i = 0; i < this.head.height; i++){
+ if (updates[i].nodes[i] != current) break;
+ else updates[i].nodes[i] = current.nodes[i];
+ }
+ if (this.head.nodes[this.head.height - 1] == null) this.head.decrementHeight();
+ }
+ };
+ this.resetComparisons = function(){
+ comparisons = 0;
+ };
+}
diff --git a/source/web/scripts/ajax/src/collections/SortedList.js b/source/web/scripts/ajax/src/collections/SortedList.js
new file mode 100644
index 0000000000..c8d6df3287
--- /dev/null
+++ b/source/web/scripts/ajax/src/collections/SortedList.js
@@ -0,0 +1,201 @@
+dojo.provide("dojo.collections.SortedList");
+dojo.require("dojo.collections.Collections");
+
+dojo.collections.SortedList=function(/* object? */ dictionary){
+ // summary
+ // creates a collection that acts like a dictionary but is also internally sorted.
+ // Note that the act of adding any elements forces an internal resort, making this object potentially slow.
+ var _this=this;
+ var items={};
+ var q=[];
+ var sorter=function(a,b){
+ if (a.key > b.key) return 1;
+ if (a.key < b.key) return -1;
+ return 0;
+ };
+ var build=function(){
+ q=[];
+ var e=_this.getIterator();
+ while (!e.atEnd()){
+ q.push(e.get());
+ }
+ q.sort(sorter);
+ };
+ var testObject={};
+
+ this.count=q.length;
+ this.add=function(/* string */ k,/* object */v){
+ // summary
+ // add the passed value to the dictionary at location k
+ if (!items[k]) {
+ items[k]=new dojo.collections.DictionaryEntry(k,v);
+ this.count=q.push(items[k]);
+ q.sort(sorter);
+ }
+ };
+ this.clear=function(){
+ // summary
+ // clear the internal collections
+ items={};
+ q=[];
+ this.count=q.length;
+ };
+ this.clone=function(){
+ // summary
+ // create a clone of this sorted list
+ return new dojo.collections.SortedList(this); // dojo.collections.SortedList
+ };
+ this.contains=this.containsKey=function(/* string */ k){
+ // summary
+ // Check to see if the list has a location k
+ if(testObject[k]){
+ return false; // bool
+ }
+ return (items[k]!=null); // bool
+ };
+ this.containsValue=function(/* object */ o){
+ // summary
+ // Check to see if this list contains the passed object
+ var e=this.getIterator();
+ while (!e.atEnd()){
+ var item=e.get();
+ if(item.value==o){
+ return true; // bool
+ }
+ }
+ return false; // bool
+ };
+ this.copyTo=function(/* array */ arr, /* int */ i){
+ // summary
+ // copy the contents of the list into array arr at index i
+ var e=this.getIterator();
+ var idx=i;
+ while(!e.atEnd()){
+ arr.splice(idx,0,e.get());
+ idx++;
+ }
+ };
+ this.entry=function(/* string */ k){
+ // summary
+ // return the object at location k
+ return items[k]; // dojo.collections.DictionaryEntry
+ };
+ this.forEach=function(/* function */ fn, /* object? */ scope){
+ // summary
+ // functional iterator, following the mozilla spec.
+ var s=scope||dj_global;
+ if(Array.forEach){
+ Array.forEach(q, fn, s);
+ }else{
+ for(var i=0; i>16)^0xffff))+(((sum&0xffff)^0xffff)+1);
+ }
+ return sum;
+ }
+ function split(x){
+ var r=x&0xffffffff;
+ if(r<0) {
+ r=-r;
+ return [((r&0xffff)^0xffff)+1,(r>>16)^0xffff];
+ }
+ return [r&0xffff,(r>>16)];
+ }
+ function xor(x,y){
+ var xs=split(x);
+ var ys=split(y);
+ return (0x10000*(xs[1]^ys[1]))+(xs[0]^ys[0]);
+ }
+ function $(v, box){
+ var d=v&0xff; v>>=8;
+ var c=v&0xff; v>>=8;
+ var b=v&0xff; v>>=8;
+ var a=v&0xff;
+ var r=add(box.s0[a],box.s1[b]);
+ r=xor(r,box.s2[c]);
+ return add(r,box.s3[d]);
+ }
+////////////////////////////////////////////////////////////////////////////
+ function eb(o, box){
+ var l=o.left;
+ var r=o.right;
+ l=xor(l,box.p[0]);
+ r=xor(r,xor($(l,box),box.p[1]));
+ l=xor(l,xor($(r,box),box.p[2]));
+ r=xor(r,xor($(l,box),box.p[3]));
+ l=xor(l,xor($(r,box),box.p[4]));
+ r=xor(r,xor($(l,box),box.p[5]));
+ l=xor(l,xor($(r,box),box.p[6]));
+ r=xor(r,xor($(l,box),box.p[7]));
+ l=xor(l,xor($(r,box),box.p[8]));
+ r=xor(r,xor($(l,box),box.p[9]));
+ l=xor(l,xor($(r,box),box.p[10]));
+ r=xor(r,xor($(l,box),box.p[11]));
+ l=xor(l,xor($(r,box),box.p[12]));
+ r=xor(r,xor($(l,box),box.p[13]));
+ l=xor(l,xor($(r,box),box.p[14]));
+ r=xor(r,xor($(l,box),box.p[15]));
+ l=xor(l,xor($(r,box),box.p[16]));
+ o.right=l;
+ o.left=xor(r,box.p[17]);
+ }
+
+ function db(o, box){
+ var l=o.left;
+ var r=o.right;
+ l=xor(l,box.p[17]);
+ r=xor(r,xor($(l,box),box.p[16]));
+ l=xor(l,xor($(r,box),box.p[15]));
+ r=xor(r,xor($(l,box),box.p[14]));
+ l=xor(l,xor($(r,box),box.p[13]));
+ r=xor(r,xor($(l,box),box.p[12]));
+ l=xor(l,xor($(r,box),box.p[11]));
+ r=xor(r,xor($(l,box),box.p[10]));
+ l=xor(l,xor($(r,box),box.p[9]));
+ r=xor(r,xor($(l,box),box.p[8]));
+ l=xor(l,xor($(r,box),box.p[7]));
+ r=xor(r,xor($(l,box),box.p[6]));
+ l=xor(l,xor($(r,box),box.p[5]));
+ r=xor(r,xor($(l,box),box.p[4]));
+ l=xor(l,xor($(r,box),box.p[3]));
+ r=xor(r,xor($(l,box),box.p[2]));
+ l=xor(l,xor($(r,box),box.p[1]));
+ o.right=l;
+ o.left=xor(r,box.p[0]);
+ }
+
+ // Note that we aren't caching contexts here; it might take a little longer
+ // but we should be more secure this way.
+ function init(key){
+ var k=key;
+ if (typeof(k)=="string"){
+ var a=[];
+ for(var i=0; i>>18)&0x3f));
+ s.push(tab.charAt((t>>>12)&0x3f));
+ s.push(tab.charAt((t>>>6)&0x3f));
+ s.push(tab.charAt(t&0x3f));
+ }
+ // deal with trailers, based on patch from Peter Wood.
+ switch(rm){
+ case 2:{
+ var t=ba[i++]<<16|ba[i++]<<8;
+ s.push(tab.charAt((t>>>18)&0x3f));
+ s.push(tab.charAt((t>>>12)&0x3f));
+ s.push(tab.charAt((t>>>6)&0x3f));
+ s.push(p);
+ break;
+ }
+ case 1:{
+ var t=ba[i++]<<16;
+ s.push(tab.charAt((t>>>18)&0x3f));
+ s.push(tab.charAt((t>>>12)&0x3f));
+ s.push(p);
+ s.push(p);
+ break;
+ }
+ }
+ return s.join("");
+ }
+ function fromBase64(str){
+ var s=str.split("");
+ var p="=";
+ var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var out=[];
+ var l=s.length;
+ while(s[--l]==p){ }
+ for (var i=0; i>>16)&0xff);
+ out.push((t>>>8)&0xff);
+ out.push(t&0xff);
+ }
+ return out;
+ }
+////////////////////////////////////////////////////////////////////////////
+// PUBLIC FUNCTIONS
+// 0.2: Only supporting ECB mode for now.
+////////////////////////////////////////////////////////////////////////////
+ this.getIV=function(outputType){
+ var out=outputType||dojo.crypto.outputTypes.Base64;
+ switch(out){
+ case dojo.crypto.outputTypes.Hex:{
+ var s=[];
+ for(var i=0; i> 3;
+ var pos=0;
+ var o={};
+ var isCBC=(mode==dojo.crypto.cipherModes.CBC);
+ var vector={left:iv.left||null, right:iv.right||null};
+ for(var i=0; i>24)&0xff);
+ cipher.push((o.left>>16)&0xff);
+ cipher.push((o.left>>8)&0xff);
+ cipher.push(o.left&0xff);
+ cipher.push((o.right>>24)&0xff);
+ cipher.push((o.right>>16)&0xff);
+ cipher.push((o.right>>8)&0xff);
+ cipher.push(o.right&0xff);
+ pos+=8;
+ }
+ switch(out){
+ case dojo.crypto.outputTypes.Hex:{
+ var s=[];
+ for(var i=0; i> 3;
+ var pos=0;
+ var o={};
+ var isCBC=(mode==dojo.crypto.cipherModes.CBC);
+ var vector={left:iv.left||null, right:iv.right||null};
+ for(var i=0; i>24)&0xff);
+ pt.push((o.left>>16)&0xff);
+ pt.push((o.left>>8)&0xff);
+ pt.push(o.left&0xff);
+ pt.push((o.right>>24)&0xff);
+ pt.push((o.right>>16)&0xff);
+ pt.push((o.right>>8)&0xff);
+ pt.push(o.right&0xff);
+ pos+=8;
+ }
+
+ // check for padding, and remove.
+ if(pt[pt.length-1]==pt[pt.length-2]||pt[pt.length-1]==0x01){
+ var n=pt[pt.length-1];
+ pt.splice(pt.length-n, n);
+ }
+
+ // convert to string
+ for(var i=0; i>5]|=(s.charCodeAt(i/chrsz)&mask)<<(i%32);
+ return wa;
+ }
+ function toString(wa){
+ var s=[];
+ for(var i=0; i>5]>>>(i%32))&mask));
+ return s.join("");
+ }
+ function toHex(wa) {
+ var h="0123456789abcdef";
+ var s=[];
+ for(var i=0; i>2]>>((i%4)*8+4))&0xF)+h.charAt((wa[i>>2]>>((i%4)*8))&0xF));
+ }
+ return s.join("");
+ }
+ function toBase64(wa){
+ var p="=";
+ var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var s=[];
+ for(var i=0; i>2]>>8*(i%4))&0xFF)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&0xFF)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&0xFF);
+ for(var j=0; j<4; j++){
+ if(i*8+j*6>wa.length*32) s.push(p);
+ else s.push(tab.charAt((t>>6*(3-j))&0x3F));
+ }
+ }
+ return s.join("");
+ }
+ function add(x,y) {
+ var l=(x&0xFFFF)+(y&0xFFFF);
+ var m=(x>>16)+(y>>16)+(l>>16);
+ return (m<<16)|(l&0xFFFF);
+ }
+ function R(n,c){ return (n<>>(32-c)); }
+ function C(q,a,b,x,s,t){ return add(R(add(add(a,q),add(x,t)),s),b); }
+ function FF(a,b,c,d,x,s,t){ return C((b&c)|((~b)&d),a,b,x,s,t); }
+ function GG(a,b,c,d,x,s,t){ return C((b&d)|(c&(~d)),a,b,x,s,t); }
+ function HH(a,b,c,d,x,s,t){ return C(b^c^d,a,b,x,s,t); }
+ function II(a,b,c,d,x,s,t){ return C(c^(b|(~d)),a,b,x,s,t); }
+ function core(x,len){
+ x[len>>5]|=0x80<<((len)%32);
+ x[(((len+64)>>>9)<<4)+14]=len;
+ var a= 1732584193;
+ var b=-271733879;
+ var c=-1732584194;
+ var d= 271733878;
+ for(var i=0; i16) wa=core(wa,key.length*chrsz);
+ var l=[], r=[];
+ for(var i=0; i<16; i++){
+ l[i]=wa[i]^0x36363636;
+ r[i]=wa[i]^0x5c5c5c5c;
+ }
+ var h=core(l.concat(toWord(data)),512+data.length*chrsz);
+ return core(r.concat(h),640);
+ }
+
+ // Public functions
+ this.compute=function(data,outputType){
+ var out=outputType||dojo.crypto.outputTypes.Base64;
+ switch(out){
+ case dojo.crypto.outputTypes.Hex:{
+ return toHex(core(toWord(data),data.length*chrsz));
+ }
+ case dojo.crypto.outputTypes.String:{
+ return toString(core(toWord(data),data.length*chrsz));
+ }
+ default:{
+ return toBase64(core(toWord(data),data.length*chrsz));
+ }
+ }
+ };
+ this.getHMAC=function(data,key,outputType){
+ var out=outputType||dojo.crypto.outputTypes.Base64;
+ switch(out){
+ case dojo.crypto.outputTypes.Hex:{
+ return toHex(hmac(data,key));
+ }
+ case dojo.crypto.outputTypes.String:{
+ return toString(hmac(data,key));
+ }
+ default:{
+ return toBase64(hmac(data,key));
+ }
+ }
+ };
+}();
diff --git a/source/web/scripts/ajax/src/crypto/Rijndael.js b/source/web/scripts/ajax/src/crypto/Rijndael.js
new file mode 100644
index 0000000000..6eddf57ad2
--- /dev/null
+++ b/source/web/scripts/ajax/src/crypto/Rijndael.js
@@ -0,0 +1,12 @@
+dojo.provide("dojo.crypto.Rijndael");
+dojo.require("dojo.crypto");
+dojo.require("dojo.experimental");
+
+dojo.experimental("dojo.crypto.Rijndael");
+
+dojo.crypto.Rijndael = new function(){
+ this.encrypt=function(plaintext, key){
+ };
+ this.decrypt=function(ciphertext, key){
+ };
+}();
diff --git a/source/web/scripts/ajax/src/crypto/SHA1.js b/source/web/scripts/ajax/src/crypto/SHA1.js
new file mode 100644
index 0000000000..7119a7c1c9
--- /dev/null
+++ b/source/web/scripts/ajax/src/crypto/SHA1.js
@@ -0,0 +1,154 @@
+dojo.require("dojo.crypto");
+dojo.provide("dojo.crypto.SHA1");
+dojo.require("dojo.experimental");
+
+/*
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined
+ * in FIPS PUB 180-1
+ *
+ * Version 2.1a Copyright Paul Johnston 2000 - 2002.
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
+ * Distributed under the BSD License
+ * See http://pajhome.org.uk/crypt/md5 for details.
+ *
+ * Dojo port by Tom Trenka
+ */
+dojo.experimental("dojo.crypto.SHA1");
+
+dojo.crypto.SHA1 = new function(){
+ var chrsz=8;
+ var mask=(1<>5]|=(s.charCodeAt(i/chrsz)&mask)<<(i%32);
+ return wa;
+ }
+ function toString(wa){
+ var s=[];
+ for(var i=0; i>5]>>>(i%32))&mask));
+ return s.join("");
+ }
+ function toHex(wa) {
+ var h="0123456789abcdef";
+ var s=[];
+ for(var i=0; i>2]>>((i%4)*8+4))&0xF)+h.charAt((wa[i>>2]>>((i%4)*8))&0xF));
+ }
+ return s.join("");
+ }
+ function toBase64(wa){
+ var p="=";
+ var tab="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+ var s=[];
+ for(var i=0; i>2]>>8*(i%4))&0xFF)<<16)|(((wa[i+1>>2]>>8*((i+1)%4))&0xFF)<<8)|((wa[i+2>>2]>>8*((i+2)%4))&0xFF);
+ for(var j=0; j<4; j++){
+ if(i*8+j*6>wa.length*32) s.push(p);
+ else s.push(tab.charAt((t>>6*(3-j))&0x3F));
+ }
+ }
+ return s.join("");
+ }
+
+ // math
+ function add(x,y){
+ var l=(x&0xffff)+(y&0xffff);
+ var m=(x>>16)+(y>>16)+(l>>16);
+ return (m<<16)|(l&0xffff);
+ }
+ function r(x,n){ return (x<>>(32-n)); }
+
+ // SHA rounds
+ function f(u,v,w){ return ((u&v)|(~u&w)); }
+ function g(u,v,w){ return ((u&v)|(u&w)|(v&w)); }
+ function h(u,v,w){ return (u^v^w); }
+
+ function fn(i,u,v,w){
+ if(i<20) return f(u,v,w);
+ if(i<40) return h(u,v,w);
+ if(i<60) return g(u,v,w);
+ return h(u,v,w);
+ }
+ function cnst(i){
+ if(i<20) return 1518500249;
+ if(i<40) return 1859775393;
+ if(i<60) return -1894007588;
+ return -899497514;
+ }
+
+ function core(x,len){
+ x[len>>5]|=0x80<<(24-len%32);
+ x[((len+64>>9)<<4)+15]=len;
+
+ var w=[];
+ var a= 1732584193; // 0x67452301
+ var b=-271733879; // 0xefcdab89
+ var c=-1732584194; // 0x98badcfe
+ var d= 271733878; // 0x10325476
+ var e=-1009589776; // 0xc3d2e1f0
+
+ for(var i=0; i16) wa=core(wa,key.length*chrsz);
+ var l=[], r=[];
+ for(var i=0; i<16; i++){
+ l[i]=wa[i]^0x36363636;
+ r[i]=wa[i]^0x5c5c5c5c;
+ }
+ var h=core(l.concat(toWord(data)),512+data.length*chrsz);
+ return core(r.concat(h),640);
+ }
+
+ this.compute=function(data,outputType){
+ var out=outputType||dojo.crypto.outputTypes.Base64;
+ switch(out){
+ case dojo.crypto.outputTypes.Hex:{
+ return toHex(core(toWord(data),data.length*chrsz));
+ }
+ case dojo.crypto.outputTypes.String:{
+ return toString(core(toWord(data),data.length*chrsz));
+ }
+ default:{
+ return toBase64(core(toWord(data),data.length*chrsz));
+ }
+ }
+ };
+ this.getHMAC=function(data,key,outputType){
+ var out=outputType||dojo.crypto.outputTypes.Base64;
+ switch(out){
+ case dojo.crypto.outputTypes.Hex:{
+ return toHex(hmac(data,key));
+ }
+ case dojo.crypto.outputTypes.String:{
+ return toString(hmac(data,key));
+ }
+ default:{
+ return toBase64(hmac(data,key));
+ }
+ }
+ };
+}();
diff --git a/source/web/scripts/ajax/src/crypto/SHA256.js b/source/web/scripts/ajax/src/crypto/SHA256.js
new file mode 100644
index 0000000000..163eb8bcb8
--- /dev/null
+++ b/source/web/scripts/ajax/src/crypto/SHA256.js
@@ -0,0 +1,10 @@
+dojo.provide("dojo.crypto.SHA256");
+dojo.require("dojo.crypto");
+dojo.require("dojo.experimental");
+
+dojo.experimental("dojo.crypto.SHA256");
+
+dojo.crypto.SHA256 = new function(){
+ this.compute=function(s){
+ };
+}();
diff --git a/source/web/scripts/ajax/src/crypto/__package__.js b/source/web/scripts/ajax/src/crypto/__package__.js
new file mode 100644
index 0000000000..494f789bcb
--- /dev/null
+++ b/source/web/scripts/ajax/src/crypto/__package__.js
@@ -0,0 +1,7 @@
+dojo.kwCompoundRequire({
+ common: [
+ "dojo.crypto",
+ "dojo.crypto.MD5"
+ ]
+});
+dojo.provide("dojo.crypto.*");
diff --git a/source/web/scripts/ajax/src/data.js b/source/web/scripts/ajax/src/data.js
new file mode 100644
index 0000000000..5b6de2fc59
--- /dev/null
+++ b/source/web/scripts/ajax/src/data.js
@@ -0,0 +1,5 @@
+dojo.provide("dojo.data");
+
+// currently a stub for dojo.data
+
+dojo.data = {};
diff --git a/source/web/scripts/ajax/src/data/Attribute.js b/source/web/scripts/ajax/src/data/Attribute.js
new file mode 100644
index 0000000000..c3d0c5602e
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/Attribute.js
@@ -0,0 +1,52 @@
+dojo.provide("dojo.data.Attribute");
+dojo.require("dojo.data.Item");
+dojo.require("dojo.lang.assert");
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+dojo.data.Attribute = function(/* dojo.data.provider.Base */ dataProvider, /* string */ attributeId) {
+ /**
+ * summary:
+ * An Attribute object represents something like a column in
+ * a relational database.
+ */
+ dojo.lang.assertType(dataProvider, dojo.data.provider.Base, {optional: true});
+ dojo.lang.assertType(attributeId, String);
+ dojo.data.Item.call(this, dataProvider);
+ this._attributeId = attributeId;
+};
+dojo.inherits(dojo.data.Attribute, dojo.data.Item);
+
+// -------------------------------------------------------------------
+// Public instance methods
+// -------------------------------------------------------------------
+dojo.data.Attribute.prototype.toString = function() {
+ return this._attributeId; // string
+};
+
+dojo.data.Attribute.prototype.getAttributeId = function() {
+ /**
+ * summary:
+ * Returns the string token that uniquely identifies this
+ * attribute within the context of a data provider.
+ * For a data provider that accesses relational databases,
+ * typical attributeIds might be tokens like "name", "age",
+ * "ssn", or "dept_key".
+ */
+ return this._attributeId; // string
+};
+
+dojo.data.Attribute.prototype.getType = function() {
+ /**
+ * summary: Returns the data type of the values of this attribute.
+ */
+ return this.get('type'); // dojo.data.Type or null
+};
+
+dojo.data.Attribute.prototype.setType = function(/* dojo.data.Type or null */ type) {
+ /**
+ * summary: Sets the data type for this attribute.
+ */
+ this.set('type', type);
+};
diff --git a/source/web/scripts/ajax/src/data/Item.js b/source/web/scripts/ajax/src/data/Item.js
new file mode 100644
index 0000000000..df0b9ddf8a
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/Item.js
@@ -0,0 +1,317 @@
+dojo.provide("dojo.data.Item");
+dojo.require("dojo.data.Observable");
+dojo.require("dojo.data.Value");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.lang.assert");
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+dojo.data.Item = function(/* dojo.data.provider.Base */ dataProvider) {
+ /**
+ * summary:
+ * An Item has attributes and attribute values, sort of like
+ * a record in a database, or a 'struct' in C. Instances of
+ * the Item class know how to store and retrieve their
+ * attribute values.
+ */
+ dojo.lang.assertType(dataProvider, dojo.data.provider.Base, {optional: true});
+ dojo.data.Observable.call(this);
+ this._dataProvider = dataProvider;
+ this._dictionaryOfAttributeValues = {};
+};
+dojo.inherits(dojo.data.Item, dojo.data.Observable);
+
+// -------------------------------------------------------------------
+// Public class methods
+// -------------------------------------------------------------------
+dojo.data.Item.compare = function(/* dojo.data.Item */ itemOne, /* dojo.data.Item */ itemTwo) {
+ /**
+ * summary:
+ * Given two Items to compare, this method returns 0, 1, or -1.
+ * This method is designed to be used by sorting routines, like
+ * the JavaScript built-in Array sort() method.
+ *
+ * Example:
+ *
+ * var a = dataProvider.newItem("kermit");
+ * var b = dataProvider.newItem("elmo");
+ * var c = dataProvider.newItem("grover");
+ * var array = new Array(a, b, c);
+ * array.sort(dojo.data.Item.compare);
+ *
+ */
+ dojo.lang.assertType(itemOne, dojo.data.Item);
+ if (!dojo.lang.isOfType(itemTwo, dojo.data.Item)) {
+ return -1;
+ }
+ var nameOne = itemOne.getName();
+ var nameTwo = itemTwo.getName();
+ if (nameOne == nameTwo) {
+ var attributeArrayOne = itemOne.getAttributes();
+ var attributeArrayTwo = itemTwo.getAttributes();
+ if (attributeArrayOne.length != attributeArrayTwo.length) {
+ if (attributeArrayOne.length > attributeArrayTwo.length) {
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+ for (var i in attributeArrayOne) {
+ var attribute = attributeArrayOne[i];
+ var arrayOfValuesOne = itemOne.getValues(attribute);
+ var arrayOfValuesTwo = itemTwo.getValues(attribute);
+ dojo.lang.assert(arrayOfValuesOne && (arrayOfValuesOne.length > 0));
+ if (!arrayOfValuesTwo) {
+ return 1;
+ }
+ if (arrayOfValuesOne.length != arrayOfValuesTwo.length) {
+ if (arrayOfValuesOne.length > arrayOfValuesTwo.length) {
+ return 1;
+ } else {
+ return -1;
+ }
+ }
+ for (var j in arrayOfValuesOne) {
+ var value = arrayOfValuesOne[j];
+ if (!itemTwo.hasAttributeValue(value)) {
+ return 1;
+ }
+ }
+ return 0;
+ }
+ } else {
+ if (nameOne > nameTwo) {
+ return 1;
+ } else {
+ return -1; // 0, 1, or -1
+ }
+ }
+};
+
+// -------------------------------------------------------------------
+// Public instance methods
+// -------------------------------------------------------------------
+dojo.data.Item.prototype.toString = function() {
+ /**
+ * Returns a simple string representation of the item.
+ */
+ var arrayOfStrings = [];
+ var attributes = this.getAttributes();
+ for (var i in attributes) {
+ var attribute = attributes[i];
+ var arrayOfValues = this.getValues(attribute);
+ var valueString;
+ if (arrayOfValues.length == 1) {
+ valueString = arrayOfValues[0];
+ } else {
+ valueString = '[';
+ valueString += arrayOfValues.join(', ');
+ valueString += ']';
+ }
+ arrayOfStrings.push(' ' + attribute + ': ' + valueString);
+ }
+ var returnString = '{ ';
+ returnString += arrayOfStrings.join(',\n');
+ returnString += ' }';
+ return returnString; // string
+};
+
+dojo.data.Item.prototype.compare = function(/* dojo.data.Item */ otherItem) {
+ /**
+ * summary: Compares this Item to another Item, and returns 0, 1, or -1.
+ */
+ return dojo.data.Item.compare(this, otherItem); // 0, 1, or -1
+};
+
+dojo.data.Item.prototype.isEqual = function(/* dojo.data.Item */ otherItem) {
+ /**
+ * summary: Returns true if this Item is equal to the otherItem, or false otherwise.
+ */
+ return (this.compare(otherItem) == 0); // boolean
+};
+
+dojo.data.Item.prototype.getName = function() {
+ return this.get('name');
+};
+
+dojo.data.Item.prototype.get = function(/* string or dojo.data.Attribute */ attributeId) {
+ /**
+ * summary: Returns a single literal value, like "foo" or 33.
+ */
+ // dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
+ var literalOrValueOrArray = this._dictionaryOfAttributeValues[attributeId];
+ if (dojo.lang.isUndefined(literalOrValueOrArray)) {
+ return null; // null
+ }
+ if (literalOrValueOrArray instanceof dojo.data.Value) {
+ return literalOrValueOrArray.getValue(); // literal
+ }
+ if (dojo.lang.isArray(literalOrValueOrArray)) {
+ var dojoDataValue = literalOrValueOrArray[0];
+ return dojoDataValue.getValue(); // literal
+ }
+ return literalOrValueOrArray; // literal
+};
+
+dojo.data.Item.prototype.getValue = function(/* string or dojo.data.Attribute */ attributeId) {
+ /**
+ * summary: Returns a single instance of dojo.data.Value.
+ */
+ // dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
+ var literalOrValueOrArray = this._dictionaryOfAttributeValues[attributeId];
+ if (dojo.lang.isUndefined(literalOrValueOrArray)) {
+ return null; // null
+ }
+ if (literalOrValueOrArray instanceof dojo.data.Value) {
+ return literalOrValueOrArray; // dojo.data.Value
+ }
+ if (dojo.lang.isArray(literalOrValueOrArray)) {
+ var dojoDataValue = literalOrValueOrArray[0];
+ return dojoDataValue; // dojo.data.Value
+ }
+ var literal = literalOrValueOrArray;
+ dojoDataValue = new dojo.data.Value(literal);
+ this._dictionaryOfAttributeValues[attributeId] = dojoDataValue;
+ return dojoDataValue; // dojo.data.Value
+};
+
+dojo.data.Item.prototype.getValues = function(/* string or dojo.data.Attribute */ attributeId) {
+ /**
+ * summary: Returns an array of dojo.data.Value objects.
+ */
+ // dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
+ var literalOrValueOrArray = this._dictionaryOfAttributeValues[attributeId];
+ if (dojo.lang.isUndefined(literalOrValueOrArray)) {
+ return null; // null
+ }
+ if (literalOrValueOrArray instanceof dojo.data.Value) {
+ var array = [literalOrValueOrArray];
+ this._dictionaryOfAttributeValues[attributeId] = array;
+ return array; // Array
+ }
+ if (dojo.lang.isArray(literalOrValueOrArray)) {
+ return literalOrValueOrArray; // Array
+ }
+ var literal = literalOrValueOrArray;
+ var dojoDataValue = new dojo.data.Value(literal);
+ array = [dojoDataValue];
+ this._dictionaryOfAttributeValues[attributeId] = array;
+ return array; // Array
+};
+
+dojo.data.Item.prototype.load = function(/* string or dojo.data.Attribute */ attributeId, /* anything */ value) {
+ /**
+ * summary:
+ * Used for loading an attribute value into an item when
+ * the item is first being loaded into memory from some
+ * data store (such as a file).
+ */
+ // dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
+ this._dataProvider.registerAttribute(attributeId);
+ var literalOrValueOrArray = this._dictionaryOfAttributeValues[attributeId];
+ if (dojo.lang.isUndefined(literalOrValueOrArray)) {
+ this._dictionaryOfAttributeValues[attributeId] = value;
+ return;
+ }
+ if (!(value instanceof dojo.data.Value)) {
+ value = new dojo.data.Value(value);
+ }
+ if (literalOrValueOrArray instanceof dojo.data.Value) {
+ var array = [literalOrValueOrArray, value];
+ this._dictionaryOfAttributeValues[attributeId] = array;
+ return;
+ }
+ if (dojo.lang.isArray(literalOrValueOrArray)) {
+ literalOrValueOrArray.push(value);
+ return;
+ }
+ var literal = literalOrValueOrArray;
+ var dojoDataValue = new dojo.data.Value(literal);
+ array = [dojoDataValue, value];
+ this._dictionaryOfAttributeValues[attributeId] = array;
+};
+
+dojo.data.Item.prototype.set = function(/* string or dojo.data.Attribute */ attributeId, /* anything */ value) {
+ /**
+ * summary:
+ * Used for setting an attribute value as a result of a
+ * user action.
+ */
+ // dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
+ this._dataProvider.registerAttribute(attributeId);
+ this._dictionaryOfAttributeValues[attributeId] = value;
+ this._dataProvider.noteChange(this, attributeId, value);
+};
+
+dojo.data.Item.prototype.setValue = function(/* string or dojo.data.Attribute */ attributeId, /* dojo.data.Value */ value) {
+ this.set(attributeId, value);
+};
+
+dojo.data.Item.prototype.addValue = function(/* string or dojo.data.Attribute */ attributeId, /* anything */ value) {
+ /**
+ * summary:
+ * Used for adding an attribute value as a result of a
+ * user action.
+ */
+ this.load(attributeId, value);
+ this._dataProvider.noteChange(this, attributeId, value);
+};
+
+dojo.data.Item.prototype.setValues = function(/* string or dojo.data.Attribute */ attributeId, /* Array */ arrayOfValues) {
+ /**
+ * summary:
+ * Used for setting an array of attribute values as a result of a
+ * user action.
+ */
+ // dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
+ dojo.lang.assertType(arrayOfValues, Array);
+ this._dataProvider.registerAttribute(attributeId);
+ var finalArray = [];
+ this._dictionaryOfAttributeValues[attributeId] = finalArray;
+ for (var i in arrayOfValues) {
+ var value = arrayOfValues[i];
+ if (!(value instanceof dojo.data.Value)) {
+ value = new dojo.data.Value(value);
+ }
+ finalArray.push(value);
+ this._dataProvider.noteChange(this, attributeId, value);
+ }
+};
+
+dojo.data.Item.prototype.getAttributes = function() {
+ /**
+ * summary:
+ * Returns an array containing all of the attributes for which
+ * this item has attribute values.
+ */
+ var arrayOfAttributes = [];
+ for (var key in this._dictionaryOfAttributeValues) {
+ arrayOfAttributes.push(this._dataProvider.getAttribute(key));
+ }
+ return arrayOfAttributes; // Array
+};
+
+dojo.data.Item.prototype.hasAttribute = function(/* string or dojo.data.Attribute */ attributeId) {
+ /**
+ * summary: Returns true if the given attribute of the item has been assigned any value.
+ */
+ // dojo.lang.assertType(attributeId, [String, dojo.data.Attribute]);
+ return (attributeId in this._dictionaryOfAttributeValues); // boolean
+};
+
+dojo.data.Item.prototype.hasAttributeValue = function(/* string or dojo.data.Attribute */ attributeId, /* anything */ value) {
+ /**
+ * summary: Returns true if the given attribute of the item has been assigned the given value.
+ */
+ var arrayOfValues = this.getValues(attributeId);
+ for (var i in arrayOfValues) {
+ var candidateValue = arrayOfValues[i];
+ if (candidateValue.isEqual(value)) {
+ return true; // boolean
+ }
+ }
+ return false; // boolean
+};
+
+
diff --git a/source/web/scripts/ajax/src/data/Kind.js b/source/web/scripts/ajax/src/data/Kind.js
new file mode 100644
index 0000000000..b7f26c54ae
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/Kind.js
@@ -0,0 +1,18 @@
+dojo.provide("dojo.data.Kind");
+dojo.require("dojo.data.Item");
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+dojo.data.Kind = function(/* dojo.data.provider.Base */ dataProvider) {
+ /**
+ * summary:
+ * A Kind represents a kind of item. In the dojo data model
+ * the item Snoopy might belong to the 'kind' Dog, where in
+ * a Java program the object Snoopy would belong to the 'class'
+ * Dog, and in MySQL the record for Snoopy would be in the
+ * table Dog.
+ */
+ dojo.data.Item.call(this, dataProvider);
+};
+dojo.inherits(dojo.data.Kind, dojo.data.Item);
diff --git a/source/web/scripts/ajax/src/data/Observable.js b/source/web/scripts/ajax/src/data/Observable.js
new file mode 100644
index 0000000000..327f00bab6
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/Observable.js
@@ -0,0 +1,49 @@
+dojo.provide("dojo.data.Observable");
+dojo.require("dojo.lang.common");
+dojo.require("dojo.lang.assert");
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+dojo.data.Observable = function() {
+};
+
+// -------------------------------------------------------------------
+// Public instance methods
+// -------------------------------------------------------------------
+dojo.data.Observable.prototype.addObserver = function(/* object */ observer) {
+ /**
+ * summary: Registers an object as an observer of this item,
+ * so that the object will be notified when the item changes.
+ */
+ dojo.lang.assertType(observer, Object);
+ dojo.lang.assertType(observer.observedObjectHasChanged, Function);
+ if (!this._arrayOfObservers) {
+ this._arrayOfObservers = [];
+ }
+ if (!dojo.lang.inArray(this._arrayOfObservers, observer)) {
+ this._arrayOfObservers.push(observer);
+ }
+};
+
+dojo.data.Observable.prototype.removeObserver = function(/* object */ observer) {
+ /**
+ * summary: Removes the observer registration for a previously
+ * registered object.
+ */
+ if (!this._arrayOfObservers) {
+ return;
+ }
+ var index = dojo.lang.indexOf(this._arrayOfObservers, observer);
+ if (index != -1) {
+ this._arrayOfObservers.splice(index, 1);
+ }
+};
+
+dojo.data.Observable.prototype.getObservers = function() {
+ /**
+ * summary: Returns an array with all the observers of this item.
+ */
+ return this._arrayOfObservers; // Array or undefined
+};
+
diff --git a/source/web/scripts/ajax/src/data/ResultSet.js b/source/web/scripts/ajax/src/data/ResultSet.js
new file mode 100644
index 0000000000..a5839971e2
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/ResultSet.js
@@ -0,0 +1,60 @@
+dojo.provide("dojo.data.ResultSet");
+dojo.require("dojo.lang.assert");
+dojo.require("dojo.collections.Collections");
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+dojo.data.ResultSet = function(/* dojo.data.provider.Base */ dataProvider, /* Array */ arrayOfItems) {
+ /**
+ * summary:
+ * A ResultSet holds a collection of Items. A data provider
+ * returns a ResultSet in reponse to a query.
+ * (The name "Result Set" comes from the MySQL terminology.)
+ */
+ dojo.lang.assertType(dataProvider, dojo.data.provider.Base, {optional: true});
+ dojo.lang.assertType(arrayOfItems, Array, {optional: true});
+ dojo.data.Observable.call(this);
+ this._dataProvider = dataProvider;
+ this._arrayOfItems = [];
+ if (arrayOfItems) {
+ this._arrayOfItems = arrayOfItems;
+ }
+};
+dojo.inherits(dojo.data.ResultSet, dojo.data.Observable);
+
+// -------------------------------------------------------------------
+// Public instance methods
+// -------------------------------------------------------------------
+dojo.data.ResultSet.prototype.toString = function() {
+ var returnString = this._arrayOfItems.join(', ');
+ return returnString; // string
+};
+
+dojo.data.ResultSet.prototype.toArray = function() {
+ return this._arrayOfItems; // Array
+};
+
+dojo.data.ResultSet.prototype.getIterator = function() {
+ return new dojo.collections.Iterator(this._arrayOfItems);
+};
+
+dojo.data.ResultSet.prototype.getLength = function() {
+ return this._arrayOfItems.length; // integer
+};
+
+dojo.data.ResultSet.prototype.getItemAt = function(/* numeric */ index) {
+ return this._arrayOfItems[index];
+};
+
+dojo.data.ResultSet.prototype.indexOf = function(/* dojo.data.Item */ item) {
+ return dojo.lang.indexOf(this._arrayOfItems, item); // integer
+};
+
+dojo.data.ResultSet.prototype.contains = function(/* dojo.data.Item */ item) {
+ return dojo.lang.inArray(this._arrayOfItems, item); // boolean
+};
+
+dojo.data.ResultSet.prototype.getDataProvider = function() {
+ return this._dataProvider; // dojo.data.provider.Base
+};
\ No newline at end of file
diff --git a/source/web/scripts/ajax/src/data/SimpleStore.js b/source/web/scripts/ajax/src/data/SimpleStore.js
new file mode 100644
index 0000000000..29d830fd77
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/SimpleStore.js
@@ -0,0 +1,194 @@
+dojo.provide("dojo.data.SimpleStore");
+dojo.require("dojo.lang");
+
+dojo.require("dojo.experimental");
+dojo.experimental("dojo.data.SimpleStore");
+
+/* SimpleStore
+ * Designed to be a simple store of data with access methods...
+ * specifically to be mixed into other objects (such as widgets).
+ *
+ * This *might* be better in collections, we'll see.
+ */
+dojo.data.SimpleStore = function(/* array? */json){
+ // summary
+ // Data Store with accessor methods.
+ var data = [];
+ this.keyField = "Id";
+
+ this.get = function(){
+ // summary
+ // Get the internal data array, should not be used.
+ return data; // array
+ };
+ this.getByKey = function(/* string */key){
+ // summary
+ // Find the internal data object by key.
+ for(var i=0; i-1){
+ data.splice(idx,1);
+ }
+ this.onRemoveData(o);
+ };
+ this.removeDataByKey = function(/*string*/key){
+ // summary
+ // remove the object at key from the internal data array.
+ this.removeData(this.getDataByKey(key));
+ };
+ this.removeDataByIndex = function(/*number*/idx){
+ // summary
+ // remove the object at idx from the internal data array.
+ this.removeData(this.getDataByIndex(idx));
+ };
+
+ if(json && json.length && json[0]){
+ this.setData(json);
+ }
+};
+
+dojo.lang.extend(dojo.data.SimpleStore, {
+ getField:function(/*object*/obj, /*string*/field){
+ // helper to get the nested value if needed.
+ var parts=field.split("."), i=0, o=obj;
+ do{
+ if(parts[i].indexOf("()")>-1){
+ var temp=parts[i++].split("()")[0];
+ if(!o[temp]){
+ dojo.raise("dojo.data.SimpleStore.getField(obj, '" + field + "'): '" + field + "' is not a property of the passed object.");
+ } else {
+ o = o[temp]();
+ }
+ } else {
+ o = o[parts[i++]];
+ }
+ } while (i
+ * "Title, Year, Producer \n Alien, 1979, Ridley Scott \n Blade Runner, 1982, Ridley Scott"
+ *
+ * We will return this data structure:
+ *
+ */
+ dojo.lang.assertType(csvFileContents, String);
+
+ var lineEndingCharacters = new RegExp("\r\n|\n|\r");
+ var leadingWhiteSpaceCharacters = new RegExp("^\\s+",'g');
+ var trailingWhiteSpaceCharacters = new RegExp("\\s+$",'g');
+ var doubleQuotes = new RegExp('""','g');
+ var arrayOfOutputRecords = [];
+
+ var arrayOfInputLines = csvFileContents.split(lineEndingCharacters);
+ for (var i in arrayOfInputLines) {
+ var singleLine = arrayOfInputLines[i];
+ if (singleLine.length > 0) {
+ var listOfFields = singleLine.split(',');
+ var j = 0;
+ while (j < listOfFields.length) {
+ var space_field_space = listOfFields[j];
+ var field_space = space_field_space.replace(leadingWhiteSpaceCharacters, ''); // trim leading whitespace
+ var field = field_space.replace(trailingWhiteSpaceCharacters, ''); // trim trailing whitespace
+ var firstChar = field.charAt(0);
+ var lastChar = field.charAt(field.length - 1);
+ var secondToLastChar = field.charAt(field.length - 2);
+ var thirdToLastChar = field.charAt(field.length - 3);
+ if ((firstChar == '"') &&
+ ((lastChar != '"') ||
+ ((lastChar == '"') && (secondToLastChar == '"') && (thirdToLastChar != '"')) )) {
+ if (j+1 === listOfFields.length) {
+ // alert("The last field in record " + i + " is corrupted:\n" + field);
+ return null;
+ }
+ var nextField = listOfFields[j+1];
+ listOfFields[j] = field_space + ',' + nextField;
+ listOfFields.splice(j+1, 1); // delete element [j+1] from the list
+ } else {
+ if ((firstChar == '"') && (lastChar == '"')) {
+ field = field.slice(1, (field.length - 1)); // trim the " characters off the ends
+ field = field.replace(doubleQuotes, '"'); // replace "" with "
+ }
+ listOfFields[j] = field;
+ j += 1;
+ }
+ }
+ arrayOfOutputRecords.push(listOfFields);
+ }
+ }
+ return arrayOfOutputRecords; // Array
+ };
+
+ this.loadDataProviderFromFileContents = function(/* dojo.data.provider.Base */ dataProvider, /* string */ csvFileContents) {
+ dojo.lang.assertType(dataProvider, dojo.data.provider.Base);
+ dojo.lang.assertType(csvFileContents, String);
+ var arrayOfArrays = this.getArrayStructureFromCsvFileContents(csvFileContents);
+ if (arrayOfArrays) {
+ var arrayOfKeys = arrayOfArrays[0];
+ for (var i = 1; i < arrayOfArrays.length; ++i) {
+ var row = arrayOfArrays[i];
+ var item = dataProvider.getNewItemToLoad();
+ for (var j in row) {
+ var value = row[j];
+ var key = arrayOfKeys[j];
+ item.load(key, value);
+ }
+ }
+ }
+ };
+
+ this.getCsvStringFromResultSet = function(/* dojo.data.ResultSet */ resultSet) {
+ dojo.unimplemented('dojo.data.format.Csv.getCsvStringFromResultSet');
+ var csvString = null;
+ return csvString; // String
+ };
+
+}();
diff --git a/source/web/scripts/ajax/src/data/format/Json.js b/source/web/scripts/ajax/src/data/format/Json.js
new file mode 100644
index 0000000000..16e3d07863
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/format/Json.js
@@ -0,0 +1,93 @@
+dojo.provide("dojo.data.format.Json");
+dojo.require("dojo.lang.assert");
+
+dojo.data.format.Json = new function() {
+
+ // -------------------------------------------------------------------
+ // Public functions
+ // -------------------------------------------------------------------
+ this.loadDataProviderFromFileContents = function(/* dojo.data.provider.Base */ dataProvider, /* string */ jsonFileContents) {
+ dojo.lang.assertType(dataProvider, dojo.data.provider.Base);
+ dojo.lang.assertType(jsonFileContents, String);
+ var arrayOfJsonData = eval("(" + jsonFileContents + ")");
+ this.loadDataProviderFromArrayOfJsonData(dataProvider, arrayOfJsonData);
+ };
+
+ this.loadDataProviderFromArrayOfJsonData = function(/* dojo.data.provider.Base */ dataProvider, /* Array */ arrayOfJsonData) {
+ dojo.lang.assertType(arrayOfJsonData, Array, {optional: true});
+ if (arrayOfJsonData && (arrayOfJsonData.length > 0)) {
+ var firstRow = arrayOfJsonData[0];
+ dojo.lang.assertType(firstRow, [Array, "pureobject"]);
+ if (dojo.lang.isArray(firstRow)) {
+ _loadDataProviderFromArrayOfArrays(dataProvider, arrayOfJsonData);
+ } else {
+ dojo.lang.assertType(firstRow, "pureobject");
+ _loadDataProviderFromArrayOfObjects(dataProvider, arrayOfJsonData);
+ }
+ }
+ };
+
+ this.getJsonStringFromResultSet = function(/* dojo.data.ResultSet */ resultSet) {
+ dojo.unimplemented('dojo.data.format.Json.getJsonStringFromResultSet');
+ var jsonString = null;
+ return jsonString; // String
+ };
+
+ // -------------------------------------------------------------------
+ // Private functions
+ // -------------------------------------------------------------------
+ function _loadDataProviderFromArrayOfArrays(/* dojo.data.provider.Base */ dataProvider, /* Array */ arrayOfJsonData) {
+ /**
+ * Example:
+ * var arrayOfJsonStates = [
+ * [ "abbr", "population", "name" ]
+ * [ "WA", 5894121, "Washington" ],
+ * [ "WV", 1808344, "West Virginia" ],
+ * [ "WI", 5453896, "Wisconsin" ],
+ * [ "WY", 493782, "Wyoming" ] ];
+ * this._loadFromArrayOfArrays(arrayOfJsonStates);
+ */
+ var arrayOfKeys = arrayOfJsonData[0];
+ for (var i = 1; i < arrayOfJsonData.length; ++i) {
+ var row = arrayOfJsonData[i];
+ var item = dataProvider.getNewItemToLoad();
+ for (var j in row) {
+ var value = row[j];
+ var key = arrayOfKeys[j];
+ item.load(key, value);
+ }
+ }
+ }
+
+ function _loadDataProviderFromArrayOfObjects(/* dojo.data.provider.Base */ dataProvider, /* Array */ arrayOfJsonData) {
+ /**
+ * Example:
+ * var arrayOfJsonStates = [
+ * { abbr: "WA", name: "Washington" },
+ * { abbr: "WV", name: "West Virginia" },
+ * { abbr: "WI", name: "Wisconsin", song: "On, Wisconsin!" },
+ * { abbr: "WY", name: "Wyoming", cities: ["Lander", "Cheyenne", "Laramie"] } ];
+ * this._loadFromArrayOfArrays(arrayOfJsonStates);
+ */
+ // dojo.debug("_loadDataProviderFromArrayOfObjects");
+ for (var i in arrayOfJsonData) {
+ var row = arrayOfJsonData[i];
+ var item = dataProvider.getNewItemToLoad();
+ for (var key in row) {
+ var value = row[key];
+ if (dojo.lang.isArray(value)) {
+ var arrayOfValues = value;
+ for (var j in arrayOfValues) {
+ value = arrayOfValues[j];
+ item.load(key, value);
+ // dojo.debug("loaded: " + key + " = " + value);
+ }
+ } else {
+ item.load(key, value);
+ }
+ }
+ }
+ }
+
+}();
+
diff --git a/source/web/scripts/ajax/src/data/provider/Base.js b/source/web/scripts/ajax/src/data/provider/Base.js
new file mode 100644
index 0000000000..2dd45ce85e
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/provider/Base.js
@@ -0,0 +1,173 @@
+dojo.provide("dojo.data.provider.Base");
+dojo.require("dojo.lang.assert");
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+dojo.data.provider.Base = function() {
+ /**
+ * summary:
+ * A Data Provider serves as a connection to some data source,
+ * like a relational database. This data provider Base class
+ * serves as an abstract superclass for other data provider
+ * classes.
+ */
+ this._countOfNestedTransactions = 0;
+ this._changesInCurrentTransaction = null;
+};
+
+// -------------------------------------------------------------------
+// Public instance methods
+// -------------------------------------------------------------------
+dojo.data.provider.Base.prototype.beginTransaction = function() {
+ /**
+ * Marks the beginning of a transaction.
+ *
+ * Each time you call beginTransaction() you open a new transaction,
+ * which you need to close later using endTransaction(). Transactions
+ * may be nested, but the beginTransaction and endTransaction calls
+ * always need to come in pairs.
+ */
+ if (this._countOfNestedTransactions === 0) {
+ this._changesInCurrentTransaction = [];
+ }
+ this._countOfNestedTransactions += 1;
+};
+
+dojo.data.provider.Base.prototype.endTransaction = function() {
+ /**
+ * Marks the end of a transaction.
+ */
+ this._countOfNestedTransactions -= 1;
+ dojo.lang.assert(this._countOfNestedTransactions >= 0);
+
+ if (this._countOfNestedTransactions === 0) {
+ var listOfChangesMade = this._saveChanges();
+ this._changesInCurrentTransaction = null;
+ if (listOfChangesMade.length > 0) {
+ // dojo.debug("endTransaction: " + listOfChangesMade.length + " changes made");
+ this._notifyObserversOfChanges(listOfChangesMade);
+ }
+ }
+};
+
+dojo.data.provider.Base.prototype.getNewItemToLoad = function() {
+ return this._newItem(); // dojo.data.Item
+};
+
+dojo.data.provider.Base.prototype.newItem = function(/* string */ itemName) {
+ /**
+ * Creates a new item.
+ */
+ dojo.lang.assertType(itemName, String, {optional: true});
+ var item = this._newItem();
+ if (itemName) {
+ item.set('name', itemName);
+ }
+ return item; // dojo.data.Item
+};
+
+dojo.data.provider.Base.prototype.newAttribute = function(/* string */ attributeId) {
+ /**
+ * Creates a new attribute.
+ */
+ dojo.lang.assertType(attributeId, String, {optional: true});
+ var attribute = this._newAttribute(attributeId);
+ return attribute; // dojo.data.Attribute
+};
+
+dojo.data.provider.Base.prototype.getAttribute = function(/* string */ attributeId) {
+ dojo.unimplemented('dojo.data.provider.Base');
+ var attribute;
+ return attribute; // dojo.data.Attribute
+};
+
+dojo.data.provider.Base.prototype.getAttributes = function() {
+ dojo.unimplemented('dojo.data.provider.Base');
+ return this._arrayOfAttributes; // Array
+};
+
+dojo.data.provider.Base.prototype.fetchArray = function() {
+ dojo.unimplemented('dojo.data.provider.Base');
+ return []; // Array
+};
+
+dojo.data.provider.Base.prototype.fetchResultSet = function() {
+ dojo.unimplemented('dojo.data.provider.Base');
+ var resultSet;
+ return resultSet; // dojo.data.ResultSet
+};
+
+dojo.data.provider.Base.prototype.noteChange = function(/* dojo.data.Item */ item, /* string or dojo.data.Attribute */ attribute, /* anything */ value) {
+ var change = {item: item, attribute: attribute, value: value};
+ if (this._countOfNestedTransactions === 0) {
+ this.beginTransaction();
+ this._changesInCurrentTransaction.push(change);
+ this.endTransaction();
+ } else {
+ this._changesInCurrentTransaction.push(change);
+ }
+};
+
+dojo.data.provider.Base.prototype.addItemObserver = function(/* dojo.data.Item */ item, /* object */ observer) {
+ /**
+ * summary: Registers an object as an observer of an item,
+ * so that the object will be notified when the item changes.
+ */
+ dojo.lang.assertType(item, dojo.data.Item);
+ item.addObserver(observer);
+};
+
+dojo.data.provider.Base.prototype.removeItemObserver = function(/* dojo.data.Item */ item, /* object */ observer) {
+ /**
+ * summary: Removes the observer registration for a previously
+ * registered object.
+ */
+ dojo.lang.assertType(item, dojo.data.Item);
+ item.removeObserver(observer);
+};
+
+// -------------------------------------------------------------------
+// Private instance methods
+// -------------------------------------------------------------------
+dojo.data.provider.Base.prototype._newItem = function() {
+ var item = new dojo.data.Item(this);
+ return item; // dojo.data.Item
+};
+
+dojo.data.provider.Base.prototype._newAttribute = function(/* String */ attributeId) {
+ var attribute = new dojo.data.Attribute(this);
+ return attribute; // dojo.data.Attribute
+};
+
+dojo.data.provider.Base.prototype._saveChanges = function() {
+ var arrayOfChangesMade = this._changesInCurrentTransaction;
+ return arrayOfChangesMade; // Array
+};
+
+dojo.data.provider.Base.prototype._notifyObserversOfChanges = function(/* Array */ arrayOfChanges) {
+ var arrayOfResultSets = this._getResultSets();
+ for (var i in arrayOfChanges) {
+ var change = arrayOfChanges[i];
+ var changedItem = change.item;
+ var arrayOfItemObservers = changedItem.getObservers();
+ for (var j in arrayOfItemObservers) {
+ var observer = arrayOfItemObservers[j];
+ observer.observedObjectHasChanged(changedItem, change);
+ }
+ for (var k in arrayOfResultSets) {
+ var resultSet = arrayOfResultSets[k];
+ var arrayOfResultSetObservers = resultSet.getObservers();
+ for (var m in arrayOfResultSetObservers) {
+ observer = arrayOfResultSetObservers[m];
+ observer.observedObjectHasChanged(resultSet, change);
+ }
+ }
+ }
+};
+
+dojo.data.provider.Base.prototype._getResultSets = function() {
+ dojo.unimplemented('dojo.data.provider.Base');
+ return []; // Array
+};
+
diff --git a/source/web/scripts/ajax/src/data/provider/Delicious.js b/source/web/scripts/ajax/src/data/provider/Delicious.js
new file mode 100644
index 0000000000..307b8e9207
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/provider/Delicious.js
@@ -0,0 +1,75 @@
+dojo.provide("dojo.data.provider.Delicious");
+dojo.require("dojo.data.provider.FlatFile");
+dojo.require("dojo.data.format.Json");
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+dojo.data.provider.Delicious = function() {
+ /**
+ * summary:
+ * The Delicious Data Provider can be used to take data from
+ * del.icio.us and make it available as dojo.data.Items
+ * In order to use the Delicious Data Provider, you need
+ * to have loaded a script tag that looks like this:
+ *
+ */
+ dojo.data.provider.FlatFile.call(this);
+ // Delicious = null;
+ if (Delicious && Delicious.posts) {
+ dojo.data.format.Json.loadDataProviderFromArrayOfJsonData(this, Delicious.posts);
+ } else {
+ // document.write("");
+ /*
+ document.write("");
+ document.write("");
+ document.write("");
+ fetchComplete();
+ */
+ // dojo.debug("Delicious line 29: constructor");
+ }
+ var u = this.registerAttribute('u');
+ var d = this.registerAttribute('d');
+ var t = this.registerAttribute('t');
+
+ u.load('name', 'Bookmark');
+ d.load('name', 'Description');
+ t.load('name', 'Tags');
+
+ u.load('type', 'String');
+ d.load('type', 'String');
+ t.load('type', 'String');
+};
+dojo.inherits(dojo.data.provider.Delicious, dojo.data.provider.FlatFile);
+
+/********************************************************************
+ * FIXME: the rest of this is work in progress
+ *
+
+dojo.data.provider.Delicious.prototype.getNewItemToLoad = function() {
+ var newItem = this._newItem();
+ this._currentArray.push(newItem);
+ return newItem; // dojo.data.Item
+};
+
+dojo.data.provider.Delicious.prototype.fetchArray = function(query) {
+ if (!query) {
+ query = "gumption";
+ }
+ this._currentArray = [];
+ alert("Delicious line 60: loadDataProviderFromArrayOfJsonData");
+ alert("Delicious line 61: " + dojo);
+ var sourceUrl = "http://del.icio.us/feeds/json/" + query + "?count=8";
+ document.write("");
+ document.write("");
+ document.write("");
+ alert("line 66");
+ dojo.data.format.Json.loadDataProviderFromArrayOfJsonData(this, Delicious.posts);
+ return this._currentArray; // Array
+};
+
+callMe = function() {
+ alert("callMe!");
+};
+
+*/
diff --git a/source/web/scripts/ajax/src/data/provider/FlatFile.js b/source/web/scripts/ajax/src/data/provider/FlatFile.js
new file mode 100644
index 0000000000..23b0b395af
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/provider/FlatFile.js
@@ -0,0 +1,143 @@
+dojo.provide("dojo.data.provider.FlatFile");
+dojo.require("dojo.data.provider.Base");
+dojo.require("dojo.data.Item");
+dojo.require("dojo.data.Attribute");
+dojo.require("dojo.data.ResultSet");
+dojo.require("dojo.data.format.Json");
+dojo.require("dojo.data.format.Csv");
+dojo.require("dojo.lang.assert");
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+dojo.data.provider.FlatFile = function(/* keywords */ keywordParameters) {
+ /**
+ * summary:
+ * A Json Data Provider knows how to read in simple JSON data
+ * tables and make their contents accessable as Items.
+ */
+ dojo.lang.assertType(keywordParameters, "pureobject", {optional: true});
+ dojo.data.provider.Base.call(this);
+ this._arrayOfItems = [];
+ this._resultSet = null;
+ this._dictionaryOfAttributes = {};
+
+ if (keywordParameters) {
+ var jsonObjects = keywordParameters["jsonObjects"];
+ var jsonString = keywordParameters["jsonString"];
+ var fileUrl = keywordParameters["url"];
+ if (jsonObjects) {
+ dojo.data.format.Json.loadDataProviderFromArrayOfJsonData(this, jsonObjects);
+ }
+ if (jsonString) {
+ dojo.data.format.Json.loadDataProviderFromFileContents(this, jsonString);
+ }
+ if (fileUrl) {
+ var arrayOfParts = fileUrl.split('.');
+ var lastPart = arrayOfParts[(arrayOfParts.length - 1)];
+ var formatParser = null;
+ if (lastPart == "json") {
+ formatParser = dojo.data.format.Json;
+ }
+ if (lastPart == "csv") {
+ formatParser = dojo.data.format.Csv;
+ }
+ if (formatParser) {
+ var fileContents = dojo.hostenv.getText(fileUrl);
+ formatParser.loadDataProviderFromFileContents(this, fileContents);
+ } else {
+ dojo.lang.assert(false, "new dojo.data.provider.FlatFile({url: }) was passed a file without a .csv or .json suffix");
+ }
+ }
+ }
+};
+dojo.inherits(dojo.data.provider.FlatFile, dojo.data.provider.Base);
+
+// -------------------------------------------------------------------
+// Public instance methods
+// -------------------------------------------------------------------
+dojo.data.provider.FlatFile.prototype.getProviderCapabilities = function(/* string */ keyword) {
+ dojo.lang.assertType(keyword, String, {optional: true});
+ if (!this._ourCapabilities) {
+ this._ourCapabilities = {
+ transactions: false,
+ undo: false,
+ login: false,
+ versioning: false,
+ anonymousRead: true,
+ anonymousWrite: false,
+ permissions: false,
+ queries: false,
+ strongTyping: false,
+ datatypes: [String, Date, Number]
+ };
+ }
+ if (keyword) {
+ return this._ourCapabilities[keyword];
+ } else {
+ return this._ourCapabilities;
+ }
+};
+
+dojo.data.provider.FlatFile.prototype.registerAttribute = function(/* string or dojo.data.Attribute */ attributeId) {
+ var registeredAttribute = this.getAttribute(attributeId);
+ if (!registeredAttribute) {
+ var newAttribute = new dojo.data.Attribute(this, attributeId);
+ this._dictionaryOfAttributes[attributeId] = newAttribute;
+ registeredAttribute = newAttribute;
+ }
+ return registeredAttribute; // dojo.data.Attribute
+};
+
+dojo.data.provider.FlatFile.prototype.getAttribute = function(/* string or dojo.data.Attribute */ attributeId) {
+ var attribute = (this._dictionaryOfAttributes[attributeId] || null);
+ return attribute; // dojo.data.Attribute or null
+};
+
+dojo.data.provider.FlatFile.prototype.getAttributes = function() {
+ var arrayOfAttributes = [];
+ for (var key in this._dictionaryOfAttributes) {
+ var attribute = this._dictionaryOfAttributes[key];
+ arrayOfAttributes.push(attribute);
+ }
+ return arrayOfAttributes; // Array
+};
+
+dojo.data.provider.FlatFile.prototype.fetchArray = function(query) {
+ /**
+ * summary: Returns an Array containing all of the Items.
+ */
+ return this._arrayOfItems; // Array
+};
+
+dojo.data.provider.FlatFile.prototype.fetchResultSet = function(query) {
+ /**
+ * summary: Returns a ResultSet containing all of the Items.
+ */
+ if (!this._resultSet) {
+ this._resultSet = new dojo.data.ResultSet(this, this.fetchArray(query));
+ }
+ return this._resultSet; // dojo.data.ResultSet
+};
+
+// -------------------------------------------------------------------
+// Private instance methods
+// -------------------------------------------------------------------
+dojo.data.provider.FlatFile.prototype._newItem = function() {
+ var item = new dojo.data.Item(this);
+ this._arrayOfItems.push(item);
+ return item; // dojo.data.Item
+};
+
+dojo.data.provider.FlatFile.prototype._newAttribute = function(/* String */ attributeId) {
+ dojo.lang.assertType(attributeId, String);
+ dojo.lang.assert(this.getAttribute(attributeId) === null);
+ var attribute = new dojo.data.Attribute(this, attributeId);
+ this._dictionaryOfAttributes[attributeId] = attribute;
+ return attribute; // dojo.data.Attribute
+};
+
+dojo.data.provider.Base.prototype._getResultSets = function() {
+ return [this._resultSet]; // Array
+};
+
diff --git a/source/web/scripts/ajax/src/data/provider/JotSpot.js b/source/web/scripts/ajax/src/data/provider/JotSpot.js
new file mode 100644
index 0000000000..e5c7cc3989
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/provider/JotSpot.js
@@ -0,0 +1,17 @@
+dojo.provide("dojo.data.provider.JotSpot");
+dojo.require("dojo.data.provider.Base");
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+dojo.data.provider.JotSpot = function() {
+ /**
+ * summary:
+ * A JotSpot Data Provider knows how to read data from a JotSpot data
+ * store and make the contents accessable as dojo.data.Items.
+ */
+ dojo.unimplemented('dojo.data.provider.JotSpot');
+};
+
+dojo.inherits(dojo.data.provider.JotSpot, dojo.data.provider.Base);
+
diff --git a/source/web/scripts/ajax/src/data/provider/MySql.js b/source/web/scripts/ajax/src/data/provider/MySql.js
new file mode 100644
index 0000000000..6b3036075d
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/provider/MySql.js
@@ -0,0 +1,17 @@
+dojo.provide("dojo.data.provider.MySql");
+dojo.require("dojo.data.provider.Base");
+
+// -------------------------------------------------------------------
+// Constructor
+// -------------------------------------------------------------------
+dojo.data.provider.MySql = function() {
+ /**
+ * summary:
+ * A MySql Data Provider knows how to connect to a MySQL database
+ * on a server and and make the content records available as
+ * dojo.data.Items.
+ */
+ dojo.unimplemented('dojo.data.provider.MySql');
+};
+
+dojo.inherits(dojo.data.provider.MySql, dojo.data.provider.Base);
diff --git a/source/web/scripts/ajax/src/data/to_do.txt b/source/web/scripts/ajax/src/data/to_do.txt
new file mode 100644
index 0000000000..6e705fc6c3
--- /dev/null
+++ b/source/web/scripts/ajax/src/data/to_do.txt
@@ -0,0 +1,45 @@
+Existing Features
+ * can import data from .json or .csv format files
+ * can import data from del.icio.us
+ * can create and modify data programmatically
+ * can bind data to dojo.widget.Chart
+ * can bind data to dojo.widget.SortableTable
+ * can bind one data set to multiple widgets
+ * notifications: widgets are notified when data changes
+ * notification available per-item or per-resultSet
+ * can create ad-hoc attributes
+ * attributes can be loosely-typed
+ * attributes can have meta-data like type and display name
+ * half-implemented support for sorting
+ * half-implemented support for export to .json
+ * API for getting data in simple arrays
+ * API for getting ResultSets with iterators (precursor to support for something like the openrico.org live grid)
+
+~~~~~~~~~~~~~~~~~~~~~~~~
+To-Do List
+ * be able to import data from an html
+ * think about being able to import data from some type of XML
+ * think about integration with dojo.undo.Manager
+ * think more about how to represent the notion of different data types
+ * think about what problems we'll run into when we have a MySQL data provider
+ * in TableBindingHack, improve support for data types in the SortableTable binding
+ * deal with ids (including MySQL multi-field keys)
+ * add support for item-references: employeeItem.set('department', departmentItem);
+ * deal with Attributes as instances of Items, not just subclasses of Items
+ * unit tests for compare/sort code
+ * unit tests for everything
+ * implement item.toString('json') and item.toString('xml')
+ * implement dataProvider.newItem({name: 'foo', age: 26})
+ * deal better with transactions
+ * add support for deleting items
+ * don't send out multiple notifications to the same observer
+ * deal with item versions
+ * prototype a Yahoo data provider -- http://developer.yahoo.net/common/json.html
+ * prototype a data provider that enforces strong typing
+ * prototype a data provider that prevents ad-hoc attributes
+ * prototype a data provider that enforces single-kind item
+ * prototype a data provider that allows for login/authentication
+ * have loosely typed result sets play nicely with widgets that expect strong typing
+ * prototype an example of spreadsheet-style formulas or derivation rules
+ * experiment with some sort of fetch() that returns only a subset of a data provider's items
+
diff --git a/source/web/scripts/ajax/src/date.js b/source/web/scripts/ajax/src/date.js
new file mode 100644
index 0000000000..0f976eec19
--- /dev/null
+++ b/source/web/scripts/ajax/src/date.js
@@ -0,0 +1,614 @@
+dojo.provide("dojo.date");
+
+
+/* Supplementary Date Functions
+ *******************************/
+
+dojo.date.setDayOfYear = function (dateObject, dayofyear) {
+ dateObject.setMonth(0);
+ dateObject.setDate(dayofyear);
+ return dateObject;
+}
+
+dojo.date.getDayOfYear = function (dateObject) {
+ var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1);
+ return Math.floor((dateObject.getTime() -
+ firstDayOfYear.getTime()) / 86400000);
+}
+
+
+
+
+dojo.date.setWeekOfYear = function (dateObject, week, firstDay) {
+ if (arguments.length == 1) { firstDay = 0; } // Sunday
+ dojo.unimplemented("dojo.date.setWeekOfYear");
+}
+
+dojo.date.getWeekOfYear = function (dateObject, firstDay) {
+ if (arguments.length == 1) { firstDay = 0; } // Sunday
+
+ // work out the first day of the year corresponding to the week
+ var firstDayOfYear = new Date(dateObject.getFullYear(), 0, 1);
+ var day = firstDayOfYear.getDay();
+ firstDayOfYear.setDate(firstDayOfYear.getDate() -
+ day + firstDay - (day > firstDay ? 7 : 0));
+
+ return Math.floor((dateObject.getTime() -
+ firstDayOfYear.getTime()) / 604800000);
+}
+
+
+
+
+dojo.date.setIsoWeekOfYear = function (dateObject, week, firstDay) {
+ if (arguments.length == 1) { firstDay = 1; } // Monday
+ dojo.unimplemented("dojo.date.setIsoWeekOfYear");
+}
+
+dojo.date.getIsoWeekOfYear = function (dateObject, firstDay) {
+ if (arguments.length == 1) { firstDay = 1; } // Monday
+ dojo.unimplemented("dojo.date.getIsoWeekOfYear");
+}
+
+
+
+
+/* ISO 8601 Functions
+ *********************/
+
+dojo.date.setIso8601 = function (dateObject, string){
+ var comps = (string.indexOf("T") == -1) ? string.split(" ") : string.split("T");
+ dojo.date.setIso8601Date(dateObject, comps[0]);
+ if (comps.length == 2) { dojo.date.setIso8601Time(dateObject, comps[1]); }
+ return dateObject;
+}
+
+dojo.date.fromIso8601 = function (string) {
+ return dojo.date.setIso8601(new Date(0, 0), string);
+}
+
+
+
+
+dojo.date.setIso8601Date = function (dateObject, string) {
+ var regexp = "^([0-9]{4})((-?([0-9]{2})(-?([0-9]{2}))?)|" +
+ "(-?([0-9]{3}))|(-?W([0-9]{2})(-?([1-7]))?))?$";
+ var d = string.match(new RegExp(regexp));
+ if(!d) {
+ dojo.debug("invalid date string: " + string);
+ return false;
+ }
+ var year = d[1];
+ var month = d[4];
+ var date = d[6];
+ var dayofyear = d[8];
+ var week = d[10];
+ var dayofweek = (d[12]) ? d[12] : 1;
+
+ dateObject.setYear(year);
+
+ if (dayofyear) { dojo.date.setDayOfYear(dateObject, Number(dayofyear)); }
+ else if (week) {
+ dateObject.setMonth(0);
+ dateObject.setDate(1);
+ var gd = dateObject.getDay();
+ var day = (gd) ? gd : 7;
+ var offset = Number(dayofweek) + (7 * Number(week));
+
+ if (day <= 4) { dateObject.setDate(offset + 1 - day); }
+ else { dateObject.setDate(offset + 8 - day); }
+ } else {
+ if (month) {
+ dateObject.setDate(1);
+ dateObject.setMonth(month - 1);
+ }
+ if (date) { dateObject.setDate(date); }
+ }
+
+ return dateObject;
+}
+
+dojo.date.fromIso8601Date = function (string) {
+ return dojo.date.setIso8601Date(new Date(0, 0), string);
+}
+
+
+
+
+dojo.date.setIso8601Time = function (dateObject, string) {
+ // first strip timezone info from the end
+ var timezone = "Z|(([-+])([0-9]{2})(:?([0-9]{2}))?)$";
+ var d = string.match(new RegExp(timezone));
+
+ var offset = 0; // local time if no tz info
+ if (d) {
+ if (d[0] != 'Z') {
+ offset = (Number(d[3]) * 60) + Number(d[5]);
+ offset *= ((d[2] == '-') ? 1 : -1);
+ }
+ offset -= dateObject.getTimezoneOffset();
+ string = string.substr(0, string.length - d[0].length);
+ }
+
+ // then work out the time
+ var regexp = "^([0-9]{2})(:?([0-9]{2})(:?([0-9]{2})(\.([0-9]+))?)?)?$";
+ var d = string.match(new RegExp(regexp));
+ if(!d) {
+ dojo.debug("invalid time string: " + string);
+ return false;
+ }
+ var hours = d[1];
+ var mins = Number((d[3]) ? d[3] : 0);
+ var secs = (d[5]) ? d[5] : 0;
+ var ms = d[7] ? (Number("0." + d[7]) * 1000) : 0;
+
+ dateObject.setHours(hours);
+ dateObject.setMinutes(mins);
+ dateObject.setSeconds(secs);
+ dateObject.setMilliseconds(ms);
+
+ if (offset != 0) {
+ dateObject.setTime(dateObject.getTime() + offset * 60000);
+ }
+ return dateObject;
+}
+
+dojo.date.fromIso8601Time = function (string) {
+ return dojo.date.setIso8601Time(new Date(0, 0), string);
+}
+
+
+
+/* Informational Functions
+ **************************/
+
+dojo.date.shortTimezones = ["IDLW", "BET", "HST", "MART", "AKST", "PST", "MST",
+ "CST", "EST", "AST", "NFT", "BST", "FST", "AT", "GMT", "CET", "EET", "MSK",
+ "IRT", "GST", "AFT", "AGTT", "IST", "NPT", "ALMT", "MMT", "JT", "AWST",
+ "JST", "ACST", "AEST", "LHST", "VUT", "NFT", "NZT", "CHAST", "PHOT",
+ "LINT"];
+dojo.date.timezoneOffsets = [-720, -660, -600, -570, -540, -480, -420, -360,
+ -300, -240, -210, -180, -120, -60, 0, 60, 120, 180, 210, 240, 270, 300,
+ 330, 345, 360, 390, 420, 480, 540, 570, 600, 630, 660, 690, 720, 765, 780,
+ 840];
+/*
+dojo.date.timezones = ["International Date Line West", "Bering Standard Time",
+ "Hawaiian Standard Time", "Marquesas Time", "Alaska Standard Time",
+ "Pacific Standard Time (USA)", "Mountain Standard Time",
+ "Central Standard Time (USA)", "Eastern Standard Time (USA)",
+ "Atlantic Standard Time", "Newfoundland Time", "Brazil Standard Time",
+ "Fernando de Noronha Standard Time (Brazil)", "Azores Time",
+ "Greenwich Mean Time", "Central Europe Time", "Eastern Europe Time",
+ "Moscow Time", "Iran Standard Time", "Gulf Standard Time",
+ "Afghanistan Time", "Aqtobe Time", "Indian Standard Time", "Nepal Time",
+ "Almaty Time", "Myanmar Time", "Java Time",
+ "Australian Western Standard Time", "Japan Standard Time",
+ "Australian Central Standard Time", "Lord Hove Standard Time (Australia)",
+ "Vanuata Time", "Norfolk Time (Australia)", "New Zealand Standard Time",
+ "Chatham Standard Time (New Zealand)", "Phoenix Islands Time (Kribati)",
+ "Line Islands Time (Kribati)"];
+*/
+dojo.date.months = ["January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"];
+dojo.date.shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "June",
+ "July", "Aug", "Sep", "Oct", "Nov", "Dec"];
+dojo.date.days = ["Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday"];
+dojo.date.shortDays = ["Sun", "Mon", "Tues", "Wed", "Thur", "Fri", "Sat"];
+
+
+dojo.date.getDaysInMonth = function (dateObject) {
+ var month = dateObject.getMonth();
+ var days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+ if (month == 1 && dojo.date.isLeapYear(dateObject)) { return 29; }
+ else { return days[month]; }
+}
+
+dojo.date.isLeapYear = function (dateObject) {
+ /*
+ * Leap years are years with an additional day YYYY-02-29, where the year
+ * number is a multiple of four with the following exception: If a year
+ * is a multiple of 100, then it is only a leap year if it is also a
+ * multiple of 400. For example, 1900 was not a leap year, but 2000 is one.
+ */
+ var year = dateObject.getFullYear();
+ return (year%400 == 0) ? true : (year%100 == 0) ? false : (year%4 == 0) ? true : false;
+}
+
+
+
+dojo.date.getDayName = function (dateObject) {
+ return dojo.date.days[dateObject.getDay()];
+}
+
+dojo.date.getDayShortName = function (dateObject) {
+ return dojo.date.shortDays[dateObject.getDay()];
+}
+
+
+
+
+dojo.date.getMonthName = function (dateObject) {
+ return dojo.date.months[dateObject.getMonth()];
+}
+
+dojo.date.getMonthShortName = function (dateObject) {
+ return dojo.date.shortMonths[dateObject.getMonth()];
+}
+
+
+
+
+dojo.date.getTimezoneName = function (dateObject) {
+ // need to negate timezones to get it right
+ // i.e UTC+1 is CET winter, but getTimezoneOffset returns -60
+ var timezoneOffset = -(dateObject.getTimezoneOffset());
+
+ for (var i = 0; i < dojo.date.timezoneOffsets.length; i++) {
+ if (dojo.date.timezoneOffsets[i] == timezoneOffset) {
+ return dojo.date.shortTimezones[i];
+ }
+ }
+
+ // we don't know so return it formatted as "+HH:MM"
+ function $ (s) { s = String(s); while (s.length < 2) { s = "0" + s; } return s; }
+ return (timezoneOffset < 0 ? "-" : "+") + $(Math.floor(Math.abs(
+ timezoneOffset)/60)) + ":" + $(Math.abs(timezoneOffset)%60);
+}
+
+
+
+
+dojo.date.getOrdinal = function (dateObject) {
+ var date = dateObject.getDate();
+
+ if (date%100 != 11 && date%10 == 1) { return "st"; }
+ else if (date%100 != 12 && date%10 == 2) { return "nd"; }
+ else if (date%100 != 13 && date%10 == 3) { return "rd"; }
+ else { return "th"; }
+}
+
+
+
+/* Date Formatter Functions
+ ***************************/
+
+// POSIX strftime
+// see
+dojo.date.format = dojo.date.strftime = function (dateObject, format) {
+
+ // zero pad
+ var padChar = null;
+ function _ (s, n) {
+ s = String(s);
+ n = (n || 2) - s.length;
+ while (n-- > 0) { s = (padChar == null ? "0" : padChar) + s; }
+ return s;
+ }
+
+ function $ (property) {
+ switch (property) {
+ case "a": // abbreviated weekday name according to the current locale
+ return dojo.date.getDayShortName(dateObject); break;
+
+ case "A": // full weekday name according to the current locale
+ return dojo.date.getDayName(dateObject); break;
+
+ case "b":
+ case "h": // abbreviated month name according to the current locale
+ return dojo.date.getMonthShortName(dateObject); break;
+
+ case "B": // full month name according to the current locale
+ return dojo.date.getMonthName(dateObject); break;
+
+ case "c": // preferred date and time representation for the current
+ // locale
+ return dateObject.toLocaleString(); break;
+
+ case "C": // century number (the year divided by 100 and truncated
+ // to an integer, range 00 to 99)
+ return _(Math.floor(dateObject.getFullYear()/100)); break;
+
+ case "d": // day of the month as a decimal number (range 01 to 31)
+ return _(dateObject.getDate()); break;
+
+ case "D": // same as %m/%d/%y
+ return $("m") + "/" + $("d") + "/" + $("y"); break;
+
+ case "e": // day of the month as a decimal number, a single digit is
+ // preceded by a space (range ' 1' to '31')
+ if (padChar == null) { padChar = " "; }
+ return _(dateObject.getDate(), 2); break;
+
+ case "f": // month as a decimal number, a single digit is
+ // preceded by a space (range ' 1' to '12')
+ if (padChar == null) { padChar = " "; }
+ return _(dateObject.getMonth()+1, 2); break;
+
+ case "g": // like %G, but without the century.
+ break;
+
+ case "G": // The 4-digit year corresponding to the ISO week number
+ // (see %V). This has the same format and value as %Y,
+ // except that if the ISO week number belongs to the
+ // previous or next year, that year is used instead.
+ break;
+
+ case "F": // same as %Y-%m-%d
+ return $("Y") + "-" + $("m") + "-" + $("d"); break;
+
+ case "H": // hour as a decimal number using a 24-hour clock (range
+ // 00 to 23)
+ return _(dateObject.getHours()); break;
+
+ case "I": // hour as a decimal number using a 12-hour clock (range
+ // 01 to 12)
+ return _(dateObject.getHours() % 12 || 12); break;
+
+ case "j": // day of the year as a decimal number (range 001 to 366)
+ return _(dojo.date.getDayOfYear(dateObject), 3); break;
+
+ case "m": // month as a decimal number (range 01 to 12)
+ return _(dateObject.getMonth() + 1); break;
+
+ case "M": // minute as a decimal numbe
+ return _(dateObject.getMinutes()); break;
+
+ case "n":
+ return "\n"; break;
+
+ case "p": // either `am' or `pm' according to the given time value,
+ // or the corresponding strings for the current locale
+ return dateObject.getHours() < 12 ? "am" : "pm"; break;
+
+ case "r": // time in a.m. and p.m. notation
+ return $("I") + ":" + $("M") + ":" + $("S") + " " + $("p"); break;
+
+ case "R": // time in 24 hour notation
+ return $("H") + ":" + $("M"); break;
+
+ case "S": // second as a decimal number
+ return _(dateObject.getSeconds()); break;
+
+ case "t":
+ return "\t"; break;
+
+ case "T": // current time, equal to %H:%M:%S
+ return $("H") + ":" + $("M") + ":" + $("S"); break;
+
+ case "u": // weekday as a decimal number [1,7], with 1 representing
+ // Monday
+ return String(dateObject.getDay() || 7); break;
+
+ case "U": // week number of the current year as a decimal number,
+ // starting with the first Sunday as the first day of the
+ // first week
+ return _(dojo.date.getWeekOfYear(dateObject)); break;
+
+ case "V": // week number of the year (Monday as the first day of the
+ // week) as a decimal number [01,53]. If the week containing
+ // 1 January has four or more days in the new year, then it
+ // is considered week 1. Otherwise, it is the last week of
+ // the previous year, and the next week is week 1.
+ return _(dojo.date.getIsoWeekOfYear(dateObject)); break;
+
+ case "W": // week number of the current year as a decimal number,
+ // starting with the first Monday as the first day of the
+ // first week
+ return _(dojo.date.getWeekOfYear(dateObject, 1)); break;
+
+ case "w": // day of the week as a decimal, Sunday being 0
+ return String(dateObject.getDay()); break;
+
+ case "x": // preferred date representation for the current locale
+ // without the time
+ break;
+
+ case "X": // preferred date representation for the current locale
+ // without the time
+ break;
+
+ case "y": // year as a decimal number without a century (range 00 to
+ // 99)
+ return _(dateObject.getFullYear()%100); break;
+
+ case "Y": // year as a decimal number including the century
+ return String(dateObject.getFullYear()); break;
+
+ case "z": // time zone or name or abbreviation
+ var timezoneOffset = dateObject.getTimezoneOffset();
+ return (timezoneOffset > 0 ? "-" : "+") +
+ _(Math.floor(Math.abs(timezoneOffset)/60)) + ":" +
+ _(Math.abs(timezoneOffset)%60); break;
+
+ case "Z": // time zone or name or abbreviation
+ return dojo.date.getTimezoneName(dateObject); break;
+
+ case "%":
+ return "%"; break;
+ }
+ }
+
+ // parse the formatting string and construct the resulting string
+ var string = "";
+ var i = 0, index = 0, switchCase;
+ while ((index = format.indexOf("%", i)) != -1) {
+ string += format.substring(i, index++);
+
+ // inspect modifier flag
+ switch (format.charAt(index++)) {
+ case "_": // Pad a numeric result string with spaces.
+ padChar = " "; break;
+ case "-": // Do not pad a numeric result string.
+ padChar = ""; break;
+ case "0": // Pad a numeric result string with zeros.
+ padChar = "0"; break;
+ case "^": // Convert characters in result string to upper case.
+ switchCase = "upper"; break;
+ case "#": // Swap the case of the result string.
+ switchCase = "swap"; break;
+ default: // no modifer flag so decremenet the index
+ padChar = null; index--; break;
+ }
+
+ // toggle case if a flag is set
+ var property = $(format.charAt(index++));
+ if (switchCase == "upper" ||
+ (switchCase == "swap" && /[a-z]/.test(property))) {
+ property = property.toUpperCase();
+ } else if (switchCase == "swap" && !/[a-z]/.test(property)) {
+ property = property.toLowerCase();
+ }
+ var swicthCase = null;
+
+ string += property;
+ i = index;
+ }
+ string += format.substring(i);
+
+ return string;
+}
+
+/* compare and add
+ ******************/
+dojo.date.compareTypes={
+ // summary
+ // bitmask for comparison operations.
+ DATE:1, TIME:2
+};
+dojo.date.compare=function(/* Date */ dateA, /* Date */ dateB, /* int */ options){
+ // summary
+ // Compare two date objects by date, time, or both.
+ var dA=dateA;
+ var dB=dateB||new Date();
+ var now=new Date();
+ var opt=options||(dojo.date.compareTypes.DATE|dojo.date.compareTypes.TIME);
+ var d1=new Date(
+ ((opt&dojo.date.compareTypes.DATE)?(dA.getFullYear()):now.getFullYear()),
+ ((opt&dojo.date.compareTypes.DATE)?(dA.getMonth()):now.getMonth()),
+ ((opt&dojo.date.compareTypes.DATE)?(dA.getDate()):now.getDate()),
+ ((opt&dojo.date.compareTypes.TIME)?(dA.getHours()):0),
+ ((opt&dojo.date.compareTypes.TIME)?(dA.getMinutes()):0),
+ ((opt&dojo.date.compareTypes.TIME)?(dA.getSeconds()):0)
+ );
+ var d2=new Date(
+ ((opt&dojo.date.compareTypes.DATE)?(dB.getFullYear()):now.getFullYear()),
+ ((opt&dojo.date.compareTypes.DATE)?(dB.getMonth()):now.getMonth()),
+ ((opt&dojo.date.compareTypes.DATE)?(dB.getDate()):now.getDate()),
+ ((opt&dojo.date.compareTypes.TIME)?(dB.getHours()):0),
+ ((opt&dojo.date.compareTypes.TIME)?(dB.getMinutes()):0),
+ ((opt&dojo.date.compareTypes.TIME)?(dB.getSeconds()):0)
+ );
+ if(d1.valueOf()>d2.valueOf()){
+ return 1; // int
+ }
+ if(d1.valueOf() 0.4");
+ }
+}
diff --git a/source/web/scripts/ajax/src/debug/arrow_hide.gif b/source/web/scripts/ajax/src/debug/arrow_hide.gif
new file mode 100644
index 0000000000..8bd6b346ca
Binary files /dev/null and b/source/web/scripts/ajax/src/debug/arrow_hide.gif differ
diff --git a/source/web/scripts/ajax/src/debug/arrow_show.gif b/source/web/scripts/ajax/src/debug/arrow_show.gif
new file mode 100644
index 0000000000..4246b506fb
Binary files /dev/null and b/source/web/scripts/ajax/src/debug/arrow_show.gif differ
diff --git a/source/web/scripts/ajax/src/debug/deep.html b/source/web/scripts/ajax/src/debug/deep.html
new file mode 100644
index 0000000000..1a22fbfc45
--- /dev/null
+++ b/source/web/scripts/ajax/src/debug/deep.html
@@ -0,0 +1,362 @@
+
+
+Deep Debugger
+
+
+
+
+
+
Javascript Object Browser
+
+
+
+
+
\ No newline at end of file
diff --git a/source/web/scripts/ajax/src/debug/spacer.gif b/source/web/scripts/ajax/src/debug/spacer.gif
new file mode 100644
index 0000000000..2ce50b5867
Binary files /dev/null and b/source/web/scripts/ajax/src/debug/spacer.gif differ
diff --git a/source/web/scripts/ajax/src/dnd/DragAndDrop.js b/source/web/scripts/ajax/src/dnd/DragAndDrop.js
new file mode 100644
index 0000000000..dd286aef79
--- /dev/null
+++ b/source/web/scripts/ajax/src/dnd/DragAndDrop.js
@@ -0,0 +1,166 @@
+dojo.require("dojo.lang");
+dojo.require("dojo.lang.declare");
+dojo.provide("dojo.dnd.DragSource");
+dojo.provide("dojo.dnd.DropTarget");
+dojo.provide("dojo.dnd.DragObject");
+dojo.provide("dojo.dnd.DragAndDrop");
+
+dojo.declare("dojo.dnd.DragSource", null, {
+ type: "",
+
+ onDragEnd: function(){
+ },
+
+ onDragStart: function(){
+ },
+
+ /*
+ * This function gets called when the DOM element was
+ * selected for dragging by the HtmlDragAndDropManager.
+ */
+ onSelected: function(){
+ },
+
+ unregister: function(){
+ dojo.dnd.dragManager.unregisterDragSource(this);
+ },
+
+ reregister: function(){
+ dojo.dnd.dragManager.registerDragSource(this);
+ }
+}, function(){
+
+ //dojo.profile.start("DragSource");
+
+ var dm = dojo.dnd.dragManager;
+ if(dm["registerDragSource"]){ // side-effect prevention
+ dm.registerDragSource(this);
+ }
+
+ //dojo.profile.end("DragSource");
+
+});
+
+dojo.declare("dojo.dnd.DragObject", null, {
+ type: "",
+
+ onDragStart: function(){
+ // gets called directly after being created by the DragSource
+ // default action is to clone self as icon
+ },
+
+ onDragMove: function(){
+ // this changes the UI for the drag icon
+ // "it moves itself"
+ },
+
+ onDragOver: function(){
+ },
+
+ onDragOut: function(){
+ },
+
+ onDragEnd: function(){
+ },
+
+ // normal aliases
+ onDragLeave: this.onDragOut,
+ onDragEnter: this.onDragOver,
+
+ // non-camel aliases
+ ondragout: this.onDragOut,
+ ondragover: this.onDragOver
+}, function(){
+ var dm = dojo.dnd.dragManager;
+ if(dm["registerDragObject"]){ // side-effect prevention
+ dm.registerDragObject(this);
+ }
+});
+
+dojo.declare("dojo.dnd.DropTarget", null, {
+
+ acceptsType: function(type){
+ if(!dojo.lang.inArray(this.acceptedTypes, "*")){ // wildcard
+ if(!dojo.lang.inArray(this.acceptedTypes, type)) { return false; }
+ }
+ return true;
+ },
+
+ accepts: function(dragObjects){
+ if(!dojo.lang.inArray(this.acceptedTypes, "*")){ // wildcard
+ for (var i = 0; i < dragObjects.length; i++) {
+ if (!dojo.lang.inArray(this.acceptedTypes,
+ dragObjects[i].type)) { return false; }
+ }
+ }
+ return true;
+ },
+
+ unregister: function(){
+ dojo.dnd.dragManager.unregisterDropTarget(this);
+ },
+
+ onDragOver: function(){
+ },
+
+ onDragOut: function(){
+ },
+
+ onDragMove: function(){
+ },
+
+ onDropStart: function(){
+ },
+
+ onDrop: function(){
+ },
+
+ onDropEnd: function(){
+ }
+}, function(){
+ if (this.constructor == dojo.dnd.DropTarget) { return; } // need to be subclassed
+ this.acceptedTypes = [];
+ dojo.dnd.dragManager.registerDropTarget(this);
+});
+
+// NOTE: this interface is defined here for the convenience of the DragManager
+// implementor. It is expected that in most cases it will be satisfied by
+// extending a native event (DOM event in HTML and SVG).
+dojo.dnd.DragEvent = function(){
+ this.dragSource = null;
+ this.dragObject = null;
+ this.target = null;
+ this.eventStatus = "success";
+ //
+ // can be one of:
+ // [ "dropSuccess", "dropFailure", "dragMove",
+ // "dragStart", "dragEnter", "dragLeave"]
+ //
+}
+/*
+ * The DragManager handles listening for low-level events and dispatching
+ * them to higher-level primitives like drag sources and drop targets. In
+ * order to do this, it must keep a list of the items.
+ */
+dojo.declare("dojo.dnd.DragManager", null, {
+ selectedSources: [],
+ dragObjects: [],
+ dragSources: [],
+ registerDragSource: function(){},
+ dropTargets: [],
+ registerDropTarget: function(){},
+ lastDragTarget: null,
+ currentDragTarget: null,
+ onKeyDown: function(){},
+ onMouseOut: function(){},
+ onMouseMove: function(){},
+ onMouseUp: function(){}
+});
+
+// NOTE: despite the existance of the DragManager class, there will be a
+// singleton drag manager provided by the renderer-specific D&D support code.
+// It is therefore sane for us to assign instance variables to the DragManager
+// prototype
+
+// The renderer-specific file will define the following object:
+// dojo.dnd.dragManager = null;
diff --git a/source/web/scripts/ajax/src/dnd/HtmlDragAndDrop.js b/source/web/scripts/ajax/src/dnd/HtmlDragAndDrop.js
new file mode 100644
index 0000000000..ef3b4be037
--- /dev/null
+++ b/source/web/scripts/ajax/src/dnd/HtmlDragAndDrop.js
@@ -0,0 +1,501 @@
+dojo.provide("dojo.dnd.HtmlDragAndDrop");
+dojo.provide("dojo.dnd.HtmlDragSource");
+dojo.provide("dojo.dnd.HtmlDropTarget");
+dojo.provide("dojo.dnd.HtmlDragObject");
+
+dojo.require("dojo.dnd.HtmlDragManager");
+dojo.require("dojo.dnd.DragAndDrop");
+
+dojo.require("dojo.html.*");
+dojo.require("dojo.html.display");
+dojo.require("dojo.html.util");
+dojo.require("dojo.html.selection");
+dojo.require("dojo.html.iframe");
+dojo.require("dojo.lang.extras");
+dojo.require("dojo.lfx.*");
+dojo.require("dojo.event");
+
+dojo.declare("dojo.dnd.HtmlDragSource", dojo.dnd.DragSource, {
+ dragClass: "", // CSS classname(s) applied to node when it is being dragged
+
+ onDragStart: function(){
+ var dragObj = new dojo.dnd.HtmlDragObject(this.dragObject, this.type);
+ if(this.dragClass) { dragObj.dragClass = this.dragClass; }
+
+ if (this.constrainToContainer) {
+ dragObj.constrainTo(this.constrainingContainer || this.domNode.parentNode);
+ }
+
+ return dragObj;
+ },
+
+ setDragHandle: function(node){
+ node = dojo.byId(node);
+ dojo.dnd.dragManager.unregisterDragSource(this);
+ this.domNode = node;
+ dojo.dnd.dragManager.registerDragSource(this);
+ },
+
+ setDragTarget: function(node){
+ this.dragObject = node;
+ },
+
+ constrainTo: function(container) {
+ this.constrainToContainer = true;
+ if (container) {
+ this.constrainingContainer = container;
+ }
+ },
+
+ /*
+ *
+ * see dojo.dnd.DragSource.onSelected
+ */
+ onSelected: function() {
+ for (var i=0; i this.constraints.maxX) { x = this.constraints.maxX; }
+ if (y > this.constraints.maxY) { y = this.constraints.maxY; }
+ }
+
+ this.setAbsolutePosition(x, y);
+
+ dojo.event.topic.publish('dragMove', { source: this } );
+ },
+
+ /**
+ * Set the position of the drag clone. (x,y) is relative to .
+ */
+ setAbsolutePosition: function(x, y){
+ // The drag clone is attached to document.body so this is trivial
+ if(!this.disableY) { this.dragClone.style.top = y + "px"; }
+ if(!this.disableX) { this.dragClone.style.left = x + "px"; }
+ },
+
+
+ /**
+ * If the drag operation returned a success we reomve the clone of
+ * ourself from the original position. If the drag operation returned
+ * failure we slide back over to where we came from and end the operation
+ * with a little grace.
+ */
+ onDragEnd: function(e){
+ switch(e.dragStatus){
+
+ case "dropSuccess":
+ dojo.html.removeNode(this.dragClone);
+ this.dragClone = null;
+ break;
+
+ case "dropFailure": // slide back to the start
+ var startCoords = dojo.html.getAbsolutePosition(this.dragClone, true);
+ // offset the end so the effect can be seen
+ var endCoords = { left: this.dragStartPosition.x + 1,
+ top: this.dragStartPosition.y + 1};
+
+ // animate
+ var anim = dojo.lfx.slideTo(this.dragClone, endCoords, 500, dojo.lfx.easeOut);
+ var dragObject = this;
+ dojo.event.connect(anim, "onEnd", function (e) {
+ // pause for a second (not literally) and disappear
+ dojo.lang.setTimeout(function() {
+ dojo.html.removeNode(dragObject.dragClone);
+ // Allow drag clone to be gc'ed
+ dragObject.dragClone = null;
+ },
+ 200);
+ });
+ anim.play();
+ break;
+ }
+
+ dojo.event.topic.publish('dragEnd', { source: this } );
+ },
+
+ squelchOnClick: function(e){
+ // squelch this onClick() event because it's the result of a drag (it's not a real click)
+ dojo.event.browser.stopEvent(e);
+
+ // disconnect after a short delay to prevent "Null argument to unrollAdvice()" warning
+ dojo.lang.setTimeout(function() {
+ dojo.event.disconnect(this.domNode, "onclick", this, "squelchOnClick");
+ },50);
+ },
+
+ constrainTo: function(container) {
+ this.constrainToContainer=true;
+ if (container) {
+ this.constrainingContainer = container;
+ } else {
+ this.constrainingContainer = this.domNode.parentNode;
+ }
+ }
+}, function(node, type){
+ this.domNode = dojo.byId(node);
+ this.type = type;
+ this.constrainToContainer = false;
+ this.dragSource = null;
+});
+
+dojo.declare("dojo.dnd.HtmlDropTarget", dojo.dnd.DropTarget, {
+ vertical: false,
+ onDragOver: function(e){
+ if(!this.accepts(e.dragObjects)){ return false; }
+
+ // cache the positions of the child nodes
+ this.childBoxes = [];
+ for (var i = 0, child; i < this.domNode.childNodes.length; i++) {
+ child = this.domNode.childNodes[i];
+ if (child.nodeType != dojo.html.ELEMENT_NODE) { continue; }
+ var pos = dojo.html.getAbsolutePosition(child, true);
+ var inner = dojo.html.getBorderBox(child);
+ this.childBoxes.push({top: pos.y, bottom: pos.y+inner.height,
+ left: pos.x, right: pos.x+inner.width, height: inner.height,
+ width: inner.width, node: child});
+ }
+
+ // TODO: use dummy node
+
+ return true;
+ },
+
+ _getNodeUnderMouse: function(e){
+ // find the child
+ for (var i = 0, child; i < this.childBoxes.length; i++) {
+ with (this.childBoxes[i]) {
+ if (e.pageX >= left && e.pageX <= right &&
+ e.pageY >= top && e.pageY <= bottom) { return i; }
+ }
+ }
+
+ return -1;
+ },
+
+ createDropIndicator: function() {
+ this.dropIndicator = document.createElement("div");
+ with (this.dropIndicator.style) {
+ position = "absolute";
+ zIndex = 999;
+ if(this.vertical){
+ borderLeftWidth = "1px";
+ borderLeftColor = "black";
+ borderLeftStyle = "solid";
+ height = dojo.html.getBorderBox(this.domNode).height + "px";
+ top = dojo.html.getAbsolutePosition(this.domNode, true).y + "px";
+ }else{
+ borderTopWidth = "1px";
+ borderTopColor = "black";
+ borderTopStyle = "solid";
+ width = dojo.html.getBorderBox(this.domNode).width + "px";
+ left = dojo.html.getAbsolutePosition(this.domNode, true).x + "px";
+ }
+ }
+ },
+
+ onDragMove: function(e, dragObjects){
+ var i = this._getNodeUnderMouse(e);
+
+ if(!this.dropIndicator){
+ this.createDropIndicator();
+ }
+
+ var gravity = this.vertical ? dojo.html.gravity.WEST : dojo.html.gravity.NORTH;
+ var hide = false;
+ if(i < 0) {
+ if(this.childBoxes.length) {
+ var before = (dojo.html.gravity(this.childBoxes[0].node, e) & gravity);
+ if(before){ hide = true; }
+ } else {
+ var before = true;
+ }
+ } else {
+ var child = this.childBoxes[i];
+ var before = (dojo.html.gravity(child.node, e) & gravity);
+ if(child.node === dragObjects[0].dragSource.domNode){
+ hide = true;
+ }else{
+ var currentPosChild = before ?
+ (i>0?this.childBoxes[i-1]:child) :
+ (i
+ * (draggable selection)
+ * (dragObject generation)
+ * mouse-move ->
+ * (draggable movement)
+ * (droppable detection)
+ * (inform droppable)
+ * (inform dragObject)
+ * mouse-up
+ * (inform/destroy dragObject)
+ * (inform draggable)
+ * (inform droppable)
+ * 2.) mouse-down -> mouse-down
+ * (click-hold context menu)
+ * 3.) mouse-click ->
+ * (draggable selection)
+ * shift-mouse-click ->
+ * (augment draggable selection)
+ * mouse-down ->
+ * (dragObject generation)
+ * mouse-move ->
+ * (draggable movement)
+ * (droppable detection)
+ * (inform droppable)
+ * (inform dragObject)
+ * mouse-up
+ * (inform draggable)
+ * (inform droppable)
+ * 4.) mouse-up
+ * (clobber draggable selection)
+ */
+ disabled: false, // to kill all dragging!
+ nestedTargets: false,
+ mouseDownTimer: null, // used for click-hold operations
+ dsCounter: 0,
+ dsPrefix: "dojoDragSource",
+
+ // dimension calculation cache for use durring drag
+ dropTargetDimensions: [],
+
+ currentDropTarget: null,
+ // currentDropTargetPoints: null,
+ previousDropTarget: null,
+ _dragTriggered: false,
+
+ selectedSources: [],
+ dragObjects: [],
+
+ // mouse position properties
+ currentX: null,
+ currentY: null,
+ lastX: null,
+ lastY: null,
+ mouseDownX: null,
+ mouseDownY: null,
+ threshold: 7,
+
+ dropAcceptable: false,
+
+ cancelEvent: function(e){ e.stopPropagation(); e.preventDefault();},
+
+ // method over-rides
+ registerDragSource: function(ds){
+ //dojo.profile.start("register DragSource");
+
+ if(ds["domNode"]){
+ // FIXME: dragSource objects SHOULD have some sort of property that
+ // references their DOM node, we shouldn't just be passing nodes and
+ // expecting it to work.
+ //dojo.profile.start("register DragSource 1");
+ var dp = this.dsPrefix;
+ var dpIdx = dp+"Idx_"+(this.dsCounter++);
+ ds.dragSourceId = dpIdx;
+ this.dragSources[dpIdx] = ds;
+ ds.domNode.setAttribute(dp, dpIdx);
+ //dojo.profile.end("register DragSource 1");
+
+ //dojo.profile.start("register DragSource 2");
+
+ // so we can drag links
+ if(dojo.render.html.ie){
+ //dojo.profile.start("register DragSource IE");
+
+ dojo.event.browser.addListener(ds.domNode, "ondragstart", this.cancelEvent);
+ // terribly slow
+ //dojo.event.connect(ds.domNode, "ondragstart", this.cancelEvent);
+ //dojo.profile.end("register DragSource IE");
+
+ }
+ //dojo.profile.end("register DragSource 2");
+
+ }
+ //dojo.profile.end("register DragSource");
+ },
+
+ unregisterDragSource: function(ds){
+ if (ds["domNode"]){
+ var dp = this.dsPrefix;
+ var dpIdx = ds.dragSourceId;
+ delete ds.dragSourceId;
+ delete this.dragSources[dpIdx];
+ ds.domNode.setAttribute(dp, null);
+ if(dojo.render.html.ie){
+ dojo.event.browser.removeListener(ds.domNode, "ondragstart", this.cancelEvent);
+ }
+ }
+ },
+
+ registerDropTarget: function(dt){
+ this.dropTargets.push(dt);
+ },
+
+ unregisterDropTarget: function(dt){
+ var index = dojo.lang.find(this.dropTargets, dt, true);
+ if (index>=0) {
+ this.dropTargets.splice(index, 1);
+ }
+ },
+
+ /**
+ * Get the DOM element that is meant to drag.
+ * Loop through the parent nodes of the event target until
+ * the element is found that was created as a DragSource and
+ * return it.
+ *
+ * @param event object The event for which to get the drag source.
+ */
+ getDragSource: function(e){
+ var tn = e.target;
+ if(tn === dojo.body()){ return; }
+ var ta = dojo.html.getAttribute(tn, this.dsPrefix);
+ while((!ta)&&(tn)){
+ tn = tn.parentNode;
+ if((!tn)||(tn === dojo.body())){ return; }
+ ta = dojo.html.getAttribute(tn, this.dsPrefix);
+ }
+ return this.dragSources[ta];
+ },
+
+ onKeyDown: function(e){
+ },
+
+ onMouseDown: function(e){
+ if(this.disabled) { return; }
+
+ // only begin on left click
+ if(dojo.render.html.ie) {
+ if(e.button != 1) { return; }
+ } else if(e.which != 1) {
+ return;
+ }
+
+ var target = e.target.nodeType == dojo.html.TEXT_NODE ?
+ e.target.parentNode : e.target;
+
+ // do not start drag involvement if the user is interacting with
+ // a form element.
+ if(dojo.html.isTag(target, "button", "textarea", "input", "select", "option")) {
+ return;
+ }
+
+ // find a selection object, if one is a parent of the source node
+ var ds = this.getDragSource(e);
+
+ // this line is important. if we aren't selecting anything then
+ // we need to return now, so preventDefault() isn't called, and thus
+ // the event is propogated to other handling code
+ if(!ds){ return; }
+
+ if(!dojo.lang.inArray(this.selectedSources, ds)){
+ this.selectedSources.push(ds);
+ ds.onSelected();
+ }
+
+ this.mouseDownX = e.pageX;
+ this.mouseDownY = e.pageY;
+
+ // Must stop the mouse down from being propogated, or otherwise can't
+ // drag links in firefox.
+ // WARNING: preventing the default action on all mousedown events
+ // prevents user interaction with the contents.
+ e.preventDefault();
+
+ dojo.event.connect(document, "onmousemove", this, "onMouseMove");
+ },
+
+ onMouseUp: function(e, cancel){
+ // if we aren't dragging then ignore the mouse-up
+ // (in particular, don't call preventDefault(), because other
+ // code may need to process this event)
+ if(this.selectedSources.length==0){
+ return;
+ }
+
+ this.mouseDownX = null;
+ this.mouseDownY = null;
+ this._dragTriggered = false;
+ // e.preventDefault();
+ e.dragSource = this.dragSource;
+ // let ctrl be used for multiselect or another action
+ // if I use same key to trigger treeV3 node selection and here,
+ // I have bugs with drag'n'drop. why ?? no idea..
+ if((!e.shiftKey)&&(!e.ctrlKey)){
+ //if(!e.shiftKey){
+ if(this.currentDropTarget) {
+ this.currentDropTarget.onDropStart();
+ }
+ dojo.lang.forEach(this.dragObjects, function(tempDragObj){
+ var ret = null;
+ if(!tempDragObj){ return; }
+ if(this.currentDropTarget) {
+ e.dragObject = tempDragObj;
+
+ // NOTE: we can't get anything but the current drop target
+ // here since the drag shadow blocks mouse-over events.
+ // This is probelematic for dropping "in" something
+ var ce = this.currentDropTarget.domNode.childNodes;
+ if(ce.length > 0){
+ e.dropTarget = ce[0];
+ while(e.dropTarget == tempDragObj.domNode){
+ e.dropTarget = e.dropTarget.nextSibling;
+ }
+ }else{
+ e.dropTarget = this.currentDropTarget.domNode;
+ }
+ if(this.dropAcceptable){
+ ret = this.currentDropTarget.onDrop(e);
+ }else{
+ this.currentDropTarget.onDragOut(e);
+ }
+ }
+
+ e.dragStatus = this.dropAcceptable && ret ? "dropSuccess" : "dropFailure";
+ // decouple the calls for onDragEnd, so they don't block the execution here
+ // ie. if the onDragEnd would call an alert, the execution here is blocked until the
+ // user has confirmed the alert box and then the rest of the dnd code is executed
+ // while the mouse doesnt "hold" the dragged object anymore ... and so on
+ dojo.lang.delayThese([
+ function() {
+ // in FF1.5 this throws an exception, see
+ // http://dojotoolkit.org/pipermail/dojo-interest/2006-April/006751.html
+ try{
+ tempDragObj.dragSource.onDragEnd(e)
+ } catch(err) {
+ // since the problem seems passing e, we just copy all
+ // properties and try the copy ...
+ var ecopy = {};
+ for (var i in e) {
+ if (i=="type") { // the type property contains the exception, no idea why...
+ ecopy.type = "mouseup";
+ continue;
+ }
+ ecopy[i] = e[i];
+ }
+ tempDragObj.dragSource.onDragEnd(ecopy);
+ }
+ }
+ , function() {tempDragObj.onDragEnd(e)}]);
+ }, this);
+
+ this.selectedSources = [];
+ this.dragObjects = [];
+ this.dragSource = null;
+ if(this.currentDropTarget) {
+ this.currentDropTarget.onDropEnd();
+ }
+ } else {
+ //dojo.debug("special click");
+ }
+
+ dojo.event.disconnect(document, "onmousemove", this, "onMouseMove");
+ this.currentDropTarget = null;
+ },
+
+ onScroll: function(){
+ //dojo.profile.start("DNDManager updateoffset");
+ for(var i = 0; i < this.dragObjects.length; i++) {
+ if(this.dragObjects[i].updateDragOffset) {
+ this.dragObjects[i].updateDragOffset();
+ }
+ }
+ //dojo.profile.end("DNDManager updateoffset");
+
+ // TODO: do not recalculate, only adjust coordinates
+ if (this.dragObjects.length) {
+ this.cacheTargetLocations();
+ }
+ },
+
+ _dragStartDistance: function(x, y){
+ if((!this.mouseDownX)||(!this.mouseDownX)){
+ return;
+ }
+ var dx = Math.abs(x-this.mouseDownX);
+ var dx2 = dx*dx;
+ var dy = Math.abs(y-this.mouseDownY);
+ var dy2 = dy*dy;
+ return parseInt(Math.sqrt(dx2+dy2), 10);
+ },
+
+ cacheTargetLocations: function(){
+ dojo.profile.start("cacheTargetLocations");
+
+ this.dropTargetDimensions = [];
+ dojo.lang.forEach(this.dropTargets, function(tempTarget){
+ var tn = tempTarget.domNode;
+ //only cache dropTarget which can accept current dragSource
+ if(!tn || dojo.lang.find(tempTarget.acceptedTypes, this.dragSource.type) < 0){ return; }
+ var abs = dojo.html.getAbsolutePosition(tn, true);
+ var bb = dojo.html.getBorderBox(tn);
+ this.dropTargetDimensions.push([
+ [abs.x, abs.y], // upper-left
+ // lower-right
+ [ abs.x+bb.width, abs.y+bb.height ],
+ tempTarget
+ ]);
+ //dojo.debug("Cached for "+tempTarget)
+ }, this);
+
+ dojo.profile.end("cacheTargetLocations");
+
+ //dojo.debug("Cache locations")
+ },
+
+ onMouseMove: function(e){
+ if((dojo.render.html.ie)&&(e.button != 1)){
+ // Oooops - mouse up occurred - e.g. when mouse was not over the
+ // window. I don't think we can detect this for FF - but at least
+ // we can be nice in IE.
+ this.currentDropTarget = null;
+ this.onMouseUp(e, true);
+ return;
+ }
+
+ // if we've got some sources, but no drag objects, we need to send
+ // onDragStart to all the right parties and get things lined up for
+ // drop target detection
+
+ if( (this.selectedSources.length)&&
+ (!this.dragObjects.length) ){
+ var dx;
+ var dy;
+ if(!this._dragTriggered){
+ this._dragTriggered = (this._dragStartDistance(e.pageX, e.pageY) > this.threshold);
+ if(!this._dragTriggered){ return; }
+ dx = e.pageX - this.mouseDownX;
+ dy = e.pageY - this.mouseDownY;
+ }
+
+ // the first element is always our dragSource, if there are multiple
+ // selectedSources (elements that move along) then the first one is the master
+ // and for it the events will be fired etc.
+ this.dragSource = this.selectedSources[0];
+
+ dojo.lang.forEach(this.selectedSources, function(tempSource){
+ if(!tempSource){ return; }
+ var tdo = tempSource.onDragStart(e);
+ if(tdo){
+ tdo.onDragStart(e);
+
+ // "bump" the drag object to account for the drag threshold
+ tdo.dragOffset.y += dy;
+ tdo.dragOffset.x += dx;
+ tdo.dragSource = tempSource;
+
+ this.dragObjects.push(tdo);
+ }
+ }, this);
+
+ /* clean previous drop target in dragStart */
+ this.previousDropTarget = null;
+
+ this.cacheTargetLocations();
+ }
+
+ // FIXME: we need to add dragSources and dragObjects to e
+ dojo.lang.forEach(this.dragObjects, function(dragObj){
+ if(dragObj){ dragObj.onDragMove(e); }
+ });
+
+ // if we have a current drop target, check to see if we're outside of
+ // it. If so, do all the actions that need doing.
+ if(this.currentDropTarget){
+ //dojo.debug(dojo.html.hasParent(this.currentDropTarget.domNode))
+ var c = dojo.html.toCoordinateObject(this.currentDropTarget.domNode, true);
+ // var dtp = this.currentDropTargetPoints;
+ var dtp = [
+ [c.x,c.y], [c.x+c.width, c.y+c.height]
+ ];
+ }
+
+ if((!this.nestedTargets)&&(dtp)&&(this.isInsideBox(e, dtp))){
+ if(this.dropAcceptable){
+ this.currentDropTarget.onDragMove(e, this.dragObjects);
+ }
+ }else{
+ // FIXME: need to fix the event object!
+ // see if we can find a better drop target
+ var bestBox = this.findBestTarget(e);
+
+ if(bestBox.target === null){
+ if(this.currentDropTarget){
+ this.currentDropTarget.onDragOut(e);
+ this.previousDropTarget = this.currentDropTarget;
+ this.currentDropTarget = null;
+ // this.currentDropTargetPoints = null;
+ }
+ this.dropAcceptable = false;
+ return;
+ }
+
+ if(this.currentDropTarget !== bestBox.target){
+ if(this.currentDropTarget){
+ this.previousDropTarget = this.currentDropTarget;
+ this.currentDropTarget.onDragOut(e);
+ }
+ this.currentDropTarget = bestBox.target;
+ // this.currentDropTargetPoints = bestBox.points;
+ e.dragObjects = this.dragObjects;
+ this.dropAcceptable = this.currentDropTarget.onDragOver(e);
+
+ }else{
+ if(this.dropAcceptable){
+ this.currentDropTarget.onDragMove(e, this.dragObjects);
+ }
+ }
+ }
+ },
+
+ findBestTarget: function(e) {
+ var _this = this;
+ var bestBox = new Object();
+ bestBox.target = null;
+ bestBox.points = null;
+ dojo.lang.every(this.dropTargetDimensions, function(tmpDA) {
+ if(!_this.isInsideBox(e, tmpDA)){
+ return true;
+ }
+
+ bestBox.target = tmpDA[2];
+ bestBox.points = tmpDA;
+ // continue iterating only if _this.nestedTargets == true
+ return Boolean(_this.nestedTargets);
+ });
+
+ return bestBox;
+ },
+
+ isInsideBox: function(e, coords){
+ if( (e.pageX > coords[0][0])&&
+ (e.pageX < coords[1][0])&&
+ (e.pageY > coords[0][1])&&
+ (e.pageY < coords[1][1]) ){
+ return true;
+ }
+ return false;
+ },
+
+ onMouseOver: function(e){
+ },
+
+ onMouseOut: function(e){
+ }
+});
+
+dojo.dnd.dragManager = new dojo.dnd.HtmlDragManager();
+
+// global namespace protection closure
+(function(){
+ var d = document;
+ var dm = dojo.dnd.dragManager;
+ //TODO: when focus manager is ready, dragManager should be rewritten to use it
+ // set up event handlers on the document (or no?)
+ dojo.event.connect(d, "onkeydown", dm, "onKeyDown");
+ dojo.event.connect(d, "onmouseover", dm, "onMouseOver");
+ dojo.event.connect(d, "onmouseout", dm, "onMouseOut");
+ dojo.event.connect(d, "onmousedown", dm, "onMouseDown");
+ dojo.event.connect(d, "onmouseup", dm, "onMouseUp");
+ // TODO: process scrolling of elements, not only window (focus manager would
+ // probably come to rescue here as well)
+ dojo.event.connect(window, "onscroll", dm, "onScroll");
+})();
diff --git a/source/web/scripts/ajax/src/dnd/HtmlDragMove.js b/source/web/scripts/ajax/src/dnd/HtmlDragMove.js
new file mode 100644
index 0000000000..39880a6dae
--- /dev/null
+++ b/source/web/scripts/ajax/src/dnd/HtmlDragMove.js
@@ -0,0 +1,58 @@
+dojo.provide("dojo.dnd.HtmlDragMove");
+dojo.provide("dojo.dnd.HtmlDragMoveSource");
+dojo.provide("dojo.dnd.HtmlDragMoveObject");
+dojo.require("dojo.dnd.*");
+
+dojo.declare("dojo.dnd.HtmlDragMoveSource", dojo.dnd.HtmlDragSource, {
+ onDragStart: function(){
+ var dragObj = new dojo.dnd.HtmlDragMoveObject(this.dragObject, this.type);
+ if (this.constrainToContainer) {
+ dragObj.constrainTo(this.constrainingContainer);
+ }
+ return dragObj;
+ },
+ /*
+ * see dojo.dnd.HtmlDragSource.onSelected
+ */
+ onSelected: function() {
+ for (var i=0; i.
+ */
+ setAbsolutePosition: function(x, y){
+ // The drag clone is attached to it's constraining container so offset for that
+ if(!this.disableY) { this.domNode.style.top = (y-this.containingBlockPosition.y) + "px"; }
+ if(!this.disableX) { this.domNode.style.left = (x-this.containingBlockPosition.x) + "px"; }
+ }
+});
diff --git a/source/web/scripts/ajax/src/dnd/Sortable.js b/source/web/scripts/ajax/src/dnd/Sortable.js
new file mode 100644
index 0000000000..d38d53541a
--- /dev/null
+++ b/source/web/scripts/ajax/src/dnd/Sortable.js
@@ -0,0 +1,18 @@
+dojo.provide("dojo.dnd.Sortable");
+dojo.require("dojo.dnd.*");
+
+dojo.dnd.Sortable = function () {}
+
+dojo.lang.extend(dojo.dnd.Sortable, {
+
+ ondragstart: function (e) {
+ var dragObject = e.target;
+ while (dragObject.parentNode && dragObject.parentNode != this) {
+ dragObject = dragObject.parentNode;
+ }
+ // TODO: should apply HtmlDropTarget interface to self
+ // TODO: should apply HtmlDragObject interface?
+ return dragObject;
+ }
+
+});
diff --git a/source/web/scripts/ajax/src/dnd/TreeDragAndDrop.js b/source/web/scripts/ajax/src/dnd/TreeDragAndDrop.js
new file mode 100644
index 0000000000..632d42b434
--- /dev/null
+++ b/source/web/scripts/ajax/src/dnd/TreeDragAndDrop.js
@@ -0,0 +1,468 @@
+/**
+ * TreeDrag* specialized on managing subtree drags
+ * It selects nodes and visualises what's going on,
+ * but delegates real actions upon tree to the controller
+ *
+ * This code is considered a part of controller
+*/
+
+dojo.provide("dojo.dnd.TreeDragAndDrop");
+dojo.provide("dojo.dnd.TreeDragSource");
+dojo.provide("dojo.dnd.TreeDropTarget");
+dojo.provide("dojo.dnd.TreeDNDController");
+
+dojo.require("dojo.dnd.HtmlDragAndDrop");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.lang.array");
+dojo.require("dojo.lang.extras");
+dojo.require("dojo.html.layout");
+
+dojo.dnd.TreeDragSource = function(node, syncController, type, treeNode){
+ this.controller = syncController;
+ this.treeNode = treeNode;
+
+ dojo.dnd.HtmlDragSource.call(this, node, type);
+}
+
+dojo.inherits(dojo.dnd.TreeDragSource, dojo.dnd.HtmlDragSource);
+
+dojo.lang.extend(dojo.dnd.TreeDragSource, {
+ onDragStart: function(){
+ /* extend adds functions to prototype */
+ var dragObject = dojo.dnd.HtmlDragSource.prototype.onDragStart.call(this);
+ //dojo.debugShallow(dragObject)
+
+ dragObject.treeNode = this.treeNode;
+
+ dragObject.onDragStart = dojo.lang.hitch(dragObject, function(e) {
+
+ /* save selection */
+ this.savedSelectedNode = this.treeNode.tree.selector.selectedNode;
+ if (this.savedSelectedNode) {
+ this.savedSelectedNode.unMarkSelected();
+ }
+
+ var result = dojo.dnd.HtmlDragObject.prototype.onDragStart.apply(this, arguments);
+
+
+ /* remove background grid from cloned object */
+ var cloneGrid = this.dragClone.getElementsByTagName('img');
+ for(var i=0; i it was allowed before, no accept check is needed
+ if (position=="onto" ||
+ (!this.isAdjacentNode(sourceTreeNode, position)
+ && this.controller.canMove(sourceTreeNode, this.treeNode.parent)
+ )
+ ) {
+ return position;
+ } else {
+ return false;
+ }
+
+ },
+
+ onDragOut: function(e) {
+ this.clearAutoExpandTimer();
+
+ this.hideIndicator();
+ },
+
+
+ clearAutoExpandTimer: function() {
+ if (this.autoExpandTimer) {
+ clearTimeout(this.autoExpandTimer);
+ this.autoExpandTimer = null;
+ }
+ },
+
+
+
+ onDragMove: function(e, dragObjects){
+
+ var sourceTreeNode = dragObjects[0].treeNode;
+
+ var position = this.getAcceptPosition(e, sourceTreeNode);
+
+ if (position) {
+ this.showIndicator(position);
+ }
+
+ },
+
+ isAdjacentNode: function(sourceNode, position) {
+
+ if (sourceNode === this.treeNode) return true;
+ if (sourceNode.getNextSibling() === this.treeNode && position=="before") return true;
+ if (sourceNode.getPreviousSibling() === this.treeNode && position=="after") return true;
+
+ return false;
+ },
+
+
+ /* get DNDMode and see which position e fits */
+ getPosition: function(e, DNDMode) {
+ var node = dojo.byId(this.treeNode.labelNode);
+ var mousey = e.pageY || e.clientY + dojo.body().scrollTop;
+ var nodey = dojo.html.getAbsolutePosition(node).y;
+ var height = dojo.html.getBorderBox(node).height;
+
+ var relY = mousey - nodey;
+ var p = relY / height;
+
+ var position = ""; // "" <=> forbidden
+ if (DNDMode & dojo.widget.Tree.prototype.DNDModes.ONTO
+ && DNDMode & dojo.widget.Tree.prototype.DNDModes.BETWEEN) {
+ if (p<=0.3) {
+ position = "before";
+ } else if (p<=0.7) {
+ position = "onto";
+ } else {
+ position = "after";
+ }
+ } else if (DNDMode & dojo.widget.Tree.prototype.DNDModes.BETWEEN) {
+ if (p<=0.5) {
+ position = "before";
+ } else {
+ position = "after";
+ }
+ }
+ else if (DNDMode & dojo.widget.Tree.prototype.DNDModes.ONTO) {
+ position = "onto";
+ }
+
+
+ return position;
+ },
+
+
+
+ getTargetParentIndex: function(sourceTreeNode, position) {
+
+ var index = position == "before" ? this.treeNode.getParentIndex() : this.treeNode.getParentIndex()+1;
+ if (this.treeNode.parent === sourceTreeNode.parent
+ && this.treeNode.getParentIndex() > sourceTreeNode.getParentIndex()) {
+ index--; // dragging a node is different for simple move bacause of before-after issues
+ }
+
+ return index;
+ },
+
+
+ onDrop: function(e){
+ // onDragOut will clean position
+
+
+ var position = this.position;
+
+//dojo.debug(position);
+
+ this.onDragOut(e);
+
+ var sourceTreeNode = e.dragObject.treeNode;
+
+ if (!dojo.lang.isObject(sourceTreeNode)) {
+ dojo.raise("TreeNode not found in dragObject")
+ }
+
+ if (position == "onto") {
+ return this.controller.move(sourceTreeNode, this.treeNode, 0);
+ } else {
+ var index = this.getTargetParentIndex(sourceTreeNode, position);
+ return this.controller.move(sourceTreeNode, this.treeNode.parent, index);
+ }
+
+ //dojo.debug('drop2');
+
+
+
+ }
+
+
+});
+
+
+
+dojo.dnd.TreeDNDController = function(treeController) {
+
+ // I use this controller to perform actions
+ this.treeController = treeController;
+
+ this.dragSources = {};
+
+ this.dropTargets = {};
+
+}
+
+dojo.lang.extend(dojo.dnd.TreeDNDController, {
+
+
+ listenTree: function(tree) {
+ //dojo.debug("Listen tree "+tree);
+ dojo.event.topic.subscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
+ dojo.event.topic.subscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
+ dojo.event.topic.subscribe(tree.eventNames.moveTo, this, "onMoveTo");
+ dojo.event.topic.subscribe(tree.eventNames.addChild, this, "onAddChild");
+ dojo.event.topic.subscribe(tree.eventNames.removeNode, this, "onRemoveNode");
+ dojo.event.topic.subscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");
+ },
+
+
+ unlistenTree: function(tree) {
+ //dojo.debug("Listen tree "+tree);
+ dojo.event.topic.unsubscribe(tree.eventNames.createDOMNode, this, "onCreateDOMNode");
+ dojo.event.topic.unsubscribe(tree.eventNames.moveFrom, this, "onMoveFrom");
+ dojo.event.topic.unsubscribe(tree.eventNames.moveTo, this, "onMoveTo");
+ dojo.event.topic.unsubscribe(tree.eventNames.addChild, this, "onAddChild");
+ dojo.event.topic.unsubscribe(tree.eventNames.removeNode, this, "onRemoveNode");
+ dojo.event.topic.unsubscribe(tree.eventNames.treeDestroy, this, "onTreeDestroy");
+ },
+
+ onTreeDestroy: function(message) {
+ this.unlistenTree(message.source);
+ // I'm not widget so don't use destroy() call and dieWithTree
+ },
+
+ onCreateDOMNode: function(message) {
+ this.registerDNDNode(message.source);
+ },
+
+ onAddChild: function(message) {
+ this.registerDNDNode(message.child);
+ },
+
+ onMoveFrom: function(message) {
+ var _this = this;
+ dojo.lang.forEach(
+ message.child.getDescendants(),
+ function(node) { _this.unregisterDNDNode(node); }
+ );
+ },
+
+ onMoveTo: function(message) {
+ var _this = this;
+ dojo.lang.forEach(
+ message.child.getDescendants(),
+ function(node) { _this.registerDNDNode(node); }
+ );
+ },
+
+ /**
+ * Controller(node model) creates DNDNodes because it passes itself to node for synchroneous drops processing
+ * I can't process DnD with events cause an event can't return result success/false
+ */
+ registerDNDNode: function(node) {
+ if (!node.tree.DNDMode) return;
+
+//dojo.debug("registerDNDNode "+node);
+
+ /* I drag label, not domNode, because large domNodes are very slow to copy and large to drag */
+
+ var source = null;
+ var target = null;
+
+ if (!node.actionIsDisabled(node.actions.MOVE)) {
+ //dojo.debug("reg source")
+ var source = new dojo.dnd.TreeDragSource(node.labelNode, this, node.tree.widgetId, node);
+ this.dragSources[node.widgetId] = source;
+ }
+
+ var target = new dojo.dnd.TreeDropTarget(node.labelNode, this.treeController, node.tree.DNDAcceptTypes, node);
+
+ this.dropTargets[node.widgetId] = target;
+
+ },
+
+
+ unregisterDNDNode: function(node) {
+
+ if (this.dragSources[node.widgetId]) {
+ dojo.dnd.dragManager.unregisterDragSource(this.dragSources[node.widgetId]);
+ delete this.dragSources[node.widgetId];
+ }
+
+ if (this.dropTargets[node.widgetId]) {
+ dojo.dnd.dragManager.unregisterDropTarget(this.dropTargets[node.widgetId]);
+ delete this.dropTargets[node.widgetId];
+ }
+ }
+
+
+
+
+
+});
diff --git a/source/web/scripts/ajax/src/dnd/TreeDragAndDropV3.js b/source/web/scripts/ajax/src/dnd/TreeDragAndDropV3.js
new file mode 100644
index 0000000000..5aaed906c6
--- /dev/null
+++ b/source/web/scripts/ajax/src/dnd/TreeDragAndDropV3.js
@@ -0,0 +1,378 @@
+/**
+ * TreeDrag* specialized on managing subtree drags
+ * It selects nodes and visualises what's going on,
+ * but delegates real actions upon tree to the controller
+ *
+ * This code is considered a part of controller
+*/
+
+dojo.provide("dojo.dnd.TreeDragAndDropV3");
+dojo.provide("dojo.dnd.TreeDragSourceV3");
+dojo.provide("dojo.dnd.TreeDropTargetV3");
+
+dojo.require("dojo.dnd.HtmlDragAndDrop");
+dojo.require("dojo.lang.func");
+dojo.require("dojo.lang.array");
+dojo.require("dojo.lang.extras");
+dojo.require("dojo.Deferred");
+dojo.require("dojo.html.layout");
+
+// FIXME: if controller can't move then skip node on move start
+dojo.dnd.TreeDragSourceV3 = function(node, syncController, type, treeNode){
+ //dojo.profile.start("TreeDragSourceV3 "+treeNode);
+ this.controller = syncController;
+ this.treeNode = treeNode;
+
+ dojo.dnd.HtmlDragSource.call(this, node, type);
+ //dojo.profile.end("TreeDragSourceV3 "+treeNode);
+
+}
+
+dojo.inherits(dojo.dnd.TreeDragSourceV3, dojo.dnd.HtmlDragSource);
+
+
+// .......................................
+
+dojo.dnd.TreeDropTargetV3 = function(domNode, controller, type, treeNode){
+
+ this.treeNode = treeNode;
+ this.controller = controller; // I will sync-ly process drops
+
+ dojo.dnd.HtmlDropTarget.call(this, domNode, type);
+}
+
+dojo.inherits(dojo.dnd.TreeDropTargetV3, dojo.dnd.HtmlDropTarget);
+
+dojo.lang.extend(dojo.dnd.TreeDropTargetV3, {
+
+ autoExpandDelay: 1500,
+ autoExpandTimer: null,
+
+
+ position: null,
+
+ indicatorStyle: "2px black groove",
+
+ showIndicator: function(position) {
+
+ // do not change style too often, cause of blinking possible
+ if (this.position == position) {
+ return;
+ }
+
+ //dojo.debug("set position for "+this.treeNode)
+
+ this.hideIndicator();
+
+ this.position = position;
+
+ var node = this.treeNode;
+
+
+ node.contentNode.style.width = dojo.html.getBorderBox(node.labelNode).width + "px";
+
+ if (position == "onto") {
+ node.contentNode.style.border = this.indicatorStyle;
+ } else {
+ // FIXME: bottom-top or highlight should cover ONLY top/bottom or div itself,
+ // not span whole line (try Dnd)
+ // FAILURE: Can't put span inside div: multiline bottom-top will span multiple lines
+ if (position == "before") {
+ node.contentNode.style.borderTop = this.indicatorStyle;
+ } else if (position == "after") {
+ node.contentNode.style.borderBottom = this.indicatorStyle;
+ }
+ }
+ },
+
+ hideIndicator: function() {
+ this.treeNode.contentNode.style.borderBottom = "";
+ this.treeNode.contentNode.style.borderTop = "";
+ this.treeNode.contentNode.style.border = "";
+ this.treeNode.contentNode.style.width=""
+ this.position = null;
+ },
+
+
+
+ // is the target possibly ok ?
+ // This function is run on dragOver, but drop possibility is also determined by position over node
+ // that's why acceptsWithPosition is called
+ // doesnt take index into account ( can change while moving mouse w/o changing target )
+ /**
+ * Coarse (tree-level) access check.
+ * We can't determine real accepts status w/o position
+ */
+ onDragOver: function(e){
+ //dojo.debug("onDragOver for "+e);
+
+ var accepts = dojo.dnd.HtmlDropTarget.prototype.onDragOver.apply(this, arguments);
+
+ //dojo.debug("TreeDropTarget.onDragOver accepts:"+accepts)
+
+ if (accepts && this.treeNode.isFolder && !this.treeNode.isExpanded) {
+ this.setAutoExpandTimer();
+ }
+
+ if (accepts) {
+ this.cacheNodeCoords();
+ }
+
+
+ return accepts;
+ },
+
+ /* Parent.onDragOver calls this function to get accepts status */
+ accepts: function(dragObjects) {
+
+ var accepts = dojo.dnd.HtmlDropTarget.prototype.accepts.apply(this, arguments);
+
+ //dojo.debug("accepts "+accepts);
+
+ if (!accepts) return false;
+
+ for(var i=0; i it was allowed before, no accept check is needed
+ if (position=="onto") {
+ return position;
+ }
+
+ for(var i=0; i forbidden
+ if (DndMode & dojo.widget.TreeV3.prototype.DndModes.ONTO
+ && DndMode & dojo.widget.TreeV3.prototype.DndModes.BETWEEN) {
+ //dojo.debug("BOTH");
+ if (p<=0.33) {
+ position = "before";
+ // if children are expanded then I ignore understrike, cause it is confusing with firstChild
+ // but for last nodes I put understrike there
+ } else if (p<=0.66 || this.treeNode.isExpanded && this.treeNode.children.length && !this.treeNode.isLastNode()) {
+ position = "onto";
+ } else {
+ position = "after";
+ }
+ } else if (DndMode & dojo.widget.TreeV3.prototype.DndModes.BETWEEN) {
+ //dojo.debug("BETWEEN");
+ if (p<=0.5 || this.treeNode.isExpanded && this.treeNode.children.length && !this.treeNode.isLastNode()) {
+ position = "before";
+ } else {
+ position = "after";
+ }
+ }
+ else if (DndMode & dojo.widget.TreeV3.prototype.DndModes.ONTO) {
+ //dojo.debug("ONTO");
+ position = "onto";
+ }
+
+ //dojo.debug(position);
+
+ return position;
+ },
+
+
+
+ getTargetParentIndex: function(source, position) {
+
+ var index = position == "before" ? this.treeNode.getParentIndex() : this.treeNode.getParentIndex()+1;
+ if (source.treeNode
+ && this.treeNode.parent === source.treeNode.parent
+ && this.treeNode.getParentIndex() > source.treeNode.getParentIndex()) {
+ index--; // dragging a node is different for simple move bacause of before-after issues
+ }
+
+ return index;
+ },
+
+
+ onDrop: function(e){
+ // onDropEnd will clean position
+
+
+ var position = this.position;
+
+//dojo.debug(position);
+ var source = e.dragObject.dragSource;
+
+ //dojo.debug("onDrop "+source.treeNode+" " + position + " "+this.treeNode);
+
+
+ var targetParent, targetIndex;
+ if (position == "onto") {
+ targetParent = this.treeNode;
+ targetIndex = 0;
+ } else {
+ targetIndex = this.getTargetParentIndex(source, position);
+ targetParent = this.treeNode.parent;
+ }
+
+ //dojo.profile.start("onDrop "+sourceTreeNode);
+ var r = this.getDropHandler(e, source, targetParent, targetIndex)();
+
+ //dojo.profile.end("onDrop "+sourceTreeNode);
+
+ return r;
+
+ },
+
+ /**
+ * determine, which action I should perform with nodes
+ * e.g move, clone..
+ */
+ getDropHandler: function(e, source, targetParent, targetIndex) {
+ var handler;
+ var _this = this;
+ handler = function () {
+ //dojo.debug("Move "+source.treeNode+" to parent "+targetParent+":"+targetIndex);
+ if (source.treeNode) {
+ var result = _this.controller.move(source.treeNode, targetParent, targetIndex, true);
+ //dojo.debug("moved "+result);
+ } else {
+ if (source.onDrop) {
+ source.onDrop(targetParent, targetIndex);
+ }
+ var result = _this.controller.createChild(targetParent, targetIndex, source.getTreeNode(), true);
+ }
+
+ if (result instanceof dojo.Deferred) {
+ // return error status
+ //TODO: need handle errors somehow
+ //result.addErrback(function(r) { dojo.debugShallow(r); });
+ return (!result.fired) ? true : false;
+ } else {
+ return result;
+ }
+ }
+
+ return handler;
+ }
+
+
+});
+
diff --git a/source/web/scripts/ajax/src/dnd/__package__.js b/source/web/scripts/ajax/src/dnd/__package__.js
new file mode 100644
index 0000000000..c0bdc8f771
--- /dev/null
+++ b/source/web/scripts/ajax/src/dnd/__package__.js
@@ -0,0 +1,6 @@
+dojo.kwCompoundRequire({
+ common: ["dojo.dnd.DragAndDrop"],
+ browser: ["dojo.dnd.HtmlDragAndDrop"],
+ dashboard: ["dojo.dnd.HtmlDragAndDrop"]
+});
+dojo.provide("dojo.dnd.*");
diff --git a/source/web/scripts/ajax/src/doc.js b/source/web/scripts/ajax/src/doc.js
new file mode 100644
index 0000000000..2f65ae7f58
--- /dev/null
+++ b/source/web/scripts/ajax/src/doc.js
@@ -0,0 +1,622 @@
+/*
+ Copyright (c) 2004-2006, The Dojo Foundation
+ All Rights Reserved.
+
+ Licensed under the Academic Free License version 2.1 or above OR the
+ modified BSD license. For more information on Dojo licensing, see:
+
+ http://dojotoolkit.org/community/licensing.shtml
+*/
+
+dojo.provide("dojo.doc");
+dojo.require("dojo.io.*");
+dojo.require("dojo.event.topic");
+dojo.require("dojo.rpc.JotService");
+dojo.require("dojo.dom");
+
+/*
+ * TODO:
+ *
+ * Package summary needs to compensate for "is"
+ * Handle host environments
+ * Deal with dojo.widget weirdness
+ * Parse parameters
+ * Limit function parameters to only the valid ones (Involves packing parameters onto meta during rewriting)
+ * Package display page
+ *
+ */
+
+dojo.doc._count = 0;
+dojo.doc._keys = {};
+dojo.doc._myKeys = [];
+dojo.doc._callbacks = {function_names: []};
+dojo.doc._cache = {}; // Saves the JSON objects in cache
+dojo.doc._rpc = new dojo.rpc.JotService;
+dojo.doc._rpc.serviceUrl = "http://dojotoolkit.org/~pottedmeat/jsonrpc.php";
+
+dojo.lang.mixin(dojo.doc, {
+ functionNames: function(/*mixed*/ selectKey, /*Function*/ callback){
+ // summary: Returns an ordered list of package and function names.
+ dojo.debug("functionNames()");
+ if(!selectKey){
+ selectKey = ++dojo.doc._count;
+ }
+ dojo.doc._buildCache({
+ type: "function_names",
+ callbacks: [dojo.doc._functionNames, callback],
+ selectKey: selectKey
+ });
+ },
+
+ _functionNames: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
+ dojo.debug("_functionNames()");
+ var searchData = [];
+ for(var key in data){
+ // Add the package if it doesn't exist in its children
+ if(!dojo.lang.inArray(data[key], key)){
+ searchData.push([key, key]);
+ }
+ // Add the functions
+ for(var pkg_key in data[key]){
+ searchData.push([data[key][pkg_key], data[key][pkg_key]]);
+ }
+ }
+
+ searchData = searchData.sort(dojo.doc._sort);
+
+ if(evt.callbacks && evt.callbacks.length){
+ var callback = evt.callbacks.shift();
+ callback.call(null, type, searchData, evt);
+ }
+ },
+
+ getMeta: function(/*mixed*/ selectKey, /*Function*/ callback, /*Function*/ name, /*String?*/ id){
+ // summary: Gets information about a function in regards to its meta data
+ dojo.debug("getMeta(" + name + ")");
+ if(!selectKey){
+ selectKey = ++dojo.doc._count;
+ }
+ dojo.doc._buildCache({
+ type: "meta",
+ callbacks: [callback],
+ name: name,
+ id: id,
+ selectKey: selectKey
+ });
+ },
+
+ _getMeta: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
+ dojo.debug("_getMeta(" + evt.name + ") has package: " + evt.pkg + " with: " + type);
+ if("load" == type && evt.pkg){
+ evt.type = "meta";
+ dojo.doc._buildCache(evt);
+ }else{
+ if(evt.callbacks && evt.callbacks.length){
+ var callback = evt.callbacks.shift();
+ callback.call(null, "error", {}, evt);
+ }
+ }
+ },
+
+ getSrc: function(/*mixed*/ selectKey, /*Function*/ callback, /*String*/ name, /*String?*/ id){
+ // summary: Gets src file (created by the doc parser)
+ dojo.debug("getSrc()");
+ if(!selectKey){
+ selectKey = ++dojo.doc._count;
+ }
+ dojo.doc._buildCache({
+ type: "src",
+ callbacks: [callback],
+ name: name,
+ id: id,
+ selectKey: selectKey
+ });
+ },
+
+ _getSrc: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
+ dojo.debug("_getSrc()");
+ if(evt.pkg){
+ evt.type = "src";
+ dojo.doc._buildCache(evt);
+ }else{
+ if(evt.callbacks && evt.callbacks.length){
+ var callback = evt.callbacks.shift();
+ callback.call(null, "error", {}, evt);
+ }
+ }
+ },
+
+ getDoc: function(/*mixed*/ selectKey, /*Function*/ callback, /*String*/ name, /*String?*/ id){
+ // summary: Gets external documentation stored on jot
+ dojo.debug("getDoc()");
+ if(!selectKey){
+ selectKey = ++dojo.doc._count;
+ }
+ var input = {
+ type: "doc",
+ callbacks: [callback],
+ name: name,
+ id: id,
+ selectKey: selectKey
+ }
+ dojo.doc.functionPackage(dojo.doc._getDoc, input);
+ },
+
+ _getDoc: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
+ dojo.debug("_getDoc(" + evt.pkg + "/" + evt.name + ")");
+
+ dojo.doc._keys[evt.selectKey] = {count: 0};
+
+ var search = {};
+ search.forFormName = "DocFnForm";
+ search.limit = 1;
+
+ if(!evt.id){
+ search.filter = "it/DocFnForm/require = '" + evt.pkg + "' and it/DocFnForm/name = '" + evt.name + "' and not(it/DocFnForm/id)";
+ }else{
+ search.filter = "it/DocFnForm/require = '" + evt.pkg + "' and it/DocFnForm/name = '" + evt.name + "' and it/DocFnForm/id = '" + evt.id + "'";
+ }
+ dojo.debug(dojo.json.serialize(search));
+
+ dojo.doc._rpc.callRemote("search", search).addCallbacks(function(data){ evt.type = "fn"; dojo.doc._gotDoc("load", data.list[0], evt); }, function(data){ evt.type = "fn"; dojo.doc._gotDoc("error", {}, evt); });
+
+ search.forFormName = "DocParamForm";
+
+ if(!evt.id){
+ search.filter = "it/DocParamForm/fns = '" + evt.pkg + "=>" + evt.name + "'";
+ }else{
+ search.filter = "it/DocParamForm/fns = '" + evt.pkg + "=>" + evt.name + "=>" + evt.id + "'";
+ }
+ delete search.limit;
+
+ dojo.doc._rpc.callRemote("search", search).addCallbacks(function(data){ evt.type = "param"; dojo.doc._gotDoc("load", data.list, evt); }, function(data){ evt.type = "param"; dojo.doc._gotDoc("error", {}, evt); });
+ },
+
+ _gotDoc: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
+ dojo.debug("_gotDoc(" + evt.type + ") for " + evt.selectKey);
+ dojo.doc._keys[evt.selectKey][evt.type] = data;
+ if(++dojo.doc._keys[evt.selectKey].count == 2){
+ dojo.debug("_gotDoc() finished");
+ var keys = dojo.doc._keys[evt.selectKey];
+ var description = '';
+ if(!keys.fn){
+ keys.fn = {}
+ }
+ if(keys.fn["main/text"]){
+ description = dojo.dom.createDocumentFromText(keys.fn["main/text"]).childNodes[0].innerHTML;
+ if(!description){
+ description = keys.fn["main/text"];
+ }
+ }
+ data = {
+ description: description,
+ returns: keys.fn["DocFnForm/returns"],
+ id: keys.fn["DocFnForm/id"],
+ parameters: {},
+ variables: []
+ }
+ for(var i = 0, param; param = keys["param"][i]; i++){
+ data.parameters[param["DocParamForm/name"]] = {
+ description: param["DocParamForm/desc"]
+ };
+ }
+
+ delete dojo.doc._keys[evt.selectKey];
+
+ if(evt.callbacks && evt.callbacks.length){
+ var callback = evt.callbacks.shift();
+ callback.call(null, "load", data, evt);
+ }
+ }
+ },
+
+ getPkgMeta: function(/*mixed*/ selectKey, /*Function*/ callback, /*String*/ name){
+ dojo.debug("getPkgMeta(" + name + ")");
+ if(!selectKey){
+ selectKey = ++dojo.doc._count;
+ }
+ dojo.doc._buildCache({
+ type: "pkgmeta",
+ callbacks: [callback],
+ name: name,
+ selectKey: selectKey
+ });
+ },
+
+ _getPkgMeta: function(/*Object*/ input){
+ dojo.debug("_getPkgMeta(" + input.name + ")");
+ input.type = "pkgmeta";
+ dojo.doc._buildCache(input);
+ },
+
+ _onDocSearch: function(/*Object*/ input){
+ dojo.debug("_onDocSearch(" + input.name + ")");
+ if(!input.name){
+ return;
+ }
+ if(!input.selectKey){
+ input.selectKey = ++dojo.doc._count;
+ }
+ input.callbacks = [dojo.doc._onDocSearchFn];
+ input.name = input.name.toLowerCase();
+ input.type = "function_names";
+
+ dojo.doc._buildCache(input);
+ },
+
+ _onDocSearchFn: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
+ dojo.debug("_onDocSearchFn(" + evt.name + ")");
+ var packages = [];
+ var size = 0;
+ pkgLoop:
+ for(var pkg in data){
+ for(var i = 0, fn; fn = data[pkg][i]; i++){
+ if(fn.toLowerCase().indexOf(evt.name) != -1){
+ // Build a list of all packages that need to be loaded and their loaded state.
+ ++size;
+ packages.push(pkg);
+ continue pkgLoop;
+ }
+ }
+ }
+ dojo.doc._keys[evt.selectKey] = {};
+ dojo.doc._keys[evt.selectKey].pkgs = packages;
+ dojo.doc._keys[evt.selectKey].pkg = evt.name; // Remember what we were searching for
+ dojo.doc._keys[evt.selectKey].loaded = 0;
+ for(var i = 0, pkg; pkg = packages[i]; i++){
+ setTimeout("dojo.doc.getPkgMeta(\"" + evt.selectKey + "\", dojo.doc._onDocResults, \"" + pkg + "\");", i*10);
+ }
+ },
+
+ _onDocResults: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
+ dojo.debug("_onDocResults(" + evt.name + "/" + dojo.doc._keys[evt.selectKey].pkg + ") " + type);
+ ++dojo.doc._keys[evt.selectKey].loaded;
+
+ if(dojo.doc._keys[evt.selectKey].loaded == dojo.doc._keys[evt.selectKey].pkgs.length){
+ var info = dojo.doc._keys[evt.selectKey];
+ var pkgs = info.pkgs;
+ var name = info.pkg;
+ delete dojo.doc._keys[evt.selectKey];
+ var results = {selectKey: evt.selectKey, docResults: []};
+ data = dojo.doc._cache;
+
+ for(var i = 0, pkg; pkg = pkgs[i]; i++){
+ if(!data[pkg]){
+ continue;
+ }
+ for(var fn in data[pkg]["meta"]){
+ if(fn.toLowerCase().indexOf(name) == -1){
+ continue;
+ }
+ if(fn != "requires"){
+ for(var pId in data[pkg]["meta"][fn]){
+ var result = {
+ pkg: pkg,
+ name: fn,
+ summary: ""
+ }
+ if(data[pkg]["meta"][fn][pId].summary){
+ result.summary = data[pkg]["meta"][fn][pId].summary;
+ }
+ results.docResults.push(result);
+ }
+ }
+ }
+ }
+
+ dojo.debug("Publishing docResults");
+ dojo.doc._printResults(results);
+ }
+ },
+
+ _printResults: function(results){
+ dojo.debug("_printResults(): called");
+ // summary: Call this function to send the /doc/results topic
+ },
+
+ _onDocSelectFunction: function(/*Object*/ input){
+ // summary: Get doc, meta, and src
+ var name = input.name;
+ var selectKey = selectKey;
+ dojo.debug("_onDocSelectFunction(" + name + ")");
+ if(!name){
+ return false;
+ }
+ if(!selectKey){
+ selectKey = ++dojo.doc._count;
+ }
+
+ dojo.doc._keys[selectKey] = {size: 0};
+ dojo.doc._myKeys[++dojo.doc._count] = {selectKey: selectKey, type: "meta"}
+ dojo.doc.getMeta(dojo.doc._count, dojo.doc._onDocSelectResults, name);
+ dojo.doc._myKeys[++dojo.doc._count] = {selectKey: selectKey, type: "src"}
+ dojo.doc.getSrc(dojo.doc._count, dojo.doc._onDocSelectResults, name);
+ dojo.doc._myKeys[++dojo.doc._count] = {selectKey: selectKey, type: "doc"}
+ dojo.doc.getDoc(dojo.doc._count, dojo.doc._onDocSelectResults, name);
+ },
+
+ _onDocSelectResults: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
+ dojo.debug("dojo.doc._onDocSelectResults(" + evt.type + ", " + evt.name + ")");
+ var myKey = dojo.doc._myKeys[evt.selectKey];
+ dojo.doc._keys[myKey.selectKey][myKey.type] = data;
+ dojo.doc._keys[myKey.selectKey].size;
+ if(++dojo.doc._keys[myKey.selectKey].size == 3){
+ var key = dojo.lang.mixin(evt, dojo.doc._keys[myKey.selectKey]);
+ delete key.size;
+ dojo.debug("Publishing docFunctionDetail");
+ dojo.doc._printFunctionDetail(key);
+ delete dojo.doc._keys[myKey.selectKey];
+ delete dojo.doc._myKeys[evt.selectKey];
+ }
+ },
+
+ _printFunctionDetail: function(results) {
+ // summary: Call this function to send the /doc/functionDetail topic event
+ },
+
+ _buildCache: function(/*Object*/ input){
+ var type = input.type;
+ var pkg = input.pkg;
+ var callbacks = input.callbacks;
+ var id = input.id;
+ if(!id){
+ id = "_";
+ }
+ var name = input.name;
+
+ dojo.debug("_buildCache() type: " + type);
+ if(type == "function_names"){
+ if(!dojo.doc._cache["function_names"]){
+ dojo.debug("_buildCache() new cache");
+ if(callbacks && callbacks.length){
+ dojo.doc._callbacks.function_names.push([input, callbacks.shift()]);
+ }
+ dojo.doc._cache["function_names"] = {loading: true};
+ dojo.io.bind({
+ url: "json/function_names",
+ mimetype: "text/json",
+ error: function(type, data, evt){
+ dojo.debug("Unable to load function names");
+ for(var i = 0, callback; callback = dojo.doc._callbacks.function_names[i]; i++){
+ callback[1].call(null, "error", {}, callback[0]);
+ }
+ },
+ load: function(type, data, evt){
+ dojo.doc._cache['function_names'] = data;
+ for(var i = 0, callback; callback = dojo.doc._callbacks.function_names[i]; i++){
+ callback[1].call(null, "load", data, callback[0]);
+ }
+ }
+ });
+ }else if(dojo.doc._cache["function_names"].loading){
+ dojo.debug("_buildCache() loading cache");
+ if(callbacks && callbacks.length){
+ dojo.doc._callbacks.function_names.push([input, callbacks.shift()]);
+ }
+ }else{
+ dojo.debug("_buildCache() from cache");
+ if(callbacks && callbacks.length){
+ var callback = callbacks.shift();
+ callback.call(null, "load", dojo.doc._cache["function_names"], input);
+ }
+ }
+ }else if(type == "meta" || type == "src"){
+ if(!pkg){
+ if(type == "meta"){
+ dojo.doc.functionPackage(dojo.doc._getMeta, input);
+ }else{
+ dojo.doc.functionPackage(dojo.doc._getSrc, input);
+ }
+ }else{
+ try{
+ var cached = dojo.doc._cache[pkg][name][id][type];
+ }catch(e){}
+
+ if(cached){
+ if(callbacks && callbacks.length){
+ var callback = callbacks.shift();
+ callback.call(null, "load", cached, input);
+ return;
+ }
+ }
+
+ dojo.debug("Finding " + type + " for: " + pkg + ", function: " + name + ", id: " + id);
+
+ var mimetype = "text/json";
+ if(type == "src"){
+ mimetype = "text/plain"
+ }
+
+ var url = "json/" + pkg + "/" + name + "/" + id + "/" + type;
+
+ dojo.io.bind({
+ url: url,
+ input: input,
+ mimetype: mimetype,
+ error: function(type, data, evt, args){
+ var input = args.input;
+ var pkg = input.pkg;
+ var type = input.type;
+ var callbacks = input.callbacks;
+ var id = input.id;
+ var name = input.name;
+
+ if(callbacks && callbacks.length){
+ if(!data){
+ data = {};
+ }
+ if(!dojo.doc._cache[pkg]){
+ dojo.doc._cache[pkg] = {};
+ }
+ if(!dojo.doc._cache[pkg][name]){
+ dojo.doc._cache[pkg][name] = {};
+ }
+ if(type == "meta"){
+ data.sig = dojo.doc._cache[pkg][name][id].sig;
+ data.params = dojo.doc._cache[pkg][name][id].params;
+ }
+ var callback = callbacks.shift();
+ callback.call(null, "error", data, args.input);
+ }
+ },
+ load: function(type, data, evt, args){
+ var input = args.input;
+ var pkg = input.pkg;
+ var type = input.type;
+ var id = input.id;
+ var name = input.name;
+ var cache = dojo.doc._cache;
+ dojo.debug("_buildCache() loaded " + type);
+
+ if(!data){
+ data = {};
+ }
+ if(!cache[pkg]){
+ dojo.doc._cache[pkg] = {};
+ }
+ if(!cache[pkg][name]){
+ dojo.doc._cache[pkg][name] = {};
+ }
+ if(!cache[pkg][name][id]){
+ dojo.doc._cache[pkg][name][id] = {};
+ }
+ if(!cache[pkg][name][id].meta){
+ dojo.doc._cache[pkg][name][id].meta = {};
+ }
+ dojo.doc._cache[pkg][name][id][type] = data;
+ if(callbacks && callbacks.length){
+ var callback = callbacks.shift();
+ callback.call(null, "load", data, args.input);
+ }
+ }
+ });
+ }
+ }else if(type == "pkgmeta"){
+ try{
+ var cached = dojo.doc._cache[name]["meta"];
+ }catch(e){}
+
+ if(cached){
+ if(callbacks && callbacks.length){
+ var callback = callbacks.shift();
+ callback.call(null, "load", cached, input);
+ return;
+ }
+ }
+
+ dojo.debug("Finding package meta for: " + name);
+
+ dojo.io.bind({
+ url: "json/" + name + "/meta",
+ input: input,
+ mimetype: "text/json",
+ error: function(type, data, evt, args){
+ var callbacks = args.input.callbacks;
+ if(callbacks && callbacks.length){
+ var callback = callbacks.shift();
+ callback.call(null, "error", {}, args.input);
+ }
+ },
+ load: function(type, data, evt, args){
+ var pkg = args.input.name;
+ var cache = dojo.doc._cache;
+
+ dojo.debug("_buildCache() loaded for: " + pkg);
+ if(!cache[pkg]){
+ dojo.doc._cache[pkg] = {};
+ }
+
+ if(!cache[pkg]["meta"]){
+ dojo.doc._cache[pkg]["meta"] = {};
+ }
+
+ var methods = data.methods;
+ if(methods){
+ for(var method in methods){
+ if (method == "is") {
+ continue;
+ }
+ for(var pId in methods[method]){
+ if(!cache[pkg]["meta"][method]){
+ dojo.doc._cache[pkg]["meta"][method] = {};
+ }
+ if(!cache[pkg]["meta"][method][pId]){
+ dojo.doc._cache[pkg]["meta"][method][pId] = {};
+ }
+ dojo.doc._cache[pkg]["meta"][method][pId].summary = methods[method][pId];
+ }
+ }
+ }
+
+ dojo.doc._cache[pkg]["meta"].methods = methods;
+ var requires = data.requires;
+ if(requires){
+ dojo.doc._cache[pkg]["meta"].requires = requires;
+ }
+ if(callbacks && callbacks.length){
+ var callback = callbacks.shift();
+ callback.call(null, "load", methods, input);
+ }
+ }
+ });
+ }
+ },
+
+ selectFunction: function(/*String*/ name, /*String?*/ id){
+ // summary: The combined information
+ },
+
+ savePackage: function(/*String*/ name, /*String*/ description){
+ dojo.doc._rpc.callRemote(
+ "saveForm",
+ {
+ form: "DocPkgForm",
+ path: "/WikiHome/DojoDotDoc/id",
+ pname1: "main/text",
+ pvalue1: "Test"
+ }
+ ).addCallbacks(dojo.doc._results, dojo.doc._results);
+ },
+
+ functionPackage: function(/*Function*/ callback, /*Object*/ input){
+ dojo.debug("functionPackage() name: " + input.name + " for type: " + input.type);
+ input.type = "function_names";
+ input.callbacks.unshift(callback);
+ input.callbacks.unshift(dojo.doc._functionPackage);
+ dojo.doc._buildCache(input);
+ },
+
+ _functionPackage: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
+ dojo.debug("_functionPackage() name: " + evt.name + " for: " + evt.type + " with: " + type);
+ evt.pkg = '';
+
+ var data = dojo.doc._cache['function_names'];
+ for(var key in data){
+ if(dojo.lang.inArray(data[key], evt.name)){
+ evt.pkg = key;
+ break;
+ }
+ }
+
+ if(evt.callbacks && evt.callbacks.length){
+ var callback = evt.callbacks.shift();
+ callback.call(null, type, data[key], evt);
+ }
+ },
+
+ _sort: function(a, b){
+ if(a[0] < b[0]){
+ return -1;
+ }
+ if(a[0] > b[0]){
+ return 1;
+ }
+ return 0;
+ }
+});
+
+dojo.event.topic.subscribe("/doc/search", dojo.doc, "_onDocSearch");
+dojo.event.topic.subscribe("/doc/selectFunction", dojo.doc, "_onDocSelectFunction");
+
+dojo.event.topic.registerPublisher("/doc/results", dojo.doc, "_printResults");
+dojo.event.topic.registerPublisher("/doc/functionDetail", dojo.doc, "_printFunctionDetail");
\ No newline at end of file
diff --git a/source/web/scripts/ajax/src/docs.js b/source/web/scripts/ajax/src/docs.js
new file mode 100644
index 0000000000..03b59b9200
--- /dev/null
+++ b/source/web/scripts/ajax/src/docs.js
@@ -0,0 +1,985 @@
+dojo.provide("dojo.docs");
+dojo.require("dojo.io.*");
+dojo.require("dojo.event.topic");
+dojo.require("dojo.rpc.JotService");
+dojo.require("dojo.dom");
+dojo.require("dojo.uri.Uri");
+
+/*
+ * TODO:
+ *
+ * Package summary needs to compensate for "is"
+ * Handle host environments
+ * Deal with dojo.widget weirdness
+ * Parse parameters
+ * Limit function parameters to only the valid ones (Involves packing parameters onto meta during rewriting)
+ *
+ */
+
+dojo.docs._count = 0;
+dojo.docs._callbacks = {function_names: []};
+dojo.docs._cache = {}; // Saves the JSON objects in cache
+dojo.docs._url = dojo.uri.dojoUri("docscripts/json/");
+dojo.docs._rpc = new dojo.rpc.JotService;
+dojo.docs._rpc.serviceUrl = dojo.uri.dojoUri("docscripts/jsonrpc.php");
+
+dojo.lang.mixin(dojo.docs, {
+ functionNames: function(/*mixed*/ selectKey, /*Function*/ callback){
+ // summary: Returns an ordered list of package and function names.
+ dojo.debug("functionNames()");
+ if(!selectKey){
+ selectKey = ++dojo.docs._count;
+ }
+
+ var input = {};
+ if(typeof selectKey == "object" && selectKey.selectKey){
+ input = selectKey;
+ selectKey = selectKey.selectKey;
+ }
+
+ dojo.docs._buildCache({
+ type: "function_names",
+ callbacks: [dojo.docs._functionNames, callback],
+ selectKey: selectKey,
+ input: input
+ });
+ },
+ _functionNames: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
+ // summary: Converts the stored JSON object into a sorted list of packages
+ // and functions
+ dojo.debug("_functionNames()");
+ var searchData = [];
+ for(var key in data){
+ // Add the package if it doesn't exist in its children
+ if(!dojo.lang.inArray(data[key], key)){
+ var aKey = key;
+ if(aKey.charAt(aKey.length - 1) == "_"){
+ aKey = [aKey.substring(0, aKey.length - 1), "*"].join("");
+ }
+ searchData.push([aKey, aKey]);
+ }
+ // Add the functions
+ for(var pkg_key in data[key]){
+ var aKey = data[key][pkg_key];
+ if(aKey.charAt(aKey.length - 1) == "_"){
+ aKey = [aKey.substring(0, aKey.length - 1), "*"].join("");
+ }
+ searchData.push([aKey, aKey]);
+ }
+ }
+
+ searchData = searchData.sort(dojo.docs._sort);
+
+ if(evt.callbacks && evt.callbacks.length){
+ evt.callbacks.shift()(type, searchData, evt, evt.input);
+ }
+ },
+ getMeta: function(/*mixed*/ selectKey, /*String*/ pkg, /*String*/ name, /*Function*/ callback, /*String?*/ id){
+ // summary: Gets information about a function in regards to its meta data
+ if(typeof name == "function"){
+ // pId: a
+ // pkg: ignore
+ id = callback;
+ callback = name;
+ name = pkg;
+ pkg = null;
+ dojo.debug("getMeta(" + name + ")");
+ }else{
+ dojo.debug("getMeta(" + pkg + "/" + name + ")");
+ }
+
+ if(!id){
+ id = "_";
+ }
+
+ if(!selectKey){
+ selectKey = ++dojo.docs._count;
+ }
+
+ var input;
+ if(typeof selectKey == "object" && selectKey.selectKey){
+ input = selectKey;
+ selectKey = selectKey.selectKey;
+ }else{
+ input = {};
+ }
+
+ dojo.docs._buildCache({
+ type: "meta",
+ callbacks: [dojo.docs._gotMeta, callback],
+ pkg: pkg,
+ name: name,
+ id: id,
+ selectKey: selectKey,
+ input: input
+ });
+ },
+ _withPkg: function(/*String*/ type, /*Object*/ data, /*Object*/ evt, /*Object*/ input, /*String*/ newType){
+ dojo.debug("_withPkg(" + evt.name + ") has package: " + data[0]);
+ evt.pkg = data[0];
+ if("load" == type && evt.pkg){
+ evt.type = newType;
+ dojo.docs._buildCache(evt);
+ }else{
+ if(evt.callbacks && evt.callbacks.length){
+ evt.callbacks.shift()("error", {}, evt, evt.input);
+ }
+ }
+ },
+ _gotMeta: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
+ dojo.debug("_gotMeta(" + evt.name + ")");
+
+ var cached = dojo.docs._getCache(evt.pkg, evt.name, "meta", "methods", evt.id);
+ if(cached.summary){
+ data.summary = cached.summary;
+ }
+ if(evt.callbacks && evt.callbacks.length){
+ evt.callbacks.shift()(type, data, evt, evt.input);
+ }
+ },
+ getSrc: function(/*mixed*/ selectKey, /*String*/ name, /*Function*/ callback, /*String?*/ id){
+ // summary: Gets src file (created by the doc parser)
+ dojo.debug("getSrc(" + name + ")");
+ if(!id){
+ id = "_";
+ }
+ if(!selectKey){
+ selectKey = ++dojo.docs._count;
+ }
+
+ var input;
+ if(typeof selectKey == "object" && selectKey.selectKey){
+ input = selectKey;
+ selectKey = selectKey.selectKey;
+ }else{
+ input = {};
+ }
+
+ dojo.docs._buildCache({
+ type: "src",
+ callbacks: [callback],
+ name: name,
+ id: id,
+ input: input,
+ selectKey: selectKey
+ });
+ },
+ getDoc: function(/*mixed*/ selectKey, /*String*/ name, /*Function*/ callback, /*String?*/ id){
+ // summary: Gets external documentation stored on Jot for a given function
+ dojo.debug("getDoc(" + name + ")");
+
+ if(!id){
+ id = "_";
+ }
+
+ if(!selectKey){
+ selectKey = ++dojo.docs._count;
+ }
+
+ var input = {};
+ if(typeof selectKey == "object" && selectKey.selectKey){
+ input.input = selectKey;
+ selectKey = selectKey.selectKey;
+ }
+
+ input.type = "doc";
+ input.name = name;
+ input.selectKey = selectKey;
+ input.callbacks = [callback];
+ input.selectKey = selectKey;
+
+ dojo.docs._buildCache(input);
+ },
+ _gotDoc: function(/*String*/ type, /*Array*/ data, /*Object*/ evt, /*Object*/ input){
+ dojo.debug("_gotDoc(" + evt.type + ")");
+
+ evt[evt.type] = data;
+ if(evt.expects && evt.expects.doc){
+ for(var i = 0, expect; expect = evt.expects.doc[i]; i++){
+ if(!(expect in evt)){
+ dojo.debug("_gotDoc() waiting for more data");
+ return;
+ }
+ }
+ }
+
+ var cache = dojo.docs._getCache(evt.pkg, "meta", "methods", evt.name, evt.id, "meta");
+
+ var description = evt.fn.description;
+ cache.description = description;
+ data = {
+ returns: evt.fn.returns,
+ id: evt.id,
+ variables: [],
+ selectKey: evt.selectKey
+ }
+ if(!cache.parameters){
+ cache.parameters = {};
+ }
+ for(var i = 0, param; param = evt.param[i]; i++){
+ var fName = param["DocParamForm/name"];
+ if(!cache.parameters[fName]){
+ cache.parameters[fName] = {};
+ }
+ cache.parameters[fName].description = param["DocParamForm/desc"]
+ }
+
+ data.description = cache.description;
+ data.parameters = cache.parameters;
+
+ evt.type = "doc";
+
+ if(evt.callbacks && evt.callbacks.length){
+ evt.callbacks.shift()("load", data, evt, input);
+ }
+ },
+ getPkgDoc: function(/*mixed*/ selectKey, /*String*/ name, /*Function*/ callback){
+ // summary: Gets external documentation stored on Jot for a given package
+ dojo.debug("getPkgDoc(" + name + ")");
+ var input = {};
+ if(typeof selectKey == "object" && selectKey.selectKey){
+ input = selectKey;
+ selectKey = selectKey.selectKey;
+ }
+ if(!selectKey){
+ selectKey = ++dojo.docs._count;
+ }
+ dojo.docs._buildCache({
+ type: "pkgdoc",
+ callbacks: [callback],
+ name: name,
+ selectKey: selectKey,
+ input: input
+ });
+ },
+ getPkgInfo: function(/*mixed*/ selectKey, /*String*/ name, /*Function*/ callback){
+ // summary: Gets a combination of the metadata and external documentation for a given package
+ dojo.debug("getPkgInfo(" + name + ")");
+ if(!selectKey){
+ selectKey = ++dojo.docs._count;
+ }
+
+ var input = {
+ selectKey: selectKey,
+ expects: {
+ pkginfo: ["pkgmeta", "pkgdoc"]
+ },
+ callback: callback
+ };
+ dojo.docs.getPkgMeta(input, name, dojo.docs._getPkgInfo);
+ dojo.docs.getPkgDoc(input, name, dojo.docs._getPkgInfo);
+ },
+ _getPkgInfo: function(/*String*/ type, /*Object*/ data, /*Object*/ evt){
+ dojo.debug("_getPkgInfo() for " + evt.type);
+ var key = evt.selectKey;
+ var input = {};
+ var results = {};
+ if(typeof key == "object"){
+ input = key;
+ key = key.selectKey;
+ input[evt.type] = data;
+ if(input.expects && input.expects.pkginfo){
+ for(var i = 0, expect; expect = input.expects.pkginfo[i]; i++){
+ if(!(expect in input)){
+ dojo.debug("_getPkgInfo() waiting for more data");
+ return;
+ }
+ }
+ }
+ results = input.pkgmeta;
+ results.description = input.pkgdoc;
+ }
+
+ if(input.callback){
+ input.callback("load", results, evt);
+ }
+ },
+ getInfo: function(/*mixed*/ selectKey, /*String*/ name, /*Function*/ callback){
+ dojo.debug("getInfo(" + name + ")");
+ var input = {
+ expects: {
+ "info": ["meta", "doc"]
+ },
+ selectKey: selectKey,
+ callback: callback
+ }
+ dojo.docs.getMeta(input, name, dojo.docs._getInfo);
+ dojo.docs.getDoc(input, name, dojo.docs._getInfo);
+ },
+ _getInfo: function(/*String*/ type, /*String*/ data, /*Object*/ evt, /*Object*/ input){
+ dojo.debug("_getInfo(" + evt.type + ")");
+ if(input && input.expects && input.expects.info){
+ input[evt.type] = data;
+ for(var i = 0, expect; expect = input.expects.info[i]; i++){
+ if(!(expect in input)){
+ dojo.debug("_getInfo() waiting for more data");
+ return;
+ }
+ }
+ }
+
+ if(input.callback){
+ input.callback("load", dojo.docs._getCache(evt.pkg, "meta", "methods", evt.name, evt.id, "meta"), evt, input);
+ }
+ },
+ _getMainText: function(/*String*/ text){
+ // summary: Grabs the innerHTML from a Jot Rech Text node
+ dojo.debug("_getMainText()");
+ return text.replace(/^/, "").replace(/<\/html>$/, "").replace(/<\w+\s*\/>/g, "");
+ },
+ getPkgMeta: function(/*mixed*/ selectKey, /*String*/ name, /*Function*/ callback){
+ dojo.debug("getPkgMeta(" + name + ")");
+ var input = {};
+ if(typeof selectKey == "object" && selectKey.selectKey){
+ input = selectKey;
+ selectKey = selectKey.selectKey;
+ }else if(!selectKey){
+ selectKey = ++dojo.docs._count;
+ }
+ dojo.docs._buildCache({
+ type: "pkgmeta",
+ callbacks: [callback],
+ name: name,
+ selectKey: selectKey,
+ input: input
+ });
+ },
+ _getPkgMeta: function(/*Object*/ input){
+ dojo.debug("_getPkgMeta(" + input.name + ")");
+ input.type = "pkgmeta";
+ dojo.docs._buildCache(input);
+ },
+ _onDocSearch: function(/*Object*/ input){
+ input.name = input.name.replace("*", "_");
+ dojo.debug("_onDocSearch(" + input.name + ")");
+ if(!input.name){
+ return;
+ }
+ if(!input.selectKey){
+ input.selectKey = ++dojo.docs._count;
+ }
+ input.callbacks = [dojo.docs._onDocSearchFn];
+ input.name = input.name.toLowerCase();
+ input.type = "function_names";
+
+ dojo.docs._buildCache(input);
+ },
+ _onDocSearchFn: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
+ dojo.debug("_onDocSearchFn(" + evt.name + ")");
+
+ var packages = [];
+ pkgLoop:
+ for(var pkg in data){
+ if(pkg.toLowerCase() == evt.name.toLowerCase()){
+ evt.name = pkg;
+ dojo.debug("_onDocSearchFn found a package");
+ dojo.docs._onDocSelectPackage(evt);
+ return;
+ }
+ for(var i = 0, fn; fn = data[pkg][i]; i++){
+ if(fn.toLowerCase().indexOf(evt.name) != -1){
+ // Build a list of all packages that need to be loaded and their loaded state.
+ packages.push(pkg);
+ continue pkgLoop;
+ }
+ }
+ }
+ dojo.debug("_onDocSearchFn found a function");
+
+ evt.pkgs = packages;
+ evt.pkg = evt.name;
+ evt.loaded = 0;
+ for(var i = 0, pkg; pkg = packages[i]; i++){
+ dojo.docs.getPkgMeta(evt, pkg, dojo.docs._onDocResults);
+ }
+ },
+ _onPkgResults: function(/*String*/ type, /*Object*/ data, /*Object*/ evt, /*Object*/ input){
+ dojo.debug("_onPkgResults(" + evt.type + ")");
+ var description = "";
+ var path = "";
+ var methods = {};
+ var requires = {};
+ if(input){
+ input[evt.type] = data;
+ if(input.expects && input.expects.pkgresults){
+ for(var i = 0, expect; expect = input.expects.pkgresults[i]; i++){
+ if(!(expect in input)){
+ dojo.debug("_onPkgResults() waiting for more data");
+ return;
+ }
+ }
+ }
+ path = input.pkgdoc.path;
+ description = input.pkgdoc.description;
+ methods = input.pkgmeta.methods;
+ requires = input.pkgmeta.requires;
+ }
+ var pkg = evt.name.replace("_", "*");
+ var results = {
+ path: path,
+ description: description,
+ size: 0,
+ methods: [],
+ pkg: pkg,
+ selectKey: evt.selectKey,
+ requires: requires
+ }
+ var rePrivate = /_[^.]+$/;
+ for(var method in methods){
+ if(!rePrivate.test(method)){
+ for(var pId in methods[method]){
+ results.methods.push({
+ pkg: pkg,
+ name: method,
+ id: pId,
+ summary: methods[method][pId].summary
+ })
+ }
+ }
+ }
+ results.size = results.methods.length;
+ dojo.docs._printPkgResults(results);
+ },
+ _onDocResults: function(/*String*/ type, /*Object*/ data, /*Object*/ evt, /*Object*/ input){
+ dojo.debug("_onDocResults(" + evt.name + "/" + input.pkg + ") " + type);
+ ++input.loaded;
+
+ if(input.loaded == input.pkgs.length){
+ var pkgs = input.pkgs;
+ var name = input.pkg;
+ var results = {selectKey: evt.selectKey, docResults: []};
+ var rePrivate = /_[^.]+$/;
+ data = dojo.docs._cache;
+
+ for(var i = 0, pkg; pkg = pkgs[i]; i++){
+ var methods = dojo.docs._getCache(pkg, "meta", "methods");
+ for(var fn in methods){
+ if(fn.toLowerCase().indexOf(name) == -1){
+ continue;
+ }
+ if(fn != "requires" && !rePrivate.test(fn)){
+ for(var pId in methods[fn]){
+ var result = {
+ pkg: pkg,
+ name: fn,
+ summary: ""
+ }
+ if(methods[fn][pId].summary){
+ result.summary = methods[fn][pId].summary;
+ }
+ results.docResults.push(result);
+ }
+ }
+ }
+ }
+
+ dojo.debug("Publishing docResults");
+ dojo.docs._printFnResults(results);
+ }
+ },
+ _printFnResults: function(results){
+ dojo.debug("_printFnResults(): called");
+ // summary: Call this function to send the /docs/function/results topic
+ },
+ _printPkgResults: function(results){
+ dojo.debug("_printPkgResults(): called");
+ },
+ _onDocSelectFunction: function(/*Object*/ input){
+ // summary: Get doc, meta, and src
+ var name = input.name;
+ dojo.debug("_onDocSelectFunction(" + name + ")");
+ if(!name){
+ return false;
+ }
+ if(!input.selectKey){
+ input.selectKey = ++dojo.docs._count;
+ }
+ input.expects = {
+ "docresults": ["meta", "doc", "pkgmeta"]
+ }
+ dojo.docs.getMeta(input, name, dojo.docs._onDocSelectResults);
+ dojo.docs.getDoc(input, name, dojo.docs._onDocSelectResults);
+ },
+ _onDocSelectPackage: function(/*Object*/ input){
+ dojo.debug("_onDocSelectPackage(" + input.name + ")")
+ input.expects = {
+ "pkgresults": ["pkgmeta", "pkgdoc"]
+ };
+ if(!input.selectKey){
+ input.selectKey = ++dojo.docs._count;
+ }
+ dojo.docs.getPkgMeta(input, input.name, dojo.docs._onPkgResults);
+ dojo.docs.getPkgDoc(input, input.name, dojo.docs._onPkgResults);
+ },
+ _onDocSelectResults: function(/*String*/ type, /*Object*/ data, /*Object*/ evt, /*Object*/ input){
+ dojo.debug("_onDocSelectResults(" + evt.type + ", " + evt.name + ")");
+ if(evt.type == "meta"){
+ dojo.docs.getPkgMeta(input, evt.pkg, dojo.docs._onDocSelectResults);
+ }
+ if(input){
+ input[evt.type] = data;
+ if(input.expects && input.expects.docresults){
+ for(var i = 0, expect; expect = input.expects.docresults[i]; i++){
+ if(!(expect in input)){
+ dojo.debug("_onDocSelectResults() waiting for more data");
+ return;
+ }
+ }
+ }
+ }
+
+ dojo.docs._printFunctionDetail(input);
+ },
+
+ _printFunctionDetail: function(results) {
+ // summary: Call this function to send the /docs/function/detail topic event
+ },
+
+ _buildCache: function(/*Object*/ input){
+ dojo.debug("_buildCache(" + input.type + ", " + input.name + ")");
+ // Get stuff from the input object
+ var type = input.type;
+ var pkg = input.pkg;
+ var callbacks = input.callbacks;
+ var id = input.id;
+ if(!id){
+ id = input.id = "_";
+ }
+ var name = input.name;
+ var selectKey = input.selectKey;
+
+ var META = "meta";
+ var METHODS = "methods";
+ var SRC = "src";
+ var DESCRIPTION = "description";
+ var INPUT = "input";
+ var LOAD = "load";
+ var ERROR = "error";
+
+ var docs = dojo.docs;
+ var getCache = docs._getCache;
+
+ // Stuff to pass to RPC
+ var search = [];
+
+ if(type == "doc"){
+ if(!pkg){
+ docs.functionPackages(selectKey, name, function(){ var a = arguments; docs._withPkg.call(this, a[0], a[1], a[2], a[3], "doc"); }, input);
+ return;
+ }else{
+ var cached = getCache(pkg, META, METHODS, name, id, META);
+
+ if(cached[DESCRIPTION]){
+ callbacks.shift()(LOAD, cached[DESCRIPTION], input, input[INPUT]);
+ return;
+ }
+
+ var obj = {};
+ obj.forFormName = "DocFnForm";
+ obj.limit = 1;
+
+ obj.filter = "it/DocFnForm/require = '" + pkg + "' and it/DocFnForm/name = '" + name + "' and ";
+ if(id == "_"){
+ obj.filter += " not(it/DocFnForm/id)";
+ }else{
+ obj.filter += " it/DocFnForm/id = '" + id + "'";
+ }
+
+ obj.load = function(data){
+ var cached = getCache(pkg, META, METHODS, name, id, META);
+
+ var description = "";
+ var returns = "";
+ if(data.list && data.list.length){
+ description = docs._getMainText(data.list[0]["main/text"]);
+ returns = data.list[0]["DocFnForm/returns"];
+ }
+
+ cached[DESCRIPTION] = description;
+ if(!cached.returns){
+ cached.returns = {};
+ }
+ cached.returns.summary = returns;
+
+ input.type = "fn";
+ docs._gotDoc(LOAD, cached, input, input[INPUT]);
+ }
+ obj.error = function(data){
+ input.type = "fn";
+ docs._gotDoc(ERROR, {}, input, input[INPUT]);
+ }
+ search.push(obj);
+
+ obj = {};
+ obj.forFormName = "DocParamForm";
+
+ obj.filter = "it/DocParamForm/fns = '" + pkg + "=>" + name;
+ if(id != "_"){
+ obj.filter += "=>" + id;
+ }
+ obj.filter += "'";
+
+ obj.load = function(data){
+ var cache = getCache(pkg, META, METHODS, name, id, META);
+ for(var i = 0, param; param = data.list[i]; i++){
+ var pName = param["DocParamForm/name"];
+ if(!cache.parameters[pName]){
+ cache.parameters[pName] = {};
+ }
+ cache.parameters[pName].summary = param["DocParamForm/desc"];
+ }
+ input.type = "param";
+ docs._gotDoc(LOAD, cache.parameters, input);
+ }
+ obj.error = function(data){
+ input.type = "param";
+ docs._gotDoc(ERROR, {}, input);
+ }
+ search.push(obj);
+ }
+ }else if(type == "pkgdoc"){
+ var cached = getCache(name, META);
+
+ if(cached[DESCRIPTION]){
+ callbacks.shift()(LOAD, {description: cached[DESCRIPTION], path: cached.path}, input, input.input);
+ return;
+ }
+
+ var obj = {};
+ obj.forFormName = "DocPkgForm";
+ obj.limit = 1;
+ obj.filter = "it/DocPkgForm/require = '" + name + "'";
+
+ obj.load = function(data){
+ var description = "";
+ var list = data.list;
+ if(list && list.length && list[0]["main/text"]){
+ description = docs._getMainText(list[0]["main/text"]);
+ cached[DESCRIPTION] = description;
+ cached.path = list[0].name;
+ }
+
+ if(callbacks && callbacks.length){
+ callbacks.shift()(LOAD, {description: description, path: cached.path}, input, input.input);
+ }
+ }
+ obj.error = function(data){
+ if(callbacks && callbacks.length){
+ callbacks.shift()(ERROR, "", input, input.input);
+ }
+ }
+ search.push(obj);
+ }else if(type == "function_names"){
+ var cached = getCache();
+ if(!cached.function_names){
+ dojo.debug("_buildCache() new cache");
+ if(callbacks && callbacks.length){
+ docs._callbacks.function_names.push([input, callbacks.shift()]);
+ }
+ cached.function_names = {loading: true};
+
+ var obj = {};
+ obj.url = "function_names";
+ obj.load = function(type, data, evt){
+ cached.function_names = data;
+ while(docs._callbacks.function_names.length){
+ var parts = docs._callbacks.function_names.pop();
+ parts[1](LOAD, data, parts[0]);
+ }
+ }
+ obj.error = function(type, data, evt){
+ while(docs._callbacks.function_names.length){
+ var parts = docs._callbacks.function_names.pop();
+ parts[1](LOAD, {}, parts[0]);
+ }
+ }
+ search.push(obj);
+ }else if(cached.function_names.loading){
+ dojo.debug("_buildCache() loading cache, adding to callback list");
+ if(callbacks && callbacks.length){
+ docs._callbacks.function_names.push([input, callbacks.shift()]);
+ }
+ return;
+ }else{
+ dojo.debug("_buildCache() loading from cache");
+ if(callbacks && callbacks.length){
+ callbacks.shift()(LOAD, cached.function_names, input);
+ }
+ return;
+ }
+ }else if(type == META || type == SRC){
+ if(!pkg){
+ if(type == META){
+ docs.functionPackages(selectKey, name, function(){ var a = arguments; docs._withPkg.call(this, a[0], a[1], a[2], a[3], META); }, input);
+ return;
+ }else{
+ docs.functionPackages(selectKey, name, function(){ var a = arguments; docs._withPkg.call(this, a[0], a[1], a[2], a[3], SRC); }, input);
+ return;
+ }
+ }else{
+ var cached = getCache(pkg, META, METHODS, name, id);
+
+ if(cached[type] && cached[type].returns){
+ if(callbacks && callbacks.length){
+ callbacks.shift()(LOAD, cached[type], input);
+ return;
+ }
+ }
+
+ dojo.debug("Finding " + type + " for: " + pkg + ", function: " + name + ", id: " + id);
+
+ var obj = {};
+
+ if(type == SRC){
+ obj.mimetype = "text/plain"
+ }
+ obj.url = pkg + "/" + name + "/" + id + "/" + type;
+ obj.load = function(type, data, evt){
+ dojo.debug("_buildCache() loaded " + input.type);
+
+ if(input.type == SRC){
+ getCache(pkg, META, METHODS, name, id).src = data;
+ if(callbacks && callbacks.length){
+ callbacks.shift()(LOAD, data, input, input[INPUT]);
+ }
+ }else{
+ var cache = getCache(pkg, META, METHODS, name, id, META);
+ if(!cache.parameters){
+ cache.parameters = {};
+ }
+ for(var i = 0, param; param = data.parameters[i]; i++){
+ if(!cache.parameters[param[1]]){
+ cache.parameters[param[1]] = {};
+ }
+ cache.parameters[param[1]].type = param[0];
+ }
+ if(!cache.returns){
+ cache.returns = {};
+ }
+ cache.returns.type = data.returns;
+ }
+
+ if(callbacks && callbacks.length){
+ callbacks.shift()(LOAD, cache, input, input[INPUT]);
+ }
+ }
+ obj.error = function(type, data, evt){
+ if(callbacks && callbacks.length){
+ callbacks.shift()(ERROR, {}, input, input[INPUT]);
+ }
+ }
+ }
+
+ search.push(obj);
+ }else if(type == "pkgmeta"){
+ var cached = getCache(name, "meta");
+
+ if(cached.requires){
+ if(callbacks && callbacks.length){
+ callbacks.shift()(LOAD, cached, input, input[INPUT]);
+ return;
+ }
+ }
+
+ dojo.debug("Finding package meta for: " + name);
+
+ var obj = {};
+
+ obj.url = name + "/meta";
+ obj.load = function(type, data, evt){
+ dojo.debug("_buildCache() loaded for: " + name);
+
+ var methods = data.methods;
+ if(methods){
+ for(var method in methods){
+ if (method == "is") {
+ continue;
+ }
+ for(var pId in methods[method]){
+ getCache(name, META, METHODS, method, pId, META).summary = methods[method][pId];
+ }
+ }
+ }
+
+ var requires = data.requires;
+ var cache = getCache(name, META);
+ if(requires){
+ cache.requires = requires;
+ }
+ if(callbacks && callbacks.length){
+ callbacks.shift()(LOAD, cache, input, input[INPUT]);
+ }
+ }
+ obj.error = function(type, data, evt){
+ if(callbacks && callbacks.length){
+ callbacks.shift()(ERROR, {}, input, input[INPUT]);
+ }
+ }
+ search.push(obj);
+ }
+
+ for(var i = 0, obj; obj = search[i]; i++){
+ var load = obj.load;
+ var error = obj.error;
+ delete obj.load;
+ delete obj.error;
+ var mimetype = obj.mimetype;
+ if(!mimetype){
+ mimetype = "text/json"
+ }
+ if(obj.url){
+ dojo.io.bind({
+ url: new dojo.uri.Uri(docs._url, obj.url),
+ input: input,
+ mimetype: mimetype,
+ error: error,
+ load: load
+ });
+ }else{
+ docs._rpc.callRemote("search", obj).addCallbacks(load, error);
+ }
+ }
+ },
+ selectFunction: function(/*String*/ name, /*String?*/ id){
+ // summary: The combined information
+ },
+ savePackage: function(/*Object*/ callbackObject, /*String*/ callback, /*Object*/ parameters){
+ dojo.event.kwConnect({
+ srcObj: dojo.docs,
+ srcFunc: "_savedPkgRpc",
+ targetObj: callbackObject,
+ targetFunc: callback,
+ once: true
+ });
+
+ var props = {};
+ var cache = dojo.docs._getCache(parameters.pkg, "meta");
+
+ var i = 1;
+
+ if(!cache.path){
+ var path = "id";
+ props[["pname", i].join("")] = "DocPkgForm/require";
+ props[["pvalue", i++].join("")] = parameters.pkg;
+ }else{
+ var path = cache.path;
+ }
+
+ props.form = "//DocPkgForm";
+ props.path = ["/WikiHome/DojoDotDoc/", path].join("");
+
+ if(parameters.description){
+ props[["pname", i].join("")] = "main/text";
+ props[["pvalue", i++].join("")] = parameters.description;
+ }
+
+ dojo.docs._rpc.callRemote("saveForm", props).addCallbacks(dojo.docs._pkgRpc, dojo.docs._pkgRpc);
+ },
+ _pkgRpc: function(data){
+ if(data.name){
+ dojo.docs._getCache(data["DocPkgForm/require"], "meta").path = data.name;
+ dojo.docs._savedPkgRpc("load");
+ }else{
+ dojo.docs._savedPkgRpc("error");
+ }
+ },
+ _savedPkgRpc: function(type){
+ },
+ functionPackages: function(/*mixed*/ selectKey, /*String*/ name, /*Function*/ callback, /*Object*/ input){
+ // summary: Gets the package associated with a function and stores it in the .pkg value of input
+ dojo.debug("functionPackages() name: " + name);
+
+ if(!input){
+ input = {};
+ }
+ if(!input.callbacks){
+ input.callbacks = [];
+ }
+
+ input.type = "function_names";
+ input.name = name;
+ input.callbacks.unshift(callback);
+ input.callbacks.unshift(dojo.docs._functionPackages);
+ dojo.docs._buildCache(input);
+ },
+ _functionPackages: function(/*String*/ type, /*Array*/ data, /*Object*/ evt){
+ dojo.debug("_functionPackages() name: " + evt.name);
+ evt.pkg = '';
+
+ var results = [];
+ var data = dojo.docs._cache['function_names'];
+ for(var key in data){
+ if(dojo.lang.inArray(data[key], evt.name)){
+ dojo.debug("_functionPackages() package: " + key);
+ results.push(key);
+ }
+ }
+
+ if(evt.callbacks && evt.callbacks.length){
+ evt.callbacks.shift()(type, results, evt, evt.input);
+ }
+ },
+ setUserName: function(/*String*/ name){
+ dojo.docs._userName = name;
+ if(name && dojo.docs._password){
+ dojo.docs._logIn();
+ }
+ },
+ setPassword: function(/*String*/ password){
+ dojo.docs._password = password;
+ if(password && dojo.docs._userName){
+ dojo.docs._logIn();
+ }
+ },
+ _logIn: function(){
+ dojo.io.bind({
+ url: dojo.docs._rpc.serviceUrl.toString(),
+ method: "post",
+ mimetype: "text/json",
+ content: {
+ username: dojo.docs._userName,
+ password: dojo.docs._password
+ },
+ load: function(type, data){
+ if(data.error){
+ dojo.docs.logInSuccess();
+ }else{
+ dojo.docs.logInFailure();
+ }
+ },
+ error: function(){
+ dojo.docs.logInFailure();
+ }
+ });
+ },
+ logInSuccess: function(){},
+ logInFailure: function(){},
+ _sort: function(a, b){
+ if(a[0] < b[0]){
+ return -1;
+ }
+ if(a[0] > b[0]){
+ return 1;
+ }
+ return 0;
+ },
+ _getCache: function(/*String...*/ keys){
+ var obj = dojo.docs._cache;
+ for(var i = 0; i < arguments.length; i++){
+ var arg = arguments[i];
+ if(!obj[arg]){
+ obj[arg] = {};
+ }
+ obj = obj[arg];
+ }
+ return obj;
+ }
+});
+
+dojo.event.topic.subscribe("/docs/search", dojo.docs, "_onDocSearch");
+dojo.event.topic.subscribe("/docs/function/select", dojo.docs, "_onDocSelectFunction");
+dojo.event.topic.subscribe("/docs/package/select", dojo.docs, "_onDocSelectPackage");
+
+dojo.event.topic.registerPublisher("/docs/function/results", dojo.docs, "_printFnResults");
+dojo.event.topic.registerPublisher("/docs/package/results", dojo.docs, "_printPkgResults");
+dojo.event.topic.registerPublisher("/docs/function/detail", dojo.docs, "_printFunctionDetail");
\ No newline at end of file
diff --git a/source/web/scripts/ajax/src/dom.js b/source/web/scripts/ajax/src/dom.js
new file mode 100644
index 0000000000..5593a0d048
--- /dev/null
+++ b/source/web/scripts/ajax/src/dom.js
@@ -0,0 +1,464 @@
+dojo.provide("dojo.dom");
+
+dojo.dom.ELEMENT_NODE = 1;
+dojo.dom.ATTRIBUTE_NODE = 2;
+dojo.dom.TEXT_NODE = 3;
+dojo.dom.CDATA_SECTION_NODE = 4;
+dojo.dom.ENTITY_REFERENCE_NODE = 5;
+dojo.dom.ENTITY_NODE = 6;
+dojo.dom.PROCESSING_INSTRUCTION_NODE = 7;
+dojo.dom.COMMENT_NODE = 8;
+dojo.dom.DOCUMENT_NODE = 9;
+dojo.dom.DOCUMENT_TYPE_NODE = 10;
+dojo.dom.DOCUMENT_FRAGMENT_NODE = 11;
+dojo.dom.NOTATION_NODE = 12;
+
+dojo.dom.dojoml = "http://www.dojotoolkit.org/2004/dojoml";
+
+/**
+ * comprehensive list of XML namespaces
+**/
+dojo.dom.xmlns = {
+ svg : "http://www.w3.org/2000/svg",
+ smil : "http://www.w3.org/2001/SMIL20/",
+ mml : "http://www.w3.org/1998/Math/MathML",
+ cml : "http://www.xml-cml.org",
+ xlink : "http://www.w3.org/1999/xlink",
+ xhtml : "http://www.w3.org/1999/xhtml",
+ xul : "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
+ xbl : "http://www.mozilla.org/xbl",
+ fo : "http://www.w3.org/1999/XSL/Format",
+ xsl : "http://www.w3.org/1999/XSL/Transform",
+ xslt : "http://www.w3.org/1999/XSL/Transform",
+ xi : "http://www.w3.org/2001/XInclude",
+ xforms : "http://www.w3.org/2002/01/xforms",
+ saxon : "http://icl.com/saxon",
+ xalan : "http://xml.apache.org/xslt",
+ xsd : "http://www.w3.org/2001/XMLSchema",
+ dt: "http://www.w3.org/2001/XMLSchema-datatypes",
+ xsi : "http://www.w3.org/2001/XMLSchema-instance",
+ rdf : "http://www.w3.org/1999/02/22-rdf-syntax-ns#",
+ rdfs : "http://www.w3.org/2000/01/rdf-schema#",
+ dc : "http://purl.org/dc/elements/1.1/",
+ dcq: "http://purl.org/dc/qualifiers/1.0",
+ "soap-env" : "http://schemas.xmlsoap.org/soap/envelope/",
+ wsdl : "http://schemas.xmlsoap.org/wsdl/",
+ AdobeExtensions : "http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
+};
+
+dojo.dom.isNode = function(wh){
+ if(typeof Element == "function") {
+ try {
+ return wh instanceof Element;
+ } catch(E) {}
+ } else {
+ // best-guess
+ return wh && !isNaN(wh.nodeType);
+ }
+}
+
+dojo.dom.getUniqueId = function(){
+ var _document = dojo.doc();
+ do {
+ var id = "dj_unique_" + (++arguments.callee._idIncrement);
+ }while(_document.getElementById(id));
+ return id;
+}
+dojo.dom.getUniqueId._idIncrement = 0;
+
+dojo.dom.firstElement = dojo.dom.getFirstChildElement = function(parentNode, tagName){
+ var node = parentNode.firstChild;
+ while(node && node.nodeType != dojo.dom.ELEMENT_NODE){
+ node = node.nextSibling;
+ }
+ if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
+ node = dojo.dom.nextElement(node, tagName);
+ }
+ return node;
+}
+
+dojo.dom.lastElement = dojo.dom.getLastChildElement = function(parentNode, tagName){
+ var node = parentNode.lastChild;
+ while(node && node.nodeType != dojo.dom.ELEMENT_NODE) {
+ node = node.previousSibling;
+ }
+ if(tagName && node && node.tagName && node.tagName.toLowerCase() != tagName.toLowerCase()) {
+ node = dojo.dom.prevElement(node, tagName);
+ }
+ return node;
+}
+
+dojo.dom.nextElement = dojo.dom.getNextSiblingElement = function(node, tagName){
+ if(!node) { return null; }
+ do {
+ node = node.nextSibling;
+ } while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
+
+ if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
+ return dojo.dom.nextElement(node, tagName);
+ }
+ return node;
+}
+
+dojo.dom.prevElement = dojo.dom.getPreviousSiblingElement = function(node, tagName){
+ if(!node) { return null; }
+ if(tagName) { tagName = tagName.toLowerCase(); }
+ do {
+ node = node.previousSibling;
+ } while(node && node.nodeType != dojo.dom.ELEMENT_NODE);
+
+ if(node && tagName && tagName.toLowerCase() != node.tagName.toLowerCase()) {
+ return dojo.dom.prevElement(node, tagName);
+ }
+ return node;
+}
+
+// TODO: hmph
+/*this.forEachChildTag = function(node, unaryFunc) {
+ var child = this.getFirstChildTag(node);
+ while(child) {
+ if(unaryFunc(child) == "break") { break; }
+ child = this.getNextSiblingTag(child);
+ }
+}*/
+
+dojo.dom.moveChildren = function(srcNode, destNode, trim){
+ var count = 0;
+ if(trim) {
+ while(srcNode.hasChildNodes() &&
+ srcNode.firstChild.nodeType == dojo.dom.TEXT_NODE) {
+ srcNode.removeChild(srcNode.firstChild);
+ }
+ while(srcNode.hasChildNodes() &&
+ srcNode.lastChild.nodeType == dojo.dom.TEXT_NODE) {
+ srcNode.removeChild(srcNode.lastChild);
+ }
+ }
+ while(srcNode.hasChildNodes()){
+ destNode.appendChild(srcNode.firstChild);
+ count++;
+ }
+ return count;
+}
+
+dojo.dom.copyChildren = function(srcNode, destNode, trim){
+ var clonedNode = srcNode.cloneNode(true);
+ return this.moveChildren(clonedNode, destNode, trim);
+}
+
+dojo.dom.removeChildren = function(node){
+ var count = node.childNodes.length;
+ while(node.hasChildNodes()){ node.removeChild(node.firstChild); }
+ return count;
+}
+
+dojo.dom.replaceChildren = function(node, newChild){
+ // FIXME: what if newChild is an array-like object?
+ dojo.dom.removeChildren(node);
+ node.appendChild(newChild);
+}
+
+dojo.dom.removeNode = function(node){
+ if(node && node.parentNode){
+ // return a ref to the removed child
+ return node.parentNode.removeChild(node);
+ }
+}
+
+dojo.dom.getAncestors = function(node, filterFunction, returnFirstHit) {
+ var ancestors = [];
+ var isFunction = (filterFunction && (filterFunction instanceof Function || typeof filterFunction == "function"));
+ while(node) {
+ if (!isFunction || filterFunction(node)) {
+ ancestors.push(node);
+ }
+ if (returnFirstHit && ancestors.length > 0) { return ancestors[0]; }
+
+ node = node.parentNode;
+ }
+ if (returnFirstHit) { return null; }
+ return ancestors;
+}
+
+dojo.dom.getAncestorsByTag = function(node, tag, returnFirstHit) {
+ tag = tag.toLowerCase();
+ return dojo.dom.getAncestors(node, function(el){
+ return ((el.tagName)&&(el.tagName.toLowerCase() == tag));
+ }, returnFirstHit);
+}
+
+dojo.dom.getFirstAncestorByTag = function(node, tag) {
+ return dojo.dom.getAncestorsByTag(node, tag, true);
+}
+
+dojo.dom.isDescendantOf = function(node, ancestor, guaranteeDescendant){
+ // guaranteeDescendant allows us to be a "true" isDescendantOf function
+ if(guaranteeDescendant && node) { node = node.parentNode; }
+ while(node) {
+ if(node == ancestor){ return true; }
+ node = node.parentNode;
+ }
+ return false;
+}
+
+dojo.dom.innerXML = function(node){
+ if(node.innerXML){
+ return node.innerXML;
+ }else if (node.xml){
+ return node.xml;
+ }else if(typeof XMLSerializer != "undefined"){
+ return (new XMLSerializer()).serializeToString(node);
+ }
+}
+
+dojo.dom.createDocument = function(){
+ var doc = null;
+ var _document = dojo.doc();
+
+ if(!dj_undef("ActiveXObject")){
+ var prefixes = [ "MSXML2", "Microsoft", "MSXML", "MSXML3" ];
+ for(var i = 0; i1) {
+ var _document = dojo.doc();
+ dojo.dom.replaceChildren(node, _document.createTextNode(text));
+ return text;
+ } else {
+ if(node.textContent != undefined){ //FF 1.5
+ return node.textContent;
+ }
+ var _result = "";
+ if (node == null) { return _result; }
+ for (var i = 0; i < node.childNodes.length; i++) {
+ switch (node.childNodes[i].nodeType) {
+ case 1: // ELEMENT_NODE
+ case 5: // ENTITY_REFERENCE_NODE
+ _result += dojo.dom.textContent(node.childNodes[i]);
+ break;
+ case 3: // TEXT_NODE
+ case 2: // ATTRIBUTE_NODE
+ case 4: // CDATA_SECTION_NODE
+ _result += node.childNodes[i].nodeValue;
+ break;
+ default:
+ break;
+ }
+ }
+ return _result;
+ }
+}
+
+dojo.dom.hasParent = function (node) {
+ return node && node.parentNode && dojo.dom.isNode(node.parentNode);
+}
+
+/**
+ * Determines if node has any of the provided tag names and
+ * returns the tag name that matches, empty string otherwise.
+ *
+ * Examples:
+ *
+ * myFooNode =
+ * isTag(myFooNode, "foo"); // returns "foo"
+ * isTag(myFooNode, "bar"); // returns ""
+ * isTag(myFooNode, "FOO"); // returns ""
+ * isTag(myFooNode, "hey", "foo", "bar"); // returns "foo"
+**/
+dojo.dom.isTag = function(node /* ... */) {
+ if(node && node.tagName) {
+ for(var i=1; i2) ? args[0] : "after",
+ precedence: "last",
+ once: false,
+ delay: null,
+ rate: 0,
+ adviceMsg: false
+ };
+
+ switch(args.length){
+ case 0: return;
+ case 1: return;
+ case 2:
+ ao.srcFunc = args[0];
+ ao.adviceFunc = args[1];
+ break;
+ case 3:
+ if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isString(args[2]))){
+ ao.adviceType = "after";
+ ao.srcObj = args[0];
+ ao.srcFunc = args[1];
+ ao.adviceFunc = args[2];
+ }else if((dl.isString(args[1]))&&(dl.isString(args[2]))){
+ ao.srcFunc = args[1];
+ ao.adviceFunc = args[2];
+ }else if((dl.isObject(args[0]))&&(dl.isString(args[1]))&&(dl.isFunction(args[2]))){
+ ao.adviceType = "after";
+ ao.srcObj = args[0];
+ ao.srcFunc = args[1];
+ var tmpName = dl.nameAnonFunc(args[2], ao.adviceObj, searchForNames);
+ ao.adviceFunc = tmpName;
+ }else if((dl.isFunction(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))){
+ ao.adviceType = "after";
+ ao.srcObj = dj_global;
+ var tmpName = dl.nameAnonFunc(args[0], ao.srcObj, searchForNames);
+ ao.srcFunc = tmpName;
+ ao.adviceObj = args[1];
+ ao.adviceFunc = args[2];
+ }
+ break;
+ case 4:
+ if((dl.isObject(args[0]))&&(dl.isObject(args[2]))){
+ // we can assume that we've got an old-style "connect" from
+ // the sigslot school of event attachment. We therefore
+ // assume after-advice.
+ ao.adviceType = "after";
+ ao.srcObj = args[0];
+ ao.srcFunc = args[1];
+ ao.adviceObj = args[2];
+ ao.adviceFunc = args[3];
+ }else if((dl.isString(args[0]))&&(dl.isString(args[1]))&&(dl.isObject(args[2]))){
+ ao.adviceType = args[0];
+ ao.srcObj = dj_global;
+ ao.srcFunc = args[1];
+ ao.adviceObj = args[2];
+ ao.adviceFunc = args[3];
+ }else if((dl.isString(args[0]))&&(dl.isFunction(args[1]))&&(dl.isObject(args[2]))){
+ ao.adviceType = args[0];
+ ao.srcObj = dj_global;
+ var tmpName = dl.nameAnonFunc(args[1], dj_global, searchForNames);
+ ao.srcFunc = tmpName;
+ ao.adviceObj = args[2];
+ ao.adviceFunc = args[3];
+ }else if((dl.isString(args[0]))&&(dl.isObject(args[1]))&&(dl.isString(args[2]))&&(dl.isFunction(args[3]))){
+ ao.srcObj = args[1];
+ ao.srcFunc = args[2];
+ var tmpName = dl.nameAnonFunc(args[3], dj_global, searchForNames);
+ ao.adviceObj = dj_global;
+ ao.adviceFunc = tmpName;
+ }else if(dl.isObject(args[1])){
+ ao.srcObj = args[1];
+ ao.srcFunc = args[2];
+ ao.adviceObj = dj_global;
+ ao.adviceFunc = args[3];
+ }else if(dl.isObject(args[2])){
+ ao.srcObj = dj_global;
+ ao.srcFunc = args[1];
+ ao.adviceObj = args[2];
+ ao.adviceFunc = args[3];
+ }else{
+ ao.srcObj = ao.adviceObj = ao.aroundObj = dj_global;
+ ao.srcFunc = args[1];
+ ao.adviceFunc = args[2];
+ ao.aroundFunc = args[3];
+ }
+ break;
+ case 6:
+ ao.srcObj = args[1];
+ ao.srcFunc = args[2];
+ ao.adviceObj = args[3]
+ ao.adviceFunc = args[4];
+ ao.aroundFunc = args[5];
+ ao.aroundObj = dj_global;
+ break;
+ default:
+ ao.srcObj = args[1];
+ ao.srcFunc = args[2];
+ ao.adviceObj = args[3]
+ ao.adviceFunc = args[4];
+ ao.aroundObj = args[5];
+ ao.aroundFunc = args[6];
+ ao.once = args[7];
+ ao.delay = args[8];
+ ao.rate = args[9];
+ ao.adviceMsg = args[10];
+ break;
+ }
+
+ if(dl.isFunction(ao.aroundFunc)){
+ var tmpName = dl.nameAnonFunc(ao.aroundFunc, ao.aroundObj, searchForNames);
+ ao.aroundFunc = tmpName;
+ }
+
+ if(dl.isFunction(ao.srcFunc)){
+ ao.srcFunc = dl.getNameInObj(ao.srcObj, ao.srcFunc);
+ }
+
+ if(dl.isFunction(ao.adviceFunc)){
+ ao.adviceFunc = dl.getNameInObj(ao.adviceObj, ao.adviceFunc);
+ }
+
+ if((ao.aroundObj)&&(dl.isFunction(ao.aroundFunc))){
+ ao.aroundFunc = dl.getNameInObj(ao.aroundObj, ao.aroundFunc);
+ }
+
+ if(!ao.srcObj){
+ dojo.raise("bad srcObj for srcFunc: "+ao.srcFunc);
+ }
+ if(!ao.adviceObj){
+ dojo.raise("bad adviceObj for adviceFunc: "+ao.adviceFunc);
+ }
+
+ if(!ao.adviceFunc){
+ dojo.debug("bad adviceFunc for srcFunc: "+ao.srcFunc);
+ dojo.debugShallow(ao);
+ }
+
+ return ao;
+ }
+
+ this.connect = function(){
+ if(arguments.length == 1){
+ var ao = arguments[0];
+ }else{
+ var ao = interpolateArgs(arguments, true);
+ }
+
+ if(dojo.lang.isArray(ao.srcObj) && ao.srcObj!=""){
+ var tmpAO = {};
+ for(var x in ao){
+ tmpAO[x] = ao[x];
+ }
+ var mjps = [];
+ dojo.lang.forEach(ao.srcObj, function(src){
+ if((dojo.render.html.capable)&&(dojo.lang.isString(src))){
+ src = dojo.byId(src);
+ // dojo.debug(src);
+ }
+ tmpAO.srcObj = src;
+ // dojo.debug(tmpAO.srcObj, tmpAO.srcFunc);
+ // dojo.debug(tmpAO.adviceObj, tmpAO.adviceFunc);
+ mjps.push(dojo.event.connect.call(dojo.event, tmpAO));
+ });
+ return mjps;
+ }
+
+ // FIXME: just doing a "getForMethod()" seems to be enough to put this into infinite recursion!!
+ var mjp = dojo.event.MethodJoinPoint.getForMethod(ao.srcObj, ao.srcFunc);
+ if(ao.adviceFunc){
+ var mjp2 = dojo.event.MethodJoinPoint.getForMethod(ao.adviceObj, ao.adviceFunc);
+ }
+
+ mjp.kwAddAdvice(ao);
+
+ return mjp; // advanced users might want to fsck w/ the join point
+ // manually
+ }
+
+ this.log = function(a1, a2){
+ var kwArgs;
+ if((arguments.length == 1)&&(typeof a1 == "object")){
+ kwArgs = a1;
+ }else{
+ kwArgs = {
+ srcObj: a1,
+ srcFunc: a2
+ };
+ }
+ kwArgs.adviceFunc = function(){
+ var argsStr = [];
+ for(var x=0; x= this.jp_.around.length){
+ return this.jp_.object[this.jp_.methodname].apply(this.jp_.object, this.args);
+ // return this.jp_.run_before_after(this.object, this.args);
+ }else{
+ var ti = this.jp_.around[this.around_index];
+ var mobj = ti[0]||dj_global;
+ var meth = ti[1];
+ return mobj[meth].call(mobj, this);
+ }
+}
+
+
+dojo.event.MethodJoinPoint = function(obj, methname){
+ this.object = obj||dj_global;
+ this.methodname = methname;
+ this.methodfunc = this.object[methname];
+ this.before = [];
+ this.after = [];
+ this.around = [];
+}
+
+dojo.event.MethodJoinPoint.getForMethod = function(obj, methname) {
+ // if(!(methname in obj)){
+ if(!obj){ obj = dj_global; }
+ if(!obj[methname]){
+ // supply a do-nothing method implementation
+ obj[methname] = function(){};
+ if(!obj[methname]){
+ // e.g. cannot add to inbuilt objects in IE6
+ dojo.raise("Cannot set do-nothing method on that object "+methname);
+ }
+ }else if((!dojo.lang.isFunction(obj[methname]))&&(!dojo.lang.isAlien(obj[methname]))){
+ return null; // FIXME: should we throw an exception here instead?
+ }
+ // we hide our joinpoint instance in obj[methname + '$joinpoint']
+ var jpname = methname + "$joinpoint";
+ var jpfuncname = methname + "$joinpoint$method";
+ var joinpoint = obj[jpname];
+ if(!joinpoint){
+ var isNode = false;
+ if(dojo.event["browser"]){
+ if( (obj["attachEvent"])||
+ (obj["nodeType"])||
+ (obj["addEventListener"]) ){
+ isNode = true;
+ dojo.event.browser.addClobberNodeAttrs(obj, [jpname, jpfuncname, methname]);
+ }
+ }
+ var origArity = obj[methname].length;
+ obj[jpfuncname] = obj[methname];
+ // joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, methname);
+ joinpoint = obj[jpname] = new dojo.event.MethodJoinPoint(obj, jpfuncname);
+ obj[methname] = function(){
+ var args = [];
+
+ if((isNode)&&(!arguments.length)){
+ var evt = null;
+ try{
+ if(obj.ownerDocument){
+ evt = obj.ownerDocument.parentWindow.event;
+ }else if(obj.documentElement){
+ evt = obj.documentElement.ownerDocument.parentWindow.event;
+ }else if(obj.event){ //obj is a window
+ evt = obj.event;
+ }else{
+ evt = window.event;
+ }
+ }catch(e){
+ evt = window.event;
+ }
+
+ if(evt){
+ args.push(dojo.event.browser.fixEvent(evt, this));
+ }
+ }else{
+ for(var x=0; x0){
+ // pass a cloned array, if this event disconnects this event forEach on this.before wont work
+ dojo.lang.forEach(this.before.concat(new Array()), unrollAdvice);
+ }
+
+ var result;
+ if(this.around.length>0){
+ var mi = new dojo.event.MethodInvocation(this, obj, args);
+ result = mi.proceed();
+ }else if(this.methodfunc){
+ result = this.object[this.methodname].apply(this.object, args);
+ }
+
+ if(this.after.length>0){
+ // see comment on this.before above
+ dojo.lang.forEach(this.after.concat(new Array()), unrollAdvice);
+ }
+
+ return (this.methodfunc) ? result : null;
+ },
+
+ getArr: function(kind){
+ var arr = this.after;
+ // FIXME: we should be able to do this through props or Array.in()
+ if((typeof kind == "string")&&(kind.indexOf("before")!=-1)){
+ arr = this.before;
+ }else if(kind=="around"){
+ arr = this.around;
+ }
+ return arr;
+ },
+
+ kwAddAdvice: function(args){
+ this.addAdvice( args["adviceObj"], args["adviceFunc"],
+ args["aroundObj"], args["aroundFunc"],
+ args["adviceType"], args["precedence"],
+ args["once"], args["delay"], args["rate"],
+ args["adviceMsg"]);
+ },
+
+ addAdvice: function( thisAdviceObj, thisAdvice,
+ thisAroundObj, thisAround,
+ advice_kind, precedence,
+ once, delay, rate, asMessage){
+ var arr = this.getArr(advice_kind);
+ if(!arr){
+ dojo.raise("bad this: " + this);
+ }
+
+ var ao = [thisAdviceObj, thisAdvice, thisAroundObj, thisAround, delay, rate, asMessage];
+
+ if(once){
+ if(this.hasAdvice(thisAdviceObj, thisAdvice, advice_kind, arr) >= 0){
+ return;
+ }
+ }
+
+ if(precedence == "first"){
+ arr.unshift(ao);
+ }else{
+ arr.push(ao);
+ }
+ },
+
+ hasAdvice: function(thisAdviceObj, thisAdvice, advice_kind, arr){
+ if(!arr){ arr = this.getArr(advice_kind); }
+ var ind = -1;
+ for(var x=0; x=0; i=i-1){
+ var el = na[i];
+ if(el["__clobberAttrs__"]){
+ for(var j=0; j 0){
+ for(var i = 0;i < dojo.flash._loadedListeners.length; i++){
+ dojo.flash._loadedListeners[i].call(null);
+ }
+ }
+ },
+
+ /**
+ A callback to know if Flash is currently being installed or
+ having its version revved. To be notified if Flash is installing, connect
+ your callback to this method using the following:
+
+ dojo.event.connect(dojo.flash, "installing", myInstance, "myCallback");
+ */
+ installing: function(){
+ //dojo.debug("installing");
+ if(dojo.flash._installingListeners.length > 0){
+ for(var i = 0; i < dojo.flash._installingListeners.length; i++){
+ dojo.flash._installingListeners[i].call(null);
+ }
+ }
+ },
+
+ /** Initializes dojo.flash. */
+ _initialize: function(){
+ //dojo.debug("dojo.flash._initialize");
+ // see if we need to rev or install Flash on this platform
+ var installer = new dojo.flash.Install();
+ dojo.flash.installer = installer;
+
+ if(installer.needed() == true){
+ installer.install();
+ }else{
+ //dojo.debug("Writing object out");
+ // write the flash object into the page
+ dojo.flash.obj = new dojo.flash.Embed(this._visible);
+ dojo.flash.obj.write(dojo.flash.info.commVersion);
+
+ // initialize the way we do Flash/JavaScript communication
+ dojo.flash.comm = new dojo.flash.Communicator();
+ }
+ }
+};
+
+
+/**
+ A class that helps us determine whether Flash is available,
+ it's major and minor versions, and what Flash version features should
+ be used for Flash/JavaScript communication. Parts of this code
+ are adapted from the automatic Flash plugin detection code autogenerated
+ by the Macromedia Flash 8 authoring environment.
+
+ An instance of this class can be accessed on dojo.flash.info after
+ the page is finished loading.
+
+ This constructor must be called before the page is finished loading.
+*/
+dojo.flash.Info = function(){
+ // Visual basic helper required to detect Flash Player ActiveX control
+ // version information on Internet Explorer
+ if(dojo.render.html.ie){
+ document.writeln('');
+ }
+
+ this._detectVersion();
+ this._detectCommunicationVersion();
+}
+
+dojo.flash.Info.prototype = {
+ /** The full version string, such as "8r22". */
+ version: -1,
+
+ /**
+ The major, minor, and revisions of the plugin. For example, if the
+ plugin is 8r22, then the major version is 8, the minor version is 0,
+ and the revision is 22.
+ */
+ versionMajor: -1,
+ versionMinor: -1,
+ versionRevision: -1,
+
+ /** Whether this platform has Flash already installed. */
+ capable: false,
+
+ /**
+ The major version number for how our Flash and JavaScript communicate.
+ This can currently be the following values:
+ 6 - We use a combination of the Flash plugin methods, such as SetVariable
+ and TCallLabel, along with fscommands, to do communication.
+ 8 - We use the ExternalInterface API.
+ -1 - For some reason neither method is supported, and no communication
+ is possible.
+ */
+ commVersion: 6,
+
+ /** Set if we are in the middle of a Flash installation session. */
+ installing: false,
+
+ /**
+ Asserts that this environment has the given major, minor, and revision
+ numbers for the Flash player. Returns true if the player is equal
+ or above the given version, false otherwise.
+
+ Example: To test for Flash Player 7r14:
+
+ dojo.flash.info.isVersionOrAbove(7, 0, 14)
+ */
+ isVersionOrAbove: function(reqMajorVer, reqMinorVer, reqVer){
+ // make the revision a decimal (i.e. transform revision 14 into
+ // 0.14
+ reqVer = parseFloat("." + reqVer);
+
+ if(this.versionMajor >= reqMajorVer && this.versionMinor >= reqMinorVer
+ && this.versionRevision >= reqVer){
+ return true;
+ }else{
+ return false;
+ }
+ },
+
+ _detectVersion: function(){
+ var versionStr;
+
+ // loop backwards through the versions until we find the newest version
+ for(var testVersion = 25; testVersion > 0; testVersion--){
+ if(dojo.render.html.ie){
+ versionStr = VBGetSwfVer(testVersion);
+ }else{
+ versionStr = this._JSFlashInfo(testVersion);
+ }
+
+ if(versionStr == -1 ){
+ this.capable = false;
+ return;
+ }else if(versionStr != 0){
+ var versionArray;
+ if(dojo.render.html.ie){
+ var tempArray = versionStr.split(" ");
+ var tempString = tempArray[1];
+ versionArray = tempString.split(",");
+ }else{
+ versionArray = versionStr.split(".");
+ }
+
+ this.versionMajor = versionArray[0];
+ this.versionMinor = versionArray[1];
+ this.versionRevision = versionArray[2];
+
+ // 7.0r24 == 7.24
+ var versionString = this.versionMajor + "." + this.versionRevision;
+ this.version = parseFloat(versionString);
+
+ this.capable = true;
+
+ break;
+ }
+ }
+ },
+
+ /**
+ JavaScript helper required to detect Flash Player PlugIn version
+ information. Internet Explorer uses a corresponding Visual Basic
+ version to interact with the Flash ActiveX control.
+ */
+ _JSFlashInfo: function(testVersion){
+ // NS/Opera version >= 3 check for Flash plugin in plugin array
+ if(navigator.plugins != null && navigator.plugins.length > 0){
+ if(navigator.plugins["Shockwave Flash 2.0"] ||
+ navigator.plugins["Shockwave Flash"]){
+ var swVer2 = navigator.plugins["Shockwave Flash 2.0"] ? " 2.0" : "";
+ var flashDescription = navigator.plugins["Shockwave Flash" + swVer2].description;
+ var descArray = flashDescription.split(" ");
+ var tempArrayMajor = descArray[2].split(".");
+ var versionMajor = tempArrayMajor[0];
+ var versionMinor = tempArrayMajor[1];
+ if(descArray[3] != ""){
+ var tempArrayMinor = descArray[3].split("r");
+ }else{
+ var tempArrayMinor = descArray[4].split("r");
+ }
+ var versionRevision = tempArrayMinor[1] > 0 ? tempArrayMinor[1] : 0;
+ var version = versionMajor + "." + versionMinor + "."
+ + versionRevision;
+
+ return version;
+ }
+ }
+
+ return -1;
+ },
+
+ /**
+ Detects the mechanisms that should be used for Flash/JavaScript
+ communication, setting 'commVersion' to either 6 or 8. If the value is
+ 6, we use Flash Plugin 6+ features, such as GetVariable, TCallLabel,
+ and fscommand, to do Flash/JavaScript communication; if the value is
+ 8, we use the ExternalInterface API for communication.
+ */
+ _detectCommunicationVersion: function(){
+ if(this.capable == false){
+ this.commVersion = null;
+ return;
+ }
+
+ // detect if the user has over-ridden the default flash version
+ if (typeof djConfig["forceFlashComm"] != "undefined" &&
+ typeof djConfig["forceFlashComm"] != null){
+ this.commVersion = djConfig["forceFlashComm"];
+ return;
+ }
+
+ // we prefer Flash 6 features over Flash 8, because they are much faster
+ // and much less buggy
+
+ // at this point, we don't have a flash file to detect features on,
+ // so we need to instead look at the browser environment we are in
+ if(dojo.render.html.safari == true || dojo.render.html.opera == true){
+ this.commVersion = 8;
+ }else{
+ this.commVersion = 6;
+ }
+ }
+};
+
+/** A class that is used to write out the Flash object into the page. */
+dojo.flash.Embed = function(visible){
+ this._visible = visible;
+}
+
+dojo.flash.Embed.prototype = {
+ /**
+ The width of this Flash applet. The default is the minimal width
+ necessary to show the Flash settings dialog.
+ */
+ width: 215,
+
+ /**
+ The height of this Flash applet. The default is the minimal height
+ necessary to show the Flash settings dialog.
+ */
+ height: 138,
+
+ /** The id of the Flash object. */
+ id: "flashObject",
+
+ /** Controls whether this is a visible Flash applet or not. */
+ _visible: true,
+
+ /**
+ Writes the Flash into the page. This must be called before the page
+ is finished loading.
+ @param flashVer The Flash version to write.
+ @param doExpressInstall Whether to write out Express Install
+ information. Optional value; defaults to false.
+ */
+ write: function(flashVer, doExpressInstall){
+ //dojo.debug("write");
+ if(dojo.lang.isUndefined(doExpressInstall)){
+ doExpressInstall = false;
+ }
+
+ // determine our container div's styling
+ var containerStyle = new dojo.string.Builder();
+ containerStyle.append("width: " + this.width + "px; ");
+ containerStyle.append("height: " + this.height + "px; ");
+ if(this._visible == false){
+ containerStyle.append("position: absolute; ");
+ containerStyle.append("z-index: 10000; ");
+ containerStyle.append("top: -1000px; ");
+ containerStyle.append("left: -1000px; ");
+ }
+ containerStyle = containerStyle.toString();
+
+ // figure out the SWF file to get and how to write out the correct HTML
+ // for this Flash version
+ var objectHTML;
+ var swfloc;
+ // Flash 6
+ if(flashVer == 6){
+ swfloc = dojo.flash.flash6_version;
+ var dojoPath = djConfig.baseRelativePath;
+ swfloc = swfloc + "?baseRelativePath=" + escape(dojoPath);
+
+ objectHTML =
+ '