diff --git a/bt5/erp5_graph_editor/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml b/bt5/erp5_graph_editor/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9fce5984132e808027cc0ff47d1924915ee242e0
--- /dev/null
+++ b/bt5/erp5_graph_editor/PortalTypeWorkflowChainTemplateItem/workflow_chain_type.xml
@@ -0,0 +1,6 @@
+<workflow_chain>
+ <chain>
+  <type>Business Process</type>
+  <workflow>business_process_graph_editor_interaction_workflow</workflow>
+ </chain>
+</workflow_chain>
\ No newline at end of file
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d1f73a982a9037b1a0a6e550427b7fb417bea8ca
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>erp5_graph_editor</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_getGraph.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_getGraph.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9745efde80976e72e74eae93517866af6887b385
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_getGraph.xml
@@ -0,0 +1,107 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_body</string> </key>
+            <value> <string>import json\n
+portal = context.getPortalObject()\n
+\n
+import json\n
+position_graph = context.getProperty(\'jsplumb_graph\')\n
+\n
+if position_graph:\n
+  context.log(position_graph)\n
+  \n
+  position_graph = json.loads(position_graph)\n
+  \n
+\n
+visited_business_process_set = set() # prevent infinite recurisions\n
+\n
+def getBusinessProcessGraph(business_process):\n
+  graph = dict(node=dict(), edge=dict())\n
+  if business_process in visited_business_process_set:\n
+    return graph\n
+  visited_business_process_set.add(business_process)\n
+  for link in business_process.contentValues(portal_type=\'Business Link\'):\n
+    for trade_state in (link.getPredecessorValue(), link.getSuccessorValue()):\n
+      if trade_state is not None:\n
+        graph[\'node\'][trade_state.getReference() or trade_state.getId()] = dict(\n
+            _class=\'erp5.business_process.trade_state\',\n
+            name=trade_state.getTranslatedTitle())\n
+    if link.getPredecessor() and link.getSuccessor(): # XXX no start ??\n
+      graph[\'edge\'][link.getRelativeUrl()] = dict(\n
+        _class=\'erp5.business_process.business_link\',\n
+        source=link.getPredecessorReference() or link.getPredecessorId(),\n
+        destination=link.getSuccessorReference() or link.getSuccessorId(),\n
+        name=link.getTranslatedTitle())\n
+        \n
+  for specialise in [context] + business_process.getSpecialiseValueList(portal_type=\'Business Process\'):\n
+    specialise_graph = getBusinessProcessGraph(specialise)\n
+    for node_id, node_data in specialise_graph[\'node\'].items():\n
+      graph[\'node\'].setdefault(node_id, node_data)\n
+    for node_id, node_data in specialise_graph[\'edge\'].items():\n
+      graph[\'edge\'].setdefault(node_id, node_data)\n
+  return graph\n
+  \n
+return json.dumps(dict(graph=getBusinessProcessGraph(context), class_definition=[]), indent=2)\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>BusinessProcess_getGraph</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view.xml
new file mode 100644
index 0000000000000000000000000000000000000000..04a6d99bd4731360e2e2adcb76f756fc44220c4b
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view.xml
@@ -0,0 +1,166 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ERP5 Form" module="erp5.portal_type"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary/>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>action</string> </key>
+            <value> <string>Base_edit</string> </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>edit_order</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>enctype</string> </key>
+            <value> <string>application/x-www-form-urlencoded</string> </value>
+        </item>
+        <item>
+            <key> <string>group_list</string> </key>
+            <value>
+              <list>
+                <string>left</string>
+                <string>right</string>
+                <string>center</string>
+                <string>bottom</string>
+                <string>hidden</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>groups</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>bottom</string> </key>
+                    <value>
+                      <list>
+                        <string>listbox</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>center</string> </key>
+                    <value>
+                      <list>
+                        <string>my_description</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value>
+                      <list>
+                        <string>listbox_int_index</string>
+                        <string>listbox_order_builder_title_list</string>
+                        <string>listbox_delivery_builder_title_list</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>left</string> </key>
+                    <value>
+                      <list>
+                        <string>my_title</string>
+                        <string>my_version</string>
+                        <string>my_specialise_title_list</string>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>right</string> </key>
+                    <value>
+                      <list>
+                        <string>my_reference</string>
+                        <string>my_jsplumb_graph</string>
+                        <string>my_translated_validation_state_title</string>
+                      </list>
+                    </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>BusinessProcess_view</string> </value>
+        </item>
+        <item>
+            <key> <string>method</string> </key>
+            <value> <string>POST</string> </value>
+        </item>
+        <item>
+            <key> <string>name</string> </key>
+            <value> <string>BusinessProcessModel_view</string> </value>
+        </item>
+        <item>
+            <key> <string>pt</string> </key>
+            <value> <string>form_view</string> </value>
+        </item>
+        <item>
+            <key> <string>row_length</string> </key>
+            <value> <int>4</int> </value>
+        </item>
+        <item>
+            <key> <string>stored_encoding</string> </key>
+            <value> <string>UTF-8</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string>Business Process Model</string> </value>
+        </item>
+        <item>
+            <key> <string>unicode_mode</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>update_action</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>update_action_title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8662b00fac92d58dbc9aebc5e90942930bce987f
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list>
+                <string>columns</string>
+                <string>editable_columns</string>
+                <string>portal_types</string>
+                <string>selection_name</string>
+                <string>sort</string>
+                <string>title</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>columns</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>int_index</string>
+                          <string>Index</string>
+                        </tuple>
+                        <tuple>
+                          <string>title</string>
+                          <string>Title</string>
+                        </tuple>
+                        <tuple>
+                          <string>predecessor_title</string>
+                          <string>Predecessor</string>
+                        </tuple>
+                        <tuple>
+                          <string>successor_title</string>
+                          <string>Successor</string>
+                        </tuple>
+                        <tuple>
+                          <string>order_builder_title_list</string>
+                          <string>Order Builders</string>
+                        </tuple>
+                        <tuple>
+                          <string>delivery_builder_title_list</string>
+                          <string>Delivery Builders</string>
+                        </tuple>
+                        <tuple>
+                          <string>trade_phase_title</string>
+                          <string>Trade Phase</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>editable_columns</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>int_index</string>
+                          <string>int_index</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_listbox</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewTradeFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>portal_types</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>Business Link</string>
+                          <string>Business Link</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>selection_name</string> </key>
+                    <value> <string>business_process_model_view_selection</string> </value>
+                </item>
+                <item>
+                    <key> <string>sort</string> </key>
+                    <value>
+                      <list>
+                        <tuple>
+                          <string>int_index</string>
+                          <string>ascending</string>
+                        </tuple>
+                      </list>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Business Links</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox_delivery_builder_title_list.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox_delivery_builder_title_list.xml
new file mode 100644
index 0000000000000000000000000000000000000000..73128f976133892c03b2d6b50edd8d738d728dc7
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox_delivery_builder_title_list.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox_delivery_builder_title_list</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_listbox_delivery_builder_title_list</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewTradeFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox_int_index.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox_int_index.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0e10804225a8a5e68f733d5c5f934a2db23814bf
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox_int_index.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox_int_index</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_listbox_int_index</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewTradeFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox_order_builder_title_list.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox_order_builder_title_list.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2b8e7f7777bb9895f67b5312ecd39542fca2e907
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/listbox_order_builder_title_list.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>listbox_order_builder_title_list</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_listbox_order_builder_title_list</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewTradeFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_description.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_description.xml
new file mode 100644
index 0000000000000000000000000000000000000000..407313748d0ca03952214efde4de0b94fea2ffd6
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_description.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_description</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_description</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewTradeFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_jsplumb_graph.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_jsplumb_graph.xml
new file mode 100644
index 0000000000000000000000000000000000000000..94e894e41a105d20e0d4308e64868f25a93f33e8
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_jsplumb_graph.xml
@@ -0,0 +1,247 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="GadgetField" module="Products.ERP5Form.GadgetField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_jsplumb_graph</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+                <item>
+                    <key> <string>required_not_found</string> </key>
+                    <value> <string>Input is required but no input given.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>alternate_name</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>css_class</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>description</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>display_maxwidth</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>display_width</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>external_validator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>extra</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>gadget_url</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>js_sandbox</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>required</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>alternate_name</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>css_class</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value>
+                      <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+                    </value>
+                </item>
+                <item>
+                    <key> <string>description</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>display_maxwidth</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>display_width</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>external_validator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>extra</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>gadget_url</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>js_sandbox</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>required</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>alternate_name</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>css_class</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>default</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>description</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>display_maxwidth</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>display_width</string> </key>
+                    <value> <int>20</int> </value>
+                </item>
+                <item>
+                    <key> <string>editable</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <item>
+                    <key> <string>enabled</string> </key>
+                    <value> <int>1</int> </value>
+                </item>
+                <item>
+                    <key> <string>external_validator</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>extra</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>gadget_url</string> </key>
+                    <value> <string>http://localhost:55432/erp5/portal_skins/custom/jsplumb/index.html</string> </value>
+                </item>
+                <item>
+                    <key> <string>hidden</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>js_sandbox</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>required</string> </key>
+                    <value> <int>0</int> </value>
+                </item>
+                <item>
+                    <key> <string>title</string> </key>
+                    <value> <string>Graph</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="TALESMethod" module="Products.Formulator.TALESField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_text</string> </key>
+            <value> <string>context/BusinessProcess_getGraph</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_reference.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_reference.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0bb8ef4f85efd6fda2a287a82f8f366d84fbae1d
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_reference.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_reference</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_reference</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewTradeFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_specialise_title_list.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_specialise_title_list.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1ca815e81f3f34a80272ee84b9087130626def30
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_specialise_title_list.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_specialise_title_list</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_business_process_specialise_title_list</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewTradeFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_title.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_title.xml
new file mode 100644
index 0000000000000000000000000000000000000000..52bff3e19de037d2c65855e3e82bd986a786ecfe
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_title.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_title</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_title</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewTradeFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_translated_validation_state_title.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_translated_validation_state_title.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1f8ddf9a42025691e6ebf8e70a4bb762c74961ac
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_translated_validation_state_title.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_translated_validation_state_title</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_translated_validation_state_title</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewTradeFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_version.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_version.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3fd68126751a45317c3fc8e95b547a5c199d7fa0
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/BusinessProcess_view/my_version.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>delegated_list</string> </key>
+            <value>
+              <list/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>my_version</string> </value>
+        </item>
+        <item>
+            <key> <string>message_values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>external_validator_failed</string> </key>
+                    <value> <string>The input failed the external validator.</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>overrides</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>tales</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string></string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string></string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+        <item>
+            <key> <string>values</string> </key>
+            <value>
+              <dictionary>
+                <item>
+                    <key> <string>field_id</string> </key>
+                    <value> <string>my_view_mode_version</string> </value>
+                </item>
+                <item>
+                    <key> <string>form_id</string> </key>
+                    <value> <string>Base_viewTradeFieldLibrary</string> </value>
+                </item>
+                <item>
+                    <key> <string>target</string> </key>
+                    <value> <string>Click to edit the target</string> </value>
+                </item>
+              </dictionary>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0856c8bb7ddd9b6477c2897970edb84d2dd347ed
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>dream</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/.Input_viewProductionLine.js.swp.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/.Input_viewProductionLine.js.swp.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cf5e5a576a98f8834be9cfab7f839048d109c5e3
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/.Input_viewProductionLine.js.swp.xml
@@ -0,0 +1,255 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681758.02</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>.Input_viewProductionLine.js.swp</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/octet-stream</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">YjBWSU0gNy40AAAAABAAAM1vT1QrwMYQOUsAAGplcm9tZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAABqZXJvbWUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfmplcm9t
+ZS9zcmMvZHJlYW0vZHJlYW0vcGxhdGZvcm0vc3RhdGljL2RyZWFtL0lucHV0X3ZpZXdQcm9kdWN0
+aW9uTGluZS5qcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AMzIxMAAAAAAjIiEgExJVAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHRwAQB/AAAA
+AgAAAAAAAABIAAAAAAAAAAEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABhZAAADQIAAEkDAAAAEAAA
+SAAAAAAAAADQDwAAng8AAIwPAABoDwAASg8AACMPAADxDgAAzQ4AAIEOAAA8DgAAEw4AAOgNAADH
+DQAAqA0AAFgNAAArDQAAAA0AANcMAADHDAAApgwAAFMMAAAjDAAA8wsAALgLAACLCwAAYAsAADYL
+AAAACwAA0goAAMIKAAClCgAAWAoAAEwKAABGCgAAIwoAAJsJAACVCQAAcAkAAFoJAAA/CQAACAkA
+AOEIAADVCAAAJAgAAPMHAADLBwAAmQcAAHYHAAA+BwAAIAcAAPcGAACyBgAAigYAAFAGAAAzBgAA
+7AUAAMEFAACcBQAAkAUAAF4FAABBBQAAAgUAANMEAADHBAAAbgQAAEwEAAAKBAAA5gMAAIcDAAB7
+AwAAcwMAAEkDAABIAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfSkod2luZG93LCBySlMsIFJTVlAsIGxvb3BFdmVu
+dExpc3RlbmVyKTsAICAgIH0pOwAgICAgICAgIH0pOwAgICAgICAgICAgICByZXR1cm4gUlNWUC5h
+bGwoWyBncmFwaC5zdGFydFNlcnZpY2UoKSwgdG9vbGJveC5zdGFydFNlcnZpY2UoKSwgd2FpdEZv
+clNhdmUoZykgXSk7ACAgICAgICAgfSkucHVzaChmdW5jdGlvbih0b29sYm94KSB7ACAgICAgICAg
+ICAgIHJldHVybiBnLmdldERlY2xhcmVkR2FkZ2V0KCJwcm9kdWN0aW9ubGluZV90b29sYm94Iik7
+ACAgICAgICAgICAgIGdyYXBoID0gZ3JhcGhfZ2FkZ2V0OwAgICAgICAgIHJldHVybiBnLmdldERl
+Y2xhcmVkR2FkZ2V0KCJwcm9kdWN0aW9ubGluZV9ncmFwaCIpLnB1c2goZnVuY3Rpb24oZ3JhcGhf
+Z2FkZ2V0KSB7ACAgICAgICAgfSk7ACAgICAgICAgICAgIGNvbnNvbGUubG9nKCJEYXRhIGNoYW5n
+ZWQiLCBkYXRhKTsAICAgICAgICAkLnN1YnNjcmliZSgiRHJlYW0uR3VpLm9uRGF0YUNoYW5nZSIs
+IGZ1bmN0aW9uKGRhdGEpIHsAICAgICAgICB2YXIgZyA9IHRoaXMsIGdyYXBoOwAgICAgfSkuZGVj
+bGFyZU1ldGhvZCgic3RhcnRTZXJ2aWNlIiwgZnVuY3Rpb24oKSB7ACAgICAgICAgfSk7ACAgICAg
+ICAgICAgIHRvb2xib3hfZ2FkZ2V0LnJlbmRlcigpOwAgICAgICAgIH0pLnB1c2goZnVuY3Rpb24o
+dG9vbGJveF9nYWRnZXQpIHsAICAgICAgICAgICAgcmV0dXJuIGdhZGdldC5nZXREZWNsYXJlZEdh
+ZGdldCgicHJvZHVjdGlvbmxpbmVfdG9vbGJveCIpOwAgICAgICAgIH0pLnB1c2goZnVuY3Rpb24o
+KSB7ACAgICAgICAgICAgIHJldHVybiByZXN1bHRfbGlzdFsxXS5yZW5kZXIocmVzdWx0X2xpc3Rb
+MF0pOwAgICAgICAgIH0pLnB1c2goZnVuY3Rpb24ocmVzdWx0X2xpc3QpIHsAICAgICAgICAgICAg
+fSksIGdhZGdldC5nZXREZWNsYXJlZEdhZGdldCgicHJvZHVjdGlvbmxpbmVfZ3JhcGgiKSBdKTsA
+ICAgICAgICAgICAgICAgIF9hdHRhY2htZW50OiAiYm9keS5qc29uIgAgICAgICAgICAgICAgICAg
+X2lkOiBqaW9fa2V5LAAgICAgICAgICAgICByZXR1cm4gUlNWUC5hbGwoWyBnYWRnZXQuYXFfZ2V0
+QXR0YWNobWVudCh7ACAgICAgICAgICAgIC8qanNsaW50IG5vbWVuOiB0cnVlKi8AICAgICAgICBy
+ZXR1cm4gbmV3IFJTVlAuUXVldWUoKS5wdXNoKGZ1bmN0aW9uKCkgewAgICAgICAgIGdhZGdldC5w
+cm9wcy5qaW9fa2V5ID0gamlvX2tleTsAICAgICAgICB2YXIgamlvX2tleSA9IG9wdGlvbnMuaWQs
+IGdhZGdldCA9IHRoaXM7ACAgICB9KS5kZWNsYXJlQWNxdWlyZWRNZXRob2QoImFxX2dldEF0dGFj
+aG1lbnQiLCAiamlvX2dldEF0dGFjaG1lbnQiKS5kZWNsYXJlQWNxdWlyZWRNZXRob2QoImFxX3B1
+dEF0dGFjaG1lbnQiLCAiamlvX3B1dEF0dGFjaG1lbnQiKS5kZWNsYXJlTWV0aG9kKCJyZW5kZXIi
+LCBmdW5jdGlvbihvcHRpb25zKSB7ACAgICAgICAgfSk7ACAgICAgICAgICAgIGcucHJvcHMuZWxl
+bWVudCA9IGVsZW1lbnQ7ACAgICAgICAgcmV0dXJuIGcuZ2V0RWxlbWVudCgpLnB1c2goZnVuY3Rp
+b24oZWxlbWVudCkgewAgICAgfSkucmVhZHkoZnVuY3Rpb24oZykgewAgICAgICAgIGcucHJvcHMg
+PSB7fTsAICAgIGdhZGdldF9rbGFzcy5yZWFkeShmdW5jdGlvbihnKSB7ACAgICB9ACAgICAgICAg
+cmV0dXJuIGxvb3BFdmVudExpc3RlbmVyKGdhZGdldC5wcm9wcy5lbGVtZW50LmdldEVsZW1lbnRz
+QnlDbGFzc05hbWUoInNhdmVfZm9ybSIpWzBdLCAic3VibWl0IiwgZmFsc2UsIHNhdmVHcmFwaC5i
+aW5kKGdhZGdldCkpOwAgICAgZnVuY3Rpb24gd2FpdEZvclNhdmUoZ2FkZ2V0KSB7ACAgICB9ACAg
+ICAgICAgfSk7ACAgICAgICAgICAgIGV2dC50YXJnZXQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgi
+dWktYnRuIilbMF0uZGlzYWJsZWQgPSBmYWxzZTsAICAgICAgICB9KS5wdXNoKGZ1bmN0aW9uKCkg
+ewAgICAgICAgICAgICB9KTsAICAgICAgICAgICAgICAgIF9taW1ldHlwZTogImFwcGxpY2F0aW9u
+L2pzb24iACAgICAgICAgICAgICAgICBfZGF0YTogSlNPTi5zdHJpbmdpZnkoZGF0YSwgbnVsbCwg
+MiksACAgICAgICAgICAgICAgICBfYXR0YWNobWVudDogImJvZHkuanNvbiIsACAgICAgICAgICAg
+ICAgICBfaWQ6IGdhZGdldC5wcm9wcy5qaW9fa2V5LAAgICAgICAgICAgICByZXR1cm4gZ2FkZ2V0
+LmFxX3B1dEF0dGFjaG1lbnQoewAgICAgICAgICAgICBkYXRhLnByZWZlcmVuY2UgPSBqc29uX2dy
+YXBoX2RhdGEucHJlZmVyZW5jZXM7ACAgICAgICAgICAgIGRhdGEuZWRnZXMgPSBqc29uX2dyYXBo
+X2RhdGEuZWRnZXM7ACAgICAgICAgICAgIGRhdGEubm9kZXMgPSBqc29uX2dyYXBoX2RhdGEubm9k
+ZXM7ACAgICAgICAgICAgIHZhciBkYXRhID0gSlNPTi5wYXJzZShib2R5KSwganNvbl9ncmFwaF9k
+YXRhID0gSlNPTi5wYXJzZShncmFwaF9kYXRhKTsAICAgICAgICB9KS5wdXNoKGZ1bmN0aW9uKGJv
+ZHkpIHsAICAgICAgICAgICAgfSk7ACAgICAgICAgICAgICAgICBfYXR0YWNobWVudDogImJvZHku
+anNvbiIAICAgICAgICAgICAgICAgIF9pZDogZ2FkZ2V0LnByb3BzLmppb19rZXksACAgICAgICAg
+ICAgIHJldHVybiBnYWRnZXQuYXFfZ2V0QXR0YWNobWVudCh7ACAgICAgICAgICAgIC8vIEFsd2F5
+cyBnZXQgYSBmcmVzaCB2ZXJzaW9uLCB0byBwcmV2ZW50IGRlbGV0aW5nIHNwcmVhZHNoZWV0ICYg
+Y28AICAgICAgICAgICAgZ3JhcGhfZGF0YSA9IGRhdGE7ACAgICAgICAgfSkucHVzaChmdW5jdGlv
+bihkYXRhKSB7ACAgICAgICAgICAgIHJldHVybiBncmFwaF9nYWRnZXQuZ2V0RGF0YSgpOwAgICAg
+ICAgIH0pLnB1c2goZnVuY3Rpb24oZ3JhcGhfZ2FkZ2V0KSB7ACAgICAgICAgICAgIHJldHVybiBn
+YWRnZXQuZ2V0RGVjbGFyZWRHYWRnZXQoInByb2R1Y3Rpb25saW5lX2dyYXBoIik7ACAgICAgICAg
+ICAgIGV2dC50YXJnZXQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZSgidWktYnRuIilbMF0uZGlzYWJs
+ZWQgPSB0cnVlOwAgICAgICAgICAgICAvLyBQcmV2ZW50IGRvdWJsZSBjbGljawAgICAgICAgIHJl
+dHVybiBuZXcgUlNWUC5RdWV1ZSgpLnB1c2goZnVuY3Rpb24oKSB7ACAgICAgICAgdmFyIGdhZGdl
+dCA9IHRoaXMsIGdyYXBoX2RhdGE7ACAgICBmdW5jdGlvbiBzYXZlR3JhcGgoZXZ0KSB7ACAgICB2
+YXIgZ2FkZ2V0X2tsYXNzID0gckpTKHdpbmRvdyk7ACAgICAidXNlIHN0cmljdCI7AChmdW5jdGlv
+bih3aW5kb3csIHJKUywgUlNWUCwgbG9vcEV2ZW50TGlzdGVuZXIpIHsALypnbG9iYWwgd2luZG93
+LCBySlMsIFJTVlAsIGxvb3BFdmVudExpc3RlbmVyKi8A</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>12288</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewAddDocumentDialog.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewAddDocumentDialog.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f460c11b41fa099131b9d074ed5ed235400bd93b
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewAddDocumentDialog.html.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681758.84</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>InputModule_viewAddDocumentDialog.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Create Document</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="mixin_promise.js" type="text/javascript"></script>\n
+    <script src="InputModule_viewAddDocumentDialog.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <form class="new_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline ui-icon-plus ui-btn-icon-right">Empty</button>\n
+    </form>\n
+    <form class="import_form">\n
+      <input id="dream_import" type="file" required=""\n
+             name="dream_import">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline ui-icon-plus ui-btn-icon-right">Import</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>968</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewAddDocumentDialog.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewAddDocumentDialog.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..15909910693fcd585e2232ac99626aad67e1c291
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewAddDocumentDialog.js.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681758.95</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>InputModule_viewAddDocumentDialog.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global rJS, RSVP, promiseEventListener, promiseReadAsText,\n
+         initGadgetMixin */\n
+(function(window, rJS, RSVP, promiseEventListener, promiseReadAsText, initGadgetMixin) {\n
+    "use strict";\n
+    function createDocument(gadget, name) {\n
+        var now = new Date();\n
+        // Create jIO document\n
+        return gadget.aq_post({\n
+            title: name,\n
+            type: "Dream",\n
+            format: "application/json",\n
+            modified: now.toUTCString(),\n
+            date: now.getFullYear() + "-" + (now.getMonth() + 1) + "-" + now.getDate()\n
+        });\n
+    }\n
+    function waitForImport(gadget) {\n
+        var json_data, name;\n
+        return new RSVP.Queue().push(function() {\n
+            return promiseEventListener(gadget.props.element.getElementsByClassName("import_form")[0], "submit", false);\n
+        }).push(function(evt) {\n
+            // Prevent double click\n
+            evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            var file = evt.target.dream_import.files[0];\n
+            name = file.name;\n
+            return promiseReadAsText(file);\n
+        }).push(function(json) {\n
+            json_data = json;\n
+            return createDocument(gadget, name);\n
+        }).push(function(jio_document) {\n
+            // Add JSON as attachment\n
+            return gadget.aq_putAttachment({\n
+                _id: jio_document.id,\n
+                _attachment: "body.json",\n
+                _data: json_data,\n
+                _mimetype: "application/json"\n
+            });\n
+        });\n
+    }\n
+    function waitForNew(gadget) {\n
+        var json_data = {\n
+            nodes: {},\n
+            edges: {},\n
+            preference: {},\n
+            general: {},\n
+            wip_part_spreadsheet: [ [ "Order ID", "Due Date", "Priority", "Project Manager", "Part", "Part Type", "Sequence", "Processing Times", "Prerequisites Parts" ] ],\n
+            shift_spreadsheet: [ [ "Day", "Machines", // XXX more generic name ?\n
+            "Start", "End" ] ],\n
+            capacity_by_project_spreadsheet: [ [ "Project Name", "Sequence", "Capacity Requirements" ] ],\n
+            capacity_by_station_spreadsheet: [ [ "Day", "CS1" ] ],\n
+            dp_capacity_spreadsheet: [ [] ],\n
+            dp_route_spreadsheet: [ [] ]\n
+        }, name = "Untitled";\n
+        return new RSVP.Queue().push(function() {\n
+            return promiseEventListener(gadget.props.element.getElementsByClassName("new_form")[0], "submit", false);\n
+        }).push(function(evt) {\n
+            // Prevent double click\n
+            evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            return createDocument(gadget, name);\n
+        }).push(function(jio_document) {\n
+            // Add JSON as attachment\n
+            return gadget.aq_putAttachment({\n
+                _id: jio_document.id,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(json_data),\n
+                _mimetype: "application/json"\n
+            });\n
+        });\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_post", "jio_post").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").declareAcquiredMethod("pleaseRedirectMyHash", "pleaseRedirectMyHash").declareAcquiredMethod("whoWantsToDisplayThisDocument", "whoWantsToDisplayThisDocument").declareMethod("startService", function() {\n
+        var gadget = this;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.any([ waitForImport(gadget), waitForNew(gadget) ]);\n
+        }).push(function(result) {\n
+            return gadget.whoWantsToDisplayThisDocument(result.id);\n
+        }).push(function(url) {\n
+            return gadget.pleaseRedirectMyHash(url);\n
+        });\n
+    });\n
+})(window, rJS, RSVP, promiseEventListener, promiseReadAsText, initGadgetMixin);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3780</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewInputList.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewInputList.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a9c59e01a7555335a28b05c42cca086e65a0c31c
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewInputList.html.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681759.06</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>InputModule_viewInputList.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Document List</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/handlebars.min.js" type="text/javascript"></script>\n
+\n
+    <script id="table-template" type="text/x-handlebars-template">\n
+      <ul data-role="listview" data-inset="true" class="document-listview">\n
+        {{#documentlist}}\n
+          <li><a href="{{link}}">{{title}}</a></li>\n
+        {{/documentlist}}\n
+      </ul>\n
+    </script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="InputModule_viewInputList.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <section class="document_list"></section>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>890</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewInputList.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewInputList.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a1ee55d3564a7b1bb918f2d854c3d20f424c3873
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/InputModule_viewInputList.js.xml
@@ -0,0 +1,90 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681759.17</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>InputModule_viewInputList.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, Handlebars, initGadgetMixin */\n
+/*jslint nomen: true */\n
+(function(window, rJS, RSVP, Handlebars, initGadgetMixin) {\n
+    "use strict";\n
+    /////////////////////////////////////////////////////////////////\n
+    // Handlebars\n
+    /////////////////////////////////////////////////////////////////\n
+    // Precompile the templates while loading the first gadget instance\n
+    var gadget_klass = rJS(window), source = gadget_klass.__template_element.getElementById("table-template").innerHTML, table_template = Handlebars.compile(source);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_allDocs", "jio_allDocs").declareAcquiredMethod("pleaseRedirectMyHash", "pleaseRedirectMyHash").declareAcquiredMethod("whoWantsToDisplayThisDocument", "whoWantsToDisplayThisDocument").declareMethod("render", function() {\n
+        var gadget = this;\n
+        return gadget.aq_allDocs({\n
+            select_list: [ "title", "modified" ]\n
+        }).push(function(document_list) {\n
+            var result_list = [], doc, i;\n
+            for (i = 0; i < document_list.data.total_rows; i += 1) {\n
+                doc = document_list.data.rows[i];\n
+                result_list.push(RSVP.all([ gadget.whoWantsToDisplayThisDocument(doc.id), doc.value.title, doc.value.modified ]));\n
+            }\n
+            return RSVP.all(result_list);\n
+        }).push(function(document_list) {\n
+            // Create new doc if nothing exists\n
+            if (document_list.length === 0) {\n
+                return gadget.whoWantsToDisplayThisDocument(undefined, "view_fast_input").push(function(url) {\n
+                    return gadget.pleaseRedirectMyHash(url);\n
+                });\n
+            }\n
+            var i, parameter_list = [], doc;\n
+            for (i = 0; i < document_list.length; i += 1) {\n
+                doc = document_list[i];\n
+                parameter_list[i] = {\n
+                    link: doc[0],\n
+                    title: doc[1] + " (" + doc[2] + ")",\n
+                    date: new Date(doc[2])\n
+                };\n
+            }\n
+            parameter_list.sort(function(a, b) {\n
+                return b.date - a.date;\n
+            });\n
+            //           gadget.props.element.querySelector(\'a\').href = document_list[0];\n
+            gadget.props.element.querySelector(".document_list").innerHTML = table_template({\n
+                documentlist: parameter_list\n
+            });\n
+        });\n
+    });\n
+})(window, rJS, RSVP, Handlebars, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2461</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewAvailableCapacitySpreadsheet.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewAvailableCapacitySpreadsheet.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6582188a2eb5684d58b98c35aac61450607c45f9
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewAvailableCapacitySpreadsheet.html.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681759.28</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewAvailableCapacitySpreadsheet.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Edit Required Capacity Spreadsheet</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Input_viewAvailableCapacitySpreadsheet.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div data-gadget-url="../handsontable/index.html"\n
+         data-gadget-scope="tableeditor"></div>\n
+    <form class="save_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline\n
+        ui-icon-edit ui-btn-icon-right">Save</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>932</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewAvailableCapacitySpreadsheet.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewAvailableCapacitySpreadsheet.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e480732a7218ec12fec0a709b26f21e477275c78
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewAvailableCapacitySpreadsheet.js.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681759.39</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewAvailableCapacitySpreadsheet.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, initGadgetMixin, loopEventListener */\n
+(function(window, rJS, RSVP, initGadgetMixin, loopEventListener) {\n
+    "use strict";\n
+    function saveSpreadsheet(evt) {\n
+        var gadget = this, editor_data, editor_gadget;\n
+        return new RSVP.Queue().push(function() {\n
+            // Prevent double click\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            }\n
+            return gadget.getDeclaredGadget("tableeditor");\n
+        }).push(function(tablegadget) {\n
+            editor_gadget = tablegadget;\n
+            return editor_gadget.getData();\n
+        }).push(function(data) {\n
+            editor_data = data;\n
+            // Always get a fresh version, to prevent deleting spreadsheet & co\n
+            return gadget.aq_getAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json"\n
+            });\n
+        }).push(function(body) {\n
+            var data = JSON.parse(body);\n
+            data.capacity_by_station_spreadsheet = JSON.parse(editor_data);\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(data, null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        }).push(function() {\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = false;\n
+            }\n
+        });\n
+    }\n
+    function waitForSave(gadget) {\n
+        return loopEventListener(gadget.props.element.getElementsByClassName("save_form")[0], "submit", false, saveSpreadsheet.bind(gadget));\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ gadget.aq_getAttachment({\n
+                _id: jio_key,\n
+                _attachment: "body.json"\n
+            }), gadget.getDeclaredGadget("tableeditor") ]);\n
+        }).push(function(result_list) {\n
+            return result_list[1].render(JSON.stringify(JSON.parse(result_list[0]).capacity_by_station_spreadsheet), {\n
+                minSpareCols: 1,\n
+                minSpareRows: 1,\n
+                onChange: function() {\n
+                    if (gadget.timeout) {\n
+                        window.clearTimeout(gadget.timeout);\n
+                    }\n
+                    gadget.timeout = window.setTimeout(saveSpreadsheet.bind(gadget), 100);\n
+                }\n
+            });\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        var gadget = this;\n
+        return this.getDeclaredGadget("tableeditor").push(function(tableeditor) {\n
+            return RSVP.all([ tableeditor.startService(), waitForSave(gadget) ]);\n
+        });\n
+    });\n
+})(window, rJS, RSVP, initGadgetMixin, loopEventListener);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3085</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningCapacitySpreadsheet.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningCapacitySpreadsheet.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..24a8df3d2c16e13f8d3d60ed58b25fed378d3d49
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningCapacitySpreadsheet.html.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681759.51</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewDemandPlanningCapacitySpreadsheet.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Edit Required Capacity Spreadsheet</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Input_viewDemandPlanningCapacitySpreadsheet.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div data-gadget-url="../handsontable/index.html"\n
+         data-gadget-scope="tableeditor"></div>\n
+    <form class="save_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline\n
+        ui-icon-edit ui-btn-icon-right">Save</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>937</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningCapacitySpreadsheet.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningCapacitySpreadsheet.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f0a5022b44d334b8c037ff0747d6ad57001d8a34
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningCapacitySpreadsheet.js.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681759.6</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewDemandPlanningCapacitySpreadsheet.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, initGadgetMixin, loopEventListener */\n
+(function(window, rJS, RSVP, initGadgetMixin, loopEventListener) {\n
+    "use strict";\n
+    function saveSpreadsheet(evt) {\n
+        var gadget = this, editor_data, editor_gadget;\n
+        return new RSVP.Queue().push(function() {\n
+            // Prevent double click\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            }\n
+            return gadget.getDeclaredGadget("tableeditor");\n
+        }).push(function(tablegadget) {\n
+            editor_gadget = tablegadget;\n
+            return editor_gadget.getData();\n
+        }).push(function(data) {\n
+            editor_data = data;\n
+            // Always get a fresh version, to prevent deleting spreadsheet & co\n
+            return gadget.aq_getAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json"\n
+            });\n
+        }).push(function(body) {\n
+            var data = JSON.parse(body);\n
+            data.dp_capacity_spreadsheet = JSON.parse(editor_data);\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(data, null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        }).push(function() {\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = false;\n
+            }\n
+        });\n
+    }\n
+    function waitForSave(gadget) {\n
+        return loopEventListener(gadget.props.element.getElementsByClassName("save_form")[0], "submit", false, saveSpreadsheet.bind(gadget));\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ gadget.aq_getAttachment({\n
+                _id: jio_key,\n
+                _attachment: "body.json"\n
+            }), gadget.getDeclaredGadget("tableeditor") ]);\n
+        }).push(function(result_list) {\n
+            return result_list[1].render(JSON.stringify(JSON.parse(result_list[0]).dp_capacity_spreadsheet), {\n
+                minSpareCols: 1,\n
+                minSpareRows: 1,\n
+                onChange: function() {\n
+                    if (gadget.timeout) {\n
+                        window.clearTimeout(gadget.timeout);\n
+                    }\n
+                    gadget.timeout = window.setTimeout(saveSpreadsheet.bind(gadget), 100);\n
+                }\n
+            });\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        var gadget = this;\n
+        return this.getDeclaredGadget("tableeditor").push(function(tableeditor) {\n
+            return RSVP.all([ tableeditor.startService(), waitForSave(gadget) ]);\n
+        });\n
+    });\n
+})(window, rJS, RSVP, initGadgetMixin, loopEventListener);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3069</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningRouteSpreadsheet.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningRouteSpreadsheet.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..eda2aa44d025bb11abfc3edad3e4a1c8c60b99b6
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningRouteSpreadsheet.html.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681759.7</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewDemandPlanningRouteSpreadsheet.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Edit Required Capacity Spreadsheet</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Input_viewDemandPlanningRouteSpreadsheet.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div data-gadget-url="../handsontable/index.html"\n
+         data-gadget-scope="tableeditor"></div>\n
+    <form class="save_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline\n
+        ui-icon-edit ui-btn-icon-right">Save</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>934</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningRouteSpreadsheet.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningRouteSpreadsheet.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c814cd0415f2ed0d363aee64b29628f4ed18f80c
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningRouteSpreadsheet.js.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681759.97</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewDemandPlanningRouteSpreadsheet.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, initGadgetMixin, loopEventListener */\n
+(function(window, rJS, RSVP, initGadgetMixin, loopEventListener) {\n
+    "use strict";\n
+    function saveSpreadsheet(evt) {\n
+        var gadget = this, editor_data, editor_gadget;\n
+        return new RSVP.Queue().push(function() {\n
+            // Prevent double click\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            }\n
+            return gadget.getDeclaredGadget("tableeditor");\n
+        }).push(function(tablegadget) {\n
+            editor_gadget = tablegadget;\n
+            return editor_gadget.getData();\n
+        }).push(function(data) {\n
+            editor_data = data;\n
+            // Always get a fresh version, to prevent deleting spreadsheet & co\n
+            return gadget.aq_getAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json"\n
+            });\n
+        }).push(function(body) {\n
+            var data = JSON.parse(body);\n
+            data.dp_route_spreadsheet = JSON.parse(editor_data);\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(data, null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        }).push(function() {\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = false;\n
+            }\n
+        });\n
+    }\n
+    function waitForSave(gadget) {\n
+        return loopEventListener(gadget.props.element.getElementsByClassName("save_form")[0], "submit", false, saveSpreadsheet.bind(gadget));\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ gadget.aq_getAttachment({\n
+                _id: jio_key,\n
+                _attachment: "body.json"\n
+            }), gadget.getDeclaredGadget("tableeditor") ]);\n
+        }).push(function(result_list) {\n
+            return result_list[1].render(JSON.stringify(JSON.parse(result_list[0]).dp_route_spreadsheet), {\n
+                minSpareCols: 1,\n
+                minSpareRows: 1,\n
+                onChange: function() {\n
+                    if (gadget.timeout) {\n
+                        window.clearTimeout(gadget.timeout);\n
+                    }\n
+                    gadget.timeout = window.setTimeout(saveSpreadsheet.bind(gadget), 100);\n
+                }\n
+            });\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        var gadget = this;\n
+        return this.getDeclaredGadget("tableeditor").push(function(tableeditor) {\n
+            return RSVP.all([ tableeditor.startService(), waitForSave(gadget) ]);\n
+        });\n
+    });\n
+})(window, rJS, RSVP, initGadgetMixin, loopEventListener);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3063</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningapacitySpreadsheet.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningapacitySpreadsheet.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e55e47846e6f5d96af7d4c45d598ebf23b733c81
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningapacitySpreadsheet.html.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681760.56</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewDemandPlanningapacitySpreadsheet.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Edit Required Capacity Spreadsheet</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Input_viewAvailableCapacitySpreadsheet.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div data-gadget-url="../handsontable/index.html"\n
+         data-gadget-scope="tableeditor"></div>\n
+    <form class="save_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline\n
+        ui-icon-edit ui-btn-icon-right">Save</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>932</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningapacitySpreadsheet.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningapacitySpreadsheet.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f62b778fa5d514b45e11f85e580442167a362889
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDemandPlanningapacitySpreadsheet.js.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681760.68</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewDemandPlanningapacitySpreadsheet.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, initGadgetMixin, loopEventListener */\n
+(function(window, rJS, RSVP, initGadgetMixin, loopEventListener) {\n
+    "use strict";\n
+    function saveSpreadsheet(evt) {\n
+        var gadget = this, editor_data, editor_gadget;\n
+        return new RSVP.Queue().push(function() {\n
+            // Prevent double click\n
+            evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            return gadget.getDeclaredGadget("tableeditor");\n
+        }).push(function(tablegadget) {\n
+            editor_gadget = tablegadget;\n
+            return editor_gadget.getData();\n
+        }).push(function(data) {\n
+            editor_data = data;\n
+            // Always get a fresh version, to prevent deleting spreadsheet & co\n
+            return gadget.aq_getAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json"\n
+            });\n
+        }).push(function(body) {\n
+            var data = JSON.parse(body);\n
+            data.capacity_by_station_spreadsheet = JSON.parse(editor_data);\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(data, null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        }).push(function() {\n
+            evt.target.getElementsByClassName("ui-btn")[0].disabled = false;\n
+        });\n
+    }\n
+    function waitForSave(gadget) {\n
+        return loopEventListener(gadget.props.element.getElementsByClassName("save_form")[0], "submit", false, saveSpreadsheet.bind(gadget));\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ gadget.aq_getAttachment({\n
+                _id: jio_key,\n
+                _attachment: "body.json"\n
+            }), gadget.getDeclaredGadget("tableeditor") ]);\n
+        }).push(function(result_list) {\n
+            return result_list[1].render(JSON.stringify(JSON.parse(result_list[0]).capacity_by_station_spreadsheet), {\n
+                minSpareCols: 1,\n
+                minSpareRows: 1\n
+            });\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        var gadget = this;\n
+        return this.getDeclaredGadget("tableeditor").push(function(tableeditor) {\n
+            return RSVP.all([ tableeditor.startService(), waitForSave(gadget) ]);\n
+        });\n
+    });\n
+})(window, rJS, RSVP, initGadgetMixin, loopEventListener);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2729</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDocumentManagement.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDocumentManagement.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0945b1ada80ca84c11b8f4860d165d320681923f
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDocumentManagement.html.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681760.13</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewDocumentManagement.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Manage document</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="mixin_promise.js" type="text/javascript"></script>\n
+    <script src="Input_viewDocumentManagement.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <a class="export_link ui-btn ui-btn-inline ui-icon-action ui-btn-icon-right">Export</a>\n
+    <form class="knowledge_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline\n
+      ui-icon-refresh ui-btn-icon-right">Run Knowledge Extraction Tool</button>\n
+    </form>\n
+    <form class="delete_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline ui-icon-delete ui-btn-icon-right">Delete</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1150</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDocumentManagement.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDocumentManagement.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a19d826213f68ed6808b0a31155b03d202b8df70
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewDocumentManagement.js.xml
@@ -0,0 +1,139 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681760.25</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewDocumentManagement.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, jQuery,\n
+ promiseEventListener, initGadgetMixin */\n
+(function(window, rJS, RSVP, $, promiseEventListener, initGadgetMixin) {\n
+    "use strict";\n
+    function datatouri(data, mime_type) {\n
+        var result = "data:";\n
+        if (mime_type !== undefined) {\n
+            result += mime_type;\n
+        }\n
+        return result + ";base64," + window.btoa(data);\n
+    }\n
+    function disableAllButtons(gadget) {\n
+        // Prevent double click\n
+        var i, button_list = gadget.props.element.getElementsByClassName("ui-btn");\n
+        for (i = 0; i < button_list.length; i += 1) {\n
+            button_list[i].disabled = true;\n
+        }\n
+    }\n
+    function waitForKnowledgeExtraction(gadget) {\n
+        return new RSVP.Queue().push(function() {\n
+            return promiseEventListener(gadget.props.element.getElementsByClassName("knowledge_form")[0], "submit", false);\n
+        }).push(function() {\n
+            disableAllButtons(gadget);\n
+            return gadget.aq_getAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json"\n
+            });\n
+        }).push(function(body_json) {\n
+            $.mobile.loading("show");\n
+            // XXX Hardcoded relative URL\n
+            return gadget.aq_ajax({\n
+                url: "../../runKnowledgeExtraction",\n
+                type: "POST",\n
+                data: body_json,\n
+                headers: {\n
+                    "Content-Type": "application/json"\n
+                }\n
+            });\n
+        }).push(undefined, function(error) {\n
+            // Always drop the loader\n
+            $.mobile.loading("hide");\n
+            throw error;\n
+        }).push(function(evt) {\n
+            $.mobile.loading("hide");\n
+            var json_data = JSON.parse(evt.target.responseText);\n
+            if (json_data.success !== true) {\n
+                throw new Error(json_data.error);\n
+            }\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(json_data.data, null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        }).push(function() {\n
+            return gadget.whoWantsToDisplayThisDocument(gadget.props.jio_key);\n
+        }).push(function(url) {\n
+            return gadget.pleaseRedirectMyHash(url);\n
+        });\n
+    }\n
+    function waitForDeletion(gadget) {\n
+        return new RSVP.Queue().push(function() {\n
+            return promiseEventListener(gadget.props.element.getElementsByClassName("delete_form")[0], "submit", false);\n
+        }).push(function() {\n
+            disableAllButtons(gadget);\n
+            // Delete jIO document\n
+            return gadget.aq_remove({\n
+                _id: gadget.props.jio_key\n
+            });\n
+        }).push(function() {\n
+            return gadget.whoWantsToDisplayHome();\n
+        }).push(function(url) {\n
+            return gadget.pleaseRedirectMyHash(url);\n
+        });\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_remove", "jio_remove").declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").declareAcquiredMethod("aq_get", "jio_get").declareAcquiredMethod("aq_ajax", "jio_ajax").declareAcquiredMethod("pleaseRedirectMyHash", "pleaseRedirectMyHash").declareAcquiredMethod("whoWantsToDisplayThisDocument", "whoWantsToDisplayThisDocument").declareAcquiredMethod("whoWantsToDisplayHome", "whoWantsToDisplayHome").declareMethod("render", function(options) {\n
+        this.props.jio_key = options.id;\n
+        var gadget = this;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ gadget.aq_get({\n
+                _id: options.id\n
+            }), gadget.aq_getAttachment({\n
+                _id: options.id,\n
+                _attachment: "body.json"\n
+            }) ]);\n
+        }).push(function(result_list) {\n
+            var export_link = gadget.props.element.querySelector(".export_link");\n
+            export_link.download = result_list[0].data.title;\n
+            export_link.href = datatouri(result_list[1], "application/json");\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        return RSVP.all([ waitForDeletion(this), waitForKnowledgeExtraction(this) ]);\n
+    });\n
+})(window, rJS, RSVP, jQuery, promiseEventListener, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>4364</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewProductionLine.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewProductionLine.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4f07c82306117d6e22826ede0ec4bbeeca06653f
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewProductionLine.html.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681760.35</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewProductionLine.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Edit table</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="mixin_promise.js" type="text/javascript"></script>\n
+\n
+    <script src="Input_viewProductionLine.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div data-gadget-url="../toolbox/index.html"\n
+         data-gadget-scope="productionline_toolbox"></div>\n
+    <div data-gadget-url="../jsplumb/index.html"\n
+         data-gadget-scope="productionline_graph"></div>\n
+    <form class="save_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline\n
+              ui-icon-edit ui-btn-icon-right">Save</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>871</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewProductionLine.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewProductionLine.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3b89d37879da249d1ae3d6c6e2e180944cfc0837
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewProductionLine.js.xml
@@ -0,0 +1,113 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681758.58</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewProductionLine.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global window, rJS, RSVP, loopEventListener*/\n
+(function(window, rJS, RSVP, loopEventListener) {\n
+    "use strict";\n
+    var gadget_klass = rJS(window);\n
+    // TODO: save on parent gadget\n
+    function saveGraph(evt) {\n
+        var gadget = this;\n
+        return new RSVP.Queue().push(function() {\n
+            // Prevent double click\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            }\n
+            return gadget.getDeclaredGadget("productionline_graph");\n
+        }).push(function(graph_gadget) {\n
+            return graph_gadget.getContent();\n
+        }).push(function(body) {\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(JSON.parse(body), null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        }).push(function() {\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = false;\n
+            }\n
+        });\n
+    }\n
+    function waitForSave(gadget) {\n
+        return loopEventListener(gadget.props.element.getElementsByClassName("save_form")[0], "submit", false, saveGraph.bind(gadget));\n
+    }\n
+    gadget_klass.ready(function(g) {\n
+        g.props = {};\n
+    }).ready(function(g) {\n
+        return g.getElement().push(function(element) {\n
+            g.props.element = element;\n
+        });\n
+    }).declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").allowPublicAcquisition("notifyDataChanged", function() {\n
+        // We are notified by an included gadget that the data has changed.\n
+        // Here we save automatically. We could mark a dirty flag to warn the\n
+        // user if she leaves the page without saving.\n
+        // Since we are notified quite often and saving is resource expensive, we\n
+        // use this trick to prevent saving too many times\n
+        if (this.timeout) {\n
+            window.clearTimeout(this.timeout);\n
+        }\n
+        this.timeout = window.setTimeout(saveGraph.bind(this), 100);\n
+    }).declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this, data;\n
+        gadget.props.jio_key = jio_key;\n
+        return new RSVP.Queue().push(function() {\n
+            /*jslint nomen: true*/\n
+            return RSVP.all([ gadget.aq_getAttachment({\n
+                _id: jio_key,\n
+                _attachment: "body.json"\n
+            }), gadget.getDeclaredGadget("productionline_graph") ]);\n
+        }).push(function(result_list) {\n
+            data = result_list[0];\n
+            return result_list[1].render(data);\n
+        }).push(function() {\n
+            return gadget.getDeclaredGadget("productionline_toolbox");\n
+        }).push(function(toolbox_gadget) {\n
+            toolbox_gadget.render(data);\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        var g = this, graph;\n
+        return g.getDeclaredGadget("productionline_graph").push(function(graph_gadget) {\n
+            graph = graph_gadget;\n
+            return g.getDeclaredGadget("productionline_toolbox");\n
+        }).push(function(toolbox) {\n
+            return RSVP.all([ graph.startService(), toolbox.startService(), waitForSave(g) ]);\n
+        });\n
+    });\n
+})(window, rJS, RSVP, loopEventListener);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3328</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewRequiredCapacitySpreadsheet.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewRequiredCapacitySpreadsheet.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c7f21523ae7647665cdc40861dc760330fb9776d
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewRequiredCapacitySpreadsheet.html.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681760.45</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewRequiredCapacitySpreadsheet.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Edit Available Capacity Spreadsheet</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Input_viewRequiredCapacitySpreadsheet.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div data-gadget-url="../handsontable/index.html"\n
+         data-gadget-scope="tableeditor"></div>\n
+    <form class="save_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline\n
+        ui-icon-edit ui-btn-icon-right">Save</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>932</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewRequiredCapacitySpreadsheet.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewRequiredCapacitySpreadsheet.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..42bc7b15fa6d3a4af0951224615e28399e22199a
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewRequiredCapacitySpreadsheet.js.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681760.86</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewRequiredCapacitySpreadsheet.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, initGadgetMixin, loopEventListener */\n
+(function(window, rJS, RSVP, initGadgetMixin, loopEventListener) {\n
+    "use strict";\n
+    function saveSpreadsheet(evt) {\n
+        var gadget = this, editor_data, editor_gadget;\n
+        return new RSVP.Queue().push(function() {\n
+            // Prevent double click\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            }\n
+            return gadget.getDeclaredGadget("tableeditor");\n
+        }).push(function(tablegadget) {\n
+            editor_gadget = tablegadget;\n
+            return editor_gadget.getData();\n
+        }).push(function(data) {\n
+            editor_data = data;\n
+            // Always get a fresh version, to prevent deleting spreadsheet & co\n
+            return gadget.aq_getAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json"\n
+            });\n
+        }).push(function(body) {\n
+            var data = JSON.parse(body);\n
+            data.capacity_by_project_spreadsheet = JSON.parse(editor_data);\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(data, null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        }).push(function() {\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = false;\n
+            }\n
+        });\n
+    }\n
+    function waitForSave(gadget) {\n
+        return loopEventListener(gadget.props.element.getElementsByClassName("save_form")[0], "submit", false, saveSpreadsheet.bind(gadget));\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ gadget.aq_getAttachment({\n
+                _id: jio_key,\n
+                _attachment: "body.json"\n
+            }), gadget.getDeclaredGadget("tableeditor") ]);\n
+        }).push(function(result_list) {\n
+            return result_list[1].render(JSON.stringify(JSON.parse(result_list[0]).capacity_by_project_spreadsheet), {\n
+                minSpareRows: 1,\n
+                onChange: function() {\n
+                    if (gadget.timeout) {\n
+                        window.clearTimeout(gadget.timeout);\n
+                    }\n
+                    gadget.timeout = window.setTimeout(saveSpreadsheet.bind(gadget), 100);\n
+                }\n
+            });\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        var gadget = this;\n
+        return this.getDeclaredGadget("tableeditor").push(function(tableeditor) {\n
+            return RSVP.all([ tableeditor.startService(), waitForSave(gadget) ]);\n
+        });\n
+    });\n
+})(window, rJS, RSVP, initGadgetMixin, loopEventListener);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3052</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewResultList.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewResultList.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ebb2ef307e470d087b8ea569bb4fe17443e77bd6
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewResultList.html.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681760.97</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewResultList.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Result List</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/handlebars.min.js" type="text/javascript"></script>\n
+\n
+    <script id="table-template" type="text/x-handlebars-template">\n
+      <ul data-role="listview" data-inset="true" class="document-listview">\n
+        {{#each documentlist}}\n
+          <li><a href="{{link}}">{{title}}</a></li>\n
+        {{else}}\n
+          <p>No result yet.</p>\n
+        {{/each}}\n
+      </ul>\n
+    </script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Input_viewResultList.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <section class="document_list"></section>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>929</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewResultList.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewResultList.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d7cd658f743d02bb684f255b1a2578e89ff6a081
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewResultList.js.xml
@@ -0,0 +1,86 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681761.06</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewResultList.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, Handlebars, initGadgetMixin */\n
+/*jslint nomen: true */\n
+(function(window, rJS, RSVP, Handlebars, initGadgetMixin) {\n
+    "use strict";\n
+    /////////////////////////////////////////////////////////////////\n
+    // Handlebars\n
+    /////////////////////////////////////////////////////////////////\n
+    // Precompile the templates while loading the first gadget instance\n
+    var gadget_klass = rJS(window), source = gadget_klass.__template_element.getElementById("table-template").innerHTML, table_template = Handlebars.compile(source);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("whoWantsToDisplayThisResult", "whoWantsToDisplayThisResult").declareMethod("render", function(options) {\n
+        var gadget = this;\n
+        this.props.jio_key = options.id;\n
+        return gadget.aq_getAttachment({\n
+            _id: gadget.props.jio_key,\n
+            _attachment: "simulation.json"\n
+        }).push(undefined, function(error) {\n
+            if (error.status === 404) {\n
+                // Simulation not yet generated\n
+                return JSON.stringify([]);\n
+            }\n
+            throw error;\n
+        }).push(function(sim_json) {\n
+            var document_list = JSON.parse(sim_json), result_list = [], i;\n
+            for (i = 0; i < document_list.length; i += 1) {\n
+                result_list.push(RSVP.all([ gadget.whoWantsToDisplayThisResult(gadget.props.jio_key, i), document_list[i].score, document_list[i].key ]));\n
+            }\n
+            return RSVP.all(result_list);\n
+        }).push(function(document_list) {\n
+            var i, parameter_list = [], doc;\n
+            for (i = 0; i < document_list.length; i += 1) {\n
+                doc = document_list[i];\n
+                parameter_list[i] = {\n
+                    link: doc[0],\n
+                    title: doc[1] + " " + doc[2]\n
+                };\n
+            }\n
+            gadget.props.element.querySelector(".document_list").innerHTML = table_template({\n
+                documentlist: parameter_list\n
+            });\n
+        });\n
+    });\n
+})(window, rJS, RSVP, Handlebars, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2148</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewShiftSpreadsheet.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewShiftSpreadsheet.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d388c40e95472559e139e824635d9eb40cf3198
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewShiftSpreadsheet.html.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681761.17</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewShiftSpreadsheet.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Edit Shift Spreadsheet</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Input_viewShiftSpreadsheet.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div data-gadget-url="../handsontable/index.html"\n
+         data-gadget-scope="tableeditor"></div>\n
+    <form class="save_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline\n
+        ui-icon-edit ui-btn-icon-right">Save</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>908</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewShiftSpreadsheet.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewShiftSpreadsheet.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b5c6670669cd1875f772c535b6ad4ce4d698288b
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewShiftSpreadsheet.js.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681761.28</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewShiftSpreadsheet.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, initGadgetMixin, loopEventListener */\n
+(function(window, rJS, RSVP, initGadgetMixin, loopEventListener) {\n
+    "use strict";\n
+    function saveSpreadsheet(evt) {\n
+        var gadget = this, editor_data, editor_gadget;\n
+        return new RSVP.Queue().push(function() {\n
+            // Prevent double click\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            }\n
+            return gadget.getDeclaredGadget("tableeditor");\n
+        }).push(function(tablegadget) {\n
+            editor_gadget = tablegadget;\n
+            return editor_gadget.getData();\n
+        }).push(function(data) {\n
+            editor_data = data;\n
+            // Always get a fresh version, to prevent deleting spreadsheet & co\n
+            return gadget.aq_getAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json"\n
+            });\n
+        }).push(function(body) {\n
+            var data = JSON.parse(body);\n
+            data.shift_spreadsheet = JSON.parse(editor_data);\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(data, null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        }).push(function() {\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = false;\n
+            }\n
+        });\n
+    }\n
+    function waitForSave(gadget) {\n
+        return loopEventListener(gadget.props.element.getElementsByClassName("save_form")[0], "submit", false, saveSpreadsheet.bind(gadget));\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ gadget.aq_getAttachment({\n
+                _id: jio_key,\n
+                _attachment: "body.json"\n
+            }), gadget.getDeclaredGadget("tableeditor") ]);\n
+        }).push(function(result_list) {\n
+            return result_list[1].render(JSON.stringify(JSON.parse(result_list[0]).shift_spreadsheet), {\n
+                minSpareRows: 1,\n
+                onChange: function() {\n
+                    if (gadget.timeout) {\n
+                        window.clearTimeout(gadget.timeout);\n
+                    }\n
+                    gadget.timeout = window.setTimeout(saveSpreadsheet.bind(gadget), 100);\n
+                }\n
+            });\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        var gadget = this;\n
+        return this.getDeclaredGadget("tableeditor").push(function(tableeditor) {\n
+            return RSVP.all([ tableeditor.startService(), waitForSave(gadget) ]);\n
+        });\n
+    });\n
+})(window, rJS, RSVP, initGadgetMixin, loopEventListener);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3024</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewSimulation.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewSimulation.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6901af3f8bbdbab66c4da98024d192b2c5ad0a05
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewSimulation.html.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681761.43</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewSimulation.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Run Simulation</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/handlebars.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+\n
+    <script id="label-template" type="text/x-handlebars-template">\n
+      <label>{{label}}</label>\n
+    </script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="mixin_promise.js" type="text/javascript"></script>\n
+    <script src="Input_viewSimulation.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <form class="run_form">\n
+      <fieldset>\n
+        <div data-gadget-url="../fieldset/index.html"\n
+             data-gadget-scope="fieldset"></div>\n
+      </fieldset>\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline\n
+              ui-icon-refresh ui-btn-icon-right">Run Simulation</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1205</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewSimulation.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewSimulation.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..200760f5b84909a30fe105a07081a6537b8bad43
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewSimulation.js.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681758.69</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewSimulation.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, jQuery, promiseEventListener, initGadgetMixin */\n
+/*jslint nomen: true */\n
+(function(window, rJS, RSVP, $, promiseEventListener, initGadgetMixin) {\n
+    "use strict";\n
+    function saveForm(gadget) {\n
+        var general;\n
+        return gadget.getDeclaredGadget("fieldset").push(function(fieldset_gadget) {\n
+            return fieldset_gadget.getContent();\n
+        }).push(function(content) {\n
+            general = content;\n
+            // Always get a fresh version, to prevent deleting spreadsheet & co\n
+            return gadget.aq_getAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json"\n
+            });\n
+        }).push(function(body) {\n
+            var data = JSON.parse(body);\n
+            data.general = general;\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(data, null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        });\n
+    }\n
+    function runSimulation(gadget) {\n
+        return new RSVP.Queue().push(function() {\n
+            return gadget.aq_getAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json"\n
+            });\n
+        }).push(function(body_json) {\n
+            // XXX Hardcoded relative URL\n
+            return gadget.aq_ajax({\n
+                url: "../../runSimulation",\n
+                type: "POST",\n
+                data: body_json,\n
+                headers: {\n
+                    "Content-Type": "application/json"\n
+                }\n
+            });\n
+        }).push(function(evt) {\n
+            var json_data = JSON.parse(evt.target.responseText);\n
+            if (json_data.success !== true) {\n
+                throw new Error(json_data.error);\n
+            }\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "simulation.json",\n
+                _data: JSON.stringify(json_data.data, null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        }).push(function() {\n
+            return gadget.whoWantsToDisplayThisDocument(gadget.props.jio_key, "view_result");\n
+        }).push(function(url) {\n
+            return gadget.pleaseRedirectMyHash(url);\n
+        });\n
+    }\n
+    function waitForRunSimulation(gadget) {\n
+        var submit_evt;\n
+        return new RSVP.Queue().push(function() {\n
+            return promiseEventListener(gadget.props.element.getElementsByClassName("run_form")[0], "submit", false);\n
+        }).push(function(evt) {\n
+            submit_evt = evt;\n
+            // Prevent double click\n
+            evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            $.mobile.loading("show");\n
+            return saveForm(gadget);\n
+        }).push(function() {\n
+            return runSimulation(gadget);\n
+        }).push(undefined, function(error) {\n
+            // Always drop the loader\n
+            $.mobile.loading("hide");\n
+            throw error;\n
+        }).push(function() {\n
+            submit_evt.target.getElementsByClassName("ui-btn")[0].disabled = false;\n
+            $.mobile.loading("hide");\n
+        });\n
+    }\n
+    /////////////////////////////////////////////////////////////////\n
+    // Handlebars\n
+    /////////////////////////////////////////////////////////////////\n
+    // Precompile the templates while loading the first gadget instance\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").declareAcquiredMethod("aq_ajax", "jio_ajax").declareAcquiredMethod("pleaseRedirectMyHash", "pleaseRedirectMyHash").declareAcquiredMethod("whoWantsToDisplayThisDocument", "whoWantsToDisplayThisDocument").declareMethod("render", function(options) {\n
+        var gadget = this, data;\n
+        this.props.jio_key = options.id;\n
+        return gadget.aq_getAttachment({\n
+            _id: gadget.props.jio_key,\n
+            _attachment: "body.json"\n
+        }).push(function(json) {\n
+            var application_configuration = {};\n
+            data = JSON.parse(json);\n
+            application_configuration = data.application_configuration.general || {};\n
+            return gadget.getDeclaredGadget("fieldset").push(function(fieldset_gadget) {\n
+                return fieldset_gadget.render({\n
+                    value: data.general,\n
+                    property_definition: application_configuration\n
+                });\n
+            });\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        return waitForRunSimulation(this);\n
+    });\n
+})(window, rJS, RSVP, jQuery, promiseEventListener, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>4723</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewTable.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewTable.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..77cdb1f747c553f5910b216de63452f552a991d9
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewTable.html.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681762.53</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewTable.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Edit table</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Input_viewTable.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div data-gadget-url="../handsontable/index.html"\n
+         data-gadget-scope="tableeditor"></div>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>583</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewTable.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewTable.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..70a5cc74ef59fc45fafa7b8f3a7f117038204948
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewTable.js.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681762.63</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewTable.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global console, rJS, RSVP, initGadgetMixin */\n
+(function(window, rJS, RSVP, initGadgetMixin) {\n
+    "use strict";\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ gadget.aq_getAttachment({\n
+                _id: jio_key,\n
+                _attachment: "body.json"\n
+            }), gadget.getDeclaredGadget("tableeditor") ]);\n
+        }).push(function(result_list) {\n
+            return result_list[1].render(JSON.stringify(JSON.parse(result_list[0]).wip_part_spreadsheet));\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        return this.getDeclaredGadget("tableeditor").push(function(tableeditor) {\n
+            return tableeditor.startService();\n
+        });\n
+    });\n
+})(window, rJS, RSVP, initGadgetMixin);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1032</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewWipPartSpreadsheet.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewWipPartSpreadsheet.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ec499575a8d87c3a692cde9b5838c8bff2e938e9
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewWipPartSpreadsheet.html.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681761.56</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewWipPartSpreadsheet.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Edit Wip Part Spreadsheet</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="mixin_promise.js" type="text/javascript"></script>\n
+    <script src="Input_viewWipPartSpreadsheet.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div data-gadget-url="../handsontable/index.html"\n
+         data-gadget-scope="tableeditor"></div>\n
+    <form class="save_form">\n
+      <button type="submit" class="ui-btn ui-btn-b ui-btn-inline\n
+        ui-icon-edit ui-btn-icon-right">Save</button>\n
+    </form>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>981</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewWipPartSpreadsheet.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewWipPartSpreadsheet.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..606920f3067d0fa03f0f53ab378c5805f4a95b30
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Input_viewWipPartSpreadsheet.js.xml
@@ -0,0 +1,110 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681761.66</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Input_viewWipPartSpreadsheet.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, initGadgetMixin, loopEventListener */\n
+(function(window, rJS, RSVP, initGadgetMixin, loopEventListener) {\n
+    "use strict";\n
+    function saveSpreadsheet(evt) {\n
+        var gadget = this, editor_data, editor_gadget;\n
+        return new RSVP.Queue().push(function() {\n
+            // Prevent double click\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = true;\n
+            }\n
+            return gadget.getDeclaredGadget("tableeditor");\n
+        }).push(function(tablegadget) {\n
+            editor_gadget = tablegadget;\n
+            return editor_gadget.getData();\n
+        }).push(function(data) {\n
+            editor_data = data;\n
+            // Always get a fresh version, to prevent deleting spreadsheet & co\n
+            return gadget.aq_getAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json"\n
+            });\n
+        }).push(function(body) {\n
+            var data = JSON.parse(body);\n
+            data.wip_part_spreadsheet = JSON.parse(editor_data);\n
+            return gadget.aq_putAttachment({\n
+                _id: gadget.props.jio_key,\n
+                _attachment: "body.json",\n
+                _data: JSON.stringify(data, null, 2),\n
+                _mimetype: "application/json"\n
+            });\n
+        }).push(function() {\n
+            if (evt) {\n
+                evt.target.getElementsByClassName("ui-btn")[0].disabled = false;\n
+            }\n
+        });\n
+    }\n
+    function waitForSave(gadget) {\n
+        return loopEventListener(gadget.props.element.getElementsByClassName("save_form")[0], "submit", false, saveSpreadsheet.bind(gadget));\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareAcquiredMethod("aq_putAttachment", "jio_putAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ gadget.aq_getAttachment({\n
+                _id: jio_key,\n
+                _attachment: "body.json"\n
+            }), gadget.getDeclaredGadget("tableeditor") ]);\n
+        }).push(function(result_list) {\n
+            return result_list[1].render(JSON.stringify(JSON.parse(result_list[0]).wip_part_spreadsheet), {\n
+                minSpareRows: 1,\n
+                onChange: function() {\n
+                    if (gadget.timeout) {\n
+                        window.clearTimeout(gadget.timeout);\n
+                    }\n
+                    gadget.timeout = window.setTimeout(saveSpreadsheet.bind(gadget), 100);\n
+                }\n
+            });\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        var gadget = this;\n
+        return this.getDeclaredGadget("tableeditor").push(function(tableeditor) {\n
+            return RSVP.all([ tableeditor.startService(), waitForSave(gadget) ]);\n
+        });\n
+    });\n
+})(window, rJS, RSVP, initGadgetMixin, loopEventListener);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3030</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewCapacityUtilisationGraph.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewCapacityUtilisationGraph.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..14416ce7e3e0a9aad5a34dd9b489f7a705bec532
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewCapacityUtilisationGraph.html.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681761.76</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewCapacityUtilisationGraph.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Stations Utilization</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.flot.js"></script>\n
+    <script src="../lib/jquery.flot.stack.js"></script>\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Output_viewCapacityUtilisationGraph.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>684</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewCapacityUtilisationGraph.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewCapacityUtilisationGraph.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..73d5139d91862ab4ffa43c2eec897593dd1501d0
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewCapacityUtilisationGraph.js.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681761.88</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewCapacityUtilisationGraph.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, jQuery, initGadgetMixin */\n
+/*jslint unparam: true */\n
+(function(window, rJS, $, initGadgetMixin) {\n
+    "use strict";\n
+    function capacity_utilisation_graph_widget(all_data) {\n
+        var available_capacity_by_station = {}, station_id, series, graph_list = [], options, capacity_usage_by_station = {}, input_data = all_data.input, output_data = all_data.result;\n
+        // Compute availability by station\n
+        $.each(input_data.nodes, function(idx, obj) {\n
+            var available_capacity = [];\n
+            if (obj.intervalCapacity !== undefined) {\n
+                $.each(obj.intervalCapacity, function(i, capacity) {\n
+                    available_capacity.push([ i, capacity ]);\n
+                });\n
+                available_capacity_by_station[obj.id] = available_capacity;\n
+            }\n
+        });\n
+        // Compute used capacity by station\n
+        $.each(output_data.elementList.sort(function(a, b) {\n
+            return a.id < b.id ? -1 : 1;\n
+        }), function(idx, obj) {\n
+            if (obj.results !== undefined && obj.results.capacityUsed !== undefined) {\n
+                var capacity_usage = [];\n
+                $.each(obj.results.capacityUsed, function(i, step) {\n
+                    var period = 0, usage = 0;\n
+                    $.each(step, function(k, v) {\n
+                        if (k === "period") {\n
+                            period = v;\n
+                        }\n
+                    });\n
+                    $.each(step, function(k, v) {\n
+                        if (k !== "utilization" && k !== "period") {\n
+                            usage += v;\n
+                        }\n
+                    });\n
+                    capacity_usage.push([ period, usage ]);\n
+                });\n
+                capacity_usage_by_station[obj.id] = capacity_usage;\n
+            }\n
+        });\n
+        for (station_id in available_capacity_by_station) {\n
+            if (available_capacity_by_station.hasOwnProperty(station_id)) {\n
+                series = [ {\n
+                    label: "Capacity",\n
+                    data: available_capacity_by_station[station_id],\n
+                    color: "green"\n
+                }, {\n
+                    label: "Utilisation",\n
+                    data: capacity_usage_by_station[station_id],\n
+                    color: "red"\n
+                } ];\n
+                options = {\n
+                    series: {\n
+                        lines: {\n
+                            show: true,\n
+                            fill: true\n
+                        }\n
+                    }\n
+                };\n
+                graph_list.push([ input_data.nodes[station_id].name || station_id, series, options ]);\n
+            }\n
+        }\n
+        return graph_list;\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        gadget.props.result = options.result;\n
+        return gadget.aq_getAttachment({\n
+            _id: gadget.props.jio_key,\n
+            _attachment: "simulation.json"\n
+        }).push(function(simulation_json) {\n
+            gadget.props.result_list = capacity_utilisation_graph_widget(JSON.parse(simulation_json)[gadget.props.result]);\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        var element = $(this.props.element), graph;\n
+        $.each(this.props.result_list, function(idx, result) {\n
+            graph = $("<div class=\'capacity_graph\' " + "style=\'width: 70%; height: 250px\'></div>");\n
+            element.append($("<h2>").text(result[0]), graph);\n
+            $.plot(graph, result[1], result[2]);\n
+        });\n
+    });\n
+})(window, rJS, jQuery, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3769</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDebugJson.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDebugJson.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..31d024fc96779e37bd40453eeb9d30d07cd46045
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDebugJson.html.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681762.0</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewDebugJson.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Debug JSON</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Output_viewDebugJson.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <label for="json_input">Input</label>\n
+    <textarea spellcheck="false" rows="20" name="json_input" class="json_input"></textarea>\n
+    <label for="json_output">Output</label>\n
+    <textarea spellcheck="false" rows="20" name="json_output" class="json_output"></textarea>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>757</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDebugJson.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDebugJson.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..33d63b4f9510d198037ced180dab5fe23088dd5f
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDebugJson.js.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681762.09</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewDebugJson.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global rJS, initGadgetMixin */\n
+(function(window, rJS, initGadgetMixin) {\n
+    "use strict";\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareMethod("render", function(options) {\n
+        var gadget = this;\n
+        this.props.jio_key = options.id;\n
+        this.props.result = options.result;\n
+        return gadget.aq_getAttachment({\n
+            _id: gadget.props.jio_key,\n
+            _attachment: "simulation.json"\n
+        }).push(function(result_json) {\n
+            var result = JSON.parse(result_json);\n
+            gadget.props.element.querySelector(".json_input").textContent = JSON.stringify(result[gadget.props.result].input, undefined, " ");\n
+            gadget.props.element.querySelector(".json_output").textContent = JSON.stringify(result[gadget.props.result].result, undefined, " ");\n
+        });\n
+    });\n
+})(window, rJS, initGadgetMixin);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>954</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDownloadExcelSpreadsheet.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDownloadExcelSpreadsheet.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..12470f5396d25d220c2a5c339a31abb7e7dc1f10
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDownloadExcelSpreadsheet.html.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681762.21</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewDownloadExcelSpreadsheet.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Download Excel Spreadsheet</title>\n
+\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Output_viewDownloadExcelSpreadsheet.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <a class="download_link ui-btn ui-btn-inline ui-icon-action ui-btn-icon-right">Download</a>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>682</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDownloadExcelSpreadsheet.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDownloadExcelSpreadsheet.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..850e670d2c2fb50f8c34284b512ff7bf6fb07f57
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewDownloadExcelSpreadsheet.js.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681762.31</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewDownloadExcelSpreadsheet.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global rJS, RSVP, jQuery, initGadgetMixin */\n
+/*jslint nomen: true, unparam: true */\n
+(function(window, rJS, RSVP, $, initGadgetMixin) {\n
+    "use strict";\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        gadget.props.result = options.result;\n
+        return gadget.aq_getAttachment({\n
+            _id: gadget.props.jio_key,\n
+            _attachment: "simulation.json"\n
+        }).push(function(simulation_json) {\n
+            var result = JSON.parse(simulation_json)[0].result, download_link = gadget.props.element.querySelector(".download_link");\n
+            download_link.download = "demandPlannerOutput.xls";\n
+            download_link.href = "data:application/excel;base64," + result["demandPlannerOutput.xls"];\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        return new RSVP.Queue().push(function() {\n
+            // Infinite wait, until cancelled\n
+            return new RSVP.defer().promise;\n
+        });\n
+    });\n
+})(window, rJS, RSVP, jQuery, initGadgetMixin);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1223</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewExitStatistics.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewExitStatistics.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..276387dbc108706bb55d7526525a542fb24b529d
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewExitStatistics.html.xml
@@ -0,0 +1,109 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681762.42</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewExitStatistics.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Exit Statistics</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/handlebars.min.js" type="text/javascript"></script>\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Output_viewExitStatistics.js" type="text/javascript"></script>\n
+\n
+    <script id="interval-through-metric-template" type="text/x-handlebars-template">\n
+      <tr>\n
+        <td>Daily Attainment</td>\n
+        <td>\n
+          {{#interval_list}}\n
+            <i class="ui-link ui-btn ui-icon-{{icon}} ui-btn-inline ui-cornel-all ui-btn-icon-right">{{interval}}</i><br/>\n
+          {{/interval_list}}\n
+        </td>\n
+      </tr>\n
+      <tr>\n
+        <td>Average Daily Line Attainment</td>\n
+        <td>{{average}}%<td>\n
+      </tr>\n
+    </script>\n
+\n
+    <script id="simple-metric-template" type="text/x-handlebars-template">\n
+      <tr>\n
+        <td>{{metric}}</td>\n
+        <td>{{{value}}}</td>\n
+      </tr>\n
+    </script>\n
+\n
+    <script id="metric-object-template" type="text/x-handlebars-template">\n
+      <table width=\'100%\'>\n
+        <tbody>\n
+          <tr>\n
+            <td>Average</td>\n
+            <td>{{avg}}</td>\n
+          </tr>\n
+          <tr>\n
+            <td>Lower Bound</td>\n
+            <td>{{lb}}</td>\n
+          </tr>\n
+          <tr>\n
+            <td>Upper Bound</td>\n
+            <td>{{ub}}</td>\n
+          </tr>\n
+        </tbody>\n
+      </table>\n
+    </script>\n
+\n
+    <script id="header-template" type="text/x-handlebars-template">\n
+      <tr>\n
+        <th colspan=\'2\'>{{name}}</th>\n
+      </tr>\n
+    </script>\n
+\n
+  </head>\n
+  <body>\n
+    <table>\n
+    </table>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1813</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewExitStatistics.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewExitStatistics.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e38fcde9949e866aee1dde5e0494d948d74ca9ce
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewExitStatistics.js.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681762.74</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewExitStatistics.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, Handlebars,\n
+         initGadgetMixin */\n
+/*jslint nomen: true */\n
+(function(window, rJS, Handlebars, initGadgetMixin) {\n
+    "use strict";\n
+    /////////////////////////////////////////////////////////////////\n
+    // Handlebars\n
+    /////////////////////////////////////////////////////////////////\n
+    // Precompile the templates while loading the first gadget instance\n
+    var gadget_klass = rJS(window), header_source = gadget_klass.__template_element.getElementById("header-template").innerHTML, header_template = Handlebars.compile(header_source), metric_object_source = gadget_klass.__template_element.getElementById("metric-object-template").innerHTML, metric_object_template = Handlebars.compile(metric_object_source), metric_simple_source = gadget_klass.__template_element.getElementById("simple-metric-template").innerHTML, metric_simple_template = Handlebars.compile(metric_simple_source), metric_interval_source = gadget_klass.__template_element.getElementById("interval-through-metric-template").innerHTML, metric_interval_template = Handlebars.compile(metric_interval_source);\n
+    /////////////////////////////////////////////////////////////////\n
+    // Calculate widget\n
+    /////////////////////////////////////////////////////////////////\n
+    function calculate_average(attainment_list) {\n
+        return (attainment_list.reduce(function(a, b) {\n
+            return a + b;\n
+        }) / attainment_list.length * 100).toFixed(2);\n
+    }\n
+    function calculate_exit_stat(data) {\n
+        var output_data = data.result, input_data = data.input, elementList = output_data.elementList, i, j, metric, metric_value, element, interval_value, interval_list, attainment_list, throughputTarget = input_data.general.throughputTarget, result = "";\n
+        for (i = 0; i < elementList.length; i += 1) {\n
+            element = elementList[i];\n
+            if (element.family === "Exit") {\n
+                result += "<table>";\n
+                result += header_template({\n
+                    name: element.name || element.id\n
+                });\n
+                for (metric in element.results) {\n
+                    if (element.results.hasOwnProperty(metric)) {\n
+                        metric_value = element.results[metric];\n
+                        if (metric === "intervalThroughputList") {\n
+                            interval_list = [];\n
+                            attainment_list = [];\n
+                            for (j = 0; j < metric_value.length; j += 1) {\n
+                                interval_value = metric_value[j];\n
+                                attainment_list.push(interval_value / throughputTarget);\n
+                                if (interval_value > throughputTarget) {\n
+                                    interval_list.push({\n
+                                        interval: interval_value,\n
+                                        icon: "check"\n
+                                    });\n
+                                } else {\n
+                                    interval_list.push({\n
+                                        interval: interval_value,\n
+                                        icon: "delete"\n
+                                    });\n
+                                }\n
+                            }\n
+                            result += metric_interval_template({\n
+                                interval_list: interval_list,\n
+                                average: calculate_average(attainment_list)\n
+                            });\n
+                        } else {\n
+                            if (typeof metric_value === "object") {\n
+                                if (metric_value.ub === metric_value.lb) {\n
+                                    metric_value = metric_value.ub;\n
+                                } else {\n
+                                    metric_value.metric = metric;\n
+                                    metric_value.avg = metric_value.avg.toFixed(2);\n
+                                    metric_value.lb = metric_value.lb.toFixed(2);\n
+                                    metric_value.ub = metric_value.ub.toFixed(2);\n
+                                    metric_value = metric_object_template(metric_value);\n
+                                }\n
+                            }\n
+                            if (typeof metric_value === "number") {\n
+                                metric_value = metric_value.toFixed(2);\n
+                            }\n
+                            // Rename some metric to something more meaningful\n
+                            if (metric === "lifespan") {\n
+                                metric = "Cycle Time";\n
+                            }\n
+                            if (metric === "takt_time") {\n
+                                metric = "Average Departure Rate";\n
+                            }\n
+                            result += metric_simple_template({\n
+                                metric: metric,\n
+                                value: metric_value\n
+                            });\n
+                        }\n
+                    }\n
+                }\n
+                result += "</table>";\n
+            }\n
+        }\n
+        return result;\n
+    }\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        gadget.props.result = options.result;\n
+        return gadget.aq_getAttachment({\n
+            _id: gadget.props.jio_key,\n
+            _attachment: "simulation.json"\n
+        }).push(function(simulation_json) {\n
+            var result = calculate_exit_stat(JSON.parse(simulation_json)[gadget.props.result]);\n
+            gadget.props.element.innerHTML = result;\n
+        });\n
+    });\n
+})(window, rJS, Handlebars, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>5794</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobGantt.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobGantt.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..b5746ab67a0f965a9843a1198dc05c0222c210a5
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobGantt.html.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681762.84</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewJobGantt.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Job Gantt</title>\n
+    <link rel="stylesheet" href="../lib/dhtmlxgantt.css">\n
+\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/dhtmlxgantt.js" type="text/javascript"></script>\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Output_viewJobGantt.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div class="gant_container" style="height: 800px;"></div>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>745</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobGantt.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobGantt.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..62d9dc2de1522d09b87c201507b95690fe5a57dd
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobGantt.js.xml
@@ -0,0 +1,249 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681762.95</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewJobGantt.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, jQuery, gantt,\n
+         initGadgetMixin */\n
+/*jslint nomen: true, unparam: true */\n
+(function(window, rJS, RSVP, $, gantt, initGadgetMixin) {\n
+    "use strict";\n
+    gantt.templates.task_class = function(start, end, obj) {\n
+        return obj.parent ? "sub_task" : "";\n
+    };\n
+    function job_gantt_widget(all_data) {\n
+        // XXX: use dhx_gantt zoom level feature (\n
+        // http://dhtmlx.com/docs/products/dhtmlxGantt/02_features.html )\n
+        var now = new Date(), start_date, gantt_data = {\n
+            data: [ {\n
+                id: "by_order",\n
+                text: "By Order",\n
+                start_date: start_date,\n
+                duration: 0,\n
+                project: 1,\n
+                open: true\n
+            }, {\n
+                id: "by_station",\n
+                text: "By Station",\n
+                start_date: start_date,\n
+                duration: 0,\n
+                project: 1,\n
+                open: true\n
+            } ],\n
+            link: []\n
+        }, input_data = all_data.input, output_data = all_data.result;\n
+        // temporary hack\n
+        now.setHours(0);\n
+        now.setMinutes(0);\n
+        now.setSeconds(0);\n
+        start_date = input_data.general.currentDate;\n
+        if (start_date !== undefined && start_date !== "") {\n
+            start_date = new Date(start_date);\n
+        } else {\n
+            start_date = new Date(now.getTime());\n
+        }\n
+        function isVisibleStation(station) {\n
+            // we should be able to define in the backend which\n
+            // station is visible\n
+            return input_data.nodes[station].family !== "Buffer" && input_data.nodes[station].family !== "Exit";\n
+        }\n
+        $.each(output_data.elementList.sort(function(a, b) {\n
+            return a.id < b.id ? -1 : 1;\n
+        }), function(idx, obj) {\n
+            var input_job = null, input_order = null, i, j, node, node_key, order, component, duration, seen_parts = {};\n
+            if (obj.family === "Job") {\n
+                // find the corresponding input\n
+                // find the input order and order component for this job\n
+                for (node_key in input_data.nodes) {\n
+                    if (input_data.nodes.hasOwnProperty(node_key)) {\n
+                        node = input_data.nodes[node_key];\n
+                        if (node.wip) {\n
+                            for (i = 0; i < node.wip.length; i += 1) {\n
+                                order = node.wip[i];\n
+                                if (order.id === obj.id) {\n
+                                    input_job = input_order = order;\n
+                                }\n
+                                if (input_job === null && order.componentsList) {\n
+                                    for (j = 0; j < order.componentsList.length; j += 1) {\n
+                                        component = order.componentsList[j];\n
+                                        if (component.id === obj.id) {\n
+                                            input_order = order;\n
+                                            input_job = component;\n
+                                        }\n
+                                    }\n
+                                }\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+                duration = 0;\n
+                if (input_job === input_order) {\n
+                    // if we are on the order definition\n
+                    gantt_data.data.push({\n
+                        id: input_order.id,\n
+                        text: input_order.name,\n
+                        project: 1,\n
+                        open: false,\n
+                        parent: "by_order"\n
+                    });\n
+                }\n
+                seen_parts = {};\n
+                $.each(obj.results.schedule, function(i, schedule) {\n
+                    var task_start_date, job_full_id;\n
+                    // Filter intermediate steps in part job shop\n
+                    if (isVisibleStation(schedule.stationId)) {\n
+                        if (schedule.exitTime) {\n
+                            duration = 24 * (schedule.exitTime - schedule.entranceTime);\n
+                        } else {\n
+                            if (obj.results.schedule[i + 1]) {\n
+                                duration = obj.results.schedule[i + 1].entranceTime - schedule.entranceTime;\n
+                            } else {\n
+                                duration = obj.results.completionTime - schedule.entranceTime;\n
+                            }\n
+                        }\n
+                        if (duration > 0) {\n
+                            task_start_date = new Date(start_date.getTime());\n
+                            // for simulation time unit as days\n
+                            // task_start_date.setDate(task_start_date.getDate() +\n
+                            //   schedule[\'entranceTime\']);\n
+                            // for simulation time unit as days hours\n
+                            task_start_date.setTime(task_start_date.getTime() + schedule.entranceTime * 1e3 * 3600 * 24);\n
+                            job_full_id = input_job.id + "." + input_order.id;\n
+                            if (seen_parts[job_full_id] === undefined) {\n
+                                gantt_data.data.push({\n
+                                    id: job_full_id,\n
+                                    text: input_job.name,\n
+                                    parent: input_order.id\n
+                                });\n
+                                seen_parts[job_full_id] = 1;\n
+                            }\n
+                            gantt_data.data.push({\n
+                                id: input_order.id + "." + idx + "_" + i,\n
+                                text: schedule.stationId,\n
+                                start_date: task_start_date,\n
+                                duration: duration,\n
+                                parent: job_full_id\n
+                            });\n
+                            gantt_data.data.push({\n
+                                id: "job." + obj.id + "." + idx + "_" + i,\n
+                                text: input_order.name + "-" + input_job.name,\n
+                                start_date: task_start_date,\n
+                                duration: duration,\n
+                                parent: schedule.stationId,\n
+                                by_station: 1\n
+                            });\n
+                        }\n
+                    }\n
+                });\n
+            } else {\n
+                if (isVisibleStation(obj.id)) {\n
+                    gantt_data.data.push({\n
+                        id: obj.id,\n
+                        text: obj.id,\n
+                        project: 1,\n
+                        open: false,\n
+                        parent: "by_station"\n
+                    });\n
+                }\n
+            }\n
+        });\n
+        //     gantt_output_height = 35 * (gantt_data.data.length + 1) + 1;\n
+        gantt_data.data.sort(function(a, b) {\n
+            // sort gantt data in a chronological order\n
+            var result;\n
+            if (a.start_date === undefined && b.start_date !== undefined) {\n
+                result = 1;\n
+            } else if (a.start_date !== undefined && b.start_date === undefined) {\n
+                result = -1;\n
+            } else if (a.start_date === undefined && b.start_date === undefined) {\n
+                result = 0;\n
+            } else if (a.start_date > b.start_date) {\n
+                result = 1;\n
+            } else if (a.start_date < b.start_date) {\n
+                result = -1;\n
+            } else {\n
+                result = 0;\n
+            }\n
+            return result;\n
+        });\n
+        return gantt_data;\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        gadget.props.result = options.result;\n
+        return gadget.aq_getAttachment({\n
+            _id: gadget.props.jio_key,\n
+            _attachment: "simulation.json"\n
+        }).push(function(simulation_json) {\n
+            gadget.props.result = job_gantt_widget(JSON.parse(simulation_json)[gadget.props.result]);\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        $(this.props.element).find(".gant_container").dhx_gantt({\n
+            data: this.props.result,\n
+            readonly: true,\n
+            /* for days has simulation time unit\n
+        scale_unit: \'day\',\n
+        step: 7\n
+        */\n
+            // for hours has simulation time unit\n
+            scale_unit: "day",\n
+            duration_unit: 60 * 60 * 1e3,\n
+            //date_grid: "%H:%i",\n
+            date_scale: "%M/%d",\n
+            step: 1,\n
+            subscales: [ {\n
+                unit: "hour",\n
+                step: 4,\n
+                date: "%H:%i"\n
+            } ]\n
+        });\n
+        return new RSVP.Queue().push(function() {\n
+            // Infinite wait, until cancelled\n
+            return new RSVP.defer().promise;\n
+        }).push(undefined, function(error) {\n
+            gantt.clearAll();\n
+            throw error;\n
+        });\n
+    });\n
+})(window, rJS, RSVP, jQuery, gantt, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>9180</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobScheduleSpreadsheet.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobScheduleSpreadsheet.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bd61a047b38ef020bce743ac4d0fb4c72ccdce30
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobScheduleSpreadsheet.html.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681763.05</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewJobScheduleSpreadsheet.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Job Schedule</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+\n
+    <script src="../lib/moment.js" type="text/javascript"></script>\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Output_viewJobScheduleSpreadsheet.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div data-gadget-url="../handsontable/index.html"\n
+         data-gadget-scope="tableeditor"></div>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>671</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobScheduleSpreadsheet.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobScheduleSpreadsheet.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3086a7bbef004af56327ef28bbad39f23b5200b0
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewJobScheduleSpreadsheet.js.xml
@@ -0,0 +1,173 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681763.17</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewJobScheduleSpreadsheet.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, moment, initGadgetMixin */\n
+/*jslint nomen: true */\n
+(function(window, rJS, RSVP, moment, initGadgetMixin) {\n
+    "use strict";\n
+    function job_schedule_spreadsheet_widget(all_data) {\n
+        var now = new Date(), name, input_data = all_data.input, output_data = all_data.result, spreadsheet_data = [], spreadsheet_header = [ [ "Jobs", "ID", "Project Manager", "Due Date", "Priority", "Entrance Time", "Processing Time", "Station ID", "Step No." ] ], simulation_start_date = new Date(input_data.general.currentDate || now.getTime()), i, j, k, obj, node, component, order, node_id, due_date, entrance_date, duration, schedule, input_job = null, input_order = null;\n
+        // XXX why ?\n
+        now.setHours(0);\n
+        now.setMinutes(0);\n
+        now.setSeconds(0);\n
+        // XXX: time unit for later\n
+        //      or an utility function to map sim time to real time & vice\n
+        //      versa.\n
+        for (i = 0; i < output_data.elementList.length; i += 1) {\n
+            obj = output_data.elementList[i];\n
+            if (obj.family === "Job") {\n
+                input_job = null;\n
+                input_order = null;\n
+                // find the input order and order component for this job\n
+                // XXX this has no real meaning with capacity project\n
+                for (node_id in input_data.nodes) {\n
+                    if (input_data.nodes.hasOwnProperty(node_id)) {\n
+                        node = input_data.nodes[node_id];\n
+                        if (node.wip) {\n
+                            for (j = 0; j < node.wip.length; j += 1) {\n
+                                order = node.wip[j];\n
+                                if (order.id === obj.id) {\n
+                                    input_job = input_order = order;\n
+                                }\n
+                                if (input_job === null && order.componentsList) {\n
+                                    for (k = 0; k < order.componentsList.length; k += 1) {\n
+                                        component = order.componentsList[k];\n
+                                        if (component.id === obj.id) {\n
+                                            input_order = order;\n
+                                            input_job = component;\n
+                                        }\n
+                                    }\n
+                                }\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+                // XXX does not make sense in the case of capacity project\n
+                due_date = new Date(simulation_start_date.getTime() + input_order.dueDate * 1e3 * 3600);\n
+                for (j = 0; j < obj.results.schedule.length; j += 1) {\n
+                    schedule = obj.results.schedule[j];\n
+                    entrance_date = new Date(simulation_start_date.getTime() + // XXX: time unit\n
+                    schedule.entranceTime * 1e3 * 3600);\n
+                    duration = 0;\n
+                    if (schedule.exitTime) {\n
+                        duration = schedule.exitTime - schedule.entranceTime * 24;\n
+                    } else {\n
+                        // When duration is not returned by ManPy, it is calculated by\n
+                        // difference of entranceTime of this step and entranceTime of the\n
+                        // next step, or completionTime when this is the last step\n
+                        if (j + 1 === obj.results.schedule.length) {\n
+                            duration = obj.results.completionTime - schedule.entranceTime;\n
+                        } else {\n
+                            duration = obj.results.schedule[j + 1].entranceTime - schedule.entranceTime;\n
+                        }\n
+                    }\n
+                    name = "";\n
+                    if (obj._class === "Dream.CapacityProject") {\n
+                        name = input_order.name + "-" + schedule.stationId;\n
+                    } else {\n
+                        name = input_order.name + "-" + input_job.name;\n
+                    }\n
+                    // Duration is calculated by difference of entranceTime of this\n
+                    // step and entranceTime of the next step, or completionTime when\n
+                    // this is the last step\n
+                    if (j + 1 === obj.results.schedule.length) {\n
+                        duration = obj.results.completionTime - schedule.entranceTime;\n
+                    } else {\n
+                        duration = obj.results.schedule[j + 1].entranceTime - schedule.entranceTime;\n
+                    }\n
+                    spreadsheet_data.push([ // XXX this label is incorrect for design step, during design\n
+                    // phase we still have an order and not an order component.\n
+                    name, obj.id, input_order.manager, moment(due_date).format("YYYY/MM/DD"), input_order.priority, moment(entrance_date).format("MMM/DD HH:mm"), duration, schedule.stationId, j ]);\n
+                }\n
+            }\n
+        }\n
+        if (spreadsheet_data.length > 1) {\n
+            // Sort the spreadsheet data to an order convenient for end users\n
+            // XXX: search for a default cmp in javascript\n
+            spreadsheet_data.sort(function(a, b) {\n
+                var result = 0, order_id_a, order_id_b, entrance_a, entrance_b;\n
+                order_id_a = a[0].split("-")[0];\n
+                order_id_b = b[0].split("-")[0];\n
+                if (order_id_a !== order_id_b) {\n
+                    if (order_id_a > order_id_b) {\n
+                        result = 1;\n
+                    } else {\n
+                        result = -1;\n
+                    }\n
+                } else {\n
+                    entrance_a = a[4];\n
+                    entrance_b = b[4];\n
+                    if (entrance_a > entrance_b) {\n
+                        result = 1;\n
+                    } else if (entrance_a < entrance_b) {\n
+                        result = -1;\n
+                    } else {\n
+                        result = 0;\n
+                    }\n
+                }\n
+                return result;\n
+            });\n
+        }\n
+        return spreadsheet_header.concat(spreadsheet_data);\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        gadget.props.result = options.result;\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ gadget.aq_getAttachment({\n
+                _id: jio_key,\n
+                _attachment: "simulation.json"\n
+            }), gadget.getDeclaredGadget("tableeditor") ]);\n
+        }).push(function(result_list) {\n
+            return result_list[1].render(JSON.stringify(job_schedule_spreadsheet_widget(JSON.parse(result_list[0])[gadget.props.result])));\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        return this.getDeclaredGadget("tableeditor").push(function(tableeditor) {\n
+            return tableeditor.startService();\n
+        });\n
+    });\n
+})(window, rJS, RSVP, moment, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>7105</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewQueueStatGraph.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewQueueStatGraph.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..df84b7af3ece5f3f84a4b6477f7d28f87dd02855
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewQueueStatGraph.html.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681763.27</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewQueueStatGraph.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Queues Statistics</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.flot.js"></script>\n
+    <script src="../lib/jquery.flot.stack.js"></script>\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Output_viewQueueStatGraph.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div class="graph_container" style="width: 100%;height:300px"></div>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>676</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewQueueStatGraph.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewQueueStatGraph.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..33574e52e27c304fdc6588ff555a6569656c4475
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewQueueStatGraph.js.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681763.37</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewQueueStatGraph.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global rJS, jQuery, initGadgetMixin */\n
+/*jslint nomen: true, unparam: true */\n
+(function(window, rJS, $, initGadgetMixin) {\n
+    "use strict";\n
+    function queue_stat_widget(output_data) {\n
+        /* FIXME: does not support more than one replic.\n
+     * + see george email to integrate without the need of an EG\n
+     */\n
+        var series = [];\n
+        $.each(output_data.elementList, function(idx, el) {\n
+            if (el.family === "Buffer") {\n
+                series.push({\n
+                    label: el.name || el.id,\n
+                    data: el.results.wip_stat_list\n
+                });\n
+            }\n
+        });\n
+        return series;\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        gadget.props.result = options.result;\n
+        return gadget.aq_getAttachment({\n
+            _id: gadget.props.jio_key,\n
+            _attachment: "simulation.json"\n
+        }).push(function(simulation_json) {\n
+            gadget.props.series = queue_stat_widget(JSON.parse(simulation_json)[gadget.props.result].result);\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        // XXX Manually calculate width and height when resizing\n
+        $.plot(this.props.element.querySelector(".graph_container"), this.props.series);\n
+    });\n
+})(window, rJS, jQuery, initGadgetMixin);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1519</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewStationUtilisationGraph.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewStationUtilisationGraph.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e038714ef57b45047f05c58b2137bc7a2a1bd1ec
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewStationUtilisationGraph.html.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681763.61</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewStationUtilisationGraph.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Stations Utilization</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.flot.js"></script>\n
+    <script src="../lib/jquery.flot.stack.js"></script>\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="Output_viewStationUtilisationGraph.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+    <div class="graph_container" style="width: 100%;height:300px"></div>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>756</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewStationUtilisationGraph.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewStationUtilisationGraph.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..59e558eb759ee4e5398b98041d3e556ae4faa372
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/Output_viewStationUtilisationGraph.js.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681763.72</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>Output_viewStationUtilisationGraph.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, jQuery, initGadgetMixin */\n
+/*jslint unparam: true */\n
+(function(window, rJS, $, initGadgetMixin) {\n
+    "use strict";\n
+    function station_utilisation_graph_widget(output_data) {\n
+        var blockage_data = [], waiting_data = [], failure_data = [], working_data = [], ticks = [], counter = 1, series, options;\n
+        // XXX output is still elementList ???\n
+        $.each(output_data.elementList.sort(function(a, b) {\n
+            return a.id < b.id ? -1 : 1;\n
+        }), function(idx, obj) {\n
+            // add each object that has a working ratio\n
+            if (obj.results !== undefined && obj.results.working_ratio !== undefined) {\n
+                /* when there is only one replication, the ratio is given as a float,\n
+              otherwise we have a mapping avg, ub lb */\n
+                var blockage_ratio = 0, working_ratio = 0, waiting_ratio = 0, failure_ratio = 0;\n
+                if (obj.results.blockage_ratio !== undefined) {\n
+                    if (obj.results.blockage_ratio.avg !== undefined) {\n
+                        blockage_ratio = obj.results.blockage_ratio.avg;\n
+                    } else {\n
+                        blockage_ratio = obj.results.blockage_ratio;\n
+                    }\n
+                }\n
+                blockage_data.push([ counter, blockage_ratio ]);\n
+                // XXX merge setup & loading ratio in working ratio for now\n
+                if (obj.results.setup_ratio !== undefined) {\n
+                    if (obj.results.setup_ratio.avg !== undefined) {\n
+                        working_ratio += obj.results.setup_ratio.avg;\n
+                    } else {\n
+                        working_ratio += obj.results.setup_ratio;\n
+                    }\n
+                }\n
+                if (obj.results.loading_ratio !== undefined) {\n
+                    if (obj.results.loading_ratio.avg !== undefined) {\n
+                        working_ratio += obj.results.loading_ratio.avg;\n
+                    } else {\n
+                        working_ratio += obj.results.loading_ratio;\n
+                    }\n
+                }\n
+                if (obj.results.working_ratio !== undefined) {\n
+                    if (obj.results.working_ratio.avg !== undefined) {\n
+                        working_ratio += obj.results.working_ratio.avg;\n
+                    } else {\n
+                        working_ratio += obj.results.working_ratio;\n
+                    }\n
+                }\n
+                working_data.push([ counter, working_ratio ]);\n
+                if (obj.results.waiting_ratio !== undefined) {\n
+                    if (obj.results.waiting_ratio.avg !== undefined) {\n
+                        waiting_ratio = obj.results.waiting_ratio.avg;\n
+                    } else {\n
+                        waiting_ratio = obj.results.waiting_ratio;\n
+                    }\n
+                }\n
+                waiting_data.push([ counter, waiting_ratio ]);\n
+                if (obj.results.failure_ratio !== undefined) {\n
+                    if (obj.results.failure_ratio.avg !== undefined) {\n
+                        failure_ratio = obj.results.failure_ratio.avg;\n
+                    } else {\n
+                        failure_ratio = obj.results.failure_ratio;\n
+                    }\n
+                }\n
+                failure_data.push([ counter, failure_ratio ]);\n
+                ticks.push([ counter, obj.id ]);\n
+                counter += 1;\n
+            }\n
+        });\n
+        series = [ {\n
+            label: "Working",\n
+            data: working_data\n
+        }, {\n
+            label: "Waiting",\n
+            data: waiting_data\n
+        }, {\n
+            label: "Failures",\n
+            data: failure_data\n
+        }, {\n
+            label: "Blockage",\n
+            data: blockage_data\n
+        } ];\n
+        options = {\n
+            xaxis: {\n
+                minTickSize: 1,\n
+                ticks: ticks\n
+            },\n
+            yaxis: {\n
+                max: 100\n
+            },\n
+            series: {\n
+                bars: {\n
+                    show: true,\n
+                    barWidth: .8,\n
+                    align: "center"\n
+                },\n
+                stack: true\n
+            }\n
+        };\n
+        return [ series, options ];\n
+    }\n
+    var gadget_klass = rJS(window);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("aq_getAttachment", "jio_getAttachment").declareMethod("render", function(options) {\n
+        var jio_key = options.id, gadget = this;\n
+        gadget.props.jio_key = jio_key;\n
+        gadget.props.result = options.result;\n
+        return gadget.aq_getAttachment({\n
+            _id: gadget.props.jio_key,\n
+            _attachment: "simulation.json"\n
+        }).push(function(simulation_json) {\n
+            gadget.props.result_list = station_utilisation_graph_widget(JSON.parse(simulation_json)[gadget.props.result].result);\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        // XXX Manually calculate width and height when resizing\n
+        $.plot(this.props.element.querySelector(".graph_container"), this.props.result_list[0], this.props.result_list[1]);\n
+    });\n
+})(window, rJS, jQuery, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>5059</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/favicon.ico.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/favicon.ico.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a17423fb494a426a27aed761547c4381beb1b5d0
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/favicon.ico.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681763.82</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>favicon.ico</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/vnd.microsoft.icon</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAA
+AAAAAAD+/////////+H79P+t9Nz/sPTe/+/9+P///////v79//7+/f//////6/z3/63z3P+s89r/
+6Pv0///////+//////////////+W8NH/buq//27qv/+r8tv///////7//v/+//7//////6rz2f9n
+6br/auq8/6Dy1v///////v/////////t/Pf/dOvC/3jrwf9768T/he7M//j79//87uX//PDm//j6
+9v+C7sn/devB/33sxv947MT/7v34///////9//7//////7H03v9q6Lv/bui9/8j87v/8z7H/6aBi
+/+qgZv/90rr/wfzt/2/ov/9z6r//uvTh///////9//7////////////3/vz/3fvx/+H++P/59e3/
+7aZt/+ugav/spHD/7adw//j38f/g/PL/3fns//f+/P/////////////+/f//////+d/L//axhP/2
+sof/+uvf//LAlv/smlv/7J1g//G+l//659j/9a9///Wvff/54M3////////+/f///////ffy/+2p
+d//pomr/6Jla//C4jf/78ef/6su4/+nDrf/67+f/8baH/+mbYf/pnWT/7bF8//77+P//////////
+//349P/tqXX/6p9n/+ibZv/1u4z/qK73/3J7+P91fvn/qKz4//a8h//plVr/66Br/+2reP/9+vb/
+///////+/f//////+dvF//Stfv/7tID/z77U/2109P9pa+n/Z2jp/2Rr9f/TxNT/9rN9/+2pe//4
+3cj////////+/f////////////T9+v/Y9ej/6v/v/7Cx9f9fYez/cnju/3B37v9dZO7/s7Xz///x
+1f/35db//vr3/////////////f/+//////+q89r/a+m//3DtwP+u4OL/dG/x/1xk7P9hZuv/cHj3
+/+HAuv/voF//6Zxg//TMrv////////79///////r/Pf/dOvC/37sxv9z6b//iPPH/8zR+/+bn/X/
+l5rz/8/O9P/zr3T/659p/+2jbf/so2z//PXt/////////////////5nw0/9x6sD/bOm6/6z34///
+6tP/9b2M//W3g//+7db/8sam/+qWXf/rnGD/8LuR//////////7//v/////////n+/T/uPTf/7r2
+4v/w+vP/761+/+mbZv/qnmj/7a19//vw5v/0zrP/9M6w//vw5/////////7+/////////////v//
+/////v///////fz4/+6xhP/snGP/7KJp/+6ugP/++vf//////////v////7/////////////////
+//////7////9//7//P78///////44dD/7qt3/+2uef/34M7///////78+////fz///7+////////
+////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAA==</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1150</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.css.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..a2c30fd2d6f25f451e2cb5691d2e903e986cf6b9
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.css.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681758.24</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.css</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/css</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>@media (min-width:110em){.jqm-navmenu-panel.ui-panel-closed{visibility:visible!important;width:17em;-webkit-transition:none!important;-moz-transition:none!important;transition:none!important;-webkit-transform:none!important;-moz-transform:none!important;transform:none!important;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none;height:100%;position:absolute;display:block}.ui-panel-page-content-open{width:auto}.ui-panel-page-content-open.ui-panel-page-content-position-left{margin-right:17em}.ui-panel-dismiss,.menu_link{display:none!important}.gadget_container,header,nav{margin-left:17em}.close-entry{display:none!important}.gadget_container{padding:1em}}[data-gadget-scope=productionline_toolbox]{position:relative;width:19.5%;float:left}[data-gadget-scope=productionline_graph]{position:relative;width:79.5%;float:right}form.save_form{display:none}</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>865</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f4f137bdd01839ca7a5c083b33813e4aaa24838a
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.html.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681763.93</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Dream Simulation test debug</title>\n
+    <link rel="shortcut icon" href="favicon.ico">\n
+\n
+    <link rel="stylesheet" href="../lib/jquerymobile.css">\n
+    <link rel="stylesheet" href="index.css" />\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/handlebars.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+    <script src="mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="index.js" type="text/javascript"></script>\n
+\n
+    <script id="panel-template" type="text/x-handlebars-template">\n
+      <ul data-role="listview">\n
+        <li><a class="home_link ui-btn ui-icon-home ui-btn-icon-left" data-icon="home">Documents</a></li>\n
+        <li><a class="fast_input_link ui-btn ui-icon-plus ui-btn-icon-left" data-icon="plus">New Document</a></li>\n
+        {{#navigationlist}}\n
+          <li><a href="{{link}}">{{title}}</a></li>\n
+        {{/navigationlist}}\n
+      </ul>\n
+    </script>\n
+\n
+    <script id="active-navigation-template" type="text/x-handlebars-template">\n
+      <li><a class="ui-btn-active ui-state-persist" href="{{link}}">{{title}} ahah</a></li>\n
+    </script>\n
+\n
+    <script id="navigation-template" type="text/x-handlebars-template">\n
+      <li><a href="{{link}}">{{title}}</a></li>\n
+    </script>\n
+\n
+    <script id="error-template" type="text/x-handlebars-template">\n
+      <h1>An Error Has Occurred</h1>\n
+      <a href="javascript: location.reload()">Click here to reload the page</a><br/>\n
+      The error detail is:\n
+      <pre>{{error}}</pre>\n
+    </script>\n
+\n
+  </head>\n
+  <body>\n
+\n
+    <!-- ID are bad, but required for JQM panel -->\n
+    <div class="jqm-navmenu-panel"\n
+         data-role="panel"\n
+         id="leftpanel"\n
+         data-display="overlay"\n
+         data-position="left"\n
+         data-theme="b">\n
+    </div>\n
+\n
+    <header data-role="header">\n
+\n
+      <div data-role="controlgroup" data-type="horizontal" class="ui-btn-left">\n
+        <a href="#leftpanel"\n
+           data-icon="bars"\n
+           class="menu_link ui-btn ui-icon-bars ui-btn-icon-left">Menu</a>\n
+        <a data-icon="carat-u"\n
+           class="back_link ui-btn ui-icon-carat-u ui-btn-icon-left">Parent</a>\n
+      </div>\n
+      <h1>Dream Simulation</h1>\n
+\n
+      <div data-role="controlgroup" data-type="horizontal" class="ui-btn-right">\n
+        <a data-icon="forward"\n
+           class="next_link ui-btn ui-icon-forward ui-btn-icon-right">Next</a>\n
+      </div>\n
+\n
+    </header>\n
+\n
+    <div class="nav_container"></div>\n
+\n
+    <article class="gadget_container"></article>\n
+\n
+    <aside>\n
+      <section data-gadget-url="../jio_bridge/index.html"\n
+               data-gadget-scope="jio"\n
+               data-gadget-sandbox="public"></section>\n
+    </aside>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3023</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.js.orig.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.js.orig.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f3754631f56f599207255c86a44380ee107a0462
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.js.orig.xml
@@ -0,0 +1,503 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681758.43</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.js.orig</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/octet-stream</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global console, jQuery, rJS, RSVP, alert, Handlebars, initGadgetMixin */\n
+/*jslint nomen: true */\n
+(function(window, $, rJS, RSVP, Handlebars, initGadgetMixin) {\n
+    "use strict";\n
+    /////////////////////////////////////////////////////////////////\n
+    // Desactivate jQuery Mobile URL management\n
+    /////////////////////////////////////////////////////////////////\n
+    $.mobile.ajaxEnabled = false;\n
+    $.mobile.linkBindingEnabled = false;\n
+    $.mobile.hashListeningEnabled = false;\n
+    $.mobile.pushStateEnabled = false;\n
+    /////////////////////////////////////////////////////////////////\n
+    // Minimalistic ERP5\'s like portal type configuration\n
+    /////////////////////////////////////////////////////////////////\n
+    // XXX we should use lists instead to keep ordering\n
+    var portal_types = {\n
+        "Input Module": {\n
+            view: {\n
+                gadget: "InputModule_viewInputList",\n
+                type: "object_list",\n
+                title: "Document List"\n
+            },\n
+            view_fast_input: {\n
+                gadget: "InputModule_viewAddDocumentDialog",\n
+                type: "object_fast_input",\n
+                title: "Create Document"\n
+            }\n
+        },\n
+        Input: {\n
+            view: {\n
+                gadget: "Input_viewProductionLine",\n
+                type: "object_view",\n
+                title: "Production Line"\n
+            },\n
+            view_wip_part_spreadsheet: {\n
+                gadget: "Input_viewWipPartSpreadsheet",\n
+                type: "object_view",\n
+                title: "WIP Part Spreadsheet",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.wip_part_spreadsheet;\n
+                }\n
+            },\n
+            view_shift_spreadsheet: {\n
+                gadget: "Input_viewShiftSpreadsheet",\n
+                type: "object_view",\n
+                title: "Shift Spreadsheet",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.shift_spreadsheet;\n
+                }\n
+            },\n
+            view_available_capacity_spreadsheet: {\n
+                gadget: "Input_viewAvailableCapacitySpreadsheet",\n
+                type: "object_view",\n
+                title: "Available Capacity Spreadsheet",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.capacity_by_project_spreadsheet;\n
+                }\n
+            },\n
+            view_required_capacity_spreadsheet: {\n
+                gadget: "Input_viewRequiredCapacitySpreadsheet",\n
+                type: "object_view",\n
+                title: "Required Capacity Spreadsheet",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.capacity_by_station_spreadsheet;\n
+                }\n
+            },\n
+            view_dp_capacity_spreadsheet: {\n
+                gadget: "Input_viewDemandPlanningCapacitySpreadsheet",\n
+                type: "object_view",\n
+                title: "Demand Planning Required Capacity Spreadsheet",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.dp_capacity_spreadsheet;\n
+                }\n
+            },\n
+            view_dp_route_spreadsheet: {\n
+                gadget: "Input_viewDemandPlanningRouteSpreadsheet",\n
+                type: "object_view",\n
+                title: "Demand Planning Route Spreadsheet",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.dp_route_spreadsheet;\n
+                }\n
+            },\n
+            view_simu: {\n
+                gadget: "Input_viewSimulation",\n
+                type: "object_view",\n
+                title: "Run simulation"\n
+            },\n
+            view_management: {\n
+                gadget: "Input_viewDocumentManagement",\n
+                type: "object_view",\n
+                title: "Manage document"\n
+            },\n
+            view_result: {\n
+                gadget: "Input_viewResultList",\n
+                type: "object_view",\n
+                title: "Results"\n
+            }\n
+        },\n
+        Output: {\n
+            view: {\n
+                gadget: "Output_viewStationUtilisationGraph",\n
+                type: "object_view",\n
+                title: "Stations Utilization",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.station_utilisation_graph;\n
+                }\n
+            },\n
+            download_excel_spreadsheet: {\n
+                gadget: "Output_viewDownloadExcelSpreadsheet",\n
+                type: "object_view",\n
+                title: "Download Excel Spreadsheet",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.download_excel_spreadsheet;\n
+                }\n
+            },\n
+            view_capacity_utilization: {\n
+                gadget: "Output_viewCapacityUtilisationGraph",\n
+                type: "object_view",\n
+                title: "Capacity Utilization",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.capacity_utilisation_graph;\n
+                }\n
+            },\n
+            view_queue_stat: {\n
+                gadget: "Output_viewQueueStatGraph",\n
+                type: "object_view",\n
+                title: "Queues Statistics",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.queue_stat;\n
+                }\n
+            },\n
+            view_exit_stat: {\n
+                gadget: "Output_viewExitStatistics",\n
+                type: "object_view",\n
+                title: "Exit Statistics",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.exit_stat;\n
+                }\n
+            },\n
+            view_gantt: {\n
+                gadget: "Output_viewJobGantt",\n
+                type: "object_view",\n
+                title: "Job Gantt",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.job_gantt;\n
+                }\n
+            },\n
+            view_schedule: {\n
+                gadget: "Output_viewJobScheduleSpreadsheet",\n
+                type: "object_view",\n
+                title: "Job Schedule",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.job_schedule_spreadsheet;\n
+                }\n
+            },\n
+            view_debug: {\n
+                gadget: "Output_viewDebugJson",\n
+                type: "object_view",\n
+                title: "Debug JSON",\n
+                condition: function(gadget) {\n
+                    return gadget.props.configuration_dict["Dream-Configuration"].gui.debug_json;\n
+                }\n
+            }\n
+        }\n
+    }, panel_template, navigation_template, active_navigation_template, error_template, gadget_klass = rJS(window);\n
+    function calculateTabHTML(gadget, options, key, title, active) {\n
+        return new RSVP.Queue().push(function() {\n
+            var kw = {\n
+                action: key,\n
+                id: options.id\n
+            };\n
+            if (options.result !== undefined) {\n
+                kw.result = options.result;\n
+            }\n
+            return gadget.aq_pleasePublishMyState(kw);\n
+        }).push(function(url) {\n
+            var kw = {\n
+                title: title,\n
+                link: url\n
+            };\n
+            if (active === true) {\n
+                return active_navigation_template(kw);\n
+            }\n
+            return navigation_template(kw);\n
+        });\n
+    }\n
+    function getNextLink(gadget, portal_type, options) {\n
+        var forward_kw = {\n
+            action: options.action || "view"\n
+        }, queue = new RSVP.Queue();\n
+        if (portal_type === "Input") {\n
+            forward_kw.id = options.id;\n
+        } else if (portal_type === "Output") {\n
+            forward_kw.id = options.id;\n
+            queue.push(function() {\n
+                return gadget.getDeclaredGadget("jio");\n
+            }).push(function(jio_gadget) {\n
+                return jio_gadget.getAttachment({\n
+                    _id: options.id,\n
+                    _attachment: "simulation.json"\n
+                });\n
+            }).push(function(sim_json) {\n
+                var document_list = JSON.parse(sim_json), current = parseInt(options.result, 10);\n
+                if (current === document_list.length - 1) {\n
+                    forward_kw.result = 0;\n
+                } else {\n
+                    forward_kw.result = current + 1;\n
+                }\n
+            });\n
+        } else if (portal_type !== "Input Module") {\n
+            throw new Error("Unknown portal type: " + portal_type);\n
+        }\n
+        return queue.push(function() {\n
+            return gadget.aq_pleasePublishMyState(forward_kw);\n
+        });\n
+    }\n
+    function getTitle(gadget, portal_type, options) {\n
+        var title;\n
+        if (portal_type === "Input Module") {\n
+            title = "Documents";\n
+        } else if (portal_type === "Input") {\n
+            title = gadget.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+                return jio_gadget.get({\n
+                    _id: options.id\n
+                });\n
+            }).push(function(jio_doc) {\n
+                return jio_doc.data.title + " (" + jio_doc.data.modified + ")";\n
+            });\n
+        } else if (portal_type === "Output") {\n
+            title = gadget.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+                return jio_gadget.getAttachment({\n
+                    _id: options.id,\n
+                    _attachment: "simulation.json"\n
+                });\n
+            }).push(function(sim_json) {\n
+                var document_list = JSON.parse(sim_json);\n
+                return document_list[options.result].score + " " + document_list[options.result].key;\n
+            });\n
+        } else {\n
+            throw new Error("Unknown portal type: " + portal_type);\n
+        }\n
+        return title;\n
+    }\n
+    function calculateNavigationHTML(gadget, portal_type, options) {\n
+        var nav_html, action;\n
+        if (portal_types[portal_type][options.action].type === "object_view") {\n
+            return new RSVP.Queue().push(function() {\n
+                var url_list = [], key2;\n
+                for (key2 in portal_types[portal_type]) {\n
+                    if (portal_types[portal_type].hasOwnProperty(key2)) {\n
+                        action = portal_types[portal_type][key2];\n
+                        if (action.type === "object_view") {\n
+                            if (action.condition === undefined || action.condition(gadget)) {\n
+                                url_list.push(calculateTabHTML(gadget, options, key2, action.title, key2 === options.action));\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+                return RSVP.all(url_list);\n
+            }).push(function(entry_list) {\n
+                var i;\n
+                nav_html = \'<nav data-role="navbar" data-collapsible="true"><ul>\';\n
+                for (i = 0; i < entry_list.length; i += 1) {\n
+                    nav_html += entry_list[i];\n
+                }\n
+                nav_html += "</ul></nav>";\n
+                return nav_html;\n
+            });\n
+        }\n
+    }\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("pleaseRedirectMyHash", "pleaseRedirectMyHash").allowPublicAcquisition("jio_allDocs", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.allDocs.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_ajax", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.ajax.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_post", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.post.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_remove", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.remove.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_get", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.get.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_putAttachment", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.putAttachment.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_getAttachment", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.getAttachment.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("whoWantsToDisplayHome", function() {\n
+        // Hey, I want to display some URL\n
+        return this.aq_pleasePublishMyState({});\n
+    }).allowPublicAcquisition("whoWantsToDisplayThisDocument", function(param_list) {\n
+        // Hey, I want to display some jIO document\n
+        // XXX should be merged with whoWantsToDisplayThisResult\n
+        var kw = {\n
+            action: param_list[1] || "view"\n
+        };\n
+        if (param_list[0] !== undefined) {\n
+            kw.id = param_list[0];\n
+        }\n
+        return this.aq_pleasePublishMyState(kw);\n
+    }).allowPublicAcquisition("whoWantsToDisplayThisResult", function(param_list) {\n
+        // Hey, I want to display some jIO document\n
+        // We\'ll display the result using the first enabled action\n
+        var action = "view", action_info, action_id;\n
+        for (action_id in portal_types.Output) {\n
+            if (portal_types.Output.hasOwnProperty(action_id)) {\n
+                action_info = portal_types.Output[action_id];\n
+                if (action_info.condition === undefined || action_info.condition(this)) {\n
+                    action = action_id;\n
+                    break;\n
+                }\n
+            }\n
+        }\n
+        return this.aq_pleasePublishMyState({\n
+            action: action,\n
+            id: param_list[0],\n
+            result: param_list[1]\n
+        });\n
+    }).allowPublicAcquisition("getConfigurationDict", function() {\n
+        return this.props.configuration_dict;\n
+    }).ready(function() {\n
+        if (panel_template === undefined) {\n
+            // XXX Only works as root gadget\n
+            panel_template = Handlebars.compile(document.getElementById("panel-template").innerHTML);\n
+            navigation_template = Handlebars.compile(document.getElementById("navigation-template").innerHTML);\n
+            active_navigation_template = Handlebars.compile(document.getElementById("active-navigation-template").innerHTML);\n
+            error_template = Handlebars.compile(document.getElementById("error-template").innerHTML);\n
+        }\n
+    }).ready(function(g) {\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ g.aq_pleasePublishMyState({}), g.aq_pleasePublishMyState({\n
+                action: "view_fast_input"\n
+            }) ]);\n
+        }).push(function(link_list) {\n
+            var panel = g.props.element.querySelector("#leftpanel");\n
+            panel.innerHTML = panel_template({\n
+                navigationlist: []\n
+            });\n
+            panel.getElementsByClassName("home_link")[0].href = link_list[0];\n
+            panel.getElementsByClassName("fast_input_link")[0].href = link_list[1];\n
+            // XXX JQuery mobile\n
+            $(panel).trigger("create");\n
+        });\n
+    }).ready(function(g) {\n
+        var jio_gadget;\n
+        return g.getDeclaredGadget("jio").push(function(gadget) {\n
+            jio_gadget = gadget;\n
+            return jio_gadget.createJio({\n
+                type: "local",\n
+                username: "dream",\n
+                applicationname: "dream"\n
+            });\n
+        }).push(function() {\n
+            g.props.configuration_dict = {\n
+                "Dream-Configuration": {\n
+                    _class: "Dream.Configuration",\n
+                    gui: {\n
+                        debug_json: 1,\n
+                        download_excel_spreadsheet: 0,\n
+                        exit_stat: 1,\n
+                        job_gantt: 0,\n
+                        job_schedule_spreadsheet: 0,\n
+                        queue_stat: 1,\n
+                        shift_spreadsheet: 0,\n
+                        station_utilisation_graph: 1,\n
+                        wip_part_spreadsheet: 0,\n
+                        wip_spreadsheet: 0\n
+                    },\n
+                    property_list: [ {\n
+                        _class: "Dream.Property",\n
+                        _default: 10,\n
+                        id: "numberOfReplications",\n
+                        name: "Number of replications",\n
+                        type: "number"\n
+                    } ]\n
+                }\n
+            };\n
+        });\n
+    }).declareMethod("render", function(options) {\n
+        var gadget = this, back_kw = {\n
+            action: "view"\n
+        }, page_gadget, portal_type = "Input Module", nav_element = gadget.props.element.getElementsByClassName("nav_container")[0], element = gadget.props.element.getElementsByClassName("gadget_container")[0];\n
+        if (options.action === undefined) {\n
+            // Redirect to the view action\n
+            options.action = "view";\n
+            return gadget.aq_pleasePublishMyState(options).push(gadget.pleaseRedirectMyHash.bind(gadget));\n
+        }\n
+        // Detect what is the kind of document displayed\n
+        if (options.id !== undefined) {\n
+            if (options.result === undefined) {\n
+                portal_type = "Input";\n
+            } else {\n
+                portal_type = "Output";\n
+                back_kw.action = "view_result";\n
+                back_kw.id = options.id;\n
+            }\n
+        }\n
+        // Get the action information\n
+        return gadget.declareGadget(portal_types[portal_type][options.action].gadget + ".html").push(function(g) {\n
+            page_gadget = g;\n
+            if (page_gadget.render !== undefined) {\n
+                return page_gadget.render(options);\n
+            }\n
+        }).push(function() {\n
+            return RSVP.all([ page_gadget.getElement(), calculateNavigationHTML(gadget, portal_type, options), gadget.aq_pleasePublishMyState(back_kw), getTitle(gadget, portal_type, options), getNextLink(gadget, portal_type, options) ]);\n
+        }).push(function(result_list) {\n
+            var nav_html = result_list[1], page_element = result_list[0];\n
+            // Update title\n
+            gadget.props.element.querySelector("header h1").textContent = result_list[3];\n
+            // XXX Hide the back button in case of module display?\n
+            // Update back link\n
+            gadget.props.element.getElementsByClassName("back_link")[0].href = result_list[2];\n
+            // XXX Hide the forward button in case of non result?\n
+            // Update forward link\n
+            gadget.props.element.getElementsByClassName("next_link")[0].href = result_list[4];\n
+            // Update the navigation panel\n
+            // Clear the previous rendering\n
+            while (nav_element.firstChild) {\n
+                nav_element.removeChild(nav_element.firstChild);\n
+            }\n
+            if (nav_html !== undefined) {\n
+                nav_element.innerHTML = nav_html;\n
+                $(nav_element).trigger("create");\n
+            }\n
+            // Append in the DOM at the end to reduce flickering and reduce DOM\n
+            // modifications\n
+            // Clear the previous rendering\n
+            while (element.firstChild) {\n
+                element.removeChild(element.firstChild);\n
+            }\n
+            element.appendChild(page_element);\n
+            $(element).trigger("create");\n
+            // XXX RenderJS hack to start sub gadget services\n
+            // Only work if this gadget has no parent.\n
+            if (page_gadget.startService !== undefined) {\n
+                return page_gadget.startService();\n
+            }\n
+        }).push(undefined, function(error) {\n
+            if (error instanceof RSVP.CancellationError) {\n
+                throw error;\n
+            }\n
+            console.error(error);\n
+            document.querySelector("article[class=\'gadget_container\']").innerHTML = error_template({\n
+                error: error\n
+            });\n
+        });\n
+    });\n
+})(window, jQuery, rJS, RSVP, Handlebars, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>20699</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..56c8e0a03b70e569d7823999bd85b9b1f4a77bdf
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/index.js.xml
@@ -0,0 +1,449 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681764.24</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global console, jQuery, rJS, RSVP, alert, Handlebars, initGadgetMixin */\n
+/*jslint nomen: true */\n
+(function(window, $, rJS, RSVP, Handlebars, initGadgetMixin) {\n
+    "use strict";\n
+    /////////////////////////////////////////////////////////////////\n
+    // Desactivate jQuery Mobile URL management\n
+    /////////////////////////////////////////////////////////////////\n
+    $.mobile.ajaxEnabled = false;\n
+    $.mobile.linkBindingEnabled = false;\n
+    $.mobile.hashListeningEnabled = false;\n
+    $.mobile.pushStateEnabled = false;\n
+    /////////////////////////////////////////////////////////////////\n
+    // Minimalistic ERP5\'s like portal type configuration\n
+    /////////////////////////////////////////////////////////////////\n
+    // XXX we should use lists instead to keep ordering\n
+    var portal_types = {\n
+        "Input Module": {\n
+            view: {\n
+                gadget: "InputModule_viewInputList",\n
+                type: "object_list",\n
+                title: "Document List"\n
+            },\n
+            view_fast_input: {\n
+                gadget: "InputModule_viewAddDocumentDialog",\n
+                type: "object_fast_input",\n
+                title: "Create Document"\n
+            }\n
+        },\n
+        // TODO: remove this once everything is merged.\n
+        Input: {\n
+            view: {\n
+                gadget: "Input_viewProductionLine",\n
+                type: "object_view",\n
+                title: "Production Line"\n
+            },\n
+            view_wip_part_spreadsheet: {\n
+                gadget: "Input_viewWipPartSpreadsheet",\n
+                type: "object_view",\n
+                title: "WIP Part Spreadsheet"\n
+            },\n
+            view_shift_spreadsheet: {\n
+                gadget: "Input_viewShiftSpreadsheet",\n
+                type: "object_view",\n
+                title: "Shift Spreadsheet"\n
+            },\n
+            view_available_capacity_spreadsheet: {\n
+                gadget: "Input_viewAvailableCapacitySpreadsheet",\n
+                type: "object_view",\n
+                title: "Available Capacity Spreadsheet"\n
+            },\n
+            view_required_capacity_spreadsheet: {\n
+                gadget: "Input_viewRequiredCapacitySpreadsheet",\n
+                type: "object_view",\n
+                title: "Required Capacity Spreadsheet"\n
+            },\n
+            view_dp_capacity_spreadsheet: {\n
+                gadget: "Input_viewDemandPlanningCapacitySpreadsheet",\n
+                type: "object_view",\n
+                title: "Demand Planning Required Capacity Spreadsheet"\n
+            },\n
+            view_dp_route_spreadsheet: {\n
+                gadget: "Input_viewDemandPlanningRouteSpreadsheet",\n
+                type: "object_view",\n
+                title: "Demand Planning Route Spreadsheet"\n
+            },\n
+            view_simu: {\n
+                gadget: "Input_viewSimulation",\n
+                type: "object_view",\n
+                title: "Run simulation"\n
+            },\n
+            view_management: {\n
+                gadget: "Input_viewDocumentManagement",\n
+                type: "object_view",\n
+                title: "Manage document"\n
+            },\n
+            view_result: {\n
+                gadget: "Input_viewResultList",\n
+                type: "object_view",\n
+                title: "Results"\n
+            }\n
+        },\n
+        Output: {\n
+            view: {\n
+                gadget: "Output_viewStationUtilisationGraph",\n
+                type: "object_view",\n
+                title: "Stations Utilization"\n
+            },\n
+            download_excel_spreadsheet: {\n
+                gadget: "Output_viewDownloadExcelSpreadsheet",\n
+                type: "object_view",\n
+                title: "Download Excel Spreadsheet"\n
+            },\n
+            view_capacity_utilization: {\n
+                gadget: "Output_viewCapacityUtilisationGraph",\n
+                type: "object_view",\n
+                title: "Capacity Utilization"\n
+            },\n
+            view_queue_stat: {\n
+                gadget: "Output_viewQueueStatGraph",\n
+                type: "object_view",\n
+                title: "Queues Statistics"\n
+            },\n
+            view_exit_stat: {\n
+                gadget: "Output_viewExitStatistics",\n
+                type: "object_view",\n
+                title: "Exit Statistics"\n
+            },\n
+            view_gantt: {\n
+                gadget: "Output_viewJobGantt",\n
+                type: "object_view",\n
+                title: "Job Gantt"\n
+            },\n
+            view_schedule: {\n
+                gadget: "Output_viewJobScheduleSpreadsheet",\n
+                type: "object_view",\n
+                title: "Job Schedule"\n
+            },\n
+            view_debug: {\n
+                gadget: "Output_viewDebugJson",\n
+                type: "object_view",\n
+                title: "Debug JSON"\n
+            }\n
+        }\n
+    }, panel_template, navigation_template, active_navigation_template, error_template, gadget_klass = rJS(window);\n
+    function calculateTabHTML(gadget, options, key, title, active) {\n
+        return new RSVP.Queue().push(function() {\n
+            var kw = {\n
+                action: key,\n
+                id: options.id\n
+            };\n
+            if (options.result !== undefined) {\n
+                kw.result = options.result;\n
+            }\n
+            return gadget.aq_pleasePublishMyState(kw);\n
+        }).push(function(url) {\n
+            var kw = {\n
+                title: title,\n
+                link: url\n
+            };\n
+            if (active === true) {\n
+                return active_navigation_template(kw);\n
+            }\n
+            return navigation_template(kw);\n
+        });\n
+    }\n
+    function getNextLink(gadget, portal_type, options) {\n
+        var forward_kw = {\n
+            action: options.action || "view"\n
+        }, queue = new RSVP.Queue();\n
+        if (portal_type === "Input") {\n
+            forward_kw.id = options.id;\n
+        } else if (portal_type === "Output") {\n
+            forward_kw.id = options.id;\n
+            queue.push(function() {\n
+                return gadget.getDeclaredGadget("jio");\n
+            }).push(function(jio_gadget) {\n
+                return jio_gadget.getAttachment({\n
+                    _id: options.id,\n
+                    _attachment: "simulation.json"\n
+                });\n
+            }).push(function(sim_json) {\n
+                var document_list = JSON.parse(sim_json), current = parseInt(options.result, 10);\n
+                if (current === document_list.length - 1) {\n
+                    forward_kw.result = 0;\n
+                } else {\n
+                    forward_kw.result = current + 1;\n
+                }\n
+            });\n
+        } else if (portal_type !== "Input Module") {\n
+            throw new Error("Unknown portal type: " + portal_type);\n
+        }\n
+        return queue.push(function() {\n
+            return gadget.aq_pleasePublishMyState(forward_kw);\n
+        });\n
+    }\n
+    function getTitle(gadget, portal_type, options) {\n
+        var title;\n
+        if (portal_type === "Input Module") {\n
+            title = "Documents";\n
+        } else if (portal_type === "Input") {\n
+            title = gadget.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+                return jio_gadget.get({\n
+                    _id: options.id\n
+                });\n
+            }).push(function(jio_doc) {\n
+                return jio_doc.data.title + " (" + jio_doc.data.modified + ")";\n
+            });\n
+        } else if (portal_type === "Output") {\n
+            title = gadget.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+                return jio_gadget.getAttachment({\n
+                    _id: options.id,\n
+                    _attachment: "simulation.json"\n
+                });\n
+            }).push(function(sim_json) {\n
+                var document_list = JSON.parse(sim_json);\n
+                return document_list[options.result].score + " " + document_list[options.result].key;\n
+            });\n
+        } else {\n
+            throw new Error("Unknown portal type: " + portal_type);\n
+        }\n
+        return title;\n
+    }\n
+    function calculateNavigationHTML(gadget, portal_type, options) {\n
+        var nav_html, action;\n
+        if (portal_types[portal_type][options.action].type === "object_view") {\n
+            return new RSVP.Queue().push(function() {\n
+                var url_list = [], key2;\n
+                for (key2 in portal_types[portal_type]) {\n
+                    if (portal_types[portal_type].hasOwnProperty(key2)) {\n
+                        action = portal_types[portal_type][key2];\n
+                        if (action.type === "object_view") {\n
+                            if (action.condition === undefined || action.condition(gadget)) {\n
+                                url_list.push(calculateTabHTML(gadget, options, key2, action.title, key2 === options.action));\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+                return RSVP.all(url_list);\n
+            }).push(function(entry_list) {\n
+                var i;\n
+                nav_html = \'<nav data-role="navbar" data-collapsible="true"><ul>\';\n
+                for (i = 0; i < entry_list.length; i += 1) {\n
+                    nav_html += entry_list[i];\n
+                }\n
+                nav_html += "</ul></nav>";\n
+                return nav_html;\n
+            });\n
+        }\n
+    }\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareAcquiredMethod("pleaseRedirectMyHash", "pleaseRedirectMyHash").allowPublicAcquisition("jio_allDocs", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.allDocs.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_ajax", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.ajax.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_post", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.post.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_remove", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.remove.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_get", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.get.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_putAttachment", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.putAttachment.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("jio_getAttachment", function(param_list) {\n
+        return this.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            return jio_gadget.getAttachment.apply(jio_gadget, param_list);\n
+        });\n
+    }).allowPublicAcquisition("whoWantsToDisplayHome", function() {\n
+        // Hey, I want to display some URL\n
+        return this.aq_pleasePublishMyState({});\n
+    }).allowPublicAcquisition("whoWantsToDisplayThisDocument", function(param_list) {\n
+        // Hey, I want to display some jIO document\n
+        // XXX should be merged with whoWantsToDisplayThisResult\n
+        var kw = {\n
+            action: param_list[1] || "view"\n
+        };\n
+        if (param_list[0] !== undefined) {\n
+            kw.id = param_list[0];\n
+        }\n
+        return this.aq_pleasePublishMyState(kw);\n
+    }).allowPublicAcquisition("whoWantsToDisplayThisResult", function(param_list) {\n
+        // Hey, I want to display some jIO document\n
+        // We\'ll display the result using the first enabled action\n
+        var action = "view", action_info, action_id;\n
+        for (action_id in portal_types.Output) {\n
+            if (portal_types.Output.hasOwnProperty(action_id)) {\n
+                action_info = portal_types.Output[action_id];\n
+                if (action_info.condition === undefined || action_info.condition(this)) {\n
+                    action = action_id;\n
+                    break;\n
+                }\n
+            }\n
+        }\n
+        return this.aq_pleasePublishMyState({\n
+            action: action,\n
+            id: param_list[0],\n
+            result: param_list[1]\n
+        });\n
+    }).ready(function() {\n
+        if (panel_template === undefined) {\n
+            // XXX Only works as root gadget\n
+            panel_template = Handlebars.compile(document.getElementById("panel-template").innerHTML);\n
+            navigation_template = Handlebars.compile(document.getElementById("navigation-template").innerHTML);\n
+            active_navigation_template = Handlebars.compile(document.getElementById("active-navigation-template").innerHTML);\n
+            error_template = Handlebars.compile(document.getElementById("error-template").innerHTML);\n
+        }\n
+    }).ready(function(g) {\n
+        return new RSVP.Queue().push(function() {\n
+            return RSVP.all([ g.aq_pleasePublishMyState({}), g.aq_pleasePublishMyState({\n
+                action: "view_fast_input"\n
+            }) ]);\n
+        }).push(function(link_list) {\n
+            var panel = g.props.element.querySelector("#leftpanel");\n
+            panel.innerHTML = panel_template({\n
+                navigationlist: []\n
+            });\n
+            panel.getElementsByClassName("home_link")[0].href = link_list[0];\n
+            panel.getElementsByClassName("fast_input_link")[0].href = link_list[1];\n
+            // XXX JQuery mobile\n
+            $(panel).trigger("create");\n
+        });\n
+    }).ready(function(g) {\n
+        return g.getDeclaredGadget("jio").push(function(gadget) {\n
+            return gadget.createJio({\n
+                type: "local",\n
+                username: "dream",\n
+                applicationname: "dream"\n
+            });\n
+        });\n
+    }).declareMethod("render", function(options) {\n
+        var gadget = this, back_kw = {\n
+            action: "view"\n
+        }, page_gadget, portal_type = "Input Module", nav_element = gadget.props.element.getElementsByClassName("nav_container")[0], element = gadget.props.element.getElementsByClassName("gadget_container")[0];\n
+        if (options.action === undefined) {\n
+            // Redirect to the view action\n
+            options.action = "view";\n
+            return gadget.aq_pleasePublishMyState(options).push(gadget.pleaseRedirectMyHash.bind(gadget));\n
+        }\n
+        // Detect what is the kind of document displayed\n
+        if (options.id !== undefined) {\n
+            if (options.result === undefined) {\n
+                portal_type = "Input";\n
+            } else {\n
+                portal_type = "Output";\n
+                back_kw.action = "view_result";\n
+                back_kw.id = options.id;\n
+            }\n
+        }\n
+        return gadget.getDeclaredGadget("jio").push(function(jio_gadget) {\n
+            if (options.id) {\n
+                return jio_gadget.getAttachment({\n
+                    _id: options.id,\n
+                    _attachment: "body.json"\n
+                });\n
+            }\n
+        }).push(function(result) {\n
+            var data;\n
+            if (result) {\n
+                data = JSON.parse(result);\n
+                gadget.props.data = data;\n
+                portal_types.Input = data.application_configuration.input;\n
+                portal_types.Output = data.application_configuration.output;\n
+            }\n
+            // Get the action information\n
+            return gadget.declareGadget(portal_types[portal_type][options.action].gadget + ".html");\n
+        }).push(function(g) {\n
+            page_gadget = g;\n
+            if (page_gadget.render !== undefined) {\n
+                return page_gadget.render(options);\n
+            }\n
+        }).push(function() {\n
+            return RSVP.all([ page_gadget.getElement(), calculateNavigationHTML(gadget, portal_type, options), gadget.aq_pleasePublishMyState(back_kw), getTitle(gadget, portal_type, options), getNextLink(gadget, portal_type, options) ]);\n
+        }).push(function(result_list) {\n
+            var nav_html = result_list[1], page_element = result_list[0];\n
+            // Update title\n
+            gadget.props.element.querySelector("header h1").textContent = result_list[3];\n
+            // XXX Hide the back button in case of module display?\n
+            // Update back link\n
+            gadget.props.element.getElementsByClassName("back_link")[0].href = result_list[2];\n
+            // XXX Hide the forward button in case of non result?\n
+            // Update forward link\n
+            gadget.props.element.getElementsByClassName("next_link")[0].href = result_list[4];\n
+            // Update the navigation panel\n
+            // Clear the previous rendering\n
+            while (nav_element.firstChild) {\n
+                nav_element.removeChild(nav_element.firstChild);\n
+            }\n
+            if (nav_html !== undefined) {\n
+                nav_element.innerHTML = nav_html;\n
+                $(nav_element).trigger("create");\n
+            }\n
+            // Append in the DOM at the end to reduce flickering and reduce DOM\n
+            // modifications\n
+            // Clear the previous rendering\n
+            while (element.firstChild) {\n
+                element.removeChild(element.firstChild);\n
+            }\n
+            element.appendChild(page_element);\n
+            $(element).trigger("create");\n
+            // XXX RenderJS hack to start sub gadget services\n
+            // Only work if this gadget has no parent.\n
+            if (page_gadget.startService !== undefined) {\n
+                return page_gadget.startService();\n
+            }\n
+        }).push(undefined, function(error) {\n
+            if (error instanceof RSVP.CancellationError) {\n
+                throw error;\n
+            }\n
+            console.error(error);\n
+            document.querySelector("article[class=\'gadget_container\']").innerHTML = error_template({\n
+                error: error\n
+            });\n
+        });\n
+    });\n
+})(window, jQuery, rJS, RSVP, Handlebars, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>17784</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/mixin_document_page.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/mixin_document_page.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bc4e5afd99d5d48100a97a6ac94e05912e1ffa44
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/mixin_document_page.js.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681757.81</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>mixin_document_page.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global console, RSVP */\n
+(function(window, RSVP) {\n
+    "use strict";\n
+    window.initDocumentPageMixin = function(gadget_klass) {\n
+        gadget_klass.declareAcquiredMethod("whoWantToDisplayThisDocumentPage", "whoWantToDisplayThisDocumentPage").declareMethod("getNavigationList", function() {\n
+            var key = this.props.jio_key, gadget = this;\n
+            return new RSVP.Queue().push(function() {\n
+                // XXX Conditional simulation menu\n
+                return RSVP.all([ gadget.whoWantToDisplayThisDocumentPage("Input_viewProductionLine", key), gadget.whoWantToDisplayThisDocumentPage("Input_viewTable", key), gadget.whoWantToDisplayThisDocumentPage("Input_viewSimulation", key), gadget.whoWantToDisplayThisDocumentPage("Input_viewDocumentManagement", key), gadget.whoWantToDisplayThisDocumentPage("Output_viewStationUtilisationGraph", key), gadget.whoWantToDisplayThisDocumentPage("Output_viewQueueStatGraph", key), gadget.whoWantToDisplayThisDocumentPage("Output_viewExitStatistics", key), gadget.whoWantToDisplayThisDocumentPage("Output_viewJobGantt", key), gadget.whoWantToDisplayThisDocumentPage("Output_viewJobScheduleSpreadsheet", key), gadget.whoWantToDisplayThisDocumentPage("Output_viewDebugJson", key) ]);\n
+            }).push(function(result_list) {\n
+                return [ {\n
+                    link: result_list[0],\n
+                    title: "Production line"\n
+                }, {\n
+                    link: result_list[1],\n
+                    title: "Edit table"\n
+                }, {\n
+                    link: result_list[2],\n
+                    title: "Run simulation"\n
+                }, {\n
+                    link: result_list[3],\n
+                    title: "Manage document"\n
+                }, {\n
+                    link: result_list[4],\n
+                    title: "Stations Utilization"\n
+                }, {\n
+                    link: result_list[5],\n
+                    title: "Queues Statistics"\n
+                }, {\n
+                    link: result_list[6],\n
+                    title: "Exit Statistics"\n
+                }, {\n
+                    link: result_list[7],\n
+                    title: "Job Gantt"\n
+                }, {\n
+                    link: result_list[8],\n
+                    title: "Job Schedule"\n
+                }, {\n
+                    link: result_list[9],\n
+                    title: "Debug JSON"\n
+                } ];\n
+            });\n
+        });\n
+    };\n
+})(window, RSVP);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2425</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/mixin_gadget.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/mixin_gadget.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8d871e0fe9c1136565001e1c40396a0f24c05c9c
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/mixin_gadget.js.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681764.03</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>mixin_gadget.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>(function(window) {\n
+    "use strict";\n
+    window.initGadgetMixin = function(gadget_klass) {\n
+        gadget_klass.ready(function(g) {\n
+            g.props = {};\n
+        }).ready(function(g) {\n
+            return g.getElement().push(function(element) {\n
+                g.props.element = element;\n
+            });\n
+        });\n
+    };\n
+})(window);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>338</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/mixin_promise.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/mixin_promise.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c13cc76f0e634a8599bf495beedb8caf72b50581
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/dream/mixin_promise.js.xml
@@ -0,0 +1,118 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681764.13</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>mixin_promise.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global RSVP, FileReader */\n
+/*jslint unparam: true */\n
+(function(window, RSVP, FileReader) {\n
+    "use strict";\n
+    window.loopEventListener = function(target, type, useCapture, callback, allowDefault) {\n
+        //////////////////////////\n
+        // Infinite event listener (promise is never resolved)\n
+        // eventListener is removed when promise is cancelled/rejected\n
+        //////////////////////////\n
+        var handle_event_callback, callback_promise;\n
+        function cancelResolver() {\n
+            if (callback_promise !== undefined && typeof callback_promise.cancel === "function") {\n
+                callback_promise.cancel();\n
+            }\n
+        }\n
+        function canceller() {\n
+            if (handle_event_callback !== undefined) {\n
+                target.removeEventListener(type, handle_event_callback, useCapture);\n
+            }\n
+            cancelResolver();\n
+        }\n
+        function itsANonResolvableTrap(resolve, reject) {\n
+            handle_event_callback = function(evt) {\n
+                evt.stopPropagation();\n
+                if (allowDefault !== true) {\n
+                    evt.preventDefault();\n
+                }\n
+                cancelResolver();\n
+                callback_promise = new RSVP.Queue().push(function() {\n
+                    return callback(evt);\n
+                }).push(undefined, function(error) {\n
+                    if (!(error instanceof RSVP.CancellationError)) {\n
+                        canceller();\n
+                        reject(error);\n
+                    }\n
+                });\n
+            };\n
+            target.addEventListener(type, handle_event_callback, useCapture);\n
+        }\n
+        return new RSVP.Promise(itsANonResolvableTrap, canceller);\n
+    };\n
+    window.promiseEventListener = function(target, type, useCapture) {\n
+        //////////////////////////\n
+        // Resolve the promise as soon as the event is triggered\n
+        // eventListener is removed when promise is cancelled/resolved/rejected\n
+        //////////////////////////\n
+        var handle_event_callback;\n
+        function canceller() {\n
+            target.removeEventListener(type, handle_event_callback, useCapture);\n
+        }\n
+        function resolver(resolve) {\n
+            handle_event_callback = function(evt) {\n
+                canceller();\n
+                evt.stopPropagation();\n
+                evt.preventDefault();\n
+                resolve(evt);\n
+                return false;\n
+            };\n
+            target.addEventListener(type, handle_event_callback, useCapture);\n
+        }\n
+        return new RSVP.Promise(resolver, canceller);\n
+    };\n
+    window.promiseReadAsText = function(file) {\n
+        return new RSVP.Promise(function(resolve, reject) {\n
+            var reader = new FileReader();\n
+            reader.onload = function(evt) {\n
+                resolve(evt.target.result);\n
+            };\n
+            reader.onerror = function(evt) {\n
+                reject(evt);\n
+            };\n
+            reader.readAsText(file);\n
+        });\n
+    };\n
+})(window, RSVP, FileReader);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2995</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/fieldset.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/fieldset.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d573949bd37d2ccc51c94227c3baaf2a8a7bba9f
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/fieldset.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>fieldset</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/fieldset/fieldset.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/fieldset/fieldset.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ccf129d6a332655b44b0c94e572d86e3547d4f9a
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/fieldset/fieldset.js.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681764.56</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>fieldset.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, RSVP, jQuery, Handlebars,\n
+  promiseEventListener, initGadgetMixin*/\n
+/*jslint nomen: true */\n
+(function(window, rJS, RSVP, Handlebars, initGadgetMixin) {\n
+    "use strict";\n
+    /////////////////////////////////////////////////////////////////\n
+    // Handlebars\n
+    /////////////////////////////////////////////////////////////////\n
+    // Precompile the templates while loading the first gadget instance\n
+    var gadget_klass = rJS(window), source = gadget_klass.__template_element.getElementById("label-template").innerHTML, label_template = Handlebars.compile(source);\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareMethod("render", function(options, node_id) {\n
+        // XXX node_id is added like a property so that one can change the node\n
+        // id\n
+        var gadget = this, queue;\n
+        gadget.props.key = options.key;\n
+        // used for recursive fieldsets\n
+        gadget.props.field_gadget_list = [];\n
+        function addField(property_id, property_definition, value) {\n
+            var sub_gadget;\n
+            queue.push(function() {\n
+                // XXX this is incorrect for recursive fieldsets.\n
+                // we should use nested fieldset with legend\n
+                gadget.props.element.insertAdjacentHTML("beforeend", label_template({\n
+                    "for": property_id,\n
+                    name: property_definition.name || property_id\n
+                }));\n
+                if (property_definition.type === "object") {\n
+                    // Create a recursive fieldset for this key.\n
+                    return gadget.declareGadget("../fieldset/index.html");\n
+                }\n
+                if (property_definition.type === "number") {\n
+                    return gadget.declareGadget("../number_field/index.html");\n
+                }\n
+                if (property_definition.enum) {\n
+                    return gadget.declareGadget("../list_field/index.html");\n
+                }\n
+                return gadget.declareGadget("../string_field/index.html");\n
+            }).push(function(gg) {\n
+                sub_gadget = gg;\n
+                return sub_gadget.render({\n
+                    key: property_id,\n
+                    value: value,\n
+                    property_definition: property_definition\n
+                });\n
+            }).push(function() {\n
+                return sub_gadget.getElement();\n
+            }).push(function(sub_element) {\n
+                gadget.props.element.appendChild(sub_element);\n
+                gadget.props.field_gadget_list.push(sub_gadget);\n
+            });\n
+        }\n
+        queue = new RSVP.Queue().push(function() {\n
+            if (node_id) {\n
+                addField("id", {\n
+                    type: "string"\n
+                }, node_id);\n
+            }\n
+            Object.keys(options.property_definition.properties).forEach(function(property_name) {\n
+                var property_definition = options.property_definition.properties[property_name], value = (options.value || {})[property_name] === undefined ? property_definition._default : options.value[property_name];\n
+                // XXX some properties are not editable\n
+                if (property_name !== "coordinate" && property_name !== "_class") {\n
+                    addField(property_name, property_definition, value);\n
+                }\n
+            });\n
+        });\n
+        return queue;\n
+    }).declareMethod("getContent", function() {\n
+        var i, promise_list = [], gadget = this;\n
+        for (i = 0; i < this.props.field_gadget_list.length; i += 1) {\n
+            promise_list.push(this.props.field_gadget_list[i].getContent());\n
+        }\n
+        return RSVP.Queue().push(function() {\n
+            return RSVP.all(promise_list);\n
+        }).push(function(result_list) {\n
+            var name, result = {}, content = result;\n
+            if (gadget.props.key) {\n
+                content = result[gadget.props.key] = {};\n
+            }\n
+            for (i = 0; i < result_list.length; i += 1) {\n
+                for (name in result_list[i]) {\n
+                    if (result_list[i].hasOwnProperty(name)) {\n
+                        content[name] = result_list[i][name];\n
+                    }\n
+                }\n
+            }\n
+            return result;\n
+        });\n
+    });\n
+})(window, rJS, RSVP, Handlebars, initGadgetMixin);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>4262</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/fieldset/index.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/fieldset/index.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..66c530435f854ce27832e798b1ef52fa37e72ecb
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/fieldset/index.html.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681764.69</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <meta name="viewport" content="width=device-width, initial-scale=1">\n
+    <title>Fieldset</title>\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/handlebars.min.js" type="text/javascript"></script>\n
+    <script src="../lib/jquery.js" type="text/javascript"></script>\n
+    <script src="../lib/jquerymobile.js" type="text/javascript"></script>\n
+\n
+    <script id="label-template" type="text/x-handlebars-template">\n
+      <label for="{{for}}">{{name}}</label>\n
+    </script>\n
+\n
+    <script src="../dream/mixin_gadget.js" type="text/javascript"></script>\n
+    <script src="fieldset.js" type="text/javascript"></script>\n
+  </head>\n
+  <body>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>825</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable.xml
new file mode 100644
index 0000000000000000000000000000000000000000..513192fe8c40145168d5583ca53ec6b092cd0b5e
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>handsontable</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/handsontable.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/handsontable.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f595f5e0ad648e8fa599f3a19a4cee5af840945b
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/handsontable.js.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681765.0</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>handsontable.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global jQuery, rJS, window, JSON, RSVP */\n
+(function(window, $, rJS, JSON, RSVP) {\n
+    "use strict";\n
+    rJS(window).declareMethod("render", function(content, options) {\n
+        var data = JSON.parse(content);\n
+        return this.getElement().push(function(element) {\n
+            $(element).find(".table-container").handsontable($.extend({\n
+                data: data,\n
+                stretchH: "all"\n
+            }, options || {}));\n
+        });\n
+    }).declareMethod("getData", function() {\n
+        return this.getElement().push(function(element) {\n
+            var data = $(element).find(".table-container").handsontable("getData");\n
+            return JSON.stringify(data);\n
+        });\n
+    }).declareMethod("startService", function() {\n
+        var gadget_element;\n
+        return this.getElement().push(function(element) {\n
+            gadget_element = element;\n
+            $(element).find(".table-container").handsontable("render");\n
+        }).push(function() {\n
+            // Infinite wait, until cancelled\n
+            return new RSVP.defer().promise;\n
+        }).push(undefined, function(error) {\n
+            $(gadget_element).find(".table-container").handsontable("destroy");\n
+            throw error;\n
+        });\n
+    });\n
+})(window, jQuery, rJS, JSON, RSVP);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1257</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/index.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/index.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..66cd56bb361fd7b8b045eba60396def8316680ef
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/index.html.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681765.14</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <link rel="stylesheet" href="../lib/handsontable.css">\n
+\n
+    <script src="../lib/jquery.js"></script>\n
+    <script src="../lib/rsvp.min.js"></script>\n
+    <script src="../lib/renderjs.min.js"></script>\n
+    <script src="../lib/handsontable.js"></script>\n
+\n
+    <script src="handsontable.js"></script>\n
+  </head>\n
+  <body>\n
+    <div class="table-container"></div>\n
+      \n
+      mmmh ?\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>455</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/test.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/test.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5333892582ce7fed037568a027d361b534068454
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/test.html.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681765.26</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>test.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <link rel="stylesheet" href="../lib/qunit.css">\n
+    \n
+    <script src="../lib/rsvp.min.js"></script>\n
+    <script src="../lib/renderjs.min.js"></script>\n
+    <script src="../lib/qunit.js"></script>\n
+    <script src="../lib/jquery.js"></script>\n
+    <script src="test.js"></script>\n
+  </head>\n
+  <body>\n
+    <div id="qunit"></div>\n
+    <div id="qunit-fixture"></div>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>438</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/test.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2b7bd8f268763eab3cd0016a4cae439619f4d0b5
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/handsontable/test.js.xml
@@ -0,0 +1,96 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681765.36</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global rJS, JSON, QUnit, jQuery*/\n
+(function(rJS, JSON, QUnit, $) {\n
+    "use strict";\n
+    var start = QUnit.start, stop = QUnit.stop, test = QUnit.test, equal = QUnit.equal, sample = JSON.stringify([ [ "row1", "data11", "data12", "data13" ], [ "row2", "data21", "data22", "data23" ], [ "row3", "data31", "data32", "data33" ] ]);\n
+    QUnit.config.testTimeout = 5e3;\n
+    rJS(window).ready(function(g) {\n
+        test("data output is equal to input", function() {\n
+            var hstable_gadget;\n
+            stop();\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                hstable_gadget = new_gadget;\n
+                return hstable_gadget.render(sample);\n
+            }).then(function() {\n
+                return hstable_gadget.getData();\n
+            }).then(function(data) {\n
+                equal(data, sample);\n
+            }).always(start);\n
+        });\n
+        test("the table is displayed", function() {\n
+            var hstable_gadget;\n
+            stop();\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                hstable_gadget = new_gadget;\n
+                return hstable_gadget.render(sample);\n
+            }).then(function() {\n
+                var rows = $("table tbody tr");\n
+                equal(rows.length, 3);\n
+                equal(rows[0].childNodes.length, 4);\n
+                equal(rows[0].childNodes[2].innerHTML, "data12");\n
+            }).always(start);\n
+        });\n
+        test("the gadget can be configured", function() {\n
+            var hstable_gadget;\n
+            stop();\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                hstable_gadget = new_gadget;\n
+                return hstable_gadget.render(sample, {\n
+                    minSpareRows: 1\n
+                });\n
+            }).then(function() {\n
+                var rows = $("table tbody tr");\n
+                // There is one spare row\n
+                equal(rows.length, 4);\n
+            }).then(function() {\n
+                return hstable_gadget.getData();\n
+            }).then(function(data) {\n
+                equal(data, JSON.stringify([ [ "row1", "data11", "data12", "data13" ], [ "row2", "data21", "data22", "data23" ], [ "row3", "data31", "data32", "data33" ], [ null, null, null, null ] ]));\n
+            }).always(start);\n
+        });\n
+    });\n
+})(rJS, JSON, QUnit, jQuery);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2588</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jio_bridge.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jio_bridge.xml
new file mode 100644
index 0000000000000000000000000000000000000000..736fba3cce9d4bdef335a638f0c1b1da6e739f9d
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jio_bridge.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>jio_bridge</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jio_bridge/index.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jio_bridge/index.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1e5ef10907ddba9cccc1969cfc2385403a661b22
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jio_bridge/index.html.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681765.77</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />\n
+    <meta name="viewport" content="width=device-width, user-scalable=no" />\n
+    <title>Jio Gadget</title>\n
+\n
+    <!-- renderjs -->\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/uritemplate.min.js" type="text/javascript"></script>\n
+    <script src="../lib/URI.js" type="text/javascript"></script>\n
+    <script src="../lib/jio.js" type="text/javascript"></script>\n
+    <!-- custom script -->\n
+    <script src="jiogadget.js" type="text/javascript"></script>\n
+\n
+  </head>\n
+  <body>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>641</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jio_bridge/jiogadget.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jio_bridge/jiogadget.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d75a25dd740be331ef81b63c003582ed1febba53
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jio_bridge/jiogadget.js.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681765.94</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jiogadget.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global rJS, jIO */\n
+(function(rJS, jIO) {\n
+    "use strict";\n
+    rJS(window).ready(function(gadget) {\n
+        // Initialize the gadget local parameters\n
+        gadget.state_parameter_dict = {};\n
+    }).declareMethod("createJio", function(jio_options) {\n
+        this.state_parameter_dict.jio_storage = jIO.createJIO(jio_options);\n
+    }).declareMethod("ajax", function() {\n
+        return jIO.util.ajax.apply(this, arguments);\n
+    }).declareMethod("allDocs", function() {\n
+        var storage = this.state_parameter_dict.jio_storage;\n
+        return storage.allDocs.apply(storage, arguments);\n
+    }).declareMethod("get", function() {\n
+        var storage = this.state_parameter_dict.jio_storage;\n
+        return storage.get.apply(storage, arguments);\n
+    }).declareMethod("remove", function() {\n
+        var storage = this.state_parameter_dict.jio_storage;\n
+        return storage.remove.apply(storage, arguments);\n
+    }).declareMethod("getAttachment", function() {\n
+        var storage = this.state_parameter_dict.jio_storage;\n
+        return storage.getAttachment.apply(storage, arguments).then(function(response) {\n
+            return jIO.util.readBlobAsText(response.data);\n
+        }).then(function(lala) {\n
+            return lala.target.result;\n
+        });\n
+    }).declareMethod("putAttachment", function() {\n
+        var storage = this.state_parameter_dict.jio_storage;\n
+        return storage.putAttachment.apply(storage, arguments);\n
+    }).declareMethod("post", function() {\n
+        // XXX set modified value\n
+        var storage = this.state_parameter_dict.jio_storage;\n
+        return storage.post.apply(storage, arguments);\n
+    });\n
+})(rJS, jIO);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1638</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb.xml
new file mode 100644
index 0000000000000000000000000000000000000000..3d1c9fa734b1ad11abed350f409576c65d3f9172
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>jsplumb</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/index.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/index.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f75188d27d6659e3043b4f0948940266672ece40
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/index.html.xml
@@ -0,0 +1,97 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17687388.65</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+     <link rel="stylesheet" href="../lib/jquery-ui.css">\n
+\n
+<!--    <link rel="stylesheet" href="../lib/jquerymobile.css">  -->\n
+    <link rel="stylesheet" href="jsplumb.css">\n
+\n
+    <script src="../lib/jquery.js"></script>\n
+    <script src="../lib/jquery-ui.js"></script>\n
+    <script src="../lib/jquerymobile.js"></script> \n
+<!--\n
+    <script src="../lib/rsvp.min.js"></script>\n
+    <script src="../lib/renderjs.min.js"></script>\n
+-->\n
+    <script src="../lib/jquery.jsplumb.js"></script>\n
+    <script src="../lib/handlebars.min.js"></script>\n
+\n
+    <script id="node-template" type="text/x-handlebars-template">\n
+      <div class="window {{class}}"\n
+           id="{{element_id}}"\n
+           title="{{title}}">\n
+        {{name}}\n
+        <div class="ep"></div>\n
+      </div>\n
+    </script>\n
+\n
+    <template id="popup-edit-template">\n
+      <div id="node-edit-popup" data-position-to="origin">\n
+        <div data-role="header" data-theme="a">\n
+          <h1 class="node_class">Node edition</h1>\n
+          <a href="#" data-rel="back" class="ui-btn ui-corner-all ui-shadow ui-btn-a ui-icon-delete ui-btn-icon-notext ui-btn-right">Close</a>\n
+        </div>\n
+        <br/>\n
+        <form class="ui-content">\n
+          <fieldset></fieldset>\n
+          <input type="button" value="Delete">\n
+          <input type="submit" value="Validate">\n
+        </form>\n
+      </div>\n
+    </template>\n
+\n
+    <script src="../dream/mixin_gadget.js"></script>\n
+    <script src="../dream/mixin_promise.js"></script>\n
+\n
+    <script src="jsplumb.js"></script>\n
+  </head>\n
+  <body>\n
+    <div id="main"></div>\n
+    <div class="dummy_window"></div>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1656</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/jsplumb.css.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/jsplumb.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e3fefce0d56785ecd87ea4e1cfac6d37d071eb6b
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/jsplumb.css.xml
@@ -0,0 +1,211 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17682995.33</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jsplumb.css</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/css</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>#main {\n
+    /* these two margins settings are here just to ensure that jsPlumb handles\n
+       margins properly.*/\n
+    position: relative;\n
+    margin:20px auto;\n
+    font-size: 80%;\n
+    border: 1px solid #999;\n
+    /* width: 100%; */\n
+    width: 600px;\n
+    height: 600px;\n
+    overflow: hidden;\n
+    border-radius: 10px;\n
+    background-color:#eaedef;\n
+    text-align: center;\n
+}\n
+\n
+.selected {\n
+    color:rgb(189, 11, 11) !important;\n
+}\n
+\n
+.window, .label {\n
+    background-color:white;\n
+    text-align:center;\n
+    z-index:23;\n
+    cursor:pointer;\n
+    box-shadow: 2px 2px 19px #aaa;\n
+    -o-box-shadow: 2px 2px 19px #aaa;\n
+    -webkit-box-shadow: 2px 2px 19px #aaa;\n
+    -moz-box-shadow: 2px 2px 19px #aaa;\n
+}\n
+\n
+path, ._jsPlumb_endpoint {\n
+    cursor:pointer;\n
+}\n
+\n
+._jsPlumb_endpoint_drop_allowed {\n
+    border: 4px solid #123456;\n
+    box-shadow: 6px 6px 19px #444;\n
+    -o-box-shadow: 6px 6px 19px #444;\n
+    -webkit-box-shadow: 6px 6px 19px #444;\n
+    -moz-box-shadow: 6px 6px 19px #444;\n
+}\n
+\n
+/* z index stuff */\n
+\n
+._jsPlumb_connector {\n
+    z-index:18;\n
+}\n
+\n
+._jsPlumb_endpoint {\n
+    z-index:19;\n
+}\n
+\n
+._jsPlumb_overlay {\n
+    z-index:23;\n
+}\n
+\n
+._jsPlumb_connector._jsPlumb_hover {\n
+    z-index:21 !important;\n
+}\n
+\n
+._jsPlumb_endpoint._jsPlumb_hover {\n
+    z-index:22 !important;\n
+}\n
+\n
+._jsPlumb_overlay {\n
+    border:1px solid #346789;\n
+    opacity:0.8;\n
+    filter:alpha(opacity=80);\n
+    background-color:white;\n
+    color:black;\n
+    font-family:helvetica;\n
+    padding:0.5em;\n
+}\n
+\n
+.Dream-Source, .Dream-BatchSource {\n
+    border: 1px solid #bbc;\n
+    background-color:#ffe;\n
+    background-image: linear-gradient(to bottom, #ffe 0%, #dde 100%);\n
+}\n
+\n
+.Dream-Machine, .Dream-MachineJobShop, .Dream-BatchScrapMachine, .Dream-MachineManagedJob, .Dream-MouldAssembly {\n
+    border: 1px solid #cbc;\n
+    background-color: #fef;\n
+    background-image: linear-gradient(to bottom, #fef 0%, #ede 100%);\n
+}\n
+\n
+.Dream-Queue, .Dream-QueueJobShop, .Dream-LineClearance, .Dream-QueueManagedJob, .Dream-ConditionalBuffer, .Dream-OrderDecomposition, .Dream-MouldAssemblyBuffer {\n
+    border: 1px solid #bcc;\n
+    background-color:#eff;\n
+    background-image: linear-gradient(to bottom, #eff 0%, #dee 100%);\n
+}\n
+\n
+.Dream-Exit, .Dream-ExitJobShop {\n
+    border: 1px solid #ccb;\n
+    background-color:#eef;\n
+    background-image: linear-gradient(to bottom, #eef 0%, #dde 100%);\n
+}\n
+\n
+.Dream-EventGenerator {\n
+    border: 1px solid #cba;\n
+    background-color:#fdc;\n
+    background-image: linear-gradient(to bottom, #fdc 0%, #ecb 100%);\n
+}\n
+\n
+.Dream-BatchDecomposition, .Dream-BatchDecompositionStartTime, .Dream-BatchReassembly {\n
+    border: 1px solid #bcb;\n
+    background-color:#dfd;\n
+    background-image: linear-gradient(to bottom, #dfd 0%, #cec 100%);\n
+}\n
+\n
+.Dream-Repairman {\n
+    border: 1px solid #cbb;\n
+    background-color:#fdd;\n
+    background-image: linear-gradient(to bottom, #fdd 0%, #dcc 100%);\n
+}\n
+\n
+.window, .dummy_window {\n
+    border:1px solid lightgray;\n
+    width:100px;\n
+    height:64px;\n
+    position:absolute;\n
+    color:black;\n
+    font-family:serif;\n
+    font-style:italic;\n
+    padding-top:0.9em;\n
+    font-size:0.9em;\n
+    cursor:move;\n
+    font-size:11px;\n
+    -webkit-transition:background-color 0.1s ease-in;\n
+    -moz-transition:background-color 0.1s ease-in;\n
+    transition:background-color 0.1s ease-in;\n
+    border-radius: 5px;\n
+}\n
+\n
+.window:hover {\n
+    background-color: #5c96bc;\n
+    background-image: none;\n
+    color:white;\n
+}\n
+\n
+.dummy_window {\n
+    position: absolute;\n
+    top: 0;\n
+    left: 0;\n
+    visibility: hidden;\n
+}\n
+\n
+.ep {\n
+    position:absolute;\n
+    bottom:37%;\n
+    right:5px;\n
+    width:1em;\n
+    height:1em;\n
+    background-color:orange;\n
+    cursor:pointer;\n
+    box-shadow: 0px 0px 2px black;\n
+    -webkit-transition:-webkit-box-shadow 0.25s ease-in;\n
+    -moz-transition:-moz-box-shadow 0.25s ease-in;\n
+    transition:box-shadow 0.25s ease-in;\n
+}\n
+\n
+._jsPlumb_source_hover, ._jsPlumb_target_hover, .dragHover {\n
+    background-color:#1e8151;\n
+    background-image: none;\n
+    color:white;\n
+}\n
+\n
+path {\n
+    cursor:pointer;\n
+}\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>3922</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/jsplumb.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/jsplumb.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..59ead5400a8a951e7c784af163f910b1e58c1c1e
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/jsplumb.js.xml
@@ -0,0 +1,610 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17687421.03</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jsplumb.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/* ===========================================================================\n
+ * Copyright 2013 Nexedi SA and Contributors\n
+ *\n
+ * This file is part of DREAM.\n
+ *\n
+ * DREAM is free software: you can redistribute it and/or modify\n
+ * it under the terms of the GNU Lesser General Public License as published by\n
+ * the Free Software Foundation, either version 3 of the License, or\n
+ * (at your option) any later version.\n
+ *\n
+ * DREAM is distributed in the hope that it will be useful,\n
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n
+ * GNU Lesser General Public License for more details.\n
+ *\n
+ * You should have received a copy of the GNU Lesser General Public License\n
+ * along with DREAM.  If not, see <http://www.gnu.org/licenses/>.\n
+ * ==========================================================================*/\n
+/*global RSVP, rJS, $, jsPlumb, Handlebars,\n
+  loopEventListener, promiseEventListener, DOMParser, confirm */\n
+/*jslint unparam: true todo: true */\n
+(function(RSVP, rJS, $, jsPlumb, Handlebars, loopEventListener, promiseEventListener, DOMParser) {\n
+    "use strict";\n
+    /* TODO:\n
+ * drop jquery ui dependency\n
+ * less dependancies ( promise event listner ? )\n
+ * document exposed css / jsplumb config\n
+ * no more handlebars\n
+ * auto springy layout\n
+ * drop zoom level\n
+ * edge edit popup on click\n
+ * rename draggable()\n
+ * somehow choose edge class on connect\n
+ */\n
+    /*jslint nomen: true */\n
+    var gadget_klass = rJS(window),\n
+    domParser = new DOMParser(),\n
+    node_template_source = gadget_klass.__template_element.getElementById("node-template").innerHTML,\n
+    node_template = Handlebars.compile(node_template_source),\n
+    popup_edit_template = gadget_klass.__template_element.getElementById("popup-edit-template");\n
+    \n
+    function loopJsplumbBind(gadget, type, callback) {\n
+        //////////////////////////\n
+        // Infinite event listener (promise is never resolved)\n
+        // eventListener is removed when promise is cancelled/rejected\n
+        //////////////////////////\n
+        var handle_event_callback, callback_promise, jsplumb_instance = gadget.props.jsplumb_instance;\n
+        function cancelResolver() {\n
+            if (callback_promise !== undefined && typeof callback_promise.cancel === "function") {\n
+                callback_promise.cancel();\n
+            }\n
+        }\n
+        function canceller() {\n
+            if (handle_event_callback !== undefined) {\n
+                jsplumb_instance.unbind(type);\n
+            }\n
+            cancelResolver();\n
+        }\n
+        function resolver(resolve, reject) {\n
+            handle_event_callback = function() {\n
+                var args = arguments;\n
+                cancelResolver();\n
+                callback_promise = new RSVP.Queue().push(function() {\n
+                    return callback.apply(jsplumb_instance, args);\n
+                }).push(undefined, function(error) {\n
+                    if (!(error instanceof RSVP.CancellationError)) {\n
+                        canceller();\n
+                        reject(error);\n
+                    }\n
+                });\n
+            };\n
+            jsplumb_instance.bind(type, handle_event_callback);\n
+        }\n
+        return new RSVP.Promise(resolver, canceller);\n
+    }\n
+    function getNodeId(gadget, element_id) {\n
+        // returns the ID of the node in the graph from its DOM element id\n
+        var node_id;\n
+        $.each(gadget.props.node_id_to_dom_element_id, function(k, v) {\n
+            if (v === element_id) {\n
+                node_id = k;\n
+                return false;\n
+            }\n
+        });\n
+        return node_id;\n
+    }\n
+    function generateNodeId(gadget, element) {\n
+        // Generate a node id\n
+        var n = 1, class_def = gadget.props.data.class_definition[element._class], id = class_def.short_id || element._class;\n
+        while (gadget.props.data.graph.node[id + n] !== undefined) {\n
+            n += 1;\n
+        }\n
+        return id + n;\n
+    }\n
+    function generateDomElementId(gadget_element) {\n
+        // Generate a probably unique DOM element ID.\n
+        var n = 1;\n
+        while ($(gadget_element).find("#DreamNode_" + n).length > 0) {\n
+            n += 1;\n
+        }\n
+        return "DreamNode_" + n;\n
+    }\n
+    function updateConnectionData(gadget, connection, remove, edge_data) {\n
+        if (remove) {\n
+            delete gadget.props.data.graph.edge[connection.id];\n
+        } else {\n
+            edge_data = edge_data || {\n
+                _class: "Dream.Edge"\n
+            };\n
+            edge_data.source = getNodeId(gadget, connection.sourceId);\n
+            edge_data.destination = getNodeId(gadget, connection.targetId);\n
+            gadget.props.data.graph.edge[connection.id] = edge_data;\n
+        }\n
+        gadget.notifyDataChanged();\n
+    }\n
+    function waitForConnection(gadget) {\n
+        loopJsplumbBind(gadget, "connection", function(info, originalEvent) {\n
+            updateConnectionData(gadget, info.connection);\n
+        });\n
+    }\n
+    function waitForConnectionDetached(gadget) {\n
+        loopJsplumbBind(gadget, "connectionDetached", function(info, originalEvent) {\n
+            updateConnectionData(gadget, info.connection, true);\n
+        });\n
+    }\n
+    function waitForConnectionClick(gadget) {\n
+        // TODO: dialog to edit connection properties\n
+        loopJsplumbBind(gadget, "click", function(connection) {\n
+            if (confirm("Delete connection ?")) {\n
+                gadget.props.jsplumb_instance.detach(connection);\n
+            }\n
+        });\n
+    }\n
+    function convertToAbsolutePosition(gadget, x, y) {\n
+        var zoom_level = gadget.props.zoom_level * 1.1111, canvas_size_x = $(gadget.props.main).width(), canvas_size_y = $(gadget.props.main).height(), size_x = $(gadget.props.element).find(".dummy_window").width() * zoom_level, size_y = $(gadget.props.element).find(".dummy_window").height() * zoom_level, top = Math.floor(y * (canvas_size_y - size_y)) + "px", left = Math.floor(x * (canvas_size_x - size_x)) + "px";\n
+        return [ left, top ];\n
+    }\n
+    function convertToRelativePosition(gadget, x, y) {\n
+        var zoom_level = gadget.props.zoom_level * 1.1111, canvas_size_x = $(gadget.props.main).width(), canvas_size_y = $(gadget.props.main).height(), size_x = $(gadget.props.element).find(".dummy_window").width() * zoom_level, size_y = $(gadget.props.element).find(".dummy_window").height() * zoom_level, top = Math.max(Math.min(y.replace("px", "") / (canvas_size_y - size_y), 1), 0), left = Math.max(Math.min(x.replace("px", "") / (canvas_size_x - size_x), 1), 0);\n
+        return [ left, top ];\n
+    }\n
+    function updateElementCoordinate(gadget, node_id, coordinate) {\n
+        var element_id = gadget.props.node_id_to_dom_element_id[node_id], element, relative_position;\n
+        if (coordinate === undefined) {\n
+            element = $(gadget.props.element).find("#" + element_id);\n
+            relative_position = convertToRelativePosition(gadget, element.css("left"), element.css("top"));\n
+            coordinate = {\n
+                left: relative_position[0],\n
+                top: relative_position[1]\n
+            };\n
+        }\n
+        gadget.props.data.graph.node[node_id].coordinate = coordinate;\n
+        gadget.notifyDataChanged();\n
+        return coordinate;\n
+    }\n
+    function draggable(gadget) {\n
+        var jsplumb_instance = gadget.props.jsplumb_instance, stop = function(element) {\n
+            updateElementCoordinate(gadget, getNodeId(gadget, element.target.id));\n
+        };\n
+        // XXX This function should only touch the node element that we just added.\n
+        jsplumb_instance.draggable(jsplumb_instance.getSelector(".window"), {\n
+            containment: "parent",\n
+            grid: [ 10, 10 ],\n
+            stop: stop\n
+        });\n
+        jsplumb_instance.makeSource(jsplumb_instance.getSelector(".window"), {\n
+            filter: ".ep",\n
+            anchor: "Continuous",\n
+            connector: [ "StateMachine", {\n
+                curviness: 20\n
+            } ],\n
+            connectorStyle: {\n
+                strokeStyle: "#5c96bc",\n
+                lineWidth: 2,\n
+                outlineColor: "transparent",\n
+                outlineWidth: 4\n
+            }\n
+        });\n
+        jsplumb_instance.makeTarget(jsplumb_instance.getSelector(".window"), {\n
+            dropOptions: {\n
+                hoverClass: "dragHover"\n
+            },\n
+            anchor: "Continuous"\n
+        });\n
+    }\n
+    function updateNodeStyle(gadget, element_id) {\n
+        // Update node size according to the zoom level\n
+        // XXX does nothing for now\n
+        var zoom_level = gadget.props.zoom_level * 1.1111, element = $(gadget.props.element).find("#" + element_id), new_value;\n
+        $.each(gadget.props.style_attr_list, function(i, j) {\n
+            new_value = $(gadget.props.element).find(".dummy_window").css(j).replace("px", "") * zoom_level + "px";\n
+            element.css(j, new_value);\n
+        });\n
+    }\n
+    // function redraw(gadget) {\n
+    //   var coordinates = gadget.props.preference_container.coordinates || {},\n
+    //     absolute_position,\n
+    //     element;\n
+    //   $.each(coordinates, function (node_id, v) {\n
+    //     absolute_position = convertToAbsolutePosition(\n
+    //       gadget,\n
+    //       v.left,\n
+    //       v.top\n
+    //     );\n
+    //     element = $(gadget.props.element).find(\n
+    //       \'#\' + gadget.props.node_id_to_dom_element_id[node_id];\n
+    //     );\n
+    //     element.css(\'top\', absolute_position[1]);\n
+    //     element.css(\'left\', absolute_position[0]);\n
+    //     gadget.props.jsplumb_instance.repaint(element);\n
+    //   });\n
+    // }\n
+    // function positionGraph(gadget) {\n
+    //   $.ajax(\n
+    //     \'/positionGraph\',\n
+    //     {\n
+    //       data: JSON.stringify(getData()),\n
+    //       contentType: \'application/json\',\n
+    //       type: \'POST\',\n
+    //       success: function (data, textStatus, jqXHR) {\n
+    //         $.each(data, function (node, pos) {\n
+    //           convertToAbsolutePosition(\n
+    //             gadget,\n
+    //             pos.left,\n
+    //             pos.top\n
+    //           );\n
+    //           updateElementCoordinate(gadget, node, {\n
+    //             top: pos.top,\n
+    //             left: pos.left\n
+    //           });\n
+    //         });\n
+    //         redraw(gadget);\n
+    //       }\n
+    //     }\n
+    //   );\n
+    // }\n
+    function removeElement(gadget, node_id) {\n
+        var element_id = gadget.props.node_id_to_dom_element_id[node_id];\n
+        gadget.props.jsplumb_instance.removeAllEndpoints($(gadget.props.element).find("#" + element_id));\n
+        $(gadget.props.element).find("#" + element_id).remove();\n
+        delete gadget.props.data.graph.node[node_id];\n
+        $.each(gadget.props.data.graph.edge, function(k, v) {\n
+            if (node_id === v.source || node_id === v.destination) {\n
+                delete gadget.props.data.graph.edge[k];\n
+            }\n
+        });\n
+        gadget.notifyDataChanged();\n
+    }\n
+    function updateElementData(gadget, node_id, data) {\n
+        var element_id = gadget.props.node_id_to_dom_element_id[node_id], new_id = data.id;\n
+        if (data.data.name) {\n
+            $(gadget.props.element).find("#" + element_id).text(data.data.name).attr("title", data.data.name).append(\'<div class="ep"></div></div>\');\n
+            gadget.props.data.graph.node[node_id].name = data.data.name;\n
+        }\n
+        delete data.id;\n
+        $.extend(gadget.props.data.graph.node[node_id], data.data);\n
+        if (new_id && new_id !== node_id) {\n
+            gadget.props.data.graph.node[new_id] = gadget.props.data.graph.node[node_id];\n
+            delete gadget.props.data.graph.node[node_id];\n
+            gadget.props.node_id_to_dom_element_id[new_id] = gadget.props.node_id_to_dom_element_id[node_id];\n
+            delete gadget.props.node_id_to_dom_element_id[node_id];\n
+            delete gadget.props.data.graph.node[new_id].id;\n
+            $.each(gadget.props.data.graph.edge, function(k, v) {\n
+                if (v.source === node_id) {\n
+                    v.source = new_id;\n
+                }\n
+                if (v.destination === node_id) {\n
+                    v.destination = new_id;\n
+                }\n
+            });\n
+        }\n
+        gadget.notifyDataChanged();\n
+    }\n
+    function addEdge(gadget, edge_id, edge_data) {\n
+        var overlays = [], connection;\n
+        if (edge_data.name) {\n
+            overlays = [ [ "Label", {\n
+                cssClass: "l1 component label",\n
+                label: edge_data.name\n
+            } ] ];\n
+        }\n
+        if (gadget.props.data.graph.node[edge_data.source] === undefined) {\n
+            throw new Error("Edge Source " + edge_data.source + " does not exist");\n
+        }\n
+        if (gadget.props.data.graph.node[edge_data.source] === undefined) {\n
+            throw new Error("Edge Destination " + edge_data.source + " does not exist");\n
+        }\n
+        // If an edge has this data:\n
+        // { _class: \'Edge\', \n
+        //   source: \'N1\',\n
+        //   destination: \'N2\',\n
+        //   jsplumb_source_endpoint: \'BottomCenter\',\n
+        //   jsplumb_destination_endpoint: \'LeftMiddle\',\n
+        //   jsplumb_connector: \'Flowchart\' }\n
+        // Then it is rendered using a flowchart connector. The difficulty is that\n
+        // jsplumb does not let you configure the connector type on the edge, but\n
+        // on the source endpoint. One solution seem to create all types of\n
+        // endpoints on nodes.\n
+        if (edge_data.jsplumb_connector === "Flowchart") {\n
+            connection = gadget.props.jsplumb_instance.connect({\n
+                uuids: [ edge_data.source + ".flowChart" + edge_data.jsplumb_source_endpoint, edge_data.destination + ".flowChart" + edge_data.jsplumb_destination_endpoint ],\n
+                overlays: overlays\n
+            });\n
+        } else {\n
+            connection = gadget.props.jsplumb_instance.connect({\n
+                source: gadget.props.node_id_to_dom_element_id[edge_data.source],\n
+                target: gadget.props.node_id_to_dom_element_id[edge_data.destination],\n
+                Connector: [ "Bezier", {\n
+                    curviness: 75\n
+                } ],\n
+                overlays: overlays\n
+            });\n
+        }\n
+        // jsplumb assigned an id, but we are controlling ids ourselves.\n
+        connection.id = edge_id;\n
+    }\n
+    function expandSchema(class_definition, full_schema) {\n
+        // minimal expanding of json schema, supports merging allOf and $ref\n
+        // references\n
+        // TODO: check for a library that would provide full support\n
+        var property, referenced, i, expanded_class_definition = {\n
+            properties: class_definition.properties || {}\n
+        };\n
+        if (class_definition.allOf) {\n
+            for (i = 0; i < class_definition.allOf.length; i += 1) {\n
+                referenced = class_definition.allOf[i];\n
+                if (referenced.$ref) {\n
+                    referenced = expandSchema(full_schema.class_definition[referenced.$ref.substr(1, referenced.$ref.length)], full_schema);\n
+                }\n
+                if (referenced.properties) {\n
+                    for (property in referenced.properties) {\n
+                        if (referenced.properties.hasOwnProperty(property)) {\n
+                            if (referenced.properties[property].type) {\n
+                                expanded_class_definition.properties[property] = referenced.properties[property];\n
+                            }\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        }\n
+        return expanded_class_definition;\n
+    }\n
+    function openNodeDialog(gadget, element) {\n
+        var node_id = getNodeId(gadget, element.id), node_data = gadget.props.data.graph.node[node_id], node_edit_popup = $(gadget.props.element).find("#popup-edit-template"), schema, fieldset_element, delete_promise;\n
+        // If we have no definition for this, we do not allow edition.\n
+        if (gadget.props.data.class_definition[node_data._class] === undefined) {\n
+            return;\n
+        }\n
+        schema = expandSchema(gadget.props.data.class_definition[node_data._class], gadget.props.data);\n
+        if (node_edit_popup.length !== 0) {\n
+            node_edit_popup.remove();\n
+        }\n
+        gadget.props.element.appendChild(document.importNode(popup_edit_template.content, true).children[0]);\n
+        node_edit_popup = $(gadget.props.element).find("#node-edit-popup");\n
+        // Set the name of the popup to the node class\n
+        node_edit_popup.find(".node_class").text(node_data._class);\n
+        fieldset_element = node_edit_popup.find("fieldset")[0];\n
+        node_edit_popup.popup();\n
+        node_data.id = node_id;\n
+        // XXX\n
+        function save_promise(fieldset_gadget, node_id) {\n
+            return RSVP.Queue().push(function() {\n
+                return promiseEventListener(node_edit_popup.find("form")[0], "submit", false);\n
+            }).push(function(evt) {\n
+                var data = {\n
+                    // XXX id should not be handled differently ...\n
+                    id: $(evt.target[1]).val(),\n
+                    data: {}\n
+                };\n
+                return fieldset_gadget.getContent().then(function(r) {\n
+                    $.extend(data.data, r);\n
+                    updateElementData(gadget, node_id, data);\n
+                });\n
+            });\n
+        }\n
+        delete_promise = new RSVP.Queue().push(function() {\n
+            return promiseEventListener(node_edit_popup.find("form [type=\'button\']")[0], "click", false);\n
+        }).push(function() {\n
+            return removeElement(gadget, node_id);\n
+        });\n
+        return gadget.declareGadget("../fieldset/index.html", {\n
+            element: fieldset_element,\n
+            scope: "fieldset"\n
+        }).push(function(fieldset_gadget) {\n
+            return RSVP.all([ fieldset_gadget, fieldset_gadget.render({\n
+                value: node_data,\n
+                property_definition: schema\n
+            }, node_id) ]);\n
+        }).push(function(fieldset_gadget) {\n
+            node_edit_popup.enhanceWithin();\n
+            node_edit_popup.popup("open");\n
+            return fieldset_gadget[0];\n
+        }).push(function(fieldset_gadget) {\n
+            // Expose the dialog handling promise so that we can wait for it in\n
+            // test.\n
+            gadget.props.dialog_promise = RSVP.any([ save_promise(fieldset_gadget, node_id), delete_promise ]);\n
+            return gadget.props.dialog_promise;\n
+        }).push(function() {\n
+            node_edit_popup.popup("close");\n
+            node_edit_popup.remove();\n
+            delete gadget.props.dialog_promise;\n
+        });\n
+    }\n
+    function waitForNodeClick(gadget, node) {\n
+        gadget.props.nodes_click_monitor.monitor(loopEventListener(node, "dblclick", false, openNodeDialog.bind(null, gadget, node)));\n
+    }\n
+    function addNode(gadget, node_id, node_data) {\n
+        var render_element = $(gadget.props.main), class_definition = gadget.props.data.class_definition[node_data._class], coordinate = node_data.coordinate, dom_element_id, box, absolute_position, domElement;\n
+        dom_element_id = generateDomElementId(gadget.props.element);\n
+        gadget.props.node_id_to_dom_element_id[node_id] = dom_element_id;\n
+        node_data.name = node_data.name || class_definition.name;\n
+        gadget.props.data.graph.node[node_id] = node_data;\n
+        if (coordinate === undefined) {\n
+            coordinate = {\n
+                top: 0,\n
+                left: 0\n
+            };\n
+        }\n
+        node_data.coordinate = updateElementCoordinate(gadget, node_id, coordinate);\n
+        // XXX make node template an option, or use CSS from class_definition\n
+        /*jslint nomen: true*/\n
+        domElement = domParser.parseFromString(node_template({\n
+            "class": node_data._class.replace(".", "-"),\n
+            element_id: dom_element_id,\n
+            title: node_data.name || node_data.id,\n
+            name: node_data.name || node_data.id\n
+        }), "text/html").querySelector(".window");\n
+        render_element.append(domElement);\n
+        waitForNodeClick(gadget, domElement);\n
+        box = $(gadget.props.element).find("#" + dom_element_id);\n
+        absolute_position = convertToAbsolutePosition(gadget, coordinate.left, coordinate.top);\n
+        box.css("top", absolute_position[1]);\n
+        box.css("left", absolute_position[0]);\n
+        updateNodeStyle(gadget, dom_element_id);\n
+        draggable(gadget);\n
+        // XXX make only this element draggable.\n
+        // Add some flowchart endpoints\n
+        // TODO: add them all !\n
+        gadget.props.jsplumb_instance.addEndpoint(dom_element_id, {\n
+            isSource: true,\n
+            maxConnections: -1,\n
+            connector: [ "Flowchart", {\n
+                stub: [ 40, 60 ],\n
+                gap: 10,\n
+                cornerRadius: 5,\n
+                alwaysRespectStubs: true\n
+            } ]\n
+        }, {\n
+            anchor: "BottomCenter",\n
+            uuid: node_id + ".flowchartBottomCenter"\n
+        });\n
+        gadget.props.jsplumb_instance.addEndpoint(dom_element_id, {\n
+            isTarget: true,\n
+            maxConnections: -1\n
+        }, {\n
+            anchor: "LeftMiddle",\n
+            uuid: node_id + ".flowChartLeftMiddle"\n
+        });\n
+        gadget.notifyDataChanged();\n
+    }\n
+    function waitForDrop(gadget) {\n
+        var callback;\n
+        function canceller() {\n
+            if (callback !== undefined) {\n
+                gadget.props.main.removeEventListener("drop", callback, false);\n
+            }\n
+        }\n
+        /*jslint unparam: true*/\n
+        function resolver(resolve, reject) {\n
+            callback = function(evt) {\n
+                try {\n
+                    var class_name = JSON.parse(evt.dataTransfer.getData("application/json")), offset = $(gadget.props.main).offset(), relative_position = convertToRelativePosition(gadget, evt.clientX - offset.left + "px", evt.clientY - offset.top + "px");\n
+                    addNode(gadget, generateNodeId(gadget, {\n
+                        _class: class_name\n
+                    }), {\n
+                        coordinate: {\n
+                            left: relative_position[0],\n
+                            top: relative_position[1]\n
+                        },\n
+                        _class: class_name\n
+                    });\n
+                } catch (e) {\n
+                    reject(e);\n
+                }\n
+            };\n
+            gadget.props.main.addEventListener("drop", callback, false);\n
+        }\n
+        return new RSVP.all([ // loopEventListener adds an event listener that will prevent default for\n
+        // dragover\n
+        loopEventListener(gadget.props.main, "dragover", false, function() {\n
+            return undefined;\n
+        }), RSVP.Promise(resolver, canceller) ]);\n
+    }\n
+    gadget_klass.ready(function(g) {\n
+        g.props = {};\n
+        g.props.node_id_to_dom_element_id = {};\n
+        g.props.zoom_level = 1;\n
+        g.props.style_attr_list = [ "width", "height", "padding-top", "line-height" ];\n
+        g.getElement().then(function(element) {\n
+            g.props.element = element;\n
+        });\n
+    }).declareAcquiredMethod("notifyDataChanged", "notifyDataChanged").declareMethod("render", function(data) {\n
+        var gadget = this;\n
+        this.props.data = {};\n
+        console.log("render", data);\n
+        if (data.value) {\n
+          // Gadget embedded in ERP5\n
+          this.props.erp5_key = data.key;\n
+          data = data.value;\n
+        }\n
+        \n
+        if (data) {\n
+          this.props.data = JSON.parse(data);\n
+          // load the data\n
+          $.each(this.props.data.graph.node, function(key, value) {\n
+              addNode(gadget, key, value);\n
+          });\n
+          $.each(this.props.data.graph.edge, function(key, value) {\n
+              addEdge(gadget, key, value);\n
+          });\n
+        }\n
+        this.props.jsplumb_instance = jsPlumb.getInstance();\n
+    }).declareMethod("getContent", function() {\n
+        if (this.props.erp5_key) {\n
+          // ERP5\n
+          return JSON.stringify({key: this.props.erp5_key, value: this.props.data});\n
+        }\n
+        return JSON.stringify(this.props.data);\n
+    }).declareMethod("startService", function() {\n
+      // no more needed, see below\n
+    }).declareService(function() {\n
+        var gadget = this, jsplumb_instance;\n
+        this.props.jsplumb_instance = jsPlumb.getInstance();\n
+        jsplumb_instance= gadget.props.jsplumb_instance;\n
+        this.props.main = this.props.element.querySelector("#main");\n
+        jsplumb_instance.setRenderMode(jsplumb_instance.SVG);\n
+        jsplumb_instance.importDefaults({\n
+            HoverPaintStyle: {\n
+                strokeStyle: "#1e8151",\n
+                lineWidth: 2\n
+            },\n
+            Endpoint: [ "Dot", {\n
+                radius: 2\n
+            } ],\n
+            ConnectionOverlays: [ [ "Arrow", {\n
+                location: 1,\n
+                id: "arrow",\n
+                length: 14,\n
+                foldback: .8\n
+            } ] ],\n
+            Container: this.props.main\n
+        });\n
+        draggable(gadget);\n
+        this.props.nodes_click_monitor = RSVP.Monitor();\n
+                console.log(this.props.data);\n
+        if (this.props.data) {\n
+          // load the data\n
+          $.each(this.props.data.graph.node, function(key, value) {\n
+              addNode(gadget, key, value);\n
+          });\n
+          $.each(this.props.data.graph.edge, function(key, value) {\n
+              addEdge(gadget, key, value);\n
+          });\n
+        }\n
+        return RSVP.all([ waitForDrop(gadget), waitForConnection(gadget), waitForConnectionDetached(gadget), waitForConnectionClick(gadget), gadget.props.nodes_click_monitor ]);\n
+    });\n
+})(RSVP, rJS, $, jsPlumb, Handlebars, loopEventListener, promiseEventListener, DOMParser);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>25449</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/test.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/test.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1d646c2e3e5c3b1d9428378e2db74e5031786747
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/test.html.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681766.24</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>test.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <link rel="stylesheet" href="../lib/qunit.css">\n
+    \n
+    <script src="../lib/rsvp.min.js"></script>\n
+    <script src="../lib/renderjs.min.js"></script>\n
+    <script src="../lib/qunit.js"></script>\n
+    <script src="../lib/jquery.js"></script>\n
+    <script src="../lib/jquery.simulate.js"></script>\n
+    <script src="test.js"></script>\n
+  </head>\n
+  <body>\n
+    <div id="qunit"></div>\n
+    <div id="qunit-fixture"></div>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>492</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/test.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/test.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..0ec459de67ea44dc9e0ecc7b98c0a608d2eb954f
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/jsplumb/test.js.xml
@@ -0,0 +1,573 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681766.37</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>test.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global rJS, JSON, QUnit, jQuery, RSVP, console, setTimeout*/\n
+(function(rJS, JSON, QUnit, RSVP, $) {\n
+    "use strict";\n
+    var start = QUnit.start, stop = QUnit.stop, test = QUnit.test, equal = QUnit.equal, ok = QUnit.ok, error_handler = function(e) {\n
+        console.error(e);\n
+        ok(false, e);\n
+    }, sample_class_definition = {\n
+        edge: {\n
+            description: "Base definition for edge",\n
+            properties: {\n
+                _class: {\n
+                    type: "string"\n
+                },\n
+                destination: {\n
+                    type: "string"\n
+                },\n
+                name: {\n
+                    type: "string"\n
+                },\n
+                required: [ "name", "_class", "source", "destination" ],\n
+                source: {\n
+                    type: "string"\n
+                }\n
+            },\n
+            type: "object"\n
+        },\n
+        "Example.Edge": {\n
+            _class: "edge",\n
+            allOf: [ {\n
+                $ref: "#edge"\n
+            }, {\n
+                properties: {\n
+                    color: {\n
+                        "enum": [ "red", "green", "blue" ]\n
+                    }\n
+                }\n
+            } ],\n
+            description: "An example edge with a color property"\n
+        },\n
+        "Example.Node": {\n
+            _class: "node",\n
+            allOf: [ {\n
+                $ref: "#node"\n
+            }, {\n
+                properties: {\n
+                    shape: {\n
+                        type: "string"\n
+                    }\n
+                }\n
+            } ],\n
+            description: "An example node with a shape property"\n
+        },\n
+        node: {\n
+            description: "Base definition for node",\n
+            properties: {\n
+                _class: {\n
+                    type: "string"\n
+                },\n
+                coordinate: {\n
+                    properties: {\n
+                        left: "number",\n
+                        top: "number"\n
+                    },\n
+                    type: "object"\n
+                },\n
+                name: {\n
+                    type: "string"\n
+                },\n
+                required: [ "name", "_class" ]\n
+            },\n
+            type: "object"\n
+        }\n
+    }, sample_graph = {\n
+        edge: {\n
+            edge1: {\n
+                _class: "Example.Edge",\n
+                source: "N1",\n
+                destination: "N2",\n
+                color: "blue"\n
+            }\n
+        },\n
+        node: {\n
+            N1: {\n
+                _class: "Example.Node",\n
+                name: "Node 1",\n
+                coordinate: {\n
+                    top: 0,\n
+                    left: 0\n
+                },\n
+                shape: "square"\n
+            },\n
+            N2: {\n
+                _class: "Example.Node",\n
+                name: "Node 2",\n
+                shape: "circle"\n
+            }\n
+        }\n
+    }, sample_graph_not_connected = {\n
+        edge: {},\n
+        node: {\n
+            N1: {\n
+                _class: "Example.Node",\n
+                name: "Node 1",\n
+                shape: "square"\n
+            },\n
+            N2: {\n
+                _class: "Example.Node",\n
+                name: "Node 2",\n
+                shape: "circle"\n
+            }\n
+        }\n
+    }, sample_data_graph = JSON.stringify({\n
+        class_definition: sample_class_definition,\n
+        graph: sample_graph\n
+    }), sample_data_graph_not_connected = JSON.stringify({\n
+        class_definition: sample_class_definition,\n
+        graph: sample_graph_not_connected\n
+    }), sample_data_empty_graph = JSON.stringify({\n
+        class_definition: sample_class_definition,\n
+        graph: {\n
+            node: {},\n
+            edge: {}\n
+        }\n
+    });\n
+    QUnit.config.testTimeout = 5e3;\n
+    rJS(window).ready(function(g) {\n
+        test("Sample graph can be loaded and output is equal to input", function() {\n
+            var jsplumb_gadget;\n
+            stop();\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                jsplumb_gadget = new_gadget;\n
+                return jsplumb_gadget.render(sample_data_graph);\n
+            }).then(function() {\n
+                return jsplumb_gadget.getContent();\n
+            }).then(function(content) {\n
+                equal(content, sample_data_graph);\n
+            }).fail(error_handler).always(start);\n
+        });\n
+        test("New node can be drag & dropped", function() {\n
+            var jsplumb_gadget;\n
+            stop();\n
+            function runTest() {\n
+                // XXX here I used getContent to have a promise, but there must be a\n
+                // more elegant way.\n
+                return jsplumb_gadget.getContent().then(function() {\n
+                    // fake a drop event\n
+                    var e = new Event("drop");\n
+                    e.dataTransfer = {\n
+                        getData: function(type) {\n
+                            // make sure we are called properly\n
+                            equal("application/json", type, "The drag&dropped element must have data type application/json");\n
+                            return JSON.stringify("Example.Node");\n
+                        }\n
+                    };\n
+                    jsplumb_gadget.props.main.dispatchEvent(e);\n
+                }).then(function() {\n
+                    return jsplumb_gadget.getContent();\n
+                }).then(function(content) {\n
+                    var node, graph = JSON.parse(content).graph;\n
+                    equal(1, Object.keys(graph.node).length);\n
+                    node = graph.node[Object.keys(graph.node)[0]];\n
+                    equal("Example.Node", node._class);\n
+                });\n
+            }\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                jsplumb_gadget = new_gadget;\n
+                jsplumb_gadget.render(sample_data_empty_graph);\n
+            }).then(function() {\n
+                return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);\n
+            }).fail(error_handler).always(start);\n
+        });\n
+        test("Node can be dragged", function() {\n
+            var jsplumb_gadget;\n
+            stop();\n
+            function runTest() {\n
+                return jsplumb_gadget.getContent().then(function() {\n
+                    // 100 and 60 are about 10% of the #main div ( set by css, so this\n
+                    // might change )\n
+                    $("div[title=\'Node 1\']").simulate("drag", {\n
+                        dx: 100,\n
+                        dy: 60\n
+                    });\n
+                }).then(function() {\n
+                    return jsplumb_gadget.getContent();\n
+                }).then(function(content) {\n
+                    var graph = JSON.parse(content).graph, node_coordinate = graph.node.N1.coordinate;\n
+                    // Since original coordinates where 0,0 we are now about 0.1,0.1\n
+                    // as we moved 10%\n
+                    ok(node_coordinate.top - .1 < .1, "Top is ok");\n
+                    ok(node_coordinate.left - .1 < .1, "Left is ok");\n
+                });\n
+            }\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                jsplumb_gadget = new_gadget;\n
+                jsplumb_gadget.render(sample_data_graph);\n
+            }).then(function() {\n
+                return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);\n
+            }).fail(error_handler).always(start);\n
+        });\n
+        test("Node properties can be edited", function() {\n
+            var jsplumb_gadget;\n
+            stop();\n
+            function runTest() {\n
+                return jsplumb_gadget.getContent().then(function() {\n
+                    // click on a node to see display the popup\n
+                    $("div[title=\'Node 1\']").simulate("dblclick");\n
+                    // Promises that handle the dialog actions are not available\n
+                    // immediately after clicking.\n
+                    var promise = RSVP.Promise(function(resolve) {\n
+                        var fillDialog = function() {\n
+                            if (!jsplumb_gadget.props.dialog_promise) {\n
+                                // Dialog not ready. Let\'s retry later.\n
+                                // XXX this condition is actually incorrect. We need to wait\n
+                                // for the event listener to have been registered for the\n
+                                // dialog buttons. This setTimeout is good enough for now.\n
+                                return setTimeout(fillDialog, 1e3);\n
+                            }\n
+                            // check displayed values\n
+                            equal($("input[name=\'id\']").val(), "N1");\n
+                            equal($("input[name=\'name\']").val(), "Node 1");\n
+                            equal($("input[name=\'shape\']").val(), "square");\n
+                            // change the name\n
+                            $("input[name=\'name\']").val("Modified Name");\n
+                            equal(1, $("input[value=\'Validate\']").length, "There should be one validate button");\n
+                            // and save\n
+                            $("input[value=\'Validate\']").click();\n
+                            // resolve our test promise once the dialog handling promise is\n
+                            // finished.\n
+                            jsplumb_gadget.props.dialog_promise.then(resolve);\n
+                        };\n
+                        fillDialog();\n
+                    });\n
+                    return promise.then(function() {\n
+                        return jsplumb_gadget.getContent().then(function(content) {\n
+                            var graph = JSON.parse(content).graph, node = graph.node.N1;\n
+                            equal("Modified Name", node.name, "Data is modified");\n
+                            equal("Modified Name", $("div#" + jsplumb_gadget.props.node_id_to_dom_element_id.N1).text(), "DOM is modified");\n
+                            equal(1, $("div[title=\'Modified Name\']").length, "DOM title attribute is modified");\n
+                        });\n
+                    });\n
+                });\n
+            }\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                jsplumb_gadget = new_gadget;\n
+                jsplumb_gadget.render(sample_data_graph);\n
+            }).then(function() {\n
+                return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);\n
+            }).fail(error_handler).always(start);\n
+        });\n
+        test("Node can be connected", function() {\n
+            var jsplumb_gadget;\n
+            stop();\n
+            function runTest() {\n
+                return jsplumb_gadget.getContent().then(function(content) {\n
+                    var node1 = jsplumb_gadget.props.main.querySelector("div[title=\'Node 1\']"), node2 = jsplumb_gadget.props.main.querySelector("div[title=\'Node 2\']");\n
+                    equal(0, Object.keys(JSON.parse(content).graph.edge).length, "There are no edge at the beginning");\n
+                    jsplumb_gadget.props.jsplumb_instance.connect({\n
+                        source: node1.id,\n
+                        target: node2.id\n
+                    });\n
+                }).then(function() {\n
+                    return jsplumb_gadget.getContent();\n
+                }).then(function(content) {\n
+                    var edge, graph = JSON.parse(content).graph;\n
+                    equal(2, Object.keys(graph.node).length, "We still have 2 nodes");\n
+                    equal(1, Object.keys(graph.edge).length, "We have 1 edge");\n
+                    edge = graph.edge[Object.keys(graph.edge)[0]];\n
+                    // XXX how edge class would be set ? the first one from schema ?\n
+                    //equal("Example.Edge", edge._class, "Edge class is correct");\n
+                    equal("N1", edge.source, "edge source is correct");\n
+                    equal("N2", edge.destination, "edge destination is correct");\n
+                });\n
+            }\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                jsplumb_gadget = new_gadget;\n
+                jsplumb_gadget.render(sample_data_graph_not_connected);\n
+            }).then(function() {\n
+                return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);\n
+            }).fail(error_handler).always(start);\n
+        });\n
+        test("Node can be deleted", function() {\n
+            var jsplumb_gadget;\n
+            stop();\n
+            function runTest() {\n
+                return jsplumb_gadget.getContent().then(function() {\n
+                    equal(1, $("div[title=\'Node 1\']").length, "node 1 is visible");\n
+                    equal(1, $("._jsPlumb_connector").length, "there is 1 connection");\n
+                    // click on node 1 to see display the popup\n
+                    $("div[title=\'Node 1\']").simulate("dblclick");\n
+                    // Promises that handle the dialog actions are not available\n
+                    // immediately after clicking.\n
+                    var promise = RSVP.Promise(function(resolve) {\n
+                        var waitForDialogAndDelete = function() {\n
+                            if (!jsplumb_gadget.props.dialog_promise) {\n
+                                // Dialog not ready. Let\'s retry later.\n
+                                // XXX this condition is actually incorrect. We need to wait\n
+                                // for the event listener to have been registered for the\n
+                                // dialog buttons. This setTimeout is good enough for now.\n
+                                return setTimeout(waitForDialogAndDelete, 1e3);\n
+                            }\n
+                            equal(1, $("input[value=\'Delete\']").length, "There should be one delete button");\n
+                            $("input[value=\'Delete\']").click();\n
+                            // resolve our test promise once the dialog handling promise is\n
+                            // finished.\n
+                            jsplumb_gadget.props.dialog_promise.then(resolve);\n
+                        };\n
+                        waitForDialogAndDelete();\n
+                    });\n
+                    return promise.then(function() {\n
+                        return jsplumb_gadget.getContent().then(function(content) {\n
+                            var graph = JSON.parse(content).graph;\n
+                            equal(1, Object.keys(graph.node).length, "node is removed from data");\n
+                            equal(0, Object.keys(graph.edge).length, "edge referencing this node is also removed");\n
+                            equal(0, $("div[title=\'Node 1\']").length, "DOM element for node is removed");\n
+                            equal(0, $("._jsPlumb_connector").length, "DOM element for edge is removed");\n
+                        });\n
+                    });\n
+                });\n
+            }\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                jsplumb_gadget = new_gadget;\n
+                jsplumb_gadget.render(sample_data_graph);\n
+            }).then(function() {\n
+                return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);\n
+            }).fail(error_handler).always(start);\n
+        });\n
+        test("Node id can be changed (connections are updated and node" + " can be edited afterwards)", function() {\n
+            var jsplumb_gadget;\n
+            stop();\n
+            function runTest() {\n
+                return jsplumb_gadget.getContent().then(function() {\n
+                    // click on a node to see display the popup\n
+                    $("div[title=\'Node 1\']").simulate("dblclick");\n
+                    // Promises that handle the dialog actions are not available\n
+                    // immediately after clicking.\n
+                    var promise = RSVP.Promise(function(resolve) {\n
+                        var fillDialog = function() {\n
+                            if (!jsplumb_gadget.props.dialog_promise) {\n
+                                // Dialog not ready. Let\'s retry later.\n
+                                // XXX this condition is actually incorrect. We need to wait\n
+                                // for the event listener to have been registered for the\n
+                                // dialog buttons. This setTimeout is good enough for now.\n
+                                return setTimeout(fillDialog, 1e3);\n
+                            }\n
+                            equal($("input[name=\'id\']").val(), "N1");\n
+                            // change the id\n
+                            $("input[name=\'id\']").val("N1b");\n
+                            equal(1, $("input[value=\'Validate\']").length, "There should be one validate button");\n
+                            $("input[value=\'Validate\']").click();\n
+                            // resolve our test promise once the dialog handling promise is\n
+                            // finished.\n
+                            jsplumb_gadget.props.dialog_promise.then(resolve);\n
+                        };\n
+                        fillDialog();\n
+                    });\n
+                    return promise.then(function() {\n
+                        return jsplumb_gadget.getContent().then(function(content) {\n
+                            var graph = JSON.parse(content).graph;\n
+                            equal(2, Object.keys(graph.node).length, "We still have two nodes");\n
+                            ok(graph.node.N1b !== undefined, "Node Id changed");\n
+                            equal(1, Object.keys(graph.edge).length, "We still have one connection");\n
+                            equal("N1b", graph.edge.edge1.source, "Connection source has been updated");\n
+                        });\n
+                    });\n
+                });\n
+            }\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                jsplumb_gadget = new_gadget;\n
+                jsplumb_gadget.render(sample_data_graph);\n
+            }).then(function() {\n
+                return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);\n
+            }).fail(error_handler).always(start);\n
+        });\n
+        test("New node can be edited", function() {\n
+            var jsplumb_gadget, node_id;\n
+            stop();\n
+            function runTest() {\n
+                // XXX here I used getContent to have a promise, but there must be a\n
+                // more elegant way.\n
+                return jsplumb_gadget.getContent().then(function() {\n
+                    // fake a drop event\n
+                    var e = new Event("drop");\n
+                    e.dataTransfer = {\n
+                        getData: function(type) {\n
+                            // make sure we are called properly\n
+                            equal("application/json", type, "The drag&dropped element must have data type application/json");\n
+                            return JSON.stringify("Example.Node");\n
+                        }\n
+                    };\n
+                    jsplumb_gadget.props.main.dispatchEvent(e);\n
+                }).then(function() {\n
+                    return jsplumb_gadget.getContent();\n
+                }).then(function(content) {\n
+                    var node, graph = JSON.parse(content).graph;\n
+                    equal(1, Object.keys(graph.node).length);\n
+                    node_id = Object.keys(graph.node)[0];\n
+                    node = graph.node[node_id];\n
+                    equal("Example.Node", node._class);\n
+                }).then(function() {\n
+                    // click the new node to see display the popup\n
+                    // XXX at the moment nodes have class window\n
+                    equal(1, $("div.window").length, "We have a new node");\n
+                    $("div.window").simulate("dblclick");\n
+                    // Promises that handle the dialog actions are not available\n
+                    // immediately after clicking.\n
+                    var promise = RSVP.Promise(function(resolve) {\n
+                        var fillDialog = function() {\n
+                            if (!jsplumb_gadget.props.dialog_promise) {\n
+                                // Dialog not ready. Let\'s retry later.\n
+                                // XXX this condition is actually incorrect. We need to wait\n
+                                // for the event listener to have been registered for the\n
+                                // dialog buttons. This setTimeout is good enough for now.\n
+                                return setTimeout(fillDialog, 1e3);\n
+                            }\n
+                            // check displayed values\n
+                            equal($("input[name=\'id\']").val(), node_id);\n
+                            equal($("input[name=\'name\']").val(), "");\n
+                            equal($("input[name=\'shape\']").val(), "");\n
+                            // change the name\n
+                            $("input[name=\'name\']").val("Modified Name");\n
+                            equal(1, $("input[value=\'Validate\']").length, "There should be one validate button");\n
+                            // and save\n
+                            $("input[value=\'Validate\']").click();\n
+                            // resolve our test promise once the dialog handling promise is\n
+                            // finished.\n
+                            jsplumb_gadget.props.dialog_promise.then(resolve);\n
+                        };\n
+                        fillDialog();\n
+                    });\n
+                    return promise.then(function() {\n
+                        return jsplumb_gadget.getContent().then(function(content) {\n
+                            var graph = JSON.parse(content).graph, node = graph.node[node_id];\n
+                            equal("Modified Name", node.name, "Data is modified");\n
+                            equal("Modified Name", $("div.window").text(), "DOM is modified");\n
+                        });\n
+                    });\n
+                });\n
+            }\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                jsplumb_gadget = new_gadget;\n
+                jsplumb_gadget.render(sample_data_empty_graph);\n
+            }).then(function() {\n
+                return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);\n
+            }).fail(error_handler).always(start);\n
+        });\n
+        test("New node can be deleted", function() {\n
+            var jsplumb_gadget, node_id;\n
+            stop();\n
+            function runTest() {\n
+                // XXX here I used getContent to have a promise, but there must be a\n
+                // more elegant way.\n
+                return jsplumb_gadget.getContent().then(function() {\n
+                    // fake a drop event\n
+                    var e = new Event("drop");\n
+                    e.dataTransfer = {\n
+                        getData: function(type) {\n
+                            // make sure we are called properly\n
+                            equal("application/json", type, "The drag&dropped element must have data type application/json");\n
+                            return JSON.stringify("Example.Node");\n
+                        }\n
+                    };\n
+                    jsplumb_gadget.props.main.dispatchEvent(e);\n
+                }).then(function() {\n
+                    return jsplumb_gadget.getContent();\n
+                }).then(function(content) {\n
+                    var node, graph = JSON.parse(content).graph;\n
+                    equal(1, Object.keys(graph.node).length);\n
+                    node_id = Object.keys(graph.node)[0];\n
+                    node = graph.node[node_id];\n
+                    equal("Example.Node", node._class);\n
+                }).then(function() {\n
+                    // click the new node to see display the popup\n
+                    // XXX at the moment nodes have class window\n
+                    equal(1, $("div.window").length, "We have a new node");\n
+                    $("div.window").simulate("dblclick");\n
+                    // Promises that handle the dialog actions are not available\n
+                    // immediately after clicking.\n
+                    var promise = RSVP.Promise(function(resolve) {\n
+                        var waitForDialogAndDelete = function() {\n
+                            if (!jsplumb_gadget.props.dialog_promise) {\n
+                                // Dialog not ready. Let\'s retry later.\n
+                                // XXX this condition is actually incorrect. We need to wait\n
+                                // for the event listener to have been registered for the\n
+                                // dialog buttons. This setTimeout is good enough for now.\n
+                                return setTimeout(waitForDialogAndDelete, 1e3);\n
+                            }\n
+                            equal(1, $("input[value=\'Delete\']").length, "There should be one delete button");\n
+                            $("input[value=\'Delete\']").click();\n
+                            // resolve our test promise once the dialog handling promise is\n
+                            // finished.\n
+                            jsplumb_gadget.props.dialog_promise.then(resolve);\n
+                        };\n
+                        waitForDialogAndDelete();\n
+                    });\n
+                    return promise.then(function() {\n
+                        return jsplumb_gadget.getContent().then(function(content) {\n
+                            var graph = JSON.parse(content).graph;\n
+                            equal(0, Object.keys(graph.node).length, "node is removed from data");\n
+                            equal(0, $("div.window").length, "DOM is modified");\n
+                        });\n
+                    });\n
+                });\n
+            }\n
+            g.declareGadget("./index.html", {\n
+                element: document.querySelector("#qunit-fixture")\n
+            }).then(function(new_gadget) {\n
+                jsplumb_gadget = new_gadget;\n
+                jsplumb_gadget.render(sample_data_empty_graph);\n
+            }).then(function() {\n
+                return RSVP.any([ jsplumb_gadget.startService(), runTest() ]);\n
+            }).fail(error_handler).always(start);\n
+        });\n
+    });\n
+})(rJS, JSON, QUnit, RSVP, jQuery);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>26485</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib.xml
new file mode 100644
index 0000000000000000000000000000000000000000..49c19727c0716b21ce094ade1a84c90a7a9edacc
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>lib</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/URI.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/URI.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dd3f20532615548e443892a6a4e0390e5d3a0c8f
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/URI.js.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681771.3</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>URI.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*! URI.js v1.12.0 http://medialize.github.com/URI.js/ */\n
+/* build contains: IPv6.js, punycode.js, SecondLevelDomains.js, URI.js, URI.fragmentQuery.js */\n
+(function(e,k){"object"===typeof exports?module.exports=k():"function"===typeof define&&define.amd?define(k):e.IPv6=k(e)})(this,function(e){var k=e&&e.IPv6;return{best:function(e){e=e.toLowerCase().split(":");var k=e.length,d=8;""===e[0]&&""===e[1]&&""===e[2]?(e.shift(),e.shift()):""===e[0]&&""===e[1]?e.shift():""===e[k-1]&&""===e[k-2]&&e.pop();k=e.length;-1!==e[k-1].indexOf(".")&&(d=7);var g;for(g=0;g<k&&""!==e[g];g++);if(g<d)for(e.splice(g,1,"0000");e.length<d;)e.splice(g,0,"0000");for(g=0;g<d;g++){for(var k=\n
+e[g].split(""),q=0;3>q;q++)if("0"===k[0]&&1<k.length)k.splice(0,1);else break;e[g]=k.join("")}var k=-1,l=q=0,r=-1,z=!1;for(g=0;g<d;g++)z?"0"===e[g]?l+=1:(z=!1,l>q&&(k=r,q=l)):"0"==e[g]&&(z=!0,r=g,l=1);l>q&&(k=r,q=l);1<q&&e.splice(k,q,"");k=e.length;d="";""===e[0]&&(beststr=":");for(g=0;g<k;g++){d+=e[g];if(g===k-1)break;d+=":"}""===e[k-1]&&(d+=":");return d},noConflict:function(){e.IPv6===this&&(e.IPv6=k);return this}}});\n
+(function(e){function k(a){throw RangeError(p[a]);}function u(a,b){for(var c=a.length;c--;)a[c]=b(a[c]);return a}function m(a,b){return u(a.split(h),b).join(".")}function d(a){for(var b=[],c=0,d=a.length,h,p;c<d;)h=a.charCodeAt(c++),55296<=h&&56319>=h&&c<d?(p=a.charCodeAt(c++),56320==(p&64512)?b.push(((h&1023)<<10)+(p&1023)+65536):(b.push(h),c--)):b.push(h);return b}function g(a){return u(a,function(a){var b="";65535<a&&(a-=65536,b+=x(a>>>10&1023|55296),a=56320|a&1023);return b+=x(a)}).join("")}function q(a,\n
+b){return a+22+75*(26>a)-((0!=b)<<5)}function l(a,b,c){var d=0;a=c?A(a/H):a>>1;for(a+=A(a/b);a>n*y>>1;d+=s)a=A(a/n);return A(d+(n+1)*a/(a+I))}function r(b){var c=[],d=b.length,h,p=0,e=F,f=G,n,x,q,t,m;n=b.lastIndexOf(a);0>n&&(n=0);for(x=0;x<n;++x)128<=b.charCodeAt(x)&&k("not-basic"),c.push(b.charCodeAt(x));for(n=0<n?n+1:0;n<d;){x=p;h=1;for(q=s;;q+=s){n>=d&&k("invalid-input");t=b.charCodeAt(n++);t=10>t-48?t-22:26>t-65?t-65:26>t-97?t-97:s;(t>=s||t>A((w-p)/h))&&k("overflow");p+=t*h;m=q<=f?v:q>=f+y?y:\n
+q-f;if(t<m)break;t=s-m;h>A(w/t)&&k("overflow");h*=t}h=c.length+1;f=l(p-x,h,0==x);A(p/h)>w-e&&k("overflow");e+=A(p/h);p%=h;c.splice(p++,0,e)}return g(c)}function z(b){var c,h,p,e,f,n,g,m,r,t=[],B,u,z;b=d(b);B=b.length;c=F;h=0;f=G;for(n=0;n<B;++n)r=b[n],128>r&&t.push(x(r));for((p=e=t.length)&&t.push(a);p<B;){g=w;for(n=0;n<B;++n)r=b[n],r>=c&&r<g&&(g=r);u=p+1;g-c>A((w-h)/u)&&k("overflow");h+=(g-c)*u;c=g;for(n=0;n<B;++n)if(r=b[n],r<c&&++h>w&&k("overflow"),r==c){m=h;for(g=s;;g+=s){r=g<=f?v:g>=f+y?y:g-f;\n
+if(m<r)break;z=m-r;m=s-r;t.push(x(q(r+z%m,0)));m=A(z/m)}t.push(x(q(m,0)));f=l(h,u,p==e);h=0;++p}++h;++c}return t.join("")}var D="object"==typeof exports&&exports,E="object"==typeof module&&module&&module.exports==D&&module,C="object"==typeof global&&global;if(C.global===C||C.window===C)e=C;var f,w=2147483647,s=36,v=1,y=26,I=38,H=700,G=72,F=128,a="-",b=/^xn--/,c=/[^ -~]/,h=/\\x2E|\\u3002|\\uFF0E|\\uFF61/g,p={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)",\n
+"invalid-input":"Invalid input"},n=s-v,A=Math.floor,x=String.fromCharCode,B;f={version:"1.2.3",ucs2:{decode:d,encode:g},decode:r,encode:z,toASCII:function(a){return m(a,function(a){return c.test(a)?"xn--"+z(a):a})},toUnicode:function(a){return m(a,function(a){return b.test(a)?r(a.slice(4).toLowerCase()):a})}};if("function"==typeof define&&"object"==typeof define.amd&&define.amd)define(function(){return f});else if(D&&!D.nodeType)if(E)E.exports=f;else for(B in f)f.hasOwnProperty(B)&&(D[B]=f[B]);else e.punycode=\n
+f})(this);\n
+(function(e,k){"object"===typeof exports?module.exports=k():"function"===typeof define&&define.amd?define(k):e.SecondLevelDomains=k(e)})(this,function(e){var k=e&&e.SecondLevelDomains,u=Object.prototype.hasOwnProperty,m={list:{ac:"com|gov|mil|net|org",ae:"ac|co|gov|mil|name|net|org|pro|sch",af:"com|edu|gov|net|org",al:"com|edu|gov|mil|net|org",ao:"co|ed|gv|it|og|pb",ar:"com|edu|gob|gov|int|mil|net|org|tur",at:"ac|co|gv|or",au:"asn|com|csiro|edu|gov|id|net|org",ba:"co|com|edu|gov|mil|net|org|rs|unbi|unmo|unsa|untz|unze",bb:"biz|co|com|edu|gov|info|net|org|store|tv",\n
+bh:"biz|cc|com|edu|gov|info|net|org",bn:"com|edu|gov|net|org",bo:"com|edu|gob|gov|int|mil|net|org|tv",br:"adm|adv|agr|am|arq|art|ato|b|bio|blog|bmd|cim|cng|cnt|com|coop|ecn|edu|eng|esp|etc|eti|far|flog|fm|fnd|fot|fst|g12|ggf|gov|imb|ind|inf|jor|jus|lel|mat|med|mil|mus|net|nom|not|ntr|odo|org|ppg|pro|psc|psi|qsl|rec|slg|srv|tmp|trd|tur|tv|vet|vlog|wiki|zlg",bs:"com|edu|gov|net|org",bz:"du|et|om|ov|rg",ca:"ab|bc|mb|nb|nf|nl|ns|nt|nu|on|pe|qc|sk|yk",ck:"biz|co|edu|gen|gov|info|net|org",cn:"ac|ah|bj|com|cq|edu|fj|gd|gov|gs|gx|gz|ha|hb|he|hi|hl|hn|jl|js|jx|ln|mil|net|nm|nx|org|qh|sc|sd|sh|sn|sx|tj|tw|xj|xz|yn|zj",\n
+co:"com|edu|gov|mil|net|nom|org",cr:"ac|c|co|ed|fi|go|or|sa",cy:"ac|biz|com|ekloges|gov|ltd|name|net|org|parliament|press|pro|tm","do":"art|com|edu|gob|gov|mil|net|org|sld|web",dz:"art|asso|com|edu|gov|net|org|pol",ec:"com|edu|fin|gov|info|med|mil|net|org|pro",eg:"com|edu|eun|gov|mil|name|net|org|sci",er:"com|edu|gov|ind|mil|net|org|rochest|w",es:"com|edu|gob|nom|org",et:"biz|com|edu|gov|info|name|net|org",fj:"ac|biz|com|info|mil|name|net|org|pro",fk:"ac|co|gov|net|nom|org",fr:"asso|com|f|gouv|nom|prd|presse|tm",\n
+gg:"co|net|org",gh:"com|edu|gov|mil|org",gn:"ac|com|gov|net|org",gr:"com|edu|gov|mil|net|org",gt:"com|edu|gob|ind|mil|net|org",gu:"com|edu|gov|net|org",hk:"com|edu|gov|idv|net|org",id:"ac|co|go|mil|net|or|sch|web",il:"ac|co|gov|idf|k12|muni|net|org","in":"ac|co|edu|ernet|firm|gen|gov|i|ind|mil|net|nic|org|res",iq:"com|edu|gov|i|mil|net|org",ir:"ac|co|dnssec|gov|i|id|net|org|sch",it:"edu|gov",je:"co|net|org",jo:"com|edu|gov|mil|name|net|org|sch",jp:"ac|ad|co|ed|go|gr|lg|ne|or",ke:"ac|co|go|info|me|mobi|ne|or|sc",\n
+kh:"com|edu|gov|mil|net|org|per",ki:"biz|com|de|edu|gov|info|mob|net|org|tel",km:"asso|com|coop|edu|gouv|k|medecin|mil|nom|notaires|pharmaciens|presse|tm|veterinaire",kn:"edu|gov|net|org",kr:"ac|busan|chungbuk|chungnam|co|daegu|daejeon|es|gangwon|go|gwangju|gyeongbuk|gyeonggi|gyeongnam|hs|incheon|jeju|jeonbuk|jeonnam|k|kg|mil|ms|ne|or|pe|re|sc|seoul|ulsan",kw:"com|edu|gov|net|org",ky:"com|edu|gov|net|org",kz:"com|edu|gov|mil|net|org",lb:"com|edu|gov|net|org",lk:"assn|com|edu|gov|grp|hotel|int|ltd|net|ngo|org|sch|soc|web",\n
+lr:"com|edu|gov|net|org",lv:"asn|com|conf|edu|gov|id|mil|net|org",ly:"com|edu|gov|id|med|net|org|plc|sch",ma:"ac|co|gov|m|net|org|press",mc:"asso|tm",me:"ac|co|edu|gov|its|net|org|priv",mg:"com|edu|gov|mil|nom|org|prd|tm",mk:"com|edu|gov|inf|name|net|org|pro",ml:"com|edu|gov|net|org|presse",mn:"edu|gov|org",mo:"com|edu|gov|net|org",mt:"com|edu|gov|net|org",mv:"aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro",mw:"ac|co|com|coop|edu|gov|int|museum|net|org",mx:"com|edu|gob|net|org",my:"com|edu|gov|mil|name|net|org|sch",\n
+nf:"arts|com|firm|info|net|other|per|rec|store|web",ng:"biz|com|edu|gov|mil|mobi|name|net|org|sch",ni:"ac|co|com|edu|gob|mil|net|nom|org",np:"com|edu|gov|mil|net|org",nr:"biz|com|edu|gov|info|net|org",om:"ac|biz|co|com|edu|gov|med|mil|museum|net|org|pro|sch",pe:"com|edu|gob|mil|net|nom|org|sld",ph:"com|edu|gov|i|mil|net|ngo|org",pk:"biz|com|edu|fam|gob|gok|gon|gop|gos|gov|net|org|web",pl:"art|bialystok|biz|com|edu|gda|gdansk|gorzow|gov|info|katowice|krakow|lodz|lublin|mil|net|ngo|olsztyn|org|poznan|pwr|radom|slupsk|szczecin|torun|warszawa|waw|wroc|wroclaw|zgora",\n
+pr:"ac|biz|com|edu|est|gov|info|isla|name|net|org|pro|prof",ps:"com|edu|gov|net|org|plo|sec",pw:"belau|co|ed|go|ne|or",ro:"arts|com|firm|info|nom|nt|org|rec|store|tm|www",rs:"ac|co|edu|gov|in|org",sb:"com|edu|gov|net|org",sc:"com|edu|gov|net|org",sh:"co|com|edu|gov|net|nom|org",sl:"com|edu|gov|net|org",st:"co|com|consulado|edu|embaixada|gov|mil|net|org|principe|saotome|store",sv:"com|edu|gob|org|red",sz:"ac|co|org",tr:"av|bbs|bel|biz|com|dr|edu|gen|gov|info|k12|name|net|org|pol|tel|tsk|tv|web",tt:"aero|biz|cat|co|com|coop|edu|gov|info|int|jobs|mil|mobi|museum|name|net|org|pro|tel|travel",\n
+tw:"club|com|ebiz|edu|game|gov|idv|mil|net|org",mu:"ac|co|com|gov|net|or|org",mz:"ac|co|edu|gov|org",na:"co|com",nz:"ac|co|cri|geek|gen|govt|health|iwi|maori|mil|net|org|parliament|school",pa:"abo|ac|com|edu|gob|ing|med|net|nom|org|sld",pt:"com|edu|gov|int|net|nome|org|publ",py:"com|edu|gov|mil|net|org",qa:"com|edu|gov|mil|net|org",re:"asso|com|nom",ru:"ac|adygeya|altai|amur|arkhangelsk|astrakhan|bashkiria|belgorod|bir|bryansk|buryatia|cbg|chel|chelyabinsk|chita|chukotka|chuvashia|com|dagestan|e-burg|edu|gov|grozny|int|irkutsk|ivanovo|izhevsk|jar|joshkar-ola|kalmykia|kaluga|kamchatka|karelia|kazan|kchr|kemerovo|khabarovsk|khakassia|khv|kirov|koenig|komi|kostroma|kranoyarsk|kuban|kurgan|kursk|lipetsk|magadan|mari|mari-el|marine|mil|mordovia|mosreg|msk|murmansk|nalchik|net|nnov|nov|novosibirsk|nsk|omsk|orenburg|org|oryol|penza|perm|pp|pskov|ptz|rnd|ryazan|sakhalin|samara|saratov|simbirsk|smolensk|spb|stavropol|stv|surgut|tambov|tatarstan|tom|tomsk|tsaritsyn|tsk|tula|tuva|tver|tyumen|udm|udmurtia|ulan-ude|vladikavkaz|vladimir|vladivostok|volgograd|vologda|voronezh|vrn|vyatka|yakutia|yamal|yekaterinburg|yuzhno-sakhalinsk",\n
+rw:"ac|co|com|edu|gouv|gov|int|mil|net",sa:"com|edu|gov|med|net|org|pub|sch",sd:"com|edu|gov|info|med|net|org|tv",se:"a|ac|b|bd|c|d|e|f|g|h|i|k|l|m|n|o|org|p|parti|pp|press|r|s|t|tm|u|w|x|y|z",sg:"com|edu|gov|idn|net|org|per",sn:"art|com|edu|gouv|org|perso|univ",sy:"com|edu|gov|mil|net|news|org",th:"ac|co|go|in|mi|net|or",tj:"ac|biz|co|com|edu|go|gov|info|int|mil|name|net|nic|org|test|web",tn:"agrinet|com|defense|edunet|ens|fin|gov|ind|info|intl|mincom|nat|net|org|perso|rnrt|rns|rnu|tourism",tz:"ac|co|go|ne|or",\n
+ua:"biz|cherkassy|chernigov|chernovtsy|ck|cn|co|com|crimea|cv|dn|dnepropetrovsk|donetsk|dp|edu|gov|if|in|ivano-frankivsk|kh|kharkov|kherson|khmelnitskiy|kiev|kirovograd|km|kr|ks|kv|lg|lugansk|lutsk|lviv|me|mk|net|nikolaev|od|odessa|org|pl|poltava|pp|rovno|rv|sebastopol|sumy|te|ternopil|uzhgorod|vinnica|vn|zaporizhzhe|zhitomir|zp|zt",ug:"ac|co|go|ne|or|org|sc",uk:"ac|bl|british-library|co|cym|gov|govt|icnet|jet|lea|ltd|me|mil|mod|national-library-scotland|nel|net|nhs|nic|nls|org|orgn|parliament|plc|police|sch|scot|soc",\n
+us:"dni|fed|isa|kids|nsn",uy:"com|edu|gub|mil|net|org",ve:"co|com|edu|gob|info|mil|net|org|web",vi:"co|com|k12|net|org",vn:"ac|biz|com|edu|gov|health|info|int|name|net|org|pro",ye:"co|com|gov|ltd|me|net|org|plc",yu:"ac|co|edu|gov|org",za:"ac|agric|alt|bourse|city|co|cybernet|db|edu|gov|grondar|iaccess|imt|inca|landesign|law|mil|net|ngo|nis|nom|olivetti|org|pix|school|tm|web",zm:"ac|co|com|edu|gov|net|org|sch"},has_expression:null,is_expression:null,has:function(d){return!!d.match(m.has_expression)},\n
+is:function(d){return!!d.match(m.is_expression)},get:function(d){return(d=d.match(m.has_expression))&&d[1]||null},noConflict:function(){e.SecondLevelDomains===this&&(e.SecondLevelDomains=k);return this},init:function(){var d="",e;for(e in m.list)u.call(m.list,e)&&(d+="|("+("("+m.list[e]+")."+e)+")");m.has_expression=RegExp("\\\\.("+d.substr(1)+")$","i");m.is_expression=RegExp("^("+d.substr(1)+")$","i")}};m.init();return m});\n
+(function(e,k){"object"===typeof exports?module.exports=k(require("./punycode"),require("./IPv6"),require("./SecondLevelDomains")):"function"===typeof define&&define.amd?define(["./punycode","./IPv6","./SecondLevelDomains"],k):e.URI=k(e.punycode,e.IPv6,e.SecondLevelDomains,e)})(this,function(e,k,u,m){function d(a,b){if(!(this instanceof d))return new d(a,b);void 0===a&&(a="undefined"!==typeof location?location.href+"":"");this.href(a);return void 0!==b?this.absoluteTo(b):this}function g(a){return a.replace(/([.*+?^=!:${}()|[\\]\\/\\\\])/g,\n
+"\\\\$1")}function q(a){return void 0===a?"Undefined":String(Object.prototype.toString.call(a)).slice(8,-1)}function l(a){return"Array"===q(a)}function r(a,b){var c,d;if(l(b)){c=0;for(d=b.length;c<d;c++)if(!r(a,b[c]))return!1;return!0}var p=q(b);c=0;for(d=a.length;c<d;c++)if("RegExp"===p){if("string"===typeof a[c]&&a[c].match(b))return!0}else if(a[c]===b)return!0;return!1}function z(a,b){if(!l(a)||!l(b)||a.length!==b.length)return!1;a.sort();b.sort();for(var c=0,d=a.length;c<d;c++)if(a[c]!==b[c])return!1;\n
+return!0}function D(a){return escape(a)}function E(a){return encodeURIComponent(a).replace(/[!\'()*]/g,D).replace(/\\*/g,"%2A")}var C=m&&m.URI;d.version="1.12.0";var f=d.prototype,w=Object.prototype.hasOwnProperty;d._parts=function(){return{protocol:null,username:null,password:null,hostname:null,urn:null,port:null,path:null,query:null,fragment:null,duplicateQueryParameters:d.duplicateQueryParameters,escapeQuerySpace:d.escapeQuerySpace}};d.duplicateQueryParameters=!1;d.escapeQuerySpace=!0;d.protocol_expression=\n
+/^[a-z][a-z0-9.+-]*$/i;d.idn_expression=/[^a-z0-9\\.-]/i;d.punycode_expression=/(xn--)/i;d.ip4_expression=/^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/;d.ip6_expression=/^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)(\\.(25[0-5]|2[0-4]\\d|1\\d\\d|[1-9]?\\d)){3}))|:)))(%.+)?\\s*$/;\n
+d.find_uri_expression=/\\b((?:[a-z][\\w-]+:(?:\\/{1,3}|[a-z0-9%])|www\\d{0,3}[.]|[a-z0-9.\\-]+[.][a-z]{2,4}\\/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]{};:\'".,<>?\\u00ab\\u00bb\\u201c\\u201d\\u2018\\u2019]))/ig;d.findUri={start:/\\b(?:([a-z][a-z0-9.+-]*:\\/\\/)|www\\.)/gi,end:/[\\s\\r\\n]|$/,trim:/[`!()\\[\\]{};:\'".,<>?\\u00ab\\u00bb\\u201c\\u201d\\u201e\\u2018\\u2019]+$/};d.defaultPorts={http:"80",https:"443",ftp:"21",gopher:"70",ws:"80",wss:"443"};d.invalid_hostname_characters=\n
+/[^a-zA-Z0-9\\.-]/;d.domAttributes={a:"href",blockquote:"cite",link:"href",base:"href",script:"src",form:"action",img:"src",area:"href",iframe:"src",embed:"src",source:"src",track:"src",input:"src"};d.getDomAttribute=function(a){if(a&&a.nodeName){var b=a.nodeName.toLowerCase();return"input"===b&&"image"!==a.type?void 0:d.domAttributes[b]}};d.encode=E;d.decode=decodeURIComponent;d.iso8859=function(){d.encode=escape;d.decode=unescape};d.unicode=function(){d.encode=E;d.decode=decodeURIComponent};d.characters=\n
+{pathname:{encode:{expression:/%(24|26|2B|2C|3B|3D|3A|40)/ig,map:{"%24":"$","%26":"&","%2B":"+","%2C":",","%3B":";","%3D":"=","%3A":":","%40":"@"}},decode:{expression:/[\\/\\?#]/g,map:{"/":"%2F","?":"%3F","#":"%23"}}},reserved:{encode:{expression:/%(21|23|24|26|27|28|29|2A|2B|2C|2F|3A|3B|3D|3F|40|5B|5D)/ig,map:{"%3A":":","%2F":"/","%3F":"?","%23":"#","%5B":"[","%5D":"]","%40":"@","%21":"!","%24":"$","%26":"&","%27":"\'","%28":"(","%29":")","%2A":"*","%2B":"+","%2C":",","%3B":";","%3D":"="}}}};d.encodeQuery=\n
+function(a,b){var c=d.encode(a+"");return b?c.replace(/%20/g,"+"):c};d.decodeQuery=function(a,b){a+="";try{return d.decode(b?a.replace(/\\+/g,"%20"):a)}catch(c){return a}};d.recodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;b<c;b++)a[b]=d.encodePathSegment(d.decode(a[b]));return a.join("/")};d.decodePath=function(a){a=(a+"").split("/");for(var b=0,c=a.length;b<c;b++)a[b]=d.decodePathSegment(a[b]);return a.join("/")};var s={encode:"encode",decode:"decode"},v,y=function(a,b){return function(c){return d[b](c+\n
+"").replace(d.characters[a][b].expression,function(c){return d.characters[a][b].map[c]})}};for(v in s)d[v+"PathSegment"]=y("pathname",s[v]);d.encodeReserved=y("reserved","encode");d.parse=function(a,b){var c;b||(b={});c=a.indexOf("#");-1<c&&(b.fragment=a.substring(c+1)||null,a=a.substring(0,c));c=a.indexOf("?");-1<c&&(b.query=a.substring(c+1)||null,a=a.substring(0,c));"//"===a.substring(0,2)?(b.protocol=null,a=a.substring(2),a=d.parseAuthority(a,b)):(c=a.indexOf(":"),-1<c&&(b.protocol=a.substring(0,\n
+c)||null,b.protocol&&!b.protocol.match(d.protocol_expression)?b.protocol=void 0:"file"===b.protocol?a=a.substring(c+3):"//"===a.substring(c+1,c+3)?(a=a.substring(c+3),a=d.parseAuthority(a,b)):(a=a.substring(c+1),b.urn=!0)));b.path=a;return b};d.parseHost=function(a,b){var c=a.indexOf("/"),d;-1===c&&(c=a.length);"["===a.charAt(0)?(d=a.indexOf("]"),b.hostname=a.substring(1,d)||null,b.port=a.substring(d+2,c)||null):a.indexOf(":")!==a.lastIndexOf(":")?(b.hostname=a.substring(0,c)||null,b.port=null):(d=\n
+a.substring(0,c).split(":"),b.hostname=d[0]||null,b.port=d[1]||null);b.hostname&&"/"!==a.substring(c).charAt(0)&&(c++,a="/"+a);return a.substring(c)||"/"};d.parseAuthority=function(a,b){a=d.parseUserinfo(a,b);return d.parseHost(a,b)};d.parseUserinfo=function(a,b){var c=a.indexOf("/"),h=-1<c?a.lastIndexOf("@",c):a.indexOf("@");-1<h&&(-1===c||h<c)?(c=a.substring(0,h).split(":"),b.username=c[0]?d.decode(c[0]):null,c.shift(),b.password=c[0]?d.decode(c.join(":")):null,a=a.substring(h+1)):(b.username=null,\n
+b.password=null);return a};d.parseQuery=function(a,b){if(!a)return{};a=a.replace(/&+/g,"&").replace(/^\\?*&*|&+$/g,"");if(!a)return{};for(var c={},h=a.split("&"),p=h.length,n,e,f=0;f<p;f++)n=h[f].split("="),e=d.decodeQuery(n.shift(),b),n=n.length?d.decodeQuery(n.join("="),b):null,c[e]?("string"===typeof c[e]&&(c[e]=[c[e]]),c[e].push(n)):c[e]=n;return c};d.build=function(a){var b="";a.protocol&&(b+=a.protocol+":");a.urn||!b&&!a.hostname||(b+="//");b+=d.buildAuthority(a)||"";"string"===typeof a.path&&\n
+("/"!==a.path.charAt(0)&&"string"===typeof a.hostname&&(b+="/"),b+=a.path);"string"===typeof a.query&&a.query&&(b+="?"+a.query);"string"===typeof a.fragment&&a.fragment&&(b+="#"+a.fragment);return b};d.buildHost=function(a){var b="";if(a.hostname)d.ip6_expression.test(a.hostname)?b=a.port?b+("["+a.hostname+"]:"+a.port):b+a.hostname:(b+=a.hostname,a.port&&(b+=":"+a.port));else return"";return b};d.buildAuthority=function(a){return d.buildUserinfo(a)+d.buildHost(a)};d.buildUserinfo=function(a){var b=\n
+"";a.username&&(b+=d.encode(a.username),a.password&&(b+=":"+d.encode(a.password)),b+="@");return b};d.buildQuery=function(a,b,c){var h="",p,e,f,k;for(e in a)if(w.call(a,e)&&e)if(l(a[e]))for(p={},f=0,k=a[e].length;f<k;f++)void 0!==a[e][f]&&void 0===p[a[e][f]+""]&&(h+="&"+d.buildQueryParameter(e,a[e][f],c),!0!==b&&(p[a[e][f]+""]=!0));else void 0!==a[e]&&(h+="&"+d.buildQueryParameter(e,a[e],c));return h.substring(1)};d.buildQueryParameter=function(a,b,c){return d.encodeQuery(a,c)+(null!==b?"="+d.encodeQuery(b,\n
+c):"")};d.addQuery=function(a,b,c){if("object"===typeof b)for(var h in b)w.call(b,h)&&d.addQuery(a,h,b[h]);else if("string"===typeof b)void 0===a[b]?a[b]=c:("string"===typeof a[b]&&(a[b]=[a[b]]),l(c)||(c=[c]),a[b]=a[b].concat(c));else throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");};d.removeQuery=function(a,b,c){var h;if(l(b))for(c=0,h=b.length;c<h;c++)a[b[c]]=void 0;else if("object"===typeof b)for(h in b)w.call(b,h)&&d.removeQuery(a,h,b[h]);else if("string"===\n
+typeof b)if(void 0!==c)if(a[b]===c)a[b]=void 0;else{if(l(a[b])){h=a[b];var p={},e,f;if(l(c))for(e=0,f=c.length;e<f;e++)p[c[e]]=!0;else p[c]=!0;e=0;for(f=h.length;e<f;e++)void 0!==p[h[e]]&&(h.splice(e,1),f--,e--);a[b]=h}}else a[b]=void 0;else throw new TypeError("URI.addQuery() accepts an object, string as the first parameter");};d.hasQuery=function(a,b,c,h){if("object"===typeof b){for(var e in b)if(w.call(b,e)&&!d.hasQuery(a,e,b[e]))return!1;return!0}if("string"!==typeof b)throw new TypeError("URI.hasQuery() accepts an object, string as the name parameter");\n
+switch(q(c)){case "Undefined":return b in a;case "Boolean":return a=Boolean(l(a[b])?a[b].length:a[b]),c===a;case "Function":return!!c(a[b],b,a);case "Array":return l(a[b])?(h?r:z)(a[b],c):!1;case "RegExp":return l(a[b])?h?r(a[b],c):!1:Boolean(a[b]&&a[b].match(c));case "Number":c=String(c);case "String":return l(a[b])?h?r(a[b],c):!1:a[b]===c;default:throw new TypeError("URI.hasQuery() accepts undefined, boolean, string, number, RegExp, Function as the value parameter");}};d.commonPath=function(a,b){var c=\n
+Math.min(a.length,b.length),d;for(d=0;d<c;d++)if(a.charAt(d)!==b.charAt(d)){d--;break}if(1>d)return a.charAt(0)===b.charAt(0)&&"/"===a.charAt(0)?"/":"";if("/"!==a.charAt(d)||"/"!==b.charAt(d))d=a.substring(0,d).lastIndexOf("/");return a.substring(0,d+1)};d.withinString=function(a,b,c){c||(c={});var h=c.start||d.findUri.start,e=c.end||d.findUri.end,f=c.trim||d.findUri.trim,k=/[a-z0-9-]=["\']?$/i;for(h.lastIndex=0;;){var g=h.exec(a);if(!g)break;g=g.index;if(c.ignoreHtml){var l=a.slice(Math.max(g-3,0),\n
+g);if(l&&k.test(l))continue}var l=g+a.slice(g).search(e),q=a.slice(g,l).replace(f,"");c.ignore&&c.ignore.test(q)||(l=g+q.length,q=b(q,g,l,a),a=a.slice(0,g)+q+a.slice(l),h.lastIndex=g+q.length)}h.lastIndex=0;return a};d.ensureValidHostname=function(a){if(a.match(d.invalid_hostname_characters)){if(!e)throw new TypeError("Hostname \'"+a+"\' contains characters other than [A-Z0-9.-] and Punycode.js is not available");if(e.toASCII(a).match(d.invalid_hostname_characters))throw new TypeError("Hostname \'"+\n
+a+"\' contains characters other than [A-Z0-9.-]");}};d.noConflict=function(a){if(a)return a={URI:this.noConflict()},URITemplate&&"function"==typeof URITemplate.noConflict&&(a.URITemplate=URITemplate.noConflict()),k&&"function"==typeof k.noConflict&&(a.IPv6=k.noConflict()),SecondLevelDomains&&"function"==typeof SecondLevelDomains.noConflict&&(a.SecondLevelDomains=SecondLevelDomains.noConflict()),a;m.URI===this&&(m.URI=C);return this};f.build=function(a){if(!0===a)this._deferred_build=!0;else if(void 0===\n
+a||this._deferred_build)this._string=d.build(this._parts),this._deferred_build=!1;return this};f.clone=function(){return new d(this)};f.valueOf=f.toString=function(){return this.build(!1)._string};s={protocol:"protocol",username:"username",password:"password",hostname:"hostname",port:"port"};y=function(a){return function(b,c){if(void 0===b)return this._parts[a]||"";this._parts[a]=b||null;this.build(!c);return this}};for(v in s)f[v]=y(s[v]);s={query:"?",fragment:"#"};y=function(a,b){return function(c,\n
+d){if(void 0===c)return this._parts[a]||"";null!==c&&(c+="",c.charAt(0)===b&&(c=c.substring(1)));this._parts[a]=c;this.build(!d);return this}};for(v in s)f[v]=y(v,s[v]);s={search:["?","query"],hash:["#","fragment"]};y=function(a,b){return function(c,d){var e=this[a](c,d);return"string"===typeof e&&e.length?b+e:e}};for(v in s)f[v]=y(s[v][1],s[v][0]);f.pathname=function(a,b){if(void 0===a||!0===a){var c=this._parts.path||(this._parts.hostname?"/":"");return a?d.decodePath(c):c}this._parts.path=a?d.recodePath(a):\n
+"/";this.build(!b);return this};f.path=f.pathname;f.href=function(a,b){var c;if(void 0===a)return this.toString();this._string="";this._parts=d._parts();var h=a instanceof d,e="object"===typeof a&&(a.hostname||a.path||a.pathname);a.nodeName&&(e=d.getDomAttribute(a),a=a[e]||"",e=!1);!h&&e&&void 0!==a.pathname&&(a=a.toString());if("string"===typeof a)this._parts=d.parse(a,this._parts);else if(h||e)for(c in h=h?a._parts:a,h)w.call(this._parts,c)&&(this._parts[c]=h[c]);else throw new TypeError("invalid input");\n
+this.build(!b);return this};f.is=function(a){var b=!1,c=!1,h=!1,e=!1,f=!1,g=!1,k=!1,l=!this._parts.urn;this._parts.hostname&&(l=!1,c=d.ip4_expression.test(this._parts.hostname),h=d.ip6_expression.test(this._parts.hostname),b=c||h,f=(e=!b)&&u&&u.has(this._parts.hostname),g=e&&d.idn_expression.test(this._parts.hostname),k=e&&d.punycode_expression.test(this._parts.hostname));switch(a.toLowerCase()){case "relative":return l;case "absolute":return!l;case "domain":case "name":return e;case "sld":return f;\n
+case "ip":return b;case "ip4":case "ipv4":case "inet4":return c;case "ip6":case "ipv6":case "inet6":return h;case "idn":return g;case "url":return!this._parts.urn;case "urn":return!!this._parts.urn;case "punycode":return k}return null};var I=f.protocol,H=f.port,G=f.hostname;f.protocol=function(a,b){if(void 0!==a&&a&&(a=a.replace(/:(\\/\\/)?$/,""),!a.match(d.protocol_expression)))throw new TypeError("Protocol \'"+a+"\' contains characters other than [A-Z0-9.+-] or doesn\'t start with [A-Z]");return I.call(this,\n
+a,b)};f.scheme=f.protocol;f.port=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a&&(0===a&&(a=null),a&&(a+="",":"===a.charAt(0)&&(a=a.substring(1)),a.match(/[^0-9]/))))throw new TypeError("Port \'"+a+"\' contains characters other than [0-9]");return H.call(this,a,b)};f.hostname=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0!==a){var c={};d.parseHost(a,c);a=c.hostname}return G.call(this,a,b)};f.host=function(a,b){if(this._parts.urn)return void 0===a?"":this;\n
+if(void 0===a)return this._parts.hostname?d.buildHost(this._parts):"";d.parseHost(a,this._parts);this.build(!b);return this};f.authority=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a)return this._parts.hostname?d.buildAuthority(this._parts):"";d.parseAuthority(a,this._parts);this.build(!b);return this};f.userinfo=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.username)return"";var c=d.buildUserinfo(this._parts);return c.substring(0,\n
+c.length-1)}"@"!==a[a.length-1]&&(a+="@");d.parseUserinfo(a,this._parts);this.build(!b);return this};f.resource=function(a,b){var c;if(void 0===a)return this.path()+this.search()+this.hash();c=d.parse(a);this._parts.path=c.path;this._parts.query=c.query;this._parts.fragment=c.fragment;this.build(!b);return this};f.subdomain=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.length-this.domain().length-\n
+1;return this._parts.hostname.substring(0,c)||""}c=this._parts.hostname.length-this.domain().length;c=this._parts.hostname.substring(0,c);c=RegExp("^"+g(c));a&&"."!==a.charAt(a.length-1)&&(a+=".");a&&d.ensureValidHostname(a);this._parts.hostname=this._parts.hostname.replace(c,a);this.build(!b);return this};f.domain=function(a,b){if(this._parts.urn)return void 0===a?"":this;"boolean"===typeof a&&(b=a,a=void 0);if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.match(/\\./g);\n
+if(c&&2>c.length)return this._parts.hostname;c=this._parts.hostname.length-this.tld(b).length-1;c=this._parts.hostname.lastIndexOf(".",c-1)+1;return this._parts.hostname.substring(c)||""}if(!a)throw new TypeError("cannot set domain empty");d.ensureValidHostname(a);!this._parts.hostname||this.is("IP")?this._parts.hostname=a:(c=RegExp(g(this.domain())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a));this.build(!b);return this};f.tld=function(a,b){if(this._parts.urn)return void 0===a?"":\n
+this;"boolean"===typeof a&&(b=a,a=void 0);if(void 0===a){if(!this._parts.hostname||this.is("IP"))return"";var c=this._parts.hostname.lastIndexOf("."),c=this._parts.hostname.substring(c+1);return!0!==b&&u&&u.list[c.toLowerCase()]?u.get(this._parts.hostname)||c:c}if(a)if(a.match(/[^a-zA-Z0-9-]/))if(u&&u.is(a))c=RegExp(g(this.tld())+"$"),this._parts.hostname=this._parts.hostname.replace(c,a);else throw new TypeError("TLD \'"+a+"\' contains characters other than [A-Z0-9]");else{if(!this._parts.hostname||\n
+this.is("IP"))throw new ReferenceError("cannot set TLD on non-domain host");c=RegExp(g(this.tld())+"$");this._parts.hostname=this._parts.hostname.replace(c,a)}else throw new TypeError("cannot set TLD empty");this.build(!b);return this};f.directory=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path&&!this._parts.hostname)return"";if("/"===this._parts.path)return"/";var c=this._parts.path.length-this.filename().length-1,c=this._parts.path.substring(0,\n
+c)||(this._parts.hostname?"/":"");return a?d.decodePath(c):c}c=this._parts.path.length-this.filename().length;c=this._parts.path.substring(0,c);c=RegExp("^"+g(c));this.is("relative")||(a||(a="/"),"/"!==a.charAt(0)&&(a="/"+a));a&&"/"!==a.charAt(a.length-1)&&(a+="/");a=d.recodePath(a);this._parts.path=this._parts.path.replace(c,a);this.build(!b);return this};f.filename=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";\n
+var c=this._parts.path.lastIndexOf("/"),c=this._parts.path.substring(c+1);return a?d.decodePathSegment(c):c}c=!1;"/"===a.charAt(0)&&(a=a.substring(1));a.match(/\\.?\\//)&&(c=!0);var h=RegExp(g(this.filename())+"$");a=d.recodePath(a);this._parts.path=this._parts.path.replace(h,a);c?this.normalizePath(b):this.build(!b);return this};f.suffix=function(a,b){if(this._parts.urn)return void 0===a?"":this;if(void 0===a||!0===a){if(!this._parts.path||"/"===this._parts.path)return"";var c=this.filename(),h=c.lastIndexOf(".");\n
+if(-1===h)return"";c=c.substring(h+1);c=/^[a-z0-9%]+$/i.test(c)?c:"";return a?d.decodePathSegment(c):c}"."===a.charAt(0)&&(a=a.substring(1));if(c=this.suffix())h=a?RegExp(g(c)+"$"):RegExp(g("."+c)+"$");else{if(!a)return this;this._parts.path+="."+d.recodePath(a)}h&&(a=d.recodePath(a),this._parts.path=this._parts.path.replace(h,a));this.build(!b);return this};f.segment=function(a,b,c){var d=this._parts.urn?":":"/",e=this.path(),f="/"===e.substring(0,1),e=e.split(d);void 0!==a&&"number"!==typeof a&&\n
+(c=b,b=a,a=void 0);if(void 0!==a&&"number"!==typeof a)throw Error("Bad segment \'"+a+"\', must be 0-based integer");f&&e.shift();0>a&&(a=Math.max(e.length+a,0));if(void 0===b)return void 0===a?e:e[a];if(null===a||void 0===e[a])if(l(b)){e=[];a=0;for(var g=b.length;a<g;a++)if(b[a].length||e.length&&e[e.length-1].length)e.length&&!e[e.length-1].length&&e.pop(),e.push(b[a])}else{if(b||"string"===typeof b)""===e[e.length-1]?e[e.length-1]=b:e.push(b)}else b||"string"===typeof b&&b.length?e[a]=b:e.splice(a,\n
+1);f&&e.unshift("");return this.path(e.join(d),c)};f.segmentCoded=function(a,b,c){var e,f;"number"!==typeof a&&(c=b,b=a,a=void 0);if(void 0===b){a=this.segment(a,b,c);if(l(a))for(e=0,f=a.length;e<f;e++)a[e]=d.decode(a[e]);else a=void 0!==a?d.decode(a):void 0;return a}if(l(b))for(e=0,f=b.length;e<f;e++)b[e]=d.decode(b[e]);else b="string"===typeof b?d.encode(b):b;return this.segment(a,b,c)};var F=f.query;f.query=function(a,b){if(!0===a)return d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);\n
+if("function"===typeof a){var c=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace),e=a.call(this,c);this._parts.query=d.buildQuery(e||c,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);this.build(!b);return this}return void 0!==a&&"string"!==typeof a?(this._parts.query=d.buildQuery(a,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace),this.build(!b),this):F.call(this,a,b)};f.setQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);\n
+if("object"===typeof a)for(var f in a)w.call(a,f)&&(e[f]=a[f]);else if("string"===typeof a)e[a]=void 0!==b?b:null;else throw new TypeError("URI.addQuery() accepts an object, string as the name parameter");this._parts.query=d.buildQuery(e,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);"string"!==typeof a&&(c=b);this.build(!c);return this};f.addQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);d.addQuery(e,a,void 0===b?null:b);this._parts.query=\n
+d.buildQuery(e,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);"string"!==typeof a&&(c=b);this.build(!c);return this};f.removeQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);d.removeQuery(e,a,b);this._parts.query=d.buildQuery(e,this._parts.duplicateQueryParameters,this._parts.escapeQuerySpace);"string"!==typeof a&&(c=b);this.build(!c);return this};f.hasQuery=function(a,b,c){var e=d.parseQuery(this._parts.query,this._parts.escapeQuerySpace);\n
+return d.hasQuery(e,a,b,c)};f.setSearch=f.setQuery;f.addSearch=f.addQuery;f.removeSearch=f.removeQuery;f.hasSearch=f.hasQuery;f.normalize=function(){return this._parts.urn?this.normalizeProtocol(!1).normalizeQuery(!1).normalizeFragment(!1).build():this.normalizeProtocol(!1).normalizeHostname(!1).normalizePort(!1).normalizePath(!1).normalizeQuery(!1).normalizeFragment(!1).build()};f.normalizeProtocol=function(a){"string"===typeof this._parts.protocol&&(this._parts.protocol=this._parts.protocol.toLowerCase(),\n
+this.build(!a));return this};f.normalizeHostname=function(a){this._parts.hostname&&(this.is("IDN")&&e?this._parts.hostname=e.toASCII(this._parts.hostname):this.is("IPv6")&&k&&(this._parts.hostname=k.best(this._parts.hostname)),this._parts.hostname=this._parts.hostname.toLowerCase(),this.build(!a));return this};f.normalizePort=function(a){"string"===typeof this._parts.protocol&&this._parts.port===d.defaultPorts[this._parts.protocol]&&(this._parts.port=null,this.build(!a));return this};f.normalizePath=\n
+function(a){if(this._parts.urn||!this._parts.path||"/"===this._parts.path)return this;var b,c=this._parts.path,e="",f,g;"/"!==c.charAt(0)&&(b=!0,c="/"+c);c=c.replace(/(\\/(\\.\\/)+)|(\\/\\.$)/g,"/").replace(/\\/{2,}/g,"/");b&&(e=c.substring(1).match(/^(\\.\\.\\/)+/)||"")&&(e=e[0]);for(;;){f=c.indexOf("/..");if(-1===f)break;else if(0===f){c=c.substring(3);continue}g=c.substring(0,f).lastIndexOf("/");-1===g&&(g=f);c=c.substring(0,g)+c.substring(f+3)}b&&this.is("relative")&&(c=e+c.substring(1));c=d.recodePath(c);\n
+this._parts.path=c;this.build(!a);return this};f.normalizePathname=f.normalizePath;f.normalizeQuery=function(a){"string"===typeof this._parts.query&&(this._parts.query.length?this.query(d.parseQuery(this._parts.query,this._parts.escapeQuerySpace)):this._parts.query=null,this.build(!a));return this};f.normalizeFragment=function(a){this._parts.fragment||(this._parts.fragment=null,this.build(!a));return this};f.normalizeSearch=f.normalizeQuery;f.normalizeHash=f.normalizeFragment;f.iso8859=function(){var a=\n
+d.encode,b=d.decode;d.encode=escape;d.decode=decodeURIComponent;this.normalize();d.encode=a;d.decode=b;return this};f.unicode=function(){var a=d.encode,b=d.decode;d.encode=E;d.decode=unescape;this.normalize();d.encode=a;d.decode=b;return this};f.readable=function(){var a=this.clone();a.username("").password("").normalize();var b="";a._parts.protocol&&(b+=a._parts.protocol+"://");a._parts.hostname&&(a.is("punycode")&&e?(b+=e.toUnicode(a._parts.hostname),a._parts.port&&(b+=":"+a._parts.port)):b+=a.host());\n
+a._parts.hostname&&a._parts.path&&"/"!==a._parts.path.charAt(0)&&(b+="/");b+=a.path(!0);if(a._parts.query){for(var c="",f=0,g=a._parts.query.split("&"),k=g.length;f<k;f++){var l=(g[f]||"").split("="),c=c+("&"+d.decodeQuery(l[0],this._parts.escapeQuerySpace).replace(/&/g,"%26"));void 0!==l[1]&&(c+="="+d.decodeQuery(l[1],this._parts.escapeQuerySpace).replace(/&/g,"%26"))}b+="?"+c.substring(1)}return b+=d.decodeQuery(a.hash(),!0)};f.absoluteTo=function(a){var b=this.clone(),c=["protocol","username",\n
+"password","hostname","port"],e,f;if(this._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");a instanceof d||(a=new d(a));b._parts.protocol||(b._parts.protocol=a._parts.protocol);if(this._parts.hostname)return b;for(e=0;f=c[e];e++)b._parts[f]=a._parts[f];b._parts.path?".."===b._parts.path.substring(-2)&&(b._parts.path+="/"):(b._parts.path=a._parts.path,b._parts.query||(b._parts.query=a._parts.query));"/"!==b.path().charAt(0)&&(a=a.directory(),b._parts.path=(a?\n
+a+"/":"")+b._parts.path,b.normalizePath());b.build();return b};f.relativeTo=function(a){var b=this.clone().normalize(),c,e,f,g;if(b._parts.urn)throw Error("URNs do not have any generally defined hierarchical components");a=(new d(a)).normalize();c=b._parts;e=a._parts;f=b.path();g=a.path();if("/"!==f.charAt(0))throw Error("URI is already relative");if("/"!==g.charAt(0))throw Error("Cannot calculate a URI relative to another relative URI");c.protocol===e.protocol&&(c.protocol=null);if(c.username===\n
+e.username&&c.password===e.password&&null===c.protocol&&null===c.username&&null===c.password&&c.hostname===e.hostname&&c.port===e.port)c.hostname=null,c.port=null;else return b.build();if(f===g)return c.path="",b.build();a=d.commonPath(b.path(),a.path());if(!a)return b.build();e=e.path.substring(a.length).replace(/[^\\/]*$/,"").replace(/.*?\\//g,"../");c.path=e+c.path.substring(a.length);return b.build()};f.equals=function(a){var b=this.clone();a=new d(a);var c={},e={},f={},g;b.normalize();a.normalize();\n
+if(b.toString()===a.toString())return!0;c=b.query();e=a.query();b.query("");a.query("");if(b.toString()!==a.toString()||c.length!==e.length)return!1;c=d.parseQuery(c,this._parts.escapeQuerySpace);e=d.parseQuery(e,this._parts.escapeQuerySpace);for(g in c)if(w.call(c,g)){if(!l(c[g])){if(c[g]!==e[g])return!1}else if(!z(c[g],e[g]))return!1;f[g]=!0}for(g in e)if(w.call(e,g)&&!f[g])return!1;return!0};f.duplicateQueryParameters=function(a){this._parts.duplicateQueryParameters=!!a;return this};f.escapeQuerySpace=\n
+function(a){this._parts.escapeQuerySpace=!!a;return this};return d});\n
+(function(e,k){"object"===typeof exports?module.exports=k(require("./URI")):"function"===typeof define&&define.amd?define(["./URI"],k):k(e.URI)})(this,function(e){var k=e.prototype,u=k.fragment;e.fragmentPrefix="?";var m=e._parts;e._parts=function(){var d=m();d.fragmentPrefix=e.fragmentPrefix;return d};k.fragmentPrefix=function(d){this._parts.fragmentPrefix=d;return this};k.fragment=function(d,g){var k=this._parts.fragmentPrefix,l=this._parts.fragment||"";return!0===d?l.substring(0,k.length)!==k?\n
+{}:e.parseQuery(l.substring(k.length)):void 0!==d&&"string"!==typeof d?(this._parts.fragment=k+e.buildQuery(d),this.build(!g),this):u.call(this,d,g)};k.addFragment=function(d,g,k){var l=this._parts.fragmentPrefix,m=e.parseQuery((this._parts.fragment||"").substring(l.length));e.addQuery(m,d,g);this._parts.fragment=l+e.buildQuery(m);"string"!==typeof d&&(k=g);this.build(!k);return this};k.removeFragment=function(d,g,k){var l=this._parts.fragmentPrefix,m=e.parseQuery((this._parts.fragment||"").substring(l.length));\n
+e.removeQuery(m,d,g);this._parts.fragment=l+e.buildQuery(m);"string"!==typeof d&&(k=g);this.build(!k);return this};k.addHash=k.addFragment;k.removeHash=k.removeFragment;return{}});\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>38751</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/dhtmlxgantt.css.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/dhtmlxgantt.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fe243bd5b20b98bbdf7eb3068f31c4bcfa65a528
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/dhtmlxgantt.css.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681771.44</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>dhtmlxgantt.css</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/css</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*\n
+This software is allowed to use under GPL or you need to obtain Commercial or Enterise License \n
+ to use it in non-GPL project. Please contact sales@dhtmlx.com for details\n
+*/\n
+.gridHoverStyle{background-color:#fff3a1}.gridSelection{background-color:#fff3a1}.timelineSelection{background-color:#fff3a1}.gantt_grid_scale .gantt_grid_head_cell{color:#a6a6a6;border-top:0!important;border-right:0!important}.gantt_grid_data .gantt_cell{border-right:0;color:#454545}.gantt_task_link .gantt_link_arrow_right{border-width:6px;margin-top:-3px}.gantt_task_link .gantt_link_arrow_left{border-width:6px;margin-left:-6px;margin-top:-3px}.gantt_task_link .gantt_link_arrow_top{border-width:6px}.gantt_task_link .gantt_link_arrow_down{border-width:6px}.gantt_task_line .gantt_task_progress_drag{bottom:-4px;height:16px;margin-left:-8px;width:16px}.chartHeaderBg{background-color:#fff}.gantt_task .gantt_task_scale .gantt_scale_cell{color:#a6a6a6;border-right:1px solid #ebebeb}.gantt_row.gantt_project,.gantt_row.odd.gantt_project{background-color:#edffef}.gantt_task_row.gantt_project,.gantt_task_row.odd.gantt_project{background-color:#f5fff6}.gantt_task_line.gantt_project{background-color:#65c16f;border:1px solid #3c9445}.gantt_task_line.gantt_project .gantt_task_progress{background-color:#46ad51}.buttonBg{background:#fff}.dhx_cal_light .dhx_btn_set{margin:5px 10px}.dhx_btn_set.dhx_cancel_btn_set{background:#fff;color:#454545;border:1px solid #cecece}.dhx_btn_set.dhx_save_btn_set{background:#3db9d3;text-shadow:0 -1px 0 #248a9f;color:#fff}.dhx_btn_set.dhx_delete_btn_set{text-shadow:0 -1px 0 #6f6f6f;background:#ec8e00;text-shadow:0 -1px 0 #a60;color:#fff}.dhx_delete_btn{margin-top:2px;width:20px}.dhx_cal_light_wide{padding-left:0!important;padding-right:0!important}.dhx_cal_light_wide .dhx_cal_larea{border-left:0!important;border-right:0!important}.dhtmlx_popup_button.dhtmlx_ok_button{background:#3db9d3;text-shadow:0 -1px 0 #248a9f;color:#fff;font-weight:700;border-width:0}.dhtmlx_popup_button.dhtmlx_cancel_button{font-weight:700;color:#454544}.dhx_qi_big_icon.icon_edit{color:#454545;background:#fff}.dhx_qi_big_icon.icon_delete{text-shadow:0 -1px 0 #a60;background:#ec8e00;color:#fff;border-width:0}.gantt_container{font-family:Arial;font-size:13px;border:1px solid #cecece;position:relative;white-space:nowrap}.gantt_grid{border-right:1px solid #cecece}.gantt_task_scroll{overflow-x:scroll}.gantt_task{position:relative}.gantt_task,.gantt_grid{overflow-x:hidden;overflow-y:hidden;display:inline-block;vertical-align:top}.gantt_grid_scale,.gantt_task_scale{color:#6b6b6b;font-size:12px;border-bottom:1px solid #cecece}.gantt_grid_scale{background-color:#fff}.gantt_task_scale{background-color:#fff}.gantt_scale_line{box-sizing:border-box;-moz-box-sizing:border-box;border-top:1px solid #cecece}.gantt_scale_line:first-child{border-top:0}.gantt_grid_head_cell{display:inline-block;vertical-align:top;border-right:1px solid #cecece;text-align:center;position:relative;cursor:default;height:100%;box-sizing:border-box;-moz-box-sizing:border-box;line-height:33px;-moz-user-select:-moz-none;-webkit-user-select:none;-user-select:none}.gantt_scale_line{clear:both}.gantt_grid_data{width:100%;overflow:hidden}.gantt_row{position:relative;-webkit-user-select:none;-moz-user-select:none;-moz-user-select:-moz-none}.gantt_add,.gantt_grid_head_add{width:100%;height:100%;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTQ3MjMyMENDNkI0MTFFMjk4MTI5QTg3MDhFNDVDQTkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTQ3MjMyMERDNkI0MTFFMjk4MTI5QTg3MDhFNDVDQTkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1NDcyMzIwQUM2QjQxMUUyOTgxMjlBODcwOEU0NUNBOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1NDcyMzIwQkM2QjQxMUUyOTgxMjlBODcwOEU0NUNBOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PshZT8UAAABbSURBVHjaYrTdeZmBEsCER+4wEP+H4sPkGGCDg020ARR7gb4GIAcYDKMDdPnDyAbYkGG5DVW9cIQMvUdBBAuUY4vDz8iAcZinA2zgCHqAYQMseAywJcYFAAEGAM+UFGuohFczAAAAAElFTkSuQmCC);background-position:center center;background-repeat:no-repeat;cursor:pointer;position:relative;-moz-opacity:.3;opacity:.3}.gantt_grid_head_cell.gantt_grid_head_add{-moz-opacity:.6;opacity:.6;top:0}.gantt_grid_head_cell.gantt_grid_head_add:hover{-moz-opacity:1;opacity:1}.gantt_grid_data .gantt_row:hover,.gantt_grid_data .gantt_row.odd:hover{background-color:#fff3a1}.gantt_grid_data .gantt_row:hover .gantt_add,.gantt_grid_data .gantt_row.odd:hover .gantt_add{-moz-opacity:1;opacity:1}.gantt_task_row,.gantt_row{border-bottom:1px solid #ebebeb}.gantt_row,.gantt_task_row{background-color:#fff}.gantt_row.odd,.gantt_task_row.odd{background-color:#fff}.gantt_row,.gantt_cell,.gantt_task_row,.gantt_task_cell,.gantt_grid_head_cell,.gantt_scale_cell{box-sizing:border-box;-moz-box-sizing:border-box}.gantt_grid_head_cell,.gantt_scale_cell{line-height:inherit}.gantt_cell{display:inline-block;vertical-align:top;border-right:1px solid #ebebeb;padding-left:6px;padding-right:6px;height:100%;overflow:hidden;white-space:nowrap;font-size:13px}.gantt_grid_scale .gantt_last_cell,.gantt_grid_data .gantt_last_cell,.gantt_task_scale .gantt_last_cell,.gantt_task_bg .gantt_last_cell{border-right-width:0}.gantt_task_bg{overflow:hidden}.gantt_scale_cell{display:inline-block;white-space:nowrap;overflow:hidden;border-right:1px solid #cecece;text-align:center;height:100%}.gantt_task_cell{display:inline-block;height:100%;border-right:1px solid #ebebeb}.gantt_ver_scroll{width:0;background-color:transparent;height:1px;overflow-x:hidden;overflow-y:scroll;display:none;position:absolute;right:0}.gantt_ver_scroll>div{width:1px;height:1px}.gantt_hor_scroll{height:0;background-color:transparent;width:100%;clear:both;overflow-x:scroll;overflow-y:hidden;display:none}.gantt_hor_scroll>div{width:5000px;height:1px}.gantt_tree_indent{width:15px;height:100%;display:inline-block}.gantt_tree_content,.gantt_tree_icon{vertical-align:top}.gantt_tree_icon{width:28px;height:100%;display:inline-block;background-repeat:no-repeat;background-position:center center}.gantt_tree_content{height:100%;display:inline-block}.gantt_tree_icon.gantt_open{background-image:url(data:image/gif;base64,R0lGODlhEgASALMJAMrKyt3d3ejp6d7f3+/v75aWlvf39////wAAAP///wAAAAAAAAAAAAAAAAAAAAAAACH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6M0I5RTczQjVDMDdBMTFFMTgxRjc4Mzk4M0Q3MjVFQzAiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6M0I5RTczQjZDMDdBMTFFMTgxRjc4Mzk4M0Q3MjVFQzAiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozQjlFNzNCM0MwN0ExMUUxODFGNzgzOTgzRDcyNUVDMCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozQjlFNzNCNEMwN0ExMUUxODFGNzgzOTgzRDcyNUVDMCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAEAAAkALAAAAAASABIAAARJMMlJq704661B+SAIXAVhnKhBFKSZnmuLImhslXPN3ibi+6pdBXc4IIpB2YkGE1IKAoL0ICUInJNCYMDtDgJYiScUGnHO6LQkAgA7);width:18px;cursor:pointer}.gantt_tree_icon.gantt_close{background-image:url(data:image/gif;base64,R0lGODlhEgASALMJAMrKyt3d3ejp6d7f3+/v75aWlvf39wAAAP///////wAAAAAAAAAAAAAAAAAAAAAAACH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MzY0QzNGM0VDMDdBMTFFMUE3MDlCNUM2QjU1NDA5RjgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MzY0QzNGM0ZDMDdBMTFFMUE3MDlCNUM2QjU1NDA5RjgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDozNjRDM0YzQ0MwN0ExMUUxQTcwOUI1QzZCNTU0MDlGOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDozNjRDM0YzREMwN0ExMUUxQTcwOUI1QzZCNTU0MDlGOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAEAAAkALAAAAAASABIAAARDMMlJq704661B+SAIXAVhnKhBFKSZnmv7wqxVzmpd3Uff5zKEUAi0uV4xm4DAbBIEOkohMKhaB4HoxBMKjTjgsFgSAQA7);width:18px;cursor:pointer}.gantt_tree_icon.gantt_blank{width:18px}.gantt_tree_icon.gantt_folder_open{background-image:url(data:image/gif;base64,R0lGODlhEgASAJECAJeXl7Gvrf///wAAACH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTdDRDM3QzVDMDZEMTFFMUJGMzhFMDhCN0RGRjBGQ0YiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTdDRDM3QzZDMDZEMTFFMUJGMzhFMDhCN0RGRjBGQ0YiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1N0NEMzdDM0MwNkQxMUUxQkYzOEUwOEI3REZGMEZDRiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1N0NEMzdDNEMwNkQxMUUxQkYzOEUwOEI3REZGMEZDRiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAEAAAIALAAAAAASABIAAAIzlI+pywcPm3mhWgkCsjBOvVkimElG9ZlCBlXd+2XjjLKg5GqoeZXqvsOQXK/ijUZTKVUFADs=)}.gantt_tree_icon.gantt_folder_closed{background-image:url(data:image/gif;base64,R0lGODlhEgASAJECAJeXl7Gvrf///wAAACH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NTAyMTU1RTNDMDZEMTFFMUJGNzZCRThBRkFCRjg4MTIiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NTAyMTU1RTRDMDZEMTFFMUJGNzZCRThBRkFCRjg4MTIiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MDIxNTVFMUMwNkQxMUUxQkY3NkJFOEFGQUJGODgxMiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MDIxNTVFMkMwNkQxMUUxQkY3NkJFOEFGQUJGODgxMiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAEAAAIALAAAAAASABIAAAIwlI+pywcPm3mhWgkCsjBOvVkimElG9ZlCuYIY6TYs+6bmHDO4igfdD3GNhheV0VQAADs=)}.gantt_tree_icon.gantt_file{background-image:url(data:image/gif;base64,R0lGODlhEgASAJECAJeXl7Gvrf///wAAACH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4wLWMwNjAgNjEuMTM0Nzc3LCAyMDEwLzAyLzEyLTE3OjMyOjAwICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NzkxQzI4RjZDMDZEMTFFMTgwRjhBQURDQzI3NDU3QUEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6NzkxQzI4RjdDMDZEMTFFMTgwRjhBQURDQzI3NDU3QUEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo3OTFDMjhGNEMwNkQxMUUxODBGOEFBRENDMjc0NTdBQSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo3OTFDMjhGNUMwNkQxMUUxODBGOEFBRENDMjc0NTdBQSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAEAAAIALAAAAAASABIAAAIylI+pwN16QJiUQiFThRlJm3RRFYSlR5qXMKmXaMDuuMoyOi8n/e6xn8NMHETgh5RaKQsAOw==)}.gantt_grid_head_cell .gantt_sort{position:absolute;right:5px;top:8px;width:7px;height:13px;background-repeat:no-repeat;background-position:center center}.gantt_grid_head_cell .gantt_sort.gantt_asc{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAANCAYAAABlyXS1AAAARUlEQVR4nGNgQAKGxib/GbABkIS7b8B/DAUwCRiGK0CXwFBAb1DfP/U/LszwHwi2X7qFgUEArBtdAVwCBmAKMCSQFSDzAWXXaOHsXeqkAAAAAElFTkSuQmCC)}.gantt_grid_head_cell .gantt_sort.gantt_desc{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAANCAYAAABlyXS1AAAARUlEQVR42mNgQAL1/VP/M2ADIIntF2/9x1AAlrh0C47hCmA60DFYwX88gIFGwNDY5D8uDFbg7hvwHx2jmIBTAlkB0e4BAEjlaNtBWJPnAAAAAElFTkSuQmCC)}.gantt_inserted,.gantt_updated{font-weight:700}.gantt_deleted{text-decoration:line-through}.gantt_invalid{background-color:FFE0E0}.gantt_error{color:red}.dhtmlx_message_area{position:fixed;right:5px;width:250px;z-index:1000}.dhtmlx-info{min-width:120px;padding:4px 4px 4px 20px;font-family:Arial;z-index:10000;margin:5px;margin-bottom:10px;-webkit-transition:all .5s ease;-moz-transition:all .5s ease;-o-transition:all .5s ease;transition:all .5s ease}.dhtmlx-info.hidden{height:0;padding:0;border-width:0;margin:0;overflow:hidden}.dhtmlx_modal_box{overflow:hidden;display:inline-block;min-width:250px;width:250px;text-align:center;position:fixed;z-index:20000;box-shadow:3px 3px 3px rgba(0,0,0,.07);font-family:Arial;border-radius:6px;border:1px solid #cecece;background:#fff}.dhtmlx_popup_title{border-top-left-radius:6px;border-top-right-radius:6px;border-width:0}.dhtmlx_button,.dhtmlx_popup_button{border:1px solid #cecece;height:30px;line-height:30px;display:inline-block;margin:0 5px;border-radius:4px;background:#fff}.dhtmlx-info,.dhtmlx_popup_button,.dhtmlx_button{user-select:none;-webkit-user-select:none;-moz-user-select:-moz-none;cursor:pointer}.dhtmlx_popup_text{overflow:hidden}.dhtmlx_popup_controls{border-radius:6px;padding:10px}.dhtmlx_popup_button{min-width:100px}div.dhx_modal_cover{background-color:#000;cursor:default;filter:alpha(opacity=20);opacity:.2;position:fixed;z-index:19999;left:0;top:0;width:100%;height:100%;border:0;zoom:1}.dhtmlx-info img,.dhtmlx_modal_box img{float:left;margin-right:20px}.dhtmlx-alert-error,.dhtmlx-confirm-error{border:1px solid red}.dhtmlx_button input,.dhtmlx_popup_button div{border-radius:4px;font-size:14px;-moz-box-sizing:content-box;box-sizing:content-box;padding:0;margin:0;vertical-align:top}.dhtmlx_popup_title{color:#fff;text-shadow:1px 1px #000;height:40px;line-height:40px;font-size:20px}.dhtmlx_popup_text{margin:15px 15px 5px;font-size:14px;color:#000;min-height:30px;border-radius:6px}.dhtmlx-info,.dhtmlx-error{font-size:14px;color:#000;box-shadow:3px 3px 3px rgba(0,0,0,.07);padding:0;background-color:#FFF;border-radius:3px;border:1px solid #fff}.dhtmlx-info div{padding:5px 10px;background-color:#fff;border-radius:3px;border:1px solid #cecece}.dhtmlx-error{background-color:#d81b1b;border:1px solid #ff3c3c;box-shadow:3px 3px 3px rgba(0,0,0,.07)}.dhtmlx-error div{background-color:#d81b1b;border:1px solid #940000;color:#FFF}.gantt_grid div,.gantt_data_area div{-ms-touch-action:none;-webkit-tap-highlight-color:rgba(0,0,0,0)}.gantt_data_area{position:relative;overflow-x:hidden;overflow-y:hidden;-moz-user-select:-moz-none;-webkit-user-select:none;-user-select:none}.gantt_links_area{position:absolute;left:0;top:0}.gantt_task_content,.gantt_task_progress,.gantt_side_content{line-height:inherit;overflow:hidden;height:100%}.gantt_task_content{font-size:12px;color:#fff;position:absolute;white-space:nowrap;text-align:center}.gantt_task_progress{text-align:center;z-index:0;background:#299cb4}.gantt_task_line{-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;position:absolute;-moz-box-sizing:border-box;box-sizing:border-box;background-color:#3db9d3;border:1px solid #2898b0;-webkit-user-select:none;-moz-user-select:none;-moz-user-select:-moz-none}.gantt_task_line.gantt_drag_move div{cursor:move}.gantt_side_content{position:absolute;white-space:nowrap;color:#6e6e6e;bottom:7px;font-size:11px}.gantt_side_content.gantt_left{right:100%;padding-right:15px}.gantt_side_content.gantt_right{left:100%;padding-left:15px}.gantt_side_content.gantt_link_crossing{bottom:8.75px}.gantt_task_link .gantt_line_wrapper,.gantt_link_arrow{position:absolute;cursor:pointer}.gantt_line_wrapper div{background-color:#ffa011}.gantt_task_link:hover .gantt_line_wrapper div{box-shadow:0 0 5px 0 #ffa011}.gantt_task_link div.gantt_link_arrow{background-color:transparent;border-style:solid;width:0;height:0}.gantt_link_control{position:absolute;width:13px;top:0}.gantt_link_control div{display:none;cursor:pointer;box-sizing:border-box;position:relative;top:50%;margin-top:-7.5px;vertical-align:middle;border:1px solid #929292;-webkit-border-radius:6.5px;-moz-border-radius:6.5px;border-radius:6.5px;height:13px;width:13px;background-color:#f0f0f0}.gantt_link_control div:hover{background-color:#fff}.gantt_link_control.task_left{left:-13px}.gantt_link_control.task_right{right:-13px}.gantt_task_line.gantt_selected .gantt_link_control div,.gantt_task_line:hover .gantt_link_control div{display:block}.gantt_link_target .gantt_link_control div{display:block}.gantt_link_source,.gantt_link_target{box-shadow:0 0 3px #3db9d3}.gantt_link_target.link_start_allow,.gantt_link_target.link_finish_allow{box-shadow:0 0 3px #ffbf5e}.gantt_link_target.link_start_deny,.gantt_link_target.link_finish_deny{box-shadow:0 0 3px #e87e7b}.link_start_allow .gantt_link_control.task_left div,.link_finish_allow .gantt_link_control.task_right div{background-color:#ffbf5e;border-color:#ffa011}.link_start_deny .gantt_link_control.task_left div,.link_finish_deny .gantt_link_control.task_right div{background-color:#e87e7b;border-color:#dd3e3a}.gantt_link_arrow_right{border-width:4px 0 4px 6px;border-color:transparent transparent transparent #ffa011;margin-top:-1px}.gantt_link_arrow_left{border-width:4px 6px 4px 0;margin-top:-1px;border-color:transparent #ffa011 transparent transparent}.gantt_link_arrow_top{border-width:0 4px 6px;border-color:transparent transparent #ffa011}.gantt_link_arrow_down{border-width:4px 6px 0 4px;border-color:#ffa011 transparent transparent}.gantt_task_drag,.gantt_task_progress_drag{cursor:w-resize;height:100%;display:none;position:absolute}.gantt_task_line.gantt_selected .gantt_task_progress_drag,.gantt_task_line:hover .gantt_task_progress_drag,.gantt_task_line.gantt_selected .gantt_task_drag,.gantt_task_line:hover .gantt_task_drag{display:block}.gantt_task_drag{width:6px;background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAACCAYAAAB7Xa1eAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QYDDjkw3UJvAwAAABRJREFUCNdj/P//PwM2wASl/6PTAKrrBf4+lD8LAAAAAElFTkSuQmCC);z-index:1;top:0}.gantt_task_drag.task_left{left:0}.gantt_task_drag.task_right{right:0}.gantt_task_progress_drag{height:8px;width:8px;bottom:-4px;margin-left:-4px;background-position:bottom;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MkY3Rjk0RUVDMkYzMTFFMkI1OThEQTA3ODU0OTkzMEEiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MkY3Rjk0RUZDMkYzMTFFMkI1OThEQTA3ODU0OTkzMEEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyRjdGOTRFQ0MyRjMxMUUyQjU5OERBMDc4NTQ5OTMwQSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyRjdGOTRFREMyRjMxMUUyQjU5OERBMDc4NTQ5OTMwQSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PobPBzIAAADkSURBVHjaYpk2bRoDDsAExL1QdjEQ/8OmiAWHZk4gXqymqhQM4ty6fU8OSMUA8XdiDBAB4k0a6iqWRga6EKcwMQXduHlnL5DpB8Rv0J2JDFSA+JiOtgZcMwiA2CAxkBxUDVYDLEAKgIpV9XQ0MZwFEgPJAZnHoWpRDAgC4n2W5saiQKfjClQGkBxQDciL+6B6wAbkA/EqJwdrTkUFOQZCAKQGpBbIXA3SCzJggo+XK7OEuBgDsQCkFqgHrBfsBT5eHgZSAUwP2IBfv36TbABMDygdtK1Zv6UESLORaAbIhG6AAAMAKN8wE24DXWcAAAAASUVORK5CYII=);background-repeat:no-repeat;z-index:2}.gantt_link_tooltip{box-shadow:3px 3px 3px #888;background-color:#fff;border-left:1px dotted #cecece;border-top:1px dotted #cecece;font-family:Tahoma;font-size:8pt;color:#444;padding:6px;line-height:20px}.gantt_link_direction{height:0;border:0 none #ffa011;border-bottom-style:dashed;border-bottom-width:2px;transform-origin:0 0;-ms-transform-origin:0 0;-webkit-transform-origin:0 0;z-index:2;margin-left:1px;position:absolute}.gantt_grid_data .gantt_row.gantt_selected,.gantt_grid_data .gantt_row.odd.gantt_selected{background-color:#fff3a1}.gantt_task_row.gantt_selected{background-color:#fff3a1}.gantt_task_row.gantt_selected .gantt_task_cell{border-right-color:#ffec6e}.gantt_task_line.gantt_selected{box-shadow:0 0 5px #299cb4}.gantt_task_line.gantt_project.gantt_selected{box-shadow:0 0 5px #46ad51}.dhx_unselectable,.dhx_unselectable div{-webkit-user-select:none;-moz-user-select:none;-moz-user-select:-moz-none}.dhx_cal_light{-webkit-tap-highlight-color:transparent;background:#fff;border-radius:6px;font-family:Arial;font-size:13px;border:1px solid #cecece;color:#6b6b6b;font-size:12px;position:absolute;z-index:10001;width:550px;height:250px;box-shadow:3px 3px 3px rgba(0,0,0,.07)}.dhx_cal_light_wide{width:650px}.dhx_cal_light select{font-family:Arial;border:1px solid #cecece;font-size:13px;padding:2px;margin:0}.dhx_cal_ltitle{padding:7px 10px;overflow:hidden;white-space:nowrap;-webkit-border-top-left-radius:6px;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:6px;-webkit-border-bottom-right-radius:0;-moz-border-radius-topleft:6px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:0;border-top-left-radius:6px;border-bottom-left-radius:0;border-top-right-radius:6px;border-bottom-right-radius:0}.dhx_cal_ltitle span{white-space:nowrap}.dhx_cal_lsection{color:#727272;font-weight:700;padding:12px 0 5px 10px}.dhx_cal_lsection .dhx_fullday{float:right;margin-right:5px;font-size:12px;font-weight:400;line-height:20px;vertical-align:top;cursor:pointer}.dhx_cal_lsection{font-size:13px}.dhx_cal_ltext{padding:2px 10px;overflow:hidden}.dhx_cal_ltext textarea{overflow:auto;font-family:Arial;font-size:13px;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #cecece;height:100%;width:100%;outline:0!important;resize:none}.dhx_time{font-weight:700}.dhx_cal_light .dhx_title{padding-left:10px}.dhx_cal_larea{border:1px solid #cecece;border-left:0;border-right:0;background-color:#fff;overflow:hidden;height:1px}.dhx_btn_set{margin:10px 7px 5px 10px;padding:5px 15px 5px 10px;float:left;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;border-width:0;border-color:#cecece;border-style:solid;height:32px;font-weight:700;background:#fff;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;cursor:pointer}.dhx_btn_set div{float:left;font-size:13px;height:22px;line-height:22px;background-repeat:no-repeat;vertical-align:middle}.dhx_save_btn{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTk1OUU5RDFDMzA0MTFFMkExMUZBQTdDNDAzOUE5RjMiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTk1OUU5RDJDMzA0MTFFMkExMUZBQTdDNDAzOUE5RjMiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoxOTU5RTlDRkMzMDQxMUUyQTExRkFBN0M0MDM5QTlGMyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoxOTU5RTlEMEMzMDQxMUUyQTExRkFBN0M0MDM5QTlGMyIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PjDroXYAAAEXSURBVHjaYvz//z8DJYCRUgPIAUxAbAnEHiAHMIBcQCwGaRYXF3e6evXqoffv39/dv38/CymaGSUkJBzv3LlzCsj///fv3wdAihkkIQnEvkAshU8zLy+v7a1bt06ANP/79+87kDIAy505cybq06dPr3p7ezuwGQLTfOPGjWP/ESAZLg8kPKBO+g01RBJNszWyZqC6uSgWgIg/f/4shxnS2dnZBjMEqNkSFGBImi8CKTYMA4BYCGjIczRDHC5dunQQSfN7IKWI4UUkjjdMMdCwnw8ePLjwHxV4Yw1gZA5Q47z/2EELzhhCE+ABGvIQWSeQvwcU38QaAML2wHj+C/X3MyAlijeB4ZBoBOIPQGxJKIVSnBsBAgwABddBclWfcZUAAAAASUVORK5CYII=);margin-top:2px;width:21px}.dhx_cancel_btn{margin-top:2px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDkzMDA3MzlDMzA0MTFFMjg2QTVFMzFEQzgwRkJERDYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MDkzMDA3M0FDMzA0MTFFMjg2QTVFMzFEQzgwRkJERDYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowOTMwMDczN0MzMDQxMUUyODZBNUUzMURDODBGQkRENiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowOTMwMDczOEMzMDQxMUUyODZBNUUzMURDODBGQkRENiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmYuYOUAAAEdSURBVHjaYvz//z8DJYAFXWDlypU8QKoIiD2A2AwqfAqIdwBxX3h4+Bdk9YzILgBqtgdS84FYEYeF94E4EWjIQZgAE5LmQCB1AKoZZKMPEAtAMYh9GSp3AKjWD8UFQAEhIPshEIOc3wHENUBb/qJ57SyQMoJyPwKxElDNO1gYFEE17wMKVmIJlzNQzeegrjaA6qmBecEbSvfh0GwMxGeBhoPoemQ9MAO0kEIbl2YTqPAFKK2IbMB3AjabYIkRZmQD7kNpMyI0G0PpO8gGbIUFJj7NQDk2INWIrIcJKfBAKcwJqvkcDs0TgFgXGo19KCkRmpDWQdWDEk0NUoCBoq0FqhkE/IEWbKJKUmZEz43QzFSKIzN1481M5ACAAAMAlfl/lCwRpagAAAAASUVORK5CYII=);width:20px}.dhx_delete_btn{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjFENzI3NUNDMzA0MTFFMjhBNjJGQTc3MUIyQzYzNEYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjFENzI3NURDMzA0MTFFMjhBNjJGQTc3MUIyQzYzNEYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyMUQ3Mjc1QUMzMDQxMUUyOEE2MkZBNzcxQjJDNjM0RiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyMUQ3Mjc1QkMzMDQxMUUyOEE2MkZBNzcxQjJDNjM0RiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmUD0gAAAABvSURBVHjaYvz//z8DIyMjAxYQicReji4J0ofKQNP8HwmgGQbXB8IsWGwDSSwDuioKjY9uBthVjFAXYHUGAQA2kYmBUoAUBpGk0LAwgBvwH+YX4mkwptgLowYMRgOITUyYKRFIN/wnDjQgJySAAAMApryKzL8wjfUAAAAASUVORK5CYII=);margin-top:2px;width:20px}.dhx_cal_cover{width:100%;height:100%;position:absolute;z-index:10000;top:0;left:0;background-color:#000;opacity:.1;filter:alpha(opacity=10)}.dhx_custom_button{padding:0 3px;font-family:Arial;font-size:13px;font-weight:400;margin-right:5px;margin-top:0;cursor:pointer}.dhx_custom_button div{cursor:pointer;float:left;height:21px;line-height:21px;vertical-align:middle}.dhx_cal_light_wide{width:580px;padding:2px 4px}.dhx_cal_light_wide .dhx_cal_larea{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;border:1px solid #cecece}.dhx_cal_light_wide .dhx_cal_lsection{border:0;float:left;text-align:right;width:80px;height:20px;padding:5px 10px 0 0}.dhx_cal_light_wide .dhx_wrap_section{position:relative;padding:10px 0;overflow:hidden;border-bottom:1px solid #ebebeb}.dhx_cal_light_wide .dhx_section_time{overflow:hidden;padding-top:2px!important;padding-right:0;height:20px!important}.dhx_cal_light_wide .dhx_cal_ltext{padding-right:0}.dhx_cal_light_wide .dhx_cal_larea{padding:0 10px;width:100%}.dhx_cal_light_wide .dhx_section_time{background:transparent}.dhx_cal_light_wide .dhx_cal_checkbox label{padding-left:0}.dhx_cal_light_wide .dhx_cal_lsection .dhx_fullday{float:none;margin-right:0;font-weight:700;cursor:pointer}.dhx_cal_light_wide .dhx_custom_button{position:absolute;top:0;right:0;margin-top:2px}.dhx_cal_light_wide .dhx_repeat_right{margin-right:55px}.dhx_cal_light_wide.dhx_cal_light_full{width:738px}.dhx_cal_wide_checkbox input{margin-top:8px;margin-left:14px}.dhx_cal_light input{font-size:13px}.dhx_custom_button{float:right;height:21px;width:90px;-webkit-border-radius:4px;-moz-border-radius:4px;-ms-border-radius:4px;-o-border-radius:4px;border-radius:4px}.dhx_section_time{background-color:#fff;white-space:nowrap;padding:2px 10px 5px;padding-top:2px!important}.dhx_section_time .dhx_time_selects{float:left;height:25px}.dhx_section_time .dhx_time_selects select{height:23px;padding:2px;border:1px solid #cecece}.dhx_gantt_duration{width:100px;height:23px;float:left;white-space:nowrap;margin-left:20px;line-height:23px}.dhx_gantt_duration .dhx_gantt_duration_value,.dhx_gantt_duration .dhx_gantt_duration_dec,.dhx_gantt_duration .dhx_gantt_duration_inc{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;text-align:center;vertical-align:top;height:100%;border:1px solid #cecece}.dhx_gantt_duration .dhx_gantt_duration_value{width:40px;padding:3px 4px;border-left-width:0;border-right-width:0}.dhx_gantt_duration .dhx_gantt_duration_dec,.dhx_gantt_duration .dhx_gantt_duration_inc{width:20px;padding:1px;padding-bottom:3px;background:#fff}.dhx_gantt_duration .dhx_gantt_duration_dec{-moz-border-top-left-radius:4px;-moz-border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;-webkit-border-bottom-left-radius:4px;border-top-left-radius:4px;border-bottom-left-radius:4px}.dhx_gantt_duration .dhx_gantt_duration_inc{margin-right:4px;-moz-border-top-right-radius:4px;-moz-border-bottom-right-radius:4px;-webkit-border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-top-right-radius:4px;border-bottom-right-radius:4px}.dhx_cal_quick_info{border:1px solid #cecece;border-radius:6px;position:absolute;z-index:300;box-shadow:3px 3px 3px rgba(0,0,0,.07);background-color:#fff;width:300px;transition:left .5s ease,right .5s;-moz-transition:left .5s ease,right .5s;-webkit-transition:left .5s ease,right .5s;-o-transition:left .5s ease,right .5s}.dhx_no_animate{transition:none;-moz-transition:none;-webkit-transition:none;-o-transition:none}.dhx_cal_quick_info.dhx_qi_left .dhx_qi_big_icon{float:right}.dhx_cal_qi_title{-webkit-border-top-left-radius:6px;-webkit-border-bottom-left-radius:0;-webkit-border-top-right-radius:6px;-webkit-border-bottom-right-radius:0;-moz-border-radius-topleft:6px;-moz-border-radius-bottomleft:0;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:0;border-top-left-radius:6px;border-bottom-left-radius:0;border-top-right-radius:6px;border-bottom-right-radius:0;padding:5px 0 8px 12px;color:#454545;background-color:#fff;border-bottom:1px solid #cecece}.dhx_cal_qi_tdate{font-size:14px;font-weight:700}.dhx_cal_qi_tcontent{font-size:13px}.dhx_cal_qi_content{padding:16px 8px;font-size:13px;color:#454545;overflow:hidden}.dhx_cal_qi_controls{-webkit-border-top-left-radius:0;-webkit-border-bottom-left-radius:6px;-webkit-border-top-right-radius:0;-webkit-border-bottom-right-radius:6px;-moz-border-radius-topleft:0;-moz-border-radius-bottomleft:6px;-moz-border-radius-topright:0;-moz-border-radius-bottomright:6px;border-top-left-radius:0;border-bottom-left-radius:6px;border-top-right-radius:0;border-bottom-right-radius:6px;padding-left:7px}.dhx_cal_qi_controls .dhx_menu_icon{margin-top:6px;background-repeat:no-repeat}.dhx_cal_qi_controls .dhx_menu_icon.icon_edit{width:20px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH3QYFCjI5ZQj5bAAAAFNJREFUOMvt0zEOACAIA0DkwTymH8bJTRTKZGJXyaWEKPKTCQAH4Ls37cItcDUzsxHNDLZNhCq7Gt1wh9ErV7EjyGAhyGLphlnsClWuS32rn0czAV+vNGrM/LBtAAAAAElFTkSuQmCC)}.dhx_cal_qi_controls .dhx_menu_icon.icon_delete{width:20px;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MjFENzI3NUNDMzA0MTFFMjhBNjJGQTc3MUIyQzYzNEYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MjFENzI3NURDMzA0MTFFMjhBNjJGQTc3MUIyQzYzNEYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoyMUQ3Mjc1QUMzMDQxMUUyOEE2MkZBNzcxQjJDNjM0RiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoyMUQ3Mjc1QkMzMDQxMUUyOEE2MkZBNzcxQjJDNjM0RiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PmUD0gAAAABvSURBVHjaYvz//z8DIyMjAxYQicReji4J0ofKQNP8HwmgGQbXB8IsWGwDSSwDuioKjY9uBthVjFAXYHUGAQA2kYmBUoAUBpGk0LAwgBvwH+YX4mkwptgLowYMRgOITUyYKRFIN/wnDjQgJySAAAMApryKzL8wjfUAAAAASUVORK5CYII=)}.dhx_qi_big_icon{font-size:13px;border-radius:4px;font-weight:700;background:#fff;margin:5px 9px 8px 0;min-width:60px;line-height:32px;vertical-align:middle;padding:0 10px 0 5px;cursor:pointer;border:1px solid #cecece}.dhx_cal_qi_controls div{float:left;height:32px;text-align:center;line-height:32px}.gantt_tooltip{box-shadow:3px 3px 3px rgba(0,0,0,.07);background-color:#fff;border-left:1px solid rgba(0,0,0,.07);border-top:1px solid rgba(0,0,0,.07);font-family:Arial;font-size:8pt;color:#454545;padding:10px;position:absolute;z-index:500}.gantt_noselect{-moz-user-select:-moz-none;-webkit-user-select:none;-user-select:none}.gantt_drag_marker{position:absolute;font-family:Arial;font-size:13px}.gantt_drag_marker .gantt_tree_indent,.gantt_drag_marker .gantt_tree_icon.gantt_blank,.gantt_drag_marker .gantt_tree_icon.gantt_open,.gantt_drag_marker .gantt_tree_icon.gantt_close{display:none}.gantt_drag_marker,.gantt_drag_marker .gantt_row.odd{background-color:#fff}.gantt_drag_marker .gantt_row{border-left:1px solid #d2d2d2;border-top:1px solid #d2d2d2}.gantt_drag_marker .gantt_cell{border-color:#d2d2d2}.gantt_row.gantt_over,.gantt_task_row.gantt_over{background-color:#0070fe}.gantt_row.gantt_transparent .gantt_cell{opacity:.7}.gantt_task_row.gantt_transparent{background-color:#f8fdfd}.dhtmlx_popup_button.dhtmlx_delete_button{background:#3db9d3;text-shadow:0 -1px 0 #248a9f;color:#fff;font-weight:700;border-width:0}
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>39454</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/dhtmlxgantt.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/dhtmlxgantt.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..68b1baf0d2d9c047323a295ec70526a87897b8aa
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/dhtmlxgantt.js.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681771.55</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>dhtmlxgantt.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>123993</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*\n
+This software is allowed to use under GPL or you need to obtain Commercial or Enterise License \n
+ to use it in non-GPL project. Please contact sales@dhtmlx.com for details\n
+*/\n
+function dtmlXMLLoaderObject(t,e,n,i){return this.xmlDoc="",this.async="undefined"!=typeof n?n:!0,this.onloadAction=t||null,this.mainObject=e||null,this.waitCall=null,this.rSeed=i||!1,this}function callerFunction(t,e){return this.handler=function(n){return n||(n=window.event),t(n,e),!0},this.handler}function getAbsoluteLeft(t){return getOffset(t).left}function getAbsoluteTop(t){return getOffset(t).top}function getOffsetSum(t){for(var e=0,n=0;t;)e+=parseInt(t.offsetTop),n+=parseInt(t.offsetLeft),t=t.offsetParent;return{top:e,left:n}}function getOffsetRect(t){var e=t.getBoundingClientRect(),n=document.body,i=document.documentElement,a=window.pageYOffset||i.scrollTop||n.scrollTop,r=window.pageXOffset||i.scrollLeft||n.scrollLeft,s=i.clientTop||n.clientTop||0,o=i.clientLeft||n.clientLeft||0,d=e.top+a-s,l=e.left+r-o;return{top:Math.round(d),left:Math.round(l)}}function getOffset(t){return t.getBoundingClientRect?getOffsetRect(t):getOffsetSum(t)}function convertStringToBoolean(t){switch("string"==typeof t\046\046(t=t.toLowerCase()),t){case"1":case"true":case"yes":case"y":case 1:case!0:return!0;default:return!1}}function getUrlSymbol(t){return-1!=t.indexOf("?")?"\046":"?"}function dhtmlDragAndDropObject(){return window.dhtmlDragAndDrop?window.dhtmlDragAndDrop:(this.lastLanding=0,this.dragNode=0,this.dragStartNode=0,this.dragStartObject=0,this.tempDOMU=null,this.tempDOMM=null,this.waitDrag=0,window.dhtmlDragAndDrop=this,this)}function _dhtmlxError(){return this.catches||(this.catches=new Array),this}function dhtmlXHeir(t,e){for(var n in e)"function"==typeof e[n]\046\046(t[n]=e[n]);return t}function dhtmlxEvent(t,e,n){t.addEventListener?t.addEventListener(e,n,!1):t.attachEvent\046\046t.attachEvent("on"+e,n)}function dhtmlxDetachEvent(t,e,n){t.removeEventListener?t.removeEventListener(e,n,!1):t.detachEvent\046\046t.detachEvent("on"+e,n)}function dhtmlxDnD(t,e){e\046\046(this._settings=e),dhtmlxEventable(this),dhtmlxEvent(t,"mousedown",dhtmlx.bind(function(e){this.dragStart(t,e)},this))}function dataProcessor(t){return this.serverProcessor=t,this.action_param="!nativeeditor_status",this.object=null,this.updatedRows=[],this.autoUpdate=!0,this.updateMode="cell",this._tMode="GET",this.post_delim="_",this._waitMode=0,this._in_progress={},this._invalid={},this.mandatoryFields=[],this.messages=[],this.styles={updated:"font-weight:bold;",inserted:"font-weight:bold;",deleted:"text-decoration : line-through;",invalid:"background-color:FFE0E0;",invalid_cell:"border-bottom:2px solid red;",error:"color:red;",clear:"font-weight:normal;text-decoration:none;"},this.enableUTFencoding(!0),dhtmlxEventable(this),this}dhtmlx=function(t){for(var e in t)dhtmlx[e]=t[e];return dhtmlx},dhtmlx.extend_api=function(t,e,n){var i=window[t];i\046\046(window[t]=function(t){if(t\046\046"object"==typeof t\046\046!t.tagName){var n=i.apply(this,e._init?e._init(t):arguments);for(var a in dhtmlx)e[a]\046\046this[e[a]](dhtmlx[a]);for(var a in t)e[a]?this[e[a]](t[a]):0==a.indexOf("on")\046\046this.attachEvent(a,t[a])}else var n=i.apply(this,arguments);return e._patch\046\046e._patch(this),n||this},window[t].prototype=i.prototype,n\046\046dhtmlXHeir(window[t].prototype,n))},dhtmlxAjax={get:function(t,e){var n=new dtmlXMLLoaderObject(!0);return n.async=arguments.length\0743,n.waitCall=e,n.loadXML(t),n},post:function(t,e,n){var i=new dtmlXMLLoaderObject(!0);return i.async=arguments.length\0744,i.waitCall=n,i.loadXML(t,!0,e),i},getSync:function(t){return this.get(t,null,!0)},postSync:function(t,e){return this.post(t,e,null,!0)}},dtmlXMLLoaderObject.count=0,dtmlXMLLoaderObject.prototype.waitLoadFunction=function(t){var e=!0;return this.check=function(){if(t\046\046null!=t.onloadAction\046\046(!t.xmlDoc.readyState||4==t.xmlDoc.readyState)){if(!e)return;e=!1,dtmlXMLLoaderObject.count++,"function"==typeof t.onloadAction\046\046t.onloadAction(t.mainObject,null,null,null,t),t.waitCall\046\046(t.waitCall.call(this,t),t.waitCall=null)}},this.check},dtmlXMLLoaderObject.prototype.getXMLTopNode=function(t,e){if(this.xmlDoc.responseXML){var n=this.xmlDoc.responseXML.getElementsByTagName(t);if(0==n.length\046\046-1!=t.indexOf(":"))var n=this.xmlDoc.responseXML.getElementsByTagName(t.split(":")[1]);var i=n[0]}else var i=this.xmlDoc.documentElement;if(i)return this._retry=!1,i;if(!this._retry\046\046_isIE){this._retry=!0;var e=this.xmlDoc;return this.loadXMLString(this.xmlDoc.responseText.replace(/^[\\s]+/,""),!0),this.getXMLTopNode(t,e)}return dhtmlxError.throwError("LoadXML","Incorrect XML",[e||this.xmlDoc,this.mainObject]),document.createElement("DIV")},dtmlXMLLoaderObject.prototype.loadXMLString=function(t,e){if(_isIE)this.xmlDoc=new ActiveXObject("Microsoft.XMLDOM"),this.xmlDoc.async=this.async,this.xmlDoc.onreadystatechange=function(){},this.xmlDoc.loadXML(t);else{var n=new DOMParser;this.xmlDoc=n.parseFromString(t,"text/xml")}e||(this.onloadAction\046\046this.onloadAction(this.mainObject,null,null,null,this),this.waitCall\046\046(this.waitCall(),this.waitCall=null))},dtmlXMLLoaderObject.prototype.loadXML=function(t,e,n,i){this.rSeed\046\046(t+=(-1!=t.indexOf("?")?"\046":"?")+"a_dhx_rSeed="+(new Date).valueOf()),this.filePath=t,this.xmlDoc=!_isIE\046\046window.XMLHttpRequest?new XMLHttpRequest:new ActiveXObject("Microsoft.XMLHTTP"),this.async\046\046(this.xmlDoc.onreadystatechange=new this.waitLoadFunction(this)),this.xmlDoc.open(e?"POST":"GET",t,this.async),i?(this.xmlDoc.setRequestHeader("User-Agent","dhtmlxRPC v0.1 ("+navigator.userAgent+")"),this.xmlDoc.setRequestHeader("Content-type","text/xml")):e\046\046this.xmlDoc.setRequestHeader("Content-type","application/x-www-form-urlencoded"),this.xmlDoc.setRequestHeader("X-Requested-With","XMLHttpRequest"),this.xmlDoc.send(null||n),this.async||new this.waitLoadFunction(this)()},dtmlXMLLoaderObject.prototype.destructor=function(){return this._filterXPath=null,this._getAllNamedChilds=null,this._retry=null,this.async=null,this.rSeed=null,this.filePath=null,this.onloadAction=null,this.mainObject=null,this.xmlDoc=null,this.doXPath=null,this.doXPathOpera=null,this.doXSLTransToObject=null,this.doXSLTransToString=null,this.loadXML=null,this.loadXMLString=null,this.doSerialization=null,this.xmlNodeToJSON=null,this.getXMLTopNode=null,this.setXSLParamValue=null,null},dtmlXMLLoaderObject.prototype.xmlNodeToJSON=function(t){for(var e={},n=0;n\074t.attributes.length;n++)e[t.attributes[n].name]=t.attributes[n].value;e._tagvalue=t.firstChild?t.firstChild.nodeValue:"";for(var n=0;n\074t.childNodes.length;n++){var i=t.childNodes[n].tagName;i\046\046(e[i]||(e[i]=[]),e[i].push(this.xmlNodeToJSON(t.childNodes[n])))}return e},dhtmlDragAndDropObject.prototype.removeDraggableItem=function(t){t.onmousedown=null,t.dragStarter=null,t.dragLanding=null},dhtmlDragAndDropObject.prototype.addDraggableItem=function(t,e){t.onmousedown=this.preCreateDragCopy,t.dragStarter=e,this.addDragLanding(t,e)},dhtmlDragAndDropObject.prototype.addDragLanding=function(t,e){t.dragLanding=e},dhtmlDragAndDropObject.prototype.preCreateDragCopy=function(t){return!t\046\046!window.event||2!=(t||event).button?window.dhtmlDragAndDrop.waitDrag?(window.dhtmlDragAndDrop.waitDrag=0,document.body.onmouseup=window.dhtmlDragAndDrop.tempDOMU,document.body.onmousemove=window.dhtmlDragAndDrop.tempDOMM,!1):(window.dhtmlDragAndDrop.dragNode\046\046window.dhtmlDragAndDrop.stopDrag(t),window.dhtmlDragAndDrop.waitDrag=1,window.dhtmlDragAndDrop.tempDOMU=document.body.onmouseup,window.dhtmlDragAndDrop.tempDOMM=document.body.onmousemove,window.dhtmlDragAndDrop.dragStartNode=this,window.dhtmlDragAndDrop.dragStartObject=this.dragStarter,document.body.onmouseup=window.dhtmlDragAndDrop.preCreateDragCopy,document.body.onmousemove=window.dhtmlDragAndDrop.callDrag,window.dhtmlDragAndDrop.downtime=(new Date).valueOf(),t\046\046t.preventDefault?(t.preventDefault(),!1):!1):void 0},dhtmlDragAndDropObject.prototype.callDrag=function(t){if(t||(t=window.event),dragger=window.dhtmlDragAndDrop,!((new Date).valueOf()-dragger.downtime\074100)){if(!dragger.dragNode){if(!dragger.waitDrag)return dragger.stopDrag(t,!0);if(dragger.dragNode=dragger.dragStartObject._createDragNode(dragger.dragStartNode,t),!dragger.dragNode)return dragger.stopDrag();dragger.dragNode.onselectstart=function(){return!1},dragger.gldragNode=dragger.dragNode,document.body.appendChild(dragger.dragNode),document.body.onmouseup=dragger.stopDrag,dragger.waitDrag=0,dragger.dragNode.pWindow=window,dragger.initFrameRoute()}if(dragger.dragNode.parentNode!=window.document.body\046\046dragger.gldragNode){var e=dragger.gldragNode;dragger.gldragNode.old\046\046(e=dragger.gldragNode.old),e.parentNode.removeChild(e);var n=dragger.dragNode.pWindow;if(e.pWindow\046\046e.pWindow.dhtmlDragAndDrop.lastLanding\046\046e.pWindow.dhtmlDragAndDrop.lastLanding.dragLanding._dragOut(e.pWindow.dhtmlDragAndDrop.lastLanding),_isIE){var i=document.createElement("Div");i.innerHTML=dragger.dragNode.outerHTML,dragger.dragNode=i.childNodes[0]}else dragger.dragNode=dragger.dragNode.cloneNode(!0);dragger.dragNode.pWindow=window,dragger.gldragNode.old=dragger.dragNode,document.body.appendChild(dragger.dragNode),n.dhtmlDragAndDrop.dragNode=dragger.dragNode}if(dragger.dragNode.style.left=t.clientX+15+(dragger.fx?-1*dragger.fx:0)+(document.body.scrollLeft||document.documentElement.scrollLeft)+"px",dragger.dragNode.style.top=t.clientY+3+(dragger.fy?-1*dragger.fy:0)+(document.body.scrollTop||document.documentElement.scrollTop)+"px",t.srcElement)a=t.srcElement;else var a=t.target;dragger.checkLanding(a,t)}},dhtmlDragAndDropObject.prototype.calculateFramePosition=function(t){if(window.name){for(var e=parent.frames[window.name].frameElement.offsetParent,n=0,i=0;e;)n+=e.offsetLeft,i+=e.offsetTop,e=e.offsetParent;if(parent.dhtmlDragAndDrop){var a=parent.dhtmlDragAndDrop.calculateFramePosition(1);n+=1*a.split("_")[0],i+=1*a.split("_")[1]}if(t)return n+"_"+i;this.fx=n,this.fy=i}return"0_0"},dhtmlDragAndDropObject.prototype.checkLanding=function(t,e){t\046\046t.dragLanding?(this.lastLanding\046\046this.lastLanding.dragLanding._dragOut(this.lastLanding),this.lastLanding=t,this.lastLanding=this.lastLanding.dragLanding._dragIn(this.lastLanding,this.dragStartNode,e.clientX,e.clientY,e),this.lastLanding_scr=_isIE?e.srcElement:e.target):t\046\046"BODY"!=t.tagName?this.checkLanding(t.parentNode,e):(this.lastLanding\046\046this.lastLanding.dragLanding._dragOut(this.lastLanding,e.clientX,e.clientY,e),this.lastLanding=0,this._onNotFound\046\046this._onNotFound())},dhtmlDragAndDropObject.prototype.stopDrag=function(t,e){if(dragger=window.dhtmlDragAndDrop,!e){dragger.stopFrameRoute();var n=dragger.lastLanding;dragger.lastLanding=null,n\046\046n.dragLanding._drag(dragger.dragStartNode,dragger.dragStartObject,n,_isIE?event.srcElement:t.target)}dragger.lastLanding=null,dragger.dragNode\046\046dragger.dragNode.parentNode==document.body\046\046dragger.dragNode.parentNode.removeChild(dragger.dragNode),dragger.dragNode=0,dragger.gldragNode=0,dragger.fx=0,dragger.fy=0,dragger.dragStartNode=0,dragger.dragStartObject=0,document.body.onmouseup=dragger.tempDOMU,document.body.onmousemove=dragger.tempDOMM,dragger.tempDOMU=null,dragger.tempDOMM=null,dragger.waitDrag=0},dhtmlDragAndDropObject.prototype.stopFrameRoute=function(t){t\046\046window.dhtmlDragAndDrop.stopDrag(1,1);for(var e=0;e\074window.frames.length;e++)try{window.frames[e]!=t\046\046window.frames[e].dhtmlDragAndDrop\046\046window.frames[e].dhtmlDragAndDrop.stopFrameRoute(window)}catch(n){}try{parent.dhtmlDragAndDrop\046\046parent!=window\046\046parent!=t\046\046parent.dhtmlDragAndDrop.stopFrameRoute(window)}catch(n){}},dhtmlDragAndDropObject.prototype.initFrameRoute=function(t,e){t\046\046(window.dhtmlDragAndDrop.preCreateDragCopy(),window.dhtmlDragAndDrop.dragStartNode=t.dhtmlDragAndDrop.dragStartNode,window.dhtmlDragAndDrop.dragStartObject=t.dhtmlDragAndDrop.dragStartObject,window.dhtmlDragAndDrop.dragNode=t.dhtmlDragAndDrop.dragNode,window.dhtmlDragAndDrop.gldragNode=t.dhtmlDragAndDrop.dragNode,window.document.body.onmouseup=window.dhtmlDragAndDrop.stopDrag,window.waitDrag=0,!_isIE\046\046e\046\046(!_isFF||1.8\076_FFrv)\046\046window.dhtmlDragAndDrop.calculateFramePosition());try{parent.dhtmlDragAndDrop\046\046parent!=window\046\046parent!=t\046\046parent.dhtmlDragAndDrop.initFrameRoute(window)}catch(n){}for(var i=0;i\074window.frames.length;i++)try{window.frames[i]!=t\046\046window.frames[i].dhtmlDragAndDrop\046\046window.frames[i].dhtmlDragAndDrop.initFrameRoute(window,!t||e?1:0)}catch(n){}},_isFF=!1,_isIE=!1,_isOpera=!1,_isKHTML=!1,_isMacOS=!1,_isChrome=!1,_FFrv=!1,_KHTMLrv=!1,_OperaRv=!1,-1!=navigator.userAgent.indexOf("Macintosh")\046\046(_isMacOS=!0),navigator.userAgent.toLowerCase().indexOf("chrome")\076-1\046\046(_isChrome=!0),-1!=navigator.userAgent.indexOf("Safari")||-1!=navigator.userAgent.indexOf("Konqueror")?(_KHTMLrv=parseFloat(navigator.userAgent.substr(navigator.userAgent.indexOf("Safari")+7,5)),_KHTMLrv\076525?(_isFF=!0,_FFrv=1.9):_isKHTML=!0):-1!=navigator.userAgent.indexOf("Opera")?(_isOpera=!0,_OperaRv=parseFloat(navigator.userAgent.substr(navigator.userAgent.indexOf("Opera")+6,3))):-1!=navigator.appName.indexOf("Microsoft")?(_isIE=!0,-1==navigator.appVersion.indexOf("MSIE 8.0")\046\046-1==navigator.appVersion.indexOf("MSIE 9.0")\046\046-1==navigator.appVersion.indexOf("MSIE 10.0")||"BackCompat"==document.compatMode||(_isIE=8)):(_isFF=!0,_FFrv=parseFloat(navigator.userAgent.split("rv:")[1])),dtmlXMLLoaderObject.prototype.doXPath=function(t,e,n,i){if(_isKHTML||!_isIE\046\046!window.XPathResult)return this.doXPathOpera(t,e);if(_isIE)return e||(e=this.xmlDoc.nodeName?this.xmlDoc:this.xmlDoc.responseXML),e||dhtmlxError.throwError("LoadXML","Incorrect XML",[e||this.xmlDoc,this.mainObject]),null!=n\046\046e.setProperty("SelectionNamespaces","xmlns:xsl=\'"+n+"\'"),"single"==i?e.selectSingleNode(t):e.selectNodes(t)||new Array(0);var a=e;e||(e=this.xmlDoc.nodeName?this.xmlDoc:this.xmlDoc.responseXML),e||dhtmlxError.throwError("LoadXML","Incorrect XML",[e||this.xmlDoc,this.mainObject]),-1!=e.nodeName.indexOf("document")?a=e:(a=e,e=e.ownerDocument);var r=XPathResult.ANY_TYPE;"single"==i\046\046(r=XPathResult.FIRST_ORDERED_NODE_TYPE);var s=new Array,o=e.evaluate(t,a,function(){return n},r,null);if(r==XPathResult.FIRST_ORDERED_NODE_TYPE)return o.singleNodeValue;for(var d=o.iterateNext();d;)s[s.length]=d,d=o.iterateNext();return s},_dhtmlxError.prototype.catchError=function(t,e){this.catches[t]=e},_dhtmlxError.prototype.throwError=function(t,e,n){return this.catches[t]?this.catches[t](t,e,n):this.catches.ALL?this.catches.ALL(t,e,n):(alert("Error type: "+arguments[0]+"\\nDescription: "+arguments[1]),null)},window.dhtmlxError=new _dhtmlxError,dtmlXMLLoaderObject.prototype.doXPathOpera=function(t,e){var n=t.replace(/[\\/]+/gi,"/").split("/"),i=null,a=1;if(!n.length)return[];if("."==n[0])i=[e];else{if(""!=n[0])return[];i=(this.xmlDoc.responseXML||this.xmlDoc).getElementsByTagName(n[a].replace(/\\[[^\\]]*\\]/g,"")),a++}for(a;a\074n.length;a++)i=this._getAllNamedChilds(i,n[a]);return-1!=n[a-1].indexOf("[")\046\046(i=this._filterXPath(i,n[a-1])),i},dtmlXMLLoaderObject.prototype._filterXPath=function(t,e){for(var n=new Array,e=e.replace(/[^\\[]*\\[\\@/g,"").replace(/[\\[\\]\\@]*/g,""),i=0;i\074t.length;i++)t[i].getAttribute(e)\046\046(n[n.length]=t[i]);return n},dtmlXMLLoaderObject.prototype._getAllNamedChilds=function(t,e){var n=new Array;_isKHTML\046\046(e=e.toUpperCase());for(var i=0;i\074t.length;i++)for(var a=0;a\074t[i].childNodes.length;a++)_isKHTML?t[i].childNodes[a].tagName\046\046t[i].childNodes[a].tagName.toUpperCase()==e\046\046(n[n.length]=t[i].childNodes[a]):t[i].childNodes[a].tagName==e\046\046(n[n.length]=t[i].childNodes[a]);return n},dtmlXMLLoaderObject.prototype.xslDoc=null,dtmlXMLLoaderObject.prototype.setXSLParamValue=function(t,e,n){n||(n=this.xslDoc),n.responseXML\046\046(n=n.responseXML);var i=this.doXPath("/xsl:stylesheet/xsl:variable[@name=\'"+t+"\']",n,"http://www.w3.org/1999/XSL/Transform","single");null!=i\046\046(i.firstChild.nodeValue=e)},dtmlXMLLoaderObject.prototype.doXSLTransToObject=function(t,e){if(t||(t=this.xslDoc),t.responseXML\046\046(t=t.responseXML),e||(e=this.xmlDoc),e.responseXML\046\046(e=e.responseXML),_isIE){var n=new ActiveXObject("Msxml2.DOMDocument.3.0");try{e.transformNodeToObject(t,n)}catch(i){n=e.transformNode(t)}}else{this.XSLProcessor||(this.XSLProcessor=new XSLTProcessor,this.XSLProcessor.importStylesheet(t));var n=this.XSLProcessor.transformToDocument(e)}return n},dtmlXMLLoaderObject.prototype.doXSLTransToString=function(t,e){var n=this.doXSLTransToObject(t,e);return"string"==typeof n?n:this.doSerialization(n)},dtmlXMLLoaderObject.prototype.doSerialization=function(t){if(t||(t=this.xmlDoc),t.responseXML\046\046(t=t.responseXML),_isIE)return t.xml;var e=new XMLSerializer;return e.serializeToString(t)},dhtmlxEventable=function(obj){obj.attachEvent=function(t,e,n){return t="ev_"+t.toLowerCase(),this[t]||(this[t]=new this.eventCatcher(n||this)),t+":"+this[t].addEvent(e)},obj.callEvent=function(t,e){return t="ev_"+t.toLowerCase(),this[t]?this[t].apply(this,e):!0},obj.checkEvent=function(t){return!!this["ev_"+t.toLowerCase()]},obj.eventCatcher=function(obj){var dhx_catch=[],z=function(){for(var t=!0,e=0;e\074dhx_catch.length;e++)if(null!=dhx_catch[e]){var n=dhx_catch[e].apply(obj,arguments);t=t\046\046n}return t};return z.addEvent=function(ev){return"function"!=typeof ev\046\046(ev=eval(ev)),ev?dhx_catch.push(ev)-1:!1},z.removeEvent=function(t){dhx_catch[t]=null},z},obj.detachEvent=function(t){if(0!=t){var e=t.split(":");this[e[0]].removeEvent(e[1])}},obj.detachAllEvents=function(){for(var t in this)0==t.indexOf("ev_")\046\046(this.detachEvent(t),this[t]=null)},obj=null},window.dhtmlx||(window.dhtmlx={}),function(){function t(t,e){var i=t.callback;n(!1),t.box.parentNode.removeChild(t.box),c=t.box=null,i\046\046i(e)}function e(e){if(c){e=e||event;var n=e.which||event.keyCode;return dhtmlx.message.keyboard\046\046((13==n||32==n)\046\046t(c,!0),27==n\046\046t(c,!1)),e.preventDefault\046\046e.preventDefault(),!(e.cancelBubble=!0)}}function n(t){n.cover||(n.cover=document.createElement("DIV"),n.cover.onkeydown=e,n.cover.className="dhx_modal_cover",document.body.appendChild(n.cover)),document.body.scrollHeight,n.cover.style.display=t?"inline-block":"none"}function i(t,e){var n="dhtmlx_"+t.toLowerCase().replace(/ /g,"_")+"_button";return"\074div class=\'dhtmlx_popup_button "+n+"\' result=\'"+e+"\' \076\074div\076"+t+"\074/div\076\074/div\076"}function a(t){g.area||(g.area=document.createElement("DIV"),g.area.className="dhtmlx_message_area",g.area.style[g.position]="5px",document.body.appendChild(g.area)),g.hide(t.id);var e=document.createElement("DIV");return e.innerHTML="\074div\076"+t.text+"\074/div\076",e.className="dhtmlx-info dhtmlx-"+t.type,e.onclick=function(){g.hide(t.id),t=null},"bottom"==g.position\046\046g.area.firstChild?g.area.insertBefore(e,g.area.firstChild):g.area.appendChild(e),t.expire\0760\046\046(g.timers[t.id]=window.setTimeout(function(){g.hide(t.id)},t.expire)),g.pull[t.id]=e,e=null,t.id}function r(e,n,a){var r=document.createElement("DIV");r.className=" dhtmlx_modal_box dhtmlx-"+e.type,r.setAttribute("dhxbox",1);var s="";if(e.width\046\046(r.style.width=e.width),e.height\046\046(r.style.height=e.height),e.title\046\046(s+=\'\074div class="dhtmlx_popup_title"\076\'+e.title+"\074/div\076"),s+=\'\074div class="dhtmlx_popup_text"\076\074span\076\'+(e.content?"":e.text)+\'\074/span\076\074/div\076\074div  class="dhtmlx_popup_controls"\076\',n\046\046(s+=i(e.ok||"OK",!0)),a\046\046(s+=i(e.cancel||"Cancel",!1)),e.buttons)for(var o=0;o\074e.buttons.length;o++)s+=i(e.buttons[o],o);if(s+="\074/div\076",r.innerHTML=s,e.content){var d=e.content;"string"==typeof d\046\046(d=document.getElementById(d)),"none"==d.style.display\046\046(d.style.display=""),r.childNodes[e.title?1:0].appendChild(d)}return r.onclick=function(n){n=n||event;var i=n.target||n.srcElement;if(i.className||(i=i.parentNode),"dhtmlx_popup_button"==i.className.split(" ")[0]){var a=i.getAttribute("result");a="true"==a||("false"==a?!1:a),t(e,a)}},e.box=r,(n||a)\046\046(c=e),r}function s(t,i,a){var s=t.tagName?t:r(t,i,a);t.hidden||n(!0),document.body.appendChild(s);var o=Math.abs(Math.floor(((window.innerWidth||document.documentElement.offsetWidth)-s.offsetWidth)/2)),d=Math.abs(Math.floor(((window.innerHeight||document.documentElement.offsetHeight)-s.offsetHeight)/2));return s.style.top="top"==t.position?"-3px":d+"px",s.style.left=o+"px",s.onkeydown=e,s.focus(),t.hidden\046\046dhtmlx.modalbox.hide(s),s}function o(t){return s(t,!0,!1)}function d(t){return s(t,!0,!0)}function l(t){return s(t)}function h(t,e,n){return"object"!=typeof t\046\046("function"==typeof e\046\046(n=e,e=""),t={text:t,type:e,callback:n}),t}function _(t,e,n,i){return"object"!=typeof t\046\046(t={text:t,type:e,expire:n,id:i}),t.id=t.id||g.uid(),t.expire=t.expire||g.expire,t}var c=null;document.attachEvent?document.attachEvent("onkeydown",e):document.addEventListener("keydown",e,!0),dhtmlx.alert=function(){var t=h.apply(this,arguments);return t.type=t.type||"confirm",o(t)},dhtmlx.confirm=function(){var t=h.apply(this,arguments);return t.type=t.type||"alert",d(t)},dhtmlx.modalbox=function(){var t=h.apply(this,arguments);return t.type=t.type||"alert",l(t)},dhtmlx.modalbox.hide=function(t){for(;t\046\046t.getAttribute\046\046!t.getAttribute("dhxbox");)t=t.parentNode;t\046\046(t.parentNode.removeChild(t),n(!1))};var g=dhtmlx.message=function(t){t=_.apply(this,arguments),t.type=t.type||"info";var e=t.type.split("-")[0];switch(e){case"alert":return o(t);case"confirm":return d(t);case"modalbox":return l(t);default:return a(t)}};g.seed=(new Date).valueOf(),g.uid=function(){return g.seed++},g.expire=4e3,g.keyboard=!0,g.position="top",g.pull={},g.timers={},g.hideAll=function(){for(var t in g.pull)g.hide(t)},g.hide=function(t){var e=g.pull[t];e\046\046e.parentNode\046\046(window.setTimeout(function(){e.parentNode.removeChild(e),e=null},2e3),e.className+=" hidden",g.timers[t]\046\046window.clearTimeout(g.timers[t]),delete g.pull[t])}}(),gantt={version:"2.0.0"},dhtmlxEventable=function(obj){obj._silent_mode=!1,obj._silentStart=function(){this._silent_mode=!0},obj._silentEnd=function(){this._silent_mode=!1},obj.attachEvent=function(t,e,n){return t="ev_"+t.toLowerCase(),this[t]||(this[t]=new this._eventCatcher(n||this)),t+":"+this[t].addEvent(e)},obj.callEvent=function(t,e){return this._silent_mode?!0:(t="ev_"+t.toLowerCase(),this[t]?this[t].apply(this,e):!0)},obj.checkEvent=function(t){return!!this["ev_"+t.toLowerCase()]},obj._eventCatcher=function(obj){var dhx_catch=[],z=function(){for(var t=!0,e=0;e\074dhx_catch.length;e++)if(null!=dhx_catch[e]){var n=dhx_catch[e].apply(obj,arguments);t=t\046\046n}return t};return z.addEvent=function(ev){return"function"!=typeof ev\046\046(ev=eval(ev)),ev?dhx_catch.push(ev)-1:!1},z.removeEvent=function(t){dhx_catch[t]=null},z},obj.detachEvent=function(t){if(0!=t){var e=t.split(":");this[e[0]].removeEvent(e[1])}},obj.detachAllEvents=function(){for(var t in this)0==t.indexOf("ev_")\046\046delete this[t]},obj=null},dhtmlx.copy=function(t){var e,n,i;if(t\046\046"object"==typeof t){for(i={},n=[Array,Date,Number,String,Boolean],e=0;e\074n.length;e++)t instanceof n[e]\046\046(i=e?new n[e](t):new n[e]);for(e in t)Object.prototype.hasOwnProperty.apply(t,[e])\046\046(i[e]=dhtmlx.copy(t[e]))}return i||t},dhtmlx.mixin=function(t,e,n){for(var i in e)(!t[i]||n)\046\046(t[i]=e[i]);return t},dhtmlx.defined=function(t){return"undefined"!=typeof t},dhtmlx.uid=function(){return this._seed||(this._seed=(new Date).valueOf()),this._seed++,this._seed},dhtmlx.bind=function(t,e){return function(){return t.apply(e,arguments)}},gantt._get_position=function(t){if(t.getBoundingClientRect){var e=t.getBoundingClientRect(),n=document.body,i=document.documentElement,a=window.pageYOffset||i.scrollTop||n.scrollTop,r=window.pageXOffset||i.scrollLeft||n.scrollLeft,s=i.clientTop||n.clientTop||0,o=i.clientLeft||n.clientLeft||0,d=e.top+a-s,l=e.left+r-o;return{y:Math.round(d),x:Math.round(l),width:t.offsetHeight,height:t.offsetWidth}}for(var d=0,l=0;t;)d+=parseInt(t.offsetTop,10),l+=parseInt(t.offsetLeft,10),t=t.offsetParent;return{y:d,x:l,width:t.offsetHeight,height:t.offsetWidth}},gantt._detectScrollSize=function(){var t=document.createElement("div");t.style.cssText="visibility:hidden;position:absolute;left:-1000px;width:100px;padding:0px;margin:0px;height:110px;min-height:100px;overflow-y:scroll;",document.body.appendChild(t);var e=t.offsetWidth-t.clientWidth;return document.body.removeChild(t),e},dhtmlxEventable(gantt),gantt._click={},gantt._dbl_click={},gantt._context_menu={},gantt._on_click=function(t){t=t||window.event;var e=t.target||t.srcElement,n=gantt.locate(t),i=gantt._find_ev_handler(t,e,gantt._click,n);if(i)if(null!==n){var a=!gantt.checkEvent("onTaskClick")||gantt.callEvent("onTaskClick",[n,t]);a\046\046gantt.config.select_task\046\046gantt.selectTask(n)}else gantt.callEvent("onEmptyClick",[t])},gantt._on_contextmenu=function(t){t=t||window.event;var e=t.target||t.srcElement,n=gantt.locate(e),i=gantt.locate(e,gantt.config.link_attribute),a=!gantt.checkEvent("onContextMenu")||gantt.callEvent("onContextMenu",[n,i,t]);return a||t.preventDefault(),a},gantt._find_ev_handler=function(t,e,n,i){for(var a=!0;e\046\046e.parentNode;){var r=e.className;if(r){r=r.split(" ");for(var s=0;s\074r.length;s++)r[s]\046\046n[r[s]]\046\046(a=n[r[s]].call(gantt,t,i,e),a=!("undefined"!=typeof a\046\046a!==!0))}e=e.parentNode}return a},gantt._on_dblclick=function(t){t=t||window.event;var e=t.target||t.srcElement,n=gantt.locate(t),i=gantt._find_ev_handler(t,e,gantt._dbl_click,n);if(i\046\046null!==n){var a=!gantt.checkEvent("onTaskDblClick")||gantt.callEvent("onTaskDblClick",[n,t]);a\046\046gantt.config.details_on_dblclick\046\046gantt.showLightbox(n)}},gantt._on_mousemove=function(t){if(gantt.checkEvent("onMouseMove")){var e=gantt.locate(t);gantt._last_move_event=t,gantt.callEvent("onMouseMove",[e,t])}},dhtmlxDnD.prototype={dragStart:function(t,e){this.config={obj:t,marker:null,started:!1,pos:this.getPosition(e),sensitivity:4},this._settings\046\046dhtmlx.mixin(this.config,this._settings,!0);var n=dhtmlx.bind(function(e){return this.dragMove(t,e)},this);dhtmlx.bind(function(e){return this.dragScroll(t,e)},this);var i=dhtmlx.bind(function(t){return dhtmlx.defined(this.config.updates_per_second)\046\046!gantt._checkTimeout(this,this.config.updates_per_second)?!0:n(t)},this),a=dhtmlx.bind(function(){return dhtmlxDetachEvent(document.body,"mousemove",i),dhtmlxDetachEvent(document.body,"mouseup",a),this.dragEnd(t)},this);dhtmlxEvent(document.body,"mousemove",i),dhtmlxEvent(document.body,"mouseup",a),document.body.className+=" gantt_noselect"},dragMove:function(t,e){if(!this.config.marker\046\046!this.config.started){var n=this.getPosition(e),i=n.x-this.config.pos.x,a=n.y-this.config.pos.y,r=Math.sqrt(Math.pow(Math.abs(i),2)+Math.pow(Math.abs(a),2));if(r\076this.config.sensitivity){if(this.config.started=!0,this.config.ignore=!1,this.callEvent("onBeforeDragStart",[t,e])===!1)return this.config.ignore=!0,!0;var s=this.config.marker=document.createElement("div");s.className="gantt_drag_marker",s.innerHTML="Dragging object",document.body.appendChild(s),this.callEvent("onAfterDragStart",[t,e])}else this.config.ignore=!0}this.config.ignore||(e.pos=this.getPosition(e),this.config.marker.style.left=e.pos.x+"px",this.config.marker.style.top=e.pos.y+"px",this.callEvent("onDragMove",[t,e]))},dragEnd:function(){this.config.marker\046\046(this.config.marker.parentNode.removeChild(this.config.marker),this.config.marker=null,this.callEvent("onDragEnd",[])),document.body.className=document.body.className.replace(" gantt_noselect","")},getPosition:function(t){var e=0,n=0;return t=t||window.event,t.pageX||t.pageY?(e=t.pageX,n=t.pageY):(t.clientX||t.clientY)\046\046(e=t.clientX+document.body.scrollLeft+document.documentElement.scrollLeft,n=t.clientY+document.body.scrollTop+document.documentElement.scrollTop),{x:e,y:n}}},gantt._init_grid=function(){this._click.gantt_close=dhtmlx.bind(function(t,e){this.close(e)},this),this._click.gantt_open=dhtmlx.bind(function(t,e){this.open(e)},this),this._click.gantt_row=dhtmlx.bind(function(t,e,n){if(null!==e){var i=this.getTaskNode(e),a=Math.max(i.offsetLeft-this.config.task_scroll_offset,0);this._scroll_task_area(a),this.callEvent("onTaskRowClick",[e,n])}},this),this._click.gantt_grid_head_cell=dhtmlx.bind(function(t,e,n){var i=n.getAttribute("column_id");if(this.callEvent("onGridHeaderClick",[i,t]))if("add"==i)this._click.gantt_add(t,0);else if(this.config.sort){var a=this._sort\046\046this._sort.direction\046\046this._sort.name==i?this._sort.direction:"desc";a="desc"==a?"asc":"desc",this._sort={name:i,direction:a},this._render_grid_header(),this.sort(i,"desc"==a)}},this),!this.config.sort\046\046this.config.order_branch\046\046this._init_dnd(),this._click.gantt_add=dhtmlx.bind(function(t,e){var n=e?this.getTask(e):!1,i="";if(n)i=n.start_date;else{var a=this._order[0];i=a?this.getTask(a).start_date:this.config.start_date}n\046\046(n.$open=!0);var r={text:gantt.locale.labels.new_task,start_date:this.templates.xml_format(i),duration:1,progress:0,parent:e};this.callEvent("onTaskCreated",[r]),this.addTask(r),this.showTask(r.id),this.config.details_on_create\046\046this.showLightbox(r.id)},this)},gantt._render_grid=function(){this._calc_grid_width(),this._render_grid_header()},gantt._calc_grid_width=function(){if(this.config.autofit){for(var t=this.config.columns,e=0,n=[],i=[],a=0;a\074t.length;a++){var r=parseInt(t[a].width,10);window.isNaN(r)\046\046(r=50,n.push(a)),i[a]=r,e+=r}var s=this.config.grid_width-e;if(s/(n.length\0760?n.length:i.length\0760?i.length:1),n.length\0760)for(var o=s/(n.length?n.length:1),a=0;a\074n.length;a++){var d=n[a];i[d]+=o}else for(var o=s/(i.length?i.length:1),a=0;a\074i.length;a++)i[a]+=o;for(var a=0;a\074i.length;a++)t[a].width=i[a]}},gantt._render_grid_header=function(){for(var t=this.config.columns,e=[],n=0,i=this.locale.labels,a=this.config.scale_height-2,r=0;r\074t.length;r++){var s=r==t.length-1,o=t[r];s\046\046this.config.grid_width\076n+o.width\046\046(o.width=this.config.grid_width-n),n+=o.width;var d=this._sort\046\046o.name==this._sort.name?"\074div class=\'gantt_sort gantt_"+this._sort.direction+"\'\076\074/div\076":"",l="gantt_grid_head_cell"+(" gantt_grid_head_"+o.name)+(s?" gantt_last_cell":"")+this.templates.grid_header_class(o.name,o),h="width:"+(o.width-(s?1:0))+"px;",_=i["column_"+o.name]||o.label;_=_||"";var c="\074div class=\'"+l+"\' style=\'"+h+"\' column_id=\'"+o.name+"\'\076"+_+d+"\074/div\076";e.push(c)}this.$grid_scale.style.height=this.config.scale_height-1+"px",this.$grid_scale.style.lineHeight=a+"px",this.$grid_scale.style.width=n-1+"px",this.$grid_scale.innerHTML=e.join("")},gantt._render_grid_item=function(t){for(var e=this.config.columns,n=[],i=0;i\074e.length;i++){var a,r,s=i==e.length-1,o=e[i];"add"==o.name\046\046i==e.length-1?r="\074div class=\'gantt_add\'\076\074/div\076":(r=o.template?o.template(t):t[o.name],r instanceof Date\046\046(r=this.templates.date_grid(r)),r="\074div class=\'gantt_tree_content\'\076"+r+"\074/div\076");var d="gantt_cell"+(s?" gantt_last_cell":""),l="";if(o.tree){for(var h=0;h\074t.$level;h++)l+=this.templates.grid_indent(t);var _=this._branches[t.id]\046\046this._branches[t.id].length\0760;_?(l+=this.templates.grid_open(t),l+=this.templates.grid_folder(t)):(l+=this.templates.grid_blank(t),l+=this.templates.grid_file(t))}var c="width:"+(o.width-(s?1:0))+"px;";dhtmlx.defined(o.align)\046\046(c+="text-align:"+o.align+";"),a="\074div class=\'"+d+"\' style=\'"+c+"\'\076"+l+r+"\074/div\076",n.push(a)}var d=0===t.$index%2?"":" odd";if(d+=t.$transparent?" gantt_transparent":"",this.templates.grid_row_class){var g=this.templates.grid_row_class.call(this,t.start_date,t.end_date,t);g\046\046(d+=" "+g)}this.getState().selected_task==t.id\046\046(d+=" gantt_selected");var u=document.createElement("div");return u.className="gantt_row"+d,u.style.height=this.config.row_height+"px",u.style.lineHeight=gantt.config.row_height+"px",u.setAttribute(this.config.task_attribute,t.id),u.innerHTML=n.join(""),u},gantt.open=function(t){gantt._set_item_state(t,!0),this.callEvent("onTaskOpened",[t])},gantt.close=function(t){gantt._set_item_state(t,!1),this.callEvent("onTaskClosed",[t])},gantt._set_item_state=function(t,e){t\046\046this._pull[t]\046\046(this._pull[t].$open=e,this.refreshData())},gantt.getTaskIndex=function(t){for(var e=this._branches[this.getTask(t).parent],n=0;n\074e.length;n++)if(e[n]==t)return n;return-1},gantt.getGlobalTaskIndex=function(t){for(var e=this._order,n=0;n\074e.length;n++)if(e[n]==t)return n;return-1},gantt.moveTask=function(t,e,n){var i=arguments[3];if(i){if(i===t)return;n=this.getTask(i).parent,e=this.getTaskIndex(i)}n=n||0;var a=this.getTask(t);this._branches[a.parent];var r=this._branches[n];if(-1==e\046\046(e=r.length+1),a.parent==n){var s=this.getTaskIndex(t);if(s==e)return;e\076s\046\046e--}this._branch_update(a.parent,t),r=this._branches[n];var o=r[e];o?r=r.slice(0,e).concat([t]).concat(r.slice(e)):r.push(t),a.parent=n,this._branches[n]=r,this.refreshData()\n
+},gantt._init_dnd=function(){var t=new dhtmlxDnD(this.$grid_data,{updates_per_second:60});dhtmlx.defined(this.config.dnd_sensitivity)\046\046(t.config.sensitivity=this.config.dnd_sensitivity),t.attachEvent("onBeforeDragStart",dhtmlx.bind(function(t,e){var n=this._locateHTML(e);return n?(this.hideQuickInfo\046\046this._hideQuickInfo(),void 0):!1},this)),t.attachEvent("onAfterDragStart",dhtmlx.bind(function(e,n){var i=this._locateHTML(n);t.config.marker.innerHTML=i.outerHTML,t.config.id=this.locate(n);var a=this.getTask(t.config.id);a.$open=!1,a.$transparent=!0,this.refreshData()},this)),t.attachEvent("onDragMove",dhtmlx.bind(function(e,n){var i=t.config,a=this._get_position(this.$grid_data),r=a.x+10,s=n.pos.y-10;s\074a.y\046\046(s=a.y),s\076a.y+this.$grid_data.offsetHeight-this.config.row_height\046\046(s=a.y+this.$grid_data.offsetHeight-this.config.row_height),i.marker.style.left=r+"px",i.marker.style.top=s+"px";var o=document.elementFromPoint(a.x-document.body.scrollLeft+1,s-document.body.scrollTop),d=this.locate(o);if(this.isTaskExists(d)){var l=gantt._get_position(o),h=this.getTask(d),_=this.getTask(t.config.id);if(l.y+o.offsetHeight/2\074s){var c=this.getGlobalTaskIndex(h.id),g=this._pull[this._order[c+1+(h.id==_.id?1:0)]];if(g){if(g.id==_.id)return;h=g}else if(g=this._pull[this._order[c+1]],g.$level==_.$level)return this.moveTask(_.id,-1,g.parent),i.target="next:"+g.id,void 0}if(h.$level==_.$level\046\046_.id!=h.id)this.moveTask(_.id,0,0,h.id),i.target=h.id;else{if(_.id==h.id)return;var c=this.getGlobalTaskIndex(h.id),u=this._pull[this._order[c-1]];u\046\046u.$level==_.$level\046\046_.id!=u.id\046\046(this.moveTask(_.id,-1,u.parent),i.target="next:"+u.id)}}return!0},this)),t.attachEvent("onDragEnd",dhtmlx.bind(function(){this.getTask(t.config.id).$transparent=!1,this.refreshData(),this.callEvent("onRowDragEnd",[t.config.id,t.config.target])},this))},gantt._scale_helpers={getSum:function(t,e,n){void 0===n\046\046(n=t.length-1),void 0===e\046\046(e=0);for(var i=0,a=e;n\076=a;a++)i+=t[a];return i},setSumWidth:function(t,e,n,i){var a=e.width;void 0===i\046\046(i=a.length-1),void 0===n\046\046(n=0);var r=i-n+1;if(!(n\076a.length-1||0\076=r||i\076a.length-1)\046\046t){var s=this.getSum(a,n,i),o=t-s;this.adjustSize(o,a,n,i),this.adjustSize(-o,a,i+1),e.full_width=this.getSum(a)}},splitSize:function(t,e){for(var n=[],i=0;e\076i;i++)n[i]=0;return this.adjustSize(t,n),n},adjustSize:function(t,e,n,i){n||(n=0),void 0===i\046\046(i=e.length-1);for(var a=i-n+1,r=this.getSum(e,n,i),s=0,o=n;i\076=o;o++){var d=Math.floor(t*(r?e[o]/r:1/a));e[o]+=d,s+=d}e[e.length-1]+=t-s},sortScales:function(t){function e(t,e){var n=new Date(1970,0,1);return gantt.date.add(n,e,t)-n}t.sort(function(t,n){return e(t.unit,t.step)\074e(n.unit,n.step)?1:-1})},primaryScale:function(){return gantt._init_template("date_scale"),{unit:gantt.config.scale_unit,step:gantt.config.step,template:gantt.templates.date_scale,date:gantt.config.date_scale,css:gantt.templates.scale_cell_class}},prepareConfigs:function(t,e,n,i){for(var a=this.prepareScaleConfig(t[t.length-1],e,n).full_width,r=this.splitSize(i,t.length),s=[],o=0;o\074t.length;o++){var d=this.prepareScaleConfig(t[o],e,a,r[o]);this.formatScales(d),s.push(d)}for(var o=0;o\074s.length-1;o++)this.alineScaleColumns(s[s.length-1],s[o]);return s},prepareScaleConfig:function(t,e,n,i){var a=dhtmlx.mixin({count:0,col_width:0,full_width:0,height:i,width:[],trace_x:[]},t);this.eachColumn(t.unit,t.step,function(t){a.count++,a.trace_x.push(new Date(t))});var r=n;return a.col_width=Math.floor(r/a.count),e\046\046a.col_width\074e\046\046(a.col_width=e,r=a.col_width*a.count),a.width=this.splitSize(r,a.count),a.full_width=this.getSum(a.width),a},alineScaleColumns:function(t,e,n,i){for(var a=e.trace_x,r=t.trace_x,s=n||0,o=i||r.length-1,d=0,l=1;l\074a.length;l++)for(var h=s;o\076=h;h++)if(+r[h]!=+a[l]);else{var _=this.getSum(t.width,s,h-1),c=this.getSum(e.width,d,l-1);c!=_\046\046this.setSumWidth(_,e,d,l-1),s=h,d=l}},eachColumn:function(t,e,n){var i=new Date(gantt._min_date),a=new Date(gantt._max_date);gantt.date[t+"_start"]\046\046(i=gantt.date[t+"_start"](i));for(var r=new Date(i);+a\076+r;)n.call(this,new Date(r)),r=gantt.date.add(r,e,t)},formatScales:function(t){var e=t.trace_x,n=0,i=t.width.length-1,a=0;if(+e[0]\074+gantt._min_date\046\046n!=i){var r=Math.floor(t.width[0]*((e[1]-gantt._min_date)/(e[1]-e[0])));a+=t.width[0]-r,t.width[0]=r,e[0]=new Date(gantt._min_date)}var s=e.length-1,o=e[s],d=gantt.date.add(o,t.step,t.unit);if(+d\076+gantt._max_date\046\046s\0760){var r=t.width[s]-Math.floor(t.width[s]*((d-gantt._max_date)/(d-o)));a+=t.width[s]-r,t.width[s]=r}if(a){for(var l=this.getSum(t.width),h=0,_=0;_\074t.width.length;_++){var c=Math.floor(a*(t.width[_]/l));t.width[_]+=c,h+=c}this.adjustSize(a-h,t.width)}}},gantt._tasks_dnd={drag:null,_events:{before_start:{},before_finish:{},after_finish:{}},_handlers:{},init:function(){this.clear_drag_state();var t=gantt.config.drag_mode;this.set_actions();var e={before_start:"onBeforeTaskDrag",before_finish:"onBeforeTaskChanged",after_finish:"onAfterTaskDrag"};for(var n in this._events)for(var i in t)this._events[n][i]=e[n];this._handlers[t.move]=this._move,this._handlers[t.resize]=this._resize,this._handlers[t.progress]=this._resize_progress},set_actions:function(){var t=gantt.$task_data;dhtmlxEvent(t,"mousemove",dhtmlx.bind(function(t){this.on_mouse_move(t||event)},this)),dhtmlxEvent(t,"mousedown",dhtmlx.bind(function(t){this.on_mouse_down(t||event)},this)),dhtmlxEvent(t,"mouseup",dhtmlx.bind(function(t){this.on_mouse_up(t||event)},this))},clear_drag_state:function(){this.drag={id:null,mode:null,pos:null,start:null,obj:null,left:null}},_drag_timeout:function(){return this._cancel_drag?!1:(setTimeout(dhtmlx.bind(function(){this._cancel_drag=!1},this),25),this._cancel_drag=!0)},_resize:function(t,e,n){var i=gantt.config;n.left?t.start_date=new Date(n.start.valueOf()+e):t.end_date=new Date(n.start.valueOf()+e),t.end_date-t.start_date\074i.min_duration\046\046(n.left?t.start_date=new Date(t.end_date.valueOf()-i.min_duration):t.end_date=new Date(t.start_date.valueOf()+i.min_duration)),gantt._update_task_duration(t)},_resize_progress:function(t,e,n){var i=n.obj_s_x=n.obj_s_x||gantt._pos_from_date(t.start_date),a=n.obj_e_x=n.obj_e_x||gantt._pos_from_date(t.end_date),r=Math.max(0,n.pos.x-i);t.progress=Math.min(1,r/(a-i))},_move:function(t,e,n){t.start_date=new Date(n.obj.start_date.valueOf()+e),t.end_date=new Date(n.obj.end_date.valueOf()+e)},on_mouse_move:function(t){this.drag.start_drag\046\046this._start_dnd(t);var e=this.drag;if(e.mode){if(!gantt._checkTimeout(this,40))return;this._update_on_move(t)}},_update_on_move:function(t){var e=this.drag;if(e.mode){var n=gantt._get_mouse_pos(t);if(e.pos\046\046e.pos.x==n.x)return;e.pos=n;var i=gantt._date_from_pos(n.x);if(!i||isNaN(i.getTime()))return;var a=i-e.start,r=gantt.getTask(e.id);if(this._handlers[e.mode]){var s=dhtmlx.mixin({},r),o=dhtmlx.mixin({},r);this._handlers[e.mode].apply(this,[o,a,e]),dhtmlx.mixin(r,o,!0),gantt._update_parents(e.id,!0),gantt.callEvent("onTaskDrag",[r.id,e.mode,o,s,t]),dhtmlx.mixin(r,o,!0),gantt._update_parents(e.id),gantt.refreshTask(e.id)}}},on_mouse_down:function(t,e){if(2!=t.button\046\046!gantt.config.readonly\046\046!this.drag.mode){this.clear_drag_state(),e=e||t.target||t.srcElement;var n=gantt._trim(e.className||"");if(!n||!this._get_drag_mode(n))return e.parentNode?this.on_mouse_down(t,e.parentNode):void 0;var i=this._get_drag_mode(n);if(i)if(i.mode\046\046i.mode!=gantt.config.drag_mode.ignore\046\046gantt.config["drag_"+i.mode]){var a=gantt.locate(e),r=dhtmlx.copy(gantt.getTask(a)||{});if(gantt._is_flex_task(r)\046\046i.mode!=gantt.config.drag_mode.progress)return this.clear_drag_state(),void 0;i.id=a;var s=gantt._get_mouse_pos(t);i.start=gantt._date_from_pos(s.x),i.obj=r,this.drag.start_drag=i}else this.clear_drag_state();else if(gantt.checkEvent("onMouseDown")\046\046gantt.callEvent("onMouseDown",[n.split(" ")[0]])\046\046e.parentNode)return this.on_mouse_down(t,e.parentNode)}},on_mouse_up:function(t){var e=this.drag;if(e.mode\046\046e.id){var n=gantt.getTask(e.id);if(this._fireEvent("before_finish",e.mode,[e.id,e.mode,dhtmlx.copy(e.obj),t])){var i=e.id;if(this.clear_drag_state(),gantt.config.round_dnd_dates){var a=gantt._tasks;gantt._round_task_dates(n,a.step,a.unit)}else gantt._round_task_dates(n,gantt.config.time_step,"minute");gantt._update_task_duration(n),gantt.updateTask(n.id),this._fireEvent("after_finish",e.mode,[i,e.mode,t])}else e.obj._dhx_changed=!1,dhtmlx.mixin(n,e.obj,!0),gantt.updateTask(n.id)}this.clear_drag_state()},_get_drag_mode:function(t){var e=gantt.config.drag_mode,n=(t||"").split(" "),i=n[0],a={mode:null,left:null};switch(i){case"gantt_task_line":case"gantt_task_content":a.mode=e.move;break;case"gantt_task_drag":a.mode=e.resize,n[1]\046\046-1!==n[1].indexOf("left",n[1].length-"left".length)\046\046(a.left=!0);break;case"gantt_task_progress_drag":a.mode=e.progress;break;case"gantt_link_control":case"gantt_link_point":a.mode=e.ignore;break;default:a=null}return a},_start_dnd:function(t){var e=this.drag=this.drag.start_drag;delete e.start_drag;var n=gantt.config,i=e.id;n["drag_"+e.mode]\046\046gantt.callEvent("onBeforeDrag",[i,e.mode,t])\046\046this._fireEvent("before_start",e.mode,[i,e.mode,t])?delete e.start_drag:this.clear_drag_state()},_fireEvent:function(t,e,n){dhtmlx.assert(this._events[t],"Invalid stage:{"+t+"}");var i=this._events[t][e];return dhtmlx.assert(i,"Unknown after drop mode:{"+e+"}"),dhtmlx.assert(n,"Invalid event arguments"),gantt.checkEvent(i)?gantt.callEvent(i,n):!0}},gantt._render_link=function(t){var e=this.getLink(t);gantt._linkRenderer.render_item(e,this.$task_links)},gantt._get_link_type=function(t,e){var n;return t\046\046e?n=gantt.config.links.start_to_start:!t\046\046e?n=gantt.config.links.finish_to_start:t||e?t\046\046!e\046\046(n=null):n=gantt.config.links.finish_to_finish,n},gantt.isLinkAllowed=function(t,e,n,i){if("object"==typeof t)var a=t;else var a={source:t,target:e,type:this._get_link_type(n,i)};if(!a)return!1;if(!(a.source\046\046a.target\046\046a.type))return!1;if(a.source==a.target)return!1;var r=!0;return this.checkEvent("onLinkValidation")\046\046(r=this.callEvent("onLinkValidation",[a])),r},gantt._render_link_element=function(t){if(gantt.isTaskVisible(t.source)\046\046gantt.isTaskVisible(t.target)){var e=this._path_builder.get_points(t),n=gantt._drawer,i=n.get_lines(e),a=document.createElement("div"),r="gantt_task_link",s=this.templates.link_class?this.templates.link_class(t):"";s\046\046(r+=" "+s),a.className=r,a.setAttribute(gantt.config.link_attribute,t.id);for(var o=0;o\074i.length;o++)o==i.length-1\046\046(i[o].size-=gantt.config.link_arrow_size),a.appendChild(n.render_line(i[o],i[o+1]));var d=i[i.length-1].direction,l=gantt._render_link_arrow(e[e.length-1],d);return a.appendChild(l),a}},gantt._render_link_arrow=function(t,e){var n=document.createElement("div"),i=gantt._drawer,a=t.y,r=t.x,s=gantt.config.link_arrow_size,o=gantt.config.row_height,d="gantt_link_arrow gantt_link_arrow_"+e;switch(e){case i.dirs.right:a-=(s-o)/2,r-=s;break;case i.dirs.left:a-=(s-o)/2;break;case i.dirs.up:r-=(s-o)/2;break;case i.dirs.down:a-=s,r-=(s-o)/2}return n.style.cssText=["top:"+a+"px","left:"+r+"px"].join(";"),n.className=d,n},gantt._drawer={current_pos:null,dirs:{left:"left",right:"right",up:"up",down:"down"},path:[],clear:function(){this.current_pos=null,this.path=[]},point:function(t){this.current_pos=dhtmlx.copy(t)},get_lines:function(t){this.clear(),this.point(t[0]);for(var e=1;e\074t.length;e++)this.line_to(t[e]);return this.get_path()},line_to:function(t){var e=dhtmlx.copy(t),n=this.current_pos,i=this._get_line(n,e);this.path.push(i),this.current_pos=e},get_path:function(){return this.path},get_wrapper_sizes:function(t){var e,n=gantt.config.link_wrapper_width,i=(gantt.config.link_line_width,t.y+(gantt.config.row_height-n)/2);switch(t.direction){case this.dirs.left:e={top:i,height:n,lineHeight:n,left:t.x-t.size-n/2,width:t.size+n};break;case this.dirs.right:e={top:i,lineHeight:n,height:n,left:t.x-n/2,width:t.size+n};break;case this.dirs.up:e={top:i-t.size,lineHeight:t.size+n,height:t.size+n,left:t.x-n/2,width:n};break;case this.dirs.down:e={top:i,lineHeight:t.size+n,height:t.size+n,left:t.x-n/2,width:n}}return e},get_line_sizes:function(t){var e,n=gantt.config.link_line_width,i=gantt.config.link_wrapper_width,a=t.size+n;switch(t.direction){case this.dirs.left:case this.dirs.right:e={height:n,width:a,marginTop:(i-n)/2,marginLeft:(i-n)/2};break;case this.dirs.up:case this.dirs.down:e={height:a,width:n,marginTop:(i-n)/2,marginLeft:(i-n)/2}}return e},render_line:function(t){var e=this.get_wrapper_sizes(t),n=document.createElement("div");n.style.cssText=["top:"+e.top+"px","left:"+e.left+"px","height:"+e.height+"px","width:"+e.width+"px"].join(";"),n.className="gantt_line_wrapper";var i=this.get_line_sizes(t),a=document.createElement("div");return a.style.cssText=["height:"+i.height+"px","width:"+i.width+"px","margin-top:"+i.marginTop+"px","margin-left:"+i.marginLeft+"px"].join(";"),a.className="gantt_link_line_"+t.direction,n.appendChild(a),n},_get_line:function(t,e){var n=this.get_direction(t,e),i={x:t.x,y:t.y,direction:this.get_direction(t,e)};return i.size=n==this.dirs.left||n==this.dirs.right?Math.abs(t.x-e.x):Math.abs(t.y-e.y),i},get_direction:function(t,e){var n=0;return n=e.x\074t.x?this.dirs.left:e.x\076t.x?this.dirs.right:e.y\076t.y?this.dirs.down:this.dirs.up}},gantt._y_from_ind=function(t){return t*gantt.config.row_height},gantt._path_builder={path:[],clear:function(){this.path=[]},current:function(){return this.path[this.path.length-1]},point:function(t){return t?(this.path.push(dhtmlx.copy(t)),t):this.current()},point_to:function(t,e,n){n=n?{x:n.x,y:n.y}:dhtmlx.copy(this.point());var i=gantt._drawer.dirs;switch(t){case i.left:n.x-=e;break;case i.right:n.x+=e;break;case i.up:n.y-=e;break;case i.down:n.y+=e}return this.point(n)},get_points:function(t){var e=this.get_endpoint(t),n=gantt.config,i=e.e_y-e.y,a=e.e_x-e.x,r=gantt._drawer.dirs;this.clear(),this.point({x:e.x,y:e.y});var s=2*n.link_arrow_size,o=e.e_x\076e.x;if(t.type==gantt.config.links.start_to_start)this.point_to(r.left,s),o?(this.point_to(r.down,i),this.point_to(r.right,a)):(this.point_to(r.right,a),this.point_to(r.down,i)),this.point_to(r.right,s);else if(t.type==gantt.config.links.finish_to_start)if(o=e.e_x\076e.x+2*s,this.point_to(r.right,s),o)a-=s,this.point_to(r.down,i),this.point_to(r.right,a);else{a-=2*s;var d=i\0760?1:-1;this.point_to(r.down,d*(n.row_height/2)),this.point_to(r.right,a),this.point_to(r.down,d*(Math.abs(i)-n.row_height/2)),this.point_to(r.right,s)}else t.type==gantt.config.links.finish_to_finish\046\046(this.point_to(r.right,s),o?(this.point_to(r.right,a),this.point_to(r.down,i)):(this.point_to(r.down,i),this.point_to(r.right,a)),this.point_to(r.left,s));return this.path},get_endpoint:function(t){var e,n,i=gantt.config.links,a=gantt._get_visible_order(t.source),r=gantt._get_visible_order(t.target);return t.type==i.start_to_start?(e=gantt._pull[t.source].start_date,n=gantt._pull[t.target].start_date):t.type==i.finish_to_finish?(e=gantt._pull[t.source].end_date,n=gantt._pull[t.target].end_date):t.type==i.finish_to_start?(e=gantt._pull[t.source].end_date,n=gantt._pull[t.target].start_date):dhtmlx.assert(!1,"Invalid link type"),{x:gantt._pos_from_date(e),e_x:gantt._pos_from_date(n),y:gantt._y_from_ind(a),e_y:gantt._y_from_ind(r)}}},gantt._init_links_dnd=function(){function t(t){var e=n(),i=["gantt_link_tooltip"];e.from\046\046e.to\046\046(gantt.isLinkAllowed(e.from,e.to,e.from_start,e.to_start)?i.push("gantt_allowed_link"):i.push("gantt_invalid_link"));var a=gantt.templates.drag_link_class(e.from,e.from_start,e.to,e.to_start);a\046\046i.push(a);var r="\074div class=\'"+a+"\'\076"+gantt.templates.drag_link(e.from,e.from_start,e.to,e.to_start)+"\074/div\076";t.innerHTML=r}function e(t,e){t.style.left=e.x+5+"px",t.style.top=e.y+5+"px"}function n(){return{from:gantt._link_source_task,to:gantt._link_target_task,from_start:gantt._link_source_task_start,to_start:gantt._link_target_task_start}}function i(){gantt._link_source_task=gantt._link_source_task_start=gantt._link_target_task=gantt._link_target_task_start=null}function a(t,e,i,a){var d=o(),l=n(),h=["gantt_link_direction"];gantt.templates.link_direction_class\046\046h.push(gantt.templates.link_direction_class(l.from,l.from_start,l.to,l.to_start));var _=Math.sqrt(Math.pow(i-t,2)+Math.pow(a-e,2));if(_=Math.max(0,_-3)){d.className=h.join(" ");var c=(a-e)/(i-t),g=Math.atan(c);2==s(t,i,e,a)?g+=Math.PI:3==s(t,i,e,a)\046\046(g-=Math.PI);var u=Math.sin(g),f=Math.cos(g),p=Math.round(e),m=Math.round(t),v=["-webkit-transform: rotate("+g+"rad)","-moz-transform: rotate("+g+"rad)","-ms-transform: rotate("+g+"rad)","-o-transform: rotate("+g+"rad)","transform: rotate("+g+"rad)","width:"+Math.round(_)+"px"];if(-1!=window.navigator.userAgent.indexOf("MSIE 8.0")){v.push(\'-ms-filter: "\'+r(u,f)+\'"\');var x=Math.abs(Math.round(t-i)),k=Math.abs(Math.round(a-e));switch(s(t,i,e,a)){case 1:p-=k;break;case 2:m-=x,p-=k;break;case 3:m-=x}}v.push("top:"+p+"px"),v.push("left:"+m+"px"),d.style.cssText=v.join(";")}}function r(t,e){return"progid:DXImageTransform.Microsoft.Matrix(M11 = "+e+","+"M12 = -"+t+","+"M21 = "+t+","+"M22 = "+e+","+"SizingMethod = \'auto expand\'"+")"}function s(t,e,n,i){return e\076=t?n\076=i?1:4:n\076=i?2:3}function o(){return l._direction||(l._direction=document.createElement("div"),gantt.$task_links.appendChild(l._direction)),l._direction}function d(){l._direction\046\046(l._direction.parentNode.removeChild(l._direction),l._direction=null)}var l=new dhtmlxDnD(this.$task_bars,{sensitivity:0,updates_per_second:60}),h="task_left",_="gantt_link_point",c="gantt_link_control";l.attachEvent("onBeforeDragStart",dhtmlx.bind(function(t,e){var n=e.target||e.srcElement;if(i(),gantt.getState().drag_id)return!1;if(gantt._locate_css(n,_)){gantt._locate_css(n,h)\046\046(gantt._link_source_task_start=!0);var a=gantt._link_source_task=this.locate(e),r=gantt.getTask(a);return this._dir_start={y:gantt._y_from_ind(gantt._get_visible_order(a))+gantt.config.row_height/2,x:gantt._pos_from_date(gantt._link_source_task_start?r.start_date:r.end_date)},!0}return!1},this)),l.attachEvent("onAfterDragStart",dhtmlx.bind(function(){t(l.config.marker)},this)),l.attachEvent("onDragMove",dhtmlx.bind(function(n,i){var r=l.config,s=l.getPosition(i);e(r.marker,s);var o=gantt._is_link_drop_area(i),d=gantt._link_target_task,_=gantt._link_landing,c=gantt._link_target_task_start,g=gantt.locate(i);if(o)var u=!1,u=!!gantt._locate_css(i,h),o=!!g;if(gantt._link_target_task=g,gantt._link_landing=o,gantt._link_target_task_start=u,o){var f=gantt.getTask(g),p=Math.floor((i.srcElement||i.target).offsetWidth/2);this._dir_end={y:gantt._y_from_ind(gantt._get_visible_order(g))+gantt.config.row_height/2,x:gantt._pos_from_date(u?f.start_date:f.end_date)+(u?-1:1)*p}}else this._dir_end=gantt._get_mouse_pos(i);var m=!(_==o\046\046d==g\046\046c==u);return m\046\046(d\046\046gantt.refreshTask(d,!1),g\046\046gantt.refreshTask(g,!1)),m\046\046t(r.marker),a(this._dir_start.x,this._dir_start.y,this._dir_end.x,this._dir_end.y),!0},this)),l.attachEvent("onDragEnd",dhtmlx.bind(function(){var t=n();if(t.from\046\046t.to\046\046t.from!=t.to){var e=gantt._get_link_type(t.from_start,t.to_start);e\046\046gantt.addLink({source:t.from,target:t.to,type:e})}i(),t.from\046\046gantt.refreshTask(t.from,!1),t.to\046\046gantt.refreshTask(t.to,!1),d()},this)),gantt._is_link_drop_area=function(t){return!!gantt._locate_css(t,c)}},gantt._get_link_state=function(){return{link_landing_area:this._link_landing,link_target_id:this._link_target_task,link_target_start:this._link_target_task_start,link_source_id:this._link_source_task,link_source_start:this._link_source_task_start}},gantt._init_tasks=function(){function t(t,e,n,i){for(var a=0;a\074t.length;a++)t[a].change_id(e,n),t[a].render_item(i)}this._tasks={col_width:this.config.columnWidth,width:[],full_width:0,trace_x:[],rendered:{}},this._click.gantt_task_link=dhtmlx.bind(function(t){var e=this.locate(t,gantt.config.link_attribute);e\046\046this.callEvent("onLinkClick",[e,t])},this),this._dbl_click.gantt_task_link=dhtmlx.bind(function(t,e){var e=this.locate(t,gantt.config.link_attribute);this._delete_link_handler(e,t)},this),this._dbl_click.gantt_link_point=dhtmlx.bind(function(t,e,n){var e=this.locate(t),i=this.getTask(e),a=null;return n.parentNode\046\046n.parentNode.className\046\046(a=n.parentNode.className.indexOf("_left")\076-1?i.$target[0]:i.$source[0]),a\046\046this._delete_link_handler(a,t),!1},this),this._tasks_dnd.init(),this._init_links_dnd(),this._taskRenderer=gantt._task_renderer("line",this._render_task_element,this.$task_bars),this._linkRenderer=gantt._task_renderer("links",this._render_link_element,this.$task_links),this._gridRenderer=gantt._task_renderer("grid_items",this._render_grid_item,this.$grid_data),this._bgRenderer=gantt._task_renderer("bg_lines",this._render_bg_line,this.$task_bg),this.attachEvent("onTaskIdChange",function(e,n){var i=this._get_task_renderers();t(i,e,n,this.getTask(n))}),this.attachEvent("onLinkIdChange",function(e,n){var i=this._get_link_renderers();t(i,e,n,this.getLink(n))})},gantt._get_task_renderers=function(){return[this._taskRenderer,this._gridRenderer,this._bgRenderer]},gantt._get_link_renderers=function(){return[this._linkRenderer]},gantt._delete_link_handler=function(t,e){if(t\046\046this.callEvent("onLinkDblClick",[t,e])){var n="",i=gantt.locale.labels.link+" "+this.templates.link_description(this.getLink(t))+" "+gantt.locale.labels.confirm_link_deleting;window.setTimeout(function(){gantt._dhtmlx_confirm(i,n,function(){gantt.deleteLink(t)})},gantt.config.touch?300:1)}},gantt.getTaskNode=function(t){return this._taskRenderer.rendered[t]},gantt.getLinkNode=function(t){return this._linkRenderer.rendered[t]},gantt._get_tasks_data=function(){for(var t=[],e=0;e\074this._order.length;e++){var n=this._pull[this._order[e]];n.$index=e,this._update_parents(n.id,!0),t.push(n)}return t},gantt._get_links_data=function(){var t=[];for(var e in this._lpull)t.push(this._lpull[e]);return t},gantt._render_data=function(){this._update_layout_sizes();for(var t=this._get_tasks_data(),e=this._get_task_renderers(),n=0;n\074e.length;n++)e[n].render_items(t);var i=gantt._get_links_data();e=this._get_link_renderers();for(var n=0;n\074e.length;n++)e[n].render_items(i)},gantt._update_layout_sizes=function(){var t=this._tasks,e=this.config.task_height;"full"==e\046\046(e=this.config.row_height-5),e=Math.min(e,this.config.row_height),t.bar_height=e,this.$task_data.style.height=this.$task.offsetHeight-this.config.scale_height+"px",this.$task_bg.style.width=t.full_width+"px";for(var n=this.config.columns,i=0,a=0;a\074n.length;a++)i+=n[a].width;this.$grid_data.style.width=i-1+"px"},gantt._init_tasks_range=function(){var t=this.config.scale_unit;if(this.config.start_date\046\046this.config.end_date)return this._min_date=this.date[t+"_start"](new Date(this.config.start_date)),this._max_date=this.date[t+"_start"](new Date(this.config.end_date)),void 0;var e=this._get_tasks_data(),n=this._init_task({id:0});e.push(n);var i=-1/0,a=1/0;this.eachTask(function(t){+t.end_date\076+i\046\046(i=new Date(t.end_date))},"0"),this.eachTask(function(t){+t.start_date\074+a\046\046(a=new Date(t.start_date))},"0"),this._min_date=a,this._max_date=i,i\046\046i!=-1/0||(this._min_date=new Date,this._max_date=new Date(this._min_date)),this._min_date=this.date[t+"_start"](this._min_date),+this._min_date==+a\046\046(this._min_date=this.date.add(this.date[t+"_start"](this._min_date),-1,t)),this._max_date=this.date[t+"_start"](this._max_date),this._max_date=this.date.add(this._max_date,1,t)},gantt._prepare_scale_html=function(t){var e=[],n=null,i=null,a=null;(t.template||t.date)\046\046(i=t.template||this.date.date_to_str(t.date)),a=t.css||gantt.templates.scale_cell_class;for(var r=0;r\074t.count;r++){n=new Date(t.trace_x[r]);var s=i.call(this,n),o=t.width[r],d="width:"+o+"px;",l="gantt_scale_cell"+(r==t.count-1?" gantt_last_cell":""),h=a.call(this,n);h\046\046(l+=" "+h);var _="\074div class=\'"+l+"\' style=\'"+d+"\'\076"+s+"\074/div\076";e.push(_)}return e.join("")},gantt._render_tasks_scales=function(){this._init_tasks_range(),this._scroll_resize(),this._set_sizes();var t=this._scale_helpers,e=[t.primaryScale()].concat(this.config.subscales);t.sortScales(e);for(var n=t.prepareConfigs(e,this.config.min_column_width,this.$task.offsetWidth,this.config.scale_height-1),i=this._tasks=n[n.length-1],a=[],r=0;r\074n.length;r++)a.push(\'\074div class="gantt_scale_line" style="height:\'+n[r].height+"px;line-height:"+n[r].height+\'px"\076\'+this._prepare_scale_html(n[r])+"\074/div\076");this.$task_scale.style.height=this.config.scale_height-1+"px",this.$task_data.style.width=this.$task_scale.style.width=i.full_width+this.$scroll_ver.offsetWidth+"px",this.$task_links.style.width=this.$task_bars.style.width=i.full_width+"px",e=a.join(""),this.$task_scale.innerHTML=e},gantt._render_bg_line=function(t){for(var e=gantt._tasks,n=e.count,i=[],a=0;n\076a;a++){var r=e.width[a],s="width:"+r+"px;",o="gantt_task_cell"+(a==n-1?" gantt_last_cell":"");h=this.templates.task_cell_class(t,e.trace_x[a]),h\046\046(o+=" "+h);var d="\074div class=\'"+o+"\' style=\'"+s+"\'\076\074/div\076";i.push(d)}var l=0!==t.$index%2,h=gantt.templates.task_row_class(t.start_date,t.end_date,t),_="gantt_task_row"+(l?" odd":"")+(h?" "+h:"");this.getState().selected_task==t.id\046\046(_+=" gantt_selected");var c=document.createElement("div");return c.className=_,c.style.height=gantt.config.row_height+"px",c.setAttribute(this.config.task_attribute,t.id),c.innerHTML=i.join(""),c},gantt._adjust_scales=function(){if(this.config.fit_tasks){var t=+this._min_date,e=+this._max_date;if(this._init_tasks_range(),+this._min_date!=t||+this._max_date!=e)return this.render(),this.callEvent("onScaleAdjusted",[]),!0}return!1},gantt.refreshTask=function(t,e){var n=this._get_task_renderers(),i=this.getTask(t);if(i\046\046this.isTaskVisible(t))for(var a=0;a\074n.length;a++)n[a].render_item(i);else for(var a=0;a\074n.length;a++)n[a].remove_item(t);if(void 0===e||e){for(var i=this.getTask(t),a=0;a\074i.$source.length;a++)gantt.refreshLink(i.$source[a]);for(var a=0;a\074i.$target.length;a++)gantt.refreshLink(i.$target[a])}},gantt.refreshLink=function(t){this.isLinkExists(t)?gantt._render_link(t):gantt._linkRenderer.remove_item(t)},gantt._combine_item_class=function(t,e,n){var i=[t];e\046\046i.push(e);var a=gantt.getState();this._is_flex_task(this.getTask(n))\046\046i.push("gantt_dependent_task"),this.config.select_task\046\046n==a.selected_task\046\046i.push("gantt_selected"),n==a.drag_id\046\046i.push("gantt_drag_"+a.drag_mode);var r=gantt._get_link_state();if(r.link_source_id==n\046\046i.push("gantt_link_source"),r.link_target_id==n\046\046i.push("gantt_link_target"),r.link_landing_area\046\046r.link_target_id\046\046r.link_source_id\046\046r.link_target_id!=r.link_source_id){var s=r.link_source_id,o=r.link_source_start,d=r.link_target_start,l=gantt.isLinkAllowed(s,n,o,d),h="";h=l?d?"link_start_allow":"link_finish_allow":d?"link_start_deny":"link_finish_deny",i.push(h)}return i.join(" ")},gantt._render_pair=function(t,e,n,i){var a=gantt.getState();+n.end_date\074=+a.max_date\046\046t.appendChild(i(e+" task_right")),+n.start_date\076=+a.min_date\046\046t.appendChild(i(e+" task_left"))},gantt._render_task_element=function(t){if(!(+t.start_date\074+this._max_date\046\046+t.end_date\076+this._min_date))return!1;var e=this._get_task_coord(t),n=this._pos_from_date(t.end_date),i=this.config,a=this._tasks.bar_height;a=Math.min(a,this.config.row_height);var r=Math.floor((this.config.row_height-a)/2),s=document.createElement("div"),o=Math.round(n-e.x);s.setAttribute(this.config.task_attribute,t.id),s.appendChild(gantt._render_task_content(t,o)),s.className=this._combine_item_class("gantt_task_line",this.templates.task_class(t.start_date,t.end_date,t),t.id),s.style.cssText=["left:"+e.x+"px","top:"+(r+e.y)+"px","height:"+a+"px","line-height:"+a+"px","width:"+o+"px"].join(";");var d=this._render_leftside_content(t);return d\046\046s.appendChild(d),d=this._render_rightside_content(t),d\046\046s.appendChild(d),i.show_progress\046\046this._render_task_progress(t,s,o),i.drag_resize\046\046!this._is_flex_task(t)\046\046gantt._render_pair(s,"gantt_task_drag",t,function(t){var e=document.createElement("div");return e.className=t,e}),i.drag_links\046\046gantt._render_pair(s,"gantt_link_control",t,function(t){var e=document.createElement("div");e.className=t,e.style.cssText=["height:"+a+"px","line-height:"+a+"px"].join(";");var n=document.createElement("div");return n.className="gantt_link_point",e.appendChild(n),e}),s},gantt._render_side_content=function(t,e,n){if(!e)return null;var i=e(t.start_date,t.end_date,t);if(!i)return null;var a=document.createElement("div");return a.className="gantt_side_content "+n,a.innerHTML=i,a},gantt._render_leftside_content=function(t){var e="gantt_left "+gantt._get_link_crossing_css(!0,t);return gantt._render_side_content(t,this.templates.leftside_text,e)},gantt._render_rightside_content=function(t){var e="gantt_right "+gantt._get_link_crossing_css(!1,t);return gantt._render_side_content(t,this.templates.rightside_text,e)},gantt._get_conditions=function(t){return t?{$source:[gantt.config.links.start_to_start],$target:[gantt.config.links.start_to_start,gantt.config.links.finish_to_start]}:{$source:[gantt.config.links.finish_to_start,gantt.config.links.finish_to_finish],$target:[gantt.config.links.finish_to_finish]}},gantt._get_link_crossing_css=function(t,e){var n=gantt._get_conditions(t);for(var i in n)for(var a=e[i],r=0;r\074a.length;r++)for(var s=gantt.getLink(a[r]),o=0;o\074n[i].length;o++)if(s.type==n[i][o])return"gantt_link_crossing";return""},gantt._render_task_content=function(t,e){var n=document.createElement("div");return n.innerHTML=this.templates.task_text(t.start_date,t.end_date,t),n.className="gantt_task_content",n.style.width=e+"px",n},gantt._render_task_progress=function(t,e,n){var i=1*t.progress||0;n=Math.max(n-2,0);var a=document.createElement("div"),r=Math.round(n*i);if(a.style.width=r+"px",a.className="gantt_task_progress",a.innerHTML=this.templates.progress_text(t.start_date,t.end_date,t),e.appendChild(a),this.config.drag_progress){var s=document.createElement("div");s.style.left=r+"px",s.className="gantt_task_progress_drag",a.appendChild(s),e.appendChild(s)}},gantt._get_line=function(t){var e={second:1,minute:60,hour:3600,day:86400,week:604800,month:2592e3,year:31536e3};return e[t]||0},gantt._date_from_pos=function(t){var e=this._tasks;if(0\076t||t\076e.full_width)return null;for(var n=0,i=0;i+e.width[n]\074t;)n++,i+=e.width[n];var a=(t-i)/e.width[n],r=gantt._get_coll_duration(e,e.trace_x[n]),s=new Date(e.trace_x[n].valueOf()+Math.round(a*r));return s},gantt._pos_from_date=function(t){var e=gantt._day_index_by_date(t);dhtmlx.assert(e\076=0,"Invalid day index");for(var n=Math.floor(e),i=e%1,a=0,r=1;n\076=r;r++)a+=gantt._tasks.width[r-1];return i\046\046(a+=n\074gantt._tasks.width.length?gantt._tasks.width[n]*(i%1):1),a},gantt._day_index_by_date=function(t){var e=new Date(t),n=gantt._tasks.trace_x;if(+e\074=this._min_date)return 0;if(+e\076=this._max_date)return n.length;for(var i=0;i\074n.length-1\046\046!(+e\074n[i+1]);i++);return i+(t-n[i])/gantt._get_coll_duration(gantt._tasks,n[i])},gantt._get_coll_duration=function(t,e){return gantt.date.add(e,t.step,t.unit)-e},gantt._get_y_pos=function(t){var e=this._get_visible_order(t);return dhtmlx.assert(-1!=e,"Task index not found"),e*this.config.row_height},gantt._get_task_coord=function(t){return{x:gantt._pos_from_date(t.start_date),y:gantt._get_y_pos(t.id)}},gantt._correct_shift=function(t,e){return t-=6e4*(new Date(gantt._min_date).getTimezoneOffset()-new Date(t).getTimezoneOffset())*(e?-1:1)},gantt._scroll_task_area=function(t,e){1*t===t\046\046(this.$task.scrollLeft=t),1*e===e\046\046(this.$task_data.scrollTop=e)},gantt._get_mouse_pos=function(t){if(t.pageX||t.pageY)var e={x:t.pageX,y:t.pageY};var n=_isIE?document.documentElement:document.body,e={x:t.clientX+n.scrollLeft-n.clientLeft,y:t.clientY+n.scrollTop-n.clientTop},i=gantt._get_position(gantt.$task_data);return e.x=e.x-i.x+gantt.$task_data.scrollLeft,e.y=e.y-i.y+gantt.$task_data.scrollTop,e},gantt._task_renderer=function(t,e,n){return this._task_area_pulls||(this._task_area_pulls={}),this._task_area_renderers||(this._task_area_renderers={}),this._task_area_renderers[t]?this._task_area_renderers[t]:(e||dhtmlx.assert(!1,"Invalid renderer call"),this._task_area_renderers[t]={render_item:function(i,a){var r=gantt._task_area_pulls[t];a=a||n;var s=e.call(gantt,i);s\046\046(r[i.id]?this.replace_item(i.id,s):(r[i.id]=s,a.appendChild(s)))\n
+},render_items:function(e,i){this.rendered=gantt._task_area_pulls[t]={},i=i||n,i.innerHTML="";for(var a=document.createDocumentFragment(),r=0,s=e.length;s\076r;r++)this.render_item(e[r],a);i.appendChild(a)},replace_item:function(t,e){var n=this.rendered[t];n\046\046n.parentNode\046\046n.parentNode.replaceChild(e,n),this.rendered[t]=e},remove_item:function(t){var e=this.rendered[t];e\046\046e.parentNode\046\046e.parentNode.removeChild(e),delete this.rendered[t]},change_id:function(t,e){this.rendered[e]=this.rendered[t],delete this.rendered[t]},rendered:this._task_area_pulls[t],node:n},this._task_area_renderers[t])},gantt.showTask=function(t){var e=this.getTaskNode(t),n=Math.max(e.offsetLeft-this.config.task_scroll_offset,0),i=e.offsetTop-(this.$task_data.offsetHeight-this.config.row_height)/2;this._scroll_task_area(n,i)},gantt._pull={},gantt._branches={},gantt._order=[],gantt._lpull={},gantt.load=function(t,e,n){dhtmlx.assert(arguments.length,"Invalid load arguments"),this.callEvent("onLoadStart",[]);var i="json",a=null;arguments.length\076=3?(i=e,a=n):"string"==typeof arguments[1]?i=arguments[1]:"function"==typeof arguments[1]\046\046(a=arguments[1]),dhtmlxAjax.get(t,dhtmlx.bind(function(t){this.on_load(t,i),"function"==typeof a\046\046a.call(this)},this))},gantt.parse=function(t,e){this.on_load({xmlDoc:{responseText:t}},e)},gantt.serialize=function(t){return t=t||"json",this[t].serialize()},gantt.on_load=function(t,e){e||(e="json"),dhtmlx.assert(this[e],"Invalid data type:\'"+e+"\'");var n=t.xmlDoc.responseText,i=this[e].parse(n,t);this._process_loading(i),this.callEvent("onLoadEnd",[])},gantt._process_loading=function(t){t.collections\046\046this._load_collections(t.collections);for(var e={},n=t.data,i=0;i\074n.length;i++){var a=n[i];this._init_task(a),this.callEvent("onTaskLoading",[e[i]])\046\046(e[a.id]=a,this._branches[a.parent]||(this._branches[a.parent]=[]),this._branches[a.parent].push(a.id))}dhtmlx.mixin(this._pull,e,!0),this._sync_order();for(var i in this._pull)this._pull[i].$level=this._item_level(this._pull[i]);this._init_links(t.links||(t.collections?t.collections.links:[]))},gantt._init_links=function(t){if(t)for(var e=0;e\074t.length;e++){var n=this._init_link(t[e]);this._lpull[n.id]=n}this._sync_links()},gantt._load_collections=function(t){var e=!1;for(var n in t)if(t.hasOwnProperty(n)){e=!0;var i=t[n],a=this.serverList[n];if(!a)continue;a.splice(0,a.length);for(var r=0;r\074i.length;r++){var s=i[r],o=dhtmlx.copy(s);o.key=o.value;for(var d in s)if(s.hasOwnProperty(d)){if("value"==d||"label"==d)continue;o[d]=s[d]}a.push(o)}}e\046\046this.callEvent("onOptionsLoad",[])},gantt._sync_order=function(){this._order=[],this._sync_order_item({parent:0,$open:!0,$ignore:!0,id:0}),this._scroll_resize(),this._set_sizes()},gantt.attachEvent("onBeforeTaskDisplay",function(t,e){return!e.$ignore}),gantt._sync_order_item=function(t){if(t.id\046\046this.callEvent("onBeforeTaskDisplay",[t.id,t])\046\046this._order.push(t.id),t.$open){var e=this._branches[t.id];if(e)for(var n=0;n\074e.length;n++)this._sync_order_item(this._pull[e[n]])}},gantt._get_visible_order=function(t){dhtmlx.assert(t,"Invalid argument");for(var e=this._order,n=0,i=e.length;i\076n;n++)if(e[n]==t)return n;return-1},gantt.eachTask=function(t,e,n){e=e||0,n=n||this;var i=this._branches[e];if(i)for(var a=0;a\074i.length;a++){var r=this._pull[i[a]];t.call(n,r),this._branches[r.id]\046\046this.eachTask(t,r.id,n)}},gantt.json={parse:function(data){return dhtmlx.assert(data,"Invalid data"),"string"==typeof data\046\046(window.JSON?data=JSON.parse(data):(gantt._temp=eval("("+data+")"),data=gantt._temp||{},gantt._temp=null)),data.dhx_security\046\046(dhtmlx.security_key=data.dhx_security),data},_copyLink:function(t){var e={};for(var n in t)e[n]=t[n];return e},_copyObject:function(t){var e={};for(var n in t)"$"!=n.charAt(0)\046\046(e[n]=t[n]);return e.start_date=gantt.templates.xml_format(e.start_date),e.end_date\046\046(e.end_date=gantt.templates.xml_format(e.end_date)),e},serialize:function(){var t=[],e=[];gantt.eachTask(function(e){t.push(this._copyObject(e))},0,this);for(var n in gantt._lpull)e.push(this._copyLink(gantt._lpull[n]));return{data:t,links:e}}},gantt.xml={_xmlNodeToJSON:function(t,e){for(var n={},i=0;i\074t.attributes.length;i++)n[t.attributes[i].name]=t.attributes[i].value;if(!e){for(var i=0;i\074t.childNodes.length;i++){var a=t.childNodes[i];1==a.nodeType\046\046(n[a.tagName]=a.firstChild?a.firstChild.nodeValue:"")}n.text||(n.text=t.firstChild?t.firstChild.nodeValue:"")}return n},_getCollections:function(t){for(var e={},n=t.doXPath("//coll_options"),i=0;i\074n.length;i++)for(var a=n[i].getAttribute("for"),r=e[a]=[],s=t.doXPath(".//item",n[i]),o=0;o\074s.length;o++){for(var d=s[o],l=d.attributes,h={key:s[o].getAttribute("value"),label:s[o].getAttribute("label")},_=0;_\074l.length;_++){var c=l[_];"value"!=c.nodeName\046\046"label"!=c.nodeName\046\046(h[c.nodeName]=c.nodeValue)}r.push(h)}return e},_getXML:function(t,e,n){if(n=n||"data",e.getXMLTopNode||(e=new dtmlXMLLoaderObject(function(){}),e.loadXMLString(t)),xml=e.getXMLTopNode(n),xml.tagName!=n)throw"Invalid XML data";var i=xml.getAttribute("dhx_security");return i\046\046(dhtmlx.security_key=i),e},parse:function(t,e){e=this._getXML(t,e);var n={},i=n.data=[];xml=e.doXPath("//task");for(var a=0;a\074xml.length;a++)i[a]=this._xmlNodeToJSON(xml[a]);return n.collections=this._getCollections(e),n},_copyLink:function(t){return"\074item id=\'"+t.id+"\' source=\'"+t.source+"\' target=\'"+t.target+"\' type=\'"+t.type+"\' /\076"},_copyObject:function(t){var e=gantt.templates.xml_format(t.start_date),n=gantt.templates.xml_format(t.end_date);return"\074task id=\'"+t.id+"\' parent=\'"+(t.parent||"")+"\' start_date=\'"+e+"\' duration=\'"+t.duration+"\' open=\'"+!!t.open+"\' progress=\'"+t.progress+"\' end_date=\'"+n+"\'\076\074![CDATA["+t.text+"]]\076\074/task\076"},serialize:function(){var t=[],e=[];gantt.eachTask(function(e){t.push(this._copyObject(e))},0,this);for(var n in gantt._lpull)e.push(this._copyLink(gantt._lpull[n]));return"\074data\076"+t.join("")+"\074coll_options for=\'links\'\076"+e.join("")+"\074/coll_options\076\074/data\076"}},gantt.oldxml={parse:function(t,e){e=gantt.xml._getXML(t,e,"projects");var n={collections:{links:[]}},i=n.data=[];xml=e.doXPath("//task");for(var a=0;a\074xml.length;a++){i[a]=gantt.xml._xmlNodeToJSON(xml[a]);var r=xml[a].parentNode;i[a].parent="project"==r.tagName?"project-"+r.getAttribute("id"):r.parentNode.getAttribute("id")}xml=e.doXPath("//project");for(var a=0;a\074xml.length;a++){var s=gantt.xml._xmlNodeToJSON(xml[a],!0);s.id="project-"+s.id,i.push(s)}for(var a=0;a\074i.length;a++){var s=i[a];s.start_date=s.startdate||s.est,s.end_date=s.enddate,s.text=s.name,s.duration=s.duration/8,s.open=1,s.duration||s.end_date||(s.duration=1),s.predecessortasks\046\046n.collections.links.push({target:s.id,source:s.predecessortasks,type:gantt.config.links.finish_to_start})}return n},serialize:function(){webix.message("Serialization to \'old XML\' is not implemented")}},gantt.serverList=function(t,e){return this.serverList[t]=e?e.slice(0):this.serverList[t]||[]},gantt.getTask=function(t){return dhtmlx.assert(this._pull[t]),this._pull[t]},gantt.getTaskByTime=function(t,e){var n=this._pull,i=[];if(t||e){t=+t||-1/0,e=+e||1/0;for(var a in n){var r=n[a];+r.start_date\074e\046\046+r.end_date\076t\046\046i.push(r)}}else for(var a in n)i.push(n[a]);return i},gantt.isTaskExists=function(t){return dhtmlx.defined(this._pull[t])},gantt.isTaskVisible=function(t){if(!this._pull[t])return!1;if(!(+this._pull[t].start_date\074+this._max_date\046\046+this._pull[t].end_date\076+this._min_date))return!1;for(var e=0,n=this._order.length;n\076e;e++)if(this._order[e]==t)return!0;return!1},gantt.updateTask=function(t,e){return dhtmlx.defined(e)||(e=this.getTask(t)),this.callEvent("onBeforeTaskUpdate",[t,e])===!1?!1:(this._pull[e.id]=e,this._update_parents(e.id),this.refreshTask(e.id),this.callEvent("onAfterTaskUpdate",[t,e]),this._sync_order(),this._adjust_scales(),void 0)},gantt.addTask=function(t,e){return dhtmlx.defined(e)||(e=t.parent||0),dhtmlx.defined(this._pull[e])||(e=0),t.parent=e,t=this._init_task(t),this.callEvent("onBeforeTaskAdd",[t.id,t])===!1?!1:(this._pull[t.id]=t,this._branches[t.parent]||(this._branches[t.parent]=[]),this._branches[t.parent].push(t.id),this.refreshData(),this.callEvent("onAfterTaskAdd",[t.id,t]),this._adjust_scales(),t.id)},gantt.deleteTask=function(t){return this._deleteTask(t)},gantt._deleteTask=function(t,e){var n=this.getTask(t);if(!e\046\046this.callEvent("onBeforeTaskDelete",[t,n])===!1)return!1;!e\046\046this._dp\046\046this._dp.setUpdateMode("off");var i=this._branches[n.id]||[];this._selected_task==t\046\046(this._selected_task=null);for(var a=0;a\074i.length;a++)this._silentStart(),this._deleteTask(i[a],!0),this._dp\046\046(this._dp._ganttMode="tasks",this._dp.setUpdated(i[a],!0,"deleted")),this._silentEnd();for(!e\046\046this._dp\046\046this._dp.setUpdateMode("cell");n.$source.length\0760;)this.deleteLink(n.$source[0]);for(;n.$target.length\0760;)this.deleteLink(n.$target[0]);return delete this._pull[t],delete this._branches[t],this._branch_update(n.parent,t),e||(this.callEvent("onAfterTaskDelete",[t,n]),this.refreshData()),!0},gantt.clearAll=function(){this._pull={},this._branches={},this._order=[],this._order_full=[],this._lpull={},this.refreshData(),this.callEvent("onClear",[])},gantt.changeTaskId=function(t,e){var n=this._pull[e]=this._pull[t];this._pull[e].id=e,delete this._pull[t];for(var i in this._pull)this._pull[i].parent==t\046\046(this._pull[i].parent=e);this._lightbox_id==t\046\046(this._lightbox_id=e),this._branch_update(n.parent,t,e),this._sync_order(),this.callEvent("onTaskIdChange",[t,e])},gantt._branch_update=function(t,e,n){var i=this._branches[t];if(i){for(var a=[],r=0;r\074i.length;r++)i[r]!=e?a.push(i[r]):n\046\046a.push(n);this._branches[t]=a}},gantt._get_duration_unit=function(){return 1e3*gantt._get_line(this.config.duration_unit)||this.config.duration_unit},gantt._init_task=function(t){dhtmlx.defined(t.id)||(t.id=dhtmlx.uid()),t.start_date\046\046(t.start_date=gantt.date.parseDate(t.start_date,"xml_date")),t.end_date\046\046(t.end_date=gantt.date.parseDate(t.end_date,"xml_date"));var e=this._get_duration_unit();return t.start_date\046\046t.duration\046\046(t.end_date=new Date(t.start_date.valueOf()+t.duration*e)),gantt._init_task_timing(t),t.$source=[],t.$target=[],t.parent=t.parent||0,t.$open=dhtmlx.defined(t.open)?t.open:!1,t.$level=this._item_level(t),t},gantt._init_task_timing=function(t){t.$no_end=!(t.end_date||t.duration),t.$no_start=!t.start_date},gantt._is_flex_task=function(t){return!(!t.$no_end\046\046!t.$no_start)},gantt._update_parents=function(t,e){if(t){for(var n=this.getTask(t);!n.$no_end\046\046!n.$no_start\046\046n.parent\046\046this.isTaskExists(n.parent);)n=this.getTask(n.parent);if(n.$no_end){var i=0;this.eachTask(function(t){+t.end_date\076+i\046\046(i=new Date(t.end_date))},n.id),i\046\046(n.end_date=i)}if(n.$no_start){var a=1/0;this.eachTask(function(t){+t.start_date\074+a\046\046(a=new Date(t.start_date))},n.id),1/0!=a\046\046(n.start_date=a)}(n.$no_end||n.$no_start)\046\046(this._update_task_duration(n),e||this.refreshTask(n.id,!0)),n.parent\046\046this.isTaskExists(n.parent)\046\046this._update_parents(n.parent,e)}},gantt._round_date=function(t,e,n){var i=new Date(1970,0,1),n=gantt.date.add(i,e,n)-i,a=t-i,r=a%n,s=a-r+Math.round(r/n)*n;return new Date(+i+s)},gantt._round_task_dates=function(t,e,n){t.start_date=this._round_date(+t.start_date,e,n),t.end_date=this._round_date(+t.end_date,e,n),t.end_date\074=t.start_date\046\046(t.end_date=gantt.date.add(t.start_date,e,n))},gantt._update_task_duration=function(t){t.start_date\046\046t.end_date\046\046(t.duration=Math.round((t.end_date-t.start_date)/(this.config.duration_step*this._get_duration_unit())))},gantt._item_level=function(t){for(var e=0;t.parent\046\046dhtmlx.defined(this._pull[t.parent]);)t=this._pull[t.parent],e++;return e},gantt.sort=function(t,e,n){var i=!arguments[3];dhtmlx.defined(n)||(n=0),dhtmlx.defined(t)||(t="order");var a="string"==typeof t?function(n,i){var a=n[t]\076i[t];return e\046\046(a=!a),a?1:-1}:t,r=this._branches[n];if(r){for(var s=[],o=r.length-1;o\076=0;o--)s[o]=this._pull[r[o]];s.sort(a);for(var o=0;o\074s.length;o++)r[o]=s[o].id,this.sort(t,e,r[o],!0)}i\046\046this.refreshData()},gantt.getNext=function(t){for(var e=0;e\074this._order.length-1;e++)if(this._order[e]==t)return this._order[e+1];return null},gantt.getPrev=function(t){for(var e=1;e\074this._order.length;e++)if(this._order[e]==t)return this._order[e-1];return null},gantt._dp_init=function(t){t.setTransactionMode("POST",!0),t.serverProcessor+=(-1!=t.serverProcessor.indexOf("?")?"\046":"?")+"editing=true",t._serverProcessor=t.serverProcessor,t.styles={updated:"gantt_updated",inserted:"gantt_inserted",deleted:"gantt_deleted",invalid:"gantt_invalid",error:"gantt_error",clear:""},t._methods=["_row_style","setCellTextStyle","_change_id","_delete_task"],this.attachEvent("onAfterTaskAdd",function(e){t._ganttMode="tasks",t.setUpdated(e,!0,"inserted")}),this.attachEvent("onAfterTaskUpdate",function(e){t._ganttMode="tasks",t.setUpdated(e,!0)}),this.attachEvent("onAfterTaskDelete",function(e){t._ganttMode="tasks",t.setUpdated(e,!0,"deleted")}),this.attachEvent("onAfterLinkUpdate",function(e){t._ganttMode="links",t.setUpdated(e,!0)}),this.attachEvent("onAfterLinkAdd",function(e){t._ganttMode="links",t.setUpdated(e,!0,"inserted")}),this.attachEvent("onAfterLinkDelete",function(e){t._ganttMode="links",t.setUpdated(e,!0,"deleted")}),this.attachEvent("onRowDragEnd",function(e,n){t._ganttMode="tasks",this.getTask(e).target=n,t.setUpdated(e,!0,"order")}),t.attachEvent("onBeforeDataSending",function(){return this.serverProcessor=this._serverProcessor+getUrlSymbol(this._serverProcessor)+"gantt_mode="+this._ganttMode,!0}),t._getRowData=dhtmlx.bind(function(e){var n;n="tasks"==t._ganttMode?this.isTaskExists(e)?this.getTask(e):{id:e}:this.isLinkExists(e)?this.getLink(e):{id:e};var i={};for(var a in n)if("$"!=a.substr(0,1)){var r=n[a];i[a]=r instanceof Date?this.templates.xml_format(r):r}return n.$no_start\046\046(n.start_date="",n.duration=""),n.$no_end\046\046(n.end_date="",n.duration=""),i[t.action_param]=this.getUserData(e,t.action_param),i},this),this._change_id=dhtmlx.bind(function(e,n){"tasks"!=t._ganttMode?this.changeLinkId(e,n):this.changeTaskId(e,n)},this),this._row_style=function(e,n){if("tasks"==t._ganttMode){var i=gantt.getTaskRowNode(e);if(i)if(n)i.className+=" "+n;else{var a=/ (gantt_updated|gantt_inserted|gantt_deleted|gantt_invalid|gantt_error)/g;i.className=i.className.replace(a,"")}}},this._delete_task=function(){},this._dp=t},gantt.getUserData=function(t,e){return this.userdata||(this.userdata={}),this.userdata[t]\046\046this.userdata[t][e]?this.userdata[t][e]:""},gantt.setUserData=function(t,e,n){this.userdata||(this.userdata={}),this.userdata[t]||(this.userdata[t]={}),this.userdata[t][e]=n},gantt._init_link=function(t){return dhtmlx.defined(t.id)||(t.id=dhtmlx.uid()),t},gantt._sync_links=function(){for(var t in this._pull)this._pull[t].$source=[],this._pull[t].$target=[];for(var t in this._lpull){var e=this._lpull[t];this._pull[e.source]\046\046this._pull[e.source].$source.push(t),this._pull[e.target]\046\046this._pull[e.target].$target.push(t)}},gantt.getLink=function(t){return dhtmlx.assert(this._lpull[t],"Link doesn\'t exist"),this._lpull[t]},gantt.isLinkExists=function(t){return dhtmlx.defined(this._lpull[t])},gantt.addLink=function(t){return t=this._init_link(t),this.callEvent("onBeforeLinkAdd",[t.id,t])===!1?!1:(this._lpull[t.id]=t,this._sync_links(),this._render_link(t.id),this.callEvent("onAfterLinkAdd",[t.id,t]),t.id)},gantt.updateLink=function(t,e){return dhtmlx.defined(e)||(e=this.getLink(t)),this.callEvent("onBeforeLinkUpdate",[t,e])===!1?!1:(this._lpull[t]=e,this._sync_links(),this._render_link(t),this.callEvent("onAfterLinkUpdate",[t,e]),!0)},gantt.deleteLink=function(t){return this._deleteLink(t)},gantt._deleteLink=function(t,e){var n=this.getLink(t);return e||this.callEvent("onBeforeLinkDelete",[t,n])!==!1?(delete this._lpull[t],this._sync_links(),this.refreshLink(t),e||this.callEvent("onAfterLinkDelete",[t,n]),!0):!1},gantt.changeLinkId=function(t,e){this._lpull[e]=this._lpull[t],this._lpull[e].id=e,delete this._lpull[t],this._sync_links(),this.callEvent("onLinkIdChange",[t,e])},gantt.getChildren=function(t){return dhtmlx.defined(this._branches[t])?this._branches[t]:[]},gantt.hasChild=function(t){return dhtmlx.defined(this._branches[t])},gantt.refreshData=function(){this._sync_order(),this._render_data()},gantt._configure=function(t,e){for(var n in e)"undefined"==typeof t[n]\046\046(t[n]=e[n])},gantt._init_skin=function(){if(!gantt.skin)for(var t=document.getElementsByTagName("link"),e=0;e\074t.length;e++){var n=t[e].href.match("dhtmlxgantt_([a-z]+).css");if(n){gantt.skin=n[1];break}}gantt.skin||(gantt.skin="terrace");var i=gantt.skins[gantt.skin];this._configure(gantt.config,i.config);var a=gantt.config.columns;a[1]\046\046"undefined"==typeof a[1].width\046\046(a[1].width=i._second_column_width),a[2]\046\046"undefined"==typeof a[2].width\046\046(a[2].width=i._third_column_width),i._lightbox_template\046\046(gantt._lightbox_template=i._lightbox_template),gantt._init_skin=function(){}},gantt.skins={},gantt._lightbox_methods={},gantt._lightbox_template="\074div class=\'dhx_cal_ltitle\'\076\074span class=\'dhx_mark\'\076\046nbsp;\074/span\076\074span class=\'dhx_time\'\076\074/span\076\074span class=\'dhx_title\'\076\074/span\076\074/div\076\074div class=\'dhx_cal_larea\'\076\074/div\076",gantt.showLightbox=function(t){if(t\046\046this.callEvent("onBeforeLightbox",[t])){var e=this.getLightbox();this._center_lightbox(e),this.showCover(),this._fill_lightbox(t,e),this.callEvent("onLightbox",[t])}},gantt._get_timepicker_step=function(){if(this.config.round_dnd_dates){var t=gantt._tasks,e=this._get_line(t.unit)*t.step/60;return e\076=1440\046\046(e=this.config.time_step),e}return this.config.time_step},gantt.getLabel=function(t,e){for(var n=this.config.lightbox.sections,i=0;i\074n.length;i++)if(n[i].map_to==t)for(var a=n[i].options,r=0;r\074a.length;r++)if(a[r].key==e)return a[r].label;return""},gantt.getLightbox=function(){if(!this._lightbox){var t=document.createElement("DIV");t.className="dhx_cal_light";var e=this._is_lightbox_timepicker();(gantt.config.wide_form||e)\046\046(t.className+=" dhx_cal_light_wide"),e\046\046(gantt.config.wide_form=!0,t.className+=" dhx_cal_light_full"),t.style.visibility="hidden";var n=this._lightbox_template,i=this.config.buttons_left;for(var a in i)n+="\074div class=\'dhx_btn_set dhx_left_btn_set "+i[a]+"_set\'\076\074div dhx_button=\'1\' class=\'"+i[a]+"\'\076\074/div\076\074div\076"+this.locale.labels[i[a]]+"\074/div\076\074/div\076";i=this.config.buttons_right;for(var a in i)n+="\074div class=\'dhx_btn_set dhx_right_btn_set "+i[a]+"_set\' style=\'float:right;\'\076\074div dhx_button=\'1\' class=\'"+i[a]+"\'\076\074/div\076\074div\076"+this.locale.labels[i[a]]+"\074/div\076\074/div\076";n+="\074/div\076",t.innerHTML=n,gantt.config.drag_lightbox\046\046(t.firstChild.onmousedown=gantt._ready_to_dnd,t.firstChild.onselectstart=function(){return!1},t.firstChild.style.cursor="pointer",gantt._init_dnd_events()),document.body.insertBefore(t,document.body.firstChild),this._lightbox=t;var r=this.config.lightbox.sections;n=this._render_sections(r);for(var s=t.getElementsByTagName("div"),a=0;a\074s.length;a++){var o=s[a];if("dhx_cal_larea"==o.className){o.innerHTML=n;break}}this.resizeLightbox(),this._init_lightbox_events(this),t.style.display="none",t.style.visibility="visible"}return this._lightbox},gantt._render_sections=function(t){for(var e="",n=0;n\074t.length;n++){var i=this.form_blocks[t[n].type];if(i){t[n].id="area_"+dhtmlx.uid();var a="";t[n].button\046\046(a="\074div class=\'dhx_custom_button\' index=\'"+n+"\'\076\074div class=\'dhx_custom_button_"+t[n].button+"\'\076\074/div\076\074div\076"+this.locale.labels["button_"+t[n].button]+"\074/div\076\074/div\076"),this.config.wide_form\046\046(e+="\074div class=\'dhx_wrap_section\'\076"),e+="\074div id=\'"+t[n].id+"\' class=\'dhx_cal_lsection\'\076"+a+this.locale.labels["section_"+t[n].name]+"\074/div\076"+i.render.call(this,t[n]),e+="\074/div\076"}}return e},gantt.resizeLightbox=function(){var t=this._lightbox;if(t){var e=t.childNodes[1];e.style.height="0px",e.style.height=e.scrollHeight+"px",t.style.height=e.scrollHeight+this.config.lightbox_additional_height+"px",e.style.height=e.scrollHeight+"px"}},gantt._center_lightbox=function(t){if(t){t.style.display="block";var e=window.pageYOffset||document.body.scrollTop||document.documentElement.scrollTop,n=window.pageXOffset||document.body.scrollLeft||document.documentElement.scrollLeft,i=window.innerHeight||document.documentElement.clientHeight;t.style.top=e?Math.round(e+Math.max((i-t.offsetHeight)/2,0))+"px":Math.round(Math.max((i-t.offsetHeight)/2,0)+9)+"px",t.style.left=document.documentElement.scrollWidth\076document.body.offsetWidth?Math.round(n+(document.body.offsetWidth-t.offsetWidth)/2)+"px":Math.round((document.body.offsetWidth-t.offsetWidth)/2)+"px"}},gantt.showCover=function(){this._cover=document.createElement("DIV"),this._cover.className="dhx_cal_cover";var t=void 0!==document.height?document.height:document.body.offsetHeight,e=document.documentElement?document.documentElement.scrollHeight:0;this._cover.style.height=Math.max(t,e)+"px",document.body.appendChild(this._cover)},gantt._init_lightbox_events=function(){gantt.lightbox_events={},gantt.lightbox_events.dhx_save_btn=function(){gantt._save_lightbox()},gantt.lightbox_events.dhx_delete_btn=function(){gantt.callEvent("onLightboxDelete",[gantt._lightbox_id])\046\046gantt.$click.buttons["delete"](gantt._lightbox_id)},gantt.lightbox_events.dhx_cancel_btn=function(){gantt._cancel_lightbox()},gantt.lightbox_events["default"]=function(t,e){if(e.getAttribute("dhx_button"))gantt.callEvent("onLightboxButton",[e.className,e,t]);else{var n,i,a;-1!=e.className.indexOf("dhx_custom_button")\046\046(-1!=e.className.indexOf("dhx_custom_button_")?(n=e.parentNode.getAttribute("index"),a=e.parentNode.parentNode):(n=e.getAttribute("index"),a=e.parentNode,e=e.firstChild)),n\046\046(i=gantt.form_blocks[gantt.config.lightbox.sections[n].type],i.button_click(n,e,a,a.nextSibling))}},dhtmlxEvent(gantt.getLightbox(),"click",function(t){t=t||window.event;var e=t.target?t.target:t.srcElement;if(e.className||(e=e.previousSibling),e\046\046e.className\046\0460===e.className.indexOf("dhx_btn_set")\046\046(e=e.firstChild),e\046\046e.className){var n=dhtmlx.defined(gantt.lightbox_events[e.className])?gantt.lightbox_events[e.className]:gantt.lightbox_events["default"];return n(t,e)}return!1}),gantt.getLightbox().onkeydown=function(t){switch((t||event).keyCode){case gantt.keys.edit_save:if((t||event).shiftKey)return;gantt._save_lightbox();break;case gantt.keys.edit_cancel:gantt._cancel_lightbox()}}},gantt._cancel_lightbox=function(){this.callEvent("onLightboxCancel",[this._lightbox_id,this.$new]),this.hideLightbox()},gantt._save_lightbox=function(){var t=this.getLightboxValues();this.callEvent("onLightboxSave",[this._lightbox_id,t,!!t.$new])\046\046(t.$new?this.addTask(t):(dhtmlx.mixin(this.getTask(t.id),t,!0),this.updateTask(t.id)),this.refreshData(),this.hideLightbox())},gantt.getLightboxValues=function(){for(var t=dhtmlx.mixin({},this.getTask(this._lightbox_id)),e=this.config.lightbox.sections,n=0;n\074e.length;n++){var i=document.getElementById(e[n].id);i=i?i.nextSibling:i;var a=this.form_blocks[e[n].type],r=a.get_value.call(this,i,t,e[n]);"auto"!=e[n].map_to\046\046(t[e[n].map_to]=r)}return t},gantt.hideLightbox=function(){var t=this.getLightbox();t\046\046(t.style.display="none"),this._lightbox_id=null,this.hideCover(),this.callEvent("onAfterLightbox",[])},gantt.hideCover=function(){this._cover\046\046this._cover.parentNode.removeChild(this._cover),this._cover=null},gantt.resetLightbox=function(){gantt._lightbox\046\046!gantt._custom_lightbox\046\046gantt._lightbox.parentNode.removeChild(gantt._lightbox),gantt._lightbox=null},gantt._fill_lightbox=function(t,e){var n=this.getTask(t),i=e.getElementsByTagName("span");gantt.templates.lightbox_header?(i[1].innerHTML="",i[2].innerHTML=gantt.templates.lightbox_header(n.start_date,n.end_date,n)):(i[1].innerHTML=this.templates.task_time(n.start_date,n.end_date,n),i[2].innerHTML=(this.templates.task_text(n.start_date,n.end_date,n)||"").substr(0,70));for(var a=this.config.lightbox.sections,r=0;r\074a.length;r++){var s=a[r],o=document.getElementById(s.id).nextSibling,d=this.form_blocks[s.type],l=dhtmlx.defined(n[s.map_to])?n[s.map_to]:s.default_value;d.set_value.call(this,o,l,n,s),s.focus\046\046d.focus.call(this,o)}gantt._lightbox_id=t},gantt.getLightboxSection=function(t){var e=this.config.lightbox.sections,n=0;for(n;n\074e.length\046\046e[n].name!=t;n++);var i=e[n];this._lightbox||this.getLightbox();var a=document.getElementById(i.id),r=a.nextSibling,s={section:i,header:a,node:r,getValue:function(t){return this.form_blocks[i.type].get_value(r,t||{},i)},setValue:function(t,e){return this.form_blocks[i.type].set_value(r,t,e||{},i)}},o=this._lightbox_methods["get_"+i.type+"_control"];return o?o(s):s},gantt._lightbox_methods.get_template_control=function(t){return t.control=t.node,t},gantt._lightbox_methods.get_select_control=function(t){return t.control=t.node.getElementsByTagName("select")[0],t},gantt._lightbox_methods.get_textarea_control=function(t){return t.control=t.node.getElementsByTagName("textarea")[0],t},gantt._lightbox_methods.get_time_control=function(t){return t.control=t.node.getElementsByTagName("select"),t},gantt._init_dnd_events=function(){dhtmlxEvent(document.body,"mousemove",gantt._move_while_dnd),dhtmlxEvent(document.body,"mouseup",gantt._finish_dnd),gantt._init_dnd_events=function(){}},gantt._move_while_dnd=function(t){if(gantt._dnd_start_lb){document.dhx_unselectable||(document.body.className+=" dhx_unselectable",document.dhx_unselectable=!0);var e=gantt.getLightbox(),n=t\046\046t.target?[t.pageX,t.pageY]:[event.clientX,event.clientY];e.style.top=gantt._lb_start[1]+n[1]-gantt._dnd_start_lb[1]+"px",e.style.left=gantt._lb_start[0]+n[0]-gantt._dnd_start_lb[0]+"px"}},gantt._ready_to_dnd=function(t){var e=gantt.getLightbox();gantt._lb_start=[parseInt(e.style.left,10),parseInt(e.style.top,10)],gantt._dnd_start_lb=t\046\046t.target?[t.pageX,t.pageY]:[event.clientX,event.clientY]},gantt._finish_dnd=function(){gantt._lb_start\046\046(gantt._lb_start=gantt._dnd_start_lb=!1,document.body.className=document.body.className.replace(" dhx_unselectable",""),document.dhx_unselectable=!1)},gantt._focus=function(t,e){t\046\046t.focus\046\046(gantt.config.touch||(e\046\046t.select\046\046t.select(),t.focus()))},gantt.form_blocks={getTimePicker:function(t){var e=t.time_format;if(!e){var e=["%d","%m","%Y"];gantt._get_line(gantt._tasks.unit)\074gantt._get_line("day")\046\046e.push("%H:%i")}t._time_format_order={size:0};var n=this.config,i=this.date.date_part(new Date(gantt._min_date.valueOf())),a=1440,r=0;gantt.config.limit_time_select\046\046(a=60*n.last_hour+1,r=60*n.first_hour,i.setHours(n.first_hour));for(var s="",o=0;o\074e.length;o++){var d=e[o];switch(o\0760\046\046(s+=" "),d){case"%Y":t._time_format_order[2]=o,t._time_format_order.size++,s+="\074select\076";for(var l=i.getFullYear()-5,h=0;10\076h;h++)s+="\074option value=\'"+(l+h)+"\'\076"+(l+h)+"\074/option\076";s+="\074/select\076 ";break;case"%m":t._time_format_order[1]=o,t._time_format_order.size++,s+="\074select\076";for(var h=0;12\076h;h++)s+="\074option value=\'"+h+"\'\076"+this.locale.date.month_full[h]+"\074/option\076";s+="\074/select\076";break;case"%d":t._time_format_order[0]=o,t._time_format_order.size++,s+="\074select\076";for(var h=1;32\076h;h++)s+="\074option value=\'"+h+"\'\076"+h+"\074/option\076";s+="\074/select\076";break;case"%H:%i":var a=1440,r=0;t._time_format_order[3]=o,t._time_format_order.size++,s+="\074select\076";var h=r,_=i.getDate();for(t._time_values=[];a\076h;){var c=this.templates.time_picker(i);s+="\074option value=\'"+h+"\'\076"+c+"\074/option\076",t._time_values.push(h),i.setTime(i.valueOf()+1e3*60*this._get_timepicker_step());var g=i.getDate()!=_?1:0;h=60*24*g+60*i.getHours()+i.getMinutes()}s+="\074/select\076"}}return s},_fill_lightbox_select:function(t,e,n,i){if(t[e+i[0]].value=n.getDate(),t[e+i[1]].value=n.getMonth(),t[e+i[2]].value=n.getFullYear(),dhtmlx.defined(i[3])){var a=60*n.getHours()+n.getMinutes();a=Math.round(a/gantt._get_timepicker_step())*gantt._get_timepicker_step(),t[e+i[3]].value=a}},template:{render:function(t){var e=(t.height||"30")+"px";return"\074div class=\'dhx_cal_ltext dhx_cal_template\' style=\'height:"+e+";\'\076\074/div\076"},set_value:function(t,e){t.innerHTML=e||""},get_value:function(t){return t.innerHTML||""},focus:function(){}},textarea:{render:function(t){var e=(t.height||"130")+"px";return"\074div class=\'dhx_cal_ltext\' style=\'height:"+e+";\'\076\074textarea\076\074/textarea\076\074/div\076"},set_value:function(t,e){t.firstChild.value=e||""},get_value:function(t){return t.firstChild.value},focus:function(t){var e=t.firstChild;gantt._focus(e,!0)}},select:{render:function(t){for(var e=(t.height||"23")+"px",n="\074div class=\'dhx_cal_ltext\' style=\'height:"+e+";\'\076\074select style=\'width:100%;\'\076",i=0;i\074t.options.length;i++)n+="\074option value=\'"+t.options[i].key+"\'\076"+t.options[i].label+"\074/option\076";return n+="\074/select\076\074/div\076"},set_value:function(t,e,n,i){var a=t.firstChild;!a._dhx_onchange\046\046i.onchange\046\046(a.onchange=i.onchange,a._dhx_onchange=!0),"undefined"==typeof e\046\046(e=(a.options[0]||{}).value),a.value=e||""},get_value:function(t){return t.firstChild.value},focus:function(t){var e=t.firstChild;gantt._focus(e,!0)}},time:{render:function(t){var e=this.form_blocks.getTimePicker.call(this,t),n="\074div style=\'height:30px;padding-top:0px;font-size:inherit;text-align:center;\' class=\'dhx_section_time\'\076"+e+"\074span style=\'font-weight:normal; font-size:10pt;\'\076 \046nbsp;\046ndash;\046nbsp; \074/span\076"+e+"\074/div\076";return n},set_value:function(t,e,n,i){function a(){var t=new Date(s[o[2]].value,s[o[1]].value,s[o[0]].value,0,0),e=new Date(t.getTime()+1e3*60*gantt.config.event_duration);this.form_blocks._fill_lightbox_select(s,o.size,e,o,r)}var r=this.config,s=t.getElementsByTagName("select"),o=i._time_format_order;if(i._time_format_size,r.auto_end_date\046\046r.event_duration)for(var d=0;4\076d;d++)s[d].onchange=a;this.form_blocks._fill_lightbox_select(s,0,n.start_date,o,r),this.form_blocks._fill_lightbox_select(s,o.size,n.end_date,o,r)},get_value:function(t,e,n){var i=t.getElementsByTagName("select"),a=n._time_format_order,r=0,s=0;if(dhtmlx.defined(a[3])){var o=parseInt(i[a[3]].value,10);r=Math.floor(o/60),s=o%60}if(e.start_date=new Date(i[a[2]].value,i[a[1]].value,i[a[0]].value,r,s),r=s=0,dhtmlx.defined(a[3])){var o=parseInt(i[a.size+a[3]].value,10);r=Math.floor(o/60),s=o%60}return e.end_date=new Date(i[a[2]+a.size].value,i[a[1]+a.size].value,i[a[0]+a.size].value,r,s),e.end_date\074=e.start_date\046\046(e.end_date=gantt.date.add(e.start_date,gantt._get_timepicker_step(),"minute")),{start_date:new Date(e.start_date),end_date:new Date(e.end_date)}},focus:function(t){gantt._focus(t.getElementsByTagName("select")[0])}},duration:{render:function(t){var e=this.form_blocks.getTimePicker.call(this,t);e="\074div class=\'dhx_time_selects\'\076"+e+"\074/div\076";var n=this.locale.labels[this._tasks.unit+"s"],i="\074div class=\'dhx_gantt_duration\'\076\074input type=\'button\' class=\'dhx_gantt_duration_dec\' value=\'-\'\076\074input type=\'text\' value=\'5\' class=\'dhx_gantt_duration_value\'\076\074input type=\'button\' class=\'dhx_gantt_duration_inc\' value=\'+\'\076 "+n+" \074span\076\074/span\076\074/div\076",a="\074div style=\'height:30px;padding-top:0px;font-size:inherit;\' class=\'dhx_section_time\'\076"+e+" "+i+"\074/div\076";return a},set_value:function(t,e,n,i){function a(){var e=gantt.form_blocks.duration._get_start_date.call(gantt,t,i),n=gantt.form_blocks.duration._get_duration.call(gantt,t,i),a=gantt.date.add(e,n,gantt._tasks.unit);_.innerHTML=gantt.templates.task_date(a)}function r(t){var e=l.value;e=parseInt(e,10),window.isNaN(e)\046\046(e=0),e+=t,1\076e\046\046(e=1),l.value=e,a()}var s=this.config,o=t.getElementsByTagName("select"),d=t.getElementsByTagName("input"),l=d[1],h=[d[0],d[2]],_=t.getElementsByTagName("span")[0],c=i._time_format_order;h[0].onclick=dhtmlx.bind(function(){r(-1*this.config.duration_step)},this),h[1].onclick=dhtmlx.bind(function(){r(1*this.config.duration_step)},this),o[0].onchange=a,o[1].onchange=a,o[2].onchange=a,o[3]\046\046(o[3].onchange=a),l.onkeydown=dhtmlx.bind(function(t){t=t||window.event;var e=t.charCode||t.keyCode||t.which;return 40==e?(r(-1*this.config.duration_step),!1):38==e?(r(1*this.config.duration_step),!1):(window.setTimeout(function(){a()},1),void 0)},this),l.onchange=dhtmlx.bind(function(){a()},this),this.form_blocks._fill_lightbox_select(o,0,n.start_date,c,s);var g,u=gantt._tasks.unit;g=n.end_date?(n.end_date.valueOf()-n.start_date.valueOf())/(1e3*this._get_line(u)):n.duration,g=Math.round(g),l.value=g,a()},_get_start_date:function(t,e){var n=t.getElementsByTagName("select"),i=e._time_format_order,a=0,r=0;\n
+if(dhtmlx.defined(i[3])){var s=parseInt(n[i[3]].value,10);a=Math.floor(s/60),r=s%60}return new Date(n[i[2]].value,n[i[1]].value,n[i[0]].value,a,r)},_get_duration:function(t){var e=t.getElementsByTagName("input")[1];return e=parseInt(e.value,10),window.isNaN(e)\046\046(e=1),0\076e\046\046(e*=-1),e},get_value:function(t,e,n){e.start_date=this.form_blocks.duration._get_start_date(t,n);var i=this.form_blocks.duration._get_duration(t,n);return e.end_date=this.date.add(e.start_date,i,this._tasks.unit),e.duration=i,{start_date:new Date(e.start_date),end_date:new Date(e.end_date)}},focus:function(t){gantt._focus(t.getElementsByTagName("select")[0])}}},gantt._is_lightbox_timepicker=function(){for(var t=this.config.lightbox.sections,e=0;e\074t.length;e++)if("time"==t[e].name\046\046"time"==t[e].type)return!0;return!1},gantt._dhtmlx_confirm=function(t,e,n,i){if(!t)return n();var a={text:t};e\046\046(a.title=e),i\046\046(a.ok=i),n\046\046(a.callback=function(t){t\046\046n()}),dhtmlx.confirm(a)},dataProcessor.prototype={setTransactionMode:function(t,e){this._tMode=t,this._tSend=e},escape:function(t){return this._utf?encodeURIComponent(t):escape(t)},enableUTFencoding:function(t){this._utf=convertStringToBoolean(t)},setDataColumns:function(t){this._columns="string"==typeof t?t.split(","):t},getSyncState:function(){return!this.updatedRows.length},enableDataNames:function(t){this._endnm=convertStringToBoolean(t)},enablePartialDataSend:function(t){this._changed=convertStringToBoolean(t)},setUpdateMode:function(t,e){this.autoUpdate="cell"==t,this.updateMode=t,this.dnd=e},ignore:function(t,e){this._silent_mode=!0,t.call(e||window),this._silent_mode=!1},setUpdated:function(t,e,n){if(!this._silent_mode){var i=this.findRow(t);n=n||"updated";var a=this.obj.getUserData(t,this.action_param);a\046\046"updated"==n\046\046(n=a),e?(this.set_invalid(t,!1),this.updatedRows[i]=t,this.obj.setUserData(t,this.action_param,n),this._in_progress[t]\046\046(this._in_progress[t]="wait")):this.is_invalid(t)||(this.updatedRows.splice(i,1),this.obj.setUserData(t,this.action_param,"")),e||this._clearUpdateFlag(t),this.markRow(t,e,n),e\046\046this.autoUpdate\046\046this.sendData(t)}},_clearUpdateFlag:function(){},markRow:function(t,e,n){var i="",a=this.is_invalid(t);if(a\046\046(i=this.styles[a],e=!0),this.callEvent("onRowMark",[t,e,n,a])\046\046(i=this.styles[e?n:"clear"]+i,this.obj[this._methods[0]](t,i),a\046\046a.details)){i+=this.styles[a+"_cell"];for(var r=0;r\074a.details.length;r++)a.details[r]\046\046this.obj[this._methods[1]](t,r,i)}},getState:function(t){return this.obj.getUserData(t,this.action_param)},is_invalid:function(t){return this._invalid[t]},set_invalid:function(t,e,n){n\046\046(e={value:e,details:n,toString:function(){return this.value.toString()}}),this._invalid[t]=e},checkBeforeUpdate:function(){return!0},sendData:function(t){return!this._waitMode||"tree"!=this.obj.mytype\046\046!this.obj._h2?(this.obj.editStop\046\046this.obj.editStop(),"undefined"==typeof t||this._tSend?this.sendAllData():this._in_progress[t]?!1:(this.messages=[],!this.checkBeforeUpdate(t)\046\046this.callEvent("onValidationError",[t,this.messages])?!1:(this._beforeSendData(this._getRowData(t),t),void 0))):void 0},_beforeSendData:function(t,e){return this.callEvent("onBeforeUpdate",[e,this.getState(e),t])?(this._sendData(t,e),void 0):!1},serialize:function(t,e){if("string"==typeof t)return t;if("undefined"!=typeof e)return this.serialize_one(t,"");var n=[],i=[];for(var a in t)t.hasOwnProperty(a)\046\046(n.push(this.serialize_one(t[a],a+this.post_delim)),i.push(a));return n.push("ids="+this.escape(i.join(","))),dhtmlx.security_key\046\046n.push("dhx_security="+dhtmlx.security_key),n.join("\046")},serialize_one:function(t,e){if("string"==typeof t)return t;var n=[];for(var i in t)t.hasOwnProperty(i)\046\046n.push(this.escape((e||"")+i)+"="+this.escape(t[i]));return n.join("\046")},_sendData:function(t,e){if(t){if(!this.callEvent("onBeforeDataSending",e?[e,this.getState(e),t]:[null,null,t]))return!1;e\046\046(this._in_progress[e]=(new Date).valueOf());var n=new dtmlXMLLoaderObject(this.afterUpdate,this,!0),i=this.serverProcessor+(this._user?getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+this.obj.getUserData(0,"version")].join("\046"):"");"POST"!=this._tMode?n.loadXML(i+(-1!=i.indexOf("?")?"\046":"?")+this.serialize(t,e)):n.loadXML(i,!0,this.serialize(t,e)),this._waitMode++}},sendAllData:function(){if(this.updatedRows.length){this.messages=[];for(var t=!0,e=0;e\074this.updatedRows.length;e++)t\046=this.checkBeforeUpdate(this.updatedRows[e]);if(!t\046\046!this.callEvent("onValidationError",["",this.messages]))return!1;if(this._tSend)this._sendData(this._getAllData());else for(var e=0;e\074this.updatedRows.length;e++)if(!this._in_progress[this.updatedRows[e]]){if(this.is_invalid(this.updatedRows[e]))continue;if(this._beforeSendData(this._getRowData(this.updatedRows[e]),this.updatedRows[e]),this._waitMode\046\046("tree"==this.obj.mytype||this.obj._h2))return}}},_getAllData:function(){for(var t={},e=!1,n=0;n\074this.updatedRows.length;n++){var i=this.updatedRows[n];this._in_progress[i]||this.is_invalid(i)||this.callEvent("onBeforeUpdate",[i,this.getState(i)])\046\046(t[i]=this._getRowData(i,i+this.post_delim),e=!0,this._in_progress[i]=(new Date).valueOf())}return e?t:null},setVerificator:function(t,e){this.mandatoryFields[t]=e||function(t){return""!=t}},clearVerificator:function(t){this.mandatoryFields[t]=!1},findRow:function(t){var e=0;for(e=0;e\074this.updatedRows.length\046\046t!=this.updatedRows[e];e++);return e},defineAction:function(t,e){this._uActions||(this._uActions=[]),this._uActions[t]=e},afterUpdateCallback:function(t,e,n,i){var a=t,r="error"!=n\046\046"invalid"!=n;if(r||this.set_invalid(t,n),this._uActions\046\046this._uActions[n]\046\046!this._uActions[n](i))return delete this._in_progress[a];"wait"!=this._in_progress[a]\046\046this.setUpdated(t,!1);var s=t;switch(n){case"inserted":case"insert":e!=t\046\046(this.obj[this._methods[2]](t,e),t=e);break;case"delete":case"deleted":return this.obj.setUserData(t,this.action_param,"true_deleted"),this.obj[this._methods[3]](t),delete this._in_progress[a],this.callEvent("onAfterUpdate",[t,n,e,i])}"wait"!=this._in_progress[a]?(r\046\046this.obj.setUserData(t,this.action_param,""),delete this._in_progress[a]):(delete this._in_progress[a],this.setUpdated(e,!0,this.obj.getUserData(t,this.action_param))),this.callEvent("onAfterUpdate",[s,n,e,i])},afterUpdate:function(t,e,n,i,a){if(a.getXMLTopNode("data"),a.xmlDoc.responseXML){for(var r=a.doXPath("//data/action"),s=0;s\074r.length;s++){var o=r[s],d=o.getAttribute("type"),l=o.getAttribute("sid"),h=o.getAttribute("tid");t.afterUpdateCallback(l,h,d,o)}t.finalizeUpdate()}},finalizeUpdate:function(){this._waitMode\046\046this._waitMode--,("tree"==this.obj.mytype||this.obj._h2)\046\046this.updatedRows.length\046\046this.sendData(),this.callEvent("onAfterUpdateFinish",[]),this.updatedRows.length||this.callEvent("onFullSync",[])},init:function(t){this.obj=t,this.obj._dp_init\046\046this.obj._dp_init(this)},setOnAfterUpdate:function(t){this.attachEvent("onAfterUpdate",t)},enableDebug:function(){},setOnBeforeUpdateHandler:function(t){this.attachEvent("onBeforeDataSending",t)},setAutoUpdate:function(t,e){t=t||2e3,this._user=e||(new Date).valueOf(),this._need_update=!1,this._loader=null,this._update_busy=!1,this.attachEvent("onAfterUpdate",function(t,e,n,i){this.afterAutoUpdate(t,e,n,i)}),this.attachEvent("onFullSync",function(){this.fullSync()});var n=this;window.setInterval(function(){n.loadUpdate()},t)},afterAutoUpdate:function(t,e){return"collision"==e?(this._need_update=!0,!1):!0},fullSync:function(){return 1==this._need_update\046\046(this._need_update=!1,this.loadUpdate()),!0},getUpdates:function(t,e){return this._update_busy?!1:(this._update_busy=!0,this._loader=this._loader||new dtmlXMLLoaderObject(!0),this._loader.async=!0,this._loader.waitCall=e,this._loader.loadXML(t),void 0)},_v:function(t){return t.firstChild?t.firstChild.nodeValue:""},_a:function(t){for(var e=[],n=0;n\074t.length;n++)e[n]=this._v(t[n]);return e},loadUpdate:function(){var t=this,e=this.obj.getUserData(0,"version"),n=this.serverProcessor+getUrlSymbol(this.serverProcessor)+["dhx_user="+this._user,"dhx_version="+e].join("\046");n=n.replace("editing=true\046",""),this.getUpdates(n,function(){var e=t._loader.doXPath("//userdata");t.obj.setUserData(0,"version",t._v(e[0]));var n=t._loader.doXPath("//update");if(n.length){t._silent_mode=!0;for(var i=0;i\074n.length;i++){var a=n[i].getAttribute("status"),r=n[i].getAttribute("id"),s=n[i].getAttribute("parent");switch(a){case"inserted":t.callEvent("insertCallback",[n[i],r,s]);break;case"updated":t.callEvent("updateCallback",[n[i],r,s]);break;case"deleted":t.callEvent("deleteCallback",[n[i],r,s])}}t._silent_mode=!1}t._update_busy=!1,t=null})}},dhtmlx.assert=function(t,e){t||dhtmlx.message({type:"error",text:e,expire:-1})},gantt.init=function(t,e,n){e\046\046n\046\046(this.config.start_date=this._min_date=new Date(e),this.config.end_date=this._max_date=new Date(n)),this._init_skin(),this.config.scroll_size||(this.config.scroll_size=this._detectScrollSize()),this._reinit(t),this.attachEvent("onLoadEnd",this.render),dhtmlxEvent(window,"resize",this._on_resize),this.init=function(t){this.$container\046\046(this.$container.innerHTML=""),this._reinit(t)},this.callEvent("onGanttReady",[])},gantt._reinit=function(t){this._init_html_area(t),this._set_sizes(),this._task_area_pulls={},this._task_area_renderers={},this._init_touch_events(),this._init_templates(),this._init_grid(),this._init_tasks(),this.render(),dhtmlxEvent(this.$container,"click",this._on_click),dhtmlxEvent(this.$container,"dblclick",this._on_dblclick),dhtmlxEvent(this.$container,"mousemove",this._on_mousemove),dhtmlxEvent(this.$container,"contextmenu",this._on_contextmenu)},gantt._init_html_area=function(t){this._obj="string"==typeof t?document.getElementById(t):t,dhtmlx.assert(this._obj,"Invalid html container: "+t);var e="\074div class=\'gantt_container\'\076\074div class=\'gantt_grid\'\076\074/div\076\074div class=\'gantt_task\'\076\074/div\076";e+="\074div class=\'gantt_ver_scroll\'\076\074div\076\074/div\076\074/div\076\074div class=\'gantt_hor_scroll\'\076\074div\076\074/div\076\074/div\076\074/div\076",this._obj.innerHTML=e,this.$container=this._obj.firstChild;var n=this.$container.childNodes;this.$grid=n[0],this.$task=n[1],this.$scroll_ver=n[2],this.$scroll_hor=n[3],this.$grid.innerHTML="\074div class=\'gantt_grid_scale\'\076\074/div\076\074div class=\'gantt_grid_data\'\076\074/div\076",this.$grid_scale=this.$grid.childNodes[0],this.$grid_data=this.$grid.childNodes[1],this.$task.innerHTML="\074div class=\'gantt_task_scale\'\076\074/div\076\074div class=\'gantt_data_area\'\076\074div class=\'gantt_task_bg\'\076\074/div\076\074div class=\'gantt_links_area\'\076\074/div\076\074div class=\'gantt_bars_area\'\076\074/div\076\074/div\076",this.$task_scale=this.$task.childNodes[0],this.$task_data=this.$task.childNodes[1],this.$task_bg=this.$task_data.childNodes[0],this.$task_links=this.$task_data.childNodes[1],this.$task_bars=this.$task_data.childNodes[2]},gantt.$click={buttons:{edit:function(t){gantt.showLightbox(t)},"delete":function(t){var e=gantt.locale.labels.confirm_deleting,n=gantt.locale.labels.confirm_deleting_title;gantt._dhtmlx_confirm(e,n,function(){gantt.deleteTask(t),gantt.hideLightbox()})}}},gantt._set_sizes=function(){this._x=this._obj.clientWidth,this._y=this._obj.clientHeight,this.$grid.style.height=this.$task.style.height=this._y-this.$scroll_hor.offsetHeight-2+"px",this.$grid_data.style.height=this.$task_data.style.height=this._y-(this.config.scale_height||0)-this.$scroll_hor.offsetHeight-2+"px",this.$grid.style.width=this.config.grid_width-1+"px",this.$grid_data.style.width=this.config.grid_width-1+"px",this.$task.style.width=this._x-this.config.grid_width-2+"px"},gantt.getScrollState=function(){return{x:this.$task.scrollLeft,y:this.$task_data.scrollTop}},gantt.scrollTo=function(t,e){null!==t\046\046(this.$task.scrollLeft=t),null!==e\046\046(this.$task_data.scrollTop=e)},gantt._on_resize=gantt.setSizes=function(){gantt._set_sizes(),gantt._render_scroll()},gantt.render=function(){if(this._render_grid(),this._render_tasks_scales(),this._render_scroll(),this._on_resize(),this._render_data(),this.config.initial_scroll){var t=this._order[0]||0;t\046\046this.showTask(t)}},gantt._render_scroll=function(){this._scroll_resize();var t=this;dhtmlxEvent(this.$scroll_hor,"scroll",function(){if(!gantt._touch_scroll_active){var e=t.$scroll_hor.scrollLeft;t._scroll_task_area(e)}}),dhtmlxEvent(this.$scroll_ver,"scroll",function(){if(!gantt._touch_scroll_active){var e=t.$scroll_ver.scrollTop;t.$grid_data.scrollTop=e,t._scroll_task_area(null,e)}}),dhtmlxEvent(this.$task,"scroll",function(){var e=t.$task.scrollLeft;t.$scroll_hor.scrollLeft=e}),dhtmlxEvent(this.$task_data,"scroll",function(){var e=t.$task_data.scrollTop;t.$scroll_ver.scrollTop=t.$grid_data.scrollTop=e}),dhtmlxEvent(this.$container,"mousewheel",function(e){if(e.wheelDeltaX){var n=e.wheelDeltaX/-40,i=t.$task.scrollLeft+30*n;t._scroll_task_area(i,null),t.$scroll_hor.scrollTop=a}else{var n=e.wheelDelta/-40;"undefined"==typeof e.wheelDelta\046\046(n=e.detail);var a=t.$grid_data.scrollTop+30*n;t._scroll_task_area(null,a),t.$scroll_ver.scrollTop=a}return e.preventDefault\046\046e.preventDefault(),e.cancelBubble=!0,!1}),this._render_scroll=this._scroll_resize},gantt._scroll_resize=function(){var t=this.config.grid_width,e=this._x-t,n=this._y-this.config.scale_height,i=this.$task_data.offsetWidth-this.config.scroll_size,a=this.config.row_height*this._order.length,r=i\076e,s=a\076n;this.$scroll_hor.style.display=r?"block":"none",this.$scroll_hor.style.height=(r?this.config.scroll_size:0)+"px",this.$scroll_hor.style.width=this._x-(s?this.config.scroll_size:2)+"px",this.$scroll_hor.firstChild.style.width=i+t+this.config.scroll_size+2+"px",this.$scroll_ver.style.display=s?"block":"none",this.$scroll_ver.style.width=(s?this.config.scroll_size:0)+"px",this.$scroll_ver.style.height=this._y-(r?this.config.scroll_size:0)-this.config.scale_height+"px",this.$scroll_ver.style.top=this.config.scale_height+"px",this.$scroll_ver.firstChild.style.height=this.config.scale_height+a+"px"},gantt.locate=function(t){var e=gantt._get_target_node(t);if("gantt_task_cell"==e.className)return null;for(var n=arguments[1]||this.config.task_attribute;e;){if(e.getAttribute){var i=e.getAttribute(n);if(i)return i}e=e.parentNode}return null},gantt._get_target_node=function(t){var e;return t.tagName?e=t:(t=t||window.event,e=t.target||t.srcElement),e},gantt._trim=function(t){var e=String.prototype.trim||function(){return this.replace(/^\\s+|\\s+$/g,"")};return e.apply(t)},gantt._locate_css=function(t,e,n){void 0===n\046\046(n=!0);for(var i=gantt._get_target_node(t),a="";i;){if(a=i.className){var r=a.indexOf(e);if(r\076=0){if(!n)return i;var s=0===r||!gantt._trim(a.charAt(r-1)),o=r+e.length\076=a.length||!gantt._trim(a.charAt(r+e.length));if(s\046\046o)return i}}i=i.parentNode}return null},gantt._locateHTML=function(t,e){var n=gantt._get_target_node(t);for(e=e||this.config.task_attribute;n;){if(n.getAttribute){var i=n.getAttribute(e);if(i)return n}n=n.parentNode}return null},gantt.getTaskRowNode=function(t){for(var e=this.$grid_data.childNodes,n=this.config.task_attribute,i=0;i\074e.length;i++)if(e[i].getAttribute){var a=e[i].getAttribute(n);if(a==t)return e[i]}return null},gantt.getState=function(){return{drag_id:this._tasks_dnd.drag.id,drag_mode:this._tasks_dnd.drag.mode,selected_task:this._selected_task,min_date:this._min_date,max_date:this._max_date,lightbox:this._lightbox_id}},gantt._checkTimeout=function(t,e){if(!e)return!0;var n=1e3/e;return 1\076n?!0:t._on_timeout?!1:(setTimeout(function(){delete t._on_timeout},n),t._on_timeout=!0)},gantt.selectTask=function(t){if(this.config.select_task){if(t){if(this._selected_task==t)return this._selected_task;if(!this.callEvent("onBeforeTaskSelected",[t]))return!1;this.unselectTask(),this._selected_task=t,this.refreshTask(t),this.callEvent("onTaskSelected",[t])}return this._selected_task}},gantt.unselectTask=function(){var t=this._selected_task;t\046\046(this._selected_task=null,this.refreshTask(t),this.callEvent("onTaskUnselected",[t]))},gantt.getSelectedId=function(){return dhtmlx.defined(this._selected_task)?this._selected_task:null},gantt.date={init:function(){for(var t=gantt.locale.date.month_short,e=gantt.locale.date.month_short_hash={},n=0;n\074t.length;n++)e[t[n]]=n;for(var t=gantt.locale.date.month_full,e=gantt.locale.date.month_full_hash={},n=0;n\074t.length;n++)e[t[n]]=n},date_part:function(t){return t.setHours(0),t.setMinutes(0),t.setSeconds(0),t.setMilliseconds(0),t.getHours()\046\046t.setTime(t.getTime()+36e5*(24-t.getHours())),t},time_part:function(t){return(t.valueOf()/1e3-60*t.getTimezoneOffset())%86400},week_start:function(t){var e=t.getDay();return gantt.config.start_on_monday\046\046(0===e?e=6:e--),this.date_part(this.add(t,-1*e,"day"))},month_start:function(t){return t.setDate(1),this.date_part(t)},year_start:function(t){return t.setMonth(0),this.month_start(t)},day_start:function(t){return this.date_part(t)},hour_start:function(t){var e=t.getHours();return this.day_start(t),t.setHours(e),t},minute_start:function(t){var e=t.getMinutes();return this.hour_start(t),t.setMinutes(e),t},add:function(t,e,n){var i=new Date(t.valueOf());switch(n){case"week":e*=7;case"day":i.setDate(i.getDate()+e),!t.getHours()\046\046i.getHours()\046\046i.setTime(i.getTime()+36e5*(24-i.getHours()));break;case"month":i.setMonth(i.getMonth()+e);break;case"year":i.setYear(i.getFullYear()+e);break;case"hour":i.setHours(i.getHours()+e);break;case"minute":i.setMinutes(i.getMinutes()+e);break;default:return gantt.date["add_"+n](t,e,n)}return i},to_fixed:function(t){return 10\076t?"0"+t:t},copy:function(t){return new Date(t.valueOf())},date_to_str:function(t,e){return t=t.replace(/%[a-zA-Z]/g,function(t){switch(t){case"%d":return\'"+gantt.date.to_fixed(date.getDate())+"\';case"%m":return\'"+gantt.date.to_fixed((date.getMonth()+1))+"\';case"%j":return\'"+date.getDate()+"\';case"%n":return\'"+(date.getMonth()+1)+"\';case"%y":return\'"+gantt.date.to_fixed(date.getFullYear()%100)+"\';case"%Y":return\'"+date.getFullYear()+"\';case"%D":return\'"+gantt.locale.date.day_short[date.getDay()]+"\';case"%l":return\'"+gantt.locale.date.day_full[date.getDay()]+"\';case"%M":return\'"+gantt.locale.date.month_short[date.getMonth()]+"\';case"%F":return\'"+gantt.locale.date.month_full[date.getMonth()]+"\';case"%h":return\'"+gantt.date.to_fixed((date.getHours()+11)%12+1)+"\';case"%g":return\'"+((date.getHours()+11)%12+1)+"\';case"%G":return\'"+date.getHours()+"\';case"%H":return\'"+gantt.date.to_fixed(date.getHours())+"\';case"%i":return\'"+gantt.date.to_fixed(date.getMinutes())+"\';case"%a":return\'"+(date.getHours()\07611?"pm":"am")+"\';case"%A":return\'"+(date.getHours()\07611?"PM":"AM")+"\';case"%s":return\'"+gantt.date.to_fixed(date.getSeconds())+"\';case"%W":return\'"+gantt.date.to_fixed(gantt.date.getISOWeek(date))+"\';default:return t}}),e\046\046(t=t.replace(/date\\.get/g,"date.getUTC")),new Function("date",\'return "\'+t+\'";\')},str_to_date:function(t,e){for(var n="var temp=date.match(/[a-zA-Z]+|[0-9]+/g);",i=t.match(/%[a-zA-Z]/g),a=0;a\074i.length;a++)switch(i[a]){case"%j":case"%d":n+="set[2]=temp["+a+"]||1;";break;case"%n":case"%m":n+="set[1]=(temp["+a+"]||1)-1;";break;case"%y":n+="set[0]=temp["+a+"]*1+(temp["+a+"]\07650?1900:2000);";break;case"%g":case"%G":case"%h":case"%H":n+="set[3]=temp["+a+"]||0;";break;case"%i":n+="set[4]=temp["+a+"]||0;";break;case"%Y":n+="set[0]=temp["+a+"]||0;";break;case"%a":case"%A":n+="set[3]=set[3]%12+((temp["+a+"]||\'\').toLowerCase()==\'am\'?0:12);";break;case"%s":n+="set[5]=temp["+a+"]||0;";break;case"%M":n+="set[1]=gantt.locale.date.month_short_hash[temp["+a+"]]||0;";break;case"%F":n+="set[1]=gantt.locale.date.month_full_hash[temp["+a+"]]||0;"}var r="set[0],set[1],set[2],set[3],set[4],set[5]";return e\046\046(r=" Date.UTC("+r+")"),new Function("date","var set=[0,0,1,0,0,0]; "+n+" return new Date("+r+");")},getISOWeek:function(t){if(!t)return!1;var e=t.getDay();0===e\046\046(e=7);var n=new Date(t.valueOf());n.setDate(t.getDate()+(4-e));var i=n.getFullYear(),a=Math.round((n.getTime()-new Date(i,0,1).getTime())/864e5),r=1+Math.floor(a/7);return r},getUTCISOWeek:function(t){return this.getISOWeek(t)},convert_to_utc:function(t){return new Date(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate(),t.getUTCHours(),t.getUTCMinutes(),t.getUTCSeconds())},parseDate:function(t,e){return"string"==typeof t\046\046(dhtmlx.defined(e)\046\046(e="string"==typeof e?dhtmlx.defined(gantt.templates[e])?gantt.templates[e]:gantt.date.str_to_date(e):gantt.templates.xml_date),t=e(t)),t}},gantt.config||(gantt.config={}),gantt.config||(gantt.config={}),gantt.templates||(gantt.templates={}),function(){dhtmlx.mixin(gantt.config,{links:{finish_to_start:"0",start_to_start:"1",finish_to_finish:"2"},duration_unit:"day",min_duration:36e5,xml_date:"%d-%m-%Y %H:%i",api_date:"%d-%m-%Y %H:%i",start_on_monday:!0,server_utc:!1,show_progress:!0,fit_tasks:!1,select_task:!0,readonly:!1,date_grid:"%Y-%m-%d",drag_links:!0,drag_progress:!0,drag_resize:!0,drag_move:!0,drag_mode:{resize:"resize",progress:"progress",move:"move",ignore:"ignore"},round_dnd_dates:!0,link_wrapper_width:20,autofit:!0,columns:[{name:"text",tree:!0,width:"*"},{name:"start_date",align:"center"},{name:"duration",align:"center"},{name:"add",width:"44"}],step:1,scale_unit:"day",subscales:[],time_step:60,duration_step:1,date_scale:"%d %M",task_date:"%d %F %Y",time_picker:"%H:%i",task_attribute:"task_id",link_attribute:"link_id",buttons_left:["dhx_save_btn","dhx_cancel_btn"],buttons_right:["dhx_delete_btn"],lightbox:{sections:[{name:"description",height:70,map_to:"text",type:"textarea",focus:!0},{name:"time",height:72,type:"duration",map_to:"auto"}]},drag_lightbox:!0,sort:!1,details_on_create:!0,details_on_dblclick:!0,initial_scroll:!0,task_scroll_offset:100,task_height:"full",min_column_width:70}),gantt.keys={edit_save:13,edit_cancel:27},gantt._init_template=function(t){this.config[t].$used||(this.templates[t]=this.date.date_to_str(this.config[t]),this.config[t].$used=!0)},gantt._init_templates=function(){var t=gantt.locale.labels;t.dhx_save_btn=t.icon_save,t.dhx_cancel_btn=t.icon_cancel,t.dhx_delete_btn=t.icon_delete;var e=this.date.date_to_str,n=this.config;gantt._init_template("date_scale"),gantt._init_template("date_grid"),gantt._init_template("task_date"),dhtmlx.mixin(this.templates,{xml_date:this.date.str_to_date(n.xml_date,n.server_utc),xml_format:e(n.xml_date,n.server_utc),api_date:this.date.str_to_date(n.api_date),progress_text:function(){return""},grid_header_class:function(){return""},task_text:function(t,e,n){return n.text},task_class:function(){return""},grid_row_class:function(){return""},task_row_class:function(){return""},task_cell_class:function(){return""},scale_cell_class:function(){return""},task_class:function(){return""},grid_indent:function(){return"\074div class=\'gantt_tree_indent\'\076\074/div\076"},grid_folder:function(t){return"\074div class=\'gantt_tree_icon gantt_folder_"+(t.$open?"open":"closed")+"\'\076\074/div\076"},grid_file:function(){return"\074div class=\'gantt_tree_icon gantt_file\'\076\074/div\076"},grid_open:function(t){return"\074div class=\'gantt_tree_icon gantt_"+(t.$open?"close":"open")+"\'\076\074/div\076"},grid_blank:function(){return"\074div class=\'gantt_tree_icon gantt_blank\'\076\074/div\076"},task_time:function(t,e){return gantt.templates.task_date(t)+" - "+gantt.templates.task_date(e)},time_picker:e(n.time_picker),link_class:function(){return""},link_description:function(t){var e=gantt.getTask(t.source),n=gantt.getTask(t.target);return"\074b\076"+e.text+"\074/b\076 \046ndash;  \074b\076"+n.text+"\074/b\076"},drag_link:function(t,e,n,i){t=gantt.getTask(t);var a=gantt.locale.labels,r="\074b\076"+t.text+"\074/b\076 "+(e?a.link_start:a.link_end)+"\074br/\076";return n\046\046(n=gantt.getTask(n),r+="\074b\076 "+n.text+"\074/b\076 "+(i?a.link_start:a.link_end)+"\074br/\076"),r},drag_link_class:function(t,e,n,i){var a="";if(t\046\046n){var r=gantt.isLinkAllowed(t,n,e,i);a=" "+(r?"gantt_link_allow":"gantt_link_deny")}return"gantt_link_tooltip"+a}}),this.callEvent("onTemplatesReady",[])}}(),window.jQuery\046\046!function(t){var e=[];t.fn.dhx_gantt=function(n){if("string"!=typeof n){var i=[];return this.each(function(){if(this\046\046this.getAttribute\046\046!this.getAttribute("dhxgantt")){for(var t in n)"data"!=t\046\046(gantt.config[t]=n[t]);gantt.init(this),n.data\046\046gantt.parse(n.data),i.push(gantt)}}),1===i.length?i[0]:i}return e[n]?e[n].apply(this,[]):(t.error("Method "+n+" does not exist on jQuery.dhx_gantt"),void 0)}}(jQuery),gantt.locale={date:{month_full:["January","February","March","April","May","June","July","August","September","October","November","December"],month_short:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],day_full:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],day_short:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"]},labels:{new_task:"New task",icon_save:"Save",icon_cancel:"Cancel",icon_details:"Details",icon_edit:"Edit",icon_delete:"Delete",confirm_closing:"",confirm_deleting:"Task will be deleted permanently, are you sure?",section_description:"Description",section_time:"Time period",column_text:"Task name",column_start_date:"Start time",column_duration:"Duration",column_add:"",link:"Link",confirm_link_deleting:"will be deleted",link_start:" (start)",link_end:" (end)",minutes:"Minutes",hours:"Hours",days:"Days",weeks:"Week",months:"Months",years:"Years"}},gantt.skins.skyblue={config:{grid_width:350,row_height:27,scale_height:27,task_height:24,link_line_width:1,link_arrow_size:8,lightbox_additional_height:75},_second_column_width:95,_third_column_width:80},gantt.skins.meadow={config:{grid_width:350,row_height:27,scale_height:30,task_height:24,link_line_width:2,link_arrow_size:6,lightbox_additional_height:72},_second_column_width:95,_third_column_width:80},gantt.skins.terrace={config:{grid_width:360,row_height:35,scale_height:35,task_height:24,link_line_width:2,link_arrow_size:6,lightbox_additional_height:75},_second_column_width:90,_third_column_width:70},gantt.skins.broadway={config:{grid_width:360,row_height:35,scale_height:35,task_height:24,link_line_width:1,link_arrow_size:7,lightbox_additional_height:86},_second_column_width:90,_third_column_width:80,_lightbox_template:"\074div class=\'dhx_cal_ltitle\'\076\074span class=\'dhx_mark\'\076\046nbsp;\074/span\076\074span class=\'dhx_time\'\076\074/span\076\074span class=\'dhx_title\'\076\074/span\076\074div class=\'dhx_cancel_btn\'\076\074/div\076\074/div\076\074div class=\'dhx_cal_larea\'\076\074/div\076",_config_buttons_left:{},_config_buttons_right:{dhx_delete_btn:"icon_delete",dhx_save_btn:"icon_save"}},gantt.config.touch_drag=50,gantt.config.touch=!0,gantt._init_touch_events=function(){"force"!=this.config.touch\046\046(this.config.touch=this.config.touch\046\046(-1!=navigator.userAgent.indexOf("Mobile")||-1!=navigator.userAgent.indexOf("iPad")||-1!=navigator.userAgent.indexOf("Android")||-1!=navigator.userAgent.indexOf("Touch"))),this.config.touch\046\046(window.navigator.msPointerEnabled?this._touch_events(["MSPointerMove","MSPointerDown","MSPointerUp"],function(t){return t.pointerType==t.MSPOINTER_TYPE_MOUSE?null:t},function(t){return!t||t.pointerType==t.MSPOINTER_TYPE_MOUSE}):this._touch_events(["touchmove","touchstart","touchend"],function(t){return t.touches\046\046t.touches.length\0761?null:t.touches[0]?{target:t.target,pageX:t.touches[0].pageX,pageY:t.touches[0].pageY}:t},function(){return!1}))},gantt._touch_events=function(t,e,n){function i(t){return t\046\046t.preventDefault\046\046t.preventDefault(),(t||event).cancelBubble=!0,!1}var a,r=0,s=!1,o=!1,d=null;this._gantt_touch_event_ready||(this._gantt_touch_event_ready=1,dhtmlxEvent(document.body,t[0],function(t){if(!n(t)\046\046s){var l=e(t);if(l\046\046d){var h=d.pageX-l.pageX,_=d.pageY-l.pageY;!o\046\046(Math.abs(h)\0765||Math.abs(_)\0765)\046\046(gantt._touch_scroll_active=o=!0,r=0,a=gantt.getScrollState()),o\046\046gantt.scrollTo(a.x+h,a.y+_)}return i(t)}})),dhtmlxEvent(this.$container,"contextmenu",function(t){return s?i(t):void 0}),dhtmlxEvent(this.$container,t[1],function(t){if(!n(t)){if(t.touches\046\046t.touches.length\0761)return s=!1,void 0;if(s=!0,d=e(t),d\046\046r){var a=new Date;500\076a-r?(gantt._on_dblclick(d),i(t)):r=a}else r=new Date}}),dhtmlxEvent(this.$container,t[2],function(t){n(t)||(gantt._touch_scroll_active=s=o=!1)})};</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/handlebars.min.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/handlebars.min.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..130049292cb03af5356be4b6f693be29062e45ca
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/handlebars.min.js.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681769.06</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>handlebars.min.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*!\n
+\n
+ handlebars v2.0.0-alpha.4\n
+\n
+Copyright (C) 2011-2014 by Yehuda Katz\n
+\n
+Permission is hereby granted, free of charge, to any person obtaining a copy\n
+of this software and associated documentation files (the "Software"), to deal\n
+in the Software without restriction, including without limitation the rights\n
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n
+copies of the Software, and to permit persons to whom the Software is\n
+furnished to do so, subject to the following conditions:\n
+\n
+The above copyright notice and this permission notice shall be included in\n
+all copies or substantial portions of the Software.\n
+\n
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n
+THE SOFTWARE.\n
+\n
+@license\n
+*/\n
+this.Handlebars=function(){var a=function(){"use strict";function a(a){this.string=a}var b;return a.prototype.toString=function(){return""+this.string},b=a}(),b=function(a){"use strict";function b(a){return i[a]||"&amp;"}function c(a){for(var b=1;b<arguments.length;b++)for(var c in arguments[b])Object.prototype.hasOwnProperty.call(arguments[b],c)&&(a[c]=arguments[b][c]);return a}function d(a){return a instanceof h?a.toString():a||0===a?(a=""+a,k.test(a)?a.replace(j,b):a):""}function e(a){return a||0===a?n(a)&&0===a.length?!0:!1:!0}function f(a,b){return(a?a+".":"")+b}var g={},h=a,i={"&":"&amp;","<":"&lt;",">":"&gt;",\'"\':"&quot;","\'":"&#x27;","`":"&#x60;"},j=/[&<>"\'`]/g,k=/[&<>"\'`]/;g.extend=c;var l=Object.prototype.toString;g.toString=l;var m=function(a){return"function"==typeof a};m(/x/)&&(m=function(a){return"function"==typeof a&&"[object Function]"===l.call(a)});var m;g.isFunction=m;var n=Array.isArray||function(a){return a&&"object"==typeof a?"[object Array]"===l.call(a):!1};return g.isArray=n,g.escapeExpression=d,g.isEmpty=e,g.appendContextPath=f,g}(a),c=function(){"use strict";function a(a,b){var d;b&&b.firstLine&&(d=b.firstLine,a+=" - "+d+":"+b.firstColumn);for(var e=Error.prototype.constructor.call(this,a),f=0;f<c.length;f++)this[c[f]]=e[c[f]];d&&(this.lineNumber=d,this.column=b.firstColumn)}var b,c=["description","fileName","lineNumber","message","name","number","stack"];return a.prototype=new Error,b=a}(),d=function(a,b){"use strict";function c(a,b){this.helpers=a||{},this.partials=b||{},d(this)}function d(a){a.registerHelper("helperMissing",function(){if(1===arguments.length)return void 0;throw new h("Missing helper: \'"+arguments[arguments.length-1].name+"\'")}),a.registerHelper("blockHelperMissing",function(b,c){var d=c.inverse||function(){},e=c.fn;if(m(b)&&(b=b.call(this)),b===!0)return e(this);if(b===!1||null==b)return d(this);if(l(b))return b.length>0?(c.ids&&(c.ids=[c.name]),a.helpers.each(b,c)):d(this);if(c.data&&c.ids){var f=q(c.data);f.contextPath=g.appendContextPath(c.data.contextPath,c.name),c={data:f}}return e(b,c)}),a.registerHelper("each",function(a,b){b||(b=a,a=this);var c,d,e=b.fn,f=b.inverse,h=0,i="";if(b.data&&b.ids&&(d=g.appendContextPath(b.data.contextPath,b.ids[0])+"."),m(a)&&(a=a.call(this)),b.data&&(c=q(b.data)),a&&"object"==typeof a)if(l(a))for(var j=a.length;j>h;h++)c&&(c.index=h,c.first=0===h,c.last=h===a.length-1,d&&(c.contextPath=d+h)),i+=e(a[h],{data:c});else for(var k in a)a.hasOwnProperty(k)&&(c&&(c.key=k,c.index=h,c.first=0===h,d&&(c.contextPath=d+k)),i+=e(a[k],{data:c}),h++);return 0===h&&(i=f(this)),i}),a.registerHelper("if",function(a,b){return m(a)&&(a=a.call(this)),!b.hash.includeZero&&!a||g.isEmpty(a)?b.inverse(this):b.fn(this)}),a.registerHelper("unless",function(b,c){return a.helpers["if"].call(this,b,{fn:c.inverse,inverse:c.fn,hash:c.hash})}),a.registerHelper("with",function(a,b){m(a)&&(a=a.call(this));var c=b.fn;if(!g.isEmpty(a)){if(b.data&&b.ids){var d=q(b.data);d.contextPath=g.appendContextPath(b.data.contextPath,b.ids[0]),b={data:d}}return c(a,b)}}),a.registerHelper("log",function(b,c){var d=c.data&&null!=c.data.level?parseInt(c.data.level,10):1;a.log(d,b)}),a.registerHelper("lookup",function(a,b){return a&&a[b]})}function e(a,b){p.log(a,b)}var f={},g=a,h=b,i="2.0.0-alpha.4";f.VERSION=i;var j=5;f.COMPILER_REVISION=j;var k={1:"<= 1.0.rc.2",2:"== 1.0.0-rc.3",3:"== 1.0.0-rc.4",4:"== 1.x.x",5:">= 2.0.0"};f.REVISION_CHANGES=k;var l=g.isArray,m=g.isFunction,n=g.toString,o="[object Object]";f.HandlebarsEnvironment=c,c.prototype={constructor:c,logger:p,log:e,registerHelper:function(a,b,c){if(n.call(a)===o){if(c||b)throw new h("Arg not supported with multiple helpers");g.extend(this.helpers,a)}else c&&(b.not=c),this.helpers[a]=b},unregisterHelper:function(a){delete this.helpers[a]},registerPartial:function(a,b){n.call(a)===o?g.extend(this.partials,a):this.partials[a]=b},unregisterPartial:function(a){delete this.partials[a]}};var p={methodMap:{0:"debug",1:"info",2:"warn",3:"error"},DEBUG:0,INFO:1,WARN:2,ERROR:3,level:3,log:function(a,b){if(p.level<=a){var c=p.methodMap[a];"undefined"!=typeof console&&console[c]&&console[c].call(console,b)}}};f.logger=p,f.log=e;var q=function(a){var b=g.extend({},a);return b._parent=a,b};return f.createFrame=q,f}(b,c),e=function(a,b,c){"use strict";function d(a){var b=a&&a[0]||1,c=n;if(b!==c){if(c>b){var d=o[c],e=o[b];throw new m("Template was precompiled with an older version of Handlebars than the current runtime. Please update your precompiler to a newer version ("+d+") or downgrade your runtime to an older version ("+e+").")}throw new m("Template was precompiled with a newer version of Handlebars than the current runtime. Please update your runtime to a newer version ("+a[1]+").")}}function e(a,b){if(!b)throw new m("No environment passed to template");b.VM.checkRevision(a.compiler);var c=function(a,c,d,e,f,g,h){e&&(d=l.extend({},d,e));var i=b.VM.invokePartial.call(this,a,c,d,f,g,h);if(null!=i)return i;if(b.compile){var j={helpers:f,partials:g,data:h};return g[c]=b.compile(a,{data:void 0!==h},b),g[c](d,j)}throw new m("The partial "+c+" could not be compiled when running in runtime-only mode")},d={escapeExpression:l.escapeExpression,invokePartial:c,fn:function(b){return a[b]},programs:[],program:function(a,b){var c=this.programs[a],d=this.fn(a);return b?c=g(this,a,d,b):c||(c=this.programs[a]=g(this,a,d)),c},programWithDepth:b.VM.programWithDepth,data:function(a,b){for(;a&&b--;)a=a._parent;return a},merge:function(a,b){var c=a||b;return a&&b&&a!==b&&(c=l.extend({},b,a)),c},noop:b.VM.noop,compilerInfo:a.compiler},e=function(b,c){c=c||{};var f=c.data;return e._setup(c),!c.partial&&a.useData&&(f=j(b,f)),a.main.call(d,b,d.helpers,d.partials,f)};return e._setup=function(c){c.partial?(d.helpers=c.helpers,d.partials=c.partials):(d.helpers=d.merge(c.helpers,b.helpers),a.usePartial&&(d.partials=d.merge(c.partials,b.partials)))},e._child=function(a){return d.programWithDepth(a)},e}function f(a,b){var c=Array.prototype.slice.call(arguments,2),d=this,e=d.fn(a),f=function(a,f){return f=f||{},e.apply(d,[a,d.helpers,d.partials,f.data||b].concat(c))};return f.program=a,f.depth=c.length,f}function g(a,b,c,d){var e=function(b,e){return e=e||{},c.call(a,b,a.helpers,a.partials,e.data||d)};return e.program=b,e.depth=0,e}function h(a,b,c,d,e,f){var g={partial:!0,helpers:d,partials:e,data:f};if(void 0===a)throw new m("The partial "+b+" could not be found");return a instanceof Function?a(c,g):void 0}function i(){return""}function j(a,b){return b&&"root"in b||(b=b?p(b):{},b.root=a),b}var k={},l=a,m=b,n=c.COMPILER_REVISION,o=c.REVISION_CHANGES,p=c.createFrame;return k.checkRevision=d,k.template=e,k.programWithDepth=f,k.program=g,k.invokePartial=h,k.noop=i,k}(b,c,d),f=function(a,b,c,d,e){"use strict";var f,g=a,h=b,i=c,j=d,k=e,l=function(){var a=new g.HandlebarsEnvironment;return j.extend(a,g),a.SafeString=h,a.Exception=i,a.Utils=j,a.VM=k,a.template=function(b){return k.template(b,a)},a},m=l();return m.create=l,f=m}(d,a,c,b,e),g=function(a){"use strict";function b(a){a=a||{},this.firstLine=a.first_line,this.firstColumn=a.first_column,this.lastColumn=a.last_column,this.lastLine=a.last_line}var c,d=a,e={ProgramNode:function(a,c,d,f){var g,h;3===arguments.length?(f=d,d=null):2===arguments.length&&(f=c,c=null),b.call(this,f),this.type="program",this.statements=a,this.strip={},d?(h=d[0],h?(g={first_line:h.firstLine,last_line:h.lastLine,last_column:h.lastColumn,first_column:h.firstColumn},this.inverse=new e.ProgramNode(d,c,g)):this.inverse=new e.ProgramNode(d,c),this.strip.right=c.left):c&&(this.strip.left=c.right)},MustacheNode:function(a,c,d,f,g){if(b.call(this,g),this.type="mustache",this.strip=f,null!=d&&d.charAt){var h=d.charAt(3)||d.charAt(2);this.escaped="{"!==h&&"&"!==h}else this.escaped=!!d;this.sexpr=a instanceof e.SexprNode?a:new e.SexprNode(a,c),this.sexpr.isRoot=!0,this.id=this.sexpr.id,this.params=this.sexpr.params,this.hash=this.sexpr.hash,this.eligibleHelper=this.sexpr.eligibleHelper,this.isHelper=this.sexpr.isHelper},SexprNode:function(a,c,d){b.call(this,d),this.type="sexpr",this.hash=c;var e=this.id=a[0],f=this.params=a.slice(1);this.isHelper=!(!f.length&&!c),this.eligibleHelper=this.isHelper||e.isSimple},PartialNode:function(a,c,d,e,f){b.call(this,f),this.type="partial",this.partialName=a,this.context=c,this.hash=d,this.strip=e},BlockNode:function(a,c,e,f,g){if(b.call(this,g),a.sexpr.id.original!==f.path.original)throw new d(a.sexpr.id.original+" doesn\'t match "+f.path.original,this);this.type="block",this.mustache=a,this.program=c,this.inverse=e,this.strip={left:a.strip.left,right:f.strip.right},(c||e).strip.left=a.strip.right,(e||c).strip.right=f.strip.left,e&&!c&&(this.isInverse=!0)},RawBlockNode:function(a,c,f,g){if(b.call(this,g),a.sexpr.id.original!==f)throw new d(a.sexpr.id.original+" doesn\'t match "+f,this);c=new e.ContentNode(c,g),this.type="block",this.mustache=a,this.program=new e.ProgramNode([c],g)},ContentNode:function(a,c){b.call(this,c),this.type="content",this.string=a},HashNode:function(a,c){b.call(this,c),this.type="hash",this.pairs=a},IdNode:function(a,c){b.call(this,c),this.type="ID";for(var e="",f=[],g=0,h="",i=0,j=a.length;j>i;i++){var k=a[i].part;if(e+=(a[i].separator||"")+k,".."===k||"."===k||"this"===k){if(f.length>0)throw new d("Invalid path: "+e,this);".."===k?(g++,h+="../"):this.isScoped=!0}else f.push(k)}this.original=e,this.parts=f,this.string=f.join("."),this.depth=g,this.idName=h+this.string,this.isSimple=1===a.length&&!this.isScoped&&0===g,this.stringModeValue=this.string},PartialNameNode:function(a,c){b.call(this,c),this.type="PARTIAL_NAME",this.name=a.original},DataNode:function(a,c){b.call(this,c),this.type="DATA",this.id=a,this.stringModeValue=a.stringModeValue,this.idName="@"+a.stringModeValue},StringNode:function(a,c){b.call(this,c),this.type="STRING",this.original=this.string=this.stringModeValue=a},NumberNode:function(a,c){b.call(this,c),this.type="NUMBER",this.original=this.number=a,this.stringModeValue=Number(a)},BooleanNode:function(a,c){b.call(this,c),this.type="BOOLEAN",this.bool=a,this.stringModeValue="true"===a},CommentNode:function(a,c){b.call(this,c),this.type="comment",this.comment=a}};return c=e}(c),h=function(){"use strict";var a,b=function(){function a(a,b){return{left:"~"===a.charAt(2),right:"~"===b.charAt(0)||"~"===b.charAt(1)}}function b(){this.yy={}}var c={trace:function(){},yy:{},symbols_:{error:2,root:3,statements:4,EOF:5,program:6,simpleInverse:7,statement:8,openRawBlock:9,CONTENT:10,END_RAW_BLOCK:11,openInverse:12,closeBlock:13,openBlock:14,mustache:15,partial:16,COMMENT:17,OPEN_RAW_BLOCK:18,sexpr:19,CLOSE_RAW_BLOCK:20,OPEN_BLOCK:21,CLOSE:22,OPEN_INVERSE:23,OPEN_ENDBLOCK:24,path:25,OPEN:26,OPEN_UNESCAPED:27,CLOSE_UNESCAPED:28,OPEN_PARTIAL:29,partialName:30,param:31,partial_option0:32,partial_option1:33,sexpr_repetition0:34,sexpr_option0:35,dataName:36,STRING:37,NUMBER:38,BOOLEAN:39,OPEN_SEXPR:40,CLOSE_SEXPR:41,hash:42,hash_repetition_plus0:43,hashSegment:44,ID:45,EQUALS:46,DATA:47,pathSegments:48,SEP:49,$accept:0,$end:1},terminals_:{2:"error",5:"EOF",10:"CONTENT",11:"END_RAW_BLOCK",17:"COMMENT",18:"OPEN_RAW_BLOCK",20:"CLOSE_RAW_BLOCK",21:"OPEN_BLOCK",22:"CLOSE",23:"OPEN_INVERSE",24:"OPEN_ENDBLOCK",26:"OPEN",27:"OPEN_UNESCAPED",28:"CLOSE_UNESCAPED",29:"OPEN_PARTIAL",37:"STRING",38:"NUMBER",39:"BOOLEAN",40:"OPEN_SEXPR",41:"CLOSE_SEXPR",45:"ID",46:"EQUALS",47:"DATA",49:"SEP"},productions_:[0,[3,2],[3,1],[6,2],[6,3],[6,2],[6,1],[6,1],[6,0],[4,1],[4,2],[8,3],[8,3],[8,3],[8,1],[8,1],[8,1],[8,1],[9,3],[14,3],[12,3],[13,3],[15,3],[15,3],[16,5],[16,4],[7,2],[19,3],[19,1],[31,1],[31,1],[31,1],[31,1],[31,1],[31,3],[42,1],[44,3],[30,1],[30,1],[30,1],[36,2],[25,1],[48,3],[48,1],[32,0],[32,1],[33,0],[33,1],[34,0],[34,2],[35,0],[35,1],[43,1],[43,2]],performAction:function(b,c,d,e,f,g){var h=g.length-1;switch(f){case 1:return new e.ProgramNode(g[h-1],this._$);case 2:return new e.ProgramNode([],this._$);case 3:this.$=new e.ProgramNode([],g[h-1],g[h],this._$);break;case 4:this.$=new e.ProgramNode(g[h-2],g[h-1],g[h],this._$);break;case 5:this.$=new e.ProgramNode(g[h-1],g[h],[],this._$);break;case 6:this.$=new e.ProgramNode(g[h],this._$);break;case 7:this.$=new e.ProgramNode([],this._$);break;case 8:this.$=new e.ProgramNode([],this._$);break;case 9:this.$=[g[h]];break;case 10:g[h-1].push(g[h]),this.$=g[h-1];break;case 11:this.$=new e.RawBlockNode(g[h-2],g[h-1],g[h],this._$);break;case 12:this.$=new e.BlockNode(g[h-2],g[h-1].inverse,g[h-1],g[h],this._$);break;case 13:this.$=new e.BlockNode(g[h-2],g[h-1],g[h-1].inverse,g[h],this._$);break;case 14:this.$=g[h];break;case 15:this.$=g[h];break;case 16:this.$=new e.ContentNode(g[h],this._$);break;case 17:this.$=new e.CommentNode(g[h],this._$);break;case 18:this.$=new e.MustacheNode(g[h-1],null,"","",this._$);break;case 19:this.$=new e.MustacheNode(g[h-1],null,g[h-2],a(g[h-2],g[h]),this._$);break;case 20:this.$=new e.MustacheNode(g[h-1],null,g[h-2],a(g[h-2],g[h]),this._$);break;case 21:this.$={path:g[h-1],strip:a(g[h-2],g[h])};break;case 22:this.$=new e.MustacheNode(g[h-1],null,g[h-2],a(g[h-2],g[h]),this._$);break;case 23:this.$=new e.MustacheNode(g[h-1],null,g[h-2],a(g[h-2],g[h]),this._$);break;case 24:this.$=new e.PartialNode(g[h-3],g[h-2],g[h-1],a(g[h-4],g[h]),this._$);break;case 25:this.$=new e.PartialNode(g[h-2],void 0,g[h-1],a(g[h-3],g[h]),this._$);break;case 26:this.$=a(g[h-1],g[h]);break;case 27:this.$=new e.SexprNode([g[h-2]].concat(g[h-1]),g[h],this._$);break;case 28:this.$=new e.SexprNode([g[h]],null,this._$);break;case 29:this.$=g[h];break;case 30:this.$=new e.StringNode(g[h],this._$);break;case 31:this.$=new e.NumberNode(g[h],this._$);break;case 32:this.$=new e.BooleanNode(g[h],this._$);break;case 33:this.$=g[h];break;case 34:g[h-1].isHelper=!0,this.$=g[h-1];break;case 35:this.$=new e.HashNode(g[h],this._$);break;case 36:this.$=[g[h-2],g[h]];break;case 37:this.$=new e.PartialNameNode(g[h],this._$);break;case 38:this.$=new e.PartialNameNode(new e.StringNode(g[h],this._$),this._$);break;case 39:this.$=new e.PartialNameNode(new e.NumberNode(g[h],this._$));break;case 40:this.$=new e.DataNode(g[h],this._$);break;case 41:this.$=new e.IdNode(g[h],this._$);break;case 42:g[h-2].push({part:g[h],separator:g[h-1]}),this.$=g[h-2];break;case 43:this.$=[{part:g[h]}];break;case 48:this.$=[];break;case 49:g[h-1].push(g[h]);break;case 52:this.$=[g[h]];break;case 53:g[h-1].push(g[h])}},table:[{3:1,4:2,5:[1,3],8:4,9:5,10:[1,10],12:6,14:7,15:8,16:9,17:[1,11],18:[1,12],21:[1,14],23:[1,13],26:[1,15],27:[1,16],29:[1,17]},{1:[3]},{5:[1,18],8:19,9:5,10:[1,10],12:6,14:7,15:8,16:9,17:[1,11],18:[1,12],21:[1,14],23:[1,13],26:[1,15],27:[1,16],29:[1,17]},{1:[2,2]},{5:[2,9],10:[2,9],17:[2,9],18:[2,9],21:[2,9],23:[2,9],24:[2,9],26:[2,9],27:[2,9],29:[2,9]},{10:[1,20]},{4:23,6:21,7:22,8:4,9:5,10:[1,10],12:6,14:7,15:8,16:9,17:[1,11],18:[1,12],21:[1,14],23:[1,24],24:[2,8],26:[1,15],27:[1,16],29:[1,17]},{4:23,6:25,7:22,8:4,9:5,10:[1,10],12:6,14:7,15:8,16:9,17:[1,11],18:[1,12],21:[1,14],23:[1,24],24:[2,8],26:[1,15],27:[1,16],29:[1,17]},{5:[2,14],10:[2,14],17:[2,14],18:[2,14],21:[2,14],23:[2,14],24:[2,14],26:[2,14],27:[2,14],29:[2,14]},{5:[2,15],10:[2,15],17:[2,15],18:[2,15],21:[2,15],23:[2,15],24:[2,15],26:[2,15],27:[2,15],29:[2,15]},{5:[2,16],10:[2,16],17:[2,16],18:[2,16],21:[2,16],23:[2,16],24:[2,16],26:[2,16],27:[2,16],29:[2,16]},{5:[2,17],10:[2,17],17:[2,17],18:[2,17],21:[2,17],23:[2,17],24:[2,17],26:[2,17],27:[2,17],29:[2,17]},{19:26,25:27,36:28,45:[1,31],47:[1,30],48:29},{19:32,25:27,36:28,45:[1,31],47:[1,30],48:29},{19:33,25:27,36:28,45:[1,31],47:[1,30],48:29},{19:34,25:27,36:28,45:[1,31],47:[1,30],48:29},{19:35,25:27,36:28,45:[1,31],47:[1,30],48:29},{25:37,30:36,37:[1,38],38:[1,39],45:[1,31],48:29},{1:[2,1]},{5:[2,10],10:[2,10],17:[2,10],18:[2,10],21:[2,10],23:[2,10],24:[2,10],26:[2,10],27:[2,10],29:[2,10]},{11:[1,40]},{13:41,24:[1,42]},{4:43,8:4,9:5,10:[1,10],12:6,14:7,15:8,16:9,17:[1,11],18:[1,12],21:[1,14],23:[1,13],24:[2,7],26:[1,15],27:[1,16],29:[1,17]},{7:44,8:19,9:5,10:[1,10],12:6,14:7,15:8,16:9,17:[1,11],18:[1,12],21:[1,14],23:[1,24],24:[2,6],26:[1,15],27:[1,16],29:[1,17]},{19:32,22:[1,45],25:27,36:28,45:[1,31],47:[1,30],48:29},{13:46,24:[1,42]},{20:[1,47]},{20:[2,48],22:[2,48],28:[2,48],34:48,37:[2,48],38:[2,48],39:[2,48],40:[2,48],41:[2,48],45:[2,48],47:[2,48]},{20:[2,28],22:[2,28],28:[2,28],41:[2,28]},{20:[2,41],22:[2,41],28:[2,41],37:[2,41],38:[2,41],39:[2,41],40:[2,41],41:[2,41],45:[2,41],47:[2,41],49:[1,49]},{25:50,45:[1,31],48:29},{20:[2,43],22:[2,43],28:[2,43],37:[2,43],38:[2,43],39:[2,43],40:[2,43],41:[2,43],45:[2,43],47:[2,43],49:[2,43]},{22:[1,51]},{22:[1,52]},{22:[1,53]},{28:[1,54]},{22:[2,46],25:57,31:55,33:56,36:61,37:[1,58],38:[1,59],39:[1,60],40:[1,62],42:63,43:64,44:66,45:[1,65],47:[1,30],48:29},{22:[2,37],37:[2,37],38:[2,37],39:[2,37],40:[2,37],45:[2,37],47:[2,37]},{22:[2,38],37:[2,38],38:[2,38],39:[2,38],40:[2,38],45:[2,38],47:[2,38]},{22:[2,39],37:[2,39],38:[2,39],39:[2,39],40:[2,39],45:[2,39],47:[2,39]},{5:[2,11],10:[2,11],17:[2,11],18:[2,11],21:[2,11],23:[2,11],24:[2,11],26:[2,11],27:[2,11],29:[2,11]},{5:[2,12],10:[2,12],17:[2,12],18:[2,12],21:[2,12],23:[2,12],24:[2,12],26:[2,12],27:[2,12],29:[2,12]},{25:67,45:[1,31],48:29},{8:19,9:5,10:[1,10],12:6,14:7,15:8,16:9,17:[1,11],18:[1,12],21:[1,14],23:[1,13],24:[2,3],26:[1,15],27:[1,16],29:[1,17]},{4:68,8:4,9:5,10:[1,10],12:6,14:7,15:8,16:9,17:[1,11],18:[1,12],21:[1,14],23:[1,13],24:[2,5],26:[1,15],27:[1,16],29:[1,17]},{10:[2,26],17:[2,26],18:[2,26],21:[2,26],23:[2,26],24:[2,26],26:[2,26],27:[2,26],29:[2,26]},{5:[2,13],10:[2,13],17:[2,13],18:[2,13],21:[2,13],23:[2,13],24:[2,13],26:[2,13],27:[2,13],29:[2,13]},{10:[2,18]},{20:[2,50],22:[2,50],25:57,28:[2,50],31:70,35:69,36:61,37:[1,58],38:[1,59],39:[1,60],40:[1,62],41:[2,50],42:71,43:64,44:66,45:[1,65],47:[1,30],48:29},{45:[1,72]},{20:[2,40],22:[2,40],28:[2,40],37:[2,40],38:[2,40],39:[2,40],40:[2,40],41:[2,40],45:[2,40],47:[2,40]},{10:[2,20],17:[2,20],18:[2,20],21:[2,20],23:[2,20],24:[2,20],26:[2,20],27:[2,20],29:[2,20]},{10:[2,19],17:[2,19],18:[2,19],21:[2,19],23:[2,19],24:[2,19],26:[2,19],27:[2,19],29:[2,19]},{5:[2,22],10:[2,22],17:[2,22],18:[2,22],21:[2,22],23:[2,22],24:[2,22],26:[2,22],27:[2,22],29:[2,22]},{5:[2,23],10:[2,23],17:[2,23],18:[2,23],21:[2,23],23:[2,23],24:[2,23],26:[2,23],27:[2,23],29:[2,23]},{22:[2,44],32:73,42:74,43:64,44:66,45:[1,75]},{22:[1,76]},{20:[2,29],22:[2,29],28:[2,29],37:[2,29],38:[2,29],39:[2,29],40:[2,29],41:[2,29],45:[2,29],47:[2,29]},{20:[2,30],22:[2,30],28:[2,30],37:[2,30],38:[2,30],39:[2,30],40:[2,30],41:[2,30],45:[2,30],47:[2,30]},{20:[2,31],22:[2,31],28:[2,31],37:[2,31],38:[2,31],39:[2,31],40:[2,31],41:[2,31],45:[2,31],47:[2,31]},{20:[2,32],22:[2,32],28:[2,32],37:[2,32],38:[2,32],39:[2,32],40:[2,32],41:[2,32],45:[2,32],47:[2,32]},{20:[2,33],22:[2,33],28:[2,33],37:[2,33],38:[2,33],39:[2,33],40:[2,33],41:[2,33],45:[2,33],47:[2,33]},{19:77,25:27,36:28,45:[1,31],47:[1,30],48:29},{22:[2,47]},{20:[2,35],22:[2,35],28:[2,35],41:[2,35],44:78,45:[1,75]},{20:[2,43],22:[2,43],28:[2,43],37:[2,43],38:[2,43],39:[2,43],40:[2,43],41:[2,43],45:[2,43],46:[1,79],47:[2,43],49:[2,43]},{20:[2,52],22:[2,52],28:[2,52],41:[2,52],45:[2,52]},{22:[1,80]},{8:19,9:5,10:[1,10],12:6,14:7,15:8,16:9,17:[1,11],18:[1,12],21:[1,14],23:[1,13],24:[2,4],26:[1,15],27:[1,16],29:[1,17]},{20:[2,27],22:[2,27],28:[2,27],41:[2,27]},{20:[2,49],22:[2,49],28:[2,49],37:[2,49],38:[2,49],39:[2,49],40:[2,49],41:[2,49],45:[2,49],47:[2,49]},{20:[2,51],22:[2,51],28:[2,51],41:[2,51]},{20:[2,42],22:[2,42],28:[2,42],37:[2,42],38:[2,42],39:[2,42],40:[2,42],41:[2,42],45:[2,42],47:[2,42],49:[2,42]},{22:[1,81]},{22:[2,45]},{46:[1,79]},{5:[2,25],10:[2,25],17:[2,25],18:[2,25],21:[2,25],23:[2,25],24:[2,25],26:[2,25],27:[2,25],29:[2,25]},{41:[1,82]},{20:[2,53],22:[2,53],28:[2,53],41:[2,53],45:[2,53]},{25:57,31:83,36:61,37:[1,58],38:[1,59],39:[1,60],40:[1,62],45:[1,31],47:[1,30],48:29},{5:[2,21],10:[2,21],17:[2,21],18:[2,21],21:[2,21],23:[2,21],24:[2,21],26:[2,21],27:[2,21],29:[2,21]},{5:[2,24],10:[2,24],17:[2,24],18:[2,24],21:[2,24],23:[2,24],24:[2,24],26:[2,24],27:[2,24],29:[2,24]},{20:[2,34],22:[2,34],28:[2,34],37:[2,34],38:[2,34],39:[2,34],40:[2,34],41:[2,34],45:[2,34],47:[2,34]},{20:[2,36],22:[2,36],28:[2,36],41:[2,36],45:[2,36]}],defaultActions:{3:[2,2],18:[2,1],47:[2,18],63:[2,47],74:[2,45]},parseError:function(a){throw new Error(a)},parse:function(a){function b(){var a;return a=c.lexer.lex()||1,"number"!=typeof a&&(a=c.symbols_[a]||a),a}var c=this,d=[0],e=[null],f=[],g=this.table,h="",i=0,j=0,k=0;this.lexer.setInput(a),this.lexer.yy=this.yy,this.yy.lexer=this.lexer,this.yy.parser=this,"undefined"==typeof this.lexer.yylloc&&(this.lexer.yylloc={});var l=this.lexer.yylloc;f.push(l);var m=this.lexer.options&&this.lexer.options.ranges;"function"==typeof this.yy.parseError&&(this.parseError=this.yy.parseError);for(var n,o,p,q,r,s,t,u,v,w={};;){if(p=d[d.length-1],this.defaultActions[p]?q=this.defaultActions[p]:((null===n||"undefined"==typeof n)&&(n=b()),q=g[p]&&g[p][n]),"undefined"==typeof q||!q.length||!q[0]){var x="";if(!k){v=[];for(s in g[p])this.terminals_[s]&&s>2&&v.push("\'"+this.terminals_[s]+"\'");x=this.lexer.showPosition?"Parse error on line "+(i+1)+":\\n"+this.lexer.showPosition()+"\\nExpecting "+v.join(", ")+", got \'"+(this.terminals_[n]||n)+"\'":"Parse error on line "+(i+1)+": Unexpected "+(1==n?"end of input":"\'"+(this.terminals_[n]||n)+"\'"),this.parseError(x,{text:this.lexer.match,token:this.terminals_[n]||n,line:this.lexer.yylineno,loc:l,expected:v})}}if(q[0]instanceof Array&&q.length>1)throw new Error("Parse Error: multiple actions possible at state: "+p+", token: "+n);switch(q[0]){case 1:d.push(n),e.push(this.lexer.yytext),f.push(this.lexer.yylloc),d.push(q[1]),n=null,o?(n=o,o=null):(j=this.lexer.yyleng,h=this.lexer.yytext,i=this.lexer.yylineno,l=this.lexer.yylloc,k>0&&k--);break;case 2:if(t=this.productions_[q[1]][1],w.$=e[e.length-t],w._$={first_line:f[f.length-(t||1)].first_line,last_line:f[f.length-1].last_line,first_column:f[f.length-(t||1)].first_column,last_column:f[f.length-1].last_column},m&&(w._$.range=[f[f.length-(t||1)].range[0],f[f.length-1].range[1]]),r=this.performAction.call(w,h,j,i,this.yy,q[1],e,f),"undefined"!=typeof r)return r;t&&(d=d.slice(0,-1*t*2),e=e.slice(0,-1*t),f=f.slice(0,-1*t)),d.push(this.productions_[q[1]][0]),e.push(w.$),f.push(w._$),u=g[d[d.length-2]][d[d.length-1]],d.push(u);break;case 3:return!0}}return!0}},d=function(){var a={EOF:1,parseError:function(a,b){if(!this.yy.parser)throw new Error(a);this.yy.parser.parseError(a,b)},setInput:function(a){return this._input=a,this._more=this._less=this.done=!1,this.yylineno=this.yyleng=0,this.yytext=this.matched=this.match="",this.conditionStack=["INITIAL"],this.yylloc={first_line:1,first_column:0,last_line:1,last_column:0},this.options.ranges&&(this.yylloc.range=[0,0]),this.offset=0,this},input:function(){var a=this._input[0];this.yytext+=a,this.yyleng++,this.offset++,this.match+=a,this.matched+=a;var b=a.match(/(?:\\r\\n?|\\n).*/g);return b?(this.yylineno++,this.yylloc.last_line++):this.yylloc.last_column++,this.options.ranges&&this.yylloc.range[1]++,this._input=this._input.slice(1),a},unput:function(a){var b=a.length,c=a.split(/(?:\\r\\n?|\\n)/g);this._input=a+this._input,this.yytext=this.yytext.substr(0,this.yytext.length-b-1),this.offset-=b;var d=this.match.split(/(?:\\r\\n?|\\n)/g);this.match=this.match.substr(0,this.match.length-1),this.matched=this.matched.substr(0,this.matched.length-1),c.length-1&&(this.yylineno-=c.length-1);var e=this.yylloc.range;return this.yylloc={first_line:this.yylloc.first_line,last_line:this.yylineno+1,first_column:this.yylloc.first_column,last_column:c?(c.length===d.length?this.yylloc.first_column:0)+d[d.length-c.length].length-c[0].length:this.yylloc.first_column-b},this.options.ranges&&(this.yylloc.range=[e[0],e[0]+this.yyleng-b]),this},more:function(){return this._more=!0,this},less:function(a){this.unput(this.match.slice(a))},pastInput:function(){var a=this.matched.substr(0,this.matched.length-this.match.length);return(a.length>20?"...":"")+a.substr(-20).replace(/\\n/g,"")},upcomingInput:function(){var a=this.match;return a.length<20&&(a+=this._input.substr(0,20-a.length)),(a.substr(0,20)+(a.length>20?"...":"")).replace(/\\n/g,"")},showPosition:function(){var a=this.pastInput(),b=new Array(a.length+1).join("-");return a+this.upcomingInput()+"\\n"+b+"^"},next:function(){if(this.done)return this.EOF;this._input||(this.done=!0);var a,b,c,d,e;this._more||(this.yytext="",this.match="");for(var f=this._currentRules(),g=0;g<f.length&&(c=this._input.match(this.rules[f[g]]),!c||b&&!(c[0].length>b[0].length)||(b=c,d=g,this.options.flex));g++);return b?(e=b[0].match(/(?:\\r\\n?|\\n).*/g),e&&(this.yylineno+=e.length),this.yylloc={first_line:this.yylloc.last_line,last_line:this.yylineno+1,first_column:this.yylloc.last_column,last_column:e?e[e.length-1].length-e[e.length-1].match(/\\r?\\n?/)[0].length:this.yylloc.last_column+b[0].length},this.yytext+=b[0],this.match+=b[0],this.matches=b,this.yyleng=this.yytext.length,this.options.ranges&&(this.yylloc.range=[this.offset,this.offset+=this.yyleng]),this._more=!1,this._input=this._input.slice(b[0].length),this.matched+=b[0],a=this.performAction.call(this,this.yy,this,f[d],this.conditionStack[this.conditionStack.length-1]),this.done&&this._input&&(this.done=!1),a?a:void 0):""===this._input?this.EOF:this.parseError("Lexical error on line "+(this.yylineno+1)+". Unrecognized text.\\n"+this.showPosition(),{text:"",token:null,line:this.yylineno})},lex:function(){var a=this.next();return"undefined"!=typeof a?a:this.lex()},begin:function(a){this.conditionStack.push(a)},popState:function(){return this.conditionStack.pop()},_currentRules:function(){return this.conditions[this.conditionStack[this.conditionStack.length-1]].rules},topState:function(){return this.conditionStack[this.conditionStack.length-2]},pushState:function(a){this.begin(a)}};return a.options={},a.performAction=function(a,b,c,d){function e(a,c){return b.yytext=b.yytext.substr(a,b.yyleng-c)}switch(c){case 0:if("\\\\\\\\"===b.yytext.slice(-2)?(e(0,1),this.begin("mu")):"\\\\"===b.yytext.slice(-1)?(e(0,1),this.begin("emu")):this.begin("mu"),b.yytext)return 10;break;case 1:return 10;case 2:return this.popState(),10;case 3:return b.yytext=b.yytext.substr(5,b.yyleng-9),this.popState(),11;case 4:return 10;case 5:return e(0,4),this.popState(),17;case 6:return 40;case 7:return 41;case 8:return 18;case 9:return this.popState(),this.begin("raw"),20;case 10:return b.yytext=b.yytext.substr(4,b.yyleng-8),this.popState(),"RAW_BLOCK";case 11:return 29;case 12:return 21;case 13:return 24;case 14:return 23;case 15:return 23;case 16:return 27;case 17:return 26;case 18:this.popState(),this.begin("com");break;case 19:return e(3,5),this.popState(),17;case 20:return 26;case 21:return 46;case 22:return 45;case 23:return 45;case 24:return 49;case 25:break;case 26:return this.popState(),28;case 27:return this.popState(),22;case 28:return b.yytext=e(1,2).replace(/\\\\"/g,\'"\'),37;case 29:return b.yytext=e(1,2).replace(/\\\\\'/g,"\'"),37;case 30:return 47;case 31:return 39;case 32:return 39;case 33:return 38;case 34:return 45;case 35:return b.yytext=e(1,2),45;case 36:return"INVALID";case 37:return 5}},a.rules=[/^(?:[^\\x00]*?(?=(\\{\\{)))/,/^(?:[^\\x00]+)/,/^(?:[^\\x00]{2,}?(?=(\\{\\{|\\\\\\{\\{|\\\\\\\\\\{\\{|$)))/,/^(?:\\{\\{\\{\\{\\/[^\\s!"#%-,\\.\\/;->@\\[-\\^`\\{-~]+(?=[=}\\s\\/.])\\}\\}\\}\\})/,/^(?:[^\\x00]*?(?=(\\{\\{\\{\\{\\/)))/,/^(?:[\\s\\S]*?--\\}\\})/,/^(?:\\()/,/^(?:\\))/,/^(?:\\{\\{\\{\\{)/,/^(?:\\}\\}\\}\\})/,/^(?:\\{\\{\\{\\{[^\\x00]*\\}\\}\\}\\})/,/^(?:\\{\\{(~)?>)/,/^(?:\\{\\{(~)?#)/,/^(?:\\{\\{(~)?\\/)/,/^(?:\\{\\{(~)?\\^)/,/^(?:\\{\\{(~)?\\s*else\\b)/,/^(?:\\{\\{(~)?\\{)/,/^(?:\\{\\{(~)?&)/,/^(?:\\{\\{!--)/,/^(?:\\{\\{![\\s\\S]*?\\}\\})/,/^(?:\\{\\{(~)?)/,/^(?:=)/,/^(?:\\.\\.)/,/^(?:\\.(?=([=~}\\s\\/.)])))/,/^(?:[\\/.])/,/^(?:\\s+)/,/^(?:\\}(~)?\\}\\})/,/^(?:(~)?\\}\\})/,/^(?:"(\\\\["]|[^"])*")/,/^(?:\'(\\\\[\']|[^\'])*\')/,/^(?:@)/,/^(?:true(?=([~}\\s)])))/,/^(?:false(?=([~}\\s)])))/,/^(?:-?[0-9]+(?:\\.[0-9]+)?(?=([~}\\s)])))/,/^(?:([^\\s!"#%-,\\.\\/;->@\\[-\\^`\\{-~]+(?=([=~}\\s\\/.)]))))/,/^(?:\\[[^\\]]*\\])/,/^(?:.)/,/^(?:$)/],a.conditions={mu:{rules:[6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37],inclusive:!1},emu:{rules:[2],inclusive:!1},com:{rules:[5],inclusive:!1},raw:{rules:[3,4],inclusive:!1},INITIAL:{rules:[0,1,37],inclusive:!0}},a}();return c.lexer=d,b.prototype=c,c.Parser=b,new b}();return a=b}(),i=function(a,b){"use strict";function c(a){return a.constructor===f.ProgramNode?a:(e.yy=f,e.parse(a))}var d={},e=a,f=b;return d.parser=e,d.parse=c,d}(h,g),j=function(a){"use strict";function b(){}function c(a,b,c){if(null==a||"string"!=typeof a&&a.constructor!==c.AST.ProgramNode)throw new f("You must pass a string or Handlebars AST to Handlebars.precompile. You passed "+a);b=b||{},"data"in b||(b.data=!0);var d=c.parse(a),e=(new c.Compiler).compile(d,b);return(new c.JavaScriptCompiler).compile(e,b)}function d(a,b,c){function d(){var d=c.parse(a),e=(new c.Compiler).compile(d,b),f=(new c.JavaScriptCompiler).compile(e,b,void 0,!0);return c.template(f)}if(null==a||"string"!=typeof a&&a.constructor!==c.AST.ProgramNode)throw new f("You must pass a string or Handlebars AST to Handlebars.compile. You passed "+a);b=b||{},"data"in b||(b.data=!0);var e,g=function(a,b){return e||(e=d()),e.call(this,a,b)};return g._setup=function(a){return e||(e=d()),e._setup(a)},g._child=function(a){return e||(e=d()),e._child(a)},g}var e={},f=a;return e.Compiler=b,b.prototype={compiler:b,disassemble:function(){for(var a,b,c,d=this.opcodes,e=[],f=0,g=d.length;g>f;f++)if(a=d[f],"DECLARE"===a.opcode)e.push("DECLARE "+a.name+"="+a.value);else{b=[];for(var h=0;h<a.args.length;h++)c=a.args[h],"string"==typeof c&&(c=\'"\'+c.replace("\\n","\\\\n")+\'"\'),b.push(c);e.push(a.opcode+" "+b.join(" "))}return e.join("\\n")},equals:function(a){var b=this.opcodes.length;if(a.opcodes.length!==b)return!1;for(var c=0;b>c;c++){var d=this.opcodes[c],e=a.opcodes[c];if(d.opcode!==e.opcode||d.args.length!==e.args.length)return!1;for(var f=0;f<d.args.length;f++)if(d.args[f]!==e.args[f])return!1}if(b=this.children.length,a.children.length!==b)return!1;for(c=0;b>c;c++)if(!this.children[c].equals(a.children[c]))return!1;return!0},guid:0,compile:function(a,b){this.opcodes=[],this.children=[],this.depths={list:[]},this.options=b,this.stringParams=b.stringParams,this.trackIds=b.trackIds;var c=this.options.knownHelpers;if(this.options.knownHelpers={helperMissing:!0,blockHelperMissing:!0,each:!0,"if":!0,unless:!0,"with":!0,log:!0,lookup:!0},c)for(var d in c)this.options.knownHelpers[d]=c[d];return this.accept(a)},accept:function(a){var b,c=a.strip||{};return c.left&&this.opcode("strip"),b=this[a.type](a),c.right&&this.opcode("strip"),b},program:function(a){for(var b=a.statements,c=0,d=b.length;d>c;c++)this.accept(b[c]);return this.isSimple=1===d,this.depths.list=this.depths.list.sort(function(a,b){return a-b}),this},compileProgram:function(a){var b,c=(new this.compiler).compile(a,this.options),d=this.guid++;this.usePartial=this.usePartial||c.usePartial,this.children[d]=c;for(var e=0,f=c.depths.list.length;f>e;e++)b=c.depths.list[e],2>b||this.addDepth(b-1);return d},block:function(a){var b=a.mustache,c=a.program,d=a.inverse;c&&(c=this.compileProgram(c)),d&&(d=this.compileProgram(d));var e=b.sexpr,f=this.classifySexpr(e);"helper"===f?this.helperSexpr(e,c,d):"simple"===f?(this.simpleSexpr(e),this.opcode("pushProgram",c),this.opcode("pushProgram",d),this.opcode("emptyHash"),this.opcode("blockValue",e.id.original)):(this.ambiguousSexpr(e,c,d),this.opcode("pushProgram",c),this.opcode("pushProgram",d),this.opcode("emptyHash"),this.opcode("ambiguousBlockValue")),this.opcode("append")},hash:function(a){var b,c,d=a.pairs;for(this.opcode("pushHash"),b=0,c=d.length;c>b;b++)this.pushParam(d[b][1]);for(;b--;)this.opcode("assignToHash",d[b][0]);this.opcode("popHash")},partial:function(a){var b=a.partialName;this.usePartial=!0,a.hash?this.accept(a.hash):this.opcode("push","undefined"),a.context?this.accept(a.context):this.opcode("push","depth0"),this.opcode("invokePartial",b.name),this.opcode("append")\n
+},content:function(a){this.opcode("appendContent",a.string)},mustache:function(a){this.sexpr(a.sexpr),a.escaped&&!this.options.noEscape?this.opcode("appendEscaped"):this.opcode("append")},ambiguousSexpr:function(a,b,c){var d=a.id,e=d.parts[0],f=null!=b||null!=c;this.opcode("getContext",d.depth),this.opcode("pushProgram",b),this.opcode("pushProgram",c),this.opcode("invokeAmbiguous",e,f)},simpleSexpr:function(a){var b=a.id;"DATA"===b.type?this.DATA(b):b.parts.length?this.ID(b):(this.addDepth(b.depth),this.opcode("getContext",b.depth),this.opcode("pushContext")),this.opcode("resolvePossibleLambda")},helperSexpr:function(a,b,c){var d=this.setupFullMustacheParams(a,b,c),e=a.id,g=e.parts[0];if(this.options.knownHelpers[g])this.opcode("invokeKnownHelper",d.length,g);else{if(this.options.knownHelpersOnly)throw new f("You specified knownHelpersOnly, but used the unknown helper "+g,a);this.ID(e),this.opcode("invokeHelper",d.length,e.original,a.isRoot)}},sexpr:function(a){var b=this.classifySexpr(a);"simple"===b?this.simpleSexpr(a):"helper"===b?this.helperSexpr(a):this.ambiguousSexpr(a)},ID:function(a){this.addDepth(a.depth),this.opcode("getContext",a.depth);var b=a.parts[0];b?this.opcode("lookupOnContext",a.parts[0]):this.opcode("pushContext");for(var c=1,d=a.parts.length;d>c;c++)this.opcode("lookup",a.parts[c])},DATA:function(a){this.options.data=!0,this.opcode("lookupData",a.id.depth);for(var b=a.id.parts,c=0,d=b.length;d>c;c++)this.opcode("lookup",b[c])},STRING:function(a){this.opcode("pushString",a.string)},NUMBER:function(a){this.opcode("pushLiteral",a.number)},BOOLEAN:function(a){this.opcode("pushLiteral",a.bool)},comment:function(){},opcode:function(a){this.opcodes.push({opcode:a,args:[].slice.call(arguments,1)})},declare:function(a,b){this.opcodes.push({opcode:"DECLARE",name:a,value:b})},addDepth:function(a){0!==a&&(this.depths[a]||(this.depths[a]=!0,this.depths.list.push(a)))},classifySexpr:function(a){var b=a.isHelper,c=a.eligibleHelper,d=this.options;if(c&&!b){var e=a.id.parts[0];d.knownHelpers[e]?b=!0:d.knownHelpersOnly&&(c=!1)}return b?"helper":c?"ambiguous":"simple"},pushParams:function(a){for(var b=0,c=a.length;c>b;b++)this.pushParam(a[b])},pushParam:function(a){this.stringParams?(a.depth&&this.addDepth(a.depth),this.opcode("getContext",a.depth||0),this.opcode("pushStringParam",a.stringModeValue,a.type),"sexpr"===a.type&&this.sexpr(a)):(this.trackIds&&this.opcode("pushId",a.type,a.idName||a.stringModeValue),this.accept(a))},setupFullMustacheParams:function(a,b,c){var d=a.params;return this.pushParams(d),this.opcode("pushProgram",b),this.opcode("pushProgram",c),a.hash?this.hash(a.hash):this.opcode("emptyHash"),d}},e.precompile=c,e.compile=d,e}(c),k=function(a,b){"use strict";function c(a){this.value=a}function d(){}var e,f=a.COMPILER_REVISION,g=a.REVISION_CHANGES,h=a.log,i=b;d.prototype={nameLookup:function(a,b){var c,e;return 0===a.indexOf("depth")&&(c=!0),e=d.isValidJavaScriptVariableName(b)?a+"."+b:a+"[\'"+b+"\']",c?"("+a+" && "+e+")":e},compilerInfo:function(){var a=f,b=g[a];return[a,b]},appendToBuffer:function(a){return this.environment.isSimple?"return "+a+";":{appendToBuffer:!0,content:a,toString:function(){return"buffer += "+a+";"}}},initializeBuffer:function(){return this.quotedString("")},namespace:"Handlebars",compile:function(a,b,c,d){this.environment=a,this.options=b||{},this.stringParams=this.options.stringParams,this.trackIds=this.options.trackIds,this.precompile=!d,h("debug",this.environment.disassemble()+"\\n\\n"),this.name=this.environment.name,this.isChild=!!c,this.context=c||{programs:[],environments:[]},this.preamble(),this.stackSlot=0,this.stackVars=[],this.aliases={},this.registers={list:[]},this.hashes=[],this.compileStack=[],this.inlineStack=[],this.compileChildren(a,b);var e,f,g,j=a.opcodes;for(f=0,g=j.length;g>f;f++)e=j[f],"DECLARE"===e.opcode?this[e.name]=e.value:this[e.opcode].apply(this,e.args),e.opcode!==this.stripNext&&(this.stripNext=!1);if(this.pushSource(""),this.stackSlot||this.inlineStack.length||this.compileStack.length)throw new i("Compile completed with content left on stack");var k=this.createFunctionContext(d);if(this.isChild)return k;var l={compiler:this.compilerInfo(),main:k},m=this.context.programs;for(f=0,g=m.length;g>f;f++)m[f]&&(l[f]=m[f]);return this.environment.usePartial&&(l.usePartial=!0),this.options.data&&(l.useData=!0),d||(l.compiler=JSON.stringify(l.compiler),l=this.objectLiteral(l)),l},preamble:function(){this.lastContext=0,this.source=[]},createFunctionContext:function(a){var b="",c=this.stackVars.concat(this.registers.list);c.length>0&&(b+=", "+c.join(", "));for(var d in this.aliases)this.aliases.hasOwnProperty(d)&&(b+=", "+d+"="+this.aliases[d]);for(var e=["depth0","helpers","partials","data"],f=0,g=this.environment.depths.list.length;g>f;f++)e.push("depth"+this.environment.depths.list[f]);var h=this.mergeSource(b);return a?(e.push(h),Function.apply(this,e)):"function("+e.join(",")+") {\\n  "+h+"}"},mergeSource:function(a){for(var b,c,d="",e=!this.forceBuffer,f=0,g=this.source.length;g>f;f++){var h=this.source[f];h.appendToBuffer?b=b?b+"\\n    + "+h.content:h.content:(b&&(d?d+="buffer += "+b+";\\n  ":(c=!0,d=b+";\\n  "),b=void 0),d+=h+"\\n  ",this.environment.isSimple||(e=!1))}return e?(b||!d)&&(d+="return "+(b||\'""\')+";\\n"):(a+=", buffer = "+(c?"":this.initializeBuffer()),d+=b?"return buffer + "+b+";\\n":"return buffer;\\n"),a&&(d="var "+a.substring(2)+(c?"":";\\n  ")+d),d},blockValue:function(a){this.aliases.blockHelperMissing="helpers.blockHelperMissing";var b=["depth0"];this.setupParams(a,0,b),this.replaceStack(function(a){return b.splice(1,0,a),"blockHelperMissing.call("+b.join(", ")+")"})},ambiguousBlockValue:function(){this.aliases.blockHelperMissing="helpers.blockHelperMissing";var a=["depth0"];this.setupParams("",0,a,!0),this.flushInline();var b=this.topStack();a.splice(1,0,b),this.pushSource("if (!"+this.lastHelper+") { "+b+" = blockHelperMissing.call("+a.join(", ")+"); }")},appendContent:function(a){this.pendingContent&&(a=this.pendingContent+a),this.stripNext&&(a=a.replace(/^\\s+/,"")),this.pendingContent=a},strip:function(){this.pendingContent&&(this.pendingContent=this.pendingContent.replace(/\\s+$/,"")),this.stripNext="strip"},append:function(){this.flushInline();var a=this.popStack();this.pushSource("if("+a+" || "+a+" === 0) { "+this.appendToBuffer(a)+" }"),this.environment.isSimple&&this.pushSource("else { "+this.appendToBuffer("\'\'")+" }")},appendEscaped:function(){this.aliases.escapeExpression="this.escapeExpression",this.pushSource(this.appendToBuffer("escapeExpression("+this.popStack()+")"))},getContext:function(a){this.lastContext!==a&&(this.lastContext=a)},lookupOnContext:function(a){this.push(this.nameLookup("depth"+this.lastContext,a,"context"))},pushContext:function(){this.pushStackLiteral("depth"+this.lastContext)},resolvePossibleLambda:function(){this.aliases.functionType=\'"function"\',this.replaceStack(function(a){return"typeof "+a+" === functionType ? "+a+".apply(depth0) : "+a})},lookup:function(a){this.replaceStack(function(b){return b+" == null || "+b+" === false ? "+b+" : "+this.nameLookup(b,a,"context")})},lookupData:function(a){a?this.pushStackLiteral("this.data(data, "+a+")"):this.pushStackLiteral("data")},pushStringParam:function(a,b){this.pushStackLiteral("depth"+this.lastContext),this.pushString(b),"sexpr"!==b&&("string"==typeof a?this.pushString(a):this.pushStackLiteral(a))},emptyHash:function(){this.pushStackLiteral("{}"),this.trackIds&&this.push("{}"),this.stringParams&&(this.push("{}"),this.push("{}"))},pushHash:function(){this.hash&&this.hashes.push(this.hash),this.hash={values:[],types:[],contexts:[],ids:[]}},popHash:function(){var a=this.hash;this.hash=this.hashes.pop(),this.trackIds&&this.push("{"+a.ids.join(",")+"}"),this.stringParams&&(this.push("{"+a.contexts.join(",")+"}"),this.push("{"+a.types.join(",")+"}")),this.push("{\\n    "+a.values.join(",\\n    ")+"\\n  }")},pushString:function(a){this.pushStackLiteral(this.quotedString(a))},push:function(a){return this.inlineStack.push(a),a},pushLiteral:function(a){this.pushStackLiteral(a)},pushProgram:function(a){null!=a?this.pushStackLiteral(this.programExpression(a)):this.pushStackLiteral(null)},invokeHelper:function(a,b,c){this.aliases.helperMissing="helpers.helperMissing",this.useRegister("helper");var d=this.popStack(),e=this.setupHelper(a,b),f="helper = "+e.name+" || "+d+" || helperMissing";e.paramsInit&&(f+=","+e.paramsInit),this.push("("+f+",helper.call("+e.callParams+"))"),c||this.flushInline()},invokeKnownHelper:function(a,b){var c=this.setupHelper(a,b);this.push(c.name+".call("+c.callParams+")")},invokeAmbiguous:function(a,b){this.aliases.functionType=\'"function"\',this.useRegister("helper"),this.emptyHash();var c=this.setupHelper(0,a,b),d=this.lastHelper=this.nameLookup("helpers",a,"helper"),e=this.nameLookup("depth"+this.lastContext,a,"context");this.push("((helper = "+d+" || "+e+(c.paramsInit?"),("+c.paramsInit:"")+"),(typeof helper === functionType ? helper.call("+c.callParams+") : helper))")},invokePartial:function(a){var b=[this.nameLookup("partials",a,"partial"),"\'"+a+"\'",this.popStack(),this.popStack(),"helpers","partials"];this.options.data&&b.push("data"),this.push("this.invokePartial("+b.join(", ")+")")},assignToHash:function(a){var b,c,d,e=this.popStack();this.trackIds&&(d=this.popStack()),this.stringParams&&(c=this.popStack(),b=this.popStack());var f=this.hash;b&&f.contexts.push("\'"+a+"\': "+b),c&&f.types.push("\'"+a+"\': "+c),d&&f.ids.push("\'"+a+"\': "+d),f.values.push("\'"+a+"\': ("+e+")")},pushId:function(a,b){"ID"===a||"DATA"===a?this.pushString(b):"sexpr"===a?this.pushStackLiteral("true"):this.pushStackLiteral("null")},compiler:d,compileChildren:function(a,b){for(var c,d,e=a.children,f=0,g=e.length;g>f;f++){c=e[f],d=new this.compiler;var h=this.matchExistingProgram(c);null==h?(this.context.programs.push(""),h=this.context.programs.length,c.index=h,c.name="program"+h,this.context.programs[h]=d.compile(c,b,this.context,!this.precompile),this.context.environments[h]=c):(c.index=h,c.name="program"+h)}},matchExistingProgram:function(a){for(var b=0,c=this.context.environments.length;c>b;b++){var d=this.context.environments[b];if(d&&d.equals(a))return b}},programExpression:function(a){if(null==a)return"this.noop";for(var b,c=this.environment.children[a],d=c.depths.list,e=[c.index,"data"],f=0,g=d.length;g>f;f++)b=d[f],e.push("depth"+(b-1));return(0===d.length?"this.program(":"this.programWithDepth(")+e.join(", ")+")"},register:function(a,b){this.useRegister(a),this.pushSource(a+" = "+b+";")},useRegister:function(a){this.registers[a]||(this.registers[a]=!0,this.registers.list.push(a))},pushStackLiteral:function(a){return this.push(new c(a))},pushSource:function(a){this.pendingContent&&(this.source.push(this.appendToBuffer(this.quotedString(this.pendingContent))),this.pendingContent=void 0),a&&this.source.push(a)},pushStack:function(a){this.flushInline();var b=this.incrStack();return a&&this.pushSource(b+" = "+a+";"),this.compileStack.push(b),b},replaceStack:function(a){var b,d,e,f="",g=this.isInline();if(g){var h=this.popStack(!0);if(h instanceof c)b=h.value,e=!0;else{d=!this.stackSlot;var i=d?this.incrStack():this.topStackName();f="("+this.push(i)+" = "+h+"),",b=this.topStack()}}else b=this.topStack();var j=a.call(this,b);return g?(e||this.popStack(),d&&this.stackSlot--,this.push("("+f+j+")")):(/^stack/.test(b)||(b=this.nextStack()),this.pushSource(b+" = ("+f+j+");")),b},nextStack:function(){return this.pushStack()},incrStack:function(){return this.stackSlot++,this.stackSlot>this.stackVars.length&&this.stackVars.push("stack"+this.stackSlot),this.topStackName()},topStackName:function(){return"stack"+this.stackSlot},flushInline:function(){var a=this.inlineStack;if(a.length){this.inlineStack=[];for(var b=0,d=a.length;d>b;b++){var e=a[b];e instanceof c?this.compileStack.push(e):this.pushStack(e)}}},isInline:function(){return this.inlineStack.length},popStack:function(a){var b=this.isInline(),d=(b?this.inlineStack:this.compileStack).pop();if(!a&&d instanceof c)return d.value;if(!b){if(!this.stackSlot)throw new i("Invalid stack pop");this.stackSlot--}return d},topStack:function(a){var b=this.isInline()?this.inlineStack:this.compileStack,d=b[b.length-1];return!a&&d instanceof c?d.value:d},quotedString:function(a){return\'"\'+a.replace(/\\\\/g,"\\\\\\\\").replace(/"/g,\'\\\\"\').replace(/\\n/g,"\\\\n").replace(/\\r/g,"\\\\r").replace(/\\u2028/g,"\\\\u2028").replace(/\\u2029/g,"\\\\u2029")+\'"\'},objectLiteral:function(a){var b=[];for(var c in a)a.hasOwnProperty(c)&&b.push(this.quotedString(c)+":"+a[c]);return"{"+b.join(",")+"}"},setupHelper:function(a,b,c){var d=[],e=this.setupParams(b,a,d,c),f=this.nameLookup("helpers",b,"helper");return{params:d,paramsInit:e,name:f,callParams:["depth0"].concat(d).join(", ")}},setupOptions:function(a,b,c){var d,e,f,g={},h=[],i=[],j=[];g.name=this.quotedString(a),g.hash=this.popStack(),this.trackIds&&(g.hashIds=this.popStack()),this.stringParams&&(g.hashTypes=this.popStack(),g.hashContexts=this.popStack()),e=this.popStack(),f=this.popStack(),(f||e)&&(f||(f="this.noop"),e||(e="this.noop"),g.fn=f,g.inverse=e);for(var k=b;k--;)d=this.popStack(),c[k]=d,this.trackIds&&(j[k]=this.popStack()),this.stringParams&&(i[k]=this.popStack(),h[k]=this.popStack());return this.trackIds&&(g.ids="["+j.join(",")+"]"),this.stringParams&&(g.types="["+i.join(",")+"]",g.contexts="["+h.join(",")+"]"),this.options.data&&(g.data="data"),g},setupParams:function(a,b,c,d){var e=this.objectLiteral(this.setupOptions(a,b,c));return d?(this.useRegister("options"),c.push("options"),"options="+e):(c.push(e),"")}};for(var j="break else new var case finally return void catch for switch while continue function this with default if throw delete in try do instanceof typeof abstract enum int short boolean export interface static byte extends long super char final native synchronized class float package throws const goto private transient debugger implements protected volatile double import public let yield".split(" "),k=d.RESERVED_WORDS={},l=0,m=j.length;m>l;l++)k[j[l]]=!0;return d.isValidJavaScriptVariableName=function(a){return!d.RESERVED_WORDS[a]&&/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(a)},e=d}(d,c),l=function(a,b,c,d,e){"use strict";var f,g=a,h=b,i=c.parser,j=c.parse,k=d.Compiler,l=d.compile,m=d.precompile,n=e,o=g.create,p=function(){var a=o();return a.compile=function(b,c){return l(b,c,a)},a.precompile=function(b,c){return m(b,c,a)},a.AST=h,a.Compiler=k,a.JavaScriptCompiler=n,a.Parser=i,a.parse=j,a};return g=p(),g.create=p,f=g}(f,g,i,j,k);return l}();
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>47711</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/handsontable.css.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/handsontable.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..03d76480dab63bdf6dac7fa8a6622142645b5928
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/handsontable.css.xml
@@ -0,0 +1,538 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681769.49</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>handsontable.css</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/css</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/**\n
+ * Handsontable 0.10.5\n
+ * Handsontable is a simple jQuery plugin for editable tables with basic copy-paste compatibility with Excel and Google Docs\n
+ *\n
+ * Copyright 2012, Marcin Warpechowski\n
+ * Licensed under the MIT license.\n
+ * http://handsontable.com/\n
+ *\n
+ * Date: Mon Mar 31 2014 14:19:47 GMT+0200 (CEST)\n
+ */\n
+\n
+.handsontable {\n
+  position: relative;\n
+}\n
+\n
+.handsontable.htAutoColumnSize {\n
+  visibility: hidden;\n
+  left: 0;\n
+  position: absolute;\n
+  top: 0;\n
+}\n
+\n
+.handsontable table,\n
+.handsontable tbody,\n
+.handsontable thead,\n
+.handsontable td,\n
+.handsontable th,\n
+.handsontable div {\n
+  box-sizing: content-box;\n
+  -webkit-box-sizing: content-box;\n
+  -moz-box-sizing: content-box;\n
+}\n
+\n
+.handsontable table.htCore {\n
+  border-collapse: separate;\n
+  /*it must be separate, otherwise there are offset miscalculations in WebKit: http://stackoverflow.com/questions/2655987/border-collapse-differences-in-ff-and-webkit*/\n
+  position: relative;\n
+  /*this actually only changes appearance of user selection - does not make text unselectable\n
+  -webkit-user-select: none;\n
+  -khtml-user-select: none;\n
+  -moz-user-select: none;\n
+  -o-user-select: none;\n
+  -ms-user-select: none;\n
+  /*user-select: none; /*no browser supports unprefixed version*/\n
+  border-spacing: 0;\n
+  margin: 0;\n
+  border-width: 0;\n
+  table-layout: fixed;\n
+  width: 0;\n
+  outline-width: 0;\n
+  /* reset bootstrap table style. for more info see: https://github.com/warpech/jquery-handsontable/issues/224 */\n
+  max-width: none;\n
+  max-height: none;\n
+}\n
+\n
+.handsontable col {\n
+  width: 50px;\n
+}\n
+\n
+.handsontable col.rowHeader {\n
+  width: 50px;\n
+}\n
+\n
+.handsontable th,\n
+.handsontable td {\n
+  border-right: 1px solid #CCC;\n
+  border-bottom: 1px solid #CCC;\n
+  height: 22px;\n
+  empty-cells: show;\n
+  line-height: 21px;\n
+  padding: 0 4px 0 4px;\n
+  /* top, bottom padding different than 0 is handled poorly by FF with HTML5 doctype */\n
+  background-color: #FFF;\n
+  vertical-align: top;\n
+  overflow: hidden;\n
+  outline-width: 0;\n
+  white-space: pre-line;\n
+  /* preserve new line character in cell */\n
+}\n
+\n
+.handsontable td.htInvalid {\n
+  -webkit-transition: background 0.75s ease;\n
+  transition: background 0.75s ease;\n
+  background-color: #ff4c42;\n
+}\n
+\n
+.handsontable th:last-child {\n
+  /*Foundation framework fix*/\n
+  border-right: 1px solid #CCC;\n
+  border-bottom: 1px solid #CCC;\n
+}\n
+\n
+.handsontable tr:first-child th.htNoFrame,\n
+.handsontable th:first-child.htNoFrame,\n
+.handsontable th.htNoFrame {\n
+  border-left-width: 0;\n
+  background-color: white;\n
+  border-color: #FFF;\n
+}\n
+\n
+.handsontable th:first-child,\n
+.handsontable td:first-child,\n
+.handsontable .htNoFrame + th,\n
+.handsontable .htNoFrame + td {\n
+  border-left: 1px solid #CCC;\n
+}\n
+\n
+.handsontable tr:first-child th,\n
+.handsontable tr:first-child td {\n
+  border-top: 1px solid #CCC;\n
+}\n
+\n
+.handsontable thead tr:last-child th {\n
+  border-bottom-width: 0;\n
+}\n
+\n
+.handsontable thead tr.lastChild th {\n
+  border-bottom-width: 0;\n
+}\n
+\n
+.handsontable th {\n
+  background-color: #EEE;\n
+  color: #222;\n
+  text-align: center;\n
+  font-weight: normal;\n
+  white-space: nowrap;\n
+}\n
+\n
+.handsontable thead th {\n
+  padding: 0;\n
+}\n
+\n
+.handsontable th.active {\n
+  background-color: #CCC;\n
+}\n
+\n
+.handsontable thead th .relative {\n
+  position: relative;\n
+  padding: 2px 4px;\n
+}\n
+\n
+/* plugins */\n
+\n
+.handsontable .manualColumnMover {\n
+  position: absolute;\n
+  left: 0;\n
+  top: 0;\n
+  background-color: transparent;\n
+  width: 5px;\n
+  height: 25px;\n
+  z-index: 999;\n
+  cursor: move;\n
+}\n
+\n
+.handsontable th .manualColumnMover:hover,\n
+.handsontable th .manualColumnMover.active {\n
+  background-color: #88F;\n
+}\n
+\n
+.handsontable .manualColumnResizer {\n
+  position: absolute;\n
+  top: 0;\n
+  cursor: col-resize;\n
+}\n
+\n
+.handsontable .manualColumnResizerHandle {\n
+  background-color: transparent;\n
+  width: 5px;\n
+  height: 25px;\n
+}\n
+\n
+.handsontable .manualColumnResizer:hover .manualColumnResizerHandle,\n
+.handsontable .manualColumnResizer.active .manualColumnResizerHandle {\n
+  background-color: #AAB;\n
+}\n
+\n
+.handsontable .manualColumnResizerLine {\n
+  position: absolute;\n
+  right: 0;\n
+  top: 0;\n
+  background-color: #AAB;\n
+  display: none;\n
+  width: 0;\n
+  border-right: 1px dashed #777;\n
+}\n
+\n
+.handsontable .manualColumnResizer.active .manualColumnResizerLine {\n
+  display: block;\n
+}\n
+\n
+.handsontable .columnSorting:hover {\n
+  text-decoration: underline;\n
+  cursor: pointer;\n
+}\n
+\n
+/* border line */\n
+\n
+.handsontable .wtBorder {\n
+  position: absolute;\n
+  font-size: 0;\n
+}\n
+\n
+.handsontable td.area {\n
+  background-color: #EEF4FF;\n
+}\n
+\n
+/* fill handle */\n
+\n
+.handsontable .wtBorder.corner {\n
+  font-size: 0;\n
+  cursor: crosshair;\n
+}\n
+\n
+.handsontable .htBorder.htFillBorder {\n
+  background: red;\n
+  width: 1px;\n
+  height: 1px;\n
+}\n
+\n
+.handsontableInput {\n
+  border: 2px solid #5292F7;\n
+  outline-width: 0;\n
+  margin: 0;\n
+  padding: 1px 4px 0 2px;\n
+  font-family: Arial, Helvetica, sans-serif;\n
+  /*repeat from .handsontable (inherit doesn\'t work with IE<8) */\n
+  line-height: 1.3em;\n
+  /*repeat from .handsontable (inherit doesn\'t work with IE<8) */\n
+  font-size: inherit;\n
+  -webkit-box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.4);\n
+  box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.4);\n
+  resize: none;\n
+  /*below are needed to overwrite stuff added by jQuery UI Bootstrap theme*/\n
+  display: inline-block;\n
+  color: #000;\n
+  border-radius: 0;\n
+  background-color: #FFF;\n
+  /*overwrite styles potentionally made by a framework*/\n
+}\n
+\n
+.handsontableInputHolder {\n
+  position: absolute;\n
+  top: 0;\n
+  left: 0;\n
+  z-index: 100;\n
+}\n
+\n
+.htSelectEditor {\n
+  -webkit-appearance: menulist-button !important;\n
+  position: absolute;\n
+}\n
+\n
+/*\n
+TextRenderer readOnly cell\n
+*/\n
+\n
+.handsontable .htDimmed {\n
+  color: #777;\n
+}\n
+\n
+/*\n
+TextRenderer placeholder value\n
+*/\n
+\n
+.handsontable .htPlaceholder {\n
+  color: #999;\n
+}\n
+\n
+/*\n
+AutocompleteRenderer down arrow\n
+*/\n
+\n
+.handsontable .htAutocompleteArrow {\n
+  float: right;\n
+  font-size: 10px;\n
+  color: #EEE;\n
+  cursor: default;\n
+  width: 16px;\n
+  text-align: center;\n
+}\n
+\n
+.handsontable td .htAutocompleteArrow:hover {\n
+  color: #777;\n
+}\n
+\n
+/*\n
+CheckboxRenderer\n
+*/\n
+\n
+.handsontable .htCheckboxRendererInput.noValue {\n
+  opacity: 0.5;\n
+}\n
+\n
+/*\n
+NumericRenderer\n
+*/\n
+\n
+.handsontable .htNumeric {\n
+  text-align: right;\n
+}\n
+\n
+/*context menu rules*/\n
+\n
+ul.context-menu-list {\n
+  color: black;\n
+}\n
+\n
+ul.context-menu-list li {\n
+  margin-bottom: 0;\n
+  /*Foundation framework fix*/\n
+}\n
+\n
+/**\n
+ * dragdealer\n
+ */\n
+\n
+.handsontable .dragdealer {\n
+  position: relative;\n
+  width: 9px;\n
+  height: 9px;\n
+  background: #F8F8F8;\n
+  border: 1px solid #DDD;\n
+}\n
+\n
+.handsontable .dragdealer .handle {\n
+  position: absolute;\n
+  width: 9px;\n
+  height: 9px;\n
+  background: #C5C5C5;\n
+}\n
+\n
+.handsontable .dragdealer .disabled {\n
+  background: #898989;\n
+}\n
+\n
+/**\n
+ * Handsontable in Handsontable\n
+ */\n
+\n
+.handsontable .handsontable .wtHider {\n
+  padding: 0 0 5px 0;\n
+}\n
+\n
+.handsontable .handsontable table {\n
+  -webkit-box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.4);\n
+  box-shadow: 1px 2px 5px rgba(0, 0, 0, 0.4);\n
+}\n
+\n
+/**\n
+ * Handsontable listbox theme\n
+ */\n
+\n
+.handsontable.listbox {\n
+  margin: 0;\n
+}\n
+\n
+.handsontable.listbox table {\n
+  border: 1px solid #ccc;\n
+  border-collapse: separate;\n
+  background: white;\n
+}\n
+\n
+.handsontable.listbox th,\n
+.handsontable.listbox tr:first-child th,\n
+.handsontable.listbox tr:last-child th,\n
+.handsontable.listbox tr:first-child td,\n
+.handsontable.listbox td {\n
+  border-width: 0;\n
+}\n
+\n
+.handsontable.listbox th,\n
+.handsontable.listbox td {\n
+  white-space: nowrap;\n
+  text-overflow: ellipsis;\n
+}\n
+\n
+.handsontable.listbox td.htDimmed {\n
+  cursor: default;\n
+  color: inherit;\n
+  font-style: inherit;\n
+}\n
+\n
+.handsontable.listbox .wtBorder {\n
+  visibility: hidden;\n
+}\n
+\n
+.handsontable.listbox tr td.current,\n
+.handsontable.listbox tr:hover td {\n
+  background: #eee;\n
+}\n
+\n
+.htContextMenu {\n
+  display: none;\n
+  position: absolute;\n
+}\n
+\n
+.htContextMenu table.htCore {\n
+  outline: 1px solid #bbb;\n
+}\n
+\n
+.htContextMenu .wtBorder {\n
+  visibility: hidden;\n
+}\n
+\n
+.htContextMenu table tbody tr td {\n
+  background: white;\n
+  border-width: 0;\n
+  padding: 4px 6px 0px 6px;\n
+  cursor: pointer;\n
+  overflow: hidden;\n
+  white-space: nowrap;\n
+  text-overflow: ellipsis;\n
+}\n
+\n
+.htContextMenu table tbody tr td:first-child {\n
+  border: 0;\n
+}\n
+\n
+.htContextMenu table tbody tr td.htDimmed{\n
+  font-style: normal;\n
+  color: #323232;\n
+}\n
+\n
+.htContextMenu table tbody tr td.current{\n
+  background: rgb(233, 233, 233);\n
+}\n
+\n
+.htContextMenu table tbody tr td.htSeparator {\n
+  border-top: 1px solid #bbb;\n
+  height: 0;\n
+  padding: 0;\n
+}\n
+\n
+.htContextMenu table tbody tr td.htDisabled {\n
+  color: #999;\n
+}\n
+\n
+.htContextMenu table tbody tr td.htDisabled:hover {\n
+  background: white;\n
+  color: #999;\n
+  cursor: default;\n
+}\n
+\n
+.handsontable td.htSearchResult {\n
+  background: #fcedd9;\n
+  color: #583707;\n
+}\n
+\n
+/*WalkontableDebugOverlay*/\n
+\n
+.wtDebugHidden {\n
+  display: none;\n
+}\n
+\n
+.wtDebugVisible {\n
+  display: block;\n
+  -webkit-animation-duration: 0.5s;\n
+  -webkit-animation-name: wtFadeInFromNone;\n
+  animation-duration: 0.5s;\n
+  animation-name: wtFadeInFromNone;\n
+}\n
+\n
+@keyframes wtFadeInFromNone {\n
+  0% {\n
+    display: none;\n
+    opacity: 0;\n
+  }\n
+\n
+  1% {\n
+    display: block;\n
+    opacity: 0;\n
+  }\n
+\n
+  100% {\n
+    display: block;\n
+    opacity: 1;\n
+  }\n
+}\n
+\n
+@-webkit-keyframes wtFadeInFromNone {\n
+  0% {\n
+    display: none;\n
+    opacity: 0;\n
+  }\n
+\n
+  1% {\n
+    display: block;\n
+    opacity: 0;\n
+  }\n
+\n
+  100% {\n
+    display: block;\n
+    opacity: 1;\n
+  }\n
+}
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>8975</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/handsontable.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/handsontable.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7462bd3449b0b86fe89aef376842cbc1ea795047
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/handsontable.js.xml
@@ -0,0 +1,14770 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681769.63</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>handsontable.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>438392</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/**\n
+ * Handsontable 0.10.5\n
+ * Handsontable is a simple jQuery plugin for editable tables with basic copy-paste compatibility with Excel and Google Docs\n
+ *\n
+ * Copyright 2012, Marcin Warpechowski\n
+ * Licensed under the MIT license.\n
+ * http://handsontable.com/\n
+ *\n
+ * Date: Mon Mar 31 2014 14:19:47 GMT+0200 (CEST)\n
+ */\n
+/*jslint white: true, browser: true, plusplus: true, indent: 4, maxerr: 50 */\n
+\n
+var Handsontable = { //class namespace\n
+  extension: {}, //extenstion namespace\n
+  plugins: {}, //plugin namespace\n
+  helper: {} //helper namespace\n
+};\n
+\n
+(function ($, window, Handsontable) {\n
+  "use strict";\n
+//http://stackoverflow.com/questions/3629183/why-doesnt-indexof-work-on-an-array-ie8\n
+if (!Array.prototype.indexOf) {\n
+  Array.prototype.indexOf = function (elt /*, from*/) {\n
+    var len = this.length >>> 0;\n
+\n
+    var from = Number(arguments[1]) || 0;\n
+    from = (from < 0)\n
+      ? Math.ceil(from)\n
+      : Math.floor(from);\n
+    if (from < 0)\n
+      from += len;\n
+\n
+    for (; from < len; from++) {\n
+      if (from in this &&\n
+        this[from] === elt)\n
+        return from;\n
+    }\n
+    return -1;\n
+  };\n
+}\n
+/**\n
+ * Array.filter() shim by Trevor Menagh (https://github.com/trevmex) with some modifications\n
+ */\n
+\n
+if (!Array.prototype.filter) {\n
+  Array.prototype.filter = function (fun, thisp) {\n
+    "use strict";\n
+\n
+    if (typeof this === "undefined" || this === null) {\n
+      throw new TypeError();\n
+    }\n
+    if (typeof fun !== "function") {\n
+      throw new TypeError();\n
+    }\n
+\n
+    thisp = thisp || this;\n
+\n
+    if (isNodeList(thisp)) {\n
+      thisp = convertNodeListToArray(thisp);\n
+    }\n
+\n
+    var len = thisp.length,\n
+      res = [],\n
+      i,\n
+      val;\n
+\n
+    for (i = 0; i < len; i += 1) {\n
+      if (thisp.hasOwnProperty(i)) {\n
+        val = thisp[i]; // in case fun mutates this\n
+        if (fun.call(thisp, val, i, thisp)) {\n
+          res.push(val);\n
+        }\n
+      }\n
+    }\n
+\n
+    return res;\n
+\n
+    function isNodeList(object) {\n
+      return /NodeList/i.test(object.item);\n
+    }\n
+\n
+    function convertNodeListToArray(nodeList) {\n
+      var array = [];\n
+\n
+      for (var i = 0, len = nodeList.length; i < len; i++){\n
+        array[i] = nodeList[i]\n
+      }\n
+\n
+      return array;\n
+    }\n
+  };\n
+}\n
+\n
+/*\n
+ * Copyright 2012 The Polymer Authors. All rights reserved.\n
+ * Use of this source code is governed by a BSD-style\n
+ * license that can be found in the LICENSE file.\n
+ */\n
+\n
+if (typeof WeakMap === \'undefined\') {\n
+  (function() {\n
+    var defineProperty = Object.defineProperty;\n
+\n
+    try {\n
+      var properDefineProperty = true;\n
+      defineProperty(function(){}, \'foo\', {});\n
+    } catch (e) {\n
+      properDefineProperty = false;\n
+    }\n
+\n
+    /*\n
+      IE8 does not support Date.now() but IE8 compatibility mode in IE9 and IE10 does.\n
+      M$ deserves a high five for this one :)\n
+     */\n
+    var counter = +(new Date) % 1e9;\n
+\n
+    var WeakMap = function() {\n
+      this.name = \'__st\' + (Math.random() * 1e9 >>> 0) + (counter++ + \'__\');\n
+      if(!properDefineProperty){\n
+        this._wmCache = [];\n
+      }\n
+    };\n
+\n
+    if(properDefineProperty){\n
+      WeakMap.prototype = {\n
+        set: function(key, value) {\n
+          var entry = key[this.name];\n
+          if (entry && entry[0] === key)\n
+            entry[1] = value;\n
+          else\n
+            defineProperty(key, this.name, {value: [key, value], writable: true});\n
+\n
+        },\n
+        get: function(key) {\n
+          var entry;\n
+          return (entry = key[this.name]) && entry[0] === key ?\n
+            entry[1] : undefined;\n
+        },\n
+        \'delete\': function(key) {\n
+          this.set(key, undefined);\n
+        }\n
+      };\n
+    } else {\n
+      WeakMap.prototype = {\n
+        set: function(key, value) {\n
+\n
+          if(typeof key == \'undefined\' || typeof value == \'undefined\') return;\n
+\n
+          for(var i = 0, len = this._wmCache.length; i < len; i++){\n
+            if(this._wmCache[i].key == key){\n
+              this._wmCache[i].value = value;\n
+              return;\n
+            }\n
+          }\n
+\n
+          this._wmCache.push({key: key, value: value});\n
+\n
+        },\n
+        get: function(key) {\n
+\n
+          if(typeof key == \'undefined\') return;\n
+\n
+          for(var i = 0, len = this._wmCache.length; i < len; i++){\n
+            if(this._wmCache[i].key == key){\n
+              return  this._wmCache[i].value;\n
+            }\n
+          }\n
+\n
+          return;\n
+\n
+        },\n
+        \'delete\': function(key) {\n
+\n
+          if(typeof key == \'undefined\') return;\n
+\n
+          for(var i = 0, len = this._wmCache.length; i < len; i++){\n
+            if(this._wmCache[i].key == key){\n
+              Array.prototype.slice.call(this._wmCache, i, 1);\n
+            }\n
+          }\n
+        }\n
+      };\n
+    }\n
+\n
+    window.WeakMap = WeakMap;\n
+  })();\n
+}\n
+\n
+Handsontable.activeGuid = null;\n
+\n
+/**\n
+ * Handsontable constructor\n
+ * @param rootElement The jQuery element in which Handsontable DOM will be inserted\n
+ * @param userSettings\n
+ * @constructor\n
+ */\n
+Handsontable.Core = function (rootElement, userSettings) {\n
+  var priv\n
+    , datamap\n
+    , grid\n
+    , selection\n
+    , editorManager\n
+    , autofill\n
+    , instance = this\n
+    , GridSettings = function () {};\n
+\n
+  Handsontable.helper.extend(GridSettings.prototype, DefaultSettings.prototype); //create grid settings as a copy of default settings\n
+  Handsontable.helper.extend(GridSettings.prototype, userSettings); //overwrite defaults with user settings\n
+  Handsontable.helper.extend(GridSettings.prototype, expandType(userSettings));\n
+\n
+  this.rootElement = rootElement;\n
+  var $document = $(document.documentElement);\n
+  var $body = $(document.body);\n
+  this.guid = \'ht_\' + Handsontable.helper.randomString(); //this is the namespace for global events\n
+\n
+  if (!this.rootElement[0].id) {\n
+    this.rootElement[0].id = this.guid; //if root element does not have an id, assign a random id\n
+  }\n
+\n
+  priv = {\n
+    cellSettings: [],\n
+    columnSettings: [],\n
+    columnsSettingConflicts: [\'data\', \'width\'],\n
+    settings: new GridSettings(), // current settings instance\n
+    settingsFromDOM: {},\n
+    selStart: new Handsontable.SelectionPoint(),\n
+    selEnd: new Handsontable.SelectionPoint(),\n
+    isPopulated: null,\n
+    scrollable: null,\n
+    extensions: {},\n
+    firstRun: true\n
+  };\n
+\n
+  grid = {\n
+    /**\n
+     * Inserts or removes rows and columns\n
+     * @param {String} action Possible values: "insert_row", "insert_col", "remove_row", "remove_col"\n
+     * @param {Number} index\n
+     * @param {Number} amount\n
+     * @param {String} [source] Optional. Source of hook runner.\n
+     * @param {Boolean} [keepEmptyRows] Optional. Flag for preventing deletion of empty rows.\n
+     */\n
+    alter: function (action, index, amount, source, keepEmptyRows) {\n
+      var delta;\n
+\n
+      amount = amount || 1;\n
+\n
+      switch (action) {\n
+        case "insert_row":\n
+          delta = datamap.createRow(index, amount);\n
+\n
+          if (delta) {\n
+            if (priv.selStart.exists() && priv.selStart.row() >= index) {\n
+              priv.selStart.row(priv.selStart.row() + delta);\n
+              selection.transformEnd(delta, 0); //will call render() internally\n
+            }\n
+            else {\n
+              selection.refreshBorders(); //it will call render and prepare methods\n
+            }\n
+          }\n
+          break;\n
+\n
+        case "insert_col":\n
+          delta = datamap.createCol(index, amount);\n
+\n
+          if (delta) {\n
+\n
+            if(Handsontable.helper.isArray(instance.getSettings().colHeaders)){\n
+              var spliceArray = [index, 0];\n
+              spliceArray.length += delta; //inserts empty (undefined) elements at the end of an array\n
+              Array.prototype.splice.apply(instance.getSettings().colHeaders, spliceArray); //inserts empty (undefined) elements into the colHeader array\n
+            }\n
+\n
+            if (priv.selStart.exists() && priv.selStart.col() >= index) {\n
+              priv.selStart.col(priv.selStart.col() + delta);\n
+              selection.transformEnd(0, delta); //will call render() internally\n
+            }\n
+            else {\n
+              selection.refreshBorders(); //it will call render and prepare methods\n
+            }\n
+          }\n
+          break;\n
+\n
+        case "remove_row":\n
+          datamap.removeRow(index, amount);\n
+          priv.cellSettings.splice(index, amount);\n
+          grid.adjustRowsAndCols();\n
+          selection.refreshBorders(); //it will call render and prepare methods\n
+          break;\n
+\n
+        case "remove_col":\n
+          datamap.removeCol(index, amount);\n
+\n
+          for(var row = 0, len = datamap.getAll().length; row < len; row++){\n
+            if(row in priv.cellSettings){  //if row hasn\'t been rendered it wouldn\'t have cellSettings\n
+              priv.cellSettings[row].splice(index, amount);\n
+            }\n
+          }\n
+\n
+          if(Handsontable.helper.isArray(instance.getSettings().colHeaders)){\n
+            if(typeof index == \'undefined\'){\n
+              index = -1;\n
+            }\n
+            instance.getSettings().colHeaders.splice(index, amount);\n
+          }\n
+\n
+          priv.columnSettings.splice(index, amount);\n
+\n
+          grid.adjustRowsAndCols();\n
+          selection.refreshBorders(); //it will call render and prepare methods\n
+          break;\n
+\n
+        default:\n
+          throw new Error(\'There is no such action "\' + action + \'"\');\n
+          break;\n
+      }\n
+\n
+      if (!keepEmptyRows) {\n
+        grid.adjustRowsAndCols(); //makes sure that we did not add rows that will be removed in next refresh\n
+      }\n
+    },\n
+\n
+    /**\n
+     * Makes sure there are empty rows at the bottom of the table\n
+     */\n
+    adjustRowsAndCols: function () {\n
+      var r, rlen, emptyRows = instance.countEmptyRows(true), emptyCols;\n
+\n
+      //should I add empty rows to data source to meet minRows?\n
+      rlen = instance.countRows();\n
+      if (rlen < priv.settings.minRows) {\n
+        for (r = 0; r < priv.settings.minRows - rlen; r++) {\n
+          datamap.createRow(instance.countRows(), 1, true);\n
+        }\n
+      }\n
+\n
+      //should I add empty rows to meet minSpareRows?\n
+      if (emptyRows < priv.settings.minSpareRows) {\n
+        for (; emptyRows < priv.settings.minSpareRows && instance.countRows() < priv.settings.maxRows; emptyRows++) {\n
+          datamap.createRow(instance.countRows(), 1, true);\n
+        }\n
+      }\n
+\n
+      //count currently empty cols\n
+      emptyCols = instance.countEmptyCols(true);\n
+\n
+      //should I add empty cols to meet minCols?\n
+      if (!priv.settings.columns && instance.countCols() < priv.settings.minCols) {\n
+        for (; instance.countCols() < priv.settings.minCols; emptyCols++) {\n
+          datamap.createCol(instance.countCols(), 1, true);\n
+        }\n
+      }\n
+\n
+      //should I add empty cols to meet minSpareCols?\n
+      if (!priv.settings.columns && instance.dataType === \'array\' && emptyCols < priv.settings.minSpareCols) {\n
+        for (; emptyCols < priv.settings.minSpareCols && instance.countCols() < priv.settings.maxCols; emptyCols++) {\n
+          datamap.createCol(instance.countCols(), 1, true);\n
+        }\n
+      }\n
+\n
+      if (priv.settings.enterBeginsEditing) {\n
+        for (; (((priv.settings.minRows || priv.settings.minSpareRows) && instance.countRows() > priv.settings.minRows) && (priv.settings.minSpareRows && emptyRows > priv.settings.minSpareRows)); emptyRows--) {\n
+          datamap.removeRow();\n
+        }\n
+      }\n
+\n
+      if (priv.settings.enterBeginsEditing && !priv.settings.columns) {\n
+        for (; (((priv.settings.minCols || priv.settings.minSpareCols) && instance.countCols() > priv.settings.minCols) && (priv.settings.minSpareCols && emptyCols > priv.settings.minSpareCols)); emptyCols--) {\n
+          datamap.removeCol();\n
+        }\n
+      }\n
+\n
+      var rowCount = instance.countRows();\n
+      var colCount = instance.countCols();\n
+\n
+      if (rowCount === 0 || colCount === 0) {\n
+        selection.deselect();\n
+      }\n
+\n
+      if (priv.selStart.exists()) {\n
+        var selectionChanged;\n
+        var fromRow = priv.selStart.row();\n
+        var fromCol = priv.selStart.col();\n
+        var toRow = priv.selEnd.row();\n
+        var toCol = priv.selEnd.col();\n
+\n
+        //if selection is outside, move selection to last row\n
+        if (fromRow > rowCount - 1) {\n
+          fromRow = rowCount - 1;\n
+          selectionChanged = true;\n
+          if (toRow > fromRow) {\n
+            toRow = fromRow;\n
+          }\n
+        } else if (toRow > rowCount - 1) {\n
+          toRow = rowCount - 1;\n
+          selectionChanged = true;\n
+          if (fromRow > toRow) {\n
+            fromRow = toRow;\n
+          }\n
+        }\n
+\n
+        //if selection is outside, move selection to last row\n
+        if (fromCol > colCount - 1) {\n
+          fromCol = colCount - 1;\n
+          selectionChanged = true;\n
+          if (toCol > fromCol) {\n
+            toCol = fromCol;\n
+          }\n
+        } else if (toCol > colCount - 1) {\n
+          toCol = colCount - 1;\n
+          selectionChanged = true;\n
+          if (fromCol > toCol) {\n
+            fromCol = toCol;\n
+          }\n
+        }\n
+\n
+        if (selectionChanged) {\n
+          instance.selectCell(fromRow, fromCol, toRow, toCol);\n
+        }\n
+      }\n
+    },\n
+\n
+    /**\n
+     * Populate cells at position with 2d array\n
+     * @param {Object} start Start selection position\n
+     * @param {Array} input 2d array\n
+     * @param {Object} [end] End selection position (only for drag-down mode)\n
+     * @param {String} [source="populateFromArray"]\n
+     * @param {String} [method="overwrite"]\n
+     * @return {Object|undefined} ending td in pasted area (only if any cell was changed)\n
+     */\n
+    populateFromArray: function (start, input, end, source, method) {\n
+      var r, rlen, c, clen, setData = [], current = {};\n
+      rlen = input.length;\n
+      if (rlen === 0) {\n
+        return false;\n
+      }\n
+\n
+      var repeatCol\n
+        , repeatRow\n
+        , cmax\n
+        , rmax;\n
+\n
+      // insert data with specified pasteMode method\n
+      switch (method) {\n
+        case \'shift_down\' :\n
+          repeatCol = end ? end.col - start.col + 1 : 0;\n
+          repeatRow = end ? end.row - start.row + 1 : 0;\n
+          input = Handsontable.helper.translateRowsToColumns(input);\n
+          for (c = 0, clen = input.length, cmax = Math.max(clen, repeatCol); c < cmax; c++) {\n
+            if (c < clen) {\n
+              for (r = 0, rlen = input[c].length; r < repeatRow - rlen; r++) {\n
+                input[c].push(input[c][r % rlen]);\n
+              }\n
+              input[c].unshift(start.col + c, start.row, 0);\n
+              instance.spliceCol.apply(instance, input[c]);\n
+            }\n
+            else {\n
+              input[c % clen][0] = start.col + c;\n
+              instance.spliceCol.apply(instance, input[c % clen]);\n
+            }\n
+          }\n
+          break;\n
+\n
+        case \'shift_right\' :\n
+          repeatCol = end ? end.col - start.col + 1 : 0;\n
+          repeatRow = end ? end.row - start.row + 1 : 0;\n
+          for (r = 0, rlen = input.length, rmax = Math.max(rlen, repeatRow); r < rmax; r++) {\n
+            if (r < rlen) {\n
+              for (c = 0, clen = input[r].length; c < repeatCol - clen; c++) {\n
+                input[r].push(input[r][c % clen]);\n
+              }\n
+              input[r].unshift(start.row + r, start.col, 0);\n
+              instance.spliceRow.apply(instance, input[r]);\n
+            }\n
+            else {\n
+              input[r % rlen][0] = start.row + r;\n
+              instance.spliceRow.apply(instance, input[r % rlen]);\n
+            }\n
+          }\n
+          break;\n
+\n
+        case \'overwrite\' :\n
+        default:\n
+          // overwrite and other not specified options\n
+          current.row = start.row;\n
+          current.col = start.col;\n
+          for (r = 0; r < rlen; r++) {\n
+            if ((end && current.row > end.row) || (!priv.settings.minSpareRows && current.row > instance.countRows() - 1) || (current.row >= priv.settings.maxRows)) {\n
+              break;\n
+            }\n
+            current.col = start.col;\n
+            clen = input[r] ? input[r].length : 0;\n
+            for (c = 0; c < clen; c++) {\n
+              if ((end && current.col > end.col) || (!priv.settings.minSpareCols && current.col > instance.countCols() - 1) || (current.col >= priv.settings.maxCols)) {\n
+                break;\n
+              }\n
+              if (!instance.getCellMeta(current.row, current.col).readOnly) {\n
+                setData.push([current.row, current.col, input[r][c]]);\n
+              }\n
+              current.col++;\n
+              if (end && c === clen - 1) {\n
+                c = -1;\n
+              }\n
+            }\n
+            current.row++;\n
+            if (end && r === rlen - 1) {\n
+              r = -1;\n
+            }\n
+          }\n
+          instance.setDataAtCell(setData, null, null, source || \'populateFromArray\');\n
+          break;\n
+      }\n
+    },\n
+\n
+    /**\n
+     * Returns the top left (TL) and bottom right (BR) selection coordinates\n
+     * @param {Object[]} coordsArr\n
+     * @returns {Object}\n
+     */\n
+    getCornerCoords: function (coordsArr) {\n
+      function mapProp(func, array, prop) {\n
+        function getProp(el) {\n
+          return el[prop];\n
+        }\n
+\n
+        if (Array.prototype.map) {\n
+          return func.apply(Math, array.map(getProp));\n
+        }\n
+        return func.apply(Math, $.map(array, getProp));\n
+      }\n
+\n
+      return {\n
+        TL: {\n
+          row: mapProp(Math.min, coordsArr, "row"),\n
+          col: mapProp(Math.min, coordsArr, "col")\n
+        },\n
+        BR: {\n
+          row: mapProp(Math.max, coordsArr, "row"),\n
+          col: mapProp(Math.max, coordsArr, "col")\n
+        }\n
+      };\n
+    },\n
+\n
+    /**\n
+     * Returns array of td objects given start and end coordinates\n
+     */\n
+    getCellsAtCoords: function (start, end) {\n
+      var corners = grid.getCornerCoords([start, end]);\n
+      var r, c, output = [];\n
+      for (r = corners.TL.row; r <= corners.BR.row; r++) {\n
+        for (c = corners.TL.col; c <= corners.BR.col; c++) {\n
+          output.push(instance.view.getCellAtCoords({\n
+            row: r,\n
+            col: c\n
+          }));\n
+        }\n
+      }\n
+      return output;\n
+    }\n
+  };\n
+\n
+  this.selection = selection = { //this public assignment is only temporary\n
+    inProgress: false,\n
+\n
+    /**\n
+     * Sets inProgress to true. This enables onSelectionEnd and onSelectionEndByProp to function as desired\n
+     */\n
+    begin: function () {\n
+      instance.selection.inProgress = true;\n
+    },\n
+\n
+    /**\n
+     * Sets inProgress to false. Triggers onSelectionEnd and onSelectionEndByProp\n
+     */\n
+    finish: function () {\n
+      var sel = instance.getSelected();\n
+      instance.PluginHooks.run("afterSelectionEnd", sel[0], sel[1], sel[2], sel[3]);\n
+      instance.PluginHooks.run("afterSelectionEndByProp", sel[0], instance.colToProp(sel[1]), sel[2], instance.colToProp(sel[3]));\n
+      instance.selection.inProgress = false;\n
+    },\n
+\n
+    isInProgress: function () {\n
+      return instance.selection.inProgress;\n
+    },\n
+\n
+    /**\n
+     * Starts selection range on given td object\n
+     * @param {Object} coords\n
+     */\n
+    setRangeStart: function (coords) {\n
+      priv.selStart.coords(coords);\n
+      selection.setRangeEnd(coords);\n
+    },\n
+\n
+    /**\n
+     * Ends selection range on given td object\n
+     * @param {Object} coords\n
+     * @param {Boolean} [scrollToCell=true] If true, viewport will be scrolled to range end\n
+     */\n
+    setRangeEnd: function (coords, scrollToCell) {\n
+      instance.selection.begin();\n
+\n
+      priv.selEnd.coords(coords);\n
+      if (!priv.settings.multiSelect) {\n
+        priv.selStart.coords(coords);\n
+      }\n
+\n
+      //set up current selection\n
+      instance.view.wt.selections.current.clear();\n
+      instance.view.wt.selections.current.add(priv.selStart.arr());\n
+\n
+      //set up area selection\n
+      instance.view.wt.selections.area.clear();\n
+      if (selection.isMultiple()) {\n
+        instance.view.wt.selections.area.add(priv.selStart.arr());\n
+        instance.view.wt.selections.area.add(priv.selEnd.arr());\n
+      }\n
+\n
+      //set up highlight\n
+      if (priv.settings.currentRowClassName || priv.settings.currentColClassName) {\n
+        instance.view.wt.selections.highlight.clear();\n
+        instance.view.wt.selections.highlight.add(priv.selStart.arr());\n
+        instance.view.wt.selections.highlight.add(priv.selEnd.arr());\n
+      }\n
+\n
+      //trigger handlers\n
+      instance.PluginHooks.run("afterSelection", priv.selStart.row(), priv.selStart.col(), priv.selEnd.row(), priv.selEnd.col());\n
+      instance.PluginHooks.run("afterSelectionByProp", priv.selStart.row(), datamap.colToProp(priv.selStart.col()), priv.selEnd.row(), datamap.colToProp(priv.selEnd.col()));\n
+\n
+      if (scrollToCell !== false) {\n
+        instance.view.scrollViewport(coords);\n
+      }\n
+      selection.refreshBorders();\n
+    },\n
+\n
+    /**\n
+     * Destroys editor, redraws borders around cells, prepares editor\n
+     * @param {Boolean} revertOriginal\n
+     * @param {Boolean} keepEditor\n
+     */\n
+    refreshBorders: function (revertOriginal, keepEditor) {\n
+      if (!keepEditor) {\n
+        editorManager.destroyEditor(revertOriginal);\n
+      }\n
+      instance.view.render();\n
+      if (selection.isSelected() && !keepEditor) {\n
+        editorManager.prepareEditor();\n
+      }\n
+    },\n
+\n
+    /**\n
+     * Returns information if we have a multiselection\n
+     * @return {Boolean}\n
+     */\n
+    isMultiple: function () {\n
+      return !(priv.selEnd.col() === priv.selStart.col() && priv.selEnd.row() === priv.selStart.row());\n
+    },\n
+\n
+    /**\n
+     * Selects cell relative to current cell (if possible)\n
+     */\n
+    transformStart: function (rowDelta, colDelta, force) {\n
+      if (priv.selStart.row() + rowDelta > instance.countRows() - 1) {\n
+        if (force && priv.settings.minSpareRows > 0) {\n
+          instance.alter("insert_row", instance.countRows());\n
+        }\n
+        else if (priv.settings.autoWrapCol) {\n
+          rowDelta = 1 - instance.countRows();\n
+          colDelta = priv.selStart.col() + colDelta == instance.countCols() - 1 ? 1 - instance.countCols() : 1;\n
+        }\n
+      }\n
+      else if (priv.settings.autoWrapCol && priv.selStart.row() + rowDelta < 0 && priv.selStart.col() + colDelta >= 0) {\n
+        rowDelta = instance.countRows() - 1;\n
+        colDelta = priv.selStart.col() + colDelta == 0 ? instance.countCols() - 1 : -1;\n
+      }\n
+\n
+      if (priv.selStart.col() + colDelta > instance.countCols() - 1) {\n
+        if (force && priv.settings.minSpareCols > 0) {\n
+          instance.alter("insert_col", instance.countCols());\n
+        }\n
+        else if (priv.settings.autoWrapRow) {\n
+          rowDelta = priv.selStart.row() + rowDelta == instance.countRows() - 1 ? 1 - instance.countRows() : 1;\n
+          colDelta = 1 - instance.countCols();\n
+        }\n
+      }\n
+      else if (priv.settings.autoWrapRow && priv.selStart.col() + colDelta < 0 && priv.selStart.row() + rowDelta >= 0) {\n
+        rowDelta = priv.selStart.row() + rowDelta == 0 ? instance.countRows() - 1 : -1;\n
+        colDelta = instance.countCols() - 1;\n
+      }\n
+\n
+      var totalRows = instance.countRows();\n
+      var totalCols = instance.countCols();\n
+      var coords = {\n
+        row: priv.selStart.row() + rowDelta,\n
+        col: priv.selStart.col() + colDelta\n
+      };\n
+\n
+      if (coords.row < 0) {\n
+        coords.row = 0;\n
+      }\n
+      else if (coords.row > 0 && coords.row >= totalRows) {\n
+        coords.row = totalRows - 1;\n
+      }\n
+\n
+      if (coords.col < 0) {\n
+        coords.col = 0;\n
+      }\n
+      else if (coords.col > 0 && coords.col >= totalCols) {\n
+        coords.col = totalCols - 1;\n
+      }\n
+\n
+      selection.setRangeStart(coords);\n
+    },\n
+\n
+    /**\n
+     * Sets selection end cell relative to current selection end cell (if possible)\n
+     */\n
+    transformEnd: function (rowDelta, colDelta) {\n
+      if (priv.selEnd.exists()) {\n
+        var totalRows = instance.countRows();\n
+        var totalCols = instance.countCols();\n
+        var coords = {\n
+          row: priv.selEnd.row() + rowDelta,\n
+          col: priv.selEnd.col() + colDelta\n
+        };\n
+\n
+        if (coords.row < 0) {\n
+          coords.row = 0;\n
+        }\n
+        else if (coords.row > 0 && coords.row >= totalRows) {\n
+          coords.row = totalRows - 1;\n
+        }\n
+\n
+        if (coords.col < 0) {\n
+          coords.col = 0;\n
+        }\n
+        else if (coords.col > 0 && coords.col >= totalCols) {\n
+          coords.col = totalCols - 1;\n
+        }\n
+\n
+        selection.setRangeEnd(coords);\n
+      }\n
+    },\n
+\n
+    /**\n
+     * Returns true if currently there is a selection on screen, false otherwise\n
+     * @return {Boolean}\n
+     */\n
+    isSelected: function () {\n
+      return priv.selEnd.exists();\n
+    },\n
+\n
+    /**\n
+     * Returns true if coords is within current selection coords\n
+     * @return {Boolean}\n
+     */\n
+    inInSelection: function (coords) {\n
+      if (!selection.isSelected()) {\n
+        return false;\n
+      }\n
+      var sel = grid.getCornerCoords([priv.selStart.coords(), priv.selEnd.coords()]);\n
+      return (sel.TL.row <= coords.row && sel.BR.row >= coords.row && sel.TL.col <= coords.col && sel.BR.col >= coords.col);\n
+    },\n
+\n
+    /**\n
+     * Deselects all selected cells\n
+     */\n
+    deselect: function () {\n
+      if (!selection.isSelected()) {\n
+        return;\n
+      }\n
+      instance.selection.inProgress = false; //needed by HT inception\n
+      priv.selEnd = new Handsontable.SelectionPoint(); //create new empty point to remove the existing one\n
+      instance.view.wt.selections.current.clear();\n
+      instance.view.wt.selections.area.clear();\n
+      editorManager.destroyEditor();\n
+      selection.refreshBorders();\n
+      instance.PluginHooks.run(\'afterDeselect\');\n
+    },\n
+\n
+    /**\n
+     * Select all cells\n
+     */\n
+    selectAll: function () {\n
+      if (!priv.settings.multiSelect) {\n
+        return;\n
+      }\n
+      selection.setRangeStart({\n
+        row: 0,\n
+        col: 0\n
+      });\n
+      selection.setRangeEnd({\n
+        row: instance.countRows() - 1,\n
+        col: instance.countCols() - 1\n
+      }, false);\n
+    },\n
+\n
+    /**\n
+     * Deletes data from selected cells\n
+     */\n
+    empty: function () {\n
+      if (!selection.isSelected()) {\n
+        return;\n
+      }\n
+      var corners = grid.getCornerCoords([priv.selStart.coords(), priv.selEnd.coords()]);\n
+      var r, c, changes = [];\n
+      for (r = corners.TL.row; r <= corners.BR.row; r++) {\n
+        for (c = corners.TL.col; c <= corners.BR.col; c++) {\n
+          if (!instance.getCellMeta(r, c).readOnly) {\n
+            changes.push([r, c, \'\']);\n
+          }\n
+        }\n
+      }\n
+      instance.setDataAtCell(changes);\n
+    }\n
+  };\n
+\n
+  this.autofill = autofill = { //this public assignment is only temporary\n
+    handle: null,\n
+\n
+    /**\n
+     * Create fill handle and fill border objects\n
+     */\n
+    init: function () {\n
+      if (!autofill.handle) {\n
+        autofill.handle = {};\n
+      }\n
+      else {\n
+        autofill.handle.disabled = false;\n
+      }\n
+    },\n
+\n
+    /**\n
+     * Hide fill handle and fill border permanently\n
+     */\n
+    disable: function () {\n
+      autofill.handle.disabled = true;\n
+    },\n
+\n
+    /**\n
+     * Selects cells down to the last row in the left column, then fills down to that cell\n
+     */\n
+    selectAdjacent: function () {\n
+      var select, data, r, maxR, c;\n
+\n
+      if (selection.isMultiple()) {\n
+        select = instance.view.wt.selections.area.getCorners();\n
+      }\n
+      else {\n
+        select = instance.view.wt.selections.current.getCorners();\n
+      }\n
+\n
+      data = datamap.getAll();\n
+      rows : for (r = select[2] + 1; r < instance.countRows(); r++) {\n
+        for (c = select[1]; c <= select[3]; c++) {\n
+          if (data[r][c]) {\n
+            break rows;\n
+          }\n
+        }\n
+        if (!!data[r][select[1] - 1] || !!data[r][select[3] + 1]) {\n
+          maxR = r;\n
+        }\n
+      }\n
+      if (maxR) {\n
+        instance.view.wt.selections.fill.clear();\n
+        instance.view.wt.selections.fill.add([select[0], select[1]]);\n
+        instance.view.wt.selections.fill.add([maxR, select[3]]);\n
+        autofill.apply();\n
+      }\n
+    },\n
+\n
+    /**\n
+     * Apply fill values to the area in fill border, omitting the selection border\n
+     */\n
+    apply: function () {\n
+      var drag, select, start, end, _data;\n
+\n
+      autofill.handle.isDragged = 0;\n
+\n
+      drag = instance.view.wt.selections.fill.getCorners();\n
+      if (!drag) {\n
+        return;\n
+      }\n
+\n
+      instance.view.wt.selections.fill.clear();\n
+\n
+      if (selection.isMultiple()) {\n
+        select = instance.view.wt.selections.area.getCorners();\n
+      }\n
+      else {\n
+        select = instance.view.wt.selections.current.getCorners();\n
+      }\n
+\n
+      if (drag[0] === select[0] && drag[1] < select[1]) {\n
+        start = {\n
+          row: drag[0],\n
+          col: drag[1]\n
+        };\n
+        end = {\n
+          row: drag[2],\n
+          col: select[1] - 1\n
+        };\n
+      }\n
+      else if (drag[0] === select[0] && drag[3] > select[3]) {\n
+        start = {\n
+          row: drag[0],\n
+          col: select[3] + 1\n
+        };\n
+        end = {\n
+          row: drag[2],\n
+          col: drag[3]\n
+        };\n
+      }\n
+      else if (drag[0] < select[0] && drag[1] === select[1]) {\n
+        start = {\n
+          row: drag[0],\n
+          col: drag[1]\n
+        };\n
+        end = {\n
+          row: select[0] - 1,\n
+          col: drag[3]\n
+        };\n
+      }\n
+      else if (drag[2] > select[2] && drag[1] === select[1]) {\n
+        start = {\n
+          row: select[2] + 1,\n
+          col: drag[1]\n
+        };\n
+        end = {\n
+          row: drag[2],\n
+          col: drag[3]\n
+        };\n
+      }\n
+\n
+      if (start) {\n
+\n
+        _data = SheetClip.parse(datamap.getText(priv.selStart.coords(), priv.selEnd.coords()));\n
+        instance.PluginHooks.run(\'beforeAutofill\', start, end, _data);\n
+\n
+        grid.populateFromArray(start, _data, end, \'autofill\');\n
+\n
+        selection.setRangeStart({row: drag[0], col: drag[1]});\n
+        selection.setRangeEnd({row: drag[2], col: drag[3]});\n
+      }\n
+      /*else {\n
+       //reset to avoid some range bug\n
+       selection.refreshBorders();\n
+       }*/\n
+    },\n
+\n
+    /**\n
+     * Show fill border\n
+     */\n
+    showBorder: function (coords) {\n
+      coords.row = coords[0];\n
+      coords.col = coords[1];\n
+\n
+      var corners = grid.getCornerCoords([priv.selStart.coords(), priv.selEnd.coords()]);\n
+      if (priv.settings.fillHandle !== \'horizontal\' && (corners.BR.row < coords.row || corners.TL.row > coords.row)) {\n
+        coords = [coords.row, corners.BR.col];\n
+      }\n
+      else if (priv.settings.fillHandle !== \'vertical\') {\n
+        coords = [corners.BR.row, coords.col];\n
+      }\n
+      else {\n
+        return; //wrong direction\n
+      }\n
+\n
+      instance.view.wt.selections.fill.clear();\n
+      instance.view.wt.selections.fill.add([priv.selStart.coords().row, priv.selStart.coords().col]);\n
+      instance.view.wt.selections.fill.add([priv.selEnd.coords().row, priv.selEnd.coords().col]);\n
+      instance.view.wt.selections.fill.add(coords);\n
+      instance.view.render();\n
+    }\n
+  };\n
+\n
+  this.init = function () {\n
+    instance.PluginHooks.run(\'beforeInit\');\n
+\n
+    this.view = new Handsontable.TableView(this);\n
+    editorManager = new Handsontable.EditorManager(instance, priv, selection, datamap);\n
+\n
+    this.updateSettings(priv.settings, true);\n
+    this.parseSettingsFromDOM();\n
+\n
+\n
+    this.forceFullRender = true; //used when data was changed\n
+    this.view.render();\n
+\n
+    if (typeof priv.firstRun === \'object\') {\n
+      instance.PluginHooks.run(\'afterChange\', priv.firstRun[0], priv.firstRun[1]);\n
+      priv.firstRun = false;\n
+    }\n
+    instance.PluginHooks.run(\'afterInit\');\n
+  };\n
+\n
+  function ValidatorsQueue() { //moved this one level up so it can be used in any function here. Probably this should be moved to a separate file\n
+    var resolved = false;\n
+\n
+    return {\n
+      validatorsInQueue: 0,\n
+      addValidatorToQueue: function () {\n
+        this.validatorsInQueue++;\n
+        resolved = false;\n
+      },\n
+      removeValidatorFormQueue: function () {\n
+        this.validatorsInQueue = this.validatorsInQueue - 1 < 0 ? 0 : this.validatorsInQueue - 1;\n
+        this.checkIfQueueIsEmpty();\n
+      },\n
+      onQueueEmpty: function () {\n
+      },\n
+      checkIfQueueIsEmpty: function () {\n
+        if (this.validatorsInQueue == 0 && resolved == false) {\n
+          resolved = true;\n
+          this.onQueueEmpty();\n
+        }\n
+      }\n
+    };\n
+  }\n
+\n
+  function validateChanges(changes, source, callback) {\n
+    var waitingForValidator = new ValidatorsQueue();\n
+    waitingForValidator.onQueueEmpty = resolve;\n
+\n
+    for (var i = changes.length - 1; i >= 0; i--) {\n
+      if (changes[i] === null) {\n
+        changes.splice(i, 1);\n
+      }\n
+      else {\n
+        var row = changes[i][0];\n
+        var col = datamap.propToCol(changes[i][1]);\n
+        var logicalCol = instance.runHooksAndReturn(\'modifyCol\', col); //column order may have changes, so we need to translate physical col index (stored in datasource) to logical (displayed to user)\n
+        var cellProperties = instance.getCellMeta(row, logicalCol);\n
+\n
+        if (cellProperties.type === \'numeric\' && typeof changes[i][3] === \'string\') {\n
+          if (changes[i][3].length > 0 && /^-?[\\d\\s]*\\.?\\d*$/.test(changes[i][3])) {\n
+            changes[i][3] = numeral().unformat(changes[i][3] || \'0\'); //numeral cannot unformat empty string\n
+          }\n
+        }\n
+\n
+        if (instance.getCellValidator(cellProperties)) {\n
+          waitingForValidator.addValidatorToQueue();\n
+          instance.validateCell(changes[i][3], cellProperties, (function (i, cellProperties) {\n
+            return function (result) {\n
+              if (typeof result !== \'boolean\') {\n
+                throw new Error("Validation error: result is not boolean");\n
+              }\n
+              if (result === false && cellProperties.allowInvalid === false) {\n
+                changes.splice(i, 1);         // cancel the change\n
+                cellProperties.valid = true;  // we cancelled the change, so cell value is still valid\n
+                --i;\n
+              }\n
+              waitingForValidator.removeValidatorFormQueue();\n
+            }\n
+          })(i, cellProperties)\n
+            , source);\n
+        }\n
+      }\n
+    }\n
+    waitingForValidator.checkIfQueueIsEmpty();\n
+\n
+    function resolve() {\n
+      var beforeChangeResult;\n
+\n
+      if (changes.length) {\n
+        beforeChangeResult = instance.PluginHooks.execute("beforeChange", changes, source);\n
+        if (typeof beforeChangeResult === \'function\') {\n
+          $.when(result).then(function () {\n
+            callback(); //called when async validators and async beforeChange are resolved\n
+          });\n
+        }\n
+        else if (beforeChangeResult === false) {\n
+          changes.splice(0, changes.length); //invalidate all changes (remove everything from array)\n
+        }\n
+      }\n
+      if (typeof beforeChangeResult !== \'function\') {\n
+        callback(); //called when async validators are resolved and beforeChange was not async\n
+      }\n
+    }\n
+  }\n
+\n
+  /**\n
+   * Internal function to apply changes. Called after validateChanges\n
+   * @param {Array} changes Array in form of [row, prop, oldValue, newValue]\n
+   * @param {String} source String that identifies how this change will be described in changes array (useful in onChange callback)\n
+   */\n
+  function applyChanges(changes, source) {\n
+    var i = changes.length - 1;\n
+\n
+    if (i < 0) {\n
+      return;\n
+    }\n
+\n
+    for (; 0 <= i; i--) {\n
+      if (changes[i] === null) {\n
+        changes.splice(i, 1);\n
+        continue;\n
+      }\n
+\n
+      if (priv.settings.minSpareRows) {\n
+        while (changes[i][0] > instance.countRows() - 1) {\n
+          datamap.createRow();\n
+        }\n
+      }\n
+\n
+      if (instance.dataType === \'array\' && priv.settings.minSpareCols) {\n
+        while (datamap.propToCol(changes[i][1]) > instance.countCols() - 1) {\n
+          datamap.createCol();\n
+        }\n
+      }\n
+\n
+      datamap.set(changes[i][0], changes[i][1], changes[i][3]);\n
+    }\n
+\n
+    instance.forceFullRender = true; //used when data was changed\n
+    grid.adjustRowsAndCols();\n
+    selection.refreshBorders(null, true);\n
+    instance.PluginHooks.run(\'afterChange\', changes, source || \'edit\');\n
+  }\n
+\n
+  this.validateCell = function (value, cellProperties, callback, source) {\n
+    var validator = instance.getCellValidator(cellProperties);\n
+\n
+    if (Object.prototype.toString.call(validator) === \'[object RegExp]\') {\n
+      validator = (function (validator) {\n
+        return function (value, callback) {\n
+          callback(validator.test(value));\n
+        }\n
+      })(validator);\n
+    }\n
+\n
+    if (typeof validator == \'function\') {\n
+\n
+      value = instance.PluginHooks.execute("beforeValidate", value, cellProperties.row, cellProperties.prop, source);\n
+\n
+      // To provide consistent behaviour, validation should be always asynchronous\n
+      setTimeout(function () {\n
+        validator.call(cellProperties, value, function (valid) {\n
+          cellProperties.valid = valid;\n
+\n
+          valid = instance.PluginHooks.execute("afterValidate", valid, value, cellProperties.row, cellProperties.prop, source);\n
+\n
+          callback(valid);\n
+        });\n
+      });\n
+\n
+    } else { //resolve callback even if validator function was not found\n
+      cellProperties.valid = true;\n
+      callback(true);\n
+    }\n
+\n
+\n
+\n
+  };\n
+\n
+  function setDataInputToArray(row, prop_or_col, value) {\n
+    if (typeof row === "object") { //is it an array of changes\n
+      return row;\n
+    }\n
+    else if ($.isPlainObject(value)) { //backwards compatibility\n
+      return value;\n
+    }\n
+    else {\n
+      return [\n
+        [row, prop_or_col, value]\n
+      ];\n
+    }\n
+  }\n
+\n
+  /**\n
+   * Set data at given cell\n
+   * @public\n
+   * @param {Number|Array} row or array of changes in format [[row, col, value], ...]\n
+   * @param {Number|String} col or source String\n
+   * @param {String} value\n
+   * @param {String} source String that identifies how this change will be described in changes array (useful in onChange callback)\n
+   */\n
+  this.setDataAtCell = function (row, col, value, source) {\n
+    var input = setDataInputToArray(row, col, value)\n
+      , i\n
+      , ilen\n
+      , changes = []\n
+      , prop;\n
+\n
+    for (i = 0, ilen = input.length; i < ilen; i++) {\n
+      if (typeof input[i] !== \'object\') {\n
+        throw new Error(\'Method `setDataAtCell` accepts row number or changes array of arrays as its first parameter\');\n
+      }\n
+      if (typeof input[i][1] !== \'number\') {\n
+        throw new Error(\'Method `setDataAtCell` accepts row and column number as its parameters. If you want to use object property name, use method `setDataAtRowProp`\');\n
+      }\n
+      prop = datamap.colToProp(input[i][1]);\n
+      changes.push([\n
+        input[i][0],\n
+        prop,\n
+        datamap.get(input[i][0], prop),\n
+        input[i][2]\n
+      ]);\n
+    }\n
+\n
+    if (!source && typeof row === "object") {\n
+      source = col;\n
+    }\n
+\n
+    validateChanges(changes, source, function () {\n
+      applyChanges(changes, source);\n
+    });\n
+  };\n
+\n
+\n
+  /**\n
+   * Set data at given row property\n
+   * @public\n
+   * @param {Number|Array} row or array of changes in format [[row, prop, value], ...]\n
+   * @param {String} prop or source String\n
+   * @param {String} value\n
+   * @param {String} source String that identifies how this change will be described in changes array (useful in onChange callback)\n
+   */\n
+  this.setDataAtRowProp = function (row, prop, value, source) {\n
+    var input = setDataInputToArray(row, prop, value)\n
+      , i\n
+      , ilen\n
+      , changes = [];\n
+\n
+    for (i = 0, ilen = input.length; i < ilen; i++) {\n
+      changes.push([\n
+        input[i][0],\n
+        input[i][1],\n
+        datamap.get(input[i][0], input[i][1]),\n
+        input[i][2]\n
+      ]);\n
+    }\n
+\n
+    if (!source && typeof row === "object") {\n
+      source = prop;\n
+    }\n
+\n
+    validateChanges(changes, source, function () {\n
+      applyChanges(changes, source);\n
+    });\n
+  };\n
+\n
+  /**\n
+   * Listen to document body keyboard input\n
+   */\n
+  this.listen = function () {\n
+    Handsontable.activeGuid = instance.guid;\n
+\n
+    if (document.activeElement && document.activeElement !== document.body) {\n
+      document.activeElement.blur();\n
+    }\n
+    else if (!document.activeElement) { //IE\n
+      document.body.focus();\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Stop listening to document body keyboard input\n
+   */\n
+  this.unlisten = function () {\n
+    Handsontable.activeGuid = null;\n
+  };\n
+\n
+  /**\n
+   * Returns true if current Handsontable instance is listening on document body keyboard input\n
+   */\n
+  this.isListening = function () {\n
+    return Handsontable.activeGuid === instance.guid;\n
+  };\n
+\n
+  /**\n
+   * Destroys current editor, renders and selects current cell. If revertOriginal != true, edited data is saved\n
+   * @param {Boolean} revertOriginal\n
+   */\n
+  this.destroyEditor = function (revertOriginal) {\n
+    selection.refreshBorders(revertOriginal);\n
+  };\n
+\n
+  /**\n
+   * Populate cells at position with 2d array\n
+   * @param {Number} row Start row\n
+   * @param {Number} col Start column\n
+   * @param {Array} input 2d array\n
+   * @param {Number=} endRow End row (use when you want to cut input when certain row is reached)\n
+   * @param {Number=} endCol End column (use when you want to cut input when certain column is reached)\n
+   * @param {String=} [source="populateFromArray"]\n
+   * @param {String=} [method="overwrite"]\n
+   * @return {Object|undefined} ending td in pasted area (only if any cell was changed)\n
+   */\n
+  this.populateFromArray = function (row, col, input, endRow, endCol, source, method) {\n
+    if (!(typeof input === \'object\' && typeof input[0] === \'object\')) {\n
+      throw new Error("populateFromArray parameter `input` must be an array of arrays"); //API changed in 0.9-beta2, let\'s check if you use it correctly\n
+    }\n
+    return grid.populateFromArray({row: row, col: col}, input, typeof endRow === \'number\' ? {row: endRow, col: endCol} : null, source, method);\n
+  };\n
+\n
+  /**\n
+   * Adds/removes data from the column\n
+   * @param {Number} col Index of column in which do you want to do splice.\n
+   * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end\n
+   * @param {Number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed\n
+   * param {...*} elements Optional. The elements to add to the array. If you don\'t specify any elements, spliceCol simply removes elements from the array\n
+   */\n
+  this.spliceCol = function (col, index, amount/*, elements... */) {\n
+    return datamap.spliceCol.apply(datamap, arguments);\n
+  };\n
+\n
+  /**\n
+   * Adds/removes data from the row\n
+   * @param {Number} row Index of column in which do you want to do splice.\n
+   * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end\n
+   * @param {Number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed\n
+   * param {...*} elements Optional. The elements to add to the array. If you don\'t specify any elements, spliceCol simply removes elements from the array\n
+   */\n
+  this.spliceRow = function (row, index, amount/*, elements... */) {\n
+    return datamap.spliceRow.apply(datamap, arguments);\n
+  };\n
+\n
+  /**\n
+   * Returns the top left (TL) and bottom right (BR) selection coordinates\n
+   * @param {Object[]} coordsArr\n
+   * @returns {Object}\n
+   */\n
+  this.getCornerCoords = function (coordsArr) {\n
+    return grid.getCornerCoords(coordsArr);\n
+  };\n
+\n
+  /**\n
+   * Returns current selection. Returns undefined if there is no selection.\n
+   * @public\n
+   * @return {Array} [`startRow`, `startCol`, `endRow`, `endCol`]\n
+   */\n
+  this.getSelected = function () { //https://github.com/warpech/jquery-handsontable/issues/44  //cjl\n
+    if (selection.isSelected()) {\n
+      return [priv.selStart.row(), priv.selStart.col(), priv.selEnd.row(), priv.selEnd.col()];\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Parse settings from DOM and CSS\n
+   * @public\n
+   */\n
+  this.parseSettingsFromDOM = function () {\n
+    var overflow = this.rootElement.css(\'overflow\');\n
+    if (overflow === \'scroll\' || overflow === \'auto\') {\n
+      this.rootElement[0].style.overflow = \'visible\';\n
+      priv.settingsFromDOM.overflow = overflow;\n
+    }\n
+    else if (priv.settings.width === void 0 || priv.settings.height === void 0) {\n
+      priv.settingsFromDOM.overflow = \'auto\';\n
+    }\n
+\n
+    if (priv.settings.width === void 0) {\n
+      priv.settingsFromDOM.width = this.rootElement.width();\n
+    }\n
+    else {\n
+      priv.settingsFromDOM.width = void 0;\n
+    }\n
+\n
+    priv.settingsFromDOM.height = void 0;\n
+    if (priv.settings.height === void 0) {\n
+      if (priv.settingsFromDOM.overflow === \'scroll\' || priv.settingsFromDOM.overflow === \'auto\') {\n
+        //this needs to read only CSS/inline style and not actual height\n
+        //so we need to call getComputedStyle on cloned container\n
+        var clone = this.rootElement[0].cloneNode(false);\n
+        var parent = this.rootElement[0].parentNode;\n
+        if (parent) {\n
+          clone.removeAttribute(\'id\');\n
+          parent.appendChild(clone);\n
+          var computedClientHeight = parseInt(clone.clientHeight, 10);\n
+          var computedPaddingTop = parseInt(window.getComputedStyle(clone, null).getPropertyValue(\'paddingTop\'), 10) || 0;\n
+          var computedPaddingBottom = parseInt(window.getComputedStyle(clone, null).getPropertyValue(\'paddingBottom\'), 10) || 0;\n
+\n
+          var computedHeight = computedClientHeight - computedPaddingTop - computedPaddingBottom;\n
+\n
+          if(isNaN(computedHeight) && clone.currentStyle){\n
+            computedHeight = parseInt(clone.currentStyle.height, 10)\n
+          }\n
+\n
+          if (computedHeight > 0) {\n
+            priv.settingsFromDOM.height = computedHeight;\n
+          }\n
+          parent.removeChild(clone);\n
+        }\n
+      }\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Render visible data\n
+   * @public\n
+   */\n
+  this.render = function () {\n
+    if (instance.view) {\n
+      instance.forceFullRender = true; //used when data was changed\n
+      instance.parseSettingsFromDOM();\n
+      selection.refreshBorders(null, true);\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Load data from array\n
+   * @public\n
+   * @param {Array} data\n
+   */\n
+  this.loadData = function (data) {\n
+    if (typeof data === \'object\' && data !== null) {\n
+      if (!(data.push && data.splice)) { //check if data is array. Must use duck-type check so Backbone Collections also pass it\n
+        //when data is not an array, attempt to make a single-row array of it\n
+        data = [data];\n
+      }\n
+    }\n
+    else if(data === null) {\n
+      data = [];\n
+      var row;\n
+      for (var r = 0, rlen = priv.settings.startRows; r < rlen; r++) {\n
+        row = [];\n
+        for (var c = 0, clen = priv.settings.startCols; c < clen; c++) {\n
+          row.push(null);\n
+        }\n
+        data.push(row);\n
+      }\n
+    }\n
+    else {\n
+      throw new Error("loadData only accepts array of objects or array of arrays (" + typeof data + " given)");\n
+    }\n
+\n
+    priv.isPopulated = false;\n
+    GridSettings.prototype.data = data;\n
+\n
+    if (priv.settings.dataSchema instanceof Array || data[0]  instanceof Array) {\n
+      instance.dataType = \'array\';\n
+    }\n
+    else if (typeof priv.settings.dataSchema === \'function\') {\n
+      instance.dataType = \'function\';\n
+    }\n
+    else {\n
+      instance.dataType = \'object\';\n
+    }\n
+\n
+    datamap = new Handsontable.DataMap(instance, priv, GridSettings);\n
+\n
+    clearCellSettingCache();\n
+\n
+    grid.adjustRowsAndCols();\n
+    instance.PluginHooks.run(\'afterLoadData\');\n
+\n
+    if (priv.firstRun) {\n
+      priv.firstRun = [null, \'loadData\'];\n
+    }\n
+    else {\n
+      instance.PluginHooks.run(\'afterChange\', null, \'loadData\');\n
+      instance.render();\n
+    }\n
+\n
+    priv.isPopulated = true;\n
+\n
+\n
+\n
+    function clearCellSettingCache() {\n
+      priv.cellSettings.length = 0;\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Return the current data object (the same that was passed by `data` configuration option or `loadData` method). Optionally you can provide cell range `r`, `c`, `r2`, `c2` to get only a fragment of grid data\n
+   * @public\n
+   * @param {Number} r (Optional) From row\n
+   * @param {Number} c (Optional) From col\n
+   * @param {Number} r2 (Optional) To row\n
+   * @param {Number} c2 (Optional) To col\n
+   * @return {Array|Object}\n
+   */\n
+  this.getData = function (r, c, r2, c2) {\n
+    if (typeof r === \'undefined\') {\n
+      return datamap.getAll();\n
+    }\n
+    else {\n
+      return datamap.getRange({row: r, col: c}, {row: r2, col: c2}, datamap.DESTINATION_RENDERER);\n
+    }\n
+  };\n
+\n
+  this.getCopyableData = function (startRow, startCol, endRow, endCol) {\n
+    return datamap.getCopyableText({row: startRow, col: startCol}, {row: endRow, col: endCol});\n
+  }\n
+\n
+  /**\n
+   * Update settings\n
+   * @public\n
+   */\n
+  this.updateSettings = function (settings, init) {\n
+    var i, clen;\n
+\n
+    if (typeof settings.rows !== "undefined") {\n
+      throw new Error("\'rows\' setting is no longer supported. do you mean startRows, minRows or maxRows?");\n
+    }\n
+    if (typeof settings.cols !== "undefined") {\n
+      throw new Error("\'cols\' setting is no longer supported. do you mean startCols, minCols or maxCols?");\n
+    }\n
+\n
+    for (i in settings) {\n
+      if (i === \'data\') {\n
+        continue; //loadData will be triggered later\n
+      }\n
+      else {\n
+        if (instance.PluginHooks.hooks[i] !== void 0 || instance.PluginHooks.legacy[i] !== void 0) {\n
+          if (typeof settings[i] === \'function\' || Handsontable.helper.isArray(settings[i])) {\n
+            instance.PluginHooks.add(i, settings[i]);\n
+          }\n
+        }\n
+        else {\n
+          // Update settings\n
+          if (!init && settings.hasOwnProperty(i)) {\n
+            GridSettings.prototype[i] = settings[i];\n
+          }\n
+\n
+          //launch extensions\n
+          if (Handsontable.extension[i]) {\n
+            priv.extensions[i] = new Handsontable.extension[i](instance, settings[i]);\n
+          }\n
+        }\n
+      }\n
+    }\n
+\n
+    // Load data or create data map\n
+    if (settings.data === void 0 && priv.settings.data === void 0) {\n
+      instance.loadData(null); //data source created just now\n
+    }\n
+    else if (settings.data !== void 0) {\n
+      instance.loadData(settings.data); //data source given as option\n
+    }\n
+    else if (settings.columns !== void 0) {\n
+      datamap.createMap();\n
+    }\n
+\n
+    // Init columns constructors configuration\n
+    clen = instance.countCols();\n
+\n
+    //Clear cellSettings cache\n
+    priv.cellSettings.length = 0;\n
+\n
+    if (clen > 0) {\n
+      var proto, column;\n
+\n
+      for (i = 0; i < clen; i++) {\n
+        priv.columnSettings[i] = Handsontable.helper.columnFactory(GridSettings, priv.columnsSettingConflicts);\n
+\n
+        // shortcut for prototype\n
+        proto = priv.columnSettings[i].prototype;\n
+\n
+        // Use settings provided by user\n
+        if (GridSettings.prototype.columns) {\n
+          column = GridSettings.prototype.columns[i];\n
+          Handsontable.helper.extend(proto, column);\n
+          Handsontable.helper.extend(proto, expandType(column));\n
+        }\n
+      }\n
+    }\n
+\n
+    if (typeof settings.fillHandle !== "undefined") {\n
+      if (autofill.handle && settings.fillHandle === false) {\n
+        autofill.disable();\n
+      }\n
+      else if (!autofill.handle && settings.fillHandle !== false) {\n
+        autofill.init();\n
+      }\n
+    }\n
+\n
+    if (typeof settings.className !== "undefined") {\n
+      if (GridSettings.prototype.className) {\n
+        instance.rootElement.removeClass(GridSettings.prototype.className);\n
+      }\n
+      if (settings.className) {\n
+        instance.rootElement.addClass(settings.className);\n
+      }\n
+    }\n
+\n
+    if (!init) {\n
+      instance.PluginHooks.run(\'afterUpdateSettings\');\n
+    }\n
+\n
+    grid.adjustRowsAndCols();\n
+    if (instance.view && !priv.firstRun) {\n
+      instance.forceFullRender = true; //used when data was changed\n
+      selection.refreshBorders(null, true);\n
+    }\n
+  };\n
+\n
+  this.getValue = function () {\n
+    var sel = instance.getSelected();\n
+    if (GridSettings.prototype.getValue) {\n
+      if (typeof GridSettings.prototype.getValue === \'function\') {\n
+        return GridSettings.prototype.getValue.call(instance);\n
+      }\n
+      else if (sel) {\n
+        return instance.getData()[sel[0]][GridSettings.prototype.getValue];\n
+      }\n
+    }\n
+    else if (sel) {\n
+      return instance.getDataAtCell(sel[0], sel[1]);\n
+    }\n
+  };\n
+\n
+  function expandType(obj) {\n
+    if (!obj.hasOwnProperty(\'type\')) return; //ignore obj.prototype.type\n
+\n
+\n
+    var type, expandedType = {};\n
+\n
+    if (typeof obj.type === \'object\') {\n
+      type = obj.type;\n
+    }\n
+    else if (typeof obj.type === \'string\') {\n
+      type = Handsontable.cellTypes[obj.type];\n
+      if (type === void 0) {\n
+        throw new Error(\'You declared cell type "\' + obj.type + \'" as a string that is not mapped to a known object. Cell type must be an object or a string mapped to an object in Handsontable.cellTypes\');\n
+      }\n
+    }\n
+\n
+\n
+    for (var i in type) {\n
+      if (type.hasOwnProperty(i) && !obj.hasOwnProperty(i)) {\n
+        expandedType[i] = type[i];\n
+      }\n
+    }\n
+\n
+    return expandedType;\n
+\n
+  }\n
+\n
+  /**\n
+   * Returns current settings object\n
+   * @return {Object}\n
+   */\n
+  this.getSettings = function () {\n
+    return priv.settings;\n
+  };\n
+\n
+  /**\n
+   * Returns current settingsFromDOM object\n
+   * @return {Object}\n
+   */\n
+  this.getSettingsFromDOM = function () {\n
+    return priv.settingsFromDOM;\n
+  };\n
+\n
+  /**\n
+   * Clears grid\n
+   * @public\n
+   */\n
+  this.clear = function () {\n
+    selection.selectAll();\n
+    selection.empty();\n
+  };\n
+\n
+  /**\n
+   * Inserts or removes rows and columns\n
+   * @param {String} action See grid.alter for possible values\n
+   * @param {Number} index\n
+   * @param {Number} amount\n
+   * @param {String} [source] Optional. Source of hook runner.\n
+   * @param {Boolean} [keepEmptyRows] Optional. Flag for preventing deletion of empty rows.\n
+   * @public\n
+   */\n
+  this.alter = function (action, index, amount, source, keepEmptyRows) {\n
+    grid.alter(action, index, amount, source, keepEmptyRows);\n
+  };\n
+\n
+  /**\n
+   * Returns <td> element corresponding to params row, col\n
+   * @param {Number} row\n
+   * @param {Number} col\n
+   * @public\n
+   * @return {Element}\n
+   */\n
+  this.getCell = function (row, col) {\n
+    return instance.view.getCellAtCoords({row: row, col: col});\n
+  };\n
+\n
+  /**\n
+   * Returns property name associated with column number\n
+   * @param {Number} col\n
+   * @public\n
+   * @return {String}\n
+   */\n
+  this.colToProp = function (col) {\n
+    return datamap.colToProp(col);\n
+  };\n
+\n
+  /**\n
+   * Returns column number associated with property name\n
+   * @param {String} prop\n
+   * @public\n
+   * @return {Number}\n
+   */\n
+  this.propToCol = function (prop) {\n
+    return datamap.propToCol(prop);\n
+  };\n
+\n
+  /**\n
+   * Return value at `row`, `col`\n
+   * @param {Number} row\n
+   * @param {Number} col\n
+   * @public\n
+   * @return value (mixed data type)\n
+   */\n
+  this.getDataAtCell = function (row, col) {\n
+    return datamap.get(row, datamap.colToProp(col));\n
+  };\n
+\n
+  /**\n
+   * Return value at `row`, `prop`\n
+   * @param {Number} row\n
+   * @param {String} prop\n
+   * @public\n
+   * @return value (mixed data type)\n
+   */\n
+  this.getDataAtRowProp = function (row, prop) {\n
+    return datamap.get(row, prop);\n
+  };\n
+\n
+  /**\n
+   * Return value at `col`\n
+   * @param {Number} col\n
+   * @public\n
+   * @return value (mixed data type)\n
+   */\n
+  this.getDataAtCol = function (col) {\n
+    return [].concat.apply([], datamap.getRange({row: 0, col: col}, {row: priv.settings.data.length - 1, col: col}, datamap.DESTINATION_RENDERER));\n
+  };\n
+\n
+  /**\n
+   * Return value at `prop`\n
+   * @param {String} prop\n
+   * @public\n
+   * @return value (mixed data type)\n
+   */\n
+  this.getDataAtProp = function (prop) {\n
+    return [].concat.apply([], datamap.getRange({row: 0, col: datamap.propToCol(prop)}, {row: priv.settings.data.length - 1, col: datamap.propToCol(prop)}, datamap.DESTINATION_RENDERER));\n
+  };\n
+\n
+  /**\n
+   * Return value at `row`\n
+   * @param {Number} row\n
+   * @public\n
+   * @return value (mixed data type)\n
+   */\n
+  this.getDataAtRow = function (row) {\n
+    return priv.settings.data[row];\n
+  };\n
+\n
+  /**\n
+   * Returns cell meta data object corresponding to params row, col\n
+   * @param {Number} row\n
+   * @param {Number} col\n
+   * @public\n
+   * @return {Object}\n
+   */\n
+  this.getCellMeta = function (row, col) {\n
+    var prop = datamap.colToProp(col)\n
+      , cellProperties;\n
+\n
+    row = translateRowIndex(row);\n
+    col = translateColIndex(col);\n
+\n
+    if ("undefined" === typeof priv.columnSettings[col]) {\n
+      priv.columnSettings[col] = Handsontable.helper.columnFactory(GridSettings, priv.columnsSettingConflicts);\n
+    }\n
+\n
+    if (!priv.cellSettings[row]) {\n
+      priv.cellSettings[row] = [];\n
+    }\n
+    if (!priv.cellSettings[row][col]) {\n
+      priv.cellSettings[row][col] = new priv.columnSettings[col]();\n
+    }\n
+\n
+    cellProperties = priv.cellSettings[row][col]; //retrieve cellProperties from cache\n
+\n
+    cellProperties.row = row;\n
+    cellProperties.col = col;\n
+    cellProperties.prop = prop;\n
+    cellProperties.instance = instance;\n
+\n
+    instance.PluginHooks.run(\'beforeGetCellMeta\', row, col, cellProperties);\n
+    Handsontable.helper.extend(cellProperties, expandType(cellProperties)); //for `type` added in beforeGetCellMeta\n
+\n
+    if (cellProperties.cells) {\n
+      var settings = cellProperties.cells.call(cellProperties, row, col, prop);\n
+\n
+      if (settings) {\n
+        Handsontable.helper.extend(cellProperties, settings);\n
+        Handsontable.helper.extend(cellProperties, expandType(settings)); //for `type` added in cells\n
+      }\n
+    }\n
+\n
+    instance.PluginHooks.run(\'afterGetCellMeta\', row, col, cellProperties);\n
+\n
+    return cellProperties;\n
+\n
+    /**\n
+     * If displayed rows order is different than the order of rows stored in memory (i.e. sorting is applied)\n
+     * we need to translate logical (stored) row index to physical (displayed) index.\n
+     * @param row - original row index\n
+     * @returns {int} translated row index\n
+     */\n
+    function translateRowIndex(row){\n
+      var getVars  = {row: row};\n
+\n
+      instance.PluginHooks.execute(\'beforeGet\', getVars);\n
+\n
+      return getVars.row;\n
+    }\n
+\n
+    /**\n
+     * If displayed columns order is different than the order of columns stored in memory (i.e. column were moved using manualColumnMove plugin)\n
+     * we need to translate logical (stored) column index to physical (displayed) index.\n
+     * @param col - original column index\n
+     * @returns {int} - translated column index\n
+     */\n
+    function translateColIndex(col){\n
+      return Handsontable.PluginHooks.execute(instance, \'modifyCol\', col); // warning: this must be done after datamap.colToProp\n
+    }\n
+  };\n
+\n
+  var rendererLookup = Handsontable.helper.cellMethodLookupFactory(\'renderer\');\n
+  this.getCellRenderer = function (row, col) {\n
+    var renderer = rendererLookup.call(this, row, col);\n
+    return Handsontable.renderers.getRenderer(renderer);\n
+\n
+  };\n
+\n
+  this.getCellEditor = Handsontable.helper.cellMethodLookupFactory(\'editor\');\n
+\n
+  this.getCellValidator = Handsontable.helper.cellMethodLookupFactory(\'validator\');\n
+\n
+\n
+  /**\n
+   * Validates all cells using their validator functions and calls callback when finished. Does not render the view\n
+   * @param callback\n
+   */\n
+  this.validateCells = function (callback) {\n
+    var waitingForValidator = new ValidatorsQueue();\n
+    waitingForValidator.onQueueEmpty = callback;\n
+\n
+    var i = instance.countRows() - 1;\n
+    while (i >= 0) {\n
+      var j = instance.countCols() - 1;\n
+      while (j >= 0) {\n
+        waitingForValidator.addValidatorToQueue();\n
+        instance.validateCell(instance.getDataAtCell(i, j), instance.getCellMeta(i, j), function () {\n
+          waitingForValidator.removeValidatorFormQueue();\n
+        }, \'validateCells\');\n
+        j--;\n
+      }\n
+      i--;\n
+    }\n
+    waitingForValidator.checkIfQueueIsEmpty();\n
+  };\n
+\n
+  /**\n
+   * Return array of row headers (if they are enabled). If param `row` given, return header at given row as string\n
+   * @param {Number} row (Optional)\n
+   * @return {Array|String}\n
+   */\n
+  this.getRowHeader = function (row) {\n
+    if (row === void 0) {\n
+      var out = [];\n
+      for (var i = 0, ilen = instance.countRows(); i < ilen; i++) {\n
+        out.push(instance.getRowHeader(i));\n
+      }\n
+      return out;\n
+    }\n
+    else if (Object.prototype.toString.call(priv.settings.rowHeaders) === \'[object Array]\' && priv.settings.rowHeaders[row] !== void 0) {\n
+      return priv.settings.rowHeaders[row];\n
+    }\n
+    else if (typeof priv.settings.rowHeaders === \'function\') {\n
+      return priv.settings.rowHeaders(row);\n
+    }\n
+    else if (priv.settings.rowHeaders && typeof priv.settings.rowHeaders !== \'string\' && typeof priv.settings.rowHeaders !== \'number\') {\n
+      return row + 1;\n
+    }\n
+    else {\n
+      return priv.settings.rowHeaders;\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Returns information of this table is configured to display row headers\n
+   * @returns {boolean}\n
+   */\n
+  this.hasRowHeaders = function () {\n
+    return !!priv.settings.rowHeaders;\n
+  };\n
+\n
+  /**\n
+   * Returns information of this table is configured to display column headers\n
+   * @returns {boolean}\n
+   */\n
+  this.hasColHeaders = function () {\n
+    if (priv.settings.colHeaders !== void 0 && priv.settings.colHeaders !== null) { //Polymer has empty value = null\n
+      return !!priv.settings.colHeaders;\n
+    }\n
+    for (var i = 0, ilen = instance.countCols(); i < ilen; i++) {\n
+      if (instance.getColHeader(i)) {\n
+        return true;\n
+      }\n
+    }\n
+    return false;\n
+  };\n
+\n
+  /**\n
+   * Return array of column headers (if they are enabled). If param `col` given, return header at given column as string\n
+   * @param {Number} col (Optional)\n
+   * @return {Array|String}\n
+   */\n
+  this.getColHeader = function (col) {\n
+    if (col === void 0) {\n
+      var out = [];\n
+      for (var i = 0, ilen = instance.countCols(); i < ilen; i++) {\n
+        out.push(instance.getColHeader(i));\n
+      }\n
+      return out;\n
+    }\n
+    else {\n
+      col = Handsontable.PluginHooks.execute(instance, \'modifyCol\', col);\n
+\n
+      if (priv.settings.columns && priv.settings.columns[col] && priv.settings.columns[col].title) {\n
+        return priv.settings.columns[col].title;\n
+      }\n
+      else if (Object.prototype.toString.call(priv.settings.colHeaders) === \'[object Array]\' && priv.settings.colHeaders[col] !== void 0) {\n
+        return priv.settings.colHeaders[col];\n
+      }\n
+      else if (typeof priv.settings.colHeaders === \'function\') {\n
+        return priv.settings.colHeaders(col);\n
+      }\n
+      else if (priv.settings.colHeaders && typeof priv.settings.colHeaders !== \'string\' && typeof priv.settings.colHeaders !== \'number\') {\n
+        return Handsontable.helper.spreadsheetColumnLabel(col);\n
+      }\n
+      else {\n
+        return priv.settings.colHeaders;\n
+      }\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Return column width from settings (no guessing). Private use intended\n
+   * @param {Number} col\n
+   * @return {Number}\n
+   */\n
+  this._getColWidthFromSettings = function (col) {\n
+    var cellProperties = instance.getCellMeta(0, col);\n
+    var width = cellProperties.width;\n
+    if (width === void 0 || width === priv.settings.width) {\n
+      width = cellProperties.colWidths;\n
+    }\n
+    if (width !== void 0 && width !== null) {\n
+      switch (typeof width) {\n
+        case \'object\': //array\n
+          width = width[col];\n
+          break;\n
+\n
+        case \'function\':\n
+          width = width(col);\n
+          break;\n
+      }\n
+      if (typeof width === \'string\') {\n
+        width = parseInt(width, 10);\n
+      }\n
+    }\n
+    return width;\n
+  };\n
+\n
+  /**\n
+   * Return column width\n
+   * @param {Number} col\n
+   * @return {Number}\n
+   */\n
+  this.getColWidth = function (col) {\n
+    col = Handsontable.PluginHooks.execute(instance, \'modifyCol\', col);\n
+    var response = {\n
+      width: instance._getColWidthFromSettings(col)\n
+    };\n
+    if (!response.width) {\n
+      response.width = 50;\n
+    }\n
+    instance.PluginHooks.run(\'afterGetColWidth\', col, response);\n
+    return response.width;\n
+  };\n
+\n
+  /**\n
+   * Return total number of rows in grid\n
+   * @return {Number}\n
+   */\n
+  this.countRows = function () {\n
+    return priv.settings.data.length;\n
+  };\n
+\n
+  /**\n
+   * Return total number of columns in grid\n
+   * @return {Number}\n
+   */\n
+  this.countCols = function () {\n
+    if (instance.dataType === \'object\' || instance.dataType === \'function\') {\n
+      if (priv.settings.columns && priv.settings.columns.length) {\n
+        return priv.settings.columns.length;\n
+      }\n
+      else {\n
+        return datamap.colToPropCache.length;\n
+      }\n
+    }\n
+    else if (instance.dataType === \'array\') {\n
+      if (priv.settings.columns && priv.settings.columns.length) {\n
+        return priv.settings.columns.length;\n
+      }\n
+      else if (priv.settings.data && priv.settings.data[0] && priv.settings.data[0].length) {\n
+        return priv.settings.data[0].length;\n
+      }\n
+      else {\n
+        return 0;\n
+      }\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Return index of first visible row\n
+   * @return {Number}\n
+   */\n
+  this.rowOffset = function () {\n
+    return instance.view.wt.getSetting(\'offsetRow\');\n
+  };\n
+\n
+  /**\n
+   * Return index of first visible column\n
+   * @return {Number}\n
+   */\n
+  this.colOffset = function () {\n
+    return instance.view.wt.getSetting(\'offsetColumn\');\n
+  };\n
+\n
+  /**\n
+   * Return number of visible rows. Returns -1 if table is not visible\n
+   * @return {Number}\n
+   */\n
+  this.countVisibleRows = function () {\n
+    return instance.view.wt.drawn ? instance.view.wt.wtTable.rowStrategy.countVisible() : -1;\n
+  };\n
+\n
+  /**\n
+   * Return number of visible columns. Returns -1 if table is not visible\n
+   * @return {Number}\n
+   */\n
+  this.countVisibleCols = function () {\n
+    return instance.view.wt.drawn ? instance.view.wt.wtTable.columnStrategy.countVisible() : -1;\n
+  };\n
+\n
+  /**\n
+   * Return number of empty rows\n
+   * @return {Boolean} ending If true, will only count empty rows at the end of the data source\n
+   */\n
+  this.countEmptyRows = function (ending) {\n
+    var i = instance.countRows() - 1\n
+      , empty = 0;\n
+    while (i >= 0) {\n
+      datamap.get(i, 0);\n
+\n
+      if (instance.isEmptyRow(datamap.getVars.row)) {\n
+        empty++;\n
+      }\n
+      else if (ending) {\n
+        break;\n
+      }\n
+      i--;\n
+    }\n
+    return empty;\n
+  };\n
+\n
+  /**\n
+   * Return number of empty columns\n
+   * @return {Boolean} ending If true, will only count empty columns at the end of the data source row\n
+   */\n
+  this.countEmptyCols = function (ending) {\n
+    if (instance.countRows() < 1) {\n
+      return 0;\n
+    }\n
+\n
+    var i = instance.countCols() - 1\n
+      , empty = 0;\n
+    while (i >= 0) {\n
+      if (instance.isEmptyCol(i)) {\n
+        empty++;\n
+      }\n
+      else if (ending) {\n
+        break;\n
+      }\n
+      i--;\n
+    }\n
+    return empty;\n
+  };\n
+\n
+  /**\n
+   * Return true if the row at the given index is empty, false otherwise\n
+   * @param {Number} r Row index\n
+   * @return {Boolean}\n
+   */\n
+  this.isEmptyRow = function (r) {\n
+    return priv.settings.isEmptyRow.call(instance, r);\n
+  };\n
+\n
+  /**\n
+   * Return true if the column at the given index is empty, false otherwise\n
+   * @param {Number} c Column index\n
+   * @return {Boolean}\n
+   */\n
+  this.isEmptyCol = function (c) {\n
+    return priv.settings.isEmptyCol.call(instance, c);\n
+  };\n
+\n
+  /**\n
+   * Selects cell on grid. Optionally selects range to another cell\n
+   * @param {Number} row\n
+   * @param {Number} col\n
+   * @param {Number} [endRow]\n
+   * @param {Number} [endCol]\n
+   * @param {Boolean} [scrollToCell=true] If true, viewport will be scrolled to the selection\n
+   * @public\n
+   * @return {Boolean}\n
+   */\n
+  this.selectCell = function (row, col, endRow, endCol, scrollToCell) {\n
+    if (typeof row !== \'number\' || row < 0 || row >= instance.countRows()) {\n
+      return false;\n
+    }\n
+    if (typeof col !== \'number\' || col < 0 || col >= instance.countCols()) {\n
+      return false;\n
+    }\n
+    if (typeof endRow !== "undefined") {\n
+      if (typeof endRow !== \'number\' || endRow < 0 || endRow >= instance.countRows()) {\n
+        return false;\n
+      }\n
+      if (typeof endCol !== \'number\' || endCol < 0 || endCol >= instance.countCols()) {\n
+        return false;\n
+      }\n
+    }\n
+    priv.selStart.coords({row: row, col: col});\n
+    if (document.activeElement && document.activeElement !== document.documentElement && document.activeElement !== document.body) {\n
+      document.activeElement.blur(); //needed or otherwise prepare won\'t focus the cell. selectionSpec tests this (should move focus to selected cell)\n
+    }\n
+    instance.listen();\n
+    if (typeof endRow === "undefined") {\n
+      selection.setRangeEnd({row: row, col: col}, scrollToCell);\n
+    }\n
+    else {\n
+      selection.setRangeEnd({row: endRow, col: endCol}, scrollToCell);\n
+    }\n
+\n
+    instance.selection.finish();\n
+    return true;\n
+  };\n
+\n
+  this.selectCellByProp = function (row, prop, endRow, endProp, scrollToCell) {\n
+    arguments[1] = datamap.propToCol(arguments[1]);\n
+    if (typeof arguments[3] !== "undefined") {\n
+      arguments[3] = datamap.propToCol(arguments[3]);\n
+    }\n
+    return instance.selectCell.apply(instance, arguments);\n
+  };\n
+\n
+  /**\n
+   * Deselects current sell selection on grid\n
+   * @public\n
+   */\n
+  this.deselectCell = function () {\n
+    selection.deselect();\n
+  };\n
+\n
+  /**\n
+   * Remove grid from DOM\n
+   * @public\n
+   */\n
+  this.destroy = function () {\n
+    instance.clearTimeouts();\n
+    if (instance.view) { //in case HT is destroyed before initialization has finished\n
+      instance.view.wt.destroy();\n
+    }\n
+    instance.rootElement.empty();\n
+    instance.rootElement.removeData(\'handsontable\');\n
+    instance.rootElement.off(\'.handsontable\');\n
+    $(window).off(\'.\' + instance.guid);\n
+    $document.off(\'.\' + instance.guid);\n
+    $body.off(\'.\' + instance.guid);\n
+    instance.PluginHooks.run(\'afterDestroy\');\n
+  };\n
+\n
+  /**\n
+   * Returns active editor object\n
+   * @returns {Object}\n
+   */\n
+  this.getActiveEditor = function(){\n
+    return editorManager.getActiveEditor();\n
+  };\n
+\n
+  /**\n
+   * Return Handsontable instance\n
+   * @public\n
+   * @return {Object}\n
+   */\n
+  this.getInstance = function () {\n
+    return instance.rootElement.data("handsontable");\n
+  };\n
+\n
+  (function () {\n
+    // Create new instance of plugin hooks\n
+    instance.PluginHooks = new Handsontable.PluginHookClass();\n
+\n
+    // Upgrade methods to call of global PluginHooks instance\n
+    var _run = instance.PluginHooks.run\n
+      , _exe = instance.PluginHooks.execute;\n
+\n
+    instance.PluginHooks.run = function (key, p1, p2, p3, p4, p5) {\n
+      _run.call(this, instance, key, p1, p2, p3, p4, p5);\n
+      Handsontable.PluginHooks.run(instance, key, p1, p2, p3, p4, p5);\n
+    };\n
+\n
+    instance.PluginHooks.execute = function (key, p1, p2, p3, p4, p5) {\n
+      var globalHandlerResult = Handsontable.PluginHooks.execute(instance, key, p1, p2, p3, p4, p5);\n
+      var localHandlerResult = _exe.call(this, instance, key, globalHandlerResult, p2, p3, p4, p5);\n
+\n
+      return typeof localHandlerResult == \'undefined\' ? globalHandlerResult : localHandlerResult;\n
+\n
+    };\n
+\n
+    // Map old API with new methods\n
+    instance.addHook = function () {\n
+      instance.PluginHooks.add.apply(instance.PluginHooks, arguments);\n
+    };\n
+    instance.addHookOnce = function () {\n
+      instance.PluginHooks.once.apply(instance.PluginHooks, arguments);\n
+    };\n
+\n
+    instance.removeHook = function () {\n
+      instance.PluginHooks.remove.apply(instance.PluginHooks, arguments);\n
+    };\n
+\n
+    instance.runHooks = function () {\n
+      instance.PluginHooks.run.apply(instance.PluginHooks, arguments);\n
+    };\n
+    instance.runHooksAndReturn = function () {\n
+      return instance.PluginHooks.execute.apply(instance.PluginHooks, arguments);\n
+    };\n
+\n
+  })();\n
+\n
+  this.timeouts = {};\n
+\n
+  /**\n
+   * Sets timeout. Purpose of this method is to clear all known timeouts when `destroy` method is called\n
+   * @public\n
+   */\n
+  this.registerTimeout = function (key, handle, ms) {\n
+    clearTimeout(this.timeouts[key]);\n
+    this.timeouts[key] = setTimeout(handle, ms || 0);\n
+  };\n
+\n
+  /**\n
+   * Clears all known timeouts\n
+   * @public\n
+   */\n
+  this.clearTimeouts = function () {\n
+    for (var key in this.timeouts) {\n
+      if (this.timeouts.hasOwnProperty(key)) {\n
+        clearTimeout(this.timeouts[key]);\n
+      }\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Handsontable version\n
+   */\n
+  this.version = \'0.10.5\'; //inserted by grunt from package.json\n
+};\n
+\n
+var DefaultSettings = function () {};\n
+\n
+DefaultSettings.prototype = {\n
+  data: void 0,\n
+  width: void 0,\n
+  height: void 0,\n
+  startRows: 5,\n
+  startCols: 5,\n
+  rowHeaders: null,\n
+  colHeaders: null,\n
+  minRows: 0,\n
+  minCols: 0,\n
+  maxRows: Infinity,\n
+  maxCols: Infinity,\n
+  minSpareRows: 0,\n
+  minSpareCols: 0,\n
+  multiSelect: true,\n
+  fillHandle: true,\n
+  fixedRowsTop: 0,\n
+  fixedColumnsLeft: 0,\n
+  outsideClickDeselects: true,\n
+  enterBeginsEditing: true,\n
+  enterMoves: {row: 1, col: 0},\n
+  tabMoves: {row: 0, col: 1},\n
+  autoWrapRow: false,\n
+  autoWrapCol: false,\n
+  copyRowsLimit: 1000,\n
+  copyColsLimit: 1000,\n
+  pasteMode: \'overwrite\',\n
+  currentRowClassName: void 0,\n
+  currentColClassName: void 0,\n
+  stretchH: \'hybrid\',\n
+  isEmptyRow: function (r) {\n
+    var val;\n
+    for (var c = 0, clen = this.countCols(); c < clen; c++) {\n
+      val = this.getDataAtCell(r, c);\n
+      if (val !== \'\' && val !== null && typeof val !== \'undefined\') {\n
+        return false;\n
+      }\n
+    }\n
+    return true;\n
+  },\n
+  isEmptyCol: function (c) {\n
+    var val;\n
+    for (var r = 0, rlen = this.countRows(); r < rlen; r++) {\n
+      val = this.getDataAtCell(r, c);\n
+      if (val !== \'\' && val !== null && typeof val !== \'undefined\') {\n
+        return false;\n
+      }\n
+    }\n
+    return true;\n
+  },\n
+  observeDOMVisibility: true,\n
+  allowInvalid: true,\n
+  invalidCellClassName: \'htInvalid\',\n
+  placeholderCellClassName: \'htPlaceholder\',\n
+  readOnlyCellClassName: \'htDimmed\',\n
+  fragmentSelection: false,\n
+  readOnly: false,\n
+  nativeScrollbars: false,\n
+  type: \'text\',\n
+  copyable: true,\n
+  debug: false //shows debug overlays in Walkontable\n
+};\n
+Handsontable.DefaultSettings = DefaultSettings;\n
+\n
+$.fn.handsontable = function (action) {\n
+  var i\n
+    , ilen\n
+    , args\n
+    , output\n
+    , userSettings\n
+    , $this = this.first() // Use only first element from list\n
+    , instance = $this.data(\'handsontable\');\n
+\n
+  // Init case\n
+  if (typeof action !== \'string\') {\n
+    userSettings = action || {};\n
+    if (instance) {\n
+      instance.updateSettings(userSettings);\n
+    }\n
+    else {\n
+      instance = new Handsontable.Core($this, userSettings);\n
+      $this.data(\'handsontable\', instance);\n
+      instance.init();\n
+    }\n
+\n
+    return $this;\n
+  }\n
+  // Action case\n
+  else {\n
+    args = [];\n
+    if (arguments.length > 1) {\n
+      for (i = 1, ilen = arguments.length; i < ilen; i++) {\n
+        args.push(arguments[i]);\n
+      }\n
+    }\n
+\n
+    if (instance) {\n
+      if (typeof instance[action] !== \'undefined\') {\n
+        output = instance[action].apply(instance, args);\n
+      }\n
+      else {\n
+        throw new Error(\'Handsontable do not provide action: \' + action);\n
+      }\n
+    }\n
+\n
+    return output;\n
+  }\n
+};\n
+\n
+(function (window) {\n
+  \'use strict\';\n
+\n
+  function MultiMap() {\n
+    var map = {\n
+      arrayMap: [],\n
+      weakMap: new WeakMap()\n
+    };\n
+\n
+    return {\n
+      \'get\': function (key) {\n
+        if (canBeAnArrayMapKey(key)) {\n
+          return map.arrayMap[key];\n
+        } else if (canBeAWeakMapKey(key)) {\n
+          return map.weakMap.get(key);\n
+        }\n
+      },\n
+\n
+      \'set\': function (key, value) {\n
+        if (canBeAnArrayMapKey(key)) {\n
+          map.arrayMap[key] = value;\n
+        } else if (canBeAWeakMapKey(key)) {\n
+          map.weakMap.set(key, value);\n
+        } else {\n
+          throw new Error(\'Invalid key type\');\n
+        }\n
+\n
+\n
+      },\n
+\n
+      \'delete\': function (key) {\n
+        if (canBeAnArrayMapKey(key)) {\n
+          delete map.arrayMap[key];\n
+        } else if (canBeAWeakMapKey(key)) {\n
+          map.weakMap[\'delete\'](key);  //Delete must be called using square bracket notation, because IE8 does not handle using `delete` with dot notation\n
+        }\n
+      }\n
+    };\n
+\n
+\n
+\n
+    function canBeAnArrayMapKey(obj){\n
+      return obj !== null && !isNaNSymbol(obj) && (typeof obj == \'string\' || typeof obj == \'number\');\n
+    }\n
+\n
+    function canBeAWeakMapKey(obj){\n
+      return obj !== null && (typeof obj == \'object\' || typeof obj == \'function\');\n
+    }\n
+\n
+    function isNaNSymbol(obj){\n
+      return obj !== obj; // NaN === NaN is always false\n
+    }\n
+\n
+  }\n
+\n
+  if (!window.MultiMap){\n
+    window.MultiMap = MultiMap;\n
+  }\n
+\n
+})(window);\n
+/**\n
+ * Handsontable TableView constructor\n
+ * @param {Object} instance\n
+ */\n
+Handsontable.TableView = function (instance) {\n
+  var that = this\n
+    , $window = $(window)\n
+    , $documentElement = $(document.documentElement);\n
+\n
+  this.instance = instance;\n
+  this.settings = instance.getSettings();\n
+  this.settingsFromDOM = instance.getSettingsFromDOM();\n
+\n
+  instance.rootElement.data(\'originalStyle\', instance.rootElement[0].getAttribute(\'style\')); //needed to retrieve original style in jsFiddle link generator in HT examples. may be removed in future versions\n
+  // in IE7 getAttribute(\'style\') returns an object instead of a string, but we only support IE8+\n
+\n
+  instance.rootElement.addClass(\'handsontable\');\n
+\n
+  var table = document.createElement(\'TABLE\');\n
+  table.className = \'htCore\';\n
+  this.THEAD = document.createElement(\'THEAD\');\n
+  table.appendChild(this.THEAD);\n
+  this.TBODY = document.createElement(\'TBODY\');\n
+  table.appendChild(this.TBODY);\n
+\n
+  instance.$table = $(table);\n
+  instance.rootElement.prepend(instance.$table);\n
+\n
+  instance.rootElement.on(\'mousedown.handsontable\', function (event) {\n
+    if (!that.isTextSelectionAllowed(event.target)) {\n
+      clearTextSelection();\n
+      event.preventDefault();\n
+      window.focus(); //make sure that window that contains HOT is active. Important when HOT is in iframe.\n
+    }\n
+  });\n
+\n
+  $documentElement.on(\'keyup.\' + instance.guid, function (event) {\n
+    if (instance.selection.isInProgress() && !event.shiftKey) {\n
+      instance.selection.finish();\n
+    }\n
+  });\n
+\n
+  var isMouseDown;\n
+\n
+  $documentElement.on(\'mouseup.\' + instance.guid, function (event) {\n
+    if (instance.selection.isInProgress() && event.which === 1) { //is left mouse button\n
+      instance.selection.finish();\n
+    }\n
+\n
+    isMouseDown = false;\n
+\n
+    if (instance.autofill.handle && instance.autofill.handle.isDragged) {\n
+      if (instance.autofill.handle.isDragged > 1) {\n
+        instance.autofill.apply();\n
+      }\n
+      instance.autofill.handle.isDragged = 0;\n
+    }\n
+\n
+    if (Handsontable.helper.isOutsideInput(document.activeElement)) {\n
+      instance.unlisten();\n
+    }\n
+  });\n
+\n
+  $documentElement.on(\'mousedown.\' + instance.guid, function (event) {\n
+    var next = event.target;\n
+\n
+    if (next !== that.wt.wtTable.spreader) { //immediate click on "spreader" means click on the right side of vertical scrollbar\n
+      while (next !== document.documentElement) {\n
+        if (next === null) {\n
+          return; //click on something that was a row but now is detached (possibly because your click triggered a rerender)\n
+        }\n
+        if (next === instance.rootElement[0] || next.nodeName === \'HANDSONTABLE-TABLE\') {\n
+          return; //click inside container or Web Component (HANDSONTABLE-TABLE is the name of the custom element)\n
+        }\n
+        next = next.parentNode;\n
+      }\n
+    }\n
+\n
+    if (that.settings.outsideClickDeselects) {\n
+      instance.deselectCell();\n
+    }\n
+    else {\n
+      instance.destroyEditor();\n
+    }\n
+  });\n
+\n
+  instance.rootElement.on(\'mousedown.handsontable\', \'.dragdealer\', function () {\n
+    instance.destroyEditor();\n
+  });\n
+\n
+  instance.$table.on(\'selectstart\', function (event) {\n
+    if (that.settings.fragmentSelection) {\n
+      return;\n
+    }\n
+\n
+    //https://github.com/warpech/jquery-handsontable/issues/160\n
+    //selectstart is IE only event. Prevent text from being selected when performing drag down in IE8\n
+    event.preventDefault();\n
+  });\n
+\n
+  var clearTextSelection = function () {\n
+    //http://stackoverflow.com/questions/3169786/clear-text-selection-with-javascript\n
+    if (window.getSelection) {\n
+      if (window.getSelection().empty) {  // Chrome\n
+        window.getSelection().empty();\n
+      } else if (window.getSelection().removeAllRanges) {  // Firefox\n
+        window.getSelection().removeAllRanges();\n
+      }\n
+    } else if (document.selection) {  // IE?\n
+      document.selection.empty();\n
+    }\n
+  };\n
+\n
+  var walkontableConfig = {\n
+    debug: function () {\n
+      return that.settings.debug;\n
+    },\n
+    table: table,\n
+    stretchH: this.settings.stretchH,\n
+    data: instance.getDataAtCell,\n
+    totalRows: instance.countRows,\n
+    totalColumns: instance.countCols,\n
+    nativeScrollbars: this.settings.nativeScrollbars,\n
+    offsetRow: 0,\n
+    offsetColumn: 0,\n
+    width: this.getWidth(),\n
+    height: this.getHeight(),\n
+    fixedColumnsLeft: function () {\n
+      return that.settings.fixedColumnsLeft;\n
+    },\n
+    fixedRowsTop: function () {\n
+      return that.settings.fixedRowsTop;\n
+    },\n
+    rowHeaders: function () {\n
+      return instance.hasRowHeaders() ? [function (index, TH) {\n
+        that.appendRowHeader(index, TH);\n
+      }] : []\n
+    },\n
+    columnHeaders: function () {\n
+      return instance.hasColHeaders() ? [function (index, TH) {\n
+        that.appendColHeader(index, TH);\n
+      }] : []\n
+    },\n
+    columnWidth: instance.getColWidth,\n
+    cellRenderer: function (row, col, TD) {\n
+\n
+      var prop = that.instance.colToProp(col)\n
+        , cellProperties = that.instance.getCellMeta(row, col)\n
+        , renderer = that.instance.getCellRenderer(cellProperties);\n
+\n
+      var value = that.instance.getDataAtRowProp(row, prop);\n
+\n
+      renderer(that.instance, TD, row, col, prop, value, cellProperties);\n
+\n
+      that.instance.PluginHooks.run(\'afterRenderer\', TD, row, col, prop, value, cellProperties);\n
+\n
+    },\n
+    selections: {\n
+      current: {\n
+        className: \'current\',\n
+        border: {\n
+          width: 2,\n
+          color: \'#5292F7\',\n
+          style: \'solid\',\n
+          cornerVisible: function () {\n
+            return that.settings.fillHandle && !that.isCellEdited() && !instance.selection.isMultiple()\n
+          }\n
+        }\n
+      },\n
+      area: {\n
+        className: \'area\',\n
+        border: {\n
+          width: 1,\n
+          color: \'#89AFF9\',\n
+          style: \'solid\',\n
+          cornerVisible: function () {\n
+            return that.settings.fillHandle && !that.isCellEdited() && instance.selection.isMultiple()\n
+          }\n
+        }\n
+      },\n
+      highlight: {\n
+        highlightRowClassName: that.settings.currentRowClassName,\n
+        highlightColumnClassName: that.settings.currentColClassName\n
+      },\n
+      fill: {\n
+        className: \'fill\',\n
+        border: {\n
+          width: 1,\n
+          color: \'red\',\n
+          style: \'solid\'\n
+        }\n
+      }\n
+    },\n
+    hideBorderOnMouseDownOver: function () {\n
+      return that.settings.fragmentSelection;\n
+    },\n
+    onCellMouseDown: function (event, coords, TD) {\n
+      instance.listen();\n
+\n
+      isMouseDown = true;\n
+      var coordsObj = {row: coords[0], col: coords[1]};\n
+      if (event.button === 2 && instance.selection.inInSelection(coordsObj)) { //right mouse button\n
+        //do nothing\n
+      }\n
+      else if (event.shiftKey) {\n
+        instance.selection.setRangeEnd(coordsObj);\n
+      }\n
+      else {\n
+        instance.selection.setRangeStart(coordsObj);\n
+      }\n
+\n
+      instance.PluginHooks.run(\'afterOnCellMouseDown\', event, coords, TD);\n
+    },\n
+    /*onCellMouseOut: function (/*event, coords, TD* /) {\n
+     if (isMouseDown && that.settings.fragmentSelection === \'single\') {\n
+     clearTextSelection(); //otherwise text selection blinks during multiple cells selection\n
+     }\n
+     },*/\n
+    onCellMouseOver: function (event, coords, TD) {\n
+      var coordsObj = {row: coords[0], col: coords[1]};\n
+      if (isMouseDown) {\n
+        /*if (that.settings.fragmentSelection === \'single\') {\n
+         clearTextSelection(); //otherwise text selection blinks during multiple cells selection\n
+         }*/\n
+        instance.selection.setRangeEnd(coordsObj);\n
+      }\n
+      else if (instance.autofill.handle && instance.autofill.handle.isDragged) {\n
+        instance.autofill.handle.isDragged++;\n
+        instance.autofill.showBorder(coords);\n
+      }\n
+      instance.PluginHooks.run(\'afterOnCellMouseOver\', event, coords, TD);\n
+    },\n
+    onCellCornerMouseDown: function (event) {\n
+      instance.autofill.handle.isDragged = 1;\n
+      event.preventDefault();\n
+      instance.PluginHooks.run(\'afterOnCellCornerMouseDown\', event);\n
+    },\n
+    onCellCornerDblClick: function () {\n
+      instance.autofill.selectAdjacent();\n
+    },\n
+    beforeDraw: function (force) {\n
+      that.beforeRender(force);\n
+    },\n
+    onDraw: function(force){\n
+      that.onDraw(force);\n
+    },\n
+    onScrollVertically: function () {\n
+      instance.runHooks(\'afterScrollVertically\');\n
+    },\n
+    onScrollHorizontally: function () {\n
+      instance.runHooks(\'afterScrollHorizontally\');\n
+    }\n
+  };\n
+\n
+  instance.PluginHooks.run(\'beforeInitWalkontable\', walkontableConfig);\n
+\n
+  this.wt = new Walkontable(walkontableConfig);\n
+\n
+  $window.on(\'resize.\' + instance.guid, function () {\n
+    instance.registerTimeout(\'resizeTimeout\', function () {\n
+      instance.parseSettingsFromDOM();\n
+      var newWidth = that.getWidth();\n
+      var newHeight = that.getHeight();\n
+      if (walkontableConfig.width !== newWidth || walkontableConfig.height !== newHeight) {\n
+        instance.forceFullRender = true;\n
+        that.render();\n
+        walkontableConfig.width = newWidth;\n
+        walkontableConfig.height = newHeight;\n
+      }\n
+    }, 60);\n
+  });\n
+\n
+  $(that.wt.wtTable.spreader).on(\'mousedown.handsontable, contextmenu.handsontable\', function (event) {\n
+    if (event.target === that.wt.wtTable.spreader && event.which === 3) { //right mouse button exactly on spreader means right clickon the right hand side of vertical scrollbar\n
+      event.stopPropagation();\n
+    }\n
+  });\n
+\n
+  $documentElement.on(\'click.\' + instance.guid, function () {\n
+    if (that.settings.observeDOMVisibility) {\n
+      if (that.wt.drawInterrupted) {\n
+        that.instance.forceFullRender = true;\n
+        that.render();\n
+      }\n
+    }\n
+  });\n
+};\n
+\n
+Handsontable.TableView.prototype.isTextSelectionAllowed = function (el) {\n
+  if ( Handsontable.helper.isInput(el) ) {\n
+    return (true);\n
+  }\n
+  if (this.settings.fragmentSelection && this.wt.wtDom.isChildOf(el, this.TBODY)) {\n
+    return (true);\n
+  }\n
+  return false;\n
+};\n
+\n
+Handsontable.TableView.prototype.isCellEdited = function () {\n
+  var activeEditor = this.instance.getActiveEditor();\n
+  return activeEditor && activeEditor.isOpened();\n
+};\n
+\n
+Handsontable.TableView.prototype.getWidth = function () {\n
+  var val = this.settings.width !== void 0 ? this.settings.width : this.settingsFromDOM.width;\n
+  return typeof val === \'function\' ? val() : val;\n
+};\n
+\n
+Handsontable.TableView.prototype.getHeight = function () {\n
+  var val = this.settings.height !== void 0 ? this.settings.height : this.settingsFromDOM.height;\n
+  return typeof val === \'function\' ? val() : val;\n
+};\n
+\n
+Handsontable.TableView.prototype.beforeRender = function (force) {\n
+  if (force) { //force = did Walkontable decide to do full render\n
+    this.instance.PluginHooks.run(\'beforeRender\', this.instance.forceFullRender); //this.instance.forceFullRender = did Handsontable request full render?\n
+    this.wt.update(\'width\', this.getWidth());\n
+    this.wt.update(\'height\', this.getHeight());\n
+  }\n
+};\n
+\n
+Handsontable.TableView.prototype.onDraw = function(force){\n
+  if (force) { //force = did Walkontable decide to do full render\n
+    this.instance.PluginHooks.run(\'afterRender\', this.instance.forceFullRender); //this.instance.forceFullRender = did Handsontable request full render?\n
+  }\n
+};\n
+\n
+Handsontable.TableView.prototype.render = function () {\n
+  this.wt.draw(!this.instance.forceFullRender);\n
+  this.instance.forceFullRender = false;\n
+  this.instance.rootElement.triggerHandler(\'render.handsontable\');\n
+};\n
+\n
+/**\n
+ * Returns td object given coordinates\n
+ */\n
+Handsontable.TableView.prototype.getCellAtCoords = function (coords) {\n
+  var td = this.wt.wtTable.getCell([coords.row, coords.col]);\n
+  if (td < 0) { //there was an exit code (cell is out of bounds)\n
+    return null;\n
+  }\n
+  else {\n
+    return td;\n
+  }\n
+};\n
+\n
+/**\n
+ * Scroll viewport to selection\n
+ * @param coords\n
+ */\n
+Handsontable.TableView.prototype.scrollViewport = function (coords) {\n
+  this.wt.scrollViewport([coords.row, coords.col]);\n
+};\n
+\n
+/**\n
+ * Append row header to a TH element\n
+ * @param row\n
+ * @param TH\n
+ */\n
+Handsontable.TableView.prototype.appendRowHeader = function (row, TH) {\n
+  if (row > -1) {\n
+    this.wt.wtDom.fastInnerHTML(TH, this.instance.getRowHeader(row));\n
+  }\n
+  else {\n
+    var DIV = document.createElement(\'DIV\');\n
+    DIV.className = \'relative\';\n
+    this.wt.wtDom.fastInnerText(DIV, \'\\u00A0\');\n
+    this.wt.wtDom.empty(TH);\n
+    TH.appendChild(DIV);\n
+  }\n
+};\n
+\n
+/**\n
+ * Append column header to a TH element\n
+ * @param col\n
+ * @param TH\n
+ */\n
+Handsontable.TableView.prototype.appendColHeader = function (col, TH) {\n
+  var DIV = document.createElement(\'DIV\')\n
+    , SPAN = document.createElement(\'SPAN\');\n
+\n
+  DIV.className = \'relative\';\n
+  SPAN.className = \'colHeader\';\n
+\n
+  this.wt.wtDom.fastInnerHTML(SPAN, this.instance.getColHeader(col));\n
+  DIV.appendChild(SPAN);\n
+\n
+  this.wt.wtDom.empty(TH);\n
+  TH.appendChild(DIV);\n
+  this.instance.PluginHooks.run(\'afterGetColHeader\', col, TH);\n
+};\n
+\n
+/**\n
+ * Given a element\'s left position relative to the viewport, returns maximum element width until the right edge of the viewport (before scrollbar)\n
+ * @param {Number} left\n
+ * @return {Number}\n
+ */\n
+Handsontable.TableView.prototype.maximumVisibleElementWidth = function (left) {\n
+  var rootWidth = this.wt.wtViewport.getWorkspaceWidth();\n
+  if(this.settings.nativeScrollbars) {\n
+    return rootWidth;\n
+  }\n
+  return rootWidth - left;\n
+};\n
+\n
+/**\n
+ * Given a element\'s top position relative to the viewport, returns maximum element height until the bottom edge of the viewport (before scrollbar)\n
+ * @param {Number} top\n
+ * @return {Number}\n
+ */\n
+Handsontable.TableView.prototype.maximumVisibleElementHeight = function (top) {\n
+  var rootHeight = this.wt.wtViewport.getWorkspaceHeight();\n
+  if(this.settings.nativeScrollbars) {\n
+    return rootHeight;\n
+  }\n
+  return rootHeight - top;\n
+};\n
+\n
+/**\n
+ * Utility to register editors and common namespace for keeping reference to all editor classes\n
+ */\n
+(function (Handsontable) {\n
+  \'use strict\';\n
+\n
+  function RegisteredEditor(editorClass) {\n
+    var clazz, instances;\n
+\n
+    instances = {};\n
+    clazz = editorClass;\n
+\n
+    this.getInstance = function (hotInstance) {\n
+      if (!(hotInstance.guid in instances)) {\n
+        instances[hotInstance.guid] = new clazz(hotInstance);\n
+      }\n
+\n
+      return instances[hotInstance.guid];\n
+    }\n
+\n
+  }\n
+\n
+  var registeredEditorNames = {};\n
+  var registeredEditorClasses = new WeakMap();\n
+\n
+  Handsontable.editors = {\n
+\n
+    /**\n
+     * Registers editor under given name\n
+     * @param {String} editorName\n
+     * @param {Function} editorClass\n
+     */\n
+    registerEditor: function (editorName, editorClass) {\n
+      var editor = new RegisteredEditor(editorClass);\n
+      if (typeof editorName === "string") {\n
+        registeredEditorNames[editorName] = editor;\n
+      }\n
+      registeredEditorClasses.set(editorClass, editor);\n
+    },\n
+\n
+    /**\n
+     * Returns instance (singleton) of editor class\n
+     * @param {String|Function} editorName/editorClass\n
+     * @returns {Function} editorClass\n
+     */\n
+    getEditor: function (editorName, hotInstance) {\n
+      var editor;\n
+      if (typeof editorName == \'function\') {\n
+        if (!(registeredEditorClasses.get(editorName))) {\n
+          this.registerEditor(null, editorName);\n
+        }\n
+        editor = registeredEditorClasses.get(editorName);\n
+      }\n
+      else if (typeof editorName == \'string\') {\n
+        editor = registeredEditorNames[editorName];\n
+      }\n
+      else {\n
+        throw Error(\'Only strings and functions can be passed as "editor" parameter \');\n
+      }\n
+\n
+      if (!editor) {\n
+        throw Error(\'No editor registered under name "\' + editorName + \'"\');\n
+      }\n
+\n
+      return editor.getInstance(hotInstance);\n
+    }\n
+\n
+  };\n
+\n
+\n
+})(Handsontable);\n
+\n
+(function(Handsontable){\n
+  \'use strict\';\n
+\n
+  Handsontable.EditorManager = function(instance, priv, selection){\n
+    var that = this;\n
+    var $document = $(document);\n
+    var keyCodes = Handsontable.helper.keyCode;\n
+\n
+    var activeEditor;\n
+\n
+    var init = function () {\n
+\n
+      function onKeyDown(event) {\n
+\n
+        if (!instance.isListening()) {\n
+          return;\n
+        }\n
+\n
+        if (priv.settings.beforeOnKeyDown) { // HOT in HOT Plugin\n
+          priv.settings.beforeOnKeyDown.call(instance, event);\n
+        }\n
+\n
+        instance.PluginHooks.run(\'beforeKeyDown\', event);\n
+\n
+        if (!event.isImmediatePropagationStopped()) {\n
+\n
+          priv.lastKeyCode = event.keyCode;\n
+          if (selection.isSelected()) {\n
+            var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)\n
+\n
+            if (!activeEditor.isWaiting()) {\n
+              if (!Handsontable.helper.isMetaKey(event.keyCode) && !ctrlDown && !that.isEditorOpened()) {\n
+                that.openEditor(\'\');\n
+                event.stopPropagation(); //required by HandsontableEditor\n
+                return;\n
+              }\n
+            }\n
+\n
+            var rangeModifier = event.shiftKey ? selection.setRangeEnd : selection.setRangeStart;\n
+\n
+              switch (event.keyCode) {\n
+\n
+                case keyCodes.A:\n
+                  if (ctrlDown) {\n
+                    selection.selectAll(); //select all cells\n
+\n
+                    event.preventDefault();\n
+                    event.stopPropagation();\n
+                    break;\n
+                  }\n
+\n
+                case keyCodes.ARROW_UP:\n
+\n
+                  if (that.isEditorOpened() && !activeEditor.isWaiting()){\n
+                    that.closeEditorAndSaveChanges(ctrlDown);\n
+                  }\n
+\n
+                  moveSelectionUp(event.shiftKey);\n
+\n
+                  event.preventDefault();\n
+                  event.stopPropagation(); //required by HandsontableEditor\n
+                  break;\n
+\n
+                case keyCodes.ARROW_DOWN:\n
+                  if (that.isEditorOpened() && !activeEditor.isWaiting()){\n
+                    that.closeEditorAndSaveChanges(ctrlDown);\n
+                  }\n
+\n
+                  moveSelectionDown(event.shiftKey);\n
+\n
+                  event.preventDefault();\n
+                  event.stopPropagation(); //required by HandsontableEditor\n
+                  break;\n
+\n
+                case keyCodes.ARROW_RIGHT:\n
+                  if(that.isEditorOpened()  && !activeEditor.isWaiting()){\n
+                    that.closeEditorAndSaveChanges(ctrlDown);\n
+                  }\n
+\n
+                  moveSelectionRight(event.shiftKey);\n
+\n
+                  event.preventDefault();\n
+                  event.stopPropagation(); //required by HandsontableEditor\n
+                  break;\n
+\n
+                case keyCodes.ARROW_LEFT:\n
+                  if(that.isEditorOpened() && !activeEditor.isWaiting()){\n
+                    that.closeEditorAndSaveChanges(ctrlDown);\n
+                  }\n
+\n
+                  moveSelectionLeft(event.shiftKey);\n
+\n
+                  event.preventDefault();\n
+                  event.stopPropagation(); //required by HandsontableEditor\n
+                  break;\n
+\n
+                case keyCodes.TAB:\n
+                  var tabMoves = typeof priv.settings.tabMoves === \'function\' ? priv.settings.tabMoves(event) : priv.settings.tabMoves;\n
+                  if (event.shiftKey) {\n
+                    selection.transformStart(-tabMoves.row, -tabMoves.col); //move selection left\n
+                  }\n
+                  else {\n
+                    selection.transformStart(tabMoves.row, tabMoves.col, true); //move selection right (add a new column if needed)\n
+                  }\n
+                  event.preventDefault();\n
+                  event.stopPropagation(); //required by HandsontableEditor\n
+                  break;\n
+\n
+                case keyCodes.BACKSPACE:\n
+                case keyCodes.DELETE:\n
+                  selection.empty(event);\n
+                  that.prepareEditor();\n
+                  event.preventDefault();\n
+                  break;\n
+\n
+                case keyCodes.F2: /* F2 */\n
+                  that.openEditor();\n
+                  event.preventDefault(); //prevent Opera from opening Go to Page dialog\n
+                  break;\n
+\n
+                case keyCodes.ENTER: /* return/enter */\n
+                  if(that.isEditorOpened()){\n
+\n
+                    if (activeEditor.state !== Handsontable.EditorState.WAITING){\n
+                      that.closeEditorAndSaveChanges(ctrlDown);\n
+                    }\n
+\n
+                    moveSelectionAfterEnter(event.shiftKey);\n
+\n
+                  } else {\n
+\n
+                    if (instance.getSettings().enterBeginsEditing){\n
+                      that.openEditor();\n
+                    } else {\n
+                      moveSelectionAfterEnter(event.shiftKey);\n
+                    }\n
+\n
+                  }\n
+\n
+                  event.preventDefault(); //don\'t add newline to field\n
+                  event.stopImmediatePropagation(); //required by HandsontableEditor\n
+                  break;\n
+\n
+                case keyCodes.ESCAPE:\n
+                  if(that.isEditorOpened()){\n
+                    that.closeEditorAndRestoreOriginalValue(ctrlDown);\n
+                  }\n
+                  event.preventDefault();\n
+                  break;\n
+\n
+                case keyCodes.HOME:\n
+                  if (event.ctrlKey || event.metaKey) {\n
+                    rangeModifier({row: 0, col: priv.selStart.col()});\n
+                  }\n
+                  else {\n
+                    rangeModifier({row: priv.selStart.row(), col: 0});\n
+                  }\n
+                  event.preventDefault(); //don\'t scroll the window\n
+                  event.stopPropagation(); //required by HandsontableEditor\n
+                  break;\n
+\n
+                case keyCodes.END:\n
+                  if (event.ctrlKey || event.metaKey) {\n
+                    rangeModifier({row: instance.countRows() - 1, col: priv.selStart.col()});\n
+                  }\n
+                  else {\n
+                    rangeModifier({row: priv.selStart.row(), col: instance.countCols() - 1});\n
+                  }\n
+                  event.preventDefault(); //don\'t scroll the window\n
+                  event.stopPropagation(); //required by HandsontableEditor\n
+                  break;\n
+\n
+                case keyCodes.PAGE_UP:\n
+                  selection.transformStart(-instance.countVisibleRows(), 0);\n
+                  instance.view.wt.scrollVertical(-instance.countVisibleRows());\n
+                  instance.view.render();\n
+                  event.preventDefault(); //don\'t page up the window\n
+                  event.stopPropagation(); //required by HandsontableEditor\n
+                  break;\n
+\n
+                case keyCodes.PAGE_DOWN:\n
+                  selection.transformStart(instance.countVisibleRows(), 0);\n
+                  instance.view.wt.scrollVertical(instance.countVisibleRows());\n
+                  instance.view.render();\n
+                  event.preventDefault(); //don\'t page down the window\n
+                  event.stopPropagation(); //required by HandsontableEditor\n
+                  break;\n
+\n
+                default:\n
+                  break;\n
+              }\n
+\n
+          }\n
+        }\n
+      }\n
+      $document.on(\'keydown.handsontable.\' + instance.guid, onKeyDown);\n
+\n
+      function onDblClick() {\n
+//        that.instance.destroyEditor();\n
+        that.openEditor();\n
+      }\n
+\n
+      instance.view.wt.update(\'onCellDblClick\', onDblClick);\n
+\n
+      instance.addHook(\'afterDestroy\', function(){\n
+        $document.off(\'keydown.handsontable.\' + instance.guid);\n
+      });\n
+\n
+      function moveSelectionAfterEnter(shiftKey){\n
+        var enterMoves = typeof priv.settings.enterMoves === \'function\' ? priv.settings.enterMoves(event) : priv.settings.enterMoves;\n
+\n
+        if (shiftKey) {\n
+          selection.transformStart(-enterMoves.row, -enterMoves.col); //move selection up\n
+        }\n
+        else {\n
+          selection.transformStart(enterMoves.row, enterMoves.col, true); //move selection down (add a new row if needed)\n
+        }\n
+      }\n
+\n
+      function moveSelectionUp(shiftKey){\n
+        if (shiftKey) {\n
+          selection.transformEnd(-1, 0);\n
+        }\n
+        else {\n
+          selection.transformStart(-1, 0);\n
+        }\n
+      }\n
+\n
+      function moveSelectionDown(shiftKey){\n
+        if (shiftKey) {\n
+          selection.transformEnd(1, 0); //expanding selection down with shift\n
+        }\n
+        else {\n
+          selection.transformStart(1, 0); //move selection down\n
+        }\n
+      }\n
+\n
+      function moveSelectionRight(shiftKey){\n
+        if (shiftKey) {\n
+          selection.transformEnd(0, 1);\n
+        }\n
+        else {\n
+          selection.transformStart(0, 1);\n
+        }\n
+      }\n
+\n
+      function moveSelectionLeft(shiftKey){\n
+        if (shiftKey) {\n
+          selection.transformEnd(0, -1);\n
+        }\n
+        else {\n
+          selection.transformStart(0, -1);\n
+        }\n
+      }\n
+    };\n
+\n
+    /**\n
+     * Destroy current editor, if exists\n
+     * @param {Boolean} revertOriginal\n
+     */\n
+    this.destroyEditor = function (revertOriginal) {\n
+      this.closeEditor(revertOriginal);\n
+    };\n
+\n
+    this.getActiveEditor = function () {\n
+      return activeEditor;\n
+    };\n
+\n
+    /**\n
+     * Prepare text input to be displayed at given grid cell\n
+     */\n
+    this.prepareEditor = function () {\n
+\n
+      if (activeEditor && activeEditor.isWaiting()){\n
+\n
+        this.closeEditor(false, false, function(dataSaved){\n
+          if(dataSaved){\n
+            that.prepareEditor();\n
+          }\n
+        });\n
+\n
+        return;\n
+      }\n
+\n
+      var row = priv.selStart.row();\n
+      var col = priv.selStart.col();\n
+      var prop = instance.colToProp(col);\n
+      var td = instance.getCell(row, col);\n
+      var originalValue = instance.getDataAtCell(row, col);\n
+      var cellProperties = instance.getCellMeta(row, col);\n
+\n
+      var editorClass = instance.getCellEditor(cellProperties);\n
+      activeEditor = Handsontable.editors.getEditor(editorClass, instance);\n
+\n
+      activeEditor.prepare(row, col, prop, td, originalValue, cellProperties);\n
+\n
+    };\n
+\n
+    this.isEditorOpened = function () {\n
+      return activeEditor.isOpened();\n
+    };\n
+\n
+    this.openEditor = function (initialValue) {\n
+      if (!activeEditor.cellProperties.readOnly){\n
+        activeEditor.beginEditing(initialValue);\n
+      }\n
+    };\n
+\n
+    this.closeEditor = function (restoreOriginalValue, ctrlDown, callback) {\n
+\n
+      if (!activeEditor){\n
+        if(callback) {\n
+          callback(false);\n
+        }\n
+      }\n
+      else {\n
+        activeEditor.finishEditing(restoreOriginalValue, ctrlDown, callback);\n
+      }\n
+    };\n
+\n
+    this.closeEditorAndSaveChanges = function(ctrlDown){\n
+      return this.closeEditor(false, ctrlDown);\n
+    };\n
+\n
+    this.closeEditorAndRestoreOriginalValue = function(ctrlDown){\n
+      return this.closeEditor(true, ctrlDown);\n
+    };\n
+\n
+    init();\n
+  };\n
+\n
+})(Handsontable);\n
+\n
+/**\n
+ * Utility to register renderers and common namespace for keeping reference to all renderers classes\n
+ */\n
+(function (Handsontable) {\n
+  \'use strict\';\n
+\n
+  var registeredRenderers = {};\n
+\n
+  Handsontable.renderers = {\n
+\n
+    /**\n
+     * Registers renderer under given name\n
+     * @param {String} rendererName\n
+     * @param {Function} rendererFunction\n
+     */\n
+    registerRenderer: function (rendererName, rendererFunction) {\n
+      registeredRenderers[rendererName] = rendererFunction\n
+    },\n
+\n
+    /**\n
+     * @param {String|Function} rendererName/rendererFunction\n
+     * @returns {Function} rendererFunction\n
+     */\n
+    getRenderer: function (rendererName) {\n
+      if (typeof rendererName == \'function\'){\n
+        return rendererName;\n
+      }\n
+\n
+      if (typeof rendererName != \'string\'){\n
+        throw Error(\'Only strings and functions can be passed as "renderer" parameter \');\n
+      }\n
+\n
+      if (!(rendererName in registeredRenderers)) {\n
+        throw Error(\'No editor registered under name "\' + rendererName + \'"\');\n
+      }\n
+\n
+      return registeredRenderers[rendererName];\n
+    }\n
+\n
+  };\n
+\n
+\n
+})(Handsontable);\n
+\n
+/**\n
+ * DOM helper optimized for maximum performance\n
+ * It is recommended for Handsontable plugins and renderers, because it is much faster than jQuery\n
+ * @type {WalkonableDom}\n
+ */\n
+Handsontable.Dom = new WalkontableDom();\n
+\n
+/**\n
+ * Returns true if keyCode represents a printable character\n
+ * @param {Number} keyCode\n
+ * @return {Boolean}\n
+ */\n
+Handsontable.helper.isPrintableChar = function (keyCode) {\n
+  return ((keyCode == 32) || //space\n
+    (keyCode >= 48 && keyCode <= 57) || //0-9\n
+    (keyCode >= 96 && keyCode <= 111) || //numpad\n
+    (keyCode >= 186 && keyCode <= 192) || //;=,-./`\n
+    (keyCode >= 219 && keyCode <= 222) || //[]{}\\|"\'\n
+    keyCode >= 226 || //special chars (229 for Asian chars)\n
+    (keyCode >= 65 && keyCode <= 90)); //a-z\n
+};\n
+\n
+Handsontable.helper.isMetaKey = function (keyCode) {\n
+  var keyCodes = Handsontable.helper.keyCode;\n
+  var metaKeys = [\n
+    keyCodes.ARROW_DOWN,\n
+    keyCodes.ARROW_UP,\n
+    keyCodes.ARROW_LEFT,\n
+    keyCodes.ARROW_RIGHT,\n
+    keyCodes.HOME,\n
+    keyCodes.END,\n
+    keyCodes.DELETE,\n
+    keyCodes.BACKSPACE,\n
+    keyCodes.F1,\n
+    keyCodes.F2,\n
+    keyCodes.F3,\n
+    keyCodes.F4,\n
+    keyCodes.F5,\n
+    keyCodes.F6,\n
+    keyCodes.F7,\n
+    keyCodes.F8,\n
+    keyCodes.F9,\n
+    keyCodes.F10,\n
+    keyCodes.F11,\n
+    keyCodes.F12,\n
+    keyCodes.TAB,\n
+    keyCodes.PAGE_DOWN,\n
+    keyCodes.PAGE_UP,\n
+    keyCodes.ENTER,\n
+    keyCodes.ESCAPE,\n
+    keyCodes.SHIFT,\n
+    keyCodes.CAPS_LOCK,\n
+    keyCodes.ALT\n
+  ];\n
+\n
+  return metaKeys.indexOf(keyCode) != -1;\n
+};\n
+\n
+Handsontable.helper.isCtrlKey = function (keyCode) {\n
+\n
+  var keys = Handsontable.helper.keyCode;\n
+\n
+  return [keys.CONTROL_LEFT, 224, keys.COMMAND_LEFT, keys.COMMAND_RIGHT].indexOf(keyCode) != -1;\n
+};\n
+\n
+/**\n
+ * Converts a value to string\n
+ * @param value\n
+ * @return {String}\n
+ */\n
+Handsontable.helper.stringify = function (value) {\n
+  switch (typeof value) {\n
+    case \'string\':\n
+    case \'number\':\n
+      return value + \'\';\n
+      break;\n
+\n
+    case \'object\':\n
+      if (value === null) {\n
+        return \'\';\n
+      }\n
+      else {\n
+        return value.toString();\n
+      }\n
+      break;\n
+\n
+    case \'undefined\':\n
+      return \'\';\n
+      break;\n
+\n
+    default:\n
+      return value.toString();\n
+  }\n
+};\n
+\n
+/**\n
+ * Generates spreadsheet-like column names: A, B, C, ..., Z, AA, AB, etc\n
+ * @param index\n
+ * @returns {String}\n
+ */\n
+Handsontable.helper.spreadsheetColumnLabel = function (index) {\n
+  var dividend = index + 1;\n
+  var columnLabel = \'\';\n
+  var modulo;\n
+  while (dividend > 0) {\n
+    modulo = (dividend - 1) % 26;\n
+    columnLabel = String.fromCharCode(65 + modulo) + columnLabel;\n
+    dividend = parseInt((dividend - modulo) / 26, 10);\n
+  }\n
+  return columnLabel;\n
+};\n
+\n
+/**\n
+ * Checks if value of n is a numeric one\n
+ * http://jsperf.com/isnan-vs-isnumeric/4\n
+ * @param n\n
+ * @returns {boolean}\n
+ */\n
+Handsontable.helper.isNumeric = function (n) {\n
+    var t = typeof n;\n
+    return t == \'number\' ? !isNaN(n) && isFinite(n) :\n
+           t == \'string\' ? !n.length ? false :\n
+           n.length == 1 ? /\\d/.test(n) :\n
+           /^\\s*[+-]?\\s*(?:(?:\\d+(?:\\.\\d+)?(?:e[+-]?\\d+)?)|(?:0x[a-f\\d]+))\\s*$/i.test(n) :\n
+           t == \'object\' ? !!n && typeof n.valueOf() == "number" && !(n instanceof Date) : false;\n
+};\n
+\n
+Handsontable.helper.isArray = function (obj) {\n
+  return Object.prototype.toString.call(obj).match(/array/i) !== null;\n
+};\n
+\n
+/**\n
+ * Checks if child is a descendant of given parent node\n
+ * http://stackoverflow.com/questions/2234979/how-to-check-in-javascript-if-one-element-is-a-child-of-another\n
+ * @param parent\n
+ * @param child\n
+ * @returns {boolean}\n
+ */\n
+Handsontable.helper.isDescendant = function (parent, child) {\n
+  var node = child.parentNode;\n
+  while (node != null) {\n
+    if (node == parent) {\n
+      return true;\n
+    }\n
+    node = node.parentNode;\n
+  }\n
+  return false;\n
+};\n
+\n
+/**\n
+ * Generates a random hex string. Used as namespace for Handsontable instance events.\n
+ * @return {String} - 16 character random string: "92b1bfc74ec4"\n
+ */\n
+Handsontable.helper.randomString = function () {\n
+  return walkontableRandomString();\n
+};\n
+\n
+/**\n
+ * Inherit without without calling parent constructor, and setting `Child.prototype.constructor` to `Child` instead of `Parent`.\n
+ * Creates temporary dummy function to call it as constructor.\n
+ * Described in ticket: https://github.com/warpech/jquery-handsontable/pull/516\n
+ * @param  {Object} Child  child class\n
+ * @param  {Object} Parent parent class\n
+ * @return {Object}        extended Child\n
+ */\n
+Handsontable.helper.inherit = function (Child, Parent) {\n
+  Parent.prototype.constructor = Parent;\n
+  Child.prototype = new Parent();\n
+  Child.prototype.constructor = Child;\n
+  return Child;\n
+};\n
+\n
+/**\n
+ * Perform shallow extend of a target object with extension\'s own properties\n
+ * @param {Object} target An object that will receive the new properties\n
+ * @param {Object} extension An object containing additional properties to merge into the target\n
+ */\n
+Handsontable.helper.extend = function (target, extension) {\n
+  for (var i in extension) {\n
+    if (extension.hasOwnProperty(i)) {\n
+      target[i] = extension[i];\n
+    }\n
+  }\n
+};\n
+\n
+Handsontable.helper.getPrototypeOf = function (obj) {\n
+  var prototype;\n
+\n
+  if(typeof obj.__proto__ == "object"){\n
+    prototype = obj.__proto__;\n
+  } else {\n
+    var oldConstructor,\n
+        constructor = obj.constructor;\n
+\n
+    if (typeof obj.constructor == "function") {\n
+      oldConstructor = constructor;\n
+\n
+      if (delete obj.constructor){\n
+        constructor = obj.constructor; // get real constructor\n
+        obj.constructor = oldConstructor; // restore constructor\n
+      }\n
+\n
+\n
+    }\n
+\n
+    prototype = constructor ? constructor.prototype : null; // needed for IE\n
+\n
+  }\n
+\n
+  return prototype;\n
+};\n
+\n
+/**\n
+ * Factory for columns constructors.\n
+ * @param {Object} GridSettings\n
+ * @param {Array} conflictList\n
+ * @return {Object} ColumnSettings\n
+ */\n
+Handsontable.helper.columnFactory = function (GridSettings, conflictList) {\n
+  function ColumnSettings () {}\n
+\n
+  Handsontable.helper.inherit(ColumnSettings, GridSettings);\n
+\n
+  // Clear conflict settings\n
+  for (var i = 0, len = conflictList.length; i < len; i++) {\n
+    ColumnSettings.prototype[conflictList[i]] = void 0;\n
+  }\n
+\n
+  return ColumnSettings;\n
+};\n
+\n
+Handsontable.helper.translateRowsToColumns = function (input) {\n
+  var i\n
+    , ilen\n
+    , j\n
+    , jlen\n
+    , output = []\n
+    , olen = 0;\n
+\n
+  for (i = 0, ilen = input.length; i < ilen; i++) {\n
+    for (j = 0, jlen = input[i].length; j < jlen; j++) {\n
+      if (j == olen) {\n
+        output.push([]);\n
+        olen++;\n
+      }\n
+      output[j].push(input[i][j])\n
+    }\n
+  }\n
+  return output;\n
+};\n
+\n
+Handsontable.helper.to2dArray = function (arr) {\n
+  var i = 0\n
+    , ilen = arr.length;\n
+  while (i < ilen) {\n
+    arr[i] = [arr[i]];\n
+    i++;\n
+  }\n
+};\n
+\n
+Handsontable.helper.extendArray = function (arr, extension) {\n
+  var i = 0\n
+    , ilen = extension.length;\n
+  while (i < ilen) {\n
+    arr.push(extension[i]);\n
+    i++;\n
+  }\n
+};\n
+\n
+/**\n
+ * Determines if the given DOM element is an input field.\n
+ * Notice: By \'input\' we mean input, textarea and select nodes\n
+ * @param element - DOM element\n
+ * @returns {boolean}\n
+ */\n
+Handsontable.helper.isInput = function (element) {\n
+  var inputs = [\'INPUT\', \'SELECT\', \'TEXTAREA\'];\n
+\n
+  return inputs.indexOf(element.nodeName) > -1;\n
+}\n
+\n
+/**\n
+ * Determines if the given DOM element is an input field placed OUTSIDE of HOT.\n
+ * Notice: By \'input\' we mean input, textarea and select nodes\n
+ * @param element - DOM element\n
+ * @returns {boolean}\n
+ */\n
+Handsontable.helper.isOutsideInput = function (element) {\n
+  return Handsontable.helper.isInput(element) && element.className.indexOf(\'handsontableInput\') == -1;\n
+};\n
+\n
+Handsontable.helper.keyCode = {\n
+  MOUSE_LEFT: 1,\n
+  MOUSE_RIGHT: 3,\n
+  MOUSE_MIDDLE: 2,\n
+  BACKSPACE: 8,\n
+  COMMA: 188,\n
+  DELETE: 46,\n
+  END: 35,\n
+  ENTER: 13,\n
+  ESCAPE: 27,\n
+  CONTROL_LEFT: 91,\n
+  COMMAND_LEFT: 17,\n
+  COMMAND_RIGHT: 93,\n
+  ALT: 18,\n
+  HOME: 36,\n
+  PAGE_DOWN: 34,\n
+  PAGE_UP: 33,\n
+  PERIOD: 190,\n
+  SPACE: 32,\n
+  SHIFT: 16,\n
+  CAPS_LOCK: 20,\n
+  TAB: 9,\n
+  ARROW_RIGHT: 39,\n
+  ARROW_LEFT: 37,\n
+  ARROW_UP: 38,\n
+  ARROW_DOWN: 40,\n
+  F1: 112,\n
+  F2: 113,\n
+  F3: 114,\n
+  F4: 115,\n
+  F5: 116,\n
+  F6: 117,\n
+  F7: 118,\n
+  F8: 119,\n
+  F9: 120,\n
+  F10: 121,\n
+  F11: 122,\n
+  F12: 123,\n
+  A: 65,\n
+  X: 88,\n
+  C: 67,\n
+  V: 86\n
+};\n
+\n
+/**\n
+ * Determines whether given object is a plain Object.\n
+ * Note: String and Array are not plain Objects\n
+ * @param {*} obj\n
+ * @returns {boolean}\n
+ */\n
+Handsontable.helper.isObject = function (obj) {\n
+  return Object.prototype.toString.call(obj) == \'[object Object]\';\n
+};\n
+\n
+/**\n
+ * Determines whether given object is an Array.\n
+ * Note: String is not an Array\n
+ * @param {*} obj\n
+ * @returns {boolean}\n
+ */\n
+Handsontable.helper.isArray = function(obj){\n
+  return Array.isArray ? Array.isArray(obj) : Object.prototype.toString.call(obj) == \'[object Array]\';\n
+};\n
+\n
+Handsontable.helper.pivot = function (arr) {\n
+  var pivotedArr = [];\n
+\n
+  if(!arr || arr.length == 0 || !arr[0] || arr[0].length == 0){\n
+    return pivotedArr;\n
+  }\n
+\n
+  var rowCount = arr.length;\n
+  var colCount = arr[0].length;\n
+\n
+  for(var i = 0; i < rowCount; i++){\n
+    for(var j = 0; j < colCount; j++){
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+\n
+      if(!pivotedArr[j]){\n
+        pivotedArr[j] = [];\n
+      }\n
+\n
+      pivotedArr[j][i] = arr[i][j];\n
+    }\n
+  }\n
+\n
+  return pivotedArr;\n
+\n
+};\n
+\n
+Handsontable.helper.proxy = function (fun, context) {\n
+  return function () {\n
+    return fun.apply(context, arguments);\n
+  };\n
+};\n
+\n
+/**\n
+ * Factory that produces a function for searching methods (or any properties) which could be defined directly in\n
+ * table configuration or implicitly, within cell type definition.\n
+ *\n
+ * For example: renderer can be defined explicitly using "renderer" property in column configuration or it can be\n
+ * defined implicitly using "type" property.\n
+ *\n
+ * Methods/properties defined explicitly always takes precedence over those defined through "type".\n
+ *\n
+ * If the method/property is not found in an object, searching is continued recursively through prototype chain, until\n
+ * it reaches the Object.prototype.\n
+ *\n
+ *\n
+ * @param methodName {String} name of the method/property to search (i.e. \'renderer\', \'validator\', \'copyable\')\n
+ * @param allowUndefined {Boolean} [optional] if false, the search is continued if methodName has not been found in cell "type"\n
+ * @returns {Function}\n
+ */\n
+Handsontable.helper.cellMethodLookupFactory = function (methodName, allowUndefined) {\n
+\n
+  allowUndefined = typeof allowUndefined == \'undefined\' ? true : allowUndefined;\n
+\n
+  return function cellMethodLookup (row, col) {\n
+\n
+    return (function getMethodFromProperties(properties) {\n
+\n
+      if (!properties){\n
+\n
+        return;                       //method not found\n
+\n
+      }\n
+      else if (properties.hasOwnProperty(methodName) && properties[methodName]) { //check if it is own and is not empty\n
+\n
+        return properties[methodName];  //method defined directly\n
+\n
+      } else if (properties.hasOwnProperty(\'type\') && properties.type) { //check if it is own and is not empty\n
+\n
+        var type;\n
+\n
+        if(typeof properties.type != \'string\' ){\n
+          throw new Error(\'Cell type must be a string \');\n
+        }\n
+\n
+        type = translateTypeNameToObject(properties.type);\n
+\n
+        if (type.hasOwnProperty(methodName)) {\n
+          return type[methodName]; //method defined in type.\n
+        } else if (allowUndefined) {\n
+          return; //method does not defined in type (eg. validator), returns undefined\n
+        }\n
+\n
+      }\n
+\n
+      return getMethodFromProperties(Handsontable.helper.getPrototypeOf(properties));\n
+\n
+    })(typeof row == \'number\' ? this.getCellMeta(row, col) : row);\n
+\n
+  };\n
+\n
+  function translateTypeNameToObject(typeName) {\n
+    var type = Handsontable.cellTypes[typeName];\n
+\n
+    if(typeof type == \'undefined\'){\n
+      throw new Error(\'You declared cell type "\' + typeName + \'" as a string that is not mapped to a known object. Cell type must be an object or a string mapped to an object in Handsontable.cellTypes\');\n
+    }\n
+\n
+    return type;\n
+  }\n
+\n
+};\n
+\n
+Handsontable.helper.toString = function (obj) {\n
+  return \'\' + obj;\n
+};\n
+Handsontable.SelectionPoint = function () {\n
+  this._row = null; //private use intended\n
+  this._col = null;\n
+};\n
+\n
+Handsontable.SelectionPoint.prototype.exists = function () {\n
+  return (this._row !== null);\n
+};\n
+\n
+Handsontable.SelectionPoint.prototype.row = function (val) {\n
+  if (val !== void 0) {\n
+    this._row = val;\n
+  }\n
+  return this._row;\n
+};\n
+\n
+Handsontable.SelectionPoint.prototype.col = function (val) {\n
+  if (val !== void 0) {\n
+    this._col = val;\n
+  }\n
+  return this._col;\n
+};\n
+\n
+Handsontable.SelectionPoint.prototype.coords = function (coords) {\n
+  if (coords !== void 0) {\n
+    this._row = coords.row;\n
+    this._col = coords.col;\n
+  }\n
+  return {\n
+    row: this._row,\n
+    col: this._col\n
+  }\n
+};\n
+\n
+Handsontable.SelectionPoint.prototype.arr = function (arr) {\n
+  if (arr !== void 0) {\n
+    this._row = arr[0];\n
+    this._col = arr[1];\n
+  }\n
+  return [this._row, this._col]\n
+};\n
+(function (Handsontable) {\n
+  \'use strict\';\n
+\n
+  /**\n
+   * Utility class that gets and saves data from/to the data source using mapping of columns numbers to object property names\n
+   * TODO refactor arguments of methods getRange, getText to be numbers (not objects)\n
+   * TODO remove priv, GridSettings from object constructor\n
+   *\n
+   * @param instance\n
+   * @param priv\n
+   * @param GridSettings\n
+   * @constructor\n
+   */\n
+  Handsontable.DataMap = function (instance, priv, GridSettings) {\n
+    this.instance = instance;\n
+    this.priv = priv;\n
+    this.GridSettings = GridSettings;\n
+    this.dataSource = this.instance.getSettings().data;\n
+\n
+    if (this.dataSource[0]) {\n
+      this.duckSchema = this.recursiveDuckSchema(this.dataSource[0]);\n
+    }\n
+    else {\n
+      this.duckSchema = {};\n
+    }\n
+    this.createMap();\n
+\n
+    this.getVars = {}; //used by modifier\n
+    this.setVars = {}; //used by modifier\n
+  };\n
+\n
+  Handsontable.DataMap.prototype.DESTINATION_RENDERER = 1;\n
+  Handsontable.DataMap.prototype.DESTINATION_CLIPBOARD_GENERATOR = 2;\n
+\n
+  Handsontable.DataMap.prototype.recursiveDuckSchema = function (obj) {\n
+    var schema;\n
+    if ($.isPlainObject(obj)) {\n
+      schema = {};\n
+      for (var i in obj) {\n
+        if (obj.hasOwnProperty(i)) {\n
+          if ($.isPlainObject(obj[i])) {\n
+            schema[i] = this.recursiveDuckSchema(obj[i]);\n
+          }\n
+          else {\n
+            schema[i] = null;\n
+          }\n
+        }\n
+      }\n
+    }\n
+    else {\n
+      schema = [];\n
+    }\n
+    return schema;\n
+  };\n
+\n
+  Handsontable.DataMap.prototype.recursiveDuckColumns = function (schema, lastCol, parent) {\n
+    var prop, i;\n
+    if (typeof lastCol === \'undefined\') {\n
+      lastCol = 0;\n
+      parent = \'\';\n
+    }\n
+    if ($.isPlainObject(schema)) {\n
+      for (i in schema) {\n
+        if (schema.hasOwnProperty(i)) {\n
+          if (schema[i] === null) {\n
+            prop = parent + i;\n
+            this.colToPropCache.push(prop);\n
+            this.propToColCache.set(prop, lastCol);\n
+\n
+            lastCol++;\n
+          }\n
+          else {\n
+            lastCol = this.recursiveDuckColumns(schema[i], lastCol, i + \'.\');\n
+          }\n
+        }\n
+      }\n
+    }\n
+    return lastCol;\n
+  };\n
+\n
+  Handsontable.DataMap.prototype.createMap = function () {\n
+    if (typeof this.getSchema() === "undefined") {\n
+      throw new Error("trying to create `columns` definition but you didnt\' provide `schema` nor `data`");\n
+    }\n
+    var i, ilen, schema = this.getSchema();\n
+    this.colToPropCache = [];\n
+    this.propToColCache = new MultiMap();\n
+    var columns = this.instance.getSettings().columns;\n
+    if (columns) {\n
+      for (i = 0, ilen = columns.length; i < ilen; i++) {\n
+\n
+        if (typeof columns[i].data != \'undefined\'){\n
+          this.colToPropCache[i] = columns[i].data;\n
+          this.propToColCache.set(columns[i].data, i);\n
+        }\n
+\n
+      }\n
+    }\n
+    else {\n
+      this.recursiveDuckColumns(schema);\n
+    }\n
+  };\n
+\n
+  Handsontable.DataMap.prototype.colToProp = function (col) {\n
+    col = Handsontable.PluginHooks.execute(this.instance, \'modifyCol\', col);\n
+    if (this.colToPropCache && typeof this.colToPropCache[col] !== \'undefined\') {\n
+      return this.colToPropCache[col];\n
+    }\n
+    else {\n
+      return col;\n
+    }\n
+  };\n
+\n
+  Handsontable.DataMap.prototype.propToCol = function (prop) {\n
+    var col;\n
+    if (typeof this.propToColCache.get(prop) !== \'undefined\') {\n
+      col = this.propToColCache.get(prop);\n
+    } else {\n
+      col = prop;\n
+    }\n
+    col = Handsontable.PluginHooks.execute(this.instance, \'modifyCol\', col);\n
+    return col;\n
+  };\n
+\n
+  Handsontable.DataMap.prototype.getSchema = function () {\n
+    var schema = this.instance.getSettings().dataSchema;\n
+    if (schema) {\n
+      if (typeof schema === \'function\') {\n
+        return schema();\n
+      }\n
+      return schema;\n
+    }\n
+    return this.duckSchema;\n
+  };\n
+\n
+  /**\n
+   * Creates row at the bottom of the data array\n
+   * @param {Number} [index] Optional. Index of the row before which the new row will be inserted\n
+   */\n
+  Handsontable.DataMap.prototype.createRow = function (index, amount, createdAutomatically) {\n
+    var row\n
+      , colCount = this.instance.countCols()\n
+      , numberOfCreatedRows = 0\n
+      , currentIndex;\n
+\n
+    if (!amount) {\n
+      amount = 1;\n
+    }\n
+\n
+    if (typeof index !== \'number\' || index >= this.instance.countRows()) {\n
+      index = this.instance.countRows();\n
+    }\n
+\n
+    currentIndex = index;\n
+    var maxRows = this.instance.getSettings().maxRows;\n
+    while (numberOfCreatedRows < amount && this.instance.countRows() < maxRows) {\n
+\n
+      if (this.instance.dataType === \'array\') {\n
+        row = [];\n
+        for (var c = 0; c < colCount; c++) {\n
+          row.push(null);\n
+        }\n
+      }\n
+      else if (this.instance.dataType === \'function\') {\n
+        row = this.instance.getSettings().dataSchema(index);\n
+      }\n
+      else {\n
+        row = $.extend(true, {}, this.getSchema());\n
+      }\n
+\n
+      if (index === this.instance.countRows()) {\n
+        this.dataSource.push(row);\n
+      }\n
+      else {\n
+        this.dataSource.splice(index, 0, row);\n
+      }\n
+\n
+      numberOfCreatedRows++;\n
+      currentIndex++;\n
+    }\n
+\n
+\n
+    this.instance.PluginHooks.run(\'afterCreateRow\', index, numberOfCreatedRows, createdAutomatically);\n
+    this.instance.forceFullRender = true; //used when data was changed\n
+\n
+    return numberOfCreatedRows;\n
+  };\n
+\n
+  /**\n
+   * Creates col at the right of the data array\n
+   * @param {Number} [index] Optional. Index of the column before which the new column will be inserted\n
+   *   * @param {Number} [amount] Optional.\n
+   */\n
+  Handsontable.DataMap.prototype.createCol = function (index, amount, createdAutomatically) {\n
+    if (this.instance.dataType === \'object\' || this.instance.getSettings().columns) {\n
+      throw new Error("Cannot create new column. When data source in an object, " +\n
+        "you can only have as much columns as defined in first data row, data schema or in the \'columns\' setting." +\n
+        "If you want to be able to add new columns, you have to use array datasource.");\n
+    }\n
+    var rlen = this.instance.countRows()\n
+      , data = this.dataSource\n
+      , constructor\n
+      , numberOfCreatedCols = 0\n
+      , currentIndex;\n
+\n
+    if (!amount) {\n
+      amount = 1;\n
+    }\n
+\n
+    currentIndex = index;\n
+\n
+    var maxCols = this.instance.getSettings().maxCols;\n
+    while (numberOfCreatedCols < amount && this.instance.countCols() < maxCols) {\n
+      constructor = Handsontable.helper.columnFactory(this.GridSettings, this.priv.columnsSettingConflicts);\n
+      if (typeof index !== \'number\' || index >= this.instance.countCols()) {\n
+        for (var r = 0; r < rlen; r++) {\n
+          if (typeof data[r] === \'undefined\') {\n
+            data[r] = [];\n
+          }\n
+          data[r].push(null);\n
+        }\n
+        // Add new column constructor\n
+        this.priv.columnSettings.push(constructor);\n
+      }\n
+      else {\n
+        for (var r = 0; r < rlen; r++) {\n
+          data[r].splice(currentIndex, 0, null);\n
+        }\n
+        // Add new column constructor at given index\n
+        this.priv.columnSettings.splice(currentIndex, 0, constructor);\n
+      }\n
+\n
+      numberOfCreatedCols++;\n
+      currentIndex++;\n
+    }\n
+\n
+    this.instance.PluginHooks.run(\'afterCreateCol\', index, numberOfCreatedCols, createdAutomatically);\n
+    this.instance.forceFullRender = true; //used when data was changed\n
+\n
+    return numberOfCreatedCols;\n
+  };\n
+\n
+  /**\n
+   * Removes row from the data array\n
+   * @param {Number} [index] Optional. Index of the row to be removed. If not provided, the last row will be removed\n
+   * @param {Number} [amount] Optional. Amount of the rows to be removed. If not provided, one row will be removed\n
+   */\n
+  Handsontable.DataMap.prototype.removeRow = function (index, amount) {\n
+    if (!amount) {\n
+      amount = 1;\n
+    }\n
+    if (typeof index !== \'number\') {\n
+      index = -amount;\n
+    }\n
+\n
+    index = (this.instance.countRows() + index) % this.instance.countRows();\n
+\n
+    // We have to map the physical row ids to logical and than perform removing with (possibly) new row id\n
+    var logicRows = this.physicalRowsToLogical(index, amount);\n
+\n
+    var actionWasNotCancelled = this.instance.PluginHooks.execute(\'beforeRemoveRow\', index, amount);\n
+\n
+    if (actionWasNotCancelled === false) {\n
+      return;\n
+    }\n
+\n
+    var data = this.dataSource;\n
+    var newData = data.filter(function (row, index) {\n
+      return logicRows.indexOf(index) == -1;\n
+    });\n
+\n
+    data.length = 0;\n
+    Array.prototype.push.apply(data, newData);\n
+\n
+    this.instance.PluginHooks.run(\'afterRemoveRow\', index, amount);\n
+\n
+    this.instance.forceFullRender = true; //used when data was changed\n
+  };\n
+\n
+  /**\n
+   * Removes column from the data array\n
+   * @param {Number} [index] Optional. Index of the column to be removed. If not provided, the last column will be removed\n
+   * @param {Number} [amount] Optional. Amount of the columns to be removed. If not provided, one column will be removed\n
+   */\n
+  Handsontable.DataMap.prototype.removeCol = function (index, amount) {\n
+    if (this.instance.dataType === \'object\' || this.instance.getSettings().columns) {\n
+      throw new Error("cannot remove column with object data source or columns option specified");\n
+    }\n
+    if (!amount) {\n
+      amount = 1;\n
+    }\n
+    if (typeof index !== \'number\') {\n
+      index = -amount;\n
+    }\n
+\n
+    index = (this.instance.countCols() + index) % this.instance.countCols();\n
+\n
+    var actionWasNotCancelled = this.instance.PluginHooks.execute(\'beforeRemoveCol\', index, amount);\n
+\n
+    if (actionWasNotCancelled === false) {\n
+      return;\n
+    }\n
+\n
+    var data = this.dataSource;\n
+    for (var r = 0, rlen = this.instance.countRows(); r < rlen; r++) {\n
+      data[r].splice(index, amount);\n
+    }\n
+    this.priv.columnSettings.splice(index, amount);\n
+\n
+    this.instance.PluginHooks.run(\'afterRemoveCol\', index, amount);\n
+    this.instance.forceFullRender = true; //used when data was changed\n
+  };\n
+\n
+  /**\n
+   * Add / removes data from the column\n
+   * @param {Number} col Index of column in which do you want to do splice.\n
+   * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end\n
+   * @param {Number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed\n
+   * param {...*} elements Optional. The elements to add to the array. If you don\'t specify any elements, spliceCol simply removes elements from the array\n
+   */\n
+  Handsontable.DataMap.prototype.spliceCol = function (col, index, amount/*, elements...*/) {\n
+    var elements = 4 <= arguments.length ? [].slice.call(arguments, 3) : [];\n
+\n
+    var colData = this.instance.getDataAtCol(col);\n
+    var removed = colData.slice(index, index + amount);\n
+    var after = colData.slice(index + amount);\n
+\n
+    Handsontable.helper.extendArray(elements, after);\n
+    var i = 0;\n
+    while (i < amount) {\n
+      elements.push(null); //add null in place of removed elements\n
+      i++;\n
+    }\n
+    Handsontable.helper.to2dArray(elements);\n
+    this.instance.populateFromArray(index, col, elements, null, null, \'spliceCol\');\n
+\n
+    return removed;\n
+  };\n
+\n
+  /**\n
+   * Add / removes data from the row\n
+   * @param {Number} row Index of row in which do you want to do splice.\n
+   * @param {Number} index Index at which to start changing the array. If negative, will begin that many elements from the end\n
+   * @param {Number} amount An integer indicating the number of old array elements to remove. If amount is 0, no elements are removed\n
+   * param {...*} elements Optional. The elements to add to the array. If you don\'t specify any elements, spliceCol simply removes elements from the array\n
+   */\n
+  Handsontable.DataMap.prototype.spliceRow = function (row, index, amount/*, elements...*/) {\n
+    var elements = 4 <= arguments.length ? [].slice.call(arguments, 3) : [];\n
+\n
+    var rowData = this.instance.getDataAtRow(row);\n
+    var removed = rowData.slice(index, index + amount);\n
+    var after = rowData.slice(index + amount);\n
+\n
+    Handsontable.helper.extendArray(elements, after);\n
+    var i = 0;\n
+    while (i < amount) {\n
+      elements.push(null); //add null in place of removed elements\n
+      i++;\n
+    }\n
+    this.instance.populateFromArray(row, index, [elements], null, null, \'spliceRow\');\n
+\n
+    return removed;\n
+  };\n
+\n
+  /**\n
+   * Returns single value from the data array\n
+   * @param {Number} row\n
+   * @param {Number} prop\n
+   */\n
+  Handsontable.DataMap.prototype.get = function (row, prop) {\n
+    this.getVars.row = row;\n
+    this.getVars.prop = prop;\n
+    this.instance.PluginHooks.run(\'beforeGet\', this.getVars);\n
+    if (typeof this.getVars.prop === \'string\' && this.getVars.prop.indexOf(\'.\') > -1) {\n
+      var sliced = this.getVars.prop.split(".");\n
+      var out = this.dataSource[this.getVars.row];\n
+      if (!out) {\n
+        return null;\n
+      }\n
+      for (var i = 0, ilen = sliced.length; i < ilen; i++) {\n
+        out = out[sliced[i]];\n
+        if (typeof out === \'undefined\') {\n
+          return null;\n
+        }\n
+      }\n
+      return out;\n
+    }\n
+    else if (typeof this.getVars.prop === \'function\') {\n
+      /**\n
+       *  allows for interacting with complex structures, for example\n
+       *  d3/jQuery getter/setter properties:\n
+       *\n
+       *    {columns: [{\n
+         *      data: function(row, value){\n
+         *        if(arguments.length === 1){\n
+         *          return row.property();\n
+         *        }\n
+         *        row.property(value);\n
+         *      }\n
+         *    }]}\n
+       */\n
+      return this.getVars.prop(this.dataSource.slice(\n
+        this.getVars.row,\n
+        this.getVars.row + 1\n
+      )[0]);\n
+    }\n
+    else {\n
+      return this.dataSource[this.getVars.row] ? this.dataSource[this.getVars.row][this.getVars.prop] : null;\n
+    }\n
+  };\n
+\n
+  var copyableLookup = Handsontable.helper.cellMethodLookupFactory(\'copyable\', false);\n
+\n
+  /**\n
+   * Returns single value from the data array (intended for clipboard copy to an external application)\n
+   * @param {Number} row\n
+   * @param {Number} prop\n
+   * @return {String}\n
+   */\n
+  Handsontable.DataMap.prototype.getCopyable = function (row, prop) {\n
+    if (copyableLookup.call(this.instance, row, this.propToCol(prop))) {\n
+      return this.get(row, prop);\n
+    }\n
+    return \'\';\n
+  };\n
+\n
+  /**\n
+   * Saves single value to the data array\n
+   * @param {Number} row\n
+   * @param {Number} prop\n
+   * @param {String} value\n
+   * @param {String} [source] Optional. Source of hook runner.\n
+   */\n
+  Handsontable.DataMap.prototype.set = function (row, prop, value, source) {\n
+    this.setVars.row = row;\n
+    this.setVars.prop = prop;\n
+    this.setVars.value = value;\n
+    this.instance.PluginHooks.run(\'beforeSet\', this.setVars, source || "datamapGet");\n
+    if (typeof this.setVars.prop === \'string\' && this.setVars.prop.indexOf(\'.\') > -1) {\n
+      var sliced = this.setVars.prop.split(".");\n
+      var out = this.dataSource[this.setVars.row];\n
+      for (var i = 0, ilen = sliced.length - 1; i < ilen; i++) {\n
+        out = out[sliced[i]];\n
+      }\n
+      out[sliced[i]] = this.setVars.value;\n
+    }\n
+    else if (typeof this.setVars.prop === \'function\') {\n
+      /* see the `function` handler in `get` */\n
+      this.setVars.prop(this.dataSource.slice(\n
+        this.setVars.row,\n
+        this.setVars.row + 1\n
+      )[0], this.setVars.value);\n
+    }\n
+    else {\n
+      this.dataSource[this.setVars.row][this.setVars.prop] = this.setVars.value;\n
+    }\n
+  };\n
+\n
+  /**\n
+   * This ridiculous piece of code maps rows Id that are present in table data to those displayed for user.\n
+   * The trick is, the physical row id (stored in settings.data) is not necessary the same\n
+   * as the logical (displayed) row id (e.g. when sorting is applied).\n
+   */\n
+  Handsontable.DataMap.prototype.physicalRowsToLogical = function (index, amount) {\n
+    var totalRows = this.instance.countRows();\n
+    var physicRow = (totalRows + index) % totalRows;\n
+    var logicRows = [];\n
+    var rowsToRemove = amount;\n
+\n
+    while (physicRow < totalRows && rowsToRemove) {\n
+      this.get(physicRow, 0); //this performs an actual mapping and saves the result to getVars\n
+      logicRows.push(this.getVars.row);\n
+\n
+      rowsToRemove--;\n
+      physicRow++;\n
+    }\n
+\n
+    return logicRows;\n
+  };\n
+\n
+  /**\n
+   * Clears the data array\n
+   */\n
+  Handsontable.DataMap.prototype.clear = function () {\n
+    for (var r = 0; r < this.instance.countRows(); r++) {\n
+      for (var c = 0; c < this.instance.countCols(); c++) {\n
+        this.set(r, this.colToProp(c), \'\');\n
+      }\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Returns the data array\n
+   * @return {Array}\n
+   */\n
+  Handsontable.DataMap.prototype.getAll = function () {\n
+    return this.dataSource;\n
+  };\n
+\n
+  /**\n
+   * Returns data range as array\n
+   * @param {Object} start Start selection position\n
+   * @param {Object} end End selection position\n
+   * @param {Number} destination Destination of datamap.get\n
+   * @return {Array}\n
+   */\n
+  Handsontable.DataMap.prototype.getRange = function (start, end, destination) {\n
+    var r, rlen, c, clen, output = [], row;\n
+    var getFn = destination === this.DESTINATION_CLIPBOARD_GENERATOR ? this.getCopyable : this.get;\n
+    rlen = Math.max(start.row, end.row);\n
+    clen = Math.max(start.col, end.col);\n
+    for (r = Math.min(start.row, end.row); r <= rlen; r++) {\n
+      row = [];\n
+      for (c = Math.min(start.col, end.col); c <= clen; c++) {\n
+        row.push(getFn.call(this, r, this.colToProp(c)));\n
+      }\n
+      output.push(row);\n
+    }\n
+    return output;\n
+  };\n
+\n
+  /**\n
+   * Return data as text (tab separated columns)\n
+   * @param {Object} start (Optional) Start selection position\n
+   * @param {Object} end (Optional) End selection position\n
+   * @return {String}\n
+   */\n
+  Handsontable.DataMap.prototype.getText = function (start, end) {\n
+    return SheetClip.stringify(this.getRange(start, end, this.DESTINATION_RENDERER));\n
+  };\n
+\n
+  /**\n
+   * Return data as copyable text (tab separated columns intended for clipboard copy to an external application)\n
+   * @param {Object} start (Optional) Start selection position\n
+   * @param {Object} end (Optional) End selection position\n
+   * @return {String}\n
+   */\n
+  Handsontable.DataMap.prototype.getCopyableText = function (start, end) {\n
+    return SheetClip.stringify(this.getRange(start, end, this.DESTINATION_CLIPBOARD_GENERATOR));\n
+  };\n
+\n
+})(Handsontable);\n
+\n
+(function (Handsontable) {\n
+  \'use strict\';\n
+\n
+  /*\n
+    Adds appropriate CSS class to table cell, based on cellProperties\n
+   */\n
+  Handsontable.renderers.cellDecorator = function (instance, TD, row, col, prop, value, cellProperties) {\n
+    if (cellProperties.readOnly) {\n
+      instance.view.wt.wtDom.addClass(TD, cellProperties.readOnlyCellClassName);\n
+    }\n
+\n
+    if (cellProperties.valid === false && cellProperties.invalidCellClassName) {\n
+      instance.view.wt.wtDom.addClass(TD, cellProperties.invalidCellClassName);\n
+    }\n
+\n
+    if (!value && cellProperties.placeholder) {\n
+      instance.view.wt.wtDom.addClass(TD, cellProperties.placeholderCellClassName);\n
+    }\n
+  }\n
+\n
+})(Handsontable);\n
+/**\n
+ * Default text renderer\n
+ * @param {Object} instance Handsontable instance\n
+ * @param {Element} TD Table cell where to render\n
+ * @param {Number} row\n
+ * @param {Number} col\n
+ * @param {String|Number} prop Row object property name\n
+ * @param value Value to render (remember to escape unsafe HTML before inserting to DOM!)\n
+ * @param {Object} cellProperties Cell properites (shared by cell renderer and editor)\n
+ */\n
+(function (Handsontable) {\n
+  \'use strict\';\n
+\n
+  var TextRenderer = function (instance, TD, row, col, prop, value, cellProperties) {\n
+\n
+    Handsontable.renderers.cellDecorator.apply(this, arguments);\n
+\n
+    if (!value && cellProperties.placeholder) {\n
+      value = cellProperties.placeholder;\n
+    }\n
+\n
+    var escaped = Handsontable.helper.stringify(value);\n
+\n
+    if (cellProperties.rendererTemplate) {\n
+      instance.view.wt.wtDom.empty(TD);\n
+      var TEMPLATE = document.createElement(\'TEMPLATE\');\n
+      TEMPLATE.setAttribute(\'bind\', \'{{}}\');\n
+      TEMPLATE.innerHTML = cellProperties.rendererTemplate;\n
+      HTMLTemplateElement.decorate(TEMPLATE);\n
+      TEMPLATE.model = instance.getDataAtRow(row);\n
+      TD.appendChild(TEMPLATE);\n
+    }\n
+    else {\n
+      instance.view.wt.wtDom.fastInnerText(TD, escaped); //this is faster than innerHTML. See: https://github.com/warpech/jquery-handsontable/wiki/JavaScript-&-DOM-performance-tips\n
+    }\n
+\n
+  };\n
+\n
+  //Handsontable.TextRenderer = TextRenderer; //Left for backward compatibility\n
+  Handsontable.renderers.TextRenderer = TextRenderer;\n
+  Handsontable.renderers.registerRenderer(\'text\', TextRenderer);\n
+\n
+})(Handsontable);\n
+(function (Handsontable) {\n
+\n
+  var clonableWRAPPER = document.createElement(\'DIV\');\n
+  clonableWRAPPER.className = \'htAutocompleteWrapper\';\n
+\n
+  var clonableARROW = document.createElement(\'DIV\');\n
+  clonableARROW.className = \'htAutocompleteArrow\';\n
+  clonableARROW.appendChild(document.createTextNode(\'\\u25BC\'));\n
+//this is faster than innerHTML. See: https://github.com/warpech/jquery-handsontable/wiki/JavaScript-&-DOM-performance-tips\n
+\n
+  var wrapTdContentWithWrapper = function(TD, WRAPPER){\n
+    WRAPPER.innerHTML = TD.innerHTML;\n
+    Handsontable.Dom.empty(TD);\n
+    TD.appendChild(WRAPPER);\n
+  };\n
+\n
+  /**\n
+   * Autocomplete renderer\n
+   * @param {Object} instance Handsontable instance\n
+   * @param {Element} TD Table cell where to render\n
+   * @param {Number} row\n
+   * @param {Number} col\n
+   * @param {String|Number} prop Row object property name\n
+   * @param value Value to render (remember to escape unsafe HTML before inserting to DOM!)\n
+   * @param {Object} cellProperties Cell properites (shared by cell renderer and editor)\n
+   */\n
+  var AutocompleteRenderer = function (instance, TD, row, col, prop, value, cellProperties) {\n
+\n
+    var WRAPPER = clonableWRAPPER.cloneNode(true); //this is faster than createElement\n
+    var ARROW = clonableARROW.cloneNode(true); //this is faster than createElement\n
+\n
+    Handsontable.renderers.TextRenderer(instance, TD, row, col, prop, value, cellProperties);\n
+\n
+    TD.appendChild(ARROW);\n
+    Handsontable.Dom.addClass(TD, \'htAutocomplete\');\n
+\n
+\n
+    if (!TD.firstChild) { //http://jsperf.com/empty-node-if-needed\n
+      //otherwise empty fields appear borderless in demo/renderers.html (IE)\n
+      TD.appendChild(document.createTextNode(\'\\u00A0\')); //\\u00A0 equals &nbsp; for a text node\n
+      //this is faster than innerHTML. See: https://github.com/warpech/jquery-handsontable/wiki/JavaScript-&-DOM-performance-tips\n
+    }\n
+\n
+    if (!instance.acArrowListener) {\n
+      //not very elegant but easy and fast\n
+      instance.acArrowListener = function () {\n
+        instance.view.wt.getSetting(\'onCellDblClick\');\n
+      };\n
+\n
+      instance.rootElement.on(\'mousedown.htAutocompleteArrow\', \'.htAutocompleteArrow\', instance.acArrowListener); //this way we don\'t bind event listener to each arrow. We rely on propagation instead\n
+\n
+      //We need to unbind the listener after the table has been destroyed\n
+      instance.addHookOnce(\'afterDestroy\', function () {\n
+        this.rootElement.off(\'mousedown.htAutocompleteArrow\');\n
+      });\n
+\n
+    }\n
+  };\n
+\n
+  Handsontable.AutocompleteRenderer = AutocompleteRenderer;\n
+  Handsontable.renderers.AutocompleteRenderer = AutocompleteRenderer;\n
+  Handsontable.renderers.registerRenderer(\'autocomplete\', AutocompleteRenderer);\n
+})(Handsontable);\n
+/**\n
+ * Checkbox renderer\n
+ * @param {Object} instance Handsontable instance\n
+ * @param {Element} TD Table cell where to render\n
+ * @param {Number} row\n
+ * @param {Number} col\n
+ * @param {String|Number} prop Row object property name\n
+ * @param value Value to render (remember to escape unsafe HTML before inserting to DOM!)\n
+ * @param {Object} cellProperties Cell properites (shared by cell renderer and editor)\n
+ */\n
+(function (Handsontable) {\n
+\n
+  \'use strict\';\n
+\n
+  var clonableINPUT = document.createElement(\'INPUT\');\n
+  clonableINPUT.className = \'htCheckboxRendererInput\';\n
+  clonableINPUT.type = \'checkbox\';\n
+  clonableINPUT.setAttribute(\'autocomplete\', \'off\');\n
+\n
+  var CheckboxRenderer = function (instance, TD, row, col, prop, value, cellProperties) {\n
+\n
+    if (typeof cellProperties.checkedTemplate === "undefined") {\n
+      cellProperties.checkedTemplate = true;\n
+    }\n
+    if (typeof cellProperties.uncheckedTemplate === "undefined") {\n
+      cellProperties.uncheckedTemplate = false;\n
+    }\n
+\n
+    instance.view.wt.wtDom.empty(TD); //TODO identify under what circumstances this line can be removed\n
+\n
+    var INPUT = clonableINPUT.cloneNode(false); //this is faster than createElement\n
+\n
+    if (value === cellProperties.checkedTemplate || value === Handsontable.helper.stringify(cellProperties.checkedTemplate)) {\n
+      INPUT.checked = true;\n
+      TD.appendChild(INPUT);\n
+    }\n
+    else if (value === cellProperties.uncheckedTemplate || value === Handsontable.helper.stringify(cellProperties.uncheckedTemplate)) {\n
+      TD.appendChild(INPUT);\n
+    }\n
+    else if (value === null) { //default value\n
+      INPUT.className += \' noValue\';\n
+      TD.appendChild(INPUT);\n
+    }\n
+    else {\n
+      instance.view.wt.wtDom.fastInnerText(TD, \'#bad value#\'); //this is faster than innerHTML. See: https://github.com/warpech/jquery-handsontable/wiki/JavaScript-&-DOM-performance-tips\n
+    }\n
+\n
+    var $input = $(INPUT);\n
+\n
+    if (cellProperties.readOnly) {\n
+      $input.on(\'click\', function (event) {\n
+        event.preventDefault();\n
+      });\n
+    }\n
+    else {\n
+      $input.on(\'mousedown\', function (event) {\n
+        event.stopPropagation(); //otherwise can confuse cell mousedown handler\n
+      });\n
+\n
+      $input.on(\'mouseup\', function (event) {\n
+        event.stopPropagation(); //otherwise can confuse cell dblclick handler\n
+      });\n
+\n
+      $input.on(\'change\', function(){\n
+        if (this.checked) {\n
+          instance.setDataAtRowProp(row, prop, cellProperties.checkedTemplate);\n
+        }\n
+        else {\n
+          instance.setDataAtRowProp(row, prop, cellProperties.uncheckedTemplate);\n
+        }\n
+      });\n
+    }\n
+\n
+    if(!instance.CheckboxRenderer || !instance.CheckboxRenderer.beforeKeyDownHookBound){\n
+      instance.CheckboxRenderer = {\n
+        beforeKeyDownHookBound : true\n
+      };\n
+\n
+      instance.addHook(\'beforeKeyDown\', function(event){\n
+        if(event.keyCode == Handsontable.helper.keyCode.SPACE){\n
+\n
+          var selection = instance.getSelected();\n
+          var cell, checkbox, cellProperties;\n
+\n
+          var selStart = {\n
+            row: Math.min(selection[0], selection[2]),\n
+            col: Math.min(selection[1], selection[3])\n
+          };\n
+\n
+          var selEnd = {\n
+            row: Math.max(selection[0], selection[2]),\n
+            col: Math.max(selection[1], selection[3])\n
+          };\n
+\n
+          for(var row = selStart.row; row <= selEnd.row; row++ ){\n
+            for(var col = selEnd.col; col <= selEnd.col; col++){\n
+              cell = instance.getCell(row, col);\n
+              cellProperties = instance.getCellMeta(row, col);\n
+\n
+              checkbox = cell.querySelectorAll(\'input[type=checkbox]\');\n
+\n
+              if(checkbox.length > 0 && !cellProperties.readOnly){\n
+\n
+                if(!event.isImmediatePropagationStopped()){\n
+                  event.stopImmediatePropagation();\n
+                  event.preventDefault();\n
+                }\n
+\n
+                for(var i = 0, len = checkbox.length; i < len; i++){\n
+                  checkbox[i].checked = !checkbox[i].checked;\n
+                  $(checkbox[i]).trigger(\'change\');\n
+                }\n
+\n
+              }\n
+\n
+            }\n
+          }\n
+        }\n
+      });\n
+    }\n
+\n
+  };\n
+\n
+  Handsontable.CheckboxRenderer = CheckboxRenderer;\n
+  Handsontable.renderers.CheckboxRenderer = CheckboxRenderer;\n
+  Handsontable.renderers.registerRenderer(\'checkbox\', CheckboxRenderer);\n
+\n
+})(Handsontable);\n
+/**\n
+ * Numeric cell renderer\n
+ * @param {Object} instance Handsontable instance\n
+ * @param {Element} TD Table cell where to render\n
+ * @param {Number} row\n
+ * @param {Number} col\n
+ * @param {String|Number} prop Row object property name\n
+ * @param value Value to render (remember to escape unsafe HTML before inserting to DOM!)\n
+ * @param {Object} cellProperties Cell properites (shared by cell renderer and editor)\n
+ */\n
+(function (Handsontable) {\n
+\n
+  \'use strict\';\n
+\n
+  var NumericRenderer = function (instance, TD, row, col, prop, value, cellProperties) {\n
+    if (Handsontable.helper.isNumeric(value)) {\n
+      if (typeof cellProperties.language !== \'undefined\') {\n
+        numeral.language(cellProperties.language)\n
+      }\n
+      value = numeral(value).format(cellProperties.format || \'0\'); //docs: http://numeraljs.com/\n
+      instance.view.wt.wtDom.addClass(TD, \'htNumeric\');\n
+    }\n
+    Handsontable.renderers.TextRenderer(instance, TD, row, col, prop, value, cellProperties);\n
+  };\n
+\n
+  Handsontable.NumericRenderer = NumericRenderer; //Left for backward compatibility with versions prior 0.10.0\n
+  Handsontable.renderers.NumericRenderer = NumericRenderer;\n
+  Handsontable.renderers.registerRenderer(\'numeric\', NumericRenderer);\n
+\n
+})(Handsontable);\n
+(function(Handosntable){\n
+\n
+  \'use strict\';\n
+\n
+  var PasswordRenderer = function (instance, TD, row, col, prop, value, cellProperties) {\n
+    Handsontable.renderers.TextRenderer.apply(this, arguments);\n
+\n
+    value = TD.innerHTML;\n
+\n
+    var hash;\n
+    var hashLength = cellProperties.hashLength || value.length;\n
+    var hashSymbol = cellProperties.hashSymbol || \'*\';\n
+\n
+    for( hash = \'\'; hash.split(hashSymbol).length - 1 < hashLength; hash += hashSymbol);\n
+\n
+    instance.view.wt.wtDom.fastInnerHTML(TD, hash);\n
+\n
+  };\n
+\n
+  Handosntable.PasswordRenderer = PasswordRenderer;\n
+  Handosntable.renderers.PasswordRenderer = PasswordRenderer;\n
+  Handosntable.renderers.registerRenderer(\'password\', PasswordRenderer);\n
+\n
+})(Handsontable);\n
+(function (Handsontable) {\n
+\n
+  function HtmlRenderer(instance, TD, row, col, prop, value, cellProperties){\n
+\n
+    Handsontable.renderers.cellDecorator.apply(this, arguments);\n
+\n
+    Handsontable.Dom.fastInnerHTML(TD, value);\n
+  }\n
+\n
+  Handsontable.renderers.registerRenderer(\'html\', HtmlRenderer);\n
+  Handsontable.renderers.HtmlRenderer = HtmlRenderer;\n
+\n
+})(Handsontable);\n
+\n
+(function (Handsontable) {\n
+  \'use strict\';\n
+\n
+  Handsontable.EditorState = {\n
+    VIRGIN: \'STATE_VIRGIN\', //before editing\n
+    EDITING: \'STATE_EDITING\',\n
+    WAITING: \'STATE_WAITING\', //waiting for async validation\n
+    FINISHED: \'STATE_FINISHED\'\n
+  };\n
+\n
+  function BaseEditor(instance) {\n
+    this.instance = instance;\n
+    this.state = Handsontable.EditorState.VIRGIN;\n
+\n
+    this._opened = false;\n
+    this._closeCallback = null;\n
+\n
+    this.init();\n
+  }\n
+\n
+  BaseEditor.prototype._fireCallbacks = function(result) {\n
+    if(this._closeCallback){\n
+      this._closeCallback(result);\n
+      this._closeCallback = null;\n
+    }\n
+\n
+  }\n
+\n
+  BaseEditor.prototype.init = function(){};\n
+\n
+  BaseEditor.prototype.getValue = function(){\n
+    throw Error(\'Editor getValue() method unimplemented\');\n
+  };\n
+\n
+  BaseEditor.prototype.setValue = function(newValue){\n
+    throw Error(\'Editor setValue() method unimplemented\');\n
+  };\n
+\n
+  BaseEditor.prototype.open = function(){\n
+    throw Error(\'Editor open() method unimplemented\');\n
+  };\n
+\n
+  BaseEditor.prototype.close = function(){\n
+    throw Error(\'Editor close() method unimplemented\');\n
+  };\n
+\n
+  BaseEditor.prototype.prepare = function(row, col, prop, td, originalValue, cellProperties){\n
+    this.TD = td;\n
+    this.row = row;\n
+    this.col = col;\n
+    this.prop = prop;\n
+    this.originalValue = originalValue;\n
+    this.cellProperties = cellProperties;\n
+\n
+    this.state = Handsontable.EditorState.VIRGIN;\n
+  };\n
+\n
+  BaseEditor.prototype.extend = function(){\n
+    var baseClass = this.constructor;\n
+    function Editor(){\n
+      baseClass.apply(this, arguments);\n
+    }\n
+\n
+    function inherit(Child, Parent){\n
+      function Bridge() {\n
+      }\n
+\n
+      Bridge.prototype = Parent.prototype;\n
+      Child.prototype = new Bridge();\n
+      Child.prototype.constructor = Child;\n
+      return Child;\n
+    }\n
+\n
+    return inherit(Editor, baseClass);\n
+  };\n
+\n
+  BaseEditor.prototype.saveValue = function (val, ctrlDown) {\n
+    if (ctrlDown) { //if ctrl+enter and multiple cells selected, behave like Excel (finish editing and apply to all cells)\n
+      var sel = this.instance.getSelected();\n
+      this.instance.populateFromArray(sel[0], sel[1], val, sel[2], sel[3], \'edit\');\n
+    }\n
+    else {\n
+      this.instance.populateFromArray(this.row, this.col, val, null, null, \'edit\');\n
+    }\n
+  };\n
+\n
+  BaseEditor.prototype.beginEditing = function(initialValue){\n
+    if (this.state != Handsontable.EditorState.VIRGIN) {\n
+      return;\n
+    }\n
+\n
+    this.instance.view.scrollViewport({row: this.row, col: this.col});\n
+    this.instance.view.render();\n
+\n
+    this.state = Handsontable.EditorState.EDITING;\n
+\n
+    initialValue = typeof initialValue == \'string\' ? initialValue : this.originalValue;\n
+\n
+    this.setValue(Handsontable.helper.stringify(initialValue));\n
+\n
+    this.open();\n
+    this._opened = true;\n
+    this.focus();\n
+\n
+    this.instance.view.render(); //only rerender the selections (FillHandle should disappear when beginediting is triggered)\n
+  };\n
+\n
+  BaseEditor.prototype.finishEditing = function (restoreOriginalValue, ctrlDown, callback) {\n
+\n
+    if (callback) {\n
+      var previousCloseCallback = this._closeCallback;\n
+      this._closeCallback = function (result) {\n
+        if(previousCloseCallback){\n
+          previousCloseCallback(result);\n
+        }\n
+\n
+        callback(result);\n
+      };\n
+    }\n
+\n
+    if (this.isWaiting()) {\n
+      return;\n
+    }\n
+\n
+    if (this.state == Handsontable.EditorState.VIRGIN) {\n
+      var that = this;\n
+      setTimeout(function () {\n
+        that._fireCallbacks(true);\n
+      });\n
+      return;\n
+    }\n
+\n
+    if (this.state == Handsontable.EditorState.EDITING) {\n
+\n
+      if (restoreOriginalValue) {\n
+\n
+        this.cancelChanges();\n
+        return;\n
+\n
+      }\n
+\n
+\n
+      var val = [\n
+        [String.prototype.trim.call(this.getValue())] //String.prototype.trim is defined in Walkontable polyfill.js\n
+      ];\n
+\n
+      this.state = Handsontable.EditorState.WAITING;\n
+\n
+      this.saveValue(val, ctrlDown);\n
+\n
+      if(this.instance.getCellValidator(this.cellProperties)){\n
+        var that = this;\n
+        this.instance.addHookOnce(\'afterValidate\', function (result) {\n
+          that.state = Handsontable.EditorState.FINISHED;\n
+          that.discardEditor(result);\n
+        });\n
+      } else {\n
+        this.state = Handsontable.EditorState.FINISHED;\n
+        this.discardEditor(true);\n
+      }\n
+\n
+    }\n
+  };\n
+\n
+  BaseEditor.prototype.cancelChanges = function () {\n
+    this.state = Handsontable.EditorState.FINISHED;\n
+    this.discardEditor();\n
+  };\n
+\n
+  BaseEditor.prototype.discardEditor = function (result) {\n
+    if (this.state !== Handsontable.EditorState.FINISHED) {\n
+      return;\n
+    }\n
+\n
+    if (result === false && this.cellProperties.allowInvalid !== true) { //validator was defined and failed\n
+\n
+      this.instance.selectCell(this.row, this.col);\n
+      this.focus();\n
+\n
+      this.state = Handsontable.EditorState.EDITING;\n
+\n
+      this._fireCallbacks(false);\n
+    }\n
+    else {\n
+      this.close();\n
+      this._opened = false;\n
+\n
+      this.state = Handsontable.EditorState.VIRGIN;\n
+\n
+      this._fireCallbacks(true);\n
+    }\n
+\n
+  };\n
+\n
+  BaseEditor.prototype.isOpened = function(){\n
+    return this._opened;\n
+  };\n
+\n
+  BaseEditor.prototype.isWaiting = function () {\n
+    return this.state === Handsontable.EditorState.WAITING;\n
+  };\n
+\n
+  Handsontable.editors.BaseEditor = BaseEditor;\n
+\n
+})(Handsontable);\n
+\n
+(function(Handsontable){\n
+  var TextEditor = Handsontable.editors.BaseEditor.prototype.extend();\n
+\n
+  TextEditor.prototype.init = function(){\n
+    this.createElements();\n
+    this.bindEvents();\n
+  };\n
+\n
+  TextEditor.prototype.getValue = function(){\n
+    return this.TEXTAREA.value\n
+  };\n
+\n
+  TextEditor.prototype.setValue = function(newValue){\n
+    this.TEXTAREA.value = newValue;\n
+  };\n
+\n
+  var onBeforeKeyDown =  function onBeforeKeyDown(event){\n
+\n
+    var instance = this;\n
+    var that = instance.getActiveEditor();\n
+\n
+    var keyCodes = Handsontable.helper.keyCode;\n
+    var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)\n
+\n
+\n
+    //Process only events that have been fired in the editor\n
+    if (event.target !== that.TEXTAREA || event.isImmediatePropagationStopped()){\n
+      return;\n
+    }\n
+\n
+    if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {\n
+      //when CTRL or its equivalent is pressed and cell is edited, don\'t prepare selectable text in textarea\n
+      event.stopImmediatePropagation();\n
+      return;\n
+    }\n
+\n
+    switch (event.keyCode) {\n
+      case keyCodes.ARROW_RIGHT:\n
+        if (that.wtDom.getCaretPosition(that.TEXTAREA) !== that.TEXTAREA.value.length) {\n
+          event.stopImmediatePropagation();\n
+        }\n
+        break;\n
+\n
+      case keyCodes.ARROW_LEFT: /* arrow left */\n
+        if (that.wtDom.getCaretPosition(that.TEXTAREA) !== 0) {\n
+          event.stopImmediatePropagation();\n
+        }\n
+        break;\n
+\n
+      case keyCodes.ENTER:\n
+        var selected = that.instance.getSelected();\n
+        var isMultipleSelection = !(selected[0] === selected[2] && selected[1] === selected[3]);\n
+        if ((ctrlDown && !isMultipleSelection) || event.altKey) { //if ctrl+enter or alt+enter, add new line\n
+          if(that.isOpened()){\n
+            that.setValue(that.getValue() + \'\\n\');\n
+            that.focus();\n
+          } else {\n
+            that.beginEditing(that.originalValue + \'\\n\')\n
+          }\n
+          event.stopImmediatePropagation();\n
+        }\n
+        event.preventDefault(); //don\'t add newline to field\n
+        break;\n
+\n
+      case keyCodes.A:\n
+      case keyCodes.X:\n
+      case keyCodes.C:\n
+      case keyCodes.V:\n
+        if(ctrlDown){\n
+          event.stopImmediatePropagation(); //CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)\n
+          break;\n
+        }\n
+      case keyCodes.BACKSPACE:\n
+      case keyCodes.DELETE:\n
+      case keyCodes.HOME:\n
+      case keyCodes.END:\n
+        event.stopImmediatePropagation(); //backspace, delete, home, end should only work locally when cell is edited (not in table context)\n
+        break;\n
+    }\n
+\n
+  };\n
+\n
+  TextEditor.prototype.open = function(){\n
+    this.refreshDimensions(); //need it instantly, to prevent https://github.com/warpech/jquery-handsontable/issues/348\n
+\n
+    this.instance.addHook(\'beforeKeyDown\', onBeforeKeyDown);\n
+  };\n
+\n
+  TextEditor.prototype.close = function(){\n
+    this.textareaParentStyle.display = \'none\';\n
+\n
+    if (document.activeElement === this.TEXTAREA) {\n
+      this.instance.listen(); //don\'t refocus the table if user focused some cell outside of HT on purpose\n
+    }\n
+\n
+    this.instance.removeHook(\'beforeKeyDown\', onBeforeKeyDown);\n
+  };\n
+\n
+  TextEditor.prototype.focus = function(){\n
+    this.TEXTAREA.focus();\n
+    this.wtDom.setCaretPosition(this.TEXTAREA, this.TEXTAREA.value.length);\n
+  };\n
+\n
+  TextEditor.prototype.createElements = function () {\n
+    this.$body = $(document.body);\n
+    this.wtDom = new WalkontableDom();\n
+\n
+    this.TEXTAREA = document.createElement(\'TEXTAREA\');\n
+    this.$textarea = $(this.TEXTAREA);\n
+\n
+    this.wtDom.addClass(this.TEXTAREA, \'handsontableInput\');\n
+\n
+    this.textareaStyle = this.TEXTAREA.style;\n
+    this.textareaStyle.width = 0;\n
+    this.textareaStyle.height = 0;\n
+\n
+    this.TEXTAREA_PARENT = document.createElement(\'DIV\');\n
+    this.wtDom.addClass(this.TEXTAREA_PARENT, \'handsontableInputHolder\');\n
+\n
+    this.textareaParentStyle = this.TEXTAREA_PARENT.style;\n
+    this.textareaParentStyle.top = 0;\n
+    this.textareaParentStyle.left = 0;\n
+    this.textareaParentStyle.display = \'none\';\n
+\n
+    this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);\n
+\n
+    this.instance.rootElement[0].appendChild(this.TEXTAREA_PARENT);\n
+\n
+    var that = this;\n
+    Handsontable.PluginHooks.add(\'afterRender\', function () {\n
+      that.instance.registerTimeout(\'refresh_editor_dimensions\', function () {\n
+        that.refreshDimensions();\n
+      }, 0);\n
+    });\n
+  };\n
+\n
+  TextEditor.prototype.refreshDimensions = function () {\n
+    if (this.state !== Handsontable.EditorState.EDITING) {\n
+      return;\n
+    }\n
+\n
+    ///start prepare textarea position\n
+    this.TD = this.instance.getCell(this.row, this.col);\n
+    if (!this.TD) {\n
+      //TD is outside of the viewport. Otherwise throws exception when scrolling the table while a cell is edited\n
+      return;\n
+    }\n
+    var $td = $(this.TD); //because old td may have been scrolled out with scrollViewport\n
+    var currentOffset = this.wtDom.offset(this.TD);\n
+    var containerOffset = this.wtDom.offset(this.instance.rootElement[0]);\n
+    var scrollTop = this.instance.rootElement.scrollTop();\n
+    var scrollLeft = this.instance.rootElement.scrollLeft();\n
+    var editTop = currentOffset.top - containerOffset.top + scrollTop - 1;\n
+    var editLeft = currentOffset.left - containerOffset.left + scrollLeft - 1;\n
+\n
+    var settings = this.instance.getSettings();\n
+    var rowHeadersCount = settings.rowHeaders === false ? 0 : 1;\n
+    var colHeadersCount = settings.colHeaders === false ? 0 : 1;\n
+\n
+    if (editTop < 0) {\n
+      editTop = 0;\n
+    }\n
+    if (editLeft < 0) {\n
+      editLeft = 0;\n
+    }\n
+\n
+    if (rowHeadersCount > 0 && parseInt($td.css(\'border-top-width\'), 10) > 0) {\n
+      editTop += 1;\n
+    }\n
+    if (colHeadersCount > 0 && parseInt($td.css(\'border-left-width\'), 10) > 0) {\n
+      editLeft += 1;\n
+    }\n
+\n
+    this.textareaParentStyle.top = editTop + \'px\';\n
+    this.textareaParentStyle.left = editLeft + \'px\';\n
+    ///end prepare textarea position\n
+\n
+    var width = $td.width()\n
+      , maxWidth = this.instance.view.maximumVisibleElementWidth(editLeft) - 10 //10 is TEXTAREAs border and padding\n
+      , height = $td.outerHeight() - 4\n
+      , maxHeight = this.instance.view.maximumVisibleElementHeight(editTop) - 5; //10 is TEXTAREAs border and padding\n
+\n
+    if (parseInt($td.css(\'border-top-width\'), 10) > 0) {\n
+      height -= 1;\n
+    }\n
+    if (parseInt($td.css(\'border-left-width\'), 10) > 0) {\n
+      if (rowHeadersCount > 0) {\n
+        width -= 1;\n
+      }\n
+    }\n
+\n
+    //in future may change to pure JS http://stackoverflow.com/questions/454202/creating-a-textarea-with-auto-resize\n
+    this.$textarea.autoResize({\n
+      minHeight: Math.min(height, maxHeight),\n
+      maxHeight: maxHeight, //TEXTAREA should never be wider than visible part of the viewport (should not cover the scrollbar)\n
+      minWidth: Math.min(width, maxWidth),\n
+      maxWidth: maxWidth, //TEXTAREA should never be wider than visible part of the viewport (should not cover the scrollbar)\n
+      animate: false,\n
+      extraSpace: 0\n
+    });\n
+\n
+    this.textareaParentStyle.display = \'block\';\n
+  };\n
+\n
+  TextEditor.prototype.bindEvents = function () {\n
+    this.$textarea.on(\'cut.editor\', function (event) {\n
+      event.stopPropagation();\n
+    });\n
+\n
+    this.$textarea.on(\'paste.editor\', function (event) {\n
+      event.stopPropagation();\n
+    });\n
+  };\n
+\n
+  Handsontable.editors.TextEditor = TextEditor;\n
+  Handsontable.editors.registerEditor(\'text\', Handsontable.editors.TextEditor);\n
+\n
+})(Handsontable);\n
+\n
+(function(Handsontable){\n
+\n
+  //Blank editor, because all the work is done by renderer\n
+  var CheckboxEditor = Handsontable.editors.BaseEditor.prototype.extend();\n
+\n
+  CheckboxEditor.prototype.beginEditing = function () {\n
+    var checkbox = this.TD.querySelector(\'input[type="checkbox"]\');\n
+\n
+    if (checkbox) {\n
+      $(checkbox).trigger(\'click\');\n
+    }\n
+\n
+  };\n
+\n
+  CheckboxEditor.prototype.finishEditing = function () {};\n
+\n
+  CheckboxEditor.prototype.init = function () {};\n
+  CheckboxEditor.prototype.open = function () {};\n
+  CheckboxEditor.prototype.close = function () {};\n
+  CheckboxEditor.prototype.getValue = function () {};\n
+  CheckboxEditor.prototype.setValue = function () {};\n
+  CheckboxEditor.prototype.focus = function () {};\n
+\n
+  Handsontable.editors.CheckboxEditor = CheckboxEditor;\n
+  Handsontable.editors.registerEditor(\'checkbox\', CheckboxEditor);\n
+\n
+})(Handsontable);\n
+\n
+\n
+(function (Handsontable) {\n
+  var DateEditor = Handsontable.editors.TextEditor.prototype.extend();\n
+\n
+  DateEditor.prototype.init = function () {\n
+    if (!$.datepicker) {\n
+      throw new Error("jQuery UI Datepicker dependency not found. Did you forget to include jquery-ui.custom.js or its substitute?");\n
+    }\n
+\n
+    Handsontable.editors.TextEditor.prototype.init.apply(this, arguments);\n
+\n
+    this.isCellEdited = false;\n
+    var that = this;\n
+\n
+    this.instance.addHook(\'afterDestroy\', function () {\n
+      that.destroyElements();\n
+    })\n
+\n
+  };\n
+\n
+  DateEditor.prototype.createElements = function () {\n
+    Handsontable.editors.TextEditor.prototype.createElements.apply(this, arguments);\n
+\n
+    this.datePicker = document.createElement(\'DIV\');\n
+    this.instance.view.wt.wtDom.addClass(this.datePicker, \'htDatepickerHolder\');\n
+    this.datePickerStyle = this.datePicker.style;\n
+    this.datePickerStyle.position = \'absolute\';\n
+    this.datePickerStyle.top = 0;\n
+    this.datePickerStyle.left = 0;\n
+    this.datePickerStyle.zIndex = 99;\n
+    document.body.appendChild(this.datePicker);\n
+    this.$datePicker = $(this.datePicker);\n
+\n
+    var that = this;\n
+    var defaultOptions = {\n
+      dateFormat: "yy-mm-dd",\n
+      showButtonPanel: true,\n
+      changeMonth: true,\n
+      changeYear: true,\n
+      onSelect: function (dateStr) {\n
+        that.setValue(dateStr);\n
+        that.finishEditing(false);\n
+      }\n
+    };\n
+    this.$datePicker.datepicker(defaultOptions);\n
+\n
+    /**\n
+     * Prevent recognizing clicking on jQuery Datepicker as clicking outside of table\n
+     */\n
+    this.$datePicker.on(\'mousedown\', function (event) {\n
+      event.stopPropagation();\n
+    });\n
+\n
+    this.hideDatepicker();\n
+  };\n
+\n
+  DateEditor.prototype.destroyElements = function () {\n
+    this.$datePicker.datepicker(\'destroy\');\n
+    this.$datePicker.remove();\n
+  };\n
+\n
+  DateEditor.prototype.open = function () {\n
+    Handsontable.editors.TextEditor.prototype.open.call(this);\n
+    this.showDatepicker();\n
+  };\n
+\n
+  DateEditor.prototype.finishEditing = function (isCancelled, ctrlDown) {\n
+    this.hideDatepicker();\n
+    Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments);\n
+  };\n
+\n
+  DateEditor.prototype.showDatepicker = function () {\n
+    var $td = $(this.TD);\n
+    var offset = $td.offset();\n
+    this.datePickerStyle.top = (offset.top + $td.height()) + \'px\';\n
+    this.datePickerStyle.left = offset.left + \'px\';\n
+\n
+    var dateOptions = {\n
+      defaultDate: this.originalValue || void 0\n
+    };\n
+    $.extend(dateOptions, this.cellProperties);\n
+    this.$datePicker.datepicker("option", dateOptions);\n
+    if (this.originalValue) {\n
+      this.$datePicker.datepicker("setDate", this.originalValue);\n
+    }\n
+    this.datePickerStyle.display = \'block\';\n
+  };\n
+\n
+  DateEditor.prototype.hideDatepicker = function () {\n
+    this.datePickerStyle.display = \'none\';\n
+  };\n
+\n
+\n
+  Handsontable.editors.DateEditor = DateEditor;\n
+  Handsontable.editors.registerEditor(\'date\', DateEditor);\n
+})(Handsontable);\n
+/**\n
+ * This is inception. Using Handsontable as Handsontable editor\n
+ */\n
+(function (Handsontable) {\n
+  "use strict";\n
+\n
+  var HandsontableEditor = Handsontable.editors.TextEditor.prototype.extend();\n
+\n
+  HandsontableEditor.prototype.createElements = function () {\n
+    Handsontable.editors.TextEditor.prototype.createElements.apply(this, arguments);\n
+\n
+    var DIV = document.createElement(\'DIV\');\n
+    DIV.className = \'handsontableEditor\';\n
+    this.TEXTAREA_PARENT.appendChild(DIV);\n
+\n
+    this.$htContainer = $(DIV);\n
+    this.$htContainer.handsontable();\n
+  };\n
+\n
+  HandsontableEditor.prototype.prepare = function (td, row, col, prop, value, cellProperties) {\n
+\n
+    Handsontable.editors.TextEditor.prototype.prepare.apply(this, arguments);\n
+\n
+    var parent = this;\n
+\n
+    var options = {\n
+      startRows: 0,\n
+      startCols: 0,\n
+      minRows: 0,\n
+      minCols: 0,\n
+      className: \'listbox\',\n
+      copyPaste: false,\n
+      cells: function () {\n
+        return {\n
+          readOnly: true\n
+        }\n
+      },\n
+      fillHandle: false,\n
+      afterOnCellMouseDown: function () {\n
+        var value = this.getValue();\n
+        if (value !== void 0) { //if the value is undefined then it means we don\'t want to set the value\n
+          parent.setValue(value);\n
+        }\n
+        parent.instance.destroyEditor();\n
+      },\n
+      beforeOnKeyDown: function (event) {\n
+        var instance = this;\n
+\n
+        switch (event.keyCode) {\n
+          case Handsontable.helper.keyCode.ESCAPE:\n
+            parent.instance.destroyEditor(true);\n
+            event.stopImmediatePropagation();\n
+            event.preventDefault();\n
+            break;\n
+\n
+          case Handsontable.helper.keyCode.ENTER: //enter\n
+            var sel = instance.getSelected();\n
+            var value = this.getDataAtCell(sel[0], sel[1]);\n
+            if (value !== void 0) { //if the value is undefined then it means we don\'t want to set the value\n
+              parent.setValue(value);\n
+            }\n
+            parent.instance.destroyEditor();\n
+            break;\n
+\n
+          case Handsontable.helper.keyCode.ARROW_UP:\n
+            if (instance.getSelected() && instance.getSelected()[0] == 0 && !parent.cellProperties.strict){\n
+              instance.deselectCell();\n
+              parent.instance.listen();\n
+              parent.focus();\n
+              event.preventDefault();\n
+              event.stopImmediatePropagation();\n
+            }\n
+            break;\n
+        }\n
+      }\n
+    };\n
+\n
+    if (this.cellProperties.handsontable) {\n
+      options = $.extend(options, cellProperties.handsontable);\n
+    }\n
+    this.$htContainer.handsontable(\'destroy\');\n
+    this.$htContainer.handsontable(options);\n
+  };\n
+\n
+  var onBeforeKeyDown = function (event) {\n
+\n
+    if (event.isImmediatePropagationStopped()) {\n
+      return;\n
+    }\n
+\n
+    var editor = this.getActiveEditor();\n
+    var innerHOT = editor.$htContainer.handsontable(\'getInstance\');\n
+\n
+    if (event.keyCode == Handsontable.helper.keyCode.ARROW_DOWN) {\n
+\n
+      if (!innerHOT.getSelected()){\n
+        innerHOT.selectCell(0, 0);\n
+      } else {\n
+        var selectedRow = innerHOT.getSelected()[0];\n
+        var rowToSelect = selectedRow < innerHOT.countRows() - 1 ? selectedRow + 1 : selectedRow;\n
+\n
+        innerHOT.selectCell(rowToSelect, 0);\n
+      }\n
+\n
+      event.preventDefault();\n
+      event.stopImmediatePropagation();\n
+    }\n
+\n
+  };\n
+\n
+  HandsontableEditor.prototype.open = function () {\n
+\n
+    this.instance.addHook(\'beforeKeyDown\', onBeforeKeyDown);\n
+\n
+    Handsontable.editors.TextEditor.prototype.open.apply(this, arguments);\n
+\n
+    this.$htContainer.handsontable(\'render\');\n
+\n
+    if (this.cellProperties.strict) {\n
+      this.$htContainer.handsontable(\'selectCell\', 0, 0);\n
+      this.$textarea[0].style.visibility = \'hidden\';\n
+    } else {\n
+      this.$htContainer.handsontable(\'deselectCell\');\n
+      this.$textarea[0].style.visibility = \'visible\';\n
+    }\n
+\n
+    this.wtDom.setCaretPosition(this.$textarea[0], 0, this.$textarea[0].value.length);\n
+\n
+  };\n
+\n
+  HandsontableEditor.prototype.close = function () {\n
+\n
+    this.instance.removeHook(\'beforeKeyDown\', onBeforeKeyDown);\n
+    this.instance.listen();\n
+\n
+    Handsontable.editors.TextEditor.prototype.close.apply(this, arguments);\n
+  };\n
+\n
+  HandsontableEditor.prototype.focus = function () {\n
+\n
+    this.instance.listen();\n
+\n
+    Handsontable.editors.TextEditor.prototype.focus.apply(this, arguments);\n
+  };\n
+\n
+  HandsontableEditor.prototype.beginEditing = function (initialValue) {\n
+    var onBeginEditing = this.instance.getSettings().onBeginEditing;\n
+    if (onBeginEditing && onBeginEditing() === false) {\n
+      return;\n
+    }\n
+\n
+    Handsontable.editors.TextEditor.prototype.beginEditing.apply(this, arguments);\n
+\n
+  };\n
+\n
+  HandsontableEditor.prototype.finishEditing = function (isCancelled, ctrlDown) {\n
+    if (this.$htContainer.handsontable(\'isListening\')) { //if focus is still in the HOT editor\n
+      this.instance.listen(); //return the focus to the parent HOT instance\n
+    }\n
+\n
+    if (this.$htContainer.handsontable(\'getSelected\')) {\n
+      var value = this.$htContainer.handsontable(\'getInstance\').getValue();\n
+      if (value !== void 0) { //if the value is undefined then it means we don\'t want to set the value\n
+        this.setValue(value);\n
+      }\n
+    }\n
+\n
+    return Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments);\n
+  };\n
+\n
+  Handsontable.editors.HandsontableEditor = HandsontableEditor;\n
+  Handsontable.editors.registerEditor(\'handsontable\', HandsontableEditor);\n
+\n
+})(Handsontable);\n
+\n
+\n
+\n
+\n
+\n
+\n
+(function (Handsontable) {\n
+  var AutocompleteEditor = Handsontable.editors.HandsontableEditor.prototype.extend();\n
+\n
+  AutocompleteEditor.prototype.init = function () {\n
+    Handsontable.editors.HandsontableEditor.prototype.init.apply(this, arguments);\n
+\n
+    this.query = null;\n
+    this.choices = [];\n
+  };\n
+\n
+  AutocompleteEditor.prototype.createElements = function(){\n
+    Handsontable.editors.HandsontableEditor.prototype.createElements.apply(this, arguments);\n
+\n
+    this.$htContainer.addClass(\'autocompleteEditor\');\n
+\n
+  };\n
+\n
+  AutocompleteEditor.prototype.bindEvents = function(){\n
+\n
+    var that = this;\n
+    this.$textarea.on(\'keydown.autocompleteEditor\', function(event){\n
+      if(!Handsontable.helper.isMetaKey(event.keyCode) || [Handsontable.helper.keyCode.BACKSPACE, Handsontable.helper.keyCode.DELETE].indexOf(event.keyCode) != -1){\n
+        setTimeout(function () {\n
+          that.queryChoices(that.$textarea.val());\n
+        });\n
+      } else if (event.keyCode == Handsontable.helper.keyCode.ENTER && that.cellProperties.strict !== true){\n
+        that.$htContainer.handsontable(\'deselectCell\');\n
+      }\n
+\n
+    });\n
+\n
+    this.$htContainer.on(\'mouseleave\', function () {\n
+      if(that.cellProperties.strict === true){\n
+        that.highlightBestMatchingChoice();\n
+      }\n
+    });\n
+\n
+    this.$htContainer.on(\'mouseenter\', function () {\n
+      that.$htContainer.handsontable(\'deselectCell\');\n
+    });\n
+\n
+    Handsontable.editors.HandsontableEditor.prototype.bindEvents.apply(this, arguments);\n
+\n
+  };\n
+\n
+  var onBeforeKeyDownInner;\n
+\n
+  AutocompleteEditor.prototype.open = function () {\n
+\n
+    Handsontable.editors.HandsontableEditor.prototype.open.apply(this, arguments);\n
+\n
+    this.$textarea[0].style.visibility = \'visible\';\n
+    this.focus();\n
+\n
+    var choicesListHot =  this.$htContainer.handsontable(\'getInstance\');\n
+    var that = this;\n
+    choicesListHot.updateSettings({\n
+      \'colWidths\': [this.wtDom.outerWidth(this.TEXTAREA) - 2],\n
+      afterRenderer: function (TD, row, col, prop, value) {\n
+        var caseSensitive = this.getCellMeta(row, col).filteringCaseSensitive === true;\n
+        var indexOfMatch =  caseSensitive ? value.indexOf(this.query) : value.toLowerCase().indexOf(that.query.toLowerCase());\n
+\n
+        if(indexOfMatch != -1){\n
+          var match = value.substr(indexOfMatch, that.query.length);\n
+          TD.innerHTML = value.replace(match, \'<strong>\' + match + \'</strong>\');\n
+        }\n
+      }\n
+    });\n
+\n
+    onBeforeKeyDownInner = function (event) {\n
+      var instance = this;\n
+\n
+      if (event.keyCode == Handsontable.helper.keyCode.ARROW_UP){\n
+        if (instance.getSelected() && instance.getSelected()[0] == 0){\n
+\n
+          if(!parent.cellProperties.strict){\n
+            instance.deselectCell();\n
+          }\n
+\n
+          parent.instance.listen();\n
+          parent.focus();\n
+          event.preventDefault();\n
+          event.stopImmediatePropagation();\n
+        }\n
+      }\n
+\n
+    };\n
+\n
+    choicesListHot.addHook(\'beforeKeyDown\', onBeforeKeyDownInner);\n
+\n
+    this.queryChoices(this.TEXTAREA.value);\n
+\n
+\n
+  };\n
+\n
+  AutocompleteEditor.prototype.close = function () {\n
+\n
+    this.$htContainer.handsontable(\'getInstance\').removeHook(\'beforeKeyDown\', onBeforeKeyDownInner);\n
+\n
+    Handsontable.editors.HandsontableEditor.prototype.close.apply(this, arguments);\n
+  };\n
+\n
+  AutocompleteEditor.prototype.queryChoices = function(query){\n
+\n
+    this.query = query;\n
+\n
+    if (typeof this.cellProperties.source == \'function\'){\n
+      var that = this;\n
+\n
+      this.cellProperties.source(query, function(choices){\n
+        that.updateChoicesList(choices)\n
+      });\n
+\n
+    } else if (Handsontable.helper.isArray(this.cellProperties.source)) {\n
+\n
+      var choices;\n
+\n
+      if(!query || this.cellProperties.filter === false){\n
+        choices = this.cellProperties.source;\n
+      } else {\n
+\n
+        var filteringCaseSensitive = this.cellProperties.filteringCaseSensitive === true;\n
+        var lowerCaseQuery = query.toLowerCase();\n
+\n
+        choices = this.cellProperties.source.filter(function(choice){\n
+\n
+          if (filteringCaseSensitive) {\n
+            return choice.indexOf(query) != -1;\n
+          } else {\n
+            return choice.toLowerCase().indexOf(lowerCaseQuery) != -1;\n
+          }\n
+\n
+        });\n
+      }\n
+\n
+      this.updateChoicesList(choices)\n
+\n
+    } else {\n
+      this.updateChoicesList([]);\n
+    }\n
+\n
+  };\n
+\n
+  AutocompleteEditor.prototype.updateChoicesList = function (choices) {\n
+\n
+     this.choices = choices;\n
+\n
+    this.$htContainer.handsontable(\'loadData\', Handsontable.helper.pivot([choices]));\n
+\n
+    if(this.cellProperties.strict === true){\n
+      this.highlightBestMatchingChoice();\n
+    }\n
+\n
+    this.focus();\n
+  };\n
+\n
+  AutocompleteEditor.prototype.highlightBestMatchingChoice = function () {\n
+    var bestMatchingChoice = this.findBestMatchingChoice();\n
+\n
+    if ( typeof bestMatchingChoice == \'undefined\' && this.cellProperties.allowInvalid === false){\n
+      bestMatchingChoice = 0;\n
+    }\n
+\n
+    if(typeof bestMatchingChoice == \'undefined\'){\n
+      this.$htContainer.handsontable(\'deselectCell\');\n
+    } else {\n
+      this.$htContainer.handsontable(\'selectCell\', bestMatchingChoice, 0);\n
+    }\n
+\n
+  };\n
+\n
+  AutocompleteEditor.prototype.findBestMatchingChoice = function(){\n
+    var bestMatch = {};\n
+    var valueLength = this.getValue().length;\n
+    var currentItem;\n
+    var indexOfValue;\n
+    var charsLeft;\n
+\n
+\n
+    for(var i = 0, len = this.choices.length; i < len; i++){\n
+      currentItem = this.choices[i];\n
+\n
+      if(valueLength > 0){\n
+        indexOfValue = currentItem.indexOf(this.getValue())\n
+      } else {\n
+        indexOfValue = currentItem === this.getValue() ? 0 : -1;\n
+      }\n
+\n
+      if(indexOfValue == -1) continue;\n
+\n
+      charsLeft =  currentItem.length - indexOfValue - valueLength;\n
+\n
+      if( typeof bestMatch.indexOfValue == \'undefined\'\n
+        || bestMatch.indexOfValue > indexOfValue\n
+        || ( bestMatch.indexOfValue == indexOfValue && bestMatch.charsLeft > charsLeft ) ){\n
+\n
+        bestMatch.indexOfValue = indexOfValue;\n
+        bestMatch.charsLeft = charsLeft;\n
+        bestMatch.index = i;\n
+\n
+      }\n
+\n
+    }\n
+\n
+\n
+    return bestMatch.index;\n
+  };\n
+\n
+\n
+  Handsontable.editors.AutocompleteEditor = AutocompleteEditor;\n
+  Handsontable.editors.registerEditor(\'autocomplete\', AutocompleteEditor);\n
+\n
+})(Handsontable);\n
+\n
+(function(Handsontable){\n
+\n
+  var PasswordEditor = Handsontable.editors.TextEditor.prototype.extend();\n
+  var wtDom = new WalkontableDom();\n
+\n
+  PasswordEditor.prototype.createElements = function () {\n
+    Handsontable.editors.TextEditor.prototype.createElements.apply(this, arguments);\n
+\n
+    this.TEXTAREA = document.createElement(\'input\');\n
+    this.TEXTAREA.setAttribute(\'type\', \'password\');\n
+    this.TEXTAREA.className = \'handsontableInput\';\n
+    this.textareaStyle = this.TEXTAREA.style;\n
+    this.textareaStyle.width = 0;\n
+    this.textareaStyle.height = 0;\n
+    this.$textarea = $(this.TEXTAREA);\n
+\n
+    wtDom.empty(this.TEXTAREA_PARENT);\n
+    this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);\n
+\n
+  };\n
+\n
+  Handsontable.editors.PasswordEditor = PasswordEditor;\n
+  Handsontable.editors.registerEditor(\'password\', PasswordEditor);\n
+\n
+})(Handsontable);\n
+\n
+(function (Handsontable) {\n
+\n
+  var SelectEditor = Handsontable.editors.BaseEditor.prototype.extend();\n
+\n
+  SelectEditor.prototype.init = function(){\n
+    this.select = document.createElement(\'SELECT\');\n
+    Handsontable.Dom.addClass(this.select, \'htSelectEditor\');\n
+    this.select.style.display = \'none\';\n
+    this.instance.rootElement[0].appendChild(this.select);\n
+  };\n
+\n
+  SelectEditor.prototype.prepare = function(){\n
+    Handsontable.editors.BaseEditor.prototype.prepare.apply(this, arguments);\n
+\n
+\n
+    var selectOptions = this.cellProperties.selectOptions;\n
+    var options;\n
+\n
+    if (typeof selectOptions == \'function\'){\n
+      options =  this.prepareOptions(selectOptions(this.row, this.col, this.prop))\n
+    } else {\n
+      options =  this.prepareOptions(selectOptions);\n
+    }\n
+\n
+    Handsontable.Dom.empty(this.select);\n
+\n
+    for (var option in options){\n
+      if (options.hasOwnProperty(option)){\n
+        var optionElement = document.createElement(\'OPTION\');\n
+        optionElement.value = option;\n
+        Handsontable.Dom.fastInnerHTML(optionElement, options[option]);\n
+        this.select.appendChild(optionElement);\n
+      }\n
+    }\n
+  };\n
+\n
+  SelectEditor.prototype.prepareOptions = function(optionsToPrepare){\n
+\n
+    var preparedOptions = {};\n
+\n
+    if (Handsontable.helper.isArray(optionsToPrepare)){\n
+      for(var i = 0, len = optionsToPrepare.length; i < len; i++){\n
+        preparedOptions[optionsToPrepare[i]] = optionsToPrepare[i];\n
+      }\n
+    }\n
+    else if (typeof optionsToPrepare == \'object\') {\n
+      preparedOptions = optionsToPrepare;\n
+    }\n
+\n
+    return preparedOptions;\n
+\n
+  };\n
+\n
+  SelectEditor.prototype.getValue = function () {\n
+    return this.select.value;\n
+  };\n
+\n
+  SelectEditor.prototype.setValue = function (value) {\n
+    this.select.value = value;\n
+  };\n
+\n
+  var onBeforeKeyDown = function (event) {\n
+    var instance = this;\n
+    var editor = instance.getActiveEditor();\n
+\n
+    switch (event.keyCode){\n
+      case Handsontable.helper.keyCode.ARROW_UP:\n
+\n
+        var previousOption = editor.select.find(\'option:selected\').prev();\n
+\n
+        if (previousOption.length == 1){\n
+          previousOption.prop(\'selected\', true);\n
+        }\n
+\n
+        event.stopImmediatePropagation();\n
+        event.preventDefault();\n
+        break;\n
+\n
+      case Handsontable.helper.keyCode.ARROW_DOWN:\n
+\n
+        var nextOption = editor.select.find(\'option:selected\').next();\n
+\n
+        if (nextOption.length == 1){\n
+          nextOption.prop(\'selected\', true);\n
+        }\n
+\n
+        event.stopImmediatePropagation();\n
+        event.preventDefault();\n
+        break;\n
+    }\n
+  };\n
+\n
+  SelectEditor.prototype.open = function () {\n
+    var width = Handsontable.Dom.outerWidth(this.TD); //important - group layout reads together for better performance\n
+    var height = Handsontable.Dom.outerHeight(this.TD);\n
+    var rootOffset = Handsontable.Dom.offset(this.instance.rootElement[0]);\n
+    var tdOffset = Handsontable.Dom.offset(this.TD);\n
+\n
+    this.select.style.height = height + \'px\';\n
+    this.select.style.minWidth = width + \'px\';\n
+    this.select.style.top = tdOffset.top - rootOffset.top + \'px\';\n
+    this.select.style.left = tdOffset.left - rootOffset.left - 2 + \'px\'; //2 is cell border\n
+    this.select.style.display = \'\';\n
+\n
+    this.instance.addHook(\'beforeKeyDown\', onBeforeKeyDown);\n
+  };\n
+\n
+  SelectEditor.prototype.close = function () {\n
+    this.select.style.display = \'none\';\n
+    this.instance.removeHook(\'beforeKeyDown\', onB
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+eforeKeyDown);\n
+  };\n
+\n
+  SelectEditor.prototype.focus = function () {\n
+    this.select.focus();\n
+  };\n
+\n
+  Handsontable.editors.SelectEditor = SelectEditor;\n
+  Handsontable.editors.registerEditor(\'select\', SelectEditor);\n
+\n
+})(Handsontable);\n
+\n
+(function (Handsontable) {\n
+\n
+  var DropdownEditor = Handsontable.editors.AutocompleteEditor.prototype.extend();\n
+\n
+  DropdownEditor.prototype.prepare = function () {\n
+    Handsontable.editors.AutocompleteEditor.prototype.prepare.apply(this, arguments);\n
+\n
+    this.cellProperties.filter = false;\n
+    this.cellProperties.strict = true;\n
+\n
+  };\n
+\n
+\n
+  Handsontable.editors.DropdownEditor = DropdownEditor;\n
+  Handsontable.editors.registerEditor(\'dropdown\', DropdownEditor);\n
+\n
+\n
+})(Handsontable);\n
+/**\n
+ * Numeric cell validator\n
+ * @param {*} value - Value of edited cell\n
+ * @param {*} callback - Callback called with validation result\n
+ */\n
+Handsontable.NumericValidator = function (value, callback) {\n
+  if (value === null) {\n
+    value = \'\';\n
+  }\n
+  callback(/^-?\\d*\\.?\\d*$/.test(value));\n
+};\n
+/**\n
+ * Function responsible for validation of autocomplete value\n
+ * @param {*} value - Value of edited cell\n
+ * @param {*} calback - Callback called with validation result\n
+ */\n
+var process = function (value, callback) {\n
+\n
+  var originalVal  = value;\n
+  var lowercaseVal = typeof originalVal === \'string\' ? originalVal.toLowerCase() : null;\n
+\n
+  return function (source) {\n
+    var found = false;\n
+    for (var s = 0, slen = source.length; s < slen; s++) {\n
+      if (originalVal === source[s]) {\n
+        found = true; //perfect match\n
+        break;\n
+      }\n
+      else if (lowercaseVal === source[s].toLowerCase()) {\n
+        // changes[i][3] = source[s]; //good match, fix the case << TODO?\n
+        found = true;\n
+        break;\n
+      }\n
+    }\n
+\n
+    callback(found);\n
+  }\n
+};\n
+\n
+/**\n
+ * Autocomplete cell validator\n
+ * @param {*} value - Value of edited cell\n
+ * @param {*} calback - Callback called with validation result\n
+ */\n
+Handsontable.AutocompleteValidator = function (value, callback) {\n
+  if (this.strict && this.source) {\n
+    typeof this.source === \'function\' ? this.source(value, process(value, callback)) : process(value, callback)(this.source);\n
+  } else {\n
+    callback(true);\n
+  }\n
+};\n
+\n
+/**\n
+ * Cell type is just a shortcut for setting bunch of cellProperties (used in getCellMeta)\n
+ */\n
+\n
+Handsontable.AutocompleteCell = {\n
+  editor: Handsontable.editors.AutocompleteEditor,\n
+  renderer: Handsontable.renderers.AutocompleteRenderer,\n
+  validator: Handsontable.AutocompleteValidator\n
+};\n
+\n
+Handsontable.CheckboxCell = {\n
+  editor: Handsontable.editors.CheckboxEditor,\n
+  renderer: Handsontable.renderers.CheckboxRenderer\n
+};\n
+\n
+Handsontable.TextCell = {\n
+  editor: Handsontable.editors.TextEditor,\n
+  renderer: Handsontable.renderers.TextRenderer\n
+};\n
+\n
+Handsontable.NumericCell = {\n
+  editor: Handsontable.editors.TextEditor,\n
+  renderer: Handsontable.renderers.NumericRenderer,\n
+  validator: Handsontable.NumericValidator,\n
+  dataType: \'number\'\n
+};\n
+\n
+Handsontable.DateCell = {\n
+  editor: Handsontable.editors.DateEditor,\n
+  renderer: Handsontable.renderers.AutocompleteRenderer //displays small gray arrow on right side of the cell\n
+};\n
+\n
+Handsontable.HandsontableCell = {\n
+  editor: Handsontable.editors.HandsontableEditor,\n
+  renderer: Handsontable.renderers.AutocompleteRenderer //displays small gray arrow on right side of the cell\n
+};\n
+\n
+Handsontable.PasswordCell = {\n
+  editor: Handsontable.editors.PasswordEditor,\n
+  renderer: Handsontable.renderers.PasswordRenderer,\n
+  copyable: false\n
+};\n
+\n
+Handsontable.DropdownCell = {\n
+  editor: Handsontable.editors.DropdownEditor,\n
+  renderer: Handsontable.renderers.AutocompleteRenderer, //displays small gray arrow on right side of the cell\n
+  validator: Handsontable.AutocompleteValidator\n
+};\n
+\n
+//here setup the friendly aliases that are used by cellProperties.type\n
+Handsontable.cellTypes = {\n
+  text: Handsontable.TextCell,\n
+  date: Handsontable.DateCell,\n
+  numeric: Handsontable.NumericCell,\n
+  checkbox: Handsontable.CheckboxCell,\n
+  autocomplete: Handsontable.AutocompleteCell,\n
+  handsontable: Handsontable.HandsontableCell,\n
+  password: Handsontable.PasswordCell,\n
+  dropdown: Handsontable.DropdownCell\n
+};\n
+\n
+//here setup the friendly aliases that are used by cellProperties.renderer and cellProperties.editor\n
+Handsontable.cellLookup = {\n
+  validator: {\n
+    numeric: Handsontable.NumericValidator,\n
+    autocomplete: Handsontable.AutocompleteValidator\n
+  }\n
+};\n
+/*\n
+ * jQuery.fn.autoResize 1.1+\n
+ * --\n
+ * https://github.com/warpech/jQuery.fn.autoResize\n
+ *\n
+ * This fork differs from others in a way that it autoresizes textarea in 2-dimensions (horizontally and vertically).\n
+ * It was originally forked from alexbardas\'s repo but maybe should be merged with dpashkevich\'s repo in future.\n
+ *\n
+ * originally forked from:\n
+ * https://github.com/jamespadolsey/jQuery.fn.autoResize\n
+ * which is now located here:\n
+ * https://github.com/alexbardas/jQuery.fn.autoResize\n
+ * though the mostly maintained for is here:\n
+ * https://github.com/dpashkevich/jQuery.fn.autoResize/network\n
+ *\n
+ * --\n
+ * This program is free software. It comes without any warranty, to\n
+ * the extent permitted by applicable law. You can redistribute it\n
+ * and/or modify it under the terms of the Do What The Fuck You Want\n
+ * To Public License, Version 2, as published by Sam Hocevar. See\n
+ * http://sam.zoy.org/wtfpl/COPYING for more details. */\n
+\n
+(function($){\n
+\n
+  autoResize.defaults = {\n
+    onResize: function(){},\n
+    animate: {\n
+      duration: 200,\n
+      complete: function(){}\n
+    },\n
+    extraSpace: 50,\n
+    minHeight: \'original\',\n
+    maxHeight: 500,\n
+    minWidth: \'original\',\n
+    maxWidth: 500\n
+  };\n
+\n
+  autoResize.cloneCSSProperties = [\n
+    \'lineHeight\', \'textDecoration\', \'letterSpacing\',\n
+    \'fontSize\', \'fontFamily\', \'fontStyle\', \'fontWeight\',\n
+    \'textTransform\', \'textAlign\', \'direction\', \'wordSpacing\', \'fontSizeAdjust\',\n
+    \'padding\'\n
+  ];\n
+\n
+  autoResize.cloneCSSValues = {\n
+    position: \'absolute\',\n
+    top: -9999,\n
+    left: -9999,\n
+    opacity: 0,\n
+    overflow: \'hidden\',\n
+    overflowX: \'hidden\',\n
+    overflowY: \'hidden\',\n
+    border: \'1px solid black\',\n
+    padding: \'0.49em\' //this must be about the width of caps W character\n
+  };\n
+\n
+  autoResize.resizableFilterSelector = \'textarea,input:not(input[type]),input[type=text],input[type=password]\';\n
+\n
+  autoResize.AutoResizer = AutoResizer;\n
+\n
+  $.fn.autoResize = autoResize;\n
+\n
+  function autoResize(config) {\n
+    this.filter(autoResize.resizableFilterSelector).each(function(){\n
+      new AutoResizer( $(this), config );\n
+    });\n
+    return this;\n
+  }\n
+\n
+  function AutoResizer(el, config) {\n
+\n
+    if(this.clones) return;\n
+\n
+    this.config = $.extend({}, autoResize.defaults, config);\n
+\n
+    this.el = el;\n
+\n
+    this.nodeName = el[0].nodeName.toLowerCase();\n
+\n
+    this.previousScrollTop = null;\n
+\n
+    if (config.maxWidth === \'original\') config.maxWidth = el.width();\n
+    if (config.minWidth === \'original\') config.minWidth = el.width();\n
+    if (config.maxHeight === \'original\') config.maxHeight = el.height();\n
+    if (config.minHeight === \'original\') config.minHeight = el.height();\n
+\n
+    if (this.nodeName === \'textarea\') {\n
+      el.css({\n
+        resize: \'none\',\n
+        overflowY: \'none\'\n
+      });\n
+    }\n
+\n
+    el.data(\'AutoResizer\', this);\n
+\n
+    this.createClone();\n
+    this.injectClone();\n
+    this.bind();\n
+\n
+  }\n
+\n
+  AutoResizer.prototype = {\n
+\n
+    bind: function() {\n
+\n
+      var check = $.proxy(function(){\n
+        this.check();\n
+        return true;\n
+      }, this);\n
+\n
+      this.unbind();\n
+\n
+      this.el\n
+        .bind(\'keyup.autoResize\', check)\n
+        //.bind(\'keydown.autoResize\', check)\n
+        .bind(\'change.autoResize\', check);\n
+\n
+      this.check(null, true);\n
+\n
+    },\n
+\n
+    unbind: function() {\n
+      this.el.unbind(\'.autoResize\');\n
+    },\n
+\n
+    createClone: function() {\n
+\n
+      var el = this.el,\n
+        self = this,\n
+        config = this.config;\n
+\n
+      this.clones = $();\n
+\n
+      if (config.minHeight !== \'original\' || config.maxHeight !== \'original\') {\n
+        this.hClone = el.clone().height(\'auto\');\n
+        this.clones = this.clones.add(this.hClone);\n
+      }\n
+      if (config.minWidth !== \'original\' || config.maxWidth !== \'original\') {\n
+        this.wClone = $(\'<div/>\').width(\'auto\').css({\n
+          whiteSpace: \'nowrap\',\n
+          \'float\': \'left\'\n
+        });\n
+        this.clones = this.clones.add(this.wClone);\n
+      }\n
+\n
+      $.each(autoResize.cloneCSSProperties, function(i, p){\n
+        self.clones.css(p, el.css(p));\n
+      });\n
+\n
+      this.clones\n
+        .removeAttr(\'name\')\n
+        .removeAttr(\'id\')\n
+        .attr(\'tabIndex\', -1)\n
+        .css(autoResize.cloneCSSValues)\n
+        .css(\'overflowY\', \'scroll\');\n
+\n
+    },\n
+\n
+    check: function(e, immediate) {\n
+\n
+      var config = this.config,\n
+        wClone = this.wClone,\n
+        hClone = this.hClone,\n
+        el = this.el,\n
+        value = el.val();\n
+\n
+      if (wClone) {\n
+\n
+        wClone.text(value);\n
+\n
+        // Calculate new width + whether to change\n
+        var cloneWidth = wClone.outerWidth(),\n
+          newWidth = (cloneWidth + config.extraSpace) >= config.minWidth ?\n
+            cloneWidth + config.extraSpace : config.minWidth,\n
+          currentWidth = el.width();\n
+\n
+        newWidth = Math.min(newWidth, config.maxWidth);\n
+\n
+        if (\n
+          (newWidth < currentWidth && newWidth >= config.minWidth) ||\n
+            (newWidth >= config.minWidth && newWidth <= config.maxWidth)\n
+          ) {\n
+\n
+          config.onResize.call(el);\n
+\n
+          el.scrollLeft(0);\n
+\n
+          config.animate && !immediate ?\n
+            el.stop(1,1).animate({\n
+              width: newWidth\n
+            }, config.animate)\n
+            : el.width(newWidth);\n
+\n
+        }\n
+\n
+      }\n
+\n
+      if (hClone) {\n
+\n
+        if (newWidth) {\n
+          hClone.width(newWidth);\n
+        }\n
+\n
+        hClone.height(0).val(value).scrollTop(10000);\n
+\n
+        var scrollTop = hClone[0].scrollTop + config.extraSpace;\n
+\n
+        // Don\'t do anything if scrollTop hasen\'t changed:\n
+        if (this.previousScrollTop === scrollTop) {\n
+          return;\n
+        }\n
+\n
+        this.previousScrollTop = scrollTop;\n
+\n
+        if (scrollTop >= config.maxHeight) {\n
+          scrollTop = config.maxHeight;\n
+        }\n
+\n
+        if (scrollTop < config.minHeight) {\n
+          scrollTop = config.minHeight;\n
+        }\n
+\n
+        if(scrollTop == config.maxHeight && newWidth == config.maxWidth) {\n
+          el.css(\'overflowY\', \'scroll\');\n
+        }\n
+        else {\n
+          el.css(\'overflowY\', \'hidden\');\n
+        }\n
+\n
+        config.onResize.call(el);\n
+\n
+        // Either animate or directly apply height:\n
+        config.animate && !immediate ?\n
+          el.stop(1,1).animate({\n
+            height: scrollTop\n
+          }, config.animate)\n
+          : el.height(scrollTop);\n
+      }\n
+    },\n
+\n
+    destroy: function() {\n
+      this.unbind();\n
+      this.el.removeData(\'AutoResizer\');\n
+      this.clones.remove();\n
+      delete this.el;\n
+      delete this.hClone;\n
+      delete this.wClone;\n
+      delete this.clones;\n
+    },\n
+\n
+    injectClone: function() {\n
+      (\n
+        autoResize.cloneContainer ||\n
+          (autoResize.cloneContainer = $(\'<arclones/>\').appendTo(\'body\'))\n
+        ).empty().append(this.clones); //this should be refactored so that a node is never cloned more than once\n
+    }\n
+\n
+  };\n
+\n
+})(jQuery);\n
+/**\n
+ * SheetClip - Spreadsheet Clipboard Parser\n
+ * version 0.2\n
+ *\n
+ * This tiny library transforms JavaScript arrays to strings that are pasteable by LibreOffice, OpenOffice,\n
+ * Google Docs and Microsoft Excel.\n
+ *\n
+ * Copyright 2012, Marcin Warpechowski\n
+ * Licensed under the MIT license.\n
+ * http://github.com/warpech/sheetclip/\n
+ */\n
+/*jslint white: true*/\n
+(function (global) {\n
+  "use strict";\n
+\n
+  function countQuotes(str) {\n
+    return str.split(\'"\').length - 1;\n
+  }\n
+\n
+  global.SheetClip = {\n
+    parse: function (str) {\n
+      var r, rlen, rows, arr = [], a = 0, c, clen, multiline, last;\n
+      rows = str.split(\'\\n\');\n
+      if (rows.length > 1 && rows[rows.length - 1] === \'\') {\n
+        rows.pop();\n
+      }\n
+      for (r = 0, rlen = rows.length; r < rlen; r += 1) {\n
+        rows[r] = rows[r].split(\'\\t\');\n
+        for (c = 0, clen = rows[r].length; c < clen; c += 1) {\n
+          if (!arr[a]) {\n
+            arr[a] = [];\n
+          }\n
+          if (multiline && c === 0) {\n
+            last = arr[a].length - 1;\n
+            arr[a][last] = arr[a][last] + \'\\n\' + rows[r][0];\n
+            if (multiline && (countQuotes(rows[r][0]) & 1)) { //& 1 is a bitwise way of performing mod 2\n
+              multiline = false;\n
+              arr[a][last] = arr[a][last].substring(0, arr[a][last].length - 1).replace(/""/g, \'"\');\n
+            }\n
+          }\n
+          else {\n
+            if (c === clen - 1 && rows[r][c].indexOf(\'"\') === 0) {\n
+              arr[a].push(rows[r][c].substring(1).replace(/""/g, \'"\'));\n
+              multiline = true;\n
+            }\n
+            else {\n
+              arr[a].push(rows[r][c].replace(/""/g, \'"\'));\n
+              multiline = false;\n
+            }\n
+          }\n
+        }\n
+        if (!multiline) {\n
+          a += 1;\n
+        }\n
+      }\n
+      return arr;\n
+    },\n
+\n
+    stringify: function (arr) {\n
+      var r, rlen, c, clen, str = \'\', val;\n
+      for (r = 0, rlen = arr.length; r < rlen; r += 1) {\n
+        for (c = 0, clen = arr[r].length; c < clen; c += 1) {\n
+          if (c > 0) {\n
+            str += \'\\t\';\n
+          }\n
+          val = arr[r][c];\n
+          if (typeof val === \'string\') {\n
+            if (val.indexOf(\'\\n\') > -1) {\n
+              str += \'"\' + val.replace(/"/g, \'""\') + \'"\';\n
+            }\n
+            else {\n
+              str += val;\n
+            }\n
+          }\n
+          else if (val === null || val === void 0) { //void 0 resolves to undefined\n
+            str += \'\';\n
+          }\n
+          else {\n
+            str += val;\n
+          }\n
+        }\n
+        str += \'\\n\';\n
+      }\n
+      return str;\n
+    }\n
+  };\n
+}(window));\n
+/**\n
+ * CopyPaste.js\n
+ * Creates a textarea that stays hidden on the page and gets focused when user presses CTRL while not having a form input focused\n
+ * In future we may implement a better driver when better APIs are available\n
+ * @constructor\n
+ */\n
+var CopyPaste = (function () {\n
+  var instance;\n
+  return {\n
+    getInstance: function () {\n
+      if (!instance) {\n
+        instance = new CopyPasteClass();\n
+      } else if (instance.hasBeenDestroyed()){\n
+        instance.init();\n
+      }\n
+\n
+      instance.refCounter++;\n
+\n
+      return instance;\n
+    }\n
+  };\n
+})();\n
+\n
+function CopyPasteClass() {\n
+  this.refCounter = 0;\n
+  this.init();\n
+}\n
+\n
+CopyPasteClass.prototype.init = function () {\n
+  var that = this\n
+    , style\n
+    , parent;\n
+\n
+  this.copyCallbacks = [];\n
+  this.cutCallbacks = [];\n
+  this.pasteCallbacks = [];\n
+\n
+  this.listenerElement = document.documentElement;\n
+  parent = document.body;\n
+\n
+  if (document.getElementById(\'CopyPasteDiv\')) {\n
+    this.elDiv = document.getElementById(\'CopyPasteDiv\');\n
+    this.elTextarea = this.elDiv.firstChild;\n
+  }\n
+  else {\n
+    this.elDiv = document.createElement(\'DIV\');\n
+    this.elDiv.id = \'CopyPasteDiv\';\n
+    style = this.elDiv.style;\n
+    style.position = \'fixed\';\n
+    style.top = \'-10000px\';\n
+    style.left = \'-10000px\';\n
+    parent.appendChild(this.elDiv);\n
+\n
+    this.elTextarea = document.createElement(\'TEXTAREA\');\n
+    this.elTextarea.className = \'copyPaste\';\n
+    style = this.elTextarea.style;\n
+    style.width = \'10000px\';\n
+    style.height = \'10000px\';\n
+    style.overflow = \'hidden\';\n
+    this.elDiv.appendChild(this.elTextarea);\n
+\n
+    if (typeof style.opacity !== \'undefined\') {\n
+      style.opacity = 0;\n
+    }\n
+    else {\n
+      /*@cc_on @if (@_jscript)\n
+       if(typeof style.filter === \'string\') {\n
+       style.filter = \'alpha(opacity=0)\';\n
+       }\n
+       @end @*/\n
+    }\n
+  }\n
+\n
+  this.keydownListener = function (event) {\n
+    var isCtrlDown = false;\n
+    if (event.metaKey) { //mac\n
+      isCtrlDown = true;\n
+    }\n
+    else if (event.ctrlKey && navigator.userAgent.indexOf(\'Mac\') === -1) { //pc\n
+      isCtrlDown = true;\n
+    }\n
+\n
+    if (isCtrlDown) {\n
+      if (document.activeElement !== that.elTextarea && (that.getSelectionText() != \'\' || [\'INPUT\', \'SELECT\', \'TEXTAREA\'].indexOf(document.activeElement.nodeName) != -1)) {\n
+        return; //this is needed by fragmentSelection in Handsontable. Ignore copypaste.js behavior if fragment of cell text is selected\n
+      }\n
+\n
+      that.selectNodeText(that.elTextarea);\n
+      setTimeout(function () {\n
+        that.selectNodeText(that.elTextarea);\n
+      }, 0);\n
+    }\n
+\n
+    /* 67 = c\n
+     * 86 = v\n
+     * 88 = x\n
+     */\n
+    if (isCtrlDown && (event.keyCode === 67 || event.keyCode === 86 || event.keyCode === 88)) {\n
+      // that.selectNodeText(that.elTextarea);\n
+\n
+      if (event.keyCode === 88) { //works in all browsers, incl. Opera < 12.12\n
+        setTimeout(function () {\n
+          that.triggerCut(event);\n
+        }, 0);\n
+      }\n
+      else if (event.keyCode === 86) {\n
+        setTimeout(function () {\n
+          that.triggerPaste(event);\n
+        }, 0);\n
+      }\n
+    }\n
+  }\n
+\n
+  this._bindEvent(this.listenerElement, \'keydown\', this.keydownListener);\n
+};\n
+\n
+//http://jsperf.com/textara-selection\n
+//http://stackoverflow.com/questions/1502385/how-can-i-make-this-code-work-in-ie\n
+CopyPasteClass.prototype.selectNodeText = function (el) {\n
+  el.select();\n
+};\n
+\n
+//http://stackoverflow.com/questions/5379120/get-the-highlighted-selected-text\n
+CopyPasteClass.prototype.getSelectionText = function () {\n
+  var text = "";\n
+  if (window.getSelection) {\n
+    text = window.getSelection().toString();\n
+  } else if (document.selection && document.selection.type != "Control") {\n
+    text = document.selection.createRange().text;\n
+  }\n
+  return text;\n
+};\n
+\n
+CopyPasteClass.prototype.copyable = function (str) {\n
+  if (typeof str !== \'string\' && str.toString === void 0) {\n
+    throw new Error(\'copyable requires string parameter\');\n
+  }\n
+  this.elTextarea.value = str;\n
+};\n
+\n
+/*CopyPasteClass.prototype.onCopy = function (fn) {\n
+  this.copyCallbacks.push(fn);\n
+};*/\n
+\n
+CopyPasteClass.prototype.onCut = function (fn) {\n
+  this.cutCallbacks.push(fn);\n
+};\n
+\n
+CopyPasteClass.prototype.onPaste = function (fn) {\n
+  this.pasteCallbacks.push(fn);\n
+};\n
+\n
+CopyPasteClass.prototype.removeCallback = function (fn) {\n
+  var i, ilen;\n
+  for (i = 0, ilen = this.copyCallbacks.length; i < ilen; i++) {\n
+    if (this.copyCallbacks[i] === fn) {\n
+      this.copyCallbacks.splice(i, 1);\n
+      return true;\n
+    }\n
+  }\n
+  for (i = 0, ilen = this.cutCallbacks.length; i < ilen; i++) {\n
+    if (this.cutCallbacks[i] === fn) {\n
+      this.cutCallbacks.splice(i, 1);\n
+      return true;\n
+    }\n
+  }\n
+  for (i = 0, ilen = this.pasteCallbacks.length; i < ilen; i++) {\n
+    if (this.pasteCallbacks[i] === fn) {\n
+      this.pasteCallbacks.splice(i, 1);\n
+      return true;\n
+    }\n
+  }\n
+  return false;\n
+};\n
+\n
+CopyPasteClass.prototype.triggerCut = function (event) {\n
+  var that = this;\n
+  if (that.cutCallbacks) {\n
+    setTimeout(function () {\n
+      for (var i = 0, ilen = that.cutCallbacks.length; i < ilen; i++) {\n
+        that.cutCallbacks[i](event);\n
+      }\n
+    }, 50);\n
+  }\n
+};\n
+\n
+CopyPasteClass.prototype.triggerPaste = function (event, str) {\n
+  var that = this;\n
+  if (that.pasteCallbacks) {\n
+    setTimeout(function () {\n
+      var val = (str || that.elTextarea.value).replace(/\\n$/, \'\'); //remove trailing newline\n
+      for (var i = 0, ilen = that.pasteCallbacks.length; i < ilen; i++) {\n
+        that.pasteCallbacks[i](val, event);\n
+      }\n
+    }, 50);\n
+  }\n
+};\n
+\n
+CopyPasteClass.prototype.destroy = function () {\n
+\n
+  if(!this.hasBeenDestroyed() && --this.refCounter == 0){\n
+    if (this.elDiv && this.elDiv.parentNode) {\n
+      this.elDiv.parentNode.removeChild(this.elDiv);\n
+    }\n
+\n
+    this._unbindEvent(this.listenerElement, \'keydown\', this.keydownListener);\n
+\n
+  }\n
+\n
+};\n
+\n
+CopyPasteClass.prototype.hasBeenDestroyed = function () {\n
+  return !this.refCounter;\n
+};\n
+\n
+//old version used this:\n
+// - http://net.tutsplus.com/tutorials/javascript-ajax/javascript-from-null-cross-browser-event-binding/\n
+// - http://stackoverflow.com/questions/4643249/cross-browser-event-object-normalization\n
+//but that cannot work with jQuery.trigger\n
+CopyPasteClass.prototype._bindEvent = (function () {\n
+  if (window.jQuery) { //if jQuery exists, use jQuery event (for compatibility with $.trigger and $.triggerHandler, which can only trigger jQuery events - and we use that in tests)\n
+    return function (elem, type, cb) {\n
+      $(elem).on(type + \'.copypaste\', cb);\n
+    };\n
+  }\n
+  else {\n
+    return function (elem, type, cb) {\n
+      elem.addEventListener(type, cb, false); //sorry, IE8 will only work with jQuery\n
+    };\n
+  }\n
+})();\n
+\n
+CopyPasteClass.prototype._unbindEvent = (function () {\n
+  if (window.jQuery) { //if jQuery exists, use jQuery event (for compatibility with $.trigger and $.triggerHandler, which can only trigger jQuery events - and we use that in tests)\n
+    return function (elem, type, cb) {\n
+      $(elem).off(type + \'.copypaste\', cb);\n
+    };\n
+  }\n
+  else {\n
+    return function (elem, type, cb) {\n
+      elem.removeEventListener(type, cb, false); //sorry, IE8 will only work with jQuery\n
+    };\n
+  }\n
+})();\n
+// json-patch-duplex.js 0.3.6\n
+// (c) 2013 Joachim Wester\n
+// MIT license\n
+var jsonpatch;\n
+(function (jsonpatch) {\n
+    var objOps = {\n
+        add: function (obj, key) {\n
+            obj[key] = this.value;\n
+            return true;\n
+        },\n
+        remove: function (obj, key) {\n
+            delete obj[key];\n
+            return true;\n
+        },\n
+        replace: function (obj, key) {\n
+            obj[key] = this.value;\n
+            return true;\n
+        },\n
+        move: function (obj, key, tree) {\n
+            var temp = { op: "_get", path: this.from };\n
+            apply(tree, [temp]);\n
+            apply(tree, [\n
+                { op: "remove", path: this.from }\n
+            ]);\n
+            apply(tree, [\n
+                { op: "add", path: this.path, value: temp.value }\n
+            ]);\n
+            return true;\n
+        },\n
+        copy: function (obj, key, tree) {\n
+            var temp = { op: "_get", path: this.from };\n
+            apply(tree, [temp]);\n
+            apply(tree, [\n
+                { op: "add", path: this.path, value: temp.value }\n
+            ]);\n
+            return true;\n
+        },\n
+        test: function (obj, key) {\n
+            return (JSON.stringify(obj[key]) === JSON.stringify(this.value));\n
+        },\n
+        _get: function (obj, key) {\n
+            this.value = obj[key];\n
+        }\n
+    };\n
+\n
+    var arrOps = {\n
+        add: function (arr, i) {\n
+            arr.splice(i, 0, this.value);\n
+            return true;\n
+        },\n
+        remove: function (arr, i) {\n
+            arr.splice(i, 1);\n
+            return true;\n
+        },\n
+        replace: function (arr, i) {\n
+            arr[i] = this.value;\n
+            return true;\n
+        },\n
+        move: objOps.move,\n
+        copy: objOps.copy,\n
+        test: objOps.test,\n
+        _get: objOps._get\n
+    };\n
+\n
+    var observeOps = {\n
+        add: function (patches, path) {\n
+            var patch = {\n
+                op: "add",\n
+                path: path + escapePathComponent(this.name),\n
+                value: this.object[this.name]\n
+            };\n
+            patches.push(patch);\n
+        },\n
+        \'delete\': function (patches, path) {\n
+            var patch = {\n
+                op: "remove",\n
+                path: path + escapePathComponent(this.name)\n
+            };\n
+            patches.push(patch);\n
+        },\n
+        update: function (patches, path) {\n
+            var patch = {\n
+                op: "replace",\n
+                path: path + escapePathComponent(this.name),\n
+                value: this.object[this.name]\n
+            };\n
+            patches.push(patch);\n
+        }\n
+    };\n
+\n
+    function escapePathComponent(str) {\n
+        if (str.indexOf(\'/\') === -1 && str.indexOf(\'~\') === -1)\n
+            return str;\n
+        return str.replace(/~/g, \'~0\').replace(/\\//g, \'~1\');\n
+    }\n
+\n
+    function _getPathRecursive(root, obj) {\n
+        var found;\n
+        for (var key in root) {\n
+            if (root.hasOwnProperty(key)) {\n
+                if (root[key] === obj) {\n
+                    return escapePathComponent(key) + \'/\';\n
+                } else if (typeof root[key] === \'object\') {\n
+                    found = _getPathRecursive(root[key], obj);\n
+                    if (found != \'\') {\n
+                        return escapePathComponent(key) + \'/\' + found;\n
+                    }\n
+                }\n
+            }\n
+        }\n
+        return \'\';\n
+    }\n
+\n
+    function getPath(root, obj) {\n
+        if (root === obj) {\n
+            return \'/\';\n
+        }\n
+        var path = _getPathRecursive(root, obj);\n
+        if (path === \'\') {\n
+            throw new Error("Object not found in root");\n
+        }\n
+        return \'/\' + path;\n
+    }\n
+\n
+    var beforeDict = [];\n
+\n
+    jsonpatch.intervals;\n
+\n
+    var Mirror = (function () {\n
+        function Mirror(obj) {\n
+            this.observers = [];\n
+            this.obj = obj;\n
+        }\n
+        return Mirror;\n
+    })();\n
+\n
+    var ObserverInfo = (function () {\n
+        function ObserverInfo(callback, observer) {\n
+            this.callback = callback;\n
+            this.observer = observer;\n
+        }\n
+        return ObserverInfo;\n
+    })();\n
+\n
+    function getMirror(obj) {\n
+        for (var i = 0, ilen = beforeDict.length; i < ilen; i++) {\n
+            if (beforeDict[i].obj === obj) {\n
+                return beforeDict[i];\n
+            }\n
+        }\n
+    }\n
+\n
+    function getObserverFromMirror(mirror, callback) {\n
+        for (var j = 0, jlen = mirror.observers.length; j < jlen; j++) {\n
+            if (mirror.observers[j].callback === callback) {\n
+                return mirror.observers[j].observer;\n
+            }\n
+        }\n
+    }\n
+\n
+    function removeObserverFromMirror(mirror, observer) {\n
+        for (var j = 0, jlen = mirror.observers.length; j < jlen; j++) {\n
+            if (mirror.observers[j].observer === observer) {\n
+                mirror.observers.splice(j, 1);\n
+                return;\n
+            }\n
+        }\n
+    }\n
+\n
+    function unobserve(root, observer) {\n
+        generate(observer);\n
+        if (Object.observe) {\n
+            _unobserve(observer, root);\n
+        } else {\n
+            clearTimeout(observer.next);\n
+        }\n
+\n
+        var mirror = getMirror(root);\n
+        removeObserverFromMirror(mirror, observer);\n
+    }\n
+    jsonpatch.unobserve = unobserve;\n
+\n
+    function observe(obj, callback) {\n
+        var patches = [];\n
+        var root = obj;\n
+        var observer;\n
+        var mirror = getMirror(obj);\n
+\n
+        if (!mirror) {\n
+            mirror = new Mirror(obj);\n
+            beforeDict.push(mirror);\n
+        } else {\n
+            observer = getObserverFromMirror(mirror, callback);\n
+        }\n
+\n
+        if (observer) {\n
+            return observer;\n
+        }\n
+\n
+        if (Object.observe) {\n
+            observer = function (arr) {\n
+                //This "refresh" is needed to begin observing new object properties\n
+                _unobserve(observer, obj);\n
+                _observe(observer, obj);\n
+\n
+                var a = 0, alen = arr.length;\n
+                while (a < alen) {\n
+                    if (!(arr[a].name === \'length\' && _isArray(arr[a].object)) && !(arr[a].name === \'__Jasmine_been_here_before__\')) {\n
+                        var type = arr[a].type;\n
+\n
+                        switch (type) {\n
+                            case \'new\':\n
+                                type = \'add\';\n
+                                break;\n
+\n
+                            case \'deleted\':\n
+                                type = \'delete\';\n
+                                break;\n
+\n
+                            case \'updated\':\n
+                                type = \'update\';\n
+                                break;\n
+                        }\n
+\n
+                        observeOps[type].call(arr[a], patches, getPath(root, arr[a].object));\n
+                    }\n
+                    a++;\n
+                }\n
+\n
+                if (patches) {\n
+                    if (callback) {\n
+                        callback(patches);\n
+                    }\n
+                }\n
+                observer.patches = patches;\n
+                patches = [];\n
+            };\n
+        } else {\n
+            observer = {};\n
+\n
+            mirror.value = JSON.parse(JSON.stringify(obj));\n
+\n
+            if (callback) {\n
+                //callbacks.push(callback); this has no purpose\n
+                observer.callback = callback;\n
+                observer.next = null;\n
+                var intervals = this.intervals || [100, 1000, 10000, 60000];\n
+                var currentInterval = 0;\n
+\n
+                var dirtyCheck = function () {\n
+                    generate(observer);\n
+                };\n
+                var fastCheck = function () {\n
+                    clearTimeout(observer.next);\n
+                    observer.next = setTimeout(function () {\n
+                        dirtyCheck();\n
+                        currentInterval = 0;\n
+                        observer.next = setTimeout(slowCheck, intervals[currentInterval++]);\n
+                    }, 0);\n
+                };\n
+                var slowCheck = function () {\n
+                    dirtyCheck();\n
+                    if (currentInterval == intervals.length)\n
+                        currentInterval = intervals.length - 1;\n
+                    observer.next = setTimeout(slowCheck, intervals[currentInterval++]);\n
+                };\n
+                if (typeof window !== \'undefined\') {\n
+                    if (window.addEventListener) {\n
+                        window.addEventListener(\'mousedown\', fastCheck);\n
+                        window.addEventListener(\'mouseup\', fastCheck);\n
+                        window.addEventListener(\'keydown\', fastCheck);\n
+                    } else {\n
+                        window.attachEvent(\'onmousedown\', fastCheck);\n
+                        window.attachEvent(\'onmouseup\', fastCheck);\n
+                        window.attachEvent(\'onkeydown\', fastCheck);\n
+                    }\n
+                }\n
+                observer.next = setTimeout(slowCheck, intervals[currentInterval++]);\n
+            }\n
+        }\n
+        observer.patches = patches;\n
+        observer.object = obj;\n
+\n
+        mirror.observers.push(new ObserverInfo(callback, observer));\n
+\n
+        return _observe(observer, obj);\n
+    }\n
+    jsonpatch.observe = observe;\n
+\n
+    /// Listen to changes on an object tree, accumulate patches\n
+    function _observe(observer, obj) {\n
+        if (Object.observe) {\n
+            Object.observe(obj, observer);\n
+            for (var key in obj) {\n
+                if (obj.hasOwnProperty(key)) {\n
+                    var v = obj[key];\n
+                    if (v && typeof (v) === "object") {\n
+                        _observe(observer, v);\n
+                    }\n
+                }\n
+            }\n
+        }\n
+        return observer;\n
+    }\n
+\n
+    function _unobserve(observer, obj) {\n
+        if (Object.observe) {\n
+            Object.unobserve(obj, observer);\n
+            for (var key in obj) {\n
+                if (obj.hasOwnProperty(key)) {\n
+                    var v = obj[key];\n
+                    if (v && typeof (v) === "object") {\n
+                        _unobserve(observer, v);\n
+                    }\n
+                }\n
+            }\n
+        }\n
+        return observer;\n
+    }\n
+\n
+    function generate(observer) {\n
+        if (Object.observe) {\n
+            Object.deliverChangeRecords(observer);\n
+        } else {\n
+            var mirror;\n
+            for (var i = 0, ilen = beforeDict.length; i < ilen; i++) {\n
+                if (beforeDict[i].obj === observer.object) {\n
+                    mirror = beforeDict[i];\n
+                    break;\n
+                }\n
+            }\n
+            _generate(mirror.value, observer.object, observer.patches, "");\n
+        }\n
+        var temp = observer.patches;\n
+        if (temp.length > 0) {\n
+            observer.patches = [];\n
+            if (observer.callback) {\n
+                observer.callback(temp);\n
+            }\n
+        }\n
+        return temp;\n
+    }\n
+    jsonpatch.generate = generate;\n
+\n
+    var _objectKeys;\n
+    if (Object.keys) {\n
+        _objectKeys = Object.keys;\n
+    } else {\n
+        _objectKeys = function (obj) {\n
+            var keys = [];\n
+            for (var o in obj) {\n
+                if (obj.hasOwnProperty(o)) {\n
+                    keys.push(o);\n
+                }\n
+            }\n
+            return keys;\n
+        };\n
+    }\n
+\n
+    // Dirty check if obj is different from mirror, generate patches and update mirror\n
+    function _generate(mirror, obj, patches, path) {\n
+        var newKeys = _objectKeys(obj);\n
+        var oldKeys = _objectKeys(mirror);\n
+        var changed = false;\n
+        var deleted = false;\n
+\n
+        for (var t = oldKeys.length - 1; t >= 0; t--) {\n
+            var key = oldKeys[t];\n
+            var oldVal = mirror[key];\n
+            if (obj.hasOwnProperty(key)) {\n
+                var newVal = obj[key];\n
+                if (oldVal instanceof Object) {\n
+                    _generate(oldVal, newVal, patches, path + "/" + escapePathComponent(key));\n
+                } else {\n
+                    if (oldVal != newVal) {\n
+                        changed = true;\n
+                        patches.push({ op: "replace", path: path + "/" + escapePathComponent(key), value: newVal });\n
+                        mirror[key] = newVal;\n
+                    }\n
+                }\n
+            } else {\n
+                patches.push({ op: "remove", path: path + "/" + escapePathComponent(key) });\n
+                delete mirror[key];\n
+                deleted = true;\n
+            }\n
+        }\n
+\n
+        if (!deleted && newKeys.length == oldKeys.length) {\n
+            return;\n
+        }\n
+\n
+        for (var t = 0; t < newKeys.length; t++) {\n
+            var key = newKeys[t];\n
+            if (!mirror.hasOwnProperty(key)) {\n
+                patches.push({ op: "add", path: path + "/" + escapePathComponent(key), value: obj[key] });\n
+                mirror[key] = JSON.parse(JSON.stringify(obj[key]));\n
+            }\n
+        }\n
+    }\n
+\n
+    var _isArray;\n
+    if (Array.isArray) {\n
+        _isArray = Array.isArray;\n
+    } else {\n
+        _isArray = function (obj) {\n
+            return obj.push && typeof obj.length === \'number\';\n
+        };\n
+    }\n
+\n
+    /// Apply a json-patch operation on an object tree\n
+    function apply(tree, patches) {\n
+        var result = false, p = 0, plen = patches.length, patch;\n
+        while (p < plen) {\n
+            patch = patches[p];\n
+\n
+            // Find the object\n
+            var keys = patch.path.split(\'/\');\n
+            var obj = tree;\n
+            var t = 1;\n
+            var len = keys.length;\n
+            while (true) {\n
+                if (_isArray(obj)) {\n
+                    var index = parseInt(keys[t], 10);\n
+                    t++;\n
+                    if (t >= len) {\n
+                        result = arrOps[patch.op].call(patch, obj, index, tree);\n
+                        break;\n
+                    }\n
+                    obj = obj[index];\n
+                } else {\n
+                    var key = keys[t];\n
+                    if (key.indexOf(\'~\') != -1)\n
+                        key = key.replace(/~1/g, \'/\').replace(/~0/g, \'~\');\n
+                    t++;\n
+                    if (t >= len) {\n
+                        result = objOps[patch.op].call(patch, obj, key, tree);\n
+                        break;\n
+                    }\n
+                    obj = obj[key];\n
+                }\n
+            }\n
+            p++;\n
+        }\n
+        return result;\n
+    }\n
+    jsonpatch.apply = apply;\n
+})(jsonpatch || (jsonpatch = {}));\n
+\n
+if (typeof exports !== "undefined") {\n
+    exports.apply = jsonpatch.apply;\n
+    exports.observe = jsonpatch.observe;\n
+    exports.unobserve = jsonpatch.unobserve;\n
+    exports.generate = jsonpatch.generate;\n
+}\n
+\n
+Handsontable.PluginHookClass = (function () {\n
+\n
+  var Hooks = function () {\n
+    return {\n
+      // Hooks\n
+      beforeInitWalkontable: [],\n
+\n
+      beforeInit: [],\n
+      beforeRender: [],\n
+      beforeChange: [],\n
+      beforeRemoveCol: [],\n
+      beforeRemoveRow: [],\n
+      beforeValidate: [],\n
+      beforeGet: [],\n
+      beforeSet: [],\n
+      beforeGetCellMeta: [],\n
+      beforeAutofill: [],\n
+      beforeKeyDown: [],\n
+      beforeColumnSort: [],\n
+\n
+      afterInit : [],\n
+      afterLoadData : [],\n
+      afterUpdateSettings: [],\n
+      afterRender : [],\n
+      afterRenderer : [],\n
+      afterChange : [],\n
+      afterValidate: [],\n
+      afterGetCellMeta: [],\n
+      afterGetColHeader: [],\n
+      afterGetColWidth: [],\n
+      afterDestroy: [],\n
+      afterRemoveRow: [],\n
+      afterCreateRow: [],\n
+      afterRemoveCol: [],\n
+      afterCreateCol: [],\n
+      afterColumnResize: [],\n
+      afterColumnMove: [],\n
+      afterColumnSort: [],\n
+      afterDeselect: [],\n
+      afterSelection: [],\n
+      afterSelectionByProp: [],\n
+      afterSelectionEnd: [],\n
+      afterSelectionEndByProp: [],\n
+      afterCopyLimit: [],\n
+      afterOnCellMouseDown: [],\n
+      afterOnCellMouseOver: [],\n
+      afterOnCellCornerMouseDown: [],\n
+      afterScrollVertically: [],\n
+      afterScrollHorizontally: [],\n
+\n
+      // Modifiers\n
+      modifyCol: []\n
+    }\n
+  };\n
+\n
+  var legacy = {\n
+    onBeforeChange: "beforeChange",\n
+    onChange: "afterChange",\n
+    onCreateRow: "afterCreateRow",\n
+    onCreateCol: "afterCreateCol",\n
+    onSelection: "afterSelection",\n
+    onCopyLimit: "afterCopyLimit",\n
+    onSelectionEnd: "afterSelectionEnd",\n
+    onSelectionByProp: "afterSelectionByProp",\n
+    onSelectionEndByProp: "afterSelectionEndByProp"\n
+  };\n
+\n
+  function PluginHookClass() {\n
+\n
+    this.hooks = Hooks();\n
+\n
+    this.legacy = legacy;\n
+\n
+  }\n
+\n
+  PluginHookClass.prototype.add = function (key, fn) {\n
+    //if fn is array, run this for all the array items\n
+    if (Handsontable.helper.isArray(fn)) {\n
+      for (var i = 0, len = fn.length; i < len; i++) {\n
+        this.add(key, fn[i]);\n
+      }\n
+    }\n
+    else {\n
+      // provide support for old versions of HOT\n
+      if (key in legacy) {\n
+        key = legacy[key];\n
+      }\n
+\n
+      if (typeof this.hooks[key] === "undefined") {\n
+        this.hooks[key] = [];\n
+      }\n
+\n
+      if (this.hooks[key].indexOf(fn) == -1) {\n
+        this.hooks[key].push(fn); //only add a hook if it has not already be added (adding the same hook twice is now silently ignored)\n
+      }\n
+    }\n
+    return this;\n
+  };\n
+\n
+  PluginHookClass.prototype.once = function(key, fn){\n
+\n
+    if(Handsontable.helper.isArray(fn)){\n
+\n
+      for(var i = 0, len = fn.length; i < len; i++){\n
+        fn[i].runOnce = true;\n
+        this.add(key, fn[i]);\n
+      }\n
+\n
+    } else {\n
+      fn.runOnce = true;\n
+      this.add(key, fn);\n
+\n
+    }\n
+\n
+  };\n
+\n
+  PluginHookClass.prototype.remove = function (key, fn) {\n
+    var status = false;\n
+\n
+    // provide support for old versions of HOT\n
+    if (key in legacy) {\n
+      key = legacy[key];\n
+    }\n
+\n
+    if (typeof this.hooks[key] !== \'undefined\') {\n
+\n
+      for (var i = 0, leni = this.hooks[key].length; i < leni; i++) {\n
+\n
+        if (this.hooks[key][i] == fn) {\n
+          delete this.hooks[key][i].runOnce;\n
+          this.hooks[key].splice(i, 1);\n
+          status = true;\n
+          break;\n
+        }\n
+\n
+      }\n
+\n
+    }\n
+\n
+    return status;\n
+  };\n
+\n
+  PluginHookClass.prototype.run = function (instance, key, p1, p2, p3, p4, p5) {\n
+\n
+    // provide support for old versions of HOT\n
+    if (key in legacy) {\n
+      key = legacy[key];\n
+    }\n
+\n
+    //performance considerations - http://jsperf.com/call-vs-apply-for-a-plugin-architecture\n
+    if (typeof this.hooks[key] !== \'undefined\') {\n
+\n
+      //Make a copy of handler array\n
+      var handlers = Array.prototype.slice.call(this.hooks[key]);\n
+\n
+      for (var i = 0, leni = handlers.length; i < leni; i++) {\n
+        handlers[i].call(instance, p1, p2, p3, p4, p5);\n
+\n
+        if(handlers[i].runOnce){\n
+          this.remove(key, handlers[i]);\n
+        }\n
+      }\n
+\n
+    }\n
+\n
+  };\n
+\n
+  PluginHookClass.prototype.execute = function (instance, key, p1, p2, p3, p4, p5) {\n
+    var res, handlers;\n
+\n
+    // provide support for old versions of HOT\n
+    if (key in legacy) {\n
+      key = legacy[key];\n
+    }\n
+\n
+    //performance considerations - http://jsperf.com/call-vs-apply-for-a-plugin-architecture\n
+      if (typeof this.hooks[key] !== \'undefined\') {\n
+\n
+        handlers = Array.prototype.slice.call(this.hooks[key]);\n
+\n
+        for (var i = 0, leni = handlers.length; i < leni; i++) {\n
+\n
+          res = handlers[i].call(instance, p1, p2, p3, p4, p5);\n
+          if (res !== void 0) {\n
+            p1 = res;\n
+          }\n
+\n
+          if(handlers[i].runOnce){\n
+            this.remove(key, handlers[i]);\n
+          }\n
+\n
+          if(res === false){ //if any handler returned false\n
+            return false; //event has been cancelled and further execution of handler queue is being aborted\n
+          }\n
+\n
+        }\n
+\n
+      }\n
+\n
+    return p1;\n
+  };\n
+\n
+  return PluginHookClass;\n
+\n
+})();\n
+\n
+Handsontable.PluginHooks = new Handsontable.PluginHookClass();\n
+\n
+(function (Handsontable) {\n
+\n
+  function HandsontableAutoColumnSize() {\n
+    var plugin = this\n
+      , sampleCount = 5; //number of samples to take of each value length\n
+\n
+    this.beforeInit = function () {\n
+      var instance = this;\n
+      instance.autoColumnWidths = [];\n
+\n
+      if (instance.getSettings().autoColumnSize !== false) {\n
+        if (!instance.autoColumnSizeTmp) {\n
+          instance.autoColumnSizeTmp = {\n
+            table: null,\n
+            tableStyle: null,\n
+            theadTh: null,\n
+            tbody: null,\n
+            container: null,\n
+            containerStyle: null,\n
+            determineBeforeNextRender: true\n
+          };\n
+\n
+          instance.addHook(\'beforeRender\', htAutoColumnSize.determineIfChanged);\n
+          instance.addHook(\'afterGetColWidth\', htAutoColumnSize.getColWidth);\n
+          instance.addHook(\'afterDestroy\', htAutoColumnSize.afterDestroy);\n
+\n
+          instance.determineColumnWidth = plugin.determineColumnWidth;\n
+        }\n
+      } else {\n
+        if (instance.autoColumnSizeTmp) {\n
+          instance.removeHook(\'beforeRender\', htAutoColumnSize.determineIfChanged);\n
+          instance.removeHook(\'afterGetColWidth\', htAutoColumnSize.getColWidth);\n
+          instance.removeHook(\'afterDestroy\', htAutoColumnSize.afterDestroy);\n
+\n
+          delete instance.determineColumnWidth;\n
+\n
+          plugin.afterDestroy.call(instance);\n
+        }\n
+      }\n
+    };\n
+\n
+    this.determineIfChanged = function (force) {\n
+      if (force) {\n
+        htAutoColumnSize.determineColumnsWidth.apply(this, arguments);\n
+      }\n
+    };\n
+\n
+    this.determineColumnWidth = function (col) {\n
+      var instance = this\n
+        , tmp = instance.autoColumnSizeTmp;\n
+\n
+      if (!tmp.container) {\n
+        createTmpContainer.call(tmp, instance);\n
+      }\n
+\n
+      tmp.container.className = instance.rootElement[0].className + \' htAutoColumnSize\';\n
+      tmp.table.className = instance.$table[0].className;\n
+\n
+      var rows = instance.countRows();\n
+      var samples = {};\n
+      var maxLen = 0;\n
+      for (var r = 0; r < rows; r++) {\n
+        var value = Handsontable.helper.stringify(instance.getDataAtCell(r, col));\n
+        var len = value.length;\n
+        if (len > maxLen) {\n
+          maxLen = len;\n
+        }\n
+        if (!samples[len]) {\n
+          samples[len] = {\n
+            needed: sampleCount,\n
+            strings: []\n
+          };\n
+        }\n
+        if (samples[len].needed) {\n
+          samples[len].strings.push({value: value, row: r});\n
+          samples[len].needed--;\n
+        }\n
+      }\n
+\n
+      var settings = instance.getSettings();\n
+      if (settings.colHeaders) {\n
+        instance.view.appendColHeader(col, tmp.theadTh); //TH innerHTML\n
+      }\n
+\n
+      instance.view.wt.wtDom.empty(tmp.tbody);\n
+\n
+      for (var i in samples) {\n
+        if (samples.hasOwnProperty(i)) {\n
+          for (var j = 0, jlen = samples[i].strings.length; j < jlen; j++) {\n
+            var row = samples[i].strings[j].row;\n
+\n
+            var cellProperties = instance.getCellMeta(row, col);\n
+            cellProperties.col = col;\n
+            cellProperties.row = row;\n
+\n
+            var renderer = instance.getCellRenderer(cellProperties);\n
+\n
+            var tr = document.createElement(\'tr\');\n
+            var td = document.createElement(\'td\');\n
+\n
+            renderer(instance, td, row, col, instance.colToProp(col), samples[i].strings[j].value, cellProperties);\n
+            r++;\n
+            tr.appendChild(td);\n
+            tmp.tbody.appendChild(tr);\n
+          }\n
+        }\n
+      }\n
+\n
+      var parent = instance.rootElement[0].parentNode;\n
+      parent.appendChild(tmp.container);\n
+      var width = instance.view.wt.wtDom.outerWidth(tmp.table);\n
+      parent.removeChild(tmp.container);\n
+\n
+      if (!settings.nativeScrollbars) { //with native scrollbars a cell size can safely exceed the width of the viewport\n
+        var maxWidth = instance.view.wt.wtViewport.getViewportWidth() - 2; //2 is some overhead for cell border\n
+        if (width > maxWidth) {\n
+          width = maxWidth;\n
+        }\n
+      }\n
+\n
+      return width;\n
+    };\n
+\n
+    this.determineColumnsWidth = function () {\n
+      var instance = this;\n
+      var settings = this.getSettings();\n
+      if (settings.autoColumnSize || !settings.colWidths) {\n
+        var cols = this.countCols();\n
+        for (var c = 0; c < cols; c++) {\n
+          if (!instance._getColWidthFromSettings(c)) {\n
+            this.autoColumnWidths[c] = plugin.determineColumnWidth.call(instance, c);\n
+          }\n
+        }\n
+      }\n
+    };\n
+\n
+    this.getColWidth = function (col, response) {\n
+      if (this.autoColumnWidths[col] && this.autoColumnWidths[col] > response.width) {\n
+        response.width = this.autoColumnWidths[col];\n
+      }\n
+    };\n
+\n
+    this.afterDestroy = function () {\n
+      var instance = this;\n
+      if (instance.autoColumnSizeTmp && instance.autoColumnSizeTmp.container && instance.autoColumnSizeTmp.container.parentNode) {\n
+        instance.autoColumnSizeTmp.container.parentNode.removeChild(instance.autoColumnSizeTmp.container);\n
+      }\n
+      instance.autoColumnSizeTmp = null;\n
+    };\n
+\n
+    function createTmpContainer(instance) {\n
+      var d = document\n
+        , tmp = this;\n
+\n
+      tmp.table = d.createElement(\'table\');\n
+      tmp.theadTh = d.createElement(\'th\');\n
+      tmp.table.appendChild(d.createElement(\'thead\')).appendChild(d.createElement(\'tr\')).appendChild(tmp.theadTh);\n
+\n
+      tmp.tableStyle = tmp.table.style;\n
+      tmp.tableStyle.tableLayout = \'auto\';\n
+      tmp.tableStyle.width = \'auto\';\n
+\n
+      tmp.tbody = d.createElement(\'tbody\');\n
+      tmp.table.appendChild(tmp.tbody);\n
+\n
+      tmp.container = d.createElement(\'div\');\n
+      tmp.container.className = instance.rootElement[0].className + \' hidden\';\n
+      tmp.containerStyle = tmp.container.style;\n
+\n
+      tmp.container.appendChild(tmp.table);\n
+    }\n
+  }\n
+\n
+  var htAutoColumnSize = new HandsontableAutoColumnSize();\n
+\n
+  Handsontable.PluginHooks.add(\'beforeInit\', htAutoColumnSize.beforeInit);\n
+  Handsontable.PluginHooks.add(\'afterUpdateSettings\', htAutoColumnSize.beforeInit);\n
+\n
+})(Handsontable);\n
+\n
+/**\n
+ * This plugin sorts the view by a column (but does not sort the data source!)\n
+ * @constructor\n
+ */\n
+function HandsontableColumnSorting() {\n
+  var plugin = this;\n
+\n
+  this.init = function (source) {\n
+    var instance = this;\n
+    var sortingSettings = instance.getSettings().columnSorting;\n
+    var sortingColumn, sortingOrder;\n
+\n
+    instance.sortingEnabled = !!(sortingSettings);\n
+\n
+    if (instance.sortingEnabled) {\n
+      instance.sortIndex = [];\n
+\n
+      var loadedSortingState = loadSortingState.call(instance);\n
+\n
+      if (typeof loadedSortingState != \'undefined\') {\n
+        sortingColumn = loadedSortingState.sortColumn;\n
+        sortingOrder = loadedSortingState.sortOrder;\n
+      } else {\n
+        sortingColumn = sortingSettings.column;\n
+        sortingOrder = sortingSettings.sortOrder;\n
+      }\n
+      plugin.sortByColumn.call(instance, sortingColumn, sortingOrder);\n
+\n
+      instance.sort = function(){\n
+        var args = Array.prototype.slice.call(arguments);\n
+\n
+        return plugin.sortByColumn.apply(instance, args)\n
+      };\n
+\n
+      if (typeof instance.getSettings().observeChanges == \'undefined\'){\n
+        enableObserveChangesPlugin.call(instance);\n
+      }\n
+\n
+      if (source == \'afterInit\') {\n
+        bindColumnSortingAfterClick.call(instance);\n
+\n
+        instance.addHook(\'afterCreateRow\', plugin.afterCreateRow);\n
+        instance.addHook(\'afterRemoveRow\', plugin.afterRemoveRow);\n
+        instance.addHook(\'afterLoadData\', plugin.init);\n
+      }\n
+    } else {\n
+      delete instance.sort;\n
+\n
+      instance.removeHook(\'afterCreateRow\', plugin.afterCreateRow);\n
+      instance.removeHook(\'afterRemoveRow\', plugin.afterRemoveRow);\n
+      instance.removeHook(\'afterLoadData\', plugin.init);\n
+    }\n
+  };\n
+\n
+  this.setSortingColumn = function (col, order) {\n
+    var instance = this;\n
+\n
+    if (typeof col == \'undefined\') {\n
+      delete instance.sortColumn;\n
+      delete instance.sortOrder;\n
+\n
+      return;\n
+    } else if (instance.sortColumn === col && typeof order == \'undefined\') {\n
+      instance.sortOrder = !instance.sortOrder;\n
+    } else {\n
+      instance.sortOrder = typeof order != \'undefined\' ? order : true;\n
+    }\n
+\n
+    instance.sortColumn = col;\n
+\n
+  };\n
+\n
+  this.sortByColumn = function (col, order) {\n
+    var instance = this;\n
+\n
+    plugin.setSortingColumn.call(instance, col, order);\n
+\n
+    if(typeof instance.sortColumn == \'undefined\'){\n
+      return;\n
+    }\n
+\n
+    instance.PluginHooks.run(\'beforeColumnSort\', instance.sortColumn, instance.sortOrder);\n
+\n
+    plugin.sort.call(instance);\n
+    instance.render();\n
+\n
+    saveSortingState.call(instance);\n
+\n
+    instance.PluginHooks.run(\'afterColumnSort\', instance.sortColumn, instance.sortOrder);\n
+  };\n
+\n
+  var saveSortingState = function () {\n
+    var instance = this;\n
+\n
+    var sortingState = {};\n
+\n
+    if (typeof instance.sortColumn != \'undefined\') {\n
+      sortingState.sortColumn = instance.sortColumn;\n
+    }\n
+\n
+    if (typeof instance.sortOrder != \'undefined\') {\n
+      sortingState.sortOrder = instance.sortOrder;\n
+    }\n
+\n
+    if (sortingState.hasOwnProperty(\'sortColumn\') || sortingState.hasOwnProperty(\'sortOrder\')) {\n
+      instance.PluginHooks.run(\'persistentStateSave\', \'columnSorting\', sortingState);\n
+    }\n
+\n
+  };\n
+\n
+  var loadSortingState = function () {\n
+    var instance = this;\n
+    var storedState = {};\n
+    instance.PluginHooks.run(\'persistentStateLoad\', \'columnSorting\', storedState);\n
+\n
+    return storedState.value;\n
+  };\n
+\n
+  var bindColumnSortingAfterClick = function () {\n
+    var instance = this;\n
+\n
+    instance.rootElement.on(\'click.handsontable\', \'.columnSorting\', function (e) {\n
+      if (instance.view.wt.wtDom.hasClass(e.target, \'columnSorting\')) {\n
+        var col = getColumn(e.target);\n
+        plugin.sortByColumn.call(instance, col);\n
+      }\n
+    });\n
+\n
+    function countRowHeaders() {\n
+      var THs = instance.view.TBODY.querySelector(\'tr\').querySelectorAll(\'th\');\n
+      return THs.length;\n
+    }\n
+\n
+    function getColumn(target) {\n
+      var TH = instance.view.wt.wtDom.closest(target, \'TH\');\n
+      return instance.view.wt.wtDom.index(TH) - countRowHeaders();\n
+    }\n
+  };\n
+\n
+  function enableObserveChangesPlugin () {\n
+    var instance = this;\n
+    instance.registerTimeout(\'enableObserveChanges\', function(){\n
+      instance.updateSettings({\n
+        observeChanges: true\n
+      });\n
+    }, 0);\n
+  }\n
+\n
+  function defaultSort(sortOrder) {\n
+    return function (a, b) {\n
+      if (a[1] === b[1]) {\n
+        return 0;\n
+      }\n
+      if (a[1] === null) {\n
+        return 1;\n
+      }\n
+      if (b[1] === null) {\n
+        return -1;\n
+      }\n
+      if (a[1] < b[1]) return sortOrder ? -1 : 1;\n
+      if (a[1] > b[1]) return sortOrder ? 1 : -1;\n
+      return 0;\n
+    }\n
+  }\n
+\n
+  function dateSort(sortOrder) {\n
+    return function (a, b) {\n
+      if (a[1] === b[1]) {\n
+        return 0;\n
+      }\n
+      if (a[1] === null) {\n
+        return 1;\n
+      }\n
+      if (b[1] === null) {\n
+        return -1;\n
+      }\n
+\n
+      var aDate = new Date(a[1]);\n
+      var bDate = new Date(b[1]);\n
+\n
+      if (aDate < bDate) return sortOrder ? -1 : 1;\n
+      if (aDate > bDate) return sortOrder ? 1 : -1;\n
+\n
+      return 0;\n
+    }\n
+  }\n
+\n
+  this.sort = function () {\n
+    var instance = this;\n
+\n
+    if (typeof instance.sortOrder == \'undefined\') {\n
+      return;\n
+    }\n
+\n
+    instance.sortingEnabled = false; //this is required by translateRow plugin hook\n
+    instance.sortIndex.length = 0;\n
+\n
+    var colOffset = this.colOffset();\n
+    for (var i = 0, ilen = this.countRows() - instance.getSettings()[\'minSpareRows\']; i < ilen; i++) {\n
+      this.sortIndex.push([i, instance.getDataAtCell(i, this.sortColumn + colOffset)]);\n
+    }\n
+\n
+    var colMeta = instance.getCellMeta(0, instance.sortColumn);\n
+    var sortFunction;\n
+    switch (colMeta.type) {\n
+      case \'date\':\n
+        sortFunction = dateSort;\n
+        break;\n
+      default:\n
+        sortFunction = defaultSort;\n
+    }\n
+\n
+    this.sortIndex.sort(sortFunction(instance.sortOrder));\n
+\n
+    //Append spareRows\n
+    for(var i = this.sortIndex.length; i < instance.countRows(); i++){\n
+      this.sortIndex.push([i, instance.getDataAtCell(i, this.sortColumn + colOffset)]);\n
+    }\n
+\n
+    instance.sortingEnabled = true; //this is required by translateRow plugin hook\n
+  };\n
+\n
+  this.translateRow = function (row) {\n
+    var instance = this;\n
+\n
+    if (instance.sortingEnabled && instance.sortIndex && instance.sortIndex.length && instance.sortIndex[row]) {\n
+      return instance.sortIndex[row][0];\n
+    }\n
+\n
+    return row;\n
+  };\n
+\n
+  this.onBeforeGetSet = function (getVars) {\n
+    var instance = this;\n
+    getVars.row = plugin.translateRow.call(instance, getVars.row);\n
+  };\n
+\n
+  this.untranslateRow = function (row) {\n
+    var instance = this;\n
+    if (instance.sortingEnabled && instance.sortIndex && instance.sortIndex.length) {\n
+      for (var i = 0; i < instance.sortIndex.length; i++) {\n
+        if (instance.sortIndex[i][0] == row) {\n
+          return i;\n
+        }\n
+      }\n
+    }\n
+  };\n
+\n
+  this.getColHeader = function (col, TH) {\n
+    if (this.getSettings().columnSorting) {\n
+      this.view.wt.wtDom.addClass(TH.querySelector(\'.colHeader\'), \'columnSorting\');\n
+    }\n
+  };\n
+\n
+  function isSorted(instance){\n
+    return typeof instance.sortColumn != \'undefined\';\n
+  }\n
+\n
+  this.afterCreateRow = function(index, amount){\n
+    var instance = this;\n
+\n
+    if(!isSorted(instance)){\n
+      return;\n
+    }\n
+\n
+\n
+    for(var i = 0; i < instance.sortIndex.length; i++){\n
+      if (instance.sortIndex[i][0] >= index){\n
+        instance.sortIndex[i][0] += amount;\n
+      }\n
+    }\n
+\n
+    for(var i=0; i < amount; i++){\n
+      instance.sortIndex.splice(index+i, 0, [index+i, instance.getData()[index+i][instance.sortColumn + instance.colOffset()]]);\n
+    }\n
+\n
+\n
+\n
+    saveSortingState.call(instance);\n
+\n
+  };\n
+\n
+  this.afterRemoveRow = function(index, amount){\n
+    var instance = this;\n
+\n
+    if(!isSorted(instance)){\n
+      return;\n
+    }\n
+\n
+    var physicalRemovedIndex = plugin.translateRow.call(instance, index);\n
+\n
+    instance.sortIndex.splice(index, amount);\n
+\n
+    for(var i = 0; i < instance.sortIndex.length; i++){\n
+\n
+      if (instance.sortIndex[i][0] > physicalRemovedIndex){\n
+        instance.sortIndex[i][0] -= amount;\n
+      }\n
+    }\n
+\n
+    saveSortingState.call(instance);\n
+\n
+  };\n
+\n
+  this.afterChangeSort = function (changes/*, source*/) {\n
+    var instance = this;\n
+    var sortColumnChanged = false;\n
+    var selection = {};\n
+    if (!changes) {\n
+      return;\n
+    }\n
+\n
+    for (var i = 0; i < changes.length; i++) {\n
+      if (changes[i][1] == instance.sortColumn) {\n
+        sortColumnChanged = true;\n
+        selection.row = plugin.translateRow.call(instance, changes[i][0]);\n
+        selection.col = changes[i][1];\n
+        break;\n
+      }\n
+    }\n
+\n
+    if (sortColumnChanged) {\n
+      setTimeout(function () {\n
+        plugin.sort.call(instance);\n
+        instance.render();\n
+        instance.selectCell(plugin.untranslateRow.call(instance, selection.row), selection.col);\n
+      }, 0);\n
+    }\n
+  };\n
+}\n
+var htSortColumn = new HandsontableColumnSorting();\n
+\n
+Handsontable.PluginHooks.add(\'afterInit\', function () {\n
+  htSortColumn.init.call(this, \'afterInit\')\n
+});\n
+Handsontable.PluginHooks.add(\'afterUpdateSettings\', function () {\n
+  htSortColumn.init.call(this, \'afterUpdateSettings\')\n
+});\n
+Handsontable.PluginHooks.add(\'beforeGet\', htSortColumn.onBeforeGetSet);\n
+Handsontable.PluginHooks.add(\'beforeSet\', htSortColumn.onBeforeGetSet);\n
+Handsontable.PluginHooks.add(\'afterGetColHeader\', htSortColumn.getColHeader);\n
+\n
+\n
+(function (Handsontable) {\n
+  \'use strict\';\n
+\n
+  function ContextMenu(instance, customOptions){\n
+    this.instance = instance;\n
+    var contextMenu = this;\n
+\n
+    this.menu = createMenu();\n
+    this.enabled = true;\n
+\n
+    this.bindMouseEvents();\n
+    this.bindTableEvents();\n
+\n
+    this.instance.addHook(\'afterDestroy\', function () {\n
+       contextMenu.destroy();\n
+    });\n
+\n
+    this.defaultOptions = {\n
+      items: {\n
+        \'row_above\': {\n
+          name: \'Insert row above\',\n
+          callback: function(key, selection){\n
+            this.alter("insert_row", selection.start.row());\n
+          },\n
+          disabled: function () {\n
+            return this.countRows() >= this.getSettings().maxRows;\n
+          }\n
+        },\n
+        \'row_below\': {\n
+          name: \'Insert row below\',\n
+          callback: function(key, selection){\n
+            this.alter("insert_row", selection.end.row() + 1);\n
+          },\n
+          disabled: function () {\n
+            return this.countRows() >= this.getSettings().maxRows;\n
+          }\n
+        },\n
+        "hsep1": ContextMenu.SEPARATOR,\n
+        \'col_left\': {\n
+          name: \'Insert column on the left\',\n
+          callback: function(key, selection){\n
+            this.alter("insert_col", selection.start.col());\n
+          },\n
+          disabled: function () {\n
+            return this.countCols() >= this.getSettings().maxCols;\n
+          }\n
+        },\n
+        \'col_right\': {\n
+          name: \'Insert column on the right\',\n
+          callback: function(key, selection){\n
+            this.alter("insert_col", selection.end.col() + 1);\n
+          },\n
+          disabled: function () {\n
+            return this.countCols() >= this.getSettings().maxCols;\n
+          }\n
+        },\n
+        "hsep2": ContextMenu.SEPARATOR,\n
+        \'remove_row\': {\n
+          name: \'Remove row\',\n
+          callback: function(key, selection){\n
+            var amount = selection.end.row() - selection.start.row() + 1;\n
+            this.alter("remove_row", selection.start.row(), amount);\n
+          }\n
+        },\n
+        \'remove_col\': {\n
+          name: \'Remove column\',\n
+          callback: function(key, selection){\n
+            var amount = selection.end.col() - selection.start.col() + 1;\n
+            this.alter("remove_col", selection.start.col(), amount);\n
+          }\n
+        },\n
+        "hsep3": ContextMenu.SEPARATOR,\n
+        \'undo\': {\n
+          name: \'Undo\',\n
+          callback: function(){\n
+            this.undo();\n
+          },\n
+          disabled: function () {\n
+            return this.undoRedo && !this.undoRedo.isUndoAvailable();\n
+          }\n
+        },\n
+        \'redo\': {\n
+          name: \'Redo\',\n
+          callback: function(){\n
+            this.redo();\n
+          },\n
+          disabled: function () {\n
+            return this.undoRedo && !this.undoRedo.isRedoAvailable();\n
+          }\n
+        }\n
+\n
+      }\n
+    };\n
+\n
+    this.options = {};\n
+    Handsontable.helper.extend(this.options, this.defaultOptions);\n
+\n
+    this.updateOptions(customOptions);\n
+\n
+    function createMenu(){\n
+\n
+      var menu = $(\'body > .htContextMenu\')[0];\n
+\n
+      if(!menu){\n
+        menu = document.createElement(\'DIV\');\n
+        Handsontable.Dom.addClass(menu, \'htContextMenu\');\n
+        document.getElementsByTagName(\'body\')[0].appendChild(menu);\n
+      }\n
+\n
+      return menu;\n
+    }\n
+  }\n
+\n
+  ContextMenu.prototype.bindMouseEvents = function (){\n
+\n
+    function contextMenuOpenListener(event){\n
+\n
+      event.preventDefault();\n
+\n
+      if(event.target.nodeName != \'TD\' && !(Handsontable.Dom.hasClass(event.target, \'current\') && Handsontable.Dom.hasClass(event.target, \'wtBorder\'))){\n
+        return;\n
+      }\n
+\n
+      this.show(event.pageY, event.pageX);\n
+\n
+      $(document).on(\'mousedown.htContextMenu\', Handsontable.helper.proxy(ContextMenu.prototype.close, this));\n
+    }\n
+\n
+    this.instance.rootElement.on(\'contextmenu.htContextMenu\', Handsontable.helper.proxy(contextMenuOpenListener, this));\n
+\n
+  };\n
+\n
+  ContextMenu.prototype.bindTableEvents = function () {\n
+    var that = this;\n
+\n
+    this._afterScrollCallback = function () {\n
+      that.close();\n
+    };\n
+\n
+    this.instance.addHook(\'afterScrollVertically\', this._afterScrollCallback);\n
+    this.instance.addHook(\'afterScrollHorizontally\', this._afterScrollCallback);\n
+  };\n
+\n
+  ContextMenu.prototype.unbindTableEvents = function () {\n
+    var that = this;\n
+\n
+    if(this._afterScrollCallback){\n
+      this.instance.removeHook(\'afterScrollVertically\', this._afterScrollCallback);\n
+      this.instance.removeHook(\'afterScrollHorizontally\', this._afterScrollCallback);\n
+      this._afterScrollCallback = null;\n
+    }\n
+\n
+\n
+  };\n
+\n
+  ContextMenu.prototype.performAction = function (){\n
+\n
+    var hot = $(this.menu).handsontable(\'getInstance\');\n
+    var selectedItemIndex = hot.getSelected()[0];\n
+    var selectedItem = hot.getData()[selectedItemIndex];\n
+\n
+    if (selectedItem.disabled === true || (typeof selectedItem.disabled == \'function\' && selectedItem.disabled.call(this.instance) === true)){\n
+      return;\n
+    }\n
+\n
+    if(typeof selectedItem.callback != \'function\'){\n
+      return;\n
+    }\n
+\n
+    var corners = this.instance.getSelected();\n
+    var normalizedSelection = ContextMenu.utils.normalizeSelection(corners);\n
+\n
+    selectedItem.callback.call(this.instance, selectedItem.key, normalizedSelection);\n
+\n
+  };\n
+\n
+  ContextMenu.prototype.unbindMouseEvents = function () {\n
+    this.instance.rootElement.off(\'contextmenu.htContextMenu\');\n
+    $(document).off(\'mousedown.htContextMenu\');\n
+  };\n
+\n
+  ContextMenu.prototype.show = function(top, left){\n
+\n
+    this.menu.style.display = \'block\';\n
+\n
+    $(this.menu)\n
+      .off(\'mousedown.htContextMenu\')\n
+      .on(\'mousedown.htContextMenu\', Handsontable.helper.proxy(this.performAction, this));\n
+\n
+    $(this.menu).handsontable({\n
+      data: ContextMenu.utils.convertItemsToArray(this.getItems()),\n
+      colHeaders: false,\n
+      colWidths: [160],\n
+      readOnly: true,\n
+      copyPaste: false,\n
+      columns: [\n
+        {\n
+          data: \'name\',\n
+          renderer: Handsontable.helper.proxy(this.renderer, this)\n
+        }\n
+      ],\n
+      beforeKeyDown: Handsontable.helper.proxy(this.onBeforeKeyDown, this)\n
+    });\n
+    this.bindTableEvents();\n
+\n
+    this.setMenuPosition(top, left);\n
+\n
+    $(this.menu).handsontable(\'listen\');\n
+\n
+  };\n
+\n
+  ContextMenu.prototype.close = function () {\n
+    this.hide();\n
+    $(document).off(\'mousedown.htContextMenu\');\n
+    this.unbindTableEvents();\n
+    this.instance.listen();\n
+  };\n
+\n
+  ContextMenu.prototype.hide = function(){\n
+    this.menu.style.display = \'none\';\n
+    $(this.menu).handsontable(\'destroy\');\n
+  };\n
+\n
+  ContextMenu.prototype.renderer = function(instance, TD, row, col, prop, value, cellProperties){\n
+    var contextMenu = this;\n
+    var item = instance.getData()[row];\n
+    var wrapper = document.createElement(\'DIV\');\n
+\n
+    Handsontable.Dom.empty(TD);\n
+    TD.appendChild(wrapper);\n
+\n
+    if(itemIsSeparator(item)){\n
+      Handsontable.Dom.addClass(TD, \'htSeparator\');\n
+    } else {\n
+      Handsontable.Dom.fastInnerText(wrapper, value);\n
+    }\n
+\n
+    if (itemIsDisabled(item, contextMenu.instance)){\n
+      Handsontable.Dom.addClass(TD, \'htDisabled\');\n
+\n
+      $(wrapper).on(\'mouseenter\', function () {\n
+        instance.deselectCell();\n
+      });\n
+\n
+    } else {\n
+      Handsontable.Dom.removeClass(TD, \'htDisabled\');\n
+\n
+      $(wrapper).on(\'mouseenter\', function () {\n
+        instance.selectCell(row, col);\n
+      });\n
+\n
+    }\n
+\n
+    function itemIsSeparator(item){\n
+      return new RegExp(ContextMenu.SEPARATOR, \'i\').test(item.name);\n
+    }\n
+\n
+    function itemIsDisabled(item, instance){\n
+      return item.disabled === true || (typeof item.disabled == \'function\' && item.disabled.call(contextMenu.instance) === true);\n
+    }\n
+  };\n
+\n
+  ContextMenu.prototype.onBeforeKeyDown = function (event) {\n
+    var contextMenu = this;\n
+    var instance = $(contextMenu.menu).handsontable(\'getInstance\');\n
+    var selection = instance.getSelected();\n
+\n
+    switch(event.keyCode){\n
+\n
+      case Handsontable.helper.keyCode.ESCAPE:\n
+        contextMenu.close();\n
+        event.preventDefault();\n
+        event.stopImmediatePropagation();\n
+        break;\n
+\n
+      case Handsontable.helper.keyCode.ENTER:\n
+        if(instance.getSelected()){\n
+          contextMenu.performAction();\n
+          contextMenu.close();\n
+        }\n
+        break;\n
+\n
+      case Handsontable.helper.keyCode.ARROW_DOWN:\n
+        if(!selection){\n
+\n
+          selectFirstCell(instance);\n
+\n
+        } else {\n
+\n
+          selectNextCell(selection[0], selection[1], instance);\n
+\n
+        }\n
+\n
+        event.preventDefault();\n
+        event.stopImmediatePropagation();\n
+\n
+        break;\n
+\n
+      case Handsontable.helper.keyCode.ARROW_UP:\n
+        if(!selection){\n
+\n
+          selectLastCell(instance);\n
+\n
+        }  else {\n
+\n
+          selectPrevCell(selection[0], selection[1], instance);\n
+\n
+        }\n
+\n
+        event.preventDefault();\n
+        event.stopImmediatePropagation();\n
+\n
+        break;\n
+\n
+    }\n
+\n
+    function selectFirstCell(instance) {\n
+\n
+      var firstCell = instance.getCell(0, 0);\n
+\n
+      if(ContextMenu.utils.isSeparator(firstCell) || ContextMenu.utils.isDisabled(firstCell)){\n
+        selectNextCell(0, 0, instance);\n
+      } else {\n
+        instance.selectCell(0, 0);\n
+      }\n
+\n
+    }\n
+\n
+\n
+    function selectLastCell(instance) {\n
+\n
+      var lastRow = instance.countRows() - 1;\n
+      var lastCell = instance.getCell(lastRow, 0);\n
+\n
+      if(ContextMenu.utils.isSeparator(lastCell) || ContextMenu.utils.isDisabled(lastCell)){\n
+        selectPrevCell(lastRow, 0, instance);\n
+      } else {\n
+        instance.selectCell(lastRow, 0);\n
+      }\n
+\n
+    }\n
+\n
+    function selectNextCell(row, col, instance){\n
+      var nextRow = row + 1;\n
+      var nextCell =  nextRow < instance.countRows() ? instance.getCell(nextRow, col) : null;\n
+\n
+      if(!nextCell){\n
+        return;\n
+      }\n
+\n
+      if(ContextMenu.utils.isSeparator(nextCell) || ContextMenu.utils.isDisabled(nextCell)){\n
+        selectNextCell(nextRow, col, instance);\n
+      } else {\n
+        instance.selectCell(nextRow, col);\n
+      }\n
+    }\n
+\n
+    function selectPrevCell(row, col, instance) {\n
+\n
+      var prevRow = row - 1;\n
+      var prevCell = prevRow >= 0 ? instance.getCell(prevRow, col) : null;\n
+\n
+      if (!prevCell) {\n
+        return;\n
+      }\n
+\n
+      if(ContextMenu.utils.isSeparator(prevCell) || ContextMenu.utils.isDisabled(prevCell)){\n
+        selectPrevCell(prevRow, col, instance);\n
+      } else {\n
+        instance.selectCell(prevRow, col);\n
+      }\n
+\n
+    }\n
+\n
+  };\n
+\n
+  ContextMenu.prototype.getItems = function () {\n
+    var items = {};\n
+    function Item(rawItem){\n
+      if(typeof rawItem == \'string\'){\n
+        this.name = rawItem;\n
+      } else {\n
+        Handsontable.helper.extend(this, rawItem);\n
+      }\n
+    }\n
+    Item.prototype = this.options;\n
+\n
+    for(var itemName in this.options.items)
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="5" aka="AAAAAAAAAAU=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+{\n
+      if(this.options.items.hasOwnProperty(itemName) && (!this.itemsFilter || this.itemsFilter.indexOf(itemName) != -1)){\n
+        items[itemName] = new Item(this.options.items[itemName]);\n
+      }\n
+    }\n
+\n
+    return items;\n
+\n
+  };\n
+\n
+  ContextMenu.prototype.updateOptions = function(newOptions){\n
+    newOptions = newOptions || {};\n
+\n
+    if(newOptions.items){\n
+      for(var itemName in newOptions.items){\n
+        var item = {};\n
+\n
+        if(newOptions.items.hasOwnProperty(itemName)) {\n
+          if(this.defaultOptions.items.hasOwnProperty(itemName)\n
+            && Handsontable.helper.isObject(newOptions.items[itemName])){\n
+            Handsontable.helper.extend(item, this.defaultOptions.items[itemName]);\n
+            Handsontable.helper.extend(item, newOptions.items[itemName]);\n
+            newOptions.items[itemName] = item;\n
+          }\n
+        }\n
+\n
+      }\n
+    }\n
+\n
+    Handsontable.helper.extend(this.options, newOptions);\n
+  };\n
+\n
+  ContextMenu.prototype.setMenuPosition = function (cursorY, cursorX) {\n
+\n
+    var cursor = {\n
+      top:  cursorY,\n
+      topRelative: cursorY - document.documentElement.scrollTop,\n
+      left: cursorX,\n
+      leftRelative:cursorX - document.documentElement.scrollLeft\n
+    };\n
+\n
+    if(this.menuFitsBelowCursor(cursor)){\n
+      this.positionMenuBelowCursor(cursor);\n
+    } else {\n
+      this.positionMenuAboveCursor(cursor);\n
+    }\n
+\n
+    if(this.menuFitsOnRightOfCursor(cursor)){\n
+      this.positionMenuOnRightOfCursor(cursor);\n
+    } else {\n
+      this.positionMenuOnLeftOfCursor(cursor);\n
+    }\n
+\n
+  };\n
+\n
+  ContextMenu.prototype.menuFitsBelowCursor = function (cursor) {\n
+    return cursor.topRelative + this.menu.offsetHeight <= document.documentElement.scrollTop + document.documentElement.clientHeight;\n
+  };\n
+\n
+  ContextMenu.prototype.menuFitsOnRightOfCursor = function (cursor) {\n
+    return cursor.leftRelative + this.menu.offsetWidth <= document.documentElement.scrollLeft + document.documentElement.clientWidth;\n
+  };\n
+\n
+  ContextMenu.prototype.positionMenuBelowCursor = function (cursor) {\n
+    this.menu.style.top = cursor.top + \'px\';\n
+  };\n
+\n
+  ContextMenu.prototype.positionMenuAboveCursor = function (cursor) {\n
+    this.menu.style.top = (cursor.top - this.menu.offsetHeight) + \'px\';\n
+  };\n
+\n
+  ContextMenu.prototype.positionMenuOnRightOfCursor = function (cursor) {\n
+    this.menu.style.left = cursor.left + \'px\';\n
+  };\n
+\n
+  ContextMenu.prototype.positionMenuOnLeftOfCursor = function (cursor) {\n
+    this.menu.style.left = (cursor.left - this.menu.offsetWidth) + \'px\';\n
+  };\n
+\n
+  ContextMenu.utils = {};\n
+  ContextMenu.utils.convertItemsToArray = function (items) {\n
+    var itemArray = [];\n
+    var item;\n
+    for(var itemName in items){\n
+      if(items.hasOwnProperty(itemName)){\n
+        if(typeof items[itemName] == \'string\'){\n
+          item = {name: items[itemName]};\n
+        } else if (items[itemName].visible !== false) {\n
+          item = items[itemName];\n
+        } else {\n
+          continue;\n
+        }\n
+\n
+        item.key = itemName;\n
+        itemArray.push(item);\n
+      }\n
+    }\n
+\n
+    return itemArray;\n
+  };\n
+\n
+  ContextMenu.utils.normalizeSelection = function(corners){\n
+    var selection = {\n
+      start: new Handsontable.SelectionPoint(),\n
+      end: new Handsontable.SelectionPoint()\n
+    };\n
+\n
+    selection.start.row(Math.min(corners[0], corners[2]));\n
+    selection.start.col(Math.min(corners[1], corners[3]));\n
+\n
+    selection.end.row(Math.max(corners[0], corners[2]));\n
+    selection.end.col(Math.max(corners[1], corners[3]));\n
+\n
+    return selection;\n
+  };\n
+\n
+  ContextMenu.utils.isSeparator = function (cell) {\n
+    return Handsontable.Dom.hasClass(cell, \'htSeparator\');\n
+  };\n
+\n
+  ContextMenu.utils.isDisabled = function (cell) {\n
+    return Handsontable.Dom.hasClass(cell, \'htDisabled\');\n
+  };\n
+\n
+  ContextMenu.prototype.enable = function () {\n
+    if(!this.enabled){\n
+      this.enabled = true;\n
+      this.bindMouseEvents();\n
+    }\n
+  };\n
+\n
+  ContextMenu.prototype.disable = function () {\n
+    if(this.enabled){\n
+      this.enabled = false;\n
+      this.close();\n
+      this.unbindMouseEvents();\n
+      this.unbindTableEvents();\n
+    }\n
+  };\n
+\n
+  ContextMenu.prototype.destroy = function () {\n
+    this.close();\n
+    this.unbindMouseEvents();\n
+    this.unbindTableEvents();\n
+\n
+    if(!this.isMenuEnabledByOtherHotInstance()){\n
+      this.removeMenu();\n
+    }\n
+\n
+  };\n
+\n
+  ContextMenu.prototype.isMenuEnabledByOtherHotInstance = function () {\n
+    var hotContainers = $(\'.handsontable\');\n
+    var menuEnabled = false;\n
+\n
+    for(var i = 0, len = hotContainers.length; i < len; i++){\n
+      var instance = $(hotContainers[i]).handsontable(\'getInstance\');\n
+      if(instance && instance.getSettings().contextMenu){\n
+        menuEnabled = true;\n
+        break;\n
+      }\n
+    }\n
+\n
+    return menuEnabled;\n
+  };\n
+\n
+  ContextMenu.prototype.removeMenu = function () {\n
+    if(this.menu.parentNode){\n
+      this.menu.parentNode.removeChild(this.menu);\n
+    }\n
+  }\n
+\n
+  ContextMenu.prototype.filterItems = function(itemsToLeave){\n
+    this.itemsFilter = itemsToLeave;\n
+  };\n
+\n
+  ContextMenu.SEPARATOR = "---------";\n
+\n
+  function init(){\n
+    var instance = this;\n
+    var contextMenuSetting = instance.getSettings().contextMenu;\n
+    var customOptions = Handsontable.helper.isObject(contextMenuSetting) ? contextMenuSetting : {};\n
+\n
+    if(contextMenuSetting){\n
+      if(!instance.contextMenu){\n
+        instance.contextMenu = new ContextMenu(instance, customOptions);\n
+      }\n
+\n
+      instance.contextMenu.enable();\n
+\n
+      if(Handsontable.helper.isArray(contextMenuSetting)){\n
+        instance.contextMenu.filterItems(contextMenuSetting);\n
+      }\n
+\n
+    }  else if(instance.contextMenu){\n
+      instance.contextMenu.destroy();\n
+      delete instance.contextMenu;\n
+    }\n
+\n
+\n
+\n
+  }\n
+\n
+  Handsontable.PluginHooks.add(\'afterInit\', init);\n
+  Handsontable.PluginHooks.add(\'afterUpdateSettings\', init);\n
+\n
+  Handsontable.ContextMenu = ContextMenu;\n
+\n
+})(Handsontable);\n
+\n
+/**\n
+ * This plugin adds support for legacy features, deprecated APIs, etc.\n
+ */\n
+\n
+/**\n
+ * Support for old autocomplete syntax\n
+ * For old syntax, see: https://github.com/warpech/jquery-handsontable/blob/8c9e701d090ea4620fe08b6a1a048672fadf6c7e/README.md#defining-autocomplete\n
+ */\n
+Handsontable.PluginHooks.add(\'beforeGetCellMeta\', function (row, col, cellProperties) {\n
+  //isWritable - deprecated since 0.8.0\n
+  cellProperties.isWritable = !cellProperties.readOnly;\n
+\n
+  //autocomplete - deprecated since 0.7.1 (see CHANGELOG.md)\n
+  if (cellProperties.autoComplete) {\n
+    throw new Error("Support for legacy autocomplete syntax was removed in Handsontable 0.10.0. Please remove the property named \'autoComplete\' from your config. For replacement instructions, see wiki page https://github.com/warpech/jquery-handsontable/wiki/Migration-guide-to-0.10.x");\n
+  }\n
+});\n
+function HandsontableManualColumnMove() {\n
+  var pressed\n
+    , startCol\n
+    , endCol\n
+    , startX\n
+    , startOffset;\n
+\n
+  var ghost = document.createElement(\'DIV\')\n
+    , ghostStyle = ghost.style;\n
+\n
+  ghost.className = \'ghost\';\n
+  ghostStyle.position = \'absolute\';\n
+  ghostStyle.top = \'25px\';\n
+  ghostStyle.left = 0;\n
+  ghostStyle.width = \'10px\';\n
+  ghostStyle.height = \'10px\';\n
+  ghostStyle.backgroundColor = \'#CCC\';\n
+  ghostStyle.opacity = 0.7;\n
+\n
+  var saveManualColumnPositions = function () {\n
+    var instance = this;\n
+\n
+    instance.PluginHooks.run(\'persistentStateSave\', \'manualColumnPositions\', instance.manualColumnPositions);\n
+  };\n
+\n
+  var loadManualColumnPositions = function () {\n
+    var instance = this;\n
+    var storedState = {};\n
+    instance.PluginHooks.run(\'persistentStateLoad\', \'manualColumnPositions\', storedState);\n
+\n
+    return storedState.value;\n
+  };\n
+\n
+\n
+  var bindMoveColEvents = function () {\n
+    var instance = this;\n
+\n
+    instance.rootElement.on(\'mousemove.manualColumnMove\', function (e) {\n
+      if (pressed) {\n
+        ghostStyle.left = startOffset + e.pageX - startX + 6 + \'px\';\n
+        if (ghostStyle.display === \'none\') {\n
+          ghostStyle.display = \'block\';\n
+        }\n
+      }\n
+    });\n
+\n
+    instance.rootElement.on(\'mouseup.manualColumnMove\', function () {\n
+      if (pressed) {\n
+        if (startCol < endCol) {\n
+          endCol--;\n
+        }\n
+        if (instance.getSettings().rowHeaders) {\n
+          startCol--;\n
+          endCol--;\n
+        }\n
+        instance.manualColumnPositions.splice(endCol, 0, instance.manualColumnPositions.splice(startCol, 1)[0]);\n
+        $(\'.manualColumnMover.active\').removeClass(\'active\');\n
+        pressed = false;\n
+        instance.forceFullRender = true;\n
+        instance.view.render(); //updates all\n
+        ghostStyle.display = \'none\';\n
+\n
+        saveManualColumnPositions.call(instance);\n
+\n
+        instance.PluginHooks.run(\'afterColumnMove\', startCol, endCol);\n
+      }\n
+    });\n
+\n
+    instance.rootElement.on(\'mousedown.manualColumnMove\', \'.manualColumnMover\', function (e) {\n
+\n
+      var mover = e.currentTarget;\n
+      var TH = instance.view.wt.wtDom.closest(mover, \'TH\');\n
+      startCol = instance.view.wt.wtDom.index(TH) + instance.colOffset();\n
+      endCol = startCol;\n
+      pressed = true;\n
+      startX = e.pageX;\n
+\n
+      var TABLE = instance.$table[0];\n
+      TABLE.parentNode.appendChild(ghost);\n
+      ghostStyle.width = instance.view.wt.wtDom.outerWidth(TH) + \'px\';\n
+      ghostStyle.height = instance.view.wt.wtDom.outerHeight(TABLE) + \'px\';\n
+      startOffset = parseInt(instance.view.wt.wtDom.offset(TH).left - instance.view.wt.wtDom.offset(TABLE).left, 10);\n
+      ghostStyle.left = startOffset + 6 + \'px\';\n
+    });\n
+\n
+    instance.rootElement.on(\'mouseenter.manualColumnMove\', \'td, th\', function () {\n
+      if (pressed) {\n
+        var active = instance.view.THEAD.querySelector(\'.manualColumnMover.active\');\n
+        if (active) {\n
+          instance.view.wt.wtDom.removeClass(active, \'active\');\n
+        }\n
+        endCol = instance.view.wt.wtDom.index(this) + instance.colOffset();\n
+        var THs = instance.view.THEAD.querySelectorAll(\'th\');\n
+        var mover = THs[endCol].querySelector(\'.manualColumnMover\');\n
+        instance.view.wt.wtDom.addClass(mover, \'active\');\n
+      }\n
+    });\n
+\n
+    instance.addHook(\'afterDestroy\', unbindMoveColEvents);\n
+  };\n
+\n
+  var unbindMoveColEvents = function(){\n
+    var instance = this;\n
+    instance.rootElement.off(\'mouseup.manualColumnMove\');\n
+    instance.rootElement.off(\'mousemove.manualColumnMove\');\n
+    instance.rootElement.off(\'mousedown.manualColumnMove\');\n
+    instance.rootElement.off(\'mouseenter.manualColumnMove\');\n
+  };\n
+\n
+  this.beforeInit = function () {\n
+    this.manualColumnPositions = [];\n
+  };\n
+\n
+  this.init = function (source) {\n
+    var instance = this;\n
+\n
+    var manualColMoveEnabled = !!(this.getSettings().manualColumnMove);\n
+\n
+    if (manualColMoveEnabled) {\n
+      var initialManualColumnPositions = this.getSettings().manualColumnMove;\n
+\n
+      var loadedManualColumnPositions = loadManualColumnPositions.call(instance);\n
+\n
+      if (typeof loadedManualColumnPositions != \'undefined\') {\n
+        this.manualColumnPositions = loadedManualColumnPositions;\n
+      } else if (initialManualColumnPositions instanceof Array) {\n
+        this.manualColumnPositions = initialManualColumnPositions;\n
+      } else {\n
+        this.manualColumnPositions = [];\n
+      }\n
+\n
+\n
+      instance.forceFullRender = true;\n
+\n
+      if (source == \'afterInit\') {\n
+        bindMoveColEvents.call(this);\n
+        if (this.manualColumnPositions.length > 0) {\n
+          this.forceFullRender = true;\n
+          this.render();\n
+        }\n
+\n
+      }\n
+\n
+    } else {\n
+      unbindMoveColEvents.call(this);\n
+      this.manualColumnPositions = [];\n
+    }\n
+  };\n
+\n
+  this.modifyCol = function (col) {\n
+    //TODO test performance: http://jsperf.com/object-wrapper-vs-primitive/2\n
+    if (this.getSettings().manualColumnMove) {\n
+      if (typeof this.manualColumnPositions[col] === \'undefined\') {\n
+        this.manualColumnPositions[col] = col;\n
+      }\n
+      return this.manualColumnPositions[col];\n
+    }\n
+    return col;\n
+  };\n
+\n
+  this.getColHeader = function (col, TH) {\n
+    if (this.getSettings().manualColumnMove) {\n
+      var DIV = document.createElement(\'DIV\');\n
+      DIV.className = \'manualColumnMover\';\n
+      TH.firstChild.appendChild(DIV);\n
+    }\n
+  };\n
+}\n
+var htManualColumnMove = new HandsontableManualColumnMove();\n
+\n
+Handsontable.PluginHooks.add(\'beforeInit\', htManualColumnMove.beforeInit);\n
+Handsontable.PluginHooks.add(\'afterInit\', function () {\n
+  htManualColumnMove.init.call(this, \'afterInit\')\n
+});\n
+\n
+Handsontable.PluginHooks.add(\'afterUpdateSettings\', function () {\n
+  htManualColumnMove.init.call(this, \'afterUpdateSettings\')\n
+});\n
+Handsontable.PluginHooks.add(\'afterGetColHeader\', htManualColumnMove.getColHeader);\n
+Handsontable.PluginHooks.add(\'modifyCol\', htManualColumnMove.modifyCol);\n
+\n
+function HandsontableManualColumnResize() {\n
+  var pressed\n
+    , currentTH\n
+    , currentCol\n
+    , currentWidth\n
+    , instance\n
+    , newSize\n
+    , startX\n
+    , startWidth\n
+    , startOffset\n
+    , resizer = document.createElement(\'DIV\')\n
+    , handle = document.createElement(\'DIV\')\n
+    , line = document.createElement(\'DIV\')\n
+    , lineStyle = line.style;\n
+\n
+  resizer.className = \'manualColumnResizer\';\n
+\n
+  handle.className = \'manualColumnResizerHandle\';\n
+  resizer.appendChild(handle);\n
+\n
+  line.className = \'manualColumnResizerLine\';\n
+  resizer.appendChild(line);\n
+\n
+  var $document = $(document);\n
+\n
+  $document.mousemove(function (e) {\n
+    if (pressed) {\n
+      currentWidth = startWidth + (e.pageX - startX);\n
+      newSize = setManualSize(currentCol, currentWidth); //save col width\n
+      resizer.style.left = startOffset + currentWidth + \'px\';\n
+    }\n
+  });\n
+\n
+  $document.mouseup(function () {\n
+    if (pressed) {\n
+      instance.view.wt.wtDom.removeClass(resizer, \'active\');\n
+      pressed = false;\n
+\n
+      if(newSize != startWidth){\n
+        instance.forceFullRender = true;\n
+        instance.view.render(); //updates all\n
+\n
+        saveManualColumnWidths.call(instance);\n
+\n
+        instance.PluginHooks.run(\'afterColumnResize\', currentCol, newSize);\n
+      }\n
+\n
+      refreshResizerPosition.call(instance, currentTH);\n
+    }\n
+  });\n
+\n
+  var saveManualColumnWidths = function () {\n
+    var instance = this;\n
+\n
+    instance.PluginHooks.run(\'persistentStateSave\', \'manualColumnWidths\', instance.manualColumnWidths);\n
+  };\n
+\n
+  var loadManualColumnWidths = function () {\n
+    var instance = this;\n
+    var storedState = {};\n
+    instance.PluginHooks.run(\'persistentStateLoad\', \'manualColumnWidths\', storedState);\n
+\n
+    return storedState.value;\n
+  };\n
+\n
+  function refreshResizerPosition(TH) {\n
+    instance = this;\n
+    currentTH = TH;\n
+\n
+    var col = this.view.wt.wtTable.getCoords(TH)[1]; //getCoords returns array [row, col]\n
+    if (col >= 0) { //if not row header\n
+      currentCol = col;\n
+      var rootOffset = this.view.wt.wtDom.offset(this.rootElement[0]).left;\n
+      var thOffset = this.view.wt.wtDom.offset(TH).left;\n
+      startOffset = (thOffset - rootOffset) - 6;\n
+      resizer.style.left = startOffset + parseInt(this.view.wt.wtDom.outerWidth(TH), 10) + \'px\';\n
+\n
+      this.rootElement[0].appendChild(resizer);\n
+    }\n
+  }\n
+\n
+  function refreshLinePosition() {\n
+    var instance = this;\n
+    startWidth = parseInt(this.view.wt.wtDom.outerWidth(currentTH), 10);\n
+    instance.view.wt.wtDom.addClass(resizer, \'active\');\n
+    lineStyle.height = instance.view.wt.wtDom.outerHeight(instance.$table[0]) + \'px\';\n
+    pressed = instance;\n
+  }\n
+\n
+  var bindManualColumnWidthEvents = function () {\n
+    var instance = this;\n
+    var dblclick = 0;\n
+    var autoresizeTimeout = null;\n
+\n
+    this.rootElement.on(\'mouseenter.handsontable\', \'th\', function (e) {\n
+      if (!pressed) {\n
+        refreshResizerPosition.call(instance, e.currentTarget);\n
+      }\n
+    });\n
+\n
+    this.rootElement.on(\'mousedown.handsontable\', \'.manualColumnResizer\', function () {\n
+      if (autoresizeTimeout == null) {\n
+        autoresizeTimeout = setTimeout(function () {\n
+          if (dblclick >= 2) {\n
+            newSize = instance.determineColumnWidth.call(instance, currentCol);\n
+            setManualSize(currentCol, newSize);\n
+            instance.forceFullRender = true;\n
+            instance.view.render(); //updates all\n
+            instance.PluginHooks.run(\'afterColumnResize\', currentCol, newSize);\n
+          }\n
+          dblclick = 0;\n
+          autoresizeTimeout = null;\n
+        }, 500);\n
+      }\n
+      dblclick++;\n
+    });\n
+\n
+    this.rootElement.on(\'mousedown.handsontable\', \'.manualColumnResizer\', function (e) {\n
+      startX = e.pageX;\n
+      refreshLinePosition.call(instance);\n
+      newSize = startWidth;\n
+    });\n
+  };\n
+\n
+  this.beforeInit = function () {\n
+    this.manualColumnWidths = [];\n
+  };\n
+\n
+  this.init = function (source) {\n
+    var instance = this;\n
+    var manualColumnWidthEnabled = !!(this.getSettings().manualColumnResize);\n
+\n
+    if (manualColumnWidthEnabled) {\n
+      var initialColumnWidths = this.getSettings().manualColumnResize;\n
+\n
+      var loadedManualColumnWidths = loadManualColumnWidths.call(instance);\n
+\n
+      if (typeof loadedManualColumnWidths != \'undefined\') {\n
+        this.manualColumnWidths = loadedManualColumnWidths;\n
+      } else if (initialColumnWidths instanceof Array) {\n
+        this.manualColumnWidths = initialColumnWidths;\n
+      } else {\n
+        this.manualColumnWidths = [];\n
+      }\n
+\n
+      if (source == \'afterInit\') {\n
+        bindManualColumnWidthEvents.call(this);\n
+        instance.forceFullRender = true;\n
+        instance.render();\n
+      }\n
+    }\n
+  };\n
+\n
+\n
+  var setManualSize = function (col, width) {\n
+    width = Math.max(width, 20);\n
+\n
+    /**\n
+     *  We need to run col through modifyCol hook, in case the order of displayed columns is different than the order\n
+     *  in data source. For instance, this order can be modified by manualColumnMove plugin.\n
+     */\n
+    col = instance.PluginHooks.execute(\'modifyCol\', col);\n
+\n
+    instance.manualColumnWidths[col] = width;\n
+    return width;\n
+  };\n
+\n
+  this.getColWidth = function (col, response) {\n
+    if (this.getSettings().manualColumnResize && this.manualColumnWidths[col]) {\n
+      response.width = this.manualColumnWidths[col];\n
+    }\n
+  };\n
+}\n
+var htManualColumnResize = new HandsontableManualColumnResize();\n
+\n
+Handsontable.PluginHooks.add(\'beforeInit\', htManualColumnResize.beforeInit);\n
+Handsontable.PluginHooks.add(\'afterInit\', function () {\n
+  htManualColumnResize.init.call(this, \'afterInit\')\n
+});\n
+Handsontable.PluginHooks.add(\'afterUpdateSettings\', function () {\n
+  htManualColumnResize.init.call(this, \'afterUpdateSettings\')\n
+});\n
+Handsontable.PluginHooks.add(\'afterGetColWidth\', htManualColumnResize.getColWidth);\n
+\n
+(function HandsontableObserveChanges() {\n
+\n
+  Handsontable.PluginHooks.add(\'afterLoadData\', init);\n
+  Handsontable.PluginHooks.add(\'afterUpdateSettings\', init);\n
+\n
+  function init() {\n
+    var instance = this;\n
+    var pluginEnabled = instance.getSettings().observeChanges;\n
+\n
+    if (pluginEnabled) {\n
+      if(instance.observer) {\n
+        destroy.call(instance); //destroy observer for old data object\n
+      }\n
+      createObserver.call(instance);\n
+      bindEvents.call(instance);\n
+\n
+    } else if (!pluginEnabled){\n
+      destroy.call(instance);\n
+    }\n
+  }\n
+\n
+  function createObserver(){\n
+    var instance = this;\n
+\n
+    instance.observeChangesActive = true;\n
+\n
+    instance.pauseObservingChanges = function(){\n
+      instance.observeChangesActive = false;\n
+    };\n
+\n
+    instance.resumeObservingChanges = function(){\n
+      instance.observeChangesActive = true;\n
+    };\n
+\n
+    instance.observedData = instance.getData();\n
+    instance.observer = jsonpatch.observe(instance.observedData, function (patches) {\n
+      if(instance.observeChangesActive){\n
+        runHookForOperation.call(instance, patches);\n
+        instance.render();\n
+      }\n
+\n
+      instance.runHooks(\'afterChangesObserved\');\n
+    });\n
+  }\n
+\n
+  function runHookForOperation(rawPatches){\n
+    var instance = this;\n
+    var patches = cleanPatches(rawPatches);\n
+\n
+    for(var i = 0, len = patches.length; i < len; i++){\n
+      var patch = patches[i];\n
+      var parsedPath = parsePath(patch.path);\n
+\n
+\n
+      switch(patch.op){\n
+        case \'add\':\n
+          if(isNaN(parsedPath.col)){\n
+            instance.runHooks(\'afterCreateRow\', parsedPath.row);\n
+          } else {\n
+            instance.runHooks(\'afterCreateCol\', parsedPath.col);\n
+          }\n
+          break;\n
+\n
+        case \'remove\':\n
+          if(isNaN(parsedPath.col)){\n
+            instance.runHooks(\'afterRemoveRow\', parsedPath.row, 1);\n
+          } else {\n
+            instance.runHooks(\'afterRemoveCol\', parsedPath.col, 1);\n
+          }\n
+          break;\n
+\n
+        case \'replace\':\n
+          instance.runHooks(\'afterChange\', [parsedPath.row, parsedPath.col, null, patch.value], \'external\');\n
+          break;\n
+      }\n
+    }\n
+\n
+    function cleanPatches(rawPatches){\n
+      var patches;\n
+\n
+      patches = removeLengthRelatedPatches(rawPatches);\n
+      patches = removeMultipleAddOrRemoveColPatches(patches);\n
+\n
+      return patches;\n
+    }\n
+\n
+    /**\n
+     * Removing or adding column will produce one patch for each table row.\n
+     * This function leaves only one patch for each column add/remove operation\n
+     */\n
+    function removeMultipleAddOrRemoveColPatches(rawPatches){\n
+      var newOrRemovedColumns = [];\n
+\n
+      return rawPatches.filter(function(patch){\n
+        var parsedPath = parsePath(patch.path);\n
+\n
+        if([\'add\', \'remove\'].indexOf(patch.op) != -1 && !isNaN(parsedPath.col)){\n
+          if(newOrRemovedColumns.indexOf(parsedPath.col) != -1){\n
+            return false;\n
+          } else {\n
+            newOrRemovedColumns.push(parsedPath.col);\n
+          }\n
+        }\n
+\n
+        return true;\n
+      });\n
+\n
+    }\n
+\n
+    /**\n
+     * If observeChanges uses native Object.observe method, then it produces patches for length property.\n
+     * This function removes them.\n
+     */\n
+    function removeLengthRelatedPatches(rawPatches){\n
+      return rawPatches.filter(function(patch){\n
+        return !/[/]length/ig.test(patch.path);\n
+      })\n
+    }\n
+\n
+    function parsePath(path){\n
+      var match = path.match(/^\\/(\\d+)\\/?(.*)?$/);\n
+      return {\n
+        row: parseInt(match[1], 10),\n
+        col: /^\\d*$/.test(match[2]) ? parseInt(match[2], 10) : match[2]\n
+      }\n
+    }\n
+  }\n
+\n
+  function destroy(){\n
+    var instance = this;\n
+\n
+    if (instance.observer){\n
+      destroyObserver.call(instance);\n
+      unbindEvents.call(instance);\n
+    }\n
+  }\n
+\n
+  function destroyObserver(){\n
+    var instance = this;\n
+\n
+    jsonpatch.unobserve(instance.observedData, instance.observer);\n
+    delete instance.observeChangesActive;\n
+    delete instance.pauseObservingChanges;\n
+    delete instance.resumeObservingChanges;\n
+  }\n
+\n
+  function bindEvents(){\n
+    var instance = this;\n
+    instance.addHook(\'afterDestroy\', destroy);\n
+\n
+    instance.addHook(\'afterCreateRow\', afterTableAlter);\n
+    instance.addHook(\'afterRemoveRow\', afterTableAlter);\n
+\n
+    instance.addHook(\'afterCreateCol\', afterTableAlter);\n
+    instance.addHook(\'afterRemoveCol\', afterTableAlter);\n
+\n
+    instance.addHook(\'afterChange\', function(changes, source){\n
+      if(source != \'loadData\'){\n
+        afterTableAlter.call(this);\n
+      }\n
+    });\n
+  }\n
+\n
+  function unbindEvents(){\n
+    var instance = this;\n
+    instance.removeHook(\'afterDestroy\', destroy);\n
+\n
+    instance.removeHook(\'afterCreateRow\', afterTableAlter);\n
+    instance.removeHook(\'afterRemoveRow\', afterTableAlter);\n
+\n
+    instance.removeHook(\'afterCreateCol\', afterTableAlter);\n
+    instance.removeHook(\'afterRemoveCol\', afterTableAlter);\n
+\n
+    instance.removeHook(\'afterChange\', afterTableAlter);\n
+  }\n
+\n
+  function afterTableAlter(){\n
+    var instance = this;\n
+\n
+    instance.pauseObservingChanges();\n
+\n
+    instance.addHookOnce(\'afterChangesObserved\', function(){\n
+      instance.resumeObservingChanges();\n
+    });\n
+\n
+  }\n
+})();\n
+\n
+\n
+/*\n
+ *\n
+ * Plugin enables saving table state\n
+ *\n
+ * */\n
+\n
+\n
+function Storage(prefix) {\n
+\n
+  var savedKeys;\n
+\n
+  var saveSavedKeys = function () {\n
+    window.localStorage[prefix + \'__\' + \'persistentStateKeys\'] = JSON.stringify(savedKeys);\n
+  };\n
+\n
+  var loadSavedKeys = function () {\n
+    var keysJSON = window.localStorage[prefix + \'__\' + \'persistentStateKeys\'];\n
+    var keys = typeof keysJSON == \'string\' ? JSON.parse(keysJSON) : void 0;\n
+    savedKeys = keys ? keys : [];\n
+  };\n
+\n
+  var clearSavedKeys = function () {\n
+    savedKeys = [];\n
+    saveSavedKeys();\n
+  };\n
+\n
+  loadSavedKeys();\n
+\n
+  this.saveValue = function (key, value) {\n
+    window.localStorage[prefix + \'_\' + key] = JSON.stringify(value);\n
+    if (savedKeys.indexOf(key) == -1) {\n
+      savedKeys.push(key);\n
+      saveSavedKeys();\n
+    }\n
+\n
+  };\n
+\n
+  this.loadValue = function (key, defaultValue) {\n
+\n
+    key = typeof key != \'undefined\' ? key : defaultValue;\n
+\n
+    var value = window.localStorage[prefix + \'_\' + key];\n
+\n
+    return typeof value == "undefined" ? void 0 : JSON.parse(value);\n
+\n
+  };\n
+\n
+  this.reset = function (key) {\n
+    window.localStorage.removeItem(prefix + \'_\' + key);\n
+  };\n
+\n
+  this.resetAll = function () {\n
+    for (var index = 0; index < savedKeys.length; index++) {\n
+      window.localStorage.removeItem(prefix + \'_\' + savedKeys[index]);\n
+    }\n
+\n
+    clearSavedKeys();\n
+  };\n
+\n
+}\n
+\n
+\n
+(function (StorageClass) {\n
+  function HandsontablePersistentState() {\n
+    var plugin = this;\n
+\n
+\n
+    this.init = function () {\n
+      var instance = this,\n
+        pluginSettings = instance.getSettings()[\'persistentState\'];\n
+\n
+      plugin.enabled = !!(pluginSettings);\n
+\n
+      if (!plugin.enabled) {\n
+        removeHooks.call(instance);\n
+        return;\n
+      }\n
+\n
+      if (!instance.storage) {\n
+        instance.storage = new StorageClass(instance.rootElement[0].id);\n
+      }\n
+\n
+      instance.resetState = plugin.resetValue;\n
+\n
+      addHooks.call(instance);\n
+\n
+    };\n
+\n
+    this.saveValue = function (key, value) {\n
+      var instance = this;\n
+\n
+      instance.storage.saveValue(key, value);\n
+    };\n
+\n
+    this.loadValue = function (key, saveTo) {\n
+      var instance = this;\n
+\n
+      saveTo.value = instance.storage.loadValue(key);\n
+    };\n
+\n
+    this.resetValue = function (key) {\n
+      var instance = this;\n
+\n
+      if (typeof  key != \'undefined\') {\n
+        instance.storage.reset(key);\n
+      } else {\n
+        instance.storage.resetAll();\n
+      }\n
+\n
+    };\n
+\n
+    var hooks = {\n
+      \'persistentStateSave\': plugin.saveValue,\n
+      \'persistentStateLoad\': plugin.loadValue,\n
+      \'persistentStateReset\': plugin.resetValue\n
+    };\n
+\n
+    function addHooks() {\n
+      var instance = this;\n
+\n
+      for (var hookName in hooks) {\n
+        if (hooks.hasOwnProperty(hookName) && !hookExists.call(instance, hookName)) {\n
+          instance.PluginHooks.add(hookName, hooks[hookName]);\n
+        }\n
+      }\n
+    }\n
+\n
+    function removeHooks() {\n
+      var instance = this;\n
+\n
+      for (var hookName in hooks) {\n
+        if (hooks.hasOwnProperty(hookName) && hookExists.call(instance, hookName)) {\n
+          instance.PluginHooks.remove(hookName, hooks[hookName]);\n
+        }\n
+      }\n
+    }\n
+\n
+    function hookExists(hookName) {\n
+      var instance = this;\n
+      return instance.PluginHooks.hooks.hasOwnProperty(hookName);\n
+    }\n
+  }\n
+\n
+  var htPersistentState = new HandsontablePersistentState();\n
+  Handsontable.PluginHooks.add(\'beforeInit\', htPersistentState.init);\n
+  Handsontable.PluginHooks.add(\'afterUpdateSettings\', htPersistentState.init);\n
+})(Storage);\n
+\n
+/**\n
+ * Handsontable UndoRedo class\n
+ */\n
+(function(Handsontable){\n
+  Handsontable.UndoRedo = function (instance) {\n
+    var plugin = this;\n
+    this.instance = instance;\n
+    this.doneActions = [];\n
+    this.undoneActions = [];\n
+    this.ignoreNewActions = false;\n
+    instance.addHook("afterChange", function (changes, origin) {\n
+      if(changes){\n
+        var action = new Handsontable.UndoRedo.ChangeAction(changes);\n
+        plugin.done(action);\n
+      }\n
+    });\n
+\n
+    instance.addHook("afterCreateRow", function (index, amount, createdAutomatically) {\n
+\n
+      if (createdAutomatically) {\n
+        return;\n
+      }\n
+\n
+      var action = new Handsontable.UndoRedo.CreateRowAction(index, amount);\n
+      plugin.done(action);\n
+    });\n
+\n
+    instance.addHook("beforeRemoveRow", function (index, amount) {\n
+      var originalData = plugin.instance.getData();\n
+      index = ( originalData.length + index ) % originalData.length;\n
+      var removedData = originalData.slice(index, index + amount);\n
+      var action = new Handsontable.UndoRedo.RemoveRowAction(index, removedData);\n
+      plugin.done(action);\n
+    });\n
+\n
+    instance.addHook("afterCreateCol", function (index, amount, createdAutomatically) {\n
+\n
+      if (createdAutomatically) {\n
+        return;\n
+      }\n
+\n
+      var action = new Handsontable.UndoRedo.CreateColumnAction(index, amount);\n
+      plugin.done(action);\n
+    });\n
+\n
+    instance.addHook("beforeRemoveCol", function (index, amount) {\n
+      var originalData = plugin.instance.getData();\n
+      index = ( plugin.instance.countCols() + index ) % plugin.instance.countCols();\n
+      var removedData = [];\n
+\n
+      for (var i = 0, len = originalData.length; i < len; i++) {\n
+        removedData[i] = originalData[i].slice(index, index + amount);\n
+      }\n
+\n
+      var headers;\n
+      if(Handsontable.helper.isArray(instance.getSettings().colHeaders)){\n
+        headers = instance.getSettings().colHeaders.slice(index, index + removedData.length);\n
+      }\n
+\n
+      var action = new Handsontable.UndoRedo.RemoveColumnAction(index, removedData, headers);\n
+      plugin.done(action);\n
+    });\n
+  };\n
+\n
+  Handsontable.UndoRedo.prototype.done = function (action) {\n
+    if (!this.ignoreNewActions) {\n
+      this.doneActions.push(action);\n
+      this.undoneActions.length = 0;\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Undo operation from current revision\n
+   */\n
+  Handsontable.UndoRedo.prototype.undo = function () {\n
+    if (this.isUndoAvailable()) {\n
+      var action = this.doneActions.pop();\n
+\n
+      this.ignoreNewActions = true;\n
+      var that = this;\n
+      action.undo(this.instance, function () {\n
+        that.ignoreNewActions = false;\n
+        that.undoneActions.push(action);\n
+      });\n
+\n
+\n
+\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Redo operation from current revision\n
+   */\n
+  Handsontable.UndoRedo.prototype.redo = function () {\n
+    if (this.isRedoAvailable()) {\n
+      var action = this.undoneActions.pop();\n
+\n
+      this.ignoreNewActions = true;\n
+      var that = this;\n
+      action.redo(this.instance, function () {\n
+        that.ignoreNewActions = false;\n
+        that.doneActions.push(action);\n
+      });\n
+\n
+\n
+\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Returns true if undo point is available\n
+   * @return {Boolean}\n
+   */\n
+  Handsontable.UndoRedo.prototype.isUndoAvailable = function () {\n
+    return this.doneActions.length > 0;\n
+  };\n
+\n
+  /**\n
+   * Returns true if redo point is available\n
+   * @return {Boolean}\n
+   */\n
+  Handsontable.UndoRedo.prototype.isRedoAvailable = function () {\n
+    return this.undoneActions.length > 0;\n
+  };\n
+\n
+  /**\n
+   * Clears undo history\n
+   */\n
+  Handsontable.UndoRedo.prototype.clear = function () {\n
+    this.doneActions.length = 0;\n
+    this.undoneActions.length = 0;\n
+  };\n
+\n
+  Handsontable.UndoRedo.Action = function () {\n
+  };\n
+  Handsontable.UndoRedo.Action.prototype.undo = function () {\n
+  };\n
+  Handsontable.UndoRedo.Action.prototype.redo = function () {\n
+  };\n
+\n
+  Handsontable.UndoRedo.ChangeAction = function (changes) {\n
+    this.changes = changes;\n
+  };\n
+  Handsontable.helper.inherit(Handsontable.UndoRedo.ChangeAction, Handsontable.UndoRedo.Action);\n
+  Handsontable.UndoRedo.ChangeAction.prototype.undo = function (instance, undoneCallback) {\n
+    var data = $.extend(true, [], this.changes);\n
+    for (var i = 0, len = data.length; i < len; i++) {\n
+      data[i].splice(3, 1);\n
+    }\n
+\n
+    instance.addHookOnce(\'afterChange\', undoneCallback);\n
+\n
+    instance.setDataAtRowProp(data, null, null, \'undo\');\n
+\n
+  };\n
+  Handsontable.UndoRedo.ChangeAction.prototype.redo = function (instance, onFinishCallback) {\n
+    var data = $.extend(true, [], this.changes);\n
+    for (var i = 0, len = data.length; i < len; i++) {\n
+      data[i].splice(2, 1);\n
+    }\n
+\n
+    instance.addHookOnce(\'afterChange\', onFinishCallback);\n
+\n
+    instance.setDataAtRowProp(data, null, null, \'redo\');\n
+\n
+  };\n
+\n
+  Handsontable.UndoRedo.CreateRowAction = function (index, amount) {\n
+    this.index = index;\n
+    this.amount = amount;\n
+  };\n
+  Handsontable.helper.inherit(Handsontable.UndoRedo.CreateRowAction, Handsontable.UndoRedo.Action);\n
+  Handsontable.UndoRedo.CreateRowAction.prototype.undo = function (instance, undoneCallback) {\n
+    instance.addHookOnce(\'afterRemoveRow\', undoneCallback);\n
+    instance.alter(\'remove_row\', this.index, this.amount);\n
+  };\n
+  Handsontable.UndoRedo.CreateRowAction.prototype.redo = function (instance, redoneCallback) {\n
+    instance.addHookOnce(\'afterCreateRow\', redoneCallback);\n
+    instance.alter(\'insert_row\', this.index + 1, this.amount);\n
+  };\n
+\n
+  Handsontable.UndoRedo.RemoveRowAction = function (index, data) {\n
+    this.index = index;\n
+    this.data = data;\n
+  };\n
+  Handsontable.helper.inherit(Handsontable.UndoRedo.RemoveRowAction, Handsontable.UndoRedo.Action);\n
+  Handsontable.UndoRedo.RemoveRowAction.prototype.undo = function (instance, undoneCallback) {\n
+    var spliceArgs = [this.index, 0];\n
+    Array.prototype.push.apply(spliceArgs, this.data);\n
+\n
+    Array.prototype.splice.apply(instance.getData(), spliceArgs);\n
+\n
+    instance.addHookOnce(\'afterRender\', undoneCallback);\n
+    instance.render();\n
+  };\n
+  Handsontable.UndoRedo.RemoveRowAction.prototype.redo = function (instance, redoneCallback) {\n
+    instance.addHookOnce(\'afterRemoveRow\', redoneCallback);\n
+    instance.alter(\'remove_row\', this.index, this.data.length);\n
+  };\n
+\n
+  Handsontable.UndoRedo.CreateColumnAction = function (index, amount) {\n
+    this.index = index;\n
+    this.amount = amount;\n
+  };\n
+  Handsontable.helper.inherit(Handsontable.UndoRedo.CreateColumnAction, Handsontable.UndoRedo.Action);\n
+  Handsontable.UndoRedo.CreateColumnAction.prototype.undo = function (instance, undoneCallback) {\n
+    instance.addHookOnce(\'afterRemoveCol\', undoneCallback);\n
+    instance.alter(\'remove_col\', this.index, this.amount);\n
+  };\n
+  Handsontable.UndoRedo.CreateColumnAction.prototype.redo = function (instance, redoneCallback) {\n
+    instance.addHookOnce(\'afterCreateCol\', redoneCallback);\n
+    instance.alter(\'insert_col\', this.index + 1, this.amount);\n
+  };\n
+\n
+  Handsontable.UndoRedo.RemoveColumnAction = function (index, data, headers) {\n
+    this.index = index;\n
+    this.data = data;\n
+    this.amount = this.data[0].length;\n
+    this.headers = headers;\n
+  };\n
+  Handsontable.helper.inherit(Handsontable.UndoRedo.RemoveColumnAction, Handsontable.UndoRedo.Action);\n
+  Handsontable.UndoRedo.RemoveColumnAction.prototype.undo = function (instance, undoneCallback) {\n
+    var row, spliceArgs;\n
+    for (var i = 0, len = instance.getData().length; i < len; i++) {\n
+      row = instance.getDataAtRow(i);\n
+\n
+      spliceArgs = [this.index, 0];\n
+      Array.prototype.push.apply(spliceArgs, this.data[i]);\n
+\n
+      Array.prototype.splice.apply(row, spliceArgs);\n
+\n
+    }\n
+\n
+    if(typeof this.headers != \'undefined\'){\n
+      spliceArgs = [this.index, 0];\n
+      Array.prototype.push.apply(spliceArgs, this.headers);\n
+      Array.prototype.splice.apply(instance.getSettings().colHeaders, spliceArgs);\n
+    }\n
+\n
+    instance.addHookOnce(\'afterRender\', undoneCallback);\n
+    instance.render();\n
+  };\n
+  Handsontable.UndoRedo.RemoveColumnAction.prototype.redo = function (instance, redoneCallback) {\n
+    instance.addHookOnce(\'afterRemoveCol\', redoneCallback);\n
+    instance.alter(\'remove_col\', this.index, this.amount);\n
+  };\n
+})(Handsontable);\n
+\n
+(function(Handsontable){\n
+\n
+  function init(){\n
+    var instance = this;\n
+    var pluginEnabled = typeof instance.getSettings().undo == \'undefined\' || instance.getSettings().undo;\n
+\n
+    if(pluginEnabled){\n
+      if(!instance.undoRedo){\n
+        instance.undoRedo = new Handsontable.UndoRedo(instance);\n
+\n
+        exposeUndoRedoMethods(instance);\n
+\n
+        instance.addHook(\'beforeKeyDown\', onBeforeKeyDown);\n
+        instance.addHook(\'afterChange\', onAfterChange);\n
+      }\n
+    } else {\n
+      if(instance.undoRedo){\n
+        delete instance.undoRedo;\n
+\n
+        removeExposedUndoRedoMethods(instance);\n
+\n
+        instance.removeHook(\'beforeKeyDown\', onBeforeKeyDown);\n
+        instance.removeHook(\'afterChange\', onAfterChange);\n
+      }\n
+    }\n
+  }\n
+\n
+  function onBeforeKeyDown(event){\n
+    var instance = this;\n
+\n
+    var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey;\n
+\n
+    if(ctrlDown){\n
+      if (event.keyCode === 89 || (event.shiftKey && event.keyCode === 90)) { //CTRL + Y or CTRL + SHIFT + Z\n
+        instance.undoRedo.redo();\n
+        event.stopImmediatePropagation();\n
+      }\n
+      else if (event.keyCode === 90) { //CTRL + Z\n
+        instance.undoRedo.undo();\n
+        event.stopImmediatePropagation();\n
+      }\n
+    }\n
+  }\n
+\n
+  function onAfterChange(changes, source){\n
+    var instance = this;\n
+    if (source == \'loadData\'){\n
+      return instance.undoRedo.clear();\n
+    }\n
+  }\n
+\n
+  function exposeUndoRedoMethods(instance){\n
+    instance.undo = function(){\n
+      return instance.undoRedo.undo();\n
+    };\n
+\n
+    instance.redo = function(){\n
+      return instance.undoRedo.redo();\n
+    };\n
+\n
+    instance.isUndoAvailable = function(){\n
+      return instance.undoRedo.isUndoAvailable();\n
+    };\n
+\n
+    instance.isRedoAvailable = function(){\n
+      return instance.undoRedo.isRedoAvailable();\n
+    };\n
+\n
+    instance.clearUndo = function(){\n
+      return instance.undoRedo.clear();\n
+    };\n
+  }\n
+\n
+  function removeExposedUndoRedoMethods(instance){\n
+    delete instance.undo;\n
+    delete instance.redo;\n
+    delete instance.isUndoAvailable;\n
+    delete instance.isRedoAvailable;\n
+    delete instance.clearUndo;\n
+  }\n
+\n
+  Handsontable.PluginHooks.add(\'afterInit\', init);\n
+  Handsontable.PluginHooks.add(\'afterUpdateSettings\', init);\n
+\n
+})(Handsontable);\n
+/**\n
+ * Plugin used to scroll Handsontable by selecting a cell and dragging outside of visible viewport\n
+ * @constructor\n
+ */\n
+function DragToScroll() {\n
+  this.boundaries = null;\n
+  this.callback = null;\n
+}\n
+\n
+/**\n
+ * @param boundaries {Object} compatible with getBoundingClientRect\n
+ */\n
+DragToScroll.prototype.setBoundaries = function (boundaries) {\n
+  this.boundaries = boundaries;\n
+};\n
+\n
+/**\n
+ * @param callback {Function}\n
+ */\n
+DragToScroll.prototype.setCallback = function (callback) {\n
+  this.callback = callback;\n
+};\n
+\n
+/**\n
+ * Check if mouse position (x, y) is outside of the viewport\n
+ * @param x\n
+ * @param y\n
+ */\n
+DragToScroll.prototype.check = function (x, y) {\n
+  var diffX = 0;\n
+  var diffY = 0;\n
+\n
+  if (y < this.boundaries.top) {\n
+    //y is less than top\n
+    diffY = y - this.boundaries.top;\n
+  }\n
+  else if (y > this.boundaries.bottom) {\n
+    //y is more than bottom\n
+    diffY = y - this.boundaries.bottom;\n
+  }\n
+\n
+  if (x < this.boundaries.left) {\n
+    //x is less than left\n
+    diffX = x - this.boundaries.left;\n
+  }\n
+  else if (x > this.boundaries.right) {\n
+    //x is more than right\n
+    diffX = x - this.boundaries.right;\n
+  }\n
+\n
+  this.callback(diffX, diffY);\n
+};\n
+\n
+var listening = false;\n
+var dragToScroll;\n
+var instance;\n
+\n
+if (typeof Handsontable !== \'undefined\') {\n
+  var setupListening = function (instance) {\n
+    var scrollHandler = instance.view.wt.wtScrollbars.vertical.scrollHandler; //native scroll\n
+    dragToScroll = new DragToScroll();\n
+    if (scrollHandler === window) {\n
+      //not much we can do currently\n
+      return;\n
+    }\n
+    else if (scrollHandler) {\n
+      dragToScroll.setBoundaries(scrollHandler.getBoundingClientRect());\n
+    }\n
+    else {\n
+      dragToScroll.setBoundaries(instance.$table[0].getBoundingClientRect());\n
+    }\n
+\n
+    dragToScroll.setCallback(function (scrollX, scrollY) {\n
+      if (scrollX < 0) {\n
+        if (scrollHandler) {\n
+          scrollHandler.scrollLeft -= 50;\n
+        }\n
+        else {\n
+          instance.view.wt.scrollHorizontal(-1).draw();\n
+        }\n
+      }\n
+      else if (scrollX > 0) {\n
+        if (scrollHandler) {\n
+          scrollHandler.scrollLeft += 50;\n
+        }\n
+        else {\n
+          instance.view.wt.scrollHorizontal(1).draw();\n
+        }\n
+      }\n
+\n
+      if (scrollY < 0) {\n
+        if (scrollHandler) {\n
+          scrollHandler.scrollTop -= 20;\n
+        }\n
+        else {\n
+          instance.view.wt.scrollVertical(-1).draw();\n
+        }\n
+      }\n
+      else if (scrollY > 0) {\n
+        if (scrollHandler) {\n
+          scrollHandler.scrollTop += 20;\n
+        }\n
+        else {\n
+          instance.view.wt.scrollVertical(1).draw();\n
+        }\n
+      }\n
+    });\n
+\n
+    listening = true;\n
+  };\n
+\n
+  Handsontable.PluginHooks.add(\'afterInit\', function () {\n
+    $(document).on(\'mouseup.\' + this.guid, function () {\n
+      listening = false;\n
+    });\n
+\n
+    $(document).on(\'mousemove.\' + this.guid, function (event) {\n
+      if (listening) {\n
+        dragToScroll.check(event.clientX, event.clientY);\n
+      }\n
+    });\n
+  });\n
+\n
+  Handsontable.PluginHooks.add(\'destroy\', function () {\n
+    $(document).off(\'.\' + this.guid);\n
+  });\n
+\n
+  Handsontable.PluginHooks.add(\'afterOnCellMouseDown\', function () {\n
+    setupListening(this);\n
+  });\n
+\n
+  Handsontable.PluginHooks.add(\'afterOnCellCornerMouseDown\', function () {\n
+    setupListening(this);\n
+  });\n
+\n
+  Handsontable.plugins.DragToScroll = DragToScroll;\n
+}\n
+\n
+(function (Handsontable, CopyPaste, SheetClip) {\n
+\n
+  function CopyPastePlugin(instance) {\n
+    this.copyPasteInstance = CopyPaste.getInstance();\n
+\n
+    this.copyPasteInstance.onCut(onCut);\n
+    this.copyPasteInstance.onPaste(onPaste);\n
+    var plugin = this;\n
+\n
+    instance.addHook(\'beforeKeyDown\', onBeforeKeyDown);\n
+\n
+    function onCut() {\n
+      if (!instance.isListening()) {\n
+        return;\n
+      }\n
+\n
+      instance.selection.empty();\n
+    }\n
+\n
+    function onPaste(str) {\n
+      if (!instance.isListening() || !instance.selection.isSelected()) {\n
+        return;\n
+      }\n
+\n
+      var input = str.replace(/^[\\r\\n]*/g, \'\').replace(/[\\r\\n]*$/g, \'\') //remove newline from the start and the end of the input\n
+        , inputArray = SheetClip.parse(input)\n
+        , selected = instance.getSelected()\n
+        , coords = instance.getCornerCoords([{row: selected[0], col: selected[1]}, {row: selected[2], col: selected[3]}])\n
+        , areaStart = coords.TL\n
+        , areaEnd = {\n
+          row: Math.max(coords.BR.row, inputArray.length - 1 + coords.TL.row),\n
+          col: Math.max(coords.BR.col, inputArray[0].length - 1 + coords.TL.col)\n
+        };\n
+\n
+      instance.PluginHooks.once(\'afterChange\', function (changes, source) {\n
+        if (changes && changes.length) {\n
+          this.selectCell(areaStart.row, areaStart.col, areaEnd.row, areaEnd.col);\n
+        }\n
+      });\n
+\n
+      instance.populateFromArray(areaStart.row, areaStart.col, inputArray, areaEnd.row, areaEnd.col, \'paste\', instance.getSettings().pasteMode);\n
+    };\n
+\n
+    function onBeforeKeyDown (event) {\n
+      if (Handsontable.helper.isCtrlKey(event.keyCode) && instance.getSelected()) {\n
+        //when CTRL is pressed, prepare selectable text in textarea\n
+        //http://stackoverflow.com/questions/3902635/how-does-one-capture-a-macs-command-key-via-javascript\n
+        plugin.setCopyableText();\n
+        event.stopImmediatePropagation();\n
+        return;\n
+      }\n
+\n
+      var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)\n
+\n
+      if (event.keyCode == Handsontable.helper.keyCode.A && ctrlDown) {\n
+        setTimeout(Handsontable.helper.proxy(plugin.setCopyableText, plugin));\n
+      }\n
+\n
+    }\n
+\n
+    this.destroy = function () {\n
+      this.copyPasteInstance.removeCallback(onCut);\n
+      this.copyPasteInstance.removeCallback(onPaste);\n
+      this.copyPasteInstance.destroy();\n
+      instance.removeHook(\'beforeKeyDown\', onBeforeKeyDown);\n
+    };\n
+\n
+    instance.addHook(\'afterDestroy\', Handsontable.helper.proxy(this.destroy, this));\n
+\n
+    this.triggerPaste = Handsontable.helper.proxy(this.copyPasteInstance.triggerPaste, this.copyPasteInstance);\n
+    this.triggerCut = Handsontable.helper.proxy(this.copyPasteInstance.triggerCut, this.copyPasteInstance);\n
+\n
+    /**\n
+     * Prepares copyable text in the invisible textarea\n
+     */\n
+    this.setCopyableText = function () {\n
+\n
+      var selection = instance.getSelected();\n
+      var settings = instance.getSettings();\n
+      var copyRowsLimit = settings.copyRowsLimit;\n
+      var copyColsLimit = settings.copyColsLimit;\n
+\n
+      var startRow = Math.min(selection[0], selection[2]);\n
+      var startCol = Math.min(selection[1], selection[3]);\n
+      var endRow = Math.max(selection[0], selection[2]);\n
+      var endCol = Math.max(selection[1], selection[3]);\n
+      var finalEndRow = Math.min(endRow, startRow + copyRowsLimit - 1);\n
+      var finalEndCol = Math.min(endCol, startCol + copyColsLimit - 1);\n
+\n
+      instance.copyPaste.copyPasteInstance.copyable(instance.getCopyableData(startRow, startCol, finalEndRow, finalEndCol));\n
+\n
+      if (endRow !== finalEndRow || endCol !== finalEndCol) {\n
+        instance.PluginHooks.run("afterCopyLimit", endRow - startRow + 1, endCol - startCol + 1, copyRowsLimit, copyColsLimit);\n
+      }\n
+    };\n
+\n
+  }\n
+\n
+\n
+\n
+  function init() {\n
+    var instance  = this;\n
+    var pluginEnabled = instance.getSettings().copyPaste !== false;\n
+\n
+    if(pluginEnabled && !instance.copyPaste){\n
+\n
+      instance.copyPaste = new CopyPastePlugin(instance);\n
+\n
+    } else if (!pluginEnabled && instance.copyPaste) {\n
+\n
+      instance.copyPaste.destroy();\n
+      delete instance.copyPaste;\n
+\n
+    }\n
+\n
+  }\n
+\n
+  Handsontable.PluginHooks.add(\'afterInit\', init);\n
+  Handsontable.PluginHooks.add(\'afterUpdateSettings\', init);\n
+\n
+})(Handsontable, CopyPaste, SheetClip);\n
+(function (Handsontable) {\n
+\n
+  \'use strict\';\n
+\n
+  Handsontable.Search = function Search(instance) {\n
+    this.query = function (queryStr, callback, queryMethod) {\n
+      var rowCount = instance.countRows();\n
+      var colCount = instance.countCols();\n
+      var queryResult = [];\n
+\n
+      if (!callback) {\n
+        callback = Handsontable.Search.global.getDefaultCallback();\n
+      }\n
+\n
+      if (!queryMethod) {\n
+        queryMethod = Handsontable.Search.global.getDefaultQueryMethod();\n
+      }\n
+\n
+      for (var rowIndex = 0; rowIndex < rowCount; rowIndex++) {\n
+        for (var colIndex = 0; colIndex < colCount; colIndex++) {\n
+          var cellData = instance.getDataAtCell(rowIndex, colIndex);\n
+          var cellProperties = instance.getCellMeta(rowIndex, colIndex);\n
+          var cellCallback = cellProperties.search.callback || callback;\n
+          var cellQueryMethod = cellProperties.search.queryMethod || queryMethod;\n
+          var testResult = cellQueryMethod(queryStr, cellData);\n
+\n
+          if (testResult) {\n
+            var singleResult = {\n
+              row: rowIndex,\n
+              col: colIndex,\n
+              data: cellData\n
+            };\n
+\n
+            queryResult.push(singleResult);\n
+          }\n
+\n
+          if (cellCallback) {\n
+            cellCallback(instance, rowIndex, colIndex, cellData, testResult);\n
+          }\n
+        }\n
+      }\n
+\n
+      return queryResult;\n
+\n
+    };\n
+\n
+  };\n
+\n
+  Handsontable.Search.DEFAULT_CALLBACK = function (instance, row, col, data, testResult) {\n
+    instance.getCellMeta(row, col).isSearchResult = testResult;\n
+  };\n
+\n
+  Handsontable.Search.DEFAULT_QUERY_METHOD = function (query, value) {\n
+\n
+    if (typeof query == \'undefined\' || query == null || !query.toLowerCase || query.length == 0){\n
+      return false;\n
+    }\n
+\n
+    return value.toString().toLowerCase().indexOf(query.toLowerCase()) != -1;\n
+  };\n
+\n
+  Handsontable.Search.DEFAULT_SEARCH_RESULT_CLASS = \'htSearchResult\';\n
+\n
+  Handsontable.Search.global = (function () {\n
+\n
+    var defaultCallback = Handsontable.Search.DEFAULT_CALLBACK;\n
+    var defaultQueryMethod = Handsontable.Search.DEFAULT_QUERY_METHOD;\n
+    var defaultSearchResultClass = Handsontable.Search.DEFAULT_SEARCH_RESULT_CLASS;\n
+\n
+    return {\n
+      getDefaultCallback: function () {\n
+        return defaultCallback;\n
+      },\n
+\n
+      setDefaultCallback: function (newDefaultCallback) {\n
+        defaultCallback = newDefaultCallback;\n
+      },\n
+\n
+      getDefaultQueryMethod: function () {\n
+        return defaultQueryMethod;\n
+      },\n
+\n
+      setDefaultQueryMethod: function (newDefaultQueryMethod) {\n
+        defaultQueryMethod = newDefaultQueryMethod;\n
+      },\n
+\n
+      getDefaultSearchResultClass: function () {\n
+        return defaultSearchResultClass;\n
+      },\n
+\n
+      setDefaultSearchResultClass: function (newSearchResultClass) {\n
+        defaultSearchResultClass = newSearchResultClass;\n
+      }\n
+    }\n
+\n
+  })();\n
+\n
+\n
+\n
+  Handsontable.SearchCellDecorator = function (instance, TD, row, col, prop, value, cellProperties) {\n
+\n
+    var searchResultClass = (typeof cellProperties.search == \'object\' && cellProperties.search.searchResultClass) || Handsontable.Search.global.getDefaultSearchResultClass();\n
+\n
+    if(cellProperties.isSearchResult){\n
+      Handsontable.Dom.addClass(TD, searchResultClass);\n
+    } else {\n
+      Handsontable.Dom.removeClass(TD, searchResultClass);\n
+    }\n
+  };\n
+\n
+\n
+\n
+  var originalDecorator = Handsontable.renderers.cellDecorator;\n
+\n
+  Handsontable.renderers.cellDecorator = function (instance, TD, row, col, prop, value, cellProperties) {\n
+    originalDecorator.apply(this, arguments);\n
+    Handsontable.SearchCellDecorator.apply(this, arguments);\n
+  };\n
+\n
+  function init() {\n
+    var instance = this;\n
+\n
+    var pluginEnabled = !!instance.getSettings().search;\n
+\n
+    if (pluginEnabled) {\n
+      instance.search = new Handsontable.Search(instance);\n
+    } else {\n
+      delete instance.search;\n
+    }\n
+\n
+  }\n
+\n
+  Handsontable.PluginHooks.add(\'afterInit\', init);\n
+  Handsontable.PluginHooks.add(\'afterUpdateSettings\', init);\n
+\n
+\n
+})(Handsontable);\n
+/**\n
+ * Creates an overlay over the original Walkontable instance. The overlay renders the clone of the original Walkontable\n
+ * and (optionally) implements behavior needed for native horizontal and vertical scrolling\n
+ */\n
+function WalkontableOverlay() {\n
+  this.maxOuts = 10; //max outs in one direction (before and after table)\n
+}\n
+\n
+/*\n
+ Possible optimizations:\n
+ [x] don\'t rerender if scroll delta is smaller than the fragment outside of the viewport\n
+ [ ] move .style.top change before .draw()\n
+ [ ] put .draw() in requestAnimationFrame\n
+ [ ] don\'t rerender rows that remain visible after the scroll\n
+ */\n
+\n
+WalkontableOverlay.prototype.init = function () {\n
+  this.TABLE = this.instance.wtTable.TABLE;\n
+  this.fixed = this.instance.wtTable.hider;\n
+  this.fixedContainer = this.instance.wtTable.holder;\n
+  this.fixed.style.position = \'absolute\';\n
+  this.fixed.style.left = \'0\';\n
+  this.scrollHandler = this.getScrollableElement(this.TABLE);\n
+  this.$scrollHandler = $(this.scrollHandler); //in future remove jQuery from here\n
+};\n
+\n
+WalkontableOverlay.prototype.makeClone = function (direction) {\n
+  var clone = document.createElement(\'DIV\');\n
+  clone.className = \'ht_clone_\' + direction + \' handsontable\';\n
+  clone.style.position = \'fixed\';\n
+  clone.style.overflow = \'hidden\';\n
+\n
+  var table2 = document.createElement(\'TABLE\');\n
+  table2.className = this.instance.wtTable.TABLE.className;\n
+  clone.appendChild(table2);\n
+\n
+  this.instance.wtTable.holder.parentNode.appendChild(clone);\n
+\n
+  return new Walkontable({\n
+    cloneSource: this.instance,\n
+    cloneOverlay: this,\n
+    table: table2\n
+  });\n
+};\n
+\n
+WalkontableOverlay.prototype.getScrollableElement = function (TABLE) {\n
+  var el = TABLE.parentNode;\n
+  while (el && el.style) {\n
+    if (el.style.overflow !== \'visible\' && el.style.overflow !== \'\') {\n
+      return el;\n
+    }\n
+    if (this instanceof WalkontableHorizontalScrollbarNative && el.style.overflowX !== \'visible\' && el.style.overflowX !== \'\') {\n
+      return el;\n
+    }\n
+    el = el.parentNode;\n
+  }\n
+  return window;\n
+};\n
+\n
+WalkontableOverlay.prototype.prepare = function () {\n
+};\n
+\n
+WalkontableOverlay.prototype.onScroll = function (forcePosition) {\n
+\n
+  this.windowScrollPosition = this.getScrollPosition();\n
+  this.readSettings(); //read window scroll position\n
+\n
+  if (forcePosition) {\n
+    this.windowScrollPosition = forcePosition;\n
+  }\n
+\n
+  this.resetFixedPosition(); //may be redundant\n
+};\n
+\n
+WalkontableOverlay.prototype.availableSize = function () {\n
+  var availableSize;\n
+\n
+  if (this.windowScrollPosition > this.tableParentOffset /*&& last > -1*/) { //last -1 means that viewport is scrolled behind the table\n
+    if (this.instance.wtTable.getLastVisibleRow() === this.total - 1) {\n
+      availableSize = this.instance.wtDom.outerHeight(this.TABLE);\n
+    }\n
+    else {\n
+      availableSize = this.windowSize;\n
+    }\n
+  }\n
+  else {\n
+    availableSize = this.windowSize - (this.tableParentOffset);\n
+  }\n
+\n
+  return availableSize;\n
+};\n
+\n
+WalkontableOverlay.prototype.refresh = function (selectionsOnly) {\n
+  var last = this.getLastCell();\n
+  this.measureBefore = this.sumCellSizes(0, this.offset);\n
+  if (last === -1) { //last -1 means that viewport is scrolled behind the table\n
+    this.measureAfter = 0;\n
+  }\n
+  else {\n
+    this.measureAfter = this.sumCellSizes(last, this.total - last);\n
+  }\n
+  this.applyToDOM();\n
+  this.clone && this.clone.draw(selectionsOnly);\n
+};\n
+\n
+WalkontableOverlay.prototype.destroy = function () {\n
+  this.$scrollHandler.off(\'.\' + this.instance.guid);\n
+  $(window).off(\'.\' + this.instance.guid);\n
+  $(document).off(\'.\' + this.instance.guid);\n
+};\n
+function WalkontableBorder(instance, settings) {\n
+  var style;\n
+\n
+  //reference to instance\n
+  this.instance = instance;\n
+  this.settings = settings;\n
+  this.wtDom = this.instance.wtDom;\n
+\n
+  this.main = document.createElement("div");\n
+  style = this.main.style;\n
+  style.position = \'absolute\';\n
+  style.top = 0;\n
+  style.left = 0;\n
+//  style.visibility = \'hidden\';\n
+\n
+  for (var i = 0; i < 5; i++) {\n
+    var DIV = document.createElement(\'DIV\');\n
+    DIV.className = \'wtBorder \' + (settings.className || \'\');\n
+    style = DIV.style;\n
+    style.backgroundColor = settings.border.color;\n
+    style.height = settings.border.width + \'px\';\n
+    style.width = settings.border.width + \'px\';\n
+    this.main.appendChild(DIV);\n
+  }\n
+\n
+  this.top = this.main.childNodes[0];\n
+  this.left = this.main.childNodes[1];\n
+  this.bottom = this.main.childNodes[2];\n
+  this.right = this.main.childNodes[3];\n
+\n
+\n
+  /*$(this.top).on(sss, function(event) {\n
+   event.preventDefault();\n
+   event.stopImmediatePropagation();\n
+   $(this).hide();\n
+   });\n
+   $(this.left).on(sss, function(event) {\n
+   event.preventDefault();\n
+   event.stopImmediatePropagation();\n
+   $(this).hide();\n
+   });\n
+   $(this.bottom).on(sss, function(event) {\n
+   event.preventDefault();\n
+   event.stopImmediatePropagation();\n
+   $(this).hide();\n
+   });\n
+   $(this.right).on(sss, function(event) {\n
+   event.preventDefault();\n
+   event.stopImmediatePropagation();\n
+   $(this).hide();\n
+   });*/\n
+\n
+  this.topStyle = this.top.style;\n
+  this.leftStyle = this.left.style;\n
+  this.bottomStyle = this.bottom.style;\n
+  this.rightStyle = this.right.style;\n
+\n
+  this.corner = this.main.childNodes[4];\n
+  this.corner.className += \' corner\';\n
+  this.cornerStyle = this.corner.style;\n
+  this.cornerStyle.width = \'5px\';\n
+  this.cornerStyle.height = \'5px\';\n
+  this.cornerStyle.border = \'2px solid #FFF\';\n
+\n
+  this.disappear();\n
+  if (!instance.wtTable.bordersHolder) {\n
+    instance.wtTable.bordersHolder = document.createElement(\'div\');\n
+    instance.wtTable.bordersHolder.className = \'htBorders\';\n
+    instance.wtTable.hider.appendChild(instance.wtTable.bordersHolder);\n
+\n
+  }\n
+  instance.wtTable.bordersHolder.appendChild(this.main);\n
+\n
+  var down = false;\n
+  var $body = $(document.body);\n
+\n
+  $body.on(\'mousedown.walkontable.\' + instance.guid, function () {\n
+    down = true;\n
+  });\n
+\n
+  $body.on(\'mouseup.walkontable.\' + instance.guid, function () {\n
+    down = false\n
+  });\n
+\n
+  $(this.main.childNodes).on(\'mouseenter\', function (event) {\n
+    if (!down || !instance.getSetting(\'hideBorderOnMouseDownOver\')) {\n
+      return;\n
+    }\n
+    event.preventDefault();\n
+    event.stopImmediatePropagation();\n
+\n
+    var bounds = this.getBoundingClientRect();\n
+\n
+    var $this = $(this);\n
+    $this.hide();\n
+\n
+    var isOutside = function (event) {\n
+      if (event.clientY < Math.floor(bounds.top)) {\n
+        return true;\n
+      }\n
+      if (event.clientY > Math.ceil(bounds.top + bounds.height)) {\n
+        return true;\n
+      }\n
+      if (event.clientX < Math.floor(bounds.left)) {\n
+        return true;\n
+      }\n
+      if (event.clientX > Math.ceil(bounds.left + bounds.width)) {\n
+        return true;\n
+      }\n
+    };\n
+\n
+    $body.on(\'mousemove.border.\' + instance.guid, function (event) {\n
+      if (isOutside(event)) {\n
+        $body.off(\'mousemove.border.\' + instance.guid);\n
+        $this.show();\n
+      }\n
+    });\n
+  });\n
+}\n
+\n
+/**\n
+ * Show border around one or many cells\n
+ * @param {Array} corners\n
+ */\n
+WalkontableBorder.prototype.appear = function (corners) {\n
+  var isMultiple, fromTD, toTD, fromOffset, toOffset, containerOffset, top, minTop, left, minLeft, height, width;\n
+  if (this.disabled) {\n
+    return;\n
+  }\n
+\n
+  var instance = this.instance\n
+    , fromRow\n
+    , fromColumn\n
+    , toRow\n
+    , toColumn\n
+    , hideTop = false\n
+    , hideLeft = false\n
+    , hideBottom = false\n
+    , hideRight = false\n
+    , i\n
+    , ilen\n
+    , s;\n
+\n
+  if (!instance.wtTable.isRowInViewport(corners[0])) {\n
+    hideTop = true;\n
+  }\n
+\n
+  if (!instance.wtTable.isRowInViewport(corners[2])) {\n
+    hideBottom = true;\n
+  }\n
+\n
+  ilen = instance.wtTable.rowStrategy.countVisible();\n
+\n
+  for (i = 0; i < ilen; i++) {\n
+    s = instance.wtTable.rowFilter.visibleToSource(i);\n
+    if (s >= corners[0] && s <= corners[2]) {\n
+      fromRow = s;\n
+      break;\n
+    }\n
+  }\n
+\n
+  for (i = ilen - 1; i >= 0; i--) {\n
+    s = instance.wtTable.rowFilter.visibleToSource(i);\n
+    if (s >= corners[0] && s <= corners[2]) {\n
+      toRow = s;\n
+      break;\n
+    }\n
+  }\n
+\n
+  if (hideTop && hideBottom) {\n
+    hideLeft = true;\n
+    hideRight = true;\n
+  }\n
+  else {\n
+    if (!instance.wtTable.isColumnInViewport(corners[1])) {\n
+      hideLeft = true;\n
+    }\n
+\n
+    if (!instance.wtTable.isColumnInViewport(corners[3])) {\n
+      hideRight = true;\n
+    }\n
+\n
+    ilen = instance.wtTable.columnStrategy.countVisible();\n
+\n
+    for (i = 0; i < ilen; i++) {\n
+      s = instance.wtTable.columnFilter.visibleToSource(i);\n
+      if (s >= corners[1] && s <= corners[3]) {\n
+        fromColumn = s;\n
+        break;\n
+      }\n
+    }\n
+\n
+    for (i = ilen - 1; i >= 0; i--) {\n
+      s = instance.wtTable.columnFilter.visibleToSource(i);\n
+      if (s >= corners[1] && s <= corners[3]) {\n
+        toColumn = s;\n
+        break;\n
+      }\n
+    }\n
+  }\n
+\n
+  if (fromRow !== void 0 && fromColumn !== void 0) {\n
+    isMultiple = (fromRow !== toRow || fromColumn !== toColumn);\n
+    fromTD = instance.wtTable.getCell([fromRow, fromColumn]);\n
+    toTD = isMultiple ? instance.wtTable.getCell([toRow, toColumn]) : fromTD;\n
+    fromOffset = this.wtDom.offset(fromTD);\n
+    toOffset = isMultiple ? this.wtDom.offset(toTD) : fromOffset;\n
+    containerOffset = this.wtDom.offset(instance.wtTable.TABLE);\n
+\n
+    minTop = fromOffset.top;\n
+    height = toOffset.top + this.wtDom.outerHeight(toTD) - minTop;\n
+    minLeft = fromOffset.left;\n
+    width = toOffset.left + this.wtDom.outerWidth(toTD) - minLeft;\n
+\n
+    top = minTop - containerOffset.top - 1;\n
+    left = minLeft - containerOffset.left - 1;\n
+\n
+    var style = this.wtDom.getComputedStyle(fromTD);\n
+    if (parseInt(style[\'borderTopWidth\'], 10) > 0) {\n
+      top += 1;\n
+      height = height > 0 ? height - 1 : 0;\n
+    }\n
+    if (parseInt(style[\'borderLeftWidth\'], 10) > 0) {\n
+      left += 1;\n
+      width = width > 0 ? width - 1 : 0;\n
+    }\n
+  }\n
+  else {\n
+    this.disappear();\n
+    return;\n
+  }\n
+\n
+  if (hideTop) {\n
+    this.topStyle.display = \'none\';\n
+  }\n
+  else {\n
+    this.topStyle.top = top + \'px\';\n
+    this.topStyle.left = left + \'px\';\n
+    this.topStyle.width = width + \'px\';\n
+    this.topStyle.display = \'block\';\n
+  }\n
+\n
+  if (hideLeft) {\n
+    this.leftStyle.display = \'none\';\n
+  }\n
+  else {\n
+    this.leftStyle.top = top + \'px\';\n
+    this.leftStyle.left = left + \'px\';\n
+    this.leftStyle.height = height + \'px\';\n
+    this.leftStyle.display = \'block\';\n
+  }\n
+\n
+  var delta = Math.floor(this.settings.border.width / 2);\n
+\n
+  if (hideBottom) {\n
+    this.bottomStyle.display = \'none\';\n
+  }\n
+  else {\n
+    this.bottomStyle.top = top + height - delta + \'px\';\n
+    this.bottomStyle.left = left + \'px\';\n
+    this.bottomStyle.width = width + \'px\';\n
+    this.bottomStyle.display = \'block\';\n
+  }\n
+\n
+  if (hideRight) {\n
+    this.rightStyle.display = \'none\';\n
+  }\n
+  else {\n
+    this.rightStyle.top = top + \'px\';\n
+    this.rightStyle.left = left + width - delta + \'px\';\n
+    this.rightStyle.height = height + 1 + \'px\';\n
+    this.rightStyle.display = \'block\';\n
+  }\n
+\n
+  if (hideBottom || hideRight || !this.hasSetting(this.settings.border.cornerVisible)) {\n
+    this.cornerStyle.display = \'none\';\n
+  }\n
+  else {\n
+    this.cornerStyle.top = top + height - 4 + \'px\';\n
+    this.cornerStyle.left = left + width - 4 + \'px\';\n
+    this.cornerStyle.display = \'block\';\n
+  }\n
+};\n
+\n
+/**\n
+ * Hide border\n
+ */\n
+WalkontableBorder.prototype.disappear = function () {\n
+  this.topStyle.display = \'none\';\n
+  this.leftStyle.display = \'none\';\n
+  this.bottomStyle.display = \'none\';\n
+  this.rightStyle.display = \'none\';\n
+  this.cornerStyle.display = \'none\';\n
+};\n
+\n
+WalkontableBorder.prototype.hasSetting = function (setting) {\n
+  if (typeof setting === \'function\') {\n
+    return setting();\n
+  }\n
+  return !!setting;\n
+};\n
+/**\n
+ * WalkontableCellFilter\n
+ * @constructor\n
+ */\n
+function WalkontableCellFilter() {\n
+  this.offset = 0;\n
+  this.total = 0;\n
+  this.fixedCount = 0;\n
+}\n
+\n
+WalkontableCellFilter.prototype.source = function (n) {\n
+  return n;\n
+};\n
+\n
+WalkontableCellFilter.prototype.offsetted = function (n) {\n
+  return n + this.offset;\n
+};\n
+\n
+WalkontableCellFilter.prototype.unOffsetted = function (n) {\n
+  return n - this.offset;\n
+};\n
+\n
+WalkontableCellFilter.prototype.fixed = function (n) {\n
+  if (n < this.fixedCount) {\n
+    return n - this.offset;\n
+  }\n
+  else {\n
+    return n;\n
+  }\n
+};\n
+\n
+WalkontableCellFilter.prototype.unFixed = function (n) {\n
+  if (n < this.fixedCount) {\n
+    return n + this.offset;\n
+  }\n
+  else {\n
+    return n;\n
+  }\n
+};\n
+\n
+WalkontableCellFilter.prototype.visibleToSource = function (n) {\n
+  return this.source(this.offsetted(this.fixed(n)));\n
+};\n
+\n
+WalkontableCellFilter.prototype.sourceToVisible = function (n) {\n
+  return this.source(this.unOffsetted(this.unFixed(n)));\n
+};\n
+/**\n
+ * WalkontableCellStrategy\n
+ * @constructor\n
+ */\n
+function WalkontableCellStrategy(instance) {\n
+  this.instance = instance;\n
+}\n
+\n
+WalkontableCellStrategy.prototype.getSize = function (index) {\n
+  return this.cellSizes[index];\n
+};\n
+\n
+WalkontableCellStrategy.prototype.getContainerSize = function (proposedSize) {\n
+  return typeof this.containerSizeFn === \'function\' ? this.containerSizeFn(proposedSize) : this.containerSizeFn;\n
+};\n
+\n
+WalkontableCellStrategy.prototype.countVisible = function () {\n
+  return this.cellCount;\n
+};\n
+\n
+WalkontableCellStrategy.prototype.isLastIncomplete = function () {\n
+\n
+  if(this.instance.getSetting(\'nativeScrollbars\')){\n
+\n
+    var nativeScrollbar = this.instance.cloneFrom ? this.instance.cloneFrom.wtScrollbars.vertical : this.instance.wtScrollbars.vertical;\n
+    return this.remainingSize > nativeScrollbar.sumCellSizes(nativeScrollbar.offset, nativeScrollbar.offset + nativeScrollbar.curOuts + 1);\n
+\n
+  } else {\n
+    return this.remainingSize > 0;\n
+  }\n
+\n
+};\n
+/**\n
+ * WalkontableClassNameList\n
+ * @constructor\n
+ */\n
+function WalkontableClassNameCache() {\n
+  this.cache = [];\n
+}\n
+\n
+WalkontableClassNameCache.prototype.add = function (r, c, cls) {\n
+  if (!this.cache[r]) {\n
+    this.cache[r] = [];\n
+  }\n
+  if (!this.cache[r][c]) {\n
+    this.cache[r][c] = [];\n
+  }\n
+  this.cache[r][c][cls] = true;\n
+};\n
+\n
+WalkontableClassNameCache.prototype.test = function (r, c, cls) {\n
+  return (this.cache[r] && this.cache[r][c] && this.cache[r][c][cls]);\n
+};\n
+/**\n
+ * WalkontableColumnFilter\n
+ * @constructor\n
+ */\n
+function WalkontableColumnFilter() {\n
+  this.countTH = 0;\n
+}\n
+\n
+WalkontableColumnFilter.prototype = new WalkontableCellFilter();\n
+\n
+WalkontableColumnFilter.prototype.readSettings = function (instance) {\n
+  this.offset = instance.wtSettings.settings.offsetColumn;\n
+  this.total = instance.getSetting(\'totalColumns\');\n
+  this.fixedCount = instance.getSetting(\'fixedColumnsLeft\');\n
+  this.countTH = instance.getSetting(\'rowHeaders\').length;\n
+};\n
+\n
+WalkontableColumnFilter.prototype.offsettedTH = function (n) {\n
+  return n - this.countTH;\n
+};\n
+\n
+WalkontableColumnFilter.prototype.unOffsettedTH = function (n) {\n
+  return n + this.countTH;\n
+};\n
+\n
+WalkontableColumnFilter.prototype.visibleRowHeadedColumnToSourceColumn = function (n) {\n
+  return this.visibleToSource(this.offsettedTH(n));\n
+};\n
+\n
+WalkontableColumnFilter.prototype.sourceColumnToVisibleRowHeadedColumn = function (n) {\n
+  return this.unOffsettedTH(this.sourceToVisible(n));\n
+};\n
+/**\n
+ * WalkontableColumnStrategy\n
+ * @param containerSizeFn\n
+ * @param sizeAtIndex\n
+ * @param strategy - all, last, none\n
+ * @constructor\n
+ */\n
+function WalkontableColumnStrategy(instance, containerSizeFn, sizeAtIndex, strategy) {\n
+  var size\n
+    , i = 0;\n
+\n
+  WalkontableCellStrategy.apply(this, arguments);\n
+\n
+  this.containerSizeFn = containerSizeFn;\n
+  this.cellSizesSum = 0;\n
+  this.cellSizes = [];\n
+  this.cellStretch = [];\n
+  this.cellCount = 0;\n
+  this.remainingSize = 0;\n
+  this.strategy = strategy;\n
+\n
+  //step 1 - determine cells that fit containerSize and cache their widths\n
+  while (true) {\n
+    size = sizeAtIndex(i);\n
+    if (size === void 0) {\n
+      break; //total columns exceeded\n
+    }\n
+    if (this.cellSizesSum >= this.getContainerSize(this.cellSizesSum + size)) {\n
+      break; //total width exceeded\n
+    }\n
+    this.cellSizes.push(size);\n
+    this.cellSizesSum += size;\n
+    this.cellCount++;\n
+\n
+    i++;\n
+  }\n
+\n
+  var containerSize = this.getContainerSize(this.cellSizesSum);\n
+  this.remainingSize = this.cellSizesSum - containerSize;\n
+  //negative value means the last cell is fully visible and there is some space left for stretching\n
+  //positive value means the last cell is not fully visible\n
+}\n
+\n
+WalkontableColumnStrategy.prototype = new WalkontableCellStrategy();\n
+\n
+WalkontableColumnStrategy.prototype.getSize = function (index) {\n
+  return this.cellSizes[index] + (this.cellStretch[index] || 0);\n
+};\n
+\n
+WalkontableColumnStrategy.prototype.stretch = function () {\n
+  //step 2 - apply stretching strategy\n
+  var containerSize = this.getContainerSize(this.cellSizesSum)\n
+    , i = 0;\n
+  this.remainingSize = this.cellSizesSum - containerSize;\n
+\n
+  this.cellStretch.length = 0; //clear previous stretch\n
+\n
+  if (this.strategy === \'all\') {\n
+    if (this.remainingSize < 0) {\n
+      var ratio = containerSize / this.cellSizesSum;\n
+      var newSize;\n
+\n
+      while (i < this.cellCount - 1) { //"i < this.cellCount - 1" is needed because last cellSize is adjusted after the loop\n
+        newSize = Math.floor(ratio * this.cellSizes[i]);\n
+        this.remainingSize += newSize - this.cellSizes[i];\n
+        this.cellStretch[i] = newSize - this.cellSizes[i];\n
+        i++;\n
+      }\n
+      this.cellStretch[this.cellCount - 1] = -this.remainingSize;\n
+      this.remainingSize = 0;\n
+    }\n
+  }\n
+  else if (this.strategy === \'last\') {\n
+    if (this.remainingSize < 0 && containerSize !== Infinity) { //Infinity is with native scroll when the table is wider than the viewport (TODO: test)\n
+      this.cellStretch[this.cellCount - 1] = -th
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="6" aka="AAAAAAAAAAY=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+is.remainingSize;\n
+      this.remainingSize = 0;\n
+    }\n
+  }\n
+};\n
+function Walkontable(settings) {\n
+  var that = this,\n
+    originalHeaders = [];\n
+\n
+  this.guid = \'wt_\' + walkontableRandomString(); //this is the namespace for global events\n
+\n
+  //bootstrap from settings\n
+  this.wtDom = new WalkontableDom();\n
+  if (settings.cloneSource) {\n
+    this.cloneSource = settings.cloneSource;\n
+    this.cloneOverlay = settings.cloneOverlay;\n
+    this.wtSettings = settings.cloneSource.wtSettings;\n
+    this.wtTable = new WalkontableTable(this, settings.table);\n
+    this.wtScroll = new WalkontableScroll(this);\n
+    this.wtViewport = settings.cloneSource.wtViewport;\n
+  }\n
+  else {\n
+    this.wtSettings = new WalkontableSettings(this, settings);\n
+    this.wtTable = new WalkontableTable(this, settings.table);\n
+    this.wtScroll = new WalkontableScroll(this);\n
+    this.wtViewport = new WalkontableViewport(this);\n
+    this.wtScrollbars = new WalkontableScrollbars(this);\n
+    this.wtWheel = new WalkontableWheel(this);\n
+    this.wtEvent = new WalkontableEvent(this);\n
+  }\n
+\n
+  //find original headers\n
+  if (this.wtTable.THEAD.childNodes.length && this.wtTable.THEAD.childNodes[0].childNodes.length) {\n
+    for (var c = 0, clen = this.wtTable.THEAD.childNodes[0].childNodes.length; c < clen; c++) {\n
+      originalHeaders.push(this.wtTable.THEAD.childNodes[0].childNodes[c].innerHTML);\n
+    }\n
+    if (!this.getSetting(\'columnHeaders\').length) {\n
+      this.update(\'columnHeaders\', [function (column, TH) {\n
+        that.wtDom.fastInnerText(TH, originalHeaders[column]);\n
+      }]);\n
+    }\n
+  }\n
+\n
+  //initialize selections\n
+  this.selections = {};\n
+  var selectionsSettings = this.getSetting(\'selections\');\n
+  if (selectionsSettings) {\n
+    for (var i in selectionsSettings) {\n
+      if (selectionsSettings.hasOwnProperty(i)) {\n
+        this.selections[i] = new WalkontableSelection(this, selectionsSettings[i]);\n
+      }\n
+    }\n
+  }\n
+\n
+  this.drawn = false;\n
+  this.drawInterrupted = false;\n
+\n
+  //at this point the cached row heights may be invalid, but it is better not to reset the cache, which could cause scrollbar jumping when there are multiline cells outside of the rendered part of the table\n
+  /*if (window.Handsontable) {\n
+    Handsontable.PluginHooks.add(\'beforeChange\', function () {\n
+      if (that.rowHeightCache) {\n
+        that.rowHeightCache.length = 0;\n
+      }\n
+    });\n
+\n
+  }*/\n
+}\n
+\n
+Walkontable.prototype.draw = function (selectionsOnly) {\n
+  this.drawInterrupted = false;\n
+  if (!selectionsOnly && !this.wtDom.isVisible(this.wtTable.TABLE)) {\n
+    this.drawInterrupted = true; //draw interrupted because TABLE is not visible\n
+    return;\n
+  }\n
+\n
+  this.getSetting(\'beforeDraw\', !selectionsOnly);\n
+  selectionsOnly = selectionsOnly && this.getSetting(\'offsetRow\') === this.lastOffsetRow && this.getSetting(\'offsetColumn\') === this.lastOffsetColumn;\n
+  if (this.drawn) { //fix offsets that might have changed\n
+    this.scrollVertical(0);\n
+    this.scrollHorizontal(0);\n
+  }\n
+  this.lastOffsetRow = this.getSetting(\'offsetRow\');\n
+  this.lastOffsetColumn = this.getSetting(\'offsetColumn\');\n
+  this.wtTable.draw(selectionsOnly);\n
+  if (!this.cloneSource) {\n
+    this.getSetting(\'onDraw\',  !selectionsOnly);\n
+  }\n
+  return this;\n
+};\n
+\n
+Walkontable.prototype.update = function (settings, value) {\n
+  return this.wtSettings.update(settings, value);\n
+};\n
+\n
+Walkontable.prototype.scrollVertical = function (delta) {\n
+  var result = this.wtScroll.scrollVertical(delta);\n
+\n
+  this.getSetting(\'onScrollVertically\');\n
+\n
+  return result;\n
+};\n
+\n
+Walkontable.prototype.scrollHorizontal = function (delta) {\n
+  var result = this.wtScroll.scrollHorizontal(delta);\n
+\n
+  this.getSetting(\'onScrollHorizontally\');\n
+\n
+  return result;\n
+};\n
+\n
+Walkontable.prototype.scrollViewport = function (coords) {\n
+  this.wtScroll.scrollViewport(coords);\n
+  return this;\n
+};\n
+\n
+Walkontable.prototype.getViewport = function () {\n
+  return [\n
+    this.wtTable.rowFilter.visibleToSource(0),\n
+    this.wtTable.columnFilter.visibleToSource(0),\n
+    this.wtTable.getLastVisibleRow(),\n
+    this.wtTable.getLastVisibleColumn()\n
+  ];\n
+};\n
+\n
+Walkontable.prototype.getSetting = function (key, param1, param2, param3) {\n
+  return this.wtSettings.getSetting(key, param1, param2, param3);\n
+};\n
+\n
+Walkontable.prototype.hasSetting = function (key) {\n
+  return this.wtSettings.has(key);\n
+};\n
+\n
+Walkontable.prototype.destroy = function () {\n
+  $(document.body).off(\'.\' + this.guid);\n
+  this.wtScrollbars.destroy();\n
+  clearTimeout(this.wheelTimeout);\n
+  this.wtEvent && this.wtEvent.destroy();\n
+};\n
+/**\n
+ * A overlay that renders ALL available rows & columns positioned on top of the original Walkontable instance and all other overlays.\n
+ * Used for debugging purposes to see if the other overlays (that render only part of the rows & columns) are positioned correctly\n
+ * @param instance\n
+ * @constructor\n
+ */\n
+function WalkontableDebugOverlay(instance) {\n
+  this.instance = instance;\n
+  this.init();\n
+  this.clone = this.makeClone(\'debug\');\n
+  this.clone.wtTable.holder.style.opacity = 0.4;\n
+  this.clone.wtTable.holder.style.textShadow = \'0 0 2px #ff0000\';\n
+\n
+  var that = this;\n
+  var lastTimeout;\n
+  var lastX = 0;\n
+  var lastY = 0;\n
+  var overlayContainer = that.clone.wtTable.holder.parentNode;\n
+\n
+  $(document.body).on(\'mousemove.\' + this.instance.guid, function (event) {\n
+    if (!that.instance.wtTable.holder.parentNode) {\n
+      return; //removed from DOM\n
+    }\n
+    if ((event.clientX - lastX > -5 && event.clientX - lastX < 5) && (event.clientY - lastY > -5 && event.clientY - lastY < 5)) {\n
+      return; //ignore minor mouse movement\n
+    }\n
+    lastX = event.clientX;\n
+    lastY = event.clientY;\n
+    WalkontableDom.prototype.addClass(overlayContainer, \'wtDebugHidden\');\n
+    WalkontableDom.prototype.removeClass(overlayContainer, \'wtDebugVisible\');\n
+    clearTimeout(lastTimeout);\n
+    lastTimeout = setTimeout(function () {\n
+      WalkontableDom.prototype.removeClass(overlayContainer, \'wtDebugHidden\');\n
+      WalkontableDom.prototype.addClass(overlayContainer, \'wtDebugVisible\');\n
+    }, 1000);\n
+  });\n
+}\n
+\n
+WalkontableDebugOverlay.prototype = new WalkontableOverlay();\n
+\n
+WalkontableDebugOverlay.prototype.resetFixedPosition = function () {\n
+  if (!this.instance.wtTable.holder.parentNode) {\n
+    return; //removed from DOM\n
+  }\n
+  var elem = this.clone.wtTable.holder.parentNode;\n
+  var box = this.instance.wtTable.holder.getBoundingClientRect();\n
+  elem.style.top = Math.ceil(box.top, 10) + \'px\';\n
+  elem.style.left = Math.ceil(box.left, 10) + \'px\';\n
+};\n
+\n
+WalkontableDebugOverlay.prototype.prepare = function () {\n
+};\n
+\n
+WalkontableDebugOverlay.prototype.refresh = function (selectionsOnly) {\n
+  this.clone && this.clone.draw(selectionsOnly);\n
+};\n
+\n
+WalkontableDebugOverlay.prototype.getScrollPosition = function () {\n
+};\n
+\n
+WalkontableDebugOverlay.prototype.getLastCell = function () {\n
+};\n
+\n
+WalkontableDebugOverlay.prototype.applyToDOM = function () {\n
+};\n
+\n
+WalkontableDebugOverlay.prototype.scrollTo = function () {\n
+};\n
+\n
+WalkontableDebugOverlay.prototype.readWindowSize = function () {\n
+};\n
+\n
+WalkontableDebugOverlay.prototype.readSettings = function () {\n
+};\n
+function WalkontableDom() {\n
+}\n
+\n
+//goes up the DOM tree (including given element) until it finds an element that matches the nodeName\n
+WalkontableDom.prototype.closest = function (elem, nodeNames, until) {\n
+  while (elem != null && elem !== until) {\n
+    if (elem.nodeType === 1 && nodeNames.indexOf(elem.nodeName) > -1) {\n
+      return elem;\n
+    }\n
+    elem = elem.parentNode;\n
+  }\n
+  return null;\n
+};\n
+\n
+//goes up the DOM tree and checks if element is child of another element\n
+WalkontableDom.prototype.isChildOf = function (child, parent) {\n
+  var node = child.parentNode;\n
+  while (node != null) {\n
+    if (node == parent) {\n
+      return true;\n
+    }\n
+    node = node.parentNode;\n
+  }\n
+  return false;\n
+};\n
+\n
+/**\n
+ * Counts index of element within its parent\n
+ * WARNING: for performance reasons, assumes there are only element nodes (no text nodes). This is true for Walkotnable\n
+ * Otherwise would need to check for nodeType or use previousElementSibling\n
+ * @see http://jsperf.com/sibling-index/10\n
+ * @param {Element} elem\n
+ * @return {Number}\n
+ */\n
+WalkontableDom.prototype.index = function (elem) {\n
+  var i = 0;\n
+  while (elem = elem.previousSibling) {\n
+    ++i\n
+  }\n
+  return i;\n
+};\n
+\n
+if (document.documentElement.classList) {\n
+  // HTML5 classList API\n
+  WalkontableDom.prototype.hasClass = function (ele, cls) {\n
+    return ele.classList.contains(cls);\n
+  };\n
+\n
+  WalkontableDom.prototype.addClass = function (ele, cls) {\n
+    ele.classList.add(cls);\n
+  };\n
+\n
+  WalkontableDom.prototype.removeClass = function (ele, cls) {\n
+    ele.classList.remove(cls);\n
+  };\n
+}\n
+else {\n
+  //http://snipplr.com/view/3561/addclass-removeclass-hasclass/\n
+  WalkontableDom.prototype.hasClass = function (ele, cls) {\n
+    return ele.className.match(new RegExp(\'(\\\\s|^)\' + cls + \'(\\\\s|$)\'));\n
+  };\n
+\n
+  WalkontableDom.prototype.addClass = function (ele, cls) {\n
+    if (!this.hasClass(ele, cls)) ele.className += " " + cls;\n
+  };\n
+\n
+  WalkontableDom.prototype.removeClass = function (ele, cls) {\n
+    if (this.hasClass(ele, cls)) { //is this really needed?\n
+      var reg = new RegExp(\'(\\\\s|^)\' + cls + \'(\\\\s|$)\');\n
+      ele.className = ele.className.replace(reg, \' \').trim(); //String.prototype.trim is defined in polyfill.js\n
+    }\n
+  };\n
+}\n
+\n
+/*//http://net.tutsplus.com/tutorials/javascript-ajax/javascript-from-null-cross-browser-event-binding/\n
+ WalkontableDom.prototype.addEvent = (function () {\n
+ var that = this;\n
+ if (document.addEventListener) {\n
+ return function (elem, type, cb) {\n
+ if ((elem && !elem.length) || elem === window) {\n
+ elem.addEventListener(type, cb, false);\n
+ }\n
+ else if (elem && elem.length) {\n
+ var len = elem.length;\n
+ for (var i = 0; i < len; i++) {\n
+ that.addEvent(elem[i], type, cb);\n
+ }\n
+ }\n
+ };\n
+ }\n
+ else {\n
+ return function (elem, type, cb) {\n
+ if ((elem && !elem.length) || elem === window) {\n
+ elem.attachEvent(\'on\' + type, function () {\n
+\n
+ //normalize\n
+ //http://stackoverflow.com/questions/4643249/cross-browser-event-object-normalization\n
+ var e = window[\'event\'];\n
+ e.target = e.srcElement;\n
+ //e.offsetX = e.layerX;\n
+ //e.offsetY = e.layerY;\n
+ e.relatedTarget = e.relatedTarget || e.type == \'mouseover\' ? e.fromElement : e.toElement;\n
+ if (e.target.nodeType === 3) e.target = e.target.parentNode; //Safari bug\n
+\n
+ return cb.call(elem, e)\n
+ });\n
+ }\n
+ else if (elem.length) {\n
+ var len = elem.length;\n
+ for (var i = 0; i < len; i++) {\n
+ that.addEvent(elem[i], type, cb);\n
+ }\n
+ }\n
+ };\n
+ }\n
+ })();\n
+\n
+ WalkontableDom.prototype.triggerEvent = function (element, eventName, target) {\n
+ var event;\n
+ if (document.createEvent) {\n
+ event = document.createEvent("MouseEvents");\n
+ event.initEvent(eventName, true, true);\n
+ } else {\n
+ event = document.createEventObject();\n
+ event.eventType = eventName;\n
+ }\n
+\n
+ event.eventName = eventName;\n
+ event.target = target;\n
+\n
+ if (document.createEvent) {\n
+ target.dispatchEvent(event);\n
+ } else {\n
+ target.fireEvent("on" + event.eventType, event);\n
+ }\n
+ };*/\n
+\n
+WalkontableDom.prototype.removeTextNodes = function (elem, parent) {\n
+  if (elem.nodeType === 3) {\n
+    parent.removeChild(elem); //bye text nodes!\n
+  }\n
+  else if ([\'TABLE\', \'THEAD\', \'TBODY\', \'TFOOT\', \'TR\'].indexOf(elem.nodeName) > -1) {\n
+    var childs = elem.childNodes;\n
+    for (var i = childs.length - 1; i >= 0; i--) {\n
+      this.removeTextNodes(childs[i], elem);\n
+    }\n
+  }\n
+};\n
+\n
+/**\n
+ * Remove childs function\n
+ * WARNING - this doesn\'t unload events and data attached by jQuery\n
+ * http://jsperf.com/jquery-html-vs-empty-vs-innerhtml/9\n
+ * http://jsperf.com/jquery-html-vs-empty-vs-innerhtml/11 - no siginificant improvement with Chrome remove() method\n
+ * @param element\n
+ * @returns {void}\n
+ */\n
+//\n
+WalkontableDom.prototype.empty = function (element) {\n
+  var child;\n
+  while (child = element.lastChild) {\n
+    element.removeChild(child);\n
+  }\n
+};\n
+\n
+WalkontableDom.prototype.HTML_CHARACTERS = /(<(.*)>|&(.*);)/;\n
+\n
+/**\n
+ * Insert content into element trying avoid innerHTML method.\n
+ * @return {void}\n
+ */\n
+WalkontableDom.prototype.fastInnerHTML = function (element, content) {\n
+  if (this.HTML_CHARACTERS.test(content)) {\n
+    element.innerHTML = content;\n
+  }\n
+  else {\n
+    this.fastInnerText(element, content);\n
+  }\n
+};\n
+\n
+/**\n
+ * Insert text content into element\n
+ * @return {void}\n
+ */\n
+if (document.createTextNode(\'test\').textContent) { //STANDARDS\n
+  WalkontableDom.prototype.fastInnerText = function (element, content) {\n
+    var child = element.firstChild;\n
+    if (child && child.nodeType === 3 && child.nextSibling === null) {\n
+      //fast lane - replace existing text node\n
+      //http://jsperf.com/replace-text-vs-reuse\n
+      child.textContent = content;\n
+    }\n
+    else {\n
+      //slow lane - empty element and insert a text node\n
+      this.empty(element);\n
+      element.appendChild(document.createTextNode(content));\n
+    }\n
+  };\n
+}\n
+else { //IE8\n
+  WalkontableDom.prototype.fastInnerText = function (element, content) {\n
+    var child = element.firstChild;\n
+    if (child && child.nodeType === 3 && child.nextSibling === null) {\n
+      //fast lane - replace existing text node\n
+      //http://jsperf.com/replace-text-vs-reuse\n
+      child.data = content;\n
+    }\n
+    else {\n
+      //slow lane - empty element and insert a text node\n
+      this.empty(element);\n
+      element.appendChild(document.createTextNode(content));\n
+    }\n
+  };\n
+}\n
+\n
+/**\n
+ * Returns true/false depending if element has offset parent\n
+ * @param elem\n
+ * @returns {boolean}\n
+ */\n
+/*if (document.createTextNode(\'test\').textContent) { //STANDARDS\n
+  WalkontableDom.prototype.hasOffsetParent = function (elem) {\n
+    return !!elem.offsetParent;\n
+  }\n
+}\n
+else {\n
+  WalkontableDom.prototype.hasOffsetParent = function (elem) {\n
+    try {\n
+      if (!elem.offsetParent) {\n
+        return false;\n
+      }\n
+    }\n
+    catch (e) {\n
+      return false; //IE8 throws "Unspecified error" when offsetParent is not found - we catch it here\n
+    }\n
+    return true;\n
+  }\n
+}*/\n
+\n
+/**\n
+ * Returns true if element is attached to the DOM and visible, false otherwise\n
+ * @param elem\n
+ * @returns {boolean}\n
+ */\n
+WalkontableDom.prototype.isVisible = function (elem) {\n
+  //fast method according to benchmarks, but requires layout so slow in our case\n
+  /*\n
+  if (!WalkontableDom.prototype.hasOffsetParent(elem)) {\n
+    return false; //fixes problem with UI Bootstrap <tabs> directive\n
+  }\n
+\n
+//  if (elem.offsetWidth > 0 || (elem.parentNode && elem.parentNode.offsetWidth > 0)) { //IE10 was mistaken here\n
+  if (elem.offsetWidth > 0) {\n
+    return true;\n
+  }\n
+  */\n
+\n
+  //slow method\n
+  var next = elem;\n
+  while (next !== document.documentElement) { //until <html> reached\n
+    if (next === null) { //parent detached from DOM\n
+      return false;\n
+    }\n
+    else if (next.nodeType === 11) {  //nodeType == 1 -> DOCUMENT_FRAGMENT_NODE\n
+      if (next.host) { //this is Web Components Shadow DOM\n
+        //see: http://w3c.github.io/webcomponents/spec/shadow/#encapsulation\n
+        //according to spec, should be if (next.ownerDocument !== window.document), but that doesn\'t work yet\n
+        if (next.host.impl) { //Chrome 33.0.1723.0 canary (2013-11-29) Web Platform features disabled\n
+          return WalkontableDom.prototype.isVisible(next.host.impl);\n
+        }\n
+        else if (next.host) { //Chrome 33.0.1723.0 canary (2013-11-29) Web Platform features enabled\n
+          return WalkontableDom.prototype.isVisible(next.host);\n
+        }\n
+        else {\n
+          throw new Error("Lost in Web Components world");\n
+        }\n
+      }\n
+      else {\n
+        return false; //this is a node detached from document in IE8\n
+      }\n
+    }\n
+    else if (next.style.display === \'none\') {\n
+      return false;\n
+    }\n
+    next = next.parentNode;\n
+  }\n
+  return true;\n
+};\n
+\n
+/**\n
+ * Returns elements top and left offset relative to the document. In our usage case compatible with jQuery but 2x faster\n
+ * @param {HTMLElement} elem\n
+ * @return {Object}\n
+ */\n
+WalkontableDom.prototype.offset = function (elem) {\n
+  if (this.hasCaptionProblem() && elem.firstChild && elem.firstChild.nodeName === \'CAPTION\') {\n
+    //fixes problem with Firefox ignoring <caption> in TABLE offset (see also WalkontableDom.prototype.outerHeight)\n
+    //http://jsperf.com/offset-vs-getboundingclientrect/8\n
+    var box = elem.getBoundingClientRect();\n
+    return {\n
+      top: box.top + (window.pageYOffset || document.documentElement.scrollTop) - (document.documentElement.clientTop || 0),\n
+      left: box.left + (window.pageXOffset || document.documentElement.scrollLeft) - (document.documentElement.clientLeft || 0)\n
+    };\n
+  }\n
+\n
+  var offsetLeft = elem.offsetLeft\n
+    , offsetTop = elem.offsetTop\n
+    , lastElem = elem;\n
+\n
+  while (elem = elem.offsetParent) {\n
+    if (elem === document.body) { //from my observation, document.body always has scrollLeft/scrollTop == 0\n
+      break;\n
+    }\n
+    offsetLeft += elem.offsetLeft;\n
+    offsetTop += elem.offsetTop;\n
+    lastElem = elem;\n
+  }\n
+\n
+  if (lastElem && lastElem.style.position === \'fixed\') { //slow - http://jsperf.com/offset-vs-getboundingclientrect/6\n
+    //if(lastElem !== document.body) { //faster but does gives false positive in Firefox\n
+    offsetLeft += window.pageXOffset || document.documentElement.scrollLeft;\n
+    offsetTop += window.pageYOffset || document.documentElement.scrollTop;\n
+  }\n
+\n
+  return {\n
+    left: offsetLeft,\n
+    top: offsetTop\n
+  };\n
+};\n
+\n
+WalkontableDom.prototype.getComputedStyle = function (elem) {\n
+  return elem.currentStyle || document.defaultView.getComputedStyle(elem);\n
+};\n
+\n
+WalkontableDom.prototype.outerWidth = function (elem) {\n
+  return elem.offsetWidth;\n
+};\n
+\n
+WalkontableDom.prototype.outerHeight = function (elem) {\n
+  if (this.hasCaptionProblem() && elem.firstChild && elem.firstChild.nodeName === \'CAPTION\') {\n
+    //fixes problem with Firefox ignoring <caption> in TABLE.offsetHeight\n
+    //jQuery (1.10.1) still has this unsolved\n
+    //may be better to just switch to getBoundingClientRect\n
+    //http://bililite.com/blog/2009/03/27/finding-the-size-of-a-table/\n
+    //http://lists.w3.org/Archives/Public/www-style/2009Oct/0089.html\n
+    //http://bugs.jquery.com/ticket/2196\n
+    //http://lists.w3.org/Archives/Public/www-style/2009Oct/0140.html#start140\n
+    return elem.offsetHeight + elem.firstChild.offsetHeight;\n
+  }\n
+  else {\n
+    return elem.offsetHeight;\n
+  }\n
+};\n
+\n
+(function () {\n
+  var hasCaptionProblem;\n
+\n
+  function detectCaptionProblem() {\n
+    var TABLE = document.createElement(\'TABLE\');\n
+    TABLE.style.borderSpacing = 0;\n
+    TABLE.style.borderWidth = 0;\n
+    TABLE.style.padding = 0;\n
+    var TBODY = document.createElement(\'TBODY\');\n
+    TABLE.appendChild(TBODY);\n
+    TBODY.appendChild(document.createElement(\'TR\'));\n
+    TBODY.firstChild.appendChild(document.createElement(\'TD\'));\n
+    TBODY.firstChild.firstChild.innerHTML = \'<tr><td>t<br>t</td></tr>\';\n
+\n
+    var CAPTION = document.createElement(\'CAPTION\');\n
+    CAPTION.innerHTML = \'c<br>c<br>c<br>c\';\n
+    CAPTION.style.padding = 0;\n
+    CAPTION.style.margin = 0;\n
+    TABLE.insertBefore(CAPTION, TBODY);\n
+\n
+    document.body.appendChild(TABLE);\n
+    hasCaptionProblem = (TABLE.offsetHeight < 2 * TABLE.lastChild.offsetHeight); //boolean\n
+    document.body.removeChild(TABLE);\n
+  }\n
+\n
+  WalkontableDom.prototype.hasCaptionProblem = function () {\n
+    if (hasCaptionProblem === void 0) {\n
+      detectCaptionProblem();\n
+    }\n
+    return hasCaptionProblem;\n
+  };\n
+\n
+  /**\n
+   * Returns caret position in text input\n
+   * @author http://stackoverflow.com/questions/263743/how-to-get-caret-position-in-textarea\n
+   * @return {Number}\n
+   */\n
+  WalkontableDom.prototype.getCaretPosition = function (el) {\n
+    if (el.selectionStart) {\n
+      return el.selectionStart;\n
+    }\n
+    else if (document.selection) { //IE8\n
+      el.focus();\n
+      var r = document.selection.createRange();\n
+      if (r == null) {\n
+        return 0;\n
+      }\n
+      var re = el.createTextRange(),\n
+        rc = re.duplicate();\n
+      re.moveToBookmark(r.getBookmark());\n
+      rc.setEndPoint(\'EndToStart\', re);\n
+      return rc.text.length;\n
+    }\n
+    return 0;\n
+  };\n
+\n
+  /**\n
+   * Sets caret position in text input\n
+   * @author http://blog.vishalon.net/index.php/javascript-getting-and-setting-caret-position-in-textarea/\n
+   * @param {Element} el\n
+   * @param {Number} pos\n
+   * @param {Number} endPos\n
+   */\n
+  WalkontableDom.prototype.setCaretPosition = function (el, pos, endPos) {\n
+    if (endPos === void 0) {\n
+      endPos = pos;\n
+    }\n
+    if (el.setSelectionRange) {\n
+      el.focus();\n
+      el.setSelectionRange(pos, endPos);\n
+    }\n
+    else if (el.createTextRange) { //IE8\n
+      var range = el.createTextRange();\n
+      range.collapse(true);\n
+      range.moveEnd(\'character\', endPos);\n
+      range.moveStart(\'character\', pos);\n
+      range.select();\n
+    }\n
+  };\n
+\n
+  var cachedScrollbarWidth;\n
+  //http://stackoverflow.com/questions/986937/how-can-i-get-the-browsers-scrollbar-sizes\n
+  function walkontableCalculateScrollbarWidth() {\n
+    var inner = document.createElement(\'p\');\n
+    inner.style.width = "100%";\n
+    inner.style.height = "200px";\n
+\n
+    var outer = document.createElement(\'div\');\n
+    outer.style.position = "absolute";\n
+    outer.style.top = "0px";\n
+    outer.style.left = "0px";\n
+    outer.style.visibility = "hidden";\n
+    outer.style.width = "200px";\n
+    outer.style.height = "150px";\n
+    outer.style.overflow = "hidden";\n
+    outer.appendChild(inner);\n
+\n
+    (document.body || document.documentElement).appendChild(outer);\n
+    var w1 = inner.offsetWidth;\n
+    outer.style.overflow = \'scroll\';\n
+    var w2 = inner.offsetWidth;\n
+    if (w1 == w2) w2 = outer.clientWidth;\n
+\n
+    (document.body || document.documentElement).removeChild(outer);\n
+\n
+    return (w1 - w2);\n
+  }\n
+\n
+  /**\n
+   * Returns the computed width of the native browser scroll bar\n
+   * @return {Number} width\n
+   */\n
+  WalkontableDom.prototype.getScrollbarWidth = function () {\n
+    if (cachedScrollbarWidth === void 0) {\n
+      cachedScrollbarWidth = walkontableCalculateScrollbarWidth();\n
+    }\n
+    return cachedScrollbarWidth;\n
+  }\n
+})();\n
+\n
+function WalkontableEvent(instance) {\n
+  var that = this;\n
+\n
+  //reference to instance\n
+  this.instance = instance;\n
+\n
+  this.wtDom = this.instance.wtDom;\n
+\n
+  var dblClickOrigin = [null, null];\n
+  var dblClickTimeout = [null, null];\n
+\n
+  var onMouseDown = function (event) {\n
+    var cell = that.parentCell(event.target);\n
+\n
+    if (that.wtDom.hasClass(event.target, \'corner\')) {\n
+      that.instance.getSetting(\'onCellCornerMouseDown\', event, event.target);\n
+    }\n
+    else if (cell.TD && cell.TD.nodeName === \'TD\') {\n
+      if (that.instance.hasSetting(\'onCellMouseDown\')) {\n
+        that.instance.getSetting(\'onCellMouseDown\', event, cell.coords, cell.TD);\n
+      }\n
+    }\n
+\n
+    if (event.button !== 2) { //if not right mouse button\n
+      if (cell.TD && cell.TD.nodeName === \'TD\') {\n
+        dblClickOrigin[0] = cell.TD;\n
+        clearTimeout(dblClickTimeout[0]);\n
+        dblClickTimeout[0] = setTimeout(function () {\n
+          dblClickOrigin[0] = null;\n
+        }, 1000);\n
+      }\n
+    }\n
+  };\n
+\n
+  var lastMouseOver;\n
+  var onMouseOver = function (event) {\n
+    if (that.instance.hasSetting(\'onCellMouseOver\')) {\n
+      var TABLE = that.instance.wtTable.TABLE;\n
+      var TD = that.wtDom.closest(event.target, [\'TD\', \'TH\'], TABLE);\n
+      if (TD && TD !== lastMouseOver && that.wtDom.isChildOf(TD, TABLE)) {\n
+        lastMouseOver = TD;\n
+        if (TD.nodeName === \'TD\') {\n
+          that.instance.getSetting(\'onCellMouseOver\', event, that.instance.wtTable.getCoords(TD), TD);\n
+        }\n
+      }\n
+    }\n
+  };\n
+\n
+/*  var lastMouseOut;\n
+  var onMouseOut = function (event) {\n
+    if (that.instance.hasSetting(\'onCellMouseOut\')) {\n
+      var TABLE = that.instance.wtTable.TABLE;\n
+      var TD = that.wtDom.closest(event.target, [\'TD\', \'TH\'], TABLE);\n
+      if (TD && TD !== lastMouseOut && that.wtDom.isChildOf(TD, TABLE)) {\n
+        lastMouseOut = TD;\n
+        if (TD.nodeName === \'TD\') {\n
+          that.instance.getSetting(\'onCellMouseOut\', event, that.instance.wtTable.getCoords(TD), TD);\n
+        }\n
+      }\n
+    }\n
+  };*/\n
+\n
+  var onMouseUp = function (event) {\n
+    if (event.button !== 2) { //if not right mouse button\n
+      var cell = that.parentCell(event.target);\n
+\n
+      if (cell.TD === dblClickOrigin[0] && cell.TD === dblClickOrigin[1]) {\n
+        if (that.wtDom.hasClass(event.target, \'corner\')) {\n
+          that.instance.getSetting(\'onCellCornerDblClick\', event, cell.coords, cell.TD);\n
+        }\n
+        else if (cell.TD) {\n
+          that.instance.getSetting(\'onCellDblClick\', event, cell.coords, cell.TD);\n
+        }\n
+\n
+        dblClickOrigin[0] = null;\n
+        dblClickOrigin[1] = null;\n
+      }\n
+      else if (cell.TD === dblClickOrigin[0]) {\n
+        dblClickOrigin[1] = cell.TD;\n
+        clearTimeout(dblClickTimeout[1]);\n
+        dblClickTimeout[1] = setTimeout(function () {\n
+          dblClickOrigin[1] = null;\n
+        }, 500);\n
+      }\n
+    }\n
+  };\n
+\n
+  $(this.instance.wtTable.holder).on(\'mousedown\', onMouseDown);\n
+  $(this.instance.wtTable.TABLE).on(\'mouseover\', onMouseOver);\n
+//  $(this.instance.wtTable.TABLE).on(\'mouseout\', onMouseOut);\n
+  $(this.instance.wtTable.holder).on(\'mouseup\', onMouseUp);\n
+}\n
+\n
+WalkontableEvent.prototype.parentCell = function (elem) {\n
+  var cell = {};\n
+  var TABLE = this.instance.wtTable.TABLE;\n
+  var TD = this.wtDom.closest(elem, [\'TD\', \'TH\'], TABLE);\n
+  if (TD && this.wtDom.isChildOf(TD, TABLE)) {\n
+    cell.coords = this.instance.wtTable.getCoords(TD);\n
+    cell.TD = TD;\n
+  }\n
+  else if (this.wtDom.hasClass(elem, \'wtBorder\') && this.wtDom.hasClass(elem, \'current\')) {\n
+    cell.coords = this.instance.selections.current.selected[0];\n
+    cell.TD = this.instance.wtTable.getCell(cell.coords);\n
+  }\n
+  return cell;\n
+};\n
+\n
+WalkontableEvent.prototype.destroy = function () {\n
+  clearTimeout(this.dblClickTimeout0);\n
+  clearTimeout(this.dblClickTimeout1);\n
+};\n
+function walkontableRangesIntersect() {\n
+  var from = arguments[0];\n
+  var to = arguments[1];\n
+  for (var i = 1, ilen = arguments.length / 2; i < ilen; i++) {\n
+    if (from <= arguments[2 * i + 1] && to >= arguments[2 * i]) {\n
+      return true;\n
+    }\n
+  }\n
+  return false;\n
+}\n
+\n
+/**\n
+ * Generates a random hex string. Used as namespace for Walkontable instance events.\n
+ * @return {String} - 16 character random string: "92b1bfc74ec4"\n
+ */\n
+function walkontableRandomString() {\n
+  function s4() {\n
+    return Math.floor((1 + Math.random()) * 0x10000)\n
+      .toString(16)\n
+      .substring(1);\n
+  }\n
+\n
+  return s4() + s4() + s4() + s4();\n
+}\n
+/**\n
+ * http://notes.jetienne.com/2011/05/18/cancelRequestAnimFrame-for-paul-irish-requestAnimFrame.html\n
+ */\n
+window.requestAnimFrame = (function () {\n
+  return  window.requestAnimationFrame ||\n
+    window.webkitRequestAnimationFrame ||\n
+    window.mozRequestAnimationFrame ||\n
+    window.oRequestAnimationFrame ||\n
+    window.msRequestAnimationFrame ||\n
+    function (/* function */ callback, /* DOMElement */ element) {\n
+      return window.setTimeout(callback, 1000 / 60);\n
+    };\n
+})();\n
+\n
+window.cancelRequestAnimFrame = (function () {\n
+  return window.cancelAnimationFrame ||\n
+    window.webkitCancelRequestAnimationFrame ||\n
+    window.mozCancelRequestAnimationFrame ||\n
+    window.oCancelRequestAnimationFrame ||\n
+    window.msCancelRequestAnimationFrame ||\n
+    clearTimeout\n
+})();\n
+\n
+//http://snipplr.com/view/13523/\n
+//modified for speed\n
+//http://jsperf.com/getcomputedstyle-vs-style-vs-css/8\n
+if (!window.getComputedStyle) {\n
+  (function () {\n
+    var elem;\n
+\n
+    var styleObj = {\n
+      getPropertyValue: function getPropertyValue(prop) {\n
+        if (prop == \'float\') prop = \'styleFloat\';\n
+        return elem.currentStyle[prop.toUpperCase()] || null;\n
+      }\n
+    };\n
+\n
+    window.getComputedStyle = function (el) {\n
+      elem = el;\n
+      return styleObj;\n
+    }\n
+  })();\n
+}\n
+\n
+/**\n
+ * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/Trim\n
+ */\n
+if (!String.prototype.trim) {\n
+  var trimRegex = /^\\s+|\\s+$/g;\n
+  String.prototype.trim = function () {\n
+    return this.replace(trimRegex, \'\');\n
+  };\n
+}\n
+/**\n
+ * WalkontableRowFilter\n
+ * @constructor\n
+ */\n
+function WalkontableRowFilter() {\n
+}\n
+\n
+WalkontableRowFilter.prototype = new WalkontableCellFilter();\n
+\n
+WalkontableRowFilter.prototype.readSettings = function (instance) {\n
+  if (instance.cloneOverlay instanceof WalkontableDebugOverlay) {\n
+    this.offset = 0;\n
+  }\n
+  else {\n
+    this.offset = instance.wtSettings.settings.offsetRow;\n
+  }\n
+  this.total = instance.getSetting(\'totalRows\');\n
+  this.fixedCount = instance.getSetting(\'fixedRowsTop\');\n
+};\n
+/**\n
+ * WalkontableRowStrategy\n
+ * @param containerSizeFn\n
+ * @param sizeAtIndex\n
+ * @constructor\n
+ */\n
+function WalkontableRowStrategy(instance, containerSizeFn, sizeAtIndex) {\n
+\n
+  WalkontableCellStrategy.apply(this, arguments);\n
+\n
+  this.containerSizeFn = containerSizeFn;\n
+  this.sizeAtIndex = sizeAtIndex;\n
+  this.cellSizesSum = 0;\n
+  this.cellSizes = [];\n
+  this.cellCount = 0;\n
+  this.remainingSize = -Infinity;\n
+}\n
+\n
+WalkontableRowStrategy.prototype = new WalkontableCellStrategy();\n
+\n
+WalkontableRowStrategy.prototype.add = function (i, TD, reverse) {\n
+  if (!this.isLastIncomplete() && this.remainingSize != 0) {\n
+    var size = this.sizeAtIndex(i, TD);\n
+    if (size === void 0) {\n
+      return false; //total rows exceeded\n
+    }\n
+    var containerSize = this.getContainerSize(this.cellSizesSum + size);\n
+    if (reverse) {\n
+      this.cellSizes.unshift(size);\n
+    }\n
+    else {\n
+      this.cellSizes.push(size);\n
+    }\n
+    this.cellSizesSum += size;\n
+    this.cellCount++;\n
+    this.remainingSize = this.cellSizesSum - containerSize;\n
+\n
+    if (reverse && this.isLastIncomplete()) { //something is outside of the screen, maybe even some full rows?\n
+      return false;\n
+    }\n
+    return true;\n
+  }\n
+  return false;\n
+};\n
+\n
+WalkontableRowStrategy.prototype.remove = function () {\n
+  var size = this.cellSizes.pop();\n
+  this.cellSizesSum -= size;\n
+  this.cellCount--;\n
+  this.remainingSize -= size;\n
+};\n
+\n
+WalkontableRowStrategy.prototype.removeOutstanding = function () {\n
+  while (this.cellCount > 0 && this.cellSizes[this.cellCount - 1] < this.remainingSize) { //this row is completely off screen!\n
+    this.remove();\n
+  }\n
+};\n
+function WalkontableScroll(instance) {\n
+  this.instance = instance;\n
+}\n
+\n
+WalkontableScroll.prototype.scrollVertical = function (delta) {\n
+  if (!this.instance.drawn) {\n
+    throw new Error(\'scrollVertical can only be called after table was drawn to DOM\');\n
+  }\n
+\n
+  var instance = this.instance\n
+    , newOffset\n
+    , offset = instance.getSetting(\'offsetRow\')\n
+    , fixedCount = instance.getSetting(\'fixedRowsTop\')\n
+    , total = instance.getSetting(\'totalRows\')\n
+    , maxSize = instance.wtViewport.getViewportHeight();\n
+\n
+  if (total > 0) {\n
+    newOffset = this.scrollLogicVertical(delta, offset, total, fixedCount, maxSize, function (row) {\n
+      if (row - offset < fixedCount && row - offset >= 0) {\n
+        return instance.getSetting(\'rowHeight\', row - offset);\n
+      }\n
+      else {\n
+        return instance.getSetting(\'rowHeight\', row);\n
+      }\n
+    }, function (isReverse) {\n
+      instance.wtTable.verticalRenderReverse = isReverse;\n
+    });\n
+  }\n
+  else {\n
+    newOffset = 0;\n
+  }\n
+\n
+  if (newOffset !== offset) {\n
+    this.instance.wtScrollbars.vertical.scrollTo(newOffset);\n
+  }\n
+  return instance;\n
+};\n
+\n
+WalkontableScroll.prototype.scrollHorizontal = function (delta) {\n
+  if (!this.instance.drawn) {\n
+    throw new Error(\'scrollHorizontal can only be called after table was drawn to DOM\');\n
+  }\n
+\n
+  var instance = this.instance\n
+    , newOffset\n
+    , offset = instance.getSetting(\'offsetColumn\')\n
+    , fixedCount = instance.getSetting(\'fixedColumnsLeft\')\n
+    , total = instance.getSetting(\'totalColumns\')\n
+    , maxSize = instance.wtViewport.getViewportWidth();\n
+\n
+  if (total > 0) {\n
+    newOffset = this.scrollLogicHorizontal(delta, offset, total, fixedCount, maxSize, function (col) {\n
+      if (col - offset < fixedCount && col - offset >= 0) {\n
+        return instance.getSetting(\'columnWidth\', col - offset);\n
+      }\n
+      else {\n
+        return instance.getSetting(\'columnWidth\', col);\n
+      }\n
+    });\n
+  }\n
+  else {\n
+    newOffset = 0;\n
+  }\n
+\n
+  if (newOffset !== offset) {\n
+    this.instance.wtScrollbars.horizontal.scrollTo(newOffset);\n
+  }\n
+  return instance;\n
+};\n
+\n
+WalkontableScroll.prototype.scrollLogicVertical = function (delta, offset, total, fixedCount, maxSize, cellSizeFn, setReverseRenderFn) {\n
+  var newOffset = offset + delta;\n
+\n
+  if (newOffset >= total - fixedCount) {\n
+    newOffset = total - fixedCount - 1;\n
+    setReverseRenderFn(true);\n
+  }\n
+\n
+  if (newOffset < 0) {\n
+    newOffset = 0;\n
+  }\n
+\n
+  return newOffset;\n
+};\n
+\n
+WalkontableScroll.prototype.scrollLogicHorizontal = function (delta, offset, total, fixedCount, maxSize, cellSizeFn) {\n
+  var newOffset = offset + delta\n
+    , sum = 0\n
+    , col;\n
+\n
+  if (newOffset > fixedCount) {\n
+    if (newOffset >= total - fixedCount) {\n
+      newOffset = total - fixedCount - 1;\n
+    }\n
+\n
+    col = newOffset;\n
+    while (sum < maxSize && col < total) {\n
+      sum += cellSizeFn(col);\n
+      col++;\n
+    }\n
+\n
+    if (sum < maxSize) {\n
+      while (newOffset > 0) {\n
+        //if sum still less than available width, we cannot scroll that far (must move offset to the left)\n
+        sum += cellSizeFn(newOffset - 1);\n
+        if (sum < maxSize) {\n
+          newOffset--;\n
+        }\n
+        else {\n
+          break;\n
+        }\n
+      }\n
+    }\n
+  }\n
+  else if (newOffset < 0) {\n
+    newOffset = 0;\n
+  }\n
+\n
+  return newOffset;\n
+};\n
+\n
+/**\n
+ * Scrolls viewport to a cell by minimum number of cells\n
+ */\n
+WalkontableScroll.prototype.scrollViewport = function (coords) {\n
+  if (!this.instance.drawn) {\n
+    return;\n
+  }\n
+\n
+  var offsetRow = this.instance.getSetting(\'offsetRow\')\n
+    , offsetColumn = this.instance.getSetting(\'offsetColumn\')\n
+    , lastVisibleRow = this.instance.wtTable.getLastVisibleRow()\n
+    , totalRows = this.instance.getSetting(\'totalRows\')\n
+    , totalColumns = this.instance.getSetting(\'totalColumns\')\n
+    , fixedRowsTop = this.instance.getSetting(\'fixedRowsTop\')\n
+    , fixedColumnsLeft = this.instance.getSetting(\'fixedColumnsLeft\');\n
+\n
+  if (this.instance.getSetting(\'nativeScrollbars\')) {\n
+    var TD = this.instance.wtTable.getCell(coords);\n
+    if (typeof TD === \'object\') {\n
+      var offset = WalkontableDom.prototype.offset(TD);\n
+      var outerWidth = WalkontableDom.prototype.outerWidth(TD);\n
+      var outerHeight = WalkontableDom.prototype.outerHeight(TD);\n
+      var scrollX = this.instance.wtScrollbars.horizontal.getScrollPosition();\n
+      var scrollY = this.instance.wtScrollbars.vertical.getScrollPosition();\n
+      var clientWidth = WalkontableDom.prototype.outerWidth(this.instance.wtScrollbars.horizontal.scrollHandler);\n
+      var clientHeight = WalkontableDom.prototype.outerHeight(this.instance.wtScrollbars.vertical.scrollHandler);\n
+      if (this.instance.wtScrollbars.horizontal.scrollHandler !== window) {\n
+        offset.left = offset.left - WalkontableDom.prototype.offset(this.instance.wtScrollbars.horizontal.scrollHandler).left;\n
+      }\n
+      if (this.instance.wtScrollbars.vertical.scrollHandler !== window) {\n
+        offset.top = offset.top - WalkontableDom.prototype.offset(this.instance.wtScrollbars.vertical.scrollHandler).top;\n
+      }\n
+\n
+      clientWidth -= 20;\n
+      clientHeight -= 20;\n
+\n
+      if (outerWidth < clientWidth) {\n
+        if (offset.left < scrollX) {\n
+          this.instance.wtScrollbars.horizontal.setScrollPosition(offset.left);\n
+        }\n
+        else if (offset.left + outerWidth > scrollX + clientWidth) {\n
+          this.instance.wtScrollbars.horizontal.setScrollPosition(offset.left - clientWidth + outerWidth);\n
+        }\n
+      }\n
+      if (outerHeight < clientHeight) {\n
+        if (offset.top < scrollY) {\n
+          this.instance.wtScrollbars.vertical.setScrollPosition(offset.top);\n
+        }\n
+        else if (offset.top + outerHeight > scrollY + clientHeight) {\n
+          this.instance.wtScrollbars.vertical.setScrollPosition(offset.top - clientHeight + outerHeight);\n
+        }\n
+      }\n
+      return;\n
+    }\n
+  }\n
+\n
+  if (coords[0] < 0 || coords[0] > totalRows - 1) {\n
+    throw new Error(\'row \' + coords[0] + \' does not exist\');\n
+  }\n
+  else if (coords[1] < 0 || coords[1] > totalColumns - 1) {\n
+    throw new Error(\'column \' + coords[1] + \' does not exist\');\n
+  }\n
+\n
+  if (coords[0] > lastVisibleRow) {\n
+//    this.scrollVertical(coords[0] - lastVisibleRow + 1);\n
+    this.scrollVertical(coords[0] - fixedRowsTop - offsetRow);\n
+    this.instance.wtTable.verticalRenderReverse = true;\n
+  }\n
+  else if (coords[0] === lastVisibleRow && this.instance.wtTable.rowStrategy.isLastIncomplete()) {\n
+//    this.scrollVertical(coords[0] - lastVisibleRow + 1);\n
+    this.scrollVertical(coords[0] - fixedRowsTop - offsetRow);\n
+    this.instance.wtTable.verticalRenderReverse = true;\n
+  }\n
+  else if (coords[0] - fixedRowsTop < offsetRow) {\n
+    this.scrollVertical(coords[0] - fixedRowsTop - offsetRow);\n
+  }\n
+  else {\n
+    this.scrollVertical(0); //Craig\'s issue: remove row from the last scroll page should scroll viewport a row up if needed\n
+  }\n
+\n
+  if (this.instance.wtTable.isColumnBeforeViewport(coords[1])) {\n
+    //scroll left\n
+    this.instance.wtScrollbars.horizontal.scrollTo(coords[1] - fixedColumnsLeft);\n
+  }\n
+  else if (this.instance.wtTable.isColumnAfterViewport(coords[1]) || (this.instance.wtTable.getLastVisibleColumn() === coords[1] && !this.instance.wtTable.isLastColumnFullyVisible())) {\n
+    //scroll right\n
+    var sum = 0;\n
+    for (var i = 0; i < fixedColumnsLeft; i++) {\n
+      sum += this.instance.getSetting(\'columnWidth\', i);\n
+    }\n
+    var scrollTo = coords[1];\n
+    sum += this.instance.getSetting(\'columnWidth\', scrollTo);\n
+    var available = this.instance.wtViewport.getViewportWidth();\n
+    if (sum < available) {\n
+      var next = this.instance.getSetting(\'columnWidth\', scrollTo - 1);\n
+      while (sum + next <= available && scrollTo >= fixedColumnsLeft) {\n
+        scrollTo--;\n
+        sum += next;\n
+        next = this.instance.getSetting(\'columnWidth\', scrollTo - 1);\n
+      }\n
+    }\n
+\n
+    this.instance.wtScrollbars.horizontal.scrollTo(scrollTo - fixedColumnsLeft);\n
+  }\n
+  /*else {\n
+   //no scroll\n
+   }*/\n
+\n
+  return this.instance;\n
+};\n
+\n
+function WalkontableScrollbar() {\n
+}\n
+\n
+WalkontableScrollbar.prototype.init = function () {\n
+  var that = this;\n
+\n
+  //reference to instance\n
+  this.$table = $(this.instance.wtTable.TABLE);\n
+\n
+  //create elements\n
+  this.slider = document.createElement(\'DIV\');\n
+  this.sliderStyle = this.slider.style;\n
+  this.sliderStyle.position = \'absolute\';\n
+  this.sliderStyle.top = \'0\';\n
+  this.sliderStyle.left = \'0\';\n
+  this.sliderStyle.display = \'none\';\n
+  this.slider.className = \'dragdealer \' + this.type;\n
+\n
+  this.handle = document.createElement(\'DIV\');\n
+  this.handleStyle = this.handle.style;\n
+  this.handle.className = \'handle\';\n
+\n
+  this.slider.appendChild(this.handle);\n
+  this.container = this.instance.wtTable.holder;\n
+  this.container.appendChild(this.slider);\n
+\n
+  var firstRun = true;\n
+  this.dragTimeout = null;\n
+  var dragDelta;\n
+  var dragRender = function () {\n
+    that.onScroll(dragDelta);\n
+  };\n
+\n
+  this.dragdealer = new Dragdealer(this.slider, {\n
+    vertical: (this.type === \'vertical\'),\n
+    horizontal: (this.type === \'horizontal\'),\n
+    slide: false,\n
+    speed: 100,\n
+    animationCallback: function (x, y) {\n
+      if (firstRun) {\n
+        firstRun = false;\n
+        return;\n
+      }\n
+      that.skipRefresh = true;\n
+      dragDelta = that.type === \'vertical\' ? y : x;\n
+      if (that.dragTimeout === null) {\n
+        that.dragTimeout = setInterval(dragRender, 100);\n
+        dragRender();\n
+      }\n
+    },\n
+    callback: function (x, y) {\n
+      that.skipRefresh = false;\n
+      clearInterval(that.dragTimeout);\n
+      that.dragTimeout = null;\n
+      dragDelta = that.type === \'vertical\' ? y : x;\n
+      that.onScroll(dragDelta);\n
+    }\n
+  });\n
+  this.skipRefresh = false;\n
+};\n
+\n
+WalkontableScrollbar.prototype.onScroll = function (delta) {\n
+  if (this.instance.drawn) {\n
+    this.readSettings();\n
+    if (this.total > this.visibleCount) {\n
+      var newOffset = Math.round(this.handlePosition * this.total / this.sliderSize);\n
+\n
+      if (delta === 1) {\n
+        if (this.type === \'vertical\') {\n
+          this.instance.scrollVertical(Infinity).draw();\n
+        }\n
+        else {\n
+          this.instance.scrollHorizontal(Infinity).draw();\n
+        }\n
+      }\n
+      else if (newOffset !== this.offset) { //is new offset different than old offset\n
+        if (this.type === \'vertical\') {\n
+          this.instance.scrollVertical(newOffset - this.offset).draw();\n
+        }\n
+        else {\n
+          this.instance.scrollHorizontal(newOffset - this.offset).draw();\n
+        }\n
+      }\n
+      else {\n
+        this.refresh();\n
+      }\n
+    }\n
+  }\n
+};\n
+\n
+/**\n
+ * Returns what part of the scroller should the handle take\n
+ * @param viewportCount {Number} number of visible rows or columns\n
+ * @param totalCount {Number} total number of rows or columns\n
+ * @return {Number} 0..1\n
+ */\n
+WalkontableScrollbar.prototype.getHandleSizeRatio = function (viewportCount, totalCount) {\n
+  if (!totalCount || viewportCount > totalCount || viewportCount == totalCount) {\n
+    return 1;\n
+  }\n
+  return 1 / totalCount;\n
+};\n
+\n
+WalkontableScrollbar.prototype.prepare = function () {\n
+  if (this.skipRefresh) {\n
+    return;\n
+  }\n
+  var ratio = this.getHandleSizeRatio(this.visibleCount, this.total);\n
+  if (((ratio === 1 || isNaN(ratio)) && this.scrollMode === \'auto\') || this.scrollMode === \'none\') {\n
+    //isNaN is needed because ratio equals NaN when totalRows/totalColumns equals 0\n
+    this.visible = false;\n
+  }\n
+  else {\n
+    this.visible = true;\n
+  }\n
+};\n
+\n
+WalkontableScrollbar.prototype.refresh = function () {\n
+  if (this.skipRefresh) {\n
+    return;\n
+  }\n
+  else if (!this.visible) {\n
+    this.sliderStyle.display = \'none\';\n
+    return;\n
+  }\n
+\n
+  var ratio\n
+    , sliderSize\n
+    , handleSize\n
+    , handlePosition\n
+    , visibleCount = this.visibleCount\n
+    , tableWidth = this.instance.wtViewport.getWorkspaceWidth()\n
+    , tableHeight = this.instance.wtViewport.getWorkspaceHeight();\n
+\n
+  if (tableWidth === Infinity) {\n
+    tableWidth = this.instance.wtViewport.getWorkspaceActualWidth();\n
+  }\n
+\n
+  if (tableHeight === Infinity) {\n
+    tableHeight = this.instance.wtViewport.getWorkspaceActualHeight();\n
+  }\n
+\n
+  if (this.type === \'vertical\') {\n
+    if (this.instance.wtTable.rowStrategy.isLastIncomplete()) {\n
+      visibleCount--;\n
+    }\n
+\n
+    sliderSize = tableHeight - 2; //2 is sliders border-width\n
+\n
+    this.sliderStyle.top = this.instance.wtDom.offset(this.$table[0]).top - this.instance.wtDom.offset(this.container).top + \'px\';\n
+    this.sliderStyle.left = tableWidth - 1 + \'px\'; //1 is sliders border-width\n
+    this.sliderStyle.height = Math.max(sliderSize, 0) + \'px\';\n
+  }\n
+  else { //horizontal\n
+    sliderSize = tableWidth - 2; //2 is sliders border-width\n
+\n
+    this.sliderStyle.left = this.instance.wtDom.offset(this.$table[0]).left - this.instance.wtDom.offset(this.container).left + \'px\';\n
+    this.sliderStyle.top = tableHeight - 1 + \'px\'; //1 is sliders border-width\n
+    this.sliderStyle.width = Math.max(sliderSize, 0) + \'px\';\n
+  }\n
+\n
+  ratio = this.getHandleSizeRatio(visibleCount, this.total);\n
+  handleSize = Math.round(sliderSize * ratio);\n
+  if (handleSize < 10) {\n
+    handleSize = 15;\n
+  }\n
+\n
+  handlePosition = Math.floor(sliderSize * (this.offset / this.total));\n
+  if (handleSize + handlePosition > sliderSize) {\n
+    handlePosition = sliderSize - handleSize;\n
+  }\n
+\n
+  if (this.type === \'vertical\') {\n
+    this.handleStyle.height = handleSize + \'px\';\n
+    this.handleStyle.top = handlePosition + \'px\';\n
+\n
+  }\n
+  else { //horizontal\n
+    this.handleStyle.width = handleSize + \'px\';\n
+    this.handleStyle.left = handlePosition + \'px\';\n
+  }\n
+\n
+  this.sliderStyle.display = \'block\';\n
+};\n
+\n
+WalkontableScrollbar.prototype.destroy = function () {\n
+  clearInterval(this.dragdealer.interval);\n
+};\n
+\n
+///\n
+\n
+var WalkontableVerticalScrollbar = function (instance) {\n
+  this.instance = instance;\n
+  this.type = \'vertical\';\n
+  this.init();\n
+};\n
+\n
+WalkontableVerticalScrollbar.prototype = new WalkontableScrollbar();\n
+\n
+WalkontableVerticalScrollbar.prototype.scrollTo = function (cell) {\n
+  this.instance.update(\'offsetRow\', cell);\n
+};\n
+\n
+WalkontableVerticalScrollbar.prototype.readSettings = function () {\n
+  this.scrollMode = this.instance.getSetting(\'scrollV\');\n
+  this.offset = this.instance.getSetting(\'offsetRow\');\n
+  this.total = this.instance.getSetting(\'totalRows\');\n
+  this.visibleCount = this.instance.wtTable.rowStrategy.countVisible();\n
+  if(this.visibleCount > 1 && this.instance.wtTable.rowStrategy.isLastIncomplete()) {\n
+    this.visibleCount--;\n
+  }\n
+  this.handlePosition = parseInt(this.handleStyle.top, 10);\n
+  this.sliderSize = parseInt(this.sliderStyle.height, 10);\n
+  this.fixedCount = this.instance.getSetting(\'fixedRowsTop\');\n
+};\n
+\n
+///\n
+\n
+var WalkontableHorizontalScrollbar = function (instance) {\n
+  this.instance = instance;\n
+  this.type = \'horizontal\';\n
+  this.init();\n
+};\n
+\n
+WalkontableHorizontalScrollbar.prototype = new WalkontableScrollbar();\n
+\n
+WalkontableHorizontalScrollbar.prototype.scrollTo = function (cell) {\n
+  this.instance.update(\'offsetColumn\', cell);\n
+};\n
+\n
+WalkontableHorizontalScrollbar.prototype.readSettings = function () {\n
+  this.scrollMode = this.instance.getSetting(\'scrollH\');\n
+  this.offset = this.instance.getSetting(\'offsetColumn\');\n
+  this.total = this.instance.getSetting(\'totalColumns\');\n
+  this.visibleCount = this.instance.wtTable.columnStrategy.countVisible();\n
+  if(this.visibleCount > 1 && this.instance.wtTable.columnStrategy.isLastIncomplete()) {\n
+    this.visibleCount--;\n
+  }\n
+  this.handlePosition = parseInt(this.handleStyle.left, 10);\n
+  this.sliderSize = parseInt(this.sliderStyle.width, 10);\n
+  this.fixedCount = this.instance.getSetting(\'fixedColumnsLeft\');\n
+};\n
+\n
+WalkontableHorizontalScrollbar.prototype.getHandleSizeRatio = function (viewportCount, totalCount) {\n
+  if (!totalCount || viewportCount > totalCount || viewportCount == totalCount) {\n
+    return 1;\n
+  }\n
+  return viewportCount / totalCount;\n
+};\n
+function WalkontableCornerScrollbarNative(instance) {\n
+  this.instance = instance;\n
+  this.init();\n
+  this.clone = this.makeClone(\'corner\');\n
+}\n
+\n
+WalkontableCornerScrollbarNative.prototype = new WalkontableOverlay();\n
+\n
+WalkontableCornerScrollbarNative.prototype.resetFixedPosition = function () {\n
+  if (!this.instance.wtTable.holder.parentNode) {\n
+    return; //removed from DOM\n
+  }\n
+  var elem = this.clone.wtTable.holder.parentNode;\n
+\n
+  var box;\n
+  if (this.scrollHandler === window) {\n
+    box = this.instance.wtTable.hider.getBoundingClientRect();\n
+    var top = Math.ceil(box.top, 10);\n
+    var bottom = Math.ceil(box.bottom, 10);\n
+\n
+    if (top < 0 && bottom > 0) {\n
+      elem.style.top = \'0\';\n
+    }\n
+    else {\n
+      elem.style.top = top + \'px\';\n
+    }\n
+\n
+    var left = Math.ceil(box.left, 10);\n
+    var right = Math.ceil(box.right, 10);\n
+\n
+    if (left < 0 && right > 0) {\n
+      elem.style.left = \'0\';\n
+    }\n
+    else {\n
+      elem.style.left = left + \'px\';\n
+    }\n
+  }\n
+  else {\n
+    box = this.scrollHandler.getBoundingClientRect();\n
+    elem.style.top = Math.ceil(box.top, 10) + \'px\';\n
+    elem.style.left = Math.ceil(box.left, 10) + \'px\';\n
+  }\n
+\n
+  elem.style.width = WalkontableDom.prototype.outerWidth(this.clone.wtTable.TABLE) + 4 + \'px\';\n
+  elem.style.height = WalkontableDom.prototype.outerHeight(this.clone.wtTable.TABLE) + 4 + \'px\';\n
+};\n
+\n
+WalkontableCornerScrollbarNative.prototype.prepare = function () {\n
+};\n
+\n
+WalkontableCornerScrollbarNative.prototype.refresh = function (selectionsOnly) {\n
+  this.measureBefore = 0;\n
+  this.measureAfter = 0;\n
+  this.clone && this.clone.draw(selectionsOnly);\n
+};\n
+\n
+WalkontableCornerScrollbarNative.prototype.getScrollPosition = function () {\n
+};\n
+\n
+WalkontableCornerScrollbarNative.prototype.getLastCell = function () {\n
+};\n
+\n
+WalkontableCornerScrollbarNative.prototype.applyToDOM = function () {\n
+};\n
+\n
+WalkontableCornerScrollbarNative.prototype.scrollTo = function () {\n
+};\n
+\n
+WalkontableCornerScrollbarNative.prototype.readWindowSize = function () {\n
+};\n
+\n
+WalkontableCornerScrollbarNative.prototype.readSettings = function () {\n
+};\n
+function WalkontableHorizontalScrollbarNative(instance) {\n
+  this.instance = instance;\n
+  this.type = \'horizontal\';\n
+  this.cellSize = 50;\n
+  this.init();\n
+  this.clone = this.makeClone(\'left\');\n
+}\n
+\n
+WalkontableHorizontalScrollbarNative.prototype = new WalkontableOverlay();\n
+\n
+//resetFixedPosition (in future merge it with this.refresh?)\n
+WalkontableHorizontalScrollbarNative.prototype.resetFixedPosition = function () {\n
+  if (!this.instance.wtTable.holder.parentNode) {\n
+    return; //removed from DOM\n
+  }\n
+  var elem = this.clone.wtTable.holder.parentNode;\n
+\n
+  var box;\n
+  if (this.scrollHandler === window) {\n
+    box = this.instance.wtTable.hider.getBoundingClientRect();\n
+    var left = Math.ceil(box.left, 10);\n
+    var right = Math.ceil(box.right, 10);\n
+\n
+    if (left < 0 && right > 0) {\n
+      elem.style.left = \'0\';\n
+    }\n
+    else {\n
+      elem.style.left = left + \'px\';\n
+    }\n
+  }\n
+  else {\n
+    box = this.scrollHandler.getBoundingClientRect();\n
+    elem.style.top = Math.ceil(box.top, 10) + \'px\';\n
+    elem.style.left = Math.ceil(box.left, 10) + \'px\';\n
+  }\n
+};\n
+\n
+//react on movement of the other dimension scrollbar (in future merge it with this.refresh?)\n
+WalkontableHorizontalScrollbarNative.prototype.react = function () {\n
+  if (!this.instance.wtTable.holder.parentNode) {\n
+    return; //removed from DOM\n
+  }\n
+  var overlayContainer = this.clone.wtTable.holder.parentNode;\n
+  if (this.instance.wtScrollbars.vertical.scrollHandler === window) {\n
+    var box = this.instance.wtTable.hider.getBoundingClientRect();\n
+    overlayContainer.style.top = Math.ceil(box.top, 10) + \'px\';\n
+    overlayContainer.style.height = WalkontableDom.prototype.outerHeight(this.clone.wtTable.TABLE) + \'px\';\n
+  }\n
+  else {\n
+    this.clone.wtTable.holder.style.top = -(this.instance.wtScrollbars.vertical.windowScrollPosition - this.instance.wtScrollbars.vertical.measureBefore) + \'px\';\n
+    overlayContainer.style.height = this.instance.wtViewport.getWorkspaceHeight() + \'px\'\n
+  }\n
+  overlayContainer.style.width = WalkontableDom.prototype.outerWidth(this.clone.wtTable.TABLE) + 4 + \'px\'; //4 is for the box shadow\n
+};\n
+\n
+WalkontableHorizontalScrollbarNative.prototype.prepare = function () {\n
+};\n
+\n
+WalkontableHorizontalScrollbarNative.prototype.refresh = function (selectionsOnly) {\n
+  this.measureBefore = 0;\n
+  this.measureAfter = 0;\n
+  this.clone && this.clone.draw(selectionsOnly);\n
+};\n
+\n
+WalkontableHorizontalScrollbarNative.prototype.getScrollPosition = function () {\n
+  if (this.scrollHandler === window) {\n
+    return this.scrollHandler.scrollX;\n
+  }\n
+  else {\n
+    return this.scrollHandler.scrollLeft;\n
+  }\n
+};\n
+\n
+WalkontableHorizontalScrollbarNative.prototype.setScrollPosition = function (pos) {\n
+    this.scrollHandler.scrollLeft = pos;\n
+};\n
+\n
+WalkontableHorizontalScrollbarNative.prototype.onScroll = function () {\n
+  WalkontableOverlay.prototype.onScroll.apply(this, arguments);\n
+\n
+  this.instance.getSetting(\'onScrollHorizontally\');\n
+};\n
+\n
+WalkontableHorizontalScrollbarNative.prototype.getLastCell = function () {\n
+  return this.instance.wtTable.getLastVisibleColumn();\n
+};\n
+\n
+//applyToDOM (in future merge it with this.refresh?)\n
+WalkontableHorizontalScrollbarNative.prototype.applyToDOM = function () {\n
+  this.fixedContainer.style.paddingLeft = this.measureBefore + \'px\';\n
+  this.fixedContainer.style.paddingRight = this.measureAfter + \'px\';\n
+};\n
+\n
+WalkontableHorizontalScrollbarNative.prototype.scrollTo = function (cell) {\n
+  this.$scrollHandler.scrollLeft(this.tableParentOffset + cell * this.cellSize);\n
+};\n
+\n
+//readWindowSize (in future merge it with this.prepare?)\n
+WalkontableHorizontalScrollbarNative.prototype.readWindowSize = function () {\n
+  if (this.scrollHandler === window) {\n
+    this.windowSize = document.documentElement.clientWidth;\n
+    this.tableParentOffset = this.instance.wtTable.holderOffset.left;\n
+  }\n
+  else {\n
+    this.windowSize = WalkontableDom.prototype.outerWidth(this.scrollHandler);\n
+    this.tableParentOffset = 0;\n
+  }\n
+  this.windowScrollPosition = this.getScrollPosition();\n
+};\n
+\n
+//readSettings (in future merge it with this.prepare?)\n
+WalkontableHorizontalScrollbarNative.prototype.readSettings = function () {\n
+  this.offset = this.instance.getSetting(\'offsetColumn\');\n
+  this.total = this.instance.getSetting(\'totalColumns\');\n
+};\n
+function WalkontableVerticalScrollbarNative(instance) {\n
+  this.instance = instance;\n
+  this.type = \'vertical\';\n
+  this.cellSize = 23;\n
+  this.init();\n
+  this.clone = this.makeClone(\'top\');\n
+}\n
+\n
+WalkontableVerticalScrollbarNative.prototype = new WalkontableOverlay();\n
+\n
+//resetFixedPosition (in future merge it with this.refresh?)\n
+WalkontableVerticalScrollbarNative.prototype.resetFixedPosition = function () {\n
+  if (!this.instance.wtTable.holder.parentNode) {\n
+    return; //removed from DOM\n
+  }\n
+  var elem = this.clone.wtTable.holder.parentNode;\n
+\n
+  var box;\n
+  if (this.scrollHandler === window) {\n
+    box = this.instance.wtTable.hider.getBoundingClientRect();\n
+    var top = Math.ceil(box.top, 10);\n
+    var bottom = Math.ceil(box.bottom, 10);\n
+\n
+    if (top < 0 && bottom > 0) {\n
+      elem.style.top = \'0\';\n
+    }\n
+    else {\n
+      elem.style.top = top + \'px\';\n
+    }\n
+  }\n
+  else {\n
+    box = this.instance.wtScrollbars.horizontal.scrollHandler.getBoundingClientRect();\n
+    elem.style.top = Math.ceil(box.top, 10) + \'px\';\n
+    elem.style.left = Math.ceil(box.left, 10) + \'px\';\n
+  }\n
+\n
+  if (this.instance.wtScrollbars.horizontal.scrollHandler === window) {\n
+    elem.style.width = this.instance.wtViewport.getWorkspaceActualWidth() + \'px\';\n
+  }\n
+  else {\n
+    elem.style.width = WalkontableDom.prototype.outerWidth(this.instance.wtTable.holder.parentNode) + \'px\';\n
+  }\n
+\n
+  elem.style.height = WalkontableDom.prototype.outerHeight(this.clone.wtTable.TABLE) + 4 + \'px\';\n
+};\n
+\n
+//react on movement of the other dimension scrollbar (in future merge it with this.refresh?)\n
+WalkontableVerticalScrollbarNative.prototype.react = function () {\n
+  if (!this.instance.wtTable.holder.parentNode) {\n
+    return; //removed from DOM\n
+  }\n
+  if (this.instance.wtScrollbars.horizontal.scrollHandler !== window) {\n
+    var elem = this.clone.wtTable.holder.parentNode;\n
+    elem.firstChild.style.left = -this.instance.wtScrollbars.horizontal.windowScrollPosition + \'px\';\n
+  }\n
+};\n
+\n
+WalkontableVerticalScrollbarNative.prototype.getScrollPosition = function () {\n
+  if (this.scrollHandler === window) {\n
+    return this.scrollHandler.scrollY;\n
+  }\n
+  else {\n
+    return this.scrollHandler.scrollTop;\n
+  }\n
+};\n
+\n
+WalkontableVerticalScrollbarNative.prototype.setScrollPosition = function (pos) {\n
+  this.scrollHandler.scrollTop = pos;\n
+};\n
+\n
+WalkontableVerticalScrollbarNative.prototype.onScroll = function (forcePosition) {\n
+  WalkontableOverlay.prototype.onScroll.apply(this, arguments);\n
+\n
+  var scrollDelta;\n
+  var newOffset = 0;\n
+\n
+  if (1 == 1 || this.windowScrollPosition > this.tableParentOffset) {\n
+    scrollDelta = this.windowScrollPosition - this.tableParentOffset;\n
+\n
+    partialOffset = 0;\n
+    if (scrollDelta > 0) {\n
+      var sum = 0;\n
+      var last;\n
+      for (var i = 0; i < this.total; i++) {\n
+        last = this.instance.getSetting(\'rowHeight\', i);\n
+        sum += last;\n
+        if (sum > scrollDelta) {\n
+          break;\n
+        }\n
+      }\n
+\n
+      if (this.offset > 0) {\n
+        partialOffset = (sum - scrollDelta);\n
+      }\n
+      newOffset = i;\n
+      newOffset = Math.min(newOffset, this.total);\n
+    }\n
+  }\n
+\n
+  this.curOuts = newOffset > this.maxOuts ? this.maxOuts : newOffset;\n
+  newOffset -= this.curOuts;\n
+\n
+  this.instance.update(\'offsetRow\', newOffset);\n
+  this.readSettings(); //read new offset\n
+  this.instance.draw();\n
+\n
+  this.instance.getSetting(\'onScrollVertically\');\n
+};\n
+\n
+WalkontableVerticalScrollbarNative.prototype.getLastCell = function () {\n
+  return this.instance.getSetting(\'offsetRow\') + this.instance.wtTable.tbodyChildrenLength - 1;\n
+};\n
+\n
+var partialOffset = 0;\n
+\n
+WalkontableVerticalScrollbarNative.prototype.sumCellSizes = function (from, length) {\n
+  var sum = 0;\n
+  while (from < length) {\n
+    sum += this.instance.getSetting(\'rowHeight\', from);\n
+    from++;\n
+  }\n
+  return sum;\n
+};\n
+\n
+//applyToDOM (in future merge it with this.refresh?)\n
+WalkontableVerticalScrollbarNative.prototype.applyToDOM = function () {\n
+  var headerSize = this.instance.wtViewport.getColumnHeaderHeight();\n
+  this.fixedContainer.style.height = headerSize + this.sumCellSizes(0, this.total) + 4 + \'px\'; //+4 is needed, otherwise vertical scroll appears in Chrome (window scroll mode) - maybe because of fill handle in last row or because of box shadow\n
+  this.fixed.style.top = this.measureBefore + \'px\';\n
+  this.fixed.style.bottom = \'\';\n
+};\n
+\n
+WalkontableVerticalScrollbarNative.prototype.scrollTo = function (cell) {\n
+  var newY = this.tableParentOffset + cell * this.cellSize;\n
+  this.$scrollHandler.scrollTop(newY);\n
+  this.onScroll(newY);\n
+};\n
+\n
+//readWindowSize (in future merge it with this.prepare?)\n
+WalkontableVerticalScrollbarNative.prototype.readWindowSize = function () {\n
+  if (this.scrollHandler === window) {\n
+    this.windowSize = document.documentElement.clientHeight;\n
+    this.tableParentOffset = this.instance.wtTable.holderOffset.top;\n
+  }\n
+  else {\n
+    //this.windowSize = WalkontableDom.prototype.outerHeight(this.scrollHandler);\n
+    this.windowSize = this.scrollHandler.clientHeight; //returns height without DIV scrollbar\n
+    this.tableParentOffset = 0;\n
+  }\n
+  this.windowScrollPosition = this.getScrollPosition();\n
+};\n
+\n
+//readSettings (in future merge it with this.prepare?)\n
+WalkontableVerticalScrollbarNative.prototype.readSettings = function () {\n
+  this.offset = this.instance.getSetting(\'offsetRow\');\n
+  this.total = this.instance.getSetting(\'totalRows\');\n
+};\n
+function WalkontableScrollbars(instance) {\n
+  this.instance = instance;\n
+  if (instance.getSetting(\'nativeScrollbars\')) {\n
+    instance.update(\'scrollbarWidth\', instance.wtDom.getScrollbarWidth());\n
+    instance.update(\'scrollbarHeight\', instance.wtDom.getScrollbarWidth());\n
+    this.vertical = new WalkontableVerticalScrollbarNative(instance);\n
+    this.horizontal = new WalkontableHorizontalScrollbarNative(instance);\n
+    this.corner = new WalkontableCornerScrollbarNative(instance);\n
+    if (instance.getSetting(\'debug\')) {\n
+      this.debug = new WalkontableDebugOverlay(instance);\n
+    }\n
+    this.registerListeners();\n
+  }\n
+  else {\n
+    this.vertical = new WalkontableVerticalScrollbar(instance);\n
+    this.horizontal = new WalkontableHorizontalScrollbar(instance);\n
+  }\n
+}\n
+\n
+WalkontableScrollbars.prototype.registerListeners = function () {\n
+  var that = this;\n
+\n
+  var oldVerticalScrollPosition\n
+    , oldHorizontalScrollPosition\n
+    , oldBoxTop\n
+    , oldBoxLeft\n
+    , oldBoxWidth\n
+    , oldBoxHeight;\n
+\n
+  function refreshAll() {\n
+    if (!that.instance.wtTable.holder.parentNode) {\n
+      //Walkontable was detached from DOM, but this handler was not removed\n
+      that.destroy();\n
+      return;\n
+    }\n
+\n
+    that.vertical.windowScrollPosition = that.vertical.getScrollPosition();\n
+    that.horizontal.windowScrollPosition = that.horizontal.getScrollPosition();\n
+    that.box = that.instance.wtTable.hider.getBoundingClientRect();\n
+\n
+    if((that.box.width !== oldBoxWidth || that.box.height !== oldBoxHeight) && that.instance.rowHeightCache) {\n
+      //that.instance.rowHeightCache.length = 0; //at this point the cached row heights may be invalid, but it is better not to reset the cache, which could cause scrollbar jumping when there are multiline cells outside of the rendered part of the table\n
+      oldBoxWidth = that.box.width;\n
+      oldBoxHeight = that.box.height;\n
+      that.instance.draw();\n
+    }\n
+\n
+    if (that.vertical.windowScrollPosition !== oldVerticalScrollPosition || that.horizontal.windowScrollPosition !== oldHorizontalScrollPosition || that.box.top !== oldBoxTop || that.box.left !== oldBoxLeft) {\n
+      that.vertical.onScroll();\n
+      that.horizontal.onScroll(); //it\'s done here to make sure that all onScroll\'s are executed before changing styles\n
+\n
+      that.vertical.react();\n
+      that.horizontal.react(); //it\'s done here to make sure that all onScroll\'s are executed before changing styles\n
+\n
+      oldVerticalScrollPosition = that.vertical.windowScrollPosition;\n
+      oldHorizontalScrollPosition = that.horizontal.windowScrollPosition;\n
+      oldBoxTop = that.box.top;\n
+      oldBoxLeft = that.box.left;\n
+    }\n
+  }\n
+\n
+  var $window = $(window);\n
+  this.vertical.$scrollHandler.on(\'scroll.\' + this.instance.guid, refreshAll);\n
+  if (this.vertical.scrollHandler !== this.horizontal.scrollHandler) {\n
+    this.horizontal.$scrollHandler.on(\'scroll.\' + this.instance.guid, refreshAll);\n
+  }\n
+\n
+  if (this.vertical.scrollHandler !== window && this.horizontal.scrollHandler !== window) {\n
+    $window.on(\'scroll.\' + this.instance.guid, refreshAll);\n
+  }\n
+  $window.on(\'load.\' + this.instance.guid, refreshAll);\n
+  $window.on(\'resize.\' + this.instance.guid, refreshAll);\n
+  $(document).on(\'ready.\' + this.instance.guid, refreshAll);\n
+  setInterval(refreshAll, 100); //Marcin - only idea I have to reposition scrollbars on CSS change of the container (container was moved using some styles after page was loaded)\n
+};\n
+\n
+WalkontableScrollbars.prototype.destroy = function () {\n
+  this.vertical && this.vertical.destroy();\n
+  this.horizontal && this.horizontal.destroy();\n
+};\n
+\n
+WalkontableScrollbars.prototype.refresh = function (selectionsOnly) {\n
+  this.horizontal && this.horizontal.readSettings();\n
+  this.vertical && this.vertical.readSettings();\n
+  this.horizontal && this.horizontal.prepare();\n
+  this.vertical && this.vertical.prepare();\n
+  this.horizontal && this.horizontal.refresh(selectionsOnly);\n
+  this.vertical && this.vertical.refresh(selectionsOnly);\n
+  this.corner && this.corner.refresh(selectionsOnly);\n
+  this.debug && this.debug.refresh(selectionsOnly);\n
+};\n
+function WalkontableSelection(instance, settings) {\n
+  this.instance = instance;\n
+  this.settings = settings;\n
+  this.selected = [];\n
+  if (settings.border) {\n
+    this.border = new WalkontableBorder(instance, settings);\n
+  }\n
+}\n
+\n
+WalkontableSelection.prototype.add = function (coords) {\n
+  this.selected.push(coords);\n
+};\n
+\n
+WalkontableSelection.prototype.clear = function () {\n
+  this.selected.length = 0; //http://jsperf.com/clear-arrayxxx\n
+};\n
+\n
+/**\n
+ * Returns the top left (TL) and bottom right (BR) selection coordinates\n
+ * @returns {Object}\n
+ */\n
+WalkontableSelection.prototype.getCorners = function () {\n
+  var minRow\n
+    , minColumn\n
+    , maxRow\n
+    , maxColumn\n
+    , i\n
+    , ilen = this.selected.length;\n
+\n
+  if (ilen > 0) {\n
+    minRow = maxRow = this.selected[0][0];\n
+    minColumn = maxColumn = this.selected[0][1];\n
+\n
+    if (ilen > 1) {\n
+      for (i = 1; i < ilen; i++) {\n
+        if (this.selected[i][0] < minRow) {\n
+          minRow = this.selected[i][0];\n
+        }\n
+        else if (this.selected[i][0] > maxRow) {\n
+          maxRow = this.selected[i][0];\n
+        }\n
+\n
+        if (this.selected[i][1] < minColumn) {\n
+          minColumn = this.selected[i][1];\n
+        }\n
+        else if (this.selected[i][1] > maxColumn) {\n
+          maxColumn = this.selected[i][1];\n
+        }\n
+      }\n
+    }\n
+  }\n
+\n
+  return [minRow, minColumn, maxRow, maxColumn];\n
+};\n
+\n
+WalkontableSelection.prototype.draw = function () {\n
+  var corners, r, c, source_r, source_c;\n
+\n
+  var visibleRows = this.instance.wtTable.rowStrategy.countVisible()\n
+    , visibleColumns = this.instance.wtTable.columnStrategy.countVisible();\n
+\n
+  if (this.selected.length) {\n
+    corners = this.getCorners();\n
+\n
+    for (r = 0; r < visibleRows; r++) {\n
+      for (c = 0; c < visibleColumns; c++) {\n
+        source_r = this.instance.wtTable.rowFilter.visibleToSource(r);\n
+        source_c = this.instance.wtTable.columnFilter.visibleToSource(c);\n
+\n
+        if (source_r >= corners[0] && source_r <= corners[2] && source_c >= corners[1] && source_c <= corners[3]) {\n
+          //selected cell\n
+          this.instance.wtTable.currentCellCache.add(r, c, this.settings.className);\n
+        }\n
+        else if (source_r >= corners[0] && source_r <= corners[2]) {\n
+          //selection is in this row\n
+          this.instance.wtTable.currentCellCache.add(r, c, this.settings.highlightRowClassName);\n
+        }\n
+        else if (source_c >= corners[1] && source_c <= corners[3]) {\n
+          //selection is in this column\n
+          this.instance.wtTable.currentCellCache.add(r, c, this.settings.highlightColumnClassName);\n
+        }\n
+      }\n
+    }\n
+\n
+    this.border && this.border.appear(corners); //warning! border.appear modifies corners!\n
+  }\n
+  else {\n
+    this.border && this.border.disappear();\n
+  }\n
+};\n
+\n
+function WalkontableSettings(instance, settings) {\n
+  var that = this;\n
+  this.instance = instance;\n
+\n
+  //default settings. void 0 means it is required, null means it can be empty\n
+  this.defaults = {\n
+    table: void 0,\n
+    debug: false, //shows WalkontableDebugOverlay\n
+\n
+    //presentation mode\n
+    scrollH: \'auto\', //values: scroll (always show scrollbar), auto (show scrollbar if table does not fit in the container), none (never show scrollbar)\n
+    scrollV: \'auto\', //values: see above\n
+    nativeScrollbars: false, //values: false (dragdealer), true (native)\n
+    stretchH: \'hybrid\', //values: hybrid, all, last, none\n
+    currentRowClassName: null,\n
+    currentColumnClassName: null,\n
+\n
+    //data source\n
+    data: void 0,\n
+    offsetRow: 0,\n
+    offsetColumn: 0,\n
+    fixedColumnsLeft: 0,\n
+    fixedRowsTop: 0,\n
+    rowHeaders: function () {\n
+      return []\n
+    }, //this must be array of functions: [function (row, TH) {}]\n
+    columnHeaders: function () {\n
+      return []\n
+    }, //this must be array of functions: [function (column, TH) {}]\n
+    totalRows: void 0,\n
+    totalColumns: void 0,\n
+    width: null,\n
+    height: null,\n
+    cellRenderer: function (row, column, TD) {\n
+      var cellData = that.getSetting(\'data\', row, column);\n
+      that.instance.wtDom.fastInnerText(TD, cellData === void 0 || cellData === null ? \'\' : cellData);\n
+    },\n
+    columnWidth: 50,\n
+    selections: null,\n
+    hideBorderOnMouseDownOver: false,\n
+\n
+    //callbacks\n
+    onCellMouseDown: null,\n
+    onCellMouseOver: null,\n
+//    onCellMouseOut: null,\n
+    onCellDblClick: null,\n
+    onCellCornerMouseDown: null,\n
+    onCellCornerDblClick: null,\n
+    beforeDraw: null,\n
+    onDraw: null,\n
+    onScrollVertically: null,\n
+    onScrollHorizontally: null,\n
+\n
+    //constants\n
+    scrollbarWidth: 10,\n
+    scrollbarHeight: 10\n
+  };\n
+\n
+  //reference to settings\n
+  this.settings = {};\n
+  for (var i in this.defaults) {\n
+    if (this.defaults.hasOwnProperty(i)) {\n
+      if (settings[i] !== void 0) {\n
+        this.settings[i] = settings[i];\n
+      }\n
+      else if (this.defaults[i] === void 0) {\n
+        throw new Error(\'A required setting "\' + i + \'" was not provided\');\n
+      }\n
+      else {\n
+        this.settings[i] = this.defaults[i];\n
+      }\n
+    }\n
+  }\n
+}\n
+\n
+/**\n
+ * generic methods\n
+ */\n
+\n
+WalkontableSettings.prototype.update = function (settings, value) {\n
+  if (value === void 0) { //setti
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAc=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="7" aka="AAAAAAAAAAc=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+ngs is object\n
+    for (var i in settings) {\n
+      if (settings.hasOwnProperty(i)) {\n
+        this.settings[i] = settings[i];\n
+      }\n
+    }\n
+  }\n
+  else { //if value is defined then settings is the key\n
+    this.settings[settings] = value;\n
+  }\n
+  return this.instance;\n
+};\n
+\n
+WalkontableSettings.prototype.getSetting = function (key, param1, param2, param3) {\n
+  if (this[key]) {\n
+    return this[key](param1, param2, param3);\n
+  }\n
+  else {\n
+    return this._getSetting(key, param1, param2, param3);\n
+  }\n
+};\n
+\n
+WalkontableSettings.prototype._getSetting = function (key, param1, param2, param3) {\n
+  if (typeof this.settings[key] === \'function\') {\n
+    return this.settings[key](param1, param2, param3);\n
+  }\n
+  else if (param1 !== void 0 && Object.prototype.toString.call(this.settings[key]) === \'[object Array]\') {\n
+    return this.settings[key][param1];\n
+  }\n
+  else {\n
+    return this.settings[key];\n
+  }\n
+};\n
+\n
+WalkontableSettings.prototype.has = function (key) {\n
+  return !!this.settings[key]\n
+};\n
+\n
+/**\n
+ * specific methods\n
+ */\n
+WalkontableSettings.prototype.rowHeight = function (row, TD) {\n
+  if (!this.instance.rowHeightCache) {\n
+    this.instance.rowHeightCache = []; //hack. This cache is being invalidated in WOT core.js\n
+  }\n
+  if (this.instance.rowHeightCache[row] === void 0) {\n
+    var size = 23; //guess\n
+    if (TD) {\n
+      size = this.instance.wtDom.outerHeight(TD); //measure\n
+      this.instance.rowHeightCache[row] = size; //cache only something we measured\n
+    }\n
+    return size;\n
+  }\n
+  else {\n
+    return this.instance.rowHeightCache[row];\n
+  }\n
+};\n
+function WalkontableTable(instance, table) {\n
+  //reference to instance\n
+  this.instance = instance;\n
+  this.TABLE = table;\n
+  this.wtDom = this.instance.wtDom;\n
+  this.wtDom.removeTextNodes(this.TABLE);\n
+\n
+  //wtSpreader\n
+  var parent = this.TABLE.parentNode;\n
+  if (!parent || parent.nodeType !== 1 || !this.wtDom.hasClass(parent, \'wtHolder\')) {\n
+    var spreader = document.createElement(\'DIV\');\n
+    spreader.className = \'wtSpreader\';\n
+    if (parent) {\n
+      parent.insertBefore(spreader, this.TABLE); //if TABLE is detached (e.g. in Jasmine test), it has no parentNode so we cannot attach holder to it\n
+    }\n
+    spreader.appendChild(this.TABLE);\n
+  }\n
+  this.spreader = this.TABLE.parentNode;\n
+\n
+  //wtHider\n
+  parent = this.spreader.parentNode;\n
+  if (!parent || parent.nodeType !== 1 || !this.wtDom.hasClass(parent, \'wtHolder\')) {\n
+    var hider = document.createElement(\'DIV\');\n
+    hider.className = \'wtHider\';\n
+    if (parent) {\n
+      parent.insertBefore(hider, this.spreader); //if TABLE is detached (e.g. in Jasmine test), it has no parentNode so we cannot attach holder to it\n
+    }\n
+    hider.appendChild(this.spreader);\n
+  }\n
+  this.hider = this.spreader.parentNode;\n
+  this.hiderStyle = this.hider.style;\n
+  this.hiderStyle.position = \'relative\';\n
+\n
+  //wtHolder\n
+  parent = this.hider.parentNode;\n
+  if (!parent || parent.nodeType !== 1 || !this.wtDom.hasClass(parent, \'wtHolder\')) {\n
+    var holder = document.createElement(\'DIV\');\n
+    holder.style.position = \'relative\';\n
+    holder.className = \'wtHolder\';\n
+    if (parent) {\n
+      parent.insertBefore(holder, this.hider); //if TABLE is detached (e.g. in Jasmine test), it has no parentNode so we cannot attach holder to it\n
+    }\n
+    holder.appendChild(this.hider);\n
+  }\n
+  this.holder = this.hider.parentNode;\n
+\n
+  //bootstrap from settings\n
+  this.TBODY = this.TABLE.getElementsByTagName(\'TBODY\')[0];\n
+  if (!this.TBODY) {\n
+    this.TBODY = document.createElement(\'TBODY\');\n
+    this.TABLE.appendChild(this.TBODY);\n
+  }\n
+  this.THEAD = this.TABLE.getElementsByTagName(\'THEAD\')[0];\n
+  if (!this.THEAD) {\n
+    this.THEAD = document.createElement(\'THEAD\');\n
+    this.TABLE.insertBefore(this.THEAD, this.TBODY);\n
+  }\n
+  this.COLGROUP = this.TABLE.getElementsByTagName(\'COLGROUP\')[0];\n
+  if (!this.COLGROUP) {\n
+    this.COLGROUP = document.createElement(\'COLGROUP\');\n
+    this.TABLE.insertBefore(this.COLGROUP, this.THEAD);\n
+  }\n
+\n
+  if (this.instance.getSetting(\'columnHeaders\').length) {\n
+    if (!this.THEAD.childNodes.length) {\n
+      var TR = document.createElement(\'TR\');\n
+      this.THEAD.appendChild(TR);\n
+    }\n
+  }\n
+\n
+  this.colgroupChildrenLength = this.COLGROUP.childNodes.length;\n
+  this.theadChildrenLength = this.THEAD.firstChild ? this.THEAD.firstChild.childNodes.length : 0;\n
+  this.tbodyChildrenLength = this.TBODY.childNodes.length;\n
+\n
+  this.oldCellCache = new WalkontableClassNameCache();\n
+  this.currentCellCache = new WalkontableClassNameCache();\n
+\n
+  this.rowFilter = new WalkontableRowFilter();\n
+  this.columnFilter = new WalkontableColumnFilter();\n
+\n
+  this.verticalRenderReverse = false;\n
+}\n
+\n
+WalkontableTable.prototype.refreshHiderDimensions = function () {\n
+  var height = this.instance.wtViewport.getWorkspaceHeight();\n
+  var width = this.instance.wtViewport.getWorkspaceWidth();\n
+\n
+  var spreaderStyle = this.spreader.style;\n
+\n
+  if ((height !== Infinity || width !== Infinity) && !this.instance.getSetting(\'nativeScrollbars\')) {\n
+    if (height === Infinity) {\n
+      height = this.instance.wtViewport.getWorkspaceActualHeight();\n
+    }\n
+    if (width === Infinity) {\n
+      width = this.instance.wtViewport.getWorkspaceActualWidth();\n
+    }\n
+\n
+    this.hiderStyle.overflow = \'hidden\';\n
+\n
+    spreaderStyle.position = \'absolute\';\n
+    spreaderStyle.top = \'0\';\n
+    spreaderStyle.left = \'0\';\n
+\n
+    if (!this.instance.getSetting(\'nativeScrollbars\')) {\n
+      spreaderStyle.height = \'4000px\';\n
+      spreaderStyle.width = \'4000px\';\n
+    }\n
+\n
+    if (height < 0) { //this happens with WalkontableOverlay and causes "Invalid argument" error in IE8\n
+      height = 0;\n
+    }\n
+\n
+    this.hiderStyle.height = height + \'px\';\n
+    this.hiderStyle.width = width + \'px\';\n
+  }\n
+  else {\n
+    spreaderStyle.position = \'relative\';\n
+    spreaderStyle.width = \'auto\';\n
+    spreaderStyle.height = \'auto\';\n
+  }\n
+};\n
+\n
+WalkontableTable.prototype.refreshStretching = function () {\n
+  if (this.instance.cloneSource) {\n
+    return;\n
+  }\n
+\n
+  var instance = this.instance\n
+    , stretchH = instance.getSetting(\'stretchH\')\n
+    , totalRows = instance.getSetting(\'totalRows\')\n
+    , totalColumns = instance.getSetting(\'totalColumns\')\n
+    , offsetColumn = instance.getSetting(\'offsetColumn\');\n
+\n
+  var containerWidthFn = function (cacheWidth) {\n
+    var viewportWidth = that.instance.wtViewport.getViewportWidth(cacheWidth);\n
+    if (viewportWidth < cacheWidth && that.instance.getSetting(\'nativeScrollbars\')) {\n
+      return Infinity; //disable stretching when viewport is bigger than sum of the cell widths\n
+    }\n
+    return viewportWidth;\n
+  };\n
+\n
+  var that = this;\n
+\n
+  var columnWidthFn = function (i) {\n
+    var source_c = that.columnFilter.visibleToSource(i);\n
+    if (source_c < totalColumns) {\n
+      return instance.getSetting(\'columnWidth\', source_c);\n
+    }\n
+  };\n
+\n
+  if (stretchH === \'hybrid\') {\n
+    if (offsetColumn > 0) {\n
+      stretchH = \'last\';\n
+    }\n
+    else {\n
+      stretchH = \'none\';\n
+    }\n
+  }\n
+\n
+  var containerHeightFn = function (cacheHeight) {\n
+    if (that.instance.getSetting(\'nativeScrollbars\')) {\n
+      if (that.instance.cloneOverlay instanceof WalkontableDebugOverlay) {\n
+        return Infinity;\n
+      }\n
+      else {\n
+        return 2 * that.instance.wtViewport.getViewportHeight(cacheHeight);\n
+      }\n
+    }\n
+    return that.instance.wtViewport.getViewportHeight(cacheHeight);\n
+  };\n
+\n
+  var rowHeightFn = function (i, TD) {\n
+    if (that.instance.getSetting(\'nativeScrollbars\')) {\n
+      return 20;\n
+    }\n
+    var source_r = that.rowFilter.visibleToSource(i);\n
+    if (source_r < totalRows) {\n
+      if (that.verticalRenderReverse && i === 0) {\n
+        return that.instance.getSetting(\'rowHeight\', source_r, TD) - 1;\n
+      }\n
+      else {\n
+        return that.instance.getSetting(\'rowHeight\', source_r, TD);\n
+      }\n
+    }\n
+  };\n
+\n
+  this.columnStrategy = new WalkontableColumnStrategy(instance, containerWidthFn, columnWidthFn, stretchH);\n
+  this.rowStrategy = new WalkontableRowStrategy(instance, containerHeightFn, rowHeightFn);\n
+};\n
+\n
+WalkontableTable.prototype.adjustAvailableNodes = function () {\n
+  var displayTds\n
+    , rowHeaders = this.instance.getSetting(\'rowHeaders\')\n
+    , displayThs = rowHeaders.length\n
+    , columnHeaders = this.instance.getSetting(\'columnHeaders\')\n
+    , TR\n
+    , TD\n
+    , c;\n
+\n
+  //adjust COLGROUP\n
+  while (this.colgroupChildrenLength < displayThs) {\n
+    this.COLGROUP.appendChild(document.createElement(\'COL\'));\n
+    this.colgroupChildrenLength++;\n
+  }\n
+\n
+  this.refreshStretching(); //actually it is wrong position because it assumes rowHeader would be always 50px wide (because we measure before it is filled with text). TODO: debug\n
+  if (this.instance.cloneSource && (this.instance.cloneOverlay instanceof WalkontableHorizontalScrollbarNative || this.instance.cloneOverlay instanceof WalkontableCornerScrollbarNative)) {\n
+    displayTds = this.instance.getSetting(\'fixedColumnsLeft\');\n
+  }\n
+  else {\n
+    displayTds = this.columnStrategy.cellCount;\n
+  }\n
+\n
+  //adjust COLGROUP\n
+  while (this.colgroupChildrenLength < displayTds + displayThs) {\n
+    this.COLGROUP.appendChild(document.createElement(\'COL\'));\n
+    this.colgroupChildrenLength++;\n
+  }\n
+  while (this.colgroupChildrenLength > displayTds + displayThs) {\n
+    this.COLGROUP.removeChild(this.COLGROUP.lastChild);\n
+    this.colgroupChildrenLength--;\n
+  }\n
+\n
+  //adjust THEAD\n
+  TR = this.THEAD.firstChild;\n
+  if (columnHeaders.length) {\n
+    if (!TR) {\n
+      TR = document.createElement(\'TR\');\n
+      this.THEAD.appendChild(TR);\n
+    }\n
+\n
+    this.theadChildrenLength = TR.childNodes.length;\n
+    while (this.theadChildrenLength < displayTds + displayThs) {\n
+      TR.appendChild(document.createElement(\'TH\'));\n
+      this.theadChildrenLength++;\n
+    }\n
+    while (this.theadChildrenLength > displayTds + displayThs) {\n
+      TR.removeChild(TR.lastChild);\n
+      this.theadChildrenLength--;\n
+    }\n
+  }\n
+  else if (TR) {\n
+    this.wtDom.empty(TR);\n
+  }\n
+\n
+  //draw COLGROUP\n
+  for (c = 0; c < this.colgroupChildrenLength; c++) {\n
+    if (c < displayThs) {\n
+      this.wtDom.addClass(this.COLGROUP.childNodes[c], \'rowHeader\');\n
+    }\n
+    else {\n
+      this.wtDom.removeClass(this.COLGROUP.childNodes[c], \'rowHeader\');\n
+    }\n
+  }\n
+\n
+  //draw THEAD\n
+  if (columnHeaders.length) {\n
+    TR = this.THEAD.firstChild;\n
+    if (displayThs) {\n
+      TD = TR.firstChild; //actually it is TH but let\'s reuse single variable\n
+      for (c = 0; c < displayThs; c++) {\n
+        rowHeaders[c](-displayThs + c, TD);\n
+        TD = TD.nextSibling;\n
+      }\n
+    }\n
+  }\n
+\n
+  for (c = 0; c < displayTds; c++) {\n
+    if (columnHeaders.length) {\n
+      columnHeaders[0](this.columnFilter.visibleToSource(c), TR.childNodes[displayThs + c]);\n
+    }\n
+  }\n
+};\n
+\n
+WalkontableTable.prototype.adjustColumns = function (TR, desiredCount) {\n
+  var count = TR.childNodes.length;\n
+  while (count < desiredCount) {\n
+    var TD = document.createElement(\'TD\');\n
+    TR.appendChild(TD);\n
+    count++;\n
+  }\n
+  while (count > desiredCount) {\n
+    TR.removeChild(TR.lastChild);\n
+    count--;\n
+  }\n
+};\n
+\n
+WalkontableTable.prototype.draw = function (selectionsOnly) {\n
+  if (this.instance.getSetting(\'nativeScrollbars\')) {\n
+    this.verticalRenderReverse = false; //this is only supported in dragdealer mode, not in native\n
+  }\n
+\n
+  this.rowFilter.readSettings(this.instance);\n
+  this.columnFilter.readSettings(this.instance);\n
+\n
+  if (!selectionsOnly) {\n
+    if (this.instance.getSetting(\'nativeScrollbars\')) {\n
+      if (this.instance.cloneSource) {\n
+        this.tableOffset = this.instance.cloneSource.wtTable.tableOffset;\n
+      }\n
+      else {\n
+        this.holderOffset = this.wtDom.offset(this.holder);\n
+        this.tableOffset = this.wtDom.offset(this.TABLE);\n
+        this.instance.wtScrollbars.vertical.readWindowSize();\n
+        this.instance.wtScrollbars.horizontal.readWindowSize();\n
+        this.instance.wtViewport.resetSettings();\n
+      }\n
+    }\n
+    else {\n
+      this.tableOffset = this.wtDom.offset(this.TABLE);\n
+      this.instance.wtViewport.resetSettings();\n
+    }\n
+    this._doDraw();\n
+  }\n
+  else {\n
+    this.instance.wtScrollbars && this.instance.wtScrollbars.refresh(true);\n
+  }\n
+\n
+  this.refreshPositions(selectionsOnly);\n
+\n
+  if (!selectionsOnly) {\n
+    if (this.instance.getSetting(\'nativeScrollbars\')) {\n
+      if (!this.instance.cloneSource) {\n
+        this.instance.wtScrollbars.vertical.resetFixedPosition();\n
+        this.instance.wtScrollbars.horizontal.resetFixedPosition();\n
+        this.instance.wtScrollbars.corner.resetFixedPosition();\n
+        this.instance.wtScrollbars.debug && this.instance.wtScrollbars.debug.resetFixedPosition();\n
+      }\n
+    }\n
+  }\n
+\n
+  this.instance.drawn = true;\n
+  return this;\n
+};\n
+\n
+WalkontableTable.prototype._doDraw = function () {\n
+  var r = 0\n
+    , source_r\n
+    , c\n
+    , source_c\n
+    , offsetRow = this.instance.getSetting(\'offsetRow\')\n
+    , totalRows = this.instance.getSetting(\'totalRows\')\n
+    , totalColumns = this.instance.getSetting(\'totalColumns\')\n
+    , displayTds\n
+    , rowHeaders = this.instance.getSetting(\'rowHeaders\')\n
+    , displayThs = rowHeaders.length\n
+    , TR\n
+    , TD\n
+    , TH\n
+    , adjusted = false\n
+    , workspaceWidth\n
+    , mustBeInViewport\n
+    , res;\n
+\n
+  if (this.verticalRenderReverse) {\n
+    mustBeInViewport = offsetRow;\n
+  }\n
+\n
+  var noPartial = false;\n
+  if (this.verticalRenderReverse) {\n
+    if (offsetRow === totalRows - this.rowFilter.fixedCount - 1) {\n
+      noPartial = true;\n
+    }\n
+    else {\n
+      this.instance.update(\'offsetRow\', offsetRow + 1); //if we are scrolling reverse\n
+      this.rowFilter.readSettings(this.instance);\n
+    }\n
+  }\n
+\n
+  if (this.instance.cloneSource) {\n
+    this.columnStrategy = this.instance.cloneSource.wtTable.columnStrategy;\n
+    this.rowStrategy = this.instance.cloneSource.wtTable.rowStrategy;\n
+  }\n
+\n
+  //draw TBODY\n
+  if (totalColumns > 0) {\n
+    source_r = this.rowFilter.visibleToSource(r);\n
+\n
+    var fixedRowsTop = this.instance.getSetting(\'fixedRowsTop\');\n
+    var cloneLimit;\n
+    if (this.instance.cloneSource) { //must be run after adjustAvailableNodes because otherwise this.rowStrategy is not yet defined\n
+      if (this.instance.cloneOverlay instanceof WalkontableVerticalScrollbarNative || this.instance.cloneOverlay instanceof WalkontableCornerScrollbarNative) {\n
+        cloneLimit = fixedRowsTop;\n
+      }\n
+      else if (this.instance.cloneOverlay instanceof WalkontableHorizontalScrollbarNative) {\n
+        cloneLimit = this.rowStrategy.countVisible();\n
+      }\n
+      //else if WalkontableDebugOverlay do nothing. No cloneLimit means render ALL rows\n
+    }\n
+\n
+    this.adjustAvailableNodes();\n
+    adjusted = true;\n
+\n
+    if (this.instance.cloneSource && (this.instance.cloneOverlay instanceof WalkontableHorizontalScrollbarNative || this.instance.cloneOverlay instanceof WalkontableCornerScrollbarNative)) {\n
+      displayTds = this.instance.getSetting(\'fixedColumnsLeft\');\n
+    }\n
+    else {\n
+      displayTds = this.columnStrategy.cellCount;\n
+    }\n
+\n
+    if (!this.instance.cloneSource) {\n
+      workspaceWidth = this.instance.wtViewport.getWorkspaceWidth();\n
+      this.columnStrategy.stretch();\n
+    }\n
+\n
+    for (c = 0; c < displayTds; c++) {\n
+      this.COLGROUP.childNodes[c + displayThs].style.width = this.columnStrategy.getSize(c) + \'px\';\n
+    }\n
+\n
+    while (source_r < totalRows && source_r >= 0) {\n
+      if (r > 1000) {\n
+        throw new Error(\'Security brake: Too much TRs. Please define height for your table, which will enforce scrollbars.\');\n
+      }\n
+\n
+      if (cloneLimit !== void 0 && r === cloneLimit) {\n
+        break; //we have as much rows as needed for this clone\n
+      }\n
+\n
+      if (r >= this.tbodyChildrenLength || (this.verticalRenderReverse && r >= this.rowFilter.fixedCount)) {\n
+        TR = document.createElement(\'TR\');\n
+        for (c = 0; c < displayThs; c++) {\n
+          TR.appendChild(document.createElement(\'TH\'));\n
+        }\n
+        if (this.verticalRenderReverse && r >= this.rowFilter.fixedCount) {\n
+          this.TBODY.insertBefore(TR, this.TBODY.childNodes[this.rowFilter.fixedCount] || this.TBODY.firstChild);\n
+        }\n
+        else {\n
+          this.TBODY.appendChild(TR);\n
+        }\n
+        this.tbodyChildrenLength++;\n
+      }\n
+      else if (r === 0) {\n
+        TR = this.TBODY.firstChild;\n
+      }\n
+      else {\n
+        TR = TR.nextSibling; //http://jsperf.com/nextsibling-vs-indexed-childnodes\n
+      }\n
+\n
+      //TH\n
+      TH = TR.firstChild;\n
+      for (c = 0; c < displayThs; c++) {\n
+\n
+        //If the number of row headers increased we need to replace TD with TH\n
+        if (TH.nodeName == \'TD\') {\n
+          TD = TH;\n
+          TH = document.createElement(\'TH\');\n
+          TR.insertBefore(TH, TD);\n
+          TR.removeChild(TD);\n
+        }\n
+\n
+        rowHeaders[c](source_r, TH); //actually TH\n
+        TH = TH.nextSibling; //http://jsperf.com/nextsibling-vs-indexed-childnodes\n
+      }\n
+\n
+      this.adjustColumns(TR, displayTds + displayThs);\n
+\n
+      for (c = 0; c < displayTds; c++) {\n
+        source_c = this.columnFilter.visibleToSource(c);\n
+        if (c === 0) {\n
+          TD = TR.childNodes[this.columnFilter.sourceColumnToVisibleRowHeadedColumn(source_c)];\n
+        }\n
+        else {\n
+          TD = TD.nextSibling; //http://jsperf.com/nextsibling-vs-indexed-childnodes\n
+        }\n
+\n
+        //If the number of headers has been reduced, we need to replace excess TH with TD\n
+        if (TD.nodeName == \'TH\') {\n
+          TH = TD;\n
+          TD = document.createElement(\'TD\');\n
+          TR.insertBefore(TD, TH);\n
+          TR.removeChild(TH);\n
+        }\n
+\n
+        TD.className = \'\';\n
+        TD.removeAttribute(\'style\');\n
+        this.instance.getSetting(\'cellRenderer\', source_r, source_c, TD);\n
+      }\n
+\n
+      offsetRow = this.instance.getSetting(\'offsetRow\'); //refresh the value\n
+\n
+      //after last column is rendered, check if last cell is fully displayed\n
+      if (this.verticalRenderReverse && noPartial) {\n
+        if (-this.wtDom.outerHeight(TR.firstChild) < this.rowStrategy.remainingSize) {\n
+          this.TBODY.removeChild(TR);\n
+          this.instance.update(\'offsetRow\', offsetRow + 1);\n
+          this.tbodyChildrenLength--;\n
+          this.rowFilter.readSettings(this.instance);\n
+          break;\n
+\n
+        }\n
+        else if (!this.instance.cloneSource) {\n
+          res = this.rowStrategy.add(r, TD, this.verticalRenderReverse);\n
+          if (res === false) {\n
+            this.rowStrategy.removeOutstanding();\n
+          }\n
+        }\n
+      }\n
+      else if (!this.instance.cloneSource) {\n
+        res = this.rowStrategy.add(r, TD, this.verticalRenderReverse);\n
+\n
+        if (res === false) {\n
+          if (!this.instance.getSetting(\'nativeScrollbars\')) {\n
+            this.rowStrategy.removeOutstanding();\n
+          }\n
+        }\n
+\n
+        if (this.rowStrategy.isLastIncomplete()) {\n
+          if (this.verticalRenderReverse && !this.isRowInViewport(mustBeInViewport)) {\n
+            //we failed because one of the cells was by far too large. Recover by rendering from top\n
+            this.verticalRenderReverse = false;\n
+            this.instance.update(\'offsetRow\', mustBeInViewport);\n
+            this.draw();\n
+            return;\n
+          }\n
+          break;\n
+        }\n
+      }\n
+\n
+      if (this.instance.getSetting(\'nativeScrollbars\')) {\n
+        if (this.instance.cloneSource) {\n
+          TR.style.height = this.instance.getSetting(\'rowHeight\', source_r) + \'px\'; //if I have 2 fixed columns with one-line content and the 3rd column has a multiline content, this is the way to make sure that the overlay will has same row height\n
+        }\n
+        else {\n
+          this.instance.getSetting(\'rowHeight\', source_r, TD); //this trick saves rowHeight in rowHeightCache. It is then read in WalkontableVerticalScrollbarNative.prototype.sumCellSizes and reset in Walkontable constructor\n
+        }\n
+      }\n
+\n
+      if (this.verticalRenderReverse && r >= this.rowFilter.fixedCount) {\n
+        if (offsetRow === 0) {\n
+          break;\n
+        }\n
+        this.instance.update(\'offsetRow\', offsetRow - 1);\n
+        this.rowFilter.readSettings(this.instance);\n
+      }\n
+      else {\n
+        r++;\n
+      }\n
+\n
+      source_r = this.rowFilter.visibleToSource(r);\n
+    }\n
+  }\n
+\n
+  if (!adjusted) {\n
+    this.adjustAvailableNodes();\n
+  }\n
+\n
+  if (!(this.instance.cloneOverlay instanceof WalkontableDebugOverlay)) {\n
+    r = this.rowStrategy.countVisible();\n
+    while (this.tbodyChildrenLength > r) {\n
+      this.TBODY.removeChild(this.TBODY.lastChild);\n
+      this.tbodyChildrenLength--;\n
+    }\n
+  }\n
+\n
+  this.instance.wtScrollbars && this.instance.wtScrollbars.refresh(false);\n
+\n
+  if (!this.instance.cloneSource) {\n
+    if (workspaceWidth !== this.instance.wtViewport.getWorkspaceWidth()) {\n
+      //workspace width changed though to shown/hidden vertical scrollbar. Let\'s reapply stretching\n
+      this.columnStrategy.stretch();\n
+      for (c = 0; c < this.columnStrategy.cellCount; c++) {\n
+        this.COLGROUP.childNodes[c + displayThs].style.width = this.columnStrategy.getSize(c) + \'px\';\n
+      }\n
+    }\n
+  }\n
+\n
+  this.verticalRenderReverse = false;\n
+};\n
+\n
+WalkontableTable.prototype.refreshPositions = function (selectionsOnly) {\n
+  this.refreshHiderDimensions();\n
+  this.refreshSelections(selectionsOnly);\n
+};\n
+\n
+WalkontableTable.prototype.refreshSelections = function (selectionsOnly) {\n
+  var vr\n
+    , r\n
+    , vc\n
+    , c\n
+    , s\n
+    , slen\n
+    , classNames = []\n
+    , visibleRows = this.rowStrategy.countVisible()\n
+    , visibleColumns = this.columnStrategy.countVisible();\n
+\n
+  this.oldCellCache = this.currentCellCache;\n
+  this.currentCellCache = new WalkontableClassNameCache();\n
+\n
+  if (this.instance.selections) {\n
+    for (r in this.instance.selections) {\n
+      if (this.instance.selections.hasOwnProperty(r)) {\n
+        this.instance.selections[r].draw();\n
+        if (this.instance.selections[r].settings.className) {\n
+          classNames.push(this.instance.selections[r].settings.className);\n
+        }\n
+        if (this.instance.selections[r].settings.highlightRowClassName) {\n
+          classNames.push(this.instance.selections[r].settings.highlightRowClassName);\n
+        }\n
+        if (this.instance.selections[r].settings.highlightColumnClassName) {\n
+          classNames.push(this.instance.selections[r].settings.highlightColumnClassName);\n
+        }\n
+      }\n
+    }\n
+  }\n
+\n
+  slen = classNames.length;\n
+\n
+  for (vr = 0; vr < visibleRows; vr++) {\n
+    for (vc = 0; vc < visibleColumns; vc++) {\n
+      r = this.rowFilter.visibleToSource(vr);\n
+      c = this.columnFilter.visibleToSource(vc);\n
+      for (s = 0; s < slen; s++) {\n
+        if (this.currentCellCache.test(vr, vc, classNames[s])) {\n
+          this.wtDom.addClass(this.getCell([r, c]), classNames[s]);\n
+        }\n
+        else if (selectionsOnly && this.oldCellCache.test(vr, vc, classNames[s])) {\n
+          this.wtDom.removeClass(this.getCell([r, c]), classNames[s]);\n
+        }\n
+      }\n
+    }\n
+  }\n
+};\n
+\n
+/**\n
+ * getCell\n
+ * @param {Array} coords\n
+ * @return {Object} HTMLElement on success or {Number} one of the exit codes on error:\n
+ *  -1 row before viewport\n
+ *  -2 row after viewport\n
+ *  -3 column before viewport\n
+ *  -4 column after viewport\n
+ *\n
+ */\n
+WalkontableTable.prototype.getCell = function (coords) {\n
+  if (this.isRowBeforeViewport(coords[0])) {\n
+    return -1; //row before viewport\n
+  }\n
+  else if (this.isRowAfterViewport(coords[0])) {\n
+    return -2; //row after viewport\n
+  }\n
+  else {\n
+    if (this.isColumnBeforeViewport(coords[1])) {\n
+      return -3; //column before viewport\n
+    }\n
+    else if (this.isColumnAfterViewport(coords[1])) {\n
+      return -4; //column after viewport\n
+    }\n
+    else {\n
+      return this.TBODY.childNodes[this.rowFilter.sourceToVisible(coords[0])].childNodes[this.columnFilter.sourceColumnToVisibleRowHeadedColumn(coords[1])];\n
+    }\n
+  }\n
+};\n
+\n
+WalkontableTable.prototype.getCoords = function (TD) {\n
+  return [\n
+    this.rowFilter.visibleToSource(this.wtDom.index(TD.parentNode)),\n
+    this.columnFilter.visibleRowHeadedColumnToSourceColumn(TD.cellIndex)\n
+  ];\n
+};\n
+\n
+//returns -1 if no row is visible\n
+WalkontableTable.prototype.getLastVisibleRow = function () {\n
+  return this.rowFilter.visibleToSource(this.rowStrategy.cellCount - 1);\n
+};\n
+\n
+//returns -1 if no column is visible\n
+WalkontableTable.prototype.getLastVisibleColumn = function () {\n
+  return this.columnFilter.visibleToSource(this.columnStrategy.cellCount - 1);\n
+};\n
+\n
+WalkontableTable.prototype.isRowBeforeViewport = function (r) {\n
+  return (this.rowFilter.sourceToVisible(r) < this.rowFilter.fixedCount && r >= this.rowFilter.fixedCount);\n
+};\n
+\n
+WalkontableTable.prototype.isRowAfterViewport = function (r) {\n
+  return (r > this.getLastVisibleRow());\n
+};\n
+\n
+WalkontableTable.prototype.isColumnBeforeViewport = function (c) {\n
+  return (this.columnFilter.sourceToVisible(c) < this.columnFilter.fixedCount && c >= this.columnFilter.fixedCount);\n
+};\n
+\n
+WalkontableTable.prototype.isColumnAfterViewport = function (c) {\n
+  return (c > this.getLastVisibleColumn());\n
+};\n
+\n
+WalkontableTable.prototype.isRowInViewport = function (r) {\n
+  return (!this.isRowBeforeViewport(r) && !this.isRowAfterViewport(r));\n
+};\n
+\n
+WalkontableTable.prototype.isColumnInViewport = function (c) {\n
+  return (!this.isColumnBeforeViewport(c) && !this.isColumnAfterViewport(c));\n
+};\n
+\n
+WalkontableTable.prototype.isLastRowFullyVisible = function () {\n
+  return (this.getLastVisibleRow() === this.instance.getSetting(\'totalRows\') - 1 && !this.rowStrategy.isLastIncomplete());\n
+};\n
+\n
+WalkontableTable.prototype.isLastColumnFullyVisible = function () {\n
+  return (this.getLastVisibleColumn() === this.instance.getSetting(\'totalColumns\') - 1 && !this.columnStrategy.isLastIncomplete());\n
+};\n
+\n
+function WalkontableViewport(instance) {\n
+  this.instance = instance;\n
+  this.resetSettings();\n
+\n
+  if (this.instance.getSetting(\'nativeScrollbars\')) {\n
+    var that = this;\n
+    $(window).on(\'resize\', function () {\n
+      that.clientHeight = that.getWorkspaceHeight();\n
+    });\n
+  }\n
+}\n
+\n
+/*WalkontableViewport.prototype.isInSightVertical = function () {\n
+  //is table outside viewport bottom edge\n
+  if (tableTop > windowHeight + scrollTop) {\n
+    return -1;\n
+  }\n
+\n
+  //is table outside viewport top edge\n
+  else if (scrollTop > tableTop + tableFakeHeight) {\n
+    return -2;\n
+  }\n
+\n
+  //table is in viewport but how much exactly?\n
+  else {\n
+\n
+  }\n
+};*/\n
+\n
+//used by scrollbar\n
+WalkontableViewport.prototype.getWorkspaceHeight = function (proposedHeight) {\n
+  if (this.instance.getSetting(\'nativeScrollbars\')) {\n
+    return this.instance.wtScrollbars.vertical.windowSize;\n
+  }\n
+\n
+  var height = this.instance.getSetting(\'height\');\n
+\n
+  if (height === Infinity || height === void 0 || height === null || height < 1) {\n
+    if (this.instance.wtScrollbars.vertical instanceof WalkontableOverlay) {\n
+      height = this.instance.wtScrollbars.vertical.availableSize();\n
+    }\n
+    else {\n
+      height = Infinity;\n
+    }\n
+  }\n
+\n
+  if (height !== Infinity) {\n
+    if (proposedHeight >= height) {\n
+      height -= this.instance.getSetting(\'scrollbarHeight\');\n
+    }\n
+    else if (this.instance.wtScrollbars.horizontal.visible) {\n
+      height -= this.instance.getSetting(\'scrollbarHeight\');\n
+    }\n
+  }\n
+\n
+  return height;\n
+};\n
+\n
+WalkontableViewport.prototype.getWorkspaceWidth = function (proposedWidth) {\n
+  var width = this.instance.getSetting(\'width\');\n
+\n
+  if (width === Infinity || width === void 0 || width === null || width < 1) {\n
+    if (this.instance.wtScrollbars.horizontal instanceof WalkontableOverlay) {\n
+      width = this.instance.wtScrollbars.horizontal.availableSize();\n
+    }\n
+    else {\n
+      width = Infinity;\n
+    }\n
+  }\n
+\n
+  if (width !== Infinity) {\n
+    if (proposedWidth >= width) {\n
+      width -= this.instance.getSetting(\'scrollbarWidth\');\n
+    }\n
+    else if (this.instance.wtScrollbars.vertical.visible) {\n
+      width -= this.instance.getSetting(\'scrollbarWidth\');\n
+    }\n
+  }\n
+  return width;\n
+};\n
+\n
+WalkontableViewport.prototype.getWorkspaceActualHeight = function () {\n
+  return this.instance.wtDom.outerHeight(this.instance.wtTable.TABLE);\n
+};\n
+\n
+WalkontableViewport.prototype.getWorkspaceActualWidth = function () {\n
+  return this.instance.wtDom.outerWidth(this.instance.wtTable.TABLE) || this.instance.wtDom.outerWidth(this.instance.wtTable.TBODY) || this.instance.wtDom.outerWidth(this.instance.wtTable.THEAD); //IE8 reports 0 as <table> offsetWidth;\n
+};\n
+\n
+WalkontableViewport.prototype.getColumnHeaderHeight = function () {\n
+  if (isNaN(this.columnHeaderHeight)) {\n
+    var cellOffset = this.instance.wtDom.offset(this.instance.wtTable.TBODY)\n
+      , tableOffset = this.instance.wtTable.tableOffset;\n
+    this.columnHeaderHeight = cellOffset.top - tableOffset.top;\n
+  }\n
+  return this.columnHeaderHeight;\n
+};\n
+\n
+WalkontableViewport.prototype.getViewportHeight = function (proposedHeight) {\n
+  var containerHeight = this.getWorkspaceHeight(proposedHeight);\n
+\n
+  if (containerHeight === Infinity) {\n
+    return containerHeight;\n
+  }\n
+\n
+  var columnHeaderHeight = this.getColumnHeaderHeight();\n
+  if (columnHeaderHeight > 0) {\n
+    return containerHeight - columnHeaderHeight;\n
+  }\n
+  else {\n
+    return containerHeight;\n
+  }\n
+};\n
+\n
+WalkontableViewport.prototype.getRowHeaderWidth = function () {\n
+  if (this.instance.cloneSource) {\n
+    return this.instance.cloneSource.wtViewport.getRowHeaderWidth();\n
+  }\n
+  if (isNaN(this.rowHeaderWidth)) {\n
+    var rowHeaders = this.instance.getSetting(\'rowHeaders\');\n
+    if (rowHeaders.length) {\n
+      var TH = this.instance.wtTable.TABLE.querySelector(\'TH\');\n
+      this.rowHeaderWidth = 0;\n
+      for (var i = 0, ilen = rowHeaders.length; i < ilen; i++) {\n
+        if (TH) {\n
+          this.rowHeaderWidth += this.instance.wtDom.outerWidth(TH);\n
+          TH = TH.nextSibling;\n
+        }\n
+        else {\n
+          this.rowHeaderWidth += 50; //yes this is a cheat but it worked like that before, just taking assumption from CSS instead of measuring. TODO: proper fix\n
+        }\n
+      }\n
+    }\n
+    else {\n
+      this.rowHeaderWidth = 0;\n
+    }\n
+  }\n
+  return this.rowHeaderWidth;\n
+};\n
+\n
+WalkontableViewport.prototype.getViewportWidth = function (proposedWidth) {\n
+  var containerWidth = this.getWorkspaceWidth(proposedWidth);\n
+\n
+  if (containerWidth === Infinity) {\n
+    return containerWidth;\n
+  }\n
+\n
+  var rowHeaderWidth = this.getRowHeaderWidth();\n
+  if (rowHeaderWidth > 0) {\n
+    return containerWidth - rowHeaderWidth;\n
+  }\n
+  else {\n
+    return containerWidth;\n
+  }\n
+};\n
+\n
+WalkontableViewport.prototype.resetSettings = function () {\n
+  this.rowHeaderWidth = NaN;\n
+  this.columnHeaderHeight = NaN;\n
+};\n
+function WalkontableWheel(instance) {\n
+  if (instance.getSetting(\'nativeScrollbars\')) {\n
+    return;\n
+  }\n
+\n
+  //spreader === instance.wtTable.TABLE.parentNode\n
+  $(instance.wtTable.spreader).on(\'mousewheel\', function (event, delta, deltaX, deltaY) {\n
+    if (!deltaX && !deltaY && delta) { //we are in IE8, see https://github.com/brandonaaron/jquery-mousewheel/issues/53\n
+      deltaY = delta;\n
+    }\n
+\n
+    if (!deltaX && !deltaY) { //this happens in IE8 test case\n
+      return;\n
+    }\n
+\n
+    if (deltaY > 0 && instance.getSetting(\'offsetRow\') === 0) {\n
+      return; //attempt to scroll up when it\'s already showing first row\n
+    }\n
+    else if (deltaY < 0 && instance.wtTable.isLastRowFullyVisible()) {\n
+      return; //attempt to scroll down when it\'s already showing last row\n
+    }\n
+    else if (deltaX < 0 && instance.getSetting(\'offsetColumn\') === 0) {\n
+      return; //attempt to scroll left when it\'s already showing first column\n
+    }\n
+    else if (deltaX > 0 && instance.wtTable.isLastColumnFullyVisible()) {\n
+      return; //attempt to scroll right when it\'s already showing last column\n
+    }\n
+\n
+    //now we are sure we really want to scroll\n
+    clearTimeout(instance.wheelTimeout);\n
+    instance.wheelTimeout = setTimeout(function () { //timeout is needed because with fast-wheel scrolling mousewheel event comes dozen times per second\n
+      if (deltaY) {\n
+        //ceil is needed because jquery-mousewheel reports fractional mousewheel deltas on touchpad scroll\n
+        //see http://stackoverflow.com/questions/5527601/normalizing-mousewheel-speed-across-browsers\n
+        if (instance.wtScrollbars.vertical.visible) { // if we see scrollbar\n
+          instance.scrollVertical(-Math.ceil(deltaY)).draw();\n
+        }\n
+      }\n
+      else if (deltaX) {\n
+        if (instance.wtScrollbars.horizontal.visible) { // if we see scrollbar\n
+          instance.scrollHorizontal(Math.ceil(deltaX)).draw();\n
+        }\n
+      }\n
+    }, 0);\n
+\n
+    event.preventDefault();\n
+  });\n
+}\n
+/**\n
+ * Dragdealer JS v0.9.5 - patched by Walkontable at lines 66, 309-310, 339-340\n
+ * http://code.ovidiu.ch/dragdealer-js\n
+ *\n
+ * Copyright (c) 2010, Ovidiu Chereches\n
+ * MIT License\n
+ * http://legal.ovidiu.ch/licenses/MIT\n
+ */\n
+\n
+/* Cursor */\n
+\n
+var Cursor =\n
+{\n
+\tx: 0, y: 0,\n
+\tinit: function()\n
+\t{\n
+\t\tthis.setEvent(\'mouse\');\n
+\t\tthis.setEvent(\'touch\');\n
+\t},\n
+\tsetEvent: function(type)\n
+\t{\n
+\t\tvar moveHandler = document[\'on\' + type + \'move\'] || function(){};\n
+\t\tdocument[\'on\' + type + \'move\'] = function(e)\n
+\t\t{\n
+\t\t\tmoveHandler(e);\n
+\t\t\tCursor.refresh(e);\n
+\t\t}\n
+\t},\n
+\trefresh: function(e)\n
+\t{\n
+\t\tif(!e)\n
+\t\t{\n
+\t\t\te = window.event;\n
+\t\t}\n
+\t\tif(e.type == \'mousemove\')\n
+\t\t{\n
+\t\t\tthis.set(e);\n
+\t\t}\n
+\t\telse if(e.touches)\n
+\t\t{\n
+\t\t\tthis.set(e.touches[0]);\n
+\t\t}\n
+\t},\n
+\tset: function(e)\n
+\t{\n
+\t\tif(e.pageX || e.pageY)\n
+\t\t{\n
+\t\t\tthis.x = e.pageX;\n
+\t\t\tthis.y = e.pageY;\n
+\t\t}\n
+\t\telse if(document.body && (e.clientX || e.clientY)) //need to check whether body exists, because of IE8 issue (#1084)\n
+\t\t{\n
+\t\t\tthis.x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;\n
+\t\t\tthis.y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop;\n
+\t\t}\n
+\t}\n
+};\n
+Cursor.init();\n
+\n
+/* Position */\n
+\n
+var Position =\n
+{\n
+\tget: function(obj)\n
+\t{\n
+\t\tvar curtop = 0, curleft = 0; //Walkontable patch. Original (var curleft = curtop = 0;) created curtop in global scope\n
+\t\tif(obj.offsetParent)\n
+\t\t{\n
+\t\t\tdo\n
+\t\t\t{\n
+\t\t\t\tcurleft += obj.offsetLeft;\n
+\t\t\t\tcurtop += obj.offsetTop;\n
+\t\t\t}\n
+\t\t\twhile((obj = obj.offsetParent));\n
+\t\t}\n
+\t\treturn [curleft, curtop];\n
+\t}\n
+};\n
+\n
+/* Dragdealer */\n
+\n
+var Dragdealer = function(wrapper, options)\n
+{\n
+\tif(typeof(wrapper) == \'string\')\n
+\t{\n
+\t\twrapper = document.getElementById(wrapper);\n
+\t}\n
+\tif(!wrapper)\n
+\t{\n
+\t\treturn;\n
+\t}\n
+\tvar handle = wrapper.getElementsByTagName(\'div\')[0];\n
+\tif(!handle || handle.className.search(/(^|\\s)handle(\\s|$)/) == -1)\n
+\t{\n
+\t\treturn;\n
+\t}\n
+\tthis.init(wrapper, handle, options || {});\n
+\tthis.setup();\n
+};\n
+Dragdealer.prototype =\n
+{\n
+\tinit: function(wrapper, handle, options)\n
+\t{\n
+\t\tthis.wrapper = wrapper;\n
+\t\tthis.handle = handle;\n
+\t\tthis.options = options;\n
+\t\t\n
+\t\tthis.disabled = this.getOption(\'disabled\', false);\n
+\t\tthis.horizontal = this.getOption(\'horizontal\', true);\n
+\t\tthis.vertical = this.getOption(\'vertical\', false);\n
+\t\tthis.slide = this.getOption(\'slide\', true);\n
+\t\tthis.steps = this.getOption(\'steps\', 0);\n
+\t\tthis.snap = this.getOption(\'snap\', false);\n
+\t\tthis.loose = this.getOption(\'loose\', false);\n
+\t\tthis.speed = this.getOption(\'speed\', 10) / 100;\n
+\t\tthis.xPrecision = this.getOption(\'xPrecision\', 0);\n
+\t\tthis.yPrecision = this.getOption(\'yPrecision\', 0);\n
+\t\t\n
+\t\tthis.callback = options.callback || null;\n
+\t\tthis.animationCallback = options.animationCallback || null;\n
+\t\t\n
+\t\tthis.bounds = {\n
+\t\t\tleft: options.left || 0, right: -(options.right || 0),\n
+\t\t\ttop: options.top || 0, bottom: -(options.bottom || 0),\n
+\t\t\tx0: 0, x1: 0, xRange: 0,\n
+\t\t\ty0: 0, y1: 0, yRange: 0\n
+\t\t};\n
+\t\tthis.value = {\n
+\t\t\tprev: [-1, -1],\n
+\t\t\tcurrent: [options.x || 0, options.y || 0],\n
+\t\t\ttarget: [options.x || 0, options.y || 0]\n
+\t\t};\n
+\t\tthis.offset = {\n
+\t\t\twrapper: [0, 0],\n
+\t\t\tmouse: [0, 0],\n
+\t\t\tprev: [-999999, -999999],\n
+\t\t\tcurrent: [0, 0],\n
+\t\t\ttarget: [0, 0]\n
+\t\t};\n
+\t\tthis.change = [0, 0];\n
+\t\t\n
+\t\tthis.activity = false;\n
+\t\tthis.dragging = false;\n
+\t\tthis.tapping = false;\n
+\t},\n
+\tgetOption: function(name, defaultValue)\n
+\t{\n
+\t\treturn this.options[name] !== undefined ? this.options[name] : defaultValue;\n
+\t},\n
+\tsetup: function()\n
+\t{\n
+\t\tthis.setWrapperOffset();\n
+\t\tthis.setBoundsPadding();\n
+\t\tthis.setBounds();\n
+\t\tthis.setSteps();\n
+\t\t\n
+\t\tthis.addListeners();\n
+\t},\n
+\tsetWrapperOffset: function()\n
+\t{\n
+\t\tthis.offset.wrapper = Position.get(this.wrapper);\n
+\t},\n
+\tsetBoundsPadding: function()\n
+\t{\n
+\t\tif(!this.bounds.left && !this.bounds.right)\n
+\t\t{\n
+\t\t\tthis.bounds.left = Position.get(this.handle)[0] - this.offset.wrapper[0];\n
+\t\t\tthis.bounds.right = -this.bounds.left;\n
+\t\t}\n
+\t\tif(!this.bounds.top && !this.bounds.bottom)\n
+\t\t{\n
+\t\t\tthis.bounds.top = Position.get(this.handle)[1] - this.offset.wrapper[1];\n
+\t\t\tthis.bounds.bottom = -this.bounds.top;\n
+\t\t}\n
+\t},\n
+\tsetBounds: function()\n
+\t{\n
+\t\tthis.bounds.x0 = this.bounds.left;\n
+\t\tthis.bounds.x1 = this.wrapper.offsetWidth + this.bounds.right;\n
+\t\tthis.bounds.xRange = (this.bounds.x1 - this.bounds.x0) - this.handle.offsetWidth;\n
+\t\t\n
+\t\tthis.bounds.y0 = this.bounds.top;\n
+\t\tthis.bounds.y1 = this.wrapper.offsetHeight + this.bounds.bottom;\n
+\t\tthis.bounds.yRange = (this.bounds.y1 - this.bounds.y0) - this.handle.offsetHeight;\n
+\t\t\n
+\t\tthis.bounds.xStep = 1 / (this.xPrecision || Math.max(this.wrapper.offsetWidth, this.handle.offsetWidth));\n
+\t\tthis.bounds.yStep = 1 / (this.yPrecision || Math.max(this.wrapper.offsetHeight, this.handle.offsetHeight));\n
+\t},\n
+\tsetSteps: function()\n
+\t{\n
+\t\tif(this.steps > 1)\n
+\t\t{\n
+\t\t\tthis.stepRatios = [];\n
+\t\t\tfor(var i = 0; i <= this.steps - 1; i++)\n
+\t\t\t{\n
+\t\t\t\tthis.stepRatios[i] = i / (this.steps - 1);\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\taddListeners: function()\n
+\t{\n
+\t\tvar self = this;\n
+\t\t\n
+\t\tthis.wrapper.onselectstart = function()\n
+\t\t{\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\tthis.handle.onmousedown = this.handle.ontouchstart = function(e)\n
+\t\t{\n
+\t\t\tself.handleDownHandler(e);\n
+\t\t};\n
+\t\tthis.wrapper.onmousedown = this.wrapper.ontouchstart = function(e)\n
+\t\t{\n
+\t\t\tself.wrapperDownHandler(e);\n
+\t\t};\n
+\t\tvar mouseUpHandler = document.onmouseup || function(){};\n
+\t\tdocument.onmouseup = function(e)\n
+\t\t{\n
+\t\t\tmouseUpHandler(e);\n
+\t\t\tself.documentUpHandler(e);\n
+\t\t};\n
+\t\tvar touchEndHandler = document.ontouchend || function(){};\n
+\t\tdocument.ontouchend = function(e)\n
+\t\t{\n
+\t\t\ttouchEndHandler(e);\n
+\t\t\tself.documentUpHandler(e);\n
+\t\t};\n
+\t\tvar resizeHandler = window.onresize || function(){};\n
+\t\twindow.onresize = function(e)\n
+\t\t{\n
+\t\t\tresizeHandler(e);\n
+\t\t\tself.documentResizeHandler(e);\n
+\t\t};\n
+\t\tthis.wrapper.onmousemove = function(e)\n
+\t\t{\n
+\t\t\tself.activity = true;\n
+\t\t}\n
+\t\tthis.wrapper.onclick = function(e)\n
+\t\t{\n
+\t\t\treturn !self.activity;\n
+\t\t}\n
+\t\t\n
+\t\tthis.interval = setInterval(function(){ self.animate() }, 25);\n
+\t\tself.animate(false, true);\n
+\t},\n
+\thandleDownHandler: function(e)\n
+\t{\n
+\t\tthis.activity = false;\n
+\t\tCursor.refresh(e);\n
+\t\t\n
+\t\tthis.preventDefaults(e, true);\n
+\t\tthis.startDrag();\n
+\t},\n
+\twrapperDownHandler: function(e)\n
+\t{\n
+\t\tCursor.refresh(e);\n
+\t\t\n
+\t\tthis.preventDefaults(e, true);\n
+\t\tthis.startTap();\n
+\t},\n
+\tdocumentUpHandler: function(e)\n
+\t{\n
+\t\tthis.stopDrag();\n
+\t\tthis.stopTap();\n
+\t},\n
+\tdocumentResizeHandler: function(e)\n
+\t{\n
+\t\tthis.setWrapperOffset();\n
+\t\tthis.setBounds();\n
+\t\t\n
+\t\tthis.update();\n
+\t},\n
+\tenable: function()\n
+\t{\n
+\t\tthis.disabled = false;\n
+\t\tthis.handle.className = this.handle.className.replace(/\\s?disabled/g, \'\');\n
+\t},\n
+\tdisable: function()\n
+\t{\n
+\t\tthis.disabled = true;\n
+\t\tthis.handle.className += \' disabled\';\n
+\t},\n
+\tsetStep: function(x, y, snap)\n
+\t{\n
+\t\tthis.setValue(\n
+\t\t\tthis.steps && x > 1 ? (x - 1) / (this.steps - 1) : 0,\n
+\t\t\tthis.steps && y > 1 ? (y - 1) / (this.steps - 1) : 0,\n
+\t\t\tsnap\n
+\t\t);\n
+\t},\n
+\tsetValue: function(x, y, snap)\n
+\t{\n
+\t\tthis.setTargetValue([x, y || 0]);\n
+\t\tif(snap)\n
+\t\t{\n
+\t\t\tthis.groupCopy(this.value.current, this.value.target);\n
+\t\t}\n
+\t},\n
+\tstartTap: function(target)\n
+\t{\n
+\t\tif(this.disabled)\n
+\t\t{\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tthis.tapping = true;\n
+\n
+\t\tthis.setWrapperOffset();\n
+\t\tthis.setBounds();\n
+\n
+\t\tif(target === undefined)\n
+\t\t{\n
+\t\t\ttarget = [\n
+\t\t\t\tCursor.x - this.offset.wrapper[0] - (this.handle.offsetWidth / 2),\n
+\t\t\t\tCursor.y - this.offset.wrapper[1] - (this.handle.offsetHeight / 2)\n
+\t\t\t];\n
+\t\t}\n
+\t\tthis.setTargetOffset(target);\n
+\t},\n
+\tstopTap: function()\n
+\t{\n
+\t\tif(this.disabled || !this.tapping)\n
+\t\t{\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tthis.tapping = false;\n
+\t\t\n
+\t\tthis.setTargetValue(this.value.current);\n
+\t\tthis.result();\n
+\t},\n
+\tstartDrag: function()\n
+\t{\n
+\t\tif(this.disabled)\n
+\t\t{\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis.setWrapperOffset();\n
+\t\tthis.setBounds();\n
+\n
+\t\tthis.offset.mouse = [\n
+\t\t\tCursor.x - Position.get(this.handle)[0],\n
+\t\t\tCursor.y - Position.get(this.handle)[1]\n
+\t\t];\n
+\t\t\n
+\t\tthis.dragging = true;\n
+\t},\n
+\tstopDrag: function()\n
+\t{\n
+\t\tif(this.disabled || !this.dragging)\n
+\t\t{\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tthis.dragging = false;\n
+\t\t\n
+\t\tvar target = this.groupClone(this.value.current);\n
+\t\tif(this.slide)\n
+\t\t{\n
+\t\t\tvar ratioChange = this.change;\n
+\t\t\ttarget[0] += ratioChange[0] * 4;\n
+\t\t\ttarget[1] += ratioChange[1] * 4;\n
+\t\t}\n
+\t\tthis.setTargetValue(target);\n
+\t\tthis.result();\n
+\t},\n
+\tfeedback: function()\n
+\t{\n
+\t\tvar value = this.value.current;\n
+\t\tif(this.snap && this.steps > 1)\n
+\t\t{\n
+\t\t\tvalue = this.getClosestSteps(value);\n
+\t\t}\n
+\t\tif(!this.groupCompare(value, this.value.prev))\n
+\t\t{\n
+\t\t\tif(typeof(this.animationCallback) == \'function\')\n
+\t\t\t{\n
+\t\t\t\tthis.animationCallback(value[0], value[1]);\n
+\t\t\t}\n
+\t\t\tthis.groupCopy(this.value.prev, value);\n
+\t\t}\n
+\t},\n
+\tresult: function()\n
+\t{\n
+\t\tif(typeof(this.callback) == \'function\')\n
+\t\t{\n
+\t\t\tthis.callback(this.value.target[0], this.value.target[1]);\n
+\t\t}\n
+\t},\n
+\tanimate: function(direct, first)\n
+\t{\n
+\t\tif(direct && !this.dragging)\n
+\t\t{\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tif(this.dragging)\n
+\t\t{\n
+\t\t\tvar prevTarget = this.groupClone(this.value.target);\n
+\t\t\t\n
+\t\t\tvar offset = [\n
+\t\t\t\tCursor.x - this.offset.wrapper[0] - this.offset.mouse[0],\n
+\t\t\t\tCursor.y - this.offset.wrapper[1] - this.offset.mouse[1]\n
+\t\t\t];\n
+\t\t\tthis.setTargetOffset(offset, this.loose);\n
+\t\t\t\n
+\t\t\tthis.change = [\n
+\t\t\t\tthis.value.target[0] - prevTarget[0],\n
+\t\t\t\tthis.value.target[1] - prevTarget[1]\n
+\t\t\t];\n
+\t\t}\n
+\t\tif(this.dragging || first)\n
+\t\t{\n
+\t\t\tthis.groupCopy(this.value.current, this.value.target);\n
+\t\t}\n
+\t\tif(this.dragging || this.glide() || first)\n
+\t\t{\n
+\t\t\tthis.update();\n
+\t\t\tthis.feedback();\n
+\t\t}\n
+\t},\n
+\tglide: function()\n
+\t{\n
+\t\tvar diff = [\n
+\t\t\tthis.value.target[0] - this.value.current[0],\n
+\t\t\tthis.value.target[1] - this.value.current[1]\n
+\t\t];\n
+\t\tif(!diff[0] && !diff[1])\n
+\t\t{\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\tif(Math.abs(diff[0]) > this.bounds.xStep || Math.abs(diff[1]) > this.bounds.yStep)\n
+\t\t{\n
+\t\t\tthis.value.current[0] += diff[0] * this.speed;\n
+\t\t\tthis.value.current[1] += diff[1] * this.speed;\n
+\t\t}\n
+\t\telse\n
+\t\t{\n
+\t\t\tthis.groupCopy(this.value.current, this.value.target);\n
+\t\t}\n
+\t\treturn true;\n
+\t},\n
+\tupdate: function()\n
+\t{\n
+\t\tif(!this.snap)\n
+\t\t{\n
+\t\t\tthis.offset.current = this.getOffsetsByRatios(this.value.current);\n
+\t\t}\n
+\t\telse\n
+\t\t{\n
+\t\t\tthis.offset.current = this.getOffsetsByRatios(\n
+\t\t\t\tthis.getClosestSteps(this.value.current)\n
+\t\t\t);\n
+\t\t}\n
+\t\tthis.show();\n
+\t},\n
+\tshow: function()\n
+\t{\n
+\t\tif(!this.groupCompare(this.offset.current, this.offset.prev))\n
+\t\t{\n
+\t\t\tif(this.horizontal)\n
+\t\t\t{\n
+\t\t\t\tthis.handle.style.left = String(this.offset.current[0]) + \'px\';\n
+\t\t\t}\n
+\t\t\tif(this.vertical)\n
+\t\t\t{\n
+\t\t\t\tthis.handle.style.top = String(this.offset.current[1]) + \'px\';\n
+\t\t\t}\n
+\t\t\tthis.groupCopy(this.offset.prev, this.offset.current);\n
+\t\t}\n
+\t},\n
+\tsetTargetValue: function(value, loose)\n
+\t{\n
+\t\tvar target = loose ? this.getLooseValue(value) : this.getProperValue(value);\n
+\t\t\n
+\t\tthis.groupCopy(this.value.target, target);\n
+\t\tthis.offset.target = this.getOffsetsByRatios(target);\n
+\t},\n
+\tsetTargetOffset: function(offset, loose)\n
+\t{\n
+\t\tvar value = this.getRatiosByOffsets(offset);\n
+\t\tvar target = loose ? this.getLooseValue(value) : this.getProperValue(value);\n
+\t\t\n
+\t\tthis.groupCopy(this.value.target, target);\n
+\t\tthis.offset.target = this.getOffsetsByRatios(target);\n
+\t},\n
+\tgetLooseValue: function(value)\n
+\t{\n
+\t\tvar proper = this.getProperValue(value);\n
+\t\treturn [\n
+\t\t\tproper[0] + ((value[0] - proper[0]) / 4),\n
+\t\t\tproper[1] + ((value[1] - proper[1]) / 4)\n
+\t\t];\n
+\t},\n
+\tgetProperValue: function(value)\n
+\t{\n
+\t\tvar proper = this.groupClone(value);\n
+\n
+\t\tproper[0] = Math.max(proper[0], 0);\n
+\t\tproper[1] = Math.max(proper[1], 0);\n
+\t\tproper[0] = Math.min(proper[0], 1);\n
+\t\tproper[1] = Math.min(proper[1], 1);\n
+\n
+\t\tif((!this.dragging && !this.tapping) || this.snap)\n
+\t\t{\n
+\t\t\tif(this.steps > 1)\n
+\t\t\t{\n
+\t\t\t\tproper = this.getClosestSteps(proper);\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn proper;\n
+\t},\n
+\tgetRatiosByOffsets: function(group)\n
+\t{\n
+\t\treturn [\n
+\t\t\tthis.getRatioByOffset(group[0], this.bounds.xRange, this.bounds.x0),\n
+\t\t\tthis.getRatioByOffset(group[1], this.bounds.yRange, this.bounds.y0)\n
+\t\t];\n
+\t},\n
+\tgetRatioByOffset: function(offset, range, padding)\n
+\t{\n
+\t\treturn range ? (offset - padding) / range : 0;\n
+\t},\n
+\tgetOffsetsByRatios: function(group)\n
+\t{\n
+\t\treturn [\n
+\t\t\tthis.getOffsetByRatio(group[0], this.bounds.xRange, this.bounds.x0),\n
+\t\t\tthis.getOffsetByRatio(group[1], this.bounds.yRange, this.bounds.y0)\n
+\t\t];\n
+\t},\n
+\tgetOffsetByRatio: function(ratio, range, padding)\n
+\t{\n
+\t\treturn Math.round(ratio * range) + padding;\n
+\t},\n
+\tgetClosestSteps: function(group)\n
+\t{\n
+\t\treturn [\n
+\t\t\tthis.getClosestStep(group[0]),\n
+\t\t\tthis.getClosestStep(group[1])\n
+\t\t];\n
+\t},\n
+\tgetClosestStep: function(value)\n
+\t{\n
+\t\tvar k = 0;\n
+\t\tvar min = 1;\n
+\t\tfor(var i = 0; i <= this.steps - 1; i++)\n
+\t\t{\n
+\t\t\tif(Math.abs(this.stepRatios[i] - value) < min)\n
+\t\t\t{\n
+\t\t\t\tmin = Math.abs(this.stepRatios[i] - value);\n
+\t\t\t\tk = i;\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn this.stepRatios[k];\n
+\t},\n
+\tgroupCompare: function(a, b)\n
+\t{\n
+\t\treturn a[0] == b[0] && a[1] == b[1];\n
+\t},\n
+\tgroupCopy: function(a, b)\n
+\t{\n
+\t\ta[0] = b[0];\n
+\t\ta[1] = b[1];\n
+\t},\n
+\tgroupClone: function(a)\n
+\t{\n
+\t\treturn [a[0], a[1]];\n
+\t},\n
+\tpreventDefaults: function(e, selection)\n
+\t{\n
+\t\tif(!e)\n
+\t\t{\n
+\t\t\te = window.event;\n
+\t\t}\n
+\t\tif(e.preventDefault)\n
+\t\t{\n
+\t\t\te.preventDefault();\n
+\t\t}\n
+\t\te.returnValue = false;\n
+\t\t\n
+\t\tif(selection && document.selection)\n
+\t\t{\n
+\t\t\tdocument.selection.empty();\n
+\t\t}\n
+\t},\n
+\tcancelEvent: function(e)\n
+\t{\n
+\t\tif(!e)\n
+\t\t{\n
+\t\t\te = window.event;\n
+\t\t}\n
+\t\tif(e.stopPropagation)\n
+\t\t{\n
+\t\t\te.stopPropagation();\n
+\t\t}\n
+\t\te.cancelBubble = true;\n
+\t}\n
+};\n
+\n
+/*! Copyright (c) 2013 Brandon Aaron (http://brandonaaron.net)\n
+ * Licensed under the MIT License (LICENSE.txt).\n
+ *\n
+ * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.\n
+ * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.\n
+ * Thanks to: Seamus Leahy for adding deltaX and deltaY\n
+ *\n
+ * Version: 3.1.3\n
+ *\n
+ * Requires: 1.2.2+\n
+ */\n
+\n
+(function (factory) {\n
+    if ( typeof define === \'function\' && define.amd ) {\n
+        // AMD. Register as an anonymous module.\n
+        define([\'jquery\'], factory);\n
+    } else if (typeof exports === \'object\') {\n
+        // Node/CommonJS style for Browserify\n
+        module.exports = factory;\n
+    } else {\n
+        // Browser globals\n
+        factory(jQuery);\n
+    }\n
+}(function ($) {\n
+\n
+    var toFix = [\'wheel\', \'mousewheel\', \'DOMMouseScroll\', \'MozMousePixelScroll\'];\n
+    var toBind = \'onwheel\' in document || document.documentMode >= 9 ? [\'wheel\'] : [\'mousewheel\', \'DomMouseScroll\', \'MozMousePixelScroll\'];\n
+    var lowestDelta, lowestDeltaXY;\n
+\n
+    if ( $.event.fixHooks ) {\n
+        for ( var i = toFix.length; i; ) {\n
+            $.event.fixHooks[ toFix[--i] ] = $.event.mouseHooks;\n
+        }\n
+    }\n
+\n
+    $.event.special.mousewheel = {\n
+        setup: function() {\n
+            if ( this.addEventListener ) {\n
+                for ( var i = toBind.length; i; ) {\n
+                    this.addEventListener( toBind[--i], handler, false );\n
+                }\n
+            } else {\n
+                this.onmousewheel = handler;\n
+            }\n
+        },\n
+\n
+        teardown: function() {\n
+            if ( this.removeEventListener ) {\n
+                for ( var i = toBind.length; i; ) {\n
+                    this.removeEventListener( toBind[--i], handler, false );\n
+                }\n
+            } else {\n
+                this.onmousewheel = null;\n
+            }\n
+        }\n
+    };\n
+\n
+    $.fn.extend({\n
+        mousewheel: function(fn) {\n
+            return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");\n
+        },\n
+\n
+        unmousewheel: function(fn) {\n
+            return this.unbind("mousewheel", fn);\n
+        }\n
+    });\n
+\n
+\n
+    function handler(event) {\n
+        var orgEvent = event || window.event,\n
+            args = [].slice.call(arguments, 1),\n
+            delta = 0,\n
+            deltaX = 0,\n
+            deltaY = 0,\n
+            absDelta = 0,\n
+            absDeltaXY = 0,\n
+            fn;\n
+        event = $.event.fix(orgEvent);\n
+        event.type = "mousewheel";\n
+\n
+        // Old school scrollwheel delta\n
+        if ( orgEvent.wheelDelta ) { delta = orgEvent.wheelDelta; }\n
+        if ( orgEvent.detail )     { delta = orgEvent.detail * -1; }\n
+\n
+        // New school wheel delta (wheel event)\n
+        if ( orgEvent.deltaY ) {\n
+            deltaY = orgEvent.deltaY * -1;\n
+            delta  = deltaY;\n
+        }\n
+        if ( orgEvent.deltaX ) {\n
+            deltaX = orgEvent.deltaX;\n
+            delta  = deltaX * -1;\n
+        }\n
+\n
+        // Webkit\n
+        if ( orgEvent.wheelDeltaY !== undefined ) { deltaY = orgEvent.wheelDeltaY; }\n
+        if ( orgEvent.wheelDeltaX !== undefined ) { deltaX = orgEvent.wheelDeltaX * -1; }\n
+\n
+        // Look for lowest delta to normalize the delta values\n
+        absDelta = Math.abs(delta);\n
+        if ( !lowestDelta || absDelta < lowestDelta ) { lowestDelta = absDelta; }\n
+        absDeltaXY = Math.max(Math.abs(deltaY), Math.abs(deltaX));\n
+        if ( !lowestDeltaXY || absDeltaXY < lowestDeltaXY ) { lowestDeltaXY = absDeltaXY; }\n
+\n
+        // Get a whole value for the deltas\n
+        fn = delta > 0 ? \'floor\' : \'ceil\';\n
+        delta  = Math[fn](delta / lowestDelta);\n
+        deltaX = Math[fn](deltaX / lowestDeltaXY);\n
+        deltaY = Math[fn](deltaY / lowestDeltaXY);\n
+\n
+        // Add event and delta to the front of the arguments\n
+        args.unshift(event, delta, deltaX, deltaY);\n
+\n
+        return ($.event.dispatch || $.event.handle).apply(this, args);\n
+    }\n
+\n
+}));\n
+\n
+})(jQuery, window, Handsontable);\n
+// numeral.js\n
+// version : 1.4.7\n
+// author : Adam Draper\n
+// license : MIT\n
+// http://adamwdraper.github.com/Numeral-js/\n
+\n
+(function () {\n
+\n
+    /************************************\n
+        Constants\n
+    ************************************/\n
+\n
+    var numeral,\n
+        VERSION = \'1.4.7\',\n
+        // internal storage for language config files\n
+        languages = {},\n
+        currentLanguage = \'en\',\n
+        zeroFormat = null,\n
+        // check for nodeJS\n
+        hasModule = (typeof module !== \'undefined\' && module.exports);\n
+\n
+\n
+    /************************************\n
+        Constructors\n
+    ************************************/\n
+\n
+\n
+    // Numeral prototype object\n
+    function Numeral (number) {\n
+        this._n = number;\n
+    }\n
+\n
+    /**\n
+     * Implementation of toFixed() that treats floats more like decimals\n
+     *\n
+     * Fixes binary rounding issues (eg. (0.615).toFixed(2) === \'0.61\') that present\n
+     * problems for accounting- and finance-related software.\n
+     */\n
+    function toFixed (value, precision, optionals) {\n
+        var power = Math.pow(10, precision),\n
+            output;\n
+\n
+        // Multiply up by precision, round accurately, then divide and use native toFixed():\n
+        output = (Math.round(value * power) / power).toFixed(precision);\n
+\n
+        if (optionals) {\n
+            var optionalsRegExp = new RegExp(\'0{1,\' + optionals + \'}$\');\n
+            output = output.replace(optionalsRegExp, \'\');\n
+        }\n
+\n
+        return output;\n
+    }\n
+\n
+    /************************************\n
+        Formatting\n
+    ************************************/\n
+\n
+    // determine what type of formatting we need to do\n
+    function formatNumeral (n, format) {\n
+        var output;\n
+\n
+        // figure out what kind of format we are dealing with\n
+        if (format.indexOf(\'$\') > -1) { // currency!!!!!\n
+            output = formatCurrency(n, format);\n
+        } else if (format.indexOf(\'%\') > -1) { // percentage\n
+            output = formatPercentage(n, format);\n
+        } else if (format.indexOf(\':\') > -1) { // time\n
+            output = formatTime(n, format);\n
+        } else { // plain ol\' numbers or bytes\n
+            output = formatNumber(n, format);\n
+        }\n
+\n
+        // return string\n
+        return output;\n
+    }\n
+\n
+    // revert to number\n
+    function unformatNumeral (n, string) {\n
+        if (string.indexOf(\':\') > -1) {\n
+            n._n = unformatTime(string);\n
+        } else {\n
+            if (string === zeroFormat) {\n
+                n._n = 0;\n
+            } else {\n
+                var stringOriginal = string;\n
+                if (languages[currentLanguage].delimiters.decimal !== \'.\') {\n
+                    string = string.replace(/\\./g,\'\').replace(languages[currentLanguage].delimiters.decimal, \'.\');\n
+                }\n
+\n
+                // see if abbreviations are there so that we can multiply to the correct number\n
+                var thousandRegExp = new RegExp(languages[currentLanguage].abbreviations.thousand + \'(?:\\\\)|(\\\\\' + languages[currentLanguage].currency.symbol + \')?(?:\\\\))?)?$\'),\n
+                    millionRegExp = new RegExp(languages[currentLanguage].abbreviations.million + \'(?:\\\\)|(\\\\\' + languages[currentLanguage].currency.symbol + \')?(?:\\\\))?)?$\'),\n
+                    billionRegExp = new RegExp(languages[currentLanguage].abbreviations.billion + \'(?:\\\\)|(\\\\\' + languages[currentLanguage].currency.symbol + \')?(?:\\\\))?)?$\'),\n
+                    trillionRegExp = new RegExp(languages[currentLanguage].abbreviations.trillion + \'(?:\\\\)|(\\\\\' + languages[currentLanguage].currency.symbol + \')?(?:\\\\))?)?$\');\n
+\n
+                // see if bytes are there so that we can multiply to the correct number\n
+                var prefixes = [\'KB\', \'MB\', \'GB\', \'TB\', \'PB\', \'EB\', \'ZB\', \'YB\'],\n
+                    bytesMultiplier = false;\n
+\n
+                for (var power = 0; power <= prefixes.length; power++) {\n
+                    bytesMultiplier = (string.indexOf(prefixes[power]) > -1) ? Math.pow(1024, power + 1) : false;\n
+\n
+                    if (bytesMultiplier) {\n
+                        break;\n
+                    }\n
+                }\n
+\n
+                // do some math to create our number\n
+                n._n = ((bytesMultiplier) ? bytesMultiplier : 1) * ((stringOriginal.match(thousandRegExp)) ? Math.pow(10, 3) : 1) * ((stringOriginal.match(millionRegExp)) ? Math.pow(10, 6) : 1) * ((stringOriginal.match(billionRegExp)) ? Math.pow(10, 9) : 1) * ((stringOriginal.match(trillionRegExp)) ? Math.pow(10, 12) : 1) * ((string.indexOf(\'%\') > -1) ? 0.01 : 1) * Number(((string.indexOf(\'(\') > -1) ? \'-\' : \'\') + string.replace(/[^0-9\\.-]+/g, \'\'));\n
+\n
+                // round if we are talking about bytes\n
+                n._n = (bytesMultiplier) ? Math.ceil(n._n) : n._n;\n
+            }\n
+        }\n
+        return n._n;\n
+    }\n
+\n
+    function formatCurrency (n, format) {\n
+        var prependSymbol = (format.indexOf(\'$\') <= 1) ? true : false;\n
+\n
+        // remove $ for the moment\n
+        var space = \'\';\n
+\n
+        // check for space before or after currency\n
+        if (format.indexOf(\' $\') > -1) {\n
+            space = \' \';\n
+            format = format.replace(\' $\', \'\');\n
+        } else if (format.indexOf(\'$ \') > -1) {\n
+            space = \' \';\n
+            format = format.replace(\'$ \', \'\');\n
+        } else {\n
+            format = format.replace(\'$\', \'\');\n
+        }\n
+\n
+        // format the number\n
+        var output = formatNumeral(n, format);\n
+\n
+        // position the symbol\n
+        if (prependSymbol) {\n
+            if (output.indexOf(\'(\') > -1 || output.indexOf(\'-\') > -1) {\n
+                output = output.split(\'\');\n
+                output.splice(1, 0, languages[currentLanguage].currency.symbol + space);\n
+                output = output.join(\'\');\n
+            } else {\n
+                output = languages[currentLanguage].currency.symbol + space + output;\n
+            }\n
+        } else {\n
+            if (output.indexOf(\')\') > -1) {\n
+                output = output.split(\'\');\n
+                output.splice(-1, 0, space + languages[currentLanguage].currency.symbol);\n
+                output = output.join(\'\');\n
+            } else {\n
+                output = output + space + languages[currentLanguage].currency.symbol;\n
+            }\n
+        }\n
+\n
+        return output;\n
+    }\n
+\n
+    function formatPercentage (n, format) {\n
+        var space = \'\';\n
+        // check for space before %\n
+        if (format.indexOf(\' %\') > -1) {\n
+            space = \' \';\n
+            format = format.replace(\' %\', \'\');\n
+        } else {\n
+            format = format.replace(\'%\', \'\');\n
+        }\n
+\n
+        n._n = n._n * 100;\n
+        var output = formatNumeral(n, format);\n
+        if (output.indexOf(\')\') > -1 ) {\n
+            output = output.split(\'\');\n
+            output.splice(-1, 0, space + \'%\');\n
+            output = output.join(\'\');\n
+        } else {\n
+            output = output + space + \'%\';\n
+        }\n
+        return output;\n
+    }\n
+\n
+    function formatTime (n, format) {\n
+        var hours = Math.floor(n._n/60/60),\n
+            minutes = Math.floor((n._n - (hours * 60 * 60))/60),\n
+            seconds = Math.round(n._n - (hours * 60 * 60) - (minutes * 60));\n
+        return hours + \':\' + ((minutes < 10) ? \'0\' + minutes : minutes) + \':\' + ((seconds < 10) ? \'0\' + seconds : seconds);\n
+    }\n
+\n
+    function unformatTime (string) {\n
+        var timeArray = string.split(\':\'),\n
+            seconds = 0;\n
+        // turn hours and minutes into seconds and add them all up\n
+        if (timeArray.length === 3) {\n
+            // hours\n
+            seconds = seconds + (Number(timeArray[0]) * 60 * 60);\n
+            // minutes\n
+            seconds = seconds + (Number(timeArray[1]) * 60);\n
+            // seconds\n
+            seconds = seconds + Number(timeArray[2]);\n
+        } else if (timeArray.lenght === 2) {\n
+            // minutes\n
+            seconds = seconds + (Number(timeArray[0]) * 60);\n
+            // seconds\n
+            seconds = seconds + Number(timeArray[1]);\n
+        }\n
+        return Number(seconds);\n
+    }\n
+\n
+    function formatNumber (n, format) {\n
+        var negP = false,\n
+            optDec = false,\n
+            abbr = \'\',\n
+            bytes = \'\',\n
+            ord = \'\',\n
+            abs = Math.abs(n._n);\n
+\n
+        // check if number is zero and a custom zero format has been set\n
+        if (n._n === 0 && zeroFormat !== null) {\n
+            return zeroFormat;\n
+        } else {\n
+            // see if we should use parentheses for negative number\n
+            if (format.indexOf(\'(\') > -1) {\n
+                negP = true;\n
+                format = format.slice(1, -1);\n
+            }\n
+\n
+            // see if abbreviation is wanted\n
+            if (format.indexOf(\'a\') > -1) {\n
+                // check for space before abbreviation\n
+                if (format.indexOf(\' a\') > -1) {\n
+                    abbr = \' \';\n
+                    format = format.replace(\' a\', \'\');\n
+                } else {\n
+                    format = format.replace(\'a\', \'\');\n
+                }\n
+\n
+                if (abs >= Math.pow(10, 12)) {\n
+                    // trillion\n
+                    abbr = abbr + languages[currentLanguage].abbreviations.trillion;\n
+                    n._n = n._n / Math.pow(10, 12);\n
+                } else if (abs < Math.pow(10, 12) && abs >= Math.pow(10, 9)) {\n
+                    // billion\n
+                    abbr = abbr + languages[currentLanguage].abbreviations.billion;\n
+                    n._n = n._n / Math.pow(10, 9);\n
+                } else if (abs < Math.pow(10, 9) && abs >= Math.pow(10, 6)) {\n
+                    // million\n
+                    abbr = abbr + languages[currentLanguage].abbreviations.million;\n
+                    n._n = n._n / Math.pow(10, 6);\n
+                } else if (abs < Math.pow(10, 6) && abs >= Math.pow(10, 3)) {\n
+                    // thousand\n
+                    abbr = abbr + languages[currentLanguage].abbreviations.thousand;\n
+                    n._n = n._n / Math.pow(10, 3);\n
+                }\n
+            }\n
+\n
+            // see if we are formatting bytes\n
+            if (format.indexOf(\'b\') > -1) {\n
+                // check for space before\n
+                if (format.indexOf(\' b\') > -1) {\n
+                    bytes = \' \';\n
+                    format = format.replace(\' b\', \'\');\n
+                } else {\n
+                    format = format.replace(\'b\', \'\');\n
+                }\n
+\n
+                var prefixes = [\'B\', \'KB\', \'MB\', \'GB\', \'TB\', \'PB\', \'EB\', \'ZB\', \'YB\'],\n
+                    min,\n
+                    max;\n
+\n
+                for (var power = 0; power <= prefixes.length; power++) {\n
+                    min = Math.pow(1024, power);\n
+                    max = Math.pow(1024, power+1);\n
+\n
+                    if (n._n >= min && n._n < max) {\n
+                        bytes = bytes + prefixes[power];\n
+                        if (min > 0) {\n
+                            n._n = n._n / min;\n
+                        }\n
+                        break;\n
+                    }\n
+                }\n
+            }\n
+\n
+            // see if ordinal is wanted\n
+            if (format.indexOf(\'o\') > -1) {\n
+                // check for space before\n
+                if (format.indexOf(\' o\') > -1) {\n
+                    ord = \' \';\n
+                    format = format.replace(\' o\', \'\');\n
+                } else {\n
+                    format = format.replace(\'o\', \'\');\n
+                }\n
+\n
+                ord = ord + languages[currentLanguage].ordinal(n._n);\n
+            }\n
+\n
+            if (format.indexOf(\'[.]\') > -1) {\n
+                optDec = true;\n
+                format = format.replace(\'[.]\', \'.\');\n
+            }\n
+\n
+            var w = n._n.toString().split(\'.\')[0],\n
+                precision = format.split(\'.\')[1],\n
+                thousands = format.indexOf(\',\'),\n
+                d = \'\',\n
+                neg = false;\n
+\n
+            if (precision) {\n
+                if (precision.indexOf(\'[\') > -1) {\n
+                    precision = precision.replace(\']\', \'\');\n
+                    precision = precision.split(\'[\');\n
+                    d = toFixed(n._n, (precision[0].length + precision[1].length), precision[1].length);\n
+                } else {\n
+                    d = toFixed(n._n, precision.length);\n
+                }\n
+\n
+                w = d.split(\'.\')[0];\n
+\n
+                if (d.split(\'.\')[1].length) {\n
+                    d = languages[currentLanguage].delimiters.decimal + d.split(\'.\')[1];\n
+                } else {\n
+                    d = \'\';\n
+                }\n
+\n
+                if (optDec && Number(d) === 0) {\n
+                    d = \'\';\n
+                }\n
+            } else {\n
+                w = toFixed(n._n, null);\n
+            }\n
+\n
+            // format number\n
+            if (w.indexOf(\'-\') > -1) {\n
+                w = w.slice(1);\n
+                neg = true;\n
+            }\n
+\n
+            if (thousands > -1) {\n
+                w = w.toString().replace(/(\\d)(?=(\\d{3})+(?!\\d))/g, \'$1\' + languages[currentLanguage].delimiters.thousands);\n
+            }\n
+\n
+            if (format.indexOf(\'.\') === 0) {\n
+                w = \'\';\n
+            }\n
+\n
+            return ((negP && neg) ? \'(\' : \'\') + ((!negP && neg) ? \'-\' : \'\') + w + d + ((ord) ? ord : \'\') + ((abbr) ? abbr : \'\') + ((bytes) ? bytes : \'\') + ((negP && neg) ? \')\' : \'\');\n
+        }\n
+    }\n
+\n
+    /************************************\n
+        Top Level Functions\n
+    ************************************/\n
+\n
+    numeral = function (input) {\n
+        if (numeral.isNumeral(input)) {\n
+            input = input.value();\n
+        } else if (!Number(input)) {\n
+            input = 0;\n
+        }\n
+\n
+        return new Numeral(Number(input));\n
+    };\n
+\n
+    // version number\n
+    numeral.version = VERSION;\n
+\n
+    // compare numeral object\n
+    numeral.isNumeral = function (obj) {\n
+        return obj instanceof Numeral;\n
+    };\n
+\n
+    // This function will load languages and then set the global language.  If\n
+    // no arguments are passed in, it will simply return the current global\n
+    // language key.\n
+    numeral.language = function (key, values) {\n
+        if (!key) {\n
+            return currentLanguage;\n
+        }\n
+\n
+        if (key && !values) {\n
+            currentLanguage = key;\n
+        }\n
+\n
+        if (values || !languages[key]) {\n
+            loadLanguage(key, values);\n
+        }\n
+\n
+        return numeral;\n
+    };\n
+\n
+    numeral.language(\'en\', {\n
+        delimiters: {\n
+            thousands: \',\',\n
+            decimal: \'.\'\n
+        },\n
+        abbreviations: {\n
+            thousand: \'k\',\n
+            million: \'m\',\n
+            billion: \'b\',\n
+            trillion: \'t\'\n
+        },\n
+        ordinal: function (number) {\n
+            var b = number % 10;\n
+            return (~~ (number % 100 / 10) === 1) ? \'th\' :\n
+                (b === 1) ? \'st\' :\n
+                (b === 2) ? \'nd\' :\n
+                (b === 3) ? \'rd\' : \'th\';\n
+        },\n
+        currency: {\n
+            symbol: \'$\'\n
+        }\n
+    });\n
+\n
+    numeral.zeroFormat = function (format) {\n
+        if (typeof(format) === \'string\') {\n
+            zeroFormat = format;\n
+        } else {\n
+            zeroFormat = null;\n
+        }\n
+    };\n
+\n
+    /************************************\n
+        Helpers\n
+    ************************************/\n
+\n
+    function loadLanguage(key, values) {\n
+        languages[key] = values;\n
+    }\n
+\n
+\n
+    /************************************\n
+        Numeral Prototype\n
+    ************************************/\n
+\n
+\n
+    numeral.fn = Numeral.prototype = {\n
+\n
+        clone : function () {\n
+            return numeral(this);\n
+        },\n
+\n
+        format : function (inputString) {\n
+            return formatNumeral(this, inputString ? inputString : numeral.defaultFormat);\n
+        },\n
+\n
+        unformat : function (inputString) {\n
+            return unformatNumeral(this, inputString ? inputString : numeral.defaultFormat);\n
+        },\n
+\n
+        value : function () {\n
+            return this._n;\n
+        },\n
+\n
+        valueOf : function () {\n
+            return this._n;\n
+        },\n
+\n
+        set : function (value) {\n
+            this._n = Number(value);\n
+            return this;\n
+        },\n
+\n
+        add : function (value) {\n
+            this._n = this._n + Number(value);\n
+            return this;\n
+        },\n
+\n
+        subtract : function (value) {\n
+            this._n = this._n - Number(value);\n
+            return this;\n
+        },\n
+\n
+        multiply : function (value) {\n
+            this._n = this._n * Number(value);\n
+            return this;\n
+        },\n
+\n
+        divide : function (value) {\n
+            this._n = this._n / Number(value);\n
+            return this;\n
+        },\n
+\n
+        difference : function (value) {\n
+            var difference = this._n - Number(value);\n
+\n
+            if (difference < 0) {\n
+                difference = -difference;\n
+            }\n
+\n
+            return difference;\n
+        }\n
+\n
+    };\n
+\n
+    /************************************\n
+        Exposing Numeral\n
+    ************************************/\n
+\n
+    // CommonJS module is defined\n
+    if (hasModule) {\n
+        module.exports = numeral;\n
+    }\n
+\n
+    /*global ender:false */\n
+    if (typeof ender === \'undefined\') {\n
+        // here, `this` means `window` in the browser, or `global` on the server\n
+        // add `numeral` as a global object via a string identifier,\n
+        // for Closure Compiler \'advanced\' mode\n
+        this[\'numeral\'] = numeral;\n
+    }\n
+\n
+    /*global define:false */\n
+    if (typeof define === \'function\' && define.amd) {\n
+        define([], function () {\n
+            return numeral;\n
+        });\n
+    }\n
+}).call(this);\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8eb39eedde5f8310f5cd95eba04d6a66a06d40ae
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>images</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ajax-loader.gif.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ajax-loader.gif.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7899dfa4c0154669d1ca4d4efd0144d67338aed8
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ajax-loader.gif.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681767.01</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ajax-loader.gif</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/gif</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">R0lGODlhLgAuALMAAP///+7u7t3d3czMzLu7u6qqqpmZmYiIiHd3d2ZmZlVVVURERDMzMyIiIhER
+EQAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAwAAACwAAAAALgAuAAAE/xDISSt4OGttu/dbKGJf
+WY2oaJZpu62WK7/wNd/kiu+P6SqIwmAQGOw+rURBEGg6eaCRwiBgOpsEaGyUIFS/1wCvR0ElBl+w
+Mzsui87patFwQCDGZFtI4Y0TEnghEiMGaGkHgSp6GmdDVQN3iYKEQ5WIkjMKlUMFmDcImwOAnjKF
+lWykLkKWqTIErwSQrS6wr6OzKLV/uCm6kbwiBbWXwCEHsAUGxSIIBMIFBbfLGArQ1sTTGAfWyb+t
+ixnV1gYG0p6DzNDkdOaS6HsGyeQHdQsjDg44E1Lr9PQICRQsYMCggUF8N9y8mfcPYECBBA/mk3FC
+ir86DgMOLNgA38QUHThQKEjQ0KHAjRI/KtoiMoGdjBAjdmyBpMWCkQlynixIkUUxGMBqgDsn9J27
+ogoDIQ3ZZqlPF0UjAAAh+QQJAwAAACwAAAAALgAuAAAE/xDISSt4OGttu/dbKGJfWY2oaJZpu62W
+K7/wNd/kiu+P6SqIwmAQCAwLB9mnlSgInsVoUTADjRSGp1YbBSCqsVGCsC13FbeTeFA2T3eU9bBM
+MBwQiIOBAJdcCUOBAgQJPCN+IgeBgUmGhzYbCYtDX46HIwaTjZY3CpMFnDsIBKSAhaE3e6WgqDcF
+pQSbrS6wBJWzLq+lp7gtBboFvL0ovwS/t8OYv8fJKQfLSM0oTb8GBsLSGQrL1rLZGc/WdtizkBpY
+4gcHaL2IIQjd6gjs5ebn6vJ4CQv19tr4eBAkSKCAAYMGDRw44BHnSj6BBBcYRKiwzwQUQAIOVCDx
+YMKFaTXCiFiQQF/Ejh9BurCCguRGjhNTKmGZYoHNjh5VpvCRDYa0Gv5QAb3YaqgaTkY7OErKcyXQ
+CAAh+QQJAwAAACwAAAAALgAuAAAE/xDISSt4OGttu/dbKGJfWY2oaJZpu62WK7/wNd/kiu+P6SqI
+wmAgEAwLCIXr00oIi1BBYBoQFBIt0EhhGEa/1Kkh1UElCEPiFxoGYMkUMzqtjlapgIIsLjrT0wQG
+BwgIB11TNksSW0J/BG8hCAIIN4siBwMEcwMHPHB9mqEElJ4oiRsHogSdpTsKqmOtOwiqkLIzqaGx
+tzcGBQUEBay8M7/GtsQtxr/IySjLV84yywbN0iG+Btqk1yiG2oLdKQngBwdK4iJc5ubc6RuF7Eni
+pxkK8oQL15aR7QgJCfQ547cBCKF/CRQsYJBswpaDABUyYNDAgYNWfNQBjLiQYsWLnjpOjFiwUaJH
+iyFjjFTAsmODjzy0oGCwwCXMHUxcTHxpEeQMH+9gpKtRjxhRh0aPZsSoVGXMpiz2EI0AACH5BAkD
+AAAALAAAAAAuAC4AAAT/EMhJK3g4a22791soYl9Zjaholmm7rZYrv/A13+SK74/pKggDgSAQDA0I
+hevTShgG0EFxOi0kWqCR4hCNUqmBgEE56qAUha73WwwHBtcyBZUgDOxqKdsdECBQcyIKQ4RRBAcH
+CAgHT21uAAOAEloFhIRWIwgEfAZYNiEHlkMHLgcBkEufGmiifzIHBTKqGqGVQ648PGgFvAWdubkJ
+vbxxwDuwvb/GOwbJuMs3BtLSxdAz09Jk1tfTB9rbpYiI1eAp4uPlMouIiukuCeKKC+4pW4kICeT0
+GwmK+Anz6M3CAORfAgUM3E0S0S+fAgULEpZbGGJBvoMLIjZwAG7CCIsPRSMyaLCR47JAIhaEZDCy
+JLQTIxhkZEnSgUlgZmKybGnTWBYUDXje5MHEhc2hOHzsy6FUYA2nNSi+jArzJNWcRK829VQjAgAh
++QQJAwAAACwAAAAALgAuAAAE/xDISSt4OGttu/dbKGJfWY2oaJZpu62WK7/wNd/kiu+P6SoIA4Ew
+GAwNCIXr01IIi9CBYCoYFBIt0EhxGEah1LBBOeqgFIWh+isNTwfYMgWVSKu9X7cgEBDEVRNbdncE
+BQcHCQkHBm1UfH5yNiFOhXdXIwkEjnwDZCESIwgFaaQILgd7fHwGciJoo7B/LQipARKeHCMHsKOm
+Nwd8AAQ7r6MGBzxSPA8JBs7OsjO4OEHPyMvYi86I2NmHh9HdM9+H0+Iy3whJ5zuH6uvsN+/q5vF0
+6on19q74CQoM+1wsSORPwYKAP/ItWAAQYQ8RAxUYZMCgAUJQEA0yrOggIMYQDEUWUuTY0V4gESEp
+NmjgoCS7OSNGrmxpEqaIlSxdnjODYqZObFpQtPy5jIlDGkaP9tBxtIakfU5PvoxqsxtVnjyu+pAR
+NQIAIfkEBQMAAAAsAAAAAC4ALgAABP8QyEkreDhrbbv3WyhiX1mNqGiWabutliu/8DXf5Irvj+kq
+iAOBMBgMDQiF69NSCIfEorRYSLRAI2cBCp0WBYKBQTnqoBQGwpYbnYLBBGuZgkoU7uuud/AGD+Qq
+E1kGeHkFBwgJCQdCfH1hgDQ2IWiFdwaRGgkEjwEEZCESIwiWBQguB30BAQZzImgGsYSZKAiqAbQ9
+o7Kxpzepq6sFN04GB7EHPATBq6Ati4yMzjMJzAHJMkHRvjwDAROt2dEHuTIFAmM4jAjs0zw77PEL
+7/QP8Yrz9Tzsign5+jj6JVDwD+AMBYoUEDSIY4FCggsaMJzBQOGCBQwYTJxxESODBhJON2aYpIGB
+R5ANHIjsQbJkRpAOVIoUJaLBx5QyZ9IMgTLmSjojcK5kKWiET50nhgaKoTQUlqY5mECF0bRGS4ZW
+ixrMmlQfVzPvvvqQkTUCACH5BAkDAAAALAAAAAAuAC4AAATZEMhJq7046827/2AojmRpnmjqPQlQ
+FATxqhssxTFl0BPizrecZEDk/YBBwoRYTO0kLxuOwqQZntGnxDccqA7XMOCw8U4EpQNY3DEDBGiR
+ek4eweX0Vgh+/yzGYwdce3dxHgiIiCV9HwmJCHokAZMFHo4JmAokBpOTbhuYoX8jB50BhqCZCgwk
+CKYBHgqysqwjrqaxCgu7tUYZuwsMwr4awsYNxBnHDQ0OyRcNDMzNzs8W0w7ZD9YVDtQP4NvcE9rh
+4uMA5uro6evsEu7v7fL09fb3+Pn6+/z6EQAh+QQJAwAAACwAAAAALgAuAAAE/xDISSt4OGttu/db
+KGJfWY2oaJZpu62WK7/wNd/kiu+PKScHQ4FAKBQOCIXr01IcjNAhcWpItEAjBUIYnXoJg8FBOeqg
+nIZ0VPoNDwjWMuV8qKfV0Lb7HVdNsnWBd0gICQkIT2B7YX00NiELiIGBjRoJBYsCBGQhEiOHhHWV
+IgduAqcGciKRCK2tnC0IYaenoz2frq84B7SnBTcLhsK2LQS9ArApwcMLPAnHBzMK09Q8GMa0vzLU
+CwsM1g8GvQQz3d4M39YHAafs5ejoDeAI7AIBATPwDA3y1vT39/Lx4+cA3DqAAmYMdMAQnAGAAQYo
+bMCwILgCASQE0OaiIrgNCkDERZth8aPJkzceodzhaSWPli5x/Ik5Yw5NGSdupjCj00+Mnp2wAM3B
+ZCgMoDVUukw6EyXTnCaf8nwplQXOpBEAACH5BAkDAAAALAAAAAAuAC4AAAT/EMhJK3g4a22791so
+Yl9Zjaholmm7rZYrv/A13+SK748pJweDoVAQHhIK16elQAiJUCJhakimQKNmUPiETr+Eg1UVyyIO
+6O3QCyYMCgnUyZxGc6Pt6YAQH1FGCwiCdWgICYdnBWADjHx+EigJgoMHCGMbCYqMmwSXHDYhCoiT
+fSkHbpsDBo8iDIevljMIqYylHIAKuYeeLQe0qzMMC7nEPAUDAskCvCPCC88LDDwJyskHwQzZ2TwY
+BNUF2NrS3AbVBDMN6ercDwjVA+jpDg0O7O7VMw76+/bVAvkY+HE7ECBZQXbsDARYGAAeQh4DGAYA
+9xAHAokBrlW8IQAjs40jQQgCWEgxBCiQGw6MtJUBEsqQrF7imCBzxp+aSm7ifDRnJ40yPj91CNqS
+RVAYPmucRKmUJsimPRFCHcptqg8ZTSMAACH5BAkDAAAALAAAAAAuAC4AAAT/EMhJK3g4a22791so
+Yl9Zjaholmm7rZYrv/A13+SK748pJ4jDwVAwGA4J2aelCAqNxoJUelC0QKMFUMiFTgsEqnXUQWkR
+aO4wOg0TwmMVxQxEO7vE9nufJE+yCYF1QQiCgQhSe4pxNDYiCpCChYwaCQaKbwWUGRJZkJEJmyEI
+igMDB34iDAusC5ALM6Sms30vIwy4qwsMOAezpgY3Dbm5PAW/A6IiDczMDA08CcgIMw7WzTwYBL/B
+MtbfDtkPBgMC5gQ44OII5uYD2eHZ7O0C4uv09fY88+76PAb00PnDUa5dgYE3EASghwqhjAELBSxU
+5lDDgQAYMR5UURHDxYwYRGtxcOTQAACQ3UJ06vgAwckAyfyQLAlAgMiRK1miQXGCZYoyPuXECKoS
+C9EcS47CIFpjJsKmf55CneNvKlAeVn0oaRoBACH5BAkDAAAALAAAAAAuAC4AAAT/EMhJK3g4a227
+91soYl9Zjaholmm7rZYrv/A13+SK748pKwnEYThEJGSf1iIRRAiJhqjhoGiBRgwg0/kcSgtgKqqD
+YiwU2mb3Cy4YqqMTdnFGM5vEQ7TdPsYnIw0Mg3R2CWiGem0EBYxwIYBYg4R0DCMJB2AEm45/gQ2g
+k5YtCJqcB54hDg6grQ0zCZycfi8jq7erOAiyBAY4Dhi3PAacAwSPPDyxBAPNCMnQDwXNzb7RPAfU
+xtc8CNoD3DsJ3+G61ALg5TPeAu3p6i4G7e0E8DIE8wIF9i0J+QKo+KHAlw+ZQA0H/u1TwQ/BPwG0
+ONhQdyBAgHzWIE3kpkCAxY8BQgYYzBAp3ACQFyNKlAAPwEcBz/6U5EbA5QCVKymo0zeSJJlyPXPK
+OegzCdEeOg7W2Khu6cxrTodGi/qTB1UfSJZGAAAh+QQFAwAAACwAAAAALgAuAAAE/xDISSt4OGtt
+u/dbKGJfWY2oaJZpu62WK7/wNd/kiu+PKS+KBGJITMg+LQYwwSQenk+EogUaNZTAYBMBPRi+UlQH
+dWVgFVrn82soGKajk7VsXmSFQyi74DbGJyMODg2EZlh2dkFce3wFcCGAgYKDdCMKXm2Nb38pk5Qu
+CI18BAecLZMzCaMFBI4qPDKhBLOksLYPBrSzj7c3CboECL08rLQGwzsHugXIOAgDBAPQzb7S1tSp
+1tLYsdoD3C4H2gTgLdHWx+UjCQICA+7C6iIE7e0DvPIYB/Xt6ZDgCPi180OD2z6B/go2Q0AggMB7
+f2zcKjAggEWBBGlIGNbQokOLAzkyatx4ywAAjyBFcohx66RHVxHl2DopoIDKkTJ5JDiATwWLfDDk
+1ZCIbWgkZEZzzkzKkgdTH0eGRgAAIfkECQMAAAAsAAAAAC4ALgAABMgQyEmrvTjrzbv/YCiOZGme
+aPoxi6IkMKyoV8Pc7ZsgPF09DhuuBeMhAIckDRgUslzFY/JgOKAezCYOupMmDWATFusoO7eTKThM
+GpObGYR1fXKXOQk6oHAskUMFez4fBYWBgxsHhoWIG4yHjRkGFFaRliUEAASZlxebn50Wn5uhoqCl
+F5ClqqgTA6+vrXuwsa20A7K4ALCyFLqdCQACFZyIPFQSAsOulgMBz8LK0Z3P1crXxZEE1dDKk9Tc
+vduvfL3m5+jp6uuREQAh+QQJAwAAACwAAAAALgAuAAAE/xDISSt4OGttu/dbKGJfWY2oaJZpu62W
+K7/wNd/kiu+PKTcNBmOxUBgVso/L4QAKh8ZEApFApkDLZhCqkCK+VVRnxnQOi97vAWFVUXBlIbE7
+RRzuh3bofWNq5V1qeHkjEzwjC1ODBoRuhygJiwYIhTaPIpEHBpsGehmWl5icBgUHoTyapAUFnqct
+CauxlK43qqumtDMIsQUGubqrBKu/MrAEwgTELgnHzcotCM3HzykH0gXUKAXSvtkhCQPSs94aBQPh
+4a3ZB+ft3XvKCO3tCY6/7PMDuHugocwCANsRUNdDwo5ea+wYGACwIb1KBnEMCECRYsOLAgbUgxhx
+BoCKGDsvEtjo5kSxjxZDCugkZowMARVjNixAkqPJFgrMTQxwrgAbFz68wchWox+tooaOIuUTaqlL
+Hk6DAi0aAQAh+QQJAwAAACwAAAAALgAuAAAE/xDISSt4OGttu/dbKGJfWY2oaJZpu62WK7/wNd/k
+iu+PiTuORoNBlH12QCFxoVAsWqBfcMhgKhJOVIeXpFoT4OfoxA0umWCEWqGdlKdVdEK9Hkt4I8Z1
+rj4g2Co2eCIKdAeHCHaDKIWHjoAviykJjgcGiZI7CIcGnZCZMgqWnQYJoDijnQenNwikBQasMwkF
+tbCyMrS2Bbguura9LQi2BLzBKAfFBASxxyMGy8urziEJ0cuY1BoF1wSf2snX0yGCrAgEA9em5OWg
+BwPw6QPjNDcKA9kb1vHx3nbtWgIEGGDAzyZoAvjBI7CO3R0XCARKFECxIkV+DNu4gSIxgMWP/Toa
+OqQwqaPAjxXhGfjGYcukAiZRDiggMpDLFIUKwLs4848LH9RgOKsBEBTRjUaPksyk9OaOpkB/Eo0A
+ACH5BAkDAAAALAAAAAAuAC4AAAT/EMhJK3g4a22791soYl9Zjaholmm7rZYrv/A13+SK74/JPw5H
+oyH7/IDCBmPZAv2Cw+ViwUB1jsgoY6FQLKwUbFbKTSS+o/AxKCQrzOe0RKxRct8JRFxlo2cYeHl6
+cn4bC2YIiQgKKoUhCooHBwiOM3mSkoyVLZCYBgmbLgiYk6EtCZIGkqYpqAavBqwoCbCvsiO0rwWx
+tyEJBcC7vSEIwcLDGgbGB8gZv8aUzQ8GBAXVBZrICATc3MyNot+i3dzYfC4HAQHiKAfk3oStAOoB
+A6AivwPv5nx9IQcS6KkjoEqPJAIDEurrdi+EGhEKBAgUQLEiRYUYuTV0+NDXAHoWPkNiTFhgI40T
+IxQUABnyIsYD2TjGaFWgZUWFn5o4SQGpQMKLBBe58HELhqwa/hwhnaB0accjTq/8iEp0KNIIACH5
+BAkDAAAALAAAAAAuAC4AAAT/EMhJK3g4a22791soYl9Zjaholmm7rZYrv/A13+SK74/J85/fxkFs
+gYQZYqOR6iA1SoYUdXpilA3pdESxPoiOpXSxYHAl3quYQVYoqLb0I8t2J96quJy9sCcWKnIbDH4I
+CYIyCgkJCI2AiCkLjI0IeJAok5SXKYwHngibKAqepKEjo6QHpiKopasbCQcGs6qvGgiztLYasrm1
+PJY3CQXEBgWHPAMDPAfEzsEyAwABAb8yCM7E1hwjAtTfoDIJBNkF0DkjBd/UAtsiCATx5ATu6KwD
+3wL6BMghw/LyzJ3RoyGBtwD6EhIwcGCRJwIDAMY7NpDgrYMJMyrbGBEgxYoWQzMkGJCxJMeOE89l
+cHLKQEl9JzfSU5kjBqcCJk8upLnySAoF2OIpi2egkgsfpmCEqhHSCtMJcp5WeSKVJZCqLGQ8jQAA
+IfkEBQMAAAAsAAAAAC4ALgAABP8QyEkreDhrbbv3WyhiX1mNqGiWabutliu/8DXf5Irvj8nzn98P
+JNx1iiOHA3VCipTLEcUZgjYaUgm16rhis1uN8soog8OYLpmxYKjQmjV7AXeVFwuFwl1HzfUKdH0o
+eQoJCQqDhIaHCYojC40Ijo8hkQiYCJWWmZibGwqYB6M7BwQHQgmjo5oyCAIBAAEDQgirB60uBwG8
+vLk3CrcHlC4KvbwEPAcGzAYHiTMFxwGoNwjNzL8cIgm9At/aKAkF2AbQNCMGvN/f1SkIBfHy4Tkj
+CgMB7N8ExBsJBvLkmctiI0SCAfq+DTg1LIGtAgQiEhB4joaWEQcTChjAsaPEiAFF+1m8yI1Awo4c
+P4IkMJDgFHsG2KH0+LHAMyZHUoybSTPizRRBWoQyEDElOQQVXeZUBINpjT41XlKJGsMJVSJArvqQ
+QTUCACH5BAkDAAAALAAAAAAuAC4AAATWEMhJq7046827/2AojmRpnmiqrmzrrk/8crE8Y7V9W7mz
+8zWH8EcJOhpI4kR4RDaUSydjCgUcp9gqAMtYLLRTrxfsVZg9hMGAQCgxzOaEJ0Cny0eMhF7vEdQD
+ByQLe3wdA38GJAoIjAh3HAV/JQmNjiECfo8gjACcH36YAiMIB6WBl6GiIAmmpSKpIomtI7ADHga4
+Bq4kqhK2Gqe5uipqAAWdFAYFy8e5xGq/AGxtxswSiSnQxdLTE8zHLNoS09TWCC7Y490S4D/HbMcH
+mlr09fb3+Pk/EQAh+QQJAwAAACwAAAAALgAuAAAE/xDISSt4OGttu/dbKGJfWY2oaJZpu62WK7/w
+Nd/kiu+PyfOf3w8k3HWKQwpSqFwCJU6mLWqcUm/Wq9bpuB0IiKhj3JUVAoDAIPwjjxuzQWAeMAjJ
+jfxMQA+weQ55DQwMM31+QoOEhIZzfH87ioQLewECfAdCDAucnHGWl3Y/DAoLCqczBZeXBEKnrwoz
+B6uXCTwLCbm5lDIKtAKtO7q6vGa/mTcKCMvLtioiCb9rMwoHzMvFHFkZBrQDA8gpCQfk5c4hUCIK
+BALf7gXnG9Xl5QjZ2tsYCe78AwXWuZYZGDiQXiwVE1Ds60egYcMCECESNEDuIMKEIxIQ4OfQYUSJ
+BT4toosxopq7jh4/GkAgkgZJhQZQEvgI8UDLkUdaKDsA8SHFBDdxEtmSAQbRHEa31GjiZOnLIk6H
+VonKQobTCAAh+QQJAwAAACwAAAAALgAuAAAE/xDISSt4OGttu/dbKGJfWY2oaJZpu62WK7/wNd/k
+iu+PyfOf3w8k3HWKQwpSqFwCJU6mLWSIpqChRCBwsKpGhS0ggPC6FNt0wdw6pLdlNiqcHshTg4BA
+EKjeR3x7XFEOM3uHcTwOi4yGhwKJO4wODQ2Oh10/lJWVMwSPfjwNDKSkMwWPBEKlpTMHjwMJPAwL
+tAu1MwqwazsLCre3DDcGAwIDx5kzCwkKzb8jUxoJx9QDkSkKCdraCsIhWFTVAwTJKAoICNvM0NEa
+CgTVBAQFsiLnB+j5CQvs7RkJ8I7Jk1cA3TYEBxImzIeAn4oJKACOG0iwgEUDGBUqRKAAxYkRCUMK
+TKRo8WLGjR37NbF3gOK8kgUwGkDp8Qi2lhVhZuTYIkiLbAcwmjywrieLPz103KnhzwlTiFGefkQi
+1eaTqj5dPI0AACH5BAUDAAAALAAAAAAuAC4AAAT/EMhJK3g4a22791soYl9Zjaholmm7rZYrv/A1
+3+SK74/J85/fDyTcdYpDCgohQKKUooQg0HSGJiPFIBAAVK0cW8jA5XrB4WiZK0CgM+JNgToNHN4t
+xVQwJeBbB3x8AW5/KAWCAn6GKASJBowoiW2RI5MJlSKThZkaA4IDd50ajp8DkD8OqqszBgOvA4s8
+DauqMwiwr5g7Db2+DTNauQU8DMa/N66wBKIzxs/GI3EZCcsEBJwtDAoL3QvRV9MZB7HX19kjCwrr
+3N/S4hgKBeXmBrshCgn6CewKDO/wHiQwR7CAAQT79CFYiHCfP4ABBRK8VqCigYsHMjJsmGDBEygi
+Q+RRrEjyooGMGhd2/HgiywGSME2i1LgSIkiXMA1iRMmvRZA8CQ5cNEhTgQsflWBEqhGxCFMsYJ62
+RCL1SJKqP48yjQAAIfkECQMAAAAsAAAAAC4ALgAABNAQyEmrvTjrzbv/YCiOZGmeaKquVcJ+ShG8
+XTIEOK25OK7oml4OiBH0CMSKUWAMHJIUphRqkTKpSokAW3Rxv+DOYDIGD87nMDqtTiPa4+foQa+P
+CqS6HUToz/V7HEh9SCIODoAhhABvH4ePh4p+El4cDZcNkCKFEngcDKAMmIgjnAUFchcMCwuhoA2B
+H3izpwYHLgq5CgkJuayhsCWnwwUGxgfICAi8vQqsrSgGxMa2ycrMvgw01MjWzAnQOsfdysvOSQjd
+B9fnYe7v8PHy8zQRACH5BAkDAAAALAAAAAAuAC4AAAT/EMhJK3g4a22791soYl9Zjaholmm7rZYr
+v/A13+SK74/pKogDL/NpJQqBgG3Y66AUhqSUmTuNEgNpEmCgNicobFKgJXi/yw1WwCYnB4UzWKQg
+tNkBQuJMTGsMd2xCfH0iCYECCIQcI4B3g4spCgN3ZpEtCJRte5cpBQOgA5adKAShA5CkIqcDiqoj
+rJyvIayusxumoq23IQUEvwSpvA8GwARxwxkIxnrJGHXGXc4PB8AFBbaXfs++19eyLQ4zEiPV3gUG
+2SMO7DLkdAbnBgYHCiMN+OziLXMhR97z6CFIoGCBQQYLGDDIpw8FhTDx0M07QHEgwYIKFzJ0+HAE
+FIn0Qw4gGJngYkKF+ThaoYNgIkWRFgkeRKlypccgL0mWlKmQH4gWChKMHFqyoDsWs2C8qrGND9N+
+cp529CLVyZCqPo7WiAAAOw==</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>7825</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/animated-overlay.gif.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/animated-overlay.gif.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5b2ac1c32f9e27f200c12915b12451983182739a
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/animated-overlay.gif.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681767.14</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>animated-overlay.gif</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/gif</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAAC
+kYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFG
+iU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gn
+WGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnG
+faqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6
+vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5
+mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22Z
+nINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQW
+tRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4
+N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/i
+O7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4Z
+zWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiI
+mVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58bi
+Q3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61
+Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBno
+BwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvn
+xuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmN
+YrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU
+5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNK
+ToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo
+1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmH
+uanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOx
+TVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp
+1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiX
+mMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJD
+kU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRC
+avZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTE
+eGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kOR
+TVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCo
+sArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjY
+JvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1738</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_flat_0_aaaaaa_40x100.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_flat_0_aaaaaa_40x100.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..f94d5177138635217b3c6e3037259e0ef94e2302
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_flat_0_aaaaaa_40x100.png.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681767.26</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-bg_flat_0_aaaaaa_40x100.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAACgAAABkCAYAAAD0ZHJ6AAAAe0lEQVRoge3OMQHAIBAAMcC/kjdZ
+JHTI0A4XBdkz86wfO18H3hRUBVVBVVAVVAVVQVVQFVQFVUFVUBVUBVVBVVAVVAVVQVVQFVQFVUFV
+UBVUBVVBVVAVVAVVQVVQFVQFVUFVUBVUBVVBVVAVVAVVQVVQFVQFVUFVUBVUF8O8A8WdY6opAAAA
+AElFTkSuQmCC</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>180</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_flat_75_ffffff_40x100.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_flat_75_ffffff_40x100.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9d2c2765c49a6656f64382229c6fdee4f7c772ed
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_flat_75_ffffff_40x100.png.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681767.47</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-bg_flat_75_ffffff_40x100.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAACgAAABkCAYAAAD0ZHJ6AAAAeUlEQVRoge3OMQHAIBAAsVL/nh8J
+DDfAkCjImpn5HvbfDpwIVoKVYCVYCVaClWAlWAlWgpVgJVgJVoKVYCVYCVaClWAlWAlWgpVgJVgJ
+VoKVYCVYCVaClWAlWAlWgpVgJVgJVoKVYCVYCVaClWAlWAlWgpVgJVgJVhtqiwTEKTLXTgAAAABJ
+RU5ErkJggg==</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>178</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_55_fbf9ee_1x400.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_55_fbf9ee_1x400.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..199264066bd87cb21d5fad71206d5faa755db156
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_55_fbf9ee_1x400.png.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681767.6</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-bg_glass_55_fbf9ee_1x400.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAAEAAAGQCAYAAABvWArbAAAAP0lEQVQ4je3PMQrAMABC0a/3v2zX
+0mCXNkOgc6C4PARd5DqPGKCU8luS8SbAQhiCQRgJE56kZTfbbP9RSvnkBsWcEAZRWcgqAAAAAElF
+TkSuQmCC</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>120</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_65_ffffff_1x400.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_65_ffffff_1x400.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..64673ab86c56c290191566fd5f11fc87bf0dcac0
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_65_ffffff_1x400.png.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681767.69</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-bg_glass_65_ffffff_1x400.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAAEAAAGQCAYAAABvWArbAAAAMElEQVQ4je3LIQ4AIBTD0O3f/8wr
+FgmKhMy8pKJKwkhSKeVbbGuAPU9f4PIopTxgAeS0DRtI4yK0AAAAAElFTkSuQmCC</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>105</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_75_dadada_1x400.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_75_dadada_1x400.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a857c806e3776bc23d37be669f2745f67359794
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_75_dadada_1x400.png.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681767.8</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-bg_glass_75_dadada_1x400.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAAEAAAGQCAYAAABvWArbAAAANklEQVQ4jWN48uTJfyYGBgaGUWKU
+GCWGLfHt2zcoi5GREYNgYmJCZiG42IiB98woMUqMEtgIAMdjCdyg+eEBAAAAAElFTkSuQmCC</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>111</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_75_e6e6e6_1x400.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_75_e6e6e6_1x400.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..8b6d125a95041295dabdc170e2271af491554954
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_75_e6e6e6_1x400.png.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681767.94</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-bg_glass_75_e6e6e6_1x400.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAAEAAAGQCAYAAABvWArbAAAANUlEQVQ4je3LMQoAIBADwb38/6t5
+wFXaWAiCtUiaYZvF9hBACOFbuntVVe11B0CSjjeE8BwThQIJ8dhEl0YAAAAASUVORK5CYII=</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>110</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_95_fef1ec_1x400.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_95_fef1ec_1x400.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4ce08418d23a8174c80f104442906381a047c653
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_glass_95_fef1ec_1x400.png.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681768.09</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-bg_glass_95_fef1ec_1x400.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAAEAAAGQCAYAAABvWArbAAAAPklEQVQ4je3PMQqAMABD0Z/c/7aC
+IAXjJIhD10LJ8vgZw30eMUApZV/GhZNgSTjoLYElY/hNMJ/S6gullCkPiCIPCr4NiEwAAAAASUVO
+RK5CYII=</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>119</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_highlight-soft_75_cccccc_1x100.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_highlight-soft_75_cccccc_1x100.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..db0e001656a90baec460c897c4582bc8315cef10
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-bg_highlight-soft_75_cccccc_1x100.png.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681768.2</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-bg_highlight-soft_75_cccccc_1x100.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAAEAAABkCAYAAABHLFpgAAAALElEQVQYlWN49OjRfyYGBgaGIUT8
+//8fSqBx0Yh///4RL8vAwAAVQ2MNOwIAl6g6KkOJwk8AAAAASUVORK5CYII=</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>101</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_222222_256x240.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_222222_256x240.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9e4dccd9cc85ff623299c5c9ee58bfa00bb47bb3
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_222222_256x240.png.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681768.3</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-icons_222222_256x240.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEUiIiIiIiIiIiIiIiIiIiIi
+IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi
+IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi
+IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIi
+IiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiJdmhHzAAAA
+TnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWN
+qa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAPhUlEQVR4nO1djWLbthEGyUiq5YSSLXtp
+7FpLOmfzkmxr126tmi2p03RJ1/Xe/3EGgARxPyAgRbIk2/hkSz4CJO4+HsE7AJSVysjI2AMUUOxa
+hZ2iANhzBtZWr4BoIRSYAVN5u4QwDwQDRbcwfUi5KS3wFuDmFnQLa4Dtb//cqktwD5QEFFwfUs7P
+oCCA7y4bEJVFizcIob8KmhAplwwqVjt+9FBl3uINQniwEiryEyw9JHqGpQdEFNi+B4QQ7QOiHhys
+IPoAxUqxvdvvA9K42bsAv4S2fxfYOe57IJSRkZGRkZGxx7jxSHDHcRBXQMTyIjInBgHwBJ/bEx8P
+EANC+uhbpSSggCBAVODVabpI1S/k4WLZpTn6NpMhoX9Y40hxYERFpMcqUs4AloCtDQdID1YhnyXZ
+2hLjAYWiO9Dy1PDB7tPhIqLx+uMB8grZaR+Qxl2/C2RkZGRkZGRk7A7rBf7J0DR5/LUTjzUPIPSP
+GvQJiVJiB7kcQCiUOJrcFNtDZIf2xarQ3aGvLNxAVIFAabz90BFiBIlycTBhgWwOWCH0FLYHlPqw
+HaCvcIn2ZbosCevfPTRiFFcgvHukCjWwrc3GrGh1fsAof8EaUReKXkCB4/MzFNo97qLpFiKFYv/k
+NR5YQxQbQEofkZ2OuEOHqqT6gFTpru8CN7x/+jaZkZGRkZGRcV+x/rLUNcMMqUAscgnFocmpqkTz
+qymwVAPxfJ5PnIUUQOUKT04tEdWZyv3JCQSn96WS4pD97QfyW25A7NhSAbyhmVj0FEltA4vdiygB
+ibXhoUYgykCUP7HwPTDeEqAIcHVMkZg7Zx4k0uFANs63hPQXCoRLAwdgGsr9Az7Qv7sgQGgg1aPl
+/BJLExBWgG4RFRLFImGmIquPC/klEGyCG0AuAXaJJC+B8FVe9NYQDEcXB8g6AQcjYJ1goJIggHWC
+rFR0S6kRHN5+4BzFi8NaoN35NRxUvL+JJdZr7PV4wK6fj8nIyMjIyNhr3OxdXAYq7FHZwB6bDSzS
+h4sF0utChqo0NAvaT1hLzXwFinmCzmeDucEQK18TTaQoFgP7bNC+RZ4OT4T6gQogDFYk+1QxQlj1
+9QGSAWKiLYp8P0Ag1Gbz1ULfWHLg9iUnQNK5QQJcukm04blKLH2GgEJCY+HzXAZWCvHKco3Bp6MI
+aCjSXXRJyOxeqhnzEaF93MfFGW/O16ZvDL5TM4MJIjujz/cHypkQuuzRwWJ93BKdIt+wCRAPl9kp
+e2Ikkb2mFgGlxh/i40d3EHfdvoyMjIyMu43ylt/IAmGHnN5iIt7wKfbv01RAcJqFRl9lcjYQSnbQ
+qKgC4fYOwSJt6N6trE0twZ9kN/PqNpTQeICvr4TLsDYC06U7BMjshS+v1/aT7IwQYD5LcgRQXMT2
+FrBfBLjZ6151jDElk9tPFfpUgk2yregusX25BJbwAFEfM+YI6vGAti4bTtizB+TjfQCrERyhKb2X
+8D6A9wX75P4t4neBYJeP6pdhg/gQl8MWvytzeSTjgOQBynQdh/iXKdxOrGJ/RkZGRsb9QmXihGr5
++g8GGg9uTh+KoVZuNIzV+CwRucFBEyr1mVjx4irOxwM1BhirB6Q+2eNQi4eqR+aF6mELtoMzCR7V
+9RAFe/ZvQogNiyY8FPSUTFsLp8TeTmMui5mtw7bcaT0Yw2AA4wFRQIlkgq+1DQrNhkmoxS5Jq+u6
+bMAIGRECEANgXHTgWzwgBOhDH2l0oTQ4D8D5NMktBgNywAEMjo8rwATMZrPY7JGxBoJCkIBDQiAY
+09EGTUiBCWkUpISfGPR5AAwBfZiG2z7Ayc1yeKTxid39xBNwfHr4O0LA48ePFTvhYrF1r4tyAoz9
+n2MCqEuBtp/6GDR0oAYfG/R6wJExHYZHfhygsv7fEWCOj4bYmsP5A+pL4MkTfAnMlD4F+r3bobKv
+TyTA2P/w7PN+Agq2QW8piqMCpTBwenoKvX0AHGkGtP2YAPvTEWA7QUTAudn7/NxtOG46wWNmDtpB
+EkBzN7rBEvAFHp+YTB/q97qPAN4gHFqgBi8uLsC7qPCA6mg41G/+ErByPwEXDdoNxRhOx+M5jPEz
+QugS0ht+b1/Y3gEnYMAIAOIBE29/hIDucE8tmMsNOgK4B1RHFu4UCRlMHzv0xzcajcfdXWDs2h8T
+ArBCkoDUJYDLmz6w7ip3BFS0ve5wTRwAn6keMA9I3QYbfSZ0DKbyt+7OXjGI1idPcfNyAyfAMlCr
+zaGqphYrxHocLHRJVycnfGUcbtT+jIyMjIw9x7Nn8fJSzG0TmFtO8rZT+XT3S3ub+tKJbbLd5diT
+Vp50+zahyeHSslJ/YPrU0fuazrZO2CZ92/ZCCVXlGRiZKPJyPPRxyIFWeXLQBXJBKiq/3divEAN6
+ZwM200Qjm7EJBZeWm/PRWVCbYK7s7u2l4XaCz+lzgOfMfhMonXr7TWzeZb98dbgIzBT8Ub8eYYUq
+fZ4rVJ/MDbIDgPqTulJ/xvntWAtjIisqnwxOkGz0n077FARoY79GdA6HPE4rOy196NiMWHTZlSSA
+pcOgXpy/fHV2joaNKu3ffsAnRcBf4K/6NcIG6tIxk3HyoXPjASqfUgXbYN5PzpL2njkR9QMjeDTV
+HDTCgRuxOegjoO0FvKzP/t/gmVdI24+G7NIe8JX6Wv3dDyldMA+4YB5wwTygtd+dwRqaTqrLb1l7
+3zTSN52CNpnHuQOYPsDblybgxfkXh/oVtr+N1DEBJdhRJyd/Bd/q1z+cbNrD17iVKyajcnv9arhO
+kRPgsruuD6DmNPwpDNrLw2CoTgHni4yALr0L29+tiKAEIPn868ejx//8rpWP3OEOl5On9OwpcQm0
+MhafP/ey8f1uvDNIgGLQG8z4YO99ENgg95etwv4uYJYY8fUGHYH6j6fscHFZMftlAl9i+9XL73X3
+N/n+ZStOzfVfRvYXhrbdKOpEgVQTg/wsDuDD3kwOfQNMTJ5y+/ltUDWLunyxnRF46IqlBzGMY4X7
+inggREFioIyMjIyMHWCIB6ZNKAcXseo3vLTQTkVE7348dlwJJSz0+wLfmi8BhZqfw3D4ww/wHVLn
+Ed5/fgYvXsDZ3MlsvYUbbnDjDZ3MN3TJG4+bxjAaDl8TBri9qxEw1ccao2wTNAMLHo2f+sjrXwb/
+9qHoYqgPMBXJTVfOpmrZH23y6uvo0LHSyY6fHGwKfHJlAuMFvObjDYrIqxBgQi20h7Hd/nYVLmno
++eaNUm/eeH2GCuopntnhBJAlI2AHo9CCh1I1QxUdAbqqGY9BBLwyc3W4wYVhvY8A4BoIc1l5M7vn
+PWphZW9/Ses3n37y9a0uGqFwFQZsQQbd386DogpgEk+dzynsAZMJXq8+ns9NeukJ0PYrNATGGefJ
+QlhkLo7DTXr+y3bNiOsDvrXTz/C2q1DXZH84iRNwrP88Nj+u2DjYEE6RBxD9Knj16ujVHC67A742
+2o02RwD3gB+t7EblWvu9geOFxSnd3ROmT+nJyQkhoPlsxVONc/3TEdBos+jtA+ZzcwHgTvD1cDja
+YCcItA8w9i88A8b+mqSjc6Pvqd998QguEQPmQMeo23ODN86+p0/bn1buBkT6+oBhNZ/PYY4ZAHYb
+3PRd4LkZmPX68NRtMZn4ASvdA+qf0jMA5MP9eeg28Nug9QiLnj5A33U1MAES6xHAUNpz/9zFAYE1
+gqQDMT3G6xI9pwdw/aIgKoHCS1YGlRnSq9yCjdXjgN3j+N27YyROHxmuNAeNKPpYuXIyIyMjYy0M
+8eros59MF/PT2c602T7eA7zvhJ9dr/vzDjXaLp4Yc5+0wllzxzHv3gdmMMM7/CcQzKgVBqYTmFn+
+Z+mKm8J7k0A5F/jgCfjQ1WBhQyiOqD0lYuqBb+AyzMw9Ha2G3m6c8qQx+AlqnIceQp+Sb6i9UyQW
+bhr54+AjnZ0VzW2TAN0DmBT6PWmc6jDBE2PK2u+nF43dyP7Q0t1pOcX2fdRvH0mF2Q4JqN35rnHj
+VIeaXfIAVyUuw/aHCCiJy9iF5l1621zweI8KZrPZ9iJdb7DXJ3US0OSrtZ10imt7wHY7QesAzUMz
+1oZ3noB3qFJ/H18j97FYuw8QDN4oeKf30osvcSW2ExLo+VcbuAuo/sUIm8fMG9xocO3Ea19J9gFY
+ivnHJ2KnyfovZlgW3v6ySx32abQiIyMjIyPjhlFDTLxpwIgFMnTp6A3g4IDKNY+stkwAMAoIAbas
+xBXqUWneSAWTMjt50lTqT29rFjvXohjsDNm2YPXDFlICmrJOZ3t6tHm8AiEAl0sCeLIIorIRt+cF
+bew/QRsoAXb4o1XSfoywzm0FTMAoYBNvLyFu8v8HpLBtD1iKgC17wHb7AI6d9wFbvguAIGTHd4E9
+wG7jgIyMjIyM+434c2R3HeV/Ffx6jtZu6ijl8h59T655jhR+rdHzDOP6beABCheb8O8/WFXeOyzg
+f5oAhVYnKxP7CwaAf1afJu8bSrhS6tdaXeGnrRenOqOlz9d6QwYnA/3TLd+GE7qe3chA5YF5DfY0
+vK3adfOX/gyNp2BW25MHdxAB9qvRiiP3/XpQQFGYDU4+Mi///XumXG8pjvaUAOsBGlf4jJt+YYEz
+eEzAdw06F19R3juM7D1wita86GR0CKfDHgLuXCc4Bri6vMLdfjMc4VNSUNsdodo2xu/1+Xl/K5+a
+z8jIyMhYG/z5gJTMF1GtKq/a3rpyCvz5gJTMl9GtKq/a3rpyCmfQ4WwZmS+kXFVetb115ST48wEf
+/AGcfG1iw+tWbpbS2vJ3nQxcVr3lH3z5h972FUTLzYpOVk7l5hD+eYcYwDcAnewOotrZ4OtrPDuc
+qi/LRX0/RR4qx7Nn4U8g+qjffvuN6Gf+nC85vwauHjaYyubqvWYKY4VEfSUMitdnBCT1Ue63R543
+9m+OgCn6DroAAaHPVQxKth/wkJgHmG8bmQMsT0D6EjDfvhVRKO3ywOQUgRA7nmL1uawZmHf1k+DP
+BwQ6NdcJ+k6Md1LA5f5ONdhJ8vZ5J0vLHT99srkGOjmJbd/G1r2Nriqnse1AZt1AalU5jW2HsuuG
+0qvKGRkZGRkZGRG0gcONyXsP9v8D0/IdJADiBNiXl3327WRGgOL/9HC/0XwlIURkRhC4tz6Z/fu7
+fUf2gHvfB9z3u0BGRkZGRkbGplHcnkgguQoSqtUXuhbs/wPtMwqV0HUJAvj5vk32b8IDuL23yn7q
+AXZ5u32hbRX7d3o82Df1FZXvbh9QOfhyxldr/+3xgXU9oKmvsHyr7F/XA269/eveBXrsv7N9QALe
+/tvjA0kPWAXGbvebkbHn+D/J5nMcHzx1UAAAAABJRU5ErkJggg==</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>4369</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_2e83ff_256x240.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_2e83ff_256x240.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ca6b63ec97e7b18c56cadd5a1ea09c8cb7535e31
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_2e83ff_256x240.png.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681768.41</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-icons_2e83ff_256x240.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEUug/8ug/8ug/8ug/8ug/8u
+g/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8u
+g/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8u
+g/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8u
+g/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8ug/8lgcyYAAAA
+TnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWN
+qa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAPhUlEQVR4nO1djWLbthEGyUiq5YSSLXtp
+7FpLOmfzkmxr126tmi2p03RJ1/Xe/3EGgARxPyAgRbIk2/hkSz4CJO4+HsE7AJSVysjI2AMUUOxa
+hZ2iANhzBtZWr4BoIRSYAVN5u4QwDwQDRbcwfUi5KS3wFuDmFnQLa4Dtb//cqktwD5QEFFwfUs7P
+oCCA7y4bEJVFizcIob8KmhAplwwqVjt+9FBl3uINQniwEiryEyw9JHqGpQdEFNi+B4QQ7QOiHhys
+IPoAxUqxvdvvA9K42bsAv4S2fxfYOe57IJSRkZGRkZGxx7jxSHDHcRBXQMTyIjInBgHwBJ/bEx8P
+EANC+uhbpSSggCBAVODVabpI1S/k4WLZpTn6NpMhoX9Y40hxYERFpMcqUs4AloCtDQdID1YhnyXZ
+2hLjAYWiO9Dy1PDB7tPhIqLx+uMB8grZaR+Qxl2/C2RkZGRkZGRk7A7rBf7J0DR5/LUTjzUPIPSP
+GvQJiVJiB7kcQCiUOJrcFNtDZIf2xarQ3aGvLNxAVIFAabz90BFiBIlycTBhgWwOWCH0FLYHlPqw
+HaCvcIn2ZbosCevfPTRiFFcgvHukCjWwrc3GrGh1fsAof8EaUReKXkCB4/MzFNo97qLpFiKFYv/k
+NR5YQxQbQEofkZ2OuEOHqqT6gFTpru8CN7x/+jaZkZGRkZGRcV+x/rLUNcMMqUAscgnFocmpqkTz
+qymwVAPxfJ5PnIUUQOUKT04tEdWZyv3JCQSn96WS4pD97QfyW25A7NhSAbyhmVj0FEltA4vdiygB
+ibXhoUYgykCUP7HwPTDeEqAIcHVMkZg7Zx4k0uFANs63hPQXCoRLAwdgGsr9Az7Qv7sgQGgg1aPl
+/BJLExBWgG4RFRLFImGmIquPC/klEGyCG0AuAXaJJC+B8FVe9NYQDEcXB8g6AQcjYJ1goJIggHWC
+rFR0S6kRHN5+4BzFi8NaoN35NRxUvL+JJdZr7PV4wK6fj8nIyMjIyNhr3OxdXAYq7FHZwB6bDSzS
+h4sF0utChqo0NAvaT1hLzXwFinmCzmeDucEQK18TTaQoFgP7bNC+RZ4OT4T6gQogDFYk+1QxQlj1
+9QGSAWKiLYp8P0Ag1Gbz1ULfWHLg9iUnQNK5QQJcukm04blKLH2GgEJCY+HzXAZWCvHKco3Bp6MI
+aCjSXXRJyOxeqhnzEaF93MfFGW/O16ZvDL5TM4MJIjujz/cHypkQuuzRwWJ93BKdIt+wCRAPl9kp
+e2Ikkb2mFgGlxh/i40d3EHfdvoyMjIyMu43ylt/IAmGHnN5iIt7wKfbv01RAcJqFRl9lcjYQSnbQ
+qKgC4fYOwSJt6N6trE0twZ9kN/PqNpTQeICvr4TLsDYC06U7BMjshS+v1/aT7IwQYD5LcgRQXMT2
+FrBfBLjZ6151jDElk9tPFfpUgk2yregusX25BJbwAFEfM+YI6vGAti4bTtizB+TjfQCrERyhKb2X
+8D6A9wX75P4t4neBYJeP6pdhg/gQl8MWvytzeSTjgOQBynQdh/iXKdxOrGJ/RkZGRsb9QmXihGr5
++g8GGg9uTh+KoVZuNIzV+CwRucFBEyr1mVjx4irOxwM1BhirB6Q+2eNQi4eqR+aF6mELtoMzCR7V
+9RAFe/ZvQogNiyY8FPSUTFsLp8TeTmMui5mtw7bcaT0Yw2AA4wFRQIlkgq+1DQrNhkmoxS5Jq+u6
+bMAIGRECEANgXHTgWzwgBOhDH2l0oTQ4D8D5NMktBgNywAEMjo8rwATMZrPY7JGxBoJCkIBDQiAY
+09EGTUiBCWkUpISfGPR5AAwBfZiG2z7Ayc1yeKTxid39xBNwfHr4O0LA48ePFTvhYrF1r4tyAoz9
+n2MCqEuBtp/6GDR0oAYfG/R6wJExHYZHfhygsv7fEWCOj4bYmsP5A+pL4MkTfAnMlD4F+r3bobKv
+TyTA2P/w7PN+Agq2QW8piqMCpTBwenoKvX0AHGkGtP2YAPvTEWA7QUTAudn7/NxtOG46wWNmDtpB
+EkBzN7rBEvAFHp+YTB/q97qPAN4gHFqgBi8uLsC7qPCA6mg41G/+ErByPwEXDdoNxRhOx+M5jPEz
+QugS0ht+b1/Y3gEnYMAIAOIBE29/hIDucE8tmMsNOgK4B1RHFu4UCRlMHzv0xzcajcfdXWDs2h8T
+ArBCkoDUJYDLmz6w7ip3BFS0ve5wTRwAn6keMA9I3QYbfSZ0DKbyt+7OXjGI1idPcfNyAyfAMlCr
+zaGqphYrxHocLHRJVycnfGUcbtT+jIyMjIw9x7Nn8fJSzG0TmFtO8rZT+XT3S3ub+tKJbbLd5diT
+Vp50+zahyeHSslJ/YPrU0fuazrZO2CZ92/ZCCVXlGRiZKPJyPPRxyIFWeXLQBXJBKiq/3divEAN6
+ZwM200Qjm7EJBZeWm/PRWVCbYK7s7u2l4XaCz+lzgOfMfhMonXr7TWzeZb98dbgIzBT8Ub8eYYUq
+fZ4rVJ/MDbIDgPqTulJ/xvntWAtjIisqnwxOkGz0n077FARoY79GdA6HPE4rOy196NiMWHTZlSSA
+pcOgXpy/fHV2joaNKu3ffsAnRcBf4K/6NcIG6tIxk3HyoXPjASqfUgXbYN5PzpL2njkR9QMjeDTV
+HDTCgRuxOegjoO0FvKzP/t/gmVdI24+G7NIe8JX6Wv3dDyldMA+4YB5wwTygtd+dwRqaTqrLb1l7
+3zTSN52CNpnHuQOYPsDblybgxfkXh/oVtr+N1DEBJdhRJyd/Bd/q1z+cbNrD17iVKyajcnv9arhO
+kRPgsruuD6DmNPwpDNrLw2CoTgHni4yALr0L29+tiKAEIPn868ejx//8rpWP3OEOl5On9OwpcQm0
+MhafP/ey8f1uvDNIgGLQG8z4YO99ENgg95etwv4uYJYY8fUGHYH6j6fscHFZMftlAl9i+9XL73X3
+N/n+ZStOzfVfRvYXhrbdKOpEgVQTg/wsDuDD3kwOfQNMTJ5y+/ltUDWLunyxnRF46IqlBzGMY4X7
+inggREFioIyMjIyMHWCIB6ZNKAcXseo3vLTQTkVE7348dlwJJSz0+wLfmi8BhZqfw3D4ww/wHVLn
+Ed5/fgYvXsDZ3MlsvYUbbnDjDZ3MN3TJG4+bxjAaDl8TBri9qxEw1ccao2wTNAMLHo2f+sjrXwb/
+9qHoYqgPMBXJTVfOpmrZH23y6uvo0LHSyY6fHGwKfHJlAuMFvObjDYrIqxBgQi20h7Hd/nYVLmno
++eaNUm/eeH2GCuopntnhBJAlI2AHo9CCh1I1QxUdAbqqGY9BBLwyc3W4wYVhvY8A4BoIc1l5M7vn
+PWphZW9/Ses3n37y9a0uGqFwFQZsQQbd386DogpgEk+dzynsAZMJXq8+ns9NeukJ0PYrNATGGefJ
+QlhkLo7DTXr+y3bNiOsDvrXTz/C2q1DXZH84iRNwrP88Nj+u2DjYEE6RBxD9Knj16ujVHC67A742
+2o02RwD3gB+t7EblWvu9geOFxSnd3ROmT+nJyQkhoPlsxVONc/3TEdBos+jtA+ZzcwHgTvD1cDja
+YCcItA8w9i88A8b+mqSjc6Pvqd998QguEQPmQMeo23ODN86+p0/bn1buBkT6+oBhNZ/PYY4ZAHYb
+3PRd4LkZmPX68NRtMZn4ASvdA+qf0jMA5MP9eeg28Nug9QiLnj5A33U1MAES6xHAUNpz/9zFAYE1
+gqQDMT3G6xI9pwdw/aIgKoHCS1YGlRnSq9yCjdXjgN3j+N27YyROHxmuNAeNKPpYuXIyIyMjYy0M
+8eros59MF/PT2c602T7eA7zvhJ9dr/vzDjXaLp4Yc5+0wllzxzHv3gdmMMM7/CcQzKgVBqYTmFn+
+Z+mKm8J7k0A5F/jgCfjQ1WBhQyiOqD0lYuqBb+AyzMw9Ha2G3m6c8qQx+AlqnIceQp+Sb6i9UyQW
+bhr54+AjnZ0VzW2TAN0DmBT6PWmc6jDBE2PK2u+nF43dyP7Q0t1pOcX2fdRvH0mF2Q4JqN35rnHj
+VIeaXfIAVyUuw/aHCCiJy9iF5l1621zweI8KZrPZ9iJdb7DXJ3US0OSrtZ10imt7wHY7QesAzUMz
+1oZ3noB3qFJ/H18j97FYuw8QDN4oeKf30osvcSW2ExLo+VcbuAuo/sUIm8fMG9xocO3Ea19J9gFY
+ivnHJ2KnyfovZlgW3v6ySx32abQiIyMjIyPjhlFDTLxpwIgFMnTp6A3g4IDKNY+stkwAMAoIAbas
+xBXqUWneSAWTMjt50lTqT29rFjvXohjsDNm2YPXDFlICmrJOZ3t6tHm8AiEAl0sCeLIIorIRt+cF
+bew/QRsoAXb4o1XSfoywzm0FTMAoYBNvLyFu8v8HpLBtD1iKgC17wHb7AI6d9wFbvguAIGTHd4E9
+wG7jgIyMjIyM+434c2R3HeV/Ffx6jtZu6ijl8h59T655jhR+rdHzDOP6beABCheb8O8/WFXeOyzg
+f5oAhVYnKxP7CwaAf1afJu8bSrhS6tdaXeGnrRenOqOlz9d6QwYnA/3TLd+GE7qe3chA5YF5DfY0
+vK3adfOX/gyNp2BW25MHdxAB9qvRiiP3/XpQQFGYDU4+Mi///XumXG8pjvaUAOsBGlf4jJt+YYEz
+eEzAdw06F19R3juM7D1wita86GR0CKfDHgLuXCc4Bri6vMLdfjMc4VNSUNsdodo2xu/1+Xl/K5+a
+z8jIyMhYG/z5gJTMF1GtKq/a3rpyCvz5gJTMl9GtKq/a3rpyCmfQ4WwZmS+kXFVetb115ST48wEf
+/AGcfG1iw+tWbpbS2vJ3nQxcVr3lH3z5h972FUTLzYpOVk7l5hD+eYcYwDcAnewOotrZ4OtrPDuc
+qi/LRX0/RR4qx7Nn4U8g+qjffvuN6Gf+nC85vwauHjaYyubqvWYKY4VEfSUMitdnBCT1Ue63R543
+9m+OgCn6DroAAaHPVQxKth/wkJgHmG8bmQMsT0D6EjDfvhVRKO3ywOQUgRA7nmL1uawZmHf1k+DP
+BwQ6NdcJ+k6Md1LA5f5ONdhJ8vZ5J0vLHT99srkGOjmJbd/G1r2Nriqnse1AZt1AalU5jW2HsuuG
+0qvKGRkZGRkZGRG0gcONyXsP9v8D0/IdJADiBNiXl3327WRGgOL/9HC/0XwlIURkRhC4tz6Z/fu7
+fUf2gHvfB9z3u0BGRkZGRkbGplHcnkgguQoSqtUXuhbs/wPtMwqV0HUJAvj5vk32b8IDuL23yn7q
+AXZ5u32hbRX7d3o82Df1FZXvbh9QOfhyxldr/+3xgXU9oKmvsHyr7F/XA269/eveBXrsv7N9QALe
+/tvjA0kPWAXGbvebkbHn+D/J5nMcHzx1UAAAAABJRU5ErkJggg==</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>4369</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_454545_256x240.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_454545_256x240.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..86813ef646c27c95992037c8457b7b3207006999
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_454545_256x240.png.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681768.5</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-icons_454545_256x240.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEVFRUVFRUVFRUVFRUVFRUVF
+RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVF
+RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVF
+RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVF
+RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUWG2rLCAAAA
+TnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWN
+qa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAPhUlEQVR4nO1djWLbthEGyUiq5YSSLXtp
+7FpLOmfzkmxr126tmi2p03RJ1/Xe/3EGgARxPyAgRbIk2/hkSz4CJO4+HsE7AJSVysjI2AMUUOxa
+hZ2iANhzBtZWr4BoIRSYAVN5u4QwDwQDRbcwfUi5KS3wFuDmFnQLa4Dtb//cqktwD5QEFFwfUs7P
+oCCA7y4bEJVFizcIob8KmhAplwwqVjt+9FBl3uINQniwEiryEyw9JHqGpQdEFNi+B4QQ7QOiHhys
+IPoAxUqxvdvvA9K42bsAv4S2fxfYOe57IJSRkZGRkZGxx7jxSHDHcRBXQMTyIjInBgHwBJ/bEx8P
+EANC+uhbpSSggCBAVODVabpI1S/k4WLZpTn6NpMhoX9Y40hxYERFpMcqUs4AloCtDQdID1YhnyXZ
+2hLjAYWiO9Dy1PDB7tPhIqLx+uMB8grZaR+Qxl2/C2RkZGRkZGRk7A7rBf7J0DR5/LUTjzUPIPSP
+GvQJiVJiB7kcQCiUOJrcFNtDZIf2xarQ3aGvLNxAVIFAabz90BFiBIlycTBhgWwOWCH0FLYHlPqw
+HaCvcIn2ZbosCevfPTRiFFcgvHukCjWwrc3GrGh1fsAof8EaUReKXkCB4/MzFNo97qLpFiKFYv/k
+NR5YQxQbQEofkZ2OuEOHqqT6gFTpru8CN7x/+jaZkZGRkZGRcV+x/rLUNcMMqUAscgnFocmpqkTz
+qymwVAPxfJ5PnIUUQOUKT04tEdWZyv3JCQSn96WS4pD97QfyW25A7NhSAbyhmVj0FEltA4vdiygB
+ibXhoUYgykCUP7HwPTDeEqAIcHVMkZg7Zx4k0uFANs63hPQXCoRLAwdgGsr9Az7Qv7sgQGgg1aPl
+/BJLExBWgG4RFRLFImGmIquPC/klEGyCG0AuAXaJJC+B8FVe9NYQDEcXB8g6AQcjYJ1goJIggHWC
+rFR0S6kRHN5+4BzFi8NaoN35NRxUvL+JJdZr7PV4wK6fj8nIyMjIyNhr3OxdXAYq7FHZwB6bDSzS
+h4sF0utChqo0NAvaT1hLzXwFinmCzmeDucEQK18TTaQoFgP7bNC+RZ4OT4T6gQogDFYk+1QxQlj1
+9QGSAWKiLYp8P0Ag1Gbz1ULfWHLg9iUnQNK5QQJcukm04blKLH2GgEJCY+HzXAZWCvHKco3Bp6MI
+aCjSXXRJyOxeqhnzEaF93MfFGW/O16ZvDL5TM4MJIjujz/cHypkQuuzRwWJ93BKdIt+wCRAPl9kp
+e2Ikkb2mFgGlxh/i40d3EHfdvoyMjIyMu43ylt/IAmGHnN5iIt7wKfbv01RAcJqFRl9lcjYQSnbQ
+qKgC4fYOwSJt6N6trE0twZ9kN/PqNpTQeICvr4TLsDYC06U7BMjshS+v1/aT7IwQYD5LcgRQXMT2
+FrBfBLjZ6151jDElk9tPFfpUgk2yregusX25BJbwAFEfM+YI6vGAti4bTtizB+TjfQCrERyhKb2X
+8D6A9wX75P4t4neBYJeP6pdhg/gQl8MWvytzeSTjgOQBynQdh/iXKdxOrGJ/RkZGRsb9QmXihGr5
++g8GGg9uTh+KoVZuNIzV+CwRucFBEyr1mVjx4irOxwM1BhirB6Q+2eNQi4eqR+aF6mELtoMzCR7V
+9RAFe/ZvQogNiyY8FPSUTFsLp8TeTmMui5mtw7bcaT0Yw2AA4wFRQIlkgq+1DQrNhkmoxS5Jq+u6
+bMAIGRECEANgXHTgWzwgBOhDH2l0oTQ4D8D5NMktBgNywAEMjo8rwATMZrPY7JGxBoJCkIBDQiAY
+09EGTUiBCWkUpISfGPR5AAwBfZiG2z7Ayc1yeKTxid39xBNwfHr4O0LA48ePFTvhYrF1r4tyAoz9
+n2MCqEuBtp/6GDR0oAYfG/R6wJExHYZHfhygsv7fEWCOj4bYmsP5A+pL4MkTfAnMlD4F+r3bobKv
+TyTA2P/w7PN+Agq2QW8piqMCpTBwenoKvX0AHGkGtP2YAPvTEWA7QUTAudn7/NxtOG46wWNmDtpB
+EkBzN7rBEvAFHp+YTB/q97qPAN4gHFqgBi8uLsC7qPCA6mg41G/+ErByPwEXDdoNxRhOx+M5jPEz
+QugS0ht+b1/Y3gEnYMAIAOIBE29/hIDucE8tmMsNOgK4B1RHFu4UCRlMHzv0xzcajcfdXWDs2h8T
+ArBCkoDUJYDLmz6w7ip3BFS0ve5wTRwAn6keMA9I3QYbfSZ0DKbyt+7OXjGI1idPcfNyAyfAMlCr
+zaGqphYrxHocLHRJVycnfGUcbtT+jIyMjIw9x7Nn8fJSzG0TmFtO8rZT+XT3S3ub+tKJbbLd5diT
+Vp50+zahyeHSslJ/YPrU0fuazrZO2CZ92/ZCCVXlGRiZKPJyPPRxyIFWeXLQBXJBKiq/3divEAN6
+ZwM200Qjm7EJBZeWm/PRWVCbYK7s7u2l4XaCz+lzgOfMfhMonXr7TWzeZb98dbgIzBT8Ub8eYYUq
+fZ4rVJ/MDbIDgPqTulJ/xvntWAtjIisqnwxOkGz0n077FARoY79GdA6HPE4rOy196NiMWHTZlSSA
+pcOgXpy/fHV2joaNKu3ffsAnRcBf4K/6NcIG6tIxk3HyoXPjASqfUgXbYN5PzpL2njkR9QMjeDTV
+HDTCgRuxOegjoO0FvKzP/t/gmVdI24+G7NIe8JX6Wv3dDyldMA+4YB5wwTygtd+dwRqaTqrLb1l7
+3zTSN52CNpnHuQOYPsDblybgxfkXh/oVtr+N1DEBJdhRJyd/Bd/q1z+cbNrD17iVKyajcnv9arhO
+kRPgsruuD6DmNPwpDNrLw2CoTgHni4yALr0L29+tiKAEIPn868ejx//8rpWP3OEOl5On9OwpcQm0
+MhafP/ey8f1uvDNIgGLQG8z4YO99ENgg95etwv4uYJYY8fUGHYH6j6fscHFZMftlAl9i+9XL73X3
+N/n+ZStOzfVfRvYXhrbdKOpEgVQTg/wsDuDD3kwOfQNMTJ5y+/ltUDWLunyxnRF46IqlBzGMY4X7
+inggREFioIyMjIyMHWCIB6ZNKAcXseo3vLTQTkVE7348dlwJJSz0+wLfmi8BhZqfw3D4ww/wHVLn
+Ed5/fgYvXsDZ3MlsvYUbbnDjDZ3MN3TJG4+bxjAaDl8TBri9qxEw1ccao2wTNAMLHo2f+sjrXwb/
+9qHoYqgPMBXJTVfOpmrZH23y6uvo0LHSyY6fHGwKfHJlAuMFvObjDYrIqxBgQi20h7Hd/nYVLmno
++eaNUm/eeH2GCuopntnhBJAlI2AHo9CCh1I1QxUdAbqqGY9BBLwyc3W4wYVhvY8A4BoIc1l5M7vn
+PWphZW9/Ses3n37y9a0uGqFwFQZsQQbd386DogpgEk+dzynsAZMJXq8+ns9NeukJ0PYrNATGGefJ
+QlhkLo7DTXr+y3bNiOsDvrXTz/C2q1DXZH84iRNwrP88Nj+u2DjYEE6RBxD9Knj16ujVHC67A742
+2o02RwD3gB+t7EblWvu9geOFxSnd3ROmT+nJyQkhoPlsxVONc/3TEdBos+jtA+ZzcwHgTvD1cDja
+YCcItA8w9i88A8b+mqSjc6Pvqd998QguEQPmQMeo23ODN86+p0/bn1buBkT6+oBhNZ/PYY4ZAHYb
+3PRd4LkZmPX68NRtMZn4ASvdA+qf0jMA5MP9eeg28Nug9QiLnj5A33U1MAES6xHAUNpz/9zFAYE1
+gqQDMT3G6xI9pwdw/aIgKoHCS1YGlRnSq9yCjdXjgN3j+N27YyROHxmuNAeNKPpYuXIyIyMjYy0M
+8eros59MF/PT2c602T7eA7zvhJ9dr/vzDjXaLp4Yc5+0wllzxzHv3gdmMMM7/CcQzKgVBqYTmFn+
+Z+mKm8J7k0A5F/jgCfjQ1WBhQyiOqD0lYuqBb+AyzMw9Ha2G3m6c8qQx+AlqnIceQp+Sb6i9UyQW
+bhr54+AjnZ0VzW2TAN0DmBT6PWmc6jDBE2PK2u+nF43dyP7Q0t1pOcX2fdRvH0mF2Q4JqN35rnHj
+VIeaXfIAVyUuw/aHCCiJy9iF5l1621zweI8KZrPZ9iJdb7DXJ3US0OSrtZ10imt7wHY7QesAzUMz
+1oZ3noB3qFJ/H18j97FYuw8QDN4oeKf30osvcSW2ExLo+VcbuAuo/sUIm8fMG9xocO3Ea19J9gFY
+ivnHJ2KnyfovZlgW3v6ySx32abQiIyMjIyPjhlFDTLxpwIgFMnTp6A3g4IDKNY+stkwAMAoIAbas
+xBXqUWneSAWTMjt50lTqT29rFjvXohjsDNm2YPXDFlICmrJOZ3t6tHm8AiEAl0sCeLIIorIRt+cF
+bew/QRsoAXb4o1XSfoywzm0FTMAoYBNvLyFu8v8HpLBtD1iKgC17wHb7AI6d9wFbvguAIGTHd4E9
+wG7jgIyMjIyM+434c2R3HeV/Ffx6jtZu6ijl8h59T655jhR+rdHzDOP6beABCheb8O8/WFXeOyzg
+f5oAhVYnKxP7CwaAf1afJu8bSrhS6tdaXeGnrRenOqOlz9d6QwYnA/3TLd+GE7qe3chA5YF5DfY0
+vK3adfOX/gyNp2BW25MHdxAB9qvRiiP3/XpQQFGYDU4+Mi///XumXG8pjvaUAOsBGlf4jJt+YYEz
+eEzAdw06F19R3juM7D1wita86GR0CKfDHgLuXCc4Bri6vMLdfjMc4VNSUNsdodo2xu/1+Xl/K5+a
+z8jIyMhYG/z5gJTMF1GtKq/a3rpyCvz5gJTMl9GtKq/a3rpyCmfQ4WwZmS+kXFVetb115ST48wEf
+/AGcfG1iw+tWbpbS2vJ3nQxcVr3lH3z5h972FUTLzYpOVk7l5hD+eYcYwDcAnewOotrZ4OtrPDuc
+qi/LRX0/RR4qx7Nn4U8g+qjffvuN6Gf+nC85vwauHjaYyubqvWYKY4VEfSUMitdnBCT1Ue63R543
+9m+OgCn6DroAAaHPVQxKth/wkJgHmG8bmQMsT0D6EjDfvhVRKO3ywOQUgRA7nmL1uawZmHf1k+DP
+BwQ6NdcJ+k6Md1LA5f5ONdhJ8vZ5J0vLHT99srkGOjmJbd/G1r2Nriqnse1AZt1AalU5jW2HsuuG
+0qvKGRkZGRkZGRG0gcONyXsP9v8D0/IdJADiBNiXl3327WRGgOL/9HC/0XwlIURkRhC4tz6Z/fu7
+fUf2gHvfB9z3u0BGRkZGRkbGplHcnkgguQoSqtUXuhbs/wPtMwqV0HUJAvj5vk32b8IDuL23yn7q
+AXZ5u32hbRX7d3o82Df1FZXvbh9QOfhyxldr/+3xgXU9oKmvsHyr7F/XA269/eveBXrsv7N9QALe
+/tvjA0kPWAXGbvebkbHn+D/J5nMcHzx1UAAAAABJRU5ErkJggg==</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>4369</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_888888_256x240.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_888888_256x240.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e1753fe2c641821a020541b35f7b20129b4ab0cc
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_888888_256x240.png.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681768.62</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-icons_888888_256x240.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEWIiIiIiIiIiIiIiIiIiIiI
+iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI
+iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI
+iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiI
+iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIighcp7AAAA
+TnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWN
+qa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAPhUlEQVR4nO1djWLbthEGyUiq5YSSLXtp
+7FpLOmfzkmxr126tmi2p03RJ1/Xe/3EGgARxPyAgRbIk2/hkSz4CJO4+HsE7AJSVysjI2AMUUOxa
+hZ2iANhzBtZWr4BoIRSYAVN5u4QwDwQDRbcwfUi5KS3wFuDmFnQLa4Dtb//cqktwD5QEFFwfUs7P
+oCCA7y4bEJVFizcIob8KmhAplwwqVjt+9FBl3uINQniwEiryEyw9JHqGpQdEFNi+B4QQ7QOiHhys
+IPoAxUqxvdvvA9K42bsAv4S2fxfYOe57IJSRkZGRkZGxx7jxSHDHcRBXQMTyIjInBgHwBJ/bEx8P
+EANC+uhbpSSggCBAVODVabpI1S/k4WLZpTn6NpMhoX9Y40hxYERFpMcqUs4AloCtDQdID1YhnyXZ
+2hLjAYWiO9Dy1PDB7tPhIqLx+uMB8grZaR+Qxl2/C2RkZGRkZGRk7A7rBf7J0DR5/LUTjzUPIPSP
+GvQJiVJiB7kcQCiUOJrcFNtDZIf2xarQ3aGvLNxAVIFAabz90BFiBIlycTBhgWwOWCH0FLYHlPqw
+HaCvcIn2ZbosCevfPTRiFFcgvHukCjWwrc3GrGh1fsAof8EaUReKXkCB4/MzFNo97qLpFiKFYv/k
+NR5YQxQbQEofkZ2OuEOHqqT6gFTpru8CN7x/+jaZkZGRkZGRcV+x/rLUNcMMqUAscgnFocmpqkTz
+qymwVAPxfJ5PnIUUQOUKT04tEdWZyv3JCQSn96WS4pD97QfyW25A7NhSAbyhmVj0FEltA4vdiygB
+ibXhoUYgykCUP7HwPTDeEqAIcHVMkZg7Zx4k0uFANs63hPQXCoRLAwdgGsr9Az7Qv7sgQGgg1aPl
+/BJLExBWgG4RFRLFImGmIquPC/klEGyCG0AuAXaJJC+B8FVe9NYQDEcXB8g6AQcjYJ1goJIggHWC
+rFR0S6kRHN5+4BzFi8NaoN35NRxUvL+JJdZr7PV4wK6fj8nIyMjIyNhr3OxdXAYq7FHZwB6bDSzS
+h4sF0utChqo0NAvaT1hLzXwFinmCzmeDucEQK18TTaQoFgP7bNC+RZ4OT4T6gQogDFYk+1QxQlj1
+9QGSAWKiLYp8P0Ag1Gbz1ULfWHLg9iUnQNK5QQJcukm04blKLH2GgEJCY+HzXAZWCvHKco3Bp6MI
+aCjSXXRJyOxeqhnzEaF93MfFGW/O16ZvDL5TM4MJIjujz/cHypkQuuzRwWJ93BKdIt+wCRAPl9kp
+e2Ikkb2mFgGlxh/i40d3EHfdvoyMjIyMu43ylt/IAmGHnN5iIt7wKfbv01RAcJqFRl9lcjYQSnbQ
+qKgC4fYOwSJt6N6trE0twZ9kN/PqNpTQeICvr4TLsDYC06U7BMjshS+v1/aT7IwQYD5LcgRQXMT2
+FrBfBLjZ6151jDElk9tPFfpUgk2yregusX25BJbwAFEfM+YI6vGAti4bTtizB+TjfQCrERyhKb2X
+8D6A9wX75P4t4neBYJeP6pdhg/gQl8MWvytzeSTjgOQBynQdh/iXKdxOrGJ/RkZGRsb9QmXihGr5
++g8GGg9uTh+KoVZuNIzV+CwRucFBEyr1mVjx4irOxwM1BhirB6Q+2eNQi4eqR+aF6mELtoMzCR7V
+9RAFe/ZvQogNiyY8FPSUTFsLp8TeTmMui5mtw7bcaT0Yw2AA4wFRQIlkgq+1DQrNhkmoxS5Jq+u6
+bMAIGRECEANgXHTgWzwgBOhDH2l0oTQ4D8D5NMktBgNywAEMjo8rwATMZrPY7JGxBoJCkIBDQiAY
+09EGTUiBCWkUpISfGPR5AAwBfZiG2z7Ayc1yeKTxid39xBNwfHr4O0LA48ePFTvhYrF1r4tyAoz9
+n2MCqEuBtp/6GDR0oAYfG/R6wJExHYZHfhygsv7fEWCOj4bYmsP5A+pL4MkTfAnMlD4F+r3bobKv
+TyTA2P/w7PN+Agq2QW8piqMCpTBwenoKvX0AHGkGtP2YAPvTEWA7QUTAudn7/NxtOG46wWNmDtpB
+EkBzN7rBEvAFHp+YTB/q97qPAN4gHFqgBi8uLsC7qPCA6mg41G/+ErByPwEXDdoNxRhOx+M5jPEz
+QugS0ht+b1/Y3gEnYMAIAOIBE29/hIDucE8tmMsNOgK4B1RHFu4UCRlMHzv0xzcajcfdXWDs2h8T
+ArBCkoDUJYDLmz6w7ip3BFS0ve5wTRwAn6keMA9I3QYbfSZ0DKbyt+7OXjGI1idPcfNyAyfAMlCr
+zaGqphYrxHocLHRJVycnfGUcbtT+jIyMjIw9x7Nn8fJSzG0TmFtO8rZT+XT3S3ub+tKJbbLd5diT
+Vp50+zahyeHSslJ/YPrU0fuazrZO2CZ92/ZCCVXlGRiZKPJyPPRxyIFWeXLQBXJBKiq/3divEAN6
+ZwM200Qjm7EJBZeWm/PRWVCbYK7s7u2l4XaCz+lzgOfMfhMonXr7TWzeZb98dbgIzBT8Ub8eYYUq
+fZ4rVJ/MDbIDgPqTulJ/xvntWAtjIisqnwxOkGz0n077FARoY79GdA6HPE4rOy196NiMWHTZlSSA
+pcOgXpy/fHV2joaNKu3ffsAnRcBf4K/6NcIG6tIxk3HyoXPjASqfUgXbYN5PzpL2njkR9QMjeDTV
+HDTCgRuxOegjoO0FvKzP/t/gmVdI24+G7NIe8JX6Wv3dDyldMA+4YB5wwTygtd+dwRqaTqrLb1l7
+3zTSN52CNpnHuQOYPsDblybgxfkXh/oVtr+N1DEBJdhRJyd/Bd/q1z+cbNrD17iVKyajcnv9arhO
+kRPgsruuD6DmNPwpDNrLw2CoTgHni4yALr0L29+tiKAEIPn868ejx//8rpWP3OEOl5On9OwpcQm0
+MhafP/ey8f1uvDNIgGLQG8z4YO99ENgg95etwv4uYJYY8fUGHYH6j6fscHFZMftlAl9i+9XL73X3
+N/n+ZStOzfVfRvYXhrbdKOpEgVQTg/wsDuDD3kwOfQNMTJ5y+/ltUDWLunyxnRF46IqlBzGMY4X7
+inggREFioIyMjIyMHWCIB6ZNKAcXseo3vLTQTkVE7348dlwJJSz0+wLfmi8BhZqfw3D4ww/wHVLn
+Ed5/fgYvXsDZ3MlsvYUbbnDjDZ3MN3TJG4+bxjAaDl8TBri9qxEw1ccao2wTNAMLHo2f+sjrXwb/
+9qHoYqgPMBXJTVfOpmrZH23y6uvo0LHSyY6fHGwKfHJlAuMFvObjDYrIqxBgQi20h7Hd/nYVLmno
++eaNUm/eeH2GCuopntnhBJAlI2AHo9CCh1I1QxUdAbqqGY9BBLwyc3W4wYVhvY8A4BoIc1l5M7vn
+PWphZW9/Ses3n37y9a0uGqFwFQZsQQbd386DogpgEk+dzynsAZMJXq8+ns9NeukJ0PYrNATGGefJ
+QlhkLo7DTXr+y3bNiOsDvrXTz/C2q1DXZH84iRNwrP88Nj+u2DjYEE6RBxD9Knj16ujVHC67A742
+2o02RwD3gB+t7EblWvu9geOFxSnd3ROmT+nJyQkhoPlsxVONc/3TEdBos+jtA+ZzcwHgTvD1cDja
+YCcItA8w9i88A8b+mqSjc6Pvqd998QguEQPmQMeo23ODN86+p0/bn1buBkT6+oBhNZ/PYY4ZAHYb
+3PRd4LkZmPX68NRtMZn4ASvdA+qf0jMA5MP9eeg28Nug9QiLnj5A33U1MAES6xHAUNpz/9zFAYE1
+gqQDMT3G6xI9pwdw/aIgKoHCS1YGlRnSq9yCjdXjgN3j+N27YyROHxmuNAeNKPpYuXIyIyMjYy0M
+8eros59MF/PT2c602T7eA7zvhJ9dr/vzDjXaLp4Yc5+0wllzxzHv3gdmMMM7/CcQzKgVBqYTmFn+
+Z+mKm8J7k0A5F/jgCfjQ1WBhQyiOqD0lYuqBb+AyzMw9Ha2G3m6c8qQx+AlqnIceQp+Sb6i9UyQW
+bhr54+AjnZ0VzW2TAN0DmBT6PWmc6jDBE2PK2u+nF43dyP7Q0t1pOcX2fdRvH0mF2Q4JqN35rnHj
+VIeaXfIAVyUuw/aHCCiJy9iF5l1621zweI8KZrPZ9iJdb7DXJ3US0OSrtZ10imt7wHY7QesAzUMz
+1oZ3noB3qFJ/H18j97FYuw8QDN4oeKf30osvcSW2ExLo+VcbuAuo/sUIm8fMG9xocO3Ea19J9gFY
+ivnHJ2KnyfovZlgW3v6ySx32abQiIyMjIyPjhlFDTLxpwIgFMnTp6A3g4IDKNY+stkwAMAoIAbas
+xBXqUWneSAWTMjt50lTqT29rFjvXohjsDNm2YPXDFlICmrJOZ3t6tHm8AiEAl0sCeLIIorIRt+cF
+bew/QRsoAXb4o1XSfoywzm0FTMAoYBNvLyFu8v8HpLBtD1iKgC17wHb7AI6d9wFbvguAIGTHd4E9
+wG7jgIyMjIyM+434c2R3HeV/Ffx6jtZu6ijl8h59T655jhR+rdHzDOP6beABCheb8O8/WFXeOyzg
+f5oAhVYnKxP7CwaAf1afJu8bSrhS6tdaXeGnrRenOqOlz9d6QwYnA/3TLd+GE7qe3chA5YF5DfY0
+vK3adfOX/gyNp2BW25MHdxAB9qvRiiP3/XpQQFGYDU4+Mi///XumXG8pjvaUAOsBGlf4jJt+YYEz
+eEzAdw06F19R3juM7D1wita86GR0CKfDHgLuXCc4Bri6vMLdfjMc4VNSUNsdodo2xu/1+Xl/K5+a
+z8jIyMhYG/z5gJTMF1GtKq/a3rpyCvz5gJTMl9GtKq/a3rpyCmfQ4WwZmS+kXFVetb115ST48wEf
+/AGcfG1iw+tWbpbS2vJ3nQxcVr3lH3z5h972FUTLzYpOVk7l5hD+eYcYwDcAnewOotrZ4OtrPDuc
+qi/LRX0/RR4qx7Nn4U8g+qjffvuN6Gf+nC85vwauHjaYyubqvWYKY4VEfSUMitdnBCT1Ue63R543
+9m+OgCn6DroAAaHPVQxKth/wkJgHmG8bmQMsT0D6EjDfvhVRKO3ywOQUgRA7nmL1uawZmHf1k+DP
+BwQ6NdcJ+k6Md1LA5f5ONdhJ8vZ5J0vLHT99srkGOjmJbd/G1r2Nriqnse1AZt1AalU5jW2HsuuG
+0qvKGRkZGRkZGRG0gcONyXsP9v8D0/IdJADiBNiXl3327WRGgOL/9HC/0XwlIURkRhC4tz6Z/fu7
+fUf2gHvfB9z3u0BGRkZGRkbGplHcnkgguQoSqtUXuhbs/wPtMwqV0HUJAvj5vk32b8IDuL23yn7q
+AXZ5u32hbRX7d3o82Df1FZXvbh9QOfhyxldr/+3xgXU9oKmvsHyr7F/XA269/eveBXrsv7N9QALe
+/tvjA0kPWAXGbvebkbHn+D/J5nMcHzx1UAAAAABJRU5ErkJggg==</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>4369</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_cd0a0a_256x240.png.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_cd0a0a_256x240.png.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fed09166edf5689acf9cb1e3e04f51a9aa99b4fd
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/images/ui-icons_cd0a0a_256x240.png.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681768.71</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>ui-icons_cd0a0a_256x240.png</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>image/png</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="base64">iVBORw0KGgoAAAANSUhEUgAAAQAAAADwCAMAAADYSUr5AAAA7VBMVEXNCgrNCgrNCgrNCgrNCgrN
+CgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrN
+CgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrN
+CgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrN
+CgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrNCgrqN5j8AAAA
+TnRSTlMAGBAyBAhQv4OZLiJUcEBmYBoSzQwgPBZCSEoeWiYwUiyFNIeBw2rJz8c4RBy9uXyrtaWN
+qa2zKP2fJO8KBgKPo2KVoa9s351GPm5+kWho0kj9AAAPhUlEQVR4nO1djWLbthEGyUiq5YSSLXtp
+7FpLOmfzkmxr126tmi2p03RJ1/Xe/3EGgARxPyAgRbIk2/hkSz4CJO4+HsE7AJSVysjI2AMUUOxa
+hZ2iANhzBtZWr4BoIRSYAVN5u4QwDwQDRbcwfUi5KS3wFuDmFnQLa4Dtb//cqktwD5QEFFwfUs7P
+oCCA7y4bEJVFizcIob8KmhAplwwqVjt+9FBl3uINQniwEiryEyw9JHqGpQdEFNi+B4QQ7QOiHhys
+IPoAxUqxvdvvA9K42bsAv4S2fxfYOe57IJSRkZGRkZGxx7jxSHDHcRBXQMTyIjInBgHwBJ/bEx8P
+EANC+uhbpSSggCBAVODVabpI1S/k4WLZpTn6NpMhoX9Y40hxYERFpMcqUs4AloCtDQdID1YhnyXZ
+2hLjAYWiO9Dy1PDB7tPhIqLx+uMB8grZaR+Qxl2/C2RkZGRkZGRk7A7rBf7J0DR5/LUTjzUPIPSP
+GvQJiVJiB7kcQCiUOJrcFNtDZIf2xarQ3aGvLNxAVIFAabz90BFiBIlycTBhgWwOWCH0FLYHlPqw
+HaCvcIn2ZbosCevfPTRiFFcgvHukCjWwrc3GrGh1fsAof8EaUReKXkCB4/MzFNo97qLpFiKFYv/k
+NR5YQxQbQEofkZ2OuEOHqqT6gFTpru8CN7x/+jaZkZGRkZGRcV+x/rLUNcMMqUAscgnFocmpqkTz
+qymwVAPxfJ5PnIUUQOUKT04tEdWZyv3JCQSn96WS4pD97QfyW25A7NhSAbyhmVj0FEltA4vdiygB
+ibXhoUYgykCUP7HwPTDeEqAIcHVMkZg7Zx4k0uFANs63hPQXCoRLAwdgGsr9Az7Qv7sgQGgg1aPl
+/BJLExBWgG4RFRLFImGmIquPC/klEGyCG0AuAXaJJC+B8FVe9NYQDEcXB8g6AQcjYJ1goJIggHWC
+rFR0S6kRHN5+4BzFi8NaoN35NRxUvL+JJdZr7PV4wK6fj8nIyMjIyNhr3OxdXAYq7FHZwB6bDSzS
+h4sF0utChqo0NAvaT1hLzXwFinmCzmeDucEQK18TTaQoFgP7bNC+RZ4OT4T6gQogDFYk+1QxQlj1
+9QGSAWKiLYp8P0Ag1Gbz1ULfWHLg9iUnQNK5QQJcukm04blKLH2GgEJCY+HzXAZWCvHKco3Bp6MI
+aCjSXXRJyOxeqhnzEaF93MfFGW/O16ZvDL5TM4MJIjujz/cHypkQuuzRwWJ93BKdIt+wCRAPl9kp
+e2Ikkb2mFgGlxh/i40d3EHfdvoyMjIyMu43ylt/IAmGHnN5iIt7wKfbv01RAcJqFRl9lcjYQSnbQ
+qKgC4fYOwSJt6N6trE0twZ9kN/PqNpTQeICvr4TLsDYC06U7BMjshS+v1/aT7IwQYD5LcgRQXMT2
+FrBfBLjZ6151jDElk9tPFfpUgk2yregusX25BJbwAFEfM+YI6vGAti4bTtizB+TjfQCrERyhKb2X
+8D6A9wX75P4t4neBYJeP6pdhg/gQl8MWvytzeSTjgOQBynQdh/iXKdxOrGJ/RkZGRsb9QmXihGr5
++g8GGg9uTh+KoVZuNIzV+CwRucFBEyr1mVjx4irOxwM1BhirB6Q+2eNQi4eqR+aF6mELtoMzCR7V
+9RAFe/ZvQogNiyY8FPSUTFsLp8TeTmMui5mtw7bcaT0Yw2AA4wFRQIlkgq+1DQrNhkmoxS5Jq+u6
+bMAIGRECEANgXHTgWzwgBOhDH2l0oTQ4D8D5NMktBgNywAEMjo8rwATMZrPY7JGxBoJCkIBDQiAY
+09EGTUiBCWkUpISfGPR5AAwBfZiG2z7Ayc1yeKTxid39xBNwfHr4O0LA48ePFTvhYrF1r4tyAoz9
+n2MCqEuBtp/6GDR0oAYfG/R6wJExHYZHfhygsv7fEWCOj4bYmsP5A+pL4MkTfAnMlD4F+r3bobKv
+TyTA2P/w7PN+Agq2QW8piqMCpTBwenoKvX0AHGkGtP2YAPvTEWA7QUTAudn7/NxtOG46wWNmDtpB
+EkBzN7rBEvAFHp+YTB/q97qPAN4gHFqgBi8uLsC7qPCA6mg41G/+ErByPwEXDdoNxRhOx+M5jPEz
+QugS0ht+b1/Y3gEnYMAIAOIBE29/hIDucE8tmMsNOgK4B1RHFu4UCRlMHzv0xzcajcfdXWDs2h8T
+ArBCkoDUJYDLmz6w7ip3BFS0ve5wTRwAn6keMA9I3QYbfSZ0DKbyt+7OXjGI1idPcfNyAyfAMlCr
+zaGqphYrxHocLHRJVycnfGUcbtT+jIyMjIw9x7Nn8fJSzG0TmFtO8rZT+XT3S3ub+tKJbbLd5diT
+Vp50+zahyeHSslJ/YPrU0fuazrZO2CZ92/ZCCVXlGRiZKPJyPPRxyIFWeXLQBXJBKiq/3divEAN6
+ZwM200Qjm7EJBZeWm/PRWVCbYK7s7u2l4XaCz+lzgOfMfhMonXr7TWzeZb98dbgIzBT8Ub8eYYUq
+fZ4rVJ/MDbIDgPqTulJ/xvntWAtjIisqnwxOkGz0n077FARoY79GdA6HPE4rOy196NiMWHTZlSSA
+pcOgXpy/fHV2joaNKu3ffsAnRcBf4K/6NcIG6tIxk3HyoXPjASqfUgXbYN5PzpL2njkR9QMjeDTV
+HDTCgRuxOegjoO0FvKzP/t/gmVdI24+G7NIe8JX6Wv3dDyldMA+4YB5wwTygtd+dwRqaTqrLb1l7
+3zTSN52CNpnHuQOYPsDblybgxfkXh/oVtr+N1DEBJdhRJyd/Bd/q1z+cbNrD17iVKyajcnv9arhO
+kRPgsruuD6DmNPwpDNrLw2CoTgHni4yALr0L29+tiKAEIPn868ejx//8rpWP3OEOl5On9OwpcQm0
+MhafP/ey8f1uvDNIgGLQG8z4YO99ENgg95etwv4uYJYY8fUGHYH6j6fscHFZMftlAl9i+9XL73X3
+N/n+ZStOzfVfRvYXhrbdKOpEgVQTg/wsDuDD3kwOfQNMTJ5y+/ltUDWLunyxnRF46IqlBzGMY4X7
+inggREFioIyMjIyMHWCIB6ZNKAcXseo3vLTQTkVE7348dlwJJSz0+wLfmi8BhZqfw3D4ww/wHVLn
+Ed5/fgYvXsDZ3MlsvYUbbnDjDZ3MN3TJG4+bxjAaDl8TBri9qxEw1ccao2wTNAMLHo2f+sjrXwb/
+9qHoYqgPMBXJTVfOpmrZH23y6uvo0LHSyY6fHGwKfHJlAuMFvObjDYrIqxBgQi20h7Hd/nYVLmno
++eaNUm/eeH2GCuopntnhBJAlI2AHo9CCh1I1QxUdAbqqGY9BBLwyc3W4wYVhvY8A4BoIc1l5M7vn
+PWphZW9/Ses3n37y9a0uGqFwFQZsQQbd386DogpgEk+dzynsAZMJXq8+ns9NeukJ0PYrNATGGefJ
+QlhkLo7DTXr+y3bNiOsDvrXTz/C2q1DXZH84iRNwrP88Nj+u2DjYEE6RBxD9Knj16ujVHC67A742
+2o02RwD3gB+t7EblWvu9geOFxSnd3ROmT+nJyQkhoPlsxVONc/3TEdBos+jtA+ZzcwHgTvD1cDja
+YCcItA8w9i88A8b+mqSjc6Pvqd998QguEQPmQMeo23ODN86+p0/bn1buBkT6+oBhNZ/PYY4ZAHYb
+3PRd4LkZmPX68NRtMZn4ASvdA+qf0jMA5MP9eeg28Nug9QiLnj5A33U1MAES6xHAUNpz/9zFAYE1
+gqQDMT3G6xI9pwdw/aIgKoHCS1YGlRnSq9yCjdXjgN3j+N27YyROHxmuNAeNKPpYuXIyIyMjYy0M
+8eros59MF/PT2c602T7eA7zvhJ9dr/vzDjXaLp4Yc5+0wllzxzHv3gdmMMM7/CcQzKgVBqYTmFn+
+Z+mKm8J7k0A5F/jgCfjQ1WBhQyiOqD0lYuqBb+AyzMw9Ha2G3m6c8qQx+AlqnIceQp+Sb6i9UyQW
+bhr54+AjnZ0VzW2TAN0DmBT6PWmc6jDBE2PK2u+nF43dyP7Q0t1pOcX2fdRvH0mF2Q4JqN35rnHj
+VIeaXfIAVyUuw/aHCCiJy9iF5l1621zweI8KZrPZ9iJdb7DXJ3US0OSrtZ10imt7wHY7QesAzUMz
+1oZ3noB3qFJ/H18j97FYuw8QDN4oeKf30osvcSW2ExLo+VcbuAuo/sUIm8fMG9xocO3Ea19J9gFY
+ivnHJ2KnyfovZlgW3v6ySx32abQiIyMjIyPjhlFDTLxpwIgFMnTp6A3g4IDKNY+stkwAMAoIAbas
+xBXqUWneSAWTMjt50lTqT29rFjvXohjsDNm2YPXDFlICmrJOZ3t6tHm8AiEAl0sCeLIIorIRt+cF
+bew/QRsoAXb4o1XSfoywzm0FTMAoYBNvLyFu8v8HpLBtD1iKgC17wHb7AI6d9wFbvguAIGTHd4E9
+wG7jgIyMjIyM+434c2R3HeV/Ffx6jtZu6ijl8h59T655jhR+rdHzDOP6beABCheb8O8/WFXeOyzg
+f5oAhVYnKxP7CwaAf1afJu8bSrhS6tdaXeGnrRenOqOlz9d6QwYnA/3TLd+GE7qe3chA5YF5DfY0
+vK3adfOX/gyNp2BW25MHdxAB9qvRiiP3/XpQQFGYDU4+Mi///XumXG8pjvaUAOsBGlf4jJt+YYEz
+eEzAdw06F19R3juM7D1wita86GR0CKfDHgLuXCc4Bri6vMLdfjMc4VNSUNsdodo2xu/1+Xl/K5+a
+z8jIyMhYG/z5gJTMF1GtKq/a3rpyCvz5gJTMl9GtKq/a3rpyCmfQ4WwZmS+kXFVetb115ST48wEf
+/AGcfG1iw+tWbpbS2vJ3nQxcVr3lH3z5h972FUTLzYpOVk7l5hD+eYcYwDcAnewOotrZ4OtrPDuc
+qi/LRX0/RR4qx7Nn4U8g+qjffvuN6Gf+nC85vwauHjaYyubqvWYKY4VEfSUMitdnBCT1Ue63R543
+9m+OgCn6DroAAaHPVQxKth/wkJgHmG8bmQMsT0D6EjDfvhVRKO3ywOQUgRA7nmL1uawZmHf1k+DP
+BwQ6NdcJ+k6Md1LA5f5ONdhJ8vZ5J0vLHT99srkGOjmJbd/G1r2Nriqnse1AZt1AalU5jW2HsuuG
+0qvKGRkZGRkZGRG0gcONyXsP9v8D0/IdJADiBNiXl3327WRGgOL/9HC/0XwlIURkRhC4tz6Z/fu7
+fUf2gHvfB9z3u0BGRkZGRkbGplHcnkgguQoSqtUXuhbs/wPtMwqV0HUJAvj5vk32b8IDuL23yn7q
+AXZ5u32hbRX7d3o82Df1FZXvbh9QOfhyxldr/+3xgXU9oKmvsHyr7F/XA269/eveBXrsv7N9QALe
+/tvjA0kPWAXGbvebkbHn+D/J5nMcHzx1UAAAAABJRU5ErkJggg==</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>4369</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jio.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jio.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cf08669c9c91af5cea1e2370a871de06c9c3bfc8
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jio.js.xml
@@ -0,0 +1,8840 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681771.03</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jio.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>254586</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+(function (dependencies, module) {\n
+  if (typeof define === \'function\' && define.amd) {\n
+    return define(dependencies, module);\n
+  }\n
+  if (typeof exports === \'object\') {\n
+    return module(exports);\n
+  }\n
+  module(window);\n
+}([\'exports\'], function (exports) {\n
+/*\n
+ * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined\n
+ * in FIPS PUB 180-1\n
+ * Version 2.1a Copyright Paul Johnston 2000 - 2002.\n
+ * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet\n
+ * Distributed under the BSD License\n
+ * See http://pajhome.org.uk/crypt/md5 for details.\n
+ */\n
+\n
+/*\n
+ * Configurable variables. You may need to tweak these to be compatible with\n
+ * the server-side, but the defaults work in most cases.\n
+ */\n
+\n
+var hexcase = 0;  /* hex output format. 0 - lowercase; 1 - uppercase        */\n
+var b64pad  = "="; /* base-64 pad character. "=" for strict RFC compliance   */\n
+var chrsz   = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode      */\n
+\n
+/*\n
+ * These are the functions you\'ll usually want to call\n
+ * They take string arguments and return either hex or base-64 encoded strings\n
+ */\n
+function hex_sha1(s){return binb2hex(core_sha1(str2binb(s),s.length * chrsz));}\n
+function b64_sha1(s){return binb2b64(core_sha1(str2binb(s),s.length * chrsz));}\n
+function str_sha1(s){return binb2str(core_sha1(str2binb(s),s.length * chrsz));}\n
+function hex_hmac_sha1(key, data){ return binb2hex(core_hmac_sha1(key, data));}\n
+function b64_hmac_sha1(key, data){ return binb2b64(core_hmac_sha1(key, data));}\n
+function str_hmac_sha1(key, data){ return binb2str(core_hmac_sha1(key, data));}\n
+\n
+/*\n
+ * Perform a simple self-test to see if the VM is working\n
+ */\n
+function sha1_vm_test()\n
+{\n
+  return hex_sha1("abc") == "a9993e364706816aba3e25717850c26c9cd0d89d";\n
+}\n
+\n
+/*\n
+ * Calculate the SHA-1 of an array of big-endian words, and a bit length\n
+ */\n
+function core_sha1(x, len)\n
+{\n
+  /* append padding */\n
+  x[len >> 5] |= 0x80 << (24 - len % 32);\n
+  x[((len + 64 >> 9) << 4) + 15] = len;\n
+\n
+  var w = Array(80);\n
+  var a =  1732584193;\n
+  var b = -271733879;\n
+  var c = -1732584194;\n
+  var d =  271733878;\n
+  var e = -1009589776;\n
+\n
+  for(var i = 0; i < x.length; i += 16)\n
+  {\n
+    var olda = a;\n
+    var oldb = b;\n
+    var oldc = c;\n
+    var oldd = d;\n
+    var olde = e;\n
+\n
+    for(var j = 0; j < 80; j++)\n
+    {\n
+      if(j < 16) w[j] = x[i + j];\n
+      else w[j] = rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);\n
+      var t = safe_add(safe_add(rol(a, 5), sha1_ft(j, b, c, d)),\n
+                       safe_add(safe_add(e, w[j]), sha1_kt(j)));\n
+      e = d;\n
+      d = c;\n
+      c = rol(b, 30);\n
+      b = a;\n
+      a = t;\n
+    }\n
+\n
+    a = safe_add(a, olda);\n
+    b = safe_add(b, oldb);\n
+    c = safe_add(c, oldc);\n
+    d = safe_add(d, oldd);\n
+    e = safe_add(e, olde);\n
+  }\n
+  return Array(a, b, c, d, e);\n
+\n
+}\n
+\n
+/*\n
+ * Perform the appropriate triplet combination function for the current\n
+ * iteration\n
+ */\n
+function sha1_ft(t, b, c, d)\n
+{\n
+  if(t < 20) return (b & c) | ((~b) & d);\n
+  if(t < 40) return b ^ c ^ d;\n
+  if(t < 60) return (b & c) | (b & d) | (c & d);\n
+  return b ^ c ^ d;\n
+}\n
+\n
+/*\n
+ * Determine the appropriate additive constant for the current iteration\n
+ */\n
+function sha1_kt(t)\n
+{\n
+  return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :\n
+         (t < 60) ? -1894007588 : -899497514;\n
+}\n
+\n
+/*\n
+ * Calculate the HMAC-SHA1 of a key and some data\n
+ */\n
+function core_hmac_sha1(key, data)\n
+{\n
+  var bkey = str2binb(key);\n
+  if(bkey.length > 16) bkey = core_sha1(bkey, key.length * chrsz);\n
+\n
+  var ipad = Array(16), opad = Array(16);\n
+  for(var i = 0; i < 16; i++)\n
+  {\n
+    ipad[i] = bkey[i] ^ 0x36363636;\n
+    opad[i] = bkey[i] ^ 0x5C5C5C5C;\n
+  }\n
+\n
+  var hash = core_sha1(ipad.concat(str2binb(data)), 512 + data.length * chrsz);\n
+  return core_sha1(opad.concat(hash), 512 + 160);\n
+}\n
+\n
+/*\n
+ * Add integers, wrapping at 2^32. This uses 16-bit operations internally\n
+ * to work around bugs in some JS interpreters.\n
+ */\n
+function safe_add(x, y)\n
+{\n
+  var lsw = (x & 0xFFFF) + (y & 0xFFFF);\n
+  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n
+  return (msw << 16) | (lsw & 0xFFFF);\n
+}\n
+\n
+/*\n
+ * Bitwise rotate a 32-bit number to the left.\n
+ */\n
+function rol(num, cnt)\n
+{\n
+  return (num << cnt) | (num >>> (32 - cnt));\n
+}\n
+\n
+/*\n
+ * Convert an 8-bit or 16-bit string to an array of big-endian words\n
+ * In 8-bit function, characters >255 have their hi-byte silently ignored.\n
+ */\n
+function str2binb(str)\n
+{\n
+  var bin = Array();\n
+  var mask = (1 << chrsz) - 1;\n
+  for(var i = 0; i < str.length * chrsz; i += chrsz)\n
+    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (32 - chrsz - i%32);\n
+  return bin;\n
+}\n
+\n
+/*\n
+ * Convert an array of big-endian words to a string\n
+ */\n
+function binb2str(bin)\n
+{\n
+  var str = "";\n
+  var mask = (1 << chrsz) - 1;\n
+  for(var i = 0; i < bin.length * 32; i += chrsz)\n
+    str += String.fromCharCode((bin[i>>5] >>> (32 - chrsz - i%32)) & mask);\n
+  return str;\n
+}\n
+\n
+/*\n
+ * Convert an array of big-endian words to a hex string.\n
+ */\n
+function binb2hex(binarray)\n
+{\n
+  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";\n
+  var str = "";\n
+  for(var i = 0; i < binarray.length * 4; i++)\n
+  {\n
+    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +\n
+           hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);\n
+  }\n
+  return str;\n
+}\n
+\n
+/*\n
+ * Convert an array of big-endian words to a base-64 string\n
+ */\n
+function binb2b64(binarray)\n
+{\n
+  var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\n
+  var str = "";\n
+  for(var i = 0; i < binarray.length * 4; i += 3)\n
+  {\n
+    var triplet = (((binarray[i   >> 2] >> 8 * (3 -  i   %4)) & 0xFF) << 16)\n
+                | (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 )\n
+                |  ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);\n
+    for(var j = 0; j < 4; j++)\n
+    {\n
+      if(i * 8 + j * 6 > binarray.length * 32) str += b64pad;\n
+      else str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);\n
+    }\n
+  }\n
+  return str;\n
+}\n
+\n
+  exports.hex_sha1 = hex_sha1;\n
+  exports.b64_sha1 = b64_sha1;\n
+  exports.str_sha1 = str_sha1;\n
+  exports.hex_hmac_sha1 = hex_hmac_sha1;\n
+  exports.b64_hmac_sha1 = b64_hmac_sha1;\n
+  exports.str_hmac_sha1 = str_hmac_sha1;\n
+}));\n
+;(function (dependencies, module) {\n
+    if (typeof define === \'function\' && define.amd) {\n
+        return define(dependencies, module);\n
+    }\n
+    if (typeof exports === \'object\') {\n
+        return module(exports);\n
+    }\n
+    module(window);\n
+}([\'exports\'], function (window) {\n
+/* A JavaScript implementation of the Secure Hash Standard\n
+ * Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/\n
+ * Distributed under the BSD License\n
+ * Some bits taken from Paul Johnston\'s SHA-1 implementation\n
+ */\n
+(function () {\n
+    var chrsz   = 8;/* bits per input character. 8 - ASCII; 16 - Unicode */\n
+    var hexcase = 0;/* hex output format. 0 - lowercase; 1 - uppercase */\n
+\n
+    function safe_add (x, y) {\n
+        var lsw = (x & 0xFFFF) + (y & 0xFFFF);\n
+        var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n
+        return (msw << 16) | (lsw & 0xFFFF);\n
+    }\n
+\n
+    function S (X, n) {return ( X >>> n ) | (X << (32 - n));}\n
+\n
+    function R (X, n) {return ( X >>> n );}\n
+\n
+    function Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}\n
+\n
+    function Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}\n
+\n
+    function Sigma0256(x) {return (S(x, 2) ^ S(x, 13) ^ S(x, 22));}\n
+\n
+    function Sigma1256(x) {return (S(x, 6) ^ S(x, 11) ^ S(x, 25));}\n
+\n
+    function Gamma0256(x) {return (S(x, 7) ^ S(x, 18) ^ R(x, 3));}\n
+\n
+    function Gamma1256(x) {return (S(x, 17) ^ S(x, 19) ^ R(x, 10));}\n
+\n
+    function Sigma0512(x) {return (S(x, 28) ^ S(x, 34) ^ S(x, 39));}\n
+\n
+    function Sigma1512(x) {return (S(x, 14) ^ S(x, 18) ^ S(x, 41));}\n
+\n
+    function Gamma0512(x) {return (S(x, 1) ^ S(x, 8) ^ R(x, 7));}\n
+\n
+    function Gamma1512(x) {return (S(x, 19) ^ S(x, 61) ^ R(x, 6));}\n
+\n
+    function newArray (n) {\n
+        var a = [];\n
+        for (;n>0;n--) {\n
+            a.push(undefined);\n
+        }\n
+        return a;\n
+    }\n
+\n
+    function core_sha256 (m, l) {\n
+        var K = [0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2];\n
+        var HASH = [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19];\n
+        var W = newArray(64);\n
+        var a, b, c, d, e, f, g, h, i, j;\n
+        var T1, T2;\n
+\n
+        /* append padding */\n
+        m[l >> 5] |= 0x80 << (24 - l % 32);\n
+        m[((l + 64 >> 9) << 4) + 15] = l;\n
+\n
+        for ( var i = 0; i<m.length; i+=16 ) {\n
+            a = HASH[0];\n
+            b = HASH[1];\n
+            c = HASH[2];\n
+            d = HASH[3];\n
+            e = HASH[4];\n
+            f = HASH[5];\n
+            g = HASH[6];\n
+            h = HASH[7];\n
+\n
+            for ( var j = 0; j<64; j++) {\n
+                if (j < 16) {\n
+                    W[j] = m[j + i];\n
+                } else {\n
+                    W[j] = safe_add(safe_add(safe_add(Gamma1256(\n
+                        W[j - 2]),W[j - 7]),Gamma0256(W[j - 15])), W[j - 16]);\n
+                }\n
+\n
+                T1 = safe_add(safe_add(safe_add(safe_add(\n
+                    h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);\n
+                T2 = safe_add(Sigma0256(a), Maj(a, b, c));\n
+\n
+                h = g;\n
+                g = f;\n
+                f = e;\n
+                e = safe_add(d, T1);\n
+                d = c;\n
+                c = b;\n
+                b = a;\n
+                a = safe_add(T1, T2);\n
+            }\n
+\n
+            HASH[0] = safe_add(a, HASH[0]);\n
+            HASH[1] = safe_add(b, HASH[1]);\n
+            HASH[2] = safe_add(c, HASH[2]);\n
+            HASH[3] = safe_add(d, HASH[3]);\n
+            HASH[4] = safe_add(e, HASH[4]);\n
+            HASH[5] = safe_add(f, HASH[5]);\n
+            HASH[6] = safe_add(g, HASH[6]);\n
+            HASH[7] = safe_add(h, HASH[7]);\n
+        }\n
+        return HASH;\n
+    }\n
+\n
+    function core_sha512 (m, l) {\n
+        var K = [0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817];\n
+        var HASH = [0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179];\n
+        var W = newArray(80);\n
+        var a, b, c, d, e, f, g, h, i, j;\n
+        var T1, T2;\n
+\n
+    }\n
+\n
+    function str2binb (str) {\n
+        var bin = Array();\n
+        var mask = (1 << chrsz) - 1;\n
+        for(var i = 0; i < str.length * chrsz; i += chrsz)\n
+            bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);\n
+        return bin;\n
+    }\n
+\n
+    function binb2str (bin) {\n
+        var str = "";\n
+        var mask = (1 << chrsz) - 1;\n
+        for(var i = 0; i < bin.length * 32; i += chrsz)\n
+            str += String.fromCharCode((bin[i>>5] >>> (24 - i%32)) & mask);\n
+        return str;\n
+    }\n
+\n
+    function binb2hex (binarray) {\n
+        var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";\n
+        var str = "";\n
+        for(var i = 0; i < binarray.length * 4; i++)\n
+        {\n
+            str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +\n
+                hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);\n
+        }\n
+        return str;\n
+    }\n
+\n
+    function binb2b64 (binarray) {\n
+        var tab =\n
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";\n
+        var str = "";\n
+        for(var i = 0; i < binarray.length * 4; i += 3) {\n
+            var triplet = (((binarray[i >> 2] >> 8 * (3- i %4)) & 0xFF) << 16) |\n
+                (((binarray[i+1 >> 2] >> 8 * (3 - (i+1)%4)) & 0xFF) << 8 ) |\n
+                ((binarray[i+2 >> 2] >> 8 * (3 - (i+2)%4)) & 0xFF);\n
+            for(var j = 0; j < 4; j++) {\n
+                if(i * 8 + j * 6 > binarray.length * 32) { str += b64pad; }\n
+                else {str += tab.charAt((triplet >> 6*(3-j)) & 0x3F);}\n
+            }\n
+        }\n
+        return str;\n
+    }\n
+\n
+    function hex_sha256(s){\n
+        return binb2hex(core_sha256(str2binb(s),s.length * chrsz));\n
+    }\n
+    function b64_sha256(s){\n
+        return binb2b64(core_sha256(str2binb(s),s.length * chrsz));\n
+    }\n
+    function str_sha256(s){\n
+        return binb2str(core_sha256(str2binb(s),s.length * chrsz));\n
+    }\n
+    window.hex_sha256 = hex_sha256;\n
+    window.b64_sha256 = b64_sha256;\n
+    window.str_sha256 = str_sha256;\n
+}());\n
+}));\n
+;(function (dependencies, module) {\n
+    if (typeof define === \'function\' && define.amd) {\n
+        return define(dependencies, module);\n
+    }\n
+    if (typeof exports === \'object\') {\n
+        return module(exports);\n
+    }\n
+    module(window);\n
+}([\'exports\'], function (window) {\n
+/* A JavaScript implementation of the Secure Hash Algorithm, SHA-256\n
+ * Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/\n
+ * Distributed under the BSD License\n
+ * Some bits taken from Paul Johnston\'s SHA-1 implementation\n
+ */\n
+(function () {\n
+    var chrsz = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode  */\n
+    function safe_add (x, y) {\n
+        var lsw = (x & 0xFFFF) + (y & 0xFFFF);\n
+        var msw = (x >> 16) + (y >> 16) + (lsw >> 16);\n
+        return (msw << 16) | (lsw & 0xFFFF);\n
+    }\n
+    function S (X, n) {return ( X >>> n ) | (X << (32 - n));}\n
+    function R (X, n) {return ( X >>> n );}\n
+    function Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}\n
+    function Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}\n
+    function Sigma0256(x) {return (S(x, 2) ^ S(x, 13) ^ S(x, 22));}\n
+    function Sigma1256(x) {return (S(x, 6) ^ S(x, 11) ^ S(x, 25));}\n
+    function Gamma0256(x) {return (S(x, 7) ^ S(x, 18) ^ R(x, 3));}\n
+    function Gamma1256(x) {return (S(x, 17) ^ S(x, 19) ^ R(x, 10));}\n
+    function newArray (n) {\n
+        var a = [];\n
+        for (;n>0;n--) {\n
+            a.push(undefined);\n
+        }\n
+        return a;\n
+    }\n
+    function core_sha256 (m, l) {\n
+        var K = [0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2];\n
+        var HASH = [0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19];\n
+        var W = newArray(64);\n
+        var a, b, c, d, e, f, g, h, i, j;\n
+        var T1, T2;\n
+        /* append padding */\n
+        m[l >> 5] |= 0x80 << (24 - l % 32);\n
+        m[((l + 64 >> 9) << 4) + 15] = l;\n
+        for ( var i = 0; i<m.length; i+=16 ) {\n
+            a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3];\n
+            e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7];\n
+            for ( var j = 0; j<64; j++) {\n
+                if (j < 16) {\n
+                    W[j] = m[j + i];\n
+                } else {\n
+                    W[j] = safe_add(safe_add(safe_add(Gamma1256(\n
+                        W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);\n
+                }\n
+                T1 = safe_add(safe_add(safe_add(\n
+                    safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);\n
+                T2 = safe_add(Sigma0256(a), Maj(a, b, c));\n
+                h = g; g = f; f = e; e = safe_add(d, T1);\n
+                d = c; c = b; b = a; a = safe_add(T1, T2);\n
+            }\n
+            HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]);\n
+            HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]);\n
+            HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]);\n
+            HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]);\n
+        }\n
+        return HASH;\n
+    }\n
+    function str2binb (str) {\n
+        var bin = Array();\n
+        var mask = (1 << chrsz) - 1;\n
+        for(var i = 0; i < str.length * chrsz; i += chrsz)\n
+            bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);\n
+        return bin;\n
+    }\n
+    function binb2hex (binarray) {\n
+        var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */\n
+        var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";\n
+        var str = "";\n
+        for (var i = 0; i < binarray.length * 4; i++) {\n
+            str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) +\n
+                hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);\n
+        }\n
+        return str;\n
+    }\n
+    function hex_sha256(s){\n
+        return binb2hex(core_sha256(str2binb(s),s.length * chrsz));\n
+    }\n
+    window.hex_sha256 = hex_sha256;\n
+}());\n
+}));\n
+;(function (dependencies, module) {\n
+  "use strict";\n
+  if (typeof define === \'function\' && define.amd) {\n
+    return define(dependencies, module);\n
+  }\n
+  window.jIO = {};\n
+  module(window.jIO, RSVP, {hex_sha256: hex_sha256});\n
+}([\'exports\', \'rsvp\', \'sha256\'], function (exports, RSVP, sha256) {\n
+  "use strict";\n
+\n
+  var hex_sha256 = sha256.hex_sha256;\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global uniqueJSONStringify, methodType */\n
+\n
+var defaults = {}, constants = {};\n
+\n
+defaults.storage_types = {};\n
+\n
+constants.dcmi_types = {\n
+  \'Collection\': \'Collection\',\n
+  \'Dataset\': \'Dataset\',\n
+  \'Event\': \'Event\',\n
+  \'Image\': \'Image\',\n
+  \'InteractiveResource\': \'InteractiveResource\',\n
+  \'MovingImage\': \'MovingImage\',\n
+  \'PhysicalObject\': \'PhysicalObject\',\n
+  \'Service\': \'Service\',\n
+  \'Software\': \'Software\',\n
+  \'Sound\': \'Sound\',\n
+  \'StillImage\': \'StillImage\',\n
+  \'Text\': \'Text\'\n
+};\n
+// if (dcmi_types.Collection === \'Collection\') { is a DCMI type }\n
+// if (typeof dcmi_types[name] === \'string\')   { is a DCMI type }\n
+\n
+constants.http_status_text = {\n
+  "0": "Unknown",\n
+  "550": "Internal JIO Error",\n
+  "551": "Internal Storage Error",\n
+  "555": "Cancelled",\n
+  "Unknown": "Unknown",\n
+  "Internal JIO Error": "Internal JIO Error",\n
+  "Internal Storage Error": "Internal Storage Error",\n
+  "Cancelled": "Cancelled",\n
+  "unknown": "Unknown",\n
+  "internal_jio_error": "Internal JIO Error",\n
+  "internal_storage_error": "Internal Storage Error",\n
+  "cancelled": "Cancelled",\n
+\n
+  "200": "Ok",\n
+  "201": "Created",\n
+  "204": "No Content",\n
+  "205": "Reset Content",\n
+  "206": "Partial Content",\n
+  "304": "Not Modified",\n
+  "400": "Bad Request",\n
+  "401": "Unauthorized",\n
+  "402": "Payment Required",\n
+  "403": "Forbidden",\n
+  "404": "Not Found",\n
+  "405": "Method Not Allowed",\n
+  "406": "Not Acceptable",\n
+  "407": "Proxy Authentication Required",\n
+  "408": "Request Timeout",\n
+  "409": "Conflict",\n
+  "410": "Gone",\n
+  "411": "Length Required",\n
+  "412": "Precondition Failed",\n
+  "413": "Request Entity Too Large",\n
+  "414": "Request-URI Too Long",\n
+  "415": "Unsupported Media Type",\n
+  "416": "Requested Range Not Satisfiable",\n
+  "417": "Expectation Failed",\n
+  "418": "I\'m a teapot",\n
+  "419": "Authentication Timeout",\n
+  "500": "Internal Server Error",\n
+  "501": "Not Implemented",\n
+  "502": "Bad Gateway",\n
+  "503": "Service Unavailable",\n
+  "504": "Gateway Timeout",\n
+  "507": "Insufficient Storage",\n
+\n
+  "Ok": "Ok",\n
+  "OK": "Ok",\n
+  "Created": "Created",\n
+  "No Content": "No Content",\n
+  "Reset Content": "Reset Content",\n
+  "Partial Content": "Partial Content",\n
+  "Not Modified": "Not Modified",\n
+  "Bad Request": "Bad Request",\n
+  "Unauthorized": "Unauthorized",\n
+  "Payment Required": "Payment Required",\n
+  "Forbidden": "Forbidden",\n
+  "Not Found": "Not Found",\n
+  "Method Not Allowed": "Method Not Allowed",\n
+  "Not Acceptable": "Not Acceptable",\n
+  "Proxy Authentication Required": "Proxy Authentication Required",\n
+  "Request Timeout": "Request Timeout",\n
+  "Conflict": "Conflict",\n
+  "Gone": "Gone",\n
+  "Length Required": "Length Required",\n
+  "Precondition Failed": "Precondition Failed",\n
+  "Request Entity Too Large": "Request Entity Too Large",\n
+  "Request-URI Too Long": "Request-URI Too Long",\n
+  "Unsupported Media Type": "Unsupported Media Type",\n
+  "Requested Range Not Satisfiable": "Requested Range Not Satisfiable",\n
+  "Expectation Failed": "Expectation Failed",\n
+  "I\'m a teapot": "I\'m a teapot",\n
+  "Authentication Timeout": "Authentication Timeout",\n
+  "Internal Server Error": "Internal Server Error",\n
+  "Not Implemented": "Not Implemented",\n
+  "Bad Gateway": "Bad Gateway",\n
+  "Service Unavailable": "Service Unavailable",\n
+  "Gateway Timeout": "Gateway Timeout",\n
+  "Insufficient Storage": "Insufficient Storage",\n
+\n
+  "ok": "Ok",\n
+  "created": "Created",\n
+  "no_content": "No Content",\n
+  "reset_content": "Reset Content",\n
+  "partial_content": "Partial Content",\n
+  "not_modified": "Not Modified",\n
+  "bad_request": "Bad Request",\n
+  "unauthorized": "Unauthorized",\n
+  "payment_required": "Payment Required",\n
+  "forbidden": "Forbidden",\n
+  "not_found": "Not Found",\n
+  "method_not_allowed": "Method Not Allowed",\n
+  "not_acceptable": "Not Acceptable",\n
+  "proxy_authentication_required": "Proxy Authentication Required",\n
+  "request_timeout": "Request Timeout",\n
+  "conflict": "Conflict",\n
+  "gone": "Gone",\n
+  "length_required": "Length Required",\n
+  "precondition_failed": "Precondition Failed",\n
+  "request_entity_too_large": "Request Entity Too Large",\n
+  "request-uri_too_long": "Request-URI Too Long",\n
+  "unsupported_media_type": "Unsupported Media Type",\n
+  "requested_range_not_satisfiable": "Requested Range Not Satisfiable",\n
+  "expectation_failed": "Expectation Failed",\n
+  "im_a_teapot": "I\'m a teapot",\n
+  "authentication_timeout": "Authentication Timeout",\n
+  "internal_server_error": "Internal Server Error",\n
+  "not_implemented": "Not Implemented",\n
+  "bad_gateway": "Bad Gateway",\n
+  "service_unavailable": "Service Unavailable",\n
+  "gateway_timeout": "Gateway Timeout",\n
+  "insufficient_storage": "Insufficient Storage"\n
+};\n
+\n
+constants.http_status = {\n
+  "0": 0,\n
+  "550": 550,\n
+  "551": 551,\n
+  "555": 555,\n
+  "Unknown": 0,\n
+  "Internal JIO Error": 550,\n
+  "Internal Storage Error": 551,\n
+  "Cancelled": 555,\n
+  "unknown": 0,\n
+  "internal_jio_error": 550,\n
+  "internal_storage_error": 551,\n
+  "cancelled": 555,\n
+\n
+  "200": 200,\n
+  "201": 201,\n
+  "204": 204,\n
+  "205": 205,\n
+  "206": 206,\n
+  "304": 304,\n
+  "400": 400,\n
+  "401": 401,\n
+  "402": 402,\n
+  "403": 403,\n
+  "404": 404,\n
+  "405": 405,\n
+  "406": 406,\n
+  "407": 407,\n
+  "408": 408,\n
+  "409": 409,\n
+  "410": 410,\n
+  "411": 411,\n
+  "412": 412,\n
+  "413": 413,\n
+  "414": 414,\n
+  "415": 415,\n
+  "416": 416,\n
+  "417": 417,\n
+  "418": 418,\n
+  "419": 419,\n
+  "500": 500,\n
+  "501": 501,\n
+  "502": 502,\n
+  "503": 503,\n
+  "504": 504,\n
+  "507": 507,\n
+\n
+  "Ok": 200,\n
+  "OK": 200,\n
+  "Created": 201,\n
+  "No Content": 204,\n
+  "Reset Content": 205,\n
+  "Partial Content": 206,\n
+  "Not Modified": 304,\n
+  "Bad Request": 400,\n
+  "Unauthorized": 401,\n
+  "Payment Required": 402,\n
+  "Forbidden": 403,\n
+  "Not Found": 404,\n
+  "Method Not Allowed": 405,\n
+  "Not Acceptable": 406,\n
+  "Proxy Authentication Required": 407,\n
+  "Request Timeout": 408,\n
+  "Conflict": 409,\n
+  "Gone": 410,\n
+  "Length Required": 411,\n
+  "Precondition Failed": 412,\n
+  "Request Entity Too Large": 413,\n
+  "Request-URI Too Long": 414,\n
+  "Unsupported Media Type": 415,\n
+  "Requested Range Not Satisfiable": 416,\n
+  "Expectation Failed": 417,\n
+  "I\'m a teapot": 418,\n
+  "Authentication Timeout": 419,\n
+  "Internal Server Error": 500,\n
+  "Not Implemented": 501,\n
+  "Bad Gateway": 502,\n
+  "Service Unavailable": 503,\n
+  "Gateway Timeout": 504,\n
+  "Insufficient Storage": 507,\n
+\n
+  "ok": 200,\n
+  "created": 201,\n
+  "no_content": 204,\n
+  "reset_content": 205,\n
+  "partial_content": 206,\n
+  "not_modified": 304,\n
+  "bad_request": 400,\n
+  "unauthorized": 401,\n
+  "payment_required": 402,\n
+  "forbidden": 403,\n
+  "not_found": 404,\n
+  "method_not_allowed": 405,\n
+  "not_acceptable": 406,\n
+  "proxy_authentication_required": 407,\n
+  "request_timeout": 408,\n
+  "conflict": 409,\n
+  "gone": 410,\n
+  "length_required": 411,\n
+  "precondition_failed": 412,\n
+  "request_entity_too_large": 413,\n
+  "request-uri_too_long": 414,\n
+  "unsupported_media_type": 415,\n
+  "requested_range_not_satisfiable": 416,\n
+  "expectation_failed": 417,\n
+  "im_a_teapot": 418,\n
+  "authentication_timeout": 419,\n
+  "internal_server_error": 500,\n
+  "not_implemented": 501,\n
+  "bad_gateway": 502,\n
+  "service_unavailable": 503,\n
+  "gateway_timeout": 504,\n
+  "insufficient_storage": 507\n
+};\n
+\n
+constants.http_action = {\n
+  "0": "error",\n
+  "550": "error",\n
+  "551": "error",\n
+  "555": "error",\n
+  "Unknown": "error",\n
+  "Internal JIO Error": "error",\n
+  "Internal Storage Error": "error",\n
+  "Cancelled": "error",\n
+  "unknown": "error",\n
+  "internal_jio_error": "error",\n
+  "internal_storage_error": "error",\n
+  "cancelled": "error",\n
+\n
+  "200": "success",\n
+  "201": "success",\n
+  "204": "success",\n
+  "205": "success",\n
+  "206": "success",\n
+  "304": "success",\n
+  "400": "error",\n
+  "401": "error",\n
+  "402": "error",\n
+  "403": "error",\n
+  "404": "error",\n
+  "405": "error",\n
+  "406": "error",\n
+  "407": "error",\n
+  "408": "error",\n
+  "409": "error",\n
+  "410": "error",\n
+  "411": "error",\n
+  "412": "error",\n
+  "413": "error",\n
+  "414": "error",\n
+  "415": "error",\n
+  "416": "error",\n
+  "417": "error",\n
+  "418": "error",\n
+  "419": "retry",\n
+  "500": "retry",\n
+  "501": "error",\n
+  "502": "error",\n
+  "503": "retry",\n
+  "504": "retry",\n
+  "507": "error",\n
+\n
+  "Ok": "success",\n
+  "OK": "success",\n
+  "Created": "success",\n
+  "No Content": "success",\n
+  "Reset Content": "success",\n
+  "Partial Content": "success",\n
+  "Not Modified": "success",\n
+  "Bad Request": "error",\n
+  "Unauthorized": "error",\n
+  "Payment Required": "error",\n
+  "Forbidden": "error",\n
+  "Not Found": "error",\n
+  "Method Not Allowed": "error",\n
+  "Not Acceptable": "error",\n
+  "Proxy Authentication Required": "error",\n
+  "Request Timeout": "error",\n
+  "Conflict": "error",\n
+  "Gone": "error",\n
+  "Length Required": "error",\n
+  "Precondition Failed": "error",\n
+  "Request Entity Too Large": "error",\n
+  "Request-URI Too Long": "error",\n
+  "Unsupported Media Type": "error",\n
+  "Requested Range Not Satisfiable": "error",\n
+  "Expectation Failed": "error",\n
+  "I\'m a teapot": "error",\n
+  "Authentication Timeout": "retry",\n
+  "Internal Server Error": "retry",\n
+  "Not Implemented": "error",\n
+  "Bad Gateway": "error",\n
+  "Service Unavailable": "retry",\n
+  "Gateway Timeout": "retry",\n
+  "Insufficient Storage": "error",\n
+\n
+  "ok": "success",\n
+  "created": "success",\n
+  "no_content": "success",\n
+  "reset_content": "success",\n
+  "partial_content": "success",\n
+  "not_modified": "success",\n
+  "bad_request": "error",\n
+  "unauthorized": "error",\n
+  "payment_required": "error",\n
+  "forbidden": "error",\n
+  "not_found": "error",\n
+  "method_not_allowed": "error",\n
+  "not_acceptable": "error",\n
+  "proxy_authentication_required": "error",\n
+  "request_timeout": "error",\n
+  "conflict": "error",\n
+  "gone": "error",\n
+  "length_required": "error",\n
+  "precondition_failed": "error",\n
+  "request_entity_too_large": "error",\n
+  "request-uri_too_long": "error",\n
+  "unsupported_media_type": "error",\n
+  "requested_range_not_satisfiable": "error",\n
+  "expectation_failed": "error",\n
+  "im_a_teapot": "error",\n
+  "authentication_timeout": "retry",\n
+  "internal_server_error": "retry",\n
+  "not_implemented": "error",\n
+  "bad_gateway": "error",\n
+  "service_unavailable": "retry",\n
+  "gateway_timeout": "retry",\n
+  "insufficient_storage": "error"\n
+};\n
+\n
+constants.content_type_re =\n
+  /^([a-z]+\\/[a-zA-Z0-9\\+\\-\\.]+)(?:\\s*;\\s*charset\\s*=\\s*([a-zA-Z0-9\\-]+))?$/;\n
+\n
+/**\n
+ * Function that does nothing\n
+ */\n
+constants.emptyFunction = function () {\n
+  return;\n
+};\n
+\n
+defaults.job_rule_conditions = {};\n
+\n
+/**\n
+ * Adds some job rule conditions\n
+ */\n
+(function () {\n
+\n
+  /**\n
+   * Compare two jobs and test if they use the same storage description\n
+   *\n
+   * @param  {Object} a The first job to compare\n
+   * @param  {Object} b The second job to compare\n
+   * @return {Boolean} True if equal, else false\n
+   */\n
+  function sameStorageDescription(a, b) {\n
+    return uniqueJSONStringify(a.storage_spec) ===\n
+      uniqueJSONStringify(b.storage_spec);\n
+  }\n
+\n
+  /**\n
+   * Compare two jobs and test if they are writers\n
+   *\n
+   * @param  {Object} a The first job to compare\n
+   * @param  {Object} b The second job to compare\n
+   * @return {Boolean} True if equal, else false\n
+   */\n
+  function areWriters(a, b) {\n
+    return methodType(a.method) === \'writer\' &&\n
+      methodType(b.method) === \'writer\';\n
+  }\n
+\n
+  /**\n
+   * Compare two jobs and test if they use metadata only\n
+   *\n
+   * @param  {Object} a The first job to compare\n
+   * @param  {Object} b The second job to compare\n
+   * @return {Boolean} True if equal, else false\n
+   */\n
+  function useMetadataOnly(a, b) {\n
+    if ([\'post\', \'put\', \'get\', \'remove\', \'allDocs\'].indexOf(a.method) === -1) {\n
+      return false;\n
+    }\n
+    if ([\'post\', \'put\', \'get\', \'remove\', \'allDocs\'].indexOf(b.method) === -1) {\n
+      return false;\n
+    }\n
+    return true;\n
+  }\n
+\n
+  /**\n
+   * Compare two jobs and test if they are readers\n
+   *\n
+   * @param  {Object} a The first job to compare\n
+   * @param  {Object} b The second job to compare\n
+   * @return {Boolean} True if equal, else false\n
+   */\n
+  function areReaders(a, b) {\n
+    return methodType(a.method) === \'reader\' &&\n
+      methodType(b.method) === \'reader\';\n
+  }\n
+\n
+  /**\n
+   * Compare two jobs and test if their methods are the same\n
+   *\n
+   * @param  {Object} a The first job to compare\n
+   * @param  {Object} b The second job to compare\n
+   * @return {Boolean} True if equal, else false\n
+   */\n
+  function sameMethod(a, b) {\n
+    return a.method === b.method;\n
+  }\n
+\n
+  /**\n
+   * Compare two jobs and test if their document ids are the same\n
+   *\n
+   * @param  {Object} a The first job to compare\n
+   * @param  {Object} b The second job to compare\n
+   * @return {Boolean} True if equal, else false\n
+   */\n
+  function sameDocumentId(a, b) {\n
+    return a.kwargs._id === b.kwargs._id;\n
+  }\n
+\n
+  /**\n
+   * Test if the jobs have a document id.\n
+   *\n
+   * @param  {Object} a The first job to test\n
+   * @param  {Object} b The second job to test\n
+   * @return {Boolean} True if ids exist, else false\n
+   */\n
+  function haveDocumentIds(a, b) {\n
+    if (typeof a.kwargs._id !== "string" || a.kwargs._id === "") {\n
+      return false;\n
+    }\n
+    if (typeof b.kwargs._id !== "string" || b.kwargs._id === "") {\n
+      return false;\n
+    }\n
+    return true;\n
+  }\n
+\n
+  /**\n
+   * Compare two jobs and test if their kwargs are equal\n
+   *\n
+   * @param  {Object} a The first job to compare\n
+   * @param  {Object} b The second job to compare\n
+   * @return {Boolean} True if equal, else false\n
+   */\n
+  function sameParameters(a, b) {\n
+    return uniqueJSONStringify(a.kwargs) ===\n
+      uniqueJSONStringify(b.kwargs);\n
+  }\n
+\n
+  /**\n
+   * Compare two jobs and test if their options are equal\n
+   *\n
+   * @param  {Object} a The first job to compare\n
+   * @param  {Object} b The second job to compare\n
+   * @return {Boolean} True if equal, else false\n
+   */\n
+  function sameOptions(a, b) {\n
+    return uniqueJSONStringify(a.options) ===\n
+      uniqueJSONStringify(b.options);\n
+  }\n
+\n
+  defaults.job_rule_conditions = {\n
+    "sameStorageDescription": sameStorageDescription,\n
+    "areWriters": areWriters,\n
+    "areReaders": areReaders,\n
+    "useMetadataOnly": useMetadataOnly,\n
+    "sameMethod": sameMethod,\n
+    "sameDocumentId": sameDocumentId,\n
+    "sameParameters": sameParameters,\n
+    "sameOptions": sameOptions,\n
+    "haveDocumentIds": haveDocumentIds\n
+  };\n
+\n
+}());\n
+\n
+/*jslint indent: 2, maxlen: 80, nomen: true, sloppy: true */\n
+/*global exports, Blob, FileReader, RSVP, hex_sha256, XMLHttpRequest,\n
+  constants */\n
+\n
+/**\n
+ * Do not exports these tools unless they are not writable, not configurable.\n
+ */\n
+\n
+exports.util = {};\n
+\n
+/**\n
+ * Inherits the prototype methods from one constructor into another. The\n
+ * prototype of `constructor` will be set to a new object created from\n
+ * `superConstructor`.\n
+ *\n
+ * @param  {Function} constructor The constructor which inherits the super\n
+ *   one\n
+ * @param  {Function} superConstructor The super constructor\n
+ */\n
+function inherits(constructor, superConstructor) {\n
+  constructor.super_ = superConstructor;\n
+  constructor.prototype = Object.create(superConstructor.prototype, {\n
+    "constructor": {\n
+      "configurable": true,\n
+      "enumerable": false,\n
+      "writable": true,\n
+      "value": constructor\n
+    }\n
+  });\n
+}\n
+\n
+/**\n
+ * Clones jsonable object in depth\n
+ *\n
+ * @param  {A} object The jsonable object to clone\n
+ * @return {A} The cloned object\n
+ */\n
+function jsonDeepClone(object) {\n
+  var tmp = JSON.stringify(object);\n
+  if (tmp === undefined) {\n
+    return undefined;\n
+  }\n
+  return JSON.parse(tmp);\n
+}\n
+exports.util.jsonDeepClone = jsonDeepClone;\n
+\n
+/**\n
+ * Clones all native object in deep. Managed types: Object, Array, String,\n
+ * Number, Boolean, Function, null.\n
+ *\n
+ * It can also clone object which are serializable, like Date.\n
+ *\n
+ * To make a class serializable, you need to implement the `toJSON` function\n
+ * which returns a JSON representation of the object. The returned value is used\n
+ * as first parameter of the object constructor.\n
+ *\n
+ * @param  {A} object The object to clone\n
+ * @return {A} The cloned object\n
+ */\n
+function deepClone(object) {\n
+  var i, cloned;\n
+  if (Array.isArray(object)) {\n
+    cloned = [];\n
+    for (i = 0; i < object.length; i += 1) {\n
+      cloned[i] = deepClone(object[i]);\n
+    }\n
+    return cloned;\n
+  }\n
+  if (object === null) {\n
+    return null;\n
+  }\n
+  if (typeof object === \'object\') {\n
+    if (Object.getPrototypeOf(object) === Object.prototype) {\n
+      cloned = {};\n
+      for (i in object) {\n
+        if (object.hasOwnProperty(i)) {\n
+          cloned[i] = deepClone(object[i]);\n
+        }\n
+      }\n
+      return cloned;\n
+    }\n
+    if (object instanceof Date) {\n
+      // XXX this block is to enable phantomjs and browsers compatibility with\n
+      // Date.prototype.toJSON when it is an invalid date. In phantomjs, it\n
+      // returns `"Invalid Date"` but in browsers it returns `null`. In\n
+      // browsers, giving `null` as parameter to `new Date()` doesn\'t return an\n
+      // invalid date.\n
+\n
+      // Cloning a date with `return new Date(object)` has problems on Firefox.\n
+      // I don\'t know why...  (Tested on Firefox 23)\n
+\n
+      if (isFinite(object.getTime())) {\n
+        return new Date(object.toJSON());\n
+      }\n
+      return new Date("Invalid Date");\n
+    }\n
+    // clone serializable objects\n
+    if (typeof object.toJSON === \'function\') {\n
+      return new (Object.getPrototypeOf(object).constructor)(object.toJSON());\n
+    }\n
+    // cannot clone\n
+    return object;\n
+  }\n
+  return object;\n
+}\n
+exports.util.deepClone = deepClone;\n
+\n
+/**\n
+ * Update a dictionary by adding/replacing key values from another dict.\n
+ * Enumerable values equal to undefined are also used.\n
+ *\n
+ * @param  {Object} original The dict to update\n
+ * @param  {Object} other The other dict\n
+ * @return {Object} The updated original dict\n
+ */\n
+function dictUpdate(original, other) {\n
+  var k;\n
+  for (k in other) {\n
+    if (other.hasOwnProperty(k)) {\n
+      original[k] = other[k];\n
+    }\n
+  }\n
+  return original;\n
+}\n
+exports.util.dictUpdate = dictUpdate;\n
+\n
+/**\n
+ * Like \'dict.clear()\' in python. Delete all dict entries.\n
+ *\n
+ * @method dictClear\n
+ * @param  {Object} self The dict to clear\n
+ */\n
+function dictClear(dict) {\n
+  var i;\n
+  for (i in dict) {\n
+    if (dict.hasOwnProperty(i)) {\n
+      delete dict[i];\n
+      // dictClear(dict);\n
+      // break;\n
+    }\n
+  }\n
+}\n
+exports.util.dictClear = dictClear;\n
+\n
+/**\n
+ * Filter a dict to keep only values which keys are in `keys` list.\n
+ *\n
+ * @param  {Object} dict The dict to filter\n
+ * @param  {Array} keys The key list to keep\n
+ */\n
+function dictFilter(dict, keys) {\n
+  var i, buffer = [];\n
+  for (i = 0; i < keys.length; i += 1) {\n
+    buffer[i] = dict[keys[i]];\n
+  }\n
+  dictClear(dict);\n
+  for (i = 0; i < buffer.length; i += 1) {\n
+    dict[keys[i]] = buffer[i];\n
+  }\n
+}\n
+exports.util.dictFilter = dictFilter;\n
+\n
+/**\n
+ * Gets all elements of an array and classifies them in a dict of array.\n
+ * Dict keys are element types, and values are list of element of type \'key\'.\n
+ *\n
+ * @param  {Array} array The array of elements to pop\n
+ * @return {Object} The type dict\n
+ */\n
+function arrayValuesToTypeDict(array) {\n
+  var i, l, type_object = {}, type, v;\n
+  for (i = 0, l = array.length; i < l; i += 1) {\n
+    v = array[i];\n
+    type = Array.isArray(v) ? "array" : typeof v;\n
+    /*jslint ass: true */\n
+    (type_object[type] = type_object[type] || []).push(v);\n
+  }\n
+  return type_object;\n
+}\n
+\n
+/**\n
+ * An Universal Unique ID generator\n
+ *\n
+ * @return {String} The new UUID.\n
+ */\n
+function generateUuid() {\n
+  function S4() {\n
+    return (\'0000\' + Math.floor(\n
+      Math.random() * 0x10000 /* 65536 */\n
+    ).toString(16)).slice(-4);\n
+  }\n
+  return S4() + S4() + "-" +\n
+    S4() + "-" +\n
+    S4() + "-" +\n
+    S4() + "-" +\n
+    S4() + S4() + S4();\n
+}\n
+exports.util.generateUuid = generateUuid;\n
+\n
+/**\n
+ * Concatenate a `string` `n` times.\n
+ *\n
+ * @param  {String} string The string to concat\n
+ * @param  {Number} n The number of time to concat\n
+ * @return {String} The concatenated string\n
+ */\n
+function concatStringNTimes(string, n) {\n
+  /*jslint plusplus: true */\n
+  var res = "";\n
+  while (--n >= 0) { res += string; }\n
+  return res;\n
+}\n
+\n
+/**\n
+ * JSON stringify a value. Object keys are sorted in order to make a kind of\n
+ * deepEqual thanks to a simple string comparison.\n
+ *\n
+ *     JSON.stringify({"a": "b", "c": "d"}) ===\n
+ *       JSON.stringify({"c": "d", "a": "b"})                 // false\n
+ *\n
+ *     deepEqual({"a": "b", "c": "d"}, {"c": "d", "a": "b"}); // true\n
+ *\n
+ *     uniqueJSONStringify({"a": "b", "c": "d"}) ===\n
+ *       uniqueJSONStringify({"c": "d", "a": "b"})            // true\n
+ *\n
+ * @param  {Any} value The value to stringify\n
+ * @param  {Function,Array} [replacer] A function to replace values during parse\n
+ * @param  {String,Number} [space] Causes the result to be pretty-printed\n
+ * @return {String} The unique JSON stringified value\n
+ */\n
+function uniqueJSONStringify(value, replacer, space) {\n
+  var indent, key_value_space = "";\n
+  if (typeof space === "string") {\n
+    if (space !== "") {\n
+      indent = space;\n
+      key_value_space = " ";\n
+    }\n
+  } else if (typeof space === "number") {\n
+    if (isFinite(space) && space > 0) {\n
+      indent = concatStringNTimes(" ", space);\n
+      key_value_space = " ";\n
+    }\n
+  }\n
+\n
+  function uniqueJSONStringifyRec(key, value, deep) {\n
+    var i, l, res, my_space;\n
+    if (value && typeof value.toJSON === "function") {\n
+      value = value.toJSON();\n
+    }\n
+    if (typeof replacer === "function") {\n
+      value = replacer(key, value);\n
+    }\n
+\n
+    if (indent) {\n
+      my_space = concatStringNTimes(indent, deep);\n
+    }\n
+    if (Array.isArray(value)) {\n
+      res = [];\n
+      for (i = 0; i < value.length; i += 1) {\n
+        res[res.length] = uniqueJSONStringifyRec(i, value[i], deep + 1);\n
+        if (res[res.length - 1] === undefined) {\n
+          res[res.length - 1] = "null";\n
+        }\n
+      }\n
+      if (res.length === 0) { return "[]"; }\n
+      if (indent) {\n
+        return "[\\n" + my_space + indent +\n
+          res.join(",\\n" + my_space + indent) +\n
+          "\\n" + my_space + "]";\n
+      }\n
+      return "[" + res.join(",") + "]";\n
+    }\n
+    if (typeof value === "object" && value !== null) {\n
+      if (Array.isArray(replacer)) {\n
+        res = replacer.reduce(function (p, c) {\n
+          p.push(c);\n
+          return p;\n
+        }, []);\n
+      } else {\n
+        res = Object.keys(value);\n
+      }\n
+      res.sort();\n
+      for (i = 0, l = res.length; i < l; i += 1) {\n
+        key = res[i];\n
+        res[i] = uniqueJSONStringifyRec(key, value[key], deep + 1);\n
+        if (res[i] !== undefined) {\n
+          res[i] = JSON.stringify(key) + ":" + key_value_space + res[i];\n
+        } else {\n
+          res.splice(i, 1);\n
+          l -= 1;\n
+          i -= 1;\n
+        }\n
+      }\n
+      if (res.length === 0) { return "{}"; }\n
+      if (indent) {\n
+        return "{\\n" + my_space + indent +\n
+          res.join(",\\n" + my_space + indent) +\n
+          "\\n" + my_space + "}";\n
+      }\n
+      return "{" + res.join(",") + "}";\n
+    }\n
+    return JSON.stringify(value);\n
+  }\n
+  return uniqueJSONStringifyRec("", value, 0);\n
+}\n
+exports.util.uniqueJSONStringify = uniqueJSONStringify;\n
+\n
+function makeBinaryStringDigest(string) {\n
+  return \'sha256-\' + hex_sha256(string);\n
+}\n
+exports.util.makeBinaryStringDigest = makeBinaryStringDigest;\n
+\n
+function readBlobAsBinaryString(blob) {\n
+  var fr = new FileReader();\n
+  return new RSVP.Promise(function (resolve, reject, notify) {\n
+    fr.addEventListener("load", resolve);\n
+    fr.addEventListener("error", reject);\n
+    fr.addEventListener("progress", notify);\n
+    fr.readAsBinaryString(blob);\n
+  }, function () {\n
+    fr.abort();\n
+  });\n
+}\n
+exports.util.readBlobAsBinaryString = readBlobAsBinaryString;\n
+\n
+function readBlobAsArrayBuffer(blob) {\n
+  var fr = new FileReader();\n
+  return new RSVP.Promise(function (resolve, reject, notify) {\n
+    fr.addEventListener("load", resolve);\n
+    fr.addEventListener("error", reject);\n
+    fr.addEventListener("progress", notify);\n
+    fr.readAsArrayBuffer(blob);\n
+  }, function () {\n
+    fr.abort();\n
+  });\n
+}\n
+exports.util.readBlobAsArrayBuffer = readBlobAsArrayBuffer;\n
+\n
+function readBlobAsText(blob) {\n
+  var fr = new FileReader();\n
+  return new RSVP.Promise(function (resolve, reject, notify) {\n
+    fr.addEventListener("load", resolve);\n
+    fr.addEventListener("error", reject);\n
+    fr.addEventListener("progress", notify);\n
+    fr.readAsText(blob);\n
+  }, function () {\n
+    fr.abort();\n
+  });\n
+}\n
+exports.util.readBlobAsText = readBlobAsText;\n
+\n
+/**\n
+ * Send request with XHR and return a promise. xhr.onload: The promise is\n
+ * resolved when the status code is lower than 400 with the xhr object as first\n
+ * parameter. xhr.onerror: reject with xhr object as first\n
+ * parameter. xhr.onprogress: notifies the xhr object.\n
+ *\n
+ * @param  {Object} param The parameters\n
+ * @param  {String} [param.type="GET"] The request method\n
+ * @param  {String} [param.dataType=""] The data type to retrieve\n
+ * @param  {String} param.url The url\n
+ * @param  {Any} [param.data] The data to send\n
+ * @param  {Function} [param.beforeSend] A function called just before the send\n
+ *   request. The first parameter of this function is the XHR object.\n
+ * @return {Promise} The promise\n
+ */\n
+function ajax(param) {\n
+  var xhr = new XMLHttpRequest();\n
+  return new RSVP.Promise(function (resolve, reject, notify) {\n
+    var k;\n
+    xhr.open(param.type || "GET", param.url, true);\n
+    xhr.responseType = param.dataType || "";\n
+    if (typeof param.headers === \'object\' && param.headers !== null) {\n
+      for (k in param.headers) {\n
+        if (param.headers.hasOwnProperty(k)) {\n
+          xhr.setRequestHeader(k, param.headers[k]);\n
+        }\n
+      }\n
+    }\n
+    xhr.addEventListener("load", function (e) {\n
+      if (e.target.status >= 400) {\n
+        return reject(e);\n
+      }\n
+      resolve(e);\n
+    });\n
+    xhr.addEventListener("error", reject);\n
+    xhr.addEventListener("progress", notify);\n
+    if (typeof param.xhrFields === \'object\' && param.xhrFields !== null) {\n
+      for (k in param.xhrFields) {\n
+        if (param.xhrFields.hasOwnProperty(k)) {\n
+          xhr[k] = param.xhrFields[k];\n
+        }\n
+      }\n
+    }\n
+    if (typeof param.beforeSend === \'function\') {\n
+      param.beforeSend(xhr);\n
+    }\n
+    xhr.send(param.data);\n
+  }, function () {\n
+    xhr.abort();\n
+  });\n
+}\n
+exports.util.ajax = ajax;\n
+\n
+/**\n
+ * Acts like `Array.prototype.concat` but does not create a copy of the original\n
+ * array. It extends the original array and return it.\n
+ *\n
+ * @param  {Array} array The array to extend\n
+ * @param  {Any} [args]* Values to add in the array\n
+ * @return {Array} The original array\n
+ */\n
+function arrayExtend(array) { // args*\n
+  var i, j;\n
+  for (i = 1; i < arguments.length; i += 1) {\n
+    if (Array.isArray(arguments[i])) {\n
+      for (j = 0; j < arguments[i].length; j += 1) {\n
+        array[array.length] = arguments[i][j];\n
+      }\n
+    } else {\n
+      array[array.length] = arguments[i];\n
+    }\n
+  }\n
+  return array;\n
+}\n
+exports.util.arrayExtend = arrayExtend;\n
+\n
+/**\n
+ * Acts like `Array.prototype.concat` but does not create a copy of the original\n
+ * array. It extends the original array from a specific position and return it.\n
+ *\n
+ * @param  {Array} array The array to extend\n
+ * @param  {Number} position The position where to extend\n
+ * @param  {Any} [args]* Values to add in the array\n
+ * @return {Array} The original array\n
+ */\n
+function arrayInsert(array, position) { // args*\n
+  var array_part = array.splice(position, array.length - position);\n
+  arrayExtend.apply(null, arrayExtend([\n
+  ], [array], Array.prototype.slice.call(arguments, 2)));\n
+  return arrayExtend(array, array_part);\n
+}\n
+exports.util.arrayInsert = arrayInsert;\n
+\n
+/**\n
+ * Guess if the method is a writer or a reader.\n
+ *\n
+ * @param  {String} method The method name\n
+ * @return {String} "writer", "reader" or "unknown"\n
+ */\n
+function methodType(method) {\n
+  switch (method) {\n
+  case "post":\n
+  case "put":\n
+  case "putAttachment":\n
+  case "remove":\n
+  case "removeAttachment":\n
+  case "repair":\n
+    return \'writer\';\n
+  case "get":\n
+  case "getAttachment":\n
+  case "allDocs":\n
+  case "check":\n
+    return \'reader\';\n
+  default:\n
+    return \'unknown\';\n
+  }\n
+}\n
+\n
+/**\n
+ *     forEach(array, callback[, thisArg]): Promise\n
+ *\n
+ * It executes the provided `callback` once for each element of the array with\n
+ * an assigned value asynchronously. If the `callback` returns a promise, then\n
+ * the function will wait for its fulfillment before executing the next\n
+ * iteration.\n
+ *\n
+ * `callback` is invoked with three arguments:\n
+ *\n
+ * - the element value\n
+ * - the element index\n
+ * - the array being traversed\n
+ *\n
+ * If a `thisArg` parameter is provided to `forEach`, it will be passed to\n
+ * `callback` when invoked, for use as its `this` value.  Otherwise, the value\n
+ * `undefined` will be passed for use as its `this` value.\n
+ *\n
+ * Unlike `Array.prototype.forEach`, you can stop the iteration by throwing\n
+ * something, or by doing a `cancel` to the returned promise if it is\n
+ * cancellable promise.\n
+ *\n
+ * Inspired by `Array.prototype.forEach` from Mozilla Developer Network.\n
+ *\n
+ * @param  {Array} array The array to parse\n
+ * @param  {Function} callback Function to execute for each element.\n
+ * @param  {Any} [thisArg] Value to use as `this` when executing `callback`.\n
+ * @param  {Promise} A new promise.\n
+ */\n
+function forEach(array, fn, thisArg) {\n
+  if (arguments.length === 0) {\n
+    throw new TypeError("missing argument 0 when calling function forEach");\n
+  }\n
+  if (!Array.isArray(array)) {\n
+    throw new TypeError(array + " is not an array");\n
+  }\n
+  if (arguments.length === 1) {\n
+    throw new TypeError("missing argument 1 when calling function forEach");\n
+  }\n
+  if (typeof fn !== "function") {\n
+    throw new TypeError(fn + " is not a function");\n
+  }\n
+  var cancelled, current_promise = RSVP.resolve();\n
+  return new RSVP.Promise(function (done, fail, notify) {\n
+    var i = 0;\n
+    function next() {\n
+      if (cancelled) {\n
+        fail(new Error("Cancelled"));\n
+        return;\n
+      }\n
+      if (i < array.length) {\n
+        current_promise =\n
+          current_promise.then(fn.bind(thisArg, array[i], i, array));\n
+        current_promise.then(next, fail, notify);\n
+        i += 1;\n
+        return;\n
+      }\n
+      done();\n
+    }\n
+    next();\n
+  }, function () {\n
+    cancelled = true;\n
+    if (typeof current_promise.cancel === "function") {\n
+      current_promise.cancel();\n
+    }\n
+  });\n
+}\n
+exports.util.forEach = forEach;\n
+\n
+/**\n
+ *     range(stop, callback): Promise\n
+ *     range(start, stop[, step], callback): Promise\n
+ *\n
+ * It executes the provided `callback` once for each step between `start` and\n
+ * `stop`. If the `callback` returns a promise, then the function will wait\n
+ * for its fulfillment before executing the next iteration.\n
+ *\n
+ * `callback` is invoked with one argument:\n
+ *\n
+ * - the index of the step\n
+ *\n
+ * `start`, `stop` and `step` must be finite numbers. If `step` is not\n
+ * provided, then the default step will be `1`. If `start` and `step` are not\n
+ * provided, `start` will be `0` and `step` will be `1`.\n
+ *\n
+ * Inspired by `range()` from Python 3 built-in functions.\n
+ *\n
+ *     range(10, function (index) {\n
+ *       return notifyIndex(index);\n
+ *     }).then(onDone, onError, onNotify);\n
+ *\n
+ * @param  {Number} [start=0] The start index\n
+ * @param  {Number} stop The stop index\n
+ * @param  {Number} [step=1] One step\n
+ * @param  {Function} callback Function to execute on each iteration.\n
+ * @param  {Promise} A new promise with no fulfillment value.\n
+ */\n
+function range(start, stop, step, callback) {\n
+  var type_object, cancelled, current_promise;\n
+  type_object = arrayValuesToTypeDict([start, stop, step, callback]);\n
+\n
+  if (type_object["function"].length !== 1) {\n
+    throw new TypeError("range(): only one callback is needed");\n
+  }\n
+  start = type_object.number.length;\n
+  if (start < 1) {\n
+    throw new TypeError("range(): 1, 2 or 3 numbers are needed");\n
+  }\n
+  if (start > 3) {\n
+    throw new TypeError("range(): only 1, 2 or 3 numbers are needed");\n
+  }\n
+\n
+  callback = type_object["function"][0];\n
+\n
+  if (start === 1) {\n
+    start = 0;\n
+    stop = type_object.number[0];\n
+    step = 1;\n
+  }\n
+\n
+  if (start === 2) {\n
+    start = type_object.number[0];\n
+    stop = type_object.number[1];\n
+    step = 1;\n
+  }\n
+\n
+  if (start === 3) {\n
+    start = type_object.number[0];\n
+    stop = type_object.number[1];\n
+    step = type_object.number[2];\n
+    if (step === 0) {\n
+      throw new TypeError("range(): step must not be zero");\n
+    }\n
+  }\n
+\n
+  type_object = undefined;\n
+  current_promise = RSVP.resolve();\n
+  return new RSVP.Promise(function (done, fail, notify) {\n
+    var i = start, test;\n
+    function next() {\n
+      if (cancelled) {\n
+        fail(new Error("Cancelled"));\n
+        return;\n
+      }\n
+      test = step > 0 ? i < stop : i > stop;\n
+      if (test) {\n
+        current_promise = current_promise.then(callback.bind(null, i));\n
+        current_promise.then(next, fail, notify);\n
+        i += step;\n
+        return;\n
+      }\n
+      done();\n
+    }\n
+    next();\n
+  }, function () {\n
+    cancelled = true;\n
+    if (typeof current_promise.cancel === "function") {\n
+      current_promise.cancel();\n
+    }\n
+  });\n
+}\n
+exports.util.range = range;\n
+\n
+/*jslint indent: 2, maxlen: 80, nomen: true, sloppy: true */\n
+/*global secureMethods, exports, console */\n
+\n
+/**\n
+ * Inspired by nodejs EventEmitter class\n
+ * http://nodejs.org/api/events.html\n
+ *\n
+ * When an EventEmitter instance experiences an error, the typical action is\n
+ * to emit an \'error\' event. Error events are treated as a special case in\n
+ * node. If there is no listener for it, then the default action throws the\n
+ * exception again.\n
+ *\n
+ * All EventEmitters emit the event \'newListener\' when new listeners are added\n
+ * and \'removeListener\' when a listener is removed.\n
+ *\n
+ * @class EventEmitter\n
+ * @constructor\n
+ */\n
+function EventEmitter() {\n
+  this._events = {};\n
+  this._maxListeners = 10;\n
+}\n
+\n
+/**\n
+ * Adds a listener to the end of the listeners array for the specified\n
+ * event.\n
+ *\n
+ * @method addListener\n
+ * @param  {String} event The event name\n
+ * @param  {Function} listener The listener callback\n
+ * @return {EventEmitter} This emitter\n
+ */\n
+EventEmitter.prototype.addListener = function (event, listener) {\n
+  var listener_list;\n
+  if (typeof listener !== "function") {\n
+    return this;\n
+  }\n
+  this.emit("newListener", event, listener);\n
+  listener_list = this._events[event];\n
+  if (listener_list === undefined) {\n
+    this._events[event] = listener;\n
+    listener_list = listener;\n
+  } else if (typeof listener_list === "function") {\n
+    this._events[event] = [listener_list, listener];\n
+    listener_list = this._events[event];\n
+  } else {\n
+    listener_list[listener_list.length] = listener;\n
+  }\n
+  if (this._maxListeners > 0 &&\n
+      typeof listener_list !== "function" &&\n
+      listener_list.length > this._maxListeners &&\n
+      listener_list.warned !== true) {\n
+    console.warn("warning: possible EventEmitter memory leak detected. " +\n
+                 listener_list.length + " listeners added. " +\n
+                 "Use emitter.setMaxListeners() to increase limit.");\n
+    listener_list.warned = true;\n
+  }\n
+  return this;\n
+};\n
+\n
+/**\n
+ * #crossLink "EventEmitter/addListener:method"\n
+ *\n
+ * @method on\n
+ */\n
+EventEmitter.prototype.on = EventEmitter.prototype.addListener;\n
+\n
+/**\n
+ * Adds a one time listener for the event. This listener is invoked only the\n
+ * next time the event is fired, after which it is removed.\n
+ *\n
+ * @method once\n
+ * @param  {String} event The event name\n
+ * @param  {Function} listener The listener callback\n
+ * @return {EventEmitter} This emitter\n
+ */\n
+EventEmitter.prototype.once = function (event, listener) {\n
+  var that = this, wrapper = function () {\n
+    that.removeListener(event, wrapper);\n
+    listener.apply(that, arguments);\n
+  };\n
+  wrapper.original = listener;\n
+  return that.on(event, wrapper);\n
+};\n
+\n
+/**\n
+ * Remove a listener from the listener array for the specified event.\n
+ * Caution: changes array indices in the listener array behind the listener\n
+ *\n
+ * @method removeListener\n
+ * @param  {String} event The event name\n
+ * @param  {Function} listener The listener callback\n
+ * @return {EventEmitter} This emitter\n
+ */\n
+EventEmitter.prototype.removeListener = function (event, listener) {\n
+  var listener_list = this._events[event], i;\n
+  if (listener_list) {\n
+    if (typeof listener_list === "function") {\n
+      if (listener_list === listener || listener_list.original === listener) {\n
+        delete this._events[event];\n
+      }\n
+      return this;\n
+    }\n
+    for (i = 0; i < listener_list.length; i += 1) {\n
+      if (listener_list[i] === listener ||\n
+          listener_list[i].original === listener) {\n
+        listener_list.splice(i, 1);\n
+        this.emit("removeListener", event, listener);\n
+        break;\n
+      }\n
+    }\n
+    if (listener_list.length === 1) {\n
+      this._events[event] = listener_list[0];\n
+    }\n
+    if (listener_list.length === 0) {\n
+      this._events[event] = undefined;\n
+    }\n
+  }\n
+  return this;\n
+};\n
+\n
+/**\n
+ * Removes all listeners, or those of the specified event.\n
+ *\n
+ * @method removeAllListeners\n
+ * @param  {String} event The event name (optional)\n
+ * @return {EventEmitter} This emitter\n
+ */\n
+EventEmitter.prototype.removeAllListeners = function (event) {\n
+  var key;\n
+  if (event === undefined) {\n
+    for (key in this._events) {\n
+      if (this._events.hasOwnProperty(key)) {\n
+        delete this._events[key];\n
+      }\n
+    }\n
+    return this;\n
+  }\n
+  delete this._events[event];\n
+  return this;\n
+};\n
+\n
+/**\n
+ * By default EventEmitters will print a warning if more than 10 listeners\n
+ * are added for a particular event. This is a useful default which helps\n
+ * finding memory leaks. Obviously not all Emitters should be limited to 10.\n
+ * This function allows that to be increased. Set to zero for unlimited.\n
+ *\n
+ * @method setMaxListeners\n
+ * @param  {Number} max_listeners The maximum of listeners\n
+ */\n
+EventEmitter.prototype.setMaxListeners = function (max_listeners) {\n
+  this._maxListeners = max_listeners;\n
+};\n
+\n
+/**\n
+ * Execute each of the listeners in order with the supplied arguments.\n
+ *\n
+ * @method emit\n
+ * @param  {String} event The event name\n
+ * @param  {Any} [args]* The listener argument to give\n
+ * @return {Boolean} true if event had listeners, false otherwise.\n
+ */\n
+EventEmitter.prototype.emit = function (event) {\n
+  var i, argument_list, listener_list;\n
+  listener_list = this._events[event];\n
+  if (typeof listener_list === \'function\') {\n
+    listener_list = [listener_list];\n
+  } else if (Array.isArray(listener_list)) {\n
+    listener_list = listener_list.slice();\n
+  } else {\n
+    return false;\n
+  }\n
+  argument_list = Array.prototype.slice.call(arguments, 1);\n
+  for (i = 0; i < listener_list.length; i += 1) {\n
+    try {\n
+      listener_list[i].apply(this, argument_list);\n
+    } catch (e) {\n
+      if (this.listeners("error").length > 0) {\n
+        this.emit("error", e);\n
+        break;\n
+      }\n
+      throw e;\n
+    }\n
+  }\n
+  return true;\n
+};\n
+\n
+/**\n
+ * Returns an array of listeners for the specified event.\n
+ *\n
+ * @method listeners\n
+ * @param  {String} event The event name\n
+ * @return {Array} The array of listeners\n
+ */\n
+EventEmitter.prototype.listeners = function (event) {\n
+  return (typeof this._events[event] === \'function\' ?\n
+          [this._events[event]] : (this._events[event] || []).slice());\n
+};\n
+\n
+/**\n
+ * Static method; Return the number of listeners for a given event.\n
+ *\n
+ * @method listenerCount\n
+ * @static\n
+ * @param  {EventEmitter} emitter The event emitter\n
+ * @param  {String} event The event name\n
+ * @return {Number} The number of listener\n
+ */\n
+EventEmitter.listenerCount = function (emitter, event) {\n
+  return emitter.listeners(event).length;\n
+};\n
+\n
+exports.EventEmitter = EventEmitter;\n
+\n
+/*jslint indent: 2, maxlen: 80, nomen: true, sloppy: true */\n
+/*global EventEmitter, deepClone, inherits, exports */\n
+/*global enableRestAPI, enableRestParamChecker, enableJobMaker, enableJobRetry,\n
+  enableJobReference, enableJobChecker, enableJobQueue, enableJobRecovery,\n
+  enableJobTimeout, enableJobExecuter */\n
+\n
+function JIO(storage_spec, options) {\n
+  JIO.super_.call(this);\n
+  var shared = new EventEmitter();\n
+\n
+  shared.storage_spec = deepClone(storage_spec);\n
+\n
+  if (options === undefined) {\n
+    options = {};\n
+  } else if (typeof options !== \'object\' || Array.isArray(options)) {\n
+    throw new TypeError("JIO(): Optional argument 2 is not of type \'object\'");\n
+  }\n
+\n
+  enableRestAPI(this, shared, options);\n
+  enableRestParamChecker(this, shared, options);\n
+  enableJobMaker(this, shared, options);\n
+  enableJobReference(this, shared, options);\n
+  enableJobRetry(this, shared, options);\n
+  enableJobTimeout(this, shared, options);\n
+  enableJobChecker(this, shared, options);\n
+  enableJobQueue(this, shared, options);\n
+  enableJobRecovery(this, shared, options);\n
+  enableJobExecuter(this, shared, options);\n
+\n
+  shared.emit(\'load\');\n
+}\n
+inherits(JIO, EventEmitter);\n
+\n
+JIO.createInstance = function (storage_spec, options) {\n
+  return new JIO(storage_spec, options);\n
+};\n
+\n
+exports.JIO = JIO;\n
+\n
+exports.createJIO = JIO.createInstance;\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global deepClone, dictFilter, uniqueJSONStringify */\n
+\n
+/**\n
+ * Tool to manipulate a list of object containing at least one property: \'id\'.\n
+ * Id must be a number > 0.\n
+ *\n
+ * @class JobQueue\n
+ * @constructor\n
+ * @param  {Workspace} workspace The workspace where to store\n
+ * @param  {String} namespace The namespace to use in the workspace\n
+ * @param  {Array} job_keys An array of job keys to store\n
+ * @param  {Array} [array] An array of object\n
+ */\n
+function JobQueue(workspace, namespace, job_keys, array) {\n
+  this._workspace = workspace;\n
+  this._namespace = namespace;\n
+  this._job_keys = job_keys;\n
+  if (Array.isArray(array)) {\n
+    this._array = array;\n
+  } else {\n
+    this._array = [];\n
+  }\n
+}\n
+\n
+/**\n
+ * Store the job queue into the workspace.\n
+ *\n
+ * @method save\n
+ */\n
+JobQueue.prototype.save = function () {\n
+  var i, job_queue = deepClone(this._array);\n
+  for (i = 0; i < job_queue.length; i += 1) {\n
+    dictFilter(job_queue[i], this._job_keys);\n
+  }\n
+  if (this._array.length === 0) {\n
+    this._workspace.removeItem(this._namespace);\n
+  } else {\n
+    this._workspace.setItem(\n
+      this._namespace,\n
+      uniqueJSONStringify(job_queue)\n
+    );\n
+  }\n
+  return this;\n
+};\n
+\n
+/**\n
+ * Loads the job queue from the workspace.\n
+ *\n
+ * @method load\n
+ */\n
+JobQueue.prototype.load = function () {\n
+  var job_list;\n
+  try {\n
+    job_list = JSON.parse(this._workspace.getItem(this._namespace));\n
+  } catch (ignore) {}\n
+  if (!Array.isArray(job_list)) {\n
+    job_list = [];\n
+  }\n
+  this.clear();\n
+  new JobQueue(job_list).repair();\n
+  this.update(job_list);\n
+  return this;\n
+};\n
+\n
+/**\n
+ * Returns the array version of the job queue\n
+ *\n
+ * @method asArray\n
+ * @return {Array} The job queue as array\n
+ */\n
+JobQueue.prototype.asArray = function () {\n
+  return this._array;\n
+};\n
+\n
+/**\n
+ * Removes elements which are not objects containing at least \'id\' property.\n
+ *\n
+ * @method repair\n
+ */\n
+JobQueue.prototype.repair = function () {\n
+  var i, job;\n
+  for (i = 0; i < this._array.length; i += 1) {\n
+    job = this._array[i];\n
+    if (typeof job !== \'object\' || Array.isArray(job) ||\n
+        typeof job.id !== \'number\' || job.id <= 0) {\n
+      this._array.splice(i, 1);\n
+      i -= 1;\n
+    }\n
+  }\n
+};\n
+\n
+/**\n
+ * Post an object and generate an id\n
+ *\n
+ * @method post\n
+ * @param  {Object} job The job object\n
+ * @return {Number} The generated id\n
+ */\n
+JobQueue.prototype.post = function (job) {\n
+  var i, next = 1;\n
+  // get next id\n
+  for (i = 0; i < this._array.length; i += 1) {\n
+    if (this._array[i].id >= next) {\n
+      next = this._array[i].id + 1;\n
+    }\n
+  }\n
+  job.id = next;\n
+  this._array[this._array.length] = deepClone(job);\n
+  return this;\n
+};\n
+\n
+/**\n
+ * Put an object to the list. If an object contains the same id, it is replaced\n
+ * by the new one.\n
+ *\n
+ * @method put\n
+ * @param  {Object} job The job object with an id\n
+ */\n
+JobQueue.prototype.put = function (job) {\n
+  var i;\n
+  if (typeof job.id !== \'number\' || job.id <= 0) {\n
+    throw new TypeError("JobQueue().put(): Job id should be a positive number");\n
+  }\n
+  for (i = 0; i < this._array.length; i += 1) {\n
+    if (this._array[i].id === job.id) {\n
+      break;\n
+    }\n
+  }\n
+  this._array[i] = deepClone(job);\n
+  return this;\n
+};\n
+\n
+/**\n
+ * Puts some object into the list. Update object with the same id, and add\n
+ * unreferenced one.\n
+ *\n
+ * @method update\n
+ * @param  {Array} job_list A list of new jobs\n
+ */\n
+JobQueue.prototype.update = function (job_list) {\n
+  var i, j = 0, j_max, index = {}, next = 1, job, post_list = [];\n
+  j_max = this._array.length;\n
+  for (i = 0; i < job_list.length; i += 1) {\n
+    if (typeof job_list[i].id !== \'number\' || job_list[i].id <= 0) {\n
+      // this job has no id, it has to be post\n
+      post_list[post_list.length] = job_list[i];\n
+    } else {\n
+      job = deepClone(job_list[i]);\n
+      if (index[job.id] !== undefined) {\n
+        // this job is on the list, update\n
+        this._array[index[job.id]] = job;\n
+      } else if (j === j_max) {\n
+        // this job is not on the list, update\n
+        this._array[this._array.length] = job;\n
+      } else {\n
+        // don\'t if the job is there or not\n
+        // searching same job in the original list\n
+        while (j < j_max) {\n
+          // references visited job\n
+          index[this._array[j].id] = j;\n
+          if (this._array[j].id >= next) {\n
+            next = this._array[j].id + 1;\n
+          }\n
+          if (this._array[j].id === job.id) {\n
+            // found on the list, just update\n
+            this._array[j] = job;\n
+            break;\n
+          }\n
+          j += 1;\n
+        }\n
+        if (j === j_max) {\n
+          // not found on the list, add to the end\n
+          this._array[this._array.length] = job;\n
+        } else {\n
+          // found on the list, already updated\n
+          j += 1;\n
+        }\n
+      }\n
+      if (job.id >= next) {\n
+        next = job.id + 1;\n
+      }\n
+    }\n
+  }\n
+  for (i = 0; i < post_list.length; i += 1) {\n
+    // adding job without id\n
+    post_list[i].id = next;\n
+    next += 1;\n
+    this._array[this._array.length] = deepClone(post_list[i]);\n
+  }\n
+  return this;\n
+};\n
+\n
+/**\n
+ * Get an object from an id. Returns undefined if not found\n
+ *\n
+ * @method get\n
+ * @param  {Number} id The job id\n
+ * @return {Object} The job or undefined\n
+ */\n
+JobQueue.prototype.get = function (id) {\n
+  var i;\n
+  for (i = 0; i < this._array.length; i += 1) {\n
+    if (this._array[i].id === id) {\n
+      return deepClone(this._array[i]);\n
+    }\n
+  }\n
+};\n
+\n
+/**\n
+ * Removes an object from an id\n
+ *\n
+ * @method remove\n
+ * @param  {Number} id The job id\n
+ */\n
+JobQueue.prototype.remove = function (id) {\n
+  var i;\n
+  for (i = 0; i < this._array.length; i += 1) {\n
+    if (this._array[i].id === id) {\n
+      this._array.splice(i, 1);\n
+      return true;\n
+    }\n
+  }\n
+  return false;\n
+};\n
+\n
+/**\n
+ * Clears the list.\n
+ *\n
+ * @method clear\n
+ */\n
+JobQueue.prototype.clear = function () {\n
+  this._array.length = 0;\n
+  return this;\n
+};\n
+\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true */\n
+/*global localStorage */\n
+\n
+// keywords: js, javascript, store on local storage as array\n
+\n
+function LocalStorageArray(namespace) {\n
+  var index, next;\n
+\n
+  function nextId() {\n
+    var i = next;\n
+    next += 1;\n
+    return i;\n
+  }\n
+\n
+  this.length = function () {\n
+    return index.length;\n
+  };\n
+\n
+  this.truncate = function (length) {\n
+    var i;\n
+    if (length === index.length) {\n
+      return this;\n
+    }\n
+    if (length > index.length) {\n
+      index.length = length;\n
+      localStorage[namespace + \'.index\'] = JSON.stringify(index);\n
+      return this;\n
+    }\n
+    while (length < index.length) {\n
+      i = index.pop();\n
+      if (i !== undefined && i !== null) {\n
+        delete localStorage[namespace + \'.\' + i];\n
+      }\n
+    }\n
+    localStorage[namespace + \'.index\'] = JSON.stringify(index);\n
+    return this;\n
+  };\n
+\n
+  this.get = function (i) {\n
+    return JSON.parse(localStorage[namespace + \'.\' + index[i]] || \'null\');\n
+  };\n
+\n
+  this.set = function (i, value) {\n
+    if (index[i] === undefined || index[i] === null) {\n
+      index[i] = nextId();\n
+      localStorage[namespace + \'.\' + index[i]] = JSON.stringify(value);\n
+      localStorage[namespace + \'.index\'] = JSON.stringify(index);\n
+    } else {\n
+      localStorage[namespace + \'.\' + index[i]] = JSON.stringify(value);\n
+    }\n
+    return this;\n
+  };\n
+\n
+  this.append = function (value) {\n
+    index[index.length] = nextId();\n
+    localStorage[namespace + \'.\' + index[index.length - 1]] =\n
+      JSON.stringify(value);\n
+    localStorage[namespace + \'.index\'] = JSON.stringify(index);\n
+    return this;\n
+  };\n
+\n
+  this.pop = function (i) {\n
+    var value, key;\n
+    if (i === undefined || i === null) {\n
+      key = namespace + \'.\' + index[index.length - 1];\n
+      index.pop();\n
+    } else {\n
+      if (i < 0 || i >= index.length) {\n
+        return null;\n
+      }\n
+      key = namespace + \'.\' + i;\n
+      index.splice(i, 1);\n
+    }\n
+\n
+    value = localStorage[key];\n
+\n
+    if (index.length === 0) {\n
+      delete localStorage[namespace + \'.index\'];\n
+    } else {\n
+      localStorage[namespace + \'.index\'] = JSON.stringify(index);\n
+    }\n
+    delete localStorage[key];\n
+\n
+    return JSON.parse(value || \'null\');\n
+  };\n
+\n
+  this.clear = function () {\n
+    var i;\n
+    for (i = 0; i < index.length; i += 1) {\n
+      delete localStorage[namespace + \'.\' + index[i]];\n
+    }\n
+    index = [];\n
+    delete localStorage[namespace + \'.index\'];\n
+    return this;\n
+  };\n
+\n
+  this.reload = function () {\n
+    var i;\n
+    index = JSON.parse(localStorage[namespace + \'.index\'] || \'[]\');\n
+    next = 0;\n
+    for (i = 0; i < index.length; i += 1) {\n
+      if (next < index[i]) {\n
+        next = index[i];\n
+      }\n
+    }\n
+    return this;\n
+  };\n
+\n
+  this.toArray = function () {\n
+    var i, list = [];\n
+    for (i = 0; i < index.length; i += 1) {\n
+      list[list.length] = this.get(i);\n
+    }\n
+    return list;\n
+  };\n
+\n
+  this.update = function (list) {\n
+    if (!Array.isArray(list)) {\n
+      throw new TypeError("LocalStorageArray().saveArray(): " +\n
+                          "Argument 1 is not of type \'array\'");\n
+    }\n
+    var i, location;\n
+    // update previous values\n
+    for (i = 0; i < list.length; i += 1) {\n
+      location = index[i];\n
+      if (location === undefined || location === null) {\n
+        location = nextId();\n
+        index[i] = location;\n
+      }\n
+      localStorage[namespace + \'.\' + location] =\n
+        JSON.stringify(list[i]);\n
+    }\n
+    // remove last ones\n
+    while (list.length < index.length) {\n
+      location = index.pop();\n
+      if (location !== undefined && location !== null) {\n
+        delete localStorage[namespace + \'.\' + location];\n
+      }\n
+    }\n
+    // store index\n
+    localStorage[namespace + \'.index\'] = JSON.stringify(index);\n
+    return this;\n
+  };\n
+\n
+  this.reload();\n
+}\n
+\n
+LocalStorageArray.saveArray = function (namespace, list) {\n
+  if (!Array.isArray(list)) {\n
+    throw new TypeError("LocalStorageArray.saveArray(): " +\n
+                        "Argument 2 is not of type \'array\'");\n
+  }\n
+  var local_storage_array = new LocalStorageArray(namespace).clear(), i;\n
+  for (i = 0; i < list.length; i += 1) {\n
+    local_storage_array.append(list[i]);\n
+  }\n
+};\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global exports, deepClone, jsonDeepClone */\n
+\n
+/**\n
+ * A class to manipulate metadata\n
+ *\n
+ * @class Metadata\n
+ * @constructor\n
+ */\n
+function Metadata(metadata) {\n
+  if (arguments.length > 0) {\n
+    if (metadata === null || typeof metadata !== \'object\' ||\n
+        Array.isArray(metadata)) {\n
+      throw new TypeError("Metadata(): Optional argument 1 is not an object");\n
+    }\n
+    this._dict = metadata;\n
+  } else {\n
+    this._dict = {};\n
+  }\n
+}\n
+\n
+Metadata.prototype.format = function () {\n
+  return this.update(this._dict);\n
+};\n
+\n
+Metadata.prototype.check = function () {\n
+  var k;\n
+  for (k in this._dict) {\n
+    if (this._dict.hasOwnProperty(k)) {\n
+      if (k[0] !== \'_\') {\n
+        if (!Metadata.checkValue(this._dict[k])) {\n
+          return false;\n
+        }\n
+      }\n
+    }\n
+  }\n
+  return true;\n
+};\n
+\n
+Metadata.prototype.update = function (metadata) {\n
+  var k;\n
+  for (k in metadata) {\n
+    if (metadata.hasOwnProperty(k)) {\n
+      if (k[0] === \'_\') {\n
+        this._dict[k] = jsonDeepClone(metadata[k]);\n
+      } else {\n
+        this._dict[k] = Metadata.normalizeValue(metadata[k]);\n
+      }\n
+      if (this._dict[k] === undefined) {\n
+        delete this._dict[k];\n
+      }\n
+    }\n
+  }\n
+  return this;\n
+};\n
+\n
+Metadata.prototype.get = function (key) {\n
+  return this._dict[key];\n
+};\n
+\n
+Metadata.prototype.add = function (key, value) {\n
+  var i;\n
+  if (key[0] === \'_\') {\n
+    return this;\n
+  }\n
+  if (this._dict[key] === undefined) {\n
+    this._dict[key] = Metadata.normalizeValue(value);\n
+    if (this._dict[key] === undefined) {\n
+      delete this._dict[key];\n
+    }\n
+    return this;\n
+  }\n
+  if (!Array.isArray(this._dict[key])) {\n
+    this._dict[key] = [this._dict[key]];\n
+  }\n
+  value = Metadata.normalizeValue(value);\n
+  if (value === undefined) {\n
+    return this;\n
+  }\n
+  if (!Array.isArray(value)) {\n
+    value = [value];\n
+  }\n
+  for (i = 0; i < value.length; i += 1) {\n
+    this._dict[key][this._dict[key].length] = value[i];\n
+  }\n
+  return this;\n
+};\n
+\n
+Metadata.prototype.set = function (key, value) {\n
+  if (key[0] === \'_\') {\n
+    this._dict[key] = JSON.parse(JSON.stringify(value));\n
+  } else {\n
+    this._dict[key] = Metadata.normalizeValue(value);\n
+  }\n
+  if (this._dict[key] === undefined) {\n
+    delete this._dict[key];\n
+  }\n
+  return this;\n
+};\n
+\n
+Metadata.prototype.remove = function (key) {\n
+  delete this._dict[key];\n
+  return this;\n
+};\n
+\n
+\n
+Metadata.prototype.forEach = function (key, fun) {\n
+  var k, i, value, that = this;\n
+  if (typeof key === \'function\') {\n
+    fun = key;\n
+    key = undefined;\n
+  }\n
+  function forEach(key, fun) {\n
+    value = that._dict[key];\n
+    if (!Array.isArray(that._dict[key])) {\n
+      value = [value];\n
+    }\n
+    for (i = 0; i < value.length; i += 1) {\n
+      if (typeof value[i] === \'object\') {\n
+        fun.call(that, key, deepClone(value[i]), i);\n
+      } else {\n
+        fun.call(that, key, {\'content\': value[i]}, i);\n
+      }\n
+    }\n
+  }\n
+  if (key === undefined) {\n
+    for (k in this._dict) {\n
+      if (this._dict.hasOwnProperty(k)) {\n
+        forEach(k, fun);\n
+      }\n
+    }\n
+  } else {\n
+    forEach(key, fun);\n
+  }\n
+  return this;\n
+};\n
+\n
+Metadata.prototype.toFullDict = function () {\n
+  var dict = {};\n
+  this.forEach(function (key, value, index) {\n
+    dict[key] = dict[key] || [];\n
+    dict[key][index] = value;\n
+  });\n
+  return dict;\n
+};\n
+\n
+Metadata.asJsonableValue = function (value) {\n
+  switch (typeof value) {\n
+  case \'string\':\n
+  case \'boolean\':\n
+    return value;\n
+  case \'number\':\n
+    if (isFinite(value)) {\n
+      return value;\n
+    }\n
+    return null;\n
+  case \'object\':\n
+    if (value === null) {\n
+      return null;\n
+    }\n
+    if (value instanceof Date) {\n
+      // XXX this block is to enable phantomjs and browsers compatibility with\n
+      // Date.prototype.toJSON when it is a invalid date. In phantomjs, it\n
+      // returns `"Invalid Date"` but in browsers it returns `null`. Here, the\n
+      // result will always be `null`.\n
+      if (isNaN(value.getTime())) {\n
+        return null;\n
+      }\n
+    }\n
+    if (typeof value.toJSON === \'function\') {\n
+      return Metadata.asJsonableValue(value.toJSON());\n
+    }\n
+    return value; // dict, array\n
+  // case \'undefined\':\n
+  default:\n
+    return null;\n
+  }\n
+};\n
+\n
+Metadata.isDict = function (o) {\n
+  return typeof o === \'object\' &&\n
+    Object.getPrototypeOf(o || []) === Object.prototype;\n
+};\n
+\n
+Metadata.isContent = function (c) {\n
+  return typeof c === \'string\' ||\n
+    (typeof c === \'number\' && isFinite(c)) ||\n
+    typeof c === \'boolean\';\n
+};\n
+\n
+Metadata.contentValue = function (value) {\n
+  if (Array.isArray(value)) {\n
+    return Metadata.contentValue(value[0]);\n
+  }\n
+  if (Metadata.isDict(value)) {\n
+    return value.content;\n
+  }\n
+  return value;\n
+};\n
+\n
+Metadata.normalizeArray = function (value) {\n
+  var i;\n
+  value = value.slice();\n
+  i = 0;\n
+  while (i < value.length) {\n
+    value[i] = Metadata.asJsonableValue(value[i]);\n
+    if (Metadata.isDict(value[i])) {\n
+      value[i] = Metadata.normalizeObject(value[i]);\n
+      if (value[i] === undefined) {\n
+        value.splice(i, 1);\n
+      } else {\n
+        i += 1;\n
+      }\n
+    } else if (Metadata.isContent(value[i])) {\n
+      i += 1;\n
+    } else {\n
+      value.splice(i, 1);\n
+    }\n
+  }\n
+  if (value.length === 0) {\n
+    return;\n
+  }\n
+  if (value.length === 1) {\n
+    return value[0];\n
+  }\n
+  return value;\n
+};\n
+\n
+Metadata.normalizeObject = function (value) {\n
+  var i, count = 0, ok = false, new_value = {};\n
+  for (i in value) {\n
+    if (value.hasOwnProperty(i)) {\n
+      value[i] = Metadata.asJsonableValue(value[i]);\n
+      if (Metadata.isContent(value[i])) {\n
+        new_value[i] = value[i];\n
+        if (new_value[i] === undefined) {\n
+          delete new_value[i];\n
+        }\n
+        count += 1;\n
+        if (i === \'content\') {\n
+          ok = true;\n
+        }\n
+      }\n
+    }\n
+  }\n
+  if (ok === false) {\n
+    return;\n
+  }\n
+  if (count === 1) {\n
+    return new_value.content;\n
+  }\n
+  return new_value;\n
+};\n
+\n
+Metadata.normalizeValue = function (value) {\n
+  value = Metadata.asJsonableValue(value);\n
+  if (Metadata.isContent(value)) {\n
+    return value;\n
+  }\n
+  if (Array.isArray(value)) {\n
+    return Metadata.normalizeArray(value);\n
+  }\n
+  if (Metadata.isDict(value)) {\n
+    return Metadata.normalizeObject(value);\n
+  }\n
+};\n
+\n
+Metadata.checkArray = function (value) {\n
+  var i;\n
+  for (i = 0; i < value.length; i += 1) {\n
+    if (Metadata.isDict(value[i])) {\n
+      if (!Metadata.checkObject(value[i])) {\n
+        return false;\n
+      }\n
+    } else if (!Metadata.isContent(value[i])) {\n
+      return false;\n
+    }\n
+  }\n
+  return true;\n
+};\n
+\n
+Metadata.checkObject = function (value) {\n
+  var i, ok = false;\n
+  for (i in value) {\n
+    if (value.hasOwnProperty(i)) {\n
+      if (Metadata.isContent(value[i])) {\n
+        if (i === \'content\') {\n
+          ok = true;\n
+        }\n
+      } else {\n
+        return false;\n
+      }\n
+    }\n
+  }\n
+  if (ok === false) {\n
+    return false;\n
+  }\n
+  return true;\n
+};\n
+\n
+Metadata.checkValue = function (value) {\n
+  if (Metadata.isContent(value)) {\n
+    return true;\n
+  }\n
+  if (Array.isArray(value)) {\n
+    return Metadata.checkArray(value);\n
+  }\n
+  if (Metadata.isDict(value)) {\n
+    return Metadata.checkObject(value);\n
+  }\n
+  return false;\n
+};\n
+\n
+exports.Metadata = Metadata;\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global */\n
+\n
+/**\n
+ * An array that contain object (or array) references.\n
+ *\n
+ * @class ReferenceArray\n
+ * @constructor\n
+ * @param  {array} [array] The array where to work on\n
+ */\n
+function ReferenceArray(array) {\n
+  if (Array.isArray(array)) {\n
+    this._array = array;\n
+  } else {\n
+    this._array = [];\n
+  }\n
+}\n
+\n
+/**\n
+ * Returns the array version of the job queue\n
+ *\n
+ * @method asArray\n
+ * @return {Array} The job queue as array\n
+ */\n
+ReferenceArray.prototype.asArray = function () {\n
+  return this._array;\n
+};\n
+\n
+/**\n
+ * Returns the index of the object\n
+ *\n
+ * @method indexOf\n
+ * @param  {Object} object The object to search\n
+ */\n
+ReferenceArray.prototype.indexOf = function (object) {\n
+  var i;\n
+  for (i = 0; i < this._array.length; i += 1) {\n
+    if (this._array[i] === object) {\n
+      return i;\n
+    }\n
+  }\n
+  return -1;\n
+};\n
+\n
+/**\n
+ * Put an object to the list. If an object already exists, do nothing.\n
+ *\n
+ * @method put\n
+ * @param  {Object} object The object to add\n
+ */\n
+ReferenceArray.prototype.put = function (object) {\n
+  var i;\n
+  for (i = 0; i < this._array.length; i += 1) {\n
+    if (this._array[i] === object) {\n
+      return false;\n
+    }\n
+  }\n
+  this._array[i] = object;\n
+  return true;\n
+};\n
+\n
+/**\n
+ * Removes an object from the list\n
+ *\n
+ * @method remove\n
+ * @param  {Object} object The object to remove\n
+ */\n
+ReferenceArray.prototype.remove = function (object) {\n
+  var i;\n
+  for (i = 0; i < this._array.length; i += 1) {\n
+    if (this._array[i] === object) {\n
+      this._array.splice(i, 1);\n
+      return true;\n
+    }\n
+  }\n
+  return false;\n
+};\n
+\n
+/**\n
+ * Clears the list.\n
+ *\n
+ * @method clear\n
+ */\n
+ReferenceArray.prototype.clear = function () {\n
+  this._array.length = 0;\n
+  return this;\n
+};\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true */\n
+/*global exports, defaults */\n
+\n
+function Storage() { // (storage_spec, util)\n
+  return undefined; // this is a constructor\n
+}\n
+// end Storage\n
+\n
+function createStorage(storage_spec, util) {\n
+  if (typeof storage_spec.type !== \'string\') {\n
+    throw new TypeError("Invalid storage description");\n
+  }\n
+  if (!defaults.storage_types[storage_spec.type]) {\n
+    throw new TypeError("Unknown storage \'" + storage_spec.type + "\'");\n
+  }\n
+  return new defaults.storage_types[storage_spec.type](storage_spec, util);\n
+}\n
+\n
+function addStorage(type, Constructor) {\n
+  // var proto = {};\n
+  if (typeof type !== \'string\') {\n
+    throw new TypeError("jIO.addStorage(): Argument 1 is not of type \'string\'");\n
+  }\n
+  if (typeof Constructor !== \'function\') {\n
+    throw new TypeError("jIO.addStorage(): " +\n
+                        "Argument 2 is not of type \'function\'");\n
+  }\n
+  if (defaults.storage_types[type]) {\n
+    throw new TypeError("jIO.addStorage(): Storage type already exists");\n
+  }\n
+  // dictUpdate(proto, Constructor.prototype);\n
+  // inherits(Constructor, Storage);\n
+  // dictUpdate(Constructor.prototype, proto);\n
+  defaults.storage_types[type] = Constructor;\n
+}\n
+exports.addStorage = addStorage;\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global */\n
+\n
+/**\n
+ * A class that acts like localStorage on a simple object.\n
+ *\n
+ * Like localStorage, the object will contain only strings.\n
+ *\n
+ * @class Workspace\n
+ * @constructor\n
+ */\n
+function Workspace(object) {\n
+  this._object = object;\n
+}\n
+\n
+// // Too dangerous, never use it\n
+// /**\n
+//  * Empty the entire space.\n
+//  *\n
+//  * @method clear\n
+//  */\n
+// Workspace.prototype.clear = function () {\n
+//   var k;\n
+//   for (k in this._object) {\n
+//     if (this._object.hasOwnProperty(k)) {\n
+//       delete this._object;\n
+//     }\n
+//   }\n
+//   return undefined;\n
+// };\n
+\n
+/**\n
+ * Get an item from the space. If the value does not exists, it returns\n
+ * null. Else, it returns the string value.\n
+ *\n
+ * @method getItem\n
+ * @param  {String} key The location where to get the item\n
+ * @return {String} The item\n
+ */\n
+Workspace.prototype.getItem = function (key) {\n
+  return this._object[key] === undefined ? null : this._object[key];\n
+};\n
+\n
+/**\n
+ * Set an item into the space. The value to store is converted to string before.\n
+ *\n
+ * @method setItem\n
+ * @param  {String} key The location where to set the item\n
+ * @param  {Any} value The value to store\n
+ */\n
+Workspace.prototype.setItem = function (key, value) {\n
+  if (value === undefined) {\n
+    this._object[key] = \'undefined\';\n
+  } else if (value === null) {\n
+    this._object[key] = \'null\';\n
+  } else {\n
+    this._object[key] = value.toString();\n
+  }\n
+  return undefined;\n
+};\n
+\n
+/**\n
+ * Removes an item from the space.\n
+ *\n
+ * @method removeItem\n
+ * @param  {String} key The location where to remove the item\n
+ */\n
+Workspace.prototype.removeItem = function (key) {\n
+  delete this._object[key];\n
+  return undefined;\n
+};\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true */\n
+/*global exports, defaults */\n
+\n
+// adds\n
+// - jIO.addJobRuleCondition(name, function)\n
+\n
+function addJobRuleCondition(name, method) {\n
+  if (typeof name !== \'string\') {\n
+    throw new TypeError("jIO.addJobRuleAction(): " +\n
+                        "Argument 1 is not of type \'string\'");\n
+  }\n
+  if (typeof method !== \'function\') {\n
+    throw new TypeError("jIO.addJobRuleAction(): " +\n
+                        "Argument 2 is not of type \'function\'");\n
+  }\n
+  if (defaults.job_rule_conditions[name]) {\n
+    throw new TypeError("jIO.addJobRuleAction(): Action already exists");\n
+  }\n
+  defaults.job_rule_conditions[name] = method;\n
+}\n
+exports.addJobRuleCondition = addJobRuleCondition;\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, regexp: true */\n
+/*global constants, dictUpdate, deepClone, DOMException */\n
+\n
+function restCommandRejecter(param, args) {\n
+  // reject(status, reason, message, {"custom": "value"});\n
+  // reject(status, reason, {..});\n
+  // reject(status, {..});\n
+  var arg, current_priority, priority = [\n
+    // 0 - custom parameter values\n
+    {},\n
+    // 1 - default values\n
+    {\n
+      "status": constants.http_status.unknown,\n
+      "statusText": constants.http_status_text.unknown,\n
+      "message": "Command failed",\n
+      "reason": "unknown"\n
+    },\n
+    // 2 - status, reason, message properties\n
+    {},\n
+    // 3 - status, reason, message parameters\n
+    {},\n
+    // 4 - never change\n
+    {"result": "error", "method": param.method}\n
+  ];\n
+  args = Array.prototype.slice.call(args);\n
+  arg = args.shift();\n
+\n
+  // priority 4 - never change\n
+  current_priority = priority[4];\n
+  if (param.kwargs._id) {\n
+    current_priority.id = param.kwargs._id;\n
+  }\n
+  if (/Attachment$/.test(param.method)) {\n
+    current_priority.attachment = param.kwargs._attachment;\n
+  }\n
+\n
+  // priority 3 - status, reason, message parameters\n
+  current_priority = priority[3];\n
+  // parsing first parameter if is not an object\n
+  if (typeof arg !== \'object\' || arg === null || Array.isArray(arg)) {\n
+    // first parameter is mandatory\n
+    current_priority.status = arg;\n
+    arg = args.shift();\n
+  }\n
+  // parsing second parameter if is not an object\n
+  if (typeof arg !== \'object\' || arg === null || Array.isArray(arg)) {\n
+    if (arg !== undefined) {\n
+      current_priority.reason = arg;\n
+    }\n
+    arg = args.shift();\n
+  }\n
+  // parsing third parameter if is not an object\n
+  if (typeof arg !== \'object\' || arg === null || Array.isArray(arg)) {\n
+    if (arg !== undefined) {\n
+      current_priority.message = arg;\n
+    }\n
+    arg = args.shift();\n
+  }\n
+\n
+  // parsing fourth parameter if is an object\n
+  if (typeof arg === \'object\' && arg !== null && !Array.isArray(arg)) {\n
+    // priority 0 - custom values\n
+    dictUpdate(priority[0], arg);\n
+    // priority 2 - status, reason, message properties\n
+    current_priority = priority[2];\n
+    if (arg.hasOwnProperty(\'reason\')) {\n
+      current_priority.reason = arg.reason;\n
+    }\n
+    if (arg.hasOwnProperty(\'message\')) {\n
+      current_priority.message = arg.message;\n
+    }\n
+    if ((arg.statusText || arg.status >= 0)) {\n
+      current_priority.status = arg.statusText || arg.status;\n
+    }\n
+    if (arg instanceof Error || arg instanceof DOMException) {\n
+      if (arg.code !== undefined && arg.code !== null) {\n
+        current_priority.code = arg.code;\n
+      }\n
+      if (arg.lineNumber !== undefined && arg.lineNumber !== null) {\n
+        current_priority.lineNumber = arg.lineNumber;\n
+      }\n
+      if (arg.columnNumber !== undefined && arg.columnNumber !== null) {\n
+        current_priority.columnNumber = arg.columnNumber;\n
+      }\n
+      if (arg.filename !== undefined && arg.filename !== null) {\n
+        current_priority.filename = arg.filename;\n
+      }\n
+      if (arg.message !== undefined && arg.message !== null) {\n
+        current_priority.reason = arg.message;\n
+      }\n
+      current_priority.error = arg.name;\n
+    }\n
+  }\n
+\n
+  // merge priority dicts\n
+  for (current_priority = priority.length - 1;\n
+       current_priority > 0;\n
+       current_priority -= 1) {\n
+    dictUpdate(priority[current_priority - 1], priority[current_priority]);\n
+  }\n
+  priority = priority[0];\n
+\n
+  // check status\n
+  priority.statusText = constants.http_status_text[priority.status];\n
+  if (priority.statusText === undefined) {\n
+    return restCommandRejecter(param, [\n
+      // can create infernal loop if \'internal_storage_error\' is not defined in\n
+      // the constants\n
+      \'internal_storage_error\',\n
+      \'invalid response\',\n
+      \'Unknown status "\' + priority.status + \'"\'\n
+    ]);\n
+  }\n
+  priority.status = constants.http_status[priority.statusText];\n
+\n
+  // set default priority error if not already set\n
+  if (priority.error === undefined) {\n
+    priority.error = priority.statusText.toLowerCase().replace(/ /g, \'_\').\n
+      replace(/[^_a-z]/g, \'\');\n
+  }\n
+  param.storage_response = priority;\n
+  return param.solver.reject(deepClone(priority));\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global constants, methodType, dictUpdate, Blob, deepClone,\n
+  restCommandRejecter */\n
+\n
+function restCommandResolver(param, args) {\n
+  // resolve(\'ok\', {"custom": "value"});\n
+  // resolve(200, {...});\n
+  // resolve({...});\n
+  var arg, current_priority, priority = [\n
+    // 0 - custom parameter values\n
+    {},\n
+    // 1 - default values\n
+    {},\n
+    // 2 - status property\n
+    {},\n
+    // 3 - status parameter\n
+    {},\n
+    // 4 - never change\n
+    {"result": "success", "method": param.method}\n
+  ];\n
+  args = Array.prototype.slice.call(args);\n
+  arg = args.shift();\n
+\n
+  // priority 4 - never change\n
+  current_priority = priority[4];\n
+  if (param.kwargs._id) {\n
+    current_priority.id = param.kwargs._id;\n
+  }\n
+  if (/Attachment$/.test(param.method)) {\n
+    current_priority.attachment = param.kwargs._attachment;\n
+  }\n
+\n
+  // priority 1 - default values\n
+  current_priority = priority[1];\n
+  if (param.method === \'post\') {\n
+    current_priority.status = constants.http_status.created;\n
+    current_priority.statusText = constants.http_status_text.created;\n
+  } else if (methodType(param.method) === "writer" ||\n
+             param.method === "check") {\n
+    current_priority.status = constants.http_status.no_content;\n
+    current_priority.statusText = constants.http_status_text.no_content;\n
+  } else {\n
+    current_priority.status = constants.http_status.ok;\n
+    current_priority.statusText = constants.http_status_text.ok;\n
+  }\n
+\n
+  // priority 3 - status parameter\n
+  current_priority = priority[3];\n
+  // parsing first parameter if is not an object\n
+  if (typeof arg !== \'object\' || arg === null || Array.isArray(arg)) {\n
+    if (arg !== undefined) {\n
+      current_priority.status = arg;\n
+    }\n
+    arg = args.shift();\n
+  }\n
+\n
+  // parsing second parameter if is an object\n
+  if (typeof arg === \'object\' && arg !== null && !Array.isArray(arg)) {\n
+    // priority 0 - custom values\n
+    dictUpdate(current_priority, arg);\n
+    // priority 2 - status property\n
+    if (arg.hasOwnProperty("status") || arg.hasOwnProperty("statusText")) {\n
+      priority[2].status = arg.statusText || arg.status;\n
+    }\n
+  }\n
+\n
+  // merge priority dicts\n
+  for (current_priority = priority.length - 1;\n
+       current_priority > 0;\n
+       current_priority -= 1) {\n
+    dictUpdate(priority[current_priority - 1], priority[current_priority]);\n
+  }\n
+  priority = priority[0];\n
+\n
+  // check document id if post method\n
+  if (param.method === \'post\' &&\n
+      (typeof priority.id !== \'string\' || !priority.id)) {\n
+    return restCommandRejecter(param, [\n
+      \'internal_storage_error\',\n
+      \'invalid response\',\n
+      \'New document id have to be specified\'\n
+    ]);\n
+  }\n
+\n
+  // check status\n
+  priority.statusText = constants.http_status_text[priority.status];\n
+  if (priority.statusText === undefined) {\n
+    return restCommandRejecter(param, [\n
+      \'internal_storage_error\',\n
+      \'invalid response\',\n
+      \'Unknown status "\' + priority.status + \'"\'\n
+    ]);\n
+  }\n
+  priority.status = constants.http_status[priority.statusText];\n
+\n
+  // check data for get Attachment\n
+  if (param.method === \'getAttachment\') {\n
+    if (typeof priority.data === \'string\') {\n
+      priority.data = new Blob([priority.data], {\n
+        "type": priority.content_type || priority.mimetype || ""\n
+      });\n
+      delete priority.content_type;\n
+      delete priority.mimetype;\n
+    }\n
+    if (!(priority.data instanceof Blob)) {\n
+      return restCommandRejecter(param, [\n
+        \'internal_storage_error\',\n
+        \'invalid response\',\n
+        \'getAttachment method needs a Blob as returned "data".\'\n
+      ]);\n
+    }\n
+    // check data for readers (except check method)\n
+  } else if (methodType(param.method) === \'reader\' &&\n
+             param.method !== \'check\' &&\n
+             (typeof priority.data !== \'object\' ||\n
+              priority.data === null ||\n
+              Object.getPrototypeOf(priority.data) !== Object.prototype)) {\n
+    return restCommandRejecter(param, [\n
+      \'internal_storage_error\',\n
+      \'invalid response\',\n
+      param.method + \' method needs a dict as returned "data".\'\n
+    ]);\n
+  }\n
+\n
+  param.storage_response = priority;\n
+  return param.solver.resolve(deepClone(priority));\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */\n
+/*global arrayInsert, deepClone, defaults */\n
+\n
+// creates\n
+// - some defaults job rule actions\n
+\n
+function enableJobChecker(jio, shared, options) {\n
+\n
+  // dependencies\n
+  // - shared.jobs Object Array\n
+  // - param.promise Object\n
+\n
+  // creates\n
+  // - shared.job_rules Array\n
+\n
+  // uses \'job:new\' event\n
+  // emits \'job:modified\', \'job:start\', \'job:resolved\',\n
+  // \'job:end\', \'job:reject\' events\n
+\n
+  shared.job_rule_action_names = [undefined, "ok", "wait", "update", "deny"];\n
+\n
+  shared.job_rule_actions = {\n
+    wait: function (original_job, new_job) {\n
+      original_job.promise.always(function () {\n
+        new_job.state = \'ready\';\n
+        new_job.modified = new Date();\n
+        shared.emit(\'job:modified\', new_job);\n
+        shared.emit(\'job:start\', new_job);\n
+      });\n
+      new_job.state = \'waiting\';\n
+      new_job.modified = new Date();\n
+      shared.emit(\'job:modified\', new_job);\n
+    },\n
+    update: function (original_job, new_job) {\n
+      if (!new_job.solver) {\n
+        // promise associated to the job\n
+        new_job.state = \'done\';\n
+        shared.emit(\'job:resolved\', new_job, []); // XXX why resolve?\n
+        shared.emit(\'job:end\', new_job);\n
+      } else {\n
+        if (!original_job.solver) {\n
+          original_job.solver = new_job.solver;\n
+        } else {\n
+          original_job.promise.then(function () {\n
+            new_job.command.resolve(deepClone(original_job.storage_response));\n
+          }, function () {\n
+            new_job.command.reject(deepClone(original_job.storage_response));\n
+          }, new_job.command.notify);\n
+        }\n
+      }\n
+      new_job.state = \'running\';\n
+      new_job.modified = new Date();\n
+      shared.emit(\'job:modified\', new_job);\n
+    },\n
+    deny: function (original_job, new_job) {\n
+      new_job.state = "running";\n
+      shared.emit(\'job:reject\', new_job, [\n
+        \'precondition_failed\',\n
+        \'command denied\',\n
+        \'Command rejected by the job checker.\'\n
+      ]);\n
+    }\n
+  };\n
+\n
+  function addJobRule(job_rule) {\n
+    var i, old_position, before_position, after_position;\n
+    // job_rule = {\n
+    //   code_name: string\n
+    //   conditions: [string, ...]\n
+    //   action: \'wait\',\n
+    //   after: code_name\n
+    //   before: code_name\n
+    // }\n
+    if (typeof job_rule !== \'object\' || job_rule === null) {\n
+      // wrong job rule\n
+      return;\n
+    }\n
+    if (typeof job_rule.code_name !== \'string\') {\n
+      // wrong code name\n
+      return;\n
+    }\n
+    if (!Array.isArray(job_rule.conditions)) {\n
+      // wrong conditions\n
+      return;\n
+    }\n
+    if (job_rule.single !== undefined && typeof job_rule.single !== \'boolean\') {\n
+      // wrong single property\n
+      return;\n
+    }\n
+    if (shared.job_rule_action_names.indexOf(job_rule.action) === -1) {\n
+      // wrong action\n
+      return;\n
+    }\n
+    if (job_rule.action !== \'deny\' && job_rule.single === true) {\n
+      // only \'deny\' action doesn\'t require original_job parameter\n
+      return;\n
+    }\n
+\n
+    if (typeof job_rule.after !== \'string\') {\n
+      job_rule.after = \'\';\n
+    }\n
+    if (typeof job_rule.before !== \'string\') {\n
+      job_rule.before = \'\';\n
+    }\n
+\n
+    for (i = 0; i < shared.job_rules.length; i += 1) {\n
+      if (shared.job_rules[i].code_name === job_rule.after) {\n
+        after_position = i + 1;\n
+      }\n
+      if (shared.job_rules[i].code_name === job_rule.before) {\n
+        before_position = i;\n
+      }\n
+      if (shared.job_rules[i].code_name === job_rule.code_name) {\n
+        old_position = i;\n
+      }\n
+    }\n
+\n
+    job_rule = {\n
+      "code_name": job_rule.code_name,\n
+      "conditions": job_rule.conditions,\n
+      "single": job_rule.single || false,\n
+      "action": job_rule.action || "ok"\n
+    };\n
+\n
+    if (before_position === undefined) {\n
+      before_position = shared.job_rules.length;\n
+    }\n
+    if (after_position > before_position) {\n
+      before_position = undefined;\n
+    }\n
+    if (job_rule.action !== "ok" && before_position !== undefined) {\n
+      arrayInsert(shared.job_rules, before_position, job_rule);\n
+    }\n
+    if (old_position !== undefined) {\n
+      if (old_position >= before_position) {\n
+        old_position += 1;\n
+      }\n
+      shared.job_rules.splice(old_position, 1);\n
+    }\n
+  }\n
+\n
+  function jobsRespectConditions(original_job, new_job, conditions) {\n
+    var j;\n
+    // browsing conditions\n
+    for (j = 0; j < conditions.length; j += 1) {\n
+      if (defaults.job_rule_conditions[conditions[j]]) {\n
+        if (\n
+          !defaults.job_rule_conditions[conditions[j]](original_job, new_job)\n
+        ) {\n
+          return false;\n
+        }\n
+      }\n
+    }\n
+    return true;\n
+  }\n
+\n
+  function checkJob(job) {\n
+    var i, j;\n
+    if (job.state === \'ready\') {\n
+      // browsing rules\n
+      for (i = 0; i < shared.job_rules.length; i += 1) {\n
+        if (shared.job_rules[i].single) {\n
+          // no browse\n
+          if (\n
+            jobsRespectConditions(\n
+              job,\n
+              undefined,\n
+              shared.job_rules[i].conditions\n
+            )\n
+          ) {\n
+            shared.job_rule_actions[shared.job_rules[i].action](\n
+              undefined,\n
+              job\n
+            );\n
+            return;\n
+          }\n
+        } else {\n
+          // browsing jobs\n
+          for (j = shared.jobs.length - 1; j >= 0; j -= 1) {\n
+            if (shared.jobs[j] !== job) {\n
+              if (\n
+                jobsRespectConditions(\n
+                  shared.jobs[j],\n
+                  job,\n
+                  shared.job_rules[i].conditions\n
+                )\n
+              ) {\n
+                shared.job_rule_actions[shared.job_rules[i].action](\n
+                  shared.jobs[j],\n
+                  job\n
+                );\n
+                return;\n
+              }\n
+            }\n
+          }\n
+        }\n
+      }\n
+    }\n
+  }\n
+\n
+  var index;\n
+\n
+  if (options.job_management !== false) {\n
+\n
+    shared.job_rules = [{\n
+      "code_name": "readers update",\n
+      "conditions": [\n
+        "sameStorageDescription",\n
+        "areReaders",\n
+        "sameMethod",\n
+        "sameParameters",\n
+        "sameOptions"\n
+      ],\n
+      "action": "update"\n
+    }, {\n
+      "code_name": "metadata writers update",\n
+      "conditions": [\n
+        "sameStorageDescription",\n
+        "areWriters",\n
+        "useMetadataOnly",\n
+        "sameMethod",\n
+        "haveDocumentIds",\n
+        "sameParameters"\n
+      ],\n
+      "action": "update"\n
+    }, {\n
+      "code_name": "writers wait",\n
+      "conditions": [\n
+        "sameStorageDescription",\n
+        "areWriters",\n
+        "haveDocumentIds",\n
+        "sameDocumentId"\n
+      ],\n
+      "action": "wait"\n
+    }];\n
+\n
+    if (options.clear_job_rules === true) {\n
+      shared.job_rules.length = 0;\n
+    }\n
+\n
+    if (Array.isArray(options.job_rules)) {\n
+      for (index = 0; index < options.job_rules.length; index += 1) {\n
+        addJobRule(deepClone(options.job_rules[index]));\n
+      }\n
+    }\n
+\n
+    shared.on(\'job:new\', checkJob);\n
+\n
+  }\n
+\n
+  jio.jobRules = function () {\n
+    return deepClone(shared.job_rules);\n
+  };\n
+\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */\n
+/*global setTimeout, Job, createStorage, deepClone, restCommandResolver,\n
+  restCommandRejecter */\n
+\n
+function enableJobExecuter(jio, shared) { // , options) {\n
+\n
+  // uses \'job:new\' events\n
+  // uses actions \'job:resolve\', \'job:reject\' and \'job:notify\'\n
+\n
+  // emits \'job:modified\', \'job:started\', \'job:resolved\',\n
+  // \'job:rejected\', \'job:notified\' and \'job:end\' events\n
+  // emits action \'job:start\'\n
+\n
+  function startJobIfReady(job) {\n
+    if (job.state === \'ready\') {\n
+      shared.emit(\'job:start\', job);\n
+    }\n
+  }\n
+\n
+  function executeJobIfReady(param) {\n
+    var storage;\n
+    if (param.state === \'ready\') {\n
+      param.tried += 1;\n
+      param.started = new Date();\n
+      param.state = \'running\';\n
+      param.modified = new Date();\n
+      shared.emit(\'job:modified\', param);\n
+      shared.emit(\'job:started\', param);\n
+      try {\n
+        storage = createStorage(deepClone(param.storage_spec));\n
+      } catch (e) {\n
+        return param.command.reject(\n
+          \'internal_storage_error\',\n
+          \'invalid description\',\n
+          \'Check if the storage description respects the \' +\n
+            \'constraints provided by the storage designer. (\' +\n
+            e.name + ": " + e.message + \')\'\n
+        );\n
+      }\n
+      if (typeof storage[param.method] !== \'function\') {\n
+        return param.command.reject(\n
+          \'not_implemented\',\n
+          \'method missing\',\n
+          \'Storage "\' + param.storage_spec.type + \'", "\' +\n
+            param.method + \'" method is missing.\'\n
+        );\n
+      }\n
+      setTimeout(function () {\n
+        storage[param.method](\n
+          deepClone(param.command),\n
+          deepClone(param.kwargs),\n
+          deepClone(param.options)\n
+        );\n
+      });\n
+    }\n
+  }\n
+\n
+  function endAndResolveIfRunning(job, args) {\n
+    if (job.state === \'running\') {\n
+      job.state = \'done\';\n
+      job.modified = new Date();\n
+      shared.emit(\'job:modified\', job);\n
+      if (job.solver) {\n
+        restCommandResolver(job, args);\n
+      }\n
+      shared.emit(\'job:resolved\', job, args);\n
+      shared.emit(\'job:end\', job);\n
+    }\n
+  }\n
+\n
+  function endAndRejectIfRunning(job, args) {\n
+    if (job.state === \'running\') {\n
+      job.state = \'fail\';\n
+      job.modified = new Date();\n
+      shared.emit(\'job:modified\', job);\n
+      if (job.solver) {\n
+        restCommandRejecter(job, args);\n
+      }\n
+      shared.emit(\'job:rejected\', job, args);\n
+      shared.emit(\'job:end\', job);\n
+    }\n
+  }\n
+\n
+  function notifyJobIfRunning(job, args) {\n
+    if (job.state === \'running\' && job.solver) {\n
+      job.solver.notify(args[0]);\n
+      shared.emit(\'job:notified\', job, args);\n
+    }\n
+  }\n
+\n
+  // listeners\n
+\n
+  shared.on(\'job:new\', startJobIfReady);\n
+  shared.on(\'job:start\', executeJobIfReady);\n
+\n
+  shared.on(\'job:resolve\', endAndResolveIfRunning);\n
+  shared.on(\'job:reject\', endAndRejectIfRunning);\n
+  shared.on(\'job:notify\', notifyJobIfRunning);\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */\n
+/*global arrayExtend */\n
+\n
+function enableJobMaker(jio, shared, options) {\n
+\n
+  // dependencies\n
+  // - param.method\n
+  // - param.storage_spec\n
+  // - param.kwargs\n
+  // - param.options\n
+\n
+  // uses (Job)\n
+  // - param.created date\n
+  // - param.modified date\n
+  // - param.tried number >= 0\n
+  // - param.state string \'ready\'\n
+  // - param.method string\n
+  // - param.storage_spec object\n
+  // - param.kwargs object\n
+  // - param.options object\n
+  // - param.command object\n
+\n
+  // list of job events:\n
+  // - Job existence -> new, end\n
+  // - Job execution -> started, stopped\n
+  // - Job resolution -> resolved, rejected, notified, cancelled\n
+  // - Job modification -> modified\n
+\n
+  // emits actions \'job:resolve\', \'job:reject\' and \'job:notify\'\n
+\n
+  // uses `rest method` events\n
+  // emits \'job:new\' event\n
+\n
+  shared.job_keys = arrayExtend(shared.job_keys || [], [\n
+    "created",\n
+    "modified",\n
+    "tried",\n
+    "state",\n
+    "method",\n
+    "storage_spec",\n
+    "kwargs",\n
+    "options"\n
+  ]);\n
+\n
+  function addCommandToJob(job) {\n
+    job.command = {};\n
+    job.command.resolve = function () {\n
+      shared.emit(\'job:resolve\', job, arguments);\n
+    };\n
+    job.command.success = job.command.resolve;\n
+    job.command.reject = function () {\n
+      shared.emit(\'job:reject\', job, arguments);\n
+    };\n
+    job.command.error = job.command.reject;\n
+    job.command.notify = function () {\n
+      shared.emit(\'job:notify\', job, arguments);\n
+    };\n
+    job.command.storage = function () {\n
+      return shared.createRestApi.apply(null, arguments);\n
+    };\n
+    job.command.setCanceller = function (canceller) {\n
+      job.cancellers["command:canceller"] = canceller;\n
+    };\n
+    job.cancellers = job.cancellers || {};\n
+    job.cancellers["job:canceller"] = function () {\n
+      shared.emit("job:reject", job, ["cancelled"]);\n
+    };\n
+  }\n
+\n
+  function createJobFromRest(param) {\n
+    if (param.solver) {\n
+      // rest parameters are good\n
+      shared.emit(\'job:new\', param);\n
+    }\n
+  }\n
+\n
+  function initJob(job) {\n
+    job.state = \'ready\';\n
+    if (typeof job.tried !== \'number\' || !isFinite(job.tried)) {\n
+      job.tried = 0;\n
+    }\n
+    if (!job.created) {\n
+      job.created = new Date();\n
+    }\n
+    addCommandToJob(job);\n
+    job.modified = new Date();\n
+  }\n
+\n
+  // listeners\n
+\n
+  shared.rest_method_names.forEach(function (method) {\n
+    shared.on(method, createJobFromRest);\n
+  });\n
+\n
+  shared.on(\'job:new\', initJob);\n
+\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */\n
+/*global arrayExtend, localStorage, Workspace, uniqueJSONStringify, JobQueue,\n
+  constants, setTimeout, clearTimeout */\n
+\n
+function enableJobQueue(jio, shared, options) {\n
+\n
+  // dependencies\n
+  // - shared.storage_spec Object\n
+\n
+  // uses\n
+  // - options.workspace Workspace\n
+  // - shared.job_keys String Array\n
+\n
+  // creates\n
+  // - shared.storage_spec_str String\n
+  // - shared.workspace Workspace\n
+  // - shared.job_queue JobQueue\n
+\n
+  // uses \'job:new\', \'job:started\', \'job:stopped\', \'job:modified\',\n
+  // \'job:notified\', \'job:end\' events\n
+\n
+  // emits \'job:end\' event\n
+\n
+  function postJobIfReady(param) {\n
+    if (!param.stored && param.state === \'ready\') {\n
+      clearTimeout(param.queue_ident);\n
+      delete param.queue_ident;\n
+      shared.job_queue.load();\n
+      shared.job_queue.post(param);\n
+      shared.job_queue.save();\n
+      param.stored = true;\n
+    }\n
+  }\n
+\n
+  function deferredPutJob(param) {\n
+    if (param.queue_ident === undefined) {\n
+      param.queue_ident = setTimeout(function () {\n
+        delete param.queue_ident;\n
+        if (param.stored) {\n
+          shared.job_queue.load();\n
+          shared.job_queue.put(param);\n
+          shared.job_queue.save();\n
+        }\n
+      });\n
+    }\n
+  }\n
+\n
+  function removeJob(param) {\n
+    clearTimeout(param.queue_ident);\n
+    delete param.queue_ident;\n
+    if (param.stored) {\n
+      shared.job_queue.load();\n
+      shared.job_queue.remove(param.id);\n
+      shared.job_queue.save();\n
+      delete param.stored;\n
+      delete param.id;\n
+    }\n
+  }\n
+\n
+  function initJob(param) {\n
+    if (!param.command.end) {\n
+      param.command.end = function () {\n
+        shared.emit(\'job:end\', param);\n
+      };\n
+    }\n
+  }\n
+\n
+  shared.on(\'job:new\', initJob);\n
+\n
+  if (options.job_management !== false) {\n
+\n
+    shared.job_keys = arrayExtend(shared.job_keys || [], ["id"]);\n
+\n
+    if (typeof options.workspace !== \'object\') {\n
+      shared.workspace = localStorage;\n
+    } else {\n
+      shared.workspace = new Workspace(options.workspace);\n
+    }\n
+\n
+    if (!shared.storage_spec_str) {\n
+      shared.storage_spec_str = uniqueJSONStringify(shared.storage_spec);\n
+    }\n
+\n
+    shared.job_queue = new JobQueue(\n
+      shared.workspace,\n
+      \'jio/jobs/\' + shared.storage_spec_str,\n
+      shared.job_keys\n
+    );\n
+\n
+    // Listeners\n
+\n
+    shared.on(\'job:new\', postJobIfReady);\n
+\n
+    shared.on(\'job:started\', deferredPutJob);\n
+    shared.on(\'job:stopped\', deferredPutJob);\n
+    shared.on(\'job:modified\', deferredPutJob);\n
+    shared.on(\'job:notified\', deferredPutJob);\n
+\n
+    shared.on(\'job:end\', removeJob);\n
+\n
+  }\n
+\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */\n
+/*global setTimeout, methodType */\n
+\n
+function enableJobRecovery(jio, shared, options) {\n
+\n
+  // dependencies\n
+  // - JobQueue enabled and before this\n
+\n
+  // uses\n
+  // - shared.job_queue JobQueue\n
+\n
+  // emits \'job:new\' event\n
+\n
+  function numberOrDefault(number, default_value) {\n
+    return (typeof number === \'number\' &&\n
+            isFinite(number) ? number : default_value);\n
+  }\n
+\n
+  function recoverJob(param) {\n
+    shared.job_queue.load();\n
+    shared.job_queue.remove(param.id);\n
+    delete param.id;\n
+    if (methodType(param.method) === \'writer\' &&\n
+        (param.state === \'ready\' ||\n
+         param.state === \'running\' ||\n
+         param.state === \'waiting\')) {\n
+      shared.job_queue.save();\n
+      shared.emit(\'job:new\', param);\n
+    }\n
+  }\n
+\n
+  function jobWaiter(id, modified) {\n
+    return function () {\n
+      var job;\n
+      shared.job_queue.load();\n
+      job = shared.job_queue.get(id);\n
+      if (job && job.modified === modified) {\n
+        // job not modified, no one takes care of it\n
+        recoverJob(job);\n
+      }\n
+    };\n
+  }\n
+\n
+  var i, job_array, delay, deadline, recovery_delay;\n
+\n
+  // 1 m 30 s  ===  default firefox request timeout\n
+  recovery_delay = numberOrDefault(options.recovery_delay, 90000);\n
+  if (recovery_delay < 0) {\n
+    recovery_delay = 90000;\n
+  }\n
+\n
+  if (options.job_management !== false && options.job_recovery !== false) {\n
+\n
+    shared.job_queue.load();\n
+    job_array = shared.job_queue.asArray();\n
+\n
+    for (i = 0; i < job_array.length; i += 1) {\n
+      delay = numberOrDefault(job_array[i].timeout + recovery_delay,\n
+                              recovery_delay);\n
+      deadline = new Date(job_array[i].modified).getTime() + delay;\n
+      if (!isFinite(delay)) {\n
+        // \'modified\' date is broken\n
+        recoverJob(job_array[i]);\n
+      } else if (deadline <= Date.now()) {\n
+        // deadline reached\n
+        recoverJob(job_array[i]);\n
+      } else {\n
+        // deadline not reached yet\n
+        // wait until deadline is reached then check job again\n
+        setTimeout(jobWaiter(job_array[i].id, job_array[i].modified),\n
+                   deadline - Date.now());\n
+      }\n
+    }\n
+\n
+  }\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, unparam: true */\n
+/*global ReferenceArray */\n
+\n
+function enableJobReference(jio, shared, options) {\n
+\n
+  // creates\n
+  // - shared.jobs Object Array\n
+\n
+  // uses \'job:new\' and \'job:end\' events\n
+\n
+  shared.jobs = [];\n
+\n
+  var job_references = new ReferenceArray(shared.jobs);\n
+\n
+  shared.on(\'job:new\', function (param) {\n
+    job_references.put(param);\n
+  });\n
+\n
+  shared.on(\'job:end\', function (param) {\n
+    job_references.remove(param);\n
+  });\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */\n
+/*global arrayExtend, setTimeout, methodType, constants */\n
+\n
+function enableJobRetry(jio, shared, options) {\n
+\n
+  // dependencies\n
+  // - param.method\n
+  // - param.storage_spec\n
+  // - param.kwargs\n
+  // - param.options\n
+  // - param.command\n
+\n
+  // uses\n
+  // - options.default_writers_max_retry number >= 0 or null\n
+  // - options.default_readers_max_retry number >= 0 or null\n
+  // - options.default_max_retry number >= 0 or null\n
+  // - options.writers_max_retry number >= 0 or null\n
+  // - options.readers_max_retry number >= 0 or null\n
+  // - options.max_retry number >= 0 or null\n
+  // - param.modified date\n
+  // - param.tried number >= 0\n
+  // - param.max_retry >= 0 or undefined\n
+  // - param.state string \'ready\' \'waiting\'\n
+  // - param.method string\n
+  // - param.storage_spec object\n
+  // - param.kwargs object\n
+  // - param.options object\n
+  // - param.command object\n
+\n
+  // uses \'job:new\' and \'job:retry\' events\n
+  // emits action \'job:start\' event\n
+  // emits \'job:retry\', \'job:reject\', \'job:modified\' and \'job:stopped\' events\n
+\n
+  shared.job_keys = arrayExtend(shared.job_keys || [], ["max_retry"]);\n
+\n
+  var writers_max_retry, readers_max_retry, max_retry;\n
+\n
+  function defaultMaxRetry(param) {\n
+    if (methodType(param.method) === \'writers\') {\n
+      if (max_retry === undefined) {\n
+        return writers_max_retry;\n
+      }\n
+      return max_retry;\n
+    }\n
+    if (max_retry === undefined) {\n
+      return readers_max_retry;\n
+    }\n
+    return max_retry;\n
+  }\n
+\n
+  function positiveNumberOrDefault(number, default_value) {\n
+    return (typeof number === \'number\' &&\n
+            number >= 0 ?\n
+            number : default_value);\n
+  }\n
+\n
+  function positiveNumberNullOrDefault(number, default_value) {\n
+    return ((typeof number === \'number\' &&\n
+            number >= 0) || number === null ?\n
+            number : default_value);\n
+  }\n
+\n
+  max_retry = positiveNumberNullOrDefault(\n
+    options.max_retry || options.default_max_retry,\n
+    undefined\n
+  );\n
+  writers_max_retry = positiveNumberNullOrDefault(\n
+    options.writers_max_retry || options.default_writers_max_retry,\n
+    null\n
+  );\n
+  readers_max_retry = positiveNumberNullOrDefault(\n
+    options.readers_max_retry || options.default_readers_max_retry,\n
+    2\n
+  );\n
+\n
+  function initJob(param) {\n
+    if (typeof param.max_retry !== \'number\' || param.max_retry < 0) {\n
+      param.max_retry = positiveNumberOrDefault(\n
+        param.options.max_retry,\n
+        defaultMaxRetry(param)\n
+      );\n
+    }\n
+    param.command.reject = function (status) {\n
+      if (constants.http_action[status || 0] === "retry") {\n
+        shared.emit(\'job:retry\', param, arguments);\n
+      } else {\n
+        shared.emit(\'job:reject\', param, arguments);\n
+      }\n
+    };\n
+    param.command.retry = function () {\n
+      shared.emit(\'job:retry\', param, arguments);\n
+    };\n
+  }\n
+\n
+  function retryIfRunning(param, args) {\n
+    if (param.state === \'running\') {\n
+      if (param.max_retry === undefined ||\n
+          param.max_retry === null ||\n
+          param.max_retry >= param.tried) {\n
+        param.state = \'waiting\';\n
+        param.modified = new Date();\n
+        shared.emit(\'job:modified\', param);\n
+        shared.emit(\'job:stopped\', param);\n
+        setTimeout(function () {\n
+          param.state = \'ready\';\n
+          param.modified = new Date();\n
+          shared.emit(\'job:modified\', param);\n
+          shared.emit(\'job:start\', param);\n
+        }, Math.min(10000, param.tried * 2000));\n
+      } else {\n
+        shared.emit(\'job:reject\', param, args);\n
+      }\n
+    }\n
+  }\n
+\n
+  // listeners\n
+\n
+  shared.on(\'job:new\', initJob);\n
+\n
+  shared.on(\'job:retry\', retryIfRunning);\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */\n
+/*global arrayExtend, setTimeout, clearTimeout */\n
+\n
+function enableJobTimeout(jio, shared, options) {\n
+\n
+  // dependencies\n
+  // - param.tried number > 0\n
+  // - param.state string \'running\'\n
+\n
+  // uses\n
+  // - param.tried number > 0\n
+  // - param.timeout number >= 0\n
+  // - param.timeout_ident Timeout\n
+  // - param.state string \'running\'\n
+\n
+  // uses \'job:new\', \'job:stopped\', \'job:started\',\n
+  // \'job:notified\' and \'job:end\' events\n
+  // emits \'job:modified\' event\n
+\n
+  shared.job_keys = arrayExtend(shared.job_keys || [], ["timeout"]);\n
+\n
+  function positiveNumberOrDefault(number, default_value) {\n
+    return (typeof number === \'number\' &&\n
+            number >= 0 ?\n
+            number : default_value);\n
+  }\n
+\n
+  // Infinity by default\n
+  var default_timeout = positiveNumberOrDefault(options.default_timeout, 0);\n
+\n
+  function timeoutReject(param) {\n
+    return function () {\n
+      param.command.reject(\n
+        \'request_timeout\',\n
+        \'timeout\',\n
+        \'Operation canceled after around \' + (\n
+          Date.now() - param.modified.getTime()\n
+        ) + \' milliseconds of inactivity.\'\n
+      );\n
+    };\n
+  }\n
+\n
+  function initJob(job) {\n
+    if (typeof job.timeout !== \'number\' || !isFinite(job.timeout) ||\n
+        job.timeout < 0) {\n
+      job.timeout = positiveNumberOrDefault(\n
+        job.options.timeout,\n
+        default_timeout\n
+      );\n
+    }\n
+    job.modified = new Date();\n
+    shared.emit(\'job:modified\', job);\n
+  }\n
+\n
+  function clearJobTimeout(job) {\n
+    clearTimeout(job.timeout_ident);\n
+    delete job.timeout_ident;\n
+  }\n
+\n
+  function restartJobTimeoutIfRunning(job) {\n
+    clearTimeout(job.timeout_ident);\n
+    if (job.state === \'running\' && job.timeout > 0) {\n
+      job.timeout_ident = setTimeout(timeoutReject(job), job.timeout);\n
+      job.modified = new Date();\n
+    } else {\n
+      delete job.timeout_ident;\n
+    }\n
+  }\n
+\n
+  // listeners\n
+\n
+  shared.on(\'job:new\', initJob);\n
+\n
+  shared.on("job:stopped", clearJobTimeout);\n
+  shared.on("job:end", clearJobTimeout);\n
+\n
+  shared.on("job:started", restartJobTimeoutIfRunning);\n
+  shared.on("job:notified", restartJobTimeoutIfRunning);\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true */\n
+/*global arrayValuesToTypeDict, dictClear, RSVP, deepClone */\n
+\n
+// adds methods to JIO\n
+// - post\n
+// - put\n
+// - get\n
+// - remove\n
+// - allDocs\n
+// - putAttachment\n
+// - getAttachment\n
+// - removeAttachment\n
+// - check\n
+// - repair\n
+\n
+// event shared objet\n
+// - storage_spec object\n
+// - method string\n
+// - kwargs object\n
+// - options object\n
+// - solver object\n
+// - solver.resolve function\n
+// - solver.reject function\n
+// - solver.notify function\n
+// - cancellers object\n
+// - promise object\n
+\n
+function enableRestAPI(jio, shared) { // (jio, shared, options)\n
+\n
+  shared.rest_method_names = [\n
+    "post",\n
+    "put",\n
+    "get",\n
+    "remove",\n
+    "allDocs",\n
+    "putAttachment",\n
+    "getAttachment",\n
+    "removeAttachment",\n
+    "check",\n
+    "repair"\n
+  ];\n
+\n
+  function prepareParamAndEmit(method, storage_spec, args) {\n
+    var callback, type_dict, param = {};\n
+    type_dict = arrayValuesToTypeDict(Array.prototype.slice.call(args));\n
+    type_dict.object = type_dict.object || [];\n
+    if (method !== \'allDocs\') {\n
+      param.kwargs = type_dict.object.shift();\n
+      if (param.kwargs === undefined) {\n
+        throw new TypeError("JIO()." + method +\n
+                            "(): Argument 1 is not of type \'object\'");\n
+      }\n
+      param.kwargs = deepClone(param.kwargs);\n
+    } else {\n
+      param.kwargs = {};\n
+    }\n
+    param.solver = {};\n
+    param.options = deepClone(type_dict.object.shift()) || {};\n
+    param.promise = new RSVP.Promise(function (resolve, reject, notify) {\n
+      param.solver.resolve = resolve;\n
+      param.solver.reject = reject;\n
+      param.solver.notify = notify;\n
+    }, function () {\n
+      if (!param.cancellers) { return; }\n
+      var k;\n
+      for (k in param.cancellers) {\n
+        if (param.cancellers.hasOwnProperty(k)) {\n
+          param.cancellers[k]();\n
+        }\n
+      }\n
+    });\n
+    type_dict[\'function\'] = type_dict[\'function\'] || [];\n
+    if (type_dict[\'function\'].length === 1) {\n
+      callback = type_dict[\'function\'][0];\n
+      param.promise.then(function (answer) {\n
+        callback(undefined, answer);\n
+      }, function (answer) {\n
+        callback(answer, undefined);\n
+      });\n
+    } else if (type_dict[\'function\'].length > 1) {\n
+      param.promise.then(type_dict[\'function\'][0],\n
+                         type_dict[\'function\'][1],\n
+                         type_dict[\'function\'][2]);\n
+    }\n
+    type_dict = dictClear(type_dict);\n
+    param.storage_spec = storage_spec;\n
+    param.method = method;\n
+    shared.emit(method, param);\n
+    return param.promise;\n
+  }\n
+\n
+  shared.createRestApi = function (storage_spec, that) {\n
+    if (that === undefined) {\n
+      that = {};\n
+    }\n
+    shared.rest_method_names.forEach(function (method) {\n
+      that[method] = function () {\n
+        return prepareParamAndEmit(method, storage_spec, arguments);\n
+      };\n
+    });\n
+    return that;\n
+  };\n
+\n
+  shared.createRestApi(shared.storage_spec, jio);\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, unparam: true */\n
+/*global Blob, restCommandRejecter, Metadata */\n
+\n
+function enableRestParamChecker(jio, shared) {\n
+\n
+  // dependencies\n
+  // - param.solver\n
+  // - param.kwargs\n
+\n
+  // checks the kwargs and convert value if necessary\n
+\n
+  // which is a dict of method to use to announce that\n
+  // the command is finished\n
+\n
+\n
+  // tools\n
+\n
+  function checkId(param) {\n
+    if (typeof param.kwargs._id !== \'string\' || param.kwargs._id === \'\') {\n
+      restCommandRejecter(param, [\n
+        \'bad_request\',\n
+        \'wrong document id\',\n
+        \'Document id must be a non empty string.\'\n
+      ]);\n
+      delete param.solver;\n
+      return false;\n
+    }\n
+    return true;\n
+  }\n
+\n
+  function checkAttachmentId(param) {\n
+    if (typeof param.kwargs._attachment !== \'string\' ||\n
+        param.kwargs._attachment === \'\') {\n
+      restCommandRejecter(param, [\n
+        \'bad_request\',\n
+        \'wrong attachment id\',\n
+        \'Attachment id must be a non empty string.\'\n
+      ]);\n
+      delete param.solver;\n
+      return false;\n
+    }\n
+    return true;\n
+  }\n
+\n
+  // listeners\n
+\n
+  shared.on(\'post\', function (param) {\n
+    if (param.kwargs._id !== undefined) {\n
+      if (!checkId(param)) {\n
+        return;\n
+      }\n
+    }\n
+    new Metadata(param.kwargs).format();\n
+  });\n
+\n
+  ["put", "get", "remove"].forEach(function (method) {\n
+    shared.on(method, function (param) {\n
+      if (!checkId(param)) {\n
+        return;\n
+      }\n
+      new Metadata(param.kwargs).format();\n
+    });\n
+  });\n
+\n
+  shared.on(\'putAttachment\', function (param) {\n
+    if (!checkId(param) || !checkAttachmentId(param)) {\n
+      return;\n
+    }\n
+    if (!(param.kwargs._blob instanceof Blob) &&\n
+        typeof param.kwargs._data === \'string\') {\n
+      param.kwargs._blob = new Blob([param.kwargs._data], {\n
+        "type": param.kwargs._content_type || param.kwargs._mimetype || ""\n
+      });\n
+      delete param.kwargs._data;\n
+      delete param.kwargs._mimetype;\n
+      delete param.kwargs._content_type;\n
+    } else if (param.kwargs._blob instanceof Blob) {\n
+      delete param.kwargs._data;\n
+      delete param.kwargs._mimetype;\n
+      delete param.kwargs._content_type;\n
+    } else if (param.kwargs._data instanceof Blob) {\n
+      param.kwargs._blob = param.kwargs._data;\n
+      delete param.kwargs._data;\n
+      delete param.kwargs._mimetype;\n
+      delete param.kwargs._content_type;\n
+    } else {\n
+      restCommandRejecter(param, [\n
+        \'bad_request\',\n
+        \'wrong attachment\',\n
+        \'Attachment information must be like {"_id": document id, \' +\n
+          \'"_attachment": attachment name, "_data": string, ["_mimetype": \' +\n
+          \'content type]} or {"_id": document id, "_attachment": \' +\n
+          \'attachment name, "_blob": Blob}\'\n
+      ]);\n
+      delete param.solver;\n
+    }\n
+  });\n
+\n
+  ["getAttachment", "removeAttachment"].forEach(function (method) {\n
+    shared.on(method, function (param) {\n
+      if (!checkId(param)) {\n
+        checkAttachmentId(param);\n
+      }\n
+    });\n
+  });\n
+\n
+  ["check", "repair"].forEach(function (method) {\n
+    shared.on(method, function (param) {\n
+      if (param.kwargs._id !== undefined) {\n
+        if (!checkId(param)) {\n
+          return;\n
+        }\n
+      }\n
+    });\n
+  });\n
+\n
+}\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true */\n
+\n
+var query_class_dict = {};\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global parseStringToObject: true, emptyFunction: true, sortOn: true, limit:\n
+  true, select: true, exports, stringEscapeRegexpCharacters: true,\n
+  deepClone, RSVP, sequence */\n
+\n
+/**\n
+ * The query to use to filter a list of objects.\n
+ * This is an abstract class.\n
+ *\n
+ * @class Query\n
+ * @constructor\n
+ */\n
+function Query() {\n
+\n
+  /**\n
+   * Called before parsing the query. Must be overridden!\n
+   *\n
+   * @method onParseStart\n
+   * @param  {Object} object The object shared in the parse process\n
+   * @param  {Object} option Some option gave in parse()\n
+   */\n
+  this.onParseStart = emptyFunction;\n
+\n
+  /**\n
+   * Called when parsing a simple query. Must be overridden!\n
+   *\n
+   * @method onParseSimpleQuery\n
+   * @param  {Object} object The object shared in the parse process\n
+   * @param  {Object} option Some option gave in parse()\n
+   */\n
+  this.onParseSimpleQuery = emptyFunction;\n
+\n
+  /**\n
+   * Called when parsing a complex query. Must be overridden!\n
+   *\n
+   * @method onParseComplexQuery\n
+   * @param  {Object} object The object shared in the parse process\n
+   * @param  {Object} option Some option gave in parse()\n
+   */\n
+  this.onParseComplexQuery = emptyFunction;\n
+\n
+  /**\n
+   * Called after parsing the query. Must be overridden!\n
+   *\n
+   * @method onParseEnd\n
+   * @param  {Object} object The object shared in the parse process\n
+   * @param  {Object} option Some option gave in parse()\n
+   */\n
+  this.onParseEnd = emptyFunction;\n
+\n
+}\n
+\n
+/**\n
+ * Filter the item list with matching item only\n
+ *\n
+ * @method exec\n
+ * @param  {Array} item_list The list of object\n
+ * @param  {Object} [option] Some operation option\n
+ * @param  {Array} [option.select_list] A object keys to retrieve\n
+ * @param  {Array} [option.sort_on] Couples of object keys and "ascending"\n
+ *                 or "descending"\n
+ * @param  {Array} [option.limit] Couple of integer, first is an index and\n
+ *                 second is the length.\n
+ */\n
+Query.prototype.exec = function (item_list, option) {\n
+  var i, promises = [];\n
+  if (!Array.isArray(item_list)) {\n
+    throw new TypeError("Query().exec(): Argument 1 is not of type \'array\'");\n
+  }\n
+  if (option === undefined) {\n
+    option = {};\n
+  }\n
+  if (typeof option !== \'object\') {\n
+    throw new TypeError("Query().exec(): " +\n
+                        "Optional argument 2 is not of type \'object\'");\n
+  }\n
+  for (i = 0; i < item_list.length; i += 1) {\n
+    if (!item_list[i]) {\n
+      promises.push(RSVP.resolve(false));\n
+    } else {\n
+      promises.push(this.match(item_list[i]));\n
+    }\n
+  }\n
+  return sequence([function () {\n
+    return RSVP.all(promises);\n
+  }, function (answers) {\n
+    var j;\n
+    for (j = answers.length - 1; j >= 0; j -= 1) {\n
+      if (!answers[j]) {\n
+        item_list.splice(j, 1);\n
+      }\n
+    }\n
+    if (option.sort_on) {\n
+      return sortOn(option.sort_on, item_list);\n
+    }\n
+  }, function () {\n
+    if (option.limit) {\n
+      return limit(option.limit, item_list);\n
+    }\n
+  }, function () {\n
+    return select(option.select_list || [], item_list);\n
+  }, function () {\n
+    return item_list;\n
+  }]);\n
+};\n
+\n
+/**\n
+ * Test if an item matches this query\n
+ *\n
+ * @method match\n
+ * @param  {Object} item The object to test\n
+ * @return {Boolean} true if match, false otherwise\n
+ */\n
+Query.prototype.match = function () {\n
+  return RSVP.resolve(true);\n
+};\n
+\n
+\n
+/**\n
+ * Browse the Query in deep calling parser method in each step.\n
+ *\n
+ * `onParseStart` is called first, on end `onParseEnd` is called.\n
+ * It starts from the simple queries at the bottom of the tree calling the\n
+ * parser method `onParseSimpleQuery`, and go up calling the\n
+ * `onParseComplexQuery` method.\n
+ *\n
+ * @method parse\n
+ * @param  {Object} option Any options you want (except \'parsed\')\n
+ * @return {Any} The parse result\n
+ */\n
+Query.prototype.parse = function (option) {\n
+  var that = this, object;\n
+  /**\n
+   * The recursive parser.\n
+   *\n
+   * @param  {Object} object The object shared in the parse process\n
+   * @param  {Object} options Some options usable in the parseMethods\n
+   * @return {Any} The parser result\n
+   */\n
+  function recParse(object, option) {\n
+    var query = object.parsed;\n
+    if (query.type === "complex") {\n
+      return sequence([function () {\n
+        return sequence(query.query_list.map(function (v, i) {\n
+          /*jslint unparam: true */\n
+          return function () {\n
+            return sequence([function () {\n
+              object.parsed = query.query_list[i];\n
+              return recParse(object, option);\n
+            }, function () {\n
+              query.query_list[i] = object.parsed;\n
+            }]);\n
+          };\n
+        }));\n
+      }, function () {\n
+        object.parsed = query;\n
+        return that.onParseComplexQuery(object, option);\n
+      }]);\n
+    }\n
+    if (query.type === "simple") {\n
+      return that.onParseSimpleQuery(object, option);\n
+    }\n
+  }\n
+  object = {"parsed": JSON.parse(JSON.stringify(that.serialized()))};\n
+  return sequence([function () {\n
+    return that.onParseStar
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+t(object, option);\n
+  }, function () {\n
+    return recParse(object, option);\n
+  }, function () {\n
+    return that.onParseEnd(object, option);\n
+  }, function () {\n
+    return object.parsed;\n
+  }]);\n
+};\n
+\n
+/**\n
+ * Convert this query to a parsable string.\n
+ *\n
+ * @method toString\n
+ * @return {String} The string version of this query\n
+ */\n
+Query.prototype.toString = function () {\n
+  return "";\n
+};\n
+\n
+/**\n
+ * Convert this query to an jsonable object in order to be remake thanks to\n
+ * QueryFactory class.\n
+ *\n
+ * @method serialized\n
+ * @return {Object} The jsonable object\n
+ */\n
+Query.prototype.serialized = function () {\n
+  return undefined;\n
+};\n
+\n
+exports.Query = Query;\n
+\n
+/**\n
+ * Parse a text request to a json query object tree\n
+ *\n
+ * @param  {String} string The string to parse\n
+ * @return {Object} The json query tree\n
+ */\n
+function parseStringToObject(string) {\n
+\n
+\n
+/*\n
+\tDefault template driver for JS/CC generated parsers running as\n
+\tbrowser-based JavaScript/ECMAScript applications.\n
+\t\n
+\tWARNING: \tThis parser template will not run as console and has lesser\n
+\t\t\t\tfeatures for debugging than the console derivates for the\n
+\t\t\t\tvarious JavaScript platforms.\n
+\t\n
+\tFeatures:\n
+\t- Parser trace messages\n
+\t- Integrated panic-mode error recovery\n
+\t\n
+\tWritten 2007, 2008 by Jan Max Meyer, J.M.K S.F. Software Technologies\n
+\t\n
+\tThis is in the public domain.\n
+*/\n
+\n
+var NODEJS__dbg_withtrace\t\t= false;\n
+var NODEJS__dbg_string\t\t\t= new String();\n
+\n
+function __NODEJS_dbg_print( text )\n
+{\n
+\tNODEJS__dbg_string += text + "\\n";\n
+}\n
+\n
+function __NODEJS_lex( info )\n
+{\n
+\tvar state\t\t= 0;\n
+\tvar match\t\t= -1;\n
+\tvar match_pos\t= 0;\n
+\tvar start\t\t= 0;\n
+\tvar pos\t\t\t= info.offset + 1;\n
+\n
+\tdo\n
+\t{\n
+\t\tpos--;\n
+\t\tstate = 0;\n
+\t\tmatch = -2;\n
+\t\tstart = pos;\n
+\n
+\t\tif( info.src.length <= start )\n
+\t\t\treturn 19;\n
+\n
+\t\tdo\n
+\t\t{\n
+\n
+switch( state )\n
+{\n
+\tcase 0:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 8 ) || ( info.src.charCodeAt( pos ) >= 10 && info.src.charCodeAt( pos ) <= 31 ) || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || info.src.charCodeAt( pos ) == 59 || ( info.src.charCodeAt( pos ) >= 63 && info.src.charCodeAt( pos ) <= 64 ) || ( info.src.charCodeAt( pos ) >= 66 && info.src.charCodeAt( pos ) <= 77 ) || ( info.src.charCodeAt( pos ) >= 80 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 9 ) state = 2;\n
+\t\telse if( info.src.charCodeAt( pos ) == 40 ) state = 3;\n
+\t\telse if( info.src.charCodeAt( pos ) == 41 ) state = 4;\n
+\t\telse if( info.src.charCodeAt( pos ) == 60 || info.src.charCodeAt( pos ) == 62 ) state = 5;\n
+\t\telse if( info.src.charCodeAt( pos ) == 33 ) state = 11;\n
+\t\telse if( info.src.charCodeAt( pos ) == 79 ) state = 12;\n
+\t\telse if( info.src.charCodeAt( pos ) == 32 ) state = 13;\n
+\t\telse if( info.src.charCodeAt( pos ) == 61 ) state = 14;\n
+\t\telse if( info.src.charCodeAt( pos ) == 34 ) state = 15;\n
+\t\telse if( info.src.charCodeAt( pos ) == 65 ) state = 19;\n
+\t\telse if( info.src.charCodeAt( pos ) == 78 ) state = 20;\n
+\t\telse state = -1;\n
+\t\tbreak;\n
+\n
+\tcase 1:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 2:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse state = -1;\n
+\t\tmatch = 1;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 3:\n
+\t\tstate = -1;\n
+\t\tmatch = 3;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 4:\n
+\t\tstate = -1;\n
+\t\tmatch = 4;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 5:\n
+\t\tif( info.src.charCodeAt( pos ) == 61 ) state = 14;\n
+\t\telse state = -1;\n
+\t\tmatch = 11;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 6:\n
+\t\tstate = -1;\n
+\t\tmatch = 8;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 7:\n
+\t\tstate = -1;\n
+\t\tmatch = 9;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 8:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse state = -1;\n
+\t\tmatch = 6;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 9:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse state = -1;\n
+\t\tmatch = 5;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 10:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse state = -1;\n
+\t\tmatch = 7;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 11:\n
+\t\tif( info.src.charCodeAt( pos ) == 61 ) state = 14;\n
+\t\telse state = -1;\n
+\t\tbreak;\n
+\n
+\tcase 12:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 81 ) || ( info.src.charCodeAt( pos ) >= 83 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse if( info.src.charCodeAt( pos ) == 82 ) state = 8;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 13:\n
+\t\tstate = -1;\n
+\t\tmatch = 1;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 14:\n
+\t\tstate = -1;\n
+\t\tmatch = 11;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 15:\n
+\t\tif( info.src.charCodeAt( pos ) == 34 ) state = 7;\n
+\t\telse if( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 33 ) || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 91 ) || ( info.src.charCodeAt( pos ) >= 93 && info.src.charCodeAt( pos ) <= 254 ) ) state = 15;\n
+\t\telse if( info.src.charCodeAt( pos ) == 92 ) state = 17;\n
+\t\telse state = -1;\n
+\t\tbreak;\n
+\n
+\tcase 16:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 67 ) || ( info.src.charCodeAt( pos ) >= 69 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse if( info.src.charCodeAt( pos ) == 68 ) state = 9;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 17:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 254 ) ) state = 15;\n
+\t\telse state = -1;\n
+\t\tbreak;\n
+\n
+\tcase 18:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 83 ) || ( info.src.charCodeAt( pos ) >= 85 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse if( info.src.charCodeAt( pos ) == 84 ) state = 10;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 19:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 77 ) || ( info.src.charCodeAt( pos ) >= 79 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse if( info.src.charCodeAt( pos ) == 78 ) state = 16;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 20:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 78 ) || ( info.src.charCodeAt( pos ) >= 80 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse if( info.src.charCodeAt( pos ) == 79 ) state = 18;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+}\n
+\n
+\n
+\t\t\tpos++;\n
+\n
+\t\t}\n
+\t\twhile( state > -1 );\n
+\n
+\t}\n
+\twhile( 1 > -1 && match == 1 );\n
+\n
+\tif( match > -1 )\n
+\t{\n
+\t\tinfo.att = info.src.substr( start, match_pos - start );\n
+\t\tinfo.offset = match_pos;\n
+\t\t\n
+\n
+\t}\n
+\telse\n
+\t{\n
+\t\tinfo.att = new String();\n
+\t\tmatch = -1;\n
+\t}\n
+\n
+\treturn match;\n
+}\n
+\n
+\n
+function __NODEJS_parse( src, err_off, err_la )\n
+{\n
+\tvar\t\tsstack\t\t\t= new Array();\n
+\tvar\t\tvstack\t\t\t= new Array();\n
+\tvar \terr_cnt\t\t\t= 0;\n
+\tvar\t\tact;\n
+\tvar\t\tgo;\n
+\tvar\t\tla;\n
+\tvar\t\trval;\n
+\tvar \tparseinfo\t\t= new Function( "", "var offset; var src; var att;" );\n
+\tvar\t\tinfo\t\t\t= new parseinfo();\n
+\t\n
+/* Pop-Table */\n
+var pop_tab = new Array(\n
+\tnew Array( 0/* begin\' */, 1 ),\n
+\tnew Array( 13/* begin */, 1 ),\n
+\tnew Array( 12/* search_text */, 1 ),\n
+\tnew Array( 12/* search_text */, 2 ),\n
+\tnew Array( 12/* search_text */, 3 ),\n
+\tnew Array( 14/* and_expression */, 1 ),\n
+\tnew Array( 14/* and_expression */, 3 ),\n
+\tnew Array( 15/* boolean_expression */, 2 ),\n
+\tnew Array( 15/* boolean_expression */, 1 ),\n
+\tnew Array( 16/* expression */, 3 ),\n
+\tnew Array( 16/* expression */, 2 ),\n
+\tnew Array( 16/* expression */, 1 ),\n
+\tnew Array( 17/* value */, 2 ),\n
+\tnew Array( 17/* value */, 1 ),\n
+\tnew Array( 18/* string */, 1 ),\n
+\tnew Array( 18/* string */, 1 )\n
+);\n
+\n
+/* Action-Table */\n
+var act_tab = new Array(\n
+\t/* State 0 */ new Array( 7/* "NOT" */,5 , 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 1 */ new Array( 19/* "$" */,0 ),\n
+\t/* State 2 */ new Array( 19/* "$" */,-1 ),\n
+\t/* State 3 */ new Array( 6/* "OR" */,14 , 7/* "NOT" */,5 , 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 , 19/* "$" */,-2 , 4/* "RIGHT_PARENTHESE" */,-2 ),\n
+\t/* State 4 */ new Array( 5/* "AND" */,16 , 19/* "$" */,-5 , 7/* "NOT" */,-5 , 3/* "LEFT_PARENTHESE" */,-5 , 8/* "COLUMN" */,-5 , 11/* "OPERATOR" */,-5 , 10/* "WORD" */,-5 , 9/* "STRING" */,-5 , 6/* "OR" */,-5 , 4/* "RIGHT_PARENTHESE" */,-5 ),\n
+\t/* State 5 */ new Array( 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 6 */ new Array( 19/* "$" */,-8 , 7/* "NOT" */,-8 , 3/* "LEFT_PARENTHESE" */,-8 , 8/* "COLUMN" */,-8 , 11/* "OPERATOR" */,-8 , 10/* "WORD" */,-8 , 9/* "STRING" */,-8 , 6/* "OR" */,-8 , 5/* "AND" */,-8 , 4/* "RIGHT_PARENTHESE" */,-8 ),\n
+\t/* State 7 */ new Array( 7/* "NOT" */,5 , 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 8 */ new Array( 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 9 */ new Array( 19/* "$" */,-11 , 7/* "NOT" */,-11 , 3/* "LEFT_PARENTHESE" */,-11 , 8/* "COLUMN" */,-11 , 11/* "OPERATOR" */,-11 , 10/* "WORD" */,-11 , 9/* "STRING" */,-11 , 6/* "OR" */,-11 , 5/* "AND" */,-11 , 4/* "RIGHT_PARENTHESE" */,-11 ),\n
+\t/* State 10 */ new Array( 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 11 */ new Array( 19/* "$" */,-13 , 7/* "NOT" */,-13 , 3/* "LEFT_PARENTHESE" */,-13 , 8/* "COLUMN" */,-13 , 11/* "OPERATOR" */,-13 , 10/* "WORD" */,-13 , 9/* "STRING" */,-13 , 6/* "OR" */,-13 , 5/* "AND" */,-13 , 4/* "RIGHT_PARENTHESE" */,-13 ),\n
+\t/* State 12 */ new Array( 19/* "$" */,-14 , 7/* "NOT" */,-14 , 3/* "LEFT_PARENTHESE" */,-14 , 8/* "COLUMN" */,-14 , 11/* "OPERATOR" */,-14 , 10/* "WORD" */,-14 , 9/* "STRING" */,-14 , 6/* "OR" */,-14 , 5/* "AND" */,-14 , 4/* "RIGHT_PARENTHESE" */,-14 ),\n
+\t/* State 13 */ new Array( 19/* "$" */,-15 , 7/* "NOT" */,-15 , 3/* "LEFT_PARENTHESE" */,-15 , 8/* "COLUMN" */,-15 , 11/* "OPERATOR" */,-15 , 10/* "WORD" */,-15 , 9/* "STRING" */,-15 , 6/* "OR" */,-15 , 5/* "AND" */,-15 , 4/* "RIGHT_PARENTHESE" */,-15 ),\n
+\t/* State 14 */ new Array( 7/* "NOT" */,5 , 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 15 */ new Array( 19/* "$" */,-3 , 4/* "RIGHT_PARENTHESE" */,-3 ),\n
+\t/* State 16 */ new Array( 7/* "NOT" */,5 , 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 17 */ new Array( 19/* "$" */,-7 , 7/* "NOT" */,-7 , 3/* "LEFT_PARENTHESE" */,-7 , 8/* "COLUMN" */,-7 , 11/* "OPERATOR" */,-7 , 10/* "WORD" */,-7 , 9/* "STRING" */,-7 , 6/* "OR" */,-7 , 5/* "AND" */,-7 , 4/* "RIGHT_PARENTHESE" */,-7 ),\n
+\t/* State 18 */ new Array( 4/* "RIGHT_PARENTHESE" */,23 ),\n
+\t/* State 19 */ new Array( 19/* "$" */,-10 , 7/* "NOT" */,-10 , 3/* "LEFT_PARENTHESE" */,-10 , 8/* "COLUMN" */,-10 , 11/* "OPERATOR" */,-10 , 10/* "WORD" */,-10 , 9/* "STRING" */,-10 , 6/* "OR" */,-10 , 5/* "AND" */,-10 , 4/* "RIGHT_PARENTHESE" */,-10 ),\n
+\t/* State 20 */ new Array( 19/* "$" */,-12 , 7/* "NOT" */,-12 , 3/* "LEFT_PARENTHESE" */,-12 , 8/* "COLUMN" */,-12 , 11/* "OPERATOR" */,-12 , 10/* "WORD" */,-12 , 9/* "STRING" */,-12 , 6/* "OR" */,-12 , 5/* "AND" */,-12 , 4/* "RIGHT_PARENTHESE" */,-12 ),\n
+\t/* State 21 */ new Array( 19/* "$" */,-4 , 4/* "RIGHT_PARENTHESE" */,-4 ),\n
+\t/* State 22 */ new Array( 19/* "$" */,-6 , 7/* "NOT" */,-6 , 3/* "LEFT_PARENTHESE" */,-6 , 8/* "COLUMN" */,-6 , 11/* "OPERATOR" */,-6 , 10/* "WORD" */,-6 , 9/* "STRING" */,-6 , 6/* "OR" */,-6 , 4/* "RIGHT_PARENTHESE" */,-6 ),\n
+\t/* State 23 */ new Array( 19/* "$" */,-9 , 7/* "NOT" */,-9 , 3/* "LEFT_PARENTHESE" */,-9 , 8/* "COLUMN" */,-9 , 11/* "OPERATOR" */,-9 , 10/* "WORD" */,-9 , 9/* "STRING" */,-9 , 6/* "OR" */,-9 , 5/* "AND" */,-9 , 4/* "RIGHT_PARENTHESE" */,-9 )\n
+);\n
+\n
+/* Goto-Table */\n
+var goto_tab = new Array(\n
+\t/* State 0 */ new Array( 13/* begin */,1 , 12/* search_text */,2 , 14/* and_expression */,3 , 15/* boolean_expression */,4 , 16/* expression */,6 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 1 */ new Array(  ),\n
+\t/* State 2 */ new Array(  ),\n
+\t/* State 3 */ new Array( 12/* search_text */,15 , 14/* and_expression */,3 , 15/* boolean_expression */,4 , 16/* expression */,6 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 4 */ new Array(  ),\n
+\t/* State 5 */ new Array( 16/* expression */,17 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 6 */ new Array(  ),\n
+\t/* State 7 */ new Array( 12/* search_text */,18 , 14/* and_expression */,3 , 15/* boolean_expression */,4 , 16/* expression */,6 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 8 */ new Array( 16/* expression */,19 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 9 */ new Array(  ),\n
+\t/* State 10 */ new Array( 18/* string */,20 ),\n
+\t/* State 11 */ new Array(  ),\n
+\t/* State 12 */ new Array(  ),\n
+\t/* State 13 */ new Array(  ),\n
+\t/* State 14 */ new Array( 12/* search_text */,21 , 14/* and_expression */,3 , 15/* boolean_expression */,4 , 16/* expression */,6 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 15 */ new Array(  ),\n
+\t/* State 16 */ new Array( 14/* and_expression */,22 , 15/* boolean_expression */,4 , 16/* expression */,6 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 17 */ new Array(  ),\n
+\t/* State 18 */ new Array(  ),\n
+\t/* State 19 */ new Array(  ),\n
+\t/* State 20 */ new Array(  ),\n
+\t/* State 21 */ new Array(  ),\n
+\t/* State 22 */ new Array(  ),\n
+\t/* State 23 */ new Array(  )\n
+);\n
+\n
+\n
+\n
+/* Symbol labels */\n
+var labels = new Array(\n
+\t"begin\'" /* Non-terminal symbol */,\n
+\t"WHITESPACE" /* Terminal symbol */,\n
+\t"WHITESPACE" /* Terminal symbol */,\n
+\t"LEFT_PARENTHESE" /* Terminal symbol */,\n
+\t"RIGHT_PARENTHESE" /* Terminal symbol */,\n
+\t"AND" /* Terminal symbol */,\n
+\t"OR" /* Terminal symbol */,\n
+\t"NOT" /* Terminal symbol */,\n
+\t"COLUMN" /* Terminal symbol */,\n
+\t"STRING" /* Terminal symbol */,\n
+\t"WORD" /* Terminal symbol */,\n
+\t"OPERATOR" /* Terminal symbol */,\n
+\t"search_text" /* Non-terminal symbol */,\n
+\t"begin" /* Non-terminal symbol */,\n
+\t"and_expression" /* Non-terminal symbol */,\n
+\t"boolean_expression" /* Non-terminal symbol */,\n
+\t"expression" /* Non-terminal symbol */,\n
+\t"value" /* Non-terminal symbol */,\n
+\t"string" /* Non-terminal symbol */,\n
+\t"$" /* Terminal symbol */\n
+);\n
+\n
+\n
+\t\n
+\tinfo.offset = 0;\n
+\tinfo.src = src;\n
+\tinfo.att = new String();\n
+\t\n
+\tif( !err_off )\n
+\t\terr_off\t= new Array();\n
+\tif( !err_la )\n
+\terr_la = new Array();\n
+\t\n
+\tsstack.push( 0 );\n
+\tvstack.push( 0 );\n
+\t\n
+\tla = __NODEJS_lex( info );\n
+\n
+\twhile( true )\n
+\t{\n
+\t\tact = 25;\n
+\t\tfor( var i = 0; i < act_tab[sstack[sstack.length-1]].length; i+=2 )\n
+\t\t{\n
+\t\t\tif( act_tab[sstack[sstack.length-1]][i] == la )\n
+\t\t\t{\n
+\t\t\t\tact = act_tab[sstack[sstack.length-1]][i+1];\n
+\t\t\t\tbreak;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif( NODEJS__dbg_withtrace && sstack.length > 0 )\n
+\t\t{\n
+\t\t\t__NODEJS_dbg_print( "\\nState " + sstack[sstack.length-1] + "\\n" +\n
+\t\t\t\t\t\t\t"\\tLookahead: " + labels[la] + " (\\"" + info.att + "\\")\\n" +\n
+\t\t\t\t\t\t\t"\\tAction: " + act + "\\n" + \n
+\t\t\t\t\t\t\t"\\tSource: \\"" + info.src.substr( info.offset, 30 ) + ( ( info.offset + 30 < info.src.length ) ?\n
+\t\t\t\t\t\t\t\t\t"..." : "" ) + "\\"\\n" +\n
+\t\t\t\t\t\t\t"\\tStack: " + sstack.join() + "\\n" +\n
+\t\t\t\t\t\t\t"\\tValue stack: " + vstack.join() + "\\n" );\n
+\t\t}\n
+\t\t\n
+\t\t\t\n
+\t\t//Panic-mode: Try recovery when parse-error occurs!\n
+\t\tif( act == 25 )\n
+\t\t{\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "Error detected: There is no reduce or shift on the symbol " + labels[la] );\n
+\t\t\t\n
+\t\t\terr_cnt++;\n
+\t\t\terr_off.push( info.offset - info.att.length );\t\t\t\n
+\t\t\terr_la.push( new Array() );\n
+\t\t\tfor( var i = 0; i < act_tab[sstack[sstack.length-1]].length; i+=2 )\n
+\t\t\t\terr_la[err_la.length-1].push( labels[act_tab[sstack[sstack.length-1]][i]] );\n
+\t\t\t\n
+\t\t\t//Remember the original stack!\n
+\t\t\tvar rsstack = new Array();\n
+\t\t\tvar rvstack = new Array();\n
+\t\t\tfor( var i = 0; i < sstack.length; i++ )\n
+\t\t\t{\n
+\t\t\t\trsstack[i] = sstack[i];\n
+\t\t\t\trvstack[i] = vstack[i];\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\twhile( act == 25 && la != 19 )\n
+\t\t\t{\n
+\t\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t\t__NODEJS_dbg_print( "\\tError recovery\\n" +\n
+\t\t\t\t\t\t\t\t\t"Current lookahead: " + labels[la] + " (" + info.att + ")\\n" +\n
+\t\t\t\t\t\t\t\t\t"Action: " + act + "\\n\\n" );\n
+\t\t\t\tif( la == -1 )\n
+\t\t\t\t\tinfo.offset++;\n
+\t\t\t\t\t\n
+\t\t\t\twhile( act == 25 && sstack.length > 0 )\n
+\t\t\t\t{\n
+\t\t\t\t\tsstack.pop();\n
+\t\t\t\t\tvstack.pop();\n
+\t\t\t\t\t\n
+\t\t\t\t\tif( sstack.length == 0 )\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\t\n
+\t\t\t\t\tact = 25;\n
+\t\t\t\t\tfor( var i = 0; i < act_tab[sstack[sstack.length-1]].length; i+=2 )\n
+\t\t\t\t\t{\n
+\t\t\t\t\t\tif( act_tab[sstack[sstack.length-1]][i] == la )\n
+\t\t\t\t\t\t{\n
+\t\t\t\t\t\t\tact = act_tab[sstack[sstack.length-1]][i+1];\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\t\n
+\t\t\t\tif( act != 25 )\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t\n
+\t\t\t\tfor( var i = 0; i < rsstack.length; i++ )\n
+\t\t\t\t{\n
+\t\t\t\t\tsstack.push( rsstack[i] );\n
+\t\t\t\t\tvstack.push( rvstack[i] );\n
+\t\t\t\t}\n
+\t\t\t\t\n
+\t\t\t\tla = __NODEJS_lex( info );\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\tif( act == 25 )\n
+\t\t\t{\n
+\t\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t\t__NODEJS_dbg_print( "\\tError recovery failed, terminating parse process..." );\n
+\t\t\t\tbreak;\n
+\t\t\t}\n
+\n
+\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "\\tError recovery succeeded, continuing" );\n
+\t\t}\n
+\t\t\n
+\t\t/*\n
+\t\tif( act == 25 )\n
+\t\t\tbreak;\n
+\t\t*/\n
+\t\t\n
+\t\t\n
+\t\t//Shift\n
+\t\tif( act > 0 )\n
+\t\t{\t\t\t\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "Shifting symbol: " + labels[la] + " (" + info.att + ")" );\n
+\t\t\n
+\t\t\tsstack.push( act );\n
+\t\t\tvstack.push( info.att );\n
+\t\t\t\n
+\t\t\tla = __NODEJS_lex( info );\n
+\t\t\t\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "\\tNew lookahead symbol: " + labels[la] + " (" + info.att + ")" );\n
+\t\t}\n
+\t\t//Reduce\n
+\t\telse\n
+\t\t{\t\t\n
+\t\t\tact *= -1;\n
+\t\t\t\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "Reducing by producution: " + act );\n
+\t\t\t\n
+\t\t\trval = void(0);\n
+\t\t\t\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "\\tPerforming semantic action..." );\n
+\t\t\t\n
+switch( act )\n
+{\n
+\tcase 0:\n
+\t{\n
+\t\trval = vstack[ vstack.length - 1 ];\n
+\t}\n
+\tbreak;\n
+\tcase 1:\n
+\t{\n
+\t\t result = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 2:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 3:\n
+\t{\n
+\t\t rval = mkComplexQuery(\'OR\',[vstack[ vstack.length - 2 ],vstack[ vstack.length - 1 ]]); \n
+\t}\n
+\tbreak;\n
+\tcase 4:\n
+\t{\n
+\t\t rval = mkComplexQuery(\'OR\',[vstack[ vstack.length - 3 ],vstack[ vstack.length - 1 ]]); \n
+\t}\n
+\tbreak;\n
+\tcase 5:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 1 ] ; \n
+\t}\n
+\tbreak;\n
+\tcase 6:\n
+\t{\n
+\t\t rval = mkComplexQuery(\'AND\',[vstack[ vstack.length - 3 ],vstack[ vstack.length - 1 ]]); \n
+\t}\n
+\tbreak;\n
+\tcase 7:\n
+\t{\n
+\t\t rval = mkNotQuery(vstack[ vstack.length - 1 ]); \n
+\t}\n
+\tbreak;\n
+\tcase 8:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 9:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 2 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 10:\n
+\t{\n
+\t\t simpleQuerySetKey(vstack[ vstack.length - 1 ],vstack[ vstack.length - 2 ].split(\':\').slice(0,-1).join(\':\')); rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 11:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 12:\n
+\t{\n
+\t\t vstack[ vstack.length - 1 ].operator = vstack[ vstack.length - 2 ] ; rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 13:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 14:\n
+\t{\n
+\t\t rval = mkSimpleQuery(\'\',vstack[ vstack.length - 1 ]); \n
+\t}\n
+\tbreak;\n
+\tcase 15:\n
+\t{\n
+\t\t rval = mkSimpleQuery(\'\',vstack[ vstack.length - 1 ].split(\'"\').slice(1,-1).join(\'"\')); \n
+\t}\n
+\tbreak;\n
+}\n
+\n
+\n
+\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "\\tPopping " + pop_tab[act][1] + " off the stack..." );\n
+\t\t\t\t\n
+\t\t\tfor( var i = 0; i < pop_tab[act][1]; i++ )\n
+\t\t\t{\n
+\t\t\t\tsstack.pop();\n
+\t\t\t\tvstack.pop();\n
+\t\t\t}\n
+\t\t\t\t\t\t\t\t\t\n
+\t\t\tgo = -1;\n
+\t\t\tfor( var i = 0; i < goto_tab[sstack[sstack.length-1]].length; i+=2 )\n
+\t\t\t{\n
+\t\t\t\tif( goto_tab[sstack[sstack.length-1]][i] == pop_tab[act][0] )\n
+\t\t\t\t{\n
+\t\t\t\t\tgo = goto_tab[sstack[sstack.length-1]][i+1];\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\tif( act == 0 )\n
+\t\t\t\tbreak;\n
+\t\t\t\t\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "\\tPushing non-terminal " + labels[ pop_tab[act][0] ] );\n
+\t\t\t\t\n
+\t\t\tsstack.push( go );\n
+\t\t\tvstack.push( rval );\t\t\t\n
+\t\t}\n
+\t\t\n
+\t\tif( NODEJS__dbg_withtrace )\n
+\t\t{\t\t\n
+\t\t\talert( NODEJS__dbg_string );\n
+\t\t\tNODEJS__dbg_string = new String();\n
+\t\t}\n
+\t}\n
+\n
+\tif( NODEJS__dbg_withtrace )\n
+\t{\n
+\t\t__NODEJS_dbg_print( "\\nParse complete." );\n
+\t\talert( NODEJS__dbg_string );\n
+\t}\n
+\t\n
+\treturn err_cnt;\n
+}\n
+\n
+\n
+\n
+var arrayExtend = function () {\n
+  var j, i, newlist = [], list_list = arguments;\n
+  for (j = 0; j < list_list.length; j += 1) {\n
+    for (i = 0; i < list_list[j].length; i += 1) {\n
+      newlist.push(list_list[j][i]);\n
+    }\n
+  }\n
+  return newlist;\n
+\n
+}, mkSimpleQuery = function (key, value, operator) {\n
+  var object = {"type": "simple", "key": key, "value": value};\n
+  if (operator !== undefined) {\n
+    object.operator = operator;\n
+  }\n
+  return object;\n
+\n
+}, mkNotQuery = function (query) {\n
+  if (query.operator === "NOT") {\n
+    return query.query_list[0];\n
+  }\n
+  return {"type": "complex", "operator": "NOT", "query_list": [query]};\n
+\n
+}, mkComplexQuery = function (operator, query_list) {\n
+  var i, query_list2 = [];\n
+  for (i = 0; i < query_list.length; i += 1) {\n
+    if (query_list[i].operator === operator) {\n
+      query_list2 = arrayExtend(query_list2, query_list[i].query_list);\n
+    } else {\n
+      query_list2.push(query_list[i]);\n
+    }\n
+  }\n
+  return {type:"complex",operator:operator,query_list:query_list2};\n
+\n
+}, simpleQuerySetKey = function (query, key) {\n
+  var i;\n
+  if (query.type === "complex") {\n
+    for (i = 0; i < query.query_list.length; ++i) {\n
+      simpleQuerySetKey (query.query_list[i],key);\n
+    }\n
+    return true;\n
+  }\n
+  if (query.type === "simple" && !query.key) {\n
+    query.key = key;\n
+    return true;\n
+  }\n
+  return false;\n
+},\n
+  error_offsets = [],\n
+  error_lookaheads = [],\n
+  error_count = 0,\n
+  result;\n
+\n
+if ((error_count = __NODEJS_parse(string, error_offsets, error_lookaheads)) > 0) {\n
+  var i;\n
+  for (i = 0; i < error_count; i += 1) {\n
+    throw new Error("Parse error near \\"" +\n
+                    string.substr(error_offsets[i]) +\n
+                    "\\", expecting \\"" +\n
+                    error_lookaheads[i].join() + "\\"");\n
+  }\n
+}\n
+\n
+\n
+  return result;\n
+} // parseStringToObject\n
+\n
+Query.parseStringToObject = parseStringToObject;\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global Query: true, query_class_dict: true, inherits: true,\n
+         exports, QueryFactory, RSVP, sequence */\n
+\n
+/**\n
+ * The ComplexQuery inherits from Query, and compares one or several metadata\n
+ * values.\n
+ *\n
+ * @class ComplexQuery\n
+ * @extends Query\n
+ * @param  {Object} [spec={}] The specifications\n
+ * @param  {String} [spec.operator="AND"] The compare method to use\n
+ * @param  {String} spec.key The metadata key\n
+ * @param  {String} spec.value The value of the metadata to compare\n
+ */\n
+function ComplexQuery(spec, key_schema) {\n
+  Query.call(this);\n
+\n
+  /**\n
+   * Logical operator to use to compare object values\n
+   *\n
+   * @attribute operator\n
+   * @type String\n
+   * @default "AND"\n
+   * @optional\n
+   */\n
+  this.operator = spec.operator;\n
+\n
+  /**\n
+   * The sub Query list which are used to query an item.\n
+   *\n
+   * @attribute query_list\n
+   * @type Array\n
+   * @default []\n
+   * @optional\n
+   */\n
+  this.query_list = spec.query_list || [];\n
+  /*jslint unparam: true*/\n
+  this.query_list = this.query_list.map(\n
+    // decorate the map to avoid sending the index as key_schema argument\n
+    function (o, i) { return QueryFactory.create(o, key_schema); }\n
+  );\n
+  /*jslint unparam: false*/\n
+\n
+}\n
+inherits(ComplexQuery, Query);\n
+\n
+ComplexQuery.prototype.operator = "AND";\n
+ComplexQuery.prototype.type = "complex";\n
+\n
+/**\n
+ * #crossLink "Query/match:method"\n
+ */\n
+ComplexQuery.prototype.match = function (item) {\n
+  var operator = this.operator;\n
+  if (!(/^(?:AND|OR|NOT)$/i.test(operator))) {\n
+    operator = "AND";\n
+  }\n
+  return this[operator.toUpperCase()](item);\n
+};\n
+\n
+/**\n
+ * #crossLink "Query/toString:method"\n
+ */\n
+ComplexQuery.prototype.toString = function () {\n
+  var str_list = [], this_operator = this.operator;\n
+  if (this.operator === "NOT") {\n
+    str_list.push("NOT (");\n
+    str_list.push(this.query_list[0].toString());\n
+    str_list.push(")");\n
+    return str_list.join(" ");\n
+  }\n
+  this.query_list.forEach(function (query) {\n
+    str_list.push("(");\n
+    str_list.push(query.toString());\n
+    str_list.push(")");\n
+    str_list.push(this_operator);\n
+  });\n
+  str_list.length -= 1;\n
+  return str_list.join(" ");\n
+};\n
+\n
+/**\n
+ * #crossLink "Query/serialized:method"\n
+ */\n
+ComplexQuery.prototype.serialized = function () {\n
+  var s = {\n
+    "type": "complex",\n
+    "operator": this.operator,\n
+    "query_list": []\n
+  };\n
+  this.query_list.forEach(function (query) {\n
+    s.query_list.push(\n
+      typeof query.toJSON === "function" ? query.toJSON() : query\n
+    );\n
+  });\n
+  return s;\n
+};\n
+ComplexQuery.prototype.toJSON = ComplexQuery.prototype.serialized;\n
+\n
+/**\n
+ * Comparison operator, test if all sub queries match the\n
+ * item value\n
+ *\n
+ * @method AND\n
+ * @param  {Object} item The item to match\n
+ * @return {Boolean} true if all match, false otherwise\n
+ */\n
+ComplexQuery.prototype.AND = function (item) {\n
+  var j, promises = [];\n
+  for (j = 0; j < this.query_list.length; j += 1) {\n
+    promises.push(this.query_list[j].match(item));\n
+  }\n
+\n
+  function cancel() {\n
+    var i;\n
+    for (i = 0; i < promises.length; i += 1) {\n
+      if (typeof promises.cancel === \'function\') {\n
+        promises.cancel();\n
+      }\n
+    }\n
+  }\n
+\n
+  return new RSVP.Promise(function (resolve, reject) {\n
+    var i, count = 0;\n
+    function resolver(value) {\n
+      if (!value) {\n
+        resolve(false);\n
+      }\n
+      count += 1;\n
+      if (count === promises.length) {\n
+        resolve(true);\n
+      }\n
+    }\n
+\n
+    function rejecter(err) {\n
+      reject(err);\n
+      cancel();\n
+    }\n
+\n
+    for (i = 0; i < promises.length; i += 1) {\n
+      promises[i].then(resolver, rejecter);\n
+    }\n
+  }, cancel);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if one of the sub queries matches the\n
+ * item value\n
+ *\n
+ * @method OR\n
+ * @param  {Object} item The item to match\n
+ * @return {Boolean} true if one match, false otherwise\n
+ */\n
+ComplexQuery.prototype.OR =  function (item) {\n
+  var j, promises = [];\n
+  for (j = 0; j < this.query_list.length; j += 1) {\n
+    promises.push(this.query_list[j].match(item));\n
+  }\n
+\n
+  function cancel() {\n
+    var i;\n
+    for (i = 0; i < promises.length; i += 1) {\n
+      if (typeof promises.cancel === \'function\') {\n
+        promises.cancel();\n
+      }\n
+    }\n
+  }\n
+\n
+  return new RSVP.Promise(function (resolve, reject) {\n
+    var i, count = 0;\n
+    function resolver(value) {\n
+      if (value) {\n
+        resolve(true);\n
+      }\n
+      count += 1;\n
+      if (count === promises.length) {\n
+        resolve(false);\n
+      }\n
+    }\n
+\n
+    function rejecter(err) {\n
+      reject(err);\n
+      cancel();\n
+    }\n
+\n
+    for (i = 0; i < promises.length; i += 1) {\n
+      promises[i].then(resolver, rejecter);\n
+    }\n
+  }, cancel);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if the sub query does not match the\n
+ * item value\n
+ *\n
+ * @method NOT\n
+ * @param  {Object} item The item to match\n
+ * @return {Boolean} true if one match, false otherwise\n
+ */\n
+ComplexQuery.prototype.NOT = function (item) {\n
+  return sequence([function () {\n
+    return this.query_list[0].match(item);\n
+  }, function (answer) {\n
+    return !answer;\n
+  }]);\n
+};\n
+\n
+query_class_dict.complex = ComplexQuery;\n
+\n
+exports.ComplexQuery = ComplexQuery;\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global exports, ComplexQuery, SimpleQuery, Query, parseStringToObject,\n
+  query_class_dict */\n
+\n
+/**\n
+ * Provides static methods to create Query object\n
+ *\n
+ * @class QueryFactory\n
+ */\n
+function QueryFactory() {\n
+  return;\n
+}\n
+\n
+/**\n
+ * Creates Query object from a search text string or a serialized version\n
+ * of a Query.\n
+ *\n
+ * @method create\n
+ * @static\n
+ * @param  {Object,String} object The search text or the serialized version\n
+ *         of a Query\n
+ * @return {Query} A Query object\n
+ */\n
+QueryFactory.create = function (object, key_schema) {\n
+  if (object === "") {\n
+    return new Query();\n
+  }\n
+  if (typeof object === "string") {\n
+    object = parseStringToObject(object);\n
+  }\n
+  if (typeof (object || {}).type === "string" &&\n
+      query_class_dict[object.type]) {\n
+    return new query_class_dict[object.type](object, key_schema);\n
+  }\n
+  throw new TypeError("QueryFactory.create(): " +\n
+                      "Argument 1 is not a search text or a parsable object");\n
+};\n
+\n
+exports.QueryFactory = QueryFactory;\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global Query, exports */\n
+\n
+function objectToSearchText(query) {\n
+  var str_list = [];\n
+  if (query.type === "complex") {\n
+    str_list.push("(");\n
+    (query.query_list || []).forEach(function (sub_query) {\n
+      str_list.push(objectToSearchText(sub_query));\n
+      str_list.push(query.operator);\n
+    });\n
+    str_list.length -= 1;\n
+    str_list.push(")");\n
+    return str_list.join(" ");\n
+  }\n
+  if (query.type === "simple") {\n
+    return (query.key ? query.key + ": " : "") +\n
+      (query.operator || "") + \' "\' + query.value + \'"\';\n
+  }\n
+  throw new TypeError("This object is not a query");\n
+}\n
+Query.objectToSearchText = objectToSearchText;\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global Query, inherits, query_class_dict, exports,\n
+  searchTextToRegExp, RSVP */\n
+\n
+var checkKeySchema = function (key_schema) {\n
+  var prop;\n
+\n
+  if (key_schema !== undefined) {\n
+    if (typeof key_schema !== \'object\') {\n
+      throw new TypeError("SimpleQuery().create(): " +\n
+                          "key_schema is not of type \'object\'");\n
+    }\n
+    // key_set is mandatory\n
+    if (key_schema.key_set === undefined) {\n
+      throw new TypeError("SimpleQuery().create(): " +\n
+                          "key_schema has no \'key_set\' property");\n
+    }\n
+    for (prop in key_schema) {\n
+      if (key_schema.hasOwnProperty(prop)) {\n
+        switch (prop) {\n
+        case \'key_set\':\n
+        case \'cast_lookup\':\n
+        case \'match_lookup\':\n
+          break;\n
+        default:\n
+          throw new TypeError("SimpleQuery().create(): " +\n
+                             "key_schema has unknown property \'" + prop + "\'");\n
+        }\n
+      }\n
+    }\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * The SimpleQuery inherits from Query, and compares one metadata value\n
+ *\n
+ * @class SimpleQuery\n
+ * @extends Query\n
+ * @param  {Object} [spec={}] The specifications\n
+ * @param  {String} [spec.operator="="] The compare method to use\n
+ * @param  {String} spec.key The metadata key\n
+ * @param  {String} spec.value The value of the metadata to compare\n
+ */\n
+function SimpleQuery(spec, key_schema) {\n
+  Query.call(this);\n
+\n
+  checkKeySchema(key_schema);\n
+\n
+  this._key_schema = key_schema || {};\n
+\n
+  /**\n
+   * Operator to use to compare object values\n
+   *\n
+   * @attribute operator\n
+   * @type String\n
+   * @optional\n
+   */\n
+  this.operator = spec.operator;\n
+\n
+  /**\n
+   * Key of the object which refers to the value to compare\n
+   *\n
+   * @attribute key\n
+   * @type String\n
+   */\n
+  this.key = spec.key;\n
+\n
+  /**\n
+   * Value is used to do the comparison with the object value\n
+   *\n
+   * @attribute value\n
+   * @type String\n
+   */\n
+  this.value = spec.value;\n
+\n
+}\n
+inherits(SimpleQuery, Query);\n
+\n
+SimpleQuery.prototype.type = "simple";\n
+\n
+var checkKey = function (key) {\n
+  var prop;\n
+\n
+  if (key.read_from === undefined) {\n
+    throw new TypeError("Custom key is missing the read_from property");\n
+  }\n
+\n
+  for (prop in key) {\n
+    if (key.hasOwnProperty(prop)) {\n
+      switch (prop) {\n
+      case \'read_from\':\n
+      case \'cast_to\':\n
+      case \'equal_match\':\n
+        break;\n
+      default:\n
+        throw new TypeError("Custom key has unknown property \'" +\n
+                            prop + "\'");\n
+      }\n
+    }\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * #crossLink "Query/match:method"\n
+ */\n
+SimpleQuery.prototype.match = function (item) {\n
+  var object_value = null,\n
+    equal_match = null,\n
+    cast_to = null,\n
+    matchMethod = null,\n
+    operator = this.operator,\n
+    value = null,\n
+    key = this.key;\n
+\n
+  /*jslint regexp: true */\n
+  if (!(/^(?:!?=|<=?|>=?)$/i.test(operator))) {\n
+    // `operator` is not correct, we have to change it to "like" or "="\n
+    if (/%/.test(this.value)) {\n
+      // `value` contains a non escaped `%`\n
+      operator = "like";\n
+    } else {\n
+      // `value` does not contain non escaped `%`\n
+      operator = "=";\n
+    }\n
+  }\n
+\n
+  matchMethod = this[operator];\n
+\n
+  if (this._key_schema.key_set && this._key_schema.key_set[key] !== undefined) {\n
+    key = this._key_schema.key_set[key];\n
+  }\n
+\n
+  if (typeof key === \'object\') {\n
+    checkKey(key);\n
+    object_value = item[key.read_from];\n
+\n
+    equal_match = key.equal_match;\n
+\n
+    // equal_match can be a string\n
+    if (typeof equal_match === \'string\') {\n
+      // XXX raise error if equal_match not in match_lookup\n
+      equal_match = this._key_schema.match_lookup[equal_match];\n
+    }\n
+\n
+    // equal_match overrides the default \'=\' operator\n
+    if (equal_match !== undefined) {\n
+      matchMethod = (operator === "=" || operator === "like" ?\n
+                     equal_match : matchMethod);\n
+    }\n
+\n
+    value = this.value;\n
+    cast_to = key.cast_to;\n
+    if (cast_to) {\n
+      // cast_to can be a string\n
+      if (typeof cast_to === \'string\') {\n
+        // XXX raise error if cast_to not in cast_lookup\n
+        cast_to = this._key_schema.cast_lookup[cast_to];\n
+      }\n
+\n
+      try {\n
+        value = cast_to(value);\n
+      } catch (e) {\n
+        value = undefined;\n
+      }\n
+\n
+      try {\n
+        object_value = cast_to(object_value);\n
+      } catch (e) {\n
+        object_value = undefined;\n
+      }\n
+    }\n
+  } else {\n
+    object_value = item[key];\n
+    value = this.value;\n
+  }\n
+  if (object_value === undefined || value === undefined) {\n
+    return RSVP.resolve(false);\n
+  }\n
+  return matchMethod(object_value, value);\n
+};\n
+\n
+/**\n
+ * #crossLink "Query/toString:method"\n
+ */\n
+SimpleQuery.prototype.toString = function () {\n
+  return (this.key ? this.key + ":" : "") +\n
+    (this.operator ? " " + this.operator : "") + \' "\' + this.value + \'"\';\n
+};\n
+\n
+/**\n
+ * #crossLink "Query/serialized:method"\n
+ */\n
+SimpleQuery.prototype.serialized = function () {\n
+  var object = {\n
+    "type": "simple",\n
+    "key": this.key,\n
+    "value": this.value\n
+  };\n
+  if (this.operator !== undefined) {\n
+    object.operator = this.operator;\n
+  }\n
+  return object;\n
+};\n
+SimpleQuery.prototype.toJSON = SimpleQuery.prototype.serialized;\n
+\n
+/**\n
+ * Comparison operator, test if this query value matches the item value\n
+ *\n
+ * @method =\n
+ * @param  {String} object_value The value to compare\n
+ * @param  {String} comparison_value The comparison value\n
+ * @return {Boolean} true if match, false otherwise\n
+ */\n
+SimpleQuery.prototype["="] = function (object_value, comparison_value) {\n
+  var value, i;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  for (i = 0; i < object_value.length; i += 1) {\n
+    value = object_value[i];\n
+    if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+      value = value.content;\n
+    }\n
+    if (typeof value.cmp === "function") {\n
+      return RSVP.resolve(value.cmp(comparison_value) === 0);\n
+    }\n
+    if (\n
+      searchTextToRegExp(comparison_value.toString(), false).\n
+        test(value.toString())\n
+    ) {\n
+      return RSVP.resolve(true);\n
+    }\n
+  }\n
+  return RSVP.resolve(false);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value matches the item value\n
+ *\n
+ * @method like\n
+ * @param  {String} object_value The value to compare\n
+ * @param  {String} comparison_value The comparison value\n
+ * @return {Boolean} true if match, false otherwise\n
+ */\n
+SimpleQuery.prototype.like = function (object_value, comparison_value) {\n
+  var value, i;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  for (i = 0; i < object_value.length; i += 1) {\n
+    value = object_value[i];\n
+    if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+      value = value.content;\n
+    }\n
+    if (typeof value.cmp === "function") {\n
+      return RSVP.resolve(value.cmp(comparison_value) === 0);\n
+    }\n
+    if (\n
+      searchTextToRegExp(comparison_value.toString()).test(value.toString())\n
+    ) {\n
+      return RSVP.resolve(true);\n
+    }\n
+  }\n
+  return RSVP.resolve(false);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value does not match the item value\n
+ *\n
+ * @method !=\n
+ * @param  {String} object_value The value to compare\n
+ * @param  {String} comparison_value The comparison value\n
+ * @return {Boolean} true if not match, false otherwise\n
+ */\n
+SimpleQuery.prototype["!="] = function (object_value, comparison_value) {\n
+  var value, i;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  for (i = 0; i < object_value.length; i += 1) {\n
+    value = object_value[i];\n
+    if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+      value = value.content;\n
+    }\n
+    if (typeof value.cmp === "function") {\n
+      return RSVP.resolve(value.cmp(comparison_value) !== 0);\n
+    }\n
+    if (\n
+      searchTextToRegExp(comparison_value.toString(), false).\n
+        test(value.toString())\n
+    ) {\n
+      return RSVP.resolve(false);\n
+    }\n
+  }\n
+  return RSVP.resolve(true);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value is lower than the item value\n
+ *\n
+ * @method <\n
+ * @param  {Number, String} object_value The value to compare\n
+ * @param  {Number, String} comparison_value The comparison value\n
+ * @return {Boolean} true if lower, false otherwise\n
+ */\n
+SimpleQuery.prototype["<"] = function (object_value, comparison_value) {\n
+  var value;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  value = object_value[0];\n
+  if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+    value = value.content;\n
+  }\n
+  if (typeof value.cmp === "function") {\n
+    return RSVP.resolve(value.cmp(comparison_value) < 0);\n
+  }\n
+  return RSVP.resolve(value < comparison_value);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value is equal or lower than the\n
+ * item value\n
+ *\n
+ * @method <=\n
+ * @param  {Number, String} object_value The value to compare\n
+ * @param  {Number, String} comparison_value The comparison value\n
+ * @return {Boolean} true if equal or lower, false otherwise\n
+ */\n
+SimpleQuery.prototype["<="] = function (object_value, comparison_value) {\n
+  var value;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  value = object_value[0];\n
+  if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+    value = value.content;\n
+  }\n
+  if (typeof value.cmp === "function") {\n
+    return RSVP.resolve(value.cmp(comparison_value) <= 0);\n
+  }\n
+  return RSVP.resolve(value <= comparison_value);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value is greater than the item\n
+ * value\n
+ *\n
+ * @method >\n
+ * @param  {Number, String} object_value The value to compare\n
+ * @param  {Number, String} comparison_value The comparison value\n
+ * @return {Boolean} true if greater, false otherwise\n
+ */\n
+SimpleQuery.prototype[">"] = function (object_value, comparison_value) {\n
+  var value;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  value = object_value[0];\n
+  if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+    value = value.content;\n
+  }\n
+  if (typeof value.cmp === "function") {\n
+    return RSVP.resolve(value.cmp(comparison_value) > 0);\n
+  }\n
+  return RSVP.resolve(value > comparison_value);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value is equal or greater than the\n
+ * item value\n
+ *\n
+ * @method >=\n
+ * @param  {Number, String} object_value The value to compare\n
+ * @param  {Number, String} comparison_value The comparison value\n
+ * @return {Boolean} true if equal or greater, false otherwise\n
+ */\n
+SimpleQuery.prototype[">="] = function (object_value, comparison_value) {\n
+  var value;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  value = object_value[0];\n
+  if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+    value = value.content;\n
+  }\n
+  if (typeof value.cmp === "function") {\n
+    return RSVP.resolve(value.cmp(comparison_value) >= 0);\n
+  }\n
+  return RSVP.resolve(value >= comparison_value);\n
+};\n
+\n
+query_class_dict.simple = SimpleQuery;\n
+\n
+exports.SimpleQuery = SimpleQuery;\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global Query, RSVP, deepClone */\n
+\n
+/**\n
+ * Escapes regexp special chars from a string.\n
+ *\n
+ * @param  {String} string The string to escape\n
+ * @return {String} The escaped string\n
+ */\n
+function stringEscapeRegexpCharacters(string) {\n
+  if (typeof string === "string") {\n
+    return string.replace(/([\\\\\\.\\$\\[\\]\\(\\)\\{\\}\\^\\?\\*\\+\\-])/g, "\\\\$1");\n
+  }\n
+  throw new TypeError("Query.stringEscapeRegexpCharacters(): " +\n
+                      "Argument no 1 is not of type \'string\'");\n
+}\n
+\n
+Query.stringEscapeRegexpCharacters = stringEscapeRegexpCharacters;\n
+\n
+/**\n
+ * Convert metadata values to array of strings. ex:\n
+ *\n
+ *     "a" -> ["a"],\n
+ *     {"content": "a"} -> ["a"]\n
+ *\n
+ * @param  {Any} value The metadata value\n
+ * @return {Array} The value in string array format\n
+ */\n
+function metadataValueToStringArray(value) {\n
+  var i, new_value = [];\n
+  if (value === undefined) {\n
+    return undefined;\n
+  }\n
+  if (!Array.isArray(value)) {\n
+    value = [value];\n
+  }\n
+  for (i = 0; i < value.length; i += 1) {\n
+    if (typeof value[i] === \'object\') {\n
+      new_value[i] = value[i].content;\n
+    } else {\n
+      new_value[i] = value[i];\n
+    }\n
+  }\n
+  return new_value;\n
+}\n
+\n
+/**\n
+ * A sort function to sort items by key\n
+ *\n
+ * @param  {String} key The key to sort on\n
+ * @param  {String} [way="ascending"] \'ascending\' or \'descending\'\n
+ * @return {Function} The sort function\n
+ */\n
+function sortFunction(key, way) {\n
+  if (way === \'descending\') {\n
+    return function (a, b) {\n
+      // this comparison is 5 times faster than json comparison\n
+      var i, l;\n
+      a = metadataValueToStringArray(a[key]) || [];\n
+      b = metadataValueToStringArray(b[key]) || [];\n
+      l = a.length > b.length ? a.length : b.length;\n
+      for (i = 0; i < l; i += 1) {\n
+        if (a[i] === undefined) {\n
+          return 1;\n
+        }\n
+        if (b[i] === undefined) {\n
+          return -1;\n
+        }\n
+        if (a[i] > b[i]) {\n
+          return -1;\n
+        }\n
+        if (a[i] < b[i]) {\n
+          return 1;\n
+        }\n
+      }\n
+      return 0;\n
+    };\n
+  }\n
+  if (way === \'ascending\') {\n
+    return function (a, b) {\n
+      // this comparison is 5 times faster than json comparison\n
+      var i, l;\n
+      a = metadataValueToStringArray(a[key]) || [];\n
+      b = metadataValueToStringArray(b[key]) || [];\n
+      l = a.length > b.length ? a.length : b.length;\n
+      for (i = 0; i < l; i += 1) {\n
+        if (a[i] === undefined) {\n
+          return -1;\n
+        }\n
+        if (b[i] === undefined) {\n
+          return 1;\n
+        }\n
+        if (a[i] > b[i]) {\n
+          return 1;\n
+        }\n
+        if (a[i] < b[i]) {\n
+          return -1;\n
+        }\n
+      }\n
+      return 0;\n
+    };\n
+  }\n
+  throw new TypeError("Query.sortFunction(): " +\n
+                      "Argument 2 must be \'ascending\' or \'descending\'");\n
+}\n
+\n
+/**\n
+ * Inherits the prototype methods from one constructor into another. The\n
+ * prototype of `constructor` will be set to a new object created from\n
+ * `superConstructor`.\n
+ *\n
+ * @param  {Function} constructor The constructor which inherits the super one\n
+ * @param  {Function} superConstructor The super constructor\n
+ */\n
+function inherits(constructor, superConstructor) {\n
+  constructor.super_ = superConstructor;\n
+  constructor.prototype = Object.create(superConstructor.prototype, {\n
+    "constructor": {\n
+      "configurable": true,\n
+      "enumerable": false,\n
+      "writable": true,\n
+      "value": constructor\n
+    }\n
+  });\n
+}\n
+\n
+/**\n
+ * Does nothing\n
+ */\n
+function emptyFunction() {\n
+  return;\n
+}\n
+\n
+/**\n
+ * Filter a list of items, modifying them to select only wanted keys. If\n
+ * `clone` is true, then the method will act on a cloned list.\n
+ *\n
+ * @param  {Array} select_option Key list to keep\n
+ * @param  {Array} list The item list to filter\n
+ * @param  {Boolean} [clone=false] If true, modifies a clone of the list\n
+ * @return {Array} The filtered list\n
+ */\n
+function select(select_option, list, clone) {\n
+  var i, j, new_item;\n
+  if (!Array.isArray(select_option)) {\n
+    throw new TypeError("jioquery.select(): " +\n
+                        "Argument 1 is not of type Array");\n
+  }\n
+  if (!Array.isArray(list)) {\n
+    throw new TypeError("jioquery.select(): " +\n
+                        "Argument 2 is not of type Array");\n
+  }\n
+  if (clone === true) {\n
+    list = deepClone(list);\n
+  }\n
+  for (i = 0; i < list.length; i += 1) {\n
+    new_item = {};\n
+    for (j = 0; j < select_option.length; j += 1) {\n
+      if (list[i].hasOwnProperty([select_option[j]])) {\n
+        new_item[select_option[j]] = list[i][select_option[j]];\n
+      }\n
+    }\n
+    for (j in new_item) {\n
+      if (new_item.hasOwnProperty(j)) {\n
+        list[i] = new_item;\n
+        break;\n
+      }\n
+    }\n
+  }\n
+  return list;\n
+}\n
+\n
+Query.select = select;\n
+\n
+/**\n
+ * Sort a list of items, according to keys and directions. If `clone` is true,\n
+ * then the method will act on a cloned list.\n
+ *\n
+ * @param  {Array} sort_on_option List of couples [key, direction]\n
+ * @param  {Array} list The item list to sort\n
+ * @param  {Boolean} [clone=false] If true, modifies a clone of the list\n
+ * @return {Array} The filtered list\n
+ */\n
+function sortOn(sort_on_option, list, clone) {\n
+  var sort_index;\n
+  if (!Array.isArray(sort_on_option)) {\n
+    throw new TypeError("jioquery.sortOn(): " +\n
+                        "Argument 1 is not of type \'array\'");\n
+  }\n
+  if (clone) {\n
+    list = deepClone(list);\n
+  }\n
+  for (sort_index = sort_on_option.length - 1; sort_index >= 0;\n
+       sort_index -= 1) {\n
+    list.sort(sortFunction(\n
+      sort_on_option[sort_index][0],\n
+      sort_on_option[sort_index][1]\n
+    ));\n
+  }\n
+  return list;\n
+}\n
+\n
+Query.sortOn = sortOn;\n
+\n
+/**\n
+ * Limit a list of items, according to index and length. If `clone` is true,\n
+ * then the method will act on a cloned list.\n
+ *\n
+ * @param  {Array} limit_option A couple [from, length]\n
+ * @param  {Array} list The item list to limit\n
+ * @param  {Boolean} [clone=false] If true, modifies a clone of the list\n
+ * @return {Array} The filtered list\n
+ */\n
+function limit(limit_option, list, clone) {\n
+  if (!Array.isArray(limit_option)) {\n
+    throw new TypeError("jioquery.limit(): " +\n
+                        "Argument 1 is not of type \'array\'");\n
+  }\n
+  if (!Array.isArray(list)) {\n
+    throw new TypeError("jioquery.limit(): " +\n
+                        "Argument 2 is not of type \'array\'");\n
+  }\n
+  if (clone) {\n
+    list = deepClone(list);\n
+  }\n
+  list.splice(0, limit_option[0]);\n
+  if (limit_option[1]) {\n
+    list.splice(limit_option[1]);\n
+  }\n
+  return list;\n
+}\n
+\n
+Query.limit = limit;\n
+\n
+/**\n
+ * Convert a search text to a regexp.\n
+ *\n
+ * @param  {String} string The string to convert\n
+ * @param  {Boolean} [use_wildcard_character=true] Use wildcard "%" and "_"\n
+ * @return {RegExp} The search text regexp\n
+ */\n
+function searchTextToRegExp(string, use_wildcard_characters) {\n
+  if (typeof string !== \'string\') {\n
+    throw new TypeError("jioquery.searchTextToRegExp(): " +\n
+                        "Argument 1 is not of type \'string\'");\n
+  }\n
+  if (use_wildcard_characters === false) {\n
+    return new RegExp("^" + stringEscapeRegexpCharacters(string) + "$");\n
+  }\n
+  return new RegExp("^" + stringEscapeRegexpCharacters(string).replace(\n
+    /%/g,\n
+    ".*"\n
+  ).replace(\n
+    /_/g,\n
+    "."\n
+  ) + "$");\n
+}\n
+\n
+Query.searchTextToRegExp = searchTextToRegExp;\n
+\n
+/**\n
+ * sequence(thens): Promise\n
+ *\n
+ * Executes a sequence of *then* callbacks. It acts like\n
+ * `smth().then(callback).then(callback)...`. The first callback is called with\n
+ * no parameter.\n
+ *\n
+ * Elements of `thens` array can be a function or an array contaning at most\n
+ * three *then* callbacks: *onFulfilled*, *onRejected*, *onNotified*.\n
+ *\n
+ * When `cancel()` is executed, each then promises are cancelled at the same\n
+ * time.\n
+ *\n
+ * @param  {Array} thens An array of *then* callbacks\n
+ * @return {Promise} A new promise\n
+ */\n
+function sequence(thens) {\n
+  var promises = [];\n
+  return new RSVP.Promise(function (resolve, reject, notify) {\n
+    var i;\n
+    promises[0] = new RSVP.Promise(function (resolve) {\n
+      resolve();\n
+    });\n
+    for (i = 0; i < thens.length; i += 1) {\n
+      if (Array.isArray(thens[i])) {\n
+        promises[i + 1] = promises[i].\n
+          then(thens[i][0], thens[i][1], thens[i][2]);\n
+      } else {\n
+        promises[i + 1] = promises[i].then(thens[i]);\n
+      }\n
+    }\n
+    promises[i].then(resolve, reject, notify);\n
+  }, function () {\n
+    var i;\n
+    for (i = 0; i < promises.length; i += 1) {\n
+      promises[i].cancel();\n
+    }\n
+  });\n
+}\n
+\n
+}));\n
+;/*\n
+* Copyright 2013, Nexedi SA\n
+* Released under the LGPL license.\n
+* http://www.gnu.org/licenses/lgpl.html\n
+*/\n
+\n
+/**\n
+ * Provides some function to use complex queries with item list\n
+ *\n
+ * @module complex_queries\n
+ */\n
+// define([module_name], [dependencies], module);\n
+(function (dependencies, module) {\n
+  "use strict";\n
+  if (typeof define === \'function\' && define.amd) {\n
+    return define(dependencies, module);\n
+  }\n
+  if (typeof exports === \'object\') {\n
+    return module(exports);\n
+  }\n
+  window.complex_queries = {};\n
+  module(window.complex_queries, RSVP);\n
+}([\'exports\', \'rsvp\'], function (to_export, RSVP) {\n
+  "use strict";\n
+\n
+  /**\n
+   * Add a secured (write permission denied) property to an object.\n
+   *\n
+   * @param  {Object} object The object to fill\n
+   * @param  {String} key The object key where to store the property\n
+   * @param  {Any} value The value to store\n
+   */\n
+  function _export(key, value) {\n
+    Object.defineProperty(to_export, key, {\n
+      "configurable": false,\n
+      "enumerable": true,\n
+      "writable": false,\n
+      "value": value\n
+    });\n
+  }\n
+\n
+/**\n
+ * Parse a text request to a json query object tree\n
+ *\n
+ * @param  {String} string The string to parse\n
+ * @return {Object} The json query tree\n
+ */\n
+function parseStringToObject(string) {\n
+\n
+\n
+/*\n
+\tDefault template driver for JS/CC generated parsers running as\n
+\tbrowser-based JavaScript/ECMAScript applications.\n
+\t\n
+\tWARNING: \tThis parser template will not run as console and has lesser\n
+\t\t\t\tfeatures for debugging than the console derivates for the\n
+\t\t\t\tvarious JavaScript platforms.\n
+\t\n
+\tFeatures:\n
+\t- Parser trace messages\n
+\t- Integrated panic-mode error recovery\n
+\t\n
+\tWritten 2007, 2008 by Jan Max Meyer, J.M.K S.F. Software Technologies\n
+\t\n
+\tThis is in the public domain.\n
+*/\n
+\n
+var NODEJS__dbg_withtrace\t\t= false;\n
+var NODEJS__dbg_string\t\t\t= new String();\n
+\n
+function __NODEJS_dbg_print( text )\n
+{\n
+\tNODEJS__dbg_string += text + "\\n";\n
+}\n
+\n
+function __NODEJS_lex( info )\n
+{\n
+\tvar state\t\t= 0;\n
+\tvar match\t\t= -1;\n
+\tvar match_pos\t= 0;\n
+\tvar start\t\t= 0;\n
+\tvar pos\t\t\t= info.offset + 1;\n
+\n
+\tdo\n
+\t{\n
+\t\tpos--;\n
+\t\tstate = 0;\n
+\t\tmatch = -2;\n
+\t\tstart = pos;\n
+\n
+\t\tif( info.src.length <= start )\n
+\t\t\treturn 19;\n
+\n
+\t\tdo\n
+\t\t{\n
+\n
+switch( state )\n
+{\n
+\tcase 0:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 8 ) || ( info.src.charCodeAt( pos ) >= 10 && info.src.charCodeAt( pos ) <= 31 ) || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || info.src.charCodeAt( pos ) == 59 || ( info.src.charCodeAt( pos ) >= 63 && info.src.charCodeAt( pos ) <= 64 ) || ( info.src.charCodeAt( pos ) >= 66 && info.src.charCodeAt( pos ) <= 77 ) || ( info.src.charCodeAt( pos ) >= 80 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 9 ) state = 2;\n
+\t\telse if( info.src.charCodeAt( pos ) == 40 ) state = 3;\n
+\t\telse if( info.src.charCodeAt( pos ) == 41 ) state = 4;\n
+\t\telse if( info.src.charCodeAt( pos ) == 60 || info.src.charCodeAt( pos ) == 62 ) state = 5;\n
+\t\telse if( info.src.charCodeAt( pos ) == 33 ) state = 11;\n
+\t\telse if( info.src.charCodeAt( pos ) == 79 ) state = 12;\n
+\t\telse if( info.src.charCodeAt( pos ) == 32 ) state = 13;\n
+\t\telse if( info.src.charCodeAt( pos ) == 61 ) state = 14;\n
+\t\telse if( info.src.charCodeAt( pos ) == 34 ) state = 15;\n
+\t\telse if( info.src.charCodeAt( pos ) == 65 ) state = 19;\n
+\t\telse if( info.src.charCodeAt( pos ) == 78 ) state = 20;\n
+\t\telse state = -1;\n
+\t\tbreak;\n
+\n
+\tcase 1:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 2:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse state = -1;\n
+\t\tmatch = 1;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 3:\n
+\t\tstate = -1;\n
+\t\tmatch = 3;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 4:\n
+\t\tstate = -1;\n
+\t\tmatch = 4;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 5:\n
+\t\tif( info.src.charCodeAt( pos ) == 61 ) state = 14;\n
+\t\telse state = -1;\n
+\t\tmatch = 11;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 6:\n
+\t\tstate = -1;\n
+\t\tmatch = 8;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 7:\n
+\t\tstate = -1;\n
+\t\tmatch = 9;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 8:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse state = -1;\n
+\t\tmatch = 6;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 9:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse state = -1;\n
+\t\tmatch = 5;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 10:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse state = -1;\n
+\t\tmatch = 7;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 11:\n
+\t\tif( info.src.charCodeAt( pos ) == 61 ) state = 14;\n
+\t\telse state = -1;\n
+\t\tbreak;\n
+\n
+\tcase 12:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 81 ) || ( info.src.charCodeAt( pos ) >= 83 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse if( info.src.charCodeAt( pos ) == 82 ) state = 8;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 13:\n
+\t\tstate = -1;\n
+\t\tmatch = 1;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 14:\n
+\t\tstate = -1;\n
+\t\tmatch = 11;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 15:\n
+\t\tif( info.src.charCodeAt( pos ) == 34 ) state = 7;\n
+\t\telse if( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 33 ) || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 91 ) || ( info.src.charCodeAt( pos ) >= 93 && info.src.charCodeAt( pos ) <= 254 ) ) state = 15;\n
+\t\telse if( info.src.charCodeAt( pos ) == 92 ) state = 17;\n
+\t\telse state = -1;\n
+\t\tbreak;\n
+\n
+\tcase 16:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 67 ) || ( info.src.charCodeAt( pos ) >= 69 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse if( info.src.charCodeAt( pos ) == 68 ) state = 9;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 17:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 254 ) ) state = 15;\n
+\t\telse state = -1;\n
+\t\tbreak;\n
+\n
+\tcase 18:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 83 ) || ( info.src.charCodeAt( pos ) >= 85 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse if( info.src.charCodeAt( pos ) == 84 ) state = 10;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 19:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 77 ) || ( info.src.charCodeAt( pos ) >= 79 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse if( info.src.charCodeAt( pos ) == 78 ) state = 16;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+\tcase 20:\n
+\t\tif( ( info.src.charCodeAt( pos ) >= 0 && info.src.charCodeAt( pos ) <= 31 ) || info.src.charCodeAt( pos ) == 33 || ( info.src.charCodeAt( pos ) >= 35 && info.src.charCodeAt( pos ) <= 39 ) || ( info.src.charCodeAt( pos ) >= 42 && info.src.charCodeAt( pos ) <= 57 ) || ( info.src.charCodeAt( pos ) >= 59 && info.src.charCodeAt( pos ) <= 78 ) || ( info.src.charCodeAt( pos ) >= 80 && info.src.charCodeAt( pos ) <= 254 ) ) state = 1;\n
+\t\telse if( info.src.charCodeAt( pos ) == 58 ) state = 6;\n
+\t\telse if( info.src.charCodeAt( pos ) == 79 ) state = 18;\n
+\t\telse state = -1;\n
+\t\tmatch = 10;\n
+\t\tmatch_pos = pos;\n
+\t\tbreak;\n
+\n
+}\n
+\n
+\n
+\t\t\tpos++;\n
+\n
+\t\t}\n
+\t\twhile( state > -1 );\n
+\n
+\t}\n
+\twhile( 1 > -1 && match == 1 );\n
+\n
+\tif( match > -1 )\n
+\t{\n
+\t\tinfo.att = info.src.substr( start, match_pos - start );\n
+\t\tinfo.offset = match_pos;\n
+\t\t\n
+\n
+\t}\n
+\telse\n
+\t{\n
+\t\tinfo.att = new String();\n
+\t\tmatch = -1;\n
+\t}\n
+\n
+\treturn match;\n
+}\n
+\n
+\n
+function __NODEJS_parse( src, err_off, err_la )\n
+{\n
+\tvar\t\tsstack\t\t\t= new Array();\n
+\tvar\t\tvstack\t\t\t= new Array();\n
+\tvar \terr_cnt\t\t\t= 0;\n
+\tvar\t\tact;\n
+\tvar\t\tgo;\n
+\tvar\t\tla;\n
+\tvar\t\trval;\n
+\tvar \tparseinfo\t\t= new Function( "", "var offset; var src; var att;" );\n
+\tvar\t\tinfo\t\t\t= new parseinfo();\n
+\t\n
+/* Pop-Table */\n
+var pop_tab = new Array(\n
+\tnew Array( 0/* begin\' */, 1 ),\n
+\tnew Array( 13/* begin */, 1 ),\n
+\tnew Array( 12/* search_text */, 1 ),\n
+\tnew Array( 12/* search_text */, 2 ),\n
+\tnew Array( 12/* search_text */, 3 ),\n
+\tnew Array( 14/* and_expression */, 1 ),\n
+\tnew Array( 14/* and_expression */, 3 ),\n
+\tnew Array( 15/* boolean_expression */, 2 ),\n
+\tnew Array( 15/* boolean_expression */, 1 ),\n
+\tnew Array( 16/* expression */, 3 ),\n
+\tnew Array( 16/* expression */, 2 ),\n
+\tnew Array( 16/* expression */, 1 ),\n
+\tnew Array( 17/* value */, 2 ),\n
+\tnew Array( 17/* value */, 1 ),\n
+\tnew Array( 18/* string */, 1 ),\n
+\tnew Array( 18/* string */, 1 )\n
+);\n
+\n
+/* Action-Table */\n
+var act_tab = new Array(\n
+\t/* State 0 */ new Array( 7/* "NOT" */,5 , 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 1 */ new Array( 19/* "$" */,0 ),\n
+\t/* State 2 */ new Array( 19/* "$" */,-1 ),\n
+\t/* State 3 */ new Array( 6/* "OR" */,14 , 7/* "NOT" */,5 , 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 , 19/* "$" */,-2 , 4/* "RIGHT_PARENTHESE" */,-2 ),\n
+\t/* State 4 */ new Array( 5/* "AND" */,16 , 19/* "$" */,-5 , 7/* "NOT" */,-5 , 3/* "LEFT_PARENTHESE" */,-5 , 8/* "COLUMN" */,-5 , 11/* "OPERATOR" */,-5 , 10/* "WORD" */,-5 , 9/* "STRING" */,-5 , 6/* "OR" */,-5 , 4/* "RIGHT_PARENTHESE" */,-5 ),\n
+\t/* State 5 */ new Array( 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 6 */ new Array( 19/* "$" */,-8 , 7/* "NOT" */,-8 , 3/* "LEFT_PARENTHESE" */,-8 , 8/* "COLUMN" */,-8 , 11/* "OPERATOR" */,-8 , 10/* "WORD" */,-8 , 9/* "STRING" */,-8 , 6/* "OR" */,-8 , 5/* "AND" */,-8 , 4/* "RIGHT_PARENTHESE" */,-8 ),\n
+\t/* State 7 */ new Array( 7/* "NOT" */,5 , 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 8 */ new Array( 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 9 */ new Array( 19/* "$" */,-11 , 7/* "NOT" */,-11 , 3/* "LEFT_PARENTHESE" */,-11 , 8/* "COLUMN" */,-11 , 11/* "OPERATOR" */,-11 , 10/* "WORD" */,-11 , 9/* "STRING" */,-11 , 6/* "OR" */,-11 , 5/* "AND" */,-11 , 4/* "RIGHT_PARENTHESE" */,-11 ),\n
+\t/* State 10 */ new Array( 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 11 */ new Array( 19/* "$" */,-13 , 7/* "NOT" */,-13 , 3/* "LEFT_PARENTHESE" */,-13 , 8/* "COLUMN" */,-13 , 11/* "OPERATOR" */,-13 , 10/* "WORD" */,-13 , 9/* "STRING" */,-13 , 6/* "OR" */,-13 , 5/* "AND" */,-13 , 4/* "RIGHT_PARENTHESE" */,-13 ),\n
+\t/* State 12 */ new Array( 19/* "$" */,-14 , 7/* "NOT" */,-14 , 3/* "LEFT_PARENTHESE" */,-14 , 8/* "COLUMN" */,-14 , 11/* "OPERATOR" */,-14 , 10/* "WORD" */,-14 , 9/* "STRING" */,-14 , 6/* "OR" */,-14 , 5/* "AND" */,-14 , 4/* "RIGHT_PARENTHESE" */,-14 ),\n
+\t/* State 13 */ new Array( 19/* "$" */,-15 , 7/* "NOT" */,-15 , 3/* "LEFT_PARENTHESE" */,-15 , 8/* "COLUMN" */,-15 , 11/* "OPERATOR" */,-15 , 10/* "WORD" */,-15 , 9/* "STRING" */,-15 , 6/* "OR" */,-15 , 5/* "AND" */,-15 , 4/* "RIGHT_PARENTHESE" */,-15 ),\n
+\t/* State 14 */ new Array( 7/* "NOT" */,5 , 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 15 */ new Array( 19/* "$" */,-3 , 4/* "RIGHT_PARENTHESE" */,-3 ),\n
+\t/* State 16 */ new Array( 7/* "NOT" */,5 , 3/* "LEFT_PARENTHESE" */,7 , 8/* "COLUMN" */,8 , 11/* "OPERATOR" */,10 , 10/* "WORD" */,12 , 9/* "STRING" */,13 ),\n
+\t/* State 17 */ new Array( 19/* "$" */,-7 , 7/* "NOT" */,-7 , 3/* "LEFT_PARENTHESE" */,-7 , 8/* "COLUMN" */,-7 , 11/* "OPERATOR" */,-7 , 10/* "WORD" */,-7 , 9/* "STRING" */,-7 , 6/* "OR" */,-7 , 5/* "AND" */,-7 , 4/* "RIGHT_PARENTHESE" */,-7 ),\n
+\t/* State 18 */ new Array( 4/* "RIGHT_PARENTHESE" */,23 ),\n
+\t/* State 19 */ new Array( 19/* "$" */,-10 , 7
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/* "NOT" */,-10 , 3/* "LEFT_PARENTHESE" */,-10 , 8/* "COLUMN" */,-10 , 11/* "OPERATOR" */,-10 , 10/* "WORD" */,-10 , 9/* "STRING" */,-10 , 6/* "OR" */,-10 , 5/* "AND" */,-10 , 4/* "RIGHT_PARENTHESE" */,-10 ),\n
+\t/* State 20 */ new Array( 19/* "$" */,-12 , 7/* "NOT" */,-12 , 3/* "LEFT_PARENTHESE" */,-12 , 8/* "COLUMN" */,-12 , 11/* "OPERATOR" */,-12 , 10/* "WORD" */,-12 , 9/* "STRING" */,-12 , 6/* "OR" */,-12 , 5/* "AND" */,-12 , 4/* "RIGHT_PARENTHESE" */,-12 ),\n
+\t/* State 21 */ new Array( 19/* "$" */,-4 , 4/* "RIGHT_PARENTHESE" */,-4 ),\n
+\t/* State 22 */ new Array( 19/* "$" */,-6 , 7/* "NOT" */,-6 , 3/* "LEFT_PARENTHESE" */,-6 , 8/* "COLUMN" */,-6 , 11/* "OPERATOR" */,-6 , 10/* "WORD" */,-6 , 9/* "STRING" */,-6 , 6/* "OR" */,-6 , 4/* "RIGHT_PARENTHESE" */,-6 ),\n
+\t/* State 23 */ new Array( 19/* "$" */,-9 , 7/* "NOT" */,-9 , 3/* "LEFT_PARENTHESE" */,-9 , 8/* "COLUMN" */,-9 , 11/* "OPERATOR" */,-9 , 10/* "WORD" */,-9 , 9/* "STRING" */,-9 , 6/* "OR" */,-9 , 5/* "AND" */,-9 , 4/* "RIGHT_PARENTHESE" */,-9 )\n
+);\n
+\n
+/* Goto-Table */\n
+var goto_tab = new Array(\n
+\t/* State 0 */ new Array( 13/* begin */,1 , 12/* search_text */,2 , 14/* and_expression */,3 , 15/* boolean_expression */,4 , 16/* expression */,6 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 1 */ new Array(  ),\n
+\t/* State 2 */ new Array(  ),\n
+\t/* State 3 */ new Array( 12/* search_text */,15 , 14/* and_expression */,3 , 15/* boolean_expression */,4 , 16/* expression */,6 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 4 */ new Array(  ),\n
+\t/* State 5 */ new Array( 16/* expression */,17 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 6 */ new Array(  ),\n
+\t/* State 7 */ new Array( 12/* search_text */,18 , 14/* and_expression */,3 , 15/* boolean_expression */,4 , 16/* expression */,6 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 8 */ new Array( 16/* expression */,19 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 9 */ new Array(  ),\n
+\t/* State 10 */ new Array( 18/* string */,20 ),\n
+\t/* State 11 */ new Array(  ),\n
+\t/* State 12 */ new Array(  ),\n
+\t/* State 13 */ new Array(  ),\n
+\t/* State 14 */ new Array( 12/* search_text */,21 , 14/* and_expression */,3 , 15/* boolean_expression */,4 , 16/* expression */,6 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 15 */ new Array(  ),\n
+\t/* State 16 */ new Array( 14/* and_expression */,22 , 15/* boolean_expression */,4 , 16/* expression */,6 , 17/* value */,9 , 18/* string */,11 ),\n
+\t/* State 17 */ new Array(  ),\n
+\t/* State 18 */ new Array(  ),\n
+\t/* State 19 */ new Array(  ),\n
+\t/* State 20 */ new Array(  ),\n
+\t/* State 21 */ new Array(  ),\n
+\t/* State 22 */ new Array(  ),\n
+\t/* State 23 */ new Array(  )\n
+);\n
+\n
+\n
+\n
+/* Symbol labels */\n
+var labels = new Array(\n
+\t"begin\'" /* Non-terminal symbol */,\n
+\t"WHITESPACE" /* Terminal symbol */,\n
+\t"WHITESPACE" /* Terminal symbol */,\n
+\t"LEFT_PARENTHESE" /* Terminal symbol */,\n
+\t"RIGHT_PARENTHESE" /* Terminal symbol */,\n
+\t"AND" /* Terminal symbol */,\n
+\t"OR" /* Terminal symbol */,\n
+\t"NOT" /* Terminal symbol */,\n
+\t"COLUMN" /* Terminal symbol */,\n
+\t"STRING" /* Terminal symbol */,\n
+\t"WORD" /* Terminal symbol */,\n
+\t"OPERATOR" /* Terminal symbol */,\n
+\t"search_text" /* Non-terminal symbol */,\n
+\t"begin" /* Non-terminal symbol */,\n
+\t"and_expression" /* Non-terminal symbol */,\n
+\t"boolean_expression" /* Non-terminal symbol */,\n
+\t"expression" /* Non-terminal symbol */,\n
+\t"value" /* Non-terminal symbol */,\n
+\t"string" /* Non-terminal symbol */,\n
+\t"$" /* Terminal symbol */\n
+);\n
+\n
+\n
+\t\n
+\tinfo.offset = 0;\n
+\tinfo.src = src;\n
+\tinfo.att = new String();\n
+\t\n
+\tif( !err_off )\n
+\t\terr_off\t= new Array();\n
+\tif( !err_la )\n
+\terr_la = new Array();\n
+\t\n
+\tsstack.push( 0 );\n
+\tvstack.push( 0 );\n
+\t\n
+\tla = __NODEJS_lex( info );\n
+\n
+\twhile( true )\n
+\t{\n
+\t\tact = 25;\n
+\t\tfor( var i = 0; i < act_tab[sstack[sstack.length-1]].length; i+=2 )\n
+\t\t{\n
+\t\t\tif( act_tab[sstack[sstack.length-1]][i] == la )\n
+\t\t\t{\n
+\t\t\t\tact = act_tab[sstack[sstack.length-1]][i+1];\n
+\t\t\t\tbreak;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif( NODEJS__dbg_withtrace && sstack.length > 0 )\n
+\t\t{\n
+\t\t\t__NODEJS_dbg_print( "\\nState " + sstack[sstack.length-1] + "\\n" +\n
+\t\t\t\t\t\t\t"\\tLookahead: " + labels[la] + " (\\"" + info.att + "\\")\\n" +\n
+\t\t\t\t\t\t\t"\\tAction: " + act + "\\n" + \n
+\t\t\t\t\t\t\t"\\tSource: \\"" + info.src.substr( info.offset, 30 ) + ( ( info.offset + 30 < info.src.length ) ?\n
+\t\t\t\t\t\t\t\t\t"..." : "" ) + "\\"\\n" +\n
+\t\t\t\t\t\t\t"\\tStack: " + sstack.join() + "\\n" +\n
+\t\t\t\t\t\t\t"\\tValue stack: " + vstack.join() + "\\n" );\n
+\t\t}\n
+\t\t\n
+\t\t\t\n
+\t\t//Panic-mode: Try recovery when parse-error occurs!\n
+\t\tif( act == 25 )\n
+\t\t{\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "Error detected: There is no reduce or shift on the symbol " + labels[la] );\n
+\t\t\t\n
+\t\t\terr_cnt++;\n
+\t\t\terr_off.push( info.offset - info.att.length );\t\t\t\n
+\t\t\terr_la.push( new Array() );\n
+\t\t\tfor( var i = 0; i < act_tab[sstack[sstack.length-1]].length; i+=2 )\n
+\t\t\t\terr_la[err_la.length-1].push( labels[act_tab[sstack[sstack.length-1]][i]] );\n
+\t\t\t\n
+\t\t\t//Remember the original stack!\n
+\t\t\tvar rsstack = new Array();\n
+\t\t\tvar rvstack = new Array();\n
+\t\t\tfor( var i = 0; i < sstack.length; i++ )\n
+\t\t\t{\n
+\t\t\t\trsstack[i] = sstack[i];\n
+\t\t\t\trvstack[i] = vstack[i];\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\twhile( act == 25 && la != 19 )\n
+\t\t\t{\n
+\t\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t\t__NODEJS_dbg_print( "\\tError recovery\\n" +\n
+\t\t\t\t\t\t\t\t\t"Current lookahead: " + labels[la] + " (" + info.att + ")\\n" +\n
+\t\t\t\t\t\t\t\t\t"Action: " + act + "\\n\\n" );\n
+\t\t\t\tif( la == -1 )\n
+\t\t\t\t\tinfo.offset++;\n
+\t\t\t\t\t\n
+\t\t\t\twhile( act == 25 && sstack.length > 0 )\n
+\t\t\t\t{\n
+\t\t\t\t\tsstack.pop();\n
+\t\t\t\t\tvstack.pop();\n
+\t\t\t\t\t\n
+\t\t\t\t\tif( sstack.length == 0 )\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\t\n
+\t\t\t\t\tact = 25;\n
+\t\t\t\t\tfor( var i = 0; i < act_tab[sstack[sstack.length-1]].length; i+=2 )\n
+\t\t\t\t\t{\n
+\t\t\t\t\t\tif( act_tab[sstack[sstack.length-1]][i] == la )\n
+\t\t\t\t\t\t{\n
+\t\t\t\t\t\t\tact = act_tab[sstack[sstack.length-1]][i+1];\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\t\n
+\t\t\t\tif( act != 25 )\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t\n
+\t\t\t\tfor( var i = 0; i < rsstack.length; i++ )\n
+\t\t\t\t{\n
+\t\t\t\t\tsstack.push( rsstack[i] );\n
+\t\t\t\t\tvstack.push( rvstack[i] );\n
+\t\t\t\t}\n
+\t\t\t\t\n
+\t\t\t\tla = __NODEJS_lex( info );\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\tif( act == 25 )\n
+\t\t\t{\n
+\t\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t\t__NODEJS_dbg_print( "\\tError recovery failed, terminating parse process..." );\n
+\t\t\t\tbreak;\n
+\t\t\t}\n
+\n
+\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "\\tError recovery succeeded, continuing" );\n
+\t\t}\n
+\t\t\n
+\t\t/*\n
+\t\tif( act == 25 )\n
+\t\t\tbreak;\n
+\t\t*/\n
+\t\t\n
+\t\t\n
+\t\t//Shift\n
+\t\tif( act > 0 )\n
+\t\t{\t\t\t\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "Shifting symbol: " + labels[la] + " (" + info.att + ")" );\n
+\t\t\n
+\t\t\tsstack.push( act );\n
+\t\t\tvstack.push( info.att );\n
+\t\t\t\n
+\t\t\tla = __NODEJS_lex( info );\n
+\t\t\t\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "\\tNew lookahead symbol: " + labels[la] + " (" + info.att + ")" );\n
+\t\t}\n
+\t\t//Reduce\n
+\t\telse\n
+\t\t{\t\t\n
+\t\t\tact *= -1;\n
+\t\t\t\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "Reducing by producution: " + act );\n
+\t\t\t\n
+\t\t\trval = void(0);\n
+\t\t\t\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "\\tPerforming semantic action..." );\n
+\t\t\t\n
+switch( act )\n
+{\n
+\tcase 0:\n
+\t{\n
+\t\trval = vstack[ vstack.length - 1 ];\n
+\t}\n
+\tbreak;\n
+\tcase 1:\n
+\t{\n
+\t\t result = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 2:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 3:\n
+\t{\n
+\t\t rval = mkComplexQuery(\'OR\',[vstack[ vstack.length - 2 ],vstack[ vstack.length - 1 ]]); \n
+\t}\n
+\tbreak;\n
+\tcase 4:\n
+\t{\n
+\t\t rval = mkComplexQuery(\'OR\',[vstack[ vstack.length - 3 ],vstack[ vstack.length - 1 ]]); \n
+\t}\n
+\tbreak;\n
+\tcase 5:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 1 ] ; \n
+\t}\n
+\tbreak;\n
+\tcase 6:\n
+\t{\n
+\t\t rval = mkComplexQuery(\'AND\',[vstack[ vstack.length - 3 ],vstack[ vstack.length - 1 ]]); \n
+\t}\n
+\tbreak;\n
+\tcase 7:\n
+\t{\n
+\t\t rval = mkNotQuery(vstack[ vstack.length - 1 ]); \n
+\t}\n
+\tbreak;\n
+\tcase 8:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 9:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 2 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 10:\n
+\t{\n
+\t\t simpleQuerySetKey(vstack[ vstack.length - 1 ],vstack[ vstack.length - 2 ].split(\':\').slice(0,-1).join(\':\')); rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 11:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 12:\n
+\t{\n
+\t\t vstack[ vstack.length - 1 ].operator = vstack[ vstack.length - 2 ] ; rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 13:\n
+\t{\n
+\t\t rval = vstack[ vstack.length - 1 ]; \n
+\t}\n
+\tbreak;\n
+\tcase 14:\n
+\t{\n
+\t\t rval = mkSimpleQuery(\'\',vstack[ vstack.length - 1 ]); \n
+\t}\n
+\tbreak;\n
+\tcase 15:\n
+\t{\n
+\t\t rval = mkSimpleQuery(\'\',vstack[ vstack.length - 1 ].split(\'"\').slice(1,-1).join(\'"\')); \n
+\t}\n
+\tbreak;\n
+}\n
+\n
+\n
+\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "\\tPopping " + pop_tab[act][1] + " off the stack..." );\n
+\t\t\t\t\n
+\t\t\tfor( var i = 0; i < pop_tab[act][1]; i++ )\n
+\t\t\t{\n
+\t\t\t\tsstack.pop();\n
+\t\t\t\tvstack.pop();\n
+\t\t\t}\n
+\t\t\t\t\t\t\t\t\t\n
+\t\t\tgo = -1;\n
+\t\t\tfor( var i = 0; i < goto_tab[sstack[sstack.length-1]].length; i+=2 )\n
+\t\t\t{\n
+\t\t\t\tif( goto_tab[sstack[sstack.length-1]][i] == pop_tab[act][0] )\n
+\t\t\t\t{\n
+\t\t\t\t\tgo = goto_tab[sstack[sstack.length-1]][i+1];\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\tif( act == 0 )\n
+\t\t\t\tbreak;\n
+\t\t\t\t\n
+\t\t\tif( NODEJS__dbg_withtrace )\n
+\t\t\t\t__NODEJS_dbg_print( "\\tPushing non-terminal " + labels[ pop_tab[act][0] ] );\n
+\t\t\t\t\n
+\t\t\tsstack.push( go );\n
+\t\t\tvstack.push( rval );\t\t\t\n
+\t\t}\n
+\t\t\n
+\t\tif( NODEJS__dbg_withtrace )\n
+\t\t{\t\t\n
+\t\t\talert( NODEJS__dbg_string );\n
+\t\t\tNODEJS__dbg_string = new String();\n
+\t\t}\n
+\t}\n
+\n
+\tif( NODEJS__dbg_withtrace )\n
+\t{\n
+\t\t__NODEJS_dbg_print( "\\nParse complete." );\n
+\t\talert( NODEJS__dbg_string );\n
+\t}\n
+\t\n
+\treturn err_cnt;\n
+}\n
+\n
+\n
+\n
+var arrayExtend = function () {\n
+  var j, i, newlist = [], list_list = arguments;\n
+  for (j = 0; j < list_list.length; j += 1) {\n
+    for (i = 0; i < list_list[j].length; i += 1) {\n
+      newlist.push(list_list[j][i]);\n
+    }\n
+  }\n
+  return newlist;\n
+\n
+}, mkSimpleQuery = function (key, value, operator) {\n
+  var object = {"type": "simple", "key": key, "value": value};\n
+  if (operator !== undefined) {\n
+    object.operator = operator;\n
+  }\n
+  return object;\n
+\n
+}, mkNotQuery = function (query) {\n
+  if (query.operator === "NOT") {\n
+    return query.query_list[0];\n
+  }\n
+  return {"type": "complex", "operator": "NOT", "query_list": [query]};\n
+\n
+}, mkComplexQuery = function (operator, query_list) {\n
+  var i, query_list2 = [];\n
+  for (i = 0; i < query_list.length; i += 1) {\n
+    if (query_list[i].operator === operator) {\n
+      query_list2 = arrayExtend(query_list2, query_list[i].query_list);\n
+    } else {\n
+      query_list2.push(query_list[i]);\n
+    }\n
+  }\n
+  return {type:"complex",operator:operator,query_list:query_list2};\n
+\n
+}, simpleQuerySetKey = function (query, key) {\n
+  var i;\n
+  if (query.type === "complex") {\n
+    for (i = 0; i < query.query_list.length; ++i) {\n
+      simpleQuerySetKey (query.query_list[i],key);\n
+    }\n
+    return true;\n
+  }\n
+  if (query.type === "simple" && !query.key) {\n
+    query.key = key;\n
+    return true;\n
+  }\n
+  return false;\n
+},\n
+  error_offsets = [],\n
+  error_lookaheads = [],\n
+  error_count = 0,\n
+  result;\n
+\n
+if ((error_count = __NODEJS_parse(string, error_offsets, error_lookaheads)) > 0) {\n
+  var i;\n
+  for (i = 0; i < error_count; i += 1) {\n
+    throw new Error("Parse error near \\"" +\n
+                    string.substr(error_offsets[i]) +\n
+                    "\\", expecting \\"" +\n
+                    error_lookaheads[i].join() + "\\"");\n
+  }\n
+}\n
+\n
+\n
+  return result;\n
+} // parseStringToObject\n
+\n
+_export(\'parseStringToObject\', parseStringToObject);\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true */\n
+\n
+var query_class_dict = {};\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global Query: true, query_class_dict: true, inherits: true,\n
+         _export, QueryFactory, RSVP, sequence */\n
+\n
+/**\n
+ * The ComplexQuery inherits from Query, and compares one or several metadata\n
+ * values.\n
+ *\n
+ * @class ComplexQuery\n
+ * @extends Query\n
+ * @param  {Object} [spec={}] The specifications\n
+ * @param  {String} [spec.operator="AND"] The compare method to use\n
+ * @param  {String} spec.key The metadata key\n
+ * @param  {String} spec.value The value of the metadata to compare\n
+ */\n
+function ComplexQuery(spec, key_schema) {\n
+  Query.call(this);\n
+\n
+  /**\n
+   * Logical operator to use to compare object values\n
+   *\n
+   * @attribute operator\n
+   * @type String\n
+   * @default "AND"\n
+   * @optional\n
+   */\n
+  this.operator = spec.operator || "AND";\n
+\n
+  /**\n
+   * The sub Query list which are used to query an item.\n
+   *\n
+   * @attribute query_list\n
+   * @type Array\n
+   * @default []\n
+   * @optional\n
+   */\n
+  this.query_list = spec.query_list || [];\n
+  /*jslint unparam: true*/\n
+  this.query_list = this.query_list.map(\n
+    // decorate the map to avoid sending the index as key_schema argument\n
+    function (o, i) { return QueryFactory.create(o, key_schema); }\n
+  );\n
+  /*jslint unparam: false*/\n
+\n
+}\n
+inherits(ComplexQuery, Query);\n
+\n
+/**\n
+ * #crossLink "Query/match:method"\n
+ */\n
+ComplexQuery.prototype.match = function (item) {\n
+  var operator = this.operator;\n
+  if (!(/^(?:AND|OR|NOT)$/i.test(operator))) {\n
+    operator = "AND";\n
+  }\n
+  return this[operator.toUpperCase()](item);\n
+};\n
+\n
+/**\n
+ * #crossLink "Query/toString:method"\n
+ */\n
+ComplexQuery.prototype.toString = function () {\n
+  var str_list = ["("], this_operator = this.operator;\n
+  this.query_list.forEach(function (query) {\n
+    str_list.push(query.toString());\n
+    str_list.push(this_operator);\n
+  });\n
+  str_list[str_list.length - 1] = ")"; // replace last operator\n
+  return str_list.join(" ");\n
+};\n
+\n
+/**\n
+ * #crossLink "Query/serialized:method"\n
+ */\n
+ComplexQuery.prototype.serialized = function () {\n
+  var s = {\n
+    "type": "complex",\n
+    "operator": this.operator,\n
+    "query_list": []\n
+  };\n
+  this.query_list.forEach(function (query) {\n
+    s.query_list.push(query.serialized());\n
+  });\n
+  return s;\n
+};\n
+ComplexQuery.prototype.toJSON = ComplexQuery.prototype.serialized;\n
+\n
+/**\n
+ * Comparison operator, test if all sub queries match the\n
+ * item value\n
+ *\n
+ * @method AND\n
+ * @param  {Object} item The item to match\n
+ * @return {Boolean} true if all match, false otherwise\n
+ */\n
+ComplexQuery.prototype.AND = function (item) {\n
+  var j, promises = [];\n
+  for (j = 0; j < this.query_list.length; j += 1) {\n
+    promises.push(this.query_list[j].match(item));\n
+  }\n
+\n
+  function cancel() {\n
+    var i;\n
+    for (i = 0; i < promises.length; i += 1) {\n
+      if (typeof promises.cancel === \'function\') {\n
+        promises.cancel();\n
+      }\n
+    }\n
+  }\n
+\n
+  return new RSVP.Promise(function (resolve, reject) {\n
+    var i, count = 0;\n
+    function resolver(value) {\n
+      if (!value) {\n
+        resolve(false);\n
+      }\n
+      count += 1;\n
+      if (count === promises.length) {\n
+        resolve(true);\n
+      }\n
+    }\n
+\n
+    function rejecter(err) {\n
+      reject(err);\n
+      cancel();\n
+    }\n
+\n
+    for (i = 0; i < promises.length; i += 1) {\n
+      promises[i].then(resolver, rejecter);\n
+    }\n
+  }, cancel);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if one of the sub queries matches the\n
+ * item value\n
+ *\n
+ * @method OR\n
+ * @param  {Object} item The item to match\n
+ * @return {Boolean} true if one match, false otherwise\n
+ */\n
+ComplexQuery.prototype.OR =  function (item) {\n
+  var j, promises = [];\n
+  for (j = 0; j < this.query_list.length; j += 1) {\n
+    promises.push(this.query_list[j].match(item));\n
+  }\n
+\n
+  function cancel() {\n
+    var i;\n
+    for (i = 0; i < promises.length; i += 1) {\n
+      if (typeof promises.cancel === \'function\') {\n
+        promises.cancel();\n
+      }\n
+    }\n
+  }\n
+\n
+  return new RSVP.Promise(function (resolve, reject) {\n
+    var i, count = 0;\n
+    function resolver(value) {\n
+      if (value) {\n
+        resolve(true);\n
+      }\n
+      count += 1;\n
+      if (count === promises.length) {\n
+        resolve(false);\n
+      }\n
+    }\n
+\n
+    function rejecter(err) {\n
+      reject(err);\n
+      cancel();\n
+    }\n
+\n
+    for (i = 0; i < promises.length; i += 1) {\n
+      promises[i].then(resolver, rejecter);\n
+    }\n
+  }, cancel);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if the sub query does not match the\n
+ * item value\n
+ *\n
+ * @method NOT\n
+ * @param  {Object} item The item to match\n
+ * @return {Boolean} true if one match, false otherwise\n
+ */\n
+ComplexQuery.prototype.NOT = function (item) {\n
+  return sequence([function () {\n
+    return this.query_list[0].match(item);\n
+  }, function (answer) {\n
+    return !answer;\n
+  }]);\n
+};\n
+\n
+query_class_dict.complex = ComplexQuery;\n
+\n
+_export("ComplexQuery", ComplexQuery);\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global parseStringToObject: true, emptyFunction: true, sortOn: true, limit:\n
+  true, select: true, _export: true, stringEscapeRegexpCharacters: true,\n
+  deepClone, RSVP, sequence */\n
+\n
+/**\n
+ * The query to use to filter a list of objects.\n
+ * This is an abstract class.\n
+ *\n
+ * @class Query\n
+ * @constructor\n
+ */\n
+function Query() {\n
+\n
+  /**\n
+   * Called before parsing the query. Must be overridden!\n
+   *\n
+   * @method onParseStart\n
+   * @param  {Object} object The object shared in the parse process\n
+   * @param  {Object} option Some option gave in parse()\n
+   */\n
+  this.onParseStart = emptyFunction;\n
+\n
+  /**\n
+   * Called when parsing a simple query. Must be overridden!\n
+   *\n
+   * @method onParseSimpleQuery\n
+   * @param  {Object} object The object shared in the parse process\n
+   * @param  {Object} option Some option gave in parse()\n
+   */\n
+  this.onParseSimpleQuery = emptyFunction;\n
+\n
+  /**\n
+   * Called when parsing a complex query. Must be overridden!\n
+   *\n
+   * @method onParseComplexQuery\n
+   * @param  {Object} object The object shared in the parse process\n
+   * @param  {Object} option Some option gave in parse()\n
+   */\n
+  this.onParseComplexQuery = emptyFunction;\n
+\n
+  /**\n
+   * Called after parsing the query. Must be overridden!\n
+   *\n
+   * @method onParseEnd\n
+   * @param  {Object} object The object shared in the parse process\n
+   * @param  {Object} option Some option gave in parse()\n
+   */\n
+  this.onParseEnd = emptyFunction;\n
+\n
+}\n
+\n
+/**\n
+ * Filter the item list with matching item only\n
+ *\n
+ * @method exec\n
+ * @param  {Array} item_list The list of object\n
+ * @param  {Object} [option] Some operation option\n
+ * @param  {Array} [option.select_list] A object keys to retrieve\n
+ * @param  {Array} [option.sort_on] Couples of object keys and "ascending"\n
+ *                 or "descending"\n
+ * @param  {Array} [option.limit] Couple of integer, first is an index and\n
+ *                 second is the length.\n
+ */\n
+Query.prototype.exec = function (item_list, option) {\n
+  var i, promises = [];\n
+  if (!Array.isArray(item_list)) {\n
+    throw new TypeError("Query().exec(): Argument 1 is not of type \'array\'");\n
+  }\n
+  if (option === undefined) {\n
+    option = {};\n
+  }\n
+  if (typeof option !== \'object\') {\n
+    throw new TypeError("Query().exec(): " +\n
+                        "Optional argument 2 is not of type \'object\'");\n
+  }\n
+  for (i = 0; i < item_list.length; i += 1) {\n
+    if (!item_list[i]) {\n
+      promises.push(RSVP.resolve(false));\n
+    } else {\n
+      promises.push(this.match(item_list[i]));\n
+    }\n
+  }\n
+  return sequence([function () {\n
+    return RSVP.all(promises);\n
+  }, function (answers) {\n
+    var j;\n
+    for (j = answers.length - 1; j >= 0; j -= 1) {\n
+      if (!answers[j]) {\n
+        item_list.splice(j, 1);\n
+      }\n
+    }\n
+    if (option.sort_on) {\n
+      return sortOn(option.sort_on, item_list);\n
+    }\n
+  }, function () {\n
+    if (option.limit) {\n
+      return limit(option.limit, item_list);\n
+    }\n
+  }, function () {\n
+    return select(option.select_list || [], item_list);\n
+  }, function () {\n
+    return item_list;\n
+  }]);\n
+};\n
+\n
+/**\n
+ * Test if an item matches this query\n
+ *\n
+ * @method match\n
+ * @param  {Object} item The object to test\n
+ * @return {Boolean} true if match, false otherwise\n
+ */\n
+Query.prototype.match = function () {\n
+  return RSVP.resolve(true);\n
+};\n
+\n
+\n
+/**\n
+ * Browse the Query in deep calling parser method in each step.\n
+ *\n
+ * `onParseStart` is called first, on end `onParseEnd` is called.\n
+ * It starts from the simple queries at the bottom of the tree calling the\n
+ * parser method `onParseSimpleQuery`, and go up calling the\n
+ * `onParseComplexQuery` method.\n
+ *\n
+ * @method parse\n
+ * @param  {Object} option Any options you want (except \'parsed\')\n
+ * @return {Any} The parse result\n
+ */\n
+Query.prototype.parse = function (option) {\n
+  var that = this, object;\n
+  /**\n
+   * The recursive parser.\n
+   *\n
+   * @param  {Object} object The object shared in the parse process\n
+   * @param  {Object} options Some options usable in the parseMethods\n
+   * @return {Any} The parser result\n
+   */\n
+  function recParse(object, option) {\n
+    var query = object.parsed;\n
+    if (query.type === "complex") {\n
+      return sequence([function () {\n
+        return sequence(query.query_list.map(function (v, i) {\n
+          /*jslint unparam: true */\n
+          return function () {\n
+            sequence([function () {\n
+              object.parsed = query.query_list[i];\n
+              return recParse(object, option);\n
+            }, function () {\n
+              query.query_list[i] = object.parsed;\n
+            }]);\n
+          };\n
+        }));\n
+      }, function () {\n
+        object.parsed = query;\n
+        return that.onParseComplexQuery(object, option);\n
+      }]);\n
+    }\n
+    if (query.type === "simple") {\n
+      return that.onParseSimpleQuery(object, option);\n
+    }\n
+  }\n
+  object = {"parsed": JSON.parse(JSON.stringify(that.serialized()))};\n
+  return sequence([function () {\n
+    return that.onParseStart(object, option);\n
+  }, function () {\n
+    return recParse(object, option);\n
+  }, function () {\n
+    return that.onParseEnd(object, option);\n
+  }, function () {\n
+    return object.parsed;\n
+  }]);\n
+};\n
+\n
+/**\n
+ * Convert this query to a parsable string.\n
+ *\n
+ * @method toString\n
+ * @return {String} The string version of this query\n
+ */\n
+Query.prototype.toString = function () {\n
+  return "";\n
+};\n
+\n
+/**\n
+ * Convert this query to an jsonable object in order to be remake thanks to\n
+ * QueryFactory class.\n
+ *\n
+ * @method serialized\n
+ * @return {Object} The jsonable object\n
+ */\n
+Query.prototype.serialized = function () {\n
+  return undefined;\n
+};\n
+\n
+_export("Query", Query);\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global _export, ComplexQuery, SimpleQuery, Query, parseStringToObject,\n
+  query_class_dict */\n
+\n
+/**\n
+ * Provides static methods to create Query object\n
+ *\n
+ * @class QueryFactory\n
+ */\n
+function QueryFactory() {\n
+  return;\n
+}\n
+\n
+/**\n
+ * Creates Query object from a search text string or a serialized version\n
+ * of a Query.\n
+ *\n
+ * @method create\n
+ * @static\n
+ * @param  {Object,String} object The search text or the serialized version\n
+ *         of a Query\n
+ * @return {Query} A Query object\n
+ */\n
+QueryFactory.create = function (object, key_schema) {\n
+  if (object === "") {\n
+    return new Query();\n
+  }\n
+  if (typeof object === "string") {\n
+    object = parseStringToObject(object);\n
+  }\n
+  if (typeof (object || {}).type === "string" &&\n
+      query_class_dict[object.type]) {\n
+    return new query_class_dict[object.type](object, key_schema);\n
+  }\n
+  throw new TypeError("QueryFactory.create(): " +\n
+                      "Argument 1 is not a search text or a parsable object");\n
+};\n
+\n
+_export("QueryFactory", QueryFactory);\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global _export: true */\n
+\n
+function objectToSearchText(query) {\n
+  var str_list = [];\n
+  if (query.type === "complex") {\n
+    str_list.push("(");\n
+    (query.query_list || []).forEach(function (sub_query) {\n
+      str_list.push(objectToSearchText(sub_query));\n
+      str_list.push(query.operator);\n
+    });\n
+    str_list.length -= 1;\n
+    str_list.push(")");\n
+    return str_list.join(" ");\n
+  }\n
+  if (query.type === "simple") {\n
+    return (query.key ? query.key + ": " : "") +\n
+      (query.operator || "") + \' "\' + query.value + \'"\';\n
+  }\n
+  throw new TypeError("This object is not a query");\n
+}\n
+_export("objectToSearchText", objectToSearchText);\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global Query: true, inherits: true, query_class_dict: true, _export: true,\n
+  searchTextToRegExp, RSVP */\n
+\n
+var checkKeySchema = function (key_schema) {\n
+  var prop;\n
+\n
+  if (key_schema !== undefined) {\n
+    if (typeof key_schema !== \'object\') {\n
+      throw new TypeError("SimpleQuery().create(): " +\n
+                          "key_schema is not of type \'object\'");\n
+    }\n
+    // key_set is mandatory\n
+    if (key_schema.key_set === undefined) {\n
+      throw new TypeError("SimpleQuery().create(): " +\n
+                          "key_schema has no \'key_set\' property");\n
+    }\n
+    for (prop in key_schema) {\n
+      if (key_schema.hasOwnProperty(prop)) {\n
+        switch (prop) {\n
+        case \'key_set\':\n
+        case \'cast_lookup\':\n
+        case \'match_lookup\':\n
+          break;\n
+        default:\n
+          throw new TypeError("SimpleQuery().create(): " +\n
+                             "key_schema has unknown property \'" + prop + "\'");\n
+        }\n
+      }\n
+    }\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * The SimpleQuery inherits from Query, and compares one metadata value\n
+ *\n
+ * @class SimpleQuery\n
+ * @extends Query\n
+ * @param  {Object} [spec={}] The specifications\n
+ * @param  {String} [spec.operator="="] The compare method to use\n
+ * @param  {String} spec.key The metadata key\n
+ * @param  {String} spec.value The value of the metadata to compare\n
+ */\n
+function SimpleQuery(spec, key_schema) {\n
+  Query.call(this);\n
+\n
+  checkKeySchema(key_schema);\n
+\n
+  this._key_schema = key_schema || {};\n
+\n
+  /**\n
+   * Operator to use to compare object values\n
+   *\n
+   * @attribute operator\n
+   * @type String\n
+   * @optional\n
+   */\n
+  this.operator = spec.operator;\n
+\n
+  /**\n
+   * Key of the object which refers to the value to compare\n
+   *\n
+   * @attribute key\n
+   * @type String\n
+   */\n
+  this.key = spec.key;\n
+\n
+  /**\n
+   * Value is used to do the comparison with the object value\n
+   *\n
+   * @attribute value\n
+   * @type String\n
+   */\n
+  this.value = spec.value;\n
+\n
+}\n
+inherits(SimpleQuery, Query);\n
+\n
+\n
+var checkKey = function (key) {\n
+  var prop;\n
+\n
+  if (key.read_from === undefined) {\n
+    throw new TypeError("Custom key is missing the read_from property");\n
+  }\n
+\n
+  for (prop in key) {\n
+    if (key.hasOwnProperty(prop)) {\n
+      switch (prop) {\n
+      case \'read_from\':\n
+      case \'cast_to\':\n
+      case \'equal_match\':\n
+        break;\n
+      default:\n
+        throw new TypeError("Custom key has unknown property \'" +\n
+                            prop + "\'");\n
+      }\n
+    }\n
+  }\n
+};\n
+\n
+\n
+/**\n
+ * #crossLink "Query/match:method"\n
+ */\n
+SimpleQuery.prototype.match = function (item) {\n
+  var object_value = null,\n
+    equal_match = null,\n
+    cast_to = null,\n
+    matchMethod = null,\n
+    operator = this.operator,\n
+    value = null,\n
+    key = this.key;\n
+\n
+  /*jslint regexp: true */\n
+  if (!(/^(?:!?=|<=?|>=?)$/i.test(operator))) {\n
+    // `operator` is not correct, we have to change it to "like" or "="\n
+    if (/%/.test(this.value)) {\n
+      // `value` contains a non escaped `%`\n
+      operator = "like";\n
+    } else {\n
+      // `value` does not contain non escaped `%`\n
+      operator = "=";\n
+    }\n
+  }\n
+\n
+  matchMethod = this[operator];\n
+\n
+  if (this._key_schema.key_set && this._key_schema.key_set[key] !== undefined) {\n
+    key = this._key_schema.key_set[key];\n
+  }\n
+\n
+  if (typeof key === \'object\') {\n
+    checkKey(key);\n
+    object_value = item[key.read_from];\n
+\n
+    equal_match = key.equal_match;\n
+\n
+    // equal_match can be a string\n
+    if (typeof equal_match === \'string\') {\n
+      // XXX raise error if equal_match not in match_lookup\n
+      equal_match = this._key_schema.match_lookup[equal_match];\n
+    }\n
+\n
+    // equal_match overrides the default \'=\' operator\n
+    if (equal_match !== undefined) {\n
+      matchMethod = (operator === "=" || operator === "like" ?\n
+                     equal_match : matchMethod);\n
+    }\n
+\n
+    value = this.value;\n
+    cast_to = key.cast_to;\n
+    if (cast_to) {\n
+      // cast_to can be a string\n
+      if (typeof cast_to === \'string\') {\n
+        // XXX raise error if cast_to not in cast_lookup\n
+        cast_to = this._key_schema.cast_lookup[cast_to];\n
+      }\n
+\n
+      value = cast_to(value);\n
+      object_value = cast_to(object_value);\n
+    }\n
+  } else {\n
+    object_value = item[key];\n
+    value = this.value;\n
+  }\n
+  if (object_value === undefined || value === undefined) {\n
+    return RSVP.resolve(false);\n
+  }\n
+  return matchMethod(object_value, value);\n
+};\n
+\n
+/**\n
+ * #crossLink "Query/toString:method"\n
+ */\n
+SimpleQuery.prototype.toString = function () {\n
+  return (this.key ? this.key + ":" : "") +\n
+    (this.operator ? " " + this.operator : "") + \' "\' + this.value + \'"\';\n
+};\n
+\n
+/**\n
+ * #crossLink "Query/serialized:method"\n
+ */\n
+SimpleQuery.prototype.serialized = function () {\n
+  var object = {\n
+    "type": "simple",\n
+    "key": this.key,\n
+    "value": this.value\n
+  };\n
+  if (this.operator !== undefined) {\n
+    object.operator = this.operator;\n
+  }\n
+  return object;\n
+};\n
+SimpleQuery.prototype.toJSON = SimpleQuery.prototype.serialized;\n
+\n
+/**\n
+ * Comparison operator, test if this query value matches the item value\n
+ *\n
+ * @method =\n
+ * @param  {String} object_value The value to compare\n
+ * @param  {String} comparison_value The comparison value\n
+ * @return {Boolean} true if match, false otherwise\n
+ */\n
+SimpleQuery.prototype["="] = function (object_value, comparison_value) {\n
+  var value, i;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  for (i = 0; i < object_value.length; i += 1) {\n
+    value = object_value[i];\n
+    if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+      value = value.content;\n
+    }\n
+    if (typeof value.cmp === "function") {\n
+      return RSVP.resolve(value.cmp(comparison_value) === 0);\n
+    }\n
+    if (\n
+      searchTextToRegExp(comparison_value.toString(), false).\n
+        test(value.toString())\n
+    ) {\n
+      return RSVP.resolve(true);\n
+    }\n
+  }\n
+  return RSVP.resolve(false);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value matches the item value\n
+ *\n
+ * @method like\n
+ * @param  {String} object_value The value to compare\n
+ * @param  {String} comparison_value The comparison value\n
+ * @return {Boolean} true if match, false otherwise\n
+ */\n
+SimpleQuery.prototype.like = function (object_value, comparison_value) {\n
+  var value, i;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  for (i = 0; i < object_value.length; i += 1) {\n
+    value = object_value[i];\n
+    if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+      value = value.content;\n
+    }\n
+    if (typeof value.cmp === "function") {\n
+      return RSVP.resolve(value.cmp(comparison_value) === 0);\n
+    }\n
+    if (\n
+      searchTextToRegExp(comparison_value.toString()).test(value.toString())\n
+    ) {\n
+      return RSVP.resolve(true);\n
+    }\n
+  }\n
+  return RSVP.resolve(false);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value does not match the item value\n
+ *\n
+ * @method !=\n
+ * @param  {String} object_value The value to compare\n
+ * @param  {String} comparison_value The comparison value\n
+ * @return {Boolean} true if not match, false otherwise\n
+ */\n
+SimpleQuery.prototype["!="] = function (object_value, comparison_value) {\n
+  var value, i;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  for (i = 0; i < object_value.length; i += 1) {\n
+    value = object_value[i];\n
+    if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+      value = value.content;\n
+    }\n
+    if (typeof value.cmp === "function") {\n
+      return RSVP.resolve(value.cmp(comparison_value) !== 0);\n
+    }\n
+    if (\n
+      searchTextToRegExp(comparison_value.toString(), false).\n
+        test(value.toString())\n
+    ) {\n
+      return RSVP.resolve(false);\n
+    }\n
+  }\n
+  return RSVP.resolve(true);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value is lower than the item value\n
+ *\n
+ * @method <\n
+ * @param  {Number, String} object_value The value to compare\n
+ * @param  {Number, String} comparison_value The comparison value\n
+ * @return {Boolean} true if lower, false otherwise\n
+ */\n
+SimpleQuery.prototype["<"] = function (object_value, comparison_value) {\n
+  var value;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  value = object_value[0];\n
+  if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+    value = value.content;\n
+  }\n
+  if (typeof value.cmp === "function") {\n
+    return RSVP.resolve(value.cmp(comparison_value) < 0);\n
+  }\n
+  return RSVP.resolve(value < comparison_value);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value is equal or lower than the\n
+ * item value\n
+ *\n
+ * @method <=\n
+ * @param  {Number, String} object_value The value to compare\n
+ * @param  {Number, String} comparison_value The comparison value\n
+ * @return {Boolean} true if equal or lower, false otherwise\n
+ */\n
+SimpleQuery.prototype["<="] = function (object_value, comparison_value) {\n
+  var value;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  value = object_value[0];\n
+  if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+    value = value.content;\n
+  }\n
+  if (typeof value.cmp === "function") {\n
+    return RSVP.resolve(value.cmp(comparison_value) <= 0);\n
+  }\n
+  return RSVP.resolve(value <= comparison_value);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value is greater than the item\n
+ * value\n
+ *\n
+ * @method >\n
+ * @param  {Number, String} object_value The value to compare\n
+ * @param  {Number, String} comparison_value The comparison value\n
+ * @return {Boolean} true if greater, false otherwise\n
+ */\n
+SimpleQuery.prototype[">"] = function (object_value, comparison_value) {\n
+  var value;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  value = object_value[0];\n
+  if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+    value = value.content;\n
+  }\n
+  if (typeof value.cmp === "function") {\n
+    return RSVP.resolve(value.cmp(comparison_value) > 0);\n
+  }\n
+  return RSVP.resolve(value > comparison_value);\n
+};\n
+\n
+/**\n
+ * Comparison operator, test if this query value is equal or greater than the\n
+ * item value\n
+ *\n
+ * @method >=\n
+ * @param  {Number, String} object_value The value to compare\n
+ * @param  {Number, String} comparison_value The comparison value\n
+ * @return {Boolean} true if equal or greater, false otherwise\n
+ */\n
+SimpleQuery.prototype[">="] = function (object_value, comparison_value) {\n
+  var value;\n
+  if (!Array.isArray(object_value)) {\n
+    object_value = [object_value];\n
+  }\n
+  value = object_value[0];\n
+  if (typeof value === \'object\' && value.hasOwnProperty(\'content\')) {\n
+    value = value.content;\n
+  }\n
+  if (typeof value.cmp === "function") {\n
+    return RSVP.resolve(value.cmp(comparison_value) >= 0);\n
+  }\n
+  return RSVP.resolve(value >= comparison_value);\n
+};\n
+\n
+query_class_dict.simple = SimpleQuery;\n
+\n
+_export("SimpleQuery", SimpleQuery);\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true */\n
+/*global _export, RSVP */\n
+\n
+/**\n
+ * Escapes regexp special chars from a string.\n
+ *\n
+ * @param  {String} string The string to escape\n
+ * @return {String} The escaped string\n
+ */\n
+function stringEscapeRegexpCharacters(string) {\n
+  if (typeof string === "string") {\n
+    return string.replace(/([\\\\\\.\\$\\[\\]\\(\\)\\{\\}\\^\\?\\*\\+\\-])/g, "\\\\$1");\n
+  }\n
+  throw new TypeError("complex_queries.stringEscapeRegexpCharacters(): " +\n
+                      "Argument no 1 is not of type \'string\'");\n
+}\n
+\n
+_export("stringEscapeRegexpCharacters", stringEscapeRegexpCharacters);\n
+\n
+/**\n
+ * Convert metadata values to array of strings. ex:\n
+ *\n
+ *     "a" -> ["a"],\n
+ *     {"content": "a"} -> ["a"]\n
+ *\n
+ * @param  {Any} value The metadata value\n
+ * @return {Array} The value in string array format\n
+ */\n
+function metadataValueToStringArray(value) {\n
+  var i, new_value = [];\n
+  if (value === undefined) {\n
+    return undefined;\n
+  }\n
+  if (!Array.isArray(value)) {\n
+    value = [value];\n
+  }\n
+  for (i = 0; i < value.length; i += 1) {\n
+    if (typeof value[i] === \'object\') {\n
+      new_value[i] = value[i].content;\n
+    } else {\n
+      new_value[i] = value[i];\n
+    }\n
+  }\n
+  return new_value;\n
+}\n
+\n
+/**\n
+ * A sort function to sort items by key\n
+ *\n
+ * @param  {String} key The key to sort on\n
+ * @param  {String} [way="ascending"] \'ascending\' or \'descending\'\n
+ * @return {Function} The sort function\n
+ */\n
+function sortFunction(key, way) {\n
+  if (way === \'descending\') {\n
+    return function (a, b) {\n
+      // this comparison is 5 times faster than json comparison\n
+      var i, l;\n
+      a = metadataValueToStringArray(a[key]) || [];\n
+      b = metadataValueToStringArray(b[key]) || [];\n
+      l = a.length > b.length ? a.length : b.length;\n
+      for (i = 0; i < l; i += 1) {\n
+        if (a[i] === undefined) {\n
+          return 1;\n
+        }\n
+        if (b[i] === undefined) {\n
+          return -1;\n
+        }\n
+        if (a[i] > b[i]) {\n
+          return -1;\n
+        }\n
+        if (a[i] < b[i]) {\n
+          return 1;\n
+        }\n
+      }\n
+      return 0;\n
+    };\n
+  }\n
+  if (way === \'ascending\') {\n
+    return function (a, b) {\n
+      // this comparison is 5 times faster than json comparison\n
+      var i, l;\n
+      a = metadataValueToStringArray(a[key]) || [];\n
+      b = metadataValueToStringArray(b[key]) || [];\n
+      l = a.length > b.length ? a.length : b.length;\n
+      for (i = 0; i < l; i += 1) {\n
+        if (a[i] === undefined) {\n
+          return -1;\n
+        }\n
+        if (b[i] === undefined) {\n
+          return 1;\n
+        }\n
+        if (a[i] > b[i]) {\n
+          return 1;\n
+        }\n
+        if (a[i] < b[i]) {\n
+          return -1;\n
+        }\n
+      }\n
+      return 0;\n
+    };\n
+  }\n
+  throw new TypeError("complex_queries.sortFunction(): " +\n
+                      "Argument 2 must be \'ascending\' or \'descending\'");\n
+}\n
+\n
+/**\n
+ * Clones all native object in deep. Managed types: Object, Array, String,\n
+ * Number, Boolean, null.\n
+ *\n
+ * @param  {A} object The object to clone\n
+ * @return {A} The cloned object\n
+ */\n
+function deepClone(object) {\n
+  var i, cloned;\n
+  if (Array.isArray(object)) {\n
+    cloned = [];\n
+    for (i = 0; i < object.length; i += 1) {\n
+      cloned[i] = deepClone(object[i]);\n
+    }\n
+    return cloned;\n
+  }\n
+  if (typeof object === "object") {\n
+    cloned = {};\n
+    for (i in object) {\n
+      if (object.hasOwnProperty(i)) {\n
+        cloned[i] = deepClone(object[i]);\n
+      }\n
+    }\n
+    return cloned;\n
+  }\n
+  return object;\n
+}\n
+\n
+/**\n
+ * Inherits the prototype methods from one constructor into another. The\n
+ * prototype of `constructor` will be set to a new object created from\n
+ * `superConstructor`.\n
+ *\n
+ * @param  {Function} constructor The constructor which inherits the super one\n
+ * @param  {Function} superConstructor The super constructor\n
+ */\n
+function inherits(constructor, superConstructor) {\n
+  constructor.super_ = superConstructor;\n
+  constructor.prototype = Object.create(superConstructor.prototype, {\n
+    "constructor": {\n
+      "configurable": true,\n
+      "enumerable": false,\n
+      "writable": true,\n
+      "value": constructor\n
+    }\n
+  });\n
+}\n
+\n
+/**\n
+ * Does nothing\n
+ */\n
+function emptyFunction() {\n
+  return;\n
+}\n
+\n
+/**\n
+ * Filter a list of items, modifying them to select only wanted keys. If\n
+ * `clone` is true, then the method will act on a cloned list.\n
+ *\n
+ * @param  {Array} select_option Key list to keep\n
+ * @param  {Array} list The item list to filter\n
+ * @param  {Boolean} [clone=false] If true, modifies a clone of the list\n
+ * @return {Array} The filtered list\n
+ */\n
+function select(select_option, list, clone) {\n
+  var i, j, new_item;\n
+  if (!Array.isArray(select_option)) {\n
+    throw new TypeError("complex_queries.select(): " +\n
+                        "Argument 1 is not of type Array");\n
+  }\n
+  if (!Array.isArray(list)) {\n
+    throw new TypeError("complex_queries.select(): " +\n
+                        "Argument 2 is not of type Array");\n
+  }\n
+  if (clone === true) {\n
+    list = deepClone(list);\n
+  }\n
+  for (i = 0; i < list.length; i += 1) {\n
+    new_item = {};\n
+    for (j = 0; j < select_option.length; j += 1) {\n
+      if (list[i].hasOwnProperty([select_option[j]])) {\n
+        new_item[select_option[j]] = list[i][select_option[j]];\n
+      }\n
+    }\n
+    for (j in new_item) {\n
+      if (new_item.hasOwnProperty(j)) {\n
+        list[i] = new_item;\n
+        break;\n
+      }\n
+    }\n
+  }\n
+  return list;\n
+}\n
+\n
+_export(\'select\', select);\n
+\n
+/**\n
+ * Sort a list of items, according to keys and directions. If `clone` is true,\n
+ * then the method will act on a cloned list.\n
+ *\n
+ * @param  {Array} sort_on_option List of couples [key, direction]\n
+ * @param  {Array} list The item list to sort\n
+ * @param  {Boolean} [clone=false] If true, modifies a clone of the list\n
+ * @return {Array} The filtered list\n
+ */\n
+function sortOn(sort_on_option, list, clone) {\n
+  var sort_index;\n
+  if (!Array.isArray(sort_on_option)) {\n
+    throw new TypeError("complex_queries.sortOn(): " +\n
+                        "Argument 1 is not of type \'array\'");\n
+  }\n
+  if (clone) {\n
+    list = deepClone(list);\n
+  }\n
+  for (sort_index = sort_on_option.length - 1; sort_index >= 0;\n
+       sort_index -= 1) {\n
+    list.sort(sortFunction(\n
+      sort_on_option[sort_index][0],\n
+      sort_on_option[sort_index][1]\n
+    ));\n
+  }\n
+  return list;\n
+}\n
+\n
+_export(\'sortOn\', sortOn);\n
+\n
+/**\n
+ * Limit a list of items, according to index and length. If `clone` is true,\n
+ * then the method will act on a cloned list.\n
+ *\n
+ * @param  {Array} limit_option A couple [from, length]\n
+ * @param  {Array} list The item list to limit\n
+ * @param  {Boolean} [clone=false] If true, modifies a clone of the list\n
+ * @return {Array} The filtered list\n
+ */\n
+function limit(limit_option, list, clone) {\n
+  if (!Array.isArray(limit_option)) {\n
+    throw new TypeError("complex_queries.limit(): " +\n
+                        "Argument 1 is not of type \'array\'");\n
+  }\n
+  if (!Array.isArray(list)) {\n
+    throw new TypeError("complex_queries.limit(): " +\n
+                        "Argument 2 is not of type \'array\'");\n
+  }\n
+  if (clone) {\n
+    list = deepClone(list);\n
+  }\n
+  list.splice(0, limit_option[0]);\n
+  if (limit_option[1]) {\n
+    list.splice(limit_option[1]);\n
+  }\n
+  return list;\n
+}\n
+\n
+_export(\'limit\', limit);\n
+\n
+/**\n
+ * Convert a search text to a regexp.\n
+ *\n
+ * @param  {String} string The string to convert\n
+ * @param  {Boolean} [use_wildcard_character=true] Use wildcard "%" and "_"\n
+ * @return {RegExp} The search text regexp\n
+ */\n
+function searchTextToRegExp(string, use_wildcard_characters) {\n
+  if (typeof string !== \'string\') {\n
+    throw new TypeError("complex_queries.searchTextToRegExp(): " +\n
+                        "Argument 1 is not of type \'string\'");\n
+  }\n
+  if (use_wildcard_characters === false) {\n
+    return new RegExp("^" + stringEscapeRegexpCharacters(string) + "$");\n
+  }\n
+  return new RegExp("^" + stringEscapeRegexpCharacters(string).replace(\n
+    /%/g,\n
+    ".*"\n
+  ).replace(\n
+    /_/g,\n
+    "."\n
+  ) + "$");\n
+}\n
+\n
+_export("searchTextToRegExp", searchTextToRegExp);\n
+\n
+/**\n
+ * sequence(thens): Promise\n
+ *\n
+ * Executes a sequence of *then* callbacks. It acts like\n
+ * `smth().then(callback).then(callback)...`. The first callback is called with\n
+ * no parameter.\n
+ *\n
+ * Elements of `thens` array can be a function or an array contaning at most\n
+ * three *then* callbacks: *onFulfilled*, *onRejected*, *onNotified*.\n
+ *\n
+ * When `cancel()` is executed, each then promises are cancelled at the same\n
+ * time.\n
+ *\n
+ * @param  {Array} thens An array of *then* callbacks\n
+ * @return {Promise} A new promise\n
+ */\n
+function sequence(thens) {\n
+  var promises = [];\n
+  return new RSVP.Promise(function (resolve, reject, notify) {\n
+    var i;\n
+    promises[0] = new RSVP.Promise(function (resolve) {\n
+      resolve();\n
+    });\n
+    for (i = 0; i < thens.length; i += 1) {\n
+      if (Array.isArray(thens[i])) {\n
+        promises[i + 1] = promises[i].\n
+          then(thens[i][0], thens[i][1], thens[i][2]);\n
+      } else {\n
+        promises[i + 1] = promises[i].then(thens[i]);\n
+      }\n
+    }\n
+    promises[i].then(resolve, reject, notify);\n
+  }, function () {\n
+    var i;\n
+    for (i = 0; i < promises.length; i += 1) {\n
+      promises[i].cancel();\n
+    }\n
+  });\n
+}\n
+\n
+\n
+  return to_export;\n
+}));\n
+;/*\n
+ * Copyright 2013, Nexedi SA\n
+ * Released under the LGPL license.\n
+ * http://www.gnu.org/licenses/lgpl.html\n
+ */\n
+\n
+/*jslint indent: 2, maxlen: 80, sloppy: true, nomen: true, regexp: true */\n
+/*global jIO, localStorage, setTimeout, window, define, Blob, Uint8Array,\n
+  exports, require */\n
+\n
+/**\n
+ * JIO Local Storage. Type = \'local\'.\n
+ * Local browser "database" storage.\n
+ *\n
+ * Storage Description:\n
+ *\n
+ *     {\n
+ *       "type": "local",\n
+ *       "mode": <string>,\n
+ *         // - "localStorage" // default\n
+ *         // - "memory"\n
+ *       "username": <non empty string>, // to define user space\n
+ *       "application_name": <string> // default \'untitled\'\n
+ *     }\n
+ *\n
+ * Document are stored in path\n
+ * \'jio/localstorage/username/application_name/document_id\' like this:\n
+ *\n
+ *     {\n
+ *       "_id": "document_id",\n
+ *       "_attachments": {\n
+ *         "attachment_name": {\n
+ *           "length": data_length,\n
+ *           "digest": "md5-XXX",\n
+ *           "content_type": "mime/type"\n
+ *         },\n
+ *         "attachment_name2": {..}, ...\n
+ *       },\n
+ *       "metadata_name": "metadata_value"\n
+ *       "metadata_name2": ...\n
+ *       ...\n
+ *     }\n
+ *\n
+ * Only "_id" and "_attachments" are specific metadata keys, other one can be\n
+ * added without loss.\n
+ *\n
+ * @class LocalStorage\n
+ */\n
+\n
+// define([module_name], [dependencies], module);\n
+(function (dependencies, module) {\n
+  "use strict";\n
+  if (typeof define === \'function\' && define.amd) {\n
+    return define(dependencies, module);\n
+  }\n
+  if (typeof exports === \'object\') {\n
+    return module(exports, require(\'jio\'));\n
+  }\n
+  window.local_storage = {};\n
+  module(window.local_storage, jIO);\n
+}([\n
+  \'exports\',\n
+  \'jio\'\n
+], function (exports, jIO) {\n
+  "use strict";\n
+\n
+  /**\n
+   * Checks if an object has no enumerable keys\n
+   *\n
+   * @param  {Object} obj The object\n
+   * @return {Boolean} true if empty, else false\n
+   */\n
+  function objectIsEmpty(obj) {\n
+    var k;\n
+    for (k in obj) {\n
+      if (obj.hasOwnProperty(k)) {\n
+        return false;\n
+      }\n
+    }\n
+    return true;\n
+  }\n
+\n
+  var ram = {}, memorystorage, localstorage;\n
+\n
+  /*\n
+   * Wrapper for the localStorage used to simplify instion of any kind of\n
+   * values\n
+   */\n
+  localstorage = {\n
+    getItem: function (item) {\n
+      var value = localStorage.getItem(item);\n
+      return value === null ? null : JSON.parse(value);\n
+    },\n
+    setItem: function (item, value) {\n
+      return localStorage.setItem(item, JSON.stringify(value));\n
+    },\n
+    removeItem: function (item) {\n
+      return localStorage.removeItem(item);\n
+    }\n
+  };\n
+\n
+  /*\n
+   * Wrapper for the localStorage used to simplify instion of any kind of\n
+   * values\n
+   */\n
+  memorystorage = {\n
+    getItem: function (item) {\n
+      var value = ram[item];\n
+      return value === undefined ? null : JSON.parse(value);\n
+    },\n
+    setItem: function (item, value) {\n
+      ram[item] = JSON.stringify(value);\n
+    },\n
+    removeItem: function (item) {\n
+      delete ram[item];\n
+    }\n
+  };\n
+\n
+  /**\n
+   * The JIO LocalStorage extension\n
+   *\n
+   * @class LocalStorage\n
+   * @constructor\n
+   */\n
+  function LocalStorage(spec) {\n
+    if (typeof spec.username !== \'string\' || spec.username === \'\') {\n
+      throw new TypeError("LocalStorage \'username\' must be a non-empty string");\n
+    }\n
+    this._localpath = \'jio/localstorage/\' + spec.username + \'/\' + (\n
+      spec.application_name === null || spec.application_name ===\n
+        undefined ? \'untitled\' : spec.application_name.toString()\n
+    );\n
+    switch (spec.mode) {\n
+    case "memory":\n
+      this._database = ram;\n
+      this._storage = memorystorage;\n
+      this._mode = "memory";\n
+      break;\n
+    default:\n
+      this._database = localStorage;\n
+      this._storage = localstorage;\n
+      this._mode = "localStorage";\n
+      this._key_schema = spec.key_schema;\n
+      break;\n
+    }\n
+  }\n
+\n
+\n
+  /**\n
+   * Create a document in local storage.\n
+   *\n
+   * @method post\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} metadata The metadata to store\n
+   * @param  {Object} options The command options\n
+   */\n
+  LocalStorage.prototype.post = function (command, metadata) {\n
+    var doc, doc_id = metadata._id;\n
+    if (!doc_id) {\n
+      doc_id = jIO.util.generateUuid();\n
+    }\n
+    doc = this._storage.getItem(this._localpath + "/" + doc_id);\n
+    if (doc === null) {\n
+      // the document does not exist\n
+      doc = jIO.util.deepClone(metadata);\n
+      doc._id = doc_id;\n
+      delete doc._attachments;\n
+      this._storage.setItem(this._localpath + "/" + doc_id, doc);\n
+      command.success({"id": doc_id});\n
+    } else {\n
+      // the document already exists\n
+      command.error(\n
+        "conflict",\n
+        "document exists",\n
+        "Cannot create a new document"\n
+      );\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Create or update a document in local storage.\n
+   *\n
+   * @method put\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} metadata The metadata to store\n
+   * @param  {Object} options The command options\n
+   */\n
+  LocalStorage.prototype.put = function (command, metadata) {\n
+    var doc, tmp, status;\n
+    doc = this._storage.getItem(this._localpath + "/" + metadata._id);\n
+    if (doc === null) {\n
+      //  the document does not exist\n
+      doc = jIO.util.deepClone(metadata);\n
+      delete doc._attachments;\n
+      status = "created";\n
+    } else {\n
+      // the document already exists\n
+      tmp = jIO.util.deepClone(metadata);\n
+      tmp._attachments = doc._attachments;\n
+      doc = tmp;\n
+      status = "no_content";\n
+    }\n
+    // write\n
+    this._storage.setItem(this._localpath + "/" + metadata._id, doc);\n
+    command.success(status);\n
+  };\n
+\n
+  /**\n
+   * Add an attachment to a document\n
+   *\n
+   * @method putAttachment\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} param The given parameters\n
+   * @param  {Object} options The command options\n
+   */\n
+  LocalStorage.prototype.putAttachment = function (command, param) {\n
+    var that = this, doc, status = "created";\n
+    doc = this._storage.getItem(this._localpath + "/" + param._id);\n
+    if (doc === null) {\n
+      //  the document does not exist\n
+      return command.error(\n
+        "not_found",\n
+        "missing",\n
+        "Impossible to add attachment"\n
+      );\n
+    }\n
+\n
+    // the document already exists\n
+    // download data\n
+    jIO.util.readBlobAsBinaryString(param._blob).then(function (e) {\n
+      doc._attachments = doc._attachments || {};\n
+      if (doc._attachments[param._attachment]) {\n
+        status = "no_content";\n
+      }\n
+      doc._attachments[param._attachment] = {\n
+        "content_type": param._blob.type,\n
+        "digest": jIO.util.makeBinaryStringDigest(e.target.result),\n
+        "length": param._blob.size\n
+      };\n
+\n
+      that._storage.setItem(that._localpath + "/" + param._id + "/" +\n
+                            param._attachment, e.target.result);\n
+      that._storage.setItem(that._localpath + "/" + param._id, doc);\n
+      command.success(status,\n
+                      {"digest": doc._attachments[param._attachment].digest});\n
+    }, function (e) {\n
+      command.error(\n
+        "request_timeout",\n
+        "blob error",\n
+        "Error " + e.status + ", unable to get blob content"\n
+      );\n
+    }, function (e) {\n
+      command.notify((e.loaded / e.total) * 100);\n
+    });\n
+  };\n
+\n
+  /**\n
+   * Get a document\n
+   *\n
+   * @method get\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} param The given parameters\n
+   * @param  {Object} options The command options\n
+   */\n
+  LocalStorage.prototype.get = function (command, param) {\n
+    var doc = this._storage.getItem(\n
+      this._localpath + "/" + param._id\n
+    );\n
+    if (doc !== null) {\n
+      command.success({"data": doc});\n
+    } else {\n
+      command.error(\n
+        "not_found",\n
+        "missing",\n
+        "Cannot find document"\n
+      );\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Get an attachment\n
+   *\n
+   * @method getAttachment\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} param The given parameters\n
+   * @param  {Object} options The command options\n
+   */\n
+  LocalStorage.prototype.getAttachment = function (command, param) {\n
+    var doc, i, uint8array, binarystring;\n
+    doc = this._storage.getItem(this._localpath + "/" + param._id);\n
+    if (doc === null) {\n
+      return command.error(\n
+        "not_found",\n
+        "missing document",\n
+        "Cannot find document"\n
+      );\n
+    }\n
+\n
+    if (typeof doc._attachments !== \'object\' ||\n
+        typeof doc._attachments[param._attachment] !== \'object\') {\n
+      return command.error(\n
+        "not_found",\n
+        "missing attachment",\n
+        "Cannot find attachment"\n
+      );\n
+    }\n
+\n
+    // Storing data twice in binarystring and in uint8array (in memory)\n
+    // is not a problem here because localStorage <= 5MB\n
+    binarystring = this._storage.getItem(\n
+      this._localpath + "/" + param._id + "/" + param._attachment\n
+    ) || "";\n
+    uint8array = new Uint8Array(binarystring.length);\n
+    for (i = 0; i < binarystring.length; i += 1) {\n
+      uint8array[i] = binarystring.charCodeAt(i); // mask `& 0xFF` not necessary\n
+    }\n
+    uint8array = new Blob([uint8array.buffer], {\n
+      "type": doc._attachments[param._attachment].content_type || ""\n
+    });\n
+\n
+    command.success({\n
+      "data": uint8array,\n
+      "digest": doc._attachments[param._attachment].digest\n
+    });\n
+  };\n
+\n
+  /**\n
+   * Remove a document\n
+   *\n
+   * @method remove\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} param The given parameters\n
+   * @param  {Object} options The command options\n
+   */\n
+  LocalStorage.prototype.remove = function (command, param) {\n
+    var doc, i, attachment_list;\n
+    doc = this._storage.getItem(this._localpath + "/" + param._id);\n
+    attachment_list = [];\n
+    if (doc !== null && typeof doc === "object") {\n
+      if (typeof doc._attachments === "object") {\n
+        // prepare list of attachments\n
+        for (i in doc._attachments) {\n
+          if (doc._attachments.hasOwnProperty(i)) {\n
+            attachment_list.push(i);\n
+          }\n
+        }\n
+      }\n
+    } else {\n
+      return command.error(\n
+        "not_found",\n
+        "missing",\n
+        "Document not found"\n
+      );\n
+    }\n
+    this._storage.removeItem(this._localpath + "/" + param._id);\n
+    // delete all attachments\n
+    for (i = 0; i < attachment_list.length; i += 1) {\n
+      this._storage.removeItem(this._localpath + "/" + param._id +\n
+                               "/" + attachment_list[i]);\n
+    }\n
+    command.success();\n
+  };\n
+\n
+  /**\n
+   * Remove an attachment\n
+   *\n
+   * @method removeAttachment\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} param The given parameters\n
+   * @param  {Object} options The command options\n
+   */\n
+  LocalStorage.prototype.removeAttachment = function (command, param) {\n
+    var doc = this._storage.getItem(this._localpath + "/" + param._id);\n
+    if (typeof doc !== \'object\' || doc === null) {\n
+      return command.error(\n
+        "not_found",\n
+        "missing document",\n
+        "Document not found"\n
+      );\n
+    }\n
+    if (typeof doc._attachments !== "object" ||\n
+        typeof doc._attachments[param._attachment] !== "object") {\n
+      return command.error(\n
+        "not_found",\n
+        "missing attachment",\n
+        "Attachment not found"\n
+      );\n
+    }\n
+\n
+    delete doc._attachments[param._attachment];\n
+    if (objectIsEmpty(doc._attachments)) {\n
+      delete doc._attachments;\n
+    }\n
+    this._storage.setItem(this._localpath + "/" + param._id, doc);\n
+    this._storage.removeItem(this._localpath + "/" + param._id +\n
+                             "/" + param._attachment);\n
+    command.success();\n
+  };\n
+\n
+  /**\n
+   * Get all filenames belonging to a user from the document index\n
+   *\n
+   * @method allDocs\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} param The given parameters\n
+   * @param  {Object} options The command options\n
+   */\n
+  LocalStorage.prototype.allDocs = function (command, param, options) {\n
+    var i, row, path_re, rows, document_list, document_object, delete_id;\n
+    param.unused = true;\n
+    rows = [];\n
+    document_list = [];\n
+    path_re = new RegExp(\n
+      "^" + jIO.Query.stringEscapeRegexpCharacters(this._localpath) +\n
+        "/[^/]+$"\n
+    );\n
+    if (options.query === undefined && options.sort_on === undefined &&\n
+        options.select_list === undefined &&\n
+        options.include_docs === undefined) {\n
+      rows = [];\n
+      for (i in this._database) {\n
+        if (this._database.hasOwnProperty(i)) {\n
+          // filter non-documents\n
+          if (path_re.test(i)) {\n
+            row = { value: {} };\n
+            row.id = i.split(\'/\').slice(-1)[0];\n
+            row.key = row.id;\n
+            if (options.include_docs) {\n
+              row.doc = JSON.parse(this._storage.getItem(i));\n
+            }\n
+            rows.push(row);\n
+          }\n
+        }\n
+      }\n
+      command.success({"data": {"rows": rows, "total_rows": rows.length}});\n
+    } else {\n
+      // create jio query object from returned results\n
+      for (i in this._database) {\n
+        if (this._database.hasOwnProperty(i)) {\n
+          if (path_re.test(i)) {\n
+            document_list.push(this._storage.getItem(i));\n
+          }\n
+        }\n
+      }\n
+      options.select_list = options.select_list || [];\n
+      if (options.select_list.indexOf("_id") === -1) {\n
+        options.select_list.push("_id");\n
+        delete_id = true;\n
+      }\n
+      if (options.include_docs === true) {\n
+        document_object = {};\n
+        document_list.forEach(function (meta) {\n
+          document_object[meta._id] = meta;\n
+        });\n
+      }\n
+      jIO.QueryFactory.create(options.query || "",\n
+                              this._key_schema).\n
+        exec(document_list, options).then(function () {\n
+          document_list = document_list.map(function (value) {\n
+            var o = {\n
+              "id": value._id,\n
+              "key": value._id\n
+            };\n
+            if (options.include_docs === true) {\n
+              o.doc = document_object[value._id];\n
+              delete document_object[value._id];\n
+            }\n
+            if (delete_id) {\n
+              delete value._id;\n
+            }\n
+            o.value = value;\n
+            return o;\n
+          });\n
+          command.success({"data": {\n
+            "total_rows": document_list.length,\n
+            "rows": document_list\n
+          }});\n
+        });\n
+    }\n
+  };\n
+\n
+  /**\n
+   * Check the storage or a specific document\n
+   *\n
+   * @method check\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} param The command parameters\n
+   * @param  {Object} options The command options\n
+   */\n
+  LocalStorage.prototype.check = function (command, param) {\n
+    this.genericRepair(command, param, false);\n
+  };\n
+\n
+  /**\n
+   * Repair the storage or a specific document\n
+   *\n
+   * @method repair\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} param The command parameters\n
+   * @param  {Object} options The command options\n
+   */\n
+  LocalStorage.prototype.repair = function (command, param) {\n
+    this.genericRepair(command, param, true);\n
+  };\n
+\n
+  /**\n
+   * A generic method that manage check or repair command\n
+   *\n
+   * @method genericRepair\n
+   * @param  {Object} command The JIO command\n
+   * @param  {Object} param The command parameters\n
+   * @param  {Boolean} repair If true then repair else just check\n
+   */\n
+  LocalStorage.prototype.genericRepair = function (command, param, repair) {\n
+\n
+    var that = this, final_result;\n
+\n
+    function referenceAttachment(param, attachment) {\n
+      if (param.referenced_attachments.indexOf(attachment) !== -1) {\n
+        return;\n
+      }\n
+      var i = param.unreferenced_attachments.indexOf(attachment);\n
+      if (i !== -1) {\n
+        param.unreferenced_attachments.splice(i, 1);\n
+      }\n
+      param.referenced_attachments[param.referenced_attachments.length] =\n
+        attachment;\n
+    }\n
+\n
+    function attachmentFound(param, attachment) {\n
+      if (param.referenced_attachments.indexOf(attachment) !== -1) {\n
+        return;\n
+      }\n
+      if (param.unreferenced_attachments.indexOf(attachment) !== -1) {\n
+        return;\n
+      }\n
+      param.unreferenced_attachments[param.unreferenced_attachments.length] =\n
+        attachment;\n
+    }\n
+\n
+    function repairOne(param, repair) {\n
+      var i, doc, modified;\n
+      doc = that._storage.getItem(that._localpath + "/" + param._id);\n
+      if (doc === null) {\n
+        return; // OK\n
+      }\n
+\n
+      // check document type\n
+      if (typeof doc !== \'object\' || doc === null) {\n
+        // wrong document\n
+        if (!repair) {\n
+          return {"error": true, "answers": [\n
+            "conflict",\n
+            "corrupted",\n
+            "Document is unrecoverable"\n
+          ]};\n
+        }\n
+        // delete the document\n
+        that._storage.removeItem(that._localpath + "/" + param._id);\n
+        return; // OK\n
+      }\n
+      // good document type\n
+      // repair json document\n
+      if (!repair) {\n
+        if (!(new jIO.Metadata(doc).check())) {\n
+          return {"error": true, "answers": [\n
+            "conflict",\n
+            "corrupted",\n
+            "Some metadata might be lost"\n
+          ]};\n
+        }\n
+      } else {\n
+        modified = jIO.util.uniqueJSONStringify(doc) !==\n
+          jIO.util.uniqueJSONStringify(new jIO.Metadata(doc).format()._dict);\n
+      }\n
+      if (doc._attachments !== undefined) {\n
+        if (typeof doc._attachments !== \'object\') {\n
+          if (!repair) {\n
+            return {"error": true, "answers": [\n
+              "conflict",\n
+              "corrupted",\n
+              "Attachments are unrecoverable"\n
+            ]};\n
+          }\n
+          delete doc._attachments;\n
+          that._storage.setItem(that._localpath + "/" + param._id, doc);\n
+          return; // OK\n
+        }\n
+        for (i in doc._attachments) {\n
+          if (doc._attachments.hasOwnProperty(i)) {\n
+            // check attachment existence\n
+            if (that._storage.getItem(that._localpath + "/" + param._id + "/" +\n
+                                      i) !== \'string\') {\n
+              if (!repair) {\n
+                return {"error": true, "answers": [\n
+                  "conflict",\n
+                  "missing attachment",\n
+                  "Attachment \\"" + i + "\\" of \\"" + param._id + "\\" is missing"\n
+                ]};\n
+              }\n
+              delete doc._attachments[i];\n
+              if (objectIsEmpty(doc._attachments)) {\n
+                delete doc._attachments;\n
+              }\n
+              modified = true;\n
+            } else {\n
+              // attachment exists\n
+              // check attachment metadata\n
+              // check length\n
+              referenceAttachment(param, param._id + "/" + doc._attachments[i]);\n
+              if (doc._attachments[i].length !== undefined &&\n
+                  typeof doc._attachments[i].length !== \'number\') {\n
+                if (!repair) {\n
+                  return {"error": true, "answers": [\n
+                    "conflict",\n
+                    "corrupted",\n
+                    "Attachment metadata length corrupted"\n
+                  ]};\n
+                }\n
+                // It could take a long time to get the length, no repair.\n
+                // length can be omited\n
+                delete doc._attachments[i].length;\n
+              }\n
+              // It could take a long time to regenerate the hash, no check.\n
+              // Impossible to discover the attachment content type.\n
+            }\n
+          }\n
+        }\n
+      }\n
+      if (modified) {\n
+        that._storage.setItem(that._localpath + "/" + param._id, doc);\n
+      }\n
+      // OK\n
+    }\n
+\n
+    function repairAll(param, repair) {\n
+      var i, result;\n
+      for (i in that._database) {\n
+        if (that._database.hasOwnProperty(i)) {\n
+          // browsing every entry\n
+          if (i.slice(0, that._localpath.length) === that._localpath) {\n
+            // is part of the user space\n
+            if (/^[^\\/]+\\/[^\\/]+$/.test(i.slice(that._localpath.length + 1))) {\n
+              // this is an attachment\n
+              attachmentFound(param, i.slice(that._localpath.length + 1));\n
+            } else if (/^[^\\/]+$/.test(i.slice(that._localpath.length + 1))) {\n
+              // this is a document\n
+              param._id = i.slice(that._localpath.length + 1);\n
+              result = repairOne(param, repair);\n
+              if (result) {\n
+                return result;\n
+              }\n
+            } else {\n
+              // this is pollution\n
+              that._storage.removeItem(i);\n
+            }\n
+          }\n
+        }\n
+      }\n
+      // remove unreferenced attachments\n
+      for (i = 0; i < param.unreferenced_attachments.length; i += 1) {\n
+        that._storage.removeItem(that._localpath + "/" +\n
+                                 param.unreferenced_attachments[i]);\n
+      }\n
+    }\n
+\n
+    param.referenced_attachments = [];\n
+    param.unreferenced_attachments = [];\n
+    if (typeof param._id === \'string\') {\n
+      final_result = repairOne(param, repair) || {};\n
+    } else {\n
+      final_result = repairAll(param, repair) || {};\n
+    }\n
+    if (final_result.error) {\n
+      return command.error.apply(command, final_result.answers || []);\n
+    }\n
+    command.success.apply(command, final_result.answers || []);\n
+  };\n
+\n
+  jIO.addStorage(\'local\', LocalStorage);\n
+\n
+  //////////////////////////////////////////////////////////////////////\n
+  // Tools\n
+\n
+  function createLocalDescription(username, application_name) {\n
+    if (typeof username !== \'string\') {\n
+      throw new TypeError("LocalStorage username must be a string");\n
+    }\n
+    var description = {\n
+      "type": "local",\n
+      "username": username\n
+    };\n
+    if (typeof application_name === \'string\') {\n
+      description.application_name = application_name;\n
+    }\n
+    return description;\n
+  }\n
+\n
+  function createMemoryDescription(username, application_name) {\n
+    var description = createLocalDescription(username, application_name);\n
+    description.mode = "memory";\n
+    return description;\n
+  }\n
+\n
+  /**\n
+   * Tool to help users to create local storage description for JIO\n
+   *\n
+   * @param  {String} username The username\n
+   * @param  {String} [application_name] The application_name\n
+   * @param  {String} [mode="localStorage"] Use localStorage or memory\n
+   * @return {Object} The storage description\n
+   */\n
+  function createDescription(username, application_name, mode) {\n
+    if (mode === undefined || mode.toString() === \'localStorage\') {\n
+      return createLocalDescription(username, application_name);\n
+    }\n
+    if (mode.toString() === \'memory\') {\n
+      return createMemoryDescription(username, application_name);\n
+    }\n
+    throw new TypeError("Unknown LocalStorage \'" + mode.toString() + "\' mode");\n
+  }\n
+\n
+  exports.createDescription = createDescription;\n
+  exports.createLocalDescription = createLocalDescription;\n
+  exports.createMemoryDescription = createMemoryDescription;\n
+\n
+  function clearLocalStorage() {\n
+    var k;\n
+    for (k in localStorage) {\n
+      if (localStorage.hasOwnProperty(k)) {\n
+        if (/^jio\\/localstorage\\//.test(k)) {\n
+          localStorage.removeItem(k);\n
+        }\n
+      }\n
+    }\n
+  }\n
+\n
+  function clearMemoryStorage() {\n
+    jIO.util.dictClear(ram);\n
+  }\n
+\n
+  exports.clear = clearLocalStorage;\n
+  exports.clearLocalStorage = clearLocalStorage;\n
+  exports.clearMemoryStorage = clearMemoryStorage;\n
+\n
+}));\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery-ui.css.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery-ui.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..672779188721a5c74ea25c952fd77abfd4cbff05
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery-ui.css.xml
@@ -0,0 +1,1215 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681769.75</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jquery-ui.css</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/css</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*! jQuery UI - v1.11.0-beta.1 - 2014-04-24\n
+* http://jqueryui.com\n
+* Includes: core.css, accordion.css, autocomplete.css, button.css, datepicker.css, dialog.css, draggable.css, menu.css, progressbar.css, resizable.css, selectable.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css\n
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */\n
+\n
+/* Layout helpers\n
+----------------------------------*/\n
+.ui-helper-hidden {\n
+\tdisplay: none;\n
+}\n
+.ui-helper-hidden-accessible {\n
+\tborder: 0;\n
+\tclip: rect(0 0 0 0);\n
+\theight: 1px;\n
+\tmargin: -1px;\n
+\toverflow: hidden;\n
+\tpadding: 0;\n
+\tposition: absolute;\n
+\twidth: 1px;\n
+}\n
+.ui-helper-reset {\n
+\tmargin: 0;\n
+\tpadding: 0;\n
+\tborder: 0;\n
+\toutline: 0;\n
+\tline-height: 1.3;\n
+\ttext-decoration: none;\n
+\tfont-size: 100%;\n
+\tlist-style: none;\n
+}\n
+.ui-helper-clearfix:before,\n
+.ui-helper-clearfix:after {\n
+\tcontent: "";\n
+\tdisplay: table;\n
+\tborder-collapse: collapse;\n
+}\n
+.ui-helper-clearfix:after {\n
+\tclear: both;\n
+}\n
+.ui-helper-clearfix {\n
+\tmin-height: 0; /* support: IE7 */\n
+}\n
+.ui-helper-zfix {\n
+\twidth: 100%;\n
+\theight: 100%;\n
+\ttop: 0;\n
+\tleft: 0;\n
+\tposition: absolute;\n
+\topacity: 0;\n
+\tfilter:Alpha(Opacity=0);\n
+}\n
+\n
+.ui-front {\n
+\tz-index: 100;\n
+}\n
+\n
+\n
+/* Interaction Cues\n
+----------------------------------*/\n
+.ui-state-disabled {\n
+\tcursor: default !important;\n
+}\n
+\n
+\n
+/* Icons\n
+----------------------------------*/\n
+\n
+/* states and images */\n
+.ui-icon {\n
+\tdisplay: block;\n
+\ttext-indent: -99999px;\n
+\toverflow: hidden;\n
+\tbackground-repeat: no-repeat;\n
+}\n
+\n
+\n
+/* Misc visuals\n
+----------------------------------*/\n
+\n
+/* Overlays */\n
+.ui-widget-overlay {\n
+\tposition: fixed;\n
+\ttop: 0;\n
+\tleft: 0;\n
+\twidth: 100%;\n
+\theight: 100%;\n
+}\n
+.ui-accordion .ui-accordion-header {\n
+\tdisplay: block;\n
+\tcursor: pointer;\n
+\tposition: relative;\n
+\tmargin: 2px 0 0 0;\n
+\tpadding: .5em .5em .5em .7em;\n
+\tmin-height: 0; /* support: IE7 */\n
+\tfont-size: 100%;\n
+}\n
+.ui-accordion .ui-accordion-icons {\n
+\tpadding-left: 2.2em;\n
+}\n
+.ui-accordion .ui-accordion-icons .ui-accordion-icons {\n
+\tpadding-left: 2.2em;\n
+}\n
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon {\n
+\tposition: absolute;\n
+\tleft: .5em;\n
+\ttop: 50%;\n
+\tmargin-top: -8px;\n
+}\n
+.ui-accordion .ui-accordion-content {\n
+\tpadding: 1em 2.2em;\n
+\tborder-top: 0;\n
+\toverflow: auto;\n
+}\n
+.ui-autocomplete {\n
+\tposition: absolute;\n
+\ttop: 0;\n
+\tleft: 0;\n
+\tcursor: default;\n
+}\n
+.ui-button {\n
+\tdisplay: inline-block;\n
+\tposition: relative;\n
+\tpadding: 0;\n
+\tline-height: normal;\n
+\tmargin-right: .1em;\n
+\tcursor: pointer;\n
+\tvertical-align: middle;\n
+\ttext-align: center;\n
+\toverflow: visible; /* removes extra width in IE */\n
+}\n
+.ui-button,\n
+.ui-button:link,\n
+.ui-button:visited,\n
+.ui-button:hover,\n
+.ui-button:active {\n
+\ttext-decoration: none;\n
+}\n
+/* to make room for the icon, a width needs to be set here */\n
+.ui-button-icon-only {\n
+\twidth: 2.2em;\n
+}\n
+/* button elements seem to need a little more width */\n
+button.ui-button-icon-only {\n
+\twidth: 2.4em;\n
+}\n
+.ui-button-icons-only {\n
+\twidth: 3.4em;\n
+}\n
+button.ui-button-icons-only {\n
+\twidth: 3.7em;\n
+}\n
+\n
+/* button text element */\n
+.ui-button .ui-button-text {\n
+\tdisplay: block;\n
+\tline-height: normal;\n
+}\n
+.ui-button-text-only .ui-button-text {\n
+\tpadding: .4em 1em;\n
+}\n
+.ui-button-icon-only .ui-button-text,\n
+.ui-button-icons-only .ui-button-text {\n
+\tpadding: .4em;\n
+\ttext-indent: -9999999px;\n
+}\n
+.ui-button-text-icon-primary .ui-button-text,\n
+.ui-button-text-icons .ui-button-text {\n
+\tpadding: .4em 1em .4em 2.1em;\n
+}\n
+.ui-button-text-icon-secondary .ui-button-text,\n
+.ui-button-text-icons .ui-button-text {\n
+\tpadding: .4em 2.1em .4em 1em;\n
+}\n
+.ui-button-text-icons .ui-button-text {\n
+\tpadding-left: 2.1em;\n
+\tpadding-right: 2.1em;\n
+}\n
+/* no icon support for input elements, provide padding by default */\n
+input.ui-button {\n
+\tpadding: .4em 1em;\n
+}\n
+\n
+/* button icon element(s) */\n
+.ui-button-icon-only .ui-icon,\n
+.ui-button-text-icon-primary .ui-icon,\n
+.ui-button-text-icon-secondary .ui-icon,\n
+.ui-button-text-icons .ui-icon,\n
+.ui-button-icons-only .ui-icon {\n
+\tposition: absolute;\n
+\ttop: 50%;\n
+\tmargin-top: -8px;\n
+}\n
+.ui-button-icon-only .ui-icon {\n
+\tleft: 50%;\n
+\tmargin-left: -8px;\n
+}\n
+.ui-button-text-icon-primary .ui-button-icon-primary,\n
+.ui-button-text-icons .ui-button-icon-primary,\n
+.ui-button-icons-only .ui-button-icon-primary {\n
+\tleft: .5em;\n
+}\n
+.ui-button-text-icon-secondary .ui-button-icon-secondary,\n
+.ui-button-text-icons .ui-button-icon-secondary,\n
+.ui-button-icons-only .ui-button-icon-secondary {\n
+\tright: .5em;\n
+}\n
+\n
+/* button sets */\n
+.ui-buttonset {\n
+\tmargin-right: 7px;\n
+}\n
+.ui-buttonset .ui-button {\n
+\tmargin-left: 0;\n
+\tmargin-right: -.3em;\n
+}\n
+\n
+/* workarounds */\n
+/* reset extra padding in Firefox, see h5bp.com/l */\n
+input.ui-button::-moz-focus-inner,\n
+button.ui-button::-moz-focus-inner {\n
+\tborder: 0;\n
+\tpadding: 0;\n
+}\n
+.ui-datepicker {\n
+\twidth: 17em;\n
+\tpadding: .2em .2em 0;\n
+\tdisplay: none;\n
+}\n
+.ui-datepicker .ui-datepicker-header {\n
+\tposition: relative;\n
+\tpadding: .2em 0;\n
+}\n
+.ui-datepicker .ui-datepicker-prev,\n
+.ui-datepicker .ui-datepicker-next {\n
+\tposition: absolute;\n
+\ttop: 2px;\n
+\twidth: 1.8em;\n
+\theight: 1.8em;\n
+}\n
+.ui-datepicker .ui-datepicker-prev-hover,\n
+.ui-datepicker .ui-datepicker-next-hover {\n
+\ttop: 1px;\n
+}\n
+.ui-datepicker .ui-datepicker-prev {\n
+\tleft: 2px;\n
+}\n
+.ui-datepicker .ui-datepicker-next {\n
+\tright: 2px;\n
+}\n
+.ui-datepicker .ui-datepicker-prev-hover {\n
+\tleft: 1px;\n
+}\n
+.ui-datepicker .ui-datepicker-next-hover {\n
+\tright: 1px;\n
+}\n
+.ui-datepicker .ui-datepicker-prev span,\n
+.ui-datepicker .ui-datepicker-next span {\n
+\tdisplay: block;\n
+\tposition: absolute;\n
+\tleft: 50%;\n
+\tmargin-left: -8px;\n
+\ttop: 50%;\n
+\tmargin-top: -8px;\n
+}\n
+.ui-datepicker .ui-datepicker-title {\n
+\tmargin: 0 2.3em;\n
+\tline-height: 1.8em;\n
+\ttext-align: center;\n
+}\n
+.ui-datepicker .ui-datepicker-title select {\n
+\tfont-size: 1em;\n
+\tmargin: 1px 0;\n
+}\n
+.ui-datepicker select.ui-datepicker-month,\n
+.ui-datepicker select.ui-datepicker-year {\n
+\twidth: 49%;\n
+}\n
+.ui-datepicker table {\n
+\twidth: 100%;\n
+\tfont-size: .9em;\n
+\tborder-collapse: collapse;\n
+\tmargin: 0 0 .4em;\n
+}\n
+.ui-datepicker th {\n
+\tpadding: .7em .3em;\n
+\ttext-align: center;\n
+\tfont-weight: bold;\n
+\tborder: 0;\n
+}\n
+.ui-datepicker td {\n
+\tborder: 0;\n
+\tpadding: 1px;\n
+}\n
+.ui-datepicker td span,\n
+.ui-datepicker td a {\n
+\tdisplay: block;\n
+\tpadding: .2em;\n
+\ttext-align: right;\n
+\ttext-decoration: none;\n
+}\n
+.ui-datepicker .ui-datepicker-buttonpane {\n
+\tbackground-image: none;\n
+\tmargin: .7em 0 0 0;\n
+\tpadding: 0 .2em;\n
+\tborder-left: 0;\n
+\tborder-right: 0;\n
+\tborder-bottom: 0;\n
+}\n
+.ui-datepicker .ui-datepicker-buttonpane button {\n
+\tfloat: right;\n
+\tmargin: .5em .2em .4em;\n
+\tcursor: pointer;\n
+\tpadding: .2em .6em .3em .6em;\n
+\twidth: auto;\n
+\toverflow: visible;\n
+}\n
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {\n
+\tfloat: left;\n
+}\n
+\n
+/* with multiple calendars */\n
+.ui-datepicker.ui-datepicker-multi {\n
+\twidth: auto;\n
+}\n
+.ui-datepicker-multi .ui-datepicker-group {\n
+\tfloat: left;\n
+}\n
+.ui-datepicker-multi .ui-datepicker-group table {\n
+\twidth: 95%;\n
+\tmargin: 0 auto .4em;\n
+}\n
+.ui-datepicker-multi-2 .ui-datepicker-group {\n
+\twidth: 50%;\n
+}\n
+.ui-datepicker-multi-3 .ui-datepicker-group {\n
+\twidth: 33.3%;\n
+}\n
+.ui-datepicker-multi-4 .ui-datepicker-group {\n
+\twidth: 25%;\n
+}\n
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,\n
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {\n
+\tborder-left-width: 0;\n
+}\n
+.ui-datepicker-multi .ui-datepicker-buttonpane {\n
+\tclear: left;\n
+}\n
+.ui-datepicker-row-break {\n
+\tclear: both;\n
+\twidth: 100%;\n
+\tfont-size: 0;\n
+}\n
+\n
+/* RTL support */\n
+.ui-datepicker-rtl {\n
+\tdirection: rtl;\n
+}\n
+.ui-datepicker-rtl .ui-datepicker-prev {\n
+\tright: 2px;\n
+\tleft: auto;\n
+}\n
+.ui-datepicker-rtl .ui-datepicker-next {\n
+\tleft: 2px;\n
+\tright: auto;\n
+}\n
+.ui-datepicker-rtl .ui-datepicker-prev:hover {\n
+\tright: 1px;\n
+\tleft: auto;\n
+}\n
+.ui-datepicker-rtl .ui-datepicker-next:hover {\n
+\tleft: 1px;\n
+\tright: auto;\n
+}\n
+.ui-datepicker-rtl .ui-datepicker-buttonpane {\n
+\tclear: right;\n
+}\n
+.ui-datepicker-rtl .ui-datepicker-buttonpane button {\n
+\tfloat: left;\n
+}\n
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,\n
+.ui-datepicker-rtl .ui-datepicker-group {\n
+\tfloat: right;\n
+}\n
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,\n
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {\n
+\tborder-right-width: 0;\n
+\tborder-left-width: 1px;\n
+}\n
+.ui-dialog {\n
+\toverflow: hidden;\n
+\tposition: absolute;\n
+\ttop: 0;\n
+\tleft: 0;\n
+\tpadding: .2em;\n
+\toutline: 0;\n
+}\n
+.ui-dialog .ui-dialog-titlebar {\n
+\tpadding: .4em 1em;\n
+\tposition: relative;\n
+}\n
+.ui-dialog .ui-dialog-title {\n
+\tfloat: left;\n
+\tmargin: .1em 0;\n
+\twhite-space: nowrap;\n
+\twidth: 90%;\n
+\toverflow: hidden;\n
+\ttext-overflow: ellipsis;\n
+}\n
+.ui-dialog .ui-dialog-titlebar-close {\n
+\tposition: absolute;\n
+\tright: .3em;\n
+\ttop: 50%;\n
+\twidth: 20px;\n
+\tmargin: -10px 0 0 0;\n
+\tpadding: 1px;\n
+\theight: 20px;\n
+}\n
+.ui-dialog .ui-dialog-content {\n
+\tposition: relative;\n
+\tborder: 0;\n
+\tpadding: .5em 1em;\n
+\tbackground: none;\n
+\toverflow: auto;\n
+}\n
+.ui-dialog .ui-dialog-buttonpane {\n
+\ttext-align: left;\n
+\tborder-width: 1px 0 0 0;\n
+\tbackground-image: none;\n
+\tmargin-top: .5em;\n
+\tpadding: .3em 1em .5em .4em;\n
+}\n
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {\n
+\tfloat: right;\n
+}\n
+.ui-dialog .ui-dialog-buttonpane button {\n
+\tmargin: .5em .4em .5em 0;\n
+\tcursor: pointer;\n
+}\n
+.ui-dialog .ui-resizable-se {\n
+\twidth: 12px;\n
+\theight: 12px;\n
+\tright: -5px;\n
+\tbottom: -5px;\n
+\tbackground-position: 16px 16px;\n
+}\n
+.ui-draggable .ui-dialog-titlebar {\n
+\tcursor: move;\n
+}\n
+.ui-draggable-handle {\n
+\t-ms-touch-action: none;\n
+\ttouch-action: none;\n
+}\n
+.ui-menu {\n
+\tlist-style: none;\n
+\tpadding: 0;\n
+\tmargin: 0;\n
+\tdisplay: block;\n
+\toutline: none;\n
+}\n
+.ui-menu .ui-menu {\n
+\tposition: absolute;\n
+}\n
+.ui-menu .ui-menu-item {\n
+\tmargin: 0;\n
+\tdisplay: block;\n
+\tpadding: 3px .4em;\n
+\tcursor: pointer;\n
+\tmin-height: 0; /* support: IE7 */\n
+\t/* support: IE10, see #8844 */\n
+\tlist-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");\n
+}\n
+.ui-menu .ui-menu-divider {\n
+\tmargin: 5px 0;\n
+\theight: 0;\n
+\tfont-size: 0;\n
+\tline-height: 0;\n
+\tborder-width: 1px 0 0 0;\n
+}\n
+.ui-menu .ui-state-focus,\n
+.ui-menu .ui-state-active {\n
+\tmargin: -1px;\n
+}\n
+\n
+/* icon support */\n
+.ui-menu-icons {\n
+\tposition: relative;\n
+}\n
+.ui-menu-icons .ui-menu-item {\n
+\tposition: relative;\n
+\tpadding-left: 2em;\n
+}\n
+\n
+/* left-aligned */\n
+.ui-menu .ui-icon {\n
+\tposition: absolute;\n
+\ttop: .2em;\n
+\tleft: .2em;\n
+}\n
+\n
+/* right-aligned */\n
+.ui-menu .ui-menu-icon {\n
+\tposition: relative;\n
+\ttop: -.2em;\n
+\tfloat: right;\n
+}\n
+.ui-progressbar {\n
+\theight: 2em;\n
+\ttext-align: left;\n
+\toverflow: hidden;\n
+}\n
+.ui-progressbar .ui-progressbar-value {\n
+\tmargin: -1px;\n
+\theight: 100%;\n
+}\n
+.ui-progressbar .ui-progressbar-overlay {\n
+\tbackground: url("images/animated-overlay.gif");\n
+\theight: 100%;\n
+\tfilter: alpha(opacity=25);\n
+\topacity: 0.25;\n
+}\n
+.ui-progressbar-indeterminate .ui-progressbar-value {\n
+\tbackground-image: none;\n
+}\n
+.ui-resizable {\n
+\tposition: relative;\n
+}\n
+.ui-resizable-handle {\n
+\tposition: absolute;\n
+\tfont-size: 0.1px;\n
+\tdisplay: block;\n
+\t-ms-touch-action: none;\n
+\ttouch-action: none;\n
+}\n
+.ui-resizable-disabled .ui-resizable-handle,\n
+.ui-resizable-autohide .ui-resizable-handle {\n
+\tdisplay: none;\n
+}\n
+.ui-resizable-n {\n
+\tcursor: n-resize;\n
+\theight: 7px;\n
+\twidth: 100%;\n
+\ttop: -5px;\n
+\tleft: 0;\n
+}\n
+.ui-resizable-s {\n
+\tcursor: s-resize;\n
+\theight: 7px;\n
+\twidth: 100%;\n
+\tbottom: -5px;\n
+\tleft: 0;\n
+}\n
+.ui-resizable-e {\n
+\tcursor: e-resize;\n
+\twidth: 7px;\n
+\tright: -5px;\n
+\ttop: 0;\n
+\theight: 100%;\n
+}\n
+.ui-resizable-w {\n
+\tcursor: w-resize;\n
+\twidth: 7px;\n
+\tleft: -5px;\n
+\ttop: 0;\n
+\theight: 100%;\n
+}\n
+.ui-resizable-se {\n
+\tcursor: se-resize;\n
+\twidth: 12px;\n
+\theight: 12px;\n
+\tright: 1px;\n
+\tbottom: 1px;\n
+}\n
+.ui-resizable-sw {\n
+\tcursor: sw-resize;\n
+\twidth: 9px;\n
+\theight: 9px;\n
+\tleft: -5px;\n
+\tbottom: -5px;\n
+}\n
+.ui-resizable-nw {\n
+\tcursor: nw-resize;\n
+\twidth: 9px;\n
+\theight: 9px;\n
+\tleft: -5px;\n
+\ttop: -5px;\n
+}\n
+.ui-resizable-ne {\n
+\tcursor: ne-resize;\n
+\twidth: 9px;\n
+\theight: 9px;\n
+\tright: -5px;\n
+\ttop: -5px;\n
+}\n
+.ui-selectable {\n
+\t-ms-touch-action: none;\n
+\ttouch-action: none;\n
+}\n
+.ui-selectable-helper {\n
+\tposition: absolute;\n
+\tz-index: 100;\n
+\tborder: 1px dotted black;\n
+}\n
+.ui-slider {\n
+\tposition: relative;\n
+\ttext-align: left;\n
+}\n
+.ui-slider .ui-slider-handle {\n
+\tposition: absolute;\n
+\tz-index: 2;\n
+\twidth: 1.2em;\n
+\theight: 1.2em;\n
+\tcursor: default;\n
+\t-ms-touch-action: none;\n
+\ttouch-action: none;\n
+}\n
+.ui-slider .ui-slider-range {\n
+\tposition: absolute;\n
+\tz-index: 1;\n
+\tfont-size: .7em;\n
+\tdisplay: block;\n
+\tborder: 0;\n
+\tbackground-position: 0 0;\n
+}\n
+\n
+/* For IE8 - See #6727 */\n
+.ui-slider.ui-state-disabled .ui-slider-handle,\n
+.ui-slider.ui-state-disabled .ui-slider-range {\n
+\tfilter: inherit;\n
+}\n
+\n
+.ui-slider-horizontal {\n
+\theight: .8em;\n
+}\n
+.ui-slider-horizontal .ui-slider-handle {\n
+\ttop: -.3em;\n
+\tmargin-left: -.6em;\n
+}\n
+.ui-slider-horizontal .ui-slider-range {\n
+\ttop: 0;\n
+\theight: 100%;\n
+}\n
+.ui-slider-horizontal .ui-slider-range-min {\n
+\tleft: 0;\n
+}\n
+.ui-slider-horizontal .ui-slider-range-max {\n
+\tright: 0;\n
+}\n
+\n
+.ui-slider-vertical {\n
+\twidth: .8em;\n
+\theight: 100px;\n
+}\n
+.ui-slider-vertical .ui-slider-handle {\n
+\tleft: -.3em;\n
+\tmargin-left: 0;\n
+\tmargin-bottom: -.6em;\n
+}\n
+.ui-slider-vertical .ui-slider-range {\n
+\tleft: 0;\n
+\twidth: 100%;\n
+}\n
+.ui-slider-vertical .ui-slider-range-min {\n
+\tbottom: 0;\n
+}\n
+.ui-slider-vertical .ui-slider-range-max {\n
+\ttop: 0;\n
+}\n
+.ui-sortable-handle {\n
+\t-ms-touch-action: none;\n
+\ttouch-action: none;\n
+}\n
+.ui-spinner {\n
+\tposition: relative;\n
+\tdisplay: inline-block;\n
+\toverflow: hidden;\n
+\tpadding: 0;\n
+\tvertical-align: middle;\n
+}\n
+.ui-spinner-input {\n
+\tborder: none;\n
+\tbackground: none;\n
+\tcolor: inherit;\n
+\tpadding: 0;\n
+\tmargin: .2em 0;\n
+\tvertical-align: middle;\n
+\tmargin-left: .4em;\n
+\tmargin-right: 22px;\n
+}\n
+.ui-spinner-button {\n
+\twidth: 16px;\n
+\theight: 50%;\n
+\tfont-size: .5em;\n
+\tpadding: 0;\n
+\tmargin: 0;\n
+\ttext-align: center;\n
+\tposition: absolute;\n
+\tcursor: default;\n
+\tdisplay: block;\n
+\toverflow: hidden;\n
+\tright: 0;\n
+}\n
+/* more specificity required here to override default borders */\n
+.ui-spinner a.ui-spinner-button {\n
+\tborder-top: none;\n
+\tborder-bottom: none;\n
+\tborder-right: none;\n
+}\n
+/* vertically center icon */\n
+.ui-spinner .ui-icon {\n
+\tposition: absolute;\n
+\tmargin-top: -8px;\n
+\ttop: 50%;\n
+\tleft: 0;\n
+}\n
+.ui-spinner-up {\n
+\ttop: 0;\n
+}\n
+.ui-spinner-down {\n
+\tbottom: 0;\n
+}\n
+\n
+/* TR overrides */\n
+.ui-spinner .ui-icon-triangle-1-s {\n
+\t/* need to fix icons sprite */\n
+\tbackground-position: -65px -16px;\n
+}\n
+.ui-tabs {\n
+\tposition: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */\n
+\tpadding: .2em;\n
+}\n
+.ui-tabs .ui-tabs-nav {\n
+\tmargin: 0;\n
+\tpadding: .2em .2em 0;\n
+}\n
+.ui-tabs .ui-tabs-nav li {\n
+\tlist-style: none;\n
+\tfloat: left;\n
+\tposition: relative;\n
+\ttop: 0;\n
+\tmargin: 1px .2em 0 0;\n
+\tborder-bottom-width: 0;\n
+\tpadding: 0;\n
+\twhite-space: nowrap;\n
+}\n
+.ui-tabs .ui-tabs-nav .ui-tabs-anchor {\n
+\tfloat: left;\n
+\tpadding: .5em 1em;\n
+\ttext-decoration: none;\n
+}\n
+.ui-tabs .ui-tabs-nav li.ui-tabs-active {\n
+\tmargin-bottom: -1px;\n
+\tpadding-bottom: 1px;\n
+}\n
+.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,\n
+.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,\n
+.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {\n
+\tcursor: text;\n
+}\n
+.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {\n
+\tcursor: pointer;\n
+}\n
+.ui-tabs .ui-tabs-panel {\n
+\tdisplay: block;\n
+\tborder-width: 0;\n
+\tpadding: 1em 1.4em;\n
+\tbackground: none;\n
+}\n
+.ui-tooltip {\n
+\tpadding: 8px;\n
+\tposition: absolute;\n
+\tz-index: 9999;\n
+\tmax-width: 300px;\n
+\t-webkit-box-shadow: 0 0 5px #aaa;\n
+\tbox-shadow: 0 0 5px #aaa;\n
+}\n
+body .ui-tooltip {\n
+\tborder-width: 2px;\n
+}\n
+\n
+/* Component containers\n
+----------------------------------*/\n
+.ui-widget {\n
+\tfont-family: Verdana,Arial,sans-serif/*{ffDefault}*/;\n
+\tfont-size: 1.1em/*{fsDefault}*/;\n
+}\n
+.ui-widget .ui-widget {\n
+\tfont-size: 1em;\n
+}\n
+.ui-widget input,\n
+.ui-widget select,\n
+.ui-widget textarea,\n
+.ui-widget button {\n
+\tfont-family: Verdana,Arial,sans-serif/*{ffDefault}*/;\n
+\tfont-size: 1em;\n
+}\n
+.ui-widget-content {\n
+\tborder: 1px solid #aaaaaa/*{borderColorContent}*/;\n
+\tbackground: #ffffff/*{bgColorContent}*/ url("images/ui-bg_flat_75_ffffff_40x100.png")/*{bgImgUrlContent}*/ 50%/*{bgContentXPos}*/ 50%/*{bgContentYPos}*/ repeat-x/*{bgContentRepeat}*/;\n
+\tcolor: #222222/*{fcContent}*/;\n
+}\n
+.ui-widget-content a {\n
+\tcolor: #222222/*{fcContent}*/;\n
+}\n
+.ui-widget-header {\n
+\tborder: 1px solid #aaaaaa/*{borderColorHeader}*/;\n
+\tbackground: #cccccc/*{bgColorHeader}*/ url("images/ui-bg_highlight-soft_75_cccccc_1x100.png")/*{bgImgUrlHeader}*/ 50%/*{bgHeaderXPos}*/ 50%/*{bgHeaderYPos}*/ repeat-x/*{bgHeaderRepeat}*/;\n
+\tcolor: #222222/*{fcHeader}*/;\n
+\tfont-weight: bold;\n
+}\n
+.ui-widget-header a {\n
+\tcolor: #222222/*{fcHeader}*/;\n
+}\n
+\n
+/* Interaction states\n
+----------------------------------*/\n
+.ui-state-default,\n
+.ui-widget-content .ui-state-default,\n
+.ui-widget-header .ui-state-default {\n
+\tborder: 1px solid #d3d3d3/*{borderColorDefault}*/;\n
+\tbackground: #e6e6e6/*{bgColorDefault}*/ url("images/ui-bg_glass_75_e6e6e6_1x400.png")/*{bgImgUrlDefault}*/ 50%/*{bgDefaultXPos}*/ 50%/*{bgDefaultYPos}*/ repeat-x/*{bgDefaultRepeat}*/;\n
+\tfont-weight: normal/*{fwDefault}*/;\n
+\tcolor: #555555/*{fcDefault}*/;\n
+}\n
+.ui-state-default a,\n
+.ui-state-default a:link,\n
+.ui-state-default a:visited {\n
+\tcolor: #555555/*{fcDefault}*/;\n
+\ttext-decoration: none;\n
+}\n
+.ui-state-hover,\n
+.ui-widget-content .ui-state-hover,\n
+.ui-widget-header .ui-state-hover,\n
+.ui-state-focus,\n
+.ui-widget-content .ui-state-focus,\n
+.ui-widget-header .ui-state-focus {\n
+\tborder: 1px solid #999999/*{borderColorHover}*/;\n
+\tbackground: #dadada/*{bgColorHover}*/ url("images/ui-bg_glass_75_dadada_1x400.png")/*{bgImgUrlHover}*/ 50%/*{bgHoverXPos}*/ 50%/*{bgHoverYPos}*/ repeat-x/*{bgHoverRepeat}*/;\n
+\tfont-weight: normal/*{fwDefault}*/;\n
+\tcolor: #212121/*{fcHover}*/;\n
+}\n
+.ui-state-hover a,\n
+.ui-state-hover a:hover,\n
+.ui-state-hover a:link,\n
+.ui-state-hover a:visited,\n
+.ui-state-focus a,\n
+.ui-state-focus a:hover,\n
+.ui-state-focus a:link,\n
+.ui-state-focus a:visited {\n
+\tcolor: #212121/*{fcHover}*/;\n
+\ttext-decoration: none;\n
+}\n
+.ui-state-active,\n
+.ui-widget-content .ui-state-active,\n
+.ui-widget-header .ui-state-active {\n
+\tborder: 1px solid #aaaaaa/*{borderColorActive}*/;\n
+\tbackground: #ffffff/*{bgColorActive}*/ url("images/ui-bg_glass_65_ffffff_1x400.png")/*{bgImgUrlActive}*/ 50%/*{bgActiveXPos}*/ 50%/*{bgActiveYPos}*/ repeat-x/*{bgActiveRepeat}*/;\n
+\tfont-weight: normal/*{fwDefault}*/;\n
+\tcolor: #212121/*{fcActive}*/;\n
+}\n
+.ui-state-active a,\n
+.ui-state-active a:link,\n
+.ui-state-active a:visited {\n
+\tcolor: #212121/*{fcActive}*/;\n
+\ttext-decoration: none;\n
+}\n
+\n
+/* Interaction Cues\n
+----------------------------------*/\n
+.ui-state-highlight,\n
+.ui-widget-content .ui-state-highlight,\n
+.ui-widget-header .ui-state-highlight {\n
+\tborder: 1px solid #fcefa1/*{borderColorHighlight}*/;\n
+\tbackground: #fbf9ee/*{bgColorHighlight}*/ url("images/ui-bg_glass_55_fbf9ee_1x400.png")/*{bgImgUrlHighlight}*/ 50%/*{bgHighlightXPos}*/ 50%/*{bgHighlightYPos}*/ repeat-x/*{bgHighlightRepeat}*/;\n
+\tcolor: #363636/*{fcHighlight}*/;\n
+}\n
+.ui-state-highlight a,\n
+.ui-widget-content .ui-state-highlight a,\n
+.ui-widget-header .ui-state-highlight a {\n
+\tcolor: #363636/*{fcHighlight}*/;\n
+}\n
+.ui-state-error,\n
+.ui-widget-content .ui-state-error,\n
+.ui-widget-header .ui-state-error {\n
+\tborder: 1px solid #cd0a0a/*{borderColorError}*/;\n
+\tbackground: #fef1ec/*{bgColorError}*/ url("images/ui-bg_glass_95_fef1ec_1x400.png")/*{bgImgUrlError}*/ 50%/*{bgErrorXPos}*/ 50%/*{bgErrorYPos}*/ repeat-x/*{bgErrorRepeat}*/;\n
+\tcolor: #cd0a0a/*{fcError}*/;\n
+}\n
+.ui-state-error a,\n
+.ui-widget-content .ui-state-error a,\n
+.ui-widget-header .ui-state-error a {\n
+\tcolor: #cd0a0a/*{fcError}*/;\n
+}\n
+.ui-state-error-text,\n
+.ui-widget-content .ui-state-error-text,\n
+.ui-widget-header .ui-state-error-text {\n
+\tcolor: #cd0a0a/*{fcError}*/;\n
+}\n
+.ui-priority-primary,\n
+.ui-widget-content .ui-priority-primary,\n
+.ui-widget-header .ui-priority-primary {\n
+\tfont-weight: bold;\n
+}\n
+.ui-priority-secondary,\n
+.ui-widget-content .ui-priority-secondary,\n
+.ui-widget-header .ui-priority-secondary {\n
+\topacity: .7;\n
+\tfilter:Alpha(Opacity=70);\n
+\tfont-weight: normal;\n
+}\n
+.ui-state-disabled,\n
+.ui-widget-content .ui-state-disabled,\n
+.ui-widget-header .ui-state-disabled {\n
+\topacity: .35;\n
+\tfilter:Alpha(Opacity=35);\n
+\tbackground-image: none;\n
+}\n
+.ui-state-disabled .ui-icon {\n
+\tfilter:Alpha(Opacity=35); /* For IE8 - See #6059 */\n
+}\n
+\n
+/* Icons\n
+----------------------------------*/\n
+\n
+/* states and images */\n
+.ui-icon {\n
+\twidth: 16px;\n
+\theight: 16px;\n
+}\n
+.ui-icon,\n
+.ui-widget-content .ui-icon {\n
+\tbackground-image: url("images/ui-icons_222222_256x240.png")/*{iconsContent}*/;\n
+}\n
+.ui-widget-header .ui-icon {\n
+\tbackground-image: url("images/ui-icons_222222_256x240.png")/*{iconsHeader}*/;\n
+}\n
+.ui-state-default .ui-icon {\n
+\tbackground-image: url("images/ui-icons_888888_256x240.png")/*{iconsDefault}*/;\n
+}\n
+.ui-state-hover .ui-icon,\n
+.ui-state-focus .ui-icon {\n
+\tbackground-image: url("images/ui-icons_454545_256x240.png")/*{iconsHover}*/;\n
+}\n
+.ui-state-active .ui-icon {\n
+\tbackground-image: url("images/ui-icons_454545_256x240.png")/*{iconsActive}*/;\n
+}\n
+.ui-state-highlight .ui-icon {\n
+\tbackground-image: url("images/ui-icons_2e83ff_256x240.png")/*{iconsHighlight}*/;\n
+}\n
+.ui-state-error .ui-icon,\n
+.ui-state-error-text .ui-icon {\n
+\tbackground-image: url("images/ui-icons_cd0a0a_256x240.png")/*{iconsError}*/;\n
+}\n
+\n
+/* positioning */\n
+.ui-icon-blank { background-position: 16px 16px; }\n
+.ui-icon-carat-1-n { background-position: 0 0; }\n
+.ui-icon-carat-1-ne { background-position: -16px 0; }\n
+.ui-icon-carat-1-e { background-position: -32px 0; }\n
+.ui-icon-carat-1-se { background-position: -48px 0; }\n
+.ui-icon-carat-1-s { background-position: -64px 0; }\n
+.ui-icon-carat-1-sw { background-position: -80px 0; }\n
+.ui-icon-carat-1-w { background-position: -96px 0; }\n
+.ui-icon-carat-1-nw { background-position: -112px 0; }\n
+.ui-icon-carat-2-n-s { background-position: -128px 0; }\n
+.ui-icon-carat-2-e-w { background-position: -144px 0; }\n
+.ui-icon-triangle-1-n { background-position: 0 -16px; }\n
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }\n
+.ui-icon-triangle-1-e { background-position: -32px -16px; }\n
+.ui-icon-triangle-1-se { background-position: -48px -16px; }\n
+.ui-icon-triangle-1-s { background-position: -64px -16px; }\n
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }\n
+.ui-icon-triangle-1-w { background-position: -96px -16px; }\n
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }\n
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }\n
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }\n
+.ui-icon-arrow-1-n { background-position: 0 -32px; }\n
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }\n
+.ui-icon-arrow-1-e { background-position: -32px -32px; }\n
+.ui-icon-arrow-1-se { background-position: -48px -32px; }\n
+.ui-icon-arrow-1-s { background-position: -64px -32px; }\n
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }\n
+.ui-icon-arrow-1-w { background-position: -96px -32px; }\n
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }\n
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }\n
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }\n
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }\n
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }\n
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }\n
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }\n
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }\n
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }\n
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }\n
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }\n
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }\n
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }\n
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }\n
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }\n
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }\n
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }\n
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }\n
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }\n
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }\n
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }\n
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }\n
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }\n
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }\n
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }\n
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }\n
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }\n
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }\n
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }\n
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }\n
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }\n
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }\n
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }\n
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }\n
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }\n
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }\n
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }\n
+.ui-icon-arrow-4 { background-position: 0 -80px; }\n
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }\n
+.ui-icon-extlink { background-position: -32px -80px; }\n
+.ui-icon-newwin { background-position: -48px -80px; }\n
+.ui-icon-refresh { background-position: -64px -80px; }\n
+.ui-icon-shuffle { background-position: -80px -80px; }\n
+.ui-icon-transfer-e-w { background-position: -96px -80px; }\n
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }\n
+.ui-icon-folder-collapsed { background-position: 0 -96px; }\n
+.ui-icon-folder-open { background-position: -16px -96px; }\n
+.ui-icon-document { background-position: -32px -96px; }\n
+.ui-icon-document-b { background-position: -48px -96px; }\n
+.ui-icon-note { background-position: -64px -96px; }\n
+.ui-icon-mail-closed { background-position: -80px -96px; }\n
+.ui-icon-mail-open { background-position: -96px -96px; }\n
+.ui-icon-suitcase { background-position: -112px -96px; }\n
+.ui-icon-comment { background-position: -128px -96px; }\n
+.ui-icon-person { background-position: -144px -96px; }\n
+.ui-icon-print { background-position: -160px -96px; }\n
+.ui-icon-trash { background-position: -176px -96px; }\n
+.ui-icon-locked { background-position: -192px -96px; }\n
+.ui-icon-unlocked { background-position: -208px -96px; }\n
+.ui-icon-bookmark { background-position: -224px -96px; }\n
+.ui-icon-tag { background-position: -240px -96px; }\n
+.ui-icon-home { background-position: 0 -112px; }\n
+.ui-icon-flag { background-position: -16px -112px; }\n
+.ui-icon-calendar { background-position: -32px -112px; }\n
+.ui-icon-cart { background-position: -48px -112px; }\n
+.ui-icon-pencil { background-position: -64px -112px; }\n
+.ui-icon-clock { background-position: -80px -112px; }\n
+.ui-icon-disk { background-position: -96px -112px; }\n
+.ui-icon-calculator { background-position: -112px -112px; }\n
+.ui-icon-zoomin { background-position: -128px -112px; }\n
+.ui-icon-zoomout { background-position: -144px -112px; }\n
+.ui-icon-search { background-position: -160px -112px; }\n
+.ui-icon-wrench { background-position: -176px -112px; }\n
+.ui-icon-gear { background-position: -192px -112px; }\n
+.ui-icon-heart { background-position: -208px -112px; }\n
+.ui-icon-star { background-position: -224px -112px; }\n
+.ui-icon-link { background-position: -240px -112px; }\n
+.ui-icon-cancel { background-position: 0 -128px; }\n
+.ui-icon-plus { background-position: -16px -128px; }\n
+.ui-icon-plusthick { background-position: -32px -128px; }\n
+.ui-icon-minus { background-position: -48px -128px; }\n
+.ui-icon-minusthick { background-position: -64px -128px; }\n
+.ui-icon-close { background-position: -80px -128px; }\n
+.ui-icon-closethick { background-position: -96px -128px; }\n
+.ui-icon-key { background-position: -112px -128px; }\n
+.ui-icon-lightbulb { background-position: -128px -128px; }\n
+.ui-icon-scissors { background-position: -144px -128px; }\n
+.ui-icon-clipboard { background-position: -160px -128px; }\n
+.ui-icon-copy { background-position: -176px -128px; }\n
+.ui-icon-contact { background-position: -192px -128px; }\n
+.ui-icon-image { background-position: -208px -128px; }\n
+.ui-icon-video { background-position: -224px -128px; }\n
+.ui-icon-script { background-position: -240px -128px; }\n
+.ui-icon-alert { background-position: 0 -144px; }\n
+.ui-icon-info { background-position: -16px -144px; }\n
+.ui-icon-notice { background-position: -32px -144px; }\n
+.ui-icon-help { background-position: -48px -144px; }\n
+.ui-icon-check { background-position: -64px -144px; }\n
+.ui-icon-bullet { background-position: -80px -144px; }\n
+.ui-icon-radio-on { background-position: -96px -144px; }\n
+.ui-icon-radio-off { background-position: -112px -144px; }\n
+.ui-icon-pin-w { background-position: -128px -144px; }\n
+.ui-icon-pin-s { background-position: -144px -144px; }\n
+.ui-icon-play { background-position: 0 -160px; }\n
+.ui-icon-pause { background-position: -16px -160px; }\n
+.ui-icon-seek-next { background-position: -32px -160px; }\n
+.ui-icon-seek-prev { background-position: -48px -160px; }\n
+.ui-icon-seek-end { background-position: -64px -160px; }\n
+.ui-icon-seek-start { background-position: -80px -160px; }\n
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */\n
+.ui-icon-seek-first { background-position: -80px -160px; }\n
+.ui-icon-stop { background-position: -96px -160px; }\n
+.ui-icon-eject { background-position: -112px -160px; }\n
+.ui-icon-volume-off { background-position: -128px -160px; }\n
+.ui-icon-volume-on { background-position: -144px -160px; }\n
+.ui-icon-power { background-position: 0 -176px; }\n
+.ui-icon-signal-diag { background-position: -16px -176px; }\n
+.ui-icon-signal { background-position: -32px -176px; }\n
+.ui-icon-battery-0 { background-position: -48px -176px; }\n
+.ui-icon-battery-1 { background-position: -64px -176px; }\n
+.ui-icon-battery-2 { background-position: -80px -176px; }\n
+.ui-icon-battery-3 { background-position: -96px -176px; }\n
+.ui-icon-circle-plus { background-position: 0 -192px; }\n
+.ui-icon-circle-minus { background-position: -16px -192px; }\n
+.ui-icon-circle-close { background-position: -32px -192px; }\n
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }\n
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }\n
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }\n
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }\n
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }\n
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }\n
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }\n
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }\n
+.ui-icon-circle-zoomin { background-position: -176px -192px; }\n
+.ui-icon-circle-zoomout { background-position: -192px -192px; }\n
+.ui-icon-circle-check { background-position: -208px -192px; }\n
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }\n
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }\n
+.ui-icon-circlesmall-close { background-position: -32px -208px; }\n
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }\n
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }\n
+.ui-icon-squaresmall-close { background-position: -80px -208px; }\n
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }\n
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }\n
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }\n
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }\n
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }\n
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }\n
+\n
+\n
+/* Misc visuals\n
+----------------------------------*/\n
+\n
+/* Corner radius */\n
+.ui-corner-all,\n
+.ui-corner-top,\n
+.ui-corner-left,\n
+.ui-corner-tl {\n
+\tborder-top-left-radius: 4px/*{cornerRadius}*/;\n
+}\n
+.ui-corner-all,\n
+.ui-corner-top,\n
+.ui-corner-right,\n
+.ui-corner-tr {\n
+\tborder-top-right-radius: 4px/*{cornerRadius}*/;\n
+}\n
+.ui-corner-all,\n
+.ui-corner-bottom,\n
+.ui-corner-left,\n
+.ui-corner-bl {\n
+\tborder-bottom-left-radius: 4px/*{cornerRadius}*/;\n
+}\n
+.ui-corner-all,\n
+.ui-corner-bottom,\n
+.ui-corner-right,\n
+.ui-corner-br {\n
+\tborder-bottom-right-radius: 4px/*{cornerRadius}*/;\n
+}\n
+\n
+/* Overlays */\n
+.ui-widget-overlay {\n
+\tbackground: #aaaaaa/*{bgColorOverlay}*/ url("images/ui-bg_flat_0_aaaaaa_40x100.png")/*{bgImgUrlOverlay}*/ 50%/*{bgOverlayXPos}*/ 50%/*{bgOverlayYPos}*/ repeat-x/*{bgOverlayRepeat}*/;\n
+\topacity: .3/*{opacityOverlay}*/;\n
+\tfilter: Alpha(Opacity=30)/*{opacityFilterOverlay}*/;\n
+}\n
+.ui-widget-shadow {\n
+\tmargin: -8px/*{offsetTopShadow}*/ 0 0 -8px/*{offsetLeftShadow}*/;\n
+\tpadding: 8px/*{thicknessShadow}*/;\n
+\tbackground: #aaaaaa/*{bgColorShadow}*/ url("images/ui-bg_flat_0_aaaaaa_40x100.png")/*{bgImgUrlShadow}*/ 50%/*{bgShadowXPos}*/ 50%/*{bgShadowYPos}*/ repeat-x/*{bgShadowRepeat}*/;\n
+\topacity: .3/*{opacityShadow}*/;\n
+\tfilter: Alpha(Opacity=30)/*{opacityFilterShadow}*/;\n
+\tborder-radius: 8px/*{cornerRadiusShadow}*/;\n
+}\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>32251</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery-ui.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery-ui.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..702c54eb0092215bf9d9c85f982d686f469fe56c
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery-ui.js.xml
@@ -0,0 +1,15188 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681769.86</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jquery-ui.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>436715</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*! jQuery UI - v1.10.4 - 2014-01-17\n
+* http://jqueryui.com\n
+* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.effect.js, jquery.ui.effect-blind.js, jquery.ui.effect-bounce.js, jquery.ui.effect-clip.js, jquery.ui.effect-drop.js, jquery.ui.effect-explode.js, jquery.ui.effect-fade.js, jquery.ui.effect-fold.js, jquery.ui.effect-highlight.js, jquery.ui.effect-pulsate.js, jquery.ui.effect-scale.js, jquery.ui.effect-shake.js, jquery.ui.effect-slide.js, jquery.ui.effect-transfer.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.slider.js, jquery.ui.sortable.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.js\n
+* Copyright 2014 jQuery Foundation and other contributors; Licensed MIT */\n
+\n
+(function( $, undefined ) {\n
+\n
+var uuid = 0,\n
+\truniqueId = /^ui-id-\\d+$/;\n
+\n
+// $.ui might exist from components with no dependencies, e.g., $.ui.position\n
+$.ui = $.ui || {};\n
+\n
+$.extend( $.ui, {\n
+\tversion: "1.10.4",\n
+\n
+\tkeyCode: {\n
+\t\tBACKSPACE: 8,\n
+\t\tCOMMA: 188,\n
+\t\tDELETE: 46,\n
+\t\tDOWN: 40,\n
+\t\tEND: 35,\n
+\t\tENTER: 13,\n
+\t\tESCAPE: 27,\n
+\t\tHOME: 36,\n
+\t\tLEFT: 37,\n
+\t\tNUMPAD_ADD: 107,\n
+\t\tNUMPAD_DECIMAL: 110,\n
+\t\tNUMPAD_DIVIDE: 111,\n
+\t\tNUMPAD_ENTER: 108,\n
+\t\tNUMPAD_MULTIPLY: 106,\n
+\t\tNUMPAD_SUBTRACT: 109,\n
+\t\tPAGE_DOWN: 34,\n
+\t\tPAGE_UP: 33,\n
+\t\tPERIOD: 190,\n
+\t\tRIGHT: 39,\n
+\t\tSPACE: 32,\n
+\t\tTAB: 9,\n
+\t\tUP: 38\n
+\t}\n
+});\n
+\n
+// plugins\n
+$.fn.extend({\n
+\tfocus: (function( orig ) {\n
+\t\treturn function( delay, fn ) {\n
+\t\t\treturn typeof delay === "number" ?\n
+\t\t\t\tthis.each(function() {\n
+\t\t\t\t\tvar elem = this;\n
+\t\t\t\t\tsetTimeout(function() {\n
+\t\t\t\t\t\t$( elem ).focus();\n
+\t\t\t\t\t\tif ( fn ) {\n
+\t\t\t\t\t\t\tfn.call( elem );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}, delay );\n
+\t\t\t\t}) :\n
+\t\t\t\torig.apply( this, arguments );\n
+\t\t};\n
+\t})( $.fn.focus ),\n
+\n
+\tscrollParent: function() {\n
+\t\tvar scrollParent;\n
+\t\tif (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {\n
+\t\t\tscrollParent = this.parents().filter(function() {\n
+\t\t\t\treturn (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));\n
+\t\t\t}).eq(0);\n
+\t\t} else {\n
+\t\t\tscrollParent = this.parents().filter(function() {\n
+\t\t\t\treturn (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));\n
+\t\t\t}).eq(0);\n
+\t\t}\n
+\n
+\t\treturn (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;\n
+\t},\n
+\n
+\tzIndex: function( zIndex ) {\n
+\t\tif ( zIndex !== undefined ) {\n
+\t\t\treturn this.css( "zIndex", zIndex );\n
+\t\t}\n
+\n
+\t\tif ( this.length ) {\n
+\t\t\tvar elem = $( this[ 0 ] ), position, value;\n
+\t\t\twhile ( elem.length && elem[ 0 ] !== document ) {\n
+\t\t\t\t// Ignore z-index if position is set to a value where z-index is ignored by the browser\n
+\t\t\t\t// This makes behavior of this function consistent across browsers\n
+\t\t\t\t// WebKit always returns auto if the element is positioned\n
+\t\t\t\tposition = elem.css( "position" );\n
+\t\t\t\tif ( position === "absolute" || position === "relative" || position === "fixed" ) {\n
+\t\t\t\t\t// IE returns 0 when zIndex is not specified\n
+\t\t\t\t\t// other browsers return a string\n
+\t\t\t\t\t// we ignore the case of nested elements with an explicit value of 0\n
+\t\t\t\t\t// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>\n
+\t\t\t\t\tvalue = parseInt( elem.css( "zIndex" ), 10 );\n
+\t\t\t\t\tif ( !isNaN( value ) && value !== 0 ) {\n
+\t\t\t\t\t\treturn value;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\telem = elem.parent();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn 0;\n
+\t},\n
+\n
+\tuniqueId: function() {\n
+\t\treturn this.each(function() {\n
+\t\t\tif ( !this.id ) {\n
+\t\t\t\tthis.id = "ui-id-" + (++uuid);\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\tremoveUniqueId: function() {\n
+\t\treturn this.each(function() {\n
+\t\t\tif ( runiqueId.test( this.id ) ) {\n
+\t\t\t\t$( this ).removeAttr( "id" );\n
+\t\t\t}\n
+\t\t});\n
+\t}\n
+});\n
+\n
+// selectors\n
+function focusable( element, isTabIndexNotNaN ) {\n
+\tvar map, mapName, img,\n
+\t\tnodeName = element.nodeName.toLowerCase();\n
+\tif ( "area" === nodeName ) {\n
+\t\tmap = element.parentNode;\n
+\t\tmapName = map.name;\n
+\t\tif ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\timg = $( "img[usemap=#" + mapName + "]" )[0];\n
+\t\treturn !!img && visible( img );\n
+\t}\n
+\treturn ( /input|select|textarea|button|object/.test( nodeName ) ?\n
+\t\t!element.disabled :\n
+\t\t"a" === nodeName ?\n
+\t\t\telement.href || isTabIndexNotNaN :\n
+\t\t\tisTabIndexNotNaN) &&\n
+\t\t// the element and all of its ancestors must be visible\n
+\t\tvisible( element );\n
+}\n
+\n
+function visible( element ) {\n
+\treturn $.expr.filters.visible( element ) &&\n
+\t\t!$( element ).parents().addBack().filter(function() {\n
+\t\t\treturn $.css( this, "visibility" ) === "hidden";\n
+\t\t}).length;\n
+}\n
+\n
+$.extend( $.expr[ ":" ], {\n
+\tdata: $.expr.createPseudo ?\n
+\t\t$.expr.createPseudo(function( dataName ) {\n
+\t\t\treturn function( elem ) {\n
+\t\t\t\treturn !!$.data( elem, dataName );\n
+\t\t\t};\n
+\t\t}) :\n
+\t\t// support: jQuery <1.8\n
+\t\tfunction( elem, i, match ) {\n
+\t\t\treturn !!$.data( elem, match[ 3 ] );\n
+\t\t},\n
+\n
+\tfocusable: function( element ) {\n
+\t\treturn focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );\n
+\t},\n
+\n
+\ttabbable: function( element ) {\n
+\t\tvar tabIndex = $.attr( element, "tabindex" ),\n
+\t\t\tisTabIndexNaN = isNaN( tabIndex );\n
+\t\treturn ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );\n
+\t}\n
+});\n
+\n
+// support: jQuery <1.8\n
+if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {\n
+\t$.each( [ "Width", "Height" ], function( i, name ) {\n
+\t\tvar side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],\n
+\t\t\ttype = name.toLowerCase(),\n
+\t\t\torig = {\n
+\t\t\t\tinnerWidth: $.fn.innerWidth,\n
+\t\t\t\tinnerHeight: $.fn.innerHeight,\n
+\t\t\t\touterWidth: $.fn.outerWidth,\n
+\t\t\t\touterHeight: $.fn.outerHeight\n
+\t\t\t};\n
+\n
+\t\tfunction reduce( elem, size, border, margin ) {\n
+\t\t\t$.each( side, function() {\n
+\t\t\t\tsize -= parseFloat( $.css( elem, "padding" + this ) ) || 0;\n
+\t\t\t\tif ( border ) {\n
+\t\t\t\t\tsize -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;\n
+\t\t\t\t}\n
+\t\t\t\tif ( margin ) {\n
+\t\t\t\t\tsize -= parseFloat( $.css( elem, "margin" + this ) ) || 0;\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t\treturn size;\n
+\t\t}\n
+\n
+\t\t$.fn[ "inner" + name ] = function( size ) {\n
+\t\t\tif ( size === undefined ) {\n
+\t\t\t\treturn orig[ "inner" + name ].call( this );\n
+\t\t\t}\n
+\n
+\t\t\treturn this.each(function() {\n
+\t\t\t\t$( this ).css( type, reduce( this, size ) + "px" );\n
+\t\t\t});\n
+\t\t};\n
+\n
+\t\t$.fn[ "outer" + name] = function( size, margin ) {\n
+\t\t\tif ( typeof size !== "number" ) {\n
+\t\t\t\treturn orig[ "outer" + name ].call( this, size );\n
+\t\t\t}\n
+\n
+\t\t\treturn this.each(function() {\n
+\t\t\t\t$( this).css( type, reduce( this, size, true, margin ) + "px" );\n
+\t\t\t});\n
+\t\t};\n
+\t});\n
+}\n
+\n
+// support: jQuery <1.8\n
+if ( !$.fn.addBack ) {\n
+\t$.fn.addBack = function( selector ) {\n
+\t\treturn this.add( selector == null ?\n
+\t\t\tthis.prevObject : this.prevObject.filter( selector )\n
+\t\t);\n
+\t};\n
+}\n
+\n
+// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)\n
+if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {\n
+\t$.fn.removeData = (function( removeData ) {\n
+\t\treturn function( key ) {\n
+\t\t\tif ( arguments.length ) {\n
+\t\t\t\treturn removeData.call( this, $.camelCase( key ) );\n
+\t\t\t} else {\n
+\t\t\t\treturn removeData.call( this );\n
+\t\t\t}\n
+\t\t};\n
+\t})( $.fn.removeData );\n
+}\n
+\n
+\n
+\n
+\n
+\n
+// deprecated\n
+$.ui.ie = !!/msie [\\w.]+/.exec( navigator.userAgent.toLowerCase() );\n
+\n
+$.support.selectstart = "onselectstart" in document.createElement( "div" );\n
+$.fn.extend({\n
+\tdisableSelection: function() {\n
+\t\treturn this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +\n
+\t\t\t".ui-disableSelection", function( event ) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t});\n
+\t},\n
+\n
+\tenableSelection: function() {\n
+\t\treturn this.unbind( ".ui-disableSelection" );\n
+\t}\n
+});\n
+\n
+$.extend( $.ui, {\n
+\t// $.ui.plugin is deprecated. Use $.widget() extensions instead.\n
+\tplugin: {\n
+\t\tadd: function( module, option, set ) {\n
+\t\t\tvar i,\n
+\t\t\t\tproto = $.ui[ module ].prototype;\n
+\t\t\tfor ( i in set ) {\n
+\t\t\t\tproto.plugins[ i ] = proto.plugins[ i ] || [];\n
+\t\t\t\tproto.plugins[ i ].push( [ option, set[ i ] ] );\n
+\t\t\t}\n
+\t\t},\n
+\t\tcall: function( instance, name, args ) {\n
+\t\t\tvar i,\n
+\t\t\t\tset = instance.plugins[ name ];\n
+\t\t\tif ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tfor ( i = 0; i < set.length; i++ ) {\n
+\t\t\t\tif ( instance.options[ set[ i ][ 0 ] ] ) {\n
+\t\t\t\t\tset[ i ][ 1 ].apply( instance.element, args );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t// only used by resizable\n
+\thasScroll: function( el, a ) {\n
+\n
+\t\t//If overflow is hidden, the element might have extra content, but the user wants to hide it\n
+\t\tif ( $( el ).css( "overflow" ) === "hidden") {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\tvar scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",\n
+\t\t\thas = false;\n
+\n
+\t\tif ( el[ scroll ] > 0 ) {\n
+\t\t\treturn true;\n
+\t\t}\n
+\n
+\t\t// TODO: determine which cases actually cause this to happen\n
+\t\t// if the element doesn\'t have the scroll set, see if it\'s possible to\n
+\t\t// set the scroll\n
+\t\tel[ scroll ] = 1;\n
+\t\thas = ( el[ scroll ] > 0 );\n
+\t\tel[ scroll ] = 0;\n
+\t\treturn has;\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+(function( $, undefined ) {\n
+\n
+var uuid = 0,\n
+\tslice = Array.prototype.slice,\n
+\t_cleanData = $.cleanData;\n
+$.cleanData = function( elems ) {\n
+\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n
+\t\ttry {\n
+\t\t\t$( elem ).triggerHandler( "remove" );\n
+\t\t// http://bugs.jquery.com/ticket/8235\n
+\t\t} catch( e ) {}\n
+\t}\n
+\t_cleanData( elems );\n
+};\n
+\n
+$.widget = function( name, base, prototype ) {\n
+\tvar fullName, existingConstructor, constructor, basePrototype,\n
+\t\t// proxiedPrototype allows the provided prototype to remain unmodified\n
+\t\t// so that it can be used as a mixin for multiple widgets (#8876)\n
+\t\tproxiedPrototype = {},\n
+\t\tnamespace = name.split( "." )[ 0 ];\n
+\n
+\tname = name.split( "." )[ 1 ];\n
+\tfullName = namespace + "-" + name;\n
+\n
+\tif ( !prototype ) {\n
+\t\tprototype = base;\n
+\t\tbase = $.Widget;\n
+\t}\n
+\n
+\t// create selector for plugin\n
+\t$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {\n
+\t\treturn !!$.data( elem, fullName );\n
+\t};\n
+\n
+\t$[ namespace ] = $[ namespace ] || {};\n
+\texistingConstructor = $[ namespace ][ name ];\n
+\tconstructor = $[ namespace ][ name ] = function( options, element ) {\n
+\t\t// allow instantiation without "new" keyword\n
+\t\tif ( !this._createWidget ) {\n
+\t\t\treturn new constructor( options, element );\n
+\t\t}\n
+\n
+\t\t// allow instantiation without initializing for simple inheritance\n
+\t\t// must use "new" keyword (the code above always passes args)\n
+\t\tif ( arguments.length ) {\n
+\t\t\tthis._createWidget( options, element );\n
+\t\t}\n
+\t};\n
+\t// extend with the existing constructor to carry over any static properties\n
+\t$.extend( constructor, existingConstructor, {\n
+\t\tversion: prototype.version,\n
+\t\t// copy the object used to create the prototype in case we need to\n
+\t\t// redefine the widget later\n
+\t\t_proto: $.extend( {}, prototype ),\n
+\t\t// track widgets that inherit from this widget in case this widget is\n
+\t\t// redefined after a widget inherits from it\n
+\t\t_childConstructors: []\n
+\t});\n
+\n
+\tbasePrototype = new base();\n
+\t// we need to make the options hash a property directly on the new instance\n
+\t// otherwise we\'ll modify the options hash on the prototype that we\'re\n
+\t// inheriting from\n
+\tbasePrototype.options = $.widget.extend( {}, basePrototype.options );\n
+\t$.each( prototype, function( prop, value ) {\n
+\t\tif ( !$.isFunction( value ) ) {\n
+\t\t\tproxiedPrototype[ prop ] = value;\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tproxiedPrototype[ prop ] = (function() {\n
+\t\t\tvar _super = function() {\n
+\t\t\t\t\treturn base.prototype[ prop ].apply( this, arguments );\n
+\t\t\t\t},\n
+\t\t\t\t_superApply = function( args ) {\n
+\t\t\t\t\treturn base.prototype[ prop ].apply( this, args );\n
+\t\t\t\t};\n
+\t\t\treturn function() {\n
+\t\t\t\tvar __super = this._super,\n
+\t\t\t\t\t__superApply = this._superApply,\n
+\t\t\t\t\treturnValue;\n
+\n
+\t\t\t\tthis._super = _super;\n
+\t\t\t\tthis._superApply = _superApply;\n
+\n
+\t\t\t\treturnValue = value.apply( this, arguments );\n
+\n
+\t\t\t\tthis._super = __super;\n
+\t\t\t\tthis._superApply = __superApply;\n
+\n
+\t\t\t\treturn returnValue;\n
+\t\t\t};\n
+\t\t})();\n
+\t});\n
+\tconstructor.prototype = $.widget.extend( basePrototype, {\n
+\t\t// TODO: remove support for widgetEventPrefix\n
+\t\t// always use the name + a colon as the prefix, e.g., draggable:start\n
+\t\t// don\'t prefix for widgets that aren\'t DOM-based\n
+\t\twidgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name\n
+\t}, proxiedPrototype, {\n
+\t\tconstructor: constructor,\n
+\t\tnamespace: namespace,\n
+\t\twidgetName: name,\n
+\t\twidgetFullName: fullName\n
+\t});\n
+\n
+\t// If this widget is being redefined then we need to find all widgets that\n
+\t// are inheriting from it and redefine all of them so that they inherit from\n
+\t// the new version of this widget. We\'re essentially trying to replace one\n
+\t// level in the prototype chain.\n
+\tif ( existingConstructor ) {\n
+\t\t$.each( existingConstructor._childConstructors, function( i, child ) {\n
+\t\t\tvar childPrototype = child.prototype;\n
+\n
+\t\t\t// redefine the child widget using the same prototype that was\n
+\t\t\t// originally used, but inherit from the new version of the base\n
+\t\t\t$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );\n
+\t\t});\n
+\t\t// remove the list of existing child constructors from the old constructor\n
+\t\t// so the old child constructors can be garbage collected\n
+\t\tdelete existingConstructor._childConstructors;\n
+\t} else {\n
+\t\tbase._childConstructors.push( constructor );\n
+\t}\n
+\n
+\t$.widget.bridge( name, constructor );\n
+};\n
+\n
+$.widget.extend = function( target ) {\n
+\tvar input = slice.call( arguments, 1 ),\n
+\t\tinputIndex = 0,\n
+\t\tinputLength = input.length,\n
+\t\tkey,\n
+\t\tvalue;\n
+\tfor ( ; inputIndex < inputLength; inputIndex++ ) {\n
+\t\tfor ( key in input[ inputIndex ] ) {\n
+\t\t\tvalue = input[ inputIndex ][ key ];\n
+\t\t\tif ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {\n
+\t\t\t\t// Clone objects\n
+\t\t\t\tif ( $.isPlainObject( value ) ) {\n
+\t\t\t\t\ttarget[ key ] = $.isPlainObject( target[ key ] ) ?\n
+\t\t\t\t\t\t$.widget.extend( {}, target[ key ], value ) :\n
+\t\t\t\t\t\t// Don\'t extend strings, arrays, etc. with objects\n
+\t\t\t\t\t\t$.widget.extend( {}, value );\n
+\t\t\t\t// Copy everything else by reference\n
+\t\t\t\t} else {\n
+\t\t\t\t\ttarget[ key ] = value;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\treturn target;\n
+};\n
+\n
+$.widget.bridge = function( name, object ) {\n
+\tvar fullName = object.prototype.widgetFullName || name;\n
+\t$.fn[ name ] = function( options ) {\n
+\t\tvar isMethodCall = typeof options === "string",\n
+\t\t\targs = slice.call( arguments, 1 ),\n
+\t\t\treturnValue = this;\n
+\n
+\t\t// allow multiple hashes to be passed on init\n
+\t\toptions = !isMethodCall && args.length ?\n
+\t\t\t$.widget.extend.apply( null, [ options ].concat(args) ) :\n
+\t\t\toptions;\n
+\n
+\t\tif ( isMethodCall ) {\n
+\t\t\tthis.each(function() {\n
+\t\t\t\tvar methodValue,\n
+\t\t\t\t\tinstance = $.data( this, fullName );\n
+\t\t\t\tif ( !instance ) {\n
+\t\t\t\t\treturn $.error( "cannot call methods on " + name + " prior to initialization; " +\n
+\t\t\t\t\t\t"attempted to call method \'" + options + "\'" );\n
+\t\t\t\t}\n
+\t\t\t\tif ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {\n
+\t\t\t\t\treturn $.error( "no such method \'" + options + "\' for " + name + " widget instance" );\n
+\t\t\t\t}\n
+\t\t\t\tmethodValue = instance[ options ].apply( instance, args );\n
+\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n
+\t\t\t\t\treturnValue = methodValue && methodValue.jquery ?\n
+\t\t\t\t\t\treturnValue.pushStack( methodValue.get() ) :\n
+\t\t\t\t\t\tmethodValue;\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t} else {\n
+\t\t\tthis.each(function() {\n
+\t\t\t\tvar instance = $.data( this, fullName );\n
+\t\t\t\tif ( instance ) {\n
+\t\t\t\t\tinstance.option( options || {} )._init();\n
+\t\t\t\t} else {\n
+\t\t\t\t\t$.data( this, fullName, new object( options, this ) );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\treturn returnValue;\n
+\t};\n
+};\n
+\n
+$.Widget = function( /* options, element */ ) {};\n
+$.Widget._childConstructors = [];\n
+\n
+$.Widget.prototype = {\n
+\twidgetName: "widget",\n
+\twidgetEventPrefix: "",\n
+\tdefaultElement: "<div>",\n
+\toptions: {\n
+\t\tdisabled: false,\n
+\n
+\t\t// callbacks\n
+\t\tcreate: null\n
+\t},\n
+\t_createWidget: function( options, element ) {\n
+\t\telement = $( element || this.defaultElement || this )[ 0 ];\n
+\t\tthis.element = $( element );\n
+\t\tthis.uuid = uuid++;\n
+\t\tthis.eventNamespace = "." + this.widgetName + this.uuid;\n
+\t\tthis.options = $.widget.extend( {},\n
+\t\t\tthis.options,\n
+\t\t\tthis._getCreateOptions(),\n
+\t\t\toptions );\n
+\n
+\t\tthis.bindings = $();\n
+\t\tthis.hoverable = $();\n
+\t\tthis.focusable = $();\n
+\n
+\t\tif ( element !== this ) {\n
+\t\t\t$.data( element, this.widgetFullName, this );\n
+\t\t\tthis._on( true, this.element, {\n
+\t\t\t\tremove: function( event ) {\n
+\t\t\t\t\tif ( event.target === element ) {\n
+\t\t\t\t\t\tthis.destroy();\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t\tthis.document = $( element.style ?\n
+\t\t\t\t// element within the document\n
+\t\t\t\telement.ownerDocument :\n
+\t\t\t\t// element is window or document\n
+\t\t\t\telement.document || element );\n
+\t\t\tthis.window = $( this.document[0].defaultView || this.document[0].parentWindow );\n
+\t\t}\n
+\n
+\t\tthis._create();\n
+\t\tthis._trigger( "create", null, this._getCreateEventData() );\n
+\t\tthis._init();\n
+\t},\n
+\t_getCreateOptions: $.noop,\n
+\t_getCreateEventData: $.noop,\n
+\t_create: $.noop,\n
+\t_init: $.noop,\n
+\n
+\tdestroy: function() {\n
+\t\tthis._destroy();\n
+\t\t// we can probably remove the unbind calls in 2.0\n
+\t\t// all event bindings should go through this._on()\n
+\t\tthis.element\n
+\t\t\t.unbind( this.eventNamespace )\n
+\t\t\t// 1.9 BC for #7810\n
+\t\t\t// TODO remove dual storage\n
+\t\t\t.removeData( this.widgetName )\n
+\t\t\t.removeData( this.widgetFullName )\n
+\t\t\t// support: jquery <1.6.3\n
+\t\t\t// http://bugs.jquery.com/ticket/9413\n
+\t\t\t.removeData( $.camelCase( this.widgetFullName ) );\n
+\t\tthis.widget()\n
+\t\t\t.unbind( this.eventNamespace )\n
+\t\t\t.removeAttr( "aria-disabled" )\n
+\t\t\t.removeClass(\n
+\t\t\t\tthis.widgetFullName + "-disabled " +\n
+\t\t\t\t"ui-state-disabled" );\n
+\n
+\t\t// clean up events and states\n
+\t\tthis.bindings.unbind( this.eventNamespace );\n
+\t\tthis.hoverable.removeClass( "ui-state-hover" );\n
+\t\tthis.focusable.removeClass( "ui-state-focus" );\n
+\t},\n
+\t_destroy: $.noop,\n
+\n
+\twidget: function() {\n
+\t\treturn this.element;\n
+\t},\n
+\n
+\toption: function( key, value ) {\n
+\t\tvar options = key,\n
+\t\t\tparts,\n
+\t\t\tcurOption,\n
+\t\t\ti;\n
+\n
+\t\tif ( arguments.length === 0 ) {\n
+\t\t\t// don\'t return a reference to the internal hash\n
+\t\t\treturn $.widget.extend( {}, this.options );\n
+\t\t}\n
+\n
+\t\tif ( typeof key === "string" ) {\n
+\t\t\t// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }\n
+\t\t\toptions = {};\n
+\t\t\tparts = key.split( "." );\n
+\t\t\tkey = parts.shift();\n
+\t\t\tif ( parts.length ) {\n
+\t\t\t\tcurOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );\n
+\t\t\t\tfor ( i = 0; i < parts.length - 1; i++ ) {\n
+\t\t\t\t\tcurOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};\n
+\t\t\t\t\tcurOption = curOption[ parts[ i ] ];\n
+\t\t\t\t}\n
+\t\t\t\tkey = parts.pop();\n
+\t\t\t\tif ( arguments.length === 1 ) {\n
+\t\t\t\t\treturn curOption[ key ] === undefined ? null : curOption[ key ];\n
+\t\t\t\t}\n
+\t\t\t\tcurOption[ key ] = value;\n
+\t\t\t} else {\n
+\t\t\t\tif ( arguments.length === 1 ) {\n
+\t\t\t\t\treturn this.options[ key ] === undefined ? null : this.options[ key ];\n
+\t\t\t\t}\n
+\t\t\t\toptions[ key ] = value;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis._setOptions( options );\n
+\n
+\t\treturn this;\n
+\t},\n
+\t_setOptions: function( options ) {\n
+\t\tvar key;\n
+\n
+\t\tfor ( key in options ) {\n
+\t\t\tthis._setOption( key, options[ key ] );\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\t_setOption: function( key, value ) {\n
+\t\tthis.options[ key ] = value;\n
+\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\tthis.widget()\n
+\t\t\t\t.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )\n
+\t\t\t\t.attr( "aria-disabled", value );\n
+\t\t\tthis.hoverable.removeClass( "ui-state-hover" );\n
+\t\t\tthis.focusable.removeClass( "ui-state-focus" );\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\tenable: function() {\n
+\t\treturn this._setOption( "disabled", false );\n
+\t},\n
+\tdisable: function() {\n
+\t\treturn this._setOption( "disabled", true );\n
+\t},\n
+\n
+\t_on: function( suppressDisabledCheck, element, handlers ) {\n
+\t\tvar delegateElement,\n
+\t\t\tinstance = this;\n
+\n
+\t\t// no suppressDisabledCheck flag, shuffle arguments\n
+\t\tif ( typeof suppressDisabledCheck !== "boolean" ) {\n
+\t\t\thandlers = element;\n
+\t\t\telement = suppressDisabledCheck;\n
+\t\t\tsuppressDisabledCheck = false;\n
+\t\t}\n
+\n
+\t\t// no element argument, shuffle and use this.element\n
+\t\tif ( !handlers ) {\n
+\t\t\thandlers = element;\n
+\t\t\telement = this.element;\n
+\t\t\tdelegateElement = this.widget();\n
+\t\t} else {\n
+\t\t\t// accept selectors, DOM elements\n
+\t\t\telement = delegateElement = $( element );\n
+\t\t\tthis.bindings = this.bindings.add( element );\n
+\t\t}\n
+\n
+\t\t$.each( handlers, function( event, handler ) {\n
+\t\t\tfunction handlerProxy() {\n
+\t\t\t\t// allow widgets to customize the disabled handling\n
+\t\t\t\t// - disabled as an array instead of boolean\n
+\t\t\t\t// - disabled class as method for disabling individual parts\n
+\t\t\t\tif ( !suppressDisabledCheck &&\n
+\t\t\t\t\t\t( instance.options.disabled === true ||\n
+\t\t\t\t\t\t\t$( this ).hasClass( "ui-state-disabled" ) ) ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\treturn ( typeof handler === "string" ? instance[ handler ] : handler )\n
+\t\t\t\t\t.apply( instance, arguments );\n
+\t\t\t}\n
+\n
+\t\t\t// copy the guid so direct unbinding works\n
+\t\t\tif ( typeof handler !== "string" ) {\n
+\t\t\t\thandlerProxy.guid = handler.guid =\n
+\t\t\t\t\thandler.guid || handlerProxy.guid || $.guid++;\n
+\t\t\t}\n
+\n
+\t\t\tvar match = event.match( /^(\\w+)\\s*(.*)$/ ),\n
+\t\t\t\teventName = match[1] + instance.eventNamespace,\n
+\t\t\t\tselector = match[2];\n
+\t\t\tif ( selector ) {\n
+\t\t\t\tdelegateElement.delegate( selector, eventName, handlerProxy );\n
+\t\t\t} else {\n
+\t\t\t\telement.bind( eventName, handlerProxy );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_off: function( element, eventName ) {\n
+\t\teventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;\n
+\t\telement.unbind( eventName ).undelegate( eventName );\n
+\t},\n
+\n
+\t_delay: function( handler, delay ) {\n
+\t\tfunction handlerProxy() {\n
+\t\t\treturn ( typeof handler === "string" ? instance[ handler ] : handler )\n
+\t\t\t\t.apply( instance, arguments );\n
+\t\t}\n
+\t\tvar instance = this;\n
+\t\treturn setTimeout( handlerProxy, delay || 0 );\n
+\t},\n
+\n
+\t_hoverable: function( element ) {\n
+\t\tthis.hoverable = this.hoverable.add( element );\n
+\t\tthis._on( element, {\n
+\t\t\tmouseenter: function( event ) {\n
+\t\t\t\t$( event.currentTarget ).addClass( "ui-state-hover" );\n
+\t\t\t},\n
+\t\t\tmouseleave: function( event ) {\n
+\t\t\t\t$( event.currentTarget ).removeClass( "ui-state-hover" );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_focusable: function( element ) {\n
+\t\tthis.focusable = this.focusable.add( element );\n
+\t\tthis._on( element, {\n
+\t\t\tfocusin: function( event ) {\n
+\t\t\t\t$( event.currentTarget ).addClass( "ui-state-focus" );\n
+\t\t\t},\n
+\t\t\tfocusout: function( event ) {\n
+\t\t\t\t$( event.currentTarget ).removeClass( "ui-state-focus" );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_trigger: function( type, event, data ) {\n
+\t\tvar prop, orig,\n
+\t\t\tcallback = this.options[ type ];\n
+\n
+\t\tdata = data || {};\n
+\t\tevent = $.Event( event );\n
+\t\tevent.type = ( type === this.widgetEventPrefix ?\n
+\t\t\ttype :\n
+\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n
+\t\t// the original event may come from any element\n
+\t\t// so we need to reset the target on the new event\n
+\t\tevent.target = this.element[ 0 ];\n
+\n
+\t\t// copy original event properties over to the new event\n
+\t\torig = event.originalEvent;\n
+\t\tif ( orig ) {\n
+\t\t\tfor ( prop in orig ) {\n
+\t\t\t\tif ( !( prop in event ) ) {\n
+\t\t\t\t\tevent[ prop ] = orig[ prop ];\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis.element.trigger( event, data );\n
+\t\treturn !( $.isFunction( callback ) &&\n
+\t\t\tcallback.apply( this.element[0], [ event ].concat( data ) ) === false ||\n
+\t\t\tevent.isDefaultPrevented() );\n
+\t}\n
+};\n
+\n
+$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {\n
+\t$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {\n
+\t\tif ( typeof options === "string" ) {\n
+\t\t\toptions = { effect: options };\n
+\t\t}\n
+\t\tvar hasOptions,\n
+\t\t\teffectName = !options ?\n
+\t\t\t\tmethod :\n
+\t\t\t\toptions === true || typeof options === "number" ?\n
+\t\t\t\t\tdefaultEffect :\n
+\t\t\t\t\toptions.effect || defaultEffect;\n
+\t\toptions = options || {};\n
+\t\tif ( typeof options === "number" ) {\n
+\t\t\toptions = { duration: options };\n
+\t\t}\n
+\t\thasOptions = !$.isEmptyObject( options );\n
+\t\toptions.complete = callback;\n
+\t\tif ( options.delay ) {\n
+\t\t\telement.delay( options.delay );\n
+\t\t}\n
+\t\tif ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {\n
+\t\t\telement[ method ]( options );\n
+\t\t} else if ( effectName !== method && element[ effectName ] ) {\n
+\t\t\telement[ effectName ]( options.duration, options.easing, callback );\n
+\t\t} else {\n
+\t\t\telement.queue(function( next ) {\n
+\t\t\t\t$( this )[ method ]();\n
+\t\t\t\tif ( callback ) {\n
+\t\t\t\t\tcallback.call( element[ 0 ] );\n
+\t\t\t\t}\n
+\t\t\t\tnext();\n
+\t\t\t});\n
+\t\t}\n
+\t};\n
+});\n
+\n
+})( jQuery );\n
+(function( $, undefined ) {\n
+\n
+var mouseHandled = false;\n
+$( document ).mouseup( function() {\n
+\tmouseHandled = false;\n
+});\n
+\n
+$.widget("ui.mouse", {\n
+\tversion: "1.10.4",\n
+\toptions: {\n
+\t\tcancel: "input,textarea,button,select,option",\n
+\t\tdistance: 1,\n
+\t\tdelay: 0\n
+\t},\n
+\t_mouseInit: function() {\n
+\t\tvar that = this;\n
+\n
+\t\tthis.element\n
+\t\t\t.bind("mousedown."+this.widgetName, function(event) {\n
+\t\t\t\treturn that._mouseDown(event);\n
+\t\t\t})\n
+\t\t\t.bind("click."+this.widgetName, function(event) {\n
+\t\t\t\tif (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {\n
+\t\t\t\t\t$.removeData(event.target, that.widgetName + ".preventClickEvent");\n
+\t\t\t\t\tevent.stopImmediatePropagation();\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t});\n
+\n
+\t\tthis.started = false;\n
+\t},\n
+\n
+\t// TODO: make sure destroying one instance of mouse doesn\'t mess with\n
+\t// other instances of mouse\n
+\t_mouseDestroy: function() {\n
+\t\tthis.element.unbind("."+this.widgetName);\n
+\t\tif ( this._mouseMoveDelegate ) {\n
+\t\t\t$(document)\n
+\t\t\t\t.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)\n
+\t\t\t\t.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);\n
+\t\t}\n
+\t},\n
+\n
+\t_mouseDown: function(event) {\n
+\t\t// don\'t let more than one widget handle mouseStart\n
+\t\tif( mouseHandled ) { return; }\n
+\n
+\t\t// we may have missed mouseup (out of window)\n
+\t\t(this._mouseStarted && this._mouseUp(event));\n
+\n
+\t\tthis._mouseDownEvent = event;\n
+\n
+\t\tvar that = this,\n
+\t\t\tbtnIsLeft = (event.which === 1),\n
+\t\t\t// event.target.nodeName works around a bug in IE 8 with\n
+\t\t\t// disabled inputs (#7620)\n
+\t\t\telIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);\n
+\t\tif (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {\n
+\t\t\treturn true;\n
+\t\t}\n
+\n
+\t\tthis.mouseDelayMet = !this.options.delay;\n
+\t\tif (!this.mouseDelayMet) {\n
+\t\t\tthis._mouseDelayTimer = setTimeout(function() {\n
+\t\t\t\tthat.mouseDelayMet = true;\n
+\t\t\t}, this.options.delay);\n
+\t\t}\n
+\n
+\t\tif (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {\n
+\t\t\tthis._mouseStarted = (this._mouseStart(event) !== false);\n
+\t\t\tif (!this._mouseStarted) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t\treturn true;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Click event may never have fired (Gecko & Opera)\n
+\t\tif (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {\n
+\t\t\t$.removeData(event.target, this.widgetName + ".preventClickEvent");\n
+\t\t}\n
+\n
+\t\t// these delegates are required to keep context\n
+\t\tthis._mouseMoveDelegate = function(event) {\n
+\t\t\treturn that._mouseMove(event);\n
+\t\t};\n
+\t\tthis._mouseUpDelegate = function(event) {\n
+\t\t\treturn that._mouseUp(event);\n
+\t\t};\n
+\t\t$(document)\n
+\t\t\t.bind("mousemove."+this.widgetName, this._mouseMoveDelegate)\n
+\t\t\t.bind("mouseup."+this.widgetName, this._mouseUpDelegate);\n
+\n
+\t\tevent.preventDefault();\n
+\n
+\t\tmouseHandled = true;\n
+\t\treturn true;\n
+\t},\n
+\n
+\t_mouseMove: function(event) {\n
+\t\t// IE mouseup check - mouseup happened when mouse was out of window\n
+\t\tif ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {\n
+\t\t\treturn this._mouseUp(event);\n
+\t\t}\n
+\n
+\t\tif (this._mouseStarted) {\n
+\t\t\tthis._mouseDrag(event);\n
+\t\t\treturn event.preventDefault();\n
+\t\t}\n
+\n
+\t\tif (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {\n
+\t\t\tthis._mouseStarted =\n
+\t\t\t\t(this._mouseStart(this._mouseDownEvent, event) !== false);\n
+\t\t\t(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));\n
+\t\t}\n
+\n
+\t\treturn !this._mouseStarted;\n
+\t},\n
+\n
+\t_mouseUp: function(event) {\n
+\t\t$(document)\n
+\t\t\t.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)\n
+\t\t\t.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);\n
+\n
+\t\tif (this._mouseStarted) {\n
+\t\t\tthis._mouseStarted = false;\n
+\n
+\t\t\tif (event.target === this._mouseDownEvent.target) {\n
+\t\t\t\t$.data(event.target, this.widgetName + ".preventClickEvent", true);\n
+\t\t\t}\n
+\n
+\t\t\tthis._mouseStop(event);\n
+\t\t}\n
+\n
+\t\treturn false;\n
+\t},\n
+\n
+\t_mouseDistanceMet: function(event) {\n
+\t\treturn (Math.max(\n
+\t\t\t\tMath.abs(this._mouseDownEvent.pageX - event.pageX),\n
+\t\t\t\tMath.abs(this._mouseDownEvent.pageY - event.pageY)\n
+\t\t\t) >= this.options.distance\n
+\t\t);\n
+\t},\n
+\n
+\t_mouseDelayMet: function(/* event */) {\n
+\t\treturn this.mouseDelayMet;\n
+\t},\n
+\n
+\t// These are placeholder methods, to be overriden by extending plugin\n
+\t_mouseStart: function(/* event */) {},\n
+\t_mouseDrag: function(/* event */) {},\n
+\t_mouseStop: function(/* event */) {},\n
+\t_mouseCapture: function(/* event */) { return true; }\n
+});\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.ui = $.ui || {};\n
+\n
+var cachedScrollbarWidth,\n
+\tmax = Math.max,\n
+\tabs = Math.abs,\n
+\tround = Math.round,\n
+\trhorizontal = /left|center|right/,\n
+\trvertical = /top|center|bottom/,\n
+\troffset = /[\\+\\-]\\d+(\\.[\\d]+)?%?/,\n
+\trposition = /^\\w+/,\n
+\trpercent = /%$/,\n
+\t_position = $.fn.position;\n
+\n
+function getOffsets( offsets, width, height ) {\n
+\treturn [\n
+\t\tparseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),\n
+\t\tparseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )\n
+\t];\n
+}\n
+\n
+function parseCss( element, property ) {\n
+\treturn parseInt( $.css( element, property ), 10 ) || 0;\n
+}\n
+\n
+function getDimensions( elem ) {\n
+\tvar raw = elem[0];\n
+\tif ( raw.nodeType === 9 ) {\n
+\t\treturn {\n
+\t\t\twidth: elem.width(),\n
+\t\t\theight: elem.height(),\n
+\t\t\toffset: { top: 0, left: 0 }\n
+\t\t};\n
+\t}\n
+\tif ( $.isWindow( raw ) ) {\n
+\t\treturn {\n
+\t\t\twidth: elem.width(),\n
+\t\t\theight: elem.height(),\n
+\t\t\toffset: { top: elem.scrollTop(), left: elem.scrollLeft() }\n
+\t\t};\n
+\t}\n
+\tif ( raw.preventDefault ) {\n
+\t\treturn {\n
+\t\t\twidth: 0,\n
+\t\t\theight: 0,\n
+\t\t\toffset: { top: raw.pageY, left: raw.pageX }\n
+\t\t};\n
+\t}\n
+\treturn {\n
+\t\twidth: elem.outerWidth(),\n
+\t\theight: elem.outerHeight(),\n
+\t\toffset: elem.offset()\n
+\t};\n
+}\n
+\n
+$.position = {\n
+\tscrollbarWidth: function() {\n
+\t\tif ( cachedScrollbarWidth !== undefined ) {\n
+\t\t\treturn cachedScrollbarWidth;\n
+\t\t}\n
+\t\tvar w1, w2,\n
+\t\t\tdiv = $( "<div style=\'display:block;position:absolute;width:50px;height:50px;overflow:hidden;\'><div style=\'height:100px;width:auto;\'></div></div>" ),\n
+\t\t\tinnerDiv = div.children()[0];\n
+\n
+\t\t$( "body" ).append( div );\n
+\t\tw1 = innerDiv.offsetWidth;\n
+\t\tdiv.css( "overflow", "scroll" );\n
+\n
+\t\tw2 = innerDiv.offsetWidth;\n
+\n
+\t\tif ( w1 === w2 ) {\n
+\t\t\tw2 = div[0].clientWidth;\n
+\t\t}\n
+\n
+\t\tdiv.remove();\n
+\n
+\t\treturn (cachedScrollbarWidth = w1 - w2);\n
+\t},\n
+\tgetScrollInfo: function( within ) {\n
+\t\tvar overflowX = within.isWindow || within.isDocument ? "" :\n
+\t\t\t\twithin.element.css( "overflow-x" ),\n
+\t\t\toverflowY = within.isWindow || within.isDocument ? "" :\n
+\t\t\t\twithin.element.css( "overflow-y" ),\n
+\t\t\thasOverflowX = overflowX === "scroll" ||\n
+\t\t\t\t( overflowX === "auto" && within.width < within.element[0].scrollWidth ),\n
+\t\t\thasOverflowY = overflowY === "scroll" ||\n
+\t\t\t\t( overflowY === "auto" && within.height < within.element[0].scrollHeight );\n
+\t\treturn {\n
+\t\t\twidth: hasOverflowY ? $.position.scrollbarWidth() : 0,\n
+\t\t\theight: hasOverflowX ? $.position.scrollbarWidth() : 0\n
+\t\t};\n
+\t},\n
+\tgetWithinInfo: function( element ) {\n
+\t\tvar withinElement = $( element || window ),\n
+\t\t\tisWindow = $.isWindow( withinElement[0] ),\n
+\t\t\tisDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;\n
+\t\treturn {\n
+\t\t\telement: withinElement,\n
+\t\t\tisWindow: isWindow,\n
+\t\t\tisDocument: isDocument,\n
+\t\t\toffset: withinElement.offset() || { left: 0, top: 0 },\n
+\t\t\tscrollLeft: withinElement.scrollLeft(),\n
+\t\t\tscrollTop: withinElement.scrollTop(),\n
+\t\t\twidth: isWindow ? withinElement.width() : withinElement.outerWidth(),\n
+\t\t\theight: isWindow ? withinElement.height() : withinElement.outerHeight()\n
+\t\t};\n
+\t}\n
+};\n
+\n
+$.fn.position = function( options ) {\n
+\tif ( !options || !options.of ) {\n
+\t\treturn _position.apply( this, arguments );\n
+\t}\n
+\n
+\t// make a copy, we don\'t want to modify arguments\n
+\toptions = $.extend( {}, options );\n
+\n
+\tvar atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,\n
+\t\ttarget = $( options.of ),\n
+\t\twithin = $.position.getWithinInfo( options.within ),\n
+\t\tscrollInfo = $.position.getScrollInfo( within ),\n
+\t\tcollision = ( options.collision || "flip" ).split( " " ),\n
+\t\toffsets = {};\n
+\n
+\tdimensions = getDimensions( target );\n
+\tif ( target[0].preventDefault ) {\n
+\t\t// force left top to allow flipping\n
+\t\toptions.at = "left top";\n
+\t}\n
+\ttargetWidth = dimensions.width;\n
+\ttargetHeight = dimensions.height;\n
+\ttargetOffset = dimensions.offset;\n
+\t// clone to reuse original targetOffset later\n
+\tbasePosition = $.extend( {}, targetOffset );\n
+\n
+\t// force my and at to have valid horizontal and vertical positions\n
+\t// if a value is missing or invalid, it will be converted to center\n
+\t$.each( [ "my", "at" ], function() {\n
+\t\tvar pos = ( options[ this ] || "" ).split( " " ),\n
+\t\t\thorizontalOffset,\n
+\t\t\tverticalOffset;\n
+\n
+\t\tif ( pos.length === 1) {\n
+\t\t\tpos = rhorizontal.test( pos[ 0 ] ) ?\n
+\t\t\t\tpos.concat( [ "center" ] ) :\n
+\t\t\t\trvertical.test( pos[ 0 ] ) ?\n
+\t\t\t\t\t[ "center" ].concat( pos ) :\n
+\t\t\t\t\t[ "center", "center" ];\n
+\t\t}\n
+\t\tpos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";\n
+\t\tpos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";\n
+\n
+\t\t// calculate offsets\n
+\t\thorizontalOffset = roffset.exec( pos[ 0 ] );\n
+\t\tverticalOffset = roffset.exec( pos[ 1 ] );\n
+\t\toffsets[ this ] = [\n
+\t\t\thorizontalOffset ? horizontalOffset[ 0 ] : 0,\n
+\t\t\tverticalOffset ? verticalOffset[ 0 ] : 0\n
+\t\t];\n
+\n
+\t\t// reduce to just the positions without the offsets\n
+\t\toptions[ this ] = [\n
+\t\t\trposition.exec( pos[ 0 ] )[ 0 ],\n
+\t\t\trposition.exec( pos[ 1 ] )[ 0 ]\n
+\t\t];\n
+\t});\n
+\n
+\t// normalize collision option\n
+\tif ( collision.length === 1 ) {\n
+\t\tcollision[ 1 ] = collision[ 0 ];\n
+\t}\n
+\n
+\tif ( options.at[ 0 ] === "right" ) {\n
+\t\tbasePosition.left += targetWidth;\n
+\t} else if ( options.at[ 0 ] === "center" ) {\n
+\t\tbasePosition.left += targetWidth / 2;\n
+\t}\n
+\n
+\tif ( options.at[ 1 ] === "bottom" ) {\n
+\t\tbasePosition.top += targetHeight;\n
+\t} else if ( options.at[ 1 ] === "center" ) {\n
+\t\tbasePosition.top += targetHeight / 2;\n
+\t}\n
+\n
+\tatOffset = getOffsets( offsets.at, targetWidth, targetHeight );\n
+\tbasePosition.left += atOffset[ 0 ];\n
+\tbasePosition.top += atOffset[ 1 ];\n
+\n
+\treturn this.each(function() {\n
+\t\tvar collisionPosition, using,\n
+\t\t\telem = $( this ),\n
+\t\t\telemWidth = elem.outerWidth(),\n
+\t\t\telemHeight = elem.outerHeight(),\n
+\t\t\tmarginLeft = parseCss( this, "marginLeft" ),\n
+\t\t\tmarginTop = parseCss( this, "marginTop" ),\n
+\t\t\tcollisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,\n
+\t\t\tcollisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,\n
+\t\t\tposition = $.extend( {}, basePosition ),\n
+\t\t\tmyOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );\n
+\n
+\t\tif ( options.my[ 0 ] === "right" ) {\n
+\t\t\tposition.left -= elemWidth;\n
+\t\t} else if ( options.my[ 0 ] === "center" ) {\n
+\t\t\tposition.left -= elemWidth / 2;\n
+\t\t}\n
+\n
+\t\tif ( options.my[ 1 ] === "bottom" ) {\n
+\t\t\tposition.top -= elemHeight;\n
+\t\t} else if ( options.my[ 1 ] === "center" ) {\n
+\t\t\tposition.top -= elemHeight / 2;\n
+\t\t}\n
+\n
+\t\tposition.left += myOffset[ 0 ];\n
+\t\tposition.top += myOffset[ 1 ];\n
+\n
+\t\t// if the browser doesn\'t support fractions, then round for consistent results\n
+\t\tif ( !$.support.offsetFractions ) {\n
+\t\t\tposition.left = round( position.left );\n
+\t\t\tposition.top = round( position.top );\n
+\t\t}\n
+\n
+\t\tcollisionPosition = {\n
+\t\t\tmarginLeft: marginLeft,\n
+\t\t\tmarginTop: marginTop\n
+\t\t};\n
+\n
+\t\t$.each( [ "left", "top" ], function( i, dir ) {\n
+\t\t\tif ( $.ui.position[ collision[ i ] ] ) {\n
+\t\t\t\t$.ui.position[ collision[ i ] ][ dir ]( position, {\n
+\t\t\t\t\ttargetWidth: targetWidth,\n
+\t\t\t\t\ttargetHeight: targetHeight,\n
+\t\t\t\t\telemWidth: elemWidth,\n
+\t\t\t\t\telemHeight: elemHeight,\n
+\t\t\t\t\tcollisionPosition: collisionPosition,\n
+\t\t\t\t\tcollisionWidth: collisionWidth,\n
+\t\t\t\t\tcollisionHeight: collisionHeight,\n
+\t\t\t\t\toffset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],\n
+\t\t\t\t\tmy: options.my,\n
+\t\t\t\t\tat: options.at,\n
+\t\t\t\t\twithin: within,\n
+\t\t\t\t\telem : elem\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tif ( options.using ) {\n
+\t\t\t// adds feedback as second argument to using callback, if present\n
+\t\t\tusing = function( props ) {\n
+\t\t\t\tvar left = targetOffset.left - position.left,\n
+\t\t\t\t\tright = left + targetWidth - elemWidth,\n
+\t\t\t\t\ttop = targetOffset.top - position.top,\n
+\t\t\t\t\tbottom = top + targetHeight - elemHeight,\n
+\t\t\t\t\tfeedback = {\n
+\t\t\t\t\t\ttarget: {\n
+\t\t\t\t\t\t\telement: target,\n
+\t\t\t\t\t\t\tleft: targetOffset.left,\n
+\t\t\t\t\t\t\ttop: targetOffset.top,\n
+\t\t\t\t\t\t\twidth: targetWidth,\n
+\t\t\t\t\t\t\theight: targetHeight\n
+\t\t\t\t\t\t},\n
+\t\t\t\t\t\telement: {\n
+\t\t\t\t\t\t\telement: elem,\n
+\t\t\t\t\t\t\tleft: position.left,\n
+\t\t\t\t\t\t\ttop: position.top,\n
+\t\t\t\t\t\t\twidth: elemWidth,\n
+\t\t\t\t\t\t\theight: elemHeight\n
+\t\t\t\t\t\t},\n
+\t\t\t\t\t\thorizontal: right < 0 ? "left" : left > 0 ? "right" : "center",\n
+\t\t\t\t\t\tvertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"\n
+\t\t\t\t\t};\n
+\t\t\t\tif ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {\n
+\t\t\t\t\tfeedback.horizontal = "center";\n
+\t\t\t\t}\n
+\t\t\t\tif ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {\n
+\t\t\t\t\tfeedback.vertical = "middle";\n
+\t\t\t\t}\n
+\t\t\t\tif ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {\n
+\t\t\t\t\tfeedback.important = "horizontal";\n
+\t\t\t\t} else {\n
+\t\t\t\t\tfeedback.important = "vertical";\n
+\t\t\t\t}\n
+\t\t\t\toptions.using.call( this, props, feedback );\n
+\t\t\t};\n
+\t\t}\n
+\n
+\t\telem.offset( $.extend( position, { using: using } ) );\n
+\t});\n
+};\n
+\n
+$.ui.position = {\n
+\tfit: {\n
+\t\tleft: function( position, data ) {\n
+\t\t\tvar within = data.within,\n
+\t\t\t\twithinOffset = within.isWindow ? within.scrollLeft : within.offset.left,\n
+\t\t\t\touterWidth = within.width,\n
+\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n
+\t\t\t\toverLeft = withinOffset - collisionPosLeft,\n
+\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,\n
+\t\t\t\tnewOverRight;\n
+\n
+\t\t\t// element is wider than within\n
+\t\t\tif ( data.collisionWidth > outerWidth ) {\n
+\t\t\t\t// element is initially over the left side of within\n
+\t\t\t\tif ( overLeft > 0 && overRight <= 0 ) {\n
+\t\t\t\t\tnewOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;\n
+\t\t\t\t\tposition.left += overLeft - newOverRight;\n
+\t\t\t\t// element is initially over right side of within\n
+\t\t\t\t} else if ( overRight > 0 && overLeft <= 0 ) {\n
+\t\t\t\t\tposition.left = withinOffset;\n
+\t\t\t\t// element is initially over both left and right sides of within\n
+\t\t\t\t} else {\n
+\t\t\t\t\tif ( overLeft > overRight ) {\n
+\t\t\t\t\t\tposition.left = withinOffset + outerWidth - data.collisionWidth;\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tposition.left = withinOffset;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t// too far left -> align with left edge\n
+\t\t\t} else if ( overLeft > 0 ) {\n
+\t\t\t\tposition.left += overLeft;\n
+\t\t\t// too far right -> align with right edge\n
+\t\t\t} else if ( overRight > 0 ) {\n
+\t\t\t\tposition.left -= overRight;\n
+\t\t\t// adjust based on position and margin\n
+\t\t\t} else {\n
+\t\t\t\tposition.left = max( position.left - collisionPosLeft, position.left );\n
+\t\t\t}\n
+\t\t},\n
+\t\ttop: function( position, data ) {\n
+\t\t\tvar within = data.within,\n
+\t\t\t\twithinOffset = within.isWindow ? within.scrollTop : within.offset.top,\n
+\t\t\t\touterHeight = data.within.height,\n
+\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n
+\t\t\t\toverTop = withinOffset - collisionPosTop,\n
+\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,\n
+\t\t\t\tnewOverBottom;\n
+\n
+\t\t\t// element is taller than within\n
+\t\t\tif ( data.collisionHeight > outerHeight ) {\n
+\t\t\t\t// element is initially over the top of within\n
+\t\t\t\tif ( overTop > 0 && overBottom <= 0 ) {\n
+\t\t\t\t\tnewOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;\n
+\t\t\t\t\tposition.top += overTop - newOverBottom;\n
+\t\t\t\t// element is initially over bottom of within\n
+\t\t\t\t} else if ( overBottom > 0 && overTop <= 0 ) {\n
+\t\t\t\t\tposition.top = withinOffset;\n
+\t\t\t\t// element is initially over both top and bottom of within\n
+\t\t\t\t} else {\n
+\t\t\t\t\tif ( overTop > overBottom ) {\n
+\t\t\t\t\t\tposition.top = withinOffset + outerHeight - data.collisionHeight;\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tposition.top = withinOffset;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t// too far up -> align with top\n
+\t\t\t} else if ( overTop > 0 ) {\n
+\t\t\t\tposition.top += overTop;\n
+\t\t\t// too far down -> align with bottom edge\n
+\t\t\t} else if ( overBottom > 0 ) {\n
+\t\t\t\tposition.top -= overBottom;\n
+\t\t\t// adjust based on position and margin\n
+\t\t\t} else {\n
+\t\t\t\tposition.top = max( position.top - collisionPosTop, position.top );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\tflip: {\n
+\t\tleft: function( position, data ) {\n
+\t\t\tvar within = data.within,\n
+\t\t\t\twithinOffset = within.offset.left + within.scrollLeft,\n
+\t\t\t\touterWidth = within.width,\n
+\t\t\t\toffsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,\n
+\t\t\t\tcollisionPosLeft = position.left - data.collisionPosition.marginLeft,\n
+\t\t\t\toverLeft = collisionPosLeft - offsetLeft,\n
+\t\t\t\toverRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,\n
+\t\t\t\tmyOffset = data.my[ 0 ] === "left" ?\n
+\t\t\t\t\t-data.elemWidth :\n
+\t\t\t\t\tdata.my[ 0 ] === "right" ?\n
+\t\t\t\t\t\tdata.elemWidth :\n
+\t\t\t\t\t\t0,\n
+\t\t\t\tatOffset = data.at[ 0 ] === "left" ?\n
+\t\t\t\t\tdata.targetWidth :\n
+\t\t\t\t\tdata.at[ 0 ] === "right" ?\n
+\t\t\t\t\t\t-data.targetWidth :\n
+\t\t\t\t\t\t0,\n
+\t\t\t\toffset = -2 * data.offset[ 0 ],\n
+\t\t\t\tnewOverRight,\n
+\t\t\t\tnewOverLeft;\n
+\n
+\t\t\tif ( overLeft < 0 ) {\n
+\t\t\t\tnewOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;\n
+\t\t\t\tif ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {\n
+\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\telse if ( overRight > 0 ) {\n
+\t\t\t\tnewOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;\n
+\t\t\t\tif ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {\n
+\t\t\t\t\tposition.left += myOffset + atOffset + offset;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t},\n
+\t\ttop: function( position, data ) {\n
+\t\t\tvar within = data.within,\n
+\t\t\t\twithinOffset = within.offset.top + within.scrollTop,\n
+\t\t\t\touterHeight = within.height,\n
+\t\t\t\toffsetTop = within.isWindow ? within.scrollTop : within.offset.top,\n
+\t\t\t\tcollisionPosTop = position.top - data.collisionPosition.marginTop,\n
+\t\t\t\toverTop = collisionPosTop - offsetTop,\n
+\t\t\t\toverBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,\n
+\t\t\t\ttop = data.my[ 1 ] === "top",\n
+\t\t\t\tmyOffset = top ?\n
+\t\t\t\t\t-data.elemHeight :\n
+\t\t\t\t\tdata.my[ 1 ] === "bottom" ?\n
+\t\t\t\t\t\tdata.elemHeight :\n
+\t\t\t\t\t\t0,\n
+\t\t\t\tatOffset = data.at[ 1 ] === "top" ?\n
+\t\t\t\t\tdata.targetHeight :\n
+\t\t\t\t\tdata.at[ 1 ] === "bottom" ?\n
+\t\t\t\t\t\t-data.targetHeight :\n
+\t\t\t\t\t\t0,\n
+\t\t\t\toffset = -2 * data.offset[ 1 ],\n
+\t\t\t\tnewOverTop,\n
+\t\t\t\tnewOverBottom;\n
+\t\t\tif ( overTop < 0 ) {\n
+\t\t\t\tnewOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;\n
+\t\t\t\tif ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {\n
+\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\telse if ( overBottom > 0 ) {\n
+\t\t\t\tnewOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;\n
+\t\t\t\tif ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {\n
+\t\t\t\t\tposition.top += myOffset + atOffset + offset;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\tflipfit: {\n
+\t\tleft: function() {\n
+\t\t\t$.ui.position.flip.left.apply( this, arguments );\n
+\t\t\t$.ui.position.fit.left.apply( this, arguments );\n
+\t\t},\n
+\t\ttop: function() {\n
+\t\t\t$.ui.position.flip.top.apply( this, arguments );\n
+\t\t\t$.ui.position.fit.top.apply( this, arguments );\n
+\t\t}\n
+\t}\n
+};\n
+\n
+// fraction support test\n
+(function () {\n
+\tvar testElement, testElementParent, testElementStyle, offsetLeft, i,\n
+\t\tbody = document.getElementsByTagName( "body" )[ 0 ],\n
+\t\tdiv = document.createElement( "div" );\n
+\n
+\t//Create a "fake body" for testing based on method used in jQuery.support\n
+\ttestElement = document.createElement( body ? "div" : "body" );\n
+\ttestElementStyle = {\n
+\t\tvisibility: "hidden",\n
+\t\twidth: 0,\n
+\t\theight: 0,\n
+\t\tborder: 0,\n
+\t\tmargin: 0,\n
+\t\tbackground: "none"\n
+\t};\n
+\tif ( body ) {\n
+\t\t$.extend( testElementStyle, {\n
+\t\t\tposition: "absolute",\n
+\t\t\tleft: "-1000px",\n
+\t\t\ttop: "-1000px"\n
+\t\t});\n
+\t}\n
+\tfor ( i in testElementStyle ) {\n
+\t\ttestElement.style[ i ] = testElementStyle[ i ];\n
+\t}\n
+\ttestElement.appendChild( div );\n
+\ttestElementParent = body || document.documentElement;\n
+\ttestElementParent.insertBefore( testElement, testElementParent.firstChild );\n
+\n
+\tdiv.style.cssText = "position: absolute; left: 10.7432222px;";\n
+\n
+\toffsetLeft = $( div ).offset().left;\n
+\t$.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;\n
+\n
+\ttestElement.innerHTML = "";\n
+\ttestElementParent.removeChild( testElement );\n
+})();\n
+\n
+}( jQuery ) );\n
+(function( $, undefined ) {\n
+\n
+var uid = 0,\n
+\thideProps = {},\n
+\tshowProps = {};\n
+\n
+hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =\n
+\thideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";\n
+showProps.height = showProps.paddingTop = showProps.paddingBottom =\n
+\tshowProps.borderTopWidth = showProps.borderBottomWidth = "show";\n
+\n
+$.widget( "ui.accordion", {\n
+\tversion: "1.10.4",\n
+\toptions: {\n
+\t\tactive: 0,\n
+\t\tanimate: {},\n
+\t\tcollapsible: false,\n
+\t\tevent: "click",\n
+\t\theader: "> li > :first-child,> :not(li):even",\n
+\t\theightStyle: "auto",\n
+\t\ticons: {\n
+\t\t\tactiveHeader: "ui-icon-triangle-1-s",\n
+\t\t\theader: "ui-icon-triangle-1-e"\n
+\t\t},\n
+\n
+\t\t// callbacks\n
+\t\tactivate: null,\n
+\t\tbeforeActivate: null\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tvar options = this.options;\n
+\t\tthis.prevShow = this.prevHide = $();\n
+\t\tthis.element.addClass( "ui-accordion ui-widget ui-helper-reset" )\n
+\t\t\t// ARIA\n
+\t\t\t.attr( "role", "tablist" );\n
+\n
+\t\t// don\'t allow collapsible: false and active: false / null\n
+\t\tif ( !options.collapsible && (options.active === false || options.active == null) ) {\n
+\t\t\toptions.active = 0;\n
+\t\t}\n
+\n
+\t\tthis._processPanels();\n
+\t\t// handle negative values\n
+\t\tif ( options.active < 0 ) {\n
+\t\t\toptions.active += this.headers.length;\n
+\t\t}\n
+\t\tthis._refresh();\n
+\t},\n
+\n
+\t_getCreateEventData: function() {\n
+\t\treturn {\n
+\t\t\theader: this.active,\n
+\t\t\tpanel: !this.active.length ? $() : this.active.next(),\n
+\t\t\tcontent: !this.active.length ? $() : this.active.next()\n
+\t\t};\n
+\t},\n
+\n
+\t_createIcons: function() {\n
+\t\tvar icons = this.options.icons;\n
+\t\tif ( icons ) {\n
+\t\t\t$( "<span>" )\n
+\t\t\t\t.addClass( "ui-accordion-header-icon ui-icon " + icons.header )\n
+\t\t\t\t.prependTo( this.headers );\n
+\t\t\tthis.active.children( ".ui-accordion-header-icon" )\n
+\t\t\t\t.removeClass( icons.header )\n
+\t\t\t\t.addClass( icons.activeHeader );\n
+\t\t\tthis.headers.addClass( "ui-accordion-icons" );\n
+\t\t}\n
+\t},\n
+\n
+\t_destroyIcons: function() {\n
+\t\tthis.headers\n
+\t\t\t.removeClass( "ui-accordion-icons" )\n
+\t\t\t.children( ".ui-accordion-header-icon" )\n
+\t\t\t\t.remove();\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tvar contents;\n
+\n
+\t\t// clean up main element\n
+\t\tthis.element\n
+\t\t\t.removeClass( "ui-accordion ui-widget ui-helper-reset" )\n
+\t\t\t.removeAttr( "role" );\n
+\n
+\t\t// clean up headers\n
+\t\tthis.headers\n
+\t\t\t.removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )\n
+\t\t\t.removeAttr( "role" )\n
+\t\t\t.removeAttr( "aria-expanded" )\n
+\t\t\t.removeAttr( "aria-selected" )\n
+\t\t\t.removeAttr( "aria-controls" )\n
+\t\t\t.removeAttr( "tabIndex" )\n
+\t\t\t.each(function() {\n
+\t\t\t\tif ( /^ui-accordion/.test( this.id ) ) {\n
+\t\t\t\t\tthis.removeAttribute( "id" );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\tthis._destroyIcons();\n
+\n
+\t\t// clean up content panels\n
+\t\tcontents = this.headers.next()\n
+\t\t\t.css( "display", "" )\n
+\t\t\t.removeAttr( "role" )\n
+\t\t\t.removeAttr( "aria-hidden" )\n
+\t\t\t.removeAttr( "aria-labelledby" )\n
+\t\t\t.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )\n
+\t\t\t.each(function() {\n
+\t\t\t\tif ( /^ui-accordion/.test( this.id ) ) {\n
+\t\t\t\t\tthis.removeAttribute( "id" );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\tif ( this.options.heightStyle !== "content" ) {\n
+\t\t\tcontents.css( "height", "" );\n
+\t\t}\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tif ( key === "active" ) {\n
+\t\t\t// _activate() will handle invalid values and update this.options\n
+\t\t\tthis._activate( value );\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( key === "event" ) {\n
+\t\t\tif ( this.options.event ) {\n
+\t\t\t\tthis._off( this.headers, this.options.event );\n
+\t\t\t}\n
+\t\t\tthis._setupEvents( value );\n
+\t\t}\n
+\n
+\t\tthis._super( key, value );\n
+\n
+\t\t// setting collapsible: false while collapsed; open first panel\n
+\t\tif ( key === "collapsible" && !value && this.options.active === false ) {\n
+\t\t\tthis._activate( 0 );\n
+\t\t}\n
+\n
+\t\tif ( key === "icons" ) {\n
+\t\t\tthis._destroyIcons();\n
+\t\t\tif ( value ) {\n
+\t\t\t\tthis._createIcons();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// #5332 - opacity doesn\'t cascade to positioned elements in IE\n
+\t\t// so we need to add the disabled class to the headers and panels\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\tthis.headers.add( this.headers.next() )\n
+\t\t\t\t.toggleClass( "ui-state-disabled", !!value );\n
+\t\t}\n
+\t},\n
+\n
+\t_keydown: function( event ) {\n
+\t\tif ( event.altKey || event.ctrlKey ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tvar keyCode = $.ui.keyCode,\n
+\t\t\tlength = this.headers.length,\n
+\t\t\tcurrentIndex = this.headers.index( event.target ),\n
+\t\t\ttoFocus = false;\n
+\n
+\t\tswitch ( event.keyCode ) {\n
+\t\t\tcase keyCode.RIGHT:\n
+\t\t\tcase keyCode.DOWN:\n
+\t\t\t\ttoFocus = this.headers[ ( currentIndex + 1 ) % length ];\n
+\t\t\t\tbreak;\n
+\t\t\tcase keyCode.LEFT:\n
+\t\t\tcase keyCode.UP:\n
+\t\t\t\ttoFocus = this.headers[ ( currentIndex - 1 + length ) % length ];\n
+\t\t\t\tbreak;\n
+\t\t\tcase keyCode.SPACE:\n
+\t\t\tcase keyCode.ENTER:\n
+\t\t\t\tthis._eventHandler( event );\n
+\t\t\t\tbreak;\n
+\t\t\tcase keyCode.HOME:\n
+\t\t\t\ttoFocus = this.headers[ 0 ];\n
+\t\t\t\tbreak;\n
+\t\t\tcase keyCode.END:\n
+\t\t\t\ttoFocus = this.headers[ length - 1 ];\n
+\t\t\t\tbreak;\n
+\t\t}\n
+\n
+\t\tif ( toFocus ) {\n
+\t\t\t$( event.target ).attr( "tabIndex", -1 );\n
+\t\t\t$( toFocus ).attr( "tabIndex", 0 );\n
+\t\t\ttoFocus.focus();\n
+\t\t\tevent.preventDefault();\n
+\t\t}\n
+\t},\n
+\n
+\t_panelKeyDown : function( event ) {\n
+\t\tif ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {\n
+\t\t\t$( event.currentTarget ).prev().focus();\n
+\t\t}\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tvar options = this.options;\n
+\t\tthis._processPanels();\n
+\n
+\t\t// was collapsed or no panel\n
+\t\tif ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {\n
+\t\t\toptions.active = false;\n
+\t\t\tthis.active = $();\n
+\t\t// active false only when collapsible is true\n
+\t\t} else if ( options.active === false ) {\n
+\t\t\tthis._activate( 0 );\n
+\t\t// was active, but active panel is gone\n
+\t\t} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {\n
+\t\t\t// all remaining panel are disabled\n
+\t\t\tif ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {\n
+\t\t\t\toptions.active = false;\n
+\t\t\t\tthis.active = $();\n
+\t\t\t// activate previous panel\n
+\t\t\t} else {\n
+\t\t\t\tthis._activate( Math.max( 0, options.active - 1 ) );\n
+\t\t\t}\n
+\t\t// was active, active panel still exists\n
+\t\t} else {\n
+\t\t\t// make sure active index is correct\n
+\t\t\toptions.active = this.headers.index( this.active );\n
+\t\t}\n
+\n
+\t\tthis._destroyIcons();\n
+\n
+\t\tthis._refresh();\n
+\t},\n
+\n
+\t_processPanels: function() {\n
+\t\tthis.headers = this.element.find( this.options.header )\n
+\t\t\t.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );\n
+\n
+\t\tthis.headers.next()\n
+\t\t\t.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )\n
+\t\t\t.filter(":not(.ui-accordion-content-active)")\n
+\t\t\t.hide();\n
+\t},\n
+\n
+\t_refresh: function() {\n
+\t\tvar maxHeight,\n
+\t\t\toptions = this.options,\n
+\t\t\theightStyle = options.heightStyle,\n
+\t\t\tparent = this.element.parent(),\n
+\t\t\taccordionId = this.accordionId = "ui-accordion-" +\n
+\t\t\t\t(this.element.attr( "id" ) || ++uid);\n
+\n
+\t\tthis.active = this._findActive( options.active )\n
+\t\t\t.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" )\n
+\t\t\t.removeClass( "ui-corner-all" );\n
+\t\tthis.active.next()\n
+\t\t\t.addClass( "ui-accordion-content-active" )\n
+\t\t\t.show();\n
+\n
+\t\tthis.headers\n
+\t\t\t.attr( "role", "tab" )\n
+\t\t\t.each(function( i ) {\n
+\t\t\t\tvar header = $( this ),\n
+\t\t\t\t\theaderId = header.attr( "id" ),\n
+\t\t\t\t\tpanel = header.next(),\n
+\t\t\t\t\tpanelId = panel.attr( "id" );\n
+\t\t\t\tif ( !headerId ) {\n
+\t\t\t\t\theaderId = accordionId + "-header-" + i;\n
+\t\t\t\t\theader.attr( "id", headerId );\n
+\t\t\t\t}\n
+\t\t\t\tif ( !panelId ) {\n
+\t\t\t\t\tpanelId = accordionId + "-panel-" + i;\n
+\t\t\t\t\tpanel.attr( "id", panelId );\n
+\t\t\t\t}\n
+\t\t\t\theader.attr( "aria-controls", panelId );\n
+\t\t\t\tpanel.attr( "aria-labelledby", headerId );\n
+\t\t\t})\n
+\t\t\t.next()\n
+\t\t\t\t.attr( "role", "tabpanel" );\n
+\n
+\t\tthis.headers\n
+\t\t\t.not( this.active )\n
+\t\t\t.attr({\n
+\t\t\t\t"aria-selected": "false",\n
+\t\t\t\t"aria-expanded": "false",\n
+\t\t\t\ttabIndex: -1\n
+\t\t\t})\n
+\t\t\t.next()\n
+\t\t\t\t.attr({\n
+\t\t\t\t\t"aria-hidden": "true"\n
+\t\t\t\t})\n
+\t\t\t\t.hide();\n
+\n
+\t\t// make sure at least one header is in the tab order\n
+\t\tif ( !this.active.length ) {\n
+\t\t\tthis.headers.eq( 0 ).attr( "tabIndex", 0 );\n
+\t\t} else {\n
+\t\t\tthis.active.attr({\n
+\t\t\t\t"aria-selected": "true",\n
+\t\t\t\t"aria-expanded": "true",\n
+\t\t\t\ttabIndex: 0\n
+\t\t\t})\n
+\t\t\t.next()\n
+\t\t\t\t.attr({\n
+\t\t\t\t\t"aria-hidden": "false"\n
+\t\t\t\t});\n
+\t\t}\n
+\n
+\t\tthis._createIcons();\n
+\n
+\t\tthis._setupEvents( options.event );\n
+\n
+\t\tif ( heightStyle === "fill" ) {\n
+\t\t\tmaxHeight = parent.height();\n
+\t\t\tthis.element.siblings( ":visible" ).each(function() {\n
+\t\t\t\tvar elem = $( this ),\n
+\t\t\t\t\tposition = elem.css( "position" );\n
+\n
+\t\t\t\tif ( position === "absolute" || position === "fixed" ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\tmaxHeight -= elem.outerHeight( true );\n
+\t\t\t});\n
+\n
+\t\t\tthis.headers.each(function() {\n
+\t\t\t\tmaxHeight -= $( this ).outerHeight( true );\n
+\t\t\t});\n
+\n
+\t\t\tthis.headers.next()\n
+\t\t\t\t.each(function() {\n
+\t\t\t\t\t$( this ).height( Math.max( 0, maxHeight -\n
+\t\t\t\t\t\t$( this ).innerHeight() + $( this ).height() ) );\n
+\t\t\t\t})\n
+\t\t\t\t.css( "overflow", "auto" );\n
+\t\t} else if ( heightStyle === "auto" ) {\n
+\t\t\tmaxHeight = 0;\n
+\t\t\tthis.headers.next()\n
+\t\t\t\t.each(function() {\n
+\t\t\t\t\tmaxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );\n
+\t\t\t\t})\n
+\t\t\t\t.height( maxHeight );\n
+\t\t}\n
+\t},\n
+\n
+\t_activate: function( index ) {\n
+\t\tvar active = this._findActive( index )[ 0 ];\n
+\n
+\t\t// trying to activate the already active panel\n
+\t\tif ( active === this.active[ 0 ] ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// trying to collapse, simulate a click on the currently active header\n
+\t\tactive = active || this.active[ 0 ];\n
+\n
+\t\tthis._eventHandler({\n
+\t\t\ttarget: active,\n
+\t\t\tcurrentTarget: active,\n
+\t\t\tpreventDefault: $.noop\n
+\t\t});\n
+\t},\n
+\n
+\t_findActive: function( selector ) {\n
+\t\treturn typeof selector === "number" ? this.headers.eq( selector ) : $();\n
+\t},\n
+\n
+\t_setupEvents: function( event ) {\n
+\t\tvar events = {\n
+\t\t\tkeydown: "_keydown"\n
+\t\t};\n
+\t\tif ( event ) {\n
+\t\t\t$.each( event.split(" "), function( index, eventName ) {\n
+\t\t\t\tevents[ eventName ] = "_eventHandler";\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tthis._off( this.headers.add( this.headers.next() ) );\n
+\t\tthis._on( this.headers, events );\n
+\t\tthis._on( this.headers.next(), { keydown: "_panelKeyDown" });\n
+\t\tthis._hoverable( this.headers );\n
+\t\tthis._focusable( this.headers );\n
+\t},\n
+\n
+\t_eventHandler: function( event ) {\n
+\t\tvar options = this.options,\n
+\t\t\tactive = this.active,\n
+\t\t\tclicked = $( event.currentTarget ),\n
+\t\t\tclickedIsActive = clicked[ 0 ] === active[ 0 ],\n
+\t\t\tcollapsing = clickedIsActive && options.collapsible,\n
+\t\t\ttoShow = collapsing ? $() : clicked.next(),\n
+\t\t\ttoHide = active.next(),\n
+\t\t\teventData = {\n
+\t\t\t\toldHeader: active,\n
+\t\t\t\toldPanel: toHide,\n
+\t\t\t\tnewHeader: collapsing ? $() : clicked,\n
+\t\t\t\tnewPanel: toShow\n
+\t\t\t};\n
+\n
+\t\tevent.preventDefault();\n
+\n
+\t\tif (\n
+\t\t\t\t// click on active header, but not collapsible\n
+\t\t\t\t( clickedIsActive && !options.collapsible ) ||\n
+\t\t\t\t// allow canceling activation\n
+\t\t\t\t( this._trigger( "beforeActivate", event, eventData ) === false ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\toptions.active = collapsing ? false : this.headers.index( clicked );\n
+\n
+\t\t// when the call to ._toggle() comes after the class changes\n
+\t\t// it causes a very odd bug in IE 8 (see #6720)\n
+\t\tthis.active = clickedIsActive ? $() : clicked;\n
+\t\tthis._toggle( eventData );\n
+\n
+\t\t// switch classes\n
+\t\t// corner classes on the previously active header stay after the animation\n
+\t\tactive.removeClass( "ui-accordion-header-active ui-state-active" );\n
+\t\tif ( options.icons ) {\n
+\t\t\tactive.children( ".ui-accordion-header-icon" )\n
+\t\t\t\t.removeClass( options.icons.activeHeader )\n
+\t\t\t\t.addClass( options.icons.header );\n
+\t\t}\n
+\n
+\t\tif ( !clickedIsActive ) {\n
+\t\t\tclicked\n
+\t\t\t\t.removeClass( "ui-corner-all" )\n
+\t\t\t\t.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );\n
+\t\t\tif ( options.icons ) {\n
+\t\t\t\tclicked.children( ".ui-accordion-header-icon" )\n
+\t\t\t\t\t.removeClass( options.icons.header )\n
+\t\t\t\t\t.addClass( options.icons.activeHeader );\n
+\t\t\t}\n
+\n
+\t\t\tclicked\n
+\t\t\t\t.next()\n
+\t\t\t\t.addClass( "ui-accordion-content-active" );\n
+\t\t}\n
+\t},\n
+\n
+\t_toggle: function( data ) {\n
+\t\tvar toShow = data.newPanel,\n
+\t\t\ttoHide = this.prevShow.length ? this.prevShow : data.oldPanel;\n
+\n
+\t\t// handle activating a panel during the animation for another activation\n
+\t\tthis.prevShow.add( this.prevHide ).stop( true, true );\n
+\t\tthis.prevShow = toShow;\n
+\t\tthis.prevHide = toHide;\n
+\n
+\t\tif ( this.options.animate ) {\n
+\t\t\tthis._animate( toShow, toHide, data );\n
+\t\t} else {\n
+\t\t\ttoHide.hide();\n
+\t\t\ttoShow.show();\n
+\t\t\tthis._toggleComplete( data );\n
+\t\t}\n
+\n
+\t\ttoHide.attr({\n
+\t\t\t"aria-hidden": "true"\n
+\t\t});\n
+\t\ttoHide.prev().attr( "aria-selected", "false" );\n
+\t\t// if we\'re switching panels, remove the old header from the tab order\n
+\t\t// if we\'re opening from collapsed state, remove the previous header from the tab order\n
+\t\t// if we\'re collapsing, then keep the collapsing header in the tab order\n
+\t\tif ( toShow.length && toHide.length ) {\n
+\t\t\ttoHide.prev().attr({\n
+\t\t\t\t"tabIndex": -1,\n
+\t\t\t\t"aria-expanded": "false"\n
+\t\t\t});\n
+\t\t} else if ( toShow.length ) {\n
+\t\t\tthis.headers.filter(function() {\n
+\t\t\t\treturn $( this ).attr( "tabIndex" ) === 0;\n
+\t\t\t})\n
+\t\t\t.attr( "tabIndex", -1 );\n
+\t\t}\n
+\n
+\t\ttoShow\n
+\t\t\t.attr( "aria-hidden", "false" )\n
+\t\t\t.prev()\n
+\t\t\t\t.attr({\n
+\t\t\t\t\t"aria-selected": "true",\n
+\t\t\t\t\ttabIndex: 0,\n
+\t\t\t\t\t"aria-expanded": "true"\n
+\t\t\t\t});\n
+\t},\n
+\n
+\t_animate: function( toShow, toHide, data ) {\n
+\t\tvar total, easing, duration,\n
+\t\t\tthat = this,\n
+\t\t\tadjust = 0,\n
+\t\t\tdown = toShow.length &&\n
+\t\t\t\t( !toHide.length || ( toShow.index() < toHide.index() ) ),\n
+\t\t\tanimate = this.options.animate || {},\n
+\t\t\toptions = down && animate.down || animate,\n
+\t\t\tcomplete = function() {\n
+\t\t\t\tthat._toggleComplete( data );\n
+\t\t\t};\n
+\n
+\t\tif ( typeof options === "number" ) {\n
+\t\t\tduration = options;\n
+\t\t}\n
+\t\tif ( typeof options === "string" ) {\n
+\t\t\teasing = options;\n
+\t\t}\n
+\t\t// fall back from options to animation in case of partial down settings\n
+\t\teasing = easing || options.easing || animate.easing;\n
+\t\tduration = duration || options.duration || animate.duration;\n
+\n
+\t\tif ( !toHide.length ) {\n
+\t\t\treturn toShow.animate( showProps, duration, easing, complete );\n
+\t\t}\n
+\t\tif ( !toShow.length ) {\n
+\t\t\treturn toHide.animate( hideProps, duration, easing, complete );\n
+\t\t}\n
+\n
+\t\ttotal = toShow.show().outerHeight();\n
+\t\ttoHide.animate( hideProps, {\n
+\t\t\tduration: duration,\n
+\t\t\teasing: easing,\n
+\t\t\tstep: function( now, fx ) {\n
+\t\t\t\tfx.now = Math.round( now );\n
+\t\t\t}\n
+\t\t});\n
+\t\ttoShow\n
+\t\t\t.hide()\n
+\t\t\t.animate( showProps, {\n
+\t\t\t\tduration: duration,\n
+\t\t\t\teasing: easing,\n
+\t\t\t\tcomplete: complete,\n
+\t\t\t\tstep: function( now, fx ) {\n
+\t\t\t\t\tfx.now = Math.round( now );\n
+\t\t\t\t\tif ( fx.prop !== "height" ) {\n
+\t\t\t\t\t\tadjust += fx.now;\n
+\t\t\t\t\t} else if ( that.options.heightStyle !== "content" ) {\n
+\t\t\t\t\t\tfx.now = Math.round( total - toHide.outerHeight() - adjust );\n
+\t\t\t\t\t\tadjust = 0;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t},\n
+\n
+\t_toggleComplete: function( data ) {\n
+\t\tvar toHide = data.oldPanel;\n
+\n
+\t\ttoHide\n
+\t\t\t.removeClass( "ui-accordion-content-active" )\n
+\t\t\t.prev()\n
+\t\t\t\t.removeClass( "ui-corner-top" )\n
+\t\t\t\t.addClass( "ui-corner-all" );\n
+\n
+\t\t// Work around for rendering bug in IE (#5421)\n
+\t\tif ( toHide.length ) {\n
+\t\t\ttoHide.parent()[0].className = toHide.parent()[0].className;\n
+\t\t}\n
+\t\tthis._trigger( "activate", null, data );\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+(function( $, undefined ) {\n
+\n
+$.widget( "ui.autocomplete", {\n
+\tversion: "1.10.4",\n
+\tdefaultElement: "<input>",\n
+\toptions: {\n
+\t\tappendTo: null,\n
+\t\tautoFocus: false,\n
+\t\tdelay: 300,\n
+\t\tminLength: 1,\n
+\t\tposition: {\n
+\t\t\tmy: "left top",\n
+\t\t\tat: "left bottom",\n
+\t\t\tcollision: "none"\n
+\t\t},\n
+\t\tsource: null,\n
+\n
+\t\t// callbacks\n
+\t\tchange: null,\n
+\t\tclose: null,\n
+\t\tfocus: null,\n
+\t\topen: null,\n
+\t\tresponse: null,\n
+\t\tsearch: null,\n
+\t\tselect: null\n
+\t},\n
+\n
+\trequestIndex: 0,\n
+\tpending: 0,\n
+\n
+\t_create: function() {\n
+\t\t// Some browsers only repeat keydown events, not keypress events,\n
+\t\t// so we use the suppressKeyPress flag to determine if we\'ve already\n
+\t\t// handled the keydown event. #7269\n
+\t\t// Unfortunately the code for & in keypress is the same as the up arrow,\n
+\t\t// so we use the suppressKeyPressRepeat flag to avoid handling keypress\n
+\t\t// events when we know the keydown event was used to modify the\n
+\t\t// search term. #7799\n
+\t\tvar suppressKeyPress, suppressKeyPressRepeat, suppressInput,\n
+\t\t\tnodeName = this.element[0].nodeName.toLowerCase(),\n
+\t\t\tisTextarea = nodeName === "textarea",\n
+\t\t\tisInput = nodeName === "input";\n
+\n
+\t\tthis.isMultiLine =\n
+\t\t\t// Textareas are always multi-line\n
+\t\t\tisTextarea ? true :\n
+\t\t\t// Inputs are always single-line, even if inside a contentEditable element\n
+\t\t\t// IE also treats inputs as contentEditable\n
+\t\t\tisInput ? false :\n
+\t\t\t// All other element types are determined by whether or not they\'re contentEditable\n
+\t\t\tthis.element.prop( "isContentEditable" );\n
+\n
+\t\tthis.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];\n
+\t\tthis.isNewMenu = true;\n
+\n
+\t\tthis.element\n
+\t\t\t.addClass( "ui-autocomplete-input" )\n
+\t\t\t.attr( "autocomplete", "off" );\n
+\n
+\t\tthis._on( this.element, {\n
+\t\t\tkeydown: function( event ) {\n
+\t\t\t\tif ( this.element.prop( "readOnly" ) ) {\n
+\t\t\t\t\tsuppressKeyPress = true;\n
+\t\t\t\t\tsuppressInput = true;\n
+\t\t\t\t\tsuppressKeyPressRepeat = true;\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tsuppressKeyPress = false;\n
+\t\t\t\tsuppressInput = false;\n
+\t\t\t\tsuppressKeyPressRepeat = false;\n
+\t\t\t\tvar keyCode = $.ui.keyCode;\n
+\t\t\t\tswitch( event.keyCode ) {\n
+\t\t\t\tcase keyCode.PAGE_UP:\n
+\t\t\t\t\tsuppressKeyPress = true;\n
+\t\t\t\t\tthis._move( "previousPage", event );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase keyCode.PAGE_DOWN:\n
+\t\t\t\t\tsuppressKeyPress = true;\n
+\t\t\t\t\tthis._move( "nextPage", event );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase keyCode.UP:\n
+\t\t\t\t\tsuppressKeyPress = true;\n
+\t\t\t\t\tthis._keyEvent( "previous", event );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase keyCode.DOWN:\n
+\t\t\t\t\tsuppressKeyPress = true;\n
+\t\t\t\t\tthis._keyEvent( "next", event );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase keyCode.ENTER:\n
+\t\t\t\tcase keyCode.NUMPAD_ENTER:\n
+\t\t\t\t\t// when menu is open and has focus\n
+\t\t\t\t\tif ( this.menu.active ) {\n
+\t\t\t\t\t\t// #6055 - Opera still allows the keypress to occur\n
+\t\t\t\t\t\t// which causes forms to submit\n
+\t\t\t\t\t\tsuppressKeyPress = true;\n
+\t\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\t\tthis.menu.select( event );\n
+\t\t\t\t\t}\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase keyCode.TAB:\n
+\t\t\t\t\tif ( this.menu.active ) {\n
+\t\t\t\t\t\tthis.menu.select( event );\n
+\t\t\t\t\t}\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase keyCode.ESCAPE:\n
+\t\t\t\t\tif ( this.menu.element.is( ":visible" ) ) {\n
+\t\t\t\t\t\tthis._value( this.term );\n
+\t\t\t\t\t\tthis.close( event );\n
+\t\t\t\t\t\t// Different browsers have different default behavior for escape\n
+\t\t\t\t\t\t// Single press can mean undo or clear\n
+\t\t\t\t\t\t// Double press in IE means clear the whole form\n
+\t\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\t}\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tdefault:\n
+\t\t\t\t\tsuppressKeyPressRepeat = true;\n
+\t\t\t\t\t// search timeout should be triggered before the input value is changed\n
+\t\t\t\t\tthis._searchTimeout( event );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tkeypress: function( event ) {\n
+\t\t\t\tif ( suppressKeyPress ) {\n
+\t\t\t\t\tsuppressKeyPress = false;\n
+\t\t\t\t\tif ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {\n
+\t\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\tif ( suppressKeyPressRepeat ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// replicate some key handlers to allow them to repeat in Firefox and Opera\n
+\t\t\t\tvar keyCode = $.ui.keyCode;\n
+\t\t\t\tswitch( event.keyCode ) {\n
+\t\t\t\tcase keyCode.PAGE_UP:\n
+\t\t\t\t\tthis._move( "previousPage", event );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase keyCode.PAGE_DOWN:\n
+\t\t\t\t\tthis._move( "nextPage", event );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase keyCode.UP:\n
+\t\t\t\t\tthis._keyEvent( "previous", event );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase keyCode.DOWN:\n
+\t\t\t\t\tthis._keyEvent( "next", event );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tinput: function( event ) {\n
+\t\t\t\tif ( suppressInput ) {\n
+\t\t\t\t\tsuppressInput = false;\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\tthis._searchTimeout( event );\n
+\t\t\t},\n
+\t\t\tfocus: function() {\n
+\t\t\t\tthis.selectedItem = null;\n
+\t\t\t\tthis.previous = this._value();\n
+\t\t\t},\n
+\t\t\tblur: function( event ) {\n
+\t\t\t\tif ( this.cancelBlur ) {\n
+\t\t\t\t\tdelete this.cancelBlur;\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tclearTimeout( this.searching );\n
+\t\t\t\tthis.close( event );\n
+\t\t\t\tthis._change( event );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tthis._initSource();\n
+\t\tthis.menu = $( "<ul>" )\n
+\t\t\t.addClass( "ui-autocomplete ui-front" )\n
+\t\t\t.appendTo( this._appendTo() )\n
+\t\t\t.menu({\n
+\t\t\t\t// disable ARIA support, the live region takes care of that\n
+\t\t\t\trole: null\n
+\t\t\t})\n
+\t\t\t.hide()\n
+\t\t\t.data( "ui-menu" );\n
+\n
+\t\tthis._on( this.menu.element, {\n
+\t\t\tmousedown: function( event ) {\n
+\t\t\t\t// prevent moving focus out of the text field\n
+\t\t\t\tevent.preventDefault();\n
+\n
+\t\t\t\t// IE doesn\'t prevent moving focus even with event.preventDefault()\n
+\t\t\t\t// so we set a flag to know when we should ignore the blur event\n
+\t\t\t\tthis.cancelBlur = true;\n
+\t\t\t\tthis._delay(function() {\n
+\t\t\t\t\tdelete this.cancelBlur;\n
+\t\t\t\t});\n
+\n
+\t\t\t\t// clicking on the scrollbar causes focus to shift to the body\n
+\t\t\t\t// but we can\'t detect a mouseup or a click immediately afterward\n
+\t\t\t\t// so we have to track the next mousedown and close the menu if\n
+\t\t\t\t// the user clicks somewhere outside of the autocomplete\n
+\t\t\t\tvar menuElement = this.menu.element[ 0 ];\n
+\t\t\t\tif ( !$( event.target ).closest( ".ui-menu-item" ).length ) {\n
+\t\t\t\t\tthis._delay(function() {\n
+\t\t\t\t\t\tvar that = this;\n
+\t\t\t\t\t\tthis.document.one( "mousedown", function( event ) {\n
+\t\t\t\t\t\t\tif ( event.target !== that.element[ 0 ] &&\n
+\t\t\t\t\t\t\t\t\tevent.target !== menuElement &&\n
+\t\t\t\t\t\t\t\t\t!$.contains( menuElement, event.target ) ) {\n
+\t\t\t\t\t\t\t\tthat.close();\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t});\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tmenufocus: function( event, ui ) {\n
+\t\t\t\t// support: Firefox\n
+\t\t\t\t// Prevent accidental activation of menu items in Firefox (#7024 #9118)\n
+\t\t\t\tif ( this.isNewMenu ) {\n
+\t\t\t\t\tthis.isNewMenu = false;\n
+\t\t\t\t\tif ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {\n
+\t\t\t\t\t\tthis.menu.blur();\n
+\n
+\t\t\t\t\t\tthis.document.one( "mousemove", function() {\n
+\t\t\t\t\t\t\t$( event.target ).trigger( event.originalEvent );\n
+\t\t\t\t\t\t});\n
+\n
+\t\t\t\t\t\treturn;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\tvar item = ui.item.data( "ui-autocomplete-item" );\n
+\t\t\t\tif ( false !== this._trigger( "focus", event, { item: item } ) ) {\n
+\t\t\t\t\t// use value to match what will end up in the input, if it was a key event\n
+\t\t\t\t\tif ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {\n
+\t\t\t\t\t\tthis._value( item.value );\n
+\t\t\t\t\t}\n
+\t\t\t\t} else {\n
+\t\t\t\t\t// Normally the input is populated with the item\'s value as the\n
+\t\t\t\t\t// menu is navigated, causing screen readers to notice a change and\n
+\t\t\t\t\t// announce the item. Since the focus event was canceled, this doesn\'t\n
+\t\t\t\t\t// happen, so we update the live region so that screen readers can\n
+\t\t\t\t\t// still notice the change and announce it.\n
+\t\t\t\t\tthis.liveRegion.text( item.value );\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tmenuselect: function( event, ui ) {\n
+\t\t\t\tvar item = ui.item.data( "ui-autocomplete-item" ),\n
+\t\t\t\t\tprevious = this.previous;\n
+\n
+\t\t\t\t// only trigger when focus was lost (click on menu)\n
+\t\t\t\tif ( this.element[0] !== this.document[0].activeElement ) {\n
+\t\t\t\t\tthis.element.focus();\n
+\t\t\t\t\tthis.previous = previous;\n
+\t\t\t\t\t// #6109 - IE triggers two focus events and the second\n
+\t\t\t\t\t// is asynchronous, so we need to reset the previous\n
+\t\t\t\t\t// term synchronously and asynchronously :-(\n
+\t\t\t\t\tthis._delay(function() {\n
+\t\t\t\t\t\tthis.previous = previous;\n
+\t\t\t\t\t\tthis.selectedItem = item;\n
+\t\t\t\t\t});\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif ( false !== this._trigger( "select", event, { item: item } ) ) {\n
+\t\t\t\t\tthis._value( item.value );\n
+\t\t\t\t}\n
+\t\t\t\t// reset the term after the select event\n
+\t\t\t\t// this allows custom select handling to work properly\n
+\t\t\t\tthis.term = this._value();\n
+\n
+\t\t\t\tthis.close( event );\n
+\t\t\t\tthis.selectedItem = item;\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tthis.liveRegion = $( "<span>", {\n
+\t\t\t\trole: "status",\n
+\t\t\t\t"aria-live": "polite"\n
+\t\t\t})\n
+\t\t\t.addClass( "ui-helper-hidden-accessible" )\n
+\t\t\t.insertBefore( this.element );\n
+\n
+\t\t// turning off autocomplete prevents the browser from remembering the\n
+\t\t// value when navigating through history, so we re-enable autocomplete\n
+\t\t// if the page is unloaded before the widget is destroyed. #7790\n
+\t\tthis._on( this.window, {\n
+\t\t\tbeforeunload: function() {\n
+\t\t\t\tthis.element.removeAttr( "autocomplete" );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tclearTimeout( this.searching );\n
+\t\tthis.element\n
+\t\t\t.removeClass( "ui-autocomplete-input" )\n
+\t\t\t.removeAttr( "autocomplete" );\n
+\t\tthis.menu.element.remove();\n
+\t\tthis.liveRegion.remove();\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tthis._super( key, value );\n
+\t\tif ( key === "source" ) {\n
+\t\t\tthis._initSource();\n
+\t\t}\n
+\t\tif ( key === "appendTo" ) {\n
+\t\t\tthis.menu.element.appendTo( this._appendTo() );\n
+\t\t}\n
+\t\tif ( key === "disabled" && value && this.xhr ) {\n
+\t\t\tthis.xhr.abort();\n
+\t\t}\n
+\t},\n
+\n
+\t_appendTo: function() {\n
+\t\tvar element = this.options.appendTo;\n
+\n
+\t\tif ( element ) {\n
+\t\t\telement = element.jquery || element.nodeType ?\n
+\t\t\t\t$( element ) :\n
+\t\t\t\tthis.document.find( element ).eq( 0 );\n
+\t\t}\n
+\n
+\t\tif ( !element ) {\n
+\t\t\telement = this.element.closest( ".ui-front" );\n
+\t\t}\n
+\n
+\t\tif ( !element.length ) {\n
+\t\t\telement = this.document[0].body;\n
+\t\t}\n
+\n
+\t\treturn element;\n
+\t},\n
+\n
+\t_initSource: function() {\n
+\t\tvar array, url,\n
+\t\t\tthat = this;\n
+\t\tif ( $.isArray(this.options.source) ) {\n
+\t\t\tarray = this.options.source;\n
+\t\t\tthis.source = function( request, response ) {\n
+\t\t\t\tresponse( $.ui.autocomplete.filter( array, request.term ) );\n
+\t\t\t};\n
+\t\t} else if ( typeof this.options.source === "string" ) {\n
+\t\t\turl = this.options.source;\n
+\t\t\tthis.source = function( request, response ) {\n
+\t\t\t\tif ( that.xhr ) {\n
+\t\t\t\t\tthat.xhr.abort();\n
+\t\t\t\t}\n
+\t\t\t\tthat.xhr = $.ajax({\n
+\t\t\t\t\turl: url,\n
+\t\t\t\t\tdata: request,\n
+\t\t\t\t\tdataType: "json",\n
+\t\t\t\t\tsuccess: function( data ) {\n
+\t\t\t\t\t\tresponse( data );\n
+\t\t\t\t\t},\n
+\t\t\t\t\terror: function() {\n
+\t\t\t\t\t\tresponse( [] );\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t};\n
+\t\t} else {\n
+\t\t\tthis.source = this.options.source;\n
+\t\t}\n
+\t},\n
+\n
+\t_searchTimeout: function( event ) {\n
+\t\tclearTimeout( this.searching );\n
+\t\tthis.searching = this._delay(function() {\n
+\t\t\t// only search if the value has changed\n
+\t\t\tif ( this.term !== this._value() ) {\n
+\t\t\t\tthis.selectedItem = null;\n
+\t\t\t\tthis.search( null, event );\n
+\t\t\t}\n
+\t\t}, this.options.delay );\n
+\t},\n
+\n
+\tsearch: function( value, event ) {\n
+\t\tvalue = value != null ? value : this._value();\n
+\n
+\t\t// always save the actual value, not the one passed as an argument\n
+\t\tthis.term = this._value();\n
+\n
+\t\tif ( value.length < this.options.minLength ) {\n
+\t\t\treturn this.close( event );\n
+\t\t}\n
+\n
+\t\tif ( this._trigger( "search", event ) === false ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\treturn this._search( value );\n
+\t},\n
+\n
+\t_search: function( value ) {\n
+\t\tthis.pending++;\n
+\t\tthis.element.addClass( "ui-autocomplete-loading" );\n
+\t\tthis.cancelSearch = false;\n
+\n
+\t\tthis.source( { term: value }, this._response() );\n
+\t},\n
+\n
+\t_response: function() {\n
+\t\tvar index = ++this.requestIndex;\n
+\n
+\t\treturn $.proxy(function( content ) {\n
+\t\t\tif ( index === this.requestIndex ) {\n
+\t\t\t\tthis.__response( content );\n
+\t\t\t}\n
+\n
+\t\t\tthis.pending--;\n
+\t\t\tif ( !this.pending ) {\n
+\t\t\t\tthis.element.removeClass( "ui-autocomplete-loading" );\n
+\t\t\t}\n
+\t\t}, this );\n
+\t},\n
+\n
+\t__response: function( content ) {\n
+\t\tif ( content ) {\n
+\t\t\tcontent = this._normalize( content );\n
+\t\t}\n
+\t\tthis._trigger( "response", null, { content: content } );\n
+\t\tif ( !this.options.disabled && content && content.length && !this.cancelSearch ) {\n
+\t\t\tthis._suggest( content );\n
+\t\t\tthis._trigger( "open" );\n
+\t\t} else {\n
+\t\t\t// use ._close() instead of .close() so we don\'t cancel future searches\n
+\t\t\tthis._close();\n
+\t\t}\n
+\t},\n
+\n
+\tclose: function( event ) {\n
+\t\tthis.cancelSearch = true;\n
+\t\tthis._close( event );\n
+\t},\n
+\n
+\t_close: function( event ) {\n
+\t\tif ( this.menu.element.is( ":visible" ) ) {\n
+\t\t\tthis.menu.element.hide();\n
+\t\t\tthis.menu.blur();\n
+\t\t\tthis.isNewMenu = true;\n
+\t\t\tthis._trigger( "close", event );\n
+\t\t}\n
+\t},\n
+\n
+\t_change: function( event ) {\n
+\t\tif ( this.previous !== this._value() ) {\n
+\t\t\tthis._trigger( "change", event, { item: this.selectedItem } );\n
+\t\t}\n
+\t},\n
+\n
+\t_normalize: function( items ) {\n
+\t\t// assume all items have the right format when the first item is complete\n
+\t\tif ( items.length && items[0].label && items[0].value ) {\n
+\t\t\treturn items;\n
+\t\t}\n
+\t\treturn $.map( items, function( item ) {\n
+\t\t\tif ( typeof item === "string" ) {\n
+\t\t\t\treturn {\n
+\t\t\t\t\tlabel: item,\n
+\t\t\t\t\tvalue: item\n
+\t\t\t\t};\n
+\t\t\t}\n
+\t\t\treturn $.extend({\n
+\t\t\t\tlabel: item.label || item.value,\n
+\t\t\t\tvalue: item.value || item.label\n
+\t\t\t}, item );\n
+\t\t});\n
+\t},\n
+\n
+\t_suggest: function( items ) {\n
+\t\tvar ul = this.menu.element.empty();\n
+\t\tthis._renderMenu( ul, items );\n
+\t\tthis.isNewMenu = true;\n
+\t\tthis.menu.refresh();\n
+\n
+\t\t// size and position menu\n
+\t\tul.show();\n
+\t\tthis._resizeMenu();\n
+\t\tul.position( $.extend({\n
+\t\t\tof: this.element\n
+\t\t}, this.options.position ));\n
+\n
+\t\tif ( this.options.autoFocus ) {\n
+\t\t\tthis.menu.next();\n
+\t\t}\n
+\t},\n
+\n
+\t_resizeMenu: function() {\n
+\t\tvar ul = this.menu.element;\n
+\t\tul.outerWidth( Math.max(\n
+\t\t\t// Firefox wraps long text (possibly a rounding bug)\n
+\t\t\t// so we add 1px to avoid the wrapping (#7513)\n
+\t\t\tul.width( "" ).outerWidth() + 1,\n
+\t\t\tthis.element.outerWidth()\n
+\t\t) );\n
+\t},\n
+\n
+\t_renderMenu: function( ul, items ) {\n
+\t\tvar that = this;\n
+\t\t$.each( items, function( index, item ) {\n
+\t\t\tthat._renderItemData( ul, item );\n
+\t\t});\n
+\t},\n
+\n
+\t_renderItemData: function( ul, item ) {\n
+\t\treturn this._renderItem( ul, item ).data( "ui-autocomplete-item", item );\n
+\t},\n
+\n
+\t_renderItem: function( ul, item ) {\n
+\t\treturn $( "<li>" )\n
+\t\t\t.append( $( "<a>" ).text( item.label ) )\n
+\t\t\t.appendTo( ul );\n
+\t},\n
+\n
+\t_move: function( direction, event ) {\n
+\t\tif ( !this.menu.element.is( ":visible" ) ) {\n
+\t\t\tthis.search( null, event );\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tif ( this.menu.isFirstItem() && /^previous/.test( direction ) ||\n
+\t\t\t\tthis.menu.isLastItem() && /^next/.test( direction ) ) {\n
+\t\t\tthis._value( this.term );\n
+\t\t\tthis.menu.blur();\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tthis.menu[ direction ]( event );\n
+\t},\n
+\n
+\twidget: function() {\n
+\t\treturn this.menu.element;\n
+\t},\n
+\n
+\t_value: function() {\n
+\t\treturn this.valueMethod.apply( this.element, arguments );\n
+\t},\n
+\n
+\t_keyEvent: function( keyEvent, event ) {\n
+\t\tif ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {\n
+\t\t\tthis._move( keyEvent, event );\n
+\n
+\t\t\t// prevents moving cursor to beginning/end of the text field in some browsers\n
+\t\t\tevent.preventDefault();\n
+\t\t}\n
+\t}\n
+});\n
+\n
+$.extend( $.ui.autocomplete, {\n
+\tescapeRegex: function( value ) {\n
+\t\treturn value.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, "\\\\$&");\n
+\t},\n
+\tfilter: function(array, term) {\n
+\t\tvar matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );\n
+\t\treturn $.grep( array, function(value) {\n
+\t\t\treturn matcher.test( value.label || value.value || value );\n
+\t\t});\n
+\t}\n
+});\n
+\n
+\n
+// live region extension, adding a `messages` option\n
+// NOTE: This is an experimental API. We are still investigating\n
+// a full solution for string manipulation and internationalization.\n
+$.widget( "ui.autocomplete", $.ui.autocomplete, {\n
+\toptions: {\n
+\t\tmessages: {\n
+\t\t\tnoResults: "No search results.",\n
+\t\t\tresults: function( amount ) {\n
+\t\t\t\treturn amount + ( amount > 1 ? " results are" : " result is" ) +\n
+\t\t\t\t\t" available, use up and down arrow keys to navigate.";\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t__response: function( content ) {\n
+\t\tvar message;\n
+\t\tthis._superApply( arguments );\n
+\t\tif ( this.options.disabled || this.cancelSearch ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tif ( content && content.length ) {\n
+\t\t\tmessage = this.options.messages.results( content.length );\n
+\t\t} else {\n
+\t\t\tmessage = this.options.messages.noResults;\n
+\t\t}\n
+\t\tthis.liveRegion.text( message );\n
+\t}\n
+});\n
+\n
+}( jQuery ));\n
+(function( $, undefined ) {\n
+\n
+var lastActive,\n
+\tbaseClasses = "ui-button ui-widget ui-state-default ui-corner-all",\n
+\ttypeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",\n
+\tformResetHandler = function() {\n
+\t\tvar form = $( this );\n
+\t\tsetTimeout(function() {\n
+\t\t\tform.find( ":ui-button" ).button( "refresh" );\n
+\t\t}, 1 );\n
+\t},\n
+\tradioGroup = function( radio ) {\n
+\t\tvar name = radio.name,\n
+\t\t\tform = radio.form,\n
+\t\t\tradios = $( [] );\n
+\t\tif ( name ) {\n
+\t\t\tname = name.replace( /\'/g, "\\\\\'" );\n
+\t\t\tif ( form ) {\n
+\t\t\t\tradios = $( form ).find( "[name=\'" + name + "\']" );\n
+\t\t\t} else {\n
+\t\t\t\tradios = $( "[name=\'" + name + "\']", radio.ownerDocument )\n
+\t\t\t\t\t.filter(function() {\n
+\t\t\t\t\t\treturn !this.form;\n
+\t\t\t\t\t});\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn radios;\n
+\t};\n
+\n
+$.widget( "ui.button", {\n
+\tversion: "1.10.4",\n
+\tdefaultElement: "<button>",\n
+\toptions: {\n
+\t\tdisabled: null,\n
+\t\ttext: true,\n
+\t\tlabel: null,\n
+\t\ticons: {\n
+\t\t\tprimary: null,\n
+\t\t\tsecondary: null\n
+\t\t}\n
+\t},\n
+\t_create: function() {\n
+\t\tthis.element.closest( "form" )\n
+\t\t\t.unbind( "reset" + this.eventNamespace )\n
+\t\t\t.bind( "reset" + this.eventNamespace, formResetHandler );\n
+\n
+\t\tif ( typeof this.options.disabled !== "boolean" ) {\n
+\t\t\tthis.options.disabled = !!this.element.prop( "disabled" );\n
+\t\t} else {\n
+\t\t\tthis.element.prop( "disabled", this.options.disabled );\n
+\t\t}\n
+\n
+\t\tthis._determineButtonType();\n
+\t\tthis.hasTitle = !!this.buttonElement.attr( "title" );\n
+\n
+\t\tvar that = this,\n
+\t\t\toptions = this.options,\n
+\t\t\ttoggleButton = this.type === "checkbox" || this.type === "radio",\n
+\t\t\tactiveClass = !toggleButton ? "ui-state-active" : "";\n
+\n
+\t\tif ( options.label === null ) {\n
+\t\t\toptions.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());\n
+\t\t}\n
+\n
+\t\tthis._hoverable( this.buttonElement );\n
+\n
+\t\tthis.buttonElement\n
+\t\t\t.addClass( baseClasses )\n
+\t\t\t.attr( "role", "button" )\n
+\t\t\t.bind( "mouseenter" + this.eventNamespace, function() {\n
+\t\t\t\tif ( options.disabled ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\tif ( this === lastActive ) {\n
+\t\t\t\t\t$( this ).addClass( "ui-state-active" );\n
+\t\t\t\t}\n
+\t\t\t})\n
+\t\t\t.bind( "mouseleave" + this.eventNamespace, function() {\n
+\t\t\t\tif ( options.disabled ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\t$( this ).removeClass( activeClass );\n
+\t\t\t})\n
+\t\t\t.bind( "click" + this.eventNamespace, function( event ) {\n
+\t\t\t\tif ( options.disabled ) {\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\tevent.stopImmediatePropagation();\n
+\t\t\t\t}\n
+\t\t\t});\n
+\n
+\t\t// Can\'t use _focusable() because the element that receives focus\n
+\t\t// and the element that gets the ui-state-focus class are different\n
+\t\tthis._on({\n
+\t\t\tfocus: function() {\n
+\t\t\t\tthis.buttonElement.addClass( "ui-state-focus" );\n
+\t\t\t},\n
+\t\t\tblur: function() {\n
+\t\t\t\tthis.buttonElement.removeClass( "ui-state-focus" );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tif ( toggleButton ) {\n
+\t\t\tthis.element.bind( "change" + this.eventNamespace, function() {\n
+\t\t\t\tthat.refresh();\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tif ( this.type === "checkbox" ) {\n
+\t\t\tthis.buttonElement.bind( "click" + this.eventNamespace, function() {\n
+\t\t\t\tif ( options.disabled ) {\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t} else if ( this.type === "radio" ) {\n
+\t\t\tthis.buttonElement.bind( "click" + this.eventNamespace, function() {\n
+\t\t\t\tif ( options.disabled ) {\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t\t$( this ).addClass( "ui-state-active" );\n
+\t\t\t\tthat.buttonElement.attr( "aria-pressed", "true" );\n
+\n
+\t\t\t\tvar radio = that.element[ 0 ];\n
+\t\t\t\tradioGroup( radio )\n
+\t\t\t\t\t.not( radio )\n
+\t\t\t\t\t.map(function() {\n
+\t\t\t\t\t\treturn $( this ).button( "widget" )[ 0 ];\n
+\t\t\t\t\t})\n
+\t\t\t\t\t.removeClass( "ui-state-active" )\n
+\t\t\t\t\t.attr( "aria-pressed", "false" );\n
+\t\t\t});\n
+\t\t} else {\n
+\t\t\tthis.buttonElement\n
+\t\t\t\t.bind( "mousedown" + this.eventNamespace, function() {\n
+\t\t\t\t\tif ( options.disabled ) {\n
+\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t}\n
+\t\t\t\t\t$( this ).addClass( "ui-state-active" );\n
+\t\t\t\t\tlastActive = this;\n
+\t\t\t\t\tthat.document.one( "mouseup", function() {\n
+\t\t\t\t\t\tlastActive = null;\n
+\t\t\t\t\t});\n
+\t\t\t\t})\n
+\t\t\t\t.bind( "mouseup" + this.eventNamespace, function() {\n
+\t\t\t\t\tif ( options.disabled ) {\n
+\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t}\n
+\t\t\t\t\t$( this ).removeClass( "ui-state-active" );\n
+\t\t\t\t})\n
+\t\t\t\t.bind( "keydown" + this.eventNamespace, function(event) {\n
+\t\t\t\t\tif ( options.disabled ) {\n
+\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {\n
+\t\t\t\t\t\t$( this ).addClass( "ui-state-active" );\n
+\t\t\t\t\t}\n
+\t\t\t\t})\n
+\t\t\t\t// see #8559, we bind to blur here in case the button element loses\n
+\t\t\t\t// focus between keydown and keyup, it would be left in an "active" state\n
+\t\t\t\t.bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {\n
+\t\t\t\t\t$( this ).removeClass( "ui-state-active" );\n
+\t\t\t\t});\n
+\n
+\t\t\tif ( this.buttonElement.is("a") ) {\n
+\t\t\t\tthis.buttonElement.keyup(function(event) {\n
+\t\t\t\t\tif ( event.keyCode === $.ui.keyCode.SPACE ) {\n
+\t\t\t\t\t\t// TODO pass through original event correctly (just as 2nd argument doesn\'t work)\n
+\t\t\t\t\t\t$( this ).click();\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// TODO: pull out $.Widget\'s handling for the disabled option into\n
+\t\t// $.Widget.prototype._setOptionDisabled so it\'s easy to proxy and can\n
+\t\t// be overridden by individual plugins\n
+\t\tthis._setOption( "disabled", options.disabled );\n
+\t\tthis._resetButton();\n
+\t},\n
+\n
+\t_determineButtonType: function() {\n
+\t\tvar ancestor, labelSelector, checked;\n
+\n
+\t\tif ( this.element.is("[type=checkbox]") ) {\n
+\t\t\tthis.type = "checkbox";\n
+\t\t} else if ( this.element.is("[type=radio]") ) {\n
+\t\t\tthis.type = "radio";\n
+\t\t} else if ( this.element.is("input") ) {\n
+\t\t\tthis.type = "input";\n
+\t\t} else {\n
+\t\t\tthis.type = "button";\n
+\t\t}\n
+\n
+\t\tif ( this.type === "checkbox" || this.type === "radio" ) {\n
+\t\t\t// we don\'t search against the document in case the element\n
+\t\t\t// is disconnected from the DOM\n
+\t\t\tancestor = this.element.parents().last();\n
+\t\t\tlabelSelector = "label[for=\'" + this.element.attr("id") + "\']";\n
+\t\t\tthis.buttonElement = ancestor.find( labelSelector );\n
+\t\t\tif ( !this.buttonElement.length ) {\n
+\t\t\t\tancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();\n
+\t\t\t\tthis.buttonElement = ancestor.filter( labelSelector );\n
+\t\t\t\tif ( !this.buttonElement.length ) {\n
+\t\t\t\t\tthis.buttonElement = ancestor.find( labelSelector );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tthis.element.addClass( "ui-helper-hidden-accessible" );\n
+\n
+\t\t\tchecked = this.element.is( ":checked" );\n
+\t\t\tif ( checked ) {\n
+\t\t\t\tthis.buttonElement.addClass( "ui-state-active" );\n
+\t\t\t}\n
+\t\t\tthis.buttonElement.prop( "aria-pressed", checked );\n
+\t\t} else {\n
+\t\t\tthis.buttonElement = this.element;\n
+\t\t}\n
+\t},\n
+\n
+\twidget: function() {\n
+\t\treturn this.buttonElement;\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tthis.element\n
+\t\t\t.removeClass( "ui-helper-hidden-accessible" );\n
+\t\tthis.buttonElement\n
+\t\t\t.removeClass( baseClasses + " ui-state-active " + typeClasses )\n
+\t\t\t.removeAttr( "role" )\n
+\t\t\t.removeAttr( "aria-pressed" )\n
+\t\t\t.html( this.buttonElement.find(".ui-button-text").html() );\n
+\n
+\t\tif ( !this.hasTitle ) {\n
+\t\t\tthis.buttonElement.removeAttr( "title" );\n
+\t\t}\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tthis._super( key, value );\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\tthis.element.prop( "disabled", !!value );\n
+\t\t\tif ( value ) {\n
+\t\t\t\tthis.buttonElement.removeClass( "ui-state-focus" );\n
+\t\t\t}\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tthis._resetButton();\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\t//See #8237 & #8828\n
+\t\tvar isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );\n
+\n
+\t\tif ( isDisabled !== this.options.disabled ) {\n
+\t\t\tthis._setOption( "disabled", isDisabled );\n
+\t\t}\n
+\t\tif ( this.type === "radio" ) {\n
+\t\t\tradioGroup( this.element[0] ).each(function() {\n
+\t\t\t\tif ( $( this ).is( ":checked" ) ) {\n
+\t\t\t\t\t$( this ).button( "widget" )\n
+\t\t\t\t\t\t.addClass( "ui-state-active" )\n
+\t\t\t\t\t\t.attr( "aria-pressed", "true" );\n
+\t\t\t\t} else {\n
+\t\t\t\t\t$( this ).button( "widget" )\n
+\t\t\t\t\t\t.removeClass( "ui-state-active" )\n
+\t\t\t\t\t\t.attr( "aria-pressed", "false" );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t} else if ( this.type === "checkbox" ) {\n
+\t\t\tif ( this.element.is( ":checked" ) ) {\n
+\t\t\t\tthis.buttonElement\n
+\t\t\t\t\t.addClass( "ui-state-active" )\n
+\t\t\t\t\t.attr( "aria-pressed", "true" );\n
+\t\t\t} else {\n
+\t\t\t\tthis.buttonElement\n
+\t\t\t\t\t.removeClass( "ui-state-active" )\n
+\t\t\t\t\t.attr( "aria-pressed", "false" );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t_resetButton: function() {\n
+\t\tif ( this.type === "input" ) {\n
+\t\t\tif ( this.options.label ) {\n
+\t\t\t\tthis.element.val( this.options.label );\n
+\t\t\t}\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tvar buttonElement = this.buttonElement.removeClass( typeClasses ),\n
+\t\t\tbuttonText = $( "<span></span>", this.document[0] )\n
+\t\t\t\t.addClass( "ui-button-text" )\n
+\t\t\t\t.html( this.options.label )\n
+\t\t\t\t.appendTo( buttonElement.empty() )\n
+\t\t\t\t.text(),\n
+\t\t\ticons = this.options.icons,\n
+\t\t\tmultipleIcons = icons.primary && icons.secondary,\n
+\t\t\tbuttonClasses = [];\n
+\n
+\t\tif ( icons.primary || icons.secondary ) {\n
+\t\t\tif ( this.options.text ) {\n
+\t\t\t\tbuttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );\n
+\t\t\t}\n
+\n
+\t\t\tif ( icons.primary ) {\n
+\t\t\t\tbuttonElement.prepend( "<span class=\'ui-button-icon-primary ui-icon " + icons.primary + "\'></span>" );\n
+\t\t\t}\n
+\n
+\t\t\tif ( icons.secondary ) {\n
+\t\t\t\tbuttonElement.append( "<span class=\'ui-button-icon-secondary ui-icon " + icons.secondary + "\'></span>" );\n
+\t\t\t}\n
+\n
+\t\t\tif ( !this.options.text ) {\n
+\t\t\t\tbuttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );\n
+\n
+\t\t\t\tif ( !this.hasTitle ) {\n
+\t\t\t\t\tbuttonElement.attr( "title", $.trim( buttonText ) );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tbuttonClasses.push( "ui-button-text-only" );\n
+\t\t}\n
+\t\tbuttonElement.addClass( buttonClasses.join( " " ) );\n
+\t}\n
+});\n
+\n
+$.widget( "ui.buttonset", {\n
+\tversion: "1.10.4",\n
+\toptions: {\n
+\t\titems: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tthis.element.addClass( "ui-buttonset" );\n
+\t},\n
+\n
+\t_init: function() {\n
+\t\tthis.refresh();\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\tthis.buttons.button( "option", key, value );\n
+\t\t}\n
+\n
+\t\tthis._super( key, value );\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tvar rtl = this.element.css( "direction" ) === "rtl";\n
+\n
+\t\tthis.buttons = this.element.find( this.options.items )\n
+\t\t\t.filter( ":ui-button" )\n
+\t\t\t\t.button( "refresh" )\n
+\t\t\t.end()\n
+\t\t\t.not( ":ui-button" )\n
+\t\t\t\t.button()\n
+\t\t\t.end()\n
+\t\t\t.map(function() {\n
+\t\t\t\treturn $( this ).button( "widget" )[ 0 ];\n
+\t\t\t})\n
+\t\t\t\t.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )\n
+\t\t\t\t.filter( ":first" )\n
+\t\t\t\t\t.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )\n
+\t\t\t\t.end()\n
+\t\t\t\t.filter( ":last" )\n
+\t\t\t\t\t.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )\n
+\t\t\t\t.end()\n
+\t\t\t.end();\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tthis.element.removeClass( "ui-buttonset" );\n
+\t\tthis.buttons\n
+\t\t\t.map(function() {\n
+\t\t\t\treturn $( this ).button( "widget" )[ 0 ];\n
+\t\t\t})\n
+\t\t\t\t.removeClass( "ui-corner-left ui-corner-right" )\n
+\t\t\t.end()\n
+\t\t\t.button( "destroy" );\n
+\t}\n
+});\n
+\n
+}( jQuery ) );\n
+(function( $, undefined ) {\n
+\n
+$.extend($.ui, { datepicker: { version: "1.10.4" } });\n
+\n
+var PROP_NAME = "datepicker",\n
+\tinstActive;\n
+\n
+/* Date picker manager.\n
+   Use the singleton instance of this class, $.datepicker, to interact with the date picker.\n
+   Settings for (groups of) date pickers are maintained in an instance object,\n
+   allowing multiple different settings on the same page. */\n
+\n
+function Datepicker() {\n
+\tthis._curInst = null; // The current instance in use\n
+\tthis._keyEvent = false; // If the last event was a key event\n
+\tthis._disabledInputs = []; // List of date picker inputs that have been disabled\n
+\tthis._datepickerShowing = false; // True if the popup picker is showing , false if not\n
+\tthis._inDialog = false; // True if showing within a "dialog", false if not\n
+\tthis._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division\n
+\tthis._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class\n
+\tthis._appendClass = "ui-datepicker-append"; // The name of the append marker class\n
+\tthis._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class\n
+\tthis._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class\n
+\tthis._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class\n
+\tthis._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class\n
+\tthis._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class\n
+\tthis._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class\n
+\tthis.regional = []; // Available regional settings, indexed by language code\n
+\tthis.regional[""] = { // Default regional settings\n
+\t\tcloseText: "Done", // Display text for close link\n
+\t\tprevText: "Prev", // Display text for previous month link\n
+\t\tnextText: "Next", // Display text for next month link\n
+\t\tcurrentText: "Today", // Display text for current month link\n
+\t\tmonthNames: ["January","February","March","April","May","June",\n
+\t\t\t"July","August","September","October","November","December"], // Names of months for drop-down and formatting\n
+\t\tmonthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting\n
+\t\tdayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting\n
+\t\tdayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting\n
+\t\tdayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday\n
+\t\tweekHeader: "Wk", // Column header for week of the year\n
+\t\tdateFormat: "mm/dd/yy", // See format options on parseDate\n
+\t\tfirstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...\n
+\t\tisRTL: false, // True if right-to-left language, false if left-to-right\n
+\t\tshowMonthAfterYear: false, // True if the year select precedes month, false for month then year\n
+\t\tyearSuffix: "" // Additional text to append to the year in the month headers\n
+\t};\n
+\tthis._defaults = { // Global defaults for all the date picker instances\n
+\t\tshowOn: "focus", // "focus" for popup on focus,\n
+\t\t\t// "button" for trigger button, or "both" for either\n
+\t\tshowAnim: "fadeIn", // Name of jQuery animation for popup\n
+\t\tshowOptions: {}, // Options for enhanced animations\n
+\t\tdefaultDate: null, // Used when field is blank: actual date,\n
+\t\t\t// +/-number for offset from today, null for today\n
+\t\tappendText: "", // Display text following the input box, e.g. showing the format\n
+\t\tbuttonText: "...", // Text for trigger button\n
+\t\tbuttonImage: "", // URL for trigger button image\n
+\t\tbuttonImageOnly: false, // True if the image appears alone, false if it appears on a button\n
+\t\thideIfNoPrevNext: false, // True to hide next/previous month links\n
+\t\t\t// if not applicable, false to just disable them\n
+\t\tnavigationAsDateFormat: false, // True if date formatting applied to prev/today/next links\n
+\t\tgotoCurrent: false, // True if today link goes back to current selection instead\n
+\t\tchangeMonth: false, // True if month can be selected directly, false if only prev/next\n
+\t\tchangeYear: false, // True if year can be selected directly, false if only prev/next\n
+\t\tyearRange: "c-10:c+10", // Range of years to display in drop-down,\n
+\t\t\t// either relative to today\'s year (-nn:+nn), relative to currently displayed year\n
+\t\t\t// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)\n
+\t\tshowOtherMonths: false, // True to show dates in other months, false to leave blank\n
+\t\tselectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable\n
+\t\tshowWeek: false, // True to show week of the year, false to not show it\n
+\t\tcalculateWeek: this.iso8601Week, // How to calculate the week of the year,\n
+\t\t\t// takes a Date and returns the number of the week for it\n
+\t\tshortYearCutoff: "+10", // Short year values < this are in the current century,\n
+\t\t\t// > this are in the previous century,\n
+\t\t\t// string value starting with "+" for current year + value\n
+\t\tminDate: null, // The earliest selectable date, or null for no limit\n
+\t\tmaxDate: null, // The latest selectable date, or null for no limit\n
+\t\tduration: "fast", // Duration of display/closure\n
+\t\tbeforeShowDay: null, // Function that takes a date and returns an array with\n
+\t\t\t// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",\n
+\t\t\t// [2] = cell title (optional), e.g. $.datepicker.noWeekends\n
+\t\tbeforeShow: null, // Function that takes an input field and\n
+\t\t\t// returns a set of custom settings for the date picker\n
+\t\tonSelect: null, // Define a callback function when a date is selected\n
+\t\tonChangeMonthYear: null, // Define a callback function when the month or year is changed\n
+\t\tonClose: null, // Define a callback function when the datepicker is closed\n
+\t\tnumberOfMonths: 1, // Number of months to show at a time\n
+\t\tshowCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)\n
+\t\tstepMonths: 1, // Number of months to step back/forward\n
+\t\tstepBigMonths: 12, // Number of months to step back/forward for the big links\n
+\t\taltField: "", // Selector for an alternate field to store selected dates into\n
+\t\taltFormat: "", // The date format to use for the alternate field\n
+\t\tconstrainInput: true, // The input is constrained by the current date format\n
+\t\tshowButtonPanel: false, // True to show button panel, false to not show it\n
+\t\tautoSize: false, // True to size the input for the date format, false to leave as is\n
+\t\tdisabled: false // The initial disabled state\n
+\t};\n
+\t$.extend(this._defaults, this.regional[""]);\n
+\tthis.dpDiv = bindHover($("<div id=\'" + this._mainDivId + "\' class=\'ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all\'></div>"));\n
+}\n
+\n
+$.extend(Datepicker.prototype, {\n
+\t/* Class name added to elements to indicate already configured with a date picker. */\n
+\tmarkerClassName: "hasDatepicker",\n
+\n
+\t//Keep track of the maximum number of rows displayed (see #7043)\n
+\tmaxRows: 4,\n
+\n
+\t// TODO rename to "widget" when switching to widget factory\n
+\t_widgetDatepicker: function() {\n
+\t\treturn this.dpDiv;\n
+\t},\n
+\n
+\t/* Override the default settings for all instances of the date picker.\n
+\t * @param  settings  object - the new settings to use as defaults (anonymous object)\n
+\t * @return the manager object\n
+\t */\n
+\tsetDefaults: function(settings) {\n
+\t\textendRemove(this._defaults, settings || {});\n
+\t\treturn this;\n
+\t},\n
+\n
+\t/* Attach the date picker to a jQuery selection.\n
+\t * @param  target\telement - the target input field or division or span\n
+\t * @param  settings  object - the new settings to use for this date picker instance (anonymous)\n
+\t */\n
+\t_attachDatepicker: function(target, settings) {\n
+\t\tvar nodeName, inline, inst;\n
+\t\tnodeName = target.nodeName.toLowerCase();\n
+\t\tinline = (nodeName === "div" || nodeName === "span");\n
+\t\tif (!target.id) {\n
+\t\t\tthis.uuid += 1;\n
+\t\t\ttarget.id = "dp" + this.uuid;\n
+\t\t}\n
+\t\tinst = this._newInst($(target), inline);\n
+\t\tinst.settings = $.extend({}, settings || {});\n
+\t\tif (nodeName === "input") {\n
+\t\t\tthis._connectDatepicker(target, inst);\n
+\t\t} else if (inline) {\n
+\t\t\tthis._inlineDatepicker(target, inst);\n
+\t\t}\n
+\t},\n
+\n
+\t/* Create a new instance object. */\n
+\t_newInst: function(target, inline) {\n
+\t\tvar id = target[0].id.replace(/([^A-Za-z0-9_\\-])/g, "\\\\\\\\$1"); // escape jQuery meta chars\n
+\t\treturn {id: id, input: target, // associated target\n
+\t\t\tselectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection\n
+\t\t\tdrawMonth: 0, drawYear: 0, // month being drawn\n
+\t\t\tinline: inline, // is datepicker inline or not\n
+\t\t\tdpDiv: (!inline ? this.dpDiv : // presentation div\n
+\t\t\tbindHover($("<div class=\'" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all\'></div>")))};\n
+\t},\n
+\n
+\t/* Attach the date picker to an input field. */\n
+\t_connectDatepicker: function(target, inst) {\n
+\t\tvar input = $(target);\n
+\t\tinst.append = $([]);\n
+\t\tinst.trigger = $([]);\n
+\t\tif (input.hasClass(this.markerClassName)) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tthis._attachments(input, inst);\n
+\t\tinput.addClass(this.markerClassName).keydown(this._doKeyDown).\n
+\t\t\tkeypress(this._doKeyPress).keyup(this._doKeyUp);\n
+\t\tthis._autoSize(inst);\n
+\t\t$.data(target, PROP_NAME, inst);\n
+\t\t//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)\n
+\t\tif( inst.settings.disabled ) {\n
+\t\t\tthis._disableDatepicker( target );\n
+\t\t}\n
+\t},\n
+\n
+\t/* Make attachments based on settings. */\n
+\t_attachments: function(input, inst) {\n
+\t\tvar showOn, buttonText, buttonImage,\n
+\t\t\tappendText = this._get(inst, "appendText"),\n
+\t\t\tisRTL = this._get(inst, "isRTL");\n
+\n
+\t\tif (inst.append) {\n
+\t\t\tinst.append.remove();\n
+\t\t}\n
+\t\tif (appendText) {\n
+\t\t\tinst.append = $("<span class=\'" + this._appendClass + "\'>" + appendText + "</span>");\n
+\t\t\tinput[isRTL ? "before" : "after"](inst.append);\n
+\t\t}\n
+\n
+\t\tinput.unbind("focus", this._showDatepicker);\n
+\n
+\t\tif (inst.trigger) {\n
+\t\t\tinst.trigger.remove();\n
+\t\t}\n
+\n
+\t\tshowOn = this._get(inst, "showOn");\n
+\t\tif (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field\n
+\t\t\tinput.focus(this._showDatepicker);\n
+\t\t}\n
+\t\tif (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked\n
+\t\t\tbuttonText = this._get(inst, "buttonText");\n
+\t\t\tbuttonImage = this._get(inst, "buttonImage");\n
+\t\t\tinst.trigger = $(this._get(inst, "buttonImageOnly") ?\n
+\t\t\t\t$("<img/>").addClass(this._triggerClass).\n
+\t\t\t\t\tattr({ src: buttonImage, alt: buttonText, title: buttonText }) :\n
+\t\t\t\t$("<button type=\'button\'></button>").addClass(this._triggerClass).\n
+\t\t\t\t\thtml(!buttonImage ? buttonText : $("<img/>").attr(\n
+\t\t\t\t\t{ src:buttonImage, alt:buttonText, title:buttonText })));\n
+\t\t\tinput[isRTL ? "before" : "after"](inst.trigger);\n
+\t\t\tinst.trigger.click(function() {\n
+\t\t\t\tif ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {\n
+\t\t\t\t\t$.datepicker._hideDatepicker();\n
+\t\t\t\t} else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {\n
+\t\t\t\t\t$.datepicker._hideDatepicker();\n
+\t\t\t\t\t$.datepicker._showDatepicker(input[0]);\n
+\t\t\t\t} else {\n
+\t\t\t\t\t$.datepicker._showDatepicker(input[0]);\n
+\t\t\t\t}\n
+\t\t\t\treturn false;\n
+\t\t\t});\n
+\t\t}\n
+\t},\n
+\n
+\t/* Apply the maximum length for the date format. */\n
+\t_autoSize: function(inst) {\n
+\t\tif (this._get(inst, "autoSize") && !inst.inline) {\n
+\t\t\tvar findMax, max, maxI, i,\n
+\t\t\t\tdate = new Date(2009, 12 - 1, 20), // Ensure double digits\n
+\t\t\t\tdateFormat = this._get(inst, "dateFormat");\n
+\n
+\t\t\tif (dateFormat.match(/[DM]/)) {\n
+\t\t\t\tfindMax = function(names) {\n
+\t\t\t\t\tmax = 0;\n
+\t\t\t\t\tmaxI = 0;\n
+\t\t\t\t\tfor (i = 0; i < names.length; i++) {\n
+\t\t\t\t\t\tif (names[i].length > max) {\n
+\t\t\t\t\t\t\tmax = names[i].length;\n
+\t\t\t\t\t\t\tmaxI = i;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn maxI;\n
+\t\t\t\t};\n
+\t\t\t\tdate.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?\n
+\t\t\t\t\t"monthNames" : "monthNamesShort"))));\n
+\t\t\t\tdate.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?\n
+\t\t\t\t\t"dayNames" : "dayNamesShort"))) + 20 - date.getDay());\n
+\t\t\t}\n
+\t\t\tinst.input.attr("size", this._formatDate(inst, date).length);\n
+\t\t}\n
+\t},\n
+\n
+\t/* Attach an inline date picker to a div. */\n
+\t_inlineDatepicker: function(target, inst) {\n
+\t\tvar divSpan = $(target);\n
+\t\tif (divSpan.hasClass(this.markerClassName)) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tdivSpan.addClass(this.markerClassName).append(inst.dpDiv);\n
+\t\t$.data(target, PROP_NAME, inst);\n
+\t\tthis._setDate(inst, this._getDefaultDate(inst), true);\n
+\t\tthis._updateDatepicker(inst);\n
+\t\tthis._updateAlternate(inst);\n
+\t\t//If disabled option is true, disable the datepicker before showing it (see ticket #5665)\n
+\t\tif( inst.settings.disabled ) {\n
+\t\t\tthis._disableDatepicker( target );\n
+\t\t}\n
+\t\t// Set display:block in place of inst.dpDiv.show() which won\'t work on disconnected elements\n
+\t\t// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height\n
+\t\tinst.dpDiv.css( "display", "block" );\n
+\t},\n
+\n
+\t/* Pop-up the date picker in a "dialog" box.\n
+\t * @param  input element - ignored\n
+\t * @param  date\tstring or Date - the initial date to display\n
+\t * @param  onSelect  function - the function to call when a date is selected\n
+\t * @param  settings  object - update the dialog date picker instance\'s settings (anonymous object)\n
+\t * @param  pos int[2] - coordinates for the dialog\'s position within the screen or\n
+\t *\t\t\t\t\tevent - with x/y coordinates or\n
+\t *\t\t\t\t\tleave empty for default (screen centre)\n
+\t * @return the manager object\n
+\t */\n
+\t_dialogDatepicker: function(input, date, onSelect, settings, pos) {\n
+\t\tvar id, browserWidth, browserHeight, scrollX, scrollY,\n
+\t\t\tinst = this._dialogInst; // internal instance\n
+\n
+\t\tif (!inst) {\n
+\t\t\tthis.uuid += 1;\n
+\t\t\tid = "dp" + this.uuid;\n
+\t\t\tthis._dialogInput = $("<input type=\'text\' id=\'" + id +\n
+\t\t\t\t"\' style=\'position: absolute; top: -100px; width: 0px;\'/>");\n
+\t\t\tthis._dialogInput.keydown(this._doKeyDown);\n
+\t\t\t$("body").append(this._dialogInput);\n
+\t\t\tinst = this._dialogInst = this._newInst(this._dialogInput, false);\n
+\t\t\tinst.settings = {};\n
+\t\t\t$.data(this._dialogInput[0], PROP_NAME, inst);\n
+\t\t}\n
+\t\textendRemove(inst.settings, settings || {});\n
+\t\tdate = (date && date.constructor === Date ? this._formatDate(inst, date) : date);\n
+\t\tthis._dialogInput.val(date);\n
+\n
+\t\tthis._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);\n
+\t\tif (!this._pos) {\n
+\t\t\tbrowserWidth = document.documentElement.clientWidth;\n
+\t\t\tbrowserHeight = document.documentElement.clientHeight;\n
+\t\t\tscrollX = document.documentElement.scrollLeft || document.body.scrollLeft;\n
+\t\t\tscrollY = document.documentElement.scrollTop || document.body.scrollTop;\n
+\t\t\tthis._pos = // should use actual width/height below\n
+\t\t\t\t[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];\n
+\t\t}\n
+\n
+\t\t// move input on screen for focus, but hidden behind dialog\n
+\t\tthis._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");\n
+\t\tinst.settings.onSelect = onSelect;\n
+\t\tthis._inDialog = true;\n
+\t\tthis.dpDiv.addClass(this._dialogClass);\n
+\t\tthis._showDatepicker(this._dialogInput[0]);\n
+\t\tif ($.blockUI) {\n
+\t\t\t$.blockUI(this.dpDiv);\n
+\t\t}\n
+\t\t$.data(this._dialogInput[0], PROP_NAME, inst);\n
+\t\treturn this;\n
+\t},\n
+\n
+\t/* Detach a datepicker from its control.\n
+\t * @param  target\telement - the target input field or division or span\n
+\t */\n
+\t_destroyDatepicker: function(target) {\n
+\t\tvar nodeName,\n
+\t\t\t$target = $(target),\n
+\t\t\tinst = $.data(target, PROP_NAME);\n
+\n
+\t\tif (!$target.hasClass(this.markerClassName)) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tnodeName = target.nodeName.toLowerCase();\n
+\t\t$.removeData(target, PROP_NAME);\n
+\t\tif (nodeName === "input") {\n
+\t\t\tinst.append.remove();\n
+\t\t\tinst.trigger.remove();\n
+\t\t\t$target.removeClass(this.markerClassName).\n
+\t\t\t\tunbind("focus", this._showDatepicker).\n
+\t\t\t\tunbind("keydown", this._doKeyDown).\n
+\t\t\t\tunbind("keypress", this._doKeyPress).\n
+\t\t\t\tunbind("keyup", this._doKeyUp);\n
+\t\t} else if (nodeName === "div" || nodeName === "span") {\n
+\t\t\t$target.removeClass(this.markerClassName).empty();\n
+\t\t}\n
+\t},\n
+\n
+\t/* Enable the date picker to a jQuery selection.\n
+\t * @param  target\telement - the target input field or division or span\n
+\t */\n
+\t_enableDatepicker: function(target) {\n
+\t\tvar nodeName, inline,\n
+\t\t\t$target = $(target),\n
+\t\t\tinst = $.data(target, PROP_NAME);\n
+\n
+\t\tif (!$target.hasClass(this.markerClassName)) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tnodeName = target.nodeName.toLowerCase();\n
+\t\tif (nodeName === "input") {\n
+\t\t\ttarget.disabled = false;\n
+\t\t\tinst.trigger.filter("button").\n
+\t\t\t\teach(function() { this.disabled = false; }).end().\n
+\t\t\t\tfilter("img").css({opacity: "1.0", cursor: ""});\n
+\t\t} else if (nodeName === "div" || nodeName === "span") {\n
+\t\t\tinline = $target.children("." + this._inlineClass);\n
+\t\t\tinline.children().removeClass("ui-state-disabled");\n
+\t\t\tinline.find("select.ui-datepicker-month, select.ui-datepicker-year").\n
+\t\t\t\tprop("disabled", false);\n
+\t\t}\n
+\t\tthis._disabledInputs = $.map(this._disabledInputs,\n
+\t\t\tfunction(value) { return (value === target ? null : value); }); // delete entry\n
+\t},\n
+\n
+\t/* Disable the date picker to a jQuery selection.\n
+\t * @param  target\telement - the target input field or division or span\n
+\t */\n
+\t_disableDatepicker: function(target) {\n
+\t\tvar nodeName, inline,\n
+\t\t\t$target = $(target),\n
+\t\t\tinst = $.data(target, PROP_NAME);\n
+\n
+\t\tif (!$target.hasClass(this.markerClassName)) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tnodeName = target.nodeName.toLowerCase();\n
+\t\tif (nodeName === "input") {\n
+\t\t\ttarget.disabled = true;\n
+\t\t\tinst.trigger.filter("button").\n
+\t\t\t\teach(function() { this.disabled = true; }).end().\n
+\t\t\t\tfilter("img").css({opacity: "0.5", cursor: "default"});\n
+\t\t} else if (nodeName === "div" || nodeName === "span") {\n
+\t\t\tinline = $target.children("." + this._inlineClass);\n
+\t\t\tinline.children().addClass("ui-state-disabled");\n
+\t\t\tinline.find("select.ui-datepicker-month, select.ui-datepicker-year").\n
+\t\t\t\tprop("disabled", true);\n
+\t\t}\n
+\t\tthis._disabledInputs = $.map(this._disabledInputs,\n
+\t\t\tfunction(value) { return (value === target ? null : value); }); // delete entry\n
+\t\tthis._disabledInputs[this._disabledInputs.length] = target;\n
+\t},\n
+\n
+\t/* Is the first field in a jQuery collection disabled as a datepicker?\n
+\t * @param  target\telement - the target input field or division or span\n
+\t * @return boolean - true if disabled, false if enabled\n
+\t */\n
+\t_isDisabledDatepicker: function(target) {\n
+\t\tif (!target) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\tfor (var i = 0; i < this._disabledInputs.length; i++) {\n
+\t\t\tif (this._disabledInputs[i] === target) {\n
+\t\t\t\treturn true;\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn false;\n
+\t},\n
+\n
+\t/* Retrieve the instance data for the target control.\n
+\t * @param  target  element - the target input field or division or span\n
+\t * @return  object - the associated instance data\n
+\t * @throws  error if a jQuery problem getting data\n
+\t */\n
+\t_getInst: function(target) {\n
+\t\ttry {\n
+\t\t\treturn $.data(target, PROP_NAME);\n
+\t\t}\n
+\t\tcatch (err) {\n
+\t\t\tthrow "Missing instance data for this datepicker";\n
+\t\t}\n
+\t},\n
+\n
+\t/* Update or retrieve the settings for a date picker attached to an input field or division.\n
+\t * @param  target  element - the target input field or division or span\n
+\t * @param  name\tobject - the new settings to update or\n
+\t *\t\t\t\tstring - the name of the setting to change or retrieve,\n
+\t *\t\t\t\twhen retrieving also "all" for all instance settings or\n
+\t *\t\t\t\t"defaults" for all global defaults\n
+\t * @param  value   any - the new value for the setting\n
+\t *\t\t\t\t(omit if above is an object or to retrieve a value)\n
+\t */\n
+\t_optionDatepicker: function(target, name, value) {\n
+\t\tvar settings, date, minDate, maxDate,\n
+\t\t\tinst = this._getInst(target);\n
+\n
+\t\tif (arguments.length === 2 && typeof name === "string") {\n
+\t\t\treturn (name === "defaults" ? $.extend({}, $.datepicker._defaults) :\n
+\t\t\t\t(inst ? (name === "all" ? $.extend({}, inst.settings) :\n
+\t\t\t\tthis._get(inst, name)) : null));\n
+\t\t}\n
+\n
+\t\tsettings = name || {};\n
+\t\tif (typeof name === "string") {\n
+\t\t\tsettings = {};\n
+\t\t\tsettings[name] = value;\n
+\t\t}\n
+\n
+\t\tif (inst) {\n
+\t\t\tif (this._curInst === inst) {\n
+\t\t\t\tthis._hideDatepicker();\n
+\t\t\t}\n
+\n
+\t\t\tdate = this._getDateDatepicker(target, true);\n
+\t\t\tminDate = this._getMinMaxDate(inst, "min");\n
+\t\t\tmaxDate = this._getMinMaxDate(inst, "max");\n
+\t\t\textendRemove(inst.settings, settings);\n
+\t\t\t// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn\'t provided\n
+\t\t\tif (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {\n
+\t\t\t\tinst.settings.minDate = this._formatDate(inst, minDate);\n
+\t\t\t}\n
+\t\t\tif (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {\n
+\t\t\t\tinst.settings.maxDate = this._formatDate(inst, maxDate);\n
+\t\t\t}\n
+\t\t\tif ( "disabled" in settings ) {\n
+\t\t\t\tif ( settings.disabled ) {\n
+\t\t\t\t\tthis._disableDatepicker(target);\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthis._enableDatepicker(target);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tthis._attachments($(target), inst);\n
+\t\t\tthis._autoSize(inst);\n
+\t\t\tthis._setDate(inst, date);\n
+\t\t\tthis._updateAlternate(inst);\n
+\t\t\tthis._updateDatepicker(inst);\n
+\t\t}\n
+\t},\n
+\n
+\t// change method deprecated\n
+\t_changeDatepicker: function(target, name, value) {\n
+\t\tthis._optionDatepicker(target, name, value);\n
+\t},\n
+\n
+\t/* Redraw the date picker attached to an input field or division.\n
+\t * @param  target  element - the target input field or division or span\n
+\t */\n
+\t_refreshDatepicker: function(target) {\n
+\t\tvar inst = this._getInst(target);\n
+\t\tif (inst) {\n
+\t\t\tthis._updateDatepicker(inst);\n
+\t\t}\n
+\t},\n
+\n
+\t/* Set the dates for a jQuery selection.\n
+\t * @param  target element - the target input field or division or span\n
+\t * @param  date\tDate - the new date\n
+\t */\n
+\t_setDateDatepicker: function(target, date) {\n
+\t\tvar inst = this._getInst(target);\n
+\t\tif (inst) {\n
+\t\t\tthis._setDate(inst, date);\n
+\t\t\tthis._updateDatepicker(inst);\n
+\t\t\tthis._updateAlternate(inst);\n
+\t\t}\n
+\t},\n
+\n
+\t/* Get the date(s) for the first entry in a jQuery selection.\n
+\t * @param  target element - the target input field or division or span\n
+\t * @param  noDefault boolean - true if no default date is to be used\n
+\t * @return Date - the current date\n
+\t */\n
+\t_getDateDatepicker: function(target, noDefault) {\n
+\t\tvar inst = this._getInst(target);\n
+\t\tif (inst && !inst.inline) {\n
+\t\t\tthis._setDateFromField(inst, noDefault);\n
+\t\t}\n
+\t\treturn (inst ? this._getDate(inst) : null);\n
+\t},\n
+\n
+\t/* Handle keystrokes. */\n
+\t_doKeyDown: function(event) {\n
+\t\tvar onSelect, dateStr, sel,\n
+\t\t\tinst = $.datepicker._getInst(event.target),\n
+\t\t\thandled = true,\n
+\t\t\tisRTL = inst.dpDiv.is(".ui-datepicker-rtl");\n
+\n
+\t\tinst._keyEvent = true;\n
+\t\tif ($.datepicker._datepickerShowing) {\n
+\t\t\tswitch (event.keyCode) {\n
+\t\t\t\tcase 9: $.datepicker._hideDatepicker();\n
+\t\t\t\t\t\thandled = false;\n
+\t\t\t\t\t\tbreak; // hide on tab out\n
+\t\t\t\tcase 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +\n
+\t\t\t\t\t\t\t\t\t$.datepicker._currentClass + ")", inst.dpDiv);\n
+\t\t\t\t\t\tif (sel[0]) {\n
+\t\t\t\t\t\t\t$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\tonSelect = $.datepicker._get(inst, "onSelect");\n
+\t\t\t\t\t\tif (onSelect) {\n
+\t\t\t\t\t\t\tdateStr = $.datepicker._formatDate(inst);\n
+\n
+\t\t\t\t\t\t\t// trigger custom callback\n
+\t\t\t\t\t\t\tonSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);\n
+\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t$.datepicker._hideDatepicker();\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\treturn false; // don\'t submit the form\n
+\t\t\t\tcase 27: $.datepicker._hideDatepicker();\n
+\t\t\t\t\t\tbreak; // hide on escape\n
+\t\t\t\tcase 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?\n
+\t\t\t\t\t\t\t-$.datepicker._get(inst, "stepBigMonths") :\n
+\t\t\t\t\t\t\t-$.datepicker._get(inst, "stepMonths")), "M");\n
+\t\t\t\t\t\tbreak; // previous month/year on page up/+ ctrl\n
+\t\t\t\tcase 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?\n
+\t\t\t\t\t\t\t+$.datepicker._get(inst, "stepBigMonths") :\n
+\t\t\t\t\t\t\t+$.datepicker._get(inst, "stepMonths")), "M");\n
+\t\t\t\t\t\tbreak; // next month/year on page down/+ ctrl\n
+\t\t\t\tcase 35: if (event.ctrlKey || event.metaKey) {\n
+\t\t\t\t\t\t\t$.datepicker._clearDate(event.target);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n
+\t\t\t\t\t\tbreak; // clear on ctrl or command +end\n
+\t\t\t\tcase 36: if (event.ctrlKey || event.metaKey) {\n
+\t\t\t\t\t\t\t$.datepicker._gotoToday(event.target);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n
+\t\t\t\t\t\tbreak; // current on ctrl or command +home\n
+\t\t\t\tcase 37: if (event.ctrlKey || event.metaKey) {\n
+\t\t\t\t\t\t\t$.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n
+\t\t\t\t\t\t// -1 day on ctrl or command +left\n
+\t\t\t\t\t\tif (event.originalEvent.altKey) {\n
+\t\t\t\t\t\t\t$.datepicker._adjustDate(event.target, (event.ctrlKey ?\n
+\t\t\t\t\t\t\t\t-$.datepicker._get(inst, "stepBigMonths") :\n
+\t\t\t\t\t\t\t\t-$.datepicker._get(inst, "stepMonths")), "M");\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\t// next month/year on alt +left on Mac\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\tcase 38: if (event.ctrlKey || event.metaKey) {\n
+\t\t\t\t\t\t\t$.datepicker._adjustDate(event.target, -7, "D");\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n
+\t\t\t\t\t\tbreak; // -1 week on ctrl or command +up\n
+\t\t\t\tcase 39: if
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+ (event.ctrlKey || event.metaKey) {\n
+\t\t\t\t\t\t\t$.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n
+\t\t\t\t\t\t// +1 day on ctrl or command +right\n
+\t\t\t\t\t\tif (event.originalEvent.altKey) {\n
+\t\t\t\t\t\t\t$.datepicker._adjustDate(event.target, (event.ctrlKey ?\n
+\t\t\t\t\t\t\t\t+$.datepicker._get(inst, "stepBigMonths") :\n
+\t\t\t\t\t\t\t\t+$.datepicker._get(inst, "stepMonths")), "M");\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\t// next month/year on alt +right\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\tcase 40: if (event.ctrlKey || event.metaKey) {\n
+\t\t\t\t\t\t\t$.datepicker._adjustDate(event.target, +7, "D");\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\thandled = event.ctrlKey || event.metaKey;\n
+\t\t\t\t\t\tbreak; // +1 week on ctrl or command +down\n
+\t\t\t\tdefault: handled = false;\n
+\t\t\t}\n
+\t\t} else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home\n
+\t\t\t$.datepicker._showDatepicker(this);\n
+\t\t} else {\n
+\t\t\thandled = false;\n
+\t\t}\n
+\n
+\t\tif (handled) {\n
+\t\t\tevent.preventDefault();\n
+\t\t\tevent.stopPropagation();\n
+\t\t}\n
+\t},\n
+\n
+\t/* Filter entered characters - based on date format. */\n
+\t_doKeyPress: function(event) {\n
+\t\tvar chars, chr,\n
+\t\t\tinst = $.datepicker._getInst(event.target);\n
+\n
+\t\tif ($.datepicker._get(inst, "constrainInput")) {\n
+\t\t\tchars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));\n
+\t\t\tchr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);\n
+\t\t\treturn event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);\n
+\t\t}\n
+\t},\n
+\n
+\t/* Synchronise manual entry and field/alternate field. */\n
+\t_doKeyUp: function(event) {\n
+\t\tvar date,\n
+\t\t\tinst = $.datepicker._getInst(event.target);\n
+\n
+\t\tif (inst.input.val() !== inst.lastVal) {\n
+\t\t\ttry {\n
+\t\t\t\tdate = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),\n
+\t\t\t\t\t(inst.input ? inst.input.val() : null),\n
+\t\t\t\t\t$.datepicker._getFormatConfig(inst));\n
+\n
+\t\t\t\tif (date) { // only if valid\n
+\t\t\t\t\t$.datepicker._setDateFromField(inst);\n
+\t\t\t\t\t$.datepicker._updateAlternate(inst);\n
+\t\t\t\t\t$.datepicker._updateDatepicker(inst);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tcatch (err) {\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn true;\n
+\t},\n
+\n
+\t/* Pop-up the date picker for a given input field.\n
+\t * If false returned from beforeShow event handler do not show.\n
+\t * @param  input  element - the input field attached to the date picker or\n
+\t *\t\t\t\t\tevent - if triggered by focus\n
+\t */\n
+\t_showDatepicker: function(input) {\n
+\t\tinput = input.target || input;\n
+\t\tif (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger\n
+\t\t\tinput = $("input", input.parentNode)[0];\n
+\t\t}\n
+\n
+\t\tif ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tvar inst, beforeShow, beforeShowSettings, isFixed,\n
+\t\t\toffset, showAnim, duration;\n
+\n
+\t\tinst = $.datepicker._getInst(input);\n
+\t\tif ($.datepicker._curInst && $.datepicker._curInst !== inst) {\n
+\t\t\t$.datepicker._curInst.dpDiv.stop(true, true);\n
+\t\t\tif ( inst && $.datepicker._datepickerShowing ) {\n
+\t\t\t\t$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tbeforeShow = $.datepicker._get(inst, "beforeShow");\n
+\t\tbeforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};\n
+\t\tif(beforeShowSettings === false){\n
+\t\t\treturn;\n
+\t\t}\n
+\t\textendRemove(inst.settings, beforeShowSettings);\n
+\n
+\t\tinst.lastVal = null;\n
+\t\t$.datepicker._lastInput = input;\n
+\t\t$.datepicker._setDateFromField(inst);\n
+\n
+\t\tif ($.datepicker._inDialog) { // hide cursor\n
+\t\t\tinput.value = "";\n
+\t\t}\n
+\t\tif (!$.datepicker._pos) { // position below input\n
+\t\t\t$.datepicker._pos = $.datepicker._findPos(input);\n
+\t\t\t$.datepicker._pos[1] += input.offsetHeight; // add the height\n
+\t\t}\n
+\n
+\t\tisFixed = false;\n
+\t\t$(input).parents().each(function() {\n
+\t\t\tisFixed |= $(this).css("position") === "fixed";\n
+\t\t\treturn !isFixed;\n
+\t\t});\n
+\n
+\t\toffset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};\n
+\t\t$.datepicker._pos = null;\n
+\t\t//to avoid flashes on Firefox\n
+\t\tinst.dpDiv.empty();\n
+\t\t// determine sizing offscreen\n
+\t\tinst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});\n
+\t\t$.datepicker._updateDatepicker(inst);\n
+\t\t// fix width for dynamic number of date pickers\n
+\t\t// and adjust position before showing\n
+\t\toffset = $.datepicker._checkOffset(inst, offset, isFixed);\n
+\t\tinst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?\n
+\t\t\t"static" : (isFixed ? "fixed" : "absolute")), display: "none",\n
+\t\t\tleft: offset.left + "px", top: offset.top + "px"});\n
+\n
+\t\tif (!inst.inline) {\n
+\t\t\tshowAnim = $.datepicker._get(inst, "showAnim");\n
+\t\t\tduration = $.datepicker._get(inst, "duration");\n
+\t\t\tinst.dpDiv.zIndex($(input).zIndex()+1);\n
+\t\t\t$.datepicker._datepickerShowing = true;\n
+\n
+\t\t\tif ( $.effects && $.effects.effect[ showAnim ] ) {\n
+\t\t\t\tinst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);\n
+\t\t\t} else {\n
+\t\t\t\tinst.dpDiv[showAnim || "show"](showAnim ? duration : null);\n
+\t\t\t}\n
+\n
+\t\t\tif ( $.datepicker._shouldFocusInput( inst ) ) {\n
+\t\t\t\tinst.input.focus();\n
+\t\t\t}\n
+\n
+\t\t\t$.datepicker._curInst = inst;\n
+\t\t}\n
+\t},\n
+\n
+\t/* Generate the date picker content. */\n
+\t_updateDatepicker: function(inst) {\n
+\t\tthis.maxRows = 4; //Reset the max number of rows being displayed (see #7043)\n
+\t\tinstActive = inst; // for delegate hover events\n
+\t\tinst.dpDiv.empty().append(this._generateHTML(inst));\n
+\t\tthis._attachHandlers(inst);\n
+\t\tinst.dpDiv.find("." + this._dayOverClass + " a").mouseover();\n
+\n
+\t\tvar origyearshtml,\n
+\t\t\tnumMonths = this._getNumberOfMonths(inst),\n
+\t\t\tcols = numMonths[1],\n
+\t\t\twidth = 17;\n
+\n
+\t\tinst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");\n
+\t\tif (cols > 1) {\n
+\t\t\tinst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");\n
+\t\t}\n
+\t\tinst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +\n
+\t\t\t"Class"]("ui-datepicker-multi");\n
+\t\tinst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +\n
+\t\t\t"Class"]("ui-datepicker-rtl");\n
+\n
+\t\tif (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {\n
+\t\t\tinst.input.focus();\n
+\t\t}\n
+\n
+\t\t// deffered render of the years select (to avoid flashes on Firefox)\n
+\t\tif( inst.yearshtml ){\n
+\t\t\torigyearshtml = inst.yearshtml;\n
+\t\t\tsetTimeout(function(){\n
+\t\t\t\t//assure that inst.yearshtml didn\'t change.\n
+\t\t\t\tif( origyearshtml === inst.yearshtml && inst.yearshtml ){\n
+\t\t\t\t\tinst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);\n
+\t\t\t\t}\n
+\t\t\t\torigyearshtml = inst.yearshtml = null;\n
+\t\t\t}, 0);\n
+\t\t}\n
+\t},\n
+\n
+\t// #6694 - don\'t focus the input if it\'s already focused\n
+\t// this breaks the change event in IE\n
+\t// Support: IE and jQuery <1.9\n
+\t_shouldFocusInput: function( inst ) {\n
+\t\treturn inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );\n
+\t},\n
+\n
+\t/* Check positioning to remain on screen. */\n
+\t_checkOffset: function(inst, offset, isFixed) {\n
+\t\tvar dpWidth = inst.dpDiv.outerWidth(),\n
+\t\t\tdpHeight = inst.dpDiv.outerHeight(),\n
+\t\t\tinputWidth = inst.input ? inst.input.outerWidth() : 0,\n
+\t\t\tinputHeight = inst.input ? inst.input.outerHeight() : 0,\n
+\t\t\tviewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),\n
+\t\t\tviewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());\n
+\n
+\t\toffset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);\n
+\t\toffset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;\n
+\t\toffset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;\n
+\n
+\t\t// now check if datepicker is showing outside window viewport - move to a better place if so.\n
+\t\toffset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?\n
+\t\t\tMath.abs(offset.left + dpWidth - viewWidth) : 0);\n
+\t\toffset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?\n
+\t\t\tMath.abs(dpHeight + inputHeight) : 0);\n
+\n
+\t\treturn offset;\n
+\t},\n
+\n
+\t/* Find an object\'s position on the screen. */\n
+\t_findPos: function(obj) {\n
+\t\tvar position,\n
+\t\t\tinst = this._getInst(obj),\n
+\t\t\tisRTL = this._get(inst, "isRTL");\n
+\n
+\t\twhile (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {\n
+\t\t\tobj = obj[isRTL ? "previousSibling" : "nextSibling"];\n
+\t\t}\n
+\n
+\t\tposition = $(obj).offset();\n
+\t\treturn [position.left, position.top];\n
+\t},\n
+\n
+\t/* Hide the date picker from view.\n
+\t * @param  input  element - the input field attached to the date picker\n
+\t */\n
+\t_hideDatepicker: function(input) {\n
+\t\tvar showAnim, duration, postProcess, onClose,\n
+\t\t\tinst = this._curInst;\n
+\n
+\t\tif (!inst || (input && inst !== $.data(input, PROP_NAME))) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif (this._datepickerShowing) {\n
+\t\t\tshowAnim = this._get(inst, "showAnim");\n
+\t\t\tduration = this._get(inst, "duration");\n
+\t\t\tpostProcess = function() {\n
+\t\t\t\t$.datepicker._tidyDialog(inst);\n
+\t\t\t};\n
+\n
+\t\t\t// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed\n
+\t\t\tif ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {\n
+\t\t\t\tinst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);\n
+\t\t\t} else {\n
+\t\t\t\tinst.dpDiv[(showAnim === "slideDown" ? "slideUp" :\n
+\t\t\t\t\t(showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);\n
+\t\t\t}\n
+\n
+\t\t\tif (!showAnim) {\n
+\t\t\t\tpostProcess();\n
+\t\t\t}\n
+\t\t\tthis._datepickerShowing = false;\n
+\n
+\t\t\tonClose = this._get(inst, "onClose");\n
+\t\t\tif (onClose) {\n
+\t\t\t\tonClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);\n
+\t\t\t}\n
+\n
+\t\t\tthis._lastInput = null;\n
+\t\t\tif (this._inDialog) {\n
+\t\t\t\tthis._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });\n
+\t\t\t\tif ($.blockUI) {\n
+\t\t\t\t\t$.unblockUI();\n
+\t\t\t\t\t$("body").append(this.dpDiv);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tthis._inDialog = false;\n
+\t\t}\n
+\t},\n
+\n
+\t/* Tidy up after a dialog display. */\n
+\t_tidyDialog: function(inst) {\n
+\t\tinst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");\n
+\t},\n
+\n
+\t/* Close date picker if clicked elsewhere. */\n
+\t_checkExternalClick: function(event) {\n
+\t\tif (!$.datepicker._curInst) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tvar $target = $(event.target),\n
+\t\t\tinst = $.datepicker._getInst($target[0]);\n
+\n
+\t\tif ( ( ( $target[0].id !== $.datepicker._mainDivId &&\n
+\t\t\t\t$target.parents("#" + $.datepicker._mainDivId).length === 0 &&\n
+\t\t\t\t!$target.hasClass($.datepicker.markerClassName) &&\n
+\t\t\t\t!$target.closest("." + $.datepicker._triggerClass).length &&\n
+\t\t\t\t$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||\n
+\t\t\t( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {\n
+\t\t\t\t$.datepicker._hideDatepicker();\n
+\t\t}\n
+\t},\n
+\n
+\t/* Adjust one of the date sub-fields. */\n
+\t_adjustDate: function(id, offset, period) {\n
+\t\tvar target = $(id),\n
+\t\t\tinst = this._getInst(target[0]);\n
+\n
+\t\tif (this._isDisabledDatepicker(target[0])) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tthis._adjustInstDate(inst, offset +\n
+\t\t\t(period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning\n
+\t\t\tperiod);\n
+\t\tthis._updateDatepicker(inst);\n
+\t},\n
+\n
+\t/* Action for current link. */\n
+\t_gotoToday: function(id) {\n
+\t\tvar date,\n
+\t\t\ttarget = $(id),\n
+\t\t\tinst = this._getInst(target[0]);\n
+\n
+\t\tif (this._get(inst, "gotoCurrent") && inst.currentDay) {\n
+\t\t\tinst.selectedDay = inst.currentDay;\n
+\t\t\tinst.drawMonth = inst.selectedMonth = inst.currentMonth;\n
+\t\t\tinst.drawYear = inst.selectedYear = inst.currentYear;\n
+\t\t} else {\n
+\t\t\tdate = new Date();\n
+\t\t\tinst.selectedDay = date.getDate();\n
+\t\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n
+\t\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n
+\t\t}\n
+\t\tthis._notifyChange(inst);\n
+\t\tthis._adjustDate(target);\n
+\t},\n
+\n
+\t/* Action for selecting a new month/year. */\n
+\t_selectMonthYear: function(id, select, period) {\n
+\t\tvar target = $(id),\n
+\t\t\tinst = this._getInst(target[0]);\n
+\n
+\t\tinst["selected" + (period === "M" ? "Month" : "Year")] =\n
+\t\tinst["draw" + (period === "M" ? "Month" : "Year")] =\n
+\t\t\tparseInt(select.options[select.selectedIndex].value,10);\n
+\n
+\t\tthis._notifyChange(inst);\n
+\t\tthis._adjustDate(target);\n
+\t},\n
+\n
+\t/* Action for selecting a day. */\n
+\t_selectDay: function(id, month, year, td) {\n
+\t\tvar inst,\n
+\t\t\ttarget = $(id);\n
+\n
+\t\tif ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tinst = this._getInst(target[0]);\n
+\t\tinst.selectedDay = inst.currentDay = $("a", td).html();\n
+\t\tinst.selectedMonth = inst.currentMonth = month;\n
+\t\tinst.selectedYear = inst.currentYear = year;\n
+\t\tthis._selectDate(id, this._formatDate(inst,\n
+\t\t\tinst.currentDay, inst.currentMonth, inst.currentYear));\n
+\t},\n
+\n
+\t/* Erase the input field and hide the date picker. */\n
+\t_clearDate: function(id) {\n
+\t\tvar target = $(id);\n
+\t\tthis._selectDate(target, "");\n
+\t},\n
+\n
+\t/* Update the input field with the selected date. */\n
+\t_selectDate: function(id, dateStr) {\n
+\t\tvar onSelect,\n
+\t\t\ttarget = $(id),\n
+\t\t\tinst = this._getInst(target[0]);\n
+\n
+\t\tdateStr = (dateStr != null ? dateStr : this._formatDate(inst));\n
+\t\tif (inst.input) {\n
+\t\t\tinst.input.val(dateStr);\n
+\t\t}\n
+\t\tthis._updateAlternate(inst);\n
+\n
+\t\tonSelect = this._get(inst, "onSelect");\n
+\t\tif (onSelect) {\n
+\t\t\tonSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback\n
+\t\t} else if (inst.input) {\n
+\t\t\tinst.input.trigger("change"); // fire the change event\n
+\t\t}\n
+\n
+\t\tif (inst.inline){\n
+\t\t\tthis._updateDatepicker(inst);\n
+\t\t} else {\n
+\t\t\tthis._hideDatepicker();\n
+\t\t\tthis._lastInput = inst.input[0];\n
+\t\t\tif (typeof(inst.input[0]) !== "object") {\n
+\t\t\t\tinst.input.focus(); // restore focus\n
+\t\t\t}\n
+\t\t\tthis._lastInput = null;\n
+\t\t}\n
+\t},\n
+\n
+\t/* Update any alternate field to synchronise with the main field. */\n
+\t_updateAlternate: function(inst) {\n
+\t\tvar altFormat, date, dateStr,\n
+\t\t\taltField = this._get(inst, "altField");\n
+\n
+\t\tif (altField) { // update alternate field too\n
+\t\t\taltFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");\n
+\t\t\tdate = this._getDate(inst);\n
+\t\t\tdateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));\n
+\t\t\t$(altField).each(function() { $(this).val(dateStr); });\n
+\t\t}\n
+\t},\n
+\n
+\t/* Set as beforeShowDay function to prevent selection of weekends.\n
+\t * @param  date  Date - the date to customise\n
+\t * @return [boolean, string] - is this date selectable?, what is its CSS class?\n
+\t */\n
+\tnoWeekends: function(date) {\n
+\t\tvar day = date.getDay();\n
+\t\treturn [(day > 0 && day < 6), ""];\n
+\t},\n
+\n
+\t/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.\n
+\t * @param  date  Date - the date to get the week for\n
+\t * @return  number - the number of the week within the year that contains this date\n
+\t */\n
+\tiso8601Week: function(date) {\n
+\t\tvar time,\n
+\t\t\tcheckDate = new Date(date.getTime());\n
+\n
+\t\t// Find Thursday of this week starting on Monday\n
+\t\tcheckDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));\n
+\n
+\t\ttime = checkDate.getTime();\n
+\t\tcheckDate.setMonth(0); // Compare with Jan 1\n
+\t\tcheckDate.setDate(1);\n
+\t\treturn Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;\n
+\t},\n
+\n
+\t/* Parse a string value into a date object.\n
+\t * See formatDate below for the possible formats.\n
+\t *\n
+\t * @param  format string - the expected format of the date\n
+\t * @param  value string - the date in the above format\n
+\t * @param  settings Object - attributes include:\n
+\t *\t\t\t\t\tshortYearCutoff  number - the cutoff year for determining the century (optional)\n
+\t *\t\t\t\t\tdayNamesShort\tstring[7] - abbreviated names of the days from Sunday (optional)\n
+\t *\t\t\t\t\tdayNames\t\tstring[7] - names of the days from Sunday (optional)\n
+\t *\t\t\t\t\tmonthNamesShort string[12] - abbreviated names of the months (optional)\n
+\t *\t\t\t\t\tmonthNames\t\tstring[12] - names of the months (optional)\n
+\t * @return  Date - the extracted date value or null if value is blank\n
+\t */\n
+\tparseDate: function (format, value, settings) {\n
+\t\tif (format == null || value == null) {\n
+\t\t\tthrow "Invalid arguments";\n
+\t\t}\n
+\n
+\t\tvalue = (typeof value === "object" ? value.toString() : value + "");\n
+\t\tif (value === "") {\n
+\t\t\treturn null;\n
+\t\t}\n
+\n
+\t\tvar iFormat, dim, extra,\n
+\t\t\tiValue = 0,\n
+\t\t\tshortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,\n
+\t\t\tshortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :\n
+\t\t\t\tnew Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),\n
+\t\t\tdayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,\n
+\t\t\tdayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,\n
+\t\t\tmonthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,\n
+\t\t\tmonthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,\n
+\t\t\tyear = -1,\n
+\t\t\tmonth = -1,\n
+\t\t\tday = -1,\n
+\t\t\tdoy = -1,\n
+\t\t\tliteral = false,\n
+\t\t\tdate,\n
+\t\t\t// Check whether a format character is doubled\n
+\t\t\tlookAhead = function(match) {\n
+\t\t\t\tvar matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);\n
+\t\t\t\tif (matches) {\n
+\t\t\t\t\tiFormat++;\n
+\t\t\t\t}\n
+\t\t\t\treturn matches;\n
+\t\t\t},\n
+\t\t\t// Extract a number from the string value\n
+\t\t\tgetNumber = function(match) {\n
+\t\t\t\tvar isDoubled = lookAhead(match),\n
+\t\t\t\t\tsize = (match === "@" ? 14 : (match === "!" ? 20 :\n
+\t\t\t\t\t(match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),\n
+\t\t\t\t\tdigits = new RegExp("^\\\\d{1," + size + "}"),\n
+\t\t\t\t\tnum = value.substring(iValue).match(digits);\n
+\t\t\t\tif (!num) {\n
+\t\t\t\t\tthrow "Missing number at position " + iValue;\n
+\t\t\t\t}\n
+\t\t\t\tiValue += num[0].length;\n
+\t\t\t\treturn parseInt(num[0], 10);\n
+\t\t\t},\n
+\t\t\t// Extract a name from the string value and convert to an index\n
+\t\t\tgetName = function(match, shortNames, longNames) {\n
+\t\t\t\tvar index = -1,\n
+\t\t\t\t\tnames = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {\n
+\t\t\t\t\t\treturn [ [k, v] ];\n
+\t\t\t\t\t}).sort(function (a, b) {\n
+\t\t\t\t\t\treturn -(a[1].length - b[1].length);\n
+\t\t\t\t\t});\n
+\n
+\t\t\t\t$.each(names, function (i, pair) {\n
+\t\t\t\t\tvar name = pair[1];\n
+\t\t\t\t\tif (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {\n
+\t\t\t\t\t\tindex = pair[0];\n
+\t\t\t\t\t\tiValue += name.length;\n
+\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t\tif (index !== -1) {\n
+\t\t\t\t\treturn index + 1;\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthrow "Unknown name at position " + iValue;\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\t// Confirm that a literal character matches the string value\n
+\t\t\tcheckLiteral = function() {\n
+\t\t\t\tif (value.charAt(iValue) !== format.charAt(iFormat)) {\n
+\t\t\t\t\tthrow "Unexpected literal at position " + iValue;\n
+\t\t\t\t}\n
+\t\t\t\tiValue++;\n
+\t\t\t};\n
+\n
+\t\tfor (iFormat = 0; iFormat < format.length; iFormat++) {\n
+\t\t\tif (literal) {\n
+\t\t\t\tif (format.charAt(iFormat) === "\'" && !lookAhead("\'")) {\n
+\t\t\t\t\tliteral = false;\n
+\t\t\t\t} else {\n
+\t\t\t\t\tcheckLiteral();\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\tswitch (format.charAt(iFormat)) {\n
+\t\t\t\t\tcase "d":\n
+\t\t\t\t\t\tday = getNumber("d");\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tcase "D":\n
+\t\t\t\t\t\tgetName("D", dayNamesShort, dayNames);\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tcase "o":\n
+\t\t\t\t\t\tdoy = getNumber("o");\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tcase "m":\n
+\t\t\t\t\t\tmonth = getNumber("m");\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tcase "M":\n
+\t\t\t\t\t\tmonth = getName("M", monthNamesShort, monthNames);\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tcase "y":\n
+\t\t\t\t\t\tyear = getNumber("y");\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tcase "@":\n
+\t\t\t\t\t\tdate = new Date(getNumber("@"));\n
+\t\t\t\t\t\tyear = date.getFullYear();\n
+\t\t\t\t\t\tmonth = date.getMonth() + 1;\n
+\t\t\t\t\t\tday = date.getDate();\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tcase "!":\n
+\t\t\t\t\t\tdate = new Date((getNumber("!") - this._ticksTo1970) / 10000);\n
+\t\t\t\t\t\tyear = date.getFullYear();\n
+\t\t\t\t\t\tmonth = date.getMonth() + 1;\n
+\t\t\t\t\t\tday = date.getDate();\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tcase "\'":\n
+\t\t\t\t\t\tif (lookAhead("\'")){\n
+\t\t\t\t\t\t\tcheckLiteral();\n
+\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\tliteral = true;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tdefault:\n
+\t\t\t\t\t\tcheckLiteral();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif (iValue < value.length){\n
+\t\t\textra = value.substr(iValue);\n
+\t\t\tif (!/^\\s+/.test(extra)) {\n
+\t\t\t\tthrow "Extra/unparsed characters found in date: " + extra;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif (year === -1) {\n
+\t\t\tyear = new Date().getFullYear();\n
+\t\t} else if (year < 100) {\n
+\t\t\tyear += new Date().getFullYear() - new Date().getFullYear() % 100 +\n
+\t\t\t\t(year <= shortYearCutoff ? 0 : -100);\n
+\t\t}\n
+\n
+\t\tif (doy > -1) {\n
+\t\t\tmonth = 1;\n
+\t\t\tday = doy;\n
+\t\t\tdo {\n
+\t\t\t\tdim = this._getDaysInMonth(year, month - 1);\n
+\t\t\t\tif (day <= dim) {\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t\tmonth++;\n
+\t\t\t\tday -= dim;\n
+\t\t\t} while (true);\n
+\t\t}\n
+\n
+\t\tdate = this._daylightSavingAdjust(new Date(year, month - 1, day));\n
+\t\tif (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {\n
+\t\t\tthrow "Invalid date"; // E.g. 31/02/00\n
+\t\t}\n
+\t\treturn date;\n
+\t},\n
+\n
+\t/* Standard date formats. */\n
+\tATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)\n
+\tCOOKIE: "D, dd M yy",\n
+\tISO_8601: "yy-mm-dd",\n
+\tRFC_822: "D, d M y",\n
+\tRFC_850: "DD, dd-M-y",\n
+\tRFC_1036: "D, d M y",\n
+\tRFC_1123: "D, d M yy",\n
+\tRFC_2822: "D, d M yy",\n
+\tRSS: "D, d M y", // RFC 822\n
+\tTICKS: "!",\n
+\tTIMESTAMP: "@",\n
+\tW3C: "yy-mm-dd", // ISO 8601\n
+\n
+\t_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +\n
+\t\tMath.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),\n
+\n
+\t/* Format a date object into a string value.\n
+\t * The format can be combinations of the following:\n
+\t * d  - day of month (no leading zero)\n
+\t * dd - day of month (two digit)\n
+\t * o  - day of year (no leading zeros)\n
+\t * oo - day of year (three digit)\n
+\t * D  - day name short\n
+\t * DD - day name long\n
+\t * m  - month of year (no leading zero)\n
+\t * mm - month of year (two digit)\n
+\t * M  - month name short\n
+\t * MM - month name long\n
+\t * y  - year (two digit)\n
+\t * yy - year (four digit)\n
+\t * @ - Unix timestamp (ms since 01/01/1970)\n
+\t * ! - Windows ticks (100ns since 01/01/0001)\n
+\t * "..." - literal text\n
+\t * \'\' - single quote\n
+\t *\n
+\t * @param  format string - the desired format of the date\n
+\t * @param  date Date - the date value to format\n
+\t * @param  settings Object - attributes include:\n
+\t *\t\t\t\t\tdayNamesShort\tstring[7] - abbreviated names of the days from Sunday (optional)\n
+\t *\t\t\t\t\tdayNames\t\tstring[7] - names of the days from Sunday (optional)\n
+\t *\t\t\t\t\tmonthNamesShort string[12] - abbreviated names of the months (optional)\n
+\t *\t\t\t\t\tmonthNames\t\tstring[12] - names of the months (optional)\n
+\t * @return  string - the date in the above format\n
+\t */\n
+\tformatDate: function (format, date, settings) {\n
+\t\tif (!date) {\n
+\t\t\treturn "";\n
+\t\t}\n
+\n
+\t\tvar iFormat,\n
+\t\t\tdayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,\n
+\t\t\tdayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,\n
+\t\t\tmonthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,\n
+\t\t\tmonthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,\n
+\t\t\t// Check whether a format character is doubled\n
+\t\t\tlookAhead = function(match) {\n
+\t\t\t\tvar matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);\n
+\t\t\t\tif (matches) {\n
+\t\t\t\t\tiFormat++;\n
+\t\t\t\t}\n
+\t\t\t\treturn matches;\n
+\t\t\t},\n
+\t\t\t// Format a number, with leading zero if necessary\n
+\t\t\tformatNumber = function(match, value, len) {\n
+\t\t\t\tvar num = "" + value;\n
+\t\t\t\tif (lookAhead(match)) {\n
+\t\t\t\t\twhile (num.length < len) {\n
+\t\t\t\t\t\tnum = "0" + num;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\treturn num;\n
+\t\t\t},\n
+\t\t\t// Format a name, short or long as requested\n
+\t\t\tformatName = function(match, value, shortNames, longNames) {\n
+\t\t\t\treturn (lookAhead(match) ? longNames[value] : shortNames[value]);\n
+\t\t\t},\n
+\t\t\toutput = "",\n
+\t\t\tliteral = false;\n
+\n
+\t\tif (date) {\n
+\t\t\tfor (iFormat = 0; iFormat < format.length; iFormat++) {\n
+\t\t\t\tif (literal) {\n
+\t\t\t\t\tif (format.charAt(iFormat) === "\'" && !lookAhead("\'")) {\n
+\t\t\t\t\t\tliteral = false;\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\toutput += format.charAt(iFormat);\n
+\t\t\t\t\t}\n
+\t\t\t\t} else {\n
+\t\t\t\t\tswitch (format.charAt(iFormat)) {\n
+\t\t\t\t\t\tcase "d":\n
+\t\t\t\t\t\t\toutput += formatNumber("d", date.getDate(), 2);\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tcase "D":\n
+\t\t\t\t\t\t\toutput += formatName("D", date.getDay(), dayNamesShort, dayNames);\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tcase "o":\n
+\t\t\t\t\t\t\toutput += formatNumber("o",\n
+\t\t\t\t\t\t\t\tMath.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tcase "m":\n
+\t\t\t\t\t\t\toutput += formatNumber("m", date.getMonth() + 1, 2);\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tcase "M":\n
+\t\t\t\t\t\t\toutput += formatName("M", date.getMonth(), monthNamesShort, monthNames);\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tcase "y":\n
+\t\t\t\t\t\t\toutput += (lookAhead("y") ? date.getFullYear() :\n
+\t\t\t\t\t\t\t\t(date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tcase "@":\n
+\t\t\t\t\t\t\toutput += date.getTime();\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tcase "!":\n
+\t\t\t\t\t\t\toutput += date.getTime() * 10000 + this._ticksTo1970;\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tcase "\'":\n
+\t\t\t\t\t\t\tif (lookAhead("\'")) {\n
+\t\t\t\t\t\t\t\toutput += "\'";\n
+\t\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t\tliteral = true;\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tdefault:\n
+\t\t\t\t\t\t\toutput += format.charAt(iFormat);\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn output;\n
+\t},\n
+\n
+\t/* Extract all possible characters from the date format. */\n
+\t_possibleChars: function (format) {\n
+\t\tvar iFormat,\n
+\t\t\tchars = "",\n
+\t\t\tliteral = false,\n
+\t\t\t// Check whether a format character is doubled\n
+\t\t\tlookAhead = function(match) {\n
+\t\t\t\tvar matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);\n
+\t\t\t\tif (matches) {\n
+\t\t\t\t\tiFormat++;\n
+\t\t\t\t}\n
+\t\t\t\treturn matches;\n
+\t\t\t};\n
+\n
+\t\tfor (iFormat = 0; iFormat < format.length; iFormat++) {\n
+\t\t\tif (literal) {\n
+\t\t\t\tif (format.charAt(iFormat) === "\'" && !lookAhead("\'")) {\n
+\t\t\t\t\tliteral = false;\n
+\t\t\t\t} else {\n
+\t\t\t\t\tchars += format.charAt(iFormat);\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\tswitch (format.charAt(iFormat)) {\n
+\t\t\t\t\tcase "d": case "m": case "y": case "@":\n
+\t\t\t\t\t\tchars += "0123456789";\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tcase "D": case "M":\n
+\t\t\t\t\t\treturn null; // Accept anything\n
+\t\t\t\t\tcase "\'":\n
+\t\t\t\t\t\tif (lookAhead("\'")) {\n
+\t\t\t\t\t\t\tchars += "\'";\n
+\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\tliteral = true;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\tdefault:\n
+\t\t\t\t\t\tchars += format.charAt(iFormat);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn chars;\n
+\t},\n
+\n
+\t/* Get a setting value, defaulting if necessary. */\n
+\t_get: function(inst, name) {\n
+\t\treturn inst.settings[name] !== undefined ?\n
+\t\t\tinst.settings[name] : this._defaults[name];\n
+\t},\n
+\n
+\t/* Parse existing date and initialise date picker. */\n
+\t_setDateFromField: function(inst, noDefault) {\n
+\t\tif (inst.input.val() === inst.lastVal) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tvar dateFormat = this._get(inst, "dateFormat"),\n
+\t\t\tdates = inst.lastVal = inst.input ? inst.input.val() : null,\n
+\t\t\tdefaultDate = this._getDefaultDate(inst),\n
+\t\t\tdate = defaultDate,\n
+\t\t\tsettings = this._getFormatConfig(inst);\n
+\n
+\t\ttry {\n
+\t\t\tdate = this.parseDate(dateFormat, dates, settings) || defaultDate;\n
+\t\t} catch (event) {\n
+\t\t\tdates = (noDefault ? "" : dates);\n
+\t\t}\n
+\t\tinst.selectedDay = date.getDate();\n
+\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n
+\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n
+\t\tinst.currentDay = (dates ? date.getDate() : 0);\n
+\t\tinst.currentMonth = (dates ? date.getMonth() : 0);\n
+\t\tinst.currentYear = (dates ? date.getFullYear() : 0);\n
+\t\tthis._adjustInstDate(inst);\n
+\t},\n
+\n
+\t/* Retrieve the default date shown on opening. */\n
+\t_getDefaultDate: function(inst) {\n
+\t\treturn this._restrictMinMax(inst,\n
+\t\t\tthis._determineDate(inst, this._get(inst, "defaultDate"), new Date()));\n
+\t},\n
+\n
+\t/* A date may be specified as an exact value or a relative one. */\n
+\t_determineDate: function(inst, date, defaultDate) {\n
+\t\tvar offsetNumeric = function(offset) {\n
+\t\t\t\tvar date = new Date();\n
+\t\t\t\tdate.setDate(date.getDate() + offset);\n
+\t\t\t\treturn date;\n
+\t\t\t},\n
+\t\t\toffsetString = function(offset) {\n
+\t\t\t\ttry {\n
+\t\t\t\t\treturn $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),\n
+\t\t\t\t\t\toffset, $.datepicker._getFormatConfig(inst));\n
+\t\t\t\t}\n
+\t\t\t\tcatch (e) {\n
+\t\t\t\t\t// Ignore\n
+\t\t\t\t}\n
+\n
+\t\t\t\tvar date = (offset.toLowerCase().match(/^c/) ?\n
+\t\t\t\t\t$.datepicker._getDate(inst) : null) || new Date(),\n
+\t\t\t\t\tyear = date.getFullYear(),\n
+\t\t\t\t\tmonth = date.getMonth(),\n
+\t\t\t\t\tday = date.getDate(),\n
+\t\t\t\t\tpattern = /([+\\-]?[0-9]+)\\s*(d|D|w|W|m|M|y|Y)?/g,\n
+\t\t\t\t\tmatches = pattern.exec(offset);\n
+\n
+\t\t\t\twhile (matches) {\n
+\t\t\t\t\tswitch (matches[2] || "d") {\n
+\t\t\t\t\t\tcase "d" : case "D" :\n
+\t\t\t\t\t\t\tday += parseInt(matches[1],10); break;\n
+\t\t\t\t\t\tcase "w" : case "W" :\n
+\t\t\t\t\t\t\tday += parseInt(matches[1],10) * 7; break;\n
+\t\t\t\t\t\tcase "m" : case "M" :\n
+\t\t\t\t\t\t\tmonth += parseInt(matches[1],10);\n
+\t\t\t\t\t\t\tday = Math.min(day, $.datepicker._getDaysInMonth(year, month));\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tcase "y": case "Y" :\n
+\t\t\t\t\t\t\tyear += parseInt(matches[1],10);\n
+\t\t\t\t\t\t\tday = Math.min(day, $.datepicker._getDaysInMonth(year, month));\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tmatches = pattern.exec(offset);\n
+\t\t\t\t}\n
+\t\t\t\treturn new Date(year, month, day);\n
+\t\t\t},\n
+\t\t\tnewDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :\n
+\t\t\t\t(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));\n
+\n
+\t\tnewDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);\n
+\t\tif (newDate) {\n
+\t\t\tnewDate.setHours(0);\n
+\t\t\tnewDate.setMinutes(0);\n
+\t\t\tnewDate.setSeconds(0);\n
+\t\t\tnewDate.setMilliseconds(0);\n
+\t\t}\n
+\t\treturn this._daylightSavingAdjust(newDate);\n
+\t},\n
+\n
+\t/* Handle switch to/from daylight saving.\n
+\t * Hours may be non-zero on daylight saving cut-over:\n
+\t * > 12 when midnight changeover, but then cannot generate\n
+\t * midnight datetime, so jump to 1AM, otherwise reset.\n
+\t * @param  date  (Date) the date to check\n
+\t * @return  (Date) the corrected date\n
+\t */\n
+\t_daylightSavingAdjust: function(date) {\n
+\t\tif (!date) {\n
+\t\t\treturn null;\n
+\t\t}\n
+\t\tdate.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);\n
+\t\treturn date;\n
+\t},\n
+\n
+\t/* Set the date(s) directly. */\n
+\t_setDate: function(inst, date, noChange) {\n
+\t\tvar clear = !date,\n
+\t\t\torigMonth = inst.selectedMonth,\n
+\t\t\torigYear = inst.selectedYear,\n
+\t\t\tnewDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));\n
+\n
+\t\tinst.selectedDay = inst.currentDay = newDate.getDate();\n
+\t\tinst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();\n
+\t\tinst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();\n
+\t\tif ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {\n
+\t\t\tthis._notifyChange(inst);\n
+\t\t}\n
+\t\tthis._adjustInstDate(inst);\n
+\t\tif (inst.input) {\n
+\t\t\tinst.input.val(clear ? "" : this._formatDate(inst));\n
+\t\t}\n
+\t},\n
+\n
+\t/* Retrieve the date(s) directly. */\n
+\t_getDate: function(inst) {\n
+\t\tvar startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :\n
+\t\t\tthis._daylightSavingAdjust(new Date(\n
+\t\t\tinst.currentYear, inst.currentMonth, inst.currentDay)));\n
+\t\t\treturn startDate;\n
+\t},\n
+\n
+\t/* Attach the onxxx handlers.  These are declared statically so\n
+\t * they work with static code transformers like Caja.\n
+\t */\n
+\t_attachHandlers: function(inst) {\n
+\t\tvar stepMonths = this._get(inst, "stepMonths"),\n
+\t\t\tid = "#" + inst.id.replace( /\\\\\\\\/g, "\\\\" );\n
+\t\tinst.dpDiv.find("[data-handler]").map(function () {\n
+\t\t\tvar handler = {\n
+\t\t\t\tprev: function () {\n
+\t\t\t\t\t$.datepicker._adjustDate(id, -stepMonths, "M");\n
+\t\t\t\t},\n
+\t\t\t\tnext: function () {\n
+\t\t\t\t\t$.datepicker._adjustDate(id, +stepMonths, "M");\n
+\t\t\t\t},\n
+\t\t\t\thide: function () {\n
+\t\t\t\t\t$.datepicker._hideDatepicker();\n
+\t\t\t\t},\n
+\t\t\t\ttoday: function () {\n
+\t\t\t\t\t$.datepicker._gotoToday(id);\n
+\t\t\t\t},\n
+\t\t\t\tselectDay: function () {\n
+\t\t\t\t\t$.datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t},\n
+\t\t\t\tselectMonth: function () {\n
+\t\t\t\t\t$.datepicker._selectMonthYear(id, this, "M");\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t},\n
+\t\t\t\tselectYear: function () {\n
+\t\t\t\t\t$.datepicker._selectMonthYear(id, this, "Y");\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t};\n
+\t\t\t$(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);\n
+\t\t});\n
+\t},\n
+\n
+\t/* Generate the HTML for the current state of the date picker. */\n
+\t_generateHTML: function(inst) {\n
+\t\tvar maxDraw, prevText, prev, nextText, next, currentText, gotoDate,\n
+\t\t\tcontrols, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,\n
+\t\t\tmonthNames, monthNamesShort, beforeShowDay, showOtherMonths,\n
+\t\t\tselectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,\n
+\t\t\tcornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,\n
+\t\t\tprintDate, dRow, tbody, daySettings, otherMonth, unselectable,\n
+\t\t\ttempDate = new Date(),\n
+\t\t\ttoday = this._daylightSavingAdjust(\n
+\t\t\t\tnew Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time\n
+\t\t\tisRTL = this._get(inst, "isRTL"),\n
+\t\t\tshowButtonPanel = this._get(inst, "showButtonPanel"),\n
+\t\t\thideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),\n
+\t\t\tnavigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),\n
+\t\t\tnumMonths = this._getNumberOfMonths(inst),\n
+\t\t\tshowCurrentAtPos = this._get(inst, "showCurrentAtPos"),\n
+\t\t\tstepMonths = this._get(inst, "stepMonths"),\n
+\t\t\tisMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),\n
+\t\t\tcurrentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :\n
+\t\t\t\tnew Date(inst.currentYear, inst.currentMonth, inst.currentDay))),\n
+\t\t\tminDate = this._getMinMaxDate(inst, "min"),\n
+\t\t\tmaxDate = this._getMinMaxDate(inst, "max"),\n
+\t\t\tdrawMonth = inst.drawMonth - showCurrentAtPos,\n
+\t\t\tdrawYear = inst.drawYear;\n
+\n
+\t\tif (drawMonth < 0) {\n
+\t\t\tdrawMonth += 12;\n
+\t\t\tdrawYear--;\n
+\t\t}\n
+\t\tif (maxDate) {\n
+\t\t\tmaxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),\n
+\t\t\t\tmaxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));\n
+\t\t\tmaxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);\n
+\t\t\twhile (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {\n
+\t\t\t\tdrawMonth--;\n
+\t\t\t\tif (drawMonth < 0) {\n
+\t\t\t\t\tdrawMonth = 11;\n
+\t\t\t\t\tdrawYear--;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t\tinst.drawMonth = drawMonth;\n
+\t\tinst.drawYear = drawYear;\n
+\n
+\t\tprevText = this._get(inst, "prevText");\n
+\t\tprevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,\n
+\t\t\tthis._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),\n
+\t\t\tthis._getFormatConfig(inst)));\n
+\n
+\t\tprev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?\n
+\t\t\t"<a class=\'ui-datepicker-prev ui-corner-all\' data-handler=\'prev\' data-event=\'click\'" +\n
+\t\t\t" title=\'" + prevText + "\'><span class=\'ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "\'>" + prevText + "</span></a>" :\n
+\t\t\t(hideIfNoPrevNext ? "" : "<a class=\'ui-datepicker-prev ui-corner-all ui-state-disabled\' title=\'"+ prevText +"\'><span class=\'ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "\'>" + prevText + "</span></a>"));\n
+\n
+\t\tnextText = this._get(inst, "nextText");\n
+\t\tnextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,\n
+\t\t\tthis._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),\n
+\t\t\tthis._getFormatConfig(inst)));\n
+\n
+\t\tnext = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?\n
+\t\t\t"<a class=\'ui-datepicker-next ui-corner-all\' data-handler=\'next\' data-event=\'click\'" +\n
+\t\t\t" title=\'" + nextText + "\'><span class=\'ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "\'>" + nextText + "</span></a>" :\n
+\t\t\t(hideIfNoPrevNext ? "" : "<a class=\'ui-datepicker-next ui-corner-all ui-state-disabled\' title=\'"+ nextText + "\'><span class=\'ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "\'>" + nextText + "</span></a>"));\n
+\n
+\t\tcurrentText = this._get(inst, "currentText");\n
+\t\tgotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);\n
+\t\tcurrentText = (!navigationAsDateFormat ? currentText :\n
+\t\t\tthis.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));\n
+\n
+\t\tcontrols = (!inst.inline ? "<button type=\'button\' class=\'ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all\' data-handler=\'hide\' data-event=\'click\'>" +\n
+\t\t\tthis._get(inst, "closeText") + "</button>" : "");\n
+\n
+\t\tbuttonPanel = (showButtonPanel) ? "<div class=\'ui-datepicker-buttonpane ui-widget-content\'>" + (isRTL ? controls : "") +\n
+\t\t\t(this._isInRange(inst, gotoDate) ? "<button type=\'button\' class=\'ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all\' data-handler=\'today\' data-event=\'click\'" +\n
+\t\t\t">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";\n
+\n
+\t\tfirstDay = parseInt(this._get(inst, "firstDay"),10);\n
+\t\tfirstDay = (isNaN(firstDay) ? 0 : firstDay);\n
+\n
+\t\tshowWeek = this._get(inst, "showWeek");\n
+\t\tdayNames = this._get(inst, "dayNames");\n
+\t\tdayNamesMin = this._get(inst, "dayNamesMin");\n
+\t\tmonthNames = this._get(inst, "monthNames");\n
+\t\tmonthNamesShort = this._get(inst, "monthNamesShort");\n
+\t\tbeforeShowDay = this._get(inst, "beforeShowDay");\n
+\t\tshowOtherMonths = this._get(inst, "showOtherMonths");\n
+\t\tselectOtherMonths = this._get(inst, "selectOtherMonths");\n
+\t\tdefaultDate = this._getDefaultDate(inst);\n
+\t\thtml = "";\n
+\t\tdow;\n
+\t\tfor (row = 0; row < numMonths[0]; row++) {\n
+\t\t\tgroup = "";\n
+\t\t\tthis.maxRows = 4;\n
+\t\t\tfor (col = 0; col < numMonths[1]; col++) {\n
+\t\t\t\tselectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));\n
+\t\t\t\tcornerClass = " ui-corner-all";\n
+\t\t\t\tcalender = "";\n
+\t\t\t\tif (isMultiMonth) {\n
+\t\t\t\t\tcalender += "<div class=\'ui-datepicker-group";\n
+\t\t\t\t\tif (numMonths[1] > 1) {\n
+\t\t\t\t\t\tswitch (col) {\n
+\t\t\t\t\t\t\tcase 0: calender += " ui-datepicker-group-first";\n
+\t\t\t\t\t\t\t\tcornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;\n
+\t\t\t\t\t\t\tcase numMonths[1]-1: calender += " ui-datepicker-group-last";\n
+\t\t\t\t\t\t\t\tcornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;\n
+\t\t\t\t\t\t\tdefault: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\tcalender += "\'>";\n
+\t\t\t\t}\n
+\t\t\t\tcalender += "<div class=\'ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "\'>" +\n
+\t\t\t\t\t(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +\n
+\t\t\t\t\t(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +\n
+\t\t\t\t\tthis._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,\n
+\t\t\t\t\trow > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers\n
+\t\t\t\t\t"</div><table class=\'ui-datepicker-calendar\'><thead>" +\n
+\t\t\t\t\t"<tr>";\n
+\t\t\t\tthead = (showWeek ? "<th class=\'ui-datepicker-week-col\'>" + this._get(inst, "weekHeader") + "</th>" : "");\n
+\t\t\t\tfor (dow = 0; dow < 7; dow++) { // days of the week\n
+\t\t\t\t\tday = (dow + firstDay) % 7;\n
+\t\t\t\t\tthead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class=\'ui-datepicker-week-end\'" : "") + ">" +\n
+\t\t\t\t\t\t"<span title=\'" + dayNames[day] + "\'>" + dayNamesMin[day] + "</span></th>";\n
+\t\t\t\t}\n
+\t\t\t\tcalender += thead + "</tr></thead><tbody>";\n
+\t\t\t\tdaysInMonth = this._getDaysInMonth(drawYear, drawMonth);\n
+\t\t\t\tif (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {\n
+\t\t\t\t\tinst.selectedDay = Math.min(inst.selectedDay, daysInMonth);\n
+\t\t\t\t}\n
+\t\t\t\tleadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;\n
+\t\t\t\tcurRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate\n
+\t\t\t\tnumRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)\n
+\t\t\t\tthis.maxRows = numRows;\n
+\t\t\t\tprintDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));\n
+\t\t\t\tfor (dRow = 0; dRow < numRows; dRow++) { // create date picker rows\n
+\t\t\t\t\tcalender += "<tr>";\n
+\t\t\t\t\ttbody = (!showWeek ? "" : "<td class=\'ui-datepicker-week-col\'>" +\n
+\t\t\t\t\t\tthis._get(inst, "calculateWeek")(printDate) + "</td>");\n
+\t\t\t\t\tfor (dow = 0; dow < 7; dow++) { // create date picker days\n
+\t\t\t\t\t\tdaySettings = (beforeShowDay ?\n
+\t\t\t\t\t\t\tbeforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);\n
+\t\t\t\t\t\totherMonth = (printDate.getMonth() !== drawMonth);\n
+\t\t\t\t\t\tunselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||\n
+\t\t\t\t\t\t\t(minDate && printDate < minDate) || (maxDate && printDate > maxDate);\n
+\t\t\t\t\t\ttbody += "<td class=\'" +\n
+\t\t\t\t\t\t\t((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends\n
+\t\t\t\t\t\t\t(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months\n
+\t\t\t\t\t\t\t((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key\n
+\t\t\t\t\t\t\t(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?\n
+\t\t\t\t\t\t\t// or defaultDate is current printedDate and defaultDate is selectedDate\n
+\t\t\t\t\t\t\t" " + this._dayOverClass : "") + // highlight selected day\n
+\t\t\t\t\t\t\t(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") +  // highlight unselectable days\n
+\t\t\t\t\t\t\t(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates\n
+\t\t\t\t\t\t\t(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day\n
+\t\t\t\t\t\t\t(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "\'" + // highlight today (if different)\n
+\t\t\t\t\t\t\t((!otherMonth || showOtherMonths) && daySettings[2] ? " title=\'" + daySettings[2].replace(/\'/g, "&#39;") + "\'" : "") + // cell title\n
+\t\t\t\t\t\t\t(unselectable ? "" : " data-handler=\'selectDay\' data-event=\'click\' data-month=\'" + printDate.getMonth() + "\' data-year=\'" + printDate.getFullYear() + "\'") + ">" + // actions\n
+\t\t\t\t\t\t\t(otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months\n
+\t\t\t\t\t\t\t(unselectable ? "<span class=\'ui-state-default\'>" + printDate.getDate() + "</span>" : "<a class=\'ui-state-default" +\n
+\t\t\t\t\t\t\t(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +\n
+\t\t\t\t\t\t\t(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day\n
+\t\t\t\t\t\t\t(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months\n
+\t\t\t\t\t\t\t"\' href=\'#\'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date\n
+\t\t\t\t\t\tprintDate.setDate(printDate.getDate() + 1);\n
+\t\t\t\t\t\tprintDate = this._daylightSavingAdjust(printDate);\n
+\t\t\t\t\t}\n
+\t\t\t\t\tcalender += tbody + "</tr>";\n
+\t\t\t\t}\n
+\t\t\t\tdrawMonth++;\n
+\t\t\t\tif (drawMonth > 11) {\n
+\t\t\t\t\tdrawMonth = 0;\n
+\t\t\t\t\tdrawYear++;\n
+\t\t\t\t}\n
+\t\t\t\tcalender += "</tbody></table>" + (isMultiMonth ? "</div>" +\n
+\t\t\t\t\t\t\t((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class=\'ui-datepicker-row-break\'></div>" : "") : "");\n
+\t\t\t\tgroup += calender;\n
+\t\t\t}\n
+\t\t\thtml += group;\n
+\t\t}\n
+\t\thtml += buttonPanel;\n
+\t\tinst._keyEvent = false;\n
+\t\treturn html;\n
+\t},\n
+\n
+\t/* Generate the month and year header. */\n
+\t_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,\n
+\t\t\tsecondary, monthNames, monthNamesShort) {\n
+\n
+\t\tvar inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,\n
+\t\t\tchangeMonth = this._get(inst, "changeMonth"),\n
+\t\t\tchangeYear = this._get(inst, "changeYear"),\n
+\t\t\tshowMonthAfterYear = this._get(inst, "showMonthAfterYear"),\n
+\t\t\thtml = "<div class=\'ui-datepicker-title\'>",\n
+\t\t\tmonthHtml = "";\n
+\n
+\t\t// month selection\n
+\t\tif (secondary || !changeMonth) {\n
+\t\t\tmonthHtml += "<span class=\'ui-datepicker-month\'>" + monthNames[drawMonth] + "</span>";\n
+\t\t} else {\n
+\t\t\tinMinYear = (minDate && minDate.getFullYear() === drawYear);\n
+\t\t\tinMaxYear = (maxDate && maxDate.getFullYear() === drawYear);\n
+\t\t\tmonthHtml += "<select class=\'ui-datepicker-month\' data-handler=\'selectMonth\' data-event=\'change\'>";\n
+\t\t\tfor ( month = 0; month < 12; month++) {\n
+\t\t\t\tif ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {\n
+\t\t\t\t\tmonthHtml += "<option value=\'" + month + "\'" +\n
+\t\t\t\t\t\t(month === drawMonth ? " selected=\'selected\'" : "") +\n
+\t\t\t\t\t\t">" + monthNamesShort[month] + "</option>";\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tmonthHtml += "</select>";\n
+\t\t}\n
+\n
+\t\tif (!showMonthAfterYear) {\n
+\t\t\thtml += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");\n
+\t\t}\n
+\n
+\t\t// year selection\n
+\t\tif ( !inst.yearshtml ) {\n
+\t\t\tinst.yearshtml = "";\n
+\t\t\tif (secondary || !changeYear) {\n
+\t\t\t\thtml += "<span class=\'ui-datepicker-year\'>" + drawYear + "</span>";\n
+\t\t\t} else {\n
+\t\t\t\t// determine range of years to display\n
+\t\t\t\tyears = this._get(inst, "yearRange").split(":");\n
+\t\t\t\tthisYear = new Date().getFullYear();\n
+\t\t\t\tdetermineYear = function(value) {\n
+\t\t\t\t\tvar year = (value.match(/c[+\\-].*/) ? drawYear + parseInt(value.substring(1), 10) :\n
+\t\t\t\t\t\t(value.match(/[+\\-].*/) ? thisYear + parseInt(value, 10) :\n
+\t\t\t\t\t\tparseInt(value, 10)));\n
+\t\t\t\t\treturn (isNaN(year) ? thisYear : year);\n
+\t\t\t\t};\n
+\t\t\t\tyear = determineYear(years[0]);\n
+\t\t\t\tendYear = Math.max(year, determineYear(years[1] || ""));\n
+\t\t\t\tyear = (minDate ? Math.max(year, minDate.getFullYear()) : year);\n
+\t\t\t\tendYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);\n
+\t\t\t\tinst.yearshtml += "<select class=\'ui-datepicker-year\' data-handler=\'selectYear\' data-event=\'change\'>";\n
+\t\t\t\tfor (; year <= endYear; year++) {\n
+\t\t\t\t\tinst.yearshtml += "<option value=\'" + year + "\'" +\n
+\t\t\t\t\t\t(year === drawYear ? " selected=\'selected\'" : "") +\n
+\t\t\t\t\t\t">" + year + "</option>";\n
+\t\t\t\t}\n
+\t\t\t\tinst.yearshtml += "</select>";\n
+\n
+\t\t\t\thtml += inst.yearshtml;\n
+\t\t\t\tinst.yearshtml = null;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\thtml += this._get(inst, "yearSuffix");\n
+\t\tif (showMonthAfterYear) {\n
+\t\t\thtml += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;\n
+\t\t}\n
+\t\thtml += "</div>"; // Close datepicker_header\n
+\t\treturn html;\n
+\t},\n
+\n
+\t/* Adjust one of the date sub-fields. */\n
+\t_adjustInstDate: function(inst, offset, period) {\n
+\t\tvar year = inst.drawYear + (period === "Y" ? offset : 0),\n
+\t\t\tmonth = inst.drawMonth + (period === "M" ? offset : 0),\n
+\t\t\tday = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),\n
+\t\t\tdate = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));\n
+\n
+\t\tinst.selectedDay = date.getDate();\n
+\t\tinst.drawMonth = inst.selectedMonth = date.getMonth();\n
+\t\tinst.drawYear = inst.selectedYear = date.getFullYear();\n
+\t\tif (period === "M" || period === "Y") {\n
+\t\t\tthis._notifyChange(inst);\n
+\t\t}\n
+\t},\n
+\n
+\t/* Ensure a date is within any min/max bounds. */\n
+\t_restrictMinMax: function(inst, date) {\n
+\t\tvar minDate = this._getMinMaxDate(inst, "min"),\n
+\t\t\tmaxDate = this._getMinMaxDate(inst, "max"),\n
+\t\t\tnewDate = (minDate && date < minDate ? minDate : date);\n
+\t\treturn (maxDate && newDate > maxDate ? maxDate : newDate);\n
+\t},\n
+\n
+\t/* Notify change of month/year. */\n
+\t_notifyChange: function(inst) {\n
+\t\tvar onChange = this._get(inst, "onChangeMonthYear");\n
+\t\tif (onChange) {\n
+\t\t\tonChange.apply((inst.input ? inst.input[0] : null),\n
+\t\t\t\t[inst.selectedYear, inst.selectedMonth + 1, inst]);\n
+\t\t}\n
+\t},\n
+\n
+\t/* Determine the number of months to show. */\n
+\t_getNumberOfMonths: function(inst) {\n
+\t\tvar numMonths = this._get(inst, "numberOfMonths");\n
+\t\treturn (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));\n
+\t},\n
+\n
+\t/* Determine the current maximum date - ensure no time components are set. */\n
+\t_getMinMaxDate: function(inst, minMax) {\n
+\t\treturn this._determineDate(inst, this._get(inst, minMax + "Date"), null);\n
+\t},\n
+\n
+\t/* Find the number of days in a given month. */\n
+\t_getDaysInMonth: function(year, month) {\n
+\t\treturn 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();\n
+\t},\n
+\n
+\t/* Find the day of the week of the first of a month. */\n
+\t_getFirstDayOfMonth: function(year, month) {\n
+\t\treturn new Date(year, month, 1).getDay();\n
+\t},\n
+\n
+\t/* Determines if we should allow a "next/prev" month display change. */\n
+\t_canAdjustMonth: function(inst, offset, curYear, curMonth) {\n
+\t\tvar numMonths = this._getNumberOfMonths(inst),\n
+\t\t\tdate = this._daylightSavingAdjust(new Date(curYear,\n
+\t\t\tcurMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));\n
+\n
+\t\tif (offset < 0) {\n
+\t\t\tdate.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));\n
+\t\t}\n
+\t\treturn this._isInRange(inst, date);\n
+\t},\n
+\n
+\t/* Is the given date in the accepted range? */\n
+\t_isInRange: function(inst, date) {\n
+\t\tvar yearSplit, currentYear,\n
+\t\t\tminDate = this._getMinMaxDate(inst, "min"),\n
+\t\t\tmaxDate = this._getMinMaxDate(inst, "max"),\n
+\t\t\tminYear = null,\n
+\t\t\tmaxYear = null,\n
+\t\t\tyears = this._get(inst, "yearRange");\n
+\t\t\tif (years){\n
+\t\t\t\tyearSplit = years.split(":");\n
+\t\t\t\tcurrentYear = new Date().getFullYear();\n
+\t\t\t\tminYear = parseInt(yearSplit[0], 10);\n
+\t\t\t\tmaxYear = parseInt(yearSplit[1], 10);\n
+\t\t\t\tif ( yearSplit[0].match(/[+\\-].*/) ) {\n
+\t\t\t\t\tminYear += currentYear;\n
+\t\t\t\t}\n
+\t\t\t\tif ( yearSplit[1].match(/[+\\-].*/) ) {\n
+\t\t\t\t\tmaxYear += currentYear;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\treturn ((!minDate || date.getTime() >= minDate.getTime()) &&\n
+\t\t\t(!maxDate || date.getTime() <= maxDate.getTime()) &&\n
+\t\t\t(!minYear || date.getFullYear() >= minYear) &&\n
+\t\t\t(!maxYear || date.getFullYear() <= maxYear));\n
+\t},\n
+\n
+\t/* Provide the configuration settings for formatting/parsing. */\n
+\t_getFormatConfig: function(inst) {\n
+\t\tvar shortYearCutoff = this._get(inst, "shortYearCutoff");\n
+\t\tshortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :\n
+\t\t\tnew Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));\n
+\t\treturn {shortYearCutoff: shortYearCutoff,\n
+\t\t\tdayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),\n
+\t\t\tmonthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};\n
+\t},\n
+\n
+\t/* Format the given date for display. */\n
+\t_formatDate: function(inst, day, month, year) {\n
+\t\tif (!day) {\n
+\t\t\tinst.currentDay = inst.selectedDay;\n
+\t\t\tinst.currentMonth = inst.selectedMonth;\n
+\t\t\tinst.currentYear = inst.selectedYear;\n
+\t\t}\n
+\t\tvar date = (day ? (typeof day === "object" ? day :\n
+\t\t\tthis._daylightSavingAdjust(new Date(year, month, day))) :\n
+\t\t\tthis._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));\n
+\t\treturn this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));\n
+\t}\n
+});\n
+\n
+/*\n
+ * Bind hover events for datepicker elements.\n
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.\n
+ * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.\n
+ */\n
+function bindHover(dpDiv) {\n
+\tvar selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";\n
+\treturn dpDiv.delegate(selector, "mouseout", function() {\n
+\t\t\t$(this).removeClass("ui-state-hover");\n
+\t\t\tif (this.className.indexOf("ui-datepicker-prev") !== -1) {\n
+\t\t\t\t$(this).removeClass("ui-datepicker-prev-hover");\n
+\t\t\t}\n
+\t\t\tif (this.className.indexOf("ui-datepicker-next") !== -1) {\n
+\t\t\t\t$(this).removeClass("ui-datepicker-next-hover");\n
+\t\t\t}\n
+\t\t})\n
+\t\t.delegate(selector, "mouseover", function(){\n
+\t\t\tif (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {\n
+\t\t\t\t$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");\n
+\t\t\t\t$(this).addClass("ui-state-hover");\n
+\t\t\t\tif (this.className.indexOf("ui-datepicker-prev") !== -1) {\n
+\t\t\t\t\t$(this).addClass("ui-datepicker-prev-hover");\n
+\t\t\t\t}\n
+\t\t\t\tif (this.className.indexOf("ui-datepicker-next") !== -1) {\n
+\t\t\t\t\t$(this).addClass("ui-datepicker-next-hover");\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t});\n
+}\n
+\n
+/* jQuery extend now ignores nulls! */\n
+function extendRemove(target, props) {\n
+\t$.extend(target, props);\n
+\tfor (var name in props) {\n
+\t\tif (props[name] == null) {\n
+\t\t\ttarget[name] = props[name];\n
+\t\t}\n
+\t}\n
+\treturn target;\n
+}\n
+\n
+/* Invoke the datepicker functionality.\n
+   @param  options  string - a command, optionally followed by additional parameters or\n
+\t\t\t\t\tObject - settings for attaching new datepicker functionality\n
+   @return  jQuery object */\n
+$.fn.datepicker = function(options){\n
+\n
+\t/* Verify an empty collection wasn\'t passed - Fixes #6976 */\n
+\tif ( !this.length ) {\n
+\t\treturn this;\n
+\t}\n
+\n
+\t/* Initialise the date picker. */\n
+\tif (!$.datepicker.initialized) {\n
+\t\t$(document).mousedown($.datepicker._checkExternalClick);\n
+\t\t$.datepicker.initialized = true;\n
+\t}\n
+\n
+\t/* Append datepicker main container to body if not exist. */\n
+\tif ($("#"+$.datepicker._mainDivId).length === 0) {\n
+\t\t$("body").append($.datepicker.dpDiv);\n
+\t}\n
+\n
+\tvar otherArgs = Array.prototype.slice.call(arguments, 1);\n
+\tif (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {\n
+\t\treturn $.datepicker["_" + options + "Datepicker"].\n
+\t\t\tapply($.datepicker, [this[0]].concat(otherArgs));\n
+\t}\n
+\tif (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {\n
+\t\treturn $.datepicker["_" + options + "Datepicker"].\n
+\t\t\tapply($.datepicker, [this[0]].concat(otherArgs));\n
+\t}\n
+\treturn this.each(function() {\n
+\t\ttypeof options === "string" ?\n
+\t\t\t$.datepicker["_" + options + "Datepicker"].\n
+\t\t\t\tapply($.datepicker, [this].concat(otherArgs)) :\n
+\t\t\t$.datepicker._attachDatepicker(this, options);\n
+\t});\n
+};\n
+\n
+$.datepicker = new Datepicker(); // singleton instance\n
+$.datepicker.initialized = false;\n
+$.datepicker.uuid = new Date().getTime();\n
+$.datepicker.version = "1.10.4";\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+var sizeRelatedOptions = {\n
+\t\tbuttons: true,\n
+\t\theight: true,\n
+\t\tmaxHeight: true,\n
+\t\tmaxWidth: true,\n
+\t\tminHeight: true,\n
+\t\tminWidth: true,\n
+\t\twidth: true\n
+\t},\n
+\tresizableRelatedOptions = {\n
+\t\tmaxHeight: true,\n
+\t\tmaxWidth: true,\n
+\t\tminHeight: true,\n
+\t\tminWidth: true\n
+\t};\n
+\n
+$.widget( "ui.dialog", {\n
+\tversion: "1.10.4",\n
+\toptions: {\n
+\t\tappendTo: "body",\n
+\t\tautoOpen: true,\n
+\t\tbuttons: [],\n
+\t\tcloseOnEscape: true,\n
+\t\tcloseText: "close",\n
+\t\tdialogClass: "",\n
+\t\tdraggable: true,\n
+\t\thide: null,\n
+\t\theight: "auto",\n
+\t\tmaxHeight: null,\n
+\t\tmaxWidth: null,\n
+\t\tminHeight: 150,\n
+\t\tminWidth: 150,\n
+\t\tmodal: false,\n
+\t\tposition: {\n
+\t\t\tmy: "center",\n
+\t\t\tat: "center",\n
+\t\t\tof: window,\n
+\t\t\tcollision: "fit",\n
+\t\t\t// Ensure the titlebar is always visible\n
+\t\t\tusing: function( pos ) {\n
+\t\t\t\tvar topOffset = $( this ).css( pos ).offset().top;\n
+\t\t\t\tif ( topOffset < 0 ) {\n
+\t\t\t\t\t$( this ).css( "top", pos.top - topOffset );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t},\n
+\t\tresizable: true,\n
+\t\tshow: null,\n
+\t\ttitle: null,\n
+\t\twidth: 300,\n
+\n
+\t\t// callbacks\n
+\t\tbeforeClose: null,\n
+\t\tclose: null,\n
+\t\tdrag: null,\n
+\t\tdragStart: null,\n
+\t\tdragStop: null,\n
+\t\tfocus: null,\n
+\t\topen: null,\n
+\t\tresize: null,\n
+\t\tresizeStart: null,\n
+\t\tresizeStop: null\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tthis.originalCss = {\n
+\t\t\tdisplay: this.element[0].style.display,\n
+\t\t\twidth: this.element[0].style.width,\n
+\t\t\tminHeight: this.element[0].style.minHeight,\n
+\t\t\tmaxHeight: this.element[0].style.maxHeight,\n
+\t\t\theight: this.element[0].style.height\n
+\t\t};\n
+\t\tthis.originalPosition = {\n
+\t\t\tparent: this.element.parent(),\n
+\t\t\tindex: this.element.parent().children().index( this.element )\n
+\t\t};\n
+\t\tthis.originalTitle = this.element.attr("title");\n
+\t\tthis.options.title = this.options.title || this.originalTitle;\n
+\n
+\t\tthis._createWrapper();\n
+\n
+\t\tthis.element\n
+\t\t\t.show()\n
+\t\t\t.removeAttr("title")\n
+\t\t\t.addClass("ui-dialog-content ui-widget-content")\n
+\t\t\t.appendTo( this.uiDialog );\n
+\n
+\t\tthis._createTitlebar();\n
+\t\tthis._createButtonPane();\n
+\n
+\t\tif ( this.options.draggable && $.fn.draggable ) {\n
+\t\t\tthis._makeDraggable();\n
+\t\t}\n
+\t\tif ( this.options.resizable && $.fn.resizable ) {\n
+\t\t\tthis._makeResizable();\n
+\t\t}\n
+\n
+\t\tthis._isOpen = false;\n
+\t},\n
+\n
+\t_init: function() {\n
+\t\tif ( this.options.autoOpen ) {\n
+\t\t\tthis.open();\n
+\t\t}\n
+\t},\n
+\n
+\t_appendTo: function() {\n
+\t\tvar element = this.options.appendTo;\n
+\t\tif ( element && (element.jquery || element.nodeType) ) {\n
+\t\t\treturn $( element );\n
+\t\t}\n
+\t\treturn this.document.find( element || "body" ).eq( 0 );\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tvar next,\n
+\t\t\toriginalPosition = this.originalPosition;\n
+\n
+\t\tthis._destroyOverlay();\n
+\n
+\t\tthis.element\n
+\t\t\t.removeUniqueId()\n
+\t\t\t.removeClass("ui-dialog-content ui-widget-content")\n
+\t\t\t.css( this.originalCss )\n
+\t\t\t// Without detaching first, the following becomes really slow\n
+\t\t\t.detach();\n
+\n
+\t\tthis.uiDialog.stop( true, true ).remove();\n
+\n
+\t\tif ( this.originalTitle ) {\n
+\t\t\tthis.element.attr( "title", this.originalTitle );\n
+\t\t}\n
+\n
+\t\tnext = originalPosition.parent.children().eq( originalPosition.index );\n
+\t\t// Don\'t try to place the dialog next to itself (#8613)\n
+\t\tif ( next.length && next[0] !== this.element[0] ) {\n
+\t\t\tnext.before( this.element );\n
+\t\t} else {\n
+\t\t\toriginalPosition.parent.append( this.element );\n
+\t\t}\n
+\t},\n
+\n
+\twidget: function() {\n
+\t\treturn this.uiDialog;\n
+\t},\n
+\n
+\tdisable: $.noop,\n
+\tenable: $.noop,\n
+\n
+\tclose: function( event ) {\n
+\t\tvar activeElement,\n
+\t\t\tthat = this;\n
+\n
+\t\tif ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis._isOpen = false;\n
+\t\tthis._destroyOverlay();\n
+\n
+\t\tif ( !this.opener.filter(":focusable").focus().length ) {\n
+\n
+\t\t\t// support: IE9\n
+\t\t\t// IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>\n
+\t\t\ttry {\n
+\t\t\t\tactiveElement = this.document[ 0 ].activeElement;\n
+\n
+\t\t\t\t// Support: IE9, IE10\n
+\t\t\t\t// If the <body> is blurred, IE will switch windows, see #4520\n
+\t\t\t\tif ( activeElement && activeElement.nodeName.toLowerCase() !== "body" ) {\n
+\n
+\t\t\t\t\t// Hiding a focused element doesn\'t trigger blur in WebKit\n
+\t\t\t\t\t// so in case we have nothing to focus on, explicitly blur the active element\n
+\t\t\t\t\t// https://bugs.webkit.org/show_bug.cgi?id=47182\n
+\t\t\t\t\t$( activeElement ).blur();\n
+\t\t\t\t}\n
+\t\t\t} catch ( error ) {}\n
+\t\t}\n
+\n
+\t\tthis._hide( this.uiDialog, this.options.hide, function() {\n
+\t\t\tthat._trigger( "close", event );\n
+\t\t});\n
+\t},\n
+\n
+\tisOpen: function() {\n
+\t\treturn this._isOpen;\n
+\t},\n
+\n
+\tmoveToTop: function() {\n
+\t\tthis._moveToTop();\n
+\t},\n
+\n
+\t_moveToTop: function( event, silent ) {\n
+\t\tvar moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length;\n
+\t\tif ( moved && !silent ) {\n
+\t\t\tthis._trigger( "focus", event );\n
+\t\t}\n
+\t\treturn moved;\n
+\t},\n
+\n
+\topen: function() {\n
+\t\tvar that = this;\n
+\t\tif ( this._isOpen ) {\n
+\t\t\tif ( this._moveToTop() ) {\n
+\t\t\t\tthis._focusTabbable();\n
+\t\t\t}\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis._isOpen = true;\n
+\t\tthis.opener = $( this.document[0].activeElement );\n
+\n
+\t\tthis._size();\n
+\t\tthis._position();\n
+\t\tthis._createOverlay();\n
+\t\tthis._moveToTop( null, true );\n
+\t\tthis._show( this.uiDialog, this.options.show, function() {\n
+\t\t\tthat._focusTabbable();\n
+\t\t\tthat._trigger("focus");\n
+\t\t});\n
+\n
+\t\tthis._trigger("open");\n
+\t},\n
+\n
+\t_focusTabbable: function() {\n
+\t\t// Set focus to the first match:\n
+\t\t// 1. First element inside the dialog matching [autofocus]\n
+\t\t// 2. Tabbable element inside the content element\n
+\t\t// 3. Tabbable element inside the buttonpane\n
+\t\t// 4. The close button\n
+\t\t// 5. The dialog itself\n
+\t\tvar hasFocus = this.element.find("[autofocus]");\n
+\t\tif ( !hasFocus.length ) {\n
+\t\t\thasFocus = this.element.find(":tabbable");\n
+\t\t}\n
+\t\tif ( !hasFocus.length ) {\n
+\t\t\thasFocus = this.uiDialogButtonPane.find(":tabbable");\n
+\t\t}\n
+\t\tif ( !hasFocus.length ) {\n
+\t\t\thasFocus = this.uiDialogTitlebarClose.filter(":tabbable");\n
+\t\t}\n
+\t\tif ( !hasFocus.length ) {\n
+\t\t\thasFocus = this.uiDialog;\n
+\t\t}\n
+\t\thasFocus.eq( 0 ).focus();\n
+\t},\n
+\n
+\t_keepFocus: function( event ) {\n
+\t\tfunction checkFocus() {\n
+\t\t\tvar activeElement = this.document[0].activeElement,\n
+\t\t\t\tisActive = this.uiDialog[0] === activeElement ||\n
+\t\t\t\t\t$.contains( this.uiDialog[0], activeElement );\n
+\t\t\tif ( !isActive ) {\n
+\t\t\t\tthis._focusTabbable();\n
+\t\t\t}\n
+\t\t}\n
+\t\tevent.preventDefault();\n
+\t\tcheckFocus.call( this );\n
+\t\t// support: IE\n
+\t\t// IE <= 8 doesn\'t prevent moving focus even with event.preventDefault()\n
+\t\t// so we check again later\n
+\t\tthis._delay( checkFocus );\n
+\t},\n
+\n
+\t_createWrapper: function() {\n
+\t\tthis.uiDialog = $("<div>")\n
+\t\t\t.addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +\n
+\t\t\t\tthis.options.dialogClass )\n
+\t\t\t.hide()\n
+\t\t\t.attr({\n
+\t\t\t\t// Setting tabIndex makes the div focusable\n
+\t\t\t\ttabIndex: -1,\n
+\t\t\t\trole: "dialog"\n
+\t\t\t})\n
+\t\t\t.appendTo( this._appendTo() );\n
+\n
+\t\tthis._on( this.uiDialog, {\n
+\t\t\tkeydown: function( event ) {\n
+\t\t\t\tif ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&\n
+\t\t\t\t\t\tevent.keyCode === $.ui.keyCode.ESCAPE ) {\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\tthis.close( event );\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// prevent tabbing out of dialogs\n
+\t\t\t\tif ( event.keyCode !== $.ui.keyCode.TAB ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\tvar tabbables = this.uiDialog.find(":tabbable"),\n
+\t\t\t\t\tfirst = tabbables.filter(":first"),\n
+\t\t\t\t\tlast  = tabbables.filter(":last");\n
+\n
+\t\t\t\tif ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {\n
+\t\t\t\t\tfirst.focus( 1 );\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t} else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {\n
+\t\t\t\t\tlast.focus( 1 );\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tmousedown: function( event ) {\n
+\t\t\t\tif ( this._moveToTop( event ) ) {\n
+\t\t\t\t\tthis._focusTabbable();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\t// We assume that any existing aria-describedby attribute means\n
+\t\t// that the dialog content is marked up properly\n
+\t\t// otherwise we brute force the content as the description\n
+\t\tif ( !this.element.find("[aria-describedby]").length ) {\n
+\t\t\tthis.uiDialog.attr({\n
+\t\t\t\t"aria-describedby": this.element.uniqueId().attr("id")\n
+\t\t\t});\n
+\t\t}\n
+\t},\n
+\n
+\t_createTitlebar: function() {\n
+\t\tvar uiDialogTitle;\n
+\n
+\t\tthis.uiDialogTitlebar = $("<div>")\n
+\t\t\t.addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix")\n
+\t\t\t.prependTo( this.uiDialog );\n
+\t\tthis._on( this.uiDialogTitlebar, {\n
+\t\t\tmousedown: function( event ) {\n
+\t\t\t\t// Don\'t prevent click on close button (#8838)\n
+\t\t\t\t// Focusing a dialog that is partially scrolled out of view\n
+\t\t\t\t// causes the browser to scroll it into view, preventing the click event\n
+\t\t\t\tif ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) {\n
+\t\t\t\t\t// Dialog isn\'t getting focus when dragging (#8063)\n
+\t\t\t\t\tthis.uiDialog.focus();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\t// support: IE\n
+\t\t// Use type="button" to prevent enter keypresses in textboxes from closing the\n
+\t\t// dialog in IE (#9312)\n
+\t\tthis.uiDialogTitlebarClose = $( "<button type=\'button\'></button>" )\n
+\t\t\t.button({\n
+\t\t\t\tlabel: this.options.closeText,\n
+\t\t\t\ticons: {\n
+\t\t\t\t\tprimary: "ui-icon-closethick"\n
+\t\t\t\t},\n
+\t\t\t\ttext: false\n
+\t\t\t})\n
+\t\t\t.addClass("ui-dialog-titlebar-close")\n
+\t\t\t.appendTo( this.uiDialogTitlebar );\n
+\t\tthis._on( this.uiDialogTitlebarClose, {\n
+\t\t\tclick: function( event ) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t\tthis.close( event );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tuiDialogTitle = $("<span>")\n
+\t\t\t.uniqueId()\n
+\t\t\t.addClass("ui-dialog-title")\n
+\t\t\t.prependTo( this.uiDialogTitlebar );\n
+\t\tthis._title( uiDialogTitle );\n
+\n
+\t\tthis.uiDialog.attr({\n
+\t\t\t"aria-labelledby": uiDialogTitle.attr("id")\n
+\t\t});\n
+\t},\n
+\n
+\t_title: function( title ) {\n
+\t\tif ( !this.options.title ) {\n
+\t\t\ttitle.html("&#160;");\n
+\t\t}\n
+\t\ttitle.text( this.options.title );\n
+\t},\n
+\n
+\t_createButtonPane: function() {\n
+\t\tthis.uiDialogButtonPane = $("<div>")\n
+\t\t\t.addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");\n
+\n
+\t\tthis.uiButtonSet = $("<div>")\n
+\t\t\t.addClass("ui-dialog-buttonset")\n
+\t\t\t.appendTo( this.uiDialogButtonPane );\n
+\n
+\t\tthis._createButtons();\n
+\t},\n
+\n
+\t_createButtons: function() {\n
+\t\tvar that = this,\n
+\t\t\tbuttons = this.options.buttons;\n
+\n
+\t\t// if we already have a button pane, remove it\n
+\t\tthis.uiDialogButtonPane.remove();\n
+\t\tthis.uiButtonSet.empty();\n
+\n
+\t\tif ( $.isEmptyObject( buttons ) || ($.isArray( buttons ) && !buttons.length) ) {\n
+\t\t\tthis.uiDialog.removeClass("ui-dialog-buttons");\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t$.each( buttons, function( name, props ) {\n
+\t\t\tvar click, buttonOptions;\n
+\t\t\tprops = $.isFunction( props ) ?\n
+\t\t\t\t{ click: props, text: name } :\n
+\t\t\t\tprops;\n
+\t\t\t// Default to a non-submitting button\n
+\t\t\tprops = $.extend( { type: "button" }, props );\n
+\t\t\t// Change the context for the click callback to be the main element\n
+\t\t\tclick = props.click;\n
+\t\t\tprops.click = function() {\n
+\t\t\t\tclick.apply( that.element[0], arguments );\n
+\t\t\t};\n
+\t\t\tbuttonOptions = {\n
+\t\t\t\ticons: props.icons,\n
+\t\t\t\ttext: props.showText\n
+\t\t\t};\n
+\t\t\tdelete props.icons;\n
+\t\t\tdelete props.showText;\n
+\t\t\t$( "<button></button>", props )\n
+\t\t\t\t.button( buttonOptions )\n
+\t\t\t\t.appendTo( that.uiButtonSet );\n
+\t\t});\n
+\t\tthis.uiDialog.addClass("ui-dialog-buttons");\n
+\t\tthis.uiDialogButtonPane.appendTo( this.uiDialog );\n
+\t},\n
+\n
+\t_makeDraggable: function() {\n
+\t\tvar that = this,\n
+\t\t\toptions = this.options;\n
+\n
+\t\tfunction filteredUi( ui ) {\n
+\t\t\treturn {\n
+\t\t\t\tposition: ui.position,\n
+\t\t\t\toffset: ui.offset\n
+\t\t\t};\n
+\t\t}\n
+\n
+\t\tthis.uiDialog.draggable({\n
+\t\t\tcancel: ".ui-dialog-content, .ui-dialog-titlebar-close",\n
+\t\t\thandle: ".ui-dialog-titlebar",\n
+\t\t\tcontainment: "document",\n
+\t\t\tstart: function( event, ui ) {\n
+\t\t\t\t$( this ).addClass("ui-dialog-dragging");\n
+\t\t\t\tthat._blockFrames();\n
+\t\t\t\tthat._trigger( "dragStart", event, filteredUi( ui ) );\n
+\t\t\t},\n
+\t\t\tdrag: function( event, ui ) {\n
+\t\t\t\tthat._trigger( "drag", event, filteredUi( ui ) );\n
+\t\t\t},\n
+\t\t\tstop: function( event, ui ) {\n
+\t\t\t\toptions.position = [\n
+\t\t\t\t\tui.position.left - that.document.scrollLeft(),\n
+\t\t\t\t\tui.position.top - that.document.scrollTop()\n
+\t\t\t\t];\n
+\t\t\t\t$( this ).removeClass("ui-dialog-dragging");\n
+\t\t\t\tthat._unblockFrames();\n
+\t\t\t\tthat._trigger( "dragStop", event, filteredUi( ui ) );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_makeResizable: function() {\n
+\t\tvar that = this,\n
+\t\t\toptions = this.options,\n
+\t\t\thandles = options.resizable,\n
+\t\t\t// .ui-resizable has position: relative defined in the stylesheet\n
+\t\t\t// but dialogs have to use absolute or fixed positioning\n
+\t\t\tposition = this.uiDialog.css("position"),\n
+\t\t\tresizeHandles = typeof handles === "string" ?\n
+\t\t\t\thandles\t:\n
+\t\t\t\t"n,e,s,w,se,sw,ne,nw";\n
+\n
+\t\tfunction filteredUi( ui ) {\n
+\t\t\treturn {\n
+\t\t\t\toriginalPosition: ui.originalPosition,\n
+\t\t\t\toriginalSize: ui.originalSize,\n
+\t\t\t\tposition: ui.position,\n
+\t\t\t\tsize: ui.size\n
+\t\t\t};\n
+\t\t}\n
+\n
+\t\tthis.uiDialog.resizable({\n
+\t\t\tcancel: ".ui-dialog-content",\n
+\t\t\tcontainment: "document",\n
+\t\t\talsoResize: this.element,\n
+\t\t\tmaxWidth: options.maxWidth,\n
+\t\t\tmaxHeight: options.maxHeight,\n
+\t\t\tminWidth: options.minWidth,\n
+\t\t\tminHeight: this._minHeight(),\n
+\t\t\thandles: resizeHandles,\n
+\t\t\tstart: function( event, ui ) {\n
+\t\t\t\t$( this ).addClass("ui-dialog-resizing");\n
+\t\t\t\tthat._blockFrames();\n
+\t\t\t\tthat._trigger( "resizeStart", event, filteredUi( ui ) );\n
+\t\t\t},\n
+\t\t\tresize: function( event, ui ) {\n
+\t\t\t\tthat._trigger( "resize", event, filteredUi( ui ) );\n
+\t\t\t},\n
+\t\t\tstop: function( event, ui ) {\n
+\t\t\t\toptions.height = $( this ).height();\n
+\t\t\t\toptions.width = $( this ).width();\n
+\t\t\t\t$( this ).removeClass("ui-dialog-resizing");\n
+\t\t\t\tthat._unblockFrames();\n
+\t\t\t\tthat._trigger( "resizeStop", event, filteredUi( ui ) );\n
+\t\t\t}\n
+\t\t})\n
+\t\t.css( "position", position );\n
+\t},\n
+\n
+\t_minHeight: function() {\n
+\t\tvar options = this.options;\n
+\n
+\t\treturn options.height === "auto" ?\n
+\t\t\toptions.minHeight :\n
+\t\t\tMath.min( options.minHeight, options.height );\n
+\t},\n
+\n
+\t_position: function() {\n
+\t\t// Need to show the dialog to get the actual offset in the position plugin\n
+\t\tvar isVisible = this.uiDialog.is(":visible");\n
+\t\tif ( !isVisible ) {\n
+\t\t\tthis.uiDialog.show();\n
+\t\t}\n
+\t\tthis.uiDialog.position( this.options.position );\n
+\t\tif ( !isVisible ) {\n
+\t\t\tthis.uiDialog.hide();\n
+\t\t}\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tvar that = this,\n
+\t\t\tresize = false,\n
+\t\t\tresizableOptions = {};\n
+\n
+\t\t$.each( options, function( key, value ) {\n
+\t\t\tthat._setOption( key, value );\n
+\n
+\t\t\tif ( key in sizeRelatedOptions ) {\n
+\t\t\t\tresize = true;\n
+\t\t\t}\n
+\t\t\tif ( key in resizableRelatedOptions ) {\n
+\t\t\t\tresizableOptions[ key ] = value;\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tif ( resize ) {\n
+\t\t\tthis._size();\n
+\t\t\tthis._position();\n
+\t\t}\n
+\t\tif ( this.uiDialog.is(":data(ui-resizable)") ) {\n
+\t
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+\t\tthis.uiDialog.resizable( "option", resizableOptions );\n
+\t\t}\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tvar isDraggable, isResizable,\n
+\t\t\tuiDialog = this.uiDialog;\n
+\n
+\t\tif ( key === "dialogClass" ) {\n
+\t\t\tuiDialog\n
+\t\t\t\t.removeClass( this.options.dialogClass )\n
+\t\t\t\t.addClass( value );\n
+\t\t}\n
+\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis._super( key, value );\n
+\n
+\t\tif ( key === "appendTo" ) {\n
+\t\t\tthis.uiDialog.appendTo( this._appendTo() );\n
+\t\t}\n
+\n
+\t\tif ( key === "buttons" ) {\n
+\t\t\tthis._createButtons();\n
+\t\t}\n
+\n
+\t\tif ( key === "closeText" ) {\n
+\t\t\tthis.uiDialogTitlebarClose.button({\n
+\t\t\t\t// Ensure that we always pass a string\n
+\t\t\t\tlabel: "" + value\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tif ( key === "draggable" ) {\n
+\t\t\tisDraggable = uiDialog.is(":data(ui-draggable)");\n
+\t\t\tif ( isDraggable && !value ) {\n
+\t\t\t\tuiDialog.draggable("destroy");\n
+\t\t\t}\n
+\n
+\t\t\tif ( !isDraggable && value ) {\n
+\t\t\t\tthis._makeDraggable();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( key === "position" ) {\n
+\t\t\tthis._position();\n
+\t\t}\n
+\n
+\t\tif ( key === "resizable" ) {\n
+\t\t\t// currently resizable, becoming non-resizable\n
+\t\t\tisResizable = uiDialog.is(":data(ui-resizable)");\n
+\t\t\tif ( isResizable && !value ) {\n
+\t\t\t\tuiDialog.resizable("destroy");\n
+\t\t\t}\n
+\n
+\t\t\t// currently resizable, changing handles\n
+\t\t\tif ( isResizable && typeof value === "string" ) {\n
+\t\t\t\tuiDialog.resizable( "option", "handles", value );\n
+\t\t\t}\n
+\n
+\t\t\t// currently non-resizable, becoming resizable\n
+\t\t\tif ( !isResizable && value !== false ) {\n
+\t\t\t\tthis._makeResizable();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( key === "title" ) {\n
+\t\t\tthis._title( this.uiDialogTitlebar.find(".ui-dialog-title") );\n
+\t\t}\n
+\t},\n
+\n
+\t_size: function() {\n
+\t\t// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content\n
+\t\t// divs will both have width and height set, so we need to reset them\n
+\t\tvar nonContentHeight, minContentHeight, maxContentHeight,\n
+\t\t\toptions = this.options;\n
+\n
+\t\t// Reset content sizing\n
+\t\tthis.element.show().css({\n
+\t\t\twidth: "auto",\n
+\t\t\tminHeight: 0,\n
+\t\t\tmaxHeight: "none",\n
+\t\t\theight: 0\n
+\t\t});\n
+\n
+\t\tif ( options.minWidth > options.width ) {\n
+\t\t\toptions.width = options.minWidth;\n
+\t\t}\n
+\n
+\t\t// reset wrapper sizing\n
+\t\t// determine the height of all the non-content elements\n
+\t\tnonContentHeight = this.uiDialog.css({\n
+\t\t\t\theight: "auto",\n
+\t\t\t\twidth: options.width\n
+\t\t\t})\n
+\t\t\t.outerHeight();\n
+\t\tminContentHeight = Math.max( 0, options.minHeight - nonContentHeight );\n
+\t\tmaxContentHeight = typeof options.maxHeight === "number" ?\n
+\t\t\tMath.max( 0, options.maxHeight - nonContentHeight ) :\n
+\t\t\t"none";\n
+\n
+\t\tif ( options.height === "auto" ) {\n
+\t\t\tthis.element.css({\n
+\t\t\t\tminHeight: minContentHeight,\n
+\t\t\t\tmaxHeight: maxContentHeight,\n
+\t\t\t\theight: "auto"\n
+\t\t\t});\n
+\t\t} else {\n
+\t\t\tthis.element.height( Math.max( 0, options.height - nonContentHeight ) );\n
+\t\t}\n
+\n
+\t\tif (this.uiDialog.is(":data(ui-resizable)") ) {\n
+\t\t\tthis.uiDialog.resizable( "option", "minHeight", this._minHeight() );\n
+\t\t}\n
+\t},\n
+\n
+\t_blockFrames: function() {\n
+\t\tthis.iframeBlocks = this.document.find( "iframe" ).map(function() {\n
+\t\t\tvar iframe = $( this );\n
+\n
+\t\t\treturn $( "<div>" )\n
+\t\t\t\t.css({\n
+\t\t\t\t\tposition: "absolute",\n
+\t\t\t\t\twidth: iframe.outerWidth(),\n
+\t\t\t\t\theight: iframe.outerHeight()\n
+\t\t\t\t})\n
+\t\t\t\t.appendTo( iframe.parent() )\n
+\t\t\t\t.offset( iframe.offset() )[0];\n
+\t\t});\n
+\t},\n
+\n
+\t_unblockFrames: function() {\n
+\t\tif ( this.iframeBlocks ) {\n
+\t\t\tthis.iframeBlocks.remove();\n
+\t\t\tdelete this.iframeBlocks;\n
+\t\t}\n
+\t},\n
+\n
+\t_allowInteraction: function( event ) {\n
+\t\tif ( $( event.target ).closest(".ui-dialog").length ) {\n
+\t\t\treturn true;\n
+\t\t}\n
+\n
+\t\t// TODO: Remove hack when datepicker implements\n
+\t\t// the .ui-front logic (#8989)\n
+\t\treturn !!$( event.target ).closest(".ui-datepicker").length;\n
+\t},\n
+\n
+\t_createOverlay: function() {\n
+\t\tif ( !this.options.modal ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tvar that = this,\n
+\t\t\twidgetFullName = this.widgetFullName;\n
+\t\tif ( !$.ui.dialog.overlayInstances ) {\n
+\t\t\t// Prevent use of anchors and inputs.\n
+\t\t\t// We use a delay in case the overlay is created from an\n
+\t\t\t// event that we\'re going to be cancelling. (#2804)\n
+\t\t\tthis._delay(function() {\n
+\t\t\t\t// Handle .dialog().dialog("close") (#4065)\n
+\t\t\t\tif ( $.ui.dialog.overlayInstances ) {\n
+\t\t\t\t\tthis.document.bind( "focusin.dialog", function( event ) {\n
+\t\t\t\t\t\tif ( !that._allowInteraction( event ) ) {\n
+\t\t\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\t\t\t$(".ui-dialog:visible:last .ui-dialog-content")\n
+\t\t\t\t\t\t\t\t.data( widgetFullName )._focusTabbable();\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t});\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tthis.overlay = $("<div>")\n
+\t\t\t.addClass("ui-widget-overlay ui-front")\n
+\t\t\t.appendTo( this._appendTo() );\n
+\t\tthis._on( this.overlay, {\n
+\t\t\tmousedown: "_keepFocus"\n
+\t\t});\n
+\t\t$.ui.dialog.overlayInstances++;\n
+\t},\n
+\n
+\t_destroyOverlay: function() {\n
+\t\tif ( !this.options.modal ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( this.overlay ) {\n
+\t\t\t$.ui.dialog.overlayInstances--;\n
+\n
+\t\t\tif ( !$.ui.dialog.overlayInstances ) {\n
+\t\t\t\tthis.document.unbind( "focusin.dialog" );\n
+\t\t\t}\n
+\t\t\tthis.overlay.remove();\n
+\t\t\tthis.overlay = null;\n
+\t\t}\n
+\t}\n
+});\n
+\n
+$.ui.dialog.overlayInstances = 0;\n
+\n
+// DEPRECATED\n
+if ( $.uiBackCompat !== false ) {\n
+\t// position option with array notation\n
+\t// just override with old implementation\n
+\t$.widget( "ui.dialog", $.ui.dialog, {\n
+\t\t_position: function() {\n
+\t\t\tvar position = this.options.position,\n
+\t\t\t\tmyAt = [],\n
+\t\t\t\toffset = [ 0, 0 ],\n
+\t\t\t\tisVisible;\n
+\n
+\t\t\tif ( position ) {\n
+\t\t\t\tif ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {\n
+\t\t\t\t\tmyAt = position.split ? position.split(" ") : [ position[0], position[1] ];\n
+\t\t\t\t\tif ( myAt.length === 1 ) {\n
+\t\t\t\t\t\tmyAt[1] = myAt[0];\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t$.each( [ "left", "top" ], function( i, offsetPosition ) {\n
+\t\t\t\t\t\tif ( +myAt[ i ] === myAt[ i ] ) {\n
+\t\t\t\t\t\t\toffset[ i ] = myAt[ i ];\n
+\t\t\t\t\t\t\tmyAt[ i ] = offsetPosition;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t});\n
+\n
+\t\t\t\t\tposition = {\n
+\t\t\t\t\t\tmy: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +\n
+\t\t\t\t\t\t\tmyAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),\n
+\t\t\t\t\t\tat: myAt.join(" ")\n
+\t\t\t\t\t};\n
+\t\t\t\t}\n
+\n
+\t\t\t\tposition = $.extend( {}, $.ui.dialog.prototype.options.position, position );\n
+\t\t\t} else {\n
+\t\t\t\tposition = $.ui.dialog.prototype.options.position;\n
+\t\t\t}\n
+\n
+\t\t\t// need to show the dialog to get the actual offset in the position plugin\n
+\t\t\tisVisible = this.uiDialog.is(":visible");\n
+\t\t\tif ( !isVisible ) {\n
+\t\t\t\tthis.uiDialog.show();\n
+\t\t\t}\n
+\t\t\tthis.uiDialog.position( position );\n
+\t\t\tif ( !isVisible ) {\n
+\t\t\t\tthis.uiDialog.hide();\n
+\t\t\t}\n
+\t\t}\n
+\t});\n
+}\n
+\n
+}( jQuery ) );\n
+(function( $, undefined ) {\n
+\n
+$.widget("ui.draggable", $.ui.mouse, {\n
+\tversion: "1.10.4",\n
+\twidgetEventPrefix: "drag",\n
+\toptions: {\n
+\t\taddClasses: true,\n
+\t\tappendTo: "parent",\n
+\t\taxis: false,\n
+\t\tconnectToSortable: false,\n
+\t\tcontainment: false,\n
+\t\tcursor: "auto",\n
+\t\tcursorAt: false,\n
+\t\tgrid: false,\n
+\t\thandle: false,\n
+\t\thelper: "original",\n
+\t\tiframeFix: false,\n
+\t\topacity: false,\n
+\t\trefreshPositions: false,\n
+\t\trevert: false,\n
+\t\trevertDuration: 500,\n
+\t\tscope: "default",\n
+\t\tscroll: true,\n
+\t\tscrollSensitivity: 20,\n
+\t\tscrollSpeed: 20,\n
+\t\tsnap: false,\n
+\t\tsnapMode: "both",\n
+\t\tsnapTolerance: 20,\n
+\t\tstack: false,\n
+\t\tzIndex: false,\n
+\n
+\t\t// callbacks\n
+\t\tdrag: null,\n
+\t\tstart: null,\n
+\t\tstop: null\n
+\t},\n
+\t_create: function() {\n
+\n
+\t\tif (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {\n
+\t\t\tthis.element[0].style.position = "relative";\n
+\t\t}\n
+\t\tif (this.options.addClasses){\n
+\t\t\tthis.element.addClass("ui-draggable");\n
+\t\t}\n
+\t\tif (this.options.disabled){\n
+\t\t\tthis.element.addClass("ui-draggable-disabled");\n
+\t\t}\n
+\n
+\t\tthis._mouseInit();\n
+\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tthis.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );\n
+\t\tthis._mouseDestroy();\n
+\t},\n
+\n
+\t_mouseCapture: function(event) {\n
+\n
+\t\tvar o = this.options;\n
+\n
+\t\t// among others, prevent a drag on a resizable-handle\n
+\t\tif (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\t//Quit if we\'re not on a valid handle\n
+\t\tthis.handle = this._getHandle(event);\n
+\t\tif (!this.handle) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\t$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {\n
+\t\t\t$("<div class=\'ui-draggable-iframeFix\' style=\'background: #fff;\'></div>")\n
+\t\t\t.css({\n
+\t\t\t\twidth: this.offsetWidth+"px", height: this.offsetHeight+"px",\n
+\t\t\t\tposition: "absolute", opacity: "0.001", zIndex: 1000\n
+\t\t\t})\n
+\t\t\t.css($(this).offset())\n
+\t\t\t.appendTo("body");\n
+\t\t});\n
+\n
+\t\treturn true;\n
+\n
+\t},\n
+\n
+\t_mouseStart: function(event) {\n
+\n
+\t\tvar o = this.options;\n
+\n
+\t\t//Create and append the visible helper\n
+\t\tthis.helper = this._createHelper(event);\n
+\n
+\t\tthis.helper.addClass("ui-draggable-dragging");\n
+\n
+\t\t//Cache the helper size\n
+\t\tthis._cacheHelperProportions();\n
+\n
+\t\t//If ddmanager is used for droppables, set the global draggable\n
+\t\tif($.ui.ddmanager) {\n
+\t\t\t$.ui.ddmanager.current = this;\n
+\t\t}\n
+\n
+\t\t/*\n
+\t\t * - Position generation -\n
+\t\t * This block generates everything position related - it\'s the core of draggables.\n
+\t\t */\n
+\n
+\t\t//Cache the margins of the original element\n
+\t\tthis._cacheMargins();\n
+\n
+\t\t//Store the helper\'s css position\n
+\t\tthis.cssPosition = this.helper.css( "position" );\n
+\t\tthis.scrollParent = this.helper.scrollParent();\n
+\t\tthis.offsetParent = this.helper.offsetParent();\n
+\t\tthis.offsetParentCssPosition = this.offsetParent.css( "position" );\n
+\n
+\t\t//The element\'s absolute position on the page minus margins\n
+\t\tthis.offset = this.positionAbs = this.element.offset();\n
+\t\tthis.offset = {\n
+\t\t\ttop: this.offset.top - this.margins.top,\n
+\t\t\tleft: this.offset.left - this.margins.left\n
+\t\t};\n
+\n
+\t\t//Reset scroll cache\n
+\t\tthis.offset.scroll = false;\n
+\n
+\t\t$.extend(this.offset, {\n
+\t\t\tclick: { //Where the click happened, relative to the element\n
+\t\t\t\tleft: event.pageX - this.offset.left,\n
+\t\t\t\ttop: event.pageY - this.offset.top\n
+\t\t\t},\n
+\t\t\tparent: this._getParentOffset(),\n
+\t\t\trelative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper\n
+\t\t});\n
+\n
+\t\t//Generate the original position\n
+\t\tthis.originalPosition = this.position = this._generatePosition(event);\n
+\t\tthis.originalPageX = event.pageX;\n
+\t\tthis.originalPageY = event.pageY;\n
+\n
+\t\t//Adjust the mouse offset relative to the helper if "cursorAt" is supplied\n
+\t\t(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));\n
+\n
+\t\t//Set a containment if given in the options\n
+\t\tthis._setContainment();\n
+\n
+\t\t//Trigger event + callbacks\n
+\t\tif(this._trigger("start", event) === false) {\n
+\t\t\tthis._clear();\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\t//Recache the helper size\n
+\t\tthis._cacheHelperProportions();\n
+\n
+\t\t//Prepare the droppable offsets\n
+\t\tif ($.ui.ddmanager && !o.dropBehaviour) {\n
+\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n
+\t\t}\n
+\n
+\n
+\t\tthis._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position\n
+\n
+\t\t//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)\n
+\t\tif ( $.ui.ddmanager ) {\n
+\t\t\t$.ui.ddmanager.dragStart(this, event);\n
+\t\t}\n
+\n
+\t\treturn true;\n
+\t},\n
+\n
+\t_mouseDrag: function(event, noPropagation) {\n
+\t\t// reset any necessary cached properties (see #5009)\n
+\t\tif ( this.offsetParentCssPosition === "fixed" ) {\n
+\t\t\tthis.offset.parent = this._getParentOffset();\n
+\t\t}\n
+\n
+\t\t//Compute the helpers position\n
+\t\tthis.position = this._generatePosition(event);\n
+\t\tthis.positionAbs = this._convertPositionTo("absolute");\n
+\n
+\t\t//Call plugins and callbacks and use the resulting position if something is returned\n
+\t\tif (!noPropagation) {\n
+\t\t\tvar ui = this._uiHash();\n
+\t\t\tif(this._trigger("drag", event, ui) === false) {\n
+\t\t\t\tthis._mouseUp({});\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t\tthis.position = ui.position;\n
+\t\t}\n
+\n
+\t\tif(!this.options.axis || this.options.axis !== "y") {\n
+\t\t\tthis.helper[0].style.left = this.position.left+"px";\n
+\t\t}\n
+\t\tif(!this.options.axis || this.options.axis !== "x") {\n
+\t\t\tthis.helper[0].style.top = this.position.top+"px";\n
+\t\t}\n
+\t\tif($.ui.ddmanager) {\n
+\t\t\t$.ui.ddmanager.drag(this, event);\n
+\t\t}\n
+\n
+\t\treturn false;\n
+\t},\n
+\n
+\t_mouseStop: function(event) {\n
+\n
+\t\t//If we are using droppables, inform the manager about the drop\n
+\t\tvar that = this,\n
+\t\t\tdropped = false;\n
+\t\tif ($.ui.ddmanager && !this.options.dropBehaviour) {\n
+\t\t\tdropped = $.ui.ddmanager.drop(this, event);\n
+\t\t}\n
+\n
+\t\t//if a drop comes from outside (a sortable)\n
+\t\tif(this.dropped) {\n
+\t\t\tdropped = this.dropped;\n
+\t\t\tthis.dropped = false;\n
+\t\t}\n
+\n
+\t\t//if the original element is no longer in the DOM don\'t bother to continue (see #8269)\n
+\t\tif ( this.options.helper === "original" && !$.contains( this.element[ 0 ].ownerDocument, this.element[ 0 ] ) ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\tif((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {\n
+\t\t\t$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {\n
+\t\t\t\tif(that._trigger("stop", event) !== false) {\n
+\t\t\t\t\tthat._clear();\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t} else {\n
+\t\t\tif(this._trigger("stop", event) !== false) {\n
+\t\t\t\tthis._clear();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn false;\n
+\t},\n
+\n
+\t_mouseUp: function(event) {\n
+\t\t//Remove frame helpers\n
+\t\t$("div.ui-draggable-iframeFix").each(function() {\n
+\t\t\tthis.parentNode.removeChild(this);\n
+\t\t});\n
+\n
+\t\t//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)\n
+\t\tif( $.ui.ddmanager ) {\n
+\t\t\t$.ui.ddmanager.dragStop(this, event);\n
+\t\t}\n
+\n
+\t\treturn $.ui.mouse.prototype._mouseUp.call(this, event);\n
+\t},\n
+\n
+\tcancel: function() {\n
+\n
+\t\tif(this.helper.is(".ui-draggable-dragging")) {\n
+\t\t\tthis._mouseUp({});\n
+\t\t} else {\n
+\t\t\tthis._clear();\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\n
+\t},\n
+\n
+\t_getHandle: function(event) {\n
+\t\treturn this.options.handle ?\n
+\t\t\t!!$( event.target ).closest( this.element.find( this.options.handle ) ).length :\n
+\t\t\ttrue;\n
+\t},\n
+\n
+\t_createHelper: function(event) {\n
+\n
+\t\tvar o = this.options,\n
+\t\t\thelper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);\n
+\n
+\t\tif(!helper.parents("body").length) {\n
+\t\t\thelper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));\n
+\t\t}\n
+\n
+\t\tif(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {\n
+\t\t\thelper.css("position", "absolute");\n
+\t\t}\n
+\n
+\t\treturn helper;\n
+\n
+\t},\n
+\n
+\t_adjustOffsetFromHelper: function(obj) {\n
+\t\tif (typeof obj === "string") {\n
+\t\t\tobj = obj.split(" ");\n
+\t\t}\n
+\t\tif ($.isArray(obj)) {\n
+\t\t\tobj = {left: +obj[0], top: +obj[1] || 0};\n
+\t\t}\n
+\t\tif ("left" in obj) {\n
+\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n
+\t\t}\n
+\t\tif ("right" in obj) {\n
+\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n
+\t\t}\n
+\t\tif ("top" in obj) {\n
+\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n
+\t\t}\n
+\t\tif ("bottom" in obj) {\n
+\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n
+\t\t}\n
+\t},\n
+\n
+\t_getParentOffset: function() {\n
+\n
+\t\t//Get the offsetParent and cache its position\n
+\t\tvar po = this.offsetParent.offset();\n
+\n
+\t\t// This is a special case where we need to modify a offset calculated on start, since the following happened:\n
+\t\t// 1. The position of the helper is absolute, so it\'s position is calculated based on the next positioned parent\n
+\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn\'t the document, which means that\n
+\t\t//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag\n
+\t\tif(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {\n
+\t\t\tpo.left += this.scrollParent.scrollLeft();\n
+\t\t\tpo.top += this.scrollParent.scrollTop();\n
+\t\t}\n
+\n
+\t\t//This needs to be actually done for all browsers, since pageX/pageY includes this information\n
+\t\t//Ugly IE fix\n
+\t\tif((this.offsetParent[0] === document.body) ||\n
+\t\t\t(this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {\n
+\t\t\tpo = { top: 0, left: 0 };\n
+\t\t}\n
+\n
+\t\treturn {\n
+\t\t\ttop: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),\n
+\t\t\tleft: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)\n
+\t\t};\n
+\n
+\t},\n
+\n
+\t_getRelativeOffset: function() {\n
+\n
+\t\tif(this.cssPosition === "relative") {\n
+\t\t\tvar p = this.element.position();\n
+\t\t\treturn {\n
+\t\t\t\ttop: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),\n
+\t\t\t\tleft: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()\n
+\t\t\t};\n
+\t\t} else {\n
+\t\t\treturn { top: 0, left: 0 };\n
+\t\t}\n
+\n
+\t},\n
+\n
+\t_cacheMargins: function() {\n
+\t\tthis.margins = {\n
+\t\t\tleft: (parseInt(this.element.css("marginLeft"),10) || 0),\n
+\t\t\ttop: (parseInt(this.element.css("marginTop"),10) || 0),\n
+\t\t\tright: (parseInt(this.element.css("marginRight"),10) || 0),\n
+\t\t\tbottom: (parseInt(this.element.css("marginBottom"),10) || 0)\n
+\t\t};\n
+\t},\n
+\n
+\t_cacheHelperProportions: function() {\n
+\t\tthis.helperProportions = {\n
+\t\t\twidth: this.helper.outerWidth(),\n
+\t\t\theight: this.helper.outerHeight()\n
+\t\t};\n
+\t},\n
+\n
+\t_setContainment: function() {\n
+\n
+\t\tvar over, c, ce,\n
+\t\t\to = this.options;\n
+\n
+\t\tif ( !o.containment ) {\n
+\t\t\tthis.containment = null;\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( o.containment === "window" ) {\n
+\t\t\tthis.containment = [\n
+\t\t\t\t$( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,\n
+\t\t\t\t$( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,\n
+\t\t\t\t$( window ).scrollLeft() + $( window ).width() - this.helperProportions.width - this.margins.left,\n
+\t\t\t\t$( window ).scrollTop() + ( $( window ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top\n
+\t\t\t];\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( o.containment === "document") {\n
+\t\t\tthis.containment = [\n
+\t\t\t\t0,\n
+\t\t\t\t0,\n
+\t\t\t\t$( document ).width() - this.helperProportions.width - this.margins.left,\n
+\t\t\t\t( $( document ).height() || document.body.parentNode.scrollHeight ) - this.helperProportions.height - this.margins.top\n
+\t\t\t];\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( o.containment.constructor === Array ) {\n
+\t\t\tthis.containment = o.containment;\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( o.containment === "parent" ) {\n
+\t\t\to.containment = this.helper[ 0 ].parentNode;\n
+\t\t}\n
+\n
+\t\tc = $( o.containment );\n
+\t\tce = c[ 0 ];\n
+\n
+\t\tif( !ce ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tover = c.css( "overflow" ) !== "hidden";\n
+\n
+\t\tthis.containment = [\n
+\t\t\t( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),\n
+\t\t\t( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) + ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ) ,\n
+\t\t\t( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) - ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) - this.helperProportions.width - this.margins.left - this.margins.right,\n
+\t\t\t( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) - ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) - ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) - this.helperProportions.height - this.margins.top  - this.margins.bottom\n
+\t\t];\n
+\t\tthis.relative_container = c;\n
+\t},\n
+\n
+\t_convertPositionTo: function(d, pos) {\n
+\n
+\t\tif(!pos) {\n
+\t\t\tpos = this.position;\n
+\t\t}\n
+\n
+\t\tvar mod = d === "absolute" ? 1 : -1,\n
+\t\t\tscroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent;\n
+\n
+\t\t//Cache the scroll\n
+\t\tif (!this.offset.scroll) {\n
+\t\t\tthis.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};\n
+\t\t}\n
+\n
+\t\treturn {\n
+\t\t\ttop: (\n
+\t\t\t\tpos.top\t+\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n
+\t\t\t\tthis.offset.relative.top * mod +\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n
+\t\t\t\tthis.offset.parent.top * mod -\t\t\t\t\t\t\t\t\t\t// The offsetParent\'s offset without borders (offset + border)\n
+\t\t\t\t( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top ) * mod )\n
+\t\t\t),\n
+\t\t\tleft: (\n
+\t\t\t\tpos.left +\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n
+\t\t\t\tthis.offset.relative.left * mod +\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n
+\t\t\t\tthis.offset.parent.left * mod\t-\t\t\t\t\t\t\t\t\t\t// The offsetParent\'s offset without borders (offset + border)\n
+\t\t\t\t( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left ) * mod )\n
+\t\t\t)\n
+\t\t};\n
+\n
+\t},\n
+\n
+\t_generatePosition: function(event) {\n
+\n
+\t\tvar containment, co, top, left,\n
+\t\t\to = this.options,\n
+\t\t\tscroll = this.cssPosition === "absolute" && !( this.scrollParent[ 0 ] !== document && $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ? this.offsetParent : this.scrollParent,\n
+\t\t\tpageX = event.pageX,\n
+\t\t\tpageY = event.pageY;\n
+\n
+\t\t//Cache the scroll\n
+\t\tif (!this.offset.scroll) {\n
+\t\t\tthis.offset.scroll = {top : scroll.scrollTop(), left : scroll.scrollLeft()};\n
+\t\t}\n
+\n
+\t\t/*\n
+\t\t * - Position constraining -\n
+\t\t * Constrain the position to a mix of grid, containment.\n
+\t\t */\n
+\n
+\t\t// If we are not dragging yet, we won\'t check for options\n
+\t\tif ( this.originalPosition ) {\n
+\t\t\tif ( this.containment ) {\n
+\t\t\t\tif ( this.relative_container ){\n
+\t\t\t\t\tco = this.relative_container.offset();\n
+\t\t\t\t\tcontainment = [\n
+\t\t\t\t\t\tthis.containment[ 0 ] + co.left,\n
+\t\t\t\t\t\tthis.containment[ 1 ] + co.top,\n
+\t\t\t\t\t\tthis.containment[ 2 ] + co.left,\n
+\t\t\t\t\t\tthis.containment[ 3 ] + co.top\n
+\t\t\t\t\t];\n
+\t\t\t\t}\n
+\t\t\t\telse {\n
+\t\t\t\t\tcontainment = this.containment;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif(event.pageX - this.offset.click.left < containment[0]) {\n
+\t\t\t\t\tpageX = containment[0] + this.offset.click.left;\n
+\t\t\t\t}\n
+\t\t\t\tif(event.pageY - this.offset.click.top < containment[1]) {\n
+\t\t\t\t\tpageY = containment[1] + this.offset.click.top;\n
+\t\t\t\t}\n
+\t\t\t\tif(event.pageX - this.offset.click.left > containment[2]) {\n
+\t\t\t\t\tpageX = containment[2] + this.offset.click.left;\n
+\t\t\t\t}\n
+\t\t\t\tif(event.pageY - this.offset.click.top > containment[3]) {\n
+\t\t\t\t\tpageY = containment[3] + this.offset.click.top;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif(o.grid) {\n
+\t\t\t\t//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)\n
+\t\t\t\ttop = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;\n
+\t\t\t\tpageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;\n
+\n
+\t\t\t\tleft = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;\n
+\t\t\t\tpageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;\n
+\t\t\t}\n
+\n
+\t\t}\n
+\n
+\t\treturn {\n
+\t\t\ttop: (\n
+\t\t\t\tpageY -\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n
+\t\t\t\tthis.offset.click.top\t-\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n
+\t\t\t\tthis.offset.relative.top -\t\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n
+\t\t\t\tthis.offset.parent.top +\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent\'s offset without borders (offset + border)\n
+\t\t\t\t( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : this.offset.scroll.top )\n
+\t\t\t),\n
+\t\t\tleft: (\n
+\t\t\t\tpageX -\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n
+\t\t\t\tthis.offset.click.left -\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n
+\t\t\t\tthis.offset.relative.left -\t\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n
+\t\t\t\tthis.offset.parent.left +\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent\'s offset without borders (offset + border)\n
+\t\t\t\t( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : this.offset.scroll.left )\n
+\t\t\t)\n
+\t\t};\n
+\n
+\t},\n
+\n
+\t_clear: function() {\n
+\t\tthis.helper.removeClass("ui-draggable-dragging");\n
+\t\tif(this.helper[0] !== this.element[0] && !this.cancelHelperRemoval) {\n
+\t\t\tthis.helper.remove();\n
+\t\t}\n
+\t\tthis.helper = null;\n
+\t\tthis.cancelHelperRemoval = false;\n
+\t},\n
+\n
+\t// From now on bulk stuff - mainly helpers\n
+\n
+\t_trigger: function(type, event, ui) {\n
+\t\tui = ui || this._uiHash();\n
+\t\t$.ui.plugin.call(this, type, [event, ui]);\n
+\t\t//The absolute position has to be recalculated after plugins\n
+\t\tif(type === "drag") {\n
+\t\t\tthis.positionAbs = this._convertPositionTo("absolute");\n
+\t\t}\n
+\t\treturn $.Widget.prototype._trigger.call(this, type, event, ui);\n
+\t},\n
+\n
+\tplugins: {},\n
+\n
+\t_uiHash: function() {\n
+\t\treturn {\n
+\t\t\thelper: this.helper,\n
+\t\t\tposition: this.position,\n
+\t\t\toriginalPosition: this.originalPosition,\n
+\t\t\toffset: this.positionAbs\n
+\t\t};\n
+\t}\n
+\n
+});\n
+\n
+$.ui.plugin.add("draggable", "connectToSortable", {\n
+\tstart: function(event, ui) {\n
+\n
+\t\tvar inst = $(this).data("ui-draggable"), o = inst.options,\n
+\t\t\tuiSortable = $.extend({}, ui, { item: inst.element });\n
+\t\tinst.sortables = [];\n
+\t\t$(o.connectToSortable).each(function() {\n
+\t\t\tvar sortable = $.data(this, "ui-sortable");\n
+\t\t\tif (sortable && !sortable.options.disabled) {\n
+\t\t\t\tinst.sortables.push({\n
+\t\t\t\t\tinstance: sortable,\n
+\t\t\t\t\tshouldRevert: sortable.options.revert\n
+\t\t\t\t});\n
+\t\t\t\tsortable.refreshPositions();\t// Call the sortable\'s refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it\'s initialised as well as being kept in step with any changes that might have happened on the page).\n
+\t\t\t\tsortable._trigger("activate", event, uiSortable);\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t},\n
+\tstop: function(event, ui) {\n
+\n
+\t\t//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper\n
+\t\tvar inst = $(this).data("ui-draggable"),\n
+\t\t\tuiSortable = $.extend({}, ui, { item: inst.element });\n
+\n
+\t\t$.each(inst.sortables, function() {\n
+\t\t\tif(this.instance.isOver) {\n
+\n
+\t\t\t\tthis.instance.isOver = 0;\n
+\n
+\t\t\t\tinst.cancelHelperRemoval = true; //Don\'t remove the helper in the draggable instance\n
+\t\t\t\tthis.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)\n
+\n
+\t\t\t\t//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"\n
+\t\t\t\tif(this.shouldRevert) {\n
+\t\t\t\t\tthis.instance.options.revert = this.shouldRevert;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t//Trigger the stop of the sortable\n
+\t\t\t\tthis.instance._mouseStop(event);\n
+\n
+\t\t\t\tthis.instance.options.helper = this.instance.options._helper;\n
+\n
+\t\t\t\t//If the helper has been the original item, restore properties in the sortable\n
+\t\t\t\tif(inst.options.helper === "original") {\n
+\t\t\t\t\tthis.instance.currentItem.css({ top: "auto", left: "auto" });\n
+\t\t\t\t}\n
+\n
+\t\t\t} else {\n
+\t\t\t\tthis.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance\n
+\t\t\t\tthis.instance._trigger("deactivate", event, uiSortable);\n
+\t\t\t}\n
+\n
+\t\t});\n
+\n
+\t},\n
+\tdrag: function(event, ui) {\n
+\n
+\t\tvar inst = $(this).data("ui-draggable"), that = this;\n
+\n
+\t\t$.each(inst.sortables, function() {\n
+\n
+\t\t\tvar innermostIntersecting = false,\n
+\t\t\t\tthisSortable = this;\n
+\n
+\t\t\t//Copy over some variables to allow calling the sortable\'s native _intersectsWith\n
+\t\t\tthis.instance.positionAbs = inst.positionAbs;\n
+\t\t\tthis.instance.helperProportions = inst.helperProportions;\n
+\t\t\tthis.instance.offset.click = inst.offset.click;\n
+\n
+\t\t\tif(this.instance._intersectsWith(this.instance.containerCache)) {\n
+\t\t\t\tinnermostIntersecting = true;\n
+\t\t\t\t$.each(inst.sortables, function () {\n
+\t\t\t\t\tthis.instance.positionAbs = inst.positionAbs;\n
+\t\t\t\t\tthis.instance.helperProportions = inst.helperProportions;\n
+\t\t\t\t\tthis.instance.offset.click = inst.offset.click;\n
+\t\t\t\t\tif (this !== thisSortable &&\n
+\t\t\t\t\t\tthis.instance._intersectsWith(this.instance.containerCache) &&\n
+\t\t\t\t\t\t$.contains(thisSortable.instance.element[0], this.instance.element[0])\n
+\t\t\t\t\t) {\n
+\t\t\t\t\t\tinnermostIntersecting = false;\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn innermostIntersecting;\n
+\t\t\t\t});\n
+\t\t\t}\n
+\n
+\n
+\t\t\tif(innermostIntersecting) {\n
+\t\t\t\t//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once\n
+\t\t\t\tif(!this.instance.isOver) {\n
+\n
+\t\t\t\t\tthis.instance.isOver = 1;\n
+\t\t\t\t\t//Now we fake the start of dragging for the sortable instance,\n
+\t\t\t\t\t//by cloning the list group item, appending it to the sortable and using it as inst.currentItem\n
+\t\t\t\t\t//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn\'t create a new one)\n
+\t\t\t\t\tthis.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);\n
+\t\t\t\t\tthis.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it\n
+\t\t\t\t\tthis.instance.options.helper = function() { return ui.helper[0]; };\n
+\n
+\t\t\t\t\tevent.target = this.instance.currentItem[0];\n
+\t\t\t\t\tthis.instance._mouseCapture(event, true);\n
+\t\t\t\t\tthis.instance._mouseStart(event, true, true);\n
+\n
+\t\t\t\t\t//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes\n
+\t\t\t\t\tthis.instance.offset.click.top = inst.offset.click.top;\n
+\t\t\t\t\tthis.instance.offset.click.left = inst.offset.click.left;\n
+\t\t\t\t\tthis.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;\n
+\t\t\t\t\tthis.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;\n
+\n
+\t\t\t\t\tinst._trigger("toSortable", event);\n
+\t\t\t\t\tinst.dropped = this.instance.element; //draggable revert needs that\n
+\t\t\t\t\t//hack so receive/update callbacks work (mostly)\n
+\t\t\t\t\tinst.currentItem = inst.element;\n
+\t\t\t\t\tthis.instance.fromOutside = inst;\n
+\n
+\t\t\t\t}\n
+\n
+\t\t\t\t//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable\n
+\t\t\t\tif(this.instance.currentItem) {\n
+\t\t\t\t\tthis.instance._mouseDrag(event);\n
+\t\t\t\t}\n
+\n
+\t\t\t} else {\n
+\n
+\t\t\t\t//If it doesn\'t intersect with the sortable, and it intersected before,\n
+\t\t\t\t//we fake the drag stop of the sortable, but make sure it doesn\'t remove the helper by using cancelHelperRemoval\n
+\t\t\t\tif(this.instance.isOver) {\n
+\n
+\t\t\t\t\tthis.instance.isOver = 0;\n
+\t\t\t\t\tthis.instance.cancelHelperRemoval = true;\n
+\n
+\t\t\t\t\t//Prevent reverting on this forced stop\n
+\t\t\t\t\tthis.instance.options.revert = false;\n
+\n
+\t\t\t\t\t// The out event needs to be triggered independently\n
+\t\t\t\t\tthis.instance._trigger("out", event, this.instance._uiHash(this.instance));\n
+\n
+\t\t\t\t\tthis.instance._mouseStop(event, true);\n
+\t\t\t\t\tthis.instance.options.helper = this.instance.options._helper;\n
+\n
+\t\t\t\t\t//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it\'s original size\n
+\t\t\t\t\tthis.instance.currentItem.remove();\n
+\t\t\t\t\tif(this.instance.placeholder) {\n
+\t\t\t\t\t\tthis.instance.placeholder.remove();\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tinst._trigger("fromSortable", event);\n
+\t\t\t\t\tinst.dropped = false; //draggable revert needs that\n
+\t\t\t\t}\n
+\n
+\t\t\t}\n
+\n
+\t\t});\n
+\n
+\t}\n
+});\n
+\n
+$.ui.plugin.add("draggable", "cursor", {\n
+\tstart: function() {\n
+\t\tvar t = $("body"), o = $(this).data("ui-draggable").options;\n
+\t\tif (t.css("cursor")) {\n
+\t\t\to._cursor = t.css("cursor");\n
+\t\t}\n
+\t\tt.css("cursor", o.cursor);\n
+\t},\n
+\tstop: function() {\n
+\t\tvar o = $(this).data("ui-draggable").options;\n
+\t\tif (o._cursor) {\n
+\t\t\t$("body").css("cursor", o._cursor);\n
+\t\t}\n
+\t}\n
+});\n
+\n
+$.ui.plugin.add("draggable", "opacity", {\n
+\tstart: function(event, ui) {\n
+\t\tvar t = $(ui.helper), o = $(this).data("ui-draggable").options;\n
+\t\tif(t.css("opacity")) {\n
+\t\t\to._opacity = t.css("opacity");\n
+\t\t}\n
+\t\tt.css("opacity", o.opacity);\n
+\t},\n
+\tstop: function(event, ui) {\n
+\t\tvar o = $(this).data("ui-draggable").options;\n
+\t\tif(o._opacity) {\n
+\t\t\t$(ui.helper).css("opacity", o._opacity);\n
+\t\t}\n
+\t}\n
+});\n
+\n
+$.ui.plugin.add("draggable", "scroll", {\n
+\tstart: function() {\n
+\t\tvar i = $(this).data("ui-draggable");\n
+\t\tif(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {\n
+\t\t\ti.overflowOffset = i.scrollParent.offset();\n
+\t\t}\n
+\t},\n
+\tdrag: function( event ) {\n
+\n
+\t\tvar i = $(this).data("ui-draggable"), o = i.options, scrolled = false;\n
+\n
+\t\tif(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {\n
+\n
+\t\t\tif(!o.axis || o.axis !== "x") {\n
+\t\t\t\tif((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {\n
+\t\t\t\t\ti.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;\n
+\t\t\t\t} else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {\n
+\t\t\t\t\ti.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif(!o.axis || o.axis !== "y") {\n
+\t\t\t\tif((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {\n
+\t\t\t\t\ti.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;\n
+\t\t\t\t} else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {\n
+\t\t\t\t\ti.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t} else {\n
+\n
+\t\t\tif(!o.axis || o.axis !== "x") {\n
+\t\t\t\tif(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {\n
+\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);\n
+\t\t\t\t} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {\n
+\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif(!o.axis || o.axis !== "y") {\n
+\t\t\t\tif(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {\n
+\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);\n
+\t\t\t\t} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {\n
+\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t}\n
+\n
+\t\tif(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {\n
+\t\t\t$.ui.ddmanager.prepareOffsets(i, event);\n
+\t\t}\n
+\n
+\t}\n
+});\n
+\n
+$.ui.plugin.add("draggable", "snap", {\n
+\tstart: function() {\n
+\n
+\t\tvar i = $(this).data("ui-draggable"),\n
+\t\t\to = i.options;\n
+\n
+\t\ti.snapElements = [];\n
+\n
+\t\t$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {\n
+\t\t\tvar $t = $(this),\n
+\t\t\t\t$o = $t.offset();\n
+\t\t\tif(this !== i.element[0]) {\n
+\t\t\t\ti.snapElements.push({\n
+\t\t\t\t\titem: this,\n
+\t\t\t\t\twidth: $t.outerWidth(), height: $t.outerHeight(),\n
+\t\t\t\t\ttop: $o.top, left: $o.left\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t},\n
+\tdrag: function(event, ui) {\n
+\n
+\t\tvar ts, bs, ls, rs, l, r, t, b, i, first,\n
+\t\t\tinst = $(this).data("ui-draggable"),\n
+\t\t\to = inst.options,\n
+\t\t\td = o.snapTolerance,\n
+\t\t\tx1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,\n
+\t\t\ty1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;\n
+\n
+\t\tfor (i = inst.snapElements.length - 1; i >= 0; i--){\n
+\n
+\t\t\tl = inst.snapElements[i].left;\n
+\t\t\tr = l + inst.snapElements[i].width;\n
+\t\t\tt = inst.snapElements[i].top;\n
+\t\t\tb = t + inst.snapElements[i].height;\n
+\n
+\t\t\tif ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d || !$.contains( inst.snapElements[ i ].item.ownerDocument, inst.snapElements[ i ].item ) ) {\n
+\t\t\t\tif(inst.snapElements[i].snapping) {\n
+\t\t\t\t\t(inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));\n
+\t\t\t\t}\n
+\t\t\t\tinst.snapElements[i].snapping = false;\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\tif(o.snapMode !== "inner") {\n
+\t\t\t\tts = Math.abs(t - y2) <= d;\n
+\t\t\t\tbs = Math.abs(b - y1) <= d;\n
+\t\t\t\tls = Math.abs(l - x2) <= d;\n
+\t\t\t\trs = Math.abs(r - x1) <= d;\n
+\t\t\t\tif(ts) {\n
+\t\t\t\t\tui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;\n
+\t\t\t\t}\n
+\t\t\t\tif(bs) {\n
+\t\t\t\t\tui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;\n
+\t\t\t\t}\n
+\t\t\t\tif(ls) {\n
+\t\t\t\t\tui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;\n
+\t\t\t\t}\n
+\t\t\t\tif(rs) {\n
+\t\t\t\t\tui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tfirst = (ts || bs || ls || rs);\n
+\n
+\t\t\tif(o.snapMode !== "outer") {\n
+\t\t\t\tts = Math.abs(t - y1) <= d;\n
+\t\t\t\tbs = Math.abs(b - y2) <= d;\n
+\t\t\t\tls = Math.abs(l - x1) <= d;\n
+\t\t\t\trs = Math.abs(r - x2) <= d;\n
+\t\t\t\tif(ts) {\n
+\t\t\t\t\tui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;\n
+\t\t\t\t}\n
+\t\t\t\tif(bs) {\n
+\t\t\t\t\tui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;\n
+\t\t\t\t}\n
+\t\t\t\tif(ls) {\n
+\t\t\t\t\tui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;\n
+\t\t\t\t}\n
+\t\t\t\tif(rs) {\n
+\t\t\t\t\tui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {\n
+\t\t\t\t(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));\n
+\t\t\t}\n
+\t\t\tinst.snapElements[i].snapping = (ts || bs || ls || rs || first);\n
+\n
+\t\t}\n
+\n
+\t}\n
+});\n
+\n
+$.ui.plugin.add("draggable", "stack", {\n
+\tstart: function() {\n
+\t\tvar min,\n
+\t\t\to = this.data("ui-draggable").options,\n
+\t\t\tgroup = $.makeArray($(o.stack)).sort(function(a,b) {\n
+\t\t\t\treturn (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);\n
+\t\t\t});\n
+\n
+\t\tif (!group.length) { return; }\n
+\n
+\t\tmin = parseInt($(group[0]).css("zIndex"), 10) || 0;\n
+\t\t$(group).each(function(i) {\n
+\t\t\t$(this).css("zIndex", min + i);\n
+\t\t});\n
+\t\tthis.css("zIndex", (min + group.length));\n
+\t}\n
+});\n
+\n
+$.ui.plugin.add("draggable", "zIndex", {\n
+\tstart: function(event, ui) {\n
+\t\tvar t = $(ui.helper), o = $(this).data("ui-draggable").options;\n
+\t\tif(t.css("zIndex")) {\n
+\t\t\to._zIndex = t.css("zIndex");\n
+\t\t}\n
+\t\tt.css("zIndex", o.zIndex);\n
+\t},\n
+\tstop: function(event, ui) {\n
+\t\tvar o = $(this).data("ui-draggable").options;\n
+\t\tif(o._zIndex) {\n
+\t\t\t$(ui.helper).css("zIndex", o._zIndex);\n
+\t\t}\n
+\t}\n
+});\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+function isOverAxis( x, reference, size ) {\n
+\treturn ( x > reference ) && ( x < ( reference + size ) );\n
+}\n
+\n
+$.widget("ui.droppable", {\n
+\tversion: "1.10.4",\n
+\twidgetEventPrefix: "drop",\n
+\toptions: {\n
+\t\taccept: "*",\n
+\t\tactiveClass: false,\n
+\t\taddClasses: true,\n
+\t\tgreedy: false,\n
+\t\thoverClass: false,\n
+\t\tscope: "default",\n
+\t\ttolerance: "intersect",\n
+\n
+\t\t// callbacks\n
+\t\tactivate: null,\n
+\t\tdeactivate: null,\n
+\t\tdrop: null,\n
+\t\tout: null,\n
+\t\tover: null\n
+\t},\n
+\t_create: function() {\n
+\n
+\t\tvar proportions,\n
+\t\t\to = this.options,\n
+\t\t\taccept = o.accept;\n
+\n
+\t\tthis.isover = false;\n
+\t\tthis.isout = true;\n
+\n
+\t\tthis.accept = $.isFunction(accept) ? accept : function(d) {\n
+\t\t\treturn d.is(accept);\n
+\t\t};\n
+\n
+\t\tthis.proportions = function( /* valueToWrite */ ) {\n
+\t\t\tif ( arguments.length ) {\n
+\t\t\t\t// Store the droppable\'s proportions\n
+\t\t\t\tproportions = arguments[ 0 ];\n
+\t\t\t} else {\n
+\t\t\t\t// Retrieve or derive the droppable\'s proportions\n
+\t\t\t\treturn proportions ?\n
+\t\t\t\t\tproportions :\n
+\t\t\t\t\tproportions = {\n
+\t\t\t\t\t\twidth: this.element[ 0 ].offsetWidth,\n
+\t\t\t\t\t\theight: this.element[ 0 ].offsetHeight\n
+\t\t\t\t\t};\n
+\t\t\t}\n
+\t\t};\n
+\n
+\t\t// Add the reference and positions to the manager\n
+\t\t$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];\n
+\t\t$.ui.ddmanager.droppables[o.scope].push(this);\n
+\n
+\t\t(o.addClasses && this.element.addClass("ui-droppable"));\n
+\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tvar i = 0,\n
+\t\t\tdrop = $.ui.ddmanager.droppables[this.options.scope];\n
+\n
+\t\tfor ( ; i < drop.length; i++ ) {\n
+\t\t\tif ( drop[i] === this ) {\n
+\t\t\t\tdrop.splice(i, 1);\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis.element.removeClass("ui-droppable ui-droppable-disabled");\n
+\t},\n
+\n
+\t_setOption: function(key, value) {\n
+\n
+\t\tif(key === "accept") {\n
+\t\t\tthis.accept = $.isFunction(value) ? value : function(d) {\n
+\t\t\t\treturn d.is(value);\n
+\t\t\t};\n
+\t\t}\n
+\t\t$.Widget.prototype._setOption.apply(this, arguments);\n
+\t},\n
+\n
+\t_activate: function(event) {\n
+\t\tvar draggable = $.ui.ddmanager.current;\n
+\t\tif(this.options.activeClass) {\n
+\t\t\tthis.element.addClass(this.options.activeClass);\n
+\t\t}\n
+\t\tif(draggable){\n
+\t\t\tthis._trigger("activate", event, this.ui(draggable));\n
+\t\t}\n
+\t},\n
+\n
+\t_deactivate: function(event) {\n
+\t\tvar draggable = $.ui.ddmanager.current;\n
+\t\tif(this.options.activeClass) {\n
+\t\t\tthis.element.removeClass(this.options.activeClass);\n
+\t\t}\n
+\t\tif(draggable){\n
+\t\t\tthis._trigger("deactivate", event, this.ui(draggable));\n
+\t\t}\n
+\t},\n
+\n
+\t_over: function(event) {\n
+\n
+\t\tvar draggable = $.ui.ddmanager.current;\n
+\n
+\t\t// Bail if draggable and droppable are same element\n
+\t\tif (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\n
+\t\t\tif(this.options.hoverClass) {\n
+\t\t\t\tthis.element.addClass(this.options.hoverClass);\n
+\t\t\t}\n
+\t\t\tthis._trigger("over", event, this.ui(draggable));\n
+\t\t}\n
+\n
+\t},\n
+\n
+\t_out: function(event) {\n
+\n
+\t\tvar draggable = $.ui.ddmanager.current;\n
+\n
+\t\t// Bail if draggable and droppable are same element\n
+\t\tif (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\n
+\t\t\tif(this.options.hoverClass) {\n
+\t\t\t\tthis.element.removeClass(this.options.hoverClass);\n
+\t\t\t}\n
+\t\t\tthis._trigger("out", event, this.ui(draggable));\n
+\t\t}\n
+\n
+\t},\n
+\n
+\t_drop: function(event,custom) {\n
+\n
+\t\tvar draggable = custom || $.ui.ddmanager.current,\n
+\t\t\tchildrenIntersection = false;\n
+\n
+\t\t// Bail if draggable and droppable are same element\n
+\t\tif (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\tthis.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() {\n
+\t\t\tvar inst = $.data(this, "ui-droppable");\n
+\t\t\tif(\n
+\t\t\t\tinst.options.greedy &&\n
+\t\t\t\t!inst.options.disabled &&\n
+\t\t\t\tinst.options.scope === draggable.options.scope &&\n
+\t\t\t\tinst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) &&\n
+\t\t\t\t$.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)\n
+\t\t\t) { childrenIntersection = true; return false; }\n
+\t\t});\n
+\t\tif(childrenIntersection) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\tif(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\n
+\t\t\tif(this.options.activeClass) {\n
+\t\t\t\tthis.element.removeClass(this.options.activeClass);\n
+\t\t\t}\n
+\t\t\tif(this.options.hoverClass) {\n
+\t\t\t\tthis.element.removeClass(this.options.hoverClass);\n
+\t\t\t}\n
+\t\t\tthis._trigger("drop", event, this.ui(draggable));\n
+\t\t\treturn this.element;\n
+\t\t}\n
+\n
+\t\treturn false;\n
+\n
+\t},\n
+\n
+\tui: function(c) {\n
+\t\treturn {\n
+\t\t\tdraggable: (c.currentItem || c.element),\n
+\t\t\thelper: c.helper,\n
+\t\t\tposition: c.position,\n
+\t\t\toffset: c.positionAbs\n
+\t\t};\n
+\t}\n
+\n
+});\n
+\n
+$.ui.intersect = function(draggable, droppable, toleranceMode) {\n
+\n
+\tif (!droppable.offset) {\n
+\t\treturn false;\n
+\t}\n
+\n
+\tvar draggableLeft, draggableTop,\n
+\t\tx1 = (draggable.positionAbs || draggable.position.absolute).left,\n
+\t\ty1 = (draggable.positionAbs || draggable.position.absolute).top,\n
+\t\tx2 = x1 + draggable.helperProportions.width,\n
+\t\ty2 = y1 + draggable.helperProportions.height,\n
+\t\tl = droppable.offset.left,\n
+\t\tt = droppable.offset.top,\n
+\t\tr = l + droppable.proportions().width,\n
+\t\tb = t + droppable.proportions().height;\n
+\n
+\tswitch (toleranceMode) {\n
+\t\tcase "fit":\n
+\t\t\treturn (l <= x1 && x2 <= r && t <= y1 && y2 <= b);\n
+\t\tcase "intersect":\n
+\t\t\treturn (l < x1 + (draggable.helperProportions.width / 2) && // Right Half\n
+\t\t\t\tx2 - (draggable.helperProportions.width / 2) < r && // Left Half\n
+\t\t\t\tt < y1 + (draggable.helperProportions.height / 2) && // Bottom Half\n
+\t\t\t\ty2 - (draggable.helperProportions.height / 2) < b ); // Top Half\n
+\t\tcase "pointer":\n
+\t\t\tdraggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left);\n
+\t\t\tdraggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top);\n
+\t\t\treturn isOverAxis( draggableTop, t, droppable.proportions().height ) && isOverAxis( draggableLeft, l, droppable.proportions().width );\n
+\t\tcase "touch":\n
+\t\t\treturn (\n
+\t\t\t\t(y1 >= t && y1 <= b) ||\t// Top edge touching\n
+\t\t\t\t(y2 >= t && y2 <= b) ||\t// Bottom edge touching\n
+\t\t\t\t(y1 < t && y2 > b)\t\t// Surrounded vertically\n
+\t\t\t) && (\n
+\t\t\t\t(x1 >= l && x1 <= r) ||\t// Left edge touching\n
+\t\t\t\t(x2 >= l && x2 <= r) ||\t// Right edge touching\n
+\t\t\t\t(x1 < l && x2 > r)\t\t// Surrounded horizontally\n
+\t\t\t);\n
+\t\tdefault:\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+};\n
+\n
+/*\n
+\tThis manager tracks offsets of draggables and droppables\n
+*/\n
+$.ui.ddmanager = {\n
+\tcurrent: null,\n
+\tdroppables: { "default": [] },\n
+\tprepareOffsets: function(t, event) {\n
+\n
+\t\tvar i, j,\n
+\t\t\tm = $.ui.ddmanager.droppables[t.options.scope] || [],\n
+\t\t\ttype = event ? event.type : null, // workaround for #2317\n
+\t\t\tlist = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();\n
+\n
+\t\tdroppablesLoop: for (i = 0; i < m.length; i++) {\n
+\n
+\t\t\t//No disabled and non-accepted\n
+\t\t\tif(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) {\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\t// Filter out elements in the current dragged item\n
+\t\t\tfor (j=0; j < list.length; j++) {\n
+\t\t\t\tif(list[j] === m[i].element[0]) {\n
+\t\t\t\t\tm[i].proportions().height = 0;\n
+\t\t\t\t\tcontinue droppablesLoop;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tm[i].visible = m[i].element.css("display") !== "none";\n
+\t\t\tif(!m[i].visible) {\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\t//Activate the droppable if used directly from draggables\n
+\t\t\tif(type === "mousedown") {\n
+\t\t\t\tm[i]._activate.call(m[i], event);\n
+\t\t\t}\n
+\n
+\t\t\tm[ i ].offset = m[ i ].element.offset();\n
+\t\t\tm[ i ].proportions({ width: m[ i ].element[ 0 ].offsetWidth, height: m[ i ].element[ 0 ].offsetHeight });\n
+\n
+\t\t}\n
+\n
+\t},\n
+\tdrop: function(draggable, event) {\n
+\n
+\t\tvar dropped = false;\n
+\t\t// Create a copy of the droppables in case the list changes during the drop (#9116)\n
+\t\t$.each(($.ui.ddmanager.droppables[draggable.options.scope] || []).slice(), function() {\n
+\n
+\t\t\tif(!this.options) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\tif (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) {\n
+\t\t\t\tdropped = this._drop.call(this, event) || dropped;\n
+\t\t\t}\n
+\n
+\t\t\tif (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {\n
+\t\t\t\tthis.isout = true;\n
+\t\t\t\tthis.isover = false;\n
+\t\t\t\tthis._deactivate.call(this, event);\n
+\t\t\t}\n
+\n
+\t\t});\n
+\t\treturn dropped;\n
+\n
+\t},\n
+\tdragStart: function( draggable, event ) {\n
+\t\t//Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)\n
+\t\tdraggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {\n
+\t\t\tif( !draggable.options.refreshPositions ) {\n
+\t\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\tdrag: function(draggable, event) {\n
+\n
+\t\t//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.\n
+\t\tif(draggable.options.refreshPositions) {\n
+\t\t\t$.ui.ddmanager.prepareOffsets(draggable, event);\n
+\t\t}\n
+\n
+\t\t//Run through all droppables and check their positions based on specific tolerance options\n
+\t\t$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {\n
+\n
+\t\t\tif(this.options.disabled || this.greedyChild || !this.visible) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tvar parentInstance, scope, parent,\n
+\t\t\t\tintersects = $.ui.intersect(draggable, this, this.options.tolerance),\n
+\t\t\t\tc = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null);\n
+\t\t\tif(!c) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tif (this.options.greedy) {\n
+\t\t\t\t// find droppable parents with same scope\n
+\t\t\t\tscope = this.options.scope;\n
+\t\t\t\tparent = this.element.parents(":data(ui-droppable)").filter(function () {\n
+\t\t\t\t\treturn $.data(this, "ui-droppable").options.scope === scope;\n
+\t\t\t\t});\n
+\n
+\t\t\t\tif (parent.length) {\n
+\t\t\t\t\tparentInstance = $.data(parent[0], "ui-droppable");\n
+\t\t\t\t\tparentInstance.greedyChild = (c === "isover");\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// we just moved into a greedy child\n
+\t\t\tif (parentInstance && c === "isover") {\n
+\t\t\t\tparentInstance.isover = false;\n
+\t\t\t\tparentInstance.isout = true;\n
+\t\t\t\tparentInstance._out.call(parentInstance, event);\n
+\t\t\t}\n
+\n
+\t\t\tthis[c] = true;\n
+\t\t\tthis[c === "isout" ? "isover" : "isout"] = false;\n
+\t\t\tthis[c === "isover" ? "_over" : "_out"].call(this, event);\n
+\n
+\t\t\t// we just moved out of a greedy child\n
+\t\t\tif (parentInstance && c === "isout") {\n
+\t\t\t\tparentInstance.isout = false;\n
+\t\t\t\tparentInstance.isover = true;\n
+\t\t\t\tparentInstance._over.call(parentInstance, event);\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t},\n
+\tdragStop: function( draggable, event ) {\n
+\t\tdraggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );\n
+\t\t//Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)\n
+\t\tif( !draggable.options.refreshPositions ) {\n
+\t\t\t$.ui.ddmanager.prepareOffsets( draggable, event );\n
+\t\t}\n
+\t}\n
+};\n
+\n
+})(jQuery);\n
+(function($, undefined) {\n
+\n
+var dataSpace = "ui-effects-";\n
+\n
+$.effects = {\n
+\teffect: {}\n
+};\n
+\n
+/*!\n
+ * jQuery Color Animations v2.1.2\n
+ * https://github.com/jquery/jquery-color\n
+ *\n
+ * Copyright 2013 jQuery Foundation and other contributors\n
+ * Released under the MIT license.\n
+ * http://jquery.org/license\n
+ *\n
+ * Date: Wed Jan 16 08:47:09 2013 -0600\n
+ */\n
+(function( jQuery, undefined ) {\n
+\n
+\tvar stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",\n
+\n
+\t// plusequals test for += 100 -= 100\n
+\trplusequals = /^([\\-+])=\\s*(\\d+\\.?\\d*)/,\n
+\t// a set of RE\'s that can match strings and generate color tuples.\n
+\tstringParsers = [{\n
+\t\t\tre: /rgba?\\(\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*,\\s*(\\d{1,3})\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n
+\t\t\tparse: function( execResult ) {\n
+\t\t\t\treturn [\n
+\t\t\t\t\texecResult[ 1 ],\n
+\t\t\t\t\texecResult[ 2 ],\n
+\t\t\t\t\texecResult[ 3 ],\n
+\t\t\t\t\texecResult[ 4 ]\n
+\t\t\t\t];\n
+\t\t\t}\n
+\t\t}, {\n
+\t\t\tre: /rgba?\\(\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n
+\t\t\tparse: function( execResult ) {\n
+\t\t\t\treturn [\n
+\t\t\t\t\texecResult[ 1 ] * 2.55,\n
+\t\t\t\t\texecResult[ 2 ] * 2.55,\n
+\t\t\t\t\texecResult[ 3 ] * 2.55,\n
+\t\t\t\t\texecResult[ 4 ]\n
+\t\t\t\t];\n
+\t\t\t}\n
+\t\t}, {\n
+\t\t\t// this regex ignores A-F because it\'s compared against an already lowercased string\n
+\t\t\tre: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,\n
+\t\t\tparse: function( execResult ) {\n
+\t\t\t\treturn [\n
+\t\t\t\t\tparseInt( execResult[ 1 ], 16 ),\n
+\t\t\t\t\tparseInt( execResult[ 2 ], 16 ),\n
+\t\t\t\t\tparseInt( execResult[ 3 ], 16 )\n
+\t\t\t\t];\n
+\t\t\t}\n
+\t\t}, {\n
+\t\t\t// this regex ignores A-F because it\'s compared against an already lowercased string\n
+\t\t\tre: /#([a-f0-9])([a-f0-9])([a-f0-9])/,\n
+\t\t\tparse: function( execResult ) {\n
+\t\t\t\treturn [\n
+\t\t\t\t\tparseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),\n
+\t\t\t\t\tparseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),\n
+\t\t\t\t\tparseInt( execResult[ 3 ] + execResult[ 3 ], 16 )\n
+\t\t\t\t];\n
+\t\t\t}\n
+\t\t}, {\n
+\t\t\tre: /hsla?\\(\\s*(\\d+(?:\\.\\d+)?)\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*,\\s*(\\d+(?:\\.\\d+)?)\\%\\s*(?:,\\s*(\\d?(?:\\.\\d+)?)\\s*)?\\)/,\n
+\t\t\tspace: "hsla",\n
+\t\t\tparse: function( execResult ) {\n
+\t\t\t\treturn [\n
+\t\t\t\t\texecResult[ 1 ],\n
+\t\t\t\t\texecResult[ 2 ] / 100,\n
+\t\t\t\t\texecResult[ 3 ] / 100,\n
+\t\t\t\t\texecResult[ 4 ]\n
+\t\t\t\t];\n
+\t\t\t}\n
+\t\t}],\n
+\n
+\t// jQuery.Color( )\n
+\tcolor = jQuery.Color = function( color, green, blue, alpha ) {\n
+\t\treturn new jQuery.Color.fn.parse( color, green, blue, alpha );\n
+\t},\n
+\tspaces = {\n
+\t\trgba: {\n
+\t\t\tprops: {\n
+\t\t\t\tred: {\n
+\t\t\t\t\tidx: 0,\n
+\t\t\t\t\ttype: "byte"\n
+\t\t\t\t},\n
+\t\t\t\tgreen: {\n
+\t\t\t\t\tidx: 1,\n
+\t\t\t\t\ttype: "byte"\n
+\t\t\t\t},\n
+\t\t\t\tblue: {\n
+\t\t\t\t\tidx: 2,\n
+\t\t\t\t\ttype: "byte"\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\thsla: {\n
+\t\t\tprops: {\n
+\t\t\t\thue: {\n
+\t\t\t\t\tidx: 0,\n
+\t\t\t\t\ttype: "degrees"\n
+\t\t\t\t},\n
+\t\t\t\tsaturation: {\n
+\t\t\t\t\tidx: 1,\n
+\t\t\t\t\ttype: "percent"\n
+\t\t\t\t},\n
+\t\t\t\tlightness: {\n
+\t\t\t\t\tidx: 2,\n
+\t\t\t\t\ttype: "percent"\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\tpropTypes = {\n
+\t\t"byte": {\n
+\t\t\tfloor: true,\n
+\t\t\tmax: 255\n
+\t\t},\n
+\t\t"percent": {\n
+\t\t\tmax: 1\n
+\t\t},\n
+\t\t"degrees": {\n
+\t\t\tmod: 360,\n
+\t\t\tfloor: true\n
+\t\t}\n
+\t},\n
+\tsupport = color.support = {},\n
+\n
+\t// element for support tests\n
+\tsupportElem = jQuery( "<p>" )[ 0 ],\n
+\n
+\t// colors = jQuery.Color.names\n
+\tcolors,\n
+\n
+\t// local aliases of functions called often\n
+\teach = jQuery.each;\n
+\n
+// determine rgba support immediately\n
+supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";\n
+support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;\n
+\n
+// define cache name and alpha properties\n
+// for rgba and hsla spaces\n
+each( spaces, function( spaceName, space ) {\n
+\tspace.cache = "_" + spaceName;\n
+\tspace.props.alpha = {\n
+\t\tidx: 3,\n
+\t\ttype: "percent",\n
+\t\tdef: 1\n
+\t};\n
+});\n
+\n
+function clamp( value, prop, allowEmpty ) {\n
+\tvar type = propTypes[ prop.type ] || {};\n
+\n
+\tif ( value == null ) {\n
+\t\treturn (allowEmpty || !prop.def) ? null : prop.def;\n
+\t}\n
+\n
+\t// ~~ is an short way of doing floor for positive numbers\n
+\tvalue = type.floor ? ~~value : parseFloat( value );\n
+\n
+\t// IE will pass in empty strings as value for alpha,\n
+\t// which will hit this case\n
+\tif ( isNaN( value ) ) {\n
+\t\treturn prop.def;\n
+\t}\n
+\n
+\tif ( type.mod ) {\n
+\t\t// we add mod before modding to make sure that negatives values\n
+\t\t// get converted properly: -10 -> 350\n
+\t\treturn (value + type.mod) % type.mod;\n
+\t}\n
+\n
+\t// for now all property types without mod have min and max\n
+\treturn 0 > value ? 0 : type.max < value ? type.max : value;\n
+}\n
+\n
+function stringParse( string ) {\n
+\tvar inst = color(),\n
+\t\trgba = inst._rgba = [];\n
+\n
+\tstring = string.toLowerCase();\n
+\n
+\teach( stringParsers, function( i, parser ) {\n
+\t\tvar parsed,\n
+\t\t\tmatch = parser.re.exec( string ),\n
+\t\t\tvalues = match && parser.parse( match ),\n
+\t\t\tspaceName = parser.space || "rgba";\n
+\n
+\t\tif ( values ) {\n
+\t\t\tparsed = inst[ spaceName ]( values );\n
+\n
+\t\t\t// if this was an rgba parse the assignment might happen twice\n
+\t\t\t// oh well....\n
+\t\t\tinst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];\n
+\t\t\trgba = inst._rgba = parsed._rgba;\n
+\n
+\t\t\t// exit each( stringParsers ) here because we matched\n
+\t\t\treturn false;\n
+\t\t}\n
+\t});\n
+\n
+\t// Found a stringParser that handled it\n
+\tif ( rgba.length ) {\n
+\n
+\t\t// if this came from a parsed string, force "transparent" when alpha is 0\n
+\t\t// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)\n
+\t\tif ( rgba.join() === "0,0,0,0" ) {\n
+\t\t\tjQuery.extend( rgba, colors.transparent );\n
+\t\t}\n
+\t\treturn inst;\n
+\t}\n
+\n
+\t// named colors\n
+\treturn colors[ string ];\n
+}\n
+\n
+color.fn = jQuery.extend( color.prototype, {\n
+\tparse: function( red, green, blue, alpha ) {\n
+\t\tif ( red === undefined ) {\n
+\t\t\tthis._rgba = [ null, null, null, null ];\n
+\t\t\treturn this;\n
+\t\t}\n
+\t\tif ( red.jquery || red.nodeType ) {\n
+\t\t\tred = jQuery( red ).css( green );\n
+\t\t\tgreen = undefined;\n
+\t\t}\n
+\n
+\t\tvar inst = this,\n
+\t\t\ttype = jQuery.type( red ),\n
+\t\t\trgba = this._rgba = [];\n
+\n
+\t\t// more than 1 argument specified - assume ( red, green, blue, alpha )\n
+\t\tif ( green !== undefined ) {\n
+\t\t\tred = [ red, green, blue, alpha ];\n
+\t\t\ttype = "array";\n
+\t\t}\n
+\n
+\t\tif ( type === "string" ) {\n
+\t\t\treturn this.parse( stringParse( red ) || colors._default );\n
+\t\t}\n
+\n
+\t\tif ( type === "array" ) {\n
+\t\t\teach( spaces.rgba.props, function( key, prop ) {\n
+\t\t\t\trgba[ prop.idx ] = clamp( red[ prop.idx ], prop );\n
+\t\t\t});\n
+\t\t\treturn this;\n
+\t\t}\n
+\n
+\t\tif ( type === "object" ) {\n
+\t\t\tif ( red instanceof color ) {\n
+\t\t\t\teach( spaces, function( spaceName, space ) {\n
+\t\t\t\t\tif ( red[ space.cache ] ) {\n
+\t\t\t\t\t\tinst[ space.cache ] = red[ space.cache ].slice();\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t} else {\n
+\t\t\t\teach( spaces, function( spaceName, space ) {\n
+\t\t\t\t\tvar cache = space.cache;\n
+\t\t\t\t\teach( space.props, function( key, prop ) {\n
+\n
+\t\t\t\t\t\t// if the cache doesn\'t exist, and we know how to convert\n
+\t\t\t\t\t\tif ( !inst[ cache ] && space.to ) {\n
+\n
+\t\t\t\t\t\t\t// if the value was null, we don\'t need to copy it\n
+\t\t\t\t\t\t\t// if the key was alpha, we don\'t need to copy it either\n
+\t\t\t\t\t\t\tif ( key === "alpha" || red[ key ] == null ) {\n
+\t\t\t\t\t\t\t\treturn;\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\tinst[ cache ] = space.to( inst._rgba );\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\t// this is the only case where we allow nulls for ALL properties.\n
+\t\t\t\t\t\t// call clamp with alwaysAllowEmpty\n
+\t\t\t\t\t\tinst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );\n
+\t\t\t\t\t});\n
+\n
+\t\t\t\t\t// everything defined but alpha?\n
+\t\t\t\t\tif ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {\n
+\t\t\t\t\t\t// use the default of 1\n
+\t\t\t\t\t\tinst[ cache ][ 3 ] = 1;\n
+\t\t\t\t\t\tif ( space.from ) {\n
+\t\t\t\t\t\t\tinst._rgba = space.from( inst[ cache ] );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t\treturn this;\n
+\t\t}\n
+\t},\n
+\tis: function( compare ) {\n
+\t\tvar is = color( compare ),\n
+\t\t\tsame = true,\n
+\t\t\tinst = this;\n
+\n
+\t\teach( spaces, function( _, space ) {\n
+\t\t\tvar localCache,\n
+\t\t\t\tisCache = is[ space.cache ];\n
+\t\t\tif (isCache) {\n
+\t\t\t\tlocalCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];\n
+\t\t\t\teach( space.props, function( _, prop ) {\n
+\t\t\t\t\tif ( isCache[ prop.idx ] != null ) {\n
+\t\t\t\t\t\tsame = ( isCache[ prop.idx ] === localCache[ prop.idx ] );\n
+\t\t\t\t\t\treturn same;\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t\treturn same;\n
+\t\t});\n
+\t\treturn same;\n
+\t},\n
+\t_space: function() {\n
+\t\tvar used = [],\n
+\t\t\tinst = this;\n
+\t\teach( spaces, function( spaceName, space ) {\n
+\t\t\tif ( inst[ space.cache ] ) {\n
+\t\t\t\tused.push( spaceName );\n
+\t\t\t}\n
+\t\t});\n
+\t\treturn used.pop();\n
+\t},\n
+\ttransition: function( other, distance ) {\n
+\t\tvar end = color( other ),\n
+\t\t\tspaceName = end._space(),\n
+\t\t\tspace = spaces[ spaceName ],\n
+\t\t\tstartColor = this.alpha() === 0 ? color( "transparent" ) : this,\n
+\t\t\tstart = startColor[ space.cache ] || space.to( startColor._rgba ),\n
+\t\t\tresult = start.slice();\n
+\n
+\t\tend = end[ space.cache ];\n
+\t\teach( space.props, function( key, prop ) {\n
+\t\t\tvar index = prop.idx,\n
+\t\t\t\tstartValue = start[ index ],\n
+\t\t\t\tendValue = end[ index ],\n
+\t\t\t\ttype = propTypes[ prop.type ] || {};\n
+\n
+\t\t\t// if null, don\'t override start value\n
+\t\t\tif ( endValue === null ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\t// if null - use end\n
+\t\t\tif ( startValue === null ) {\n
+\t\t\t\tresult[ index ] = endValue;\n
+\t\t\t} else {\n
+\t\t\t\tif ( type.mod ) {\n
+\t\t\t\t\tif ( endValue - startValue > type.mod / 2 ) {\n
+\t\t\t\t\t\tstartValue += type.mod;\n
+\t\t\t\t\t} else if ( startValue - endValue > type.mod / 2 ) {\n
+\t\t\t\t\t\tstartValue -= type.mod;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\tresult[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );\n
+\t\t\t}\n
+\t\t});\n
+\t\treturn this[ spaceName ]( result );\n
+\t},\n
+\tblend: function( opaque ) {\n
+\t\t// if we are already opaque - return ourself\n
+\t\tif ( this._rgba[ 3 ] === 1 ) {\n
+\t\t\treturn this;\n
+\t\t}\n
+\n
+\t\tvar rgb = this._rgba.slice(),\n
+\t\t\ta = rgb.pop(),\n
+\t\t\tblend = color( opaque )._rgba;\n
+\n
+\t\treturn color( jQuery.map( rgb, function( v, i ) {\n
+\t\t\treturn ( 1 - a ) * blend[ i ] + a * v;\n
+\t\t}));\n
+\t},\n
+\ttoRgbaString: function() {\n
+\t\tvar prefix = "rgba(",\n
+\t\t\trgba = jQuery.map( this._rgba, function( v, i ) {\n
+\t\t\t\treturn v == null ? ( i > 2 ? 1 : 0 ) : v;\n
+\t\t\t});\n
+\n
+\t\tif ( rgba[ 3 ] === 1 ) {\n
+\t\t\trgba.pop();\n
+\t\t\tprefix = "rgb(";\n
+\t\t}\n
+\n
+\t\treturn prefix + rgba.join() + ")";\n
+\t},\n
+\ttoHslaString: function() {\n
+\t\tvar prefix = "hsla(",\n
+\t\t\thsla = jQuery.map( this.hsla(), function( v, i ) {\n
+\t\t\t\tif ( v == null ) {\n
+\t\t\t\t\tv = i > 2 ? 1 : 0;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// catch 1 and 2\n
+\t\t\t\tif ( i && i < 3 ) {\n
+\t\t\t\t\tv = Math.round( v * 100 ) + "%";\n
+\t\t\t\t}\n
+\t\t\t\treturn v;\n
+\t\t\t});\n
+\n
+\t\tif ( hsla[ 3 ] === 1 ) {\n
+\t\t\thsla.pop();\n
+\t\t\tprefix = "hsl(";\n
+\t\t}\n
+\t\treturn prefix + hsla.join() + ")";\n
+\t},\n
+\ttoHexString: function( includeAlpha ) {\n
+\t\tvar rgba = this._rgba.slice(),\n
+\t\t\talpha = rgba.pop();\n
+\n
+\t\tif ( includeAlpha ) {\n
+\t\t\trgba.push( ~~( alpha * 255 ) );\n
+\t\t}\n
+\n
+\t\treturn "#" + jQuery.map( rgba, function( v ) {\n
+\n
+\t\t\t// default to 0 when nulls exist\n
+\t\t\tv = ( v || 0 ).toString( 16 );\n
+\t\t\treturn v.length === 1 ? "0" + v : v;\n
+\t\t}).join("");\n
+\t},\n
+\ttoString: function() {\n
+\t\treturn this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();\n
+\t}\n
+});\n
+color.fn.parse.prototype = color.fn;\n
+\n
+// hsla conversions adapted from:\n
+// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021\n
+\n
+function hue2rgb( p, q, h ) {\n
+\th = ( h + 1 ) % 1;\n
+\tif ( h * 6 < 1 ) {\n
+\t\treturn p + (q - p) * h * 6;\n
+\t}\n
+\tif ( h * 2 < 1) {\n
+\t\treturn q;\n
+\t}\n
+\tif ( h * 3 < 2 ) {\n
+\t\treturn p + (q - p) * ((2/3) - h) * 6;\n
+\t}\n
+\treturn p;\n
+}\n
+\n
+spaces.hsla.to = function ( rgba ) {\n
+\tif ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {\n
+\t\treturn [ null, null, null, rgba[ 3 ] ];\n
+\t}\n
+\tvar r = rgba[ 0 ] / 255,\n
+\t\tg = rgba[ 1 ] / 255,\n
+\t\tb = rgba[ 2 ] / 255,\n
+\t\ta = rgba[ 3 ],\n
+\t\tmax = Math.max( r, g, b ),\n
+\t\tmin = Math.min( r, g, b ),\n
+\t\tdiff = max - min,\n
+\t\tadd = max + min,\n
+\t\tl = add * 0.5,\n
+\t\th, s;\n
+\n
+\tif ( min === max ) {\n
+\t\th = 0;\n
+\t} else if ( r === max ) {\n
+\t\th = ( 60 * ( g - b ) / diff ) + 360;\n
+\t} else if ( g === max ) {\n
+\t\th = ( 60 * ( b - r ) / diff ) + 120;\n
+\t} else {\n
+\t\th = ( 60 * ( r - g ) / diff ) + 240;\n
+\t}\n
+\n
+\t// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%\n
+\t// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)\n
+\tif ( diff === 0 ) {\n
+\t\ts = 0;\n
+\t} else if ( l <= 0.5 ) {\n
+\t\ts = diff / add;\n
+\t} else {\n
+\t\ts = diff / ( 2 - add );\n
+\t}\n
+\treturn [ Math.round(h) % 360, s, l, a == null ? 1 : a ];\n
+};\n
+\n
+spaces.hsla.from = function ( hsla ) {\n
+\tif ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {\n
+\t\treturn [ null, null, null, hsla[ 3 ] ];\n
+\t}\n
+\tvar h = hsla[ 0 ] / 360,\n
+\t\ts = hsla[ 1 ],\n
+\t\tl = hsla[ 2 ],\n
+\t\ta = hsla[ 3 ],\n
+\t\tq = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,\n
+\t\tp = 2 * l - q;\n
+\n
+\treturn [\n
+\t\tMath.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),\n
+\t\tMath.round( hue2rgb( p, q, h ) * 255 ),\n
+\t\tMath.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),\n
+\t\ta\n
+\t];\n
+};\n
+\n
+\n
+each( spaces, function( spaceName, space ) {\n
+\tvar props = space.props,\n
+\t\tcache = space.cache,\n
+\t\tto = space.to,\n
+\t\tfrom = space.from;\n
+\n
+\t// makes rgba() and hsla()\n
+\tcolor.fn[ spaceName ] = function( value ) {\n
+\n
+\t\t// generate a cache for this space if it doesn\'t exist\n
+\t\tif ( to && !this[ cache ] ) {\n
+\t\t\tthis[ cache ] = to( this._rgba );\n
+\t\t}\n
+\t\tif ( value === undefined ) {\n
+\t\t\treturn this[ cache ].slice();\n
+\t\t}\n
+\n
+\t\tvar ret,\n
+\t\t\ttype = jQuery.type( value ),\n
+\t\t\tarr = ( type === "array" || type === "object" ) ? value : arguments,\n
+\t\t\tlocal = this[ cache ].slice();\n
+\n
+\t\teach( props, function( key, prop ) {\n
+\t\t\tvar val = arr[ type === "object" ? key : prop.idx ];\n
+\t\t\tif ( val == null ) {\n
+\t\t\t\tval = local[ prop.idx ];\n
+\t\t\t}\n
+\t\t\tlocal[ prop.idx ] = clamp( val, prop );\n
+\t\t});\n
+\n
+\t\tif ( from ) {\n
+\t\t\tret = color( from( local ) );\n
+\t\t\tret[ cache ] = local;\n
+\t\t\treturn ret;\n
+\t\t} else {\n
+\t\t\treturn color( local );\n
+\t\t}\n
+\t};\n
+\n
+\t// makes red() green() blue() alpha() hue() saturation() lightness()\n
+\teach( props, function( key, prop ) {\n
+\t\t// alpha is included in more than one space\n
+\t\tif ( color.fn[ key ] ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tcolor.fn[ key ] = function( value ) {\n
+\t\t\tvar vtype = jQuery.type( value ),\n
+\t\t\t\tfn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),\n
+\t\t\t\tlocal = this[ fn ](),\n
+\t\t\t\tcur = local[ prop.idx ],\n
+\t\t\t\tmatch;\n
+\n
+\t\t\tif ( vtype === "undefined" ) {\n
+\t\t\t\treturn cur;\n
+\t\t\t}\n
+\n
+\t\t\tif ( vtype === "function" ) {\n
+\t\t\t\tvalue = value.call( this, cur );\n
+\t\t\t\tvtype = jQuery.type( value );\n
+\t\t\t}\n
+\t\t\tif ( value == null && prop.empty ) {\n
+\t\t\t\treturn this;\n
+\t\t\t}\n
+\t\t\tif ( vtype === "string" ) {\n
+\t\t\t\tmatch = rplusequals.exec( value );\n
+\t\t\t\tif ( match ) {\n
+\t\t\t\t\tvalue = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tlocal[ prop.idx ] = value;\n
+\t\t\treturn this[ fn ]( local );\n
+\t\t};\n
+\t});\n
+});\n
+\n
+// add cssHook and .fx.step function for each named hook.\n
+// accept a space separated string of properties\n
+color.hook = function( hook ) {\n
+\tvar hooks = hook.split( " " );\n
+\teach( hooks, function( i, hook ) {\n
+\t\tjQuery.cssHooks[ hook ] = {\n
+\t\t\tset: function( elem, value ) {\n
+\t\t\t\tvar parsed, curElem,\n
+\t\t\t\t\tbackgroundColor = "";\n
+\n
+\t\t\t\tif ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {\n
+\t\t\t\t\tvalue = color( parsed || value );\n
+\t\t\t\t\tif ( !support.rgba && value._rgba[ 3 ] !== 1 ) {\n
+\t\t\t\t\t\tcurElem = hook === "backgroundColor" ? elem.parentNode : elem;\n
+\t\t\t\t\t\twhile (\n
+\t\t\t\t\t\t\t(backgroundColor === "" || backgroundColor === "transparent") &&\n
+\t\t\t\t\t\t\tcurElem && curElem.style\n
+\t\t\t\t\t\t) {\n
+\t\t\t\t\t\t\ttry {\n
+\t\t\t\t\t\t\t\tbackgroundColor = jQuery.css( curElem, "backgroundColor" );\n
+\t\t\t\t\t\t\t\tcurElem = curElem.parentNode;\n
+\t\t\t\t\t\t\t} catch ( e ) {\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\tvalue = value.blend( backgroundColor && backgroundColor !== "transparent" ?\n
+\t\t\t\t\t\t\tbackgroundColor :\n
+\t\t\t\t\t\t\t"_default" );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tvalue = value.toRgbaString();\n
+\t\t\t\t}\n
+\t\t\t\ttry {\n
+\t\t\t\t\telem.style[ hook ] = value;\n
+\t\t\t\t} catch( e ) {\n
+\t\t\t\t\t// wrapped to prevent IE from throwing errors on "invalid" values like \'auto\' or \'inherit\'\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t};\n
+\t\tjQuery.fx.step[ hook ] = function( fx ) {\n
+\t\t\tif ( !fx.colorInit ) {\n
+\t\t\t\tfx.start = color( fx.elem, hook );\n
+\t\t\t\tfx.end = color( fx.end );\n
+\t\t\t\tfx.colorInit = true;\n
+\t\t\t}\n
+\t\t\tjQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );\n
+\t\t};\n
+\t});\n
+\n
+};\n
+\n
+color.hook( stepHooks );\n
+\n
+jQuery.cssHooks.borderColor = {\n
+\texpand: function( value ) {\n
+\t\tvar expanded = {};\n
+\n
+\t\teach( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {\n
+\t\t\texpanded[ "border" + part + "Color" ] = value;\n
+\t\t});\n
+\t\treturn expanded;\n
+\t}\n
+};\n
+\n
+// Basic color names only.\n
+// Usage of any of the other color names requires adding yourself or including\n
+// jquery.color.svg-names.js.\n
+colors = jQuery.Color.names = {\n
+\t// 4.1. Basic color keywords\n
+\taqua: "#00ffff",\n
+\tblack: "#000000",\n
+\tblue: "#0000ff",\n
+\tfuchsia: "#ff00ff",\n
+\tgray: "#808080",\n
+\tgreen: "#008000",\n
+\tlime: "#00ff00",\n
+\tmaroon: "#800000",\n
+\tnavy: "#000080",\n
+\tolive: "#808000",\n
+\tpurple: "#800080",\n
+\tred: "#ff0000",\n
+\tsilver: "#c0c0c0",\n
+\tteal: "#008080",\n
+\twhite: "#ffffff",\n
+\tyellow: "#ffff00",\n
+\n
+\t// 4.2.3. "transparent" color keyword\n
+\ttransparent: [ null, null, null, 0 ],\n
+\n
+\t_default: "#ffffff"\n
+};\n
+\n
+})( jQuery );\n
+\n
+\n
+/******************************************************************************/\n
+/****************************** CLASS ANIMATIONS ******************************/\n
+/******************************************************************************/\n
+(function() {\n
+\n
+var classAnimationActions = [ "add", "remove", "toggle" ],\n
+\tshorthandStyles = {\n
+\t\tborder: 1,\n
+\t\tborderBottom: 1,\n
+\t\tborderColor: 1,\n
+\t\tborderLeft: 1,\n
+\t\tborderRight: 1,\n
+\t\tborderTop: 1,\n
+\t\tborderWidth: 1,\n
+\t\tmargin: 1,\n
+\t\tpadding: 1\n
+\t};\n
+\n
+$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {\n
+\t$.fx.step[ prop ] = function( fx ) {\n
+\t\tif ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {\n
+\t\t\tjQuery.style( fx.elem, prop, fx.end );\n
+\t\t\tfx.setAttr = true;\n
+\t\t}\n
+\t};\n
+});\n
+\n
+function getElementStyles( elem ) {\n
+\tvar key, len,\n
+\t\tstyle = elem.ownerDocument.defaultView ?\n
+\t\t\telem.ownerDocument.defaultView.getComputedStyle( elem, null ) :\n
+\t\t\telem.currentStyle,\n
+\t\tstyles = {};\n
+\n
+\tif ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {\n
+\t\tlen = style.length;\n
+\t\twhile ( len-- ) {\n
+\t\t\tkey = style[ len ];\n
+\t\t\tif ( typeof style[ key ] === "string" ) {\n
+\t\t\t\tstyles[ $.camelCase( key ) ] = style[ key ];\n
+\t\t\t}\n
+\t\t}
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="5" aka="AAAAAAAAAAU=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+\n
+\t// support: Opera, IE <9\n
+\t} else {\n
+\t\tfor ( key in style ) {\n
+\t\t\tif ( typeof style[ key ] === "string" ) {\n
+\t\t\t\tstyles[ key ] = style[ key ];\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\treturn styles;\n
+}\n
+\n
+\n
+function styleDifference( oldStyle, newStyle ) {\n
+\tvar diff = {},\n
+\t\tname, value;\n
+\n
+\tfor ( name in newStyle ) {\n
+\t\tvalue = newStyle[ name ];\n
+\t\tif ( oldStyle[ name ] !== value ) {\n
+\t\t\tif ( !shorthandStyles[ name ] ) {\n
+\t\t\t\tif ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {\n
+\t\t\t\t\tdiff[ name ] = value;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\treturn diff;\n
+}\n
+\n
+// support: jQuery <1.8\n
+if ( !$.fn.addBack ) {\n
+\t$.fn.addBack = function( selector ) {\n
+\t\treturn this.add( selector == null ?\n
+\t\t\tthis.prevObject : this.prevObject.filter( selector )\n
+\t\t);\n
+\t};\n
+}\n
+\n
+$.effects.animateClass = function( value, duration, easing, callback ) {\n
+\tvar o = $.speed( duration, easing, callback );\n
+\n
+\treturn this.queue( function() {\n
+\t\tvar animated = $( this ),\n
+\t\t\tbaseClass = animated.attr( "class" ) || "",\n
+\t\t\tapplyClassChange,\n
+\t\t\tallAnimations = o.children ? animated.find( "*" ).addBack() : animated;\n
+\n
+\t\t// map the animated objects to store the original styles.\n
+\t\tallAnimations = allAnimations.map(function() {\n
+\t\t\tvar el = $( this );\n
+\t\t\treturn {\n
+\t\t\t\tel: el,\n
+\t\t\t\tstart: getElementStyles( this )\n
+\t\t\t};\n
+\t\t});\n
+\n
+\t\t// apply class change\n
+\t\tapplyClassChange = function() {\n
+\t\t\t$.each( classAnimationActions, function(i, action) {\n
+\t\t\t\tif ( value[ action ] ) {\n
+\t\t\t\t\tanimated[ action + "Class" ]( value[ action ] );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t};\n
+\t\tapplyClassChange();\n
+\n
+\t\t// map all animated objects again - calculate new styles and diff\n
+\t\tallAnimations = allAnimations.map(function() {\n
+\t\t\tthis.end = getElementStyles( this.el[ 0 ] );\n
+\t\t\tthis.diff = styleDifference( this.start, this.end );\n
+\t\t\treturn this;\n
+\t\t});\n
+\n
+\t\t// apply original class\n
+\t\tanimated.attr( "class", baseClass );\n
+\n
+\t\t// map all animated objects again - this time collecting a promise\n
+\t\tallAnimations = allAnimations.map(function() {\n
+\t\t\tvar styleInfo = this,\n
+\t\t\t\tdfd = $.Deferred(),\n
+\t\t\t\topts = $.extend({}, o, {\n
+\t\t\t\t\tqueue: false,\n
+\t\t\t\t\tcomplete: function() {\n
+\t\t\t\t\t\tdfd.resolve( styleInfo );\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\n
+\t\t\tthis.el.animate( this.diff, opts );\n
+\t\t\treturn dfd.promise();\n
+\t\t});\n
+\n
+\t\t// once all animations have completed:\n
+\t\t$.when.apply( $, allAnimations.get() ).done(function() {\n
+\n
+\t\t\t// set the final class\n
+\t\t\tapplyClassChange();\n
+\n
+\t\t\t// for each animated element,\n
+\t\t\t// clear all css properties that were animated\n
+\t\t\t$.each( arguments, function() {\n
+\t\t\t\tvar el = this.el;\n
+\t\t\t\t$.each( this.diff, function(key) {\n
+\t\t\t\t\tel.css( key, "" );\n
+\t\t\t\t});\n
+\t\t\t});\n
+\n
+\t\t\t// this is guarnteed to be there if you use jQuery.speed()\n
+\t\t\t// it also handles dequeuing the next anim...\n
+\t\t\to.complete.call( animated[ 0 ] );\n
+\t\t});\n
+\t});\n
+};\n
+\n
+$.fn.extend({\n
+\taddClass: (function( orig ) {\n
+\t\treturn function( classNames, speed, easing, callback ) {\n
+\t\t\treturn speed ?\n
+\t\t\t\t$.effects.animateClass.call( this,\n
+\t\t\t\t\t{ add: classNames }, speed, easing, callback ) :\n
+\t\t\t\torig.apply( this, arguments );\n
+\t\t};\n
+\t})( $.fn.addClass ),\n
+\n
+\tremoveClass: (function( orig ) {\n
+\t\treturn function( classNames, speed, easing, callback ) {\n
+\t\t\treturn arguments.length > 1 ?\n
+\t\t\t\t$.effects.animateClass.call( this,\n
+\t\t\t\t\t{ remove: classNames }, speed, easing, callback ) :\n
+\t\t\t\torig.apply( this, arguments );\n
+\t\t};\n
+\t})( $.fn.removeClass ),\n
+\n
+\ttoggleClass: (function( orig ) {\n
+\t\treturn function( classNames, force, speed, easing, callback ) {\n
+\t\t\tif ( typeof force === "boolean" || force === undefined ) {\n
+\t\t\t\tif ( !speed ) {\n
+\t\t\t\t\t// without speed parameter\n
+\t\t\t\t\treturn orig.apply( this, arguments );\n
+\t\t\t\t} else {\n
+\t\t\t\t\treturn $.effects.animateClass.call( this,\n
+\t\t\t\t\t\t(force ? { add: classNames } : { remove: classNames }),\n
+\t\t\t\t\t\tspeed, easing, callback );\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\t// without force parameter\n
+\t\t\t\treturn $.effects.animateClass.call( this,\n
+\t\t\t\t\t{ toggle: classNames }, force, speed, easing );\n
+\t\t\t}\n
+\t\t};\n
+\t})( $.fn.toggleClass ),\n
+\n
+\tswitchClass: function( remove, add, speed, easing, callback) {\n
+\t\treturn $.effects.animateClass.call( this, {\n
+\t\t\tadd: add,\n
+\t\t\tremove: remove\n
+\t\t}, speed, easing, callback );\n
+\t}\n
+});\n
+\n
+})();\n
+\n
+/******************************************************************************/\n
+/*********************************** EFFECTS **********************************/\n
+/******************************************************************************/\n
+\n
+(function() {\n
+\n
+$.extend( $.effects, {\n
+\tversion: "1.10.4",\n
+\n
+\t// Saves a set of properties in a data storage\n
+\tsave: function( element, set ) {\n
+\t\tfor( var i=0; i < set.length; i++ ) {\n
+\t\t\tif ( set[ i ] !== null ) {\n
+\t\t\t\telement.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t// Restores a set of previously saved properties from a data storage\n
+\trestore: function( element, set ) {\n
+\t\tvar val, i;\n
+\t\tfor( i=0; i < set.length; i++ ) {\n
+\t\t\tif ( set[ i ] !== null ) {\n
+\t\t\t\tval = element.data( dataSpace + set[ i ] );\n
+\t\t\t\t// support: jQuery 1.6.2\n
+\t\t\t\t// http://bugs.jquery.com/ticket/9917\n
+\t\t\t\t// jQuery 1.6.2 incorrectly returns undefined for any falsy value.\n
+\t\t\t\t// We can\'t differentiate between "" and 0 here, so we just assume\n
+\t\t\t\t// empty string since it\'s likely to be a more common value...\n
+\t\t\t\tif ( val === undefined ) {\n
+\t\t\t\t\tval = "";\n
+\t\t\t\t}\n
+\t\t\t\telement.css( set[ i ], val );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\tsetMode: function( el, mode ) {\n
+\t\tif (mode === "toggle") {\n
+\t\t\tmode = el.is( ":hidden" ) ? "show" : "hide";\n
+\t\t}\n
+\t\treturn mode;\n
+\t},\n
+\n
+\t// Translates a [top,left] array into a baseline value\n
+\t// this should be a little more flexible in the future to handle a string & hash\n
+\tgetBaseline: function( origin, original ) {\n
+\t\tvar y, x;\n
+\t\tswitch ( origin[ 0 ] ) {\n
+\t\t\tcase "top": y = 0; break;\n
+\t\t\tcase "middle": y = 0.5; break;\n
+\t\t\tcase "bottom": y = 1; break;\n
+\t\t\tdefault: y = origin[ 0 ] / original.height;\n
+\t\t}\n
+\t\tswitch ( origin[ 1 ] ) {\n
+\t\t\tcase "left": x = 0; break;\n
+\t\t\tcase "center": x = 0.5; break;\n
+\t\t\tcase "right": x = 1; break;\n
+\t\t\tdefault: x = origin[ 1 ] / original.width;\n
+\t\t}\n
+\t\treturn {\n
+\t\t\tx: x,\n
+\t\t\ty: y\n
+\t\t};\n
+\t},\n
+\n
+\t// Wraps the element around a wrapper that copies position properties\n
+\tcreateWrapper: function( element ) {\n
+\n
+\t\t// if the element is already wrapped, return it\n
+\t\tif ( element.parent().is( ".ui-effects-wrapper" )) {\n
+\t\t\treturn element.parent();\n
+\t\t}\n
+\n
+\t\t// wrap the element\n
+\t\tvar props = {\n
+\t\t\t\twidth: element.outerWidth(true),\n
+\t\t\t\theight: element.outerHeight(true),\n
+\t\t\t\t"float": element.css( "float" )\n
+\t\t\t},\n
+\t\t\twrapper = $( "<div></div>" )\n
+\t\t\t\t.addClass( "ui-effects-wrapper" )\n
+\t\t\t\t.css({\n
+\t\t\t\t\tfontSize: "100%",\n
+\t\t\t\t\tbackground: "transparent",\n
+\t\t\t\t\tborder: "none",\n
+\t\t\t\t\tmargin: 0,\n
+\t\t\t\t\tpadding: 0\n
+\t\t\t\t}),\n
+\t\t\t// Store the size in case width/height are defined in % - Fixes #5245\n
+\t\t\tsize = {\n
+\t\t\t\twidth: element.width(),\n
+\t\t\t\theight: element.height()\n
+\t\t\t},\n
+\t\t\tactive = document.activeElement;\n
+\n
+\t\t// support: Firefox\n
+\t\t// Firefox incorrectly exposes anonymous content\n
+\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=561664\n
+\t\ttry {\n
+\t\t\tactive.id;\n
+\t\t} catch( e ) {\n
+\t\t\tactive = document.body;\n
+\t\t}\n
+\n
+\t\telement.wrap( wrapper );\n
+\n
+\t\t// Fixes #7595 - Elements lose focus when wrapped.\n
+\t\tif ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\n
+\t\t\t$( active ).focus();\n
+\t\t}\n
+\n
+\t\twrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element\n
+\n
+\t\t// transfer positioning properties to the wrapper\n
+\t\tif ( element.css( "position" ) === "static" ) {\n
+\t\t\twrapper.css({ position: "relative" });\n
+\t\t\telement.css({ position: "relative" });\n
+\t\t} else {\n
+\t\t\t$.extend( props, {\n
+\t\t\t\tposition: element.css( "position" ),\n
+\t\t\t\tzIndex: element.css( "z-index" )\n
+\t\t\t});\n
+\t\t\t$.each([ "top", "left", "bottom", "right" ], function(i, pos) {\n
+\t\t\t\tprops[ pos ] = element.css( pos );\n
+\t\t\t\tif ( isNaN( parseInt( props[ pos ], 10 ) ) ) {\n
+\t\t\t\t\tprops[ pos ] = "auto";\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t\telement.css({\n
+\t\t\t\tposition: "relative",\n
+\t\t\t\ttop: 0,\n
+\t\t\t\tleft: 0,\n
+\t\t\t\tright: "auto",\n
+\t\t\t\tbottom: "auto"\n
+\t\t\t});\n
+\t\t}\n
+\t\telement.css(size);\n
+\n
+\t\treturn wrapper.css( props ).show();\n
+\t},\n
+\n
+\tremoveWrapper: function( element ) {\n
+\t\tvar active = document.activeElement;\n
+\n
+\t\tif ( element.parent().is( ".ui-effects-wrapper" ) ) {\n
+\t\t\telement.parent().replaceWith( element );\n
+\n
+\t\t\t// Fixes #7595 - Elements lose focus when wrapped.\n
+\t\t\tif ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {\n
+\t\t\t\t$( active ).focus();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\n
+\t\treturn element;\n
+\t},\n
+\n
+\tsetTransition: function( element, list, factor, value ) {\n
+\t\tvalue = value || {};\n
+\t\t$.each( list, function( i, x ) {\n
+\t\t\tvar unit = element.cssUnit( x );\n
+\t\t\tif ( unit[ 0 ] > 0 ) {\n
+\t\t\t\tvalue[ x ] = unit[ 0 ] * factor + unit[ 1 ];\n
+\t\t\t}\n
+\t\t});\n
+\t\treturn value;\n
+\t}\n
+});\n
+\n
+// return an effect options object for the given parameters:\n
+function _normalizeArguments( effect, options, speed, callback ) {\n
+\n
+\t// allow passing all options as the first parameter\n
+\tif ( $.isPlainObject( effect ) ) {\n
+\t\toptions = effect;\n
+\t\teffect = effect.effect;\n
+\t}\n
+\n
+\t// convert to an object\n
+\teffect = { effect: effect };\n
+\n
+\t// catch (effect, null, ...)\n
+\tif ( options == null ) {\n
+\t\toptions = {};\n
+\t}\n
+\n
+\t// catch (effect, callback)\n
+\tif ( $.isFunction( options ) ) {\n
+\t\tcallback = options;\n
+\t\tspeed = null;\n
+\t\toptions = {};\n
+\t}\n
+\n
+\t// catch (effect, speed, ?)\n
+\tif ( typeof options === "number" || $.fx.speeds[ options ] ) {\n
+\t\tcallback = speed;\n
+\t\tspeed = options;\n
+\t\toptions = {};\n
+\t}\n
+\n
+\t// catch (effect, options, callback)\n
+\tif ( $.isFunction( speed ) ) {\n
+\t\tcallback = speed;\n
+\t\tspeed = null;\n
+\t}\n
+\n
+\t// add options to effect\n
+\tif ( options ) {\n
+\t\t$.extend( effect, options );\n
+\t}\n
+\n
+\tspeed = speed || options.duration;\n
+\teffect.duration = $.fx.off ? 0 :\n
+\t\ttypeof speed === "number" ? speed :\n
+\t\tspeed in $.fx.speeds ? $.fx.speeds[ speed ] :\n
+\t\t$.fx.speeds._default;\n
+\n
+\teffect.complete = callback || options.complete;\n
+\n
+\treturn effect;\n
+}\n
+\n
+function standardAnimationOption( option ) {\n
+\t// Valid standard speeds (nothing, number, named speed)\n
+\tif ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {\n
+\t\treturn true;\n
+\t}\n
+\n
+\t// Invalid strings - treat as "normal" speed\n
+\tif ( typeof option === "string" && !$.effects.effect[ option ] ) {\n
+\t\treturn true;\n
+\t}\n
+\n
+\t// Complete callback\n
+\tif ( $.isFunction( option ) ) {\n
+\t\treturn true;\n
+\t}\n
+\n
+\t// Options hash (but not naming an effect)\n
+\tif ( typeof option === "object" && !option.effect ) {\n
+\t\treturn true;\n
+\t}\n
+\n
+\t// Didn\'t match any standard API\n
+\treturn false;\n
+}\n
+\n
+$.fn.extend({\n
+\teffect: function( /* effect, options, speed, callback */ ) {\n
+\t\tvar args = _normalizeArguments.apply( this, arguments ),\n
+\t\t\tmode = args.mode,\n
+\t\t\tqueue = args.queue,\n
+\t\t\teffectMethod = $.effects.effect[ args.effect ];\n
+\n
+\t\tif ( $.fx.off || !effectMethod ) {\n
+\t\t\t// delegate to the original method (e.g., .show()) if possible\n
+\t\t\tif ( mode ) {\n
+\t\t\t\treturn this[ mode ]( args.duration, args.complete );\n
+\t\t\t} else {\n
+\t\t\t\treturn this.each( function() {\n
+\t\t\t\t\tif ( args.complete ) {\n
+\t\t\t\t\t\targs.complete.call( this );\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tfunction run( next ) {\n
+\t\t\tvar elem = $( this ),\n
+\t\t\t\tcomplete = args.complete,\n
+\t\t\t\tmode = args.mode;\n
+\n
+\t\t\tfunction done() {\n
+\t\t\t\tif ( $.isFunction( complete ) ) {\n
+\t\t\t\t\tcomplete.call( elem[0] );\n
+\t\t\t\t}\n
+\t\t\t\tif ( $.isFunction( next ) ) {\n
+\t\t\t\t\tnext();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// If the element already has the correct final state, delegate to\n
+\t\t\t// the core methods so the internal tracking of "olddisplay" works.\n
+\t\t\tif ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {\n
+\t\t\t\telem[ mode ]();\n
+\t\t\t\tdone();\n
+\t\t\t} else {\n
+\t\t\t\teffectMethod.call( elem[0], args, done );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn queue === false ? this.each( run ) : this.queue( queue || "fx", run );\n
+\t},\n
+\n
+\tshow: (function( orig ) {\n
+\t\treturn function( option ) {\n
+\t\t\tif ( standardAnimationOption( option ) ) {\n
+\t\t\t\treturn orig.apply( this, arguments );\n
+\t\t\t} else {\n
+\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n
+\t\t\t\targs.mode = "show";\n
+\t\t\t\treturn this.effect.call( this, args );\n
+\t\t\t}\n
+\t\t};\n
+\t})( $.fn.show ),\n
+\n
+\thide: (function( orig ) {\n
+\t\treturn function( option ) {\n
+\t\t\tif ( standardAnimationOption( option ) ) {\n
+\t\t\t\treturn orig.apply( this, arguments );\n
+\t\t\t} else {\n
+\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n
+\t\t\t\targs.mode = "hide";\n
+\t\t\t\treturn this.effect.call( this, args );\n
+\t\t\t}\n
+\t\t};\n
+\t})( $.fn.hide ),\n
+\n
+\ttoggle: (function( orig ) {\n
+\t\treturn function( option ) {\n
+\t\t\tif ( standardAnimationOption( option ) || typeof option === "boolean" ) {\n
+\t\t\t\treturn orig.apply( this, arguments );\n
+\t\t\t} else {\n
+\t\t\t\tvar args = _normalizeArguments.apply( this, arguments );\n
+\t\t\t\targs.mode = "toggle";\n
+\t\t\t\treturn this.effect.call( this, args );\n
+\t\t\t}\n
+\t\t};\n
+\t})( $.fn.toggle ),\n
+\n
+\t// helper functions\n
+\tcssUnit: function(key) {\n
+\t\tvar style = this.css( key ),\n
+\t\t\tval = [];\n
+\n
+\t\t$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {\n
+\t\t\tif ( style.indexOf( unit ) > 0 ) {\n
+\t\t\t\tval = [ parseFloat( style ), unit ];\n
+\t\t\t}\n
+\t\t});\n
+\t\treturn val;\n
+\t}\n
+});\n
+\n
+})();\n
+\n
+/******************************************************************************/\n
+/*********************************** EASING ***********************************/\n
+/******************************************************************************/\n
+\n
+(function() {\n
+\n
+// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)\n
+\n
+var baseEasings = {};\n
+\n
+$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {\n
+\tbaseEasings[ name ] = function( p ) {\n
+\t\treturn Math.pow( p, i + 2 );\n
+\t};\n
+});\n
+\n
+$.extend( baseEasings, {\n
+\tSine: function ( p ) {\n
+\t\treturn 1 - Math.cos( p * Math.PI / 2 );\n
+\t},\n
+\tCirc: function ( p ) {\n
+\t\treturn 1 - Math.sqrt( 1 - p * p );\n
+\t},\n
+\tElastic: function( p ) {\n
+\t\treturn p === 0 || p === 1 ? p :\n
+\t\t\t-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );\n
+\t},\n
+\tBack: function( p ) {\n
+\t\treturn p * p * ( 3 * p - 2 );\n
+\t},\n
+\tBounce: function ( p ) {\n
+\t\tvar pow2,\n
+\t\t\tbounce = 4;\n
+\n
+\t\twhile ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}\n
+\t\treturn 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );\n
+\t}\n
+});\n
+\n
+$.each( baseEasings, function( name, easeIn ) {\n
+\t$.easing[ "easeIn" + name ] = easeIn;\n
+\t$.easing[ "easeOut" + name ] = function( p ) {\n
+\t\treturn 1 - easeIn( 1 - p );\n
+\t};\n
+\t$.easing[ "easeInOut" + name ] = function( p ) {\n
+\t\treturn p < 0.5 ?\n
+\t\t\teaseIn( p * 2 ) / 2 :\n
+\t\t\t1 - easeIn( p * -2 + 2 ) / 2;\n
+\t};\n
+});\n
+\n
+})();\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+var rvertical = /up|down|vertical/,\n
+\trpositivemotion = /up|left|vertical|horizontal/;\n
+\n
+$.effects.effect.blind = function( o, done ) {\n
+\t// Create element\n
+\tvar el = $( this ),\n
+\t\tprops = [ "position", "top", "bottom", "left", "right", "height", "width" ],\n
+\t\tmode = $.effects.setMode( el, o.mode || "hide" ),\n
+\t\tdirection = o.direction || "up",\n
+\t\tvertical = rvertical.test( direction ),\n
+\t\tref = vertical ? "height" : "width",\n
+\t\tref2 = vertical ? "top" : "left",\n
+\t\tmotion = rpositivemotion.test( direction ),\n
+\t\tanimation = {},\n
+\t\tshow = mode === "show",\n
+\t\twrapper, distance, margin;\n
+\n
+\t// if already wrapped, the wrapper\'s properties are my property. #6245\n
+\tif ( el.parent().is( ".ui-effects-wrapper" ) ) {\n
+\t\t$.effects.save( el.parent(), props );\n
+\t} else {\n
+\t\t$.effects.save( el, props );\n
+\t}\n
+\tel.show();\n
+\twrapper = $.effects.createWrapper( el ).css({\n
+\t\toverflow: "hidden"\n
+\t});\n
+\n
+\tdistance = wrapper[ ref ]();\n
+\tmargin = parseFloat( wrapper.css( ref2 ) ) || 0;\n
+\n
+\tanimation[ ref ] = show ? distance : 0;\n
+\tif ( !motion ) {\n
+\t\tel\n
+\t\t\t.css( vertical ? "bottom" : "right", 0 )\n
+\t\t\t.css( vertical ? "top" : "left", "auto" )\n
+\t\t\t.css({ position: "absolute" });\n
+\n
+\t\tanimation[ ref2 ] = show ? margin : distance + margin;\n
+\t}\n
+\n
+\t// start at 0 if we are showing\n
+\tif ( show ) {\n
+\t\twrapper.css( ref, 0 );\n
+\t\tif ( ! motion ) {\n
+\t\t\twrapper.css( ref2, margin + distance );\n
+\t\t}\n
+\t}\n
+\n
+\t// Animate\n
+\twrapper.animate( animation, {\n
+\t\tduration: o.duration,\n
+\t\teasing: o.easing,\n
+\t\tqueue: false,\n
+\t\tcomplete: function() {\n
+\t\t\tif ( mode === "hide" ) {\n
+\t\t\t\tel.hide();\n
+\t\t\t}\n
+\t\t\t$.effects.restore( el, props );\n
+\t\t\t$.effects.removeWrapper( el );\n
+\t\t\tdone();\n
+\t\t}\n
+\t});\n
+\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.bounce = function( o, done ) {\n
+\tvar el = $( this ),\n
+\t\tprops = [ "position", "top", "bottom", "left", "right", "height", "width" ],\n
+\n
+\t\t// defaults:\n
+\t\tmode = $.effects.setMode( el, o.mode || "effect" ),\n
+\t\thide = mode === "hide",\n
+\t\tshow = mode === "show",\n
+\t\tdirection = o.direction || "up",\n
+\t\tdistance = o.distance,\n
+\t\ttimes = o.times || 5,\n
+\n
+\t\t// number of internal animations\n
+\t\tanims = times * 2 + ( show || hide ? 1 : 0 ),\n
+\t\tspeed = o.duration / anims,\n
+\t\teasing = o.easing,\n
+\n
+\t\t// utility:\n
+\t\tref = ( direction === "up" || direction === "down" ) ? "top" : "left",\n
+\t\tmotion = ( direction === "up" || direction === "left" ),\n
+\t\ti,\n
+\t\tupAnim,\n
+\t\tdownAnim,\n
+\n
+\t\t// we will need to re-assemble the queue to stack our animations in place\n
+\t\tqueue = el.queue(),\n
+\t\tqueuelen = queue.length;\n
+\n
+\t// Avoid touching opacity to prevent clearType and PNG issues in IE\n
+\tif ( show || hide ) {\n
+\t\tprops.push( "opacity" );\n
+\t}\n
+\n
+\t$.effects.save( el, props );\n
+\tel.show();\n
+\t$.effects.createWrapper( el ); // Create Wrapper\n
+\n
+\t// default distance for the BIGGEST bounce is the outer Distance / 3\n
+\tif ( !distance ) {\n
+\t\tdistance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;\n
+\t}\n
+\n
+\tif ( show ) {\n
+\t\tdownAnim = { opacity: 1 };\n
+\t\tdownAnim[ ref ] = 0;\n
+\n
+\t\t// if we are showing, force opacity 0 and set the initial position\n
+\t\t// then do the "first" animation\n
+\t\tel.css( "opacity", 0 )\n
+\t\t\t.css( ref, motion ? -distance * 2 : distance * 2 )\n
+\t\t\t.animate( downAnim, speed, easing );\n
+\t}\n
+\n
+\t// start at the smallest distance if we are hiding\n
+\tif ( hide ) {\n
+\t\tdistance = distance / Math.pow( 2, times - 1 );\n
+\t}\n
+\n
+\tdownAnim = {};\n
+\tdownAnim[ ref ] = 0;\n
+\t// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here\n
+\tfor ( i = 0; i < times; i++ ) {\n
+\t\tupAnim = {};\n
+\t\tupAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;\n
+\n
+\t\tel.animate( upAnim, speed, easing )\n
+\t\t\t.animate( downAnim, speed, easing );\n
+\n
+\t\tdistance = hide ? distance * 2 : distance / 2;\n
+\t}\n
+\n
+\t// Last Bounce when Hiding\n
+\tif ( hide ) {\n
+\t\tupAnim = { opacity: 0 };\n
+\t\tupAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;\n
+\n
+\t\tel.animate( upAnim, speed, easing );\n
+\t}\n
+\n
+\tel.queue(function() {\n
+\t\tif ( hide ) {\n
+\t\t\tel.hide();\n
+\t\t}\n
+\t\t$.effects.restore( el, props );\n
+\t\t$.effects.removeWrapper( el );\n
+\t\tdone();\n
+\t});\n
+\n
+\t// inject all the animations we just queued to be first in line (after "inprogress")\n
+\tif ( queuelen > 1) {\n
+\t\tqueue.splice.apply( queue,\n
+\t\t\t[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );\n
+\t}\n
+\tel.dequeue();\n
+\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.clip = function( o, done ) {\n
+\t// Create element\n
+\tvar el = $( this ),\n
+\t\tprops = [ "position", "top", "bottom", "left", "right", "height", "width" ],\n
+\t\tmode = $.effects.setMode( el, o.mode || "hide" ),\n
+\t\tshow = mode === "show",\n
+\t\tdirection = o.direction || "vertical",\n
+\t\tvert = direction === "vertical",\n
+\t\tsize = vert ? "height" : "width",\n
+\t\tposition = vert ? "top" : "left",\n
+\t\tanimation = {},\n
+\t\twrapper, animate, distance;\n
+\n
+\t// Save & Show\n
+\t$.effects.save( el, props );\n
+\tel.show();\n
+\n
+\t// Create Wrapper\n
+\twrapper = $.effects.createWrapper( el ).css({\n
+\t\toverflow: "hidden"\n
+\t});\n
+\tanimate = ( el[0].tagName === "IMG" ) ? wrapper : el;\n
+\tdistance = animate[ size ]();\n
+\n
+\t// Shift\n
+\tif ( show ) {\n
+\t\tanimate.css( size, 0 );\n
+\t\tanimate.css( position, distance / 2 );\n
+\t}\n
+\n
+\t// Create Animation Object:\n
+\tanimation[ size ] = show ? distance : 0;\n
+\tanimation[ position ] = show ? 0 : distance / 2;\n
+\n
+\t// Animate\n
+\tanimate.animate( animation, {\n
+\t\tqueue: false,\n
+\t\tduration: o.duration,\n
+\t\teasing: o.easing,\n
+\t\tcomplete: function() {\n
+\t\t\tif ( !show ) {\n
+\t\t\t\tel.hide();\n
+\t\t\t}\n
+\t\t\t$.effects.restore( el, props );\n
+\t\t\t$.effects.removeWrapper( el );\n
+\t\t\tdone();\n
+\t\t}\n
+\t});\n
+\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.drop = function( o, done ) {\n
+\n
+\tvar el = $( this ),\n
+\t\tprops = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],\n
+\t\tmode = $.effects.setMode( el, o.mode || "hide" ),\n
+\t\tshow = mode === "show",\n
+\t\tdirection = o.direction || "left",\n
+\t\tref = ( direction === "up" || direction === "down" ) ? "top" : "left",\n
+\t\tmotion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",\n
+\t\tanimation = {\n
+\t\t\topacity: show ? 1 : 0\n
+\t\t},\n
+\t\tdistance;\n
+\n
+\t// Adjust\n
+\t$.effects.save( el, props );\n
+\tel.show();\n
+\t$.effects.createWrapper( el );\n
+\n
+\tdistance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;\n
+\n
+\tif ( show ) {\n
+\t\tel\n
+\t\t\t.css( "opacity", 0 )\n
+\t\t\t.css( ref, motion === "pos" ? -distance : distance );\n
+\t}\n
+\n
+\t// Animation\n
+\tanimation[ ref ] = ( show ?\n
+\t\t( motion === "pos" ? "+=" : "-=" ) :\n
+\t\t( motion === "pos" ? "-=" : "+=" ) ) +\n
+\t\tdistance;\n
+\n
+\t// Animate\n
+\tel.animate( animation, {\n
+\t\tqueue: false,\n
+\t\tduration: o.duration,\n
+\t\teasing: o.easing,\n
+\t\tcomplete: function() {\n
+\t\t\tif ( mode === "hide" ) {\n
+\t\t\t\tel.hide();\n
+\t\t\t}\n
+\t\t\t$.effects.restore( el, props );\n
+\t\t\t$.effects.removeWrapper( el );\n
+\t\t\tdone();\n
+\t\t}\n
+\t});\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.explode = function( o, done ) {\n
+\n
+\tvar rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,\n
+\t\tcells = rows,\n
+\t\tel = $( this ),\n
+\t\tmode = $.effects.setMode( el, o.mode || "hide" ),\n
+\t\tshow = mode === "show",\n
+\n
+\t\t// show and then visibility:hidden the element before calculating offset\n
+\t\toffset = el.show().css( "visibility", "hidden" ).offset(),\n
+\n
+\t\t// width and height of a piece\n
+\t\twidth = Math.ceil( el.outerWidth() / cells ),\n
+\t\theight = Math.ceil( el.outerHeight() / rows ),\n
+\t\tpieces = [],\n
+\n
+\t\t// loop\n
+\t\ti, j, left, top, mx, my;\n
+\n
+\t// children animate complete:\n
+\tfunction childComplete() {\n
+\t\tpieces.push( this );\n
+\t\tif ( pieces.length === rows * cells ) {\n
+\t\t\tanimComplete();\n
+\t\t}\n
+\t}\n
+\n
+\t// clone the element for each row and cell.\n
+\tfor( i = 0; i < rows ; i++ ) { // ===>\n
+\t\ttop = offset.top + i * height;\n
+\t\tmy = i - ( rows - 1 ) / 2 ;\n
+\n
+\t\tfor( j = 0; j < cells ; j++ ) { // |||\n
+\t\t\tleft = offset.left + j * width;\n
+\t\t\tmx = j - ( cells - 1 ) / 2 ;\n
+\n
+\t\t\t// Create a clone of the now hidden main element that will be absolute positioned\n
+\t\t\t// within a wrapper div off the -left and -top equal to size of our pieces\n
+\t\t\tel\n
+\t\t\t\t.clone()\n
+\t\t\t\t.appendTo( "body" )\n
+\t\t\t\t.wrap( "<div></div>" )\n
+\t\t\t\t.css({\n
+\t\t\t\t\tposition: "absolute",\n
+\t\t\t\t\tvisibility: "visible",\n
+\t\t\t\t\tleft: -j * width,\n
+\t\t\t\t\ttop: -i * height\n
+\t\t\t\t})\n
+\n
+\t\t\t// select the wrapper - make it overflow: hidden and absolute positioned based on\n
+\t\t\t// where the original was located +left and +top equal to the size of pieces\n
+\t\t\t\t.parent()\n
+\t\t\t\t.addClass( "ui-effects-explode" )\n
+\t\t\t\t.css({\n
+\t\t\t\t\tposition: "absolute",\n
+\t\t\t\t\toverflow: "hidden",\n
+\t\t\t\t\twidth: width,\n
+\t\t\t\t\theight: height,\n
+\t\t\t\t\tleft: left + ( show ? mx * width : 0 ),\n
+\t\t\t\t\ttop: top + ( show ? my * height : 0 ),\n
+\t\t\t\t\topacity: show ? 0 : 1\n
+\t\t\t\t}).animate({\n
+\t\t\t\t\tleft: left + ( show ? 0 : mx * width ),\n
+\t\t\t\t\ttop: top + ( show ? 0 : my * height ),\n
+\t\t\t\t\topacity: show ? 1 : 0\n
+\t\t\t\t}, o.duration || 500, o.easing, childComplete );\n
+\t\t}\n
+\t}\n
+\n
+\tfunction animComplete() {\n
+\t\tel.css({\n
+\t\t\tvisibility: "visible"\n
+\t\t});\n
+\t\t$( pieces ).remove();\n
+\t\tif ( !show ) {\n
+\t\t\tel.hide();\n
+\t\t}\n
+\t\tdone();\n
+\t}\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.fade = function( o, done ) {\n
+\tvar el = $( this ),\n
+\t\tmode = $.effects.setMode( el, o.mode || "toggle" );\n
+\n
+\tel.animate({\n
+\t\topacity: mode\n
+\t}, {\n
+\t\tqueue: false,\n
+\t\tduration: o.duration,\n
+\t\teasing: o.easing,\n
+\t\tcomplete: done\n
+\t});\n
+};\n
+\n
+})( jQuery );\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.fold = function( o, done ) {\n
+\n
+\t// Create element\n
+\tvar el = $( this ),\n
+\t\tprops = [ "position", "top", "bottom", "left", "right", "height", "width" ],\n
+\t\tmode = $.effects.setMode( el, o.mode || "hide" ),\n
+\t\tshow = mode === "show",\n
+\t\thide = mode === "hide",\n
+\t\tsize = o.size || 15,\n
+\t\tpercent = /([0-9]+)%/.exec( size ),\n
+\t\thorizFirst = !!o.horizFirst,\n
+\t\twidthFirst = show !== horizFirst,\n
+\t\tref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],\n
+\t\tduration = o.duration / 2,\n
+\t\twrapper, distance,\n
+\t\tanimation1 = {},\n
+\t\tanimation2 = {};\n
+\n
+\t$.effects.save( el, props );\n
+\tel.show();\n
+\n
+\t// Create Wrapper\n
+\twrapper = $.effects.createWrapper( el ).css({\n
+\t\toverflow: "hidden"\n
+\t});\n
+\tdistance = widthFirst ?\n
+\t\t[ wrapper.width(), wrapper.height() ] :\n
+\t\t[ wrapper.height(), wrapper.width() ];\n
+\n
+\tif ( percent ) {\n
+\t\tsize = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];\n
+\t}\n
+\tif ( show ) {\n
+\t\twrapper.css( horizFirst ? {\n
+\t\t\theight: 0,\n
+\t\t\twidth: size\n
+\t\t} : {\n
+\t\t\theight: size,\n
+\t\t\twidth: 0\n
+\t\t});\n
+\t}\n
+\n
+\t// Animation\n
+\tanimation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;\n
+\tanimation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;\n
+\n
+\t// Animate\n
+\twrapper\n
+\t\t.animate( animation1, duration, o.easing )\n
+\t\t.animate( animation2, duration, o.easing, function() {\n
+\t\t\tif ( hide ) {\n
+\t\t\t\tel.hide();\n
+\t\t\t}\n
+\t\t\t$.effects.restore( el, props );\n
+\t\t\t$.effects.removeWrapper( el );\n
+\t\t\tdone();\n
+\t\t});\n
+\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.highlight = function( o, done ) {\n
+\tvar elem = $( this ),\n
+\t\tprops = [ "backgroundImage", "backgroundColor", "opacity" ],\n
+\t\tmode = $.effects.setMode( elem, o.mode || "show" ),\n
+\t\tanimation = {\n
+\t\t\tbackgroundColor: elem.css( "backgroundColor" )\n
+\t\t};\n
+\n
+\tif (mode === "hide") {\n
+\t\tanimation.opacity = 0;\n
+\t}\n
+\n
+\t$.effects.save( elem, props );\n
+\n
+\telem\n
+\t\t.show()\n
+\t\t.css({\n
+\t\t\tbackgroundImage: "none",\n
+\t\t\tbackgroundColor: o.color || "#ffff99"\n
+\t\t})\n
+\t\t.animate( animation, {\n
+\t\t\tqueue: false,\n
+\t\t\tduration: o.duration,\n
+\t\t\teasing: o.easing,\n
+\t\t\tcomplete: function() {\n
+\t\t\t\tif ( mode === "hide" ) {\n
+\t\t\t\t\telem.hide();\n
+\t\t\t\t}\n
+\t\t\t\t$.effects.restore( elem, props );\n
+\t\t\t\tdone();\n
+\t\t\t}\n
+\t\t});\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.pulsate = function( o, done ) {\n
+\tvar elem = $( this ),\n
+\t\tmode = $.effects.setMode( elem, o.mode || "show" ),\n
+\t\tshow = mode === "show",\n
+\t\thide = mode === "hide",\n
+\t\tshowhide = ( show || mode === "hide" ),\n
+\n
+\t\t// showing or hiding leaves of the "last" animation\n
+\t\tanims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),\n
+\t\tduration = o.duration / anims,\n
+\t\tanimateTo = 0,\n
+\t\tqueue = elem.queue(),\n
+\t\tqueuelen = queue.length,\n
+\t\ti;\n
+\n
+\tif ( show || !elem.is(":visible")) {\n
+\t\telem.css( "opacity", 0 ).show();\n
+\t\tanimateTo = 1;\n
+\t}\n
+\n
+\t// anims - 1 opacity "toggles"\n
+\tfor ( i = 1; i < anims; i++ ) {\n
+\t\telem.animate({\n
+\t\t\topacity: animateTo\n
+\t\t}, duration, o.easing );\n
+\t\tanimateTo = 1 - animateTo;\n
+\t}\n
+\n
+\telem.animate({\n
+\t\topacity: animateTo\n
+\t}, duration, o.easing);\n
+\n
+\telem.queue(function() {\n
+\t\tif ( hide ) {\n
+\t\t\telem.hide();\n
+\t\t}\n
+\t\tdone();\n
+\t});\n
+\n
+\t// We just queued up "anims" animations, we need to put them next in the queue\n
+\tif ( queuelen > 1 ) {\n
+\t\tqueue.splice.apply( queue,\n
+\t\t\t[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );\n
+\t}\n
+\telem.dequeue();\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.puff = function( o, done ) {\n
+\tvar elem = $( this ),\n
+\t\tmode = $.effects.setMode( elem, o.mode || "hide" ),\n
+\t\thide = mode === "hide",\n
+\t\tpercent = parseInt( o.percent, 10 ) || 150,\n
+\t\tfactor = percent / 100,\n
+\t\toriginal = {\n
+\t\t\theight: elem.height(),\n
+\t\t\twidth: elem.width(),\n
+\t\t\touterHeight: elem.outerHeight(),\n
+\t\t\touterWidth: elem.outerWidth()\n
+\t\t};\n
+\n
+\t$.extend( o, {\n
+\t\teffect: "scale",\n
+\t\tqueue: false,\n
+\t\tfade: true,\n
+\t\tmode: mode,\n
+\t\tcomplete: done,\n
+\t\tpercent: hide ? percent : 100,\n
+\t\tfrom: hide ?\n
+\t\t\toriginal :\n
+\t\t\t{\n
+\t\t\t\theight: original.height * factor,\n
+\t\t\t\twidth: original.width * factor,\n
+\t\t\t\touterHeight: original.outerHeight * factor,\n
+\t\t\t\touterWidth: original.outerWidth * factor\n
+\t\t\t}\n
+\t});\n
+\n
+\telem.effect( o );\n
+};\n
+\n
+$.effects.effect.scale = function( o, done ) {\n
+\n
+\t// Create element\n
+\tvar el = $( this ),\n
+\t\toptions = $.extend( true, {}, o ),\n
+\t\tmode = $.effects.setMode( el, o.mode || "effect" ),\n
+\t\tpercent = parseInt( o.percent, 10 ) ||\n
+\t\t\t( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),\n
+\t\tdirection = o.direction || "both",\n
+\t\torigin = o.origin,\n
+\t\toriginal = {\n
+\t\t\theight: el.height(),\n
+\t\t\twidth: el.width(),\n
+\t\t\touterHeight: el.outerHeight(),\n
+\t\t\touterWidth: el.outerWidth()\n
+\t\t},\n
+\t\tfactor = {\n
+\t\t\ty: direction !== "horizontal" ? (percent / 100) : 1,\n
+\t\t\tx: direction !== "vertical" ? (percent / 100) : 1\n
+\t\t};\n
+\n
+\t// We are going to pass this effect to the size effect:\n
+\toptions.effect = "size";\n
+\toptions.queue = false;\n
+\toptions.complete = done;\n
+\n
+\t// Set default origin and restore for show/hide\n
+\tif ( mode !== "effect" ) {\n
+\t\toptions.origin = origin || ["middle","center"];\n
+\t\toptions.restore = true;\n
+\t}\n
+\n
+\toptions.from = o.from || ( mode === "show" ? {\n
+\t\theight: 0,\n
+\t\twidth: 0,\n
+\t\touterHeight: 0,\n
+\t\touterWidth: 0\n
+\t} : original );\n
+\toptions.to = {\n
+\t\theight: original.height * factor.y,\n
+\t\twidth: original.width * factor.x,\n
+\t\touterHeight: original.outerHeight * factor.y,\n
+\t\touterWidth: original.outerWidth * factor.x\n
+\t};\n
+\n
+\t// Fade option to support puff\n
+\tif ( options.fade ) {\n
+\t\tif ( mode === "show" ) {\n
+\t\t\toptions.from.opacity = 0;\n
+\t\t\toptions.to.opacity = 1;\n
+\t\t}\n
+\t\tif ( mode === "hide" ) {\n
+\t\t\toptions.from.opacity = 1;\n
+\t\t\toptions.to.opacity = 0;\n
+\t\t}\n
+\t}\n
+\n
+\t// Animate\n
+\tel.effect( options );\n
+\n
+};\n
+\n
+$.effects.effect.size = function( o, done ) {\n
+\n
+\t// Create element\n
+\tvar original, baseline, factor,\n
+\t\tel = $( this ),\n
+\t\tprops0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],\n
+\n
+\t\t// Always restore\n
+\t\tprops1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],\n
+\n
+\t\t// Copy for children\n
+\t\tprops2 = [ "width", "height", "overflow" ],\n
+\t\tcProps = [ "fontSize" ],\n
+\t\tvProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],\n
+\t\thProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],\n
+\n
+\t\t// Set options\n
+\t\tmode = $.effects.setMode( el, o.mode || "effect" ),\n
+\t\trestore = o.restore || mode !== "effect",\n
+\t\tscale = o.scale || "both",\n
+\t\torigin = o.origin || [ "middle", "center" ],\n
+\t\tposition = el.css( "position" ),\n
+\t\tprops = restore ? props0 : props1,\n
+\t\tzero = {\n
+\t\t\theight: 0,\n
+\t\t\twidth: 0,\n
+\t\t\touterHeight: 0,\n
+\t\t\touterWidth: 0\n
+\t\t};\n
+\n
+\tif ( mode === "show" ) {\n
+\t\tel.show();\n
+\t}\n
+\toriginal = {\n
+\t\theight: el.height(),\n
+\t\twidth: el.width(),\n
+\t\touterHeight: el.outerHeight(),\n
+\t\touterWidth: el.outerWidth()\n
+\t};\n
+\n
+\tif ( o.mode === "toggle" && mode === "show" ) {\n
+\t\tel.from = o.to || zero;\n
+\t\tel.to = o.from || original;\n
+\t} else {\n
+\t\tel.from = o.from || ( mode === "show" ? zero : original );\n
+\t\tel.to = o.to || ( mode === "hide" ? zero : original );\n
+\t}\n
+\n
+\t// Set scaling factor\n
+\tfactor = {\n
+\t\tfrom: {\n
+\t\t\ty: el.from.height / original.height,\n
+\t\t\tx: el.from.width / original.width\n
+\t\t},\n
+\t\tto: {\n
+\t\t\ty: el.to.height / original.height,\n
+\t\t\tx: el.to.width / original.width\n
+\t\t}\n
+\t};\n
+\n
+\t// Scale the css box\n
+\tif ( scale === "box" || scale === "both" ) {\n
+\n
+\t\t// Vertical props scaling\n
+\t\tif ( factor.from.y !== factor.to.y ) {\n
+\t\t\tprops = props.concat( vProps );\n
+\t\t\tel.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );\n
+\t\t\tel.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );\n
+\t\t}\n
+\n
+\t\t// Horizontal props scaling\n
+\t\tif ( factor.from.x !== factor.to.x ) {\n
+\t\t\tprops = props.concat( hProps );\n
+\t\t\tel.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );\n
+\t\t\tel.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );\n
+\t\t}\n
+\t}\n
+\n
+\t// Scale the content\n
+\tif ( scale === "content" || scale === "both" ) {\n
+\n
+\t\t// Vertical props scaling\n
+\t\tif ( factor.from.y !== factor.to.y ) {\n
+\t\t\tprops = props.concat( cProps ).concat( props2 );\n
+\t\t\tel.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );\n
+\t\t\tel.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );\n
+\t\t}\n
+\t}\n
+\n
+\t$.effects.save( el, props );\n
+\tel.show();\n
+\t$.effects.createWrapper( el );\n
+\tel.css( "overflow", "hidden" ).css( el.from );\n
+\n
+\t// Adjust\n
+\tif (origin) { // Calculate baseline shifts\n
+\t\tbaseline = $.effects.getBaseline( origin, original );\n
+\t\tel.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;\n
+\t\tel.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;\n
+\t\tel.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;\n
+\t\tel.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;\n
+\t}\n
+\tel.css( el.from ); // set top & left\n
+\n
+\t// Animate\n
+\tif ( scale === "content" || scale === "both" ) { // Scale the children\n
+\n
+\t\t// Add margins/font-size\n
+\t\tvProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);\n
+\t\thProps = hProps.concat([ "marginLeft", "marginRight" ]);\n
+\t\tprops2 = props0.concat(vProps).concat(hProps);\n
+\n
+\t\tel.find( "*[width]" ).each( function(){\n
+\t\t\tvar child = $( this ),\n
+\t\t\t\tc_original = {\n
+\t\t\t\t\theight: child.height(),\n
+\t\t\t\t\twidth: child.width(),\n
+\t\t\t\t\touterHeight: child.outerHeight(),\n
+\t\t\t\t\touterWidth: child.outerWidth()\n
+\t\t\t\t};\n
+\t\t\tif (restore) {\n
+\t\t\t\t$.effects.save(child, props2);\n
+\t\t\t}\n
+\n
+\t\t\tchild.from = {\n
+\t\t\t\theight: c_original.height * factor.from.y,\n
+\t\t\t\twidth: c_original.width * factor.from.x,\n
+\t\t\t\touterHeight: c_original.outerHeight * factor.from.y,\n
+\t\t\t\touterWidth: c_original.outerWidth * factor.from.x\n
+\t\t\t};\n
+\t\t\tchild.to = {\n
+\t\t\t\theight: c_original.height * factor.to.y,\n
+\t\t\t\twidth: c_original.width * factor.to.x,\n
+\t\t\t\touterHeight: c_original.height * factor.to.y,\n
+\t\t\t\touterWidth: c_original.width * factor.to.x\n
+\t\t\t};\n
+\n
+\t\t\t// Vertical props scaling\n
+\t\t\tif ( factor.from.y !== factor.to.y ) {\n
+\t\t\t\tchild.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );\n
+\t\t\t\tchild.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );\n
+\t\t\t}\n
+\n
+\t\t\t// Horizontal props scaling\n
+\t\t\tif ( factor.from.x !== factor.to.x ) {\n
+\t\t\t\tchild.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );\n
+\t\t\t\tchild.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );\n
+\t\t\t}\n
+\n
+\t\t\t// Animate children\n
+\t\t\tchild.css( child.from );\n
+\t\t\tchild.animate( child.to, o.duration, o.easing, function() {\n
+\n
+\t\t\t\t// Restore children\n
+\t\t\t\tif ( restore ) {\n
+\t\t\t\t\t$.effects.restore( child, props2 );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t});\n
+\t}\n
+\n
+\t// Animate\n
+\tel.animate( el.to, {\n
+\t\tqueue: false,\n
+\t\tduration: o.duration,\n
+\t\teasing: o.easing,\n
+\t\tcomplete: function() {\n
+\t\t\tif ( el.to.opacity === 0 ) {\n
+\t\t\t\tel.css( "opacity", el.from.opacity );\n
+\t\t\t}\n
+\t\t\tif( mode === "hide" ) {\n
+\t\t\t\tel.hide();\n
+\t\t\t}\n
+\t\t\t$.effects.restore( el, props );\n
+\t\t\tif ( !restore ) {\n
+\n
+\t\t\t\t// we need to calculate our new positioning based on the scaling\n
+\t\t\t\tif ( position === "static" ) {\n
+\t\t\t\t\tel.css({\n
+\t\t\t\t\t\tposition: "relative",\n
+\t\t\t\t\t\ttop: el.to.top,\n
+\t\t\t\t\t\tleft: el.to.left\n
+\t\t\t\t\t});\n
+\t\t\t\t} else {\n
+\t\t\t\t\t$.each([ "top", "left" ], function( idx, pos ) {\n
+\t\t\t\t\t\tel.css( pos, function( _, str ) {\n
+\t\t\t\t\t\t\tvar val = parseInt( str, 10 ),\n
+\t\t\t\t\t\t\t\ttoRef = idx ? el.to.left : el.to.top;\n
+\n
+\t\t\t\t\t\t\t// if original was "auto", recalculate the new value from wrapper\n
+\t\t\t\t\t\t\tif ( str === "auto" ) {\n
+\t\t\t\t\t\t\t\treturn toRef + "px";\n
+\t\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\t\treturn val + toRef + "px";\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t});\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t$.effects.removeWrapper( el );\n
+\t\t\tdone();\n
+\t\t}\n
+\t});\n
+\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.shake = function( o, done ) {\n
+\n
+\tvar el = $( this ),\n
+\t\tprops = [ "position", "top", "bottom", "left", "right", "height", "width" ],\n
+\t\tmode = $.effects.setMode( el, o.mode || "effect" ),\n
+\t\tdirection = o.direction || "left",\n
+\t\tdistance = o.distance || 20,\n
+\t\ttimes = o.times || 3,\n
+\t\tanims = times * 2 + 1,\n
+\t\tspeed = Math.round(o.duration/anims),\n
+\t\tref = (direction === "up" || direction === "down") ? "top" : "left",\n
+\t\tpositiveMotion = (direction === "up" || direction === "left"),\n
+\t\tanimation = {},\n
+\t\tanimation1 = {},\n
+\t\tanimation2 = {},\n
+\t\ti,\n
+\n
+\t\t// we will need to re-assemble the queue to stack our animations in place\n
+\t\tqueue = el.queue(),\n
+\t\tqueuelen = queue.length;\n
+\n
+\t$.effects.save( el, props );\n
+\tel.show();\n
+\t$.effects.createWrapper( el );\n
+\n
+\t// Animation\n
+\tanimation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;\n
+\tanimation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;\n
+\tanimation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;\n
+\n
+\t// Animate\n
+\tel.animate( animation, speed, o.easing );\n
+\n
+\t// Shakes\n
+\tfor ( i = 1; i < times; i++ ) {\n
+\t\tel.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );\n
+\t}\n
+\tel\n
+\t\t.animate( animation1, speed, o.easing )\n
+\t\t.animate( animation, speed / 2, o.easing )\n
+\t\t.queue(function() {\n
+\t\t\tif ( mode === "hide" ) {\n
+\t\t\t\tel.hide();\n
+\t\t\t}\n
+\t\t\t$.effects.restore( el, props );\n
+\t\t\t$.effects.removeWrapper( el );\n
+\t\t\tdone();\n
+\t\t});\n
+\n
+\t// inject all the animations we just queued to be first in line (after "inprogress")\n
+\tif ( queuelen > 1) {\n
+\t\tqueue.splice.apply( queue,\n
+\t\t\t[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );\n
+\t}\n
+\tel.dequeue();\n
+\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.slide = function( o, done ) {\n
+\n
+\t// Create element\n
+\tvar el = $( this ),\n
+\t\tprops = [ "position", "top", "bottom", "left", "right", "width", "height" ],\n
+\t\tmode = $.effects.setMode( el, o.mode || "show" ),\n
+\t\tshow = mode === "show",\n
+\t\tdirection = o.direction || "left",\n
+\t\tref = (direction === "up" || direction === "down") ? "top" : "left",\n
+\t\tpositiveMotion = (direction === "up" || direction === "left"),\n
+\t\tdistance,\n
+\t\tanimation = {};\n
+\n
+\t// Adjust\n
+\t$.effects.save( el, props );\n
+\tel.show();\n
+\tdistance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );\n
+\n
+\t$.effects.createWrapper( el ).css({\n
+\t\toverflow: "hidden"\n
+\t});\n
+\n
+\tif ( show ) {\n
+\t\tel.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );\n
+\t}\n
+\n
+\t// Animation\n
+\tanimation[ ref ] = ( show ?\n
+\t\t( positiveMotion ? "+=" : "-=") :\n
+\t\t( positiveMotion ? "-=" : "+=")) +\n
+\t\tdistance;\n
+\n
+\t// Animate\n
+\tel.animate( animation, {\n
+\t\tqueue: false,\n
+\t\tduration: o.duration,\n
+\t\teasing: o.easing,\n
+\t\tcomplete: function() {\n
+\t\t\tif ( mode === "hide" ) {\n
+\t\t\t\tel.hide();\n
+\t\t\t}\n
+\t\t\t$.effects.restore( el, props );\n
+\t\t\t$.effects.removeWrapper( el );\n
+\t\t\tdone();\n
+\t\t}\n
+\t});\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.effects.effect.transfer = function( o, done ) {\n
+\tvar elem = $( this ),\n
+\t\ttarget = $( o.to ),\n
+\t\ttargetFixed = target.css( "position" ) === "fixed",\n
+\t\tbody = $("body"),\n
+\t\tfixTop = targetFixed ? body.scrollTop() : 0,\n
+\t\tfixLeft = targetFixed ? body.scrollLeft() : 0,\n
+\t\tendPosition = target.offset(),\n
+\t\tanimation = {\n
+\t\t\ttop: endPosition.top - fixTop ,\n
+\t\t\tleft: endPosition.left - fixLeft ,\n
+\t\t\theight: target.innerHeight(),\n
+\t\t\twidth: target.innerWidth()\n
+\t\t},\n
+\t\tstartPosition = elem.offset(),\n
+\t\ttransfer = $( "<div class=\'ui-effects-transfer\'></div>" )\n
+\t\t\t.appendTo( document.body )\n
+\t\t\t.addClass( o.className )\n
+\t\t\t.css({\n
+\t\t\t\ttop: startPosition.top - fixTop ,\n
+\t\t\t\tleft: startPosition.left - fixLeft ,\n
+\t\t\t\theight: elem.innerHeight(),\n
+\t\t\t\twidth: elem.innerWidth(),\n
+\t\t\t\tposition: targetFixed ? "fixed" : "absolute"\n
+\t\t\t})\n
+\t\t\t.animate( animation, o.duration, o.easing, function() {\n
+\t\t\t\ttransfer.remove();\n
+\t\t\t\tdone();\n
+\t\t\t});\n
+};\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.widget( "ui.menu", {\n
+\tversion: "1.10.4",\n
+\tdefaultElement: "<ul>",\n
+\tdelay: 300,\n
+\toptions: {\n
+\t\ticons: {\n
+\t\t\tsubmenu: "ui-icon-carat-1-e"\n
+\t\t},\n
+\t\tmenus: "ul",\n
+\t\tposition: {\n
+\t\t\tmy: "left top",\n
+\t\t\tat: "right top"\n
+\t\t},\n
+\t\trole: "menu",\n
+\n
+\t\t// callbacks\n
+\t\tblur: null,\n
+\t\tfocus: null,\n
+\t\tselect: null\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tthis.activeMenu = this.element;\n
+\t\t// flag used to prevent firing of the click handler\n
+\t\t// as the event bubbles up through nested menus\n
+\t\tthis.mouseHandled = false;\n
+\t\tthis.element\n
+\t\t\t.uniqueId()\n
+\t\t\t.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )\n
+\t\t\t.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )\n
+\t\t\t.attr({\n
+\t\t\t\trole: this.options.role,\n
+\t\t\t\ttabIndex: 0\n
+\t\t\t})\n
+\t\t\t// need to catch all clicks on disabled menu\n
+\t\t\t// not possible through _on\n
+\t\t\t.bind( "click" + this.eventNamespace, $.proxy(function( event ) {\n
+\t\t\t\tif ( this.options.disabled ) {\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t}\n
+\t\t\t}, this ));\n
+\n
+\t\tif ( this.options.disabled ) {\n
+\t\t\tthis.element\n
+\t\t\t\t.addClass( "ui-state-disabled" )\n
+\t\t\t\t.attr( "aria-disabled", "true" );\n
+\t\t}\n
+\n
+\t\tthis._on({\n
+\t\t\t// Prevent focus from sticking to links inside menu after clicking\n
+\t\t\t// them (focus should always stay on UL during navigation).\n
+\t\t\t"mousedown .ui-menu-item > a": function( event ) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t},\n
+\t\t\t"click .ui-state-disabled > a": function( event ) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t},\n
+\t\t\t"click .ui-menu-item:has(a)": function( event ) {\n
+\t\t\t\tvar target = $( event.target ).closest( ".ui-menu-item" );\n
+\t\t\t\tif ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {\n
+\t\t\t\t\tthis.select( event );\n
+\n
+\t\t\t\t\t// Only set the mouseHandled flag if the event will bubble, see #9469.\n
+\t\t\t\t\tif ( !event.isPropagationStopped() ) {\n
+\t\t\t\t\t\tthis.mouseHandled = true;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// Open submenu on click\n
+\t\t\t\t\tif ( target.has( ".ui-menu" ).length ) {\n
+\t\t\t\t\t\tthis.expand( event );\n
+\t\t\t\t\t} else if ( !this.element.is( ":focus" ) && $( this.document[ 0 ].activeElement ).closest( ".ui-menu" ).length ) {\n
+\n
+\t\t\t\t\t\t// Redirect focus to the menu\n
+\t\t\t\t\t\tthis.element.trigger( "focus", [ true ] );\n
+\n
+\t\t\t\t\t\t// If the active item is on the top level, let it stay active.\n
+\t\t\t\t\t\t// Otherwise, blur the active item since it is no longer visible.\n
+\t\t\t\t\t\tif ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {\n
+\t\t\t\t\t\t\tclearTimeout( this.timer );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\t"mouseenter .ui-menu-item": function( event ) {\n
+\t\t\t\tvar target = $( event.currentTarget );\n
+\t\t\t\t// Remove ui-state-active class from siblings of the newly focused menu item\n
+\t\t\t\t// to avoid a jump caused by adjacent elements both having a class with a border\n
+\t\t\t\ttarget.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );\n
+\t\t\t\tthis.focus( event, target );\n
+\t\t\t},\n
+\t\t\tmouseleave: "collapseAll",\n
+\t\t\t"mouseleave .ui-menu": "collapseAll",\n
+\t\t\tfocus: function( event, keepActiveItem ) {\n
+\t\t\t\t// If there\'s already an active item, keep it active\n
+\t\t\t\t// If not, activate the first item\n
+\t\t\t\tvar item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );\n
+\n
+\t\t\t\tif ( !keepActiveItem ) {\n
+\t\t\t\t\tthis.focus( event, item );\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tblur: function( event ) {\n
+\t\t\t\tthis._delay(function() {\n
+\t\t\t\t\tif ( !$.contains( this.element[0], this.document[0].activeElement ) ) {\n
+\t\t\t\t\t\tthis.collapseAll( event );\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t},\n
+\t\t\tkeydown: "_keydown"\n
+\t\t});\n
+\n
+\t\tthis.refresh();\n
+\n
+\t\t// Clicks outside of a menu collapse any open menus\n
+\t\tthis._on( this.document, {\n
+\t\t\tclick: function( event ) {\n
+\t\t\t\tif ( !$( event.target ).closest( ".ui-menu" ).length ) {\n
+\t\t\t\t\tthis.collapseAll( event );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Reset the mouseHandled flag\n
+\t\t\t\tthis.mouseHandled = false;\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\t// Destroy (sub)menus\n
+\t\tthis.element\n
+\t\t\t.removeAttr( "aria-activedescendant" )\n
+\t\t\t.find( ".ui-menu" ).addBack()\n
+\t\t\t\t.removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )\n
+\t\t\t\t.removeAttr( "role" )\n
+\t\t\t\t.removeAttr( "tabIndex" )\n
+\t\t\t\t.removeAttr( "aria-labelledby" )\n
+\t\t\t\t.removeAttr( "aria-expanded" )\n
+\t\t\t\t.removeAttr( "aria-hidden" )\n
+\t\t\t\t.removeAttr( "aria-disabled" )\n
+\t\t\t\t.removeUniqueId()\n
+\t\t\t\t.show();\n
+\n
+\t\t// Destroy menu items\n
+\t\tthis.element.find( ".ui-menu-item" )\n
+\t\t\t.removeClass( "ui-menu-item" )\n
+\t\t\t.removeAttr( "role" )\n
+\t\t\t.removeAttr( "aria-disabled" )\n
+\t\t\t.children( "a" )\n
+\t\t\t\t.removeUniqueId()\n
+\t\t\t\t.removeClass( "ui-corner-all ui-state-hover" )\n
+\t\t\t\t.removeAttr( "tabIndex" )\n
+\t\t\t\t.removeAttr( "role" )\n
+\t\t\t\t.removeAttr( "aria-haspopup" )\n
+\t\t\t\t.children().each( function() {\n
+\t\t\t\t\tvar elem = $( this );\n
+\t\t\t\t\tif ( elem.data( "ui-menu-submenu-carat" ) ) {\n
+\t\t\t\t\t\telem.remove();\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\n
+\t\t// Destroy menu dividers\n
+\t\tthis.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );\n
+\t},\n
+\n
+\t_keydown: function( event ) {\n
+\t\tvar match, prev, character, skip, regex,\n
+\t\t\tpreventDefault = true;\n
+\n
+\t\tfunction escape( value ) {\n
+\t\t\treturn value.replace( /[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, "\\\\$&" );\n
+\t\t}\n
+\n
+\t\tswitch ( event.keyCode ) {\n
+\t\tcase $.ui.keyCode.PAGE_UP:\n
+\t\t\tthis.previousPage( event );\n
+\t\t\tbreak;\n
+\t\tcase $.ui.keyCode.PAGE_DOWN:\n
+\t\t\tthis.nextPage( event );\n
+\t\t\tbreak;\n
+\t\tcase $.ui.keyCode.HOME:\n
+\t\t\tthis._move( "first", "first", event );\n
+\t\t\tbreak;\n
+\t\tcase $.ui.keyCode.END:\n
+\t\t\tthis._move( "last", "last", event );\n
+\t\t\tbreak;\n
+\t\tcase $.ui.keyCode.UP:\n
+\t\t\tthis.previous( event );\n
+\t\t\tbreak;\n
+\t\tcase $.ui.keyCode.DOWN:\n
+\t\t\tthis.next( event );\n
+\t\t\tbreak;\n
+\t\tcase $.ui.keyCode.LEFT:\n
+\t\t\tthis.collapse( event );\n
+\t\t\tbreak;\n
+\t\tcase $.ui.keyCode.RIGHT:\n
+\t\t\tif ( this.active && !this.active.is( ".ui-state-disabled" ) ) {\n
+\t\t\t\tthis.expand( event );\n
+\t\t\t}\n
+\t\t\tbreak;\n
+\t\tcase $.ui.keyCode.ENTER:\n
+\t\tcase $.ui.keyCode.SPACE:\n
+\t\t\tthis._activate( event );\n
+\t\t\tbreak;\n
+\t\tcase $.ui.keyCode.ESCAPE:\n
+\t\t\tthis.collapse( event );\n
+\t\t\tbreak;\n
+\t\tdefault:\n
+\t\t\tpreventDefault = false;\n
+\t\t\tprev = this.previousFilter || "";\n
+\t\t\tcharacter = String.fromCharCode( event.keyCode );\n
+\t\t\tskip = false;\n
+\n
+\t\t\tclearTimeout( this.filterTimer );\n
+\n
+\t\t\tif ( character === prev ) {\n
+\t\t\t\tskip = true;\n
+\t\t\t} else {\n
+\t\t\t\tcharacter = prev + character;\n
+\t\t\t}\n
+\n
+\t\t\tregex = new RegExp( "^" + escape( character ), "i" );\n
+\t\t\tmatch = this.activeMenu.children( ".ui-menu-item" ).filter(function() {\n
+\t\t\t\treturn regex.test( $( this ).children( "a" ).text() );\n
+\t\t\t});\n
+\t\t\tmatch = skip && match.index( this.active.next() ) !== -1 ?\n
+\t\t\t\tthis.active.nextAll( ".ui-menu-item" ) :\n
+\t\t\t\tmatch;\n
+\n
+\t\t\t// If no matches on the current filter, reset to the last character pressed\n
+\t\t\t// to move down the menu to the first item that starts with that character\n
+\t\t\tif ( !match.length ) {\n
+\t\t\t\tcharacter = String.fromCharCode( event.keyCode );\n
+\t\t\t\tregex = new RegExp( "^" + escape( character ), "i" );\n
+\t\t\t\tmatch = this.activeMenu.children( ".ui-menu-item" ).filter(function() {\n
+\t\t\t\t\treturn regex.test( $( this ).children( "a" ).text() );\n
+\t\t\t\t});\n
+\t\t\t}\n
+\n
+\t\t\tif ( match.length ) {\n
+\t\t\t\tthis.focus( event, match );\n
+\t\t\t\tif ( match.length > 1 ) {\n
+\t\t\t\t\tthis.previousFilter = character;\n
+\t\t\t\t\tthis.filterTimer = this._delay(function() {\n
+\t\t\t\t\t\tdelete this.previousFilter;\n
+\t\t\t\t\t}, 1000 );\n
+\t\t\t\t} else {\n
+\t\t\t\t\tdelete this.previousFilter;\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\tdelete this.previousFilter;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( preventDefault ) {\n
+\t\t\tevent.preventDefault();\n
+\t\t}\n
+\t},\n
+\n
+\t_activate: function( event ) {\n
+\t\tif ( !this.active.is( ".ui-state-disabled" ) ) {\n
+\t\t\tif ( this.active.children( "a[aria-haspopup=\'true\']" ).length ) {\n
+\t\t\t\tthis.expand( event );\n
+\t\t\t} else {\n
+\t\t\t\tthis.select( event );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tvar menus,\n
+\t\t\ticon = this.options.icons.submenu,\n
+\t\t\tsubmenus = this.element.find( this.options.menus );\n
+\n
+\t\tthis.element.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length );\n
+\n
+\t\t// Initialize nested menus\n
+\t\tsubmenus.filter( ":not(.ui-menu)" )\n
+\t\t\t.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )\n
+\t\t\t.hide()\n
+\t\t\t.attr({\n
+\t\t\t\trole: this.options.role,\n
+\t\t\t\t"aria-hidden": "true",\n
+\t\t\t\t"aria-expanded": "false"\n
+\t\t\t})\n
+\t\t\t.each(function() {\n
+\t\t\t\tvar menu = $( this ),\n
+\t\t\t\t\titem = menu.prev( "a" ),\n
+\t\t\t\t\tsubmenuCarat = $( "<span>" )\n
+\t\t\t\t\t\t.addClass( "ui-menu-icon ui-icon " + icon )\n
+\t\t\t\t\t\t.data( "ui-menu-submenu-carat", true );\n
+\n
+\t\t\t\titem\n
+\t\t\t\t\t.attr( "aria-haspopup", "true" )\n
+\t\t\t\t\t.prepend( submenuCarat );\n
+\t\t\t\tmenu.attr( "aria-labelledby", item.attr( "id" ) );\n
+\t\t\t});\n
+\n
+\t\tmenus = submenus.add( this.element );\n
+\n
+\t\t// Don\'t refresh list items that are already adapted\n
+\t\tmenus.children( ":not(.ui-menu-item):has(a)" )\n
+\t\t\t.addClass( "ui-menu-item" )\n
+\t\t\t.attr( "role", "presentation" )\n
+\t\t\t.children( "a" )\n
+\t\t\t\t.uniqueId()\n
+\t\t\t\t.addClass( "ui-corner-all" )\n
+\t\t\t\t.attr({\n
+\t\t\t\t\ttabIndex: -1,\n
+\t\t\t\t\trole: this._itemRole()\n
+\t\t\t\t});\n
+\n
+\t\t// Initialize unlinked menu-items containing spaces and/or dashes only as dividers\n
+\t\tmenus.children( ":not(.ui-menu-item)" ).each(function() {\n
+\t\t\tvar item = $( this );\n
+\t\t\t// hyphen, em dash, en dash\n
+\t\t\tif ( !/[^\\-\\u2014\\u2013\\s]/.test( item.text() ) ) {\n
+\t\t\t\titem.addClass( "ui-widget-content ui-menu-divider" );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\t// Add aria-disabled attribute to any disabled menu item\n
+\t\tmenus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );\n
+\n
+\t\t// If the active item has been removed, blur the menu\n
+\t\tif ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {\n
+\t\t\tthis.blur();\n
+\t\t}\n
+\t},\n
+\n
+\t_itemRole: function() {\n
+\t\treturn {\n
+\t\t\tmenu: "menuitem",\n
+\t\t\tlistbox: "option"\n
+\t\t}[ this.options.role ];\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tif ( key === "icons" ) {\n
+\t\t\tthis.element.find( ".ui-menu-icon" )\n
+\t\t\t\t.removeClass( this.options.icons.submenu )\n
+\t\t\t\t.addClass( value.submenu );\n
+\t\t}\n
+\t\tthis._super( key, value );\n
+\t},\n
+\n
+\tfocus: function( event, item ) {\n
+\t\tvar nested, focused;\n
+\t\tthis.blur( event, event && event.type === "focus" );\n
+\n
+\t\tthis._scrollIntoView( item );\n
+\n
+\t\tthis.active = item.first();\n
+\t\tfocused = this.active.children( "a" ).addClass( "ui-state-focus" );\n
+\t\t// Only update aria-activedescendant if there\'s a role\n
+\t\t// otherwise we assume focus is managed elsewhere\n
+\t\tif ( this.options.role ) {\n
+\t\t\tthis.element.attr( "aria-activedescendant", focused.attr( "id" ) );\n
+\t\t}\n
+\n
+\t\t// Highlight active parent menu item, if any\n
+\t\tthis.active\n
+\t\t\t.parent()\n
+\t\t\t.closest( ".ui-menu-item" )\n
+\t\t\t.children( "a:first" )\n
+\t\t\t.addClass( "ui-state-active" );\n
+\n
+\t\tif ( event && event.type === "keydown" ) {\n
+\t\t\tthis._close();\n
+\t\t} else {\n
+\t\t\tthis.timer = this._delay(function() {\n
+\t\t\t\tthis._close();\n
+\t\t\t}, this.delay );\n
+\t\t}\n
+\n
+\t\tnested = item.children( ".ui-menu" );\n
+\t\tif ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {\n
+\t\t\tthis._startOpening(nested);\n
+\t\t}\n
+\t\tthis.activeMenu = item.parent();\n
+\n
+\t\tthis._trigger( "focus", event, { item: item } );\n
+\t},\n
+\n
+\t_scrollIntoView: function( item ) {\n
+\t\tvar borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;\n
+\t\tif ( this._hasScroll() ) {\n
+\t\t\tborderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;\n
+\t\t\tpaddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;\n
+\t\t\toffset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;\n
+\t\t\tscroll = this.activeMenu.scrollTop();\n
+\t\t\telementHeight = this.activeMenu.height();\n
+\t\t\titemHeight = item.height();\n
+\n
+\t\t\tif ( offset < 0 ) {\n
+\t\t\t\tthis.activeMenu.scrollTop( scroll + offset );\n
+\t\t\t} else if ( offset + itemHeight > elementHeight ) {\n
+\t\t\t\tthis.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\tblur: function( event, fromFocus ) {\n
+\t\tif ( !fromFocus ) {\n
+\t\t\tclearTimeout( this.timer );\n
+\t\t}\n
+\n
+\t\tif ( !this.active ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis.active.children( "a" ).removeClass( "ui-state-focus" );\n
+\t\tthis.active = null;\n
+\n
+\t\tthis._trigger( "blur", event, { item: this.active } );\n
+\t},\n
+\n
+\t_startOpening: function( submenu ) {\n
+\t\tclearTimeout( this.timer );\n
+\n
+\t\t// Don\'t open if already open fixes a Firefox bug that caused a .5 pixel\n
+\t\t// shift in the submenu position when mousing over the carat icon\n
+\t\tif ( submenu.attr( "aria-hidden" ) !== "true" ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis.timer = this._delay(function() {\n
+\t\t\tthis._close();\n
+\t\t\tthis._open( submenu );\n
+\t\t}, this.delay );\n
+\t},\n
+\n
+\t_open: function( submenu ) {\n
+\t\tvar position = $.extend({\n
+\t\t\tof: this.active\n
+\t\t}, this.options.position );\n
+\n
+\t\tclearTimeout( this.timer );\n
+\t\tthis.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )\n
+\t\t\t.hide()\n
+\t\t\t.attr( "aria-hidden", "true" );\n
+\n
+\t\tsubmenu\n
+\t\t\t.show()\n
+\t\t\t.removeAttr( "aria-hidden" )\n
+\t\t\t.attr( "aria-expanded", "true" )\n
+\t\t\t.position( position );\n
+\t},\n
+\n
+\tcollapseAll: function( event, all ) {\n
+\t\tclearTimeout( this.timer );\n
+\t\tthis.timer = this._delay(function() {\n
+\t\t\t// If we were passed an event, look for the submenu that contains the event\n
+\t\t\tvar currentMenu = all ? this.element :\n
+\t\t\t\t$( event && event.target ).closest( this.element.find( ".ui-menu" ) );\n
+\n
+\t\t\t// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway\n
+\t\t\tif ( !currentMenu.length ) {\n
+\t\t\t\tcurrentMenu = this.element;\n
+\t\t\t}\n
+\n
+\t\t\tthis._close( currentMenu );\n
+\n
+\t\t\tthis.blur( event );\n
+\t\t\tthis.activeMenu = currentMenu;\n
+\t\t}, this.delay );\n
+\t},\n
+\n
+\t// With no arguments, closes the currently active menu - if nothing is active\n
+\t// it closes all menus.  If passed an argument, it will search for menus BELOW\n
+\t_close: function( startMenu ) {\n
+\t\tif ( !startMenu ) {\n
+\t\t\tstartMenu = this.active ? this.active.parent() : this.element;\n
+\t\t}\n
+\n
+\t\tstartMenu\n
+\t\t\t.find( ".ui-menu" )\n
+\t\t\t\t.hide()\n
+\t\t\t\t.attr( "aria-hidden", "true" )\n
+\t\t\t\t.attr( "aria-expanded", "false" )\n
+\t\t\t.end()\n
+\t\t\t.find( "a.ui-state-active" )\n
+\t\t\t\t.removeClass( "ui-state-active" );\n
+\t},\n
+\n
+\tcollapse: function( event ) {\n
+\t\tvar newItem = this.active &&\n
+\t\t\tthis.active.parent().closest( ".ui-menu-item", this.element );\n
+\t\tif ( newItem && newItem.length ) {\n
+\t\t\tthis._close();\n
+\t\t\tthis.focus( event, newItem );\n
+\t\t}\n
+\t},\n
+\n
+\texpand: function( event ) {\n
+\t\tvar newItem = this.active &&\n
+\t\t\tthis.active\n
+\t\t\t\t.children( ".ui-menu " )\n
+\t\t\t\t.children( ".ui-menu-item" )\n
+\t\t\t\t.first();\n
+\n
+\t\tif ( newItem && newItem.length ) {\n
+\t\t\tthis._open( newItem.parent() );\n
+\n
+\t\t\t// Delay so Firefox will not hide activedescendant change in expanding submenu from AT\n
+\t\t\tthis._delay(function() {\n
+\t\t\t\tthis.focus( event, newItem );\n
+\t\t\t});\n
+\t\t}\n
+\t},\n
+\n
+\tnext: function( event ) {\n
+\t\tthis._move( "next", "first", event );\n
+\t},\n
+\n
+\tprevious: function( event ) {\n
+\t\tthis._move( "prev", "last", event );\n
+\t},\n
+\n
+\tisFirstItem: function() {\n
+\t\treturn this.active && !this.active.prevAll( ".ui-menu-item" ).length;\n
+\t},\n
+\n
+\tisLastItem: function() {\n
+\t\treturn this.active && !this.active.nextAll( ".ui-menu-item" ).length;\n
+\t},\n
+\n
+\t_move: function( direction, filter, event ) {\n
+\t\tvar next;\n
+\t\tif ( this.active ) {\n
+\t\t\tif ( direction === "first" || direction === "last" ) {\n
+\t\t\t\tnext = this.active\n
+\t\t\t\t\t[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )\n
+\t\t\t\t\t.eq( -1 );\n
+\t\t\t} else {\n
+\t\t\t\tnext = this.active\n
+\t\t\t\t\t[ direction + "All" ]( ".ui-menu-item" )\n
+\t\t\t\t\t.eq( 0 );\n
+\t\t\t}\n
+\t\t}\n
+\t\tif ( !next || !next.length || !this.active ) {\n
+\t\t\tnext = this.activeMenu.children( ".ui-menu-item" )[ filter ]();\n
+\t\t}\n
+\n
+\t\tthis.focus( event, next );\n
+\t},\n
+\n
+\tnextPage: function( event ) {\n
+\t\tvar item, base, height;\n
+\n
+\t\tif ( !this.active ) {\n
+\t\t\tthis.next( event );\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tif ( this.isLastItem() ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tif ( this._hasScroll() ) {\n
+\t\t\tbase = this.active.offset().top;\n
+\t\t\theight = this.element.height();\n
+\t\t\tthis.active.nextAll( ".ui-menu-item" ).each(function() {\n
+\t\t\t\titem = $( this );\n
+\t\t\t\treturn item.offset().top - base - height < 0;\n
+\t\t\t});\n
+\n
+\t\t\tthis.focus( event, item );\n
+\t\t} else {\n
+\t\t\tthis.focus( event, this.activeMenu.children( ".ui-menu-item" )\n
+\t\t\t\t[ !this.active ? "first" : "last" ]() );\n
+\t\t}\n
+\t},\n
+\n
+\tpreviousPage: function( event ) {\n
+\t\tvar item, base, height;\n
+\t\tif ( !this.active ) {\n
+\t\t\tthis.next( event );\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tif ( this.isFirstItem() ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tif ( this._hasScroll() ) {\n
+\t\t\tbase = this.active.offset().top;\n
+\t\t\theight = this.element.height();\n
+\t\t\tthis.active.prevAll( ".ui-menu-item" ).each(function() {\n
+\t\t\t\titem = $( this );\n
+\t\t\t\treturn item.offset().top - base + height > 0;\n
+\t\t\t});\n
+\n
+\t\t\tthis.focus( event, item );\n
+\t\t} else {\n
+\t\t\tthis.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );\n
+\t\t}\n
+\t},\n
+\n
+\t_hasScroll: function() {\n
+\t\treturn this.element.outerHeight() < this.element.prop( "scrollHeight" );\n
+\t},\n
+\n
+\tselect: function( event ) {\n
+\t\t// TODO: It should never be possible to not have an active item at this\n
+\t\t// point, but the tests don\'t trigger mouseenter before click.\n
+\t\tthis.active = this.active || $( event.target ).closest( ".ui-menu-item" );\n
+\t\tvar ui = { item: this.active };\n
+\t\tif ( !this.active.has( ".ui-menu" ).length ) {\n
+\t\t\tthis.collapseAll( event, true );\n
+\t\t}\n
+\t\tthis._trigger( "select", event, ui );\n
+\t}\n
+});\n
+\n
+}( jQuery ));\n
+(function( $, undefined ) {\n
+\n
+$.widget( "ui.progressbar", {\n
+\tversion: "1.10.4",\n
+\toptions: {\n
+\t\tmax: 100,\n
+\t\tvalue: 0,\n
+\n
+\t\tchange: null,\n
+\t\tcomplete: null\n
+\t},\n
+\n
+\tmin: 0,\n
+\n
+\t_create: function() {\n
+\t\t// Constrain initial value\n
+\t\tthis.oldValue = this.options.value = this._constrainedValue();\n
+\n
+\t\tthis.element\n
+\t\t\t.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )\n
+\t\t\t.attr({\n
+\t\t\t\t// Only set static values, aria-valuenow and aria-valuemax are\n
+\t\t\t\t// set inside _refreshValue()\n
+\t\t\t\trole: "progressbar",\n
+\t\t\t\t"aria-valuemin": this.min\n
+\t\t\t});\n
+\n
+\t\tthis.valueDiv = $( "<div class=\'ui-progressbar-value ui-widget-header ui-corner-left\'></div>" )\n
+\t\t\t.appendTo( this.element );\n
+\n
+\t\tthis._refreshValue();\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tthis.element\n
+\t\t\t.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )\n
+\t\t\t.removeAttr( "role" )\n
+\t\t\t.removeAttr( "aria-valuemin" )\n
+\t\t\t.removeAttr( "aria-valuemax" )\n
+\t\t\t.removeAttr( "aria-valuenow" );\n
+\n
+\t\tthis.valueDiv.remove();\n
+\t},\n
+\n
+\tvalue: function( newValue ) {\n
+\t\tif ( newValue === undefined ) {\n
+\t\t\treturn this.options.value;\n
+\t\t}\n
+\n
+\t\tthis.options.value = this._constrainedValue( newValue );\n
+\t\tthis._refreshValue();\n
+\t},\n
+\n
+\t_constrainedValue: function( newValue ) {\n
+\t\tif ( newValue === undefined ) {\n
+\t\t\tnewValue = this.options.value;\n
+\t\t}\n
+\n
+\t\tthis.indeterminate = newValue === false;\n
+\n
+\t\t// sanitize value\n
+\t\tif ( typeof newValue !== "number" ) {\n
+\t\t\tnewValue = 0;\n
+\t\t}\n
+\n
+\t\treturn this.indeterminate ? false :\n
+\t\t\tMath.min( this.options.max, Math.max( this.min, newValue ) );\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\t// Ensure "value" option is set after other values (like max)\n
+\t\tvar value = options.value;\n
+\t\tdelete options.value;\n
+\n
+\t\tthis._super( options );\n
+\n
+\t\tthis.options.value = this._constrainedValue( value );\n
+\t\tthis._refreshValue();\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tif ( key === "max" ) {\n
+\t\t\t// Don\'t allow a max less than min\n
+\t\t\tvalue = Math.max( this.min, value );\n
+\t\t}\n
+\n
+\t\tthis._super( key, value );\n
+\t},\n
+\n
+\t_percentage: function() {\n
+\t\treturn this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );\n
+\t},\n
+\n
+\t_refreshValue: function() {\n
+\t\tvar value = this.options.value,\n
+\t\t\tpercentage = this._percentage();\n
+\n
+\t\tthis.valueDiv\n
+\t\t\t.toggle( this.indeterminate || value > this.min )\n
+\t\t\t.toggleClass( "ui-corner-right", value === this.options.max )\n
+\t\t\t.width( percentage.toFixed(0) + "%" );\n
+\n
+\t\tthis.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );\n
+\n
+\t\tif ( this.indeterminate ) {\n
+\t\t\tthis.element.removeAttr( "aria-valuenow" );\n
+\t\t\tif ( !this.overlayDiv ) {\n
+\t\t\t\tthis.overlayDiv = $( "<div class=\'ui-progressbar-overlay\'></div>" ).appendTo( this.valueDiv );\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tthis.element.attr({\n
+\t\t\t\t"aria-valuemax": this.options.max,\n
+\t\t\t\t"aria-valuenow": value\n
+\t\t\t});\n
+\t\t\tif ( this.overlayDiv ) {\n
+\t\t\t\tthis.overlayDiv.remove();\n
+\t\t\t\tthis.overlayDiv = null;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( this.oldValue !== value ) {\n
+\t\t\tthis.oldValue = value;\n
+\t\t\tthis._trigger( "change" );\n
+\t\t}\n
+\t\tif ( value === this.options.max ) {\n
+\t\t\tthis._trigger( "complete" );\n
+\t\t}\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+(function( $, undefined ) {\n
+\n
+function num(v) {\n
+\treturn parseInt(v, 10) || 0;\n
+}\n
+\n
+function isNumber(value) {\n
+\treturn !isNaN(parseInt(value, 10));\n
+}\n
+\n
+$.widget("ui.resizable", $.ui.mouse, {\n
+\tversion: "1.10.4",\n
+\twidgetEventPrefix: "resize",\n
+\toptions: {\n
+\t\talsoResize: false,\n
+\t\tanimate: false,\n
+\t\tanimateDuration: "slow",\n
+\t\tanimateEasing: "swing",\n
+\t\taspectRatio: false,\n
+\t\tautoHide: false,\n
+\t\tcontainment: false,\n
+\t\tghost: false,\n
+\t\tgrid: false,\n
+\t\thandles: "e,s,se",\n
+\t\thelper: false,\n
+\t\tmaxHeight: null,\n
+\t\tmaxWidth: null,\n
+\t\tminHeight: 10,\n
+\t\tminWidth: 10,\n
+\t\t// See #7960\n
+\t\tzIndex: 90,\n
+\n
+\t\t// callbacks\n
+\t\tresize: null,\n
+\t\tstart: null,\n
+\t\tstop: null\n
+\t},\n
+\t_create: function() {\n
+\n
+\t\tvar n, i, handle, axis, hname,\n
+\t\t\tthat = this,\n
+\t\t\to = this.options;\n
+\t\tthis.element.addClass("ui-resizable");\n
+\n
+\t\t$.extend(this, {\n
+\t\t\t_aspectRatio: !!(o.aspectRatio),\n
+\t\t\taspectRatio: o.aspectRatio,\n
+\t\t\toriginalElement: this.element,\n
+\t\t\t_proportionallyResizeElements: [],\n
+\t\t\t_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null\n
+\t\t});\n
+\n
+\t\t//Wrap the element if it cannot hold child nodes\n
+\t\tif(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {\n
+\n
+\t\t\t//Create a wrapper element and set the wrapper to the new current internal element\n
+\t\t\tthis.element.wrap(\n
+\t\t\t\t$("<div class=\'ui-wrapper\' style=\'overflow: hidden;\'></div>").css({\n
+\t\t\t\t\tposition: this.element.css("position"),\n
+\t\t\t\t\twidth: this.element.outerWidth(),\n
+\t\t\t\t\theight: this.element.outerHeight(),\n
+\t\t\t\t\ttop: this.element.css("top"),\n
+\t\t\t\t\tleft: this.element.css("left")\n
+\t\t\t\t})\n
+\t\t\t);\n
+\n
+\t\t\t//Overwrite the original this.element\n
+\t\t\tthis.element = this.element.parent().data(\n
+\t\t\t\t"ui-resizable", this.element.data("ui-resizable")\n
+\t\t\t);\n
+\n
+\t\t\tthis.elementIsWrapper = true;\n
+\n
+\t\t\t//Move margins to the wrapper\n
+\t\t\tthis.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });\n
+\t\t\tthis.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});\n
+\n
+\t\t\t//Prevent Safari textarea resize\n
+\t\t\tthis.originalResizeStyle = this.originalElement.css("resize");\n
+\t\t\tthis.originalElement.css("resize", "none");\n
+\n
+\t\t\t//Push the actual element to our proportionallyResize internal array\n
+\t\t\tthis._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));\n
+\n
+\t\t\t// avoid IE jump (hard set the margin)\n
+\t\t\tthis.originalElement.css({ margin: this.originalElement.css("margin") });\n
+\n
+\t\t\t// fix handlers offset\n
+\t\t\tthis._proportionallyResize();\n
+\n
+\t\t}\n
+\n
+\t\tthis.handles = o.handles || (!$(".ui-resizable-handle", this.element).length ? "e,s,se" : { n: ".ui-resizable-n", e: ".ui-resizable-e", s: ".ui-resizable-s", w: ".ui-resizable-w", se: ".ui-resizable-se", sw: ".ui-resizable-sw", ne: ".ui-resizable-ne", nw: ".ui-resizable-nw" });\n
+\t\tif(this.handles.constructor === String) {\n
+\n
+\t\t\tif ( this.handles === "all") {\n
+\t\t\t\tthis.handles = "n,e,s,w,se,sw,ne,nw";\n
+\t\t\t}\n
+\n
+\t\t\tn = this.handles.split(",");\n
+\t\t\tthis.handles = {};\n
+\n
+\t\t\tfor(i = 0; i < n.length; i++) {\n
+\n
+\t\t\t\thandle = $.trim(n[i]);\n
+\t\t\t\thname = "ui-resizable-"+handle;\n
+\t\t\t\taxis = $("<div class=\'ui-resizable-handle " + hname + "\'></div>");\n
+\n
+\t\t\t\t// Apply zIndex to all handles - see #7960\n
+\t\t\t\taxis.css({ zIndex: o.zIndex });\n
+\n
+\t\t\t\t//TODO : What\'s going on here?\n
+\t\t\t\tif ("se" === handle) {\n
+\t\t\t\t\taxis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");\n
+\t\t\t\t}\n
+\n
+\t\t\t\t//Insert into internal handles object and append to element\n
+\t\t\t\tthis.handles[handle] = ".ui-resizable-"+handle;\n
+\t\t\t\tthis.element.append(axis);\n
+\t\t\t}\n
+\n
+\t\t}\n
+\n
+\t\tthis._renderAxis = function(target) {\n
+\n
+\t\t\tvar i, axis, padPos, padWrapper;\n
+\n
+\t\t\ttarget = target || this.element;\n
+\n
+\t\t\tfor(i in this.handles) {\n
+\n
+\t\t\t\tif(this.handles[i].constructor === String) {\n
+\t\t\t\t\tthis.handles[i] = $(this.handles[i], this.element).show();\n
+\t\t\t\t}\n
+\n
+\t\t\t\t//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)\n
+\t\t\t\tif (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {\n
+\n
+\t\t\t\t\taxis = $(this.handles[i], this.element);\n
+\n
+\t\t\t\t\t//Checking the correct pad and border\n
+\t\t\t\t\tpadWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();\n
+\n
+\t\t\t\t\t//The padding type i have to apply...\n
+\t\t\t\t\tpadPos = [ "padding",\n
+\t\t\t\t\t\t/ne|nw|n/.test(i) ? "Top" :\n
+\t\t\t\t\t\t/se|sw|s/.test(i) ? "Bottom" :\n
+\t\t\t\t\t\t/^e$/.test(i) ? "Right" : "Left" ].join("");\n
+\n
+\t\t\t\t\ttarget.css(padPos, padWrapper);\n
+\n
+\t\t\t\t\tthis._proportionallyResize();\n
+\n
+\t\t\t\t}\n
+\n
+\t\t\t\t//TODO: What\'s that good for? There\'s not anything to be executed left\n
+\t\t\t\tif(!$(this.handles[i]).length) {\n
+\t\t\t\t\tcontinue;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t};\n
+\n
+\t\t//TODO: make renderAxis a prototype function\n
+\t\tthis._renderAxis(this.element);\n
+\n
+\t\tthis._handles = $(".ui-resizable-handle", this.element)\n
+\t\t\t.disableSelection();\n
+\n
+\t\t//Matching axis name\n
+\t\tthis._handles.mouseover(function() {\n
+\t\t\tif (!that.resizing) {\n
+\t\t\t\tif (this.className) {\n
+\t\t\t\t\taxis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);\n
+\t\t\t\t}\n
+\t\t\t\t//Axis, default = se\n
+\t\t\t\tthat.axis = axis && axis[1] ? axis[1] : "se";\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\t//If we want to auto hide the elements\n
+\t\tif (o.autoHide) {\n
+\t\t\tthis._handles.hide();\n
+\t\t\t$(this.element)\n
+\t\t\t\t.addClass("ui-resizable-autohide")\n
+\t\t\t\t.mouseenter(function() {\n
+\t\t\t\t\tif (o.disabled) {\n
+\t\t\t\t\t\treturn;\n
+\t\t\t\t\t}\n
+\t\t\t\t\t$(this).removeClass("ui-resizable-autohide");\n
+\t\t\t\t\tthat._handles.show();\n
+\t\t\t\t})\n
+\t\t\t\t.mouseleave(function(){\n
+\t\t\t\t\tif (o.disabled) {\n
+\t\t\t\t\t\treturn;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif (!that.resizing) {\n
+\t\t\t\t\t\t$(this).addClass("ui-resizable-autohide");\n
+\t\t\t\t\t\tthat._handles.hide();\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t}\n
+\n
+\t\t//Initialize the mouse interaction\n
+\t\tthis._mouseInit();\n
+\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\n
+\t\tthis._mouseDestroy();\n
+\n
+\t\tvar wrapper,\n
+\t\t\t_destroy = function(exp) {\n
+\t\t\t\t$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")\n
+\t\t\t\t\t.removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();\n
+\t\t\t};\n
+\n
+\t\t//TODO: Unwrap at same DOM position\n
+\t\tif (this.elementIsWrapper) {\n
+\t\t\t_destroy(this.element);\n
+\t\t\twrapper = this.element;\n
+\t\t\tthis.originalElement.css({\n
+\t\t\t\tposition: wrapper.css("position"),\n
+\t\t\t\twidth: wrapper.outerWidth(),\n
+\t\t\t\theight: wrapper.outerHeight(),\n
+\t\t\t\ttop: wrapper.css("top"),\n
+\t\t\t\tleft: wrapper.css("left")\n
+\t\t\t}).insertAfter( wrapper );\n
+\t\t\twrapper.remove();\n
+\t\t}\n
+\n
+\t\tthis.originalElement.css("resize", this.originalResizeStyle);\n
+\t\t_destroy(this.originalElement);\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\t_mouseCapture: function(event) {\n
+\t\tvar i, handle,\n
+\t\t\tcapture = false;\n
+\n
+\t\tfor (i in this.handles) {\n
+\t\t\thandle = $(this.handles[i])[0];\n
+\t\t\tif (handle === event.target || $.contains(handle, event.target)) {\n
+\t\t\t\tcapture = true;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn !this.options.disabled && capture;\n
+\t},\n
+\n
+\t_mouseStart: function(event) {\n
+\n
+\t\tvar curleft, curtop, cursor,\n
+\t\t\to = this.options,\n
+\t\t\tiniPos = this.element.position(),\n
+\t\t\tel = this.element;\n
+\n
+\t\tthis.resizing = true;\n
+\n
+\t\t// bugfix for http://dev.jquery.com/ticket/1749\n
+\t\tif ( (/absolute/).test( el.css("position") ) ) {\n
+\t\t\tel.css({ position: "absolute", top: el.css("top"), left: el.css("left") });\n
+\t\t} else if (el.is(".ui-draggable")) {\n
+\t\t\tel.css({ position: "absolute", top: iniPos.top, left: iniPos.left });\n
+\t\t}\n
+\n
+\t\tthis._renderProxy();\n
+\n
+\t\tcurleft = num(this.helper.css("left"));\n
+\t\tcurtop = num(this.helper.css("top"));\n
+\n
+\t\tif (o.containment) {\n
+\t\t\tcurleft += $(o.containment).scrollLeft() || 0;\n
+\t\t\tcurtop += $(o.containment).scrollTop() || 0;\n
+\t\t}\n
+\n
+\t\t//Store needed variables\n
+\t\tthis.offset = this.helper.offset();\n
+\t\tthis.position = { left: curleft, top: curtop };\n
+\t\tthis.size = this._helper ? { width: this.helper.width(), height: this.helper.height() } : { width: el.width(), height: el.height() };\n
+\t\tthis.originalSize = this._helper ? { width: el.outerWidt
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="6" aka="AAAAAAAAAAY=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+h(), height: el.outerHeight() } : { width: el.width(), height: el.height() };\n
+\t\tthis.originalPosition = { left: curleft, top: curtop };\n
+\t\tthis.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };\n
+\t\tthis.originalMousePosition = { left: event.pageX, top: event.pageY };\n
+\n
+\t\t//Aspect Ratio\n
+\t\tthis.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);\n
+\n
+\t\tcursor = $(".ui-resizable-" + this.axis).css("cursor");\n
+\t\t$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);\n
+\n
+\t\tel.addClass("ui-resizable-resizing");\n
+\t\tthis._propagate("start", event);\n
+\t\treturn true;\n
+\t},\n
+\n
+\t_mouseDrag: function(event) {\n
+\n
+\t\t//Increase performance, avoid regex\n
+\t\tvar data,\n
+\t\t\tel = this.helper, props = {},\n
+\t\t\tsmp = this.originalMousePosition,\n
+\t\t\ta = this.axis,\n
+\t\t\tprevTop = this.position.top,\n
+\t\t\tprevLeft = this.position.left,\n
+\t\t\tprevWidth = this.size.width,\n
+\t\t\tprevHeight = this.size.height,\n
+\t\t\tdx = (event.pageX-smp.left)||0,\n
+\t\t\tdy = (event.pageY-smp.top)||0,\n
+\t\t\ttrigger = this._change[a];\n
+\n
+\t\tif (!trigger) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\t// Calculate the attrs that will be change\n
+\t\tdata = trigger.apply(this, [event, dx, dy]);\n
+\n
+\t\t// Put this in the mouseDrag handler since the user can start pressing shift while resizing\n
+\t\tthis._updateVirtualBoundaries(event.shiftKey);\n
+\t\tif (this._aspectRatio || event.shiftKey) {\n
+\t\t\tdata = this._updateRatio(data, event);\n
+\t\t}\n
+\n
+\t\tdata = this._respectSize(data, event);\n
+\n
+\t\tthis._updateCache(data);\n
+\n
+\t\t// plugins callbacks need to be called first\n
+\t\tthis._propagate("resize", event);\n
+\n
+\t\tif (this.position.top !== prevTop) {\n
+\t\t\tprops.top = this.position.top + "px";\n
+\t\t}\n
+\t\tif (this.position.left !== prevLeft) {\n
+\t\t\tprops.left = this.position.left + "px";\n
+\t\t}\n
+\t\tif (this.size.width !== prevWidth) {\n
+\t\t\tprops.width = this.size.width + "px";\n
+\t\t}\n
+\t\tif (this.size.height !== prevHeight) {\n
+\t\t\tprops.height = this.size.height + "px";\n
+\t\t}\n
+\t\tel.css(props);\n
+\n
+\t\tif (!this._helper && this._proportionallyResizeElements.length) {\n
+\t\t\tthis._proportionallyResize();\n
+\t\t}\n
+\n
+\t\t// Call the user callback if the element was resized\n
+\t\tif ( ! $.isEmptyObject(props) ) {\n
+\t\t\tthis._trigger("resize", event, this.ui());\n
+\t\t}\n
+\n
+\t\treturn false;\n
+\t},\n
+\n
+\t_mouseStop: function(event) {\n
+\n
+\t\tthis.resizing = false;\n
+\t\tvar pr, ista, soffseth, soffsetw, s, left, top,\n
+\t\t\to = this.options, that = this;\n
+\n
+\t\tif(this._helper) {\n
+\n
+\t\t\tpr = this._proportionallyResizeElements;\n
+\t\t\tista = pr.length && (/textarea/i).test(pr[0].nodeName);\n
+\t\t\tsoffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;\n
+\t\t\tsoffsetw = ista ? 0 : that.sizeDiff.width;\n
+\n
+\t\t\ts = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) };\n
+\t\t\tleft = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;\n
+\t\t\ttop = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;\n
+\n
+\t\t\tif (!o.animate) {\n
+\t\t\t\tthis.element.css($.extend(s, { top: top, left: left }));\n
+\t\t\t}\n
+\n
+\t\t\tthat.helper.height(that.size.height);\n
+\t\t\tthat.helper.width(that.size.width);\n
+\n
+\t\t\tif (this._helper && !o.animate) {\n
+\t\t\t\tthis._proportionallyResize();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t$("body").css("cursor", "auto");\n
+\n
+\t\tthis.element.removeClass("ui-resizable-resizing");\n
+\n
+\t\tthis._propagate("stop", event);\n
+\n
+\t\tif (this._helper) {\n
+\t\t\tthis.helper.remove();\n
+\t\t}\n
+\n
+\t\treturn false;\n
+\n
+\t},\n
+\n
+\t_updateVirtualBoundaries: function(forceAspectRatio) {\n
+\t\tvar pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,\n
+\t\t\to = this.options;\n
+\n
+\t\tb = {\n
+\t\t\tminWidth: isNumber(o.minWidth) ? o.minWidth : 0,\n
+\t\t\tmaxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,\n
+\t\t\tminHeight: isNumber(o.minHeight) ? o.minHeight : 0,\n
+\t\t\tmaxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity\n
+\t\t};\n
+\n
+\t\tif(this._aspectRatio || forceAspectRatio) {\n
+\t\t\t// We want to create an enclosing box whose aspect ration is the requested one\n
+\t\t\t// First, compute the "projected" size for each dimension based on the aspect ratio and other dimension\n
+\t\t\tpMinWidth = b.minHeight * this.aspectRatio;\n
+\t\t\tpMinHeight = b.minWidth / this.aspectRatio;\n
+\t\t\tpMaxWidth = b.maxHeight * this.aspectRatio;\n
+\t\t\tpMaxHeight = b.maxWidth / this.aspectRatio;\n
+\n
+\t\t\tif(pMinWidth > b.minWidth) {\n
+\t\t\t\tb.minWidth = pMinWidth;\n
+\t\t\t}\n
+\t\t\tif(pMinHeight > b.minHeight) {\n
+\t\t\t\tb.minHeight = pMinHeight;\n
+\t\t\t}\n
+\t\t\tif(pMaxWidth < b.maxWidth) {\n
+\t\t\t\tb.maxWidth = pMaxWidth;\n
+\t\t\t}\n
+\t\t\tif(pMaxHeight < b.maxHeight) {\n
+\t\t\t\tb.maxHeight = pMaxHeight;\n
+\t\t\t}\n
+\t\t}\n
+\t\tthis._vBoundaries = b;\n
+\t},\n
+\n
+\t_updateCache: function(data) {\n
+\t\tthis.offset = this.helper.offset();\n
+\t\tif (isNumber(data.left)) {\n
+\t\t\tthis.position.left = data.left;\n
+\t\t}\n
+\t\tif (isNumber(data.top)) {\n
+\t\t\tthis.position.top = data.top;\n
+\t\t}\n
+\t\tif (isNumber(data.height)) {\n
+\t\t\tthis.size.height = data.height;\n
+\t\t}\n
+\t\tif (isNumber(data.width)) {\n
+\t\t\tthis.size.width = data.width;\n
+\t\t}\n
+\t},\n
+\n
+\t_updateRatio: function( data ) {\n
+\n
+\t\tvar cpos = this.position,\n
+\t\t\tcsize = this.size,\n
+\t\t\ta = this.axis;\n
+\n
+\t\tif (isNumber(data.height)) {\n
+\t\t\tdata.width = (data.height * this.aspectRatio);\n
+\t\t} else if (isNumber(data.width)) {\n
+\t\t\tdata.height = (data.width / this.aspectRatio);\n
+\t\t}\n
+\n
+\t\tif (a === "sw") {\n
+\t\t\tdata.left = cpos.left + (csize.width - data.width);\n
+\t\t\tdata.top = null;\n
+\t\t}\n
+\t\tif (a === "nw") {\n
+\t\t\tdata.top = cpos.top + (csize.height - data.height);\n
+\t\t\tdata.left = cpos.left + (csize.width - data.width);\n
+\t\t}\n
+\n
+\t\treturn data;\n
+\t},\n
+\n
+\t_respectSize: function( data ) {\n
+\n
+\t\tvar o = this._vBoundaries,\n
+\t\t\ta = this.axis,\n
+\t\t\tismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),\n
+\t\t\tisminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height),\n
+\t\t\tdw = this.originalPosition.left + this.originalSize.width,\n
+\t\t\tdh = this.position.top + this.size.height,\n
+\t\t\tcw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);\n
+\t\tif (isminw) {\n
+\t\t\tdata.width = o.minWidth;\n
+\t\t}\n
+\t\tif (isminh) {\n
+\t\t\tdata.height = o.minHeight;\n
+\t\t}\n
+\t\tif (ismaxw) {\n
+\t\t\tdata.width = o.maxWidth;\n
+\t\t}\n
+\t\tif (ismaxh) {\n
+\t\t\tdata.height = o.maxHeight;\n
+\t\t}\n
+\n
+\t\tif (isminw && cw) {\n
+\t\t\tdata.left = dw - o.minWidth;\n
+\t\t}\n
+\t\tif (ismaxw && cw) {\n
+\t\t\tdata.left = dw - o.maxWidth;\n
+\t\t}\n
+\t\tif (isminh && ch) {\n
+\t\t\tdata.top = dh - o.minHeight;\n
+\t\t}\n
+\t\tif (ismaxh && ch) {\n
+\t\t\tdata.top = dh - o.maxHeight;\n
+\t\t}\n
+\n
+\t\t// fixing jump error on top/left - bug #2330\n
+\t\tif (!data.width && !data.height && !data.left && data.top) {\n
+\t\t\tdata.top = null;\n
+\t\t} else if (!data.width && !data.height && !data.top && data.left) {\n
+\t\t\tdata.left = null;\n
+\t\t}\n
+\n
+\t\treturn data;\n
+\t},\n
+\n
+\t_proportionallyResize: function() {\n
+\n
+\t\tif (!this._proportionallyResizeElements.length) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tvar i, j, borders, paddings, prel,\n
+\t\t\telement = this.helper || this.element;\n
+\n
+\t\tfor ( i=0; i < this._proportionallyResizeElements.length; i++) {\n
+\n
+\t\t\tprel = this._proportionallyResizeElements[i];\n
+\n
+\t\t\tif (!this.borderDif) {\n
+\t\t\t\tthis.borderDif = [];\n
+\t\t\t\tborders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];\n
+\t\t\t\tpaddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];\n
+\n
+\t\t\t\tfor ( j = 0; j < borders.length; j++ ) {\n
+\t\t\t\t\tthis.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tprel.css({\n
+\t\t\t\theight: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,\n
+\t\t\t\twidth: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0\n
+\t\t\t});\n
+\n
+\t\t}\n
+\n
+\t},\n
+\n
+\t_renderProxy: function() {\n
+\n
+\t\tvar el = this.element, o = this.options;\n
+\t\tthis.elementOffset = el.offset();\n
+\n
+\t\tif(this._helper) {\n
+\n
+\t\t\tthis.helper = this.helper || $("<div style=\'overflow:hidden;\'></div>");\n
+\n
+\t\t\tthis.helper.addClass(this._helper).css({\n
+\t\t\t\twidth: this.element.outerWidth() - 1,\n
+\t\t\t\theight: this.element.outerHeight() - 1,\n
+\t\t\t\tposition: "absolute",\n
+\t\t\t\tleft: this.elementOffset.left +"px",\n
+\t\t\t\ttop: this.elementOffset.top +"px",\n
+\t\t\t\tzIndex: ++o.zIndex //TODO: Don\'t modify option\n
+\t\t\t});\n
+\n
+\t\t\tthis.helper\n
+\t\t\t\t.appendTo("body")\n
+\t\t\t\t.disableSelection();\n
+\n
+\t\t} else {\n
+\t\t\tthis.helper = this.element;\n
+\t\t}\n
+\n
+\t},\n
+\n
+\t_change: {\n
+\t\te: function(event, dx) {\n
+\t\t\treturn { width: this.originalSize.width + dx };\n
+\t\t},\n
+\t\tw: function(event, dx) {\n
+\t\t\tvar cs = this.originalSize, sp = this.originalPosition;\n
+\t\t\treturn { left: sp.left + dx, width: cs.width - dx };\n
+\t\t},\n
+\t\tn: function(event, dx, dy) {\n
+\t\t\tvar cs = this.originalSize, sp = this.originalPosition;\n
+\t\t\treturn { top: sp.top + dy, height: cs.height - dy };\n
+\t\t},\n
+\t\ts: function(event, dx, dy) {\n
+\t\t\treturn { height: this.originalSize.height + dy };\n
+\t\t},\n
+\t\tse: function(event, dx, dy) {\n
+\t\t\treturn $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));\n
+\t\t},\n
+\t\tsw: function(event, dx, dy) {\n
+\t\t\treturn $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));\n
+\t\t},\n
+\t\tne: function(event, dx, dy) {\n
+\t\t\treturn $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));\n
+\t\t},\n
+\t\tnw: function(event, dx, dy) {\n
+\t\t\treturn $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));\n
+\t\t}\n
+\t},\n
+\n
+\t_propagate: function(n, event) {\n
+\t\t$.ui.plugin.call(this, n, [event, this.ui()]);\n
+\t\t(n !== "resize" && this._trigger(n, event, this.ui()));\n
+\t},\n
+\n
+\tplugins: {},\n
+\n
+\tui: function() {\n
+\t\treturn {\n
+\t\t\toriginalElement: this.originalElement,\n
+\t\t\telement: this.element,\n
+\t\t\thelper: this.helper,\n
+\t\t\tposition: this.position,\n
+\t\t\tsize: this.size,\n
+\t\t\toriginalSize: this.originalSize,\n
+\t\t\toriginalPosition: this.originalPosition\n
+\t\t};\n
+\t}\n
+\n
+});\n
+\n
+/*\n
+ * Resizable Extensions\n
+ */\n
+\n
+$.ui.plugin.add("resizable", "animate", {\n
+\n
+\tstop: function( event ) {\n
+\t\tvar that = $(this).data("ui-resizable"),\n
+\t\t\to = that.options,\n
+\t\t\tpr = that._proportionallyResizeElements,\n
+\t\t\tista = pr.length && (/textarea/i).test(pr[0].nodeName),\n
+\t\t\tsoffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,\n
+\t\t\tsoffsetw = ista ? 0 : that.sizeDiff.width,\n
+\t\t\tstyle = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },\n
+\t\t\tleft = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,\n
+\t\t\ttop = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;\n
+\n
+\t\tthat.element.animate(\n
+\t\t\t$.extend(style, top && left ? { top: top, left: left } : {}), {\n
+\t\t\t\tduration: o.animateDuration,\n
+\t\t\t\teasing: o.animateEasing,\n
+\t\t\t\tstep: function() {\n
+\n
+\t\t\t\t\tvar data = {\n
+\t\t\t\t\t\twidth: parseInt(that.element.css("width"), 10),\n
+\t\t\t\t\t\theight: parseInt(that.element.css("height"), 10),\n
+\t\t\t\t\t\ttop: parseInt(that.element.css("top"), 10),\n
+\t\t\t\t\t\tleft: parseInt(that.element.css("left"), 10)\n
+\t\t\t\t\t};\n
+\n
+\t\t\t\t\tif (pr && pr.length) {\n
+\t\t\t\t\t\t$(pr[0]).css({ width: data.width, height: data.height });\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// propagating resize, and updating values for each animation step\n
+\t\t\t\t\tthat._updateCache(data);\n
+\t\t\t\t\tthat._propagate("resize", event);\n
+\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t);\n
+\t}\n
+\n
+});\n
+\n
+$.ui.plugin.add("resizable", "containment", {\n
+\n
+\tstart: function() {\n
+\t\tvar element, p, co, ch, cw, width, height,\n
+\t\t\tthat = $(this).data("ui-resizable"),\n
+\t\t\to = that.options,\n
+\t\t\tel = that.element,\n
+\t\t\toc = o.containment,\n
+\t\t\tce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;\n
+\n
+\t\tif (!ce) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthat.containerElement = $(ce);\n
+\n
+\t\tif (/document/.test(oc) || oc === document) {\n
+\t\t\tthat.containerOffset = { left: 0, top: 0 };\n
+\t\t\tthat.containerPosition = { left: 0, top: 0 };\n
+\n
+\t\t\tthat.parentData = {\n
+\t\t\t\telement: $(document), left: 0, top: 0,\n
+\t\t\t\twidth: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight\n
+\t\t\t};\n
+\t\t}\n
+\n
+\t\t// i\'m a node, so compute top, left, right, bottom\n
+\t\telse {\n
+\t\t\telement = $(ce);\n
+\t\t\tp = [];\n
+\t\t\t$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });\n
+\n
+\t\t\tthat.containerOffset = element.offset();\n
+\t\t\tthat.containerPosition = element.position();\n
+\t\t\tthat.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };\n
+\n
+\t\t\tco = that.containerOffset;\n
+\t\t\tch = that.containerSize.height;\n
+\t\t\tcw = that.containerSize.width;\n
+\t\t\twidth = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw );\n
+\t\t\theight = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);\n
+\n
+\t\t\tthat.parentData = {\n
+\t\t\t\telement: ce, left: co.left, top: co.top, width: width, height: height\n
+\t\t\t};\n
+\t\t}\n
+\t},\n
+\n
+\tresize: function( event ) {\n
+\t\tvar woset, hoset, isParent, isOffsetRelative,\n
+\t\t\tthat = $(this).data("ui-resizable"),\n
+\t\t\to = that.options,\n
+\t\t\tco = that.containerOffset, cp = that.position,\n
+\t\t\tpRatio = that._aspectRatio || event.shiftKey,\n
+\t\t\tcop = { top:0, left:0 }, ce = that.containerElement;\n
+\n
+\t\tif (ce[0] !== document && (/static/).test(ce.css("position"))) {\n
+\t\t\tcop = co;\n
+\t\t}\n
+\n
+\t\tif (cp.left < (that._helper ? co.left : 0)) {\n
+\t\t\tthat.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));\n
+\t\t\tif (pRatio) {\n
+\t\t\t\tthat.size.height = that.size.width / that.aspectRatio;\n
+\t\t\t}\n
+\t\t\tthat.position.left = o.helper ? co.left : 0;\n
+\t\t}\n
+\n
+\t\tif (cp.top < (that._helper ? co.top : 0)) {\n
+\t\t\tthat.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);\n
+\t\t\tif (pRatio) {\n
+\t\t\t\tthat.size.width = that.size.height * that.aspectRatio;\n
+\t\t\t}\n
+\t\t\tthat.position.top = that._helper ? co.top : 0;\n
+\t\t}\n
+\n
+\t\tthat.offset.left = that.parentData.left+that.position.left;\n
+\t\tthat.offset.top = that.parentData.top+that.position.top;\n
+\n
+\t\twoset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width );\n
+\t\thoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );\n
+\n
+\t\tisParent = that.containerElement.get(0) === that.element.parent().get(0);\n
+\t\tisOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));\n
+\n
+\t\tif ( isParent && isOffsetRelative ) {\n
+\t\t\twoset -= Math.abs( that.parentData.left );\n
+\t\t}\n
+\n
+\t\tif (woset + that.size.width >= that.parentData.width) {\n
+\t\t\tthat.size.width = that.parentData.width - woset;\n
+\t\t\tif (pRatio) {\n
+\t\t\t\tthat.size.height = that.size.width / that.aspectRatio;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif (hoset + that.size.height >= that.parentData.height) {\n
+\t\t\tthat.size.height = that.parentData.height - hoset;\n
+\t\t\tif (pRatio) {\n
+\t\t\t\tthat.size.width = that.size.height * that.aspectRatio;\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\tstop: function(){\n
+\t\tvar that = $(this).data("ui-resizable"),\n
+\t\t\to = that.options,\n
+\t\t\tco = that.containerOffset,\n
+\t\t\tcop = that.containerPosition,\n
+\t\t\tce = that.containerElement,\n
+\t\t\thelper = $(that.helper),\n
+\t\t\tho = helper.offset(),\n
+\t\t\tw = helper.outerWidth() - that.sizeDiff.width,\n
+\t\t\th = helper.outerHeight() - that.sizeDiff.height;\n
+\n
+\t\tif (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {\n
+\t\t\t$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });\n
+\t\t}\n
+\n
+\t\tif (that._helper && !o.animate && (/static/).test(ce.css("position"))) {\n
+\t\t\t$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });\n
+\t\t}\n
+\n
+\t}\n
+});\n
+\n
+$.ui.plugin.add("resizable", "alsoResize", {\n
+\n
+\tstart: function () {\n
+\t\tvar that = $(this).data("ui-resizable"),\n
+\t\t\to = that.options,\n
+\t\t\t_store = function (exp) {\n
+\t\t\t\t$(exp).each(function() {\n
+\t\t\t\t\tvar el = $(this);\n
+\t\t\t\t\tel.data("ui-resizable-alsoresize", {\n
+\t\t\t\t\t\twidth: parseInt(el.width(), 10), height: parseInt(el.height(), 10),\n
+\t\t\t\t\t\tleft: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)\n
+\t\t\t\t\t});\n
+\t\t\t\t});\n
+\t\t\t};\n
+\n
+\t\tif (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {\n
+\t\t\tif (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }\n
+\t\t\telse { $.each(o.alsoResize, function (exp) { _store(exp); }); }\n
+\t\t}else{\n
+\t\t\t_store(o.alsoResize);\n
+\t\t}\n
+\t},\n
+\n
+\tresize: function (event, ui) {\n
+\t\tvar that = $(this).data("ui-resizable"),\n
+\t\t\to = that.options,\n
+\t\t\tos = that.originalSize,\n
+\t\t\top = that.originalPosition,\n
+\t\t\tdelta = {\n
+\t\t\t\theight: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,\n
+\t\t\t\ttop: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0\n
+\t\t\t},\n
+\n
+\t\t\t_alsoResize = function (exp, c) {\n
+\t\t\t\t$(exp).each(function() {\n
+\t\t\t\t\tvar el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},\n
+\t\t\t\t\t\tcss = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];\n
+\n
+\t\t\t\t\t$.each(css, function (i, prop) {\n
+\t\t\t\t\t\tvar sum = (start[prop]||0) + (delta[prop]||0);\n
+\t\t\t\t\t\tif (sum && sum >= 0) {\n
+\t\t\t\t\t\t\tstyle[prop] = sum || null;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t});\n
+\n
+\t\t\t\t\tel.css(style);\n
+\t\t\t\t});\n
+\t\t\t};\n
+\n
+\t\tif (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {\n
+\t\t\t$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });\n
+\t\t}else{\n
+\t\t\t_alsoResize(o.alsoResize);\n
+\t\t}\n
+\t},\n
+\n
+\tstop: function () {\n
+\t\t$(this).removeData("resizable-alsoresize");\n
+\t}\n
+});\n
+\n
+$.ui.plugin.add("resizable", "ghost", {\n
+\n
+\tstart: function() {\n
+\n
+\t\tvar that = $(this).data("ui-resizable"), o = that.options, cs = that.size;\n
+\n
+\t\tthat.ghost = that.originalElement.clone();\n
+\t\tthat.ghost\n
+\t\t\t.css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })\n
+\t\t\t.addClass("ui-resizable-ghost")\n
+\t\t\t.addClass(typeof o.ghost === "string" ? o.ghost : "");\n
+\n
+\t\tthat.ghost.appendTo(that.helper);\n
+\n
+\t},\n
+\n
+\tresize: function(){\n
+\t\tvar that = $(this).data("ui-resizable");\n
+\t\tif (that.ghost) {\n
+\t\t\tthat.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });\n
+\t\t}\n
+\t},\n
+\n
+\tstop: function() {\n
+\t\tvar that = $(this).data("ui-resizable");\n
+\t\tif (that.ghost && that.helper) {\n
+\t\t\tthat.helper.get(0).removeChild(that.ghost.get(0));\n
+\t\t}\n
+\t}\n
+\n
+});\n
+\n
+$.ui.plugin.add("resizable", "grid", {\n
+\n
+\tresize: function() {\n
+\t\tvar that = $(this).data("ui-resizable"),\n
+\t\t\to = that.options,\n
+\t\t\tcs = that.size,\n
+\t\t\tos = that.originalSize,\n
+\t\t\top = that.originalPosition,\n
+\t\t\ta = that.axis,\n
+\t\t\tgrid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,\n
+\t\t\tgridX = (grid[0]||1),\n
+\t\t\tgridY = (grid[1]||1),\n
+\t\t\tox = Math.round((cs.width - os.width) / gridX) * gridX,\n
+\t\t\toy = Math.round((cs.height - os.height) / gridY) * gridY,\n
+\t\t\tnewWidth = os.width + ox,\n
+\t\t\tnewHeight = os.height + oy,\n
+\t\t\tisMaxWidth = o.maxWidth && (o.maxWidth < newWidth),\n
+\t\t\tisMaxHeight = o.maxHeight && (o.maxHeight < newHeight),\n
+\t\t\tisMinWidth = o.minWidth && (o.minWidth > newWidth),\n
+\t\t\tisMinHeight = o.minHeight && (o.minHeight > newHeight);\n
+\n
+\t\to.grid = grid;\n
+\n
+\t\tif (isMinWidth) {\n
+\t\t\tnewWidth = newWidth + gridX;\n
+\t\t}\n
+\t\tif (isMinHeight) {\n
+\t\t\tnewHeight = newHeight + gridY;\n
+\t\t}\n
+\t\tif (isMaxWidth) {\n
+\t\t\tnewWidth = newWidth - gridX;\n
+\t\t}\n
+\t\tif (isMaxHeight) {\n
+\t\t\tnewHeight = newHeight - gridY;\n
+\t\t}\n
+\n
+\t\tif (/^(se|s|e)$/.test(a)) {\n
+\t\t\tthat.size.width = newWidth;\n
+\t\t\tthat.size.height = newHeight;\n
+\t\t} else if (/^(ne)$/.test(a)) {\n
+\t\t\tthat.size.width = newWidth;\n
+\t\t\tthat.size.height = newHeight;\n
+\t\t\tthat.position.top = op.top - oy;\n
+\t\t} else if (/^(sw)$/.test(a)) {\n
+\t\t\tthat.size.width = newWidth;\n
+\t\t\tthat.size.height = newHeight;\n
+\t\t\tthat.position.left = op.left - ox;\n
+\t\t} else {\n
+\t\t\tif ( newHeight - gridY > 0 ) {\n
+\t\t\t\tthat.size.height = newHeight;\n
+\t\t\t\tthat.position.top = op.top - oy;\n
+\t\t\t} else {\n
+\t\t\t\tthat.size.height = gridY;\n
+\t\t\t\tthat.position.top = op.top + os.height - gridY;\n
+\t\t\t}\n
+\t\t\tif ( newWidth - gridX > 0 ) {\n
+\t\t\t\tthat.size.width = newWidth;\n
+\t\t\t\tthat.position.left = op.left - ox;\n
+\t\t\t} else {\n
+\t\t\t\tthat.size.width = gridX;\n
+\t\t\t\tthat.position.left = op.left + os.width - gridX;\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+});\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+$.widget("ui.selectable", $.ui.mouse, {\n
+\tversion: "1.10.4",\n
+\toptions: {\n
+\t\tappendTo: "body",\n
+\t\tautoRefresh: true,\n
+\t\tdistance: 0,\n
+\t\tfilter: "*",\n
+\t\ttolerance: "touch",\n
+\n
+\t\t// callbacks\n
+\t\tselected: null,\n
+\t\tselecting: null,\n
+\t\tstart: null,\n
+\t\tstop: null,\n
+\t\tunselected: null,\n
+\t\tunselecting: null\n
+\t},\n
+\t_create: function() {\n
+\t\tvar selectees,\n
+\t\t\tthat = this;\n
+\n
+\t\tthis.element.addClass("ui-selectable");\n
+\n
+\t\tthis.dragged = false;\n
+\n
+\t\t// cache selectee children based on filter\n
+\t\tthis.refresh = function() {\n
+\t\t\tselectees = $(that.options.filter, that.element[0]);\n
+\t\t\tselectees.addClass("ui-selectee");\n
+\t\t\tselectees.each(function() {\n
+\t\t\t\tvar $this = $(this),\n
+\t\t\t\t\tpos = $this.offset();\n
+\t\t\t\t$.data(this, "selectable-item", {\n
+\t\t\t\t\telement: this,\n
+\t\t\t\t\t$element: $this,\n
+\t\t\t\t\tleft: pos.left,\n
+\t\t\t\t\ttop: pos.top,\n
+\t\t\t\t\tright: pos.left + $this.outerWidth(),\n
+\t\t\t\t\tbottom: pos.top + $this.outerHeight(),\n
+\t\t\t\t\tstartselected: false,\n
+\t\t\t\t\tselected: $this.hasClass("ui-selected"),\n
+\t\t\t\t\tselecting: $this.hasClass("ui-selecting"),\n
+\t\t\t\t\tunselecting: $this.hasClass("ui-unselecting")\n
+\t\t\t\t});\n
+\t\t\t});\n
+\t\t};\n
+\t\tthis.refresh();\n
+\n
+\t\tthis.selectees = selectees.addClass("ui-selectee");\n
+\n
+\t\tthis._mouseInit();\n
+\n
+\t\tthis.helper = $("<div class=\'ui-selectable-helper\'></div>");\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tthis.selectees\n
+\t\t\t.removeClass("ui-selectee")\n
+\t\t\t.removeData("selectable-item");\n
+\t\tthis.element\n
+\t\t\t.removeClass("ui-selectable ui-selectable-disabled");\n
+\t\tthis._mouseDestroy();\n
+\t},\n
+\n
+\t_mouseStart: function(event) {\n
+\t\tvar that = this,\n
+\t\t\toptions = this.options;\n
+\n
+\t\tthis.opos = [event.pageX, event.pageY];\n
+\n
+\t\tif (this.options.disabled) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis.selectees = $(options.filter, this.element[0]);\n
+\n
+\t\tthis._trigger("start", event);\n
+\n
+\t\t$(options.appendTo).append(this.helper);\n
+\t\t// position helper (lasso)\n
+\t\tthis.helper.css({\n
+\t\t\t"left": event.pageX,\n
+\t\t\t"top": event.pageY,\n
+\t\t\t"width": 0,\n
+\t\t\t"height": 0\n
+\t\t});\n
+\n
+\t\tif (options.autoRefresh) {\n
+\t\t\tthis.refresh();\n
+\t\t}\n
+\n
+\t\tthis.selectees.filter(".ui-selected").each(function() {\n
+\t\t\tvar selectee = $.data(this, "selectable-item");\n
+\t\t\tselectee.startselected = true;\n
+\t\t\tif (!event.metaKey && !event.ctrlKey) {\n
+\t\t\t\tselectee.$element.removeClass("ui-selected");\n
+\t\t\t\tselectee.selected = false;\n
+\t\t\t\tselectee.$element.addClass("ui-unselecting");\n
+\t\t\t\tselectee.unselecting = true;\n
+\t\t\t\t// selectable UNSELECTING callback\n
+\t\t\t\tthat._trigger("unselecting", event, {\n
+\t\t\t\t\tunselecting: selectee.element\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\t$(event.target).parents().addBack().each(function() {\n
+\t\t\tvar doSelect,\n
+\t\t\t\tselectee = $.data(this, "selectable-item");\n
+\t\t\tif (selectee) {\n
+\t\t\t\tdoSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");\n
+\t\t\t\tselectee.$element\n
+\t\t\t\t\t.removeClass(doSelect ? "ui-unselecting" : "ui-selected")\n
+\t\t\t\t\t.addClass(doSelect ? "ui-selecting" : "ui-unselecting");\n
+\t\t\t\tselectee.unselecting = !doSelect;\n
+\t\t\t\tselectee.selecting = doSelect;\n
+\t\t\t\tselectee.selected = doSelect;\n
+\t\t\t\t// selectable (UN)SELECTING callback\n
+\t\t\t\tif (doSelect) {\n
+\t\t\t\t\tthat._trigger("selecting", event, {\n
+\t\t\t\t\t\tselecting: selectee.element\n
+\t\t\t\t\t});\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthat._trigger("unselecting", event, {\n
+\t\t\t\t\t\tunselecting: selectee.element\n
+\t\t\t\t\t});\n
+\t\t\t\t}\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t},\n
+\n
+\t_mouseDrag: function(event) {\n
+\n
+\t\tthis.dragged = true;\n
+\n
+\t\tif (this.options.disabled) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tvar tmp,\n
+\t\t\tthat = this,\n
+\t\t\toptions = this.options,\n
+\t\t\tx1 = this.opos[0],\n
+\t\t\ty1 = this.opos[1],\n
+\t\t\tx2 = event.pageX,\n
+\t\t\ty2 = event.pageY;\n
+\n
+\t\tif (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }\n
+\t\tif (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }\n
+\t\tthis.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});\n
+\n
+\t\tthis.selectees.each(function() {\n
+\t\t\tvar selectee = $.data(this, "selectable-item"),\n
+\t\t\t\thit = false;\n
+\n
+\t\t\t//prevent helper from being selected if appendTo: selectable\n
+\t\t\tif (!selectee || selectee.element === that.element[0]) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tif (options.tolerance === "touch") {\n
+\t\t\t\thit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );\n
+\t\t\t} else if (options.tolerance === "fit") {\n
+\t\t\t\thit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);\n
+\t\t\t}\n
+\n
+\t\t\tif (hit) {\n
+\t\t\t\t// SELECT\n
+\t\t\t\tif (selectee.selected) {\n
+\t\t\t\t\tselectee.$element.removeClass("ui-selected");\n
+\t\t\t\t\tselectee.selected = false;\n
+\t\t\t\t}\n
+\t\t\t\tif (selectee.unselecting) {\n
+\t\t\t\t\tselectee.$element.removeClass("ui-unselecting");\n
+\t\t\t\t\tselectee.unselecting = false;\n
+\t\t\t\t}\n
+\t\t\t\tif (!selectee.selecting) {\n
+\t\t\t\t\tselectee.$element.addClass("ui-selecting");\n
+\t\t\t\t\tselectee.selecting = true;\n
+\t\t\t\t\t// selectable SELECTING callback\n
+\t\t\t\t\tthat._trigger("selecting", event, {\n
+\t\t\t\t\t\tselecting: selectee.element\n
+\t\t\t\t\t});\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\t// UNSELECT\n
+\t\t\t\tif (selectee.selecting) {\n
+\t\t\t\t\tif ((event.metaKey || event.ctrlKey) && selectee.startselected) {\n
+\t\t\t\t\t\tselectee.$element.removeClass("ui-selecting");\n
+\t\t\t\t\t\tselectee.selecting = false;\n
+\t\t\t\t\t\tselectee.$element.addClass("ui-selected");\n
+\t\t\t\t\t\tselectee.selected = true;\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tselectee.$element.removeClass("ui-selecting");\n
+\t\t\t\t\t\tselectee.selecting = false;\n
+\t\t\t\t\t\tif (selectee.startselected) {\n
+\t\t\t\t\t\t\tselectee.$element.addClass("ui-unselecting");\n
+\t\t\t\t\t\t\tselectee.unselecting = true;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\t// selectable UNSELECTING callback\n
+\t\t\t\t\t\tthat._trigger("unselecting", event, {\n
+\t\t\t\t\t\t\tunselecting: selectee.element\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\tif (selectee.selected) {\n
+\t\t\t\t\tif (!event.metaKey && !event.ctrlKey && !selectee.startselected) {\n
+\t\t\t\t\t\tselectee.$element.removeClass("ui-selected");\n
+\t\t\t\t\t\tselectee.selected = false;\n
+\n
+\t\t\t\t\t\tselectee.$element.addClass("ui-unselecting");\n
+\t\t\t\t\t\tselectee.unselecting = true;\n
+\t\t\t\t\t\t// selectable UNSELECTING callback\n
+\t\t\t\t\t\tthat._trigger("unselecting", event, {\n
+\t\t\t\t\t\t\tunselecting: selectee.element\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\treturn false;\n
+\t},\n
+\n
+\t_mouseStop: function(event) {\n
+\t\tvar that = this;\n
+\n
+\t\tthis.dragged = false;\n
+\n
+\t\t$(".ui-unselecting", this.element[0]).each(function() {\n
+\t\t\tvar selectee = $.data(this, "selectable-item");\n
+\t\t\tselectee.$element.removeClass("ui-unselecting");\n
+\t\t\tselectee.unselecting = false;\n
+\t\t\tselectee.startselected = false;\n
+\t\t\tthat._trigger("unselected", event, {\n
+\t\t\t\tunselected: selectee.element\n
+\t\t\t});\n
+\t\t});\n
+\t\t$(".ui-selecting", this.element[0]).each(function() {\n
+\t\t\tvar selectee = $.data(this, "selectable-item");\n
+\t\t\tselectee.$element.removeClass("ui-selecting").addClass("ui-selected");\n
+\t\t\tselectee.selecting = false;\n
+\t\t\tselectee.selected = true;\n
+\t\t\tselectee.startselected = true;\n
+\t\t\tthat._trigger("selected", event, {\n
+\t\t\t\tselected: selectee.element\n
+\t\t\t});\n
+\t\t});\n
+\t\tthis._trigger("stop", event);\n
+\n
+\t\tthis.helper.remove();\n
+\n
+\t\treturn false;\n
+\t}\n
+\n
+});\n
+\n
+})(jQuery);\n
+(function( $, undefined ) {\n
+\n
+// number of pages in a slider\n
+// (how many times can you page up/down to go through the whole range)\n
+var numPages = 5;\n
+\n
+$.widget( "ui.slider", $.ui.mouse, {\n
+\tversion: "1.10.4",\n
+\twidgetEventPrefix: "slide",\n
+\n
+\toptions: {\n
+\t\tanimate: false,\n
+\t\tdistance: 0,\n
+\t\tmax: 100,\n
+\t\tmin: 0,\n
+\t\torientation: "horizontal",\n
+\t\trange: false,\n
+\t\tstep: 1,\n
+\t\tvalue: 0,\n
+\t\tvalues: null,\n
+\n
+\t\t// callbacks\n
+\t\tchange: null,\n
+\t\tslide: null,\n
+\t\tstart: null,\n
+\t\tstop: null\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tthis._keySliding = false;\n
+\t\tthis._mouseSliding = false;\n
+\t\tthis._animateOff = true;\n
+\t\tthis._handleIndex = null;\n
+\t\tthis._detectOrientation();\n
+\t\tthis._mouseInit();\n
+\n
+\t\tthis.element\n
+\t\t\t.addClass( "ui-slider" +\n
+\t\t\t\t" ui-slider-" + this.orientation +\n
+\t\t\t\t" ui-widget" +\n
+\t\t\t\t" ui-widget-content" +\n
+\t\t\t\t" ui-corner-all");\n
+\n
+\t\tthis._refresh();\n
+\t\tthis._setOption( "disabled", this.options.disabled );\n
+\n
+\t\tthis._animateOff = false;\n
+\t},\n
+\n
+\t_refresh: function() {\n
+\t\tthis._createRange();\n
+\t\tthis._createHandles();\n
+\t\tthis._setupEvents();\n
+\t\tthis._refreshValue();\n
+\t},\n
+\n
+\t_createHandles: function() {\n
+\t\tvar i, handleCount,\n
+\t\t\toptions = this.options,\n
+\t\t\texistingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),\n
+\t\t\thandle = "<a class=\'ui-slider-handle ui-state-default ui-corner-all\' href=\'#\'></a>",\n
+\t\t\thandles = [];\n
+\n
+\t\thandleCount = ( options.values && options.values.length ) || 1;\n
+\n
+\t\tif ( existingHandles.length > handleCount ) {\n
+\t\t\texistingHandles.slice( handleCount ).remove();\n
+\t\t\texistingHandles = existingHandles.slice( 0, handleCount );\n
+\t\t}\n
+\n
+\t\tfor ( i = existingHandles.length; i < handleCount; i++ ) {\n
+\t\t\thandles.push( handle );\n
+\t\t}\n
+\n
+\t\tthis.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );\n
+\n
+\t\tthis.handle = this.handles.eq( 0 );\n
+\n
+\t\tthis.handles.each(function( i ) {\n
+\t\t\t$( this ).data( "ui-slider-handle-index", i );\n
+\t\t});\n
+\t},\n
+\n
+\t_createRange: function() {\n
+\t\tvar options = this.options,\n
+\t\t\tclasses = "";\n
+\n
+\t\tif ( options.range ) {\n
+\t\t\tif ( options.range === true ) {\n
+\t\t\t\tif ( !options.values ) {\n
+\t\t\t\t\toptions.values = [ this._valueMin(), this._valueMin() ];\n
+\t\t\t\t} else if ( options.values.length && options.values.length !== 2 ) {\n
+\t\t\t\t\toptions.values = [ options.values[0], options.values[0] ];\n
+\t\t\t\t} else if ( $.isArray( options.values ) ) {\n
+\t\t\t\t\toptions.values = options.values.slice(0);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif ( !this.range || !this.range.length ) {\n
+\t\t\t\tthis.range = $( "<div></div>" )\n
+\t\t\t\t\t.appendTo( this.element );\n
+\n
+\t\t\t\tclasses = "ui-slider-range" +\n
+\t\t\t\t// note: this isn\'t the most fittingly semantic framework class for this element,\n
+\t\t\t\t// but worked best visually with a variety of themes\n
+\t\t\t\t" ui-widget-header ui-corner-all";\n
+\t\t\t} else {\n
+\t\t\t\tthis.range.removeClass( "ui-slider-range-min ui-slider-range-max" )\n
+\t\t\t\t\t// Handle range switching from true to min/max\n
+\t\t\t\t\t.css({\n
+\t\t\t\t\t\t"left": "",\n
+\t\t\t\t\t\t"bottom": ""\n
+\t\t\t\t\t});\n
+\t\t\t}\n
+\n
+\t\t\tthis.range.addClass( classes +\n
+\t\t\t\t( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );\n
+\t\t} else {\n
+\t\t\tif ( this.range ) {\n
+\t\t\t\tthis.range.remove();\n
+\t\t\t}\n
+\t\t\tthis.range = null;\n
+\t\t}\n
+\t},\n
+\n
+\t_setupEvents: function() {\n
+\t\tvar elements = this.handles.add( this.range ).filter( "a" );\n
+\t\tthis._off( elements );\n
+\t\tthis._on( elements, this._handleEvents );\n
+\t\tthis._hoverable( elements );\n
+\t\tthis._focusable( elements );\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tthis.handles.remove();\n
+\t\tif ( this.range ) {\n
+\t\t\tthis.range.remove();\n
+\t\t}\n
+\n
+\t\tthis.element\n
+\t\t\t.removeClass( "ui-slider" +\n
+\t\t\t\t" ui-slider-horizontal" +\n
+\t\t\t\t" ui-slider-vertical" +\n
+\t\t\t\t" ui-widget" +\n
+\t\t\t\t" ui-widget-content" +\n
+\t\t\t\t" ui-corner-all" );\n
+\n
+\t\tthis._mouseDestroy();\n
+\t},\n
+\n
+\t_mouseCapture: function( event ) {\n
+\t\tvar position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,\n
+\t\t\tthat = this,\n
+\t\t\to = this.options;\n
+\n
+\t\tif ( o.disabled ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\tthis.elementSize = {\n
+\t\t\twidth: this.element.outerWidth(),\n
+\t\t\theight: this.element.outerHeight()\n
+\t\t};\n
+\t\tthis.elementOffset = this.element.offset();\n
+\n
+\t\tposition = { x: event.pageX, y: event.pageY };\n
+\t\tnormValue = this._normValueFromMouse( position );\n
+\t\tdistance = this._valueMax() - this._valueMin() + 1;\n
+\t\tthis.handles.each(function( i ) {\n
+\t\t\tvar thisDistance = Math.abs( normValue - that.values(i) );\n
+\t\t\tif (( distance > thisDistance ) ||\n
+\t\t\t\t( distance === thisDistance &&\n
+\t\t\t\t\t(i === that._lastChangedValue || that.values(i) === o.min ))) {\n
+\t\t\t\tdistance = thisDistance;\n
+\t\t\t\tclosestHandle = $( this );\n
+\t\t\t\tindex = i;\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tallowed = this._start( event, index );\n
+\t\tif ( allowed === false ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\tthis._mouseSliding = true;\n
+\n
+\t\tthis._handleIndex = index;\n
+\n
+\t\tclosestHandle\n
+\t\t\t.addClass( "ui-state-active" )\n
+\t\t\t.focus();\n
+\n
+\t\toffset = closestHandle.offset();\n
+\t\tmouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );\n
+\t\tthis._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {\n
+\t\t\tleft: event.pageX - offset.left - ( closestHandle.width() / 2 ),\n
+\t\t\ttop: event.pageY - offset.top -\n
+\t\t\t\t( closestHandle.height() / 2 ) -\n
+\t\t\t\t( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -\n
+\t\t\t\t( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +\n
+\t\t\t\t( parseInt( closestHandle.css("marginTop"), 10 ) || 0)\n
+\t\t};\n
+\n
+\t\tif ( !this.handles.hasClass( "ui-state-hover" ) ) {\n
+\t\t\tthis._slide( event, index, normValue );\n
+\t\t}\n
+\t\tthis._animateOff = true;\n
+\t\treturn true;\n
+\t},\n
+\n
+\t_mouseStart: function() {\n
+\t\treturn true;\n
+\t},\n
+\n
+\t_mouseDrag: function( event ) {\n
+\t\tvar position = { x: event.pageX, y: event.pageY },\n
+\t\t\tnormValue = this._normValueFromMouse( position );\n
+\n
+\t\tthis._slide( event, this._handleIndex, normValue );\n
+\n
+\t\treturn false;\n
+\t},\n
+\n
+\t_mouseStop: function( event ) {\n
+\t\tthis.handles.removeClass( "ui-state-active" );\n
+\t\tthis._mouseSliding = false;\n
+\n
+\t\tthis._stop( event, this._handleIndex );\n
+\t\tthis._change( event, this._handleIndex );\n
+\n
+\t\tthis._handleIndex = null;\n
+\t\tthis._clickOffset = null;\n
+\t\tthis._animateOff = false;\n
+\n
+\t\treturn false;\n
+\t},\n
+\n
+\t_detectOrientation: function() {\n
+\t\tthis.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";\n
+\t},\n
+\n
+\t_normValueFromMouse: function( position ) {\n
+\t\tvar pixelTotal,\n
+\t\t\tpixelMouse,\n
+\t\t\tpercentMouse,\n
+\t\t\tvalueTotal,\n
+\t\t\tvalueMouse;\n
+\n
+\t\tif ( this.orientation === "horizontal" ) {\n
+\t\t\tpixelTotal = this.elementSize.width;\n
+\t\t\tpixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );\n
+\t\t} else {\n
+\t\t\tpixelTotal = this.elementSize.height;\n
+\t\t\tpixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );\n
+\t\t}\n
+\n
+\t\tpercentMouse = ( pixelMouse / pixelTotal );\n
+\t\tif ( percentMouse > 1 ) {\n
+\t\t\tpercentMouse = 1;\n
+\t\t}\n
+\t\tif ( percentMouse < 0 ) {\n
+\t\t\tpercentMouse = 0;\n
+\t\t}\n
+\t\tif ( this.orientation === "vertical" ) {\n
+\t\t\tpercentMouse = 1 - percentMouse;\n
+\t\t}\n
+\n
+\t\tvalueTotal = this._valueMax() - this._valueMin();\n
+\t\tvalueMouse = this._valueMin() + percentMouse * valueTotal;\n
+\n
+\t\treturn this._trimAlignValue( valueMouse );\n
+\t},\n
+\n
+\t_start: function( event, index ) {\n
+\t\tvar uiHash = {\n
+\t\t\thandle: this.handles[ index ],\n
+\t\t\tvalue: this.value()\n
+\t\t};\n
+\t\tif ( this.options.values && this.options.values.length ) {\n
+\t\t\tuiHash.value = this.values( index );\n
+\t\t\tuiHash.values = this.values();\n
+\t\t}\n
+\t\treturn this._trigger( "start", event, uiHash );\n
+\t},\n
+\n
+\t_slide: function( event, index, newVal ) {\n
+\t\tvar otherVal,\n
+\t\t\tnewValues,\n
+\t\t\tallowed;\n
+\n
+\t\tif ( this.options.values && this.options.values.length ) {\n
+\t\t\totherVal = this.values( index ? 0 : 1 );\n
+\n
+\t\t\tif ( ( this.options.values.length === 2 && this.options.range === true ) &&\n
+\t\t\t\t\t( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )\n
+\t\t\t\t) {\n
+\t\t\t\tnewVal = otherVal;\n
+\t\t\t}\n
+\n
+\t\t\tif ( newVal !== this.values( index ) ) {\n
+\t\t\t\tnewValues = this.values();\n
+\t\t\t\tnewValues[ index ] = newVal;\n
+\t\t\t\t// A slide can be canceled by returning false from the slide callback\n
+\t\t\t\tallowed = this._trigger( "slide", event, {\n
+\t\t\t\t\thandle: this.handles[ index ],\n
+\t\t\t\t\tvalue: newVal,\n
+\t\t\t\t\tvalues: newValues\n
+\t\t\t\t} );\n
+\t\t\t\totherVal = this.values( index ? 0 : 1 );\n
+\t\t\t\tif ( allowed !== false ) {\n
+\t\t\t\t\tthis.values( index, newVal );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tif ( newVal !== this.value() ) {\n
+\t\t\t\t// A slide can be canceled by returning false from the slide callback\n
+\t\t\t\tallowed = this._trigger( "slide", event, {\n
+\t\t\t\t\thandle: this.handles[ index ],\n
+\t\t\t\t\tvalue: newVal\n
+\t\t\t\t} );\n
+\t\t\t\tif ( allowed !== false ) {\n
+\t\t\t\t\tthis.value( newVal );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t_stop: function( event, index ) {\n
+\t\tvar uiHash = {\n
+\t\t\thandle: this.handles[ index ],\n
+\t\t\tvalue: this.value()\n
+\t\t};\n
+\t\tif ( this.options.values && this.options.values.length ) {\n
+\t\t\tuiHash.value = this.values( index );\n
+\t\t\tuiHash.values = this.values();\n
+\t\t}\n
+\n
+\t\tthis._trigger( "stop", event, uiHash );\n
+\t},\n
+\n
+\t_change: function( event, index ) {\n
+\t\tif ( !this._keySliding && !this._mouseSliding ) {\n
+\t\t\tvar uiHash = {\n
+\t\t\t\thandle: this.handles[ index ],\n
+\t\t\t\tvalue: this.value()\n
+\t\t\t};\n
+\t\t\tif ( this.options.values && this.options.values.length ) {\n
+\t\t\t\tuiHash.value = this.values( index );\n
+\t\t\t\tuiHash.values = this.values();\n
+\t\t\t}\n
+\n
+\t\t\t//store the last changed value index for reference when handles overlap\n
+\t\t\tthis._lastChangedValue = index;\n
+\n
+\t\t\tthis._trigger( "change", event, uiHash );\n
+\t\t}\n
+\t},\n
+\n
+\tvalue: function( newValue ) {\n
+\t\tif ( arguments.length ) {\n
+\t\t\tthis.options.value = this._trimAlignValue( newValue );\n
+\t\t\tthis._refreshValue();\n
+\t\t\tthis._change( null, 0 );\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\treturn this._value();\n
+\t},\n
+\n
+\tvalues: function( index, newValue ) {\n
+\t\tvar vals,\n
+\t\t\tnewValues,\n
+\t\t\ti;\n
+\n
+\t\tif ( arguments.length > 1 ) {\n
+\t\t\tthis.options.values[ index ] = this._trimAlignValue( newValue );\n
+\t\t\tthis._refreshValue();\n
+\t\t\tthis._change( null, index );\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( arguments.length ) {\n
+\t\t\tif ( $.isArray( arguments[ 0 ] ) ) {\n
+\t\t\t\tvals = this.options.values;\n
+\t\t\t\tnewValues = arguments[ 0 ];\n
+\t\t\t\tfor ( i = 0; i < vals.length; i += 1 ) {\n
+\t\t\t\t\tvals[ i ] = this._trimAlignValue( newValues[ i ] );\n
+\t\t\t\t\tthis._change( null, i );\n
+\t\t\t\t}\n
+\t\t\t\tthis._refreshValue();\n
+\t\t\t} else {\n
+\t\t\t\tif ( this.options.values && this.options.values.length ) {\n
+\t\t\t\t\treturn this._values( index );\n
+\t\t\t\t} else {\n
+\t\t\t\t\treturn this.value();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\treturn this._values();\n
+\t\t}\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tvar i,\n
+\t\t\tvalsLength = 0;\n
+\n
+\t\tif ( key === "range" && this.options.range === true ) {\n
+\t\t\tif ( value === "min" ) {\n
+\t\t\t\tthis.options.value = this._values( 0 );\n
+\t\t\t\tthis.options.values = null;\n
+\t\t\t} else if ( value === "max" ) {\n
+\t\t\t\tthis.options.value = this._values( this.options.values.length-1 );\n
+\t\t\t\tthis.options.values = null;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( $.isArray( this.options.values ) ) {\n
+\t\t\tvalsLength = this.options.values.length;\n
+\t\t}\n
+\n
+\t\t$.Widget.prototype._setOption.apply( this, arguments );\n
+\n
+\t\tswitch ( key ) {\n
+\t\t\tcase "orientation":\n
+\t\t\t\tthis._detectOrientation();\n
+\t\t\t\tthis.element\n
+\t\t\t\t\t.removeClass( "ui-slider-horizontal ui-slider-vertical" )\n
+\t\t\t\t\t.addClass( "ui-slider-" + this.orientation );\n
+\t\t\t\tthis._refreshValue();\n
+\t\t\t\tbreak;\n
+\t\t\tcase "value":\n
+\t\t\t\tthis._animateOff = true;\n
+\t\t\t\tthis._refreshValue();\n
+\t\t\t\tthis._change( null, 0 );\n
+\t\t\t\tthis._animateOff = false;\n
+\t\t\t\tbreak;\n
+\t\t\tcase "values":\n
+\t\t\t\tthis._animateOff = true;\n
+\t\t\t\tthis._refreshValue();\n
+\t\t\t\tfor ( i = 0; i < valsLength; i += 1 ) {\n
+\t\t\t\t\tthis._change( null, i );\n
+\t\t\t\t}\n
+\t\t\t\tthis._animateOff = false;\n
+\t\t\t\tbreak;\n
+\t\t\tcase "min":\n
+\t\t\tcase "max":\n
+\t\t\t\tthis._animateOff = true;\n
+\t\t\t\tthis._refreshValue();\n
+\t\t\t\tthis._animateOff = false;\n
+\t\t\t\tbreak;\n
+\t\t\tcase "range":\n
+\t\t\t\tthis._animateOff = true;\n
+\t\t\t\tthis._refresh();\n
+\t\t\t\tthis._animateOff = false;\n
+\t\t\t\tbreak;\n
+\t\t}\n
+\t},\n
+\n
+\t//internal value getter\n
+\t// _value() returns value trimmed by min and max, aligned by step\n
+\t_value: function() {\n
+\t\tvar val = this.options.value;\n
+\t\tval = this._trimAlignValue( val );\n
+\n
+\t\treturn val;\n
+\t},\n
+\n
+\t//internal values getter\n
+\t// _values() returns array of values trimmed by min and max, aligned by step\n
+\t// _values( index ) returns single value trimmed by min and max, aligned by step\n
+\t_values: function( index ) {\n
+\t\tvar val,\n
+\t\t\tvals,\n
+\t\t\ti;\n
+\n
+\t\tif ( arguments.length ) {\n
+\t\t\tval = this.options.values[ index ];\n
+\t\t\tval = this._trimAlignValue( val );\n
+\n
+\t\t\treturn val;\n
+\t\t} else if ( this.options.values && this.options.values.length ) {\n
+\t\t\t// .slice() creates a copy of the array\n
+\t\t\t// this copy gets trimmed by min and max and then returned\n
+\t\t\tvals = this.options.values.slice();\n
+\t\t\tfor ( i = 0; i < vals.length; i+= 1) {\n
+\t\t\t\tvals[ i ] = this._trimAlignValue( vals[ i ] );\n
+\t\t\t}\n
+\n
+\t\t\treturn vals;\n
+\t\t} else {\n
+\t\t\treturn [];\n
+\t\t}\n
+\t},\n
+\n
+\t// returns the step-aligned value that val is closest to, between (inclusive) min and max\n
+\t_trimAlignValue: function( val ) {\n
+\t\tif ( val <= this._valueMin() ) {\n
+\t\t\treturn this._valueMin();\n
+\t\t}\n
+\t\tif ( val >= this._valueMax() ) {\n
+\t\t\treturn this._valueMax();\n
+\t\t}\n
+\t\tvar step = ( this.options.step > 0 ) ? this.options.step : 1,\n
+\t\t\tvalModStep = (val - this._valueMin()) % step,\n
+\t\t\talignValue = val - valModStep;\n
+\n
+\t\tif ( Math.abs(valModStep) * 2 >= step ) {\n
+\t\t\talignValue += ( valModStep > 0 ) ? step : ( -step );\n
+\t\t}\n
+\n
+\t\t// Since JavaScript has problems with large floats, round\n
+\t\t// the final value to 5 digits after the decimal point (see #4124)\n
+\t\treturn parseFloat( alignValue.toFixed(5) );\n
+\t},\n
+\n
+\t_valueMin: function() {\n
+\t\treturn this.options.min;\n
+\t},\n
+\n
+\t_valueMax: function() {\n
+\t\treturn this.options.max;\n
+\t},\n
+\n
+\t_refreshValue: function() {\n
+\t\tvar lastValPercent, valPercent, value, valueMin, valueMax,\n
+\t\t\toRange = this.options.range,\n
+\t\t\to = this.options,\n
+\t\t\tthat = this,\n
+\t\t\tanimate = ( !this._animateOff ) ? o.animate : false,\n
+\t\t\t_set = {};\n
+\n
+\t\tif ( this.options.values && this.options.values.length ) {\n
+\t\t\tthis.handles.each(function( i ) {\n
+\t\t\t\tvalPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;\n
+\t\t\t\t_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";\n
+\t\t\t\t$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );\n
+\t\t\t\tif ( that.options.range === true ) {\n
+\t\t\t\t\tif ( that.orientation === "horizontal" ) {\n
+\t\t\t\t\t\tif ( i === 0 ) {\n
+\t\t\t\t\t\t\tthat.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\tif ( i === 1 ) {\n
+\t\t\t\t\t\t\tthat.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tif ( i === 0 ) {\n
+\t\t\t\t\t\t\tthat.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\tif ( i === 1 ) {\n
+\t\t\t\t\t\t\tthat.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\tlastValPercent = valPercent;\n
+\t\t\t});\n
+\t\t} else {\n
+\t\t\tvalue = this.value();\n
+\t\t\tvalueMin = this._valueMin();\n
+\t\t\tvalueMax = this._valueMax();\n
+\t\t\tvalPercent = ( valueMax !== valueMin ) ?\n
+\t\t\t\t\t( value - valueMin ) / ( valueMax - valueMin ) * 100 :\n
+\t\t\t\t\t0;\n
+\t\t\t_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";\n
+\t\t\tthis.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );\n
+\n
+\t\t\tif ( oRange === "min" && this.orientation === "horizontal" ) {\n
+\t\t\t\tthis.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );\n
+\t\t\t}\n
+\t\t\tif ( oRange === "max" && this.orientation === "horizontal" ) {\n
+\t\t\t\tthis.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );\n
+\t\t\t}\n
+\t\t\tif ( oRange === "min" && this.orientation === "vertical" ) {\n
+\t\t\t\tthis.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );\n
+\t\t\t}\n
+\t\t\tif ( oRange === "max" && this.orientation === "vertical" ) {\n
+\t\t\t\tthis.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t_handleEvents: {\n
+\t\tkeydown: function( event ) {\n
+\t\t\tvar allowed, curVal, newVal, step,\n
+\t\t\t\tindex = $( event.target ).data( "ui-slider-handle-index" );\n
+\n
+\t\t\tswitch ( event.keyCode ) {\n
+\t\t\t\tcase $.ui.keyCode.HOME:\n
+\t\t\t\tcase $.ui.keyCode.END:\n
+\t\t\t\tcase $.ui.keyCode.PAGE_UP:\n
+\t\t\t\tcase $.ui.keyCode.PAGE_DOWN:\n
+\t\t\t\tcase $.ui.keyCode.UP:\n
+\t\t\t\tcase $.ui.keyCode.RIGHT:\n
+\t\t\t\tcase $.ui.keyCode.DOWN:\n
+\t\t\t\tcase $.ui.keyCode.LEFT:\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\tif ( !this._keySliding ) {\n
+\t\t\t\t\t\tthis._keySliding = true;\n
+\t\t\t\t\t\t$( event.target ).addClass( "ui-state-active" );\n
+\t\t\t\t\t\tallowed = this._start( event, index );\n
+\t\t\t\t\t\tif ( allowed === false ) {\n
+\t\t\t\t\t\t\treturn;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\tbreak;\n
+\t\t\t}\n
+\n
+\t\t\tstep = this.options.step;\n
+\t\t\tif ( this.options.values && this.options.values.length ) {\n
+\t\t\t\tcurVal = newVal = this.values( index );\n
+\t\t\t} else {\n
+\t\t\t\tcurVal = newVal = this.value();\n
+\t\t\t}\n
+\n
+\t\t\tswitch ( event.keyCode ) {\n
+\t\t\t\tcase $.ui.keyCode.HOME:\n
+\t\t\t\t\tnewVal = this._valueMin();\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase $.ui.keyCode.END:\n
+\t\t\t\t\tnewVal = this._valueMax();\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase $.ui.keyCode.PAGE_UP:\n
+\t\t\t\t\tnewVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase $.ui.keyCode.PAGE_DOWN:\n
+\t\t\t\t\tnewVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase $.ui.keyCode.UP:\n
+\t\t\t\tcase $.ui.keyCode.RIGHT:\n
+\t\t\t\t\tif ( curVal === this._valueMax() ) {\n
+\t\t\t\t\t\treturn;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tnewVal = this._trimAlignValue( curVal + step );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\tcase $.ui.keyCode.DOWN:\n
+\t\t\t\tcase $.ui.keyCode.LEFT:\n
+\t\t\t\t\tif ( curVal === this._valueMin() ) {\n
+\t\t\t\t\t\treturn;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tnewVal = this._trimAlignValue( curVal - step );\n
+\t\t\t\t\tbreak;\n
+\t\t\t}\n
+\n
+\t\t\tthis._slide( event, index, newVal );\n
+\t\t},\n
+\t\tclick: function( event ) {\n
+\t\t\tevent.preventDefault();\n
+\t\t},\n
+\t\tkeyup: function( event ) {\n
+\t\t\tvar index = $( event.target ).data( "ui-slider-handle-index" );\n
+\n
+\t\t\tif ( this._keySliding ) {\n
+\t\t\t\tthis._keySliding = false;\n
+\t\t\t\tthis._stop( event, index );\n
+\t\t\t\tthis._change( event, index );\n
+\t\t\t\t$( event.target ).removeClass( "ui-state-active" );\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+});\n
+\n
+}(jQuery));\n
+(function( $, undefined ) {\n
+\n
+function isOverAxis( x, reference, size ) {\n
+\treturn ( x > reference ) && ( x < ( reference + size ) );\n
+}\n
+\n
+function isFloating(item) {\n
+\treturn (/left|right/).test(item.css("float")) || (/inline|table-cell/).test(item.css("display"));\n
+}\n
+\n
+$.widget("ui.sortable", $.ui.mouse, {\n
+\tversion: "1.10.4",\n
+\twidgetEventPrefix: "sort",\n
+\tready: false,\n
+\toptions: {\n
+\t\tappendTo: "parent",\n
+\t\taxis: false,\n
+\t\tconnectWith: false,\n
+\t\tcontainment: false,\n
+\t\tcursor: "auto",\n
+\t\tcursorAt: false,\n
+\t\tdropOnEmpty: true,\n
+\t\tforcePlaceholderSize: false,\n
+\t\tforceHelperSize: false,\n
+\t\tgrid: false,\n
+\t\thandle: false,\n
+\t\thelper: "original",\n
+\t\titems: "> *",\n
+\t\topacity: false,\n
+\t\tplaceholder: false,\n
+\t\trevert: false,\n
+\t\tscroll: true,\n
+\t\tscrollSensitivity: 20,\n
+\t\tscrollSpeed: 20,\n
+\t\tscope: "default",\n
+\t\ttolerance: "intersect",\n
+\t\tzIndex: 1000,\n
+\n
+\t\t// callbacks\n
+\t\tactivate: null,\n
+\t\tbeforeStop: null,\n
+\t\tchange: null,\n
+\t\tdeactivate: null,\n
+\t\tout: null,\n
+\t\tover: null,\n
+\t\treceive: null,\n
+\t\tremove: null,\n
+\t\tsort: null,\n
+\t\tstart: null,\n
+\t\tstop: null,\n
+\t\tupdate: null\n
+\t},\n
+\t_create: function() {\n
+\n
+\t\tvar o = this.options;\n
+\t\tthis.containerCache = {};\n
+\t\tthis.element.addClass("ui-sortable");\n
+\n
+\t\t//Get the items\n
+\t\tthis.refresh();\n
+\n
+\t\t//Let\'s determine if the items are being displayed horizontally\n
+\t\tthis.floating = this.items.length ? o.axis === "x" || isFloating(this.items[0].item) : false;\n
+\n
+\t\t//Let\'s determine the parent\'s offset\n
+\t\tthis.offset = this.element.offset();\n
+\n
+\t\t//Initialize mouse events for interaction\n
+\t\tthis._mouseInit();\n
+\n
+\t\t//We\'re ready to go\n
+\t\tthis.ready = true;\n
+\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tthis.element\n
+\t\t\t.removeClass("ui-sortable ui-sortable-disabled");\n
+\t\tthis._mouseDestroy();\n
+\n
+\t\tfor ( var i = this.items.length - 1; i >= 0; i-- ) {\n
+\t\t\tthis.items[i].item.removeData(this.widgetName + "-item");\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\t_setOption: function(key, value){\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\tthis.options[ key ] = value;\n
+\n
+\t\t\tthis.widget().toggleClass( "ui-sortable-disabled", !!value );\n
+\t\t} else {\n
+\t\t\t// Don\'t call widget base _setOption for disable as it adds ui-state-disabled class\n
+\t\t\t$.Widget.prototype._setOption.apply(this, arguments);\n
+\t\t}\n
+\t},\n
+\n
+\t_mouseCapture: function(event, overrideHandle) {\n
+\t\tvar currentItem = null,\n
+\t\t\tvalidHandle = false,\n
+\t\t\tthat = this;\n
+\n
+\t\tif (this.reverting) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\tif(this.options.disabled || this.options.type === "static") {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\t//We have to refresh the items data once first\n
+\t\tthis._refreshItems(event);\n
+\n
+\t\t//Find out if the clicked node (or one of its parents) is a actual item in this.items\n
+\t\t$(event.target).parents().each(function() {\n
+\t\t\tif($.data(this, that.widgetName + "-item") === that) {\n
+\t\t\t\tcurrentItem = $(this);\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t});\n
+\t\tif($.data(event.target, that.widgetName + "-item") === that) {\n
+\t\t\tcurrentItem = $(event.target);\n
+\t\t}\n
+\n
+\t\tif(!currentItem) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\tif(this.options.handle && !overrideHandle) {\n
+\t\t\t$(this.options.handle, currentItem).find("*").addBack().each(function() {\n
+\t\t\t\tif(this === event.target) {\n
+\t\t\t\t\tvalidHandle = true;\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t\tif(!validHandle) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis.currentItem = currentItem;\n
+\t\tthis._removeCurrentsFromItems();\n
+\t\treturn true;\n
+\n
+\t},\n
+\n
+\t_mouseStart: function(event, overrideHandle, noActivation) {\n
+\n
+\t\tvar i, body,\n
+\t\t\to = this.options;\n
+\n
+\t\tthis.currentContainer = this;\n
+\n
+\t\t//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture\n
+\t\tthis.refreshPositions();\n
+\n
+\t\t//Create and append the visible helper\n
+\t\tthis.helper = this._createHelper(event);\n
+\n
+\t\t//Cache the helper size\n
+\t\tthis._cacheHelperProportions();\n
+\n
+\t\t/*\n
+\t\t * - Position generation -\n
+\t\t * This block generates everything position related - it\'s the core of draggables.\n
+\t\t */\n
+\n
+\t\t//Cache the margins of the original element\n
+\t\tthis._cacheMargins();\n
+\n
+\t\t//Get the next scrolling parent\n
+\t\tthis.scrollParent = this.helper.scrollParent();\n
+\n
+\t\t//The element\'s absolute position on the page minus margins\n
+\t\tthis.offset = this.currentItem.offset();\n
+\t\tthis.offset = {\n
+\t\t\ttop: this.offset.top - this.margins.top,\n
+\t\t\tleft: this.offset.left - this.margins.left\n
+\t\t};\n
+\n
+\t\t$.extend(this.offset, {\n
+\t\t\tclick: { //Where the click happened, relative to the element\n
+\t\t\t\tleft: event.pageX - this.offset.left,\n
+\t\t\t\ttop: event.pageY - this.offset.top\n
+\t\t\t},\n
+\t\t\tparent: this._getParentOffset(),\n
+\t\t\trelative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper\n
+\t\t});\n
+\n
+\t\t// Only after we got the offset, we can change the helper\'s position to absolute\n
+\t\t// TODO: Still need to figure out a way to make relative sorting possible\n
+\t\tthis.helper.css("position", "absolute");\n
+\t\tthis.cssPosition = this.helper.css("position");\n
+\n
+\t\t//Generate the original position\n
+\t\tthis.originalPosition = this._generatePosition(event);\n
+\t\tthis.originalPageX = event.pageX;\n
+\t\tthis.originalPageY = event.pageY;\n
+\n
+\t\t//Adjust the mouse offset relative to the helper if "cursorAt" is supplied\n
+\t\t(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));\n
+\n
+\t\t//Cache the former DOM position\n
+\t\tthis.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };\n
+\n
+\t\t//If the helper is not the original, hide the original so it\'s not playing any role during the drag, won\'t cause anything bad this way\n
+\t\tif(this.helper[0] !== this.currentItem[0]) {\n
+\t\t\tthis.currentItem.hide();\n
+\t\t}\n
+\n
+\t\t//Create the placeholder\n
+\t\tthis._createPlaceholder();\n
+\n
+\t\t//Set a containment if given in the options\n
+\t\tif(o.containment) {\n
+\t\t\tthis._setContainment();\n
+\t\t}\n
+\n
+\t\tif( o.cursor && o.cursor !== "auto" ) { // cursor option\n
+\t\t\tbody = this.document.find( "body" );\n
+\n
+\t\t\t// support: IE\n
+\t\t\tthis.storedCursor = body.css( "cursor" );\n
+\t\t\tbody.css( "cursor", o.cursor );\n
+\n
+\t\t\tthis.storedStylesheet = $( "<style>*{ cursor: "+o.cursor+" !important; }</style>" ).appendTo( body );\n
+\t\t}\n
+\n
+\t\tif(o.opacity) { // opacity option\n
+\t\t\tif (this.helper.css("opacity")) {\n
+\t\t\t\tthis._storedOpacity = this.helper.css("opacity");\n
+\t\t\t}\n
+\t\t\tthis.helper.css("opacity", o.opacity);\n
+\t\t}\n
+\n
+\t\tif(o.zIndex) { // zIndex option\n
+\t\t\tif (this.helper.css("zIndex")) {\n
+\t\t\t\tthis._storedZIndex = this.helper.css("zIndex");\n
+\t\t\t}\n
+\t\t\tthis.helper.css("zIndex", o.zIndex);\n
+\t\t}\n
+\n
+\t\t//Prepare scrolling\n
+\t\tif(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {\n
+\t\t\tthis.overflowOffset = this.scrollParent.offset();\n
+\t\t}\n
+\n
+\t\t//Call callbacks\n
+\t\tthis._trigger("start", event, this._uiHash());\n
+\n
+\t\t//Recache the helper size\n
+\t\tif(!this._preserveHelperProportions) {\n
+\t\t\tthis._cacheHelperProportions();\n
+\t\t}\n
+\n
+\n
+\t\t//Post "activate" events to possible containers\n
+\t\tif( !noActivation ) {\n
+\t\t\tfor ( i = this.containers.length - 1; i >= 0; i-- ) {\n
+\t\t\t\tthis.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t//Prepare possible droppables\n
+\t\tif($.ui.ddmanager) {\n
+\t\t\t$.ui.ddmanager.current = this;\n
+\t\t}\n
+\n
+\t\tif ($.ui.ddmanager && !o.dropBehaviour) {\n
+\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n
+\t\t}\n
+\n
+\t\tthis.dragging = true;\n
+\n
+\t\tthis.helper.addClass("ui-sortable-helper");\n
+\t\tthis._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position\n
+\t\treturn true;\n
+\n
+\t},\n
+\n
+\t_mouseDrag: function(event) {\n
+\t\tvar i, item, itemElement, intersection,\n
+\t\t\to = this.options,\n
+\t\t\tscrolled = false;\n
+\n
+\t\t//Compute the helpers position\n
+\t\tthis.position = this._generatePosition(event);\n
+\t\tthis.positionAbs = this._convertPositionTo("absolute");\n
+\n
+\t\tif (!this.lastPositionAbs) {\n
+\t\t\tthis.lastPositionAbs = this.positionAbs;\n
+\t\t}\n
+\n
+\t\t//Do scrolling\n
+\t\tif(this.options.scroll) {\n
+\t\t\tif(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {\n
+\n
+\t\t\t\tif((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {\n
+\t\t\t\t\tthis.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;\n
+\t\t\t\t} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {\n
+\t\t\t\t\tthis.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {\n
+\t\t\t\t\tthis.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;\n
+\t\t\t\t} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {\n
+\t\t\t\t\tthis.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;\n
+\t\t\t\t}\n
+\n
+\t\t\t} else {\n
+\n
+\t\t\t\tif(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {\n
+\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);\n
+\t\t\t\t} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {\n
+\t\t\t\t\tscrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {\n
+\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);\n
+\t\t\t\t} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {\n
+\t\t\t\t\tscrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);\n
+\t\t\t\t}\n
+\n
+\t\t\t}\n
+\n
+\t\t\tif(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {\n
+\t\t\t\t$.ui.ddmanager.prepareOffsets(this, event);\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t//Regenerate the absolute position used for position checks\n
+\t\tthis.positionAbs = this._convertPositionTo("absolute");\n
+\n
+\t\t//Set the helper position\n
+\t\tif(!this.options.axis || this.options.axis !== "y") {\n
+\t\t\tthis.helper[0].style.left = this.position.left+"px";\n
+\t\t}\n
+\t\tif(!this.options.axis || this.options.axis !== "x") {\n
+\t\t\tthis.helper[0].style.top = this.position.top+"px";\n
+\t\t}\n
+\n
+\t\t//Rearrange\n
+\t\tfor (i = this.items.length - 1; i >= 0; i--) {\n
+\n
+\t\t\t//Cache variables and intersection, continue if no intersection\n
+\t\t\titem = this.items[i];\n
+\t\t\titemElement = item.item[0];\n
+\t\t\tintersection = this._intersectsWithPointer(item);\n
+\t\t\tif (!intersection) {\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\t// Only put the placeholder inside the current Container, skip all\n
+\t\t\t// items from other containers. This works because when moving\n
+\t\t\t// an item from one container to another the\n
+\t\t\t// currentContainer is switched before the placeholder is moved.\n
+\t\t\t//\n
+\t\t\t// Without this, moving items in "sub-sortables" can cause\n
+\t\t\t// the placeholder to jitter beetween the outer and inner container.\n
+\t\t\tif (item.instance !== this.currentContainer) {\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\t// cannot intersect with itself\n
+\t\t\t// no useless actions that have been done before\n
+\t\t\t// no action if the item moved is the parent of the item checked\n
+\t\t\tif (itemElement !== this.currentItem[0] &&\n
+\t\t\t\tthis.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&\n
+\t\t\t\t!$.contains(this.placeholder[0], itemElement) &&\n
+\t\t\t\t(this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)\n
+\t\t\t) {\n
+\n
+\t\t\t\tthis.direction = intersection === 1 ? "down" : "up";\n
+\n
+\t\t\t\tif (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {\n
+\t\t\t\t\tthis._rearrange(event, item);\n
+\t\t\t\t} else {\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tthis._trigger("change", event, this._uiHash());\n
+\t\t\t\tbreak;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t//Post events to containers\n
+\t\tthis._contactContainers(event);\n
+\n
+\t\t//Interconnect with droppables\n
+\t\tif($.ui.ddmanager) {\n
+\t\t\t$.ui.ddmanager.drag(this, event);\n
+\t\t}\n
+\n
+\t\t//Call callbacks\n
+\t\tthis._trigger("sort", event, this._uiHash());\n
+\n
+\t\tthis.lastPositionAbs = this.positionAbs;\n
+\t\treturn false;\n
+\n
+\t},\n
+\n
+\t_mouseStop: function(event, noPropagation) {\n
+\n
+\t\tif(!event) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t//If we are using droppables, inform the manager about the drop\n
+\t\tif ($.ui.ddmanager && !this.options.dropBehaviour) {\n
+\t\t\t$.ui.ddmanager.drop(this, event);\n
+\t\t}\n
+\n
+\t\tif(this.options.revert) {\n
+\t\t\tvar that = this,\n
+\t\t\t\tcur = this.placeholder.offset(),\n
+\t\t\t\taxis = this.options.axis,\n
+\t\t\t\tanimation = {};\n
+\n
+\t\t\tif ( !axis || axis === "x" ) {\n
+\t\t\t\tanimation.left = cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft);\n
+\t\t\t}\n
+\t\t\tif ( !axis || axis === "y" ) {\n
+\t\t\t\tanimation.top = cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop);\n
+\t\t\t}\n
+\t\t\tthis.reverting = true;\n
+\t\t\t$(this.helper).animate( animation, parseInt(this.options.revert, 10) || 500, function() {\n
+\t\t\t\tthat._clear(event);\n
+\t\t\t});\n
+\t\t} else {\n
+\t\t\tthis._clear(event, noPropagation);\n
+\t\t}\n
+\n
+\t\treturn false;\n
+\n
+\t},\n
+\n
+\tcancel: function() {\n
+\n
+\t\tif(this.dragging) {\n
+\n
+\t\t\tthis._mouseUp({ target: null });\n
+\n
+\t\t\tif(this.options.helper === "original") {\n
+\t\t\t\tthis.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");\n
+\t\t\t} else {\n
+\t\t\t\tthis.currentItem.show();\n
+\t\t\t}\n
+\n
+\t\t\t//Post deactivating events to containers\n
+\t\t\tfor (var i = this.containers.length - 1; i >= 0; i--){\n
+\t\t\t\tthis.containers[i]._trigger("deactivate", null, this._uiHash(this));\n
+\t\t\t\tif(this.containers[i].containerCache.over) {\n
+\t\t\t\t\tthis.containers[i]._trigger("out", null, this._uiHash(this));\n
+\t\t\t\t\tthis.containers[i].containerCache.over = 0;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t}\n
+\n
+\t\tif (this.placeholder) {\n
+\t\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!\n
+\t\t\tif(this.placeholder[0].parentNode) {\n
+\t\t\t\tthis.placeholder[0].parentNode.removeChild(this.placeholder[0]);\n
+\t\t\t}\n
+\t\t\tif(this.options.helper !== "original" && this.helper && this.helper[0].parentNode) {\n
+\t\t\t\tthis.helper.remove();\n
+\t\t\t}\n
+\n
+\t\t\t$.extend(this, {\n
+\t\t\t\thelper: null,\n
+\t\t\t\tdragging: false,\n
+\t\t\t\treverting: false,\n
+\t\t\t\t_noFinalSort: null\n
+\t\t\t});\n
+\n
+\t\t\tif(this.domPosition.prev) {\n
+\t\t\t\t$(this.domPosition.prev).after(this.currentItem);\n
+\t\t\t} else {\n
+\t\t\t\t$(this.domPosition.parent).prepend(this.currentItem);\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\n
+\t},\n
+\n
+\tserialize: function(o) {\n
+\n
+\t\tvar items = this._getItemsAsjQuery(o && o.connected),\n
+\t\t\tstr = [];\n
+\t\to = o || {};\n
+\n
+\t\t$(items).each(function() {\n
+\t\t\tvar res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\\-=_](.+)/));\n
+\t\t\tif (res) {\n
+\t\t\t\tstr.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tif(!str.length && o.key) {\n
+\t\t\tstr.push(o.key + "=");\n
+\t\t}\n
+\n
+\t\treturn str.join("&");\n
+\n
+\t},\n
+\n
+\ttoArray: function(o) {\n
+\n
+\t\tvar items = this._getItemsAsjQuery(o && o.connected),\n
+\t\t\tret = [];\n
+\n
+\t\to = o || {};\n
+\n
+\t\titems.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });\n
+\t\treturn ret;\n
+\n
+\t},\n
+\n
+\t/* Be careful with the following core functions */\n
+\t_intersectsWith: function(item) {\n
+\n
+\t\tvar x1 = this.positionAbs.left,\n
+\t\t\tx2 = x1 + this.helperProportions.width,\n
+\t\t\ty1 = this.positionAbs.top,\n
+\t\t\ty2 = y1 + this.helperProportions.height,\n
+\t\t\tl = item.left,\n
+\t\t\tr = l + item.width,\n
+\t\t\tt = item.top,\n
+\t\t\tb = t + item.height,\n
+\t\t\tdyClick = this.offset.click.top,\n
+\t\t\tdxClick = this.offset.click.left,\n
+\t\t\tisOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t && ( y1 + dyClick ) < b ),\n
+\t\t\tisOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l && ( x1 + dxClick ) < r ),\n
+\t\t\tisOverElement = isOverElementHeight && isOverElementWidth;\n
+\n
+\t\tif ( this.options.tolerance === "pointer" ||\n
+\t\t\tthis.options.forcePointerForContainers ||\n
+\t\t\t(this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])\n
+\t\t) {\n
+\t\t\treturn isOverElement;\n
+\t\t} else {\n
+\n
+\t\t\treturn (l < x1 + (this.helperProportions.width / 2) && // Right Half\n
+\t\t\t\tx2 - (this.helperProportions.width / 2) < r && // Left Half\n
+\t\t\t\tt < y1 + (this.helperProportions.height / 2) && // Bottom Half\n
+\t\t\t\ty2 - (this.helperProportions.height / 2) < b ); // Top Half\n
+\n
+\t\t}\n
+\t},\n
+\n
+\t_intersectsWithPointer: function(item) {\n
+\n
+\t\tvar isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),\n
+\t\t\tisOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),\n
+\t\t\tisOverElement = isOverElementHeight && isOverElementWidth,\n
+\t\t\tverticalDirection = this._getDragVerticalDirection(),\n
+\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n
+\n
+\t\tif (!isOverElement) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\treturn this.floating ?\n
+\t\t\t( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )\n
+\t\t\t: ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );\n
+\n
+\t},\n
+\n
+\t_intersectsWithSides: function(item) {\n
+\n
+\t\tvar isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),\n
+\t\t\tisOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),\n
+\t\t\tverticalDirection = this._getDragVerticalDirection(),\n
+\t\t\thorizontalDirection = this._getDragHorizontalDirection();\n
+\n
+\t\tif (this.floating && horizontalDirection) {\n
+\t\t\treturn ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));\n
+\t\t} else {\n
+\t\t\treturn verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));\n
+\t\t}\n
+\n
+\t},\n
+\n
+\t_getDragVerticalDirection: function() {\n
+\t\tvar delta = this.positionAbs.top - this.lastPositionAbs.top;\n
+\t\treturn delta !== 0 && (delta > 0 ? "down" : "up");\n
+\t},\n
+\n
+\t_getDragHorizontalDirection: function() {\n
+\t\tvar delta = this.positionAbs.left - this.lastPositionAbs.left;\n
+\t\treturn delta !== 0 && (delta > 0 ? "right" : "left");\n
+\t},\n
+\n
+\trefresh: function(event) {\n
+\t\tthis._refreshItems(event);\n
+\t\tthis.refreshPositions();\n
+\t\treturn this;\n
+\t},\n
+\n
+\t_connectWith: function() {\n
+\t\tvar options = this.options;\n
+\t\treturn options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;\n
+\t},\n
+\n
+\t_getItemsAsjQuery: function(connected) {\n
+\n
+\t\tvar i, j, cur, inst,\n
+\t\t\titems = [],\n
+\t\t\tqueries = [],\n
+\t\t\tconnectWith = this._connectWith();\n
+\n
+\t\tif(connectWith && connected) {\n
+\t\t\tfor (i = connectWith.length - 1; i >= 0; i--){\n
+\t\t\t\tcur = $(connectWith[i]);\n
+\t\t\t\tfor ( j = cur.length - 1; j >= 0; j--){\n
+\t\t\t\t\tinst = $.data(cur[j], this.widgetFullName);\n
+\t\t\t\t\tif(inst && inst !== this && !inst.options.disabled) {\n
+\t\t\t\t\t\tqueries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]);\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tqueries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);\n
+\n
+\t\tfunction addItems() {\n
+\t\t\titems.push( this );\n
+\t\t}\n
+\t\tfor (i = queries.length - 1; i >= 0; i--){\n
+\t\t\tqueries[i][0].each( addItems );\n
+\t\t}\n
+\n
+\t\treturn $(items);\n
+\n
+\t},\n
+\n
+\t_removeCurrentsFromItems: function() {\n
+\n
+\t\tvar list = this.currentItem.find(":data(" + this.widgetName + "-item)");\n
+\n
+\t\tthis.items = $.grep(this.items, function (item) {\n
+\t\t\tfor (var j=0; j < list.length; j++) {\n
+\t\t\t\tif(list[j] === item.item[0]) {\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\treturn true;\n
+\t\t});\n
+\n
+\t},\n
+\n
+\t_refreshItems: function(event) {\n
+\n
+\t\tthis.items = [];\n
+\t\tthis.containers = [this];\n
+\n
+\t\tvar i, j, cur, inst, targetData, _queries, item, queriesLength,\n
+\t\t\titems = this.items,\n
+\t\t\tqueries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],\n
+\t\t\tconnectWith = this._connectWith();\n
+\n
+\t\tif(connectWith && this.ready) { //Shouldn\'t be run the first time through due to massive slow-down\n
+\t\t\tfor (i = connectWith.length - 1; i >= 0; i--){\n
+\t\t\t\tcur = $(connectWith[i]);\n
+\t\t\t\tfor (j = cur.length - 1; j >= 0; j--){\n
+\t\t\t\t\tinst = $.data(cur[j], this.widgetFullName);\n
+\t\t\t\t\tif(inst && inst !== this && !inst.options.disabled) {\n
+\t\t\t\t\t\tqueries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);\n
+\t\t\t\t\t\tthis.containers.push(inst);\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tfor (i = queries.length - 1; i >= 0; i--) {\n
+\t\t\ttargetData = queries[i][1];\n
+\t\t\t_queries = queries[i][0];\n
+\n
+\t\t\tfor (j=0, queriesLength = _queries.length; j < queriesLength; j++) {\n
+\t\t\t\titem = $(_queries[j]);\n
+\n
+\t\t\t\titem.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)\n
+\n
+\t\t\t\titems.push({\n
+\t\t\t\t\titem: item,\n
+\t\t\t\t\tinstance: targetData,\n
+\t\t\t\t\twidth: 0, height: 0,\n
+\t\t\t\t\tleft: 0, top: 0\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t},\n
+\n
+\trefreshPositions: function(fast) {\n
+\n
+\t\t//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent\'s position will change\n
+\t\tif(this.offsetParent && this.helper) {\n
+\t\t\tthis.offset.parent = this._getParentOffset();\n
+\t\t}\n
+\n
+\t\tvar i, item, t, p;\n
+\n
+\t\tfor (i = this.items.length - 1; i >= 0; i--){\n
+\t\t\titem = this.items[i];\n
+\n
+\t\t\t//We ignore calculating positions of all connected containers when we\'re not over them\n
+\t\t\tif(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\tt = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;\n
+\n
+\t\t\tif (!fast) {\n
+\t\t\t\titem.width = t.outerWidth();\n
+\t\t\t\titem.height = t.outerHeight();\n
+\t\t\t}\n
+\n
+\t\t\tp = t.offset();\n
+\t\t\titem.left = p.left;\n
+\t\t\titem.top = p.top;\n
+\t\t}\n
+\n
+\t\tif(this.options.custom && this.options.custom.refreshContainers) {\n
+\t\t\tthis.options.custom.refreshContainers.call(this);\n
+\t\t} else {\n
+\t\t\tfor (i = this.containers.length - 1; i >= 0; i
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAc=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="7" aka="AAAAAAAAAAc=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+--){\n
+\t\t\t\tp = this.containers[i].element.offset();\n
+\t\t\t\tthis.containers[i].containerCache.left = p.left;\n
+\t\t\t\tthis.containers[i].containerCache.top = p.top;\n
+\t\t\t\tthis.containers[i].containerCache.width\t= this.containers[i].element.outerWidth();\n
+\t\t\t\tthis.containers[i].containerCache.height = this.containers[i].element.outerHeight();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\t_createPlaceholder: function(that) {\n
+\t\tthat = that || this;\n
+\t\tvar className,\n
+\t\t\to = that.options;\n
+\n
+\t\tif(!o.placeholder || o.placeholder.constructor === String) {\n
+\t\t\tclassName = o.placeholder;\n
+\t\t\to.placeholder = {\n
+\t\t\t\telement: function() {\n
+\n
+\t\t\t\t\tvar nodeName = that.currentItem[0].nodeName.toLowerCase(),\n
+\t\t\t\t\t\telement = $( "<" + nodeName + ">", that.document[0] )\n
+\t\t\t\t\t\t\t.addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")\n
+\t\t\t\t\t\t\t.removeClass("ui-sortable-helper");\n
+\n
+\t\t\t\t\tif ( nodeName === "tr" ) {\n
+\t\t\t\t\t\tthat.currentItem.children().each(function() {\n
+\t\t\t\t\t\t\t$( "<td>&#160;</td>", that.document[0] )\n
+\t\t\t\t\t\t\t\t.attr( "colspan", $( this ).attr( "colspan" ) || 1 )\n
+\t\t\t\t\t\t\t\t.appendTo( element );\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t} else if ( nodeName === "img" ) {\n
+\t\t\t\t\t\telement.attr( "src", that.currentItem.attr( "src" ) );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tif ( !className ) {\n
+\t\t\t\t\t\telement.css( "visibility", "hidden" );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\treturn element;\n
+\t\t\t\t},\n
+\t\t\t\tupdate: function(container, p) {\n
+\n
+\t\t\t\t\t// 1. If a className is set as \'placeholder option, we don\'t force sizes - the class is responsible for that\n
+\t\t\t\t\t// 2. The option \'forcePlaceholderSize can be enabled to force it even if a class name is specified\n
+\t\t\t\t\tif(className && !o.forcePlaceholderSize) {\n
+\t\t\t\t\t\treturn;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t//If the element doesn\'t have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item\n
+\t\t\t\t\tif(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }\n
+\t\t\t\t\tif(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }\n
+\t\t\t\t}\n
+\t\t\t};\n
+\t\t}\n
+\n
+\t\t//Create the placeholder\n
+\t\tthat.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));\n
+\n
+\t\t//Append it after the actual current item\n
+\t\tthat.currentItem.after(that.placeholder);\n
+\n
+\t\t//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)\n
+\t\to.placeholder.update(that, that.placeholder);\n
+\n
+\t},\n
+\n
+\t_contactContainers: function(event) {\n
+\t\tvar i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom, floating,\n
+\t\t\tinnermostContainer = null,\n
+\t\t\tinnermostIndex = null;\n
+\n
+\t\t// get innermost container that intersects with item\n
+\t\tfor (i = this.containers.length - 1; i >= 0; i--) {\n
+\n
+\t\t\t// never consider a container that\'s located within the item itself\n
+\t\t\tif($.contains(this.currentItem[0], this.containers[i].element[0])) {\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\tif(this._intersectsWith(this.containers[i].containerCache)) {\n
+\n
+\t\t\t\t// if we\'ve already found a container and it\'s more "inner" than this, then continue\n
+\t\t\t\tif(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {\n
+\t\t\t\t\tcontinue;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tinnermostContainer = this.containers[i];\n
+\t\t\t\tinnermostIndex = i;\n
+\n
+\t\t\t} else {\n
+\t\t\t\t// container doesn\'t intersect. trigger "out" event if necessary\n
+\t\t\t\tif(this.containers[i].containerCache.over) {\n
+\t\t\t\t\tthis.containers[i]._trigger("out", event, this._uiHash(this));\n
+\t\t\t\t\tthis.containers[i].containerCache.over = 0;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t}\n
+\n
+\t\t// if no intersecting containers found, return\n
+\t\tif(!innermostContainer) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// move the item into the container if it\'s not there already\n
+\t\tif(this.containers.length === 1) {\n
+\t\t\tif (!this.containers[innermostIndex].containerCache.over) {\n
+\t\t\t\tthis.containers[innermostIndex]._trigger("over", event, this._uiHash(this));\n
+\t\t\t\tthis.containers[innermostIndex].containerCache.over = 1;\n
+\t\t\t}\n
+\t\t} else {\n
+\n
+\t\t\t//When entering a new container, we will find the item with the least distance and append our item near it\n
+\t\t\tdist = 10000;\n
+\t\t\titemWithLeastDistance = null;\n
+\t\t\tfloating = innermostContainer.floating || isFloating(this.currentItem);\n
+\t\t\tposProperty = floating ? "left" : "top";\n
+\t\t\tsizeProperty = floating ? "width" : "height";\n
+\t\t\tbase = this.positionAbs[posProperty] + this.offset.click[posProperty];\n
+\t\t\tfor (j = this.items.length - 1; j >= 0; j--) {\n
+\t\t\t\tif(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {\n
+\t\t\t\t\tcontinue;\n
+\t\t\t\t}\n
+\t\t\t\tif(this.items[j].item[0] === this.currentItem[0]) {\n
+\t\t\t\t\tcontinue;\n
+\t\t\t\t}\n
+\t\t\t\tif (floating && !isOverAxis(this.positionAbs.top + this.offset.click.top, this.items[j].top, this.items[j].height)) {\n
+\t\t\t\t\tcontinue;\n
+\t\t\t\t}\n
+\t\t\t\tcur = this.items[j].item.offset()[posProperty];\n
+\t\t\t\tnearBottom = false;\n
+\t\t\t\tif(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){\n
+\t\t\t\t\tnearBottom = true;\n
+\t\t\t\t\tcur += this.items[j][sizeProperty];\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif(Math.abs(cur - base) < dist) {\n
+\t\t\t\t\tdist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];\n
+\t\t\t\t\tthis.direction = nearBottom ? "up": "down";\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t//Check if dropOnEmpty is enabled\n
+\t\t\tif(!itemWithLeastDistance && !this.options.dropOnEmpty) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tif(this.currentContainer === this.containers[innermostIndex]) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\titemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);\n
+\t\t\tthis._trigger("change", event, this._uiHash());\n
+\t\t\tthis.containers[innermostIndex]._trigger("change", event, this._uiHash(this));\n
+\t\t\tthis.currentContainer = this.containers[innermostIndex];\n
+\n
+\t\t\t//Update the placeholder\n
+\t\t\tthis.options.placeholder.update(this.currentContainer, this.placeholder);\n
+\n
+\t\t\tthis.containers[innermostIndex]._trigger("over", event, this._uiHash(this));\n
+\t\t\tthis.containers[innermostIndex].containerCache.over = 1;\n
+\t\t}\n
+\n
+\n
+\t},\n
+\n
+\t_createHelper: function(event) {\n
+\n
+\t\tvar o = this.options,\n
+\t\t\thelper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);\n
+\n
+\t\t//Add the helper to the DOM if that didn\'t happen already\n
+\t\tif(!helper.parents("body").length) {\n
+\t\t\t$(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);\n
+\t\t}\n
+\n
+\t\tif(helper[0] === this.currentItem[0]) {\n
+\t\t\tthis._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };\n
+\t\t}\n
+\n
+\t\tif(!helper[0].style.width || o.forceHelperSize) {\n
+\t\t\thelper.width(this.currentItem.width());\n
+\t\t}\n
+\t\tif(!helper[0].style.height || o.forceHelperSize) {\n
+\t\t\thelper.height(this.currentItem.height());\n
+\t\t}\n
+\n
+\t\treturn helper;\n
+\n
+\t},\n
+\n
+\t_adjustOffsetFromHelper: function(obj) {\n
+\t\tif (typeof obj === "string") {\n
+\t\t\tobj = obj.split(" ");\n
+\t\t}\n
+\t\tif ($.isArray(obj)) {\n
+\t\t\tobj = {left: +obj[0], top: +obj[1] || 0};\n
+\t\t}\n
+\t\tif ("left" in obj) {\n
+\t\t\tthis.offset.click.left = obj.left + this.margins.left;\n
+\t\t}\n
+\t\tif ("right" in obj) {\n
+\t\t\tthis.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;\n
+\t\t}\n
+\t\tif ("top" in obj) {\n
+\t\t\tthis.offset.click.top = obj.top + this.margins.top;\n
+\t\t}\n
+\t\tif ("bottom" in obj) {\n
+\t\t\tthis.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;\n
+\t\t}\n
+\t},\n
+\n
+\t_getParentOffset: function() {\n
+\n
+\n
+\t\t//Get the offsetParent and cache its position\n
+\t\tthis.offsetParent = this.helper.offsetParent();\n
+\t\tvar po = this.offsetParent.offset();\n
+\n
+\t\t// This is a special case where we need to modify a offset calculated on start, since the following happened:\n
+\t\t// 1. The position of the helper is absolute, so it\'s position is calculated based on the next positioned parent\n
+\t\t// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn\'t the document, which means that\n
+\t\t//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag\n
+\t\tif(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {\n
+\t\t\tpo.left += this.scrollParent.scrollLeft();\n
+\t\t\tpo.top += this.scrollParent.scrollTop();\n
+\t\t}\n
+\n
+\t\t// This needs to be actually done for all browsers, since pageX/pageY includes this information\n
+\t\t// with an ugly IE fix\n
+\t\tif( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {\n
+\t\t\tpo = { top: 0, left: 0 };\n
+\t\t}\n
+\n
+\t\treturn {\n
+\t\t\ttop: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),\n
+\t\t\tleft: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)\n
+\t\t};\n
+\n
+\t},\n
+\n
+\t_getRelativeOffset: function() {\n
+\n
+\t\tif(this.cssPosition === "relative") {\n
+\t\t\tvar p = this.currentItem.position();\n
+\t\t\treturn {\n
+\t\t\t\ttop: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),\n
+\t\t\t\tleft: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()\n
+\t\t\t};\n
+\t\t} else {\n
+\t\t\treturn { top: 0, left: 0 };\n
+\t\t}\n
+\n
+\t},\n
+\n
+\t_cacheMargins: function() {\n
+\t\tthis.margins = {\n
+\t\t\tleft: (parseInt(this.currentItem.css("marginLeft"),10) || 0),\n
+\t\t\ttop: (parseInt(this.currentItem.css("marginTop"),10) || 0)\n
+\t\t};\n
+\t},\n
+\n
+\t_cacheHelperProportions: function() {\n
+\t\tthis.helperProportions = {\n
+\t\t\twidth: this.helper.outerWidth(),\n
+\t\t\theight: this.helper.outerHeight()\n
+\t\t};\n
+\t},\n
+\n
+\t_setContainment: function() {\n
+\n
+\t\tvar ce, co, over,\n
+\t\t\to = this.options;\n
+\t\tif(o.containment === "parent") {\n
+\t\t\to.containment = this.helper[0].parentNode;\n
+\t\t}\n
+\t\tif(o.containment === "document" || o.containment === "window") {\n
+\t\t\tthis.containment = [\n
+\t\t\t\t0 - this.offset.relative.left - this.offset.parent.left,\n
+\t\t\t\t0 - this.offset.relative.top - this.offset.parent.top,\n
+\t\t\t\t$(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,\n
+\t\t\t\t($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top\n
+\t\t\t];\n
+\t\t}\n
+\n
+\t\tif(!(/^(document|window|parent)$/).test(o.containment)) {\n
+\t\t\tce = $(o.containment)[0];\n
+\t\t\tco = $(o.containment).offset();\n
+\t\t\tover = ($(ce).css("overflow") !== "hidden");\n
+\n
+\t\t\tthis.containment = [\n
+\t\t\t\tco.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,\n
+\t\t\t\tco.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,\n
+\t\t\t\tco.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,\n
+\t\t\t\tco.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top\n
+\t\t\t];\n
+\t\t}\n
+\n
+\t},\n
+\n
+\t_convertPositionTo: function(d, pos) {\n
+\n
+\t\tif(!pos) {\n
+\t\t\tpos = this.position;\n
+\t\t}\n
+\t\tvar mod = d === "absolute" ? 1 : -1,\n
+\t\t\tscroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,\n
+\t\t\tscrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);\n
+\n
+\t\treturn {\n
+\t\t\ttop: (\n
+\t\t\t\tpos.top\t+\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n
+\t\t\t\tthis.offset.relative.top * mod +\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n
+\t\t\t\tthis.offset.parent.top * mod -\t\t\t\t\t\t\t\t\t\t\t// The offsetParent\'s offset without borders (offset + border)\n
+\t\t\t\t( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)\n
+\t\t\t),\n
+\t\t\tleft: (\n
+\t\t\t\tpos.left +\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n
+\t\t\t\tthis.offset.relative.left * mod +\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n
+\t\t\t\tthis.offset.parent.left * mod\t-\t\t\t\t\t\t\t\t\t\t// The offsetParent\'s offset without borders (offset + border)\n
+\t\t\t\t( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)\n
+\t\t\t)\n
+\t\t};\n
+\n
+\t},\n
+\n
+\t_generatePosition: function(event) {\n
+\n
+\t\tvar top, left,\n
+\t\t\to = this.options,\n
+\t\t\tpageX = event.pageX,\n
+\t\t\tpageY = event.pageY,\n
+\t\t\tscroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);\n
+\n
+\t\t// This is another very weird special case that only happens for relative elements:\n
+\t\t// 1. If the css position is relative\n
+\t\t// 2. and the scroll parent is the document or similar to the offset parent\n
+\t\t// we have to refresh the relative offset during the scroll so there are no jumps\n
+\t\tif(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {\n
+\t\t\tthis.offset.relative = this._getRelativeOffset();\n
+\t\t}\n
+\n
+\t\t/*\n
+\t\t * - Position constraining -\n
+\t\t * Constrain the position to a mix of grid, containment.\n
+\t\t */\n
+\n
+\t\tif(this.originalPosition) { //If we are not dragging yet, we won\'t check for options\n
+\n
+\t\t\tif(this.containment) {\n
+\t\t\t\tif(event.pageX - this.offset.click.left < this.containment[0]) {\n
+\t\t\t\t\tpageX = this.containment[0] + this.offset.click.left;\n
+\t\t\t\t}\n
+\t\t\t\tif(event.pageY - this.offset.click.top < this.containment[1]) {\n
+\t\t\t\t\tpageY = this.containment[1] + this.offset.click.top;\n
+\t\t\t\t}\n
+\t\t\t\tif(event.pageX - this.offset.click.left > this.containment[2]) {\n
+\t\t\t\t\tpageX = this.containment[2] + this.offset.click.left;\n
+\t\t\t\t}\n
+\t\t\t\tif(event.pageY - this.offset.click.top > this.containment[3]) {\n
+\t\t\t\t\tpageY = this.containment[3] + this.offset.click.top;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif(o.grid) {\n
+\t\t\t\ttop = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];\n
+\t\t\t\tpageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;\n
+\n
+\t\t\t\tleft = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];\n
+\t\t\t\tpageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;\n
+\t\t\t}\n
+\n
+\t\t}\n
+\n
+\t\treturn {\n
+\t\t\ttop: (\n
+\t\t\t\tpageY -\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n
+\t\t\t\tthis.offset.click.top -\t\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n
+\t\t\t\tthis.offset.relative.top\t-\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n
+\t\t\t\tthis.offset.parent.top +\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent\'s offset without borders (offset + border)\n
+\t\t\t\t( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))\n
+\t\t\t),\n
+\t\t\tleft: (\n
+\t\t\t\tpageX -\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t// The absolute mouse position\n
+\t\t\t\tthis.offset.click.left -\t\t\t\t\t\t\t\t\t\t\t\t// Click offset (relative to the element)\n
+\t\t\t\tthis.offset.relative.left\t-\t\t\t\t\t\t\t\t\t\t\t// Only for relative positioned nodes: Relative offset from element to offset parent\n
+\t\t\t\tthis.offset.parent.left +\t\t\t\t\t\t\t\t\t\t\t\t// The offsetParent\'s offset without borders (offset + border)\n
+\t\t\t\t( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))\n
+\t\t\t)\n
+\t\t};\n
+\n
+\t},\n
+\n
+\t_rearrange: function(event, i, a, hardRefresh) {\n
+\n
+\t\ta ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));\n
+\n
+\t\t//Various things done here to improve the performance:\n
+\t\t// 1. we create a setTimeout, that calls refreshPositions\n
+\t\t// 2. on the instance, we have a counter variable, that get\'s higher after every append\n
+\t\t// 3. on the local scope, we copy the counter variable, and check in the timeout, if it\'s still the same\n
+\t\t// 4. this lets only the last addition to the timeout stack through\n
+\t\tthis.counter = this.counter ? ++this.counter : 1;\n
+\t\tvar counter = this.counter;\n
+\n
+\t\tthis._delay(function() {\n
+\t\t\tif(counter === this.counter) {\n
+\t\t\t\tthis.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t},\n
+\n
+\t_clear: function(event, noPropagation) {\n
+\n
+\t\tthis.reverting = false;\n
+\t\t// We delay all events that have to be triggered to after the point where the placeholder has been removed and\n
+\t\t// everything else normalized again\n
+\t\tvar i,\n
+\t\t\tdelayedTriggers = [];\n
+\n
+\t\t// We first have to update the dom position of the actual currentItem\n
+\t\t// Note: don\'t do it if the current item is already removed (by a user), or it gets reappended (see #4088)\n
+\t\tif(!this._noFinalSort && this.currentItem.parent().length) {\n
+\t\t\tthis.placeholder.before(this.currentItem);\n
+\t\t}\n
+\t\tthis._noFinalSort = null;\n
+\n
+\t\tif(this.helper[0] === this.currentItem[0]) {\n
+\t\t\tfor(i in this._storedCSS) {\n
+\t\t\t\tif(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {\n
+\t\t\t\t\tthis._storedCSS[i] = "";\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tthis.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");\n
+\t\t} else {\n
+\t\t\tthis.currentItem.show();\n
+\t\t}\n
+\n
+\t\tif(this.fromOutside && !noPropagation) {\n
+\t\t\tdelayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });\n
+\t\t}\n
+\t\tif((this.fromOutside || this.domPosition.prev !== this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent !== this.currentItem.parent()[0]) && !noPropagation) {\n
+\t\t\tdelayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed\n
+\t\t}\n
+\n
+\t\t// Check if the items Container has Changed and trigger appropriate\n
+\t\t// events.\n
+\t\tif (this !== this.currentContainer) {\n
+\t\t\tif(!noPropagation) {\n
+\t\t\t\tdelayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });\n
+\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));\n
+\t\t\t\tdelayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));\n
+\t\t\t}\n
+\t\t}\n
+\n
+\n
+\t\t//Post events to containers\n
+\t\tfunction delayEvent( type, instance, container ) {\n
+\t\t\treturn function( event ) {\n
+\t\t\t\tcontainer._trigger( type, event, instance._uiHash( instance ) );\n
+\t\t\t};\n
+\t\t}\n
+\t\tfor (i = this.containers.length - 1; i >= 0; i--){\n
+\t\t\tif (!noPropagation) {\n
+\t\t\t\tdelayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );\n
+\t\t\t}\n
+\t\t\tif(this.containers[i].containerCache.over) {\n
+\t\t\t\tdelayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );\n
+\t\t\t\tthis.containers[i].containerCache.over = 0;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t//Do what was originally in plugins\n
+\t\tif ( this.storedCursor ) {\n
+\t\t\tthis.document.find( "body" ).css( "cursor", this.storedCursor );\n
+\t\t\tthis.storedStylesheet.remove();\n
+\t\t}\n
+\t\tif(this._storedOpacity) {\n
+\t\t\tthis.helper.css("opacity", this._storedOpacity);\n
+\t\t}\n
+\t\tif(this._storedZIndex) {\n
+\t\t\tthis.helper.css("zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex);\n
+\t\t}\n
+\n
+\t\tthis.dragging = false;\n
+\t\tif(this.cancelHelperRemoval) {\n
+\t\t\tif(!noPropagation) {\n
+\t\t\t\tthis._trigger("beforeStop", event, this._uiHash());\n
+\t\t\t\tfor (i=0; i < delayedTriggers.length; i++) {\n
+\t\t\t\t\tdelayedTriggers[i].call(this, event);\n
+\t\t\t\t} //Trigger all delayed events\n
+\t\t\t\tthis._trigger("stop", event, this._uiHash());\n
+\t\t\t}\n
+\n
+\t\t\tthis.fromOutside = false;\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\tif(!noPropagation) {\n
+\t\t\tthis._trigger("beforeStop", event, this._uiHash());\n
+\t\t}\n
+\n
+\t\t//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!\n
+\t\tthis.placeholder[0].parentNode.removeChild(this.placeholder[0]);\n
+\n
+\t\tif(this.helper[0] !== this.currentItem[0]) {\n
+\t\t\tthis.helper.remove();\n
+\t\t}\n
+\t\tthis.helper = null;\n
+\n
+\t\tif(!noPropagation) {\n
+\t\t\tfor (i=0; i < delayedTriggers.length; i++) {\n
+\t\t\t\tdelayedTriggers[i].call(this, event);\n
+\t\t\t} //Trigger all delayed events\n
+\t\t\tthis._trigger("stop", event, this._uiHash());\n
+\t\t}\n
+\n
+\t\tthis.fromOutside = false;\n
+\t\treturn true;\n
+\n
+\t},\n
+\n
+\t_trigger: function() {\n
+\t\tif ($.Widget.prototype._trigger.apply(this, arguments) === false) {\n
+\t\t\tthis.cancel();\n
+\t\t}\n
+\t},\n
+\n
+\t_uiHash: function(_inst) {\n
+\t\tvar inst = _inst || this;\n
+\t\treturn {\n
+\t\t\thelper: inst.helper,\n
+\t\t\tplaceholder: inst.placeholder || $([]),\n
+\t\t\tposition: inst.position,\n
+\t\t\toriginalPosition: inst.originalPosition,\n
+\t\t\toffset: inst.positionAbs,\n
+\t\t\titem: inst.currentItem,\n
+\t\t\tsender: _inst ? _inst.element : null\n
+\t\t};\n
+\t}\n
+\n
+});\n
+\n
+})(jQuery);\n
+(function( $ ) {\n
+\n
+function modifier( fn ) {\n
+\treturn function() {\n
+\t\tvar previous = this.element.val();\n
+\t\tfn.apply( this, arguments );\n
+\t\tthis._refresh();\n
+\t\tif ( previous !== this.element.val() ) {\n
+\t\t\tthis._trigger( "change" );\n
+\t\t}\n
+\t};\n
+}\n
+\n
+$.widget( "ui.spinner", {\n
+\tversion: "1.10.4",\n
+\tdefaultElement: "<input>",\n
+\twidgetEventPrefix: "spin",\n
+\toptions: {\n
+\t\tculture: null,\n
+\t\ticons: {\n
+\t\t\tdown: "ui-icon-triangle-1-s",\n
+\t\t\tup: "ui-icon-triangle-1-n"\n
+\t\t},\n
+\t\tincremental: true,\n
+\t\tmax: null,\n
+\t\tmin: null,\n
+\t\tnumberFormat: null,\n
+\t\tpage: 10,\n
+\t\tstep: 1,\n
+\n
+\t\tchange: null,\n
+\t\tspin: null,\n
+\t\tstart: null,\n
+\t\tstop: null\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\t// handle string values that need to be parsed\n
+\t\tthis._setOption( "max", this.options.max );\n
+\t\tthis._setOption( "min", this.options.min );\n
+\t\tthis._setOption( "step", this.options.step );\n
+\n
+\t\t// Only format if there is a value, prevents the field from being marked\n
+\t\t// as invalid in Firefox, see #9573.\n
+\t\tif ( this.value() !== "" ) {\n
+\t\t\t// Format the value, but don\'t constrain.\n
+\t\t\tthis._value( this.element.val(), true );\n
+\t\t}\n
+\n
+\t\tthis._draw();\n
+\t\tthis._on( this._events );\n
+\t\tthis._refresh();\n
+\n
+\t\t// turning off autocomplete prevents the browser from remembering the\n
+\t\t// value when navigating through history, so we re-enable autocomplete\n
+\t\t// if the page is unloaded before the widget is destroyed. #7790\n
+\t\tthis._on( this.window, {\n
+\t\t\tbeforeunload: function() {\n
+\t\t\t\tthis.element.removeAttr( "autocomplete" );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_getCreateOptions: function() {\n
+\t\tvar options = {},\n
+\t\t\telement = this.element;\n
+\n
+\t\t$.each( [ "min", "max", "step" ], function( i, option ) {\n
+\t\t\tvar value = element.attr( option );\n
+\t\t\tif ( value !== undefined && value.length ) {\n
+\t\t\t\toptions[ option ] = value;\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\treturn options;\n
+\t},\n
+\n
+\t_events: {\n
+\t\tkeydown: function( event ) {\n
+\t\t\tif ( this._start( event ) && this._keydown( event ) ) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t}\n
+\t\t},\n
+\t\tkeyup: "_stop",\n
+\t\tfocus: function() {\n
+\t\t\tthis.previous = this.element.val();\n
+\t\t},\n
+\t\tblur: function( event ) {\n
+\t\t\tif ( this.cancelBlur ) {\n
+\t\t\t\tdelete this.cancelBlur;\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tthis._stop();\n
+\t\t\tthis._refresh();\n
+\t\t\tif ( this.previous !== this.element.val() ) {\n
+\t\t\t\tthis._trigger( "change", event );\n
+\t\t\t}\n
+\t\t},\n
+\t\tmousewheel: function( event, delta ) {\n
+\t\t\tif ( !delta ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\tif ( !this.spinning && !this._start( event ) ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\n
+\t\t\tthis._spin( (delta > 0 ? 1 : -1) * this.options.step, event );\n
+\t\t\tclearTimeout( this.mousewheelTimer );\n
+\t\t\tthis.mousewheelTimer = this._delay(function() {\n
+\t\t\t\tif ( this.spinning ) {\n
+\t\t\t\t\tthis._stop( event );\n
+\t\t\t\t}\n
+\t\t\t}, 100 );\n
+\t\t\tevent.preventDefault();\n
+\t\t},\n
+\t\t"mousedown .ui-spinner-button": function( event ) {\n
+\t\t\tvar previous;\n
+\n
+\t\t\t// We never want the buttons to have focus; whenever the user is\n
+\t\t\t// interacting with the spinner, the focus should be on the input.\n
+\t\t\t// If the input is focused then this.previous is properly set from\n
+\t\t\t// when the input first received focus. If the input is not focused\n
+\t\t\t// then we need to set this.previous based on the value before spinning.\n
+\t\t\tprevious = this.element[0] === this.document[0].activeElement ?\n
+\t\t\t\tthis.previous : this.element.val();\n
+\t\t\tfunction checkFocus() {\n
+\t\t\t\tvar isActive = this.element[0] === this.document[0].activeElement;\n
+\t\t\t\tif ( !isActive ) {\n
+\t\t\t\t\tthis.element.focus();\n
+\t\t\t\t\tthis.previous = previous;\n
+\t\t\t\t\t// support: IE\n
+\t\t\t\t\t// IE sets focus asynchronously, so we need to check if focus\n
+\t\t\t\t\t// moved off of the input because the user clicked on the button.\n
+\t\t\t\t\tthis._delay(function() {\n
+\t\t\t\t\t\tthis.previous = previous;\n
+\t\t\t\t\t});\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// ensure focus is on (or stays on) the text field\n
+\t\t\tevent.preventDefault();\n
+\t\t\tcheckFocus.call( this );\n
+\n
+\t\t\t// support: IE\n
+\t\t\t// IE doesn\'t prevent moving focus even with event.preventDefault()\n
+\t\t\t// so we set a flag to know when we should ignore the blur event\n
+\t\t\t// and check (again) if focus moved off of the input.\n
+\t\t\tthis.cancelBlur = true;\n
+\t\t\tthis._delay(function() {\n
+\t\t\t\tdelete this.cancelBlur;\n
+\t\t\t\tcheckFocus.call( this );\n
+\t\t\t});\n
+\n
+\t\t\tif ( this._start( event ) === false ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tthis._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );\n
+\t\t},\n
+\t\t"mouseup .ui-spinner-button": "_stop",\n
+\t\t"mouseenter .ui-spinner-button": function( event ) {\n
+\t\t\t// button will add ui-state-active if mouse was down while mouseleave and kept down\n
+\t\t\tif ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tif ( this._start( event ) === false ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t\tthis._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );\n
+\t\t},\n
+\t\t// TODO: do we really want to consider this a stop?\n
+\t\t// shouldn\'t we just stop the repeater and wait until mouseup before\n
+\t\t// we trigger the stop event?\n
+\t\t"mouseleave .ui-spinner-button": "_stop"\n
+\t},\n
+\n
+\t_draw: function() {\n
+\t\tvar uiSpinner = this.uiSpinner = this.element\n
+\t\t\t.addClass( "ui-spinner-input" )\n
+\t\t\t.attr( "autocomplete", "off" )\n
+\t\t\t.wrap( this._uiSpinnerHtml() )\n
+\t\t\t.parent()\n
+\t\t\t\t// add buttons\n
+\t\t\t\t.append( this._buttonHtml() );\n
+\n
+\t\tthis.element.attr( "role", "spinbutton" );\n
+\n
+\t\t// button bindings\n
+\t\tthis.buttons = uiSpinner.find( ".ui-spinner-button" )\n
+\t\t\t.attr( "tabIndex", -1 )\n
+\t\t\t.button()\n
+\t\t\t.removeClass( "ui-corner-all" );\n
+\n
+\t\t// IE 6 doesn\'t understand height: 50% for the buttons\n
+\t\t// unless the wrapper has an explicit height\n
+\t\tif ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&\n
+\t\t\t\tuiSpinner.height() > 0 ) {\n
+\t\t\tuiSpinner.height( uiSpinner.height() );\n
+\t\t}\n
+\n
+\t\t// disable spinner if element was already disabled\n
+\t\tif ( this.options.disabled ) {\n
+\t\t\tthis.disable();\n
+\t\t}\n
+\t},\n
+\n
+\t_keydown: function( event ) {\n
+\t\tvar options = this.options,\n
+\t\t\tkeyCode = $.ui.keyCode;\n
+\n
+\t\tswitch ( event.keyCode ) {\n
+\t\tcase keyCode.UP:\n
+\t\t\tthis._repeat( null, 1, event );\n
+\t\t\treturn true;\n
+\t\tcase keyCode.DOWN:\n
+\t\t\tthis._repeat( null, -1, event );\n
+\t\t\treturn true;\n
+\t\tcase keyCode.PAGE_UP:\n
+\t\t\tthis._repeat( null, options.page, event );\n
+\t\t\treturn true;\n
+\t\tcase keyCode.PAGE_DOWN:\n
+\t\t\tthis._repeat( null, -options.page, event );\n
+\t\t\treturn true;\n
+\t\t}\n
+\n
+\t\treturn false;\n
+\t},\n
+\n
+\t_uiSpinnerHtml: function() {\n
+\t\treturn "<span class=\'ui-spinner ui-widget ui-widget-content ui-corner-all\'></span>";\n
+\t},\n
+\n
+\t_buttonHtml: function() {\n
+\t\treturn "" +\n
+\t\t\t"<a class=\'ui-spinner-button ui-spinner-up ui-corner-tr\'>" +\n
+\t\t\t\t"<span class=\'ui-icon " + this.options.icons.up + "\'>&#9650;</span>" +\n
+\t\t\t"</a>" +\n
+\t\t\t"<a class=\'ui-spinner-button ui-spinner-down ui-corner-br\'>" +\n
+\t\t\t\t"<span class=\'ui-icon " + this.options.icons.down + "\'>&#9660;</span>" +\n
+\t\t\t"</a>";\n
+\t},\n
+\n
+\t_start: function( event ) {\n
+\t\tif ( !this.spinning && this._trigger( "start", event ) === false ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\tif ( !this.counter ) {\n
+\t\t\tthis.counter = 1;\n
+\t\t}\n
+\t\tthis.spinning = true;\n
+\t\treturn true;\n
+\t},\n
+\n
+\t_repeat: function( i, steps, event ) {\n
+\t\ti = i || 500;\n
+\n
+\t\tclearTimeout( this.timer );\n
+\t\tthis.timer = this._delay(function() {\n
+\t\t\tthis._repeat( 40, steps, event );\n
+\t\t}, i );\n
+\n
+\t\tthis._spin( steps * this.options.step, event );\n
+\t},\n
+\n
+\t_spin: function( step, event ) {\n
+\t\tvar value = this.value() || 0;\n
+\n
+\t\tif ( !this.counter ) {\n
+\t\t\tthis.counter = 1;\n
+\t\t}\n
+\n
+\t\tvalue = this._adjustValue( value + step * this._increment( this.counter ) );\n
+\n
+\t\tif ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {\n
+\t\t\tthis._value( value );\n
+\t\t\tthis.counter++;\n
+\t\t}\n
+\t},\n
+\n
+\t_increment: function( i ) {\n
+\t\tvar incremental = this.options.incremental;\n
+\n
+\t\tif ( incremental ) {\n
+\t\t\treturn $.isFunction( incremental ) ?\n
+\t\t\t\tincremental( i ) :\n
+\t\t\t\tMath.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );\n
+\t\t}\n
+\n
+\t\treturn 1;\n
+\t},\n
+\n
+\t_precision: function() {\n
+\t\tvar precision = this._precisionOf( this.options.step );\n
+\t\tif ( this.options.min !== null ) {\n
+\t\t\tprecision = Math.max( precision, this._precisionOf( this.options.min ) );\n
+\t\t}\n
+\t\treturn precision;\n
+\t},\n
+\n
+\t_precisionOf: function( num ) {\n
+\t\tvar str = num.toString(),\n
+\t\t\tdecimal = str.indexOf( "." );\n
+\t\treturn decimal === -1 ? 0 : str.length - decimal - 1;\n
+\t},\n
+\n
+\t_adjustValue: function( value ) {\n
+\t\tvar base, aboveMin,\n
+\t\t\toptions = this.options;\n
+\n
+\t\t// make sure we\'re at a valid step\n
+\t\t// - find out where we are relative to the base (min or 0)\n
+\t\tbase = options.min !== null ? options.min : 0;\n
+\t\taboveMin = value - base;\n
+\t\t// - round to the nearest step\n
+\t\taboveMin = Math.round(aboveMin / options.step) * options.step;\n
+\t\t// - rounding is based on 0, so adjust back to our base\n
+\t\tvalue = base + aboveMin;\n
+\n
+\t\t// fix precision from bad JS floating point math\n
+\t\tvalue = parseFloat( value.toFixed( this._precision() ) );\n
+\n
+\t\t// clamp the value\n
+\t\tif ( options.max !== null && value > options.max) {\n
+\t\t\treturn options.max;\n
+\t\t}\n
+\t\tif ( options.min !== null && value < options.min ) {\n
+\t\t\treturn options.min;\n
+\t\t}\n
+\n
+\t\treturn value;\n
+\t},\n
+\n
+\t_stop: function( event ) {\n
+\t\tif ( !this.spinning ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tclearTimeout( this.timer );\n
+\t\tclearTimeout( this.mousewheelTimer );\n
+\t\tthis.counter = 0;\n
+\t\tthis.spinning = false;\n
+\t\tthis._trigger( "stop", event );\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tif ( key === "culture" || key === "numberFormat" ) {\n
+\t\t\tvar prevValue = this._parse( this.element.val() );\n
+\t\t\tthis.options[ key ] = value;\n
+\t\t\tthis.element.val( this._format( prevValue ) );\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( key === "max" || key === "min" || key === "step" ) {\n
+\t\t\tif ( typeof value === "string" ) {\n
+\t\t\t\tvalue = this._parse( value );\n
+\t\t\t}\n
+\t\t}\n
+\t\tif ( key === "icons" ) {\n
+\t\t\tthis.buttons.first().find( ".ui-icon" )\n
+\t\t\t\t.removeClass( this.options.icons.up )\n
+\t\t\t\t.addClass( value.up );\n
+\t\t\tthis.buttons.last().find( ".ui-icon" )\n
+\t\t\t\t.removeClass( this.options.icons.down )\n
+\t\t\t\t.addClass( value.down );\n
+\t\t}\n
+\n
+\t\tthis._super( key, value );\n
+\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\tif ( value ) {\n
+\t\t\t\tthis.element.prop( "disabled", true );\n
+\t\t\t\tthis.buttons.button( "disable" );\n
+\t\t\t} else {\n
+\t\t\t\tthis.element.prop( "disabled", false );\n
+\t\t\t\tthis.buttons.button( "enable" );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t_setOptions: modifier(function( options ) {\n
+\t\tthis._super( options );\n
+\t\tthis._value( this.element.val() );\n
+\t}),\n
+\n
+\t_parse: function( val ) {\n
+\t\tif ( typeof val === "string" && val !== "" ) {\n
+\t\t\tval = window.Globalize && this.options.numberFormat ?\n
+\t\t\t\tGlobalize.parseFloat( val, 10, this.options.culture ) : +val;\n
+\t\t}\n
+\t\treturn val === "" || isNaN( val ) ? null : val;\n
+\t},\n
+\n
+\t_format: function( value ) {\n
+\t\tif ( value === "" ) {\n
+\t\t\treturn "";\n
+\t\t}\n
+\t\treturn window.Globalize && this.options.numberFormat ?\n
+\t\t\tGlobalize.format( value, this.options.numberFormat, this.options.culture ) :\n
+\t\t\tvalue;\n
+\t},\n
+\n
+\t_refresh: function() {\n
+\t\tthis.element.attr({\n
+\t\t\t"aria-valuemin": this.options.min,\n
+\t\t\t"aria-valuemax": this.options.max,\n
+\t\t\t// TODO: what should we do with values that can\'t be parsed?\n
+\t\t\t"aria-valuenow": this._parse( this.element.val() )\n
+\t\t});\n
+\t},\n
+\n
+\t// update the value without triggering change\n
+\t_value: function( value, allowAny ) {\n
+\t\tvar parsed;\n
+\t\tif ( value !== "" ) {\n
+\t\t\tparsed = this._parse( value );\n
+\t\t\tif ( parsed !== null ) {\n
+\t\t\t\tif ( !allowAny ) {\n
+\t\t\t\t\tparsed = this._adjustValue( parsed );\n
+\t\t\t\t}\n
+\t\t\t\tvalue = this._format( parsed );\n
+\t\t\t}\n
+\t\t}\n
+\t\tthis.element.val( value );\n
+\t\tthis._refresh();\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tthis.element\n
+\t\t\t.removeClass( "ui-spinner-input" )\n
+\t\t\t.prop( "disabled", false )\n
+\t\t\t.removeAttr( "autocomplete" )\n
+\t\t\t.removeAttr( "role" )\n
+\t\t\t.removeAttr( "aria-valuemin" )\n
+\t\t\t.removeAttr( "aria-valuemax" )\n
+\t\t\t.removeAttr( "aria-valuenow" );\n
+\t\tthis.uiSpinner.replaceWith( this.element );\n
+\t},\n
+\n
+\tstepUp: modifier(function( steps ) {\n
+\t\tthis._stepUp( steps );\n
+\t}),\n
+\t_stepUp: function( steps ) {\n
+\t\tif ( this._start() ) {\n
+\t\t\tthis._spin( (steps || 1) * this.options.step );\n
+\t\t\tthis._stop();\n
+\t\t}\n
+\t},\n
+\n
+\tstepDown: modifier(function( steps ) {\n
+\t\tthis._stepDown( steps );\n
+\t}),\n
+\t_stepDown: function( steps ) {\n
+\t\tif ( this._start() ) {\n
+\t\t\tthis._spin( (steps || 1) * -this.options.step );\n
+\t\t\tthis._stop();\n
+\t\t}\n
+\t},\n
+\n
+\tpageUp: modifier(function( pages ) {\n
+\t\tthis._stepUp( (pages || 1) * this.options.page );\n
+\t}),\n
+\n
+\tpageDown: modifier(function( pages ) {\n
+\t\tthis._stepDown( (pages || 1) * this.options.page );\n
+\t}),\n
+\n
+\tvalue: function( newVal ) {\n
+\t\tif ( !arguments.length ) {\n
+\t\t\treturn this._parse( this.element.val() );\n
+\t\t}\n
+\t\tmodifier( this._value ).call( this, newVal );\n
+\t},\n
+\n
+\twidget: function() {\n
+\t\treturn this.uiSpinner;\n
+\t}\n
+});\n
+\n
+}( jQuery ) );\n
+(function( $, undefined ) {\n
+\n
+var tabId = 0,\n
+\trhash = /#.*$/;\n
+\n
+function getNextTabId() {\n
+\treturn ++tabId;\n
+}\n
+\n
+function isLocal( anchor ) {\n
+\t// support: IE7\n
+\t// IE7 doesn\'t normalize the href property when set via script (#9317)\n
+\tanchor = anchor.cloneNode( false );\n
+\n
+\treturn anchor.hash.length > 1 &&\n
+\t\tdecodeURIComponent( anchor.href.replace( rhash, "" ) ) ===\n
+\t\t\tdecodeURIComponent( location.href.replace( rhash, "" ) );\n
+}\n
+\n
+$.widget( "ui.tabs", {\n
+\tversion: "1.10.4",\n
+\tdelay: 300,\n
+\toptions: {\n
+\t\tactive: null,\n
+\t\tcollapsible: false,\n
+\t\tevent: "click",\n
+\t\theightStyle: "content",\n
+\t\thide: null,\n
+\t\tshow: null,\n
+\n
+\t\t// callbacks\n
+\t\tactivate: null,\n
+\t\tbeforeActivate: null,\n
+\t\tbeforeLoad: null,\n
+\t\tload: null\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tvar that = this,\n
+\t\t\toptions = this.options;\n
+\n
+\t\tthis.running = false;\n
+\n
+\t\tthis.element\n
+\t\t\t.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )\n
+\t\t\t.toggleClass( "ui-tabs-collapsible", options.collapsible )\n
+\t\t\t// Prevent users from focusing disabled tabs via click\n
+\t\t\t.delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {\n
+\t\t\t\tif ( $( this ).is( ".ui-state-disabled" ) ) {\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t}\n
+\t\t\t})\n
+\t\t\t// support: IE <9\n
+\t\t\t// Preventing the default action in mousedown doesn\'t prevent IE\n
+\t\t\t// from focusing the element, so if the anchor gets focused, blur.\n
+\t\t\t// We don\'t have to worry about focusing the previously focused\n
+\t\t\t// element since clicking on a non-focusable element should focus\n
+\t\t\t// the body anyway.\n
+\t\t\t.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {\n
+\t\t\t\tif ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {\n
+\t\t\t\t\tthis.blur();\n
+\t\t\t\t}\n
+\t\t\t});\n
+\n
+\t\tthis._processTabs();\n
+\t\toptions.active = this._initialActive();\n
+\n
+\t\t// Take disabling tabs via class attribute from HTML\n
+\t\t// into account and update option properly.\n
+\t\tif ( $.isArray( options.disabled ) ) {\n
+\t\t\toptions.disabled = $.unique( options.disabled.concat(\n
+\t\t\t\t$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {\n
+\t\t\t\t\treturn that.tabs.index( li );\n
+\t\t\t\t})\n
+\t\t\t) ).sort();\n
+\t\t}\n
+\n
+\t\t// check for length avoids error when initializing empty list\n
+\t\tif ( this.options.active !== false && this.anchors.length ) {\n
+\t\t\tthis.active = this._findActive( options.active );\n
+\t\t} else {\n
+\t\t\tthis.active = $();\n
+\t\t}\n
+\n
+\t\tthis._refresh();\n
+\n
+\t\tif ( this.active.length ) {\n
+\t\t\tthis.load( options.active );\n
+\t\t}\n
+\t},\n
+\n
+\t_initialActive: function() {\n
+\t\tvar active = this.options.active,\n
+\t\t\tcollapsible = this.options.collapsible,\n
+\t\t\tlocationHash = location.hash.substring( 1 );\n
+\n
+\t\tif ( active === null ) {\n
+\t\t\t// check the fragment identifier in the URL\n
+\t\t\tif ( locationHash ) {\n
+\t\t\t\tthis.tabs.each(function( i, tab ) {\n
+\t\t\t\t\tif ( $( tab ).attr( "aria-controls" ) === locationHash ) {\n
+\t\t\t\t\t\tactive = i;\n
+\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t}\n
+\n
+\t\t\t// check for a tab marked active via a class\n
+\t\t\tif ( active === null ) {\n
+\t\t\t\tactive = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );\n
+\t\t\t}\n
+\n
+\t\t\t// no active tab, set to false\n
+\t\t\tif ( active === null || active === -1 ) {\n
+\t\t\t\tactive = this.tabs.length ? 0 : false;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// handle numbers: negative, out of range\n
+\t\tif ( active !== false ) {\n
+\t\t\tactive = this.tabs.index( this.tabs.eq( active ) );\n
+\t\t\tif ( active === -1 ) {\n
+\t\t\t\tactive = collapsible ? false : 0;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// don\'t allow collapsible: false and active: false\n
+\t\tif ( !collapsible && active === false && this.anchors.length ) {\n
+\t\t\tactive = 0;\n
+\t\t}\n
+\n
+\t\treturn active;\n
+\t},\n
+\n
+\t_getCreateEventData: function() {\n
+\t\treturn {\n
+\t\t\ttab: this.active,\n
+\t\t\tpanel: !this.active.length ? $() : this._getPanelForTab( this.active )\n
+\t\t};\n
+\t},\n
+\n
+\t_tabKeydown: function( event ) {\n
+\t\tvar focusedTab = $( this.document[0].activeElement ).closest( "li" ),\n
+\t\t\tselectedIndex = this.tabs.index( focusedTab ),\n
+\t\t\tgoingForward = true;\n
+\n
+\t\tif ( this._handlePageNav( event ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tswitch ( event.keyCode ) {\n
+\t\t\tcase $.ui.keyCode.RIGHT:\n
+\t\t\tcase $.ui.keyCode.DOWN:\n
+\t\t\t\tselectedIndex++;\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.ui.keyCode.UP:\n
+\t\t\tcase $.ui.keyCode.LEFT:\n
+\t\t\t\tgoingForward = false;\n
+\t\t\t\tselectedIndex--;\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.ui.keyCode.END:\n
+\t\t\t\tselectedIndex = this.anchors.length - 1;\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.ui.keyCode.HOME:\n
+\t\t\t\tselectedIndex = 0;\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.ui.keyCode.SPACE:\n
+\t\t\t\t// Activate only, no collapsing\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t\tclearTimeout( this.activating );\n
+\t\t\t\tthis._activate( selectedIndex );\n
+\t\t\t\treturn;\n
+\t\t\tcase $.ui.keyCode.ENTER:\n
+\t\t\t\t// Toggle (cancel delayed activation, allow collapsing)\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t\tclearTimeout( this.activating );\n
+\t\t\t\t// Determine if we should collapse or activate\n
+\t\t\t\tthis._activate( selectedIndex === this.options.active ? false : selectedIndex );\n
+\t\t\t\treturn;\n
+\t\t\tdefault:\n
+\t\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Focus the appropriate tab, based on which key was pressed\n
+\t\tevent.preventDefault();\n
+\t\tclearTimeout( this.activating );\n
+\t\tselectedIndex = this._focusNextTab( selectedIndex, goingForward );\n
+\n
+\t\t// Navigating with control key will prevent automatic activation\n
+\t\tif ( !event.ctrlKey ) {\n
+\t\t\t// Update aria-selected immediately so that AT think the tab is already selected.\n
+\t\t\t// Otherwise AT may confuse the user by stating that they need to activate the tab,\n
+\t\t\t// but the tab will already be activated by the time the announcement finishes.\n
+\t\t\tfocusedTab.attr( "aria-selected", "false" );\n
+\t\t\tthis.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );\n
+\n
+\t\t\tthis.activating = this._delay(function() {\n
+\t\t\t\tthis.option( "active", selectedIndex );\n
+\t\t\t}, this.delay );\n
+\t\t}\n
+\t},\n
+\n
+\t_panelKeydown: function( event ) {\n
+\t\tif ( this._handlePageNav( event ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Ctrl+up moves focus to the current tab\n
+\t\tif ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {\n
+\t\t\tevent.preventDefault();\n
+\t\t\tthis.active.focus();\n
+\t\t}\n
+\t},\n
+\n
+\t// Alt+page up/down moves focus to the previous/next tab (and activates)\n
+\t_handlePageNav: function( event ) {\n
+\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {\n
+\t\t\tthis._activate( this._focusNextTab( this.options.active - 1, false ) );\n
+\t\t\treturn true;\n
+\t\t}\n
+\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {\n
+\t\t\tthis._activate( this._focusNextTab( this.options.active + 1, true ) );\n
+\t\t\treturn true;\n
+\t\t}\n
+\t},\n
+\n
+\t_findNextTab: function( index, goingForward ) {\n
+\t\tvar lastTabIndex = this.tabs.length - 1;\n
+\n
+\t\tfunction constrain() {\n
+\t\t\tif ( index > lastTabIndex ) {\n
+\t\t\t\tindex = 0;\n
+\t\t\t}\n
+\t\t\tif ( index < 0 ) {\n
+\t\t\t\tindex = lastTabIndex;\n
+\t\t\t}\n
+\t\t\treturn index;\n
+\t\t}\n
+\n
+\t\twhile ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {\n
+\t\t\tindex = goingForward ? index + 1 : index - 1;\n
+\t\t}\n
+\n
+\t\treturn index;\n
+\t},\n
+\n
+\t_focusNextTab: function( index, goingForward ) {\n
+\t\tindex = this._findNextTab( index, goingForward );\n
+\t\tthis.tabs.eq( index ).focus();\n
+\t\treturn index;\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tif ( key === "active" ) {\n
+\t\t\t// _activate() will handle invalid values and update this.options\n
+\t\t\tthis._activate( value );\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\t// don\'t use the widget factory\'s disabled handling\n
+\t\t\tthis._setupDisabled( value );\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis._super( key, value);\n
+\n
+\t\tif ( key === "collapsible" ) {\n
+\t\t\tthis.element.toggleClass( "ui-tabs-collapsible", value );\n
+\t\t\t// Setting collapsible: false while collapsed; open first panel\n
+\t\t\tif ( !value && this.options.active === false ) {\n
+\t\t\t\tthis._activate( 0 );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( key === "event" ) {\n
+\t\t\tthis._setupEvents( value );\n
+\t\t}\n
+\n
+\t\tif ( key === "heightStyle" ) {\n
+\t\t\tthis._setupHeightStyle( value );\n
+\t\t}\n
+\t},\n
+\n
+\t_tabId: function( tab ) {\n
+\t\treturn tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();\n
+\t},\n
+\n
+\t_sanitizeSelector: function( hash ) {\n
+\t\treturn hash ? hash.replace( /[!"$%&\'()*+,.\\/:;<=>?@\\[\\]\\^`{|}~]/g, "\\\\$&" ) : "";\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tvar options = this.options,\n
+\t\t\tlis = this.tablist.children( ":has(a[href])" );\n
+\n
+\t\t// get disabled tabs from class attribute from HTML\n
+\t\t// this will get converted to a boolean if needed in _refresh()\n
+\t\toptions.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {\n
+\t\t\treturn lis.index( tab );\n
+\t\t});\n
+\n
+\t\tthis._processTabs();\n
+\n
+\t\t// was collapsed or no tabs\n
+\t\tif ( options.active === false || !this.anchors.length ) {\n
+\t\t\toptions.active = false;\n
+\t\t\tthis.active = $();\n
+\t\t// was active, but active tab is gone\n
+\t\t} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {\n
+\t\t\t// all remaining tabs are disabled\n
+\t\t\tif ( this.tabs.length === options.disabled.length ) {\n
+\t\t\t\toptions.active = false;\n
+\t\t\t\tthis.active = $();\n
+\t\t\t// activate previous tab\n
+\t\t\t} else {\n
+\t\t\t\tthis._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );\n
+\t\t\t}\n
+\t\t// was active, active tab still exists\n
+\t\t} else {\n
+\t\t\t// make sure active index is correct\n
+\t\t\toptions.active = this.tabs.index( this.active );\n
+\t\t}\n
+\n
+\t\tthis._refresh();\n
+\t},\n
+\n
+\t_refresh: function() {\n
+\t\tthis._setupDisabled( this.options.disabled );\n
+\t\tthis._setupEvents( this.options.event );\n
+\t\tthis._setupHeightStyle( this.options.heightStyle );\n
+\n
+\t\tthis.tabs.not( this.active ).attr({\n
+\t\t\t"aria-selected": "false",\n
+\t\t\ttabIndex: -1\n
+\t\t});\n
+\t\tthis.panels.not( this._getPanelForTab( this.active ) )\n
+\t\t\t.hide()\n
+\t\t\t.attr({\n
+\t\t\t\t"aria-expanded": "false",\n
+\t\t\t\t"aria-hidden": "true"\n
+\t\t\t});\n
+\n
+\t\t// Make sure one tab is in the tab order\n
+\t\tif ( !this.active.length ) {\n
+\t\t\tthis.tabs.eq( 0 ).attr( "tabIndex", 0 );\n
+\t\t} else {\n
+\t\t\tthis.active\n
+\t\t\t\t.addClass( "ui-tabs-active ui-state-active" )\n
+\t\t\t\t.attr({\n
+\t\t\t\t\t"aria-selected": "true",\n
+\t\t\t\t\ttabIndex: 0\n
+\t\t\t\t});\n
+\t\t\tthis._getPanelForTab( this.active )\n
+\t\t\t\t.show()\n
+\t\t\t\t.attr({\n
+\t\t\t\t\t"aria-expanded": "true",\n
+\t\t\t\t\t"aria-hidden": "false"\n
+\t\t\t\t});\n
+\t\t}\n
+\t},\n
+\n
+\t_processTabs: function() {\n
+\t\tvar that = this;\n
+\n
+\t\tthis.tablist = this._getList()\n
+\t\t\t.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )\n
+\t\t\t.attr( "role", "tablist" );\n
+\n
+\t\tthis.tabs = this.tablist.find( "> li:has(a[href])" )\n
+\t\t\t.addClass( "ui-state-default ui-corner-top" )\n
+\t\t\t.attr({\n
+\t\t\t\trole: "tab",\n
+\t\t\t\ttabIndex: -1\n
+\t\t\t});\n
+\n
+\t\tthis.anchors = this.tabs.map(function() {\n
+\t\t\t\treturn $( "a", this )[ 0 ];\n
+\t\t\t})\n
+\t\t\t.addClass( "ui-tabs-anchor" )\n
+\t\t\t.attr({\n
+\t\t\t\trole: "presentation",\n
+\t\t\t\ttabIndex: -1\n
+\t\t\t});\n
+\n
+\t\tthis.panels = $();\n
+\n
+\t\tthis.anchors.each(function( i, anchor ) {\n
+\t\t\tvar selector, panel, panelId,\n
+\t\t\t\tanchorId = $( anchor ).uniqueId().attr( "id" ),\n
+\t\t\t\ttab = $( anchor ).closest( "li" ),\n
+\t\t\t\toriginalAriaControls = tab.attr( "aria-controls" );\n
+\n
+\t\t\t// inline tab\n
+\t\t\tif ( isLocal( anchor ) ) {\n
+\t\t\t\tselector = anchor.hash;\n
+\t\t\t\tpanel = that.element.find( that._sanitizeSelector( selector ) );\n
+\t\t\t// remote tab\n
+\t\t\t} else {\n
+\t\t\t\tpanelId = that._tabId( tab );\n
+\t\t\t\tselector = "#" + panelId;\n
+\t\t\t\tpanel = that.element.find( selector );\n
+\t\t\t\tif ( !panel.length ) {\n
+\t\t\t\t\tpanel = that._createPanel( panelId );\n
+\t\t\t\t\tpanel.insertAfter( that.panels[ i - 1 ] || that.tablist );\n
+\t\t\t\t}\n
+\t\t\t\tpanel.attr( "aria-live", "polite" );\n
+\t\t\t}\n
+\n
+\t\t\tif ( panel.length) {\n
+\t\t\t\tthat.panels = that.panels.add( panel );\n
+\t\t\t}\n
+\t\t\tif ( originalAriaControls ) {\n
+\t\t\t\ttab.data( "ui-tabs-aria-controls", originalAriaControls );\n
+\t\t\t}\n
+\t\t\ttab.attr({\n
+\t\t\t\t"aria-controls": selector.substring( 1 ),\n
+\t\t\t\t"aria-labelledby": anchorId\n
+\t\t\t});\n
+\t\t\tpanel.attr( "aria-labelledby", anchorId );\n
+\t\t});\n
+\n
+\t\tthis.panels\n
+\t\t\t.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )\n
+\t\t\t.attr( "role", "tabpanel" );\n
+\t},\n
+\n
+\t// allow overriding how to find the list for rare usage scenarios (#7715)\n
+\t_getList: function() {\n
+\t\treturn this.tablist || this.element.find( "ol,ul" ).eq( 0 );\n
+\t},\n
+\n
+\t_createPanel: function( id ) {\n
+\t\treturn $( "<div>" )\n
+\t\t\t.attr( "id", id )\n
+\t\t\t.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )\n
+\t\t\t.data( "ui-tabs-destroy", true );\n
+\t},\n
+\n
+\t_setupDisabled: function( disabled ) {\n
+\t\tif ( $.isArray( disabled ) ) {\n
+\t\t\tif ( !disabled.length ) {\n
+\t\t\t\tdisabled = false;\n
+\t\t\t} else if ( disabled.length === this.anchors.length ) {\n
+\t\t\t\tdisabled = true;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// disable tabs\n
+\t\tfor ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {\n
+\t\t\tif ( disabled === true || $.inArray( i, disabled ) !== -1 ) {\n
+\t\t\t\t$( li )\n
+\t\t\t\t\t.addClass( "ui-state-disabled" )\n
+\t\t\t\t\t.attr( "aria-disabled", "true" );\n
+\t\t\t} else {\n
+\t\t\t\t$( li )\n
+\t\t\t\t\t.removeClass( "ui-state-disabled" )\n
+\t\t\t\t\t.removeAttr( "aria-disabled" );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis.options.disabled = disabled;\n
+\t},\n
+\n
+\t_setupEvents: function( event ) {\n
+\t\tvar events = {\n
+\t\t\tclick: function( event ) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t}\n
+\t\t};\n
+\t\tif ( event ) {\n
+\t\t\t$.each( event.split(" "), function( index, eventName ) {\n
+\t\t\t\tevents[ eventName ] = "_eventHandler";\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tthis._off( this.anchors.add( this.tabs ).add( this.panels ) );\n
+\t\tthis._on( this.anchors, events );\n
+\t\tthis._on( this.tabs, { keydown: "_tabKeydown" } );\n
+\t\tthis._on( this.panels, { keydown: "_panelKeydown" } );\n
+\n
+\t\tthis._focusable( this.tabs );\n
+\t\tthis._hoverable( this.tabs );\n
+\t},\n
+\n
+\t_setupHeightStyle: function( heightStyle ) {\n
+\t\tvar maxHeight,\n
+\t\t\tparent = this.element.parent();\n
+\n
+\t\tif ( heightStyle === "fill" ) {\n
+\t\t\tmaxHeight = parent.height();\n
+\t\t\tmaxHeight -= this.element.outerHeight() - this.element.height();\n
+\n
+\t\t\tthis.element.siblings( ":visible" ).each(function() {\n
+\t\t\t\tvar elem = $( this ),\n
+\t\t\t\t\tposition = elem.css( "position" );\n
+\n
+\t\t\t\tif ( position === "absolute" || position === "fixed" ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\tmaxHeight -= elem.outerHeight( true );\n
+\t\t\t});\n
+\n
+\t\t\tthis.element.children().not( this.panels ).each(function() {\n
+\t\t\t\tmaxHeight -= $( this ).outerHeight( true );\n
+\t\t\t});\n
+\n
+\t\t\tthis.panels.each(function() {\n
+\t\t\t\t$( this ).height( Math.max( 0, maxHeight -\n
+\t\t\t\t\t$( this ).innerHeight() + $( this ).height() ) );\n
+\t\t\t})\n
+\t\t\t.css( "overflow", "auto" );\n
+\t\t} else if ( heightStyle === "auto" ) {\n
+\t\t\tmaxHeight = 0;\n
+\t\t\tthis.panels.each(function() {\n
+\t\t\t\tmaxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );\n
+\t\t\t}).height( maxHeight );\n
+\t\t}\n
+\t},\n
+\n
+\t_eventHandler: function( event ) {\n
+\t\tvar options = this.options,\n
+\t\t\tactive = this.active,\n
+\t\t\tanchor = $( event.currentTarget ),\n
+\t\t\ttab = anchor.closest( "li" ),\n
+\t\t\tclickedIsActive = tab[ 0 ] === active[ 0 ],\n
+\t\t\tcollapsing = clickedIsActive && options.collapsible,\n
+\t\t\ttoShow = collapsing ? $() : this._getPanelForTab( tab ),\n
+\t\t\ttoHide = !active.length ? $() : this._getPanelForTab( active ),\n
+\t\t\teventData = {\n
+\t\t\t\toldTab: active,\n
+\t\t\t\toldPanel: toHide,\n
+\t\t\t\tnewTab: collapsing ? $() : tab,\n
+\t\t\t\tnewPanel: toShow\n
+\t\t\t};\n
+\n
+\t\tevent.preventDefault();\n
+\n
+\t\tif ( tab.hasClass( "ui-state-disabled" ) ||\n
+\t\t\t\t// tab is already loading\n
+\t\t\t\ttab.hasClass( "ui-tabs-loading" ) ||\n
+\t\t\t\t// can\'t switch durning an animation\n
+\t\t\t\tthis.running ||\n
+\t\t\t\t// click on active header, but not collapsible\n
+\t\t\t\t( clickedIsActive && !options.collapsible ) ||\n
+\t\t\t\t// allow canceling activation\n
+\t\t\t\t( this._trigger( "beforeActivate", event, eventData ) === false ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\toptions.active = collapsing ? false : this.tabs.index( tab );\n
+\n
+\t\tthis.active = clickedIsActive ? $() : tab;\n
+\t\tif ( this.xhr ) {\n
+\t\t\tthis.xhr.abort();\n
+\t\t}\n
+\n
+\t\tif ( !toHide.length && !toShow.length ) {\n
+\t\t\t$.error( "jQuery UI Tabs: Mismatching fragment identifier." );\n
+\t\t}\n
+\n
+\t\tif ( toShow.length ) {\n
+\t\t\tthis.load( this.tabs.index( tab ), event );\n
+\t\t}\n
+\t\tthis._toggle( event, eventData );\n
+\t},\n
+\n
+\t// handles show/hide for selecting tabs\n
+\t_toggle: function( event, eventData ) {\n
+\t\tvar that = this,\n
+\t\t\ttoShow = eventData.newPanel,\n
+\t\t\ttoHide = eventData.oldPanel;\n
+\n
+\t\tthis.running = true;\n
+\n
+\t\tfunction complete() {\n
+\t\t\tthat.running = false;\n
+\t\t\tthat._trigger( "activate", event, eventData );\n
+\t\t}\n
+\n
+\t\tfunction show() {\n
+\t\t\teventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );\n
+\n
+\t\t\tif ( toShow.length && that.options.show ) {\n
+\t\t\t\tthat._show( toShow, that.options.show, complete );\n
+\t\t\t} else {\n
+\t\t\t\ttoShow.show();\n
+\t\t\t\tcomplete();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// start out by hiding, then showing, then completing\n
+\t\tif ( toHide.length && this.options.hide ) {\n
+\t\t\tthis._hide( toHide, this.options.hide, function() {\n
+\t\t\t\teventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );\n
+\t\t\t\tshow();\n
+\t\t\t});\n
+\t\t} else {\n
+\t\t\teventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );\n
+\t\t\ttoHide.hide();\n
+\t\t\tshow();\n
+\t\t}\n
+\n
+\t\ttoHide.attr({\n
+\t\t\t"aria-expanded": "false",\n
+\t\t\t"aria-hidden": "true"\n
+\t\t});\n
+\t\teventData.oldTab.attr( "aria-selected", "false" );\n
+\t\t// If we\'re switching tabs, remove the old tab from the tab order.\n
+\t\t// If we\'re opening from collapsed state, remove the previous tab from the tab order.\n
+\t\t// If we\'re collapsing, then keep the collapsing tab in the tab order.\n
+\t\tif ( toShow.length && toHide.length ) {\n
+\t\t\teventData.oldTab.attr( "tabIndex", -1 );\n
+\t\t} else if ( toShow.length ) {\n
+\t\t\tthis.tabs.filter(function() {\n
+\t\t\t\treturn $( this ).attr( "tabIndex" ) === 0;\n
+\t\t\t})\n
+\t\t\t.attr( "tabIndex", -1 );\n
+\t\t}\n
+\n
+\t\ttoShow.attr({\n
+\t\t\t"aria-expanded": "true",\n
+\t\t\t"aria-hidden": "false"\n
+\t\t});\n
+\t\teventData.newTab.attr({\n
+\t\t\t"aria-selected": "true",\n
+\t\t\ttabIndex: 0\n
+\t\t});\n
+\t},\n
+\n
+\t_activate: function( index ) {\n
+\t\tvar anchor,\n
+\t\t\tactive = this._findActive( index );\n
+\n
+\t\t// trying to activate the already active panel\n
+\t\tif ( active[ 0 ] === this.active[ 0 ] ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// trying to collapse, simulate a click on the current active header\n
+\t\tif ( !active.length ) {\n
+\t\t\tactive = this.active;\n
+\t\t}\n
+\n
+\t\tanchor = active.find( ".ui-tabs-anchor" )[ 0 ];\n
+\t\tthis._eventHandler({\n
+\t\t\ttarget: anchor,\n
+\t\t\tcurrentTarget: anchor,\n
+\t\t\tpreventDefault: $.noop\n
+\t\t});\n
+\t},\n
+\n
+\t_findActive: function( index ) {\n
+\t\treturn index === false ? $() : this.tabs.eq( index );\n
+\t},\n
+\n
+\t_getIndex: function( index ) {\n
+\t\t// meta-function to give users option to provide a href string instead of a numerical index.\n
+\t\tif ( typeof index === "string" ) {\n
+\t\t\tindex = this.anchors.index( this.anchors.filter( "[href$=\'" + index + "\']" ) );\n
+\t\t}\n
+\n
+\t\treturn index;\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tif ( this.xhr ) {\n
+\t\t\tthis.xhr.abort();\n
+\t\t}\n
+\n
+\t\tthis.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );\n
+\n
+\t\tthis.tablist\n
+\t\t\t.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )\n
+\t\t\t.removeAttr( "role" );\n
+\n
+\t\tthis.anchors\n
+\t\t\t.removeClass( "ui-tabs-anchor" )\n
+\t\t\t.removeAttr( "role" )\n
+\t\t\t.removeAttr( "tabIndex" )\n
+\t\t\t.removeUniqueId();\n
+\n
+\t\tthis.tabs.add( this.panels ).each(function() {\n
+\t\t\tif ( $.data( this, "ui-tabs-destroy" ) ) {\n
+\t\t\t\t$( this ).remove();\n
+\t\t\t} else {\n
+\t\t\t\t$( this )\n
+\t\t\t\t\t.removeClass( "ui-state-default ui-state-active ui-state-disabled " +\n
+\t\t\t\t\t\t"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )\n
+\t\t\t\t\t.removeAttr( "tabIndex" )\n
+\t\t\t\t\t.removeAttr( "aria-live" )\n
+\t\t\t\t\t.removeAttr( "aria-busy" )\n
+\t\t\t\t\t.removeAttr( "aria-selected" )\n
+\t\t\t\t\t.removeAttr( "aria-labelledby" )\n
+\t\t\t\t\t.removeAttr( "aria-hidden" )\n
+\t\t\t\t\t.removeAttr( "aria-expanded" )\n
+\t\t\t\t\t.removeAttr( "role" );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tthis.tabs.each(function() {\n
+\t\t\tvar li = $( this ),\n
+\t\t\t\tprev = li.data( "ui-tabs-aria-controls" );\n
+\t\t\tif ( prev ) {\n
+\t\t\t\tli\n
+\t\t\t\t\t.attr( "aria-controls", prev )\n
+\t\t\t\t\t.removeData( "ui-tabs-aria-controls" );\n
+\t\t\t} else {\n
+\t\t\t\tli.removeAttr( "aria-controls" );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tthis.panels.show();\n
+\n
+\t\tif ( this.options.heightStyle !== "content" ) {\n
+\t\t\tthis.panels.css( "height", "" );\n
+\t\t}\n
+\t},\n
+\n
+\tenable: function( index ) {\n
+\t\tvar disabled = this.options.disabled;\n
+\t\tif ( disabled === false ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( index === undefined ) {\n
+\t\t\tdisabled = false;\n
+\t\t} else {\n
+\t\t\tindex = this._getIndex( index );\n
+\t\t\tif ( $.isArray( disabled ) ) {\n
+\t\t\t\tdisabled = $.map( disabled, function( num ) {\n
+\t\t\t\t\treturn num !== index ? num : null;\n
+\t\t\t\t});\n
+\t\t\t} else {\n
+\t\t\t\tdisabled = $.map( this.tabs, function( li, num ) {\n
+\t\t\t\t\treturn num !== index ? num : null;\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t}\n
+\t\tthis._setupDisabled( disabled );\n
+\t},\n
+\n
+\tdisable: function( index ) {\n
+\t\tvar disabled = this.options.disabled;\n
+\t\tif ( disabled === true ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( index === undefined ) {\n
+\t\t\tdisabled = true;\n
+\t\t} else {\n
+\t\t\tindex = this._getIndex( index );\n
+\t\t\tif ( $.inArray( index, disabled ) !== -1 ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\tif ( $.isArray( disabled ) ) {\n
+\t\t\t\tdisabled = $.merge( [ index ], disabled ).sort();\n
+\t\t\t} else {\n
+\t\t\t\tdisabled = [ index ];\n
+\t\t\t}\n
+\t\t}\n
+\t\tthis._setupDisabled( disabled );\n
+\t},\n
+\n
+\tload: function( index, event ) {\n
+\t\tindex = this._getIndex( index );\n
+\t\tvar that = this,\n
+\t\t\ttab = this.tabs.eq( index ),\n
+\t\t\tanchor = tab.find( ".ui-tabs-anchor" ),\n
+\t\t\tpanel = this._getPanelForTab( tab ),\n
+\t\t\teventData = {\n
+\t\t\t\ttab: tab,\n
+\t\t\t\tpanel: panel\n
+\t\t\t};\n
+\n
+\t\t// not remote\n
+\t\tif ( isLocal( anchor[ 0 ] ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );\n
+\n
+\t\t// support: jQuery <1.8\n
+\t\t// jQuery <1.8 returns false if the request is canceled in beforeSend,\n
+\t\t// but as of 1.8, $.ajax() always returns a jqXHR object.\n
+\t\tif ( this.xhr && this.xhr.statusText !== "canceled" ) {\n
+\t\t\ttab.addClass( "ui-tabs-loading" );\n
+\t\t\tpanel.attr( "aria-busy", "true" );\n
+\n
+\t\t\tthis.xhr\n
+\t\t\t\t.success(function( response ) {\n
+\t\t\t\t\t// support: jQuery <1.8\n
+\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n
+\t\t\t\t\tsetTimeout(function() {\n
+\t\t\t\t\t\tpanel.html( response );\n
+\t\t\t\t\t\tthat._trigger( "load", event, eventData );\n
+\t\t\t\t\t}, 1 );\n
+\t\t\t\t})\n
+\t\t\t\t.complete(function( jqXHR, status ) {\n
+\t\t\t\t\t// support: jQuery <1.8\n
+\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n
+\t\t\t\t\tsetTimeout(function() {\n
+\t\t\t\t\t\tif ( status === "abort" ) {\n
+\t\t\t\t\t\t\tthat.panels.stop( false, true );\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\ttab.removeClass( "ui-tabs-loading" );\n
+\t\t\t\t\t\tpanel.removeAttr( "aria-busy" );\n
+\n
+\t\t\t\t\t\tif ( jqXHR === that.xhr ) {\n
+\t\t\t\t\t\t\tdelete that.xhr;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}, 1 );\n
+\t\t\t\t});\n
+\t\t}\n
+\t},\n
+\n
+\t_ajaxSettings: function( anchor, event, eventData ) {\n
+\t\tvar that = this;\n
+\t\treturn {\n
+\t\t\turl: anchor.attr( "href" ),\n
+\t\t\tbeforeSend: function( jqXHR, settings ) {\n
+\t\t\t\treturn that._trigger( "beforeLoad", event,\n
+\t\t\t\t\t$.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );\n
+\t\t\t}\n
+\t\t};\n
+\t},\n
+\n
+\t_getPanelForTab: function( tab ) {\n
+\t\tvar id = $( tab ).attr( "aria-controls" );\n
+\t\treturn this.element.find( this._sanitizeSelector( "#" + id ) );\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+(function( $ ) {\n
+\n
+var increments = 0;\n
+\n
+function addDescribedBy( elem, id ) {\n
+\tvar describedby = (elem.attr( "aria-describedby" ) || "").split( /\\s+/ );\n
+\tdescribedby.push( id );\n
+\telem\n
+\t\t.data( "ui-tooltip-id", id )\n
+\t\t.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );\n
+}\n
+\n
+function removeDescribedBy( elem ) {\n
+\tvar id = elem.data( "ui-tooltip-id" ),\n
+\t\tdescribedby = (elem.attr( "aria-describedby" ) || "").split( /\\s+/ ),\n
+\t\tindex = $.inArray( id, describedby );\n
+\tif ( index !== -1 ) {\n
+\t\tdescribedby.splice( index, 1 );\n
+\t}\n
+\n
+\telem.removeData( "ui-tooltip-id" );\n
+\tdescribedby = $.trim( describedby.join( " " ) );\n
+\tif ( describedby ) {\n
+\t\telem.attr( "aria-describedby", describedby );\n
+\t} else {\n
+\t\telem.removeAttr( "aria-describedby" );\n
+\t}\n
+}\n
+\n
+$.widget( "ui.tooltip", {\n
+\tversion: "1.10.4",\n
+\toptions: {\n
+\t\tcontent: function() {\n
+\t\t\t// support: IE<9, Opera in jQuery <1.7\n
+\t\t\t// .text() can\'t accept undefined, so coerce to a string\n
+\t\t\tvar title = $( this ).attr( "title" ) || "";\n
+\t\t\t// Escape title, since we\'re going from an attribute to raw HTML\n
+\t\t\treturn $( "<a>" ).text( title ).html();\n
+\t\t},\n
+\t\thide: true,\n
+\t\t// Disabled elements have inconsistent behavior across browsers (#8661)\n
+\t\titems: "[title]:not([disabled])",\n
+\t\tposition: {\n
+\t\t\tmy: "left top+15",\n
+\t\t\tat: "left bottom",\n
+\t\t\tcollision: "flipfit flip"\n
+\t\t},\n
+\t\tshow: true,\n
+\t\ttooltipClass: null,\n
+\t\ttrack: false,\n
+\n
+\t\t// callbacks\n
+\t\tclose: null,\n
+\t\topen: null\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tthis._on({\n
+\t\t\tmouseover: "open",\n
+\t\t\tfocusin: "open"\n
+\t\t});\n
+\n
+\t\t// IDs of generated tooltips, needed for destroy\n
+\t\tthis.tooltips = {};\n
+\t\t// IDs of parent tooltips where we removed the title attribute\n
+\t\tthis.parents = {};\n
+\n
+\t\tif ( this.options.disabled ) {\n
+\t\t\tthis._disable();\n
+\t\t}\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tvar that = this;\n
+\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\tthis[ value ? "_disable" : "_enable" ]();\n
+\t\t\tthis.options[ key ] = value;\n
+\t\t\t// disable element style changes\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis._super( key, value );\n
+\n
+\t\tif ( key === "content" ) {\n
+\t\t\t$.each( this.tooltips, function( id, element ) {\n
+\t\t\t\tthat._updateContent( element );\n
+\t\t\t});\n
+\t\t}\n
+\t},\n
+\n
+\t_disable: function() {\n
+\t\tvar that = this;\n
+\n
+\t\t// close open tooltips\n
+\t\t$.each( this.tooltips, function( id, element ) {\n
+\t\t\tvar event = $.Event( "blur" );\n
+\t\t\tevent.target = event.currentTarget = element[0];\n
+\t\t\tthat.close( event, true );\n
+\t\t});\n
+\n
+\t\t// remove title attributes to prevent native tooltips\n
+\t\tthis.element.find( this.options.items ).addBack().each(function() {\n
+\t\t\tvar element = $( this );\n
+\t\t\tif ( element.is( "[title]" ) ) {\n
+\t\t\t\telement\n
+\t\t\t\t\t.data( "ui-tooltip-title", element.attr( "title" ) )\n
+\t\t\t\t\t.attr( "title", "" );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_enable: function() {\n
+\t\t// restore title attributes\n
+\t\tthis.element.find( this.options.items ).addBack().each(function() {\n
+\t\t\tvar element = $( this );\n
+\t\t\tif ( element.data( "ui-tooltip-title" ) ) {\n
+\t\t\t\telement.attr( "title", element.data( "ui-tooltip-title" ) );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\topen: function( event ) {\n
+\t\tvar that = this,\n
+\t\t\ttarget = $( event ? event.target : this.element )\n
+\t\t\t\t// we need closest here due to mouseover bubbling,\n
+\t\t\t\t// but always pointing at the same event target\n
+\t\t\t\t.closest( this.options.items );\n
+\n
+\t\t// No element to show a tooltip for or the tooltip is already open\n
+\t\tif ( !target.length || target.data( "ui-tooltip-id" ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( target.attr( "title" ) ) {\n
+\t\t\ttarget.data( "ui-tooltip-title", target.attr( "title" ) );\n
+\t\t}\n
+\n
+\t\ttarget.data( "ui-tooltip-open", true );\n
+\n
+\t\t// kill parent tooltips, custom or native, for hover\n
+\t\tif ( event && event.type === "mouseover" ) {\n
+\t\t\ttarget.parents().each(function() {\n
+\t\t\t\tvar parent = $( this ),\n
+\t\t\t\t\tblurEvent;\n
+\t\t\t\tif ( parent.data( "ui-tooltip-open" ) ) {\n
+\t\t\t\t\tblurEvent = $.Event( "blur" );\n
+\t\t\t\t\tblurEvent.target = blurEvent.currentTarget = this;\n
+\t\t\t\t\tthat.close( blurEvent, true );\n
+\t\t\t\t}\n
+\t\t\t\tif ( parent.attr( "title" ) ) {\n
+\t\t\t\t\tparent.uniqueId();\n
+\t\t\t\t\tthat.parents[ this.id ] = {\n
+\t\t\t\t\t\telement: this,\n
+\t\t\t\t\t\ttitle: parent.attr( "title" )\n
+\t\t\t\t\t};\n
+\t\t\t\t\tparent.attr( "title", "" );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tthis._updateContent( target, event );\n
+\t},\n
+\n
+\t_updateContent: function( target, event ) {\n
+\t\tvar content,\n
+\t\t\tcontentOption = this.options.content,\n
+\t\t\tthat = this,\n
+\t\t\teventType = event ? event.type : null;\n
+\n
+\t\tif ( typeof contentOption === "string" ) {\n
+\t\t\treturn this._open( event, target, contentOption );\n
+\t\t}\n
+\n
+\t\tcontent = contentOption.call( target[0], function( response ) {\n
+\t\t\t// ignore async response if tooltip was closed already\n
+\t\t\tif ( !target.data( "ui-tooltip-open" ) ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\t// IE may instantly serve a cached response for ajax requests\n
+\t\t\t// delay this call to _open so the other call to _open runs first\n
+\t\t\tthat._delay(function() {\n
+\t\t\t\t// jQuery creates a special event for focusin when it doesn\'t\n
+\t\t\t\t// exist natively. To improve performance, the native event\n
+\t\t\t\t// object is reused and the type is changed. Therefore, we can\'t\n
+\t\t\t\t// rely on the type being correct after the event finished\n
+\t\t\t\t// bubbling, so we set it back to the previous value. (#8740)\n
+\t\t\t\tif ( event ) {\n
+\t\t\t\t\tevent.type = eventType;\n
+\t\t\t\t}\n
+\t\t\t\tthis._open( event, target, response );\n
+\t\t\t});\n
+\t\t});\n
+\t\tif ( content ) {\n
+\t\t\tthis._open( event, target, content );\n
+\t\t}\n
+\t},\n
+\n
+\t_open: function( event, target, content ) {\n
+\t\tvar tooltip, events, delayedShow,\n
+\t\t\tpositionOption = $.extend( {}, this.options.position );\n
+\n
+\t\tif ( !content ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Content can be updated multiple times. If the tooltip already\n
+\t\t// exists, then just update the content and bail.\n
+\t\ttooltip = this._find( target );\n
+\t\tif ( tooltip.length ) {\n
+\t\t\ttooltip.find( ".ui-tooltip-content" ).html( content );\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// if we have a title, clear it to prevent the native tooltip\n
+\t\t// we have to check first to avoid defining a title if none exists\n
+\t\t// (we don\'t want to cause an element to start matching [title])\n
+\t\t//\n
+\t\t// We use removeAttr only for key events, to allow IE to export the correct\n
+\t\t// accessible attributes. For mouse events, set to empty string to avoid\n
+\t\t// native tooltip showing up (happens only when removing inside mouseover).\n
+\t\tif ( target.is( "[title]" ) ) {\n
+\t\t\tif ( event && event.type === "mouseover" ) {\n
+\t\t\t\ttarget.attr( "title", "" );\n
+\t\t\t} else {\n
+\t\t\t\ttarget.removeAttr( "title" );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\ttooltip = this._tooltip( target );\n
+\t\taddDescribedBy( target, tooltip.attr( "id" ) );\n
+\t\ttooltip.find( ".ui-tooltip-content" ).html( content );\n
+\n
+\t\tfunction position( event ) {\n
+\t\t\tpositionOption.of = event;\n
+\t\t\tif ( tooltip.is( ":hidden" ) ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\ttooltip.position( positionOption );\n
+\t\t}\n
+\t\tif ( this.options.track && event && /^mouse/.test( event.type ) ) {\n
+\t\t\tthis._on( this.document, {\n
+\t\t\t\tmousemove: position\n
+\t\t\t});\n
+\t\t\t// trigger once to override element-relative positioning\n
+\t\t\tposition( event );\n
+\t\t} else {\n
+\t\t\ttooltip.position( $.extend({\n
+\t\t\t\tof: target\n
+\t\t\t}, this.options.position ) );\n
+\t\t}\n
+\n
+\t\ttooltip.hide();\n
+\n
+\t\tthis._show( tooltip, this.options.show );\n
+\t\t// Handle tracking tooltips that are shown with a delay (#8644). As soon\n
+\t\t// as the tooltip is visible, position the tooltip using the most recent\n
+\t\t// event.\n
+\t\tif ( this.options.show && this.options.show.delay ) {\n
+\t\t\tdelayedShow = this.delayedShow = setInterval(function() {\n
+\t\t\t\tif ( tooltip.is( ":visible" ) ) {\n
+\t\t\t\t\tposition( positionOption.of );\n
+\t\t\t\t\tclearInterval( delayedShow );\n
+\t\t\t\t}\n
+\t\t\t}, $.fx.interval );\n
+\t\t}\n
+\n
+\t\tthis._trigger( "open", event, { tooltip: tooltip } );\n
+\n
+\t\tevents = {\n
+\t\t\tkeyup: function( event ) {\n
+\t\t\t\tif ( event.keyCode === $.ui.keyCode.ESCAPE ) {\n
+\t\t\t\t\tvar fakeEvent = $.Event(event);\n
+\t\t\t\t\tfakeEvent.currentTarget = target[0];\n
+\t\t\t\t\tthis.close( fakeEvent, true );\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tremove: function() {\n
+\t\t\t\tthis._removeTooltip( tooltip );\n
+\t\t\t}\n
+\t\t};\n
+\t\tif ( !event || event.type === "mouseover" ) {\n
+\t\t\tevents.mouseleave = "close";\n
+\t\t}\n
+\t\tif ( !event || event.type === "focusin" ) {\n
+\t\t\tevents.focusout = "close";\n
+\t\t}\n
+\t\tthis._on( true, target, events );\n
+\t},\n
+\n
+\tclose: function( event ) {\n
+\t\tvar that = this,\n
+\t\t\ttarget = $( event ? event.currentTarget : this.element ),\n
+\t\t\ttooltip = this._find( target );\n
+\n
+\t\t// disabling closes the tooltip, so we need to track when we\'re closing\n
+\t\t// to avoid an infinite loop in case the tooltip becomes disabled on close\n
+\t\tif ( this.closing ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Clear the interval for delayed tracking tooltips\n
+\t\tclearInterval( this.delayedShow );\n
+\n
+\t\t// only set title if we had one before (see comment in _open())\n
+\t\tif ( target.data( "ui-tooltip-title" ) ) {\n
+\t\t\ttarget.attr( "title", target.data( "ui-tooltip-title" ) );\n
+\t\t}\n
+\n
+\t\tremoveDescribedBy( target );\n
+\n
+\t\ttooltip.stop( true );\n
+\t\tthis._hide( tooltip, this.options.hide, function() {\n
+\t\t\tthat._removeTooltip( $( this ) );\n
+\t\t});\n
+\n
+\t\ttarget.removeData( "ui-tooltip-open" );\n
+\t\tthis._off( target, "mouseleave focusout keyup" );\n
+\t\t// Remove \'remove\' binding only on delegated targets\n
+\t\tif ( target[0] !== this.element[0] ) {\n
+\t\t\tthis._off( target, "remove" );\n
+\t\t}\n
+\t\tthis._off( this.document, "mousemove" );\n
+\n
+\t\tif ( event && event.type === "mouseleave" ) {\n
+\t\t\t$.each( this.parents, function( id, parent ) {\n
+\t\t\t\t$( parent.element ).attr( "title", parent.title );\n
+\t\t\t\tdelete that.parents[ id ];\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tthis.closing = true;\n
+\t\tthis._trigger( "close", event, { tooltip: tooltip } );\n
+\t\tthis.closing = false;\n
+\t},\n
+\n
+\t_tooltip: function( element ) {\n
+\t\tvar id = "ui-tooltip-" + increments++,\n
+\t\t\ttooltip = $( "<div>" )\n
+\t\t\t\t.attr({\n
+\t\t\t\t\tid: id,\n
+\t\t\t\t\trole: "tooltip"\n
+\t\t\t\t})\n
+\t\t\t\t.addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +\n
+\t\t\t\t\t( this.options.tooltipClass || "" ) );\n
+\t\t$( "<div>" )\n
+\t\t\t.addClass( "ui-tooltip-content" )\n
+\t\t\t.appendTo( tooltip );\n
+\t\ttooltip.appendTo( this.document[0].body );\n
+\t\tthis.tooltips[ id ] = element;\n
+\t\treturn tooltip;\n
+\t},\n
+\n
+\t_find: function( target ) {\n
+\t\tvar id = target.data( "ui-tooltip-id" );\n
+\t\treturn id ? $( "#" + id ) : $();\n
+\t},\n
+\n
+\t_removeTooltip: function( tooltip ) {\n
+\t\ttooltip.remove();\n
+\t\tdelete this.tooltips[ tooltip.attr( "id" ) ];\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tvar that = this;\n
+\n
+\t\t// close open tooltips\n
+\t\t$.each( this.tooltips, function( id, element ) {\n
+\t\t\t// Delegate to close method to handle common cleanup\n
+\t\t\tvar event = $.Event( "blur" );\n
+\t\t\tevent.target = event.currentTarget = element[0];\n
+\t\t\tthat.close( event, true );\n
+\n
+\t\t\t// Remove immediately; destroying an open tooltip doesn\'t use the\n
+\t\t\t// hide animation\n
+\t\t\t$( "#" + id ).remove();\n
+\n
+\t\t\t// Restore the title\n
+\t\t\tif ( element.data( "ui-tooltip-title" ) ) {\n
+\t\t\t\telement.attr( "title", element.data( "ui-tooltip-title" ) );\n
+\t\t\t\telement.removeData( "ui-tooltip-title" );\n
+\t\t\t}\n
+\t\t});\n
+\t}\n
+});\n
+\n
+}( jQuery ) );\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.flot.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.flot.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..dd96530128df1b5a1ca896b0a80c5de2dbf28c23
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.flot.js.xml
@@ -0,0 +1,3227 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681769.97</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jquery.flot.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>122971</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/* Javascript plotting library for jQuery, version 0.8.3.\n
+\n
+Copyright (c) 2007-2014 IOLA and Ole Laursen.\n
+Licensed under the MIT license.\n
+\n
+*/\n
+\n
+// first an inline dependency, jquery.colorhelpers.js, we inline it here\n
+// for convenience\n
+\n
+/* Plugin for jQuery for working with colors.\n
+ *\n
+ * Version 1.1.\n
+ *\n
+ * Inspiration from jQuery color animation plugin by John Resig.\n
+ *\n
+ * Released under the MIT license by Ole Laursen, October 2009.\n
+ *\n
+ * Examples:\n
+ *\n
+ *   $.color.parse("#fff").scale(\'rgb\', 0.25).add(\'a\', -0.5).toString()\n
+ *   var c = $.color.extract($("#mydiv"), \'background-color\');\n
+ *   console.log(c.r, c.g, c.b, c.a);\n
+ *   $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)"\n
+ *\n
+ * Note that .scale() and .add() return the same modified object\n
+ * instead of making a new one.\n
+ *\n
+ * V. 1.1: Fix error handling so e.g. parsing an empty string does\n
+ * produce a color rather than just crashing.\n
+ */\n
+(function($){$.color={};$.color.make=function(r,g,b,a){var o={};o.r=r||0;o.g=g||0;o.b=b||0;o.a=a!=null?a:1;o.add=function(c,d){for(var i=0;i<c.length;++i)o[c.charAt(i)]+=d;return o.normalize()};o.scale=function(c,f){for(var i=0;i<c.length;++i)o[c.charAt(i)]*=f;return o.normalize()};o.toString=function(){if(o.a>=1){return"rgb("+[o.r,o.g,o.b].join(",")+")"}else{return"rgba("+[o.r,o.g,o.b,o.a].join(",")+")"}};o.normalize=function(){function clamp(min,value,max){return value<min?min:value>max?max:value}o.r=clamp(0,parseInt(o.r),255);o.g=clamp(0,parseInt(o.g),255);o.b=clamp(0,parseInt(o.b),255);o.a=clamp(0,o.a,1);return o};o.clone=function(){return $.color.make(o.r,o.b,o.g,o.a)};return o.normalize()};$.color.extract=function(elem,css){var c;do{c=elem.css(css).toLowerCase();if(c!=""&&c!="transparent")break;elem=elem.parent()}while(elem.length&&!$.nodeName(elem.get(0),"body"));if(c=="rgba(0, 0, 0, 0)")c="transparent";return $.color.parse(c)};$.color.parse=function(str){var res,m=$.color.make;if(res=/rgb\\(\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*\\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10));if(res=/rgba\\(\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]{1,3})\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\s*\\)/.exec(str))return m(parseInt(res[1],10),parseInt(res[2],10),parseInt(res[3],10),parseFloat(res[4]));if(res=/rgb\\(\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*\\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55);if(res=/rgba\\(\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\%\\s*,\\s*([0-9]+(?:\\.[0-9]+)?)\\s*\\)/.exec(str))return m(parseFloat(res[1])*2.55,parseFloat(res[2])*2.55,parseFloat(res[3])*2.55,parseFloat(res[4]));if(res=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(str))return m(parseInt(res[1],16),parseInt(res[2],16),parseInt(res[3],16));if(res=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(str))return m(parseInt(res[1]+res[1],16),parseInt(res[2]+res[2],16),parseInt(res[3]+res[3],16));var name=$.trim(str).toLowerCase();if(name=="transparent")return m(255,255,255,0);else{res=lookupColors[name]||[0,0,0];return m(res[0],res[1],res[2])}};var lookupColors={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery);\n
+\n
+// the actual Flot code\n
+(function($) {\n
+\n
+\t// Cache the prototype hasOwnProperty for faster access\n
+\n
+\tvar hasOwnProperty = Object.prototype.hasOwnProperty;\n
+\n
+    // A shim to provide \'detach\' to jQuery versions prior to 1.4.  Using a DOM\n
+    // operation produces the same effect as detach, i.e. removing the element\n
+    // without touching its jQuery data.\n
+\n
+    // Do not merge this into Flot 0.9, since it requires jQuery 1.4.4+.\n
+\n
+    if (!$.fn.detach) {\n
+        $.fn.detach = function() {\n
+            return this.each(function() {\n
+                if (this.parentNode) {\n
+                    this.parentNode.removeChild( this );\n
+                }\n
+            });\n
+        };\n
+    }\n
+\n
+\t///////////////////////////////////////////////////////////////////////////\n
+\t// The Canvas object is a wrapper around an HTML5 <canvas> tag.\n
+\t//\n
+\t// @constructor\n
+\t// @param {string} cls List of classes to apply to the canvas.\n
+\t// @param {element} container Element onto which to append the canvas.\n
+\t//\n
+\t// Requiring a container is a little iffy, but unfortunately canvas\n
+\t// operations don\'t work unless the canvas is attached to the DOM.\n
+\n
+\tfunction Canvas(cls, container) {\n
+\n
+\t\tvar element = container.children("." + cls)[0];\n
+\n
+\t\tif (element == null) {\n
+\n
+\t\t\telement = document.createElement("canvas");\n
+\t\t\telement.className = cls;\n
+\n
+\t\t\t$(element).css({ direction: "ltr", position: "absolute", left: 0, top: 0 })\n
+\t\t\t\t.appendTo(container);\n
+\n
+\t\t\t// If HTML5 Canvas isn\'t available, fall back to [Ex|Flash]canvas\n
+\n
+\t\t\tif (!element.getContext) {\n
+\t\t\t\tif (window.G_vmlCanvasManager) {\n
+\t\t\t\t\telement = window.G_vmlCanvasManager.initElement(element);\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthrow new Error("Canvas is not available. If you\'re using IE with a fall-back such as Excanvas, then there\'s either a mistake in your conditional include, or the page has no DOCTYPE and is rendering in Quirks Mode.");\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis.element = element;\n
+\n
+\t\tvar context = this.context = element.getContext("2d");\n
+\n
+\t\t// Determine the screen\'s ratio of physical to device-independent\n
+\t\t// pixels.  This is the ratio between the canvas width that the browser\n
+\t\t// advertises and the number of pixels actually present in that space.\n
+\n
+\t\t// The iPhone 4, for example, has a device-independent width of 320px,\n
+\t\t// but its screen is actually 640px wide.  It therefore has a pixel\n
+\t\t// ratio of 2, while most normal devices have a ratio of 1.\n
+\n
+\t\tvar devicePixelRatio = window.devicePixelRatio || 1,\n
+\t\t\tbackingStoreRatio =\n
+\t\t\t\tcontext.webkitBackingStorePixelRatio ||\n
+\t\t\t\tcontext.mozBackingStorePixelRatio ||\n
+\t\t\t\tcontext.msBackingStorePixelRatio ||\n
+\t\t\t\tcontext.oBackingStorePixelRatio ||\n
+\t\t\t\tcontext.backingStorePixelRatio || 1;\n
+\n
+\t\tthis.pixelRatio = devicePixelRatio / backingStoreRatio;\n
+\n
+\t\t// Size the canvas to match the internal dimensions of its container\n
+\n
+\t\tthis.resize(container.width(), container.height());\n
+\n
+\t\t// Collection of HTML div layers for text overlaid onto the canvas\n
+\n
+\t\tthis.textContainer = null;\n
+\t\tthis.text = {};\n
+\n
+\t\t// Cache of text fragments and metrics, so we can avoid expensively\n
+\t\t// re-calculating them when the plot is re-rendered in a loop.\n
+\n
+\t\tthis._textCache = {};\n
+\t}\n
+\n
+\t// Resizes the canvas to the given dimensions.\n
+\t//\n
+\t// @param {number} width New width of the canvas, in pixels.\n
+\t// @param {number} width New height of the canvas, in pixels.\n
+\n
+\tCanvas.prototype.resize = function(width, height) {\n
+\n
+\t\tif (width <= 0 || height <= 0) {\n
+\t\t\tthrow new Error("Invalid dimensions for plot, width = " + width + ", height = " + height);\n
+\t\t}\n
+\n
+\t\tvar element = this.element,\n
+\t\t\tcontext = this.context,\n
+\t\t\tpixelRatio = this.pixelRatio;\n
+\n
+\t\t// Resize the canvas, increasing its density based on the display\'s\n
+\t\t// pixel ratio; basically giving it more pixels without increasing the\n
+\t\t// size of its element, to take advantage of the fact that retina\n
+\t\t// displays have that many more pixels in the same advertised space.\n
+\n
+\t\t// Resizing should reset the state (excanvas seems to be buggy though)\n
+\n
+\t\tif (this.width != width) {\n
+\t\t\telement.width = width * pixelRatio;\n
+\t\t\telement.style.width = width + "px";\n
+\t\t\tthis.width = width;\n
+\t\t}\n
+\n
+\t\tif (this.height != height) {\n
+\t\t\telement.height = height * pixelRatio;\n
+\t\t\telement.style.height = height + "px";\n
+\t\t\tthis.height = height;\n
+\t\t}\n
+\n
+\t\t// Save the context, so we can reset in case we get replotted.  The\n
+\t\t// restore ensure that we\'re really back at the initial state, and\n
+\t\t// should be safe even if we haven\'t saved the initial state yet.\n
+\n
+\t\tcontext.restore();\n
+\t\tcontext.save();\n
+\n
+\t\t// Scale the coordinate space to match the display density; so even though we\n
+\t\t// may have twice as many pixels, we still want lines and other drawing to\n
+\t\t// appear at the same size; the extra pixels will just make them crisper.\n
+\n
+\t\tcontext.scale(pixelRatio, pixelRatio);\n
+\t};\n
+\n
+\t// Clears the entire canvas area, not including any overlaid HTML text\n
+\n
+\tCanvas.prototype.clear = function() {\n
+\t\tthis.context.clearRect(0, 0, this.width, this.height);\n
+\t};\n
+\n
+\t// Finishes rendering the canvas, including managing the text overlay.\n
+\n
+\tCanvas.prototype.render = function() {\n
+\n
+\t\tvar cache = this._textCache;\n
+\n
+\t\t// For each text layer, add elements marked as active that haven\'t\n
+\t\t// already been rendered, and remove those that are no longer active.\n
+\n
+\t\tfor (var layerKey in cache) {\n
+\t\t\tif (hasOwnProperty.call(cache, layerKey)) {\n
+\n
+\t\t\t\tvar layer = this.getTextLayer(layerKey),\n
+\t\t\t\t\tlayerCache = cache[layerKey];\n
+\n
+\t\t\t\tlayer.hide();\n
+\n
+\t\t\t\tfor (var styleKey in layerCache) {\n
+\t\t\t\t\tif (hasOwnProperty.call(layerCache, styleKey)) {\n
+\t\t\t\t\t\tvar styleCache = layerCache[styleKey];\n
+\t\t\t\t\t\tfor (var key in styleCache) {\n
+\t\t\t\t\t\t\tif (hasOwnProperty.call(styleCache, key)) {\n
+\n
+\t\t\t\t\t\t\t\tvar positions = styleCache[key].positions;\n
+\n
+\t\t\t\t\t\t\t\tfor (var i = 0, position; position = positions[i]; i++) {\n
+\t\t\t\t\t\t\t\t\tif (position.active) {\n
+\t\t\t\t\t\t\t\t\t\tif (!position.rendered) {\n
+\t\t\t\t\t\t\t\t\t\t\tlayer.append(position.element);\n
+\t\t\t\t\t\t\t\t\t\t\tposition.rendered = true;\n
+\t\t\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t\t\t\tpositions.splice(i--, 1);\n
+\t\t\t\t\t\t\t\t\t\tif (position.rendered) {\n
+\t\t\t\t\t\t\t\t\t\t\tposition.element.detach();\n
+\t\t\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\t\t\tif (positions.length == 0) {\n
+\t\t\t\t\t\t\t\t\tdelete styleCache[key];\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\tlayer.show();\n
+\t\t\t}\n
+\t\t}\n
+\t};\n
+\n
+\t// Creates (if necessary) and returns the text overlay container.\n
+\t//\n
+\t// @param {string} classes String of space-separated CSS classes used to\n
+\t//     uniquely identify the text layer.\n
+\t// @return {object} The jQuery-wrapped text-layer div.\n
+\n
+\tCanvas.prototype.getTextLayer = function(classes) {\n
+\n
+\t\tvar layer = this.text[classes];\n
+\n
+\t\t// Create the text layer if it doesn\'t exist\n
+\n
+\t\tif (layer == null) {\n
+\n
+\t\t\t// Create the text layer container, if it doesn\'t exist\n
+\n
+\t\t\tif (this.textContainer == null) {\n
+\t\t\t\tthis.textContainer = $("<div class=\'flot-text\'></div>")\n
+\t\t\t\t\t.css({\n
+\t\t\t\t\t\tposition: "absolute",\n
+\t\t\t\t\t\ttop: 0,\n
+\t\t\t\t\t\tleft: 0,\n
+\t\t\t\t\t\tbottom: 0,\n
+\t\t\t\t\t\tright: 0,\n
+\t\t\t\t\t\t\'font-size\': "smaller",\n
+\t\t\t\t\t\tcolor: "#545454"\n
+\t\t\t\t\t})\n
+\t\t\t\t\t.insertAfter(this.element);\n
+\t\t\t}\n
+\n
+\t\t\tlayer = this.text[classes] = $("<div></div>")\n
+\t\t\t\t.addClass(classes)\n
+\t\t\t\t.css({\n
+\t\t\t\t\tposition: "absolute",\n
+\t\t\t\t\ttop: 0,\n
+\t\t\t\t\tleft: 0,\n
+\t\t\t\t\tbottom: 0,\n
+\t\t\t\t\tright: 0\n
+\t\t\t\t})\n
+\t\t\t\t.appendTo(this.textContainer);\n
+\t\t}\n
+\n
+\t\treturn layer;\n
+\t};\n
+\n
+\t// Creates (if necessary) and returns a text info object.\n
+\t//\n
+\t// The object looks like this:\n
+\t//\n
+\t// {\n
+\t//     width: Width of the text\'s wrapper div.\n
+\t//     height: Height of the text\'s wrapper div.\n
+\t//     element: The jQuery-wrapped HTML div containing the text.\n
+\t//     positions: Array of positions at which this text is drawn.\n
+\t// }\n
+\t//\n
+\t// The positions array contains objects that look like this:\n
+\t//\n
+\t// {\n
+\t//     active: Flag indicating whether the text should be visible.\n
+\t//     rendered: Flag indicating whether the text is currently visible.\n
+\t//     element: The jQuery-wrapped HTML div containing the text.\n
+\t//     x: X coordinate at which to draw the text.\n
+\t//     y: Y coordinate at which to draw the text.\n
+\t// }\n
+\t//\n
+\t// Each position after the first receives a clone of the original element.\n
+\t//\n
+\t// The idea is that that the width, height, and general \'identity\' of the\n
+\t// text is constant no matter where it is placed; the placements are a\n
+\t// secondary property.\n
+\t//\n
+\t// Canvas maintains a cache of recently-used text info objects; getTextInfo\n
+\t// either returns the cached element or creates a new entry.\n
+\t//\n
+\t// @param {string} layer A string of space-separated CSS classes uniquely\n
+\t//     identifying the layer containing this text.\n
+\t// @param {string} text Text string to retrieve info for.\n
+\t// @param {(string|object)=} font Either a string of space-separated CSS\n
+\t//     classes or a font-spec object, defining the text\'s font and style.\n
+\t// @param {number=} angle Angle at which to rotate the text, in degrees.\n
+\t//     Angle is currently unused, it will be implemented in the future.\n
+\t// @param {number=} width Maximum width of the text before it wraps.\n
+\t// @return {object} a text info object.\n
+\n
+\tCanvas.prototype.getTextInfo = function(layer, text, font, angle, width) {\n
+\n
+\t\tvar textStyle, layerCache, styleCache, info;\n
+\n
+\t\t// Cast the value to a string, in case we were given a number or such\n
+\n
+\t\ttext = "" + text;\n
+\n
+\t\t// If the font is a font-spec object, generate a CSS font definition\n
+\n
+\t\tif (typeof font === "object") {\n
+\t\t\ttextStyle = font.style + " " + font.variant + " " + font.weight + " " + font.size + "px/" + font.lineHeight + "px " + font.family;\n
+\t\t} else {\n
+\t\t\ttextStyle = font;\n
+\t\t}\n
+\n
+\t\t// Retrieve (or create) the cache for the text\'s layer and styles\n
+\n
+\t\tlayerCache = this._textCache[layer];\n
+\n
+\t\tif (layerCache == null) {\n
+\t\t\tlayerCache = this._textCache[layer] = {};\n
+\t\t}\n
+\n
+\t\tstyleCache = layerCache[textStyle];\n
+\n
+\t\tif (styleCache == null) {\n
+\t\t\tstyleCache = layerCache[textStyle] = {};\n
+\t\t}\n
+\n
+\t\tinfo = styleCache[text];\n
+\n
+\t\t// If we can\'t find a matching element in our cache, create a new one\n
+\n
+\t\tif (info == null) {\n
+\n
+\t\t\tvar element = $("<div></div>").html(text)\n
+\t\t\t\t.css({\n
+\t\t\t\t\tposition: "absolute",\n
+\t\t\t\t\t\'max-width\': width,\n
+\t\t\t\t\ttop: -9999\n
+\t\t\t\t})\n
+\t\t\t\t.appendTo(this.getTextLayer(layer));\n
+\n
+\t\t\tif (typeof font === "object") {\n
+\t\t\t\telement.css({\n
+\t\t\t\t\tfont: textStyle,\n
+\t\t\t\t\tcolor: font.color\n
+\t\t\t\t});\n
+\t\t\t} else if (typeof font === "string") {\n
+\t\t\t\telement.addClass(font);\n
+\t\t\t}\n
+\n
+\t\t\tinfo = styleCache[text] = {\n
+\t\t\t\twidth: element.outerWidth(true),\n
+\t\t\t\theight: element.outerHeight(true),\n
+\t\t\t\telement: element,\n
+\t\t\t\tpositions: []\n
+\t\t\t};\n
+\n
+\t\t\telement.detach();\n
+\t\t}\n
+\n
+\t\treturn info;\n
+\t};\n
+\n
+\t// Adds a text string to the canvas text overlay.\n
+\t//\n
+\t// The text isn\'t drawn immediately; it is marked as rendering, which will\n
+\t// result in its addition to the canvas on the next render pass.\n
+\t//\n
+\t// @param {string} layer A string of space-separated CSS classes uniquely\n
+\t//     identifying the layer containing this text.\n
+\t// @param {number} x X coordinate at which to draw the text.\n
+\t// @param {number} y Y coordinate at which to draw the text.\n
+\t// @param {string} text Text string to draw.\n
+\t// @param {(string|object)=} font Either a string of space-separated CSS\n
+\t//     classes or a font-spec object, defining the text\'s font and style.\n
+\t// @param {number=} angle Angle at which to rotate the text, in degrees.\n
+\t//     Angle is currently unused, it will be implemented in the future.\n
+\t// @param {number=} width Maximum width of the text before it wraps.\n
+\t// @param {string=} halign Horizontal alignment of the text; either "left",\n
+\t//     "center" or "right".\n
+\t// @param {string=} valign Vertical alignment of the text; either "top",\n
+\t//     "middle" or "bottom".\n
+\n
+\tCanvas.prototype.addText = function(layer, x, y, text, font, angle, width, halign, valign) {\n
+\n
+\t\tvar info = this.getTextInfo(layer, text, font, angle, width),\n
+\t\t\tpositions = info.positions;\n
+\n
+\t\t// Tweak the div\'s position to match the text\'s alignment\n
+\n
+\t\tif (halign == "center") {\n
+\t\t\tx -= info.width / 2;\n
+\t\t} else if (halign == "right") {\n
+\t\t\tx -= info.width;\n
+\t\t}\n
+\n
+\t\tif (valign == "middle") {\n
+\t\t\ty -= info.height / 2;\n
+\t\t} else if (valign == "bottom") {\n
+\t\t\ty -= info.height;\n
+\t\t}\n
+\n
+\t\t// Determine whether this text already exists at this position.\n
+\t\t// If so, mark it for inclusion in the next render pass.\n
+\n
+\t\tfor (var i = 0, position; position = positions[i]; i++) {\n
+\t\t\tif (position.x == x && position.y == y) {\n
+\t\t\t\tposition.active = true;\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// If the text doesn\'t exist at this position, create a new entry\n
+\n
+\t\t// For the very first position we\'ll re-use the original element,\n
+\t\t// while for subsequent ones we\'ll clone it.\n
+\n
+\t\tposition = {\n
+\t\t\tactive: true,\n
+\t\t\trendered: false,\n
+\t\t\telement: positions.length ? info.element.clone() : info.element,\n
+\t\t\tx: x,\n
+\t\t\ty: y\n
+\t\t};\n
+\n
+\t\tpositions.push(position);\n
+\n
+\t\t// Move the element to its final position within the container\n
+\n
+\t\tposition.element.css({\n
+\t\t\ttop: Math.round(y),\n
+\t\t\tleft: Math.round(x),\n
+\t\t\t\'text-align\': halign\t// In case the text wraps\n
+\t\t});\n
+\t};\n
+\n
+\t// Removes one or more text strings from the canvas text overlay.\n
+\t//\n
+\t// If no parameters are given, all text within the layer is removed.\n
+\t//\n
+\t// Note that the text is not immediately removed; it is simply marked as\n
+\t// inactive, which will result in its removal on the next render pass.\n
+\t// This avoids the performance penalty for \'clear and redraw\' behavior,\n
+\t// where we potentially get rid of all text on a layer, but will likely\n
+\t// add back most or all of it later, as when redrawing axes, for example.\n
+\t//\n
+\t// @param {string} layer A string of space-separated CSS classes uniquely\n
+\t//     identifying the layer containing this text.\n
+\t// @param {number=} x X coordinate of the text.\n
+\t// @param {number=} y Y coordinate of the text.\n
+\t// @param {string=} text Text string to remove.\n
+\t// @param {(string|object)=} font Either a string of space-separated CSS\n
+\t//     classes or a font-spec object, defining the text\'s font and style.\n
+\t// @param {number=} angle Angle at which the text is rotated, in degrees.\n
+\t//     Angle is currently unused, it will be implemented in the future.\n
+\n
+\tCanvas.prototype.removeText = function(layer, x, y, text, font, angle) {\n
+\t\tif (text == null) {\n
+\t\t\tvar layerCache = this._textCache[layer];\n
+\t\t\tif (layerCache != null) {\n
+\t\t\t\tfor (var styleKey in layerCache) {\n
+\t\t\t\t\tif (hasOwnProperty.call(layerCache, styleKey)) {\n
+\t\t\t\t\t\tvar styleCache = layerCache[styleKey];\n
+\t\t\t\t\t\tfor (var key in styleCache) {\n
+\t\t\t\t\t\t\tif (hasOwnProperty.call(styleCache, key)) {\n
+\t\t\t\t\t\t\t\tvar positions = styleCache[key].positions;\n
+\t\t\t\t\t\t\t\tfor (var i = 0, position; position = positions[i]; i++) {\n
+\t\t\t\t\t\t\t\t\tposition.active = false;\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tvar positions = this.getTextInfo(layer, text, font, angle).positions;\n
+\t\t\tfor (var i = 0, position; position = positions[i]; i++) {\n
+\t\t\t\tif (position.x == x && position.y == y) {\n
+\t\t\t\t\tposition.active = false;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t};\n
+\n
+\t///////////////////////////////////////////////////////////////////////////\n
+\t// The top-level container for the entire plot.\n
+\n
+    function Plot(placeholder, data_, options_, plugins) {\n
+        // data is on the form:\n
+        //   [ series1, series2 ... ]\n
+        // where series is either just the data as [ [x1, y1], [x2, y2], ... ]\n
+        // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... }\n
+\n
+        var series = [],\n
+            options = {\n
+                // the color theme used for graphs\n
+                colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"],\n
+                legend: {\n
+                    show: true,\n
+                    noColumns: 1, // number of colums in legend table\n
+                    labelFormatter: null, // fn: string -> string\n
+                    labelBoxBorderColor: "#ccc", // border color for the little label boxes\n
+                    container: null, // container (as jQuery object) to put legend in, null means default on top of graph\n
+                    position: "ne", // position of default legend container within plot\n
+                    margin: 5, // distance from grid edge to default legend container within plot\n
+                    backgroundColor: null, // null means auto-detect\n
+                    backgroundOpacity: 0.85, // set to 0 to avoid background\n
+                    sorted: null    // default to no legend sorting\n
+                },\n
+                xaxis: {\n
+                    show: null, // null = auto-detect, true = always, false = never\n
+                    position: "bottom", // or "top"\n
+                    mode: null, // null or "time"\n
+                    font: null, // null (derived from CSS in placeholder) or object like { size: 11, lineHeight: 13, style: "italic", weight: "bold", family: "sans-serif", variant: "small-caps" }\n
+                    color: null, // base color, labels, ticks\n
+                    tickColor: null, // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)"\n
+                    transform: null, // null or f: number -> number to transform axis\n
+                    inverseTransform: null, // if transform is set, this should be the inverse function\n
+                    min: null, // min. value to show, null means set automatically\n
+                    max: null, // max. value to show, null means set automatically\n
+                    autoscaleMargin: null, // margin in % to add if auto-setting min/max\n
+                    ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks\n
+                    tickFormatter: null, // fn: number -> string\n
+                    labelWidth: null, // size of tick labels in pixels\n
+                    labelHeight: null,\n
+                    reserveSpace: null, // whether to reserve space even if axis isn\'t shown\n
+                    tickLength: null, // size in pixels of ticks, or "full" for whole line\n
+                    alignTicksWithAxis: null, // axis number or null for no sync\n
+                    tickDecimals: null, // no. of decimals, null means auto\n
+                    tickSize: null, // number or [number, "unit"]\n
+                    minTickSize: null // number or [number, "unit"]\n
+                },\n
+                yaxis: {\n
+                    autoscaleMargin: 0.02,\n
+                    position: "left" // or "right"\n
+                },\n
+                xaxes: [],\n
+                yaxes: [],\n
+                series: {\n
+                    points: {\n
+                        show: false,\n
+                        radius: 3,\n
+                        lineWidth: 2, // in pixels\n
+                        fill: true,\n
+                        fillColor: "#ffffff",\n
+                        symbol: "circle" // or callback\n
+                    },\n
+                    lines: {\n
+                        // we don\'t put in show: false so we can see\n
+                        // whether lines were actively disabled\n
+                        lineWidth: 2, // in pixels\n
+                        fill: false,\n
+                        fillColor: null,\n
+                        steps: false\n
+                        // Omit \'zero\', so we can later default its value to\n
+                        // match that of the \'fill\' option.\n
+                    },\n
+                    bars: {\n
+                        show: false,\n
+                        lineWidth: 2, // in pixels\n
+                        barWidth: 1, // in units of the x axis\n
+                        fill: true,\n
+                        fillColor: null,\n
+                        align: "left", // "left", "right", or "center"\n
+                        horizontal: false,\n
+                        zero: true\n
+                    },\n
+                    shadowSize: 3,\n
+                    highlightColor: null\n
+                },\n
+                grid: {\n
+                    show: true,\n
+                    aboveData: false,\n
+                    color: "#545454", // primary color used for outline and labels\n
+                    backgroundColor: null, // null for transparent, else color\n
+                    borderColor: null, // set if different from the grid color\n
+                    tickColor: null, // color for the ticks, e.g. "rgba(0,0,0,0.15)"\n
+                    margin: 0, // distance from the canvas edge to the grid\n
+                    labelMargin: 5, // in pixels\n
+                    axisMargin: 8, // in pixels\n
+                    borderWidth: 2, // in pixels\n
+                    minBorderMargin: null, // in pixels, null means taken from points radius\n
+                    markings: null, // array of ranges or fn: axes -> array of ranges\n
+                    markingsColor: "#f4f4f4",\n
+                    markingsLineWidth: 2,\n
+                    // interactive stuff\n
+                    clickable: false,\n
+                    hoverable: false,\n
+                    autoHighlight: true, // highlight in case mouse is near\n
+                    mouseActiveRadius: 10 // how far the mouse can be away to activate an item\n
+                },\n
+                interaction: {\n
+                    redrawOverlayInterval: 1000/60 // time between updates, -1 means in same flow\n
+                },\n
+                hooks: {}\n
+            },\n
+        surface = null,     // the canvas for the plot itself\n
+        overlay = null,     // canvas for interactive stuff on top of plot\n
+        eventHolder = null, // jQuery object that events should be bound to\n
+        ctx = null, octx = null,\n
+        xaxes = [], yaxes = [],\n
+        plotOffset = { left: 0, right: 0, top: 0, bottom: 0},\n
+        plotWidth = 0, plotHeight = 0,\n
+        hooks = {\n
+            processOptions: [],\n
+            processRawData: [],\n
+            processDatapoints: [],\n
+            processOffset: [],\n
+            drawBackground: [],\n
+            drawSeries: [],\n
+            draw: [],\n
+            bindEvents: [],\n
+            drawOverlay: [],\n
+            shutdown: []\n
+        },\n
+        plot = this;\n
+\n
+        // public functions\n
+        plot.setData = setData;\n
+        plot.setupGrid = setupGrid;\n
+        plot.draw = draw;\n
+        plot.getPlaceholder = function() { return placeholder; };\n
+        plot.getCanvas = function() { return surface.element; };\n
+        plot.getPlotOffset = function() { return plotOffset; };\n
+        plot.width = function () { return plotWidth; };\n
+        plot.height = function () { return plotHeight; };\n
+        plot.offset = function () {\n
+            var o = eventHolder.offset();\n
+            o.left += plotOffset.left;\n
+            o.top += plotOffset.top;\n
+            return o;\n
+        };\n
+        plot.getData = function () { return series; };\n
+        plot.getAxes = function () {\n
+            var res = {}, i;\n
+            $.each(xaxes.concat(yaxes), function (_, axis) {\n
+                if (axis)\n
+                    res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis;\n
+            });\n
+            return res;\n
+        };\n
+        plot.getXAxes = function () { return xaxes; };\n
+        plot.getYAxes = function () { return yaxes; };\n
+        plot.c2p = canvasToAxisCoords;\n
+        plot.p2c = axisToCanvasCoords;\n
+        plot.getOptions = function () { return options; };\n
+        plot.highlight = highlight;\n
+        plot.unhighlight = unhighlight;\n
+        plot.triggerRedrawOverlay = triggerRedrawOverlay;\n
+        plot.pointOffset = function(point) {\n
+            return {\n
+                left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left, 10),\n
+                top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top, 10)\n
+            };\n
+        };\n
+        plot.shutdown = shutdown;\n
+        plot.destroy = function () {\n
+            shutdown();\n
+            placeholder.removeData("plot").empty();\n
+\n
+            series = [];\n
+            options = null;\n
+            surface = null;\n
+            overlay = null;\n
+            eventHolder = null;\n
+            ctx = null;\n
+            octx = null;\n
+            xaxes = [];\n
+            yaxes = [];\n
+            hooks = null;\n
+            highlights = [];\n
+            plot = null;\n
+        };\n
+        plot.resize = function () {\n
+        \tvar width = placeholder.width(),\n
+        \t\theight = placeholder.height();\n
+            surface.resize(width, height);\n
+            overlay.resize(width, height);\n
+        };\n
+\n
+        // public attributes\n
+        plot.hooks = hooks;\n
+\n
+        // initialize\n
+        initPlugins(plot);\n
+        parseOptions(options_);\n
+        setupCanvases();\n
+        setData(data_);\n
+        setupGrid();\n
+        draw();\n
+        bindEvents();\n
+\n
+\n
+        function executeHooks(hook, args) {\n
+            args = [plot].concat(args);\n
+            for (var i = 0; i < hook.length; ++i)\n
+                hook[i].apply(this, args);\n
+        }\n
+\n
+        function initPlugins() {\n
+\n
+            // References to key classes, allowing plugins to modify them\n
+\n
+            var classes = {\n
+                Canvas: Canvas\n
+            };\n
+\n
+            for (var i = 0; i < plugins.length; ++i) {\n
+                var p = plugins[i];\n
+                p.init(plot, classes);\n
+                if (p.options)\n
+                    $.extend(true, options, p.options);\n
+            }\n
+        }\n
+\n
+        function parseOptions(opts) {\n
+\n
+            $.extend(true, options, opts);\n
+\n
+            // $.extend merges arrays, rather than replacing them.  When less\n
+            // colors are provided than the size of the default palette, we\n
+            // end up with those colors plus the remaining defaults, which is\n
+            // not expected behavior; avoid it by replacing them here.\n
+\n
+            if (opts && opts.colors) {\n
+            \toptions.colors = opts.colors;\n
+            }\n
+\n
+            if (options.xaxis.color == null)\n
+                options.xaxis.color = $.color.parse(options.grid.color).scale(\'a\', 0.22).toString();\n
+            if (options.yaxis.color == null)\n
+                options.yaxis.color = $.color.parse(options.grid.color).scale(\'a\', 0.22).toString();\n
+\n
+            if (options.xaxis.tickColor == null) // grid.tickColor for back-compatibility\n
+                options.xaxis.tickColor = options.grid.tickColor || options.xaxis.color;\n
+            if (options.yaxis.tickColor == null) // grid.tickColor for back-compatibility\n
+                options.yaxis.tickColor = options.grid.tickColor || options.yaxis.color;\n
+\n
+            if (options.grid.borderColor == null)\n
+                options.grid.borderColor = options.grid.color;\n
+            if (options.grid.tickColor == null)\n
+                options.grid.tickColor = $.color.parse(options.grid.color).scale(\'a\', 0.22).toString();\n
+\n
+            // Fill in defaults for axis options, including any unspecified\n
+            // font-spec fields, if a font-spec was provided.\n
+\n
+            // If no x/y axis options were provided, create one of each anyway,\n
+            // since the rest of the code assumes that they exist.\n
+\n
+            var i, axisOptions, axisCount,\n
+                fontSize = placeholder.css("font-size"),\n
+                fontSizeDefault = fontSize ? +fontSize.replace("px", "") : 13,\n
+                fontDefaults = {\n
+                    style: placeholder.css("font-style"),\n
+                    size: Math.round(0.8 * fontSizeDefault),\n
+                    variant: placeholder.css("font-variant"),\n
+                    weight: placeholder.css("font-weight"),\n
+                    family: placeholder.css("font-family")\n
+                };\n
+\n
+            axisCount = options.xaxes.length || 1;\n
+            for (i = 0; i < axisCount; ++i) {\n
+\n
+                axisOptions = options.xaxes[i];\n
+                if (axisOptions && !axisOptions.tickColor) {\n
+                    axisOptions.tickColor = axisOptions.color;\n
+                }\n
+\n
+                axisOptions = $.extend(true, {}, options.xaxis, axisOptions);\n
+                options.xaxes[i] = axisOptions;\n
+\n
+                if (axisOptions.font) {\n
+                    axisOptions.font = $.extend({}, fontDefaults, axisOptions.font);\n
+                    if (!axisOptions.font.color) {\n
+                        axisOptions.font.color = axisOptions.color;\n
+                    }\n
+                    if (!axisOptions.font.lineHeight) {\n
+                        axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15);\n
+                    }\n
+                }\n
+            }\n
+\n
+            axisCount = options.yaxes.length || 1;\n
+            for (i = 0; i < axisCount; ++i) {\n
+\n
+                axisOptions = options.yaxes[i];\n
+                if (axisOptions && !axisOptions.tickColor) {\n
+                    axisOptions.tickColor = axisOptions.color;\n
+                }\n
+\n
+                axisOptions = $.extend(true, {}, options.yaxis, axisOptions);\n
+                options.yaxes[i] = axisOptions;\n
+\n
+                if (axisOptions.font) {\n
+                    axisOptions.font = $.extend({}, fontDefaults, axisOptions.font);\n
+                    if (!axisOptions.font.color) {\n
+                        axisOptions.font.color = axisOptions.color;\n
+                    }\n
+                    if (!axisOptions.font.lineHeight) {\n
+                        axisOptions.font.lineHeight = Math.round(axisOptions.font.size * 1.15);\n
+                    }\n
+                }\n
+            }\n
+\n
+            // backwards compatibility, to be removed in future\n
+            if (options.xaxis.noTicks && options.xaxis.ticks == null)\n
+                options.xaxis.ticks = options.xaxis.noTicks;\n
+            if (options.yaxis.noTicks && options.yaxis.ticks == null)\n
+                options.yaxis.ticks = options.yaxis.noTicks;\n
+            if (options.x2axis) {\n
+                options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis);\n
+                options.xaxes[1].position = "top";\n
+                // Override the inherit to allow the axis to auto-scale\n
+                if (options.x2axis.min == null) {\n
+                    options.xaxes[1].min = null;\n
+                }\n
+                if (options.x2axis.max == null) {\n
+                    options.xaxes[1].max = null;\n
+                }\n
+            }\n
+            if (options.y2axis) {\n
+                options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis);\n
+                options.yaxes[1].position = "right";\n
+                // Override the inherit to allow the axis to auto-scale\n
+                if (options.y2axis.min == null) {\n
+                    options.yaxes[1].min = null;\n
+                }\n
+                if (options.y2axis.max == null) {\n
+                    options.yaxes[1].max = null;\n
+                }\n
+            }\n
+            if (options.grid.coloredAreas)\n
+                options.grid.markings = options.grid.coloredAreas;\n
+            if (options.grid.coloredAreasColor)\n
+                options.grid.markingsColor = options.grid.coloredAreasColor;\n
+            if (options.lines)\n
+                $.extend(true, options.series.lines, options.lines);\n
+            if (options.points)\n
+                $.extend(true, options.series.points, options.points);\n
+            if (options.bars)\n
+                $.extend(true, options.series.bars, options.bars);\n
+            if (options.shadowSize != null)\n
+                options.series.shadowSize = options.shadowSize;\n
+            if (options.highlightColor != null)\n
+                options.series.highlightColor = options.highlightColor;\n
+\n
+            // save options on axes for future reference\n
+            for (i = 0; i < options.xaxes.length; ++i)\n
+                getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i];\n
+            for (i = 0; i < options.yaxes.length; ++i)\n
+                getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i];\n
+\n
+            // add hooks from options\n
+            for (var n in hooks)\n
+                if (options.hooks[n] && options.hooks[n].length)\n
+                    hooks[n] = hooks[n].concat(options.hooks[n]);\n
+\n
+            executeHooks(hooks.processOptions, [options]);\n
+        }\n
+\n
+        function setData(d) {\n
+            series = parseData(d);\n
+            fillInSeriesOptions();\n
+            processData();\n
+        }\n
+\n
+        function parseData(d) {\n
+            var res = [];\n
+            for (var i = 0; i < d.length; ++i) {\n
+                var s = $.extend(true, {}, options.series);\n
+\n
+                if (d[i].data != null) {\n
+                    s.data = d[i].data; // move the data instead of deep-copy\n
+                    delete d[i].data;\n
+\n
+                    $.extend(true, s, d[i]);\n
+\n
+                    d[i].data = s.data;\n
+                }\n
+                else\n
+                    s.data = d[i];\n
+                res.push(s);\n
+            }\n
+\n
+            return res;\n
+        }\n
+\n
+        function axisNumber(obj, coord) {\n
+            var a = obj[coord + "axis"];\n
+            if (typeof a == "object") // if we got a real axis, extract number\n
+                a = a.n;\n
+            if (typeof a != "number")\n
+                a = 1; // default to first axis\n
+            return a;\n
+        }\n
+\n
+        function allAxes() {\n
+            // return flat array without annoying null entries\n
+            return $.grep(xaxes.concat(yaxes), function (a) { return a; });\n
+        }\n
+\n
+        function canvasToAxisCoords(pos) {\n
+            // return an object with x/y corresponding to all used axes\n
+            var res = {}, i, axis;\n
+            for (i = 0; i < xaxes.length; ++i) {\n
+                axis = xaxes[i];\n
+                if (axis && axis.used)\n
+                    res["x" + axis.n] = axis.c2p(pos.left);\n
+            }\n
+\n
+            for (i = 0; i < yaxes.length; ++i) {\n
+                axis = yaxes[i];\n
+                if (axis && axis.used)\n
+                    res["y" + axis.n] = axis.c2p(pos.top);\n
+            }\n
+\n
+            if (res.x1 !== undefined)\n
+                res.x = res.x1;\n
+            if (res.y1 !== undefined)\n
+                res.y = res.y1;\n
+\n
+            return res;\n
+        }\n
+\n
+        function axisToCanvasCoords(pos) {\n
+            // get canvas coords from the first pair of x/y found in pos\n
+            var res = {}, i, axis, key;\n
+\n
+            for (i = 0; i < xaxes.length; ++i) {\n
+                axis = xaxes[i];\n
+                if (axis && axis.used) {\n
+                    key = "x" + axis.n;\n
+                    if (pos[key] == null && axis.n == 1)\n
+                        key = "x";\n
+\n
+                    if (pos[key] != null) {\n
+                        res.left = axis.p2c(pos[key]);\n
+                        break;\n
+                    }\n
+                }\n
+            }\n
+\n
+            for (i = 0; i < yaxes.length; ++i) {\n
+                axis = yaxes[i];\n
+                if (axis && axis.used) {\n
+                    key = "y" + axis.n;\n
+                    if (pos[key] == null && axis.n == 1)\n
+                        key = "y";\n
+\n
+                    if (pos[key] != null) {\n
+                        res.top = axis.p2c(pos[key]);\n
+                        break;\n
+                    }\n
+                }\n
+            }\n
+\n
+            return res;\n
+        }\n
+\n
+        function getOrCreateAxis(axes, number) {\n
+            if (!axes[number - 1])\n
+                axes[number - 1] = {\n
+                    n: number, // save the number for future reference\n
+                    direction: axes == xaxes ? "x" : "y",\n
+                    options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis)\n
+                };\n
+\n
+            return axes[number - 1];\n
+        }\n
+\n
+        function fillInSeriesOptions() {\n
+\n
+            var neededColors = series.length, maxIndex = -1, i;\n
+\n
+            // Subtract the number of series that already have fixed colors or\n
+            // color indexes from the number that we still need to generate.\n
+\n
+            for (i = 0; i < series.length; ++i) {\n
+                var sc = series[i].color;\n
+                if (sc != null) {\n
+                    neededColors--;\n
+                    if (typeof sc == "number" && sc > maxIndex) {\n
+                        maxIndex = sc;\n
+                    }\n
+                }\n
+            }\n
+\n
+            // If any of the series have fixed color indexes, then we need to\n
+            // generate at least as many colors as the highest index.\n
+\n
+            if (neededColors <= maxIndex) {\n
+                neededColors = maxIndex + 1;\n
+            }\n
+\n
+            // Generate all the colors, using first the option colors and then\n
+            // variations on those colors once they\'re exhausted.\n
+\n
+            var c, colors = [], colorPool = options.colors,\n
+                colorPoolSize = colorPool.length, variation = 0;\n
+\n
+            for (i = 0; i < neededColors; i++) {\n
+\n
+                c = $.color.parse(colorPool[i % colorPoolSize] || "#666");\n
+\n
+                // Each time we exhaust the colors in the pool we adjust\n
+                // a scaling factor used to produce more variations on\n
+                // those colors. The factor alternates negative/positive\n
+                // to produce lighter/darker colors.\n
+\n
+                // Reset the variation after every few cycles, or else\n
+                // it will end up producing only white or black colors.\n
+\n
+                if (i % colorPoolSize == 0 && i) {\n
+                    if (variation >= 0) {\n
+                        if (variation < 0.5) {\n
+                            variation = -variation - 0.2;\n
+                        } else variation = 0;\n
+                    } else variation = -variation;\n
+                }\n
+\n
+                colors[i] = c.scale(\'rgb\', 1 + variation);\n
+            }\n
+\n
+            // Finalize the series options, filling in their colors\n
+\n
+            var colori = 0, s;\n
+            for (i = 0; i < series.length; ++i) {\n
+                s = series[i];\n
+\n
+                // assign colors\n
+                if (s.color == null) {\n
+                    s.color = colors[colori].toString();\n
+                    ++colori;\n
+                }\n
+                else if (typeof s.color == "number")\n
+                    s.color = colors[s.color].toString();\n
+\n
+                // turn on lines automatically in case nothing is set\n
+                if (s.lines.show == null) {\n
+                    var v, show = true;\n
+                    for (v in s)\n
+                        if (s[v] && s[v].show) {\n
+                            show = false;\n
+                            break;\n
+                        }\n
+                    if (show)\n
+                        s.lines.show = true;\n
+                }\n
+\n
+                // If nothing was provided for lines.zero, default it to match\n
+                // lines.fill, since areas by default should extend to zero.\n
+\n
+                if (s.lines.zero == null) {\n
+                    s.lines.zero = !!s.lines.fill;\n
+                }\n
+\n
+                // setup axes\n
+                s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x"));\n
+                s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y"));\n
+            }\n
+        }\n
+\n
+        function processData() {\n
+            var topSentry = Number.POSITIVE_INFINITY,\n
+                bottomSentry = Number.NEGATIVE_INFINITY,\n
+                fakeInfinity = Number.MAX_VALUE,\n
+                i, j, k, m, length,\n
+                s, points, ps, x, y, axis, val, f, p,\n
+                data, format;\n
+\n
+            function updateAxis(axis, min, max) {\n
+                if (min < axis.datamin && min != -fakeInfinity)\n
+                    axis.datamin = min;\n
+                if (max > axis.datamax && max != fakeInfinity)\n
+                    axis.datamax = max;\n
+            }\n
+\n
+            $.each(allAxes(), function (_, axis) {\n
+                // init axis\n
+                axis.datamin = topSentry;\n
+                axis.datamax = bottomSentry;\n
+                axis.used = false;\n
+            });\n
+\n
+            for (i = 0; i < series.length; ++i) {\n
+                s = series[i];\n
+                s.datapoints = { points: [] };\n
+\n
+                executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]);\n
+            }\n
+\n
+            // first pass: clean and copy data\n
+            for (i = 0; i < series.length; ++i) {\n
+                s = series[i];\n
+\n
+                data = s.data;\n
+                format = s.datapoints.format;\n
+\n
+                if (!format) {\n
+                    format = [];\n
+                    // find out how to copy\n
+                    format.push({ x: true, number: true, required: true });\n
+                    format.push({ y: true, number: true, required: true });\n
+\n
+                    if (s.bars.show || (s.lines.show && s.lines.fill)) {\n
+                        var autoscale = !!((s.bars.show && s.bars.zero) || (s.lines.show && s.lines.zero));\n
+                        format.push({ y: true, number: true, required: false, defaultValue: 0, autoscale: autoscale });\n
+                        if (s.bars.horizontal) {\n
+                            delete format[format.length - 1].y;\n
+                            format[format.length - 1].x = true;\n
+                        }\n
+                    }\n
+\n
+                    s.datapoints.format = format;\n
+                }\n
+\n
+                if (s.datapoints.pointsize != null)\n
+                    continue; // already filled in\n
+\n
+                s.datapoints.pointsize = format.length;\n
+\n
+                ps = s.datapoints.pointsize;\n
+                points = s.datapoints.points;\n
+\n
+                var insertSteps = s.lines.show && s.lines.steps;\n
+                s.xaxis.used = s.yaxis.used = true;\n
+\n
+                for (j = k = 0; j < data.length; ++j, k += ps) {\n
+                    p = data[j];\n
+\n
+                    var nullify = p == null;\n
+                    if (!nullify) {\n
+                        for (m = 0; m < ps; ++m) {\n
+                            val = p[m];\n
+                            f = format[m];\n
+\n
+                            if (f) {\n
+                                if (f.number && val != null) {\n
+                                    val = +val; // convert to number\n
+                                    if (isNaN(val))\n
+                                        val = null;\n
+                                    else if (val == Infinity)\n
+                                        val = fakeInfinity;\n
+                                    else if (val == -Infinity)\n
+                                        val = -fakeInfinity;\n
+                                }\n
+\n
+                                if (val == null) {\n
+                                    if (f.required)\n
+                                        nullify = true;\n
+\n
+                                    if (f.defaultValue != null)\n
+                                        val = f.defaultValue;\n
+                                }\n
+                            }\n
+\n
+                            points[k + m] = val;\n
+                        }\n
+                    }\n
+\n
+                    if (nullify) {\n
+                        for (m = 0; m < ps; ++m) {\n
+                            val = points[k + m];\n
+                            if (val != null) {\n
+                                f = format[m];\n
+                                // extract min/max info\n
+                                if (f.autoscale !== false) {\n
+                                    if (f.x) {\n
+                                        updateAxis(s.xaxis, val, val);\n
+                                    }\n
+                                    if (f.y) {\n
+                                        updateAxis(s.yaxis, val, val);\n
+                                    }\n
+                                }\n
+                            }\n
+                            points[k + m] = null;\n
+                        }\n
+                    }\n
+                    else {\n
+                        // a little bit of line specific stuff that\n
+                        // perhaps shouldn\'t be here, but lacking\n
+                        // better means...\n
+                        if (insertSteps && k > 0\n
+                            && points[k - ps] != null\n
+                            && points[k - ps] != points[k]\n
+                            && points[k - ps + 1] != points[k + 1]) {\n
+                            // copy the point to make room for a middle point\n
+                            for (m = 0; m < ps; ++m)\n
+                                points[k + ps + m] = points[k + m];\n
+\n
+                            // middle point has same y\n
+                            points[k + 1] = points[k - ps + 1];\n
+\n
+                            // we\'ve added a point, better reflect that\n
+                            k += ps;\n
+                        }\n
+                    }\n
+                }\n
+            }\n
+\n
+            // give the hooks a chance to run\n
+            for (i = 0; i < series.length; ++i) {\n
+                s = series[i];\n
+\n
+                executeHooks(hooks.processDatapoints, [ s, s.datapoints]);\n
+            }\n
+\n
+            // second pass: find datamax/datamin for auto-scaling\n
+            for (i = 0; i < series.length; ++i) {\n
+                s = series[i];\n
+                points = s.datapoints.points;\n
+                ps = s.datapoints.pointsize;\n
+                format = s.datapoints.format;\n
+\n
+                var xmin = topSentry, ymin = topSentry,\n
+                    xmax = bottomSentry, ymax = bottomSentry;\n
+\n
+                for (j = 0; j < points.length; j += ps) {\n
+                    if (points[j] == null)\n
+                        continue;\n
+\n
+                    for (m = 0; m < ps; ++m) {\n
+                        val = points[j + m];\n
+                        f = format[m];\n
+                        if (!f || f.autoscale === false || val == fakeInfinity || val == -fakeInfinity)\n
+                            continue;\n
+\n
+                        if (f.x) {\n
+                            if (val < xmin)\n
+                                xmin = val;\n
+                            if (val > xmax)\n
+                                xmax = val;\n
+                        }\n
+                        if (f.y) {\n
+                            if (val < ymin)\n
+                                ymin = val;\n
+                            if (val > ymax)\n
+                                ymax = val;\n
+                        }\n
+                    }\n
+                }\n
+\n
+                if (s.bars.show) {\n
+                    // make sure we got room for the bar on the dancing floor\n
+                    var delta;\n
+\n
+                    switch (s.bars.align) {\n
+                        case "left":\n
+                            delta = 0;\n
+                            break;\n
+                        case "right":\n
+                            delta = -s.bars.barWidth;\n
+                            break;\n
+                        default:\n
+                            delta = -s.bars.barWidth / 2;\n
+                    }\n
+\n
+                    if (s.bars.horizontal) {\n
+                        ymin += delta;\n
+                        ymax += delta + s.bars.barWidth;\n
+                    }\n
+                    else {\n
+                        xmin += delta;\n
+                        xmax += delta + s.bars.barWidth;\n
+                    }\n
+                }\n
+\n
+                updateAxis(s.xaxis, xmin, xmax);\n
+                updateAxis(s.yaxis, ymin, ymax);\n
+            }\n
+\n
+            $.each(allAxes(), function (_, axis) {\n
+                if (axis.datamin == topSentry)\n
+                    axis.datamin = null;\n
+                if (axis.datamax == bottomSentry)\n
+                    axis.datamax = null;\n
+            });\n
+        }\n
+\n
+        function setupCanvases() {\n
+\n
+            // Make sure the placeholder is clear of everything except canvases\n
+            // from a previous plot in this container that we\'ll try to re-use.\n
+\n
+            placeholder.css("padding", 0) // padding messes up the positioning\n
+                .children().filter(function(){\n
+                    return !$(this).hasClass("flot-overlay") && !$(this).hasClass(\'flot-base\');\n
+                }).remove();\n
+\n
+            if (placeholder.css("position") == \'static\')\n
+                placeholder.css("position", "relative"); // for positioning labels and overlay\n
+\n
+            surface = new Canvas("flot-base", placeholder);\n
+            overlay = new Canvas("flot-overlay", placeholder); // overlay canvas for interactive features\n
+\n
+            ctx = surface.context;\n
+            octx = overlay.context;\n
+\n
+            // define which element we\'re listening for events on\n
+            eventHolder = $(overlay.element).unbind();\n
+\n
+            // If we\'re re-using a plot object, shut down the old one\n
+\n
+            var existing = placeholder.data("plot");\n
+\n
+            if (existing) {\n
+                existing.shutdown();\n
+                overlay.clear();\n
+            }\n
+\n
+            // save in case we get replotted\n
+            placeholder.data("plot", plot);\n
+        }\n
+\n
+        function bindEvents() {\n
+            // bind events\n
+            if (options.grid.hoverable) {\n
+                eventHolder.mousemove(onMouseMove);\n
+\n
+                // Use bind, rather than .mouseleave, because we officially\n
+                // still support jQuery 1.2.6, which doesn\'t define a shortcut\n
+                // for mouseenter or mouseleave.  This was a bug/oversight that\n
+                // was fixed somewhere around 1.3.x.  We can return to using\n
+                // .mouseleave when we drop support for 1.2.6.\n
+\n
+                eventHolder.bind("mouseleave", onMouseLeave);\n
+            }\n
+\n
+            if (options.grid.clickable)\n
+                eventHolder.click(onClick);\n
+\n
+            executeHooks(hooks.bindEvents, [eventHolder]);\n
+        }\n
+\n
+        function shutdown() {\n
+            if (redrawTimeout)\n
+                clearTimeout(redrawTimeout);\n
+\n
+            eventHolder.unbind("mousemove", onMouseMove);\n
+            eventHolder.unbind("mouseleave", onMouseLeave);\n
+            eventHolder.unbind("click", onClick);\n
+\n
+            executeHooks(hooks.shutdown, [eventHolder]);\n
+        }\n
+\n
+        function setTransformationHelpers(axis) {\n
+            // set helper functions on the axis, assumes plot area\n
+            // has been computed already\n
+\n
+            function identity(x) { return x; }\n
+\n
+            var s, m, t = axis.options.transform || identity,\n
+                it = axis.options.inverseTransform;\n
+\n
+            // precompute how much the axis is scaling a point\n
+            // in canvas space\n
+            if (axis.direction == "x") {\n
+                s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min));\n
+                m = Math.min(t(axis.max), t(axis.min));\n
+            }\n
+            else {\n
+                s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min));\n
+                s = -s;\n
+                m = Math.max(t(axis.max), t(axis.min));\n
+            }\n
+\n
+            // data point to canvas coordinate\n
+            if (t == identity) // slight optimization\n
+                axis.p2c = function (p) { return (p - m) * s; };\n
+            else\n
+                axis.p2c = function (p) { return (t(p) - m) * s; };\n
+            // canvas coordinate to data point\n
+            if (!it)\n
+                axis.c2p = function (c) { return m + c / s; };\n
+            else\n
+                axis.c2p = function (c) { return it(m + c / s); };\n
+        }\n
+\n
+        function measureTickLabels(axis) {\n
+\n
+            var opts = axis.options,\n
+                ticks = axis.ticks || [],\n
+                labelWidth = opts.labelWidth || 0,\n
+                labelHeight = opts.labelHeight || 0,\n
+                maxWidth = labelWidth || (axis.direction == "x" ? Math.floor(surface.width / (ticks.length || 1)) : null),\n
+                legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis",\n
+                layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles,\n
+                font = opts.font || "flot-tick-label tickLabel";\n
+\n
+            for (var i = 0; i < ticks.length; ++i) {\n
+\n
+                var t = ticks[i];\n
+\n
+                if (!t.label)\n
+                    continue;\n
+\n
+                var info = surface.getTextInfo(layer, t.label, font, null, maxWidth);\n
+\n
+                labelWidth = Math.max(labelWidth, info.width);\n
+                labelHeight = Math.max(labelHeight, info.height);\n
+            }\n
+\n
+            axis.labelWidth = opts.labelWidth || labelWidth;\n
+            axis.labelHeight = opts.labelHeight || labelHeight;\n
+        }\n
+\n
+        function allocateAxisBoxFirstPhase(axis) {\n
+            // find the bounding box of the axis by looking at label\n
+            // widths/heights and ticks, make room by diminishing the\n
+            // plotOffset; this first phase only looks at one\n
+            // dimension per axis, the other dimension depends on the\n
+            // other axes so will have to wait\n
+\n
+            var lw = axis.labelWidth,\n
+                lh = axis.labelHeight,\n
+                pos = axis.options.position,\n
+                isXAxis = axis.direction === "x",\n
+                tickLength = axis.options.tickLength,\n
+                axisMargin = options.grid.axisMargin,\n
+                padding = options.grid.labelMargin,\n
+                innermost = true,\n
+                outermost = true,\n
+                first = true,\n
+                found = false;\n
+\n
+            // Determine the axis\'s position in its direction and on its side\n
+\n
+            $.each(isXAxis ? xaxes : yaxes, function(i, a) {\n
+                if (a && (a.show || a.reserveSpace)) {\n
+                    if (a === axis) {\n
+                        found = true;\n
+                    } else if (a.options.position === pos) {\n
+                        if (found) {\n
+                            outermost = false;\n
+                        } else {\n
+                            innermost = false;\n
+                        }\n
+                    }\n
+                    if (!found) {\n
+                        first = false;\n
+                    }\n
+                }\n
+            });\n
+\n
+            // The outermost axis on each side has no margin\n
+\n
+            if (outermost) {\n
+                axisMargin = 0;\n
+            }\n
+\n
+            // The ticks for the first axis in each direction stretch across\n
+\n
+            if (tickLength == null) {\n
+                tickLength = first ? "full" : 5;\n
+            }\n
+\n
+            if (!isNaN(+tickLength))\n
+                padding += +tickLength;\n
+\n
+            if (isXAxis) {\n
+                lh += padding;\n
+\n
+                if (pos == "bottom") {\n
+                    plotOffset.bottom += lh + axisMargin;\n
+                    axis.box = { top: surface.height - plotOffset.bottom, height: lh };\n
+                }\n
+                else {\n
+                    axis.box = { top: plotOffset.top + axisMargin, height: lh };\n
+                    plotOffset.top += lh + axisMargin;\n
+                }\n
+            }\n
+            else {\n
+                lw += padding;\n
+\n
+                if (pos == "left") {\n
+                    axis.box = { left: plotOffset.left + axisMargin, width: lw };\n
+                    plotOffset.left += lw + axisMargin;\n
+                }\n
+                else {\n
+                    plotOffset.right += lw + axisMargin;\n
+                    axis.box = { left: surface.width - plotOffset.right, width: lw };\n
+                }\n
+            }\n
+\n
+             // save for future reference\n
+            axis.position = pos;\n
+            axis.tickLength = tickLength;\n
+            axis.box.padding = padding;\n
+            axis.innermost = innermost;\n
+        }\n
+\n
+        function allocateAxisBoxSecondPhase(axis) {\n
+            // now that all axis boxes have been placed in one\n
+            // dimension, we can set the remaining dimension coordinates\n
+            if (axis.direction == "x") {\n
+                axis.box.left = plotOffset.left - axis.labelWidth / 2;\n
+                axis.box.width = surface.width - plotOffset.left - plotOffset.right + axis.labelWidth;\n
+            }\n
+            else {\n
+                axis.box.top = plotOffset.top - axis.labelHeight / 2;\n
+                axis.box.height = surface.height - plotOffset.bottom - plotOffset.top + axis.labelHeight;\n
+            }\n
+        }\n
+\n
+        function adjustLayoutForThingsStickingOut() {\n
+            // possibly adjust plot offset to ensure everything stays\n
+            // inside the canvas and isn\'t clipped off\n
+\n
+            var minMargin = options.grid.minBorderMargin,\n
+                axis, i;\n
+\n
+            // check stuff from the plot (FIXME: this should just read\n
+            // a value from the series, otherwise it\'s impossible to\n
+            // customize)\n
+            if (minMargin == null) {\n
+                minMargin = 0;\n
+                for (i = 0; i < series.length; ++i)\n
+                    minMargin = Math.max(minMargin, 2 * (series[i].points.radius + series[i].points.lineWidth/2));\n
+            }\n
+\n
+            var margins = {\n
+                left: minMargin,\n
+                right: minMargin,\n
+                top: minMargin,\n
+                bottom: minMargin\n
+            };\n
+\n
+            // check axis labels, note we don\'t check the actual\n
+            // labels but instead use the overall width/height to not\n
+            // jump as much around with replots\n
+            $.each(allAxes(), function (_, axis) {\n
+                if (axis.reserveSpace && axis.ticks && axis.ticks.length) {\n
+                    if (axis.direction === "x") {\n
+                        margins.left = Math.max(margins.left, axis.labelWidth / 2);\n
+                        margins.right = Math.max(margins.right, axis.labelWidth / 2);\n
+                    } else {\n
+                        margins.bottom = Math.max(margins.bottom, axis.labelHeight / 2);\n
+                        margins.top = Math.max(margins.top, axis.labelHeight / 2);\n
+                    }\n
+                }\n
+            });\n
+\n
+            plotOffset.left = Math.ceil(Math.max(margins.left, plotOffset.left));\n
+            plotOffset.right = Math.ceil(Math.max(margins.right, plotOffset.right));\n
+            plotOffset.top = Math.ceil(Math.max(margins.top, plotOffset.top));\n
+            plotOffset.bottom = Math.ceil(Math.max(margins.bottom, plotOffset.bottom));\n
+        }\n
+\n
+        function setupGrid() {\n
+            var i, axes = allAxes(), showGrid = options.grid.show;\n
+\n
+            // Initialize the plot\'s offset from the edge of the canvas\n
+\n
+            for (var a in plotOffset) {\n
+                var margin = options.grid.margin || 0;\n
+                plotOffset[a] = typeof margin == "number" ? margin : margin[a] || 0;\n
+            }\n
+\n
+            executeHooks(hooks.processOffset, [plotOffset]);\n
+\n
+            // If the grid is visible, add its border width to the offset\n
+\n
+            for (var a in plotOffset) {\n
+                if(typeof(options.grid.borderWidth) == "object") {\n
+                    plotOffset[a] += showGrid ? options.grid.borderWidth[a] : 0;\n
+                }\n
+                else {\n
+                    plotOffset[a] += showGrid ? options.grid.borderWidth : 0;\n
+                }\n
+            }\n
+\n
+            $.each(axes, function (_, axis) {\n
+                var axisOpts = axis.options;\n
+                axis.show = axisOpts.show == null ? axis.used : axisOpts.show;\n
+                axis.reserveSpace = axisOpts.reserveSpace == null ? axis.show : axisOpts.reserveSpace;\n
+                setRange(axis);\n
+            });\n
+\n
+            if (showGrid) {\n
+\n
+                var allocatedAxes = $.grep(axes, function (axis) {\n
+                    return axis.show || axis.reserveSpace;\n
+                });\n
+\n
+                $.each(allocatedAxes, function (_, axis) {\n
+                    // make the ticks\n
+                    setupTickGeneration(axis);\n
+                    setTicks(axis);\n
+                    snapRangeToTicks(axis, axis.ticks);\n
+                    // find labelWidth/Height for axis\n
+                    measureTickLabels(axis);\n
+                });\n
+\n
+                // with all dimensions calculated, we can compute the\n
+                // axis bounding boxes, start from the outside\n
+                // (reverse order)\n
+                for (i = allocatedAxes.length - 1; i >= 0; --i)\n
+                    allocateAxisBoxFirstPhase(allocatedAxes[i]);\n
+\n
+                // make sure we\'ve got enough space for things that\n
+                // might stick out\n
+                adjustLayoutForThingsStickingOut();\n
+\n
+                $.each(allocatedAxes, function (_, axis) {\n
+                    allocateAxisBoxSecondPhase(axis);\n
+                });\n
+            }\n
+\n
+            plotWidth = surface.width - plotOffset.left - plotOffset.right;\n
+            plotHeight = surface.height - plotOffset.bottom - plotOffset.top;\n
+\n
+            // now we got the proper plot dimensions, we can compute the scaling\n
+            $.each(axes, function (_, axis) {\n
+                setTransformationHelpers(axis);\n
+            });\n
+\n
+            if (showGrid) {\n
+                drawAxisLabels();\n
+            }\n
+\n
+            insertLegend();\n
+        }\n
+\n
+        function setRange(axis) {\n
+            var opts = axis.options,\n
+                min = +(opts.min != null ? opts.min : axis.datamin),\n
+                max = +(opts.max != null ? opts.max : axis.datamax),\n
+                delta = max - min;\n
+\n
+            if (delta == 0.0) {\n
+                // degenerate case\n
+                var widen = max == 0 ? 1 : 0.01;\n
+\n
+                if (opts.min == null)\n
+                    min -= widen;\n
+                // always widen max if we couldn\'t widen min to ensure we\n
+                // don\'t fall into min == max which doesn\'t work\n
+                if (opts.max == null || opts.min != null)\n
+                    max += widen;\n
+            }\n
+            else {\n
+                // consider autoscaling\n
+                var margin = opts.autoscaleMargin;\n
+                if (margin != null) {\n
+                    if (opts.min == null) {\n
+                        min -= delta * margin;\n
+                        // make sure we don\'t go below zero if all values\n
+                        // are positive\n
+                        if (min < 0 && axis.datamin != null && axis.datamin >= 0)\n
+                            min = 0;\n
+                    }\n
+                    if (opts.max == null) {\n
+                        max += delta * margin;\n
+                        if (max > 0 && axis.datamax != null && axis.datamax <= 0)\n
+                            max = 0;\n
+                    }\n
+                }\n
+            }\n
+            axis.min = min;\n
+            axis.max = max;\n
+        }\n
+\n
+        function setupTickGeneration(axis) {\n
+            var opts = axis.options;\n
+\n
+            // estimate number of ticks\n
+            var noTicks;\n
+            if (typeof opts.ticks == "number" && opts.ticks > 0)\n
+                noTicks = opts.ticks;\n
+            else\n
+                // heuristic based on the model a*sqrt(x) fitted to\n
+                // some data points that seemed reasonable\n
+                noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? surface.width : surface.height);\n
+\n
+            var delta = (axis.max - axis.min) / noTicks,\n
+                dec = -Math.floor(Math.log(delta) / Math.LN10),\n
+                maxDec = opts.tickDecimals;\n
+\n
+            if (maxDec != null && dec > maxDec) {\n
+                dec = maxDec;\n
+            }\n
+\n
+            var magn = Math.pow(10, -dec),\n
+                norm = delta / magn, // norm is between 1.0 and 10.0\n
+                size;\n
+\n
+            if (norm < 1.5) {\n
+                size = 1;\n
+            } else if (norm < 3) {\n
+                size = 2;\n
+                // special case for 2.5, requires an extra decimal\n
+                if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) {\n
+                    size = 2.5;\n
+                    ++dec;\n
+                }\n
+            } else if (norm < 7.5) {\n
+                size = 5;\n
+            } else {\n
+                size = 10;\n
+            }\n
+\n
+            size *= magn;\n
+\n
+            if (opts.minTickSize != null && size < opts.minTickSize) {\n
+                size = opts.minTickSize;\n
+            }\n
+\n
+            axis.delta = delta;\n
+            axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec);\n
+            axis.tickSize = opts.tickSize || size;\n
+\n
+            // Time mode was moved to a plug-in in 0.8, and since so many people use it\n
+            // we\'ll add an especially friendly reminder to make sure they included it.\n
+\n
+            if (opts.mode == "time" && !axis.tickGenerator) {\n
+                throw new Error("Time mode requires the flot.time plugin.");\n
+            }\n
+\n
+            // Flot supports base-10 axes; any other mode else is handled by a plug-in,\n
+            // like flot.time.js.\n
+\n
+            if (!axis.tickGenerator) {\n
+\n
+                axis.tickGenerator = function (axis) {\n
+\n
+                    var ticks = [],\n
+                        start = floorInBase(axis.min, axis.tickSize),\n
+                        i = 0,\n
+                        v = Number.NaN,\n
+                        prev;\n
+\n
+                    do {\n
+                        prev = v;\n
+                        v = start + i * axis.tickSize;\n
+                        ticks.push(v);\n
+                        ++i;\n
+                    } while (v < axis.max && v != prev);\n
+                    return ticks;\n
+                };\n
+\n
+\t\t\t\taxis.tickFormatter = function (value, axis) {\n
+\n
+\t\t\t\t\tvar factor = axis.tickDecimals ? Math.pow(10, axis.tickDecimals) : 1;\n
+\t\t\t\t\tvar formatted = "" + Math.round(value * factor) / factor;\n
+\n
+\t\t\t\t\t// If tickDecimals was specified, ensure that we have exactly that\n
+\t\t\t\t\t// much precision; otherwise default to the value\'s own precision.\n
+\n
+\t\t\t\t\tif (axis.tickDecimals != null) {\n
+\t\t\t\t\t\tvar decimal = formatted.indexOf(".");\n
+\t\t\t\t\t\tvar precision = decimal == -1 ? 0 : formatted.length - decimal - 1;\n
+\t\t\t\t\t\tif (precision < axis.tickDecimals) {\n
+\t\t\t\t\t\t\treturn (precision ? formatted : formatted + ".") + ("" + factor).substr(1, axis.tickDecimals - precision);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\n
+                    return formatted;\n
+                };\n
+            }\n
+\n
+            if ($.isFunction(opts.tickFormatter))\n
+                axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); };\n
+\n
+            if (opts.alignTicksWithAxis != null) {\n
+                var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1];\n
+                if (otherAxis && otherAxis.used && otherAxis != axis) {\n
+                    // consider snapping min/max to outermost nice ticks\n
+                    var niceTicks = axis.tickGenerator(axis);\n
+                    if (niceTicks.length > 0) {\n
+                        if (opts.min == null)\n
+                            axis.min = Math.min(axis.min, niceTicks[0]);\n
+                        if (opts.max == null && niceTicks.length > 1)\n
+                            axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]);\n
+                    }\n
+\n
+                    axis.tickGenerator = function (axis) {\n
+                        // copy ticks, scaled to this axis\n
+                        var ticks = [], v, i;\n
+                        for (i = 0; i < otherAxis.ticks.length; ++i) {\n
+                            v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min);\n
+                            v = axis.min + v * (axis.max - axis.min);\n
+                            ticks.push(v);\n
+                        }\n
+                        return ticks;\n
+                    };\n
+\n
+                    // we might need an extra decimal since forced\n
+                    // ticks don\'t necessarily fit naturally\n
+                    if (!axis.mode && opts.tickDecimals == null) {\n
+                        var extraDec = Math.max(0, -Math.floor(Math.log(axis.delta) / Math.LN10) + 1),\n
+                            ts = axis.tickGenerator(axis);\n
+\n
+                        // only proceed if the tick interval rounded\n
+                        // with an extra decimal doesn\'t give us a\n
+                        // zero at end\n
+                        if (!(ts.length > 1 && /\\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec))))\n
+                            axis.tickDecimals = extraDec;\n
+                    }\n
+                }\n
+            }\n
+        }\n
+\n
+        function setTicks(axis) {\n
+            var oticks = axis.options.ticks, ticks = [];\n
+            if (oticks == null || (typeof oticks == "number" && oticks > 0))\n
+                ticks = axis.tickGenerator(axis);\n
+            else if (oticks) {\n
+                if ($.isFunction(oticks))\n
+                    // generate the ticks\n
+                    ticks = oticks(axis);\n
+                else\n
+                    ticks = oticks;\n
+            }\n
+\n
+            // clean up/labelify the supplied ticks, copy them over\n
+            var i, v;\n
+            axis.ticks = [];\n
+            for (i = 0; i < ticks.length; ++i) {\n
+                var label = null;\n
+                var t = ticks[i];\n
+                if (typeof t == "object") {\n
+                    v = +t[0];\n
+                    if (t.length > 1)\n
+                        label = t[1];\n
+                }\n
+                else\n
+                    v = +t;\n
+                if (label == null)\n
+                    label = axis.tickFormatter(v, axis);\n
+                if (!isNaN(v))\n
+                    axis.ticks.push({ v: v, label: label });\n
+            }\n
+        }\n
+\n
+        function snapRangeToTicks(axis, ticks) {\n
+            if (axis.options.autoscaleMargin && ticks.length > 0) {\n
+                // snap to ticks\n
+                if (axis.options.min == null)\n
+                    axis.min = Math.min(axis.min, ticks[0].v);\n
+                if (axis.options.max == null && ticks.length > 1)\n
+                    axis.max = Math.max(axis.max, ticks[ticks.length - 1].v);\n
+            }\n
+        }\n
+\n
+        function draw() {\n
+\n
+            surface.clear();\n
+\n
+            executeHooks(hooks.drawBackground, [ctx]);\n
+\n
+            var grid = options.grid;\n
+\n
+            // draw background, if any\n
+            if (grid.show && grid.backgroundColor)\n
+                drawBackground();\n
+\n
+            if (grid.show && !grid.aboveData) {\n
+                drawGrid();\n
+            }\n
+\n
+            for (var i = 0; i < series.length; ++i) {\n
+                executeHooks(hooks.drawSeries, [ctx, series[i]]);\n
+                drawSeries(series[i]);\n
+            }\n
+\n
+            executeHooks(hooks.draw, [ctx]);\n
+\n
+            if (grid.show && grid.aboveData) {\n
+                drawGrid();\n
+            }\n
+\n
+            surface.render();\n
+\n
+            // A draw implies that either the axes or data have changed, so we\n
+            // should probably update the overlay highlights as well.\n
+\n
+            triggerRedrawOverlay();\n
+        }\n
+\n
+        function extractRange(ranges, coord) {\n
+            var axis, from, to, key, axes = allAxes();\n
+\n
+            for (var i = 0; i < axes.length; ++i) {\n
+                axis = axes[i];\n
+                if (axis.direction == coord) {\n
+                    key = coord + axis.n + "axis";\n
+                    if (!ranges[key] && axis.n == 1)\n
+                        key = coord + "axis"; // support x1axis as xaxis\n
+                    if (ranges[key]) {\n
+                        from = ranges[key].from;\n
+                        to = ranges[key].to;\n
+                        break;\n
+                    }\n
+                }\n
+            }\n
+\n
+            // backwards-compat stuff - to be removed in future\n
+            if (!ranges[key]) {\n
+                axis = coord == "x" ? xaxes[0] : yaxes[0];\n
+                from = ranges[coord + "1"];\n
+                to = ranges[coord + "2"];\n
+            }\n
+\n
+            // auto-reverse as an added bonus\n
+            if (from != null && to != null && from > to) {\n
+                var tmp = from;\n
+                from = to;\n
+                to = tmp;\n
+            }\n
+\n
+            return { from: from, to: to, axis: axis };\n
+        }\n
+\n
+        function drawBackground() {\n
+            ctx.save();\n
+            ctx.translate(plotOffset.left, plotOffset.top);\n
+\n
+            ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)");\n
+            ctx.fillRect(0, 0, plotWidth, plotHeight);\n
+            ctx.restore();\n
+        }\n
+\n
+        function drawGrid() {\n
+            var i, axes, bw, bc;\n
+\n
+            ctx.save();\n
+            ctx.translate(plotOffset.left, plotOffset.top);\n
+\n
+            // draw markings\n
+            var markings = options.grid.markings;\n
+            if (markings) {\n
+                if ($.isFunction(markings)) {\n
+                    axes = plot.getAxes();\n
+                    // xmin etc. is backwards compatibility, to be\n
+                    // removed in the future\n
+                    axes.xmin = axes.xaxis.min;\n
+                    axes.xmax = axes.xaxis.max;\n
+                    axes.ymin = axes.yaxis.min;\n
+                    axes.ymax = axes.yaxis.max;\n
+\n
+                    markings = markings(axes);\n
+                }\n
+\n
+                for (i = 0; i < markings.length; ++i) {\n
+                    var m = markings[i],\n
+                        xrange = extractRange(m, "x"),\n
+                        yrange = extractRange(m, "y");\n
+\n
+                    // fill in missing\n
+                    if (xrange.from == null)\n
+                        xrange.from = xrange.axis.min;\n
+                    if (xrange.to == null)\n
+                        xrange.to = xrange.axis.max;\n
+                    if (yrange.from == null)\n
+                        yrange.from = yrange.axis.min;\n
+                    if (yrange.to == null)\n
+                        yrange.to = yrange.axis.max;\n
+\n
+                    // clip\n
+                    if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max ||\n
+                        yrange.to < yrange.axis.min || yrange.from > yrange.axis.max)\n
+                        continue;\n
+\n
+                    xrange.from = Math.max(xrange.from, xrange.axis.min);\n
+                    xrange.to = Math.min(xrange.to, xrange.axis.max);\n
+                    yrange.from = Math.max(yrange.from, yrange.axis.min);\n
+                    yrange.to = Math.min(yrange.to, yrange.axis.max);\n
+\n
+                    var xequal = xrange.from === xrange.to,\n
+                        yequal = yrange.from === yrange.to;\n
+\n
+                    if (xequal && yequal) {\n
+                        continue;\n
+                    }\n
+\n
+                    // then draw\n
+                    xrange.from = Math.floor(xrange.axis.p2c(xrange.from));\n
+                    xrange.to = Math.floor(xrange.axis.p2c(xrange.to));\n
+                    yrange.from = Math.floor(yrange.axis.p2c(yrange.from));\n
+                    yrange.to = Math.floor(yrange.axis.p2c(yrange.to));\n
+\n
+                    if (xequal || yequal) {\n
+                        var lineWidth = m.lineWidth || options.grid.markingsLineWidth,\n
+                            subPixel = lineWidth % 2 ? 0.5 : 0;\n
+                        ctx.beginPath();\n
+                        ctx.strokeStyle = m.color || options.grid.markingsColor;\n
+                        ctx.lineWidth = lineWidth;\n
+                        if (xequal) {\n
+                            ctx.moveTo(xrange.to + subPixel, yrange.from);\n
+                            ctx.lineTo(xrange.to + subPixel, yrange.to);\n
+                        } else {\n
+                            ctx.moveTo(xrange.from, yrange.to + subPixel);\n
+                            ctx.lineTo(xrange.to, yrange.to + subPixel);                            \n
+                        }\n
+                        ctx.stroke();\n
+                    } else {\n
+                        ctx.fillStyle = m.color || options.grid.markingsColor;\n
+                        ctx.fillRect(xrange.from, yrange.to,\n
+                                     xrange.to - xrange.from,\n
+                                     yrange.from - yrange.to);\n
+                    }\n
+                }\n
+            }\n
+\n
+            // draw the ticks\n
+            axes = allAxes();\n
+            bw = options.grid.borderWidth;\n
+\n
+            for (var j = 0; j < axes.length; ++j) {\n
+                var axis = axes[j], box = axis.box,\n
+                    t = axis.tickLength, x, y, xoff, yoff;\n
+                if (!axis.show || axis.ticks.length == 0)\n
+                    continue;\n
+\n
+                ctx.lineWidth = 1;\n
+\n
+                // find the edges\n
+                if (axis.direction == "x") {\n
+                    x = 0;\n
+                    if (t == "full")\n
+                        y = (axis.position == "top" ? 0 : plotHeight);\n
+                    else\n
+                        y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0);\n
+                }\n
+                else {\n
+                    y = 0;\n
+                    if (t == "full")\n
+                        x = (axis.position == "left" ? 0 : plotWidth);\n
+                    else\n
+                        x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0);\n
+                }\n
+\n
+                // draw tick bar\n
+                if (!axis.innermost) {\n
+                    ctx.strokeStyle = axis.options.color;\n
+                    ctx.beginPath();\n
+                    xoff = yoff = 0;\n
+                    if (axis.direction == "x")\n
+                        xoff = plotWidth + 1;\n
+                    else\n
+                        yoff = plotHeight + 1;\n
+\n
+                    if (ctx.lineWidth == 1) {\n
+                        if (axis.direction == "x") {\n
+                            y = Math.floor(y) + 0.5;\n
+                        } else {\n
+                            x = Math.floor(x) + 0.5;\n
+                        }\n
+                    }\n
+\n
+                    ctx.moveTo(x, y);\n
+                    ctx.lineTo(x + xoff, y + yoff);\n
+                    ctx.stroke();\n
+                }\n
+\n
+                // draw ticks\n
+\n
+                ctx.strokeStyle = axis.options.tickColor;\n
+\n
+                ctx.beginPath();\n
+                for (i = 0; i < axis.ticks.length; ++i) {\n
+                    var v = axis.ticks[i].v;\n
+\n
+                    xoff = yoff = 0;\n
+\n
+                    if (isNaN(v) || v < axis.min || v > axis.max\n
+                        // skip those lying on the axes if we got a border\n
+                        || (t == "full"\n
+                            && ((typeof bw == "object" && bw[axis.position] > 0) || bw > 0)\n
+                            && (v == axis.min || v == axis.max)))\n
+                        continue;\n
+\n
+                    if (axis.direction == "x") {\n
+                        x = axis.p2c(v);\n
+                        yoff = t == "full" ? -plotHeight : t;\n
+\n
+                        if (axis.position == "top")\n
+                            yoff = -yoff;\n
+                    }\n
+                    else {\n
+                        y = axis.p2c(v);\n
+                        xoff = t == "full" ? -plotWidth : t;\n
+\n
+                        if (axis.position == "left")\n
+                            xoff = -xoff;\n
+                    }\n
+\n
+                    if (ctx.lineWidth == 1) {\n
+                        if (axis.direction == "x")\n
+                            x = Math.floor(x) + 0.5;\n
+                        else\n
+                            y = Math.floor(y) + 0.5;\n
+                    }\n
+\n
+                    ctx.moveTo(x, y);\n
+                    ctx.lineTo(x + xoff, y + yoff);\n
+                }\n
+\n
+                ctx.stroke();\n
+            }\n
+\n
+\n
+            // draw border\n
+            if (bw) {\n
+                // If either borderWidth or borderColor is an object, then draw the border\n
+                // line by line instead of as one rectangle\n
+                bc = options.grid.borderColor;\n
+                if(typeof bw == "object" || typeof bc == "object") {\n
+                    if (typeof bw !== "object") {\n
+                        bw = {top: bw, right: bw, bottom: bw, left: bw};\n
+                    }\n
+                    if (typeof bc !== "object") {\n
+                        bc = {top: bc, right: bc, bottom: bc, left: bc};\n
+                    }\n
+\n
+                    if (bw.top > 0) {\n
+                        ctx.strokeStyle = bc.top;\n
+                        ctx.lineWidth = bw.top;\n
+                        ctx.beginPath();\n
+                        ctx.moveTo(0 - bw.left, 0 - bw.top/2);\n
+                        ctx.lineTo(plotWidth, 0 - bw.top/2);\n
+                        ctx.stroke();\n
+                    }\n
+\n
+                    if (bw.right > 0) {\n
+                        ctx.strokeStyle = bc.right;\n
+                        ctx.lineWidth = bw.right;\n
+                        ctx.beginPath();\n
+                        ctx.moveTo(plotWidth + bw.right / 2, 0 - bw.top);\n
+                        ctx.lineTo(plotWidth + bw.right / 2, plotHeight);\n
+                        ctx.stroke();\n
+                    }\n
+\n
+                    if (bw.bottom > 0) {\n
+                        ctx.strokeStyle = bc.bottom;\n
+                        ctx.lineWidth = bw.bottom;\n
+                        ctx.beginPath();\n
+                        ctx.moveTo(plotWidth + bw.right, plotHeight + bw.bottom / 2);\n
+                        ctx.lineTo(0, plotHeight + bw.bottom / 2);\n
+                        ctx.stroke();\n
+                    }\n
+\n
+                    if (bw.left > 0) {\n
+                        ctx.strokeStyle = bc.left;\n
+                        ctx.lineWidth = bw.left;\n
+                        ctx.beginPath();\n
+                        ctx.moveTo(0 - bw.left/2, plotHeight + bw.bottom);\n
+                        ctx.lineTo(0- bw.left/2, 0);\n
+                        ctx.stroke();\n
+                    }\n
+                }\n
+                else {\n
+                    ctx.lineWidth = bw;\n
+                    ctx.strokeStyle = options.grid.borderColor;\n
+                    ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw);\n
+                }\n
+            }\n
+\n
+            ctx.restore();\n
+        }\n
+\n
+        function drawAxisLabels() {\n
+\n
+            $.each(allAxes(), function (_, axis) {\n
+                var box = axis.box,\n
+                    legacyStyles = axis.direction + "Axis " + axis.direction + axis.n + "Axis",\n
+                    layer = "flot-" + axis.direction + "-axis flot-" + axis.direction + axis.n + "-axis " + legacyStyles,\n
+                    font = axis.options.font || "flot-tick-label tickLabel",\n
+                    tick, x, y, halign, valign;\n
+\n
+                // Remove text before checking for axis.show and ticks.length;\n
+                // otherwise plugins, like flot-tickrotor, that draw their own\n
+                // tick labels will end up with both theirs and the defaults.\n
+\n
+                surface.removeText(layer);\n
+\n
+                if (!axis.show || axis.ticks.length == 0)\n
+                    return;\n
+\n
+                for (var i = 0; i < axis.ticks.length; ++i) {\n
+\n
+                    tick = axis.ticks[i];\n
+                    if (!tick.label || tick.v < axis.min || tick.v > axis.max)\n
+                        continue;\n
+\n
+                    if (axis.direction == "x") {\n
+                        halign = "center";\n
+                        x = plotOffset.left + axis.p2c(tick.v);\n
+                        if (axis.position == "bottom") {\n
+                            y = box.top + box.padding;\n
+                        } else {\n
+                            y = box.top + box.height - box.padding;\n
+                            valign = "bottom";\n
+                        }\n
+                    } else {\n
+                        valign = "middle";\n
+                        y = plotOffset.top + axis.p2c(tick.v);\n
+                        if (axis.position == "left") {\n
+                            x = box.left + box.width - box.padding;\n
+                            halign = "right";\n
+                        } else {\n
+                            x = box.left + box.padding;\n
+                        }\n
+                    }\n
+\n
+                    surface.addText(layer, x, y, tick.label, font, null, null, halign, valign);\n
+                }\n
+            });\n
+        }\n
+\n
+        function drawSeries(series) {\n
+            if (series.lines.show)\n
+                drawSeriesLines(series);\n
+            if (series.bars.show)\n
+                drawSeriesBars(series);\n
+            if (series.points.show)\n
+                drawSeriesPoints(series);\n
+        }\n
+\n
+        function drawSeriesLines(series) {\n
+            function plotLine(datapoints, xoffset, yoffset, axisx, axisy) {\n
+                var points = datapoints.points,\n
+                    ps = datapoints.pointsize,\n
+                    prevx = null, prevy = null;\n
+\n
+                ctx.beginPath();\n
+                for (var i = ps; i < points.length; i += ps) {\n
+                    var x1 = points[i - ps], y1 = points[i - ps + 1],\n
+                        x2 = points[i], y2 = points[i + 1];\n
+\n
+                    if (x1 == null || x2 == null)\n
+                        continue;\n
+\n
+                    // clip with ymin\n
+                    if (y1 <= y2 && y1 < axisy.min) {\n
+                        if (y2 < axisy.min)\n
+                            continue;   // line segment is outside\n
+                        // compute new intersection point\n
+                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;\n
+                        y1 = axisy.min;\n
+                    }\n
+                    else if (y2 <= y1 && y2 < axisy.min) {\n
+                        if (y1 < axisy.min)\n
+                            continue;\n
+                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;\n
+                        y2 = axisy.min;\n
+                    }\n
+\n
+                    // clip with ymax\n
+                    if (y1 >= y2 && y1 > axisy.max) {\n
+                        if (y2 > axisy.max)\n
+                            continue;\n
+                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;\n
+                        y1 = axisy.max;\n
+                    }\n
+                    else if (y2 >= y1 && y2 > axisy.max) {\n
+                        if (y1 > axisy.max)\n
+                            continue;\n
+                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;\n
+                        y2 = axisy.max;\n
+                    }\n
+\n
+                    // clip with xmin\n
+                    if (x1 <= x2 && x1 < axisx.min) {\n
+                        if (x2 < axisx.min)\n
+                            continue;\n
+                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;\n
+                        x1 = axisx.min;\n
+                    }\n
+                    else if (x2 <= x1 && x2 < axisx.min) {\n
+                        if (x1 < axisx.min)\n
+                            continue;\n
+                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;\n
+                        x2 = axisx.min;\n
+                    }\n
+\n
+                    // clip with xmax\n
+                    if (x1 >= x2 && x1 > axisx.max) {\n
+                        if (x2 > axisx.max)\n
+                            continue;\n
+                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;\n
+                        x1 = axisx.max;\n
+                    }\n
+                    else if (x2 >= x1 && x2 > axisx.max) {\n
+                        if (x1 > axisx.max)\n
+                            continue;\n
+                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;\n
+                        x2 = axisx.max;\n
+                    }\n
+\n
+                    if (x1 != prevx || y1 != prevy)\n
+                        ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset);\n
+\n
+                    prevx = x2;\n
+                    prevy = y2;\n
+                    ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset);\n
+                }\n
+                ctx.stroke();\n
+            }\n
+\n
+            function plotLineArea(datapoints, axisx, axisy) {\n
+                var points = datapoints.points,\n
+                    ps = datapoints.pointsize,\n
+                    bottom = Math.min(Math.max(0, axisy.min), axisy.max),\n
+                    i = 0, top, areaOpen = false,\n
+                    ypos = 1, segmentStart = 0, segmentEnd = 0;\n
+\n
+                // we process each segment in two turns, first forward\n
+                // direction to sketch out top, then once we hit the\n
+                // end we go backwards to sketch the bottom\n
+                while (true) {\n
+                    if (ps > 0 && i > points.length + ps)\n
+                        break;\n
+\n
+                    i += ps; // ps is negative if going backwards\n
+\n
+                    var x1 = points[i - ps],\n
+                        y1 = points[i - ps + ypos],\n
+                        x2 = points[i], y2 = points[i + ypos];\n
+\n
+                    if (areaOpen) {\n
+                        if (ps > 0 && x1 != null && x2 == null) {\n
+                            // at turning point\n
+                            segmentEnd = i;\n
+                            ps = -ps;\n
+                            ypos = 2;\n
+                            continue;\n
+                        }\n
+\n
+                        if (ps < 0 && i == segmentStart + ps) {\n
+                            // done with the reverse sweep\n
+                            ctx.fill();\n
+                            areaOpen = false;\n
+                            ps = -ps;\n
+                            ypos = 1;\n
+                            i = segmentStart = segmentEnd + ps;\n
+                            continue;\n
+                        }\n
+                    }\n
+\n
+                    if (x1 == null || x2 == null)\n
+                        continue;\n
+\n
+                    // clip x values\n
+\n
+                    // clip with xmin\n
+                    if (x1 <= x2 && x1 < axisx.min) {\n
+                        if (x2 < axisx.min)\n
+                            continue;\n
+                        y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;\n
+                        x1 = axisx.min;\n
+                    }\n
+                    else if (x2 <= x1 && x2 < axisx.min) {\n
+                        if (x1 < axisx.min)\n
+                            continue;\n
+                        y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1;\n
+                        x2 = axisx.min;\n
+                    }\n
+\n
+                    // clip with xmax\n
+                    if (x1 >= x2 && x1 > axisx.max) {\n
+                        if (x2 > axisx.max)\n
+                            continue;\n
+                        y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;\n
+                        x1 = axisx.max;\n
+                    }\n
+                    else if (x2 >= x1 && x2 > axisx.max) {\n
+                        if (x1 > axisx.max)\n
+                            continue;\n
+                        y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1;\n
+                        x2 = axisx.max;\n
+                    }\n
+\n
+                    if (!areaOpen) {\n
+                        // open area\n
+                        ctx.beginPath();\n
+                        ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom));\n
+                        areaOpen = true;\n
+                    }\n
+\n
+                    // now first check the case where both is outside\n
+                    if (y1 >= axisy.max && y2 >= axisy.max) {\n
+                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max));\n
+                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max));\n
+                        continue;\n
+                    }\n
+                    else if (y1 <= axisy.min && y2 <= axisy.min) {\n
+                        ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min));\n
+                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min));\n
+                        continue;\n
+                    }\n
+\n
+                    // else it\'s a bit more complicated, there might\n
+                    // be a flat maxed out rectangle first, then a\n
+                    // triangular cutout or reverse; to find these\n
+                    // keep track of the current x values\n
+                    var x1old = x1, x2old = x2;\n
+\n
+                    // clip the y values, without shortcutting, we\n
+                    // go through all cases in turn\n
+\n
+                    // clip with ymin\n
+                    if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) {\n
+                        x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;\n
+                        y1 = axisy.min;\n
+                    }\n
+                    else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) {\n
+                        x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1;\n
+                        y2 = axisy.min;\n
+                    }\n
+\n
+                    // clip with ymax\n
+                    if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) {\n
+                        x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;\n
+                        y1 = axisy.max;\n
+                    }\n
+                    else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) {\n
+                        x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1;\n
+                        y2 = axisy.max;\n
+                    }\n
+\n
+                    // if the x value was changed we got a rectangle\n
+                    // to fill\n
+                    if (x1 != x1old) {\n
+                        ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1));\n
+                        // it goes to (x1, y1), but we fill that below\n
+                    }\n
+\n
+                    // fill triangular section, this sometimes result\n
+                    // in redundant points if (x1, y1) hasn\'t changed\n
+                    // from previous line to, but we just ignore that\n
+                    ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1));\n
+                    ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));\n
+\n
+                    // fill the other rectangle if it\'s there\n
+                    if (x2 != x2old) {\n
+                        ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2));\n
+                        ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2));\n
+                    }\n
+                }\n
+            }\n
+\n
+            ctx.save();\n
+            ctx.translate(plotOffset.left, plotOffset.top);\n
+            ctx.lineJoin = "round";\n
+\n
+            var lw = series.lines.lineWidth,\n
+                sw = series.shadowSize;\n
+            // FIXME: consider another form of shadow when filling is turned on\n
+            if (lw > 0 && sw > 0) {\n
+                // draw shadow as a thick and thin line with transparency\n
+                ctx.lineWidth = sw;\n
+                ctx.strokeStyle = "rgba(0,0,0,0.1)";\n
+                // position shadow at angle from the mid of line\n
+                var angle = Math.PI/18;\n
+                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis);\n
+                ctx.lineWidth = sw/2;\n
+                plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis);\n
+            }\n
+\n
+            ctx.lineWidth = lw;\n
+            ctx.strokeStyle = series.color;\n
+            var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight);\n
+            if (fillStyle) {\n
+                ctx.fillStyle = fillStyle;\n
+                plotLineArea(series.datapoints, series.xaxis, series.yaxis);\n
+            }\n
+\n
+            if (lw > 0)\n
+                plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis);\n
+            ctx.restore();\n
+        }\n
+\n
+        function drawSeriesPoints(series) {\n
+            function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) {\n
+                var points = datapoints.points, ps = datapoints.pointsize;\n
+\n
+                for (var i = 0; i < points.length; i += ps) {\n
+                    var x = points[i], y = points[i + 1];\n
+                    if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)\n
+                        continue;\n
+\n
+                    ctx.beginPath();\n
+                    x = axisx.p2c(x);\n
+                    y = axisy.p2c(y) + offset;\n
+                    if (symbol == "circle")\n
+                        ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false);\n
+                    else\n
+                        symbol(ctx, x, y, radius, shadow);\n
+                    ctx.closePath();\n
+\n
+                    if (fillStyle) {\n
+                        ctx.fillStyle = fillStyle;\n
+                        ctx.fill();\n
+                    }\n
+                    ctx.stroke();\n
+                }\n
+            }\n
+\n
+            ctx.save();\n
+            ctx.translate(plotOffset.left, plotOffset.top);\n
+\n
+            var lw = series.points.lineWidth,\n
+                sw = series.shadowSize,\n
+                radius = series.points.radius,\n
+                symbol = series.points.symbol;\n
+\n
+            // If the user sets the line width to 0, we change it to a very \n
+            // small value. A line width of 0 seems to force the default of 1.\n
+            // Doing the conditional here allows the shadow setting to still be \n
+            // optional even with a lineWidth of 0.\n
+\n
+            if( lw == 0 )\n
+                lw = 0.0001;\n
+\n
+            if (lw > 0 && sw > 0) {\n
+                // draw shadow in two steps\n
+                var w = sw / 2;\n
+                ctx.lineWidth = w;\n
+                ctx.strokeStyle = "rgba(0,0,0,0.1)";\n
+                plotPoints(series.datapoints, radius, null, w + w/2, true,\n
+                           series.xaxis, series.yaxis, symbol);\n
+\n
+                ctx.strokeStyle = "rgba(0,0,0,0.2)";\n
+                plotPoints(series.datapoints, radius, null, w/2, true,\n
+                           series.xaxis, series.yaxis, symbol);\n
+            }\n
+\n
+            ctx.lineWidth = lw;\n
+            ctx.strokeStyle = series.color;\n
+            plotPoints(series.datapoints, radius,\n
+                       getFillStyle(series.points, series.color), 0, false,\n
+                       series.xaxis, series.yaxis, symbol);\n
+            ctx.restore();\n
+        }\n
+\n
+        function drawBar(x, y, b, barLeft, barRight, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) {\n
+            var left, right, bottom, top,\n
+                drawLeft, drawRight, drawTop, drawBottom,\n
+                tmp;\n
+\n
+            // in horizontal mode, we start the bar from the left\n
+            // instead of from the bottom so it appears to be\n
+            // horizontal rather than vertical\n
+            if (horizontal) {\n
+                drawBottom = drawRight = drawTop = true;\n
+                drawLeft = false;\n
+                left = b;\n
+                right = x;\n
+                top = y + barLeft;\n
+                bottom = y + barRight;\n
+\n
+                // account for negative bars\n
+                if (right < left) {\n
+                    tmp = right;\n
+                    right = left;\n
+                    left = tmp;\n
+                    drawLeft = true;\n
+                    drawRight = false;\n
+                }\n
+            }\n
+            else {\n
+                drawLeft = drawRight = drawTop = true;\n
+                drawBottom = false;\n
+                left = x + barLeft;\n
+                right = x + barRight;\n
+                bottom = b;\n
+                top = y;\n
+\n
+                // account for negative bars\n
+                if (top < bottom) {\n
+                    tmp = top;\n
+                    top = bottom;\n
+                    bottom = tmp;\n
+                    drawBottom = true;\n
+                    drawTop = false;\n
+                }\n
+            }\n
+\n
+            // clip\n
+            if (right < axisx.min || left > axisx.max ||\n
+                top < axisy.min || bottom > axisy.max)\n
+                return;\n
+\n
+            if (left < axisx.min) {\n
+                left = axisx.min;\n
+                drawLeft = false;\n
+            }\n
+\n
+            if (right > axisx.max) {\n
+                right = axisx.max;\n
+                drawRight = false;\n
+            }\n
+\n
+            if (bottom < axisy.min) {\n
+                bottom = axisy.min;\n
+                drawBottom = false;\n
+            }\n
+\n
+            if (top > axisy.max) {\n
+                top = axisy.max;\n
+                drawTop = false;\n
+            }\n
+\n
+            left = axisx.p2c(left);\n
+            bottom = axisy.p2c(bottom);\n
+            right = axisx.p2c(right);\n
+            top = axisy.p2c(top);\n
+\n
+            // fill the bar\n
+            if (fillStyleCallback) {\n
+                c.fillStyle = fillStyleCallback(bottom, top);\n
+                c.fillRect(left, top, right - left, bottom - top)\n
+            }\n
+\n
+            // draw outline\n
+            if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) {\n
+                c.beginPath();\n
+\n
+                // FIXME: inline moveTo is buggy with excanvas\n
+                c.moveTo(left, bottom);\n
+                if (drawLeft)\n
+                    c.lineTo(left, top);\n
+                else\n
+                    c.moveTo(left, top);\n
+                if (drawTop)\n
+                    c.lineTo(right, top);\n
+                else\n
+                    c.moveTo(right, top);\n
+                if (drawRight)\n
+                    c.lineTo(right, bottom);\n
+                else\n
+                    c.moveTo(right, bottom);\n
+                if (drawBottom)\n
+                    c.lineTo(left, bottom);\n
+                else\n
+                    c.moveTo(left, bottom);\n
+                c.stroke();\n
+            }\n
+        }\n
+\n
+        function drawSeriesBars(series) {\n
+            function plotBars(datapoints, barLeft, barRight, fillStyleCallback, axisx, axisy) {\n
+                var points = datapoints.points, ps = datapoints.pointsize;\n
+\n
+                for (var i = 0; i < points.length; i += ps) {\n
+                    if (points[i] == null)\n
+                        continue;\n
+                    drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth);\n
+                }\n
+            }\n
+\n
+            ctx.save();\n
+            ctx.translate(plotOffset.left, plotOffset.top);\n
+\n
+            // FIXME: figure out a way to add shadows (for instance along the right edge)\n
+            ctx.lineWidth = series.bars.lineWidth;\n
+            ctx.strokeStyle = series.color;\n
+\n
+            var barLeft;\n
+\n
+            switch (series.bars.align) {\n
+                case "left":\n
+                    barLeft = 0;\n
+                    break;\n
+                case "right":\n
+                    barLeft = -series.bars.barWidth;\n
+                    break;\n
+                default:\n
+                    barLeft = -series.bars.barWidth / 2;\n
+            }\n
+\n
+            var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null;\n
+            plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, fillStyleCallback, series.xaxis, series.yaxis);\n
+            ctx.restore();\n
+        }\n
+\n
+        function getFillStyle(filloptions, seriesColor, bottom, top) {\n
+            var fill = filloptions.fill;\n
+            if (!fill)\n
+                return null;\n
+\n
+            if (filloptions.fillColor)\n
+                return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor);\n
+\n
+            var c = $.color.parse(seriesColor);\n
+            c.a = typeof fill == "number" ? fill : 0.4;\n
+            c.normalize();\n
+            return c.toString();\n
+        }\n
+\n
+        function insertLegend() {\n
+\n
+            if (options.legend.container != null) {\n
+                $(options.legend.container).html("");\n
+            } else {\n
+                placeholder.find(".legend").remove();\n
+            }\n
+\n
+            if (!options.legend.show) {\n
+                return;\n
+            }\n
+\n
+            var fragments = [], entries = [], rowStarted = false,\n
+                lf = options.legend.labelFormatter, s, label;\n
+\n
+            // Build a list of legend entries, with each having a label and a color\n
+\n
+            for (var i = 0; i < series.length; ++i) {\n
+                s = series[i];\n
+                if (s.label) {\n
+                    label = lf ? lf(s.label, s) : s.label;\n
+                    if (label) {\n
+                        entries.push({\n
+                            label: label,\n
+                            color: s.color\n
+                        });\n
+                    }\n
+                }\n
+            }\n
+\n
+            // Sort the legend using either the default or a custom comparator\n
+\n
+            if (options.legend.sorted) {\n
+                if ($.isFunction(options.legend.sorted)) {\n
+                    entries.sort(options.legend.sorted);\n
+                } else if (options.legend.sorted == "reverse") {\n
+                \tentries.reverse();\n
+                } else {\n
+                    var ascending = options.legend.sorted != "descending";\n
+                    entries.sort(function(a, b) {\n
+                        return a.label == b.label ? 0 : (\n
+                            (a.label < b.label) != ascending ? 1 : -1   // Logical XOR\n
+                        );\n
+                    });\n
+                }\n
+            }\n
+\n
+            // Generate markup for the list of entries, in their final order\n
+\n
+            for (var i = 0; i < entries.length; ++i) {\n
+\n
+                var entry = entries[i];\n
+\n
+                if (i % options.legend.noColumns == 0) {\n
+                    if (rowStarted)\n
+                        fragments.push(\'</tr>\');\n
+                    fragments.push(\'<tr>\');\n
+                    rowStarted = true;\n
+                }\n
+\n
+                fragments.push(\n
+                    \'<td class="legendColorBox"><div style="border:1px solid \' + options.legend.labelBoxBorderColor + \';padding:1px"><div style="width:4px;height:0;border:5px solid \' + entry.color + \';overflow:hidden"></div></div></td>\' +\n
+                    \'<td class="legendLabel">\' + entry.label + \'</td>\'\n
+                );\n
+            }\n
+\n
+            if (rowStarted)\n
+                fragments.push(\'</tr>\');\n
+\n
+            if (fragments.length == 0)\n
+                return;\n
+\n
+            var table = \'<table style="font-size:smaller;color:\' + options.grid.color + \'">\' + fragments.join("") + \'</table>\';\n
+            if (options.legend.container != null)\n
+                $(options.legend.container).html(table);\n
+            else {\n
+                var pos = "",\n
+                    p = options.legend.position,\n
+                    m = options.legend.margin;\n
+                if (m[0] == null)\n
+                    m = [m, m];\n
+                if (p.charAt(0) == "n")\n
+                    pos += \'top:\' + (m[1] + plotOffset.top) + \'px;\';\n
+                else if (p.charAt(0) == "s")\n
+                    pos += \'bottom:\' + (m[1] + plotOffset.bottom) + \'px;\';\n
+                if (p.charAt(1) == "e")\n
+                    pos += \'right:\' + (m[0] + plotOffset.right) + \'px;\';\n
+                else if (p.charAt(1) == "w")\n
+                    pos += \'left:\' + (m[0] + plotOffset.left) + \'px;\';\n
+                var legend = $(\'<div class="legend">\' + table.replace(\'style="\', \'style="position:absolute;\' + pos +\';\') + \'</div>\').appendTo(placeholder);\n
+                if (options.legend.backgroundOpacity != 0.0) {\n
+                    // put in the transparent background\n
+                    // separately to avoid blended labels and\n
+                    // label boxes\n
+                    var c = options.legend.backgroundColor;\n
+                    if (c == null) {\n
+                        c = options.grid.backgroundColor;\n
+                        if (c && typeof c == "string")\n
+                            c = $.color.parse(c);\n
+                        else\n
+                            c = $.color.extract(legend, \'background-color\');\n
+                        c.a = 1;\n
+                        c = c.toString();\n
+                    }\n
+                    var div = legend.children();\n
+                    $(\'<div style="position:absolute;width:\' + div.width() + \'px;height:\' + div.height() + \'px;\' + pos +\'background-color:\' + c + \';"> </div>\').prependTo(legend).css(\'opacity\', options.legend.backgroundOpacity);\n
+                }\n
+            }\n
+        }\n
+\n
+\n
+        // interactive features\n
+\n
+        var highlights = [],\n
+            redrawTimeout = null;\n
+\n
+        // returns the data item the mouse is over, or null if none is found\n
+        function findNearbyItem(mouseX, mouseY, seriesFilter) {\n
+            var maxDistance = options.grid.mouseActiveRadius,\n
+                smallestDistance = maxDistance * maxDistance + 1,\n
+                item = null, foundPoint = false, i, j, ps;\n
+\n
+            for (i = series.length - 1; i >= 0; --i) {\n
+                if (!seriesFilter(series[i]))\n
+                    continue;\n
+\n
+                var s = series[i],\n
+                    axisx = s.xaxis,\n
+                    axisy = s.yaxis,\n
+                    points = s.datapoints.points,\n
+                    mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster\n
+                    my = axisy.c2p(mouseY),\n
+                    maxx = maxDistance / axisx.scale,\n
+                    maxy = maxDistance / axisy.scale;\n
+\n
+                ps = s.datapoints.pointsize;\n
+                // with inverse transforms, we can\'t use the maxx/maxy\n
+                // optimization, sadly\n
+                if (axisx.options.inverseTransform)\n
+                    maxx = Number.MAX_VALUE;\n
+                if (axisy.options.inverseTransform)\n
+                    maxy = Number.MAX_VALUE;\n
+\n
+                if (s.lines.show || s.points.show) {\n
+                    for (j = 0; j < points.length; j += ps) {\n
+                        var x = points[j], y = points[j + 1];\n
+                        if (x == null)\n
+                            continue;\n
+\n
+                        // For points and lines, the cursor must be within a\n
+                        // certain distance to the data point\n
+                        if (x - mx > maxx || x - mx < -maxx ||\n
+                            y - my > maxy || y - my < -maxy)\n
+                            continue;\n
+\n
+                        // We have to calculate distances in pixels, not in\n
+                        // data units, because the scales of the axes may be different\n
+                        var dx = Math.abs(axisx.p2c(x) - mouseX),\n
+                            dy = Math.abs(axisy.p2c(y) - mouseY),\n
+                            dist = dx * dx + dy * dy; // we save the sqrt\n
+\n
+                        // use <= to ensure last point takes precedence\n
+                        // (last generally means on top of)\n
+                        if (dist < smallestDistance) {\n
+                            smallestDistance = dist;\n
+                            item = [i, j / ps];\n
+                        }\n
+                    }\n
+                }\n
+\n
+                if (s.bars.show && !item) { // no other point can be nearby\n
+\n
+                    var barLeft, barRight;\n
+\n
+                    switch (s.bars.align) {\n
+                        case "left":\n
+                            barLeft = 0;\n
+                            break;\n
+                        case "right":\n
+                            barLeft = -s.bars.barWidth;\n
+                            break;\n
+                        default:\n
+                            barLeft = -s.bars.barWidth / 2;\n
+                    }\n
+\n
+                    barRight = barLeft + s.bars.barWidth;\n
+\n
+                    for (j = 0; j < points.length; j += ps) {\n
+                        var x = points[j], y = points[j + 1], b = points[j + 2];\n
+                        if (x == null)\n
+                            continue;\n
+\n
+                        // for a bar graph, the cursor must be inside the bar\n
+                        if (series[i].bars.horizontal ?\n
+                            (mx <= Math.max(b, x) && mx >= Math.min(b, x) &&\n
+                             my >= y + barLeft && my <= y + barRight) :\n
+                            (mx >= x + barLeft && mx <= x + barRight &&\n
+                             my >= Math.min(b, y) && my <= Math.max(b, y)))\n
+                                item = [i, j / ps];\n
+                    }\n
+                }\n
+            }\n
+\n
+            if (item) {\n
+                i = item[0];\n
+                j = item[1];\n
+                ps = series[i].datapoints.pointsize;\n
+\n
+                return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps),\n
+                         dataIndex: j,\n
+                         series: series[i],\n
+                         seriesIndex: i };\n
+            }\n
+\n
+            return null;\n
+        }\n
+\n
+        function onMouseMove(e) {\n
+            if (options.grid.hoverable)\n
+                triggerClickHoverEvent("plothover", e,\n
+                                       function (s) { return s["hoverable"] != false; });\n
+        }\n
+\n
+        function onMouseLeave(e) {\n
+            if (options.grid.hoverable)\n
+                triggerClickHoverEvent("plothover", e,\n
+                                       function (s) { return false; });\n
+        }\n
+\n
+        function onClick(e) {\n
+            triggerClickHoverEvent("plotclick", e,\n
+                                   function (s) { return s["clickable"] != false; });\n
+        }\n
+\n
+        // trigger click or hover event (they send the same parameters\n
+        // so we share their code)\n
+        function triggerClickHoverEvent(eventname, event, seriesFilter) {\n
+            var offset = eventHolder.offset(),\n
+                canvasX = event.pageX - offset.left - plotOffset.left,\n
+                canvasY = event.pageY - offset.top - plotOffset.top,\n
+            pos = canvasToAxisCoords({ left: canvasX, top: canvasY });\n
+\n
+            pos.pageX = event.pageX;\n
+            pos.pageY = event.pageY;\n
+\n
+            var item = findNearbyItem(canvasX, canvasY, seriesFilter);\n
+\n
+            if (item) {\n
+                // fill in mouse pos for any listeners out there\n
+                item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left, 10);\n
+                item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top, 10);\n
+            }\n
+\n
+            if (options.grid.autoHighlight) {\n
+                // clear auto-highlights\n
+                for (var i = 0; i < highlights.length; ++i) {\n
+                    var h = highlights[i];\n
+                    if (h.auto == eventname &&\n
+                        !(item && h.series == item.series &&\n
+                          h.point[0] == item.datapoint[0] &&\n
+                          h.point[1] == item.datapoint[1]))\n
+                        unhighlight(h.series, h.point);\n
+                }\n
+\n
+                if (item)\n
+                    highlight(item.series, item.datapoint, eventname);\n
+            }\n
+\n
+            placeholder.trigger(eventname, [ pos, item ]);\n
+        }\n
+\n
+        function triggerRedrawOverlay() {\n
+            var t = options.interaction.redrawOverlayInterval;\n
+            if (t == -1) {      // skip event queue\n
+                drawOverlay();\n
+                return;\n
+            }\n
+\n
+            if (!redrawTimeout)\n
+                redrawTimeout = setTimeout(drawOverlay, t);\n
+        }\n
+\n
+        function drawOverlay() {\n
+            redrawTimeout = null;\n
+\n
+            // draw highlights\n
+            octx.save();\n
+            overlay.clear();\n
+            octx.translate(plotOffset.left, plotOffset.top);\n
+\n
+            var i, hi;\n
+            for (i = 0; i < highlights.length; ++i) {\n
+                hi = highlights[i];\n
+\n
+                if (hi.series.bars.show)\n
+                    drawBarHighlight(hi.series, hi.point);\n
+                else\n
+                    drawPointHighlight(hi.series, hi.point);\n
+            }\n
+            octx.restore();\n
+\n
+            executeHooks(hooks.drawOverlay, [octx]);\n
+        }\n
+\n
+        function highlight(s, point, auto) {\n
+            if (typeof s == "number")\n
+                s = series[s];\n
+\n
+            if (typeof point == "number") {\n
+                var ps = s.datapoints.pointsize;\n
+                point = s.datapoints.points.slice(ps * point, ps * (point + 1));\n
+            }\n
+\n
+            var i = indexOfHighlight(s, point);\n
+            if (i == -1) {\n
+                highlights.push({ series: s, point: point, auto: auto });\n
+\n
+                triggerRedrawOverlay();\n
+            }\n
+            else if (!auto)\n
+                highlights[i].auto = false;\n
+        }\n
+\n
+        function unhighlight(s, point) {\n
+            if (s == null && point == null) {\n
+                highlights = [];\n
+                triggerRedrawOverlay();\n
+                return;\n
+            }\n
+\n
+            if (typeof s == "number")\n
+                s = series[s];\n
+\n
+            if (typeof point == "number") {\n
+                var ps = s.datapoints.pointsize;\n
+                point = s.datapoints.points.slice(ps * point, ps * (point + 1));\n
+            }\n
+\n
+            var i = indexOfHighlight(s, point);\n
+            if (i != -1) {\n
+                highlights.splice(i, 1);\n
+\n
+                triggerRedrawOverlay();\n
+            }\n
+        }\n
+\n
+        function indexOfHighlight(s, p) {\n
+            for (var i = 0; i < highlights.length; ++i) {\n
+                var h = highlights[i];\n
+                if (h.series == s && h.point[0] == p[0]\n
+                    && h.point[1] == p[1])\n
+                    return i;\n
+            }\n
+            return -1;\n
+        }\n
+\n
+        function drawPointHighlight(series, point) {\n
+            var x = point[0], y = point[1],\n
+                axisx = series.xaxis, axisy = series.yaxis,\n
+                highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale(\'a\', 0.5).toString();\n
+\n
+            if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)\n
+                return;\n
+\n
+            var pointRadius = series.points.radius + series.points.lineWidth / 2;\n
+            octx.lineWidth = pointRadius;\n
+            octx.strokeStyle = highlightColor;\n
+            var radius = 1.5 * pointRadius;\n
+            x = axisx.p2c(x);\n
+            y = axisy.p2c(y);\n
+\n
+            octx.beginPath();\n
+            if (series.points.symbol == "circle")\n
+                octx.arc(x, y, radius, 0, 2 * Math.PI, false);\n
+            else\n
+                series.points.symbol(octx, x, y, radius, false);\n
+            octx.closePath();\n
+            octx.stroke();\n
+        }\n
+\n
+        function drawBarHighlight(series, point) {\n
+            var highlightColor = (typeof series.highlightColor === "string") ? series.highlightColor : $.color.parse(series.color).scale(\'a\', 0.5).toString(),\n
+                fillStyle = highlightColor,\n
+                barLeft;\n
+\n
+            switch (series.bars.align) {\n
+                case "left":\n
+                    barLeft = 0;\n
+                    break;\n
+                case "right":\n
+                    barLeft = -series.bars.barWidth;\n
+                    break;\n
+                default:\n
+                    barLeft = -series.bars.barWidth / 2;\n
+            }\n
+\n
+            octx.lineWidth = series.bars.lineWidth;\n
+            octx.strokeStyle = highlightColor;\n
+\n
+            drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth,\n
+                    function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth);\n
+        }\n
+\n
+        function getColorOrGradient(spec, bottom, top, defaultColor) {\n
+            if (typeof spec == "string")\n
+                return spec;\n
+            else {\n
+                // assume this is a gradient spec; IE currently only\n
+                // supports a simple vertical gradient properly, so that\'s\n
+                // what we support too\n
+                var gradient = ctx.createLinearGradient(0, top, 0, bottom);\n
+\n
+                for (var i = 0, l = spec.colors.length; i < l; ++i) {\n
+                    var c = spec.colors[i];\n
+                    if (typeof c != "string") {\n
+                        var co = $.color.parse(defaultColor);\n
+                        if (c.brightness != null)\n
+                            co = co.scale(\'rgb\', c.brightness);\n
+                        if (c.opacity != null)\n
+                            co.a *= c.opacity;\n
+                        c = co.toString();\n
+                    }\n
+                    gradient.addColorStop(i / (l - 1), c);\n
+                }\n
+\n
+                return gradient;\n
+            }\n
+        }\n
+    }\n
+\n
+    // Add the plot function to the top level of the jQuery object\n
+\n
+    $.plot = function(placeholder, data, options) {\n
+        //var t0 = new Date();\n
+        var plot = new Plot($(placeholder), data, options, $.plot.plugins);\n
+        //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime()));\n
+        return plot;\n
+    };\n
+\n
+    $.plot.version = "0.8.3";\n
+\n
+    $.plot.plugins = [];\n
+\n
+    // Also add the plot function as a chainable property\n
+\n
+    $.fn.plot = function(data, options) {\n
+        return this.each(function() {\n
+            $.plot(this, data, options);\n
+        });\n
+    };\n
+\n
+    // round to nearby lower multiple of base\n
+    function floorInBase(n, base) {\n
+        return base * Math.floor(n / base);\n
+    }\n
+\n
+})(jQuery);\n
+
+
+]]></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.flot.stack.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.flot.stack.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1a46f405a87e10626398c2d5dca4be6891980302
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.flot.stack.js.xml
@@ -0,0 +1,232 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681770.08</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jquery.flot.stack.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/* Flot plugin for stacking data sets rather than overlyaing them.\n
+\n
+Copyright (c) 2007-2014 IOLA and Ole Laursen.\n
+Licensed under the MIT license.\n
+\n
+The plugin assumes the data is sorted on x (or y if stacking horizontally).\n
+For line charts, it is assumed that if a line has an undefined gap (from a\n
+null point), then the line above it should have the same gap - insert zeros\n
+instead of "null" if you want another behaviour. This also holds for the start\n
+and end of the chart. Note that stacking a mix of positive and negative values\n
+in most instances doesn\'t make sense (so it looks weird).\n
+\n
+Two or more series are stacked when their "stack" attribute is set to the same\n
+key (which can be any number or string or just "true"). To specify the default\n
+stack, you can set the stack option like this:\n
+\n
+\tseries: {\n
+\t\tstack: null/false, true, or a key (number/string)\n
+\t}\n
+\n
+You can also specify it for a single series, like this:\n
+\n
+\t$.plot( $("#placeholder"), [{\n
+\t\tdata: [ ... ],\n
+\t\tstack: true\n
+\t}])\n
+\n
+The stacking order is determined by the order of the data series in the array\n
+(later series end up on top of the previous).\n
+\n
+Internally, the plugin modifies the datapoints in each series, adding an\n
+offset to the y value. For line series, extra data points are inserted through\n
+interpolation. If there\'s a second y value, it\'s also adjusted (e.g for bar\n
+charts or filled areas).\n
+\n
+*/\n
+\n
+(function ($) {\n
+    var options = {\n
+        series: { stack: null } // or number/string\n
+    };\n
+    \n
+    function init(plot) {\n
+        function findMatchingSeries(s, allseries) {\n
+            var res = null;\n
+            for (var i = 0; i < allseries.length; ++i) {\n
+                if (s == allseries[i])\n
+                    break;\n
+                \n
+                if (allseries[i].stack == s.stack)\n
+                    res = allseries[i];\n
+            }\n
+            \n
+            return res;\n
+        }\n
+        \n
+        function stackData(plot, s, datapoints) {\n
+            if (s.stack == null || s.stack === false)\n
+                return;\n
+\n
+            var other = findMatchingSeries(s, plot.getData());\n
+            if (!other)\n
+                return;\n
+\n
+            var ps = datapoints.pointsize,\n
+                points = datapoints.points,\n
+                otherps = other.datapoints.pointsize,\n
+                otherpoints = other.datapoints.points,\n
+                newpoints = [],\n
+                px, py, intery, qx, qy, bottom,\n
+                withlines = s.lines.show,\n
+                horizontal = s.bars.horizontal,\n
+                withbottom = ps > 2 && (horizontal ? datapoints.format[2].x : datapoints.format[2].y),\n
+                withsteps = withlines && s.lines.steps,\n
+                fromgap = true,\n
+                keyOffset = horizontal ? 1 : 0,\n
+                accumulateOffset = horizontal ? 0 : 1,\n
+                i = 0, j = 0, l, m;\n
+\n
+            while (true) {\n
+                if (i >= points.length)\n
+                    break;\n
+\n
+                l = newpoints.length;\n
+\n
+                if (points[i] == null) {\n
+                    // copy gaps\n
+                    for (m = 0; m < ps; ++m)\n
+                        newpoints.push(points[i + m]);\n
+                    i += ps;\n
+                }\n
+                else if (j >= otherpoints.length) {\n
+                    // for lines, we can\'t use the rest of the points\n
+                    if (!withlines) {\n
+                        for (m = 0; m < ps; ++m)\n
+                            newpoints.push(points[i + m]);\n
+                    }\n
+                    i += ps;\n
+                }\n
+                else if (otherpoints[j] == null) {\n
+                    // oops, got a gap\n
+                    for (m = 0; m < ps; ++m)\n
+                        newpoints.push(null);\n
+                    fromgap = true;\n
+                    j += otherps;\n
+                }\n
+                else {\n
+                    // cases where we actually got two points\n
+                    px = points[i + keyOffset];\n
+                    py = points[i + accumulateOffset];\n
+                    qx = otherpoints[j + keyOffset];\n
+                    qy = otherpoints[j + accumulateOffset];\n
+                    bottom = 0;\n
+\n
+                    if (px == qx) {\n
+                        for (m = 0; m < ps; ++m)\n
+                            newpoints.push(points[i + m]);\n
+\n
+                        newpoints[l + accumulateOffset] += qy;\n
+                        bottom = qy;\n
+                        \n
+                        i += ps;\n
+                        j += otherps;\n
+                    }\n
+                    else if (px > qx) {\n
+                        // we got past point below, might need to\n
+                        // insert interpolated extra point\n
+                        if (withlines && i > 0 && points[i - ps] != null) {\n
+                            intery = py + (points[i - ps + accumulateOffset] - py) * (qx - px) / (points[i - ps + keyOffset] - px);\n
+                            newpoints.push(qx);\n
+                            newpoints.push(intery + qy);\n
+                            for (m = 2; m < ps; ++m)\n
+                                newpoints.push(points[i + m]);\n
+                            bottom = qy; \n
+                        }\n
+\n
+                        j += otherps;\n
+                    }\n
+                    else { // px < qx\n
+                        if (fromgap && withlines) {\n
+                            // if we come from a gap, we just skip this point\n
+                            i += ps;\n
+                            continue;\n
+                        }\n
+                            \n
+                        for (m = 0; m < ps; ++m)\n
+                            newpoints.push(points[i + m]);\n
+                        \n
+                        // we might be able to interpolate a point below,\n
+                        // this can give us a better y\n
+                        if (withlines && j > 0 && otherpoints[j - otherps] != null)\n
+                            bottom = qy + (otherpoints[j - otherps + accumulateOffset] - qy) * (px - qx) / (otherpoints[j - otherps + keyOffset] - qx);\n
+\n
+                        newpoints[l + accumulateOffset] += bottom;\n
+                        \n
+                        i += ps;\n
+                    }\n
+\n
+                    fromgap = false;\n
+                    \n
+                    if (l != newpoints.length && withbottom)\n
+                        newpoints[l + 2] += bottom;\n
+                }\n
+\n
+                // maintain the line steps invariant\n
+                if (withsteps && l != newpoints.length && l > 0\n
+                    && newpoints[l] != null\n
+                    && newpoints[l] != newpoints[l - ps]\n
+                    && newpoints[l + 1] != newpoints[l - ps + 1]) {\n
+                    for (m = 0; m < ps; ++m)\n
+                        newpoints[l + ps + m] = newpoints[l + m];\n
+                    newpoints[l + 1] = newpoints[l - ps + 1];\n
+                }\n
+            }\n
+\n
+            datapoints.points = newpoints;\n
+        }\n
+        \n
+        plot.hooks.processDatapoints.push(stackData);\n
+    }\n
+    \n
+    $.plot.plugins.push({\n
+        init: init,\n
+        options: options,\n
+        name: \'stack\',\n
+        version: \'1.2\'\n
+    });\n
+})(jQuery);\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>7090</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fcad0fba83fa9e47510e2d4c188290aaccf1e9ed
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.js.xml
@@ -0,0 +1,8940 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681771.17</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jquery.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>242142</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*!\n
+ * jQuery JavaScript Library v2.0.3\n
+ * http://jquery.com/\n
+ *\n
+ * Includes Sizzle.js\n
+ * http://sizzlejs.com/\n
+ *\n
+ * Copyright 2005, 2013 jQuery Foundation, Inc. and other contributors\n
+ * Released under the MIT license\n
+ * http://jquery.org/license\n
+ *\n
+ * Date: 2013-07-03T13:30Z\n
+ */\n
+(function( window, undefined ) {\n
+\n
+// Can\'t do this because several apps including ASP.NET trace\n
+// the stack via arguments.caller.callee and Firefox dies if\n
+// you try to trace through "use strict" call chains. (#13335)\n
+// Support: Firefox 18+\n
+//"use strict";\n
+var\n
+\t// A central reference to the root jQuery(document)\n
+\trootjQuery,\n
+\n
+\t// The deferred used on DOM ready\n
+\treadyList,\n
+\n
+\t// Support: IE9\n
+\t// For `typeof xmlNode.method` instead of `xmlNode.method !== undefined`\n
+\tcore_strundefined = typeof undefined,\n
+\n
+\t// Use the correct document accordingly with window argument (sandbox)\n
+\tlocation = window.location,\n
+\tdocument = window.document,\n
+\tdocElem = document.documentElement,\n
+\n
+\t// Map over jQuery in case of overwrite\n
+\t_jQuery = window.jQuery,\n
+\n
+\t// Map over the $ in case of overwrite\n
+\t_$ = window.$,\n
+\n
+\t// [[Class]] -> type pairs\n
+\tclass2type = {},\n
+\n
+\t// List of deleted data cache ids, so we can reuse them\n
+\tcore_deletedIds = [],\n
+\n
+\tcore_version = "2.0.3",\n
+\n
+\t// Save a reference to some core methods\n
+\tcore_concat = core_deletedIds.concat,\n
+\tcore_push = core_deletedIds.push,\n
+\tcore_slice = core_deletedIds.slice,\n
+\tcore_indexOf = core_deletedIds.indexOf,\n
+\tcore_toString = class2type.toString,\n
+\tcore_hasOwn = class2type.hasOwnProperty,\n
+\tcore_trim = core_version.trim,\n
+\n
+\t// Define a local copy of jQuery\n
+\tjQuery = function( selector, context ) {\n
+\t\t// The jQuery object is actually just the init constructor \'enhanced\'\n
+\t\treturn new jQuery.fn.init( selector, context, rootjQuery );\n
+\t},\n
+\n
+\t// Used for matching numbers\n
+\tcore_pnum = /[+-]?(?:\\d*\\.|)\\d+(?:[eE][+-]?\\d+|)/.source,\n
+\n
+\t// Used for splitting on whitespace\n
+\tcore_rnotwhite = /\\S+/g,\n
+\n
+\t// A simple way to check for HTML strings\n
+\t// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)\n
+\t// Strict HTML recognition (#11290: must start with <)\n
+\trquickExpr = /^(?:\\s*(<[\\w\\W]+>)[^>]*|#([\\w-]*))$/,\n
+\n
+\t// Match a standalone tag\n
+\trsingleTag = /^<(\\w+)\\s*\\/?>(?:<\\/\\1>|)$/,\n
+\n
+\t// Matches dashed string for camelizing\n
+\trmsPrefix = /^-ms-/,\n
+\trdashAlpha = /-([\\da-z])/gi,\n
+\n
+\t// Used by jQuery.camelCase as callback to replace()\n
+\tfcamelCase = function( all, letter ) {\n
+\t\treturn letter.toUpperCase();\n
+\t},\n
+\n
+\t// The ready event handler and self cleanup method\n
+\tcompleted = function() {\n
+\t\tdocument.removeEventListener( "DOMContentLoaded", completed, false );\n
+\t\twindow.removeEventListener( "load", completed, false );\n
+\t\tjQuery.ready();\n
+\t};\n
+\n
+jQuery.fn = jQuery.prototype = {\n
+\t// The current version of jQuery being used\n
+\tjquery: core_version,\n
+\n
+\tconstructor: jQuery,\n
+\tinit: function( selector, context, rootjQuery ) {\n
+\t\tvar match, elem;\n
+\n
+\t\t// HANDLE: $(""), $(null), $(undefined), $(false)\n
+\t\tif ( !selector ) {\n
+\t\t\treturn this;\n
+\t\t}\n
+\n
+\t\t// Handle HTML strings\n
+\t\tif ( typeof selector === "string" ) {\n
+\t\t\tif ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {\n
+\t\t\t\t// Assume that strings that start and end with <> are HTML and skip the regex check\n
+\t\t\t\tmatch = [ null, selector, null ];\n
+\n
+\t\t\t} else {\n
+\t\t\t\tmatch = rquickExpr.exec( selector );\n
+\t\t\t}\n
+\n
+\t\t\t// Match html or make sure no context is specified for #id\n
+\t\t\tif ( match && (match[1] || !context) ) {\n
+\n
+\t\t\t\t// HANDLE: $(html) -> $(array)\n
+\t\t\t\tif ( match[1] ) {\n
+\t\t\t\t\tcontext = context instanceof jQuery ? context[0] : context;\n
+\n
+\t\t\t\t\t// scripts is true for back-compat\n
+\t\t\t\t\tjQuery.merge( this, jQuery.parseHTML(\n
+\t\t\t\t\t\tmatch[1],\n
+\t\t\t\t\t\tcontext && context.nodeType ? context.ownerDocument || context : document,\n
+\t\t\t\t\t\ttrue\n
+\t\t\t\t\t) );\n
+\n
+\t\t\t\t\t// HANDLE: $(html, props)\n
+\t\t\t\t\tif ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {\n
+\t\t\t\t\t\tfor ( match in context ) {\n
+\t\t\t\t\t\t\t// Properties of context are called as methods if possible\n
+\t\t\t\t\t\t\tif ( jQuery.isFunction( this[ match ] ) ) {\n
+\t\t\t\t\t\t\t\tthis[ match ]( context[ match ] );\n
+\n
+\t\t\t\t\t\t\t// ...and otherwise set as attributes\n
+\t\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t\tthis.attr( match, context[ match ] );\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\treturn this;\n
+\n
+\t\t\t\t// HANDLE: $(#id)\n
+\t\t\t\t} else {\n
+\t\t\t\t\telem = document.getElementById( match[2] );\n
+\n
+\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n
+\t\t\t\t\t// nodes that are no longer in the document #6963\n
+\t\t\t\t\tif ( elem && elem.parentNode ) {\n
+\t\t\t\t\t\t// Inject the element directly into the jQuery object\n
+\t\t\t\t\t\tthis.length = 1;\n
+\t\t\t\t\t\tthis[0] = elem;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tthis.context = document;\n
+\t\t\t\t\tthis.selector = selector;\n
+\t\t\t\t\treturn this;\n
+\t\t\t\t}\n
+\n
+\t\t\t// HANDLE: $(expr, $(...))\n
+\t\t\t} else if ( !context || context.jquery ) {\n
+\t\t\t\treturn ( context || rootjQuery ).find( selector );\n
+\n
+\t\t\t// HANDLE: $(expr, context)\n
+\t\t\t// (which is just equivalent to: $(context).find(expr)\n
+\t\t\t} else {\n
+\t\t\t\treturn this.constructor( context ).find( selector );\n
+\t\t\t}\n
+\n
+\t\t// HANDLE: $(DOMElement)\n
+\t\t} else if ( selector.nodeType ) {\n
+\t\t\tthis.context = this[0] = selector;\n
+\t\t\tthis.length = 1;\n
+\t\t\treturn this;\n
+\n
+\t\t// HANDLE: $(function)\n
+\t\t// Shortcut for document ready\n
+\t\t} else if ( jQuery.isFunction( selector ) ) {\n
+\t\t\treturn rootjQuery.ready( selector );\n
+\t\t}\n
+\n
+\t\tif ( selector.selector !== undefined ) {\n
+\t\t\tthis.selector = selector.selector;\n
+\t\t\tthis.context = selector.context;\n
+\t\t}\n
+\n
+\t\treturn jQuery.makeArray( selector, this );\n
+\t},\n
+\n
+\t// Start with an empty selector\n
+\tselector: "",\n
+\n
+\t// The default length of a jQuery object is 0\n
+\tlength: 0,\n
+\n
+\ttoArray: function() {\n
+\t\treturn core_slice.call( this );\n
+\t},\n
+\n
+\t// Get the Nth element in the matched element set OR\n
+\t// Get the whole matched element set as a clean array\n
+\tget: function( num ) {\n
+\t\treturn num == null ?\n
+\n
+\t\t\t// Return a \'clean\' array\n
+\t\t\tthis.toArray() :\n
+\n
+\t\t\t// Return just the object\n
+\t\t\t( num < 0 ? this[ this.length + num ] : this[ num ] );\n
+\t},\n
+\n
+\t// Take an array of elements and push it onto the stack\n
+\t// (returning the new matched element set)\n
+\tpushStack: function( elems ) {\n
+\n
+\t\t// Build a new jQuery matched element set\n
+\t\tvar ret = jQuery.merge( this.constructor(), elems );\n
+\n
+\t\t// Add the old object onto the stack (as a reference)\n
+\t\tret.prevObject = this;\n
+\t\tret.context = this.context;\n
+\n
+\t\t// Return the newly-formed element set\n
+\t\treturn ret;\n
+\t},\n
+\n
+\t// Execute a callback for every element in the matched set.\n
+\t// (You can seed the arguments with an array of args, but this is\n
+\t// only used internally.)\n
+\teach: function( callback, args ) {\n
+\t\treturn jQuery.each( this, callback, args );\n
+\t},\n
+\n
+\tready: function( fn ) {\n
+\t\t// Add the callback\n
+\t\tjQuery.ready.promise().done( fn );\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\tslice: function() {\n
+\t\treturn this.pushStack( core_slice.apply( this, arguments ) );\n
+\t},\n
+\n
+\tfirst: function() {\n
+\t\treturn this.eq( 0 );\n
+\t},\n
+\n
+\tlast: function() {\n
+\t\treturn this.eq( -1 );\n
+\t},\n
+\n
+\teq: function( i ) {\n
+\t\tvar len = this.length,\n
+\t\t\tj = +i + ( i < 0 ? len : 0 );\n
+\t\treturn this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );\n
+\t},\n
+\n
+\tmap: function( callback ) {\n
+\t\treturn this.pushStack( jQuery.map(this, function( elem, i ) {\n
+\t\t\treturn callback.call( elem, i, elem );\n
+\t\t}));\n
+\t},\n
+\n
+\tend: function() {\n
+\t\treturn this.prevObject || this.constructor(null);\n
+\t},\n
+\n
+\t// For internal use only.\n
+\t// Behaves like an Array\'s method, not like a jQuery method.\n
+\tpush: core_push,\n
+\tsort: [].sort,\n
+\tsplice: [].splice\n
+};\n
+\n
+// Give the init function the jQuery prototype for later instantiation\n
+jQuery.fn.init.prototype = jQuery.fn;\n
+\n
+jQuery.extend = jQuery.fn.extend = function() {\n
+\tvar options, name, src, copy, copyIsArray, clone,\n
+\t\ttarget = arguments[0] || {},\n
+\t\ti = 1,\n
+\t\tlength = arguments.length,\n
+\t\tdeep = false;\n
+\n
+\t// Handle a deep copy situation\n
+\tif ( typeof target === "boolean" ) {\n
+\t\tdeep = target;\n
+\t\ttarget = arguments[1] || {};\n
+\t\t// skip the boolean and the target\n
+\t\ti = 2;\n
+\t}\n
+\n
+\t// Handle case when target is a string or something (possible in deep copy)\n
+\tif ( typeof target !== "object" && !jQuery.isFunction(target) ) {\n
+\t\ttarget = {};\n
+\t}\n
+\n
+\t// extend jQuery itself if only one argument is passed\n
+\tif ( length === i ) {\n
+\t\ttarget = this;\n
+\t\t--i;\n
+\t}\n
+\n
+\tfor ( ; i < length; i++ ) {\n
+\t\t// Only deal with non-null/undefined values\n
+\t\tif ( (options = arguments[ i ]) != null ) {\n
+\t\t\t// Extend the base object\n
+\t\t\tfor ( name in options ) {\n
+\t\t\t\tsrc = target[ name ];\n
+\t\t\t\tcopy = options[ name ];\n
+\n
+\t\t\t\t// Prevent never-ending loop\n
+\t\t\t\tif ( target === copy ) {\n
+\t\t\t\t\tcontinue;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Recurse if we\'re merging plain objects or arrays\n
+\t\t\t\tif ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {\n
+\t\t\t\t\tif ( copyIsArray ) {\n
+\t\t\t\t\t\tcopyIsArray = false;\n
+\t\t\t\t\t\tclone = src && jQuery.isArray(src) ? src : [];\n
+\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tclone = src && jQuery.isPlainObject(src) ? src : {};\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// Never move original objects, clone them\n
+\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n
+\n
+\t\t\t\t// Don\'t bring in undefined values\n
+\t\t\t\t} else if ( copy !== undefined ) {\n
+\t\t\t\t\ttarget[ name ] = copy;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\t// Return the modified object\n
+\treturn target;\n
+};\n
+\n
+jQuery.extend({\n
+\t// Unique for each copy of jQuery on the page\n
+\texpando: "jQuery" + ( core_version + Math.random() ).replace( /\\D/g, "" ),\n
+\n
+\tnoConflict: function( deep ) {\n
+\t\tif ( window.$ === jQuery ) {\n
+\t\t\twindow.$ = _$;\n
+\t\t}\n
+\n
+\t\tif ( deep && window.jQuery === jQuery ) {\n
+\t\t\twindow.jQuery = _jQuery;\n
+\t\t}\n
+\n
+\t\treturn jQuery;\n
+\t},\n
+\n
+\t// Is the DOM ready to be used? Set to true once it occurs.\n
+\tisReady: false,\n
+\n
+\t// A counter to track how many items to wait for before\n
+\t// the ready event fires. See #6781\n
+\treadyWait: 1,\n
+\n
+\t// Hold (or release) the ready event\n
+\tholdReady: function( hold ) {\n
+\t\tif ( hold ) {\n
+\t\t\tjQuery.readyWait++;\n
+\t\t} else {\n
+\t\t\tjQuery.ready( true );\n
+\t\t}\n
+\t},\n
+\n
+\t// Handle when the DOM is ready\n
+\tready: function( wait ) {\n
+\n
+\t\t// Abort if there are pending holds or we\'re already ready\n
+\t\tif ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Remember that the DOM is ready\n
+\t\tjQuery.isReady = true;\n
+\n
+\t\t// If a normal DOM Ready event fired, decrement, and wait if need be\n
+\t\tif ( wait !== true && --jQuery.readyWait > 0 ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// If there are functions bound, to execute\n
+\t\treadyList.resolveWith( document, [ jQuery ] );\n
+\n
+\t\t// Trigger any bound ready events\n
+\t\tif ( jQuery.fn.trigger ) {\n
+\t\t\tjQuery( document ).trigger("ready").off("ready");\n
+\t\t}\n
+\t},\n
+\n
+\t// See test/unit/core.js for details concerning isFunction.\n
+\t// Since version 1.3, DOM methods and functions like alert\n
+\t// aren\'t supported. They return false on IE (#2968).\n
+\tisFunction: function( obj ) {\n
+\t\treturn jQuery.type(obj) === "function";\n
+\t},\n
+\n
+\tisArray: Array.isArray,\n
+\n
+\tisWindow: function( obj ) {\n
+\t\treturn obj != null && obj === obj.window;\n
+\t},\n
+\n
+\tisNumeric: function( obj ) {\n
+\t\treturn !isNaN( parseFloat(obj) ) && isFinite( obj );\n
+\t},\n
+\n
+\ttype: function( obj ) {\n
+\t\tif ( obj == null ) {\n
+\t\t\treturn String( obj );\n
+\t\t}\n
+\t\t// Support: Safari <= 5.1 (functionish RegExp)\n
+\t\treturn typeof obj === "object" || typeof obj === "function" ?\n
+\t\t\tclass2type[ core_toString.call(obj) ] || "object" :\n
+\t\t\ttypeof obj;\n
+\t},\n
+\n
+\tisPlainObject: function( obj ) {\n
+\t\t// Not plain objects:\n
+\t\t// - Any object or value whose internal [[Class]] property is not "[object Object]"\n
+\t\t// - DOM nodes\n
+\t\t// - window\n
+\t\tif ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\t// Support: Firefox <20\n
+\t\t// The try/catch suppresses exceptions thrown when attempting to access\n
+\t\t// the "constructor" property of certain host objects, ie. |window.location|\n
+\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=814622\n
+\t\ttry {\n
+\t\t\tif ( obj.constructor &&\n
+\t\t\t\t\t!core_hasOwn.call( obj.constructor.prototype, "isPrototypeOf" ) ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t} catch ( e ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\t// If the function hasn\'t returned already, we\'re confident that\n
+\t\t// |obj| is a plain object, created by {} or constructed with new Object\n
+\t\treturn true;\n
+\t},\n
+\n
+\tisEmptyObject: function( obj ) {\n
+\t\tvar name;\n
+\t\tfor ( name in obj ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\treturn true;\n
+\t},\n
+\n
+\terror: function( msg ) {\n
+\t\tthrow new Error( msg );\n
+\t},\n
+\n
+\t// data: string of html\n
+\t// context (optional): If specified, the fragment will be created in this context, defaults to document\n
+\t// keepScripts (optional): If true, will include scripts passed in the html string\n
+\tparseHTML: function( data, context, keepScripts ) {\n
+\t\tif ( !data || typeof data !== "string" ) {\n
+\t\t\treturn null;\n
+\t\t}\n
+\t\tif ( typeof context === "boolean" ) {\n
+\t\t\tkeepScripts = context;\n
+\t\t\tcontext = false;\n
+\t\t}\n
+\t\tcontext = context || document;\n
+\n
+\t\tvar parsed = rsingleTag.exec( data ),\n
+\t\t\tscripts = !keepScripts && [];\n
+\n
+\t\t// Single tag\n
+\t\tif ( parsed ) {\n
+\t\t\treturn [ context.createElement( parsed[1] ) ];\n
+\t\t}\n
+\n
+\t\tparsed = jQuery.buildFragment( [ data ], context, scripts );\n
+\n
+\t\tif ( scripts ) {\n
+\t\t\tjQuery( scripts ).remove();\n
+\t\t}\n
+\n
+\t\treturn jQuery.merge( [], parsed.childNodes );\n
+\t},\n
+\n
+\tparseJSON: JSON.parse,\n
+\n
+\t// Cross-browser xml parsing\n
+\tparseXML: function( data ) {\n
+\t\tvar xml, tmp;\n
+\t\tif ( !data || typeof data !== "string" ) {\n
+\t\t\treturn null;\n
+\t\t}\n
+\n
+\t\t// Support: IE9\n
+\t\ttry {\n
+\t\t\ttmp = new DOMParser();\n
+\t\t\txml = tmp.parseFromString( data , "text/xml" );\n
+\t\t} catch ( e ) {\n
+\t\t\txml = undefined;\n
+\t\t}\n
+\n
+\t\tif ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {\n
+\t\t\tjQuery.error( "Invalid XML: " + data );\n
+\t\t}\n
+\t\treturn xml;\n
+\t},\n
+\n
+\tnoop: function() {},\n
+\n
+\t// Evaluates a script in a global context\n
+\tglobalEval: function( code ) {\n
+\t\tvar script,\n
+\t\t\t\tindirect = eval;\n
+\n
+\t\tcode = jQuery.trim( code );\n
+\n
+\t\tif ( code ) {\n
+\t\t\t// If the code includes a valid, prologue position\n
+\t\t\t// strict mode pragma, execute code by injecting a\n
+\t\t\t// script tag into the document.\n
+\t\t\tif ( code.indexOf("use strict") === 1 ) {\n
+\t\t\t\tscript = document.createElement("script");\n
+\t\t\t\tscript.text = code;\n
+\t\t\t\tdocument.head.appendChild( script ).parentNode.removeChild( script );\n
+\t\t\t} else {\n
+\t\t\t// Otherwise, avoid the DOM node creation, insertion\n
+\t\t\t// and removal by using an indirect global eval\n
+\t\t\t\tindirect( code );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t// Convert dashed to camelCase; used by the css and data modules\n
+\t// Microsoft forgot to hump their vendor prefix (#9572)\n
+\tcamelCase: function( string ) {\n
+\t\treturn string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );\n
+\t},\n
+\n
+\tnodeName: function( elem, name ) {\n
+\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();\n
+\t},\n
+\n
+\t// args is for internal usage only\n
+\teach: function( obj, callback, args ) {\n
+\t\tvar value,\n
+\t\t\ti = 0,\n
+\t\t\tlength = obj.length,\n
+\t\t\tisArray = isArraylike( obj );\n
+\n
+\t\tif ( args ) {\n
+\t\t\tif ( isArray ) {\n
+\t\t\t\tfor ( ; i < length; i++ ) {\n
+\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n
+\n
+\t\t\t\t\tif ( value === false ) {\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\tfor ( i in obj ) {\n
+\t\t\t\t\tvalue = callback.apply( obj[ i ], args );\n
+\n
+\t\t\t\t\tif ( value === false ) {\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t// A special, fast, case for the most common use of each\n
+\t\t} else {\n
+\t\t\tif ( isArray ) {\n
+\t\t\t\tfor ( ; i < length; i++ ) {\n
+\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n
+\n
+\t\t\t\t\tif ( value === false ) {\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\tfor ( i in obj ) {\n
+\t\t\t\t\tvalue = callback.call( obj[ i ], i, obj[ i ] );\n
+\n
+\t\t\t\t\tif ( value === false ) {\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn obj;\n
+\t},\n
+\n
+\ttrim: function( text ) {\n
+\t\treturn text == null ? "" : core_trim.call( text );\n
+\t},\n
+\n
+\t// results is for internal usage only\n
+\tmakeArray: function( arr, results ) {\n
+\t\tvar ret = results || [];\n
+\n
+\t\tif ( arr != null ) {\n
+\t\t\tif ( isArraylike( Object(arr) ) ) {\n
+\t\t\t\tjQuery.merge( ret,\n
+\t\t\t\t\ttypeof arr === "string" ?\n
+\t\t\t\t\t[ arr ] : arr\n
+\t\t\t\t);\n
+\t\t\t} else {\n
+\t\t\t\tcore_push.call( ret, arr );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn ret;\n
+\t},\n
+\n
+\tinArray: function( elem, arr, i ) {\n
+\t\treturn arr == null ? -1 : core_indexOf.call( arr, elem, i );\n
+\t},\n
+\n
+\tmerge: function( first, second ) {\n
+\t\tvar l = second.length,\n
+\t\t\ti = first.length,\n
+\t\t\tj = 0;\n
+\n
+\t\tif ( typeof l === "number" ) {\n
+\t\t\tfor ( ; j < l; j++ ) {\n
+\t\t\t\tfirst[ i++ ] = second[ j ];\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\twhile ( second[j] !== undefined ) {\n
+\t\t\t\tfirst[ i++ ] = second[ j++ ];\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tfirst.length = i;\n
+\n
+\t\treturn first;\n
+\t},\n
+\n
+\tgrep: function( elems, callback, inv ) {\n
+\t\tvar retVal,\n
+\t\t\tret = [],\n
+\t\t\ti = 0,\n
+\t\t\tlength = elems.length;\n
+\t\tinv = !!inv;\n
+\n
+\t\t// Go through the array, only saving the items\n
+\t\t// that pass the validator function\n
+\t\tfor ( ; i < length; i++ ) {\n
+\t\t\tretVal = !!callback( elems[ i ], i );\n
+\t\t\tif ( inv !== retVal ) {\n
+\t\t\t\tret.push( elems[ i ] );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn ret;\n
+\t},\n
+\n
+\t// arg is for internal usage only\n
+\tmap: function( elems, callback, arg ) {\n
+\t\tvar value,\n
+\t\t\ti = 0,\n
+\t\t\tlength = elems.length,\n
+\t\t\tisArray = isArraylike( elems ),\n
+\t\t\tret = [];\n
+\n
+\t\t// Go through the array, translating each of the items to their\n
+\t\tif ( isArray ) {\n
+\t\t\tfor ( ; i < length; i++ ) {\n
+\t\t\t\tvalue = callback( elems[ i ], i, arg );\n
+\n
+\t\t\t\tif ( value != null ) {\n
+\t\t\t\t\tret[ ret.length ] = value;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t// Go through every key on the object,\n
+\t\t} else {\n
+\t\t\tfor ( i in elems ) {\n
+\t\t\t\tvalue = callback( elems[ i ], i, arg );\n
+\n
+\t\t\t\tif ( value != null ) {\n
+\t\t\t\t\tret[ ret.length ] = value;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Flatten any nested arrays\n
+\t\treturn core_concat.apply( [], ret );\n
+\t},\n
+\n
+\t// A global GUID counter for objects\n
+\tguid: 1,\n
+\n
+\t// Bind a function to a context, optionally partially applying any\n
+\t// arguments.\n
+\tproxy: function( fn, context ) {\n
+\t\tvar tmp, args, proxy;\n
+\n
+\t\tif ( typeof context === "string" ) {\n
+\t\t\ttmp = fn[ context ];\n
+\t\t\tcontext = fn;\n
+\t\t\tfn = tmp;\n
+\t\t}\n
+\n
+\t\t// Quick check to determine if target is callable, in the spec\n
+\t\t// this throws a TypeError, but we will just return undefined.\n
+\t\tif ( !jQuery.isFunction( fn ) ) {\n
+\t\t\treturn undefined;\n
+\t\t}\n
+\n
+\t\t// Simulated bind\n
+\t\targs = core_slice.call( arguments, 2 );\n
+\t\tproxy = function() {\n
+\t\t\treturn fn.apply( context || this, args.concat( core_slice.call( arguments ) ) );\n
+\t\t};\n
+\n
+\t\t// Set the guid of unique handler to the same of original handler, so it can be removed\n
+\t\tproxy.guid = fn.guid = fn.guid || jQuery.guid++;\n
+\n
+\t\treturn proxy;\n
+\t},\n
+\n
+\t// Multifunctional method to get and set values of a collection\n
+\t// The value/s can optionally be executed if it\'s a function\n
+\taccess: function( elems, fn, key, value, chainable, emptyGet, raw ) {\n
+\t\tvar i = 0,\n
+\t\t\tlength = elems.length,\n
+\t\t\tbulk = key == null;\n
+\n
+\t\t// Sets many values\n
+\t\tif ( jQuery.type( key ) === "object" ) {\n
+\t\t\tchainable = true;\n
+\t\t\tfor ( i in key ) {\n
+\t\t\t\tjQuery.access( elems, fn, i, key[i], true, emptyGet, raw );\n
+\t\t\t}\n
+\n
+\t\t// Sets one value\n
+\t\t} else if ( value !== undefined ) {\n
+\t\t\tchainable = true;\n
+\n
+\t\t\tif ( !jQuery.isFunction( value ) ) {\n
+\t\t\t\traw = true;\n
+\t\t\t}\n
+\n
+\t\t\tif ( bulk ) {\n
+\t\t\t\t// Bulk operations run against the entire set\n
+\t\t\t\tif ( raw ) {\n
+\t\t\t\t\tfn.call( elems, value );\n
+\t\t\t\t\tfn = null;\n
+\n
+\t\t\t\t// ...except when executing function values\n
+\t\t\t\t} else {\n
+\t\t\t\t\tbulk = fn;\n
+\t\t\t\t\tfn = function( elem, key, value ) {\n
+\t\t\t\t\t\treturn bulk.call( jQuery( elem ), value );\n
+\t\t\t\t\t};\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif ( fn ) {\n
+\t\t\t\tfor ( ; i < length; i++ ) {\n
+\t\t\t\t\tfn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn chainable ?\n
+\t\t\telems :\n
+\n
+\t\t\t// Gets\n
+\t\t\tbulk ?\n
+\t\t\t\tfn.call( elems ) :\n
+\t\t\t\tlength ? fn( elems[0], key ) : emptyGet;\n
+\t},\n
+\n
+\tnow: Date.now,\n
+\n
+\t// A method for quickly swapping in/out CSS properties to get correct calculations.\n
+\t// Note: this method belongs to the css module but it\'s needed here for the support module.\n
+\t// If support gets modularized, this method should be moved back to the css module.\n
+\tswap: function( elem, options, callback, args ) {\n
+\t\tvar ret, name,\n
+\t\t\told = {};\n
+\n
+\t\t// Remember the old values, and insert the new ones\n
+\t\tfor ( name in options ) {\n
+\t\t\told[ name ] = elem.style[ name ];\n
+\t\t\telem.style[ name ] = options[ name ];\n
+\t\t}\n
+\n
+\t\tret = callback.apply( elem, args || [] );\n
+\n
+\t\t// Revert the old values\n
+\t\tfor ( name in options ) {\n
+\t\t\telem.style[ name ] = old[ name ];\n
+\t\t}\n
+\n
+\t\treturn ret;\n
+\t}\n
+});\n
+\n
+jQuery.ready.promise = function( obj ) {\n
+\tif ( !readyList ) {\n
+\n
+\t\treadyList = jQuery.Deferred();\n
+\n
+\t\t// Catch cases where $(document).ready() is called after the browser event has already occurred.\n
+\t\t// we once tried to use readyState "interactive" here, but it caused issues like the one\n
+\t\t// discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15\n
+\t\tif ( document.readyState === "complete" ) {\n
+\t\t\t// Handle it asynchronously to allow scripts the opportunity to delay ready\n
+\t\t\tsetTimeout( jQuery.ready );\n
+\n
+\t\t} else {\n
+\n
+\t\t\t// Use the handy event callback\n
+\t\t\tdocument.addEventListener( "DOMContentLoaded", completed, false );\n
+\n
+\t\t\t// A fallback to window.onload, that will always work\n
+\t\t\twindow.addEventListener( "load", completed, false );\n
+\t\t}\n
+\t}\n
+\treturn readyList.promise( obj );\n
+};\n
+\n
+// Populate the class2type map\n
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {\n
+\tclass2type[ "[object " + name + "]" ] = name.toLowerCase();\n
+});\n
+\n
+function isArraylike( obj ) {\n
+\tvar length = obj.length,\n
+\t\ttype = jQuery.type( obj );\n
+\n
+\tif ( jQuery.isWindow( obj ) ) {\n
+\t\treturn false;\n
+\t}\n
+\n
+\tif ( obj.nodeType === 1 && length ) {\n
+\t\treturn true;\n
+\t}\n
+\n
+\treturn type === "array" || type !== "function" &&\n
+\t\t( length === 0 ||\n
+\t\ttypeof length === "number" && length > 0 && ( length - 1 ) in obj );\n
+}\n
+\n
+// All jQuery objects should point back to these\n
+rootjQuery = jQuery(document);\n
+/*!\n
+ * Sizzle CSS Selector Engine v1.9.4-pre\n
+ * http://sizzlejs.com/\n
+ *\n
+ * Copyright 2013 jQuery Foundation, Inc. and other contributors\n
+ * Released under the MIT license\n
+ * http://jquery.org/license\n
+ *\n
+ * Date: 2013-06-03\n
+ */\n
+(function( window, undefined ) {\n
+\n
+var i,\n
+\tsupport,\n
+\tcachedruns,\n
+\tExpr,\n
+\tgetText,\n
+\tisXML,\n
+\tcompile,\n
+\toutermostContext,\n
+\tsortInput,\n
+\n
+\t// Local document vars\n
+\tsetDocument,\n
+\tdocument,\n
+\tdocElem,\n
+\tdocumentIsHTML,\n
+\trbuggyQSA,\n
+\trbuggyMatches,\n
+\tmatches,\n
+\tcontains,\n
+\n
+\t// Instance-specific data\n
+\texpando = "sizzle" + -(new Date()),\n
+\tpreferredDoc = window.document,\n
+\tdirruns = 0,\n
+\tdone = 0,\n
+\tclassCache = createCache(),\n
+\ttokenCache = createCache(),\n
+\tcompilerCache = createCache(),\n
+\thasDuplicate = false,\n
+\tsortOrder = function( a, b ) {\n
+\t\tif ( a === b ) {\n
+\t\t\thasDuplicate = true;\n
+\t\t\treturn 0;\n
+\t\t}\n
+\t\treturn 0;\n
+\t},\n
+\n
+\t// General-purpose constants\n
+\tstrundefined = typeof undefined,\n
+\tMAX_NEGATIVE = 1 << 31,\n
+\n
+\t// Instance methods\n
+\thasOwn = ({}).hasOwnProperty,\n
+\tarr = [],\n
+\tpop = arr.pop,\n
+\tpush_native = arr.push,\n
+\tpush = arr.push,\n
+\tslice = arr.slice,\n
+\t// Use a stripped-down indexOf if we can\'t use a native one\n
+\tindexOf = arr.indexOf || function( elem ) {\n
+\t\tvar i = 0,\n
+\t\t\tlen = this.length;\n
+\t\tfor ( ; i < len; i++ ) {\n
+\t\t\tif ( this[i] === elem ) {\n
+\t\t\t\treturn i;\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn -1;\n
+\t},\n
+\n
+\tbooleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",\n
+\n
+\t// Regular expressions\n
+\n
+\t// Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace\n
+\twhitespace = "[\\\\x20\\\\t\\\\r\\\\n\\\\f]",\n
+\t// http://www.w3.org/TR/css3-syntax/#characters\n
+\tcharacterEncoding = "(?:\\\\\\\\.|[\\\\w-]|[^\\\\x00-\\\\xa0])+",\n
+\n
+\t// Loosely modeled on CSS identifier characters\n
+\t// An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors\n
+\t// Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier\n
+\tidentifier = characterEncoding.replace( "w", "w#" ),\n
+\n
+\t// Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors\n
+\tattributes = "\\\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace +\n
+\t\t"*(?:([*^$|!~]?=)" + whitespace + "*(?:([\'\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|(" + identifier + ")|)|)" + whitespace + "*\\\\]",\n
+\n
+\t// Prefer arguments quoted,\n
+\t//   then not containing pseudos/brackets,\n
+\t//   then attribute selectors/non-parenthetical expressions,\n
+\t//   then anything else\n
+\t// These preferences are here to reduce the number of selectors\n
+\t//   needing tokenize in the PSEUDO preFilter\n
+\tpseudos = ":(" + characterEncoding + ")(?:\\\\((([\'\\"])((?:\\\\\\\\.|[^\\\\\\\\])*?)\\\\3|((?:\\\\\\\\.|[^\\\\\\\\()[\\\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\\\)|)",\n
+\n
+\t// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter\n
+\trtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\\\\\])(?:\\\\\\\\.)*)" + whitespace + "+$", "g" ),\n
+\n
+\trcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),\n
+\trcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),\n
+\n
+\trsibling = new RegExp( whitespace + "*[+~]" ),\n
+\trattributeQuotes = new RegExp( "=" + whitespace + "*([^\\\\]\'\\"]*)" + whitespace + "*\\\\]", "g" ),\n
+\n
+\trpseudo = new RegExp( pseudos ),\n
+\tridentifier = new RegExp( "^" + identifier + "$" ),\n
+\n
+\tmatchExpr = {\n
+\t\t"ID": new RegExp( "^#(" + characterEncoding + ")" ),\n
+\t\t"CLASS": new RegExp( "^\\\\.(" + characterEncoding + ")" ),\n
+\t\t"TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),\n
+\t\t"ATTR": new RegExp( "^" + attributes ),\n
+\t\t"PSEUDO": new RegExp( "^" + pseudos ),\n
+\t\t"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\\\(" + whitespace +\n
+\t\t\t"*(even|odd|(([+-]|)(\\\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +\n
+\t\t\t"*(\\\\d+)|))" + whitespace + "*\\\\)|)", "i" ),\n
+\t\t"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),\n
+\t\t// For use in libraries implementing .is()\n
+\t\t// We use this for POS matching in `select`\n
+\t\t"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\\\(" +\n
+\t\t\twhitespace + "*((?:-\\\\d)?\\\\d*)" + whitespace + "*\\\\)|)(?=[^-]|$)", "i" )\n
+\t},\n
+\n
+\trnative = /^[^{]+\\{\\s*\\[native \\w/,\n
+\n
+\t// Easily-parseable/retrievable ID or TAG or CLASS selectors\n
+\trquickExpr = /^(?:#([\\w-]+)|(\\w+)|\\.([\\w-]+))$/,\n
+\n
+\trinputs = /^(?:input|select|textarea|button)$/i,\n
+\trheader = /^h\\d$/i,\n
+\n
+\trescape = /\'|\\\\/g,\n
+\n
+\t// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters\n
+\trunescape = new RegExp( "\\\\\\\\([\\\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),\n
+\tfunescape = function( _, escaped, escapedWhitespace ) {\n
+\t\tvar high = "0x" + escaped - 0x10000;\n
+\t\t// NaN means non-codepoint\n
+\t\t// Support: Firefox\n
+\t\t// Workaround erroneous numeric interpretation of +"0x"\n
+\t\treturn high !== high || escapedWhitespace ?\n
+\t\t\tescaped :\n
+\t\t\t// BMP codepoint\n
+\t\t\thigh < 0 ?\n
+\t\t\t\tString.fromCharCode( high + 0x10000 ) :\n
+\t\t\t\t// Supplemental Plane codepoint (surrogate pair)\n
+\t\t\t\tString.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );\n
+\t};\n
+\n
+// Optimize for push.apply( _, NodeList )\n
+try {\n
+\tpush.apply(\n
+\t\t(arr = slice.call( preferredDoc.childNodes )),\n
+\t\tpreferredDoc.childNodes\n
+\t);\n
+\t// Support: Android<4.0\n
+\t// Detect silently failing push.apply\n
+\tarr[ preferredDoc.childNodes.length ].nodeType;\n
+} catch ( e ) {\n
+\tpush = { apply: arr.length ?\n
+\n
+\t\t// Leverage slice if possible\n
+\t\tfunction( target, els ) {\n
+\t\t\tpush_native.apply( target, slice.call(els) );\n
+\t\t} :\n
+\n
+\t\t// Support: IE<9\n
+\t\t// Otherwise append directly\n
+\t\tfunction( target, els ) {\n
+\t\t\tvar j = target.length,\n
+\t\t\t\ti = 0;\n
+\t\t\t// Can\'t trust NodeList.length\n
+\t\t\twhile ( (target[j++] = els[i++]) ) {}\n
+\t\t\ttarget.length = j - 1;\n
+\t\t}\n
+\t};\n
+}\n
+\n
+function Sizzle( selector, context, results, seed ) {\n
+\tvar match, elem, m, nodeType,\n
+\t\t// QSA vars\n
+\t\ti, groups, old, nid, newContext, newSelector;\n
+\n
+\tif ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {\n
+\t\tsetDocument( context );\n
+\t}\n
+\n
+\tcontext = context || document;\n
+\tresults = results || [];\n
+\n
+\tif ( !selector || typeof selector !== "string" ) {\n
+\t\treturn results;\n
+\t}\n
+\n
+\tif ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) {\n
+\t\treturn [];\n
+\t}\n
+\n
+\tif ( documentIsHTML && !seed ) {\n
+\n
+\t\t// Shortcuts\n
+\t\tif ( (match = rquickExpr.exec( selector )) ) {\n
+\t\t\t// Speed-up: Sizzle("#ID")\n
+\t\t\tif ( (m = match[1]) ) {\n
+\t\t\t\tif ( nodeType === 9 ) {\n
+\t\t\t\t\telem = context.getElementById( m );\n
+\t\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n
+\t\t\t\t\t// nodes that are no longer in the document #6963\n
+\t\t\t\t\tif ( elem && elem.parentNode ) {\n
+\t\t\t\t\t\t// Handle the case where IE, Opera, and Webkit return items\n
+\t\t\t\t\t\t// by name instead of ID\n
+\t\t\t\t\t\tif ( elem.id === m ) {\n
+\t\t\t\t\t\t\tresults.push( elem );\n
+\t\t\t\t\t\t\treturn results;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\treturn results;\n
+\t\t\t\t\t}\n
+\t\t\t\t} else {\n
+\t\t\t\t\t// Context is not a document\n
+\t\t\t\t\tif ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&\n
+\t\t\t\t\t\tcontains( context, elem ) && elem.id === m ) {\n
+\t\t\t\t\t\tresults.push( elem );\n
+\t\t\t\t\t\treturn results;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t// Speed-up: Sizzle("TAG")\n
+\t\t\t} else if ( match[2] ) {\n
+\t\t\t\tpush.apply( results, context.getElementsByTagName( selector ) );\n
+\t\t\t\treturn results;\n
+\n
+\t\t\t// Speed-up: Sizzle(".CLASS")\n
+\t\t\t} else if ( (m = match[3]) && support.getElementsByClassName && context.getElementsByClassName ) {\n
+\t\t\t\tpush.apply( results, context.getElementsByClassName( m ) );\n
+\t\t\t\treturn results;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// QSA path\n
+\t\tif ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {\n
+\t\t\tnid = old = expando;\n
+\t\t\tnewContext = context;\n
+\t\t\tnewSelector = nodeType === 9 && selector;\n
+\n
+\t\t\t// qSA works strangely on Element-rooted queries\n
+\t\t\t// We can work around this by specifying an extra ID on the root\n
+\t\t\t// and working up from there (Thanks to Andrew Dupont for the technique)\n
+\t\t\t// IE 8 doesn\'t work on object elements\n
+\t\t\tif ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {\n
+\t\t\t\tgroups = tokenize( selector );\n
+\n
+\t\t\t\tif ( (old = context.getAttribute("id")) ) {\n
+\t\t\t\t\tnid = old.replace( rescape, "\\\\$&" );\n
+\t\t\t\t} else {\n
+\t\t\t\t\tcontext.setAttribute( "id", nid );\n
+\t\t\t\t}\n
+\t\t\t\tnid = "[id=\'" + nid + "\'] ";\n
+\n
+\t\t\t\ti = groups.length;\n
+\t\t\t\twhile ( i-- ) {\n
+\t\t\t\t\tgroups[i] = nid + toSelector( groups[i] );\n
+\t\t\t\t}\n
+\t\t\t\tnewContext = rsibling.test( selector ) && context.parentNode || context;\n
+\t\t\t\tnewSelector = groups.join(",");\n
+\t\t\t}\n
+\n
+\t\t\tif ( newSelector ) {\n
+\t\t\t\ttry {\n
+\t\t\t\t\tpush.apply( results,\n
+\t\t\t\t\t\tnewContext.querySelectorAll( newSelector )\n
+\t\t\t\t\t);\n
+\t\t\t\t\treturn results;\n
+\t\t\t\t} catch(qsaError) {\n
+\t\t\t\t} finally {\n
+\t\t\t\t\tif ( !old ) {\n
+\t\t\t\t\t\tcontext.removeAttribute("id");\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\t// All others\n
+\treturn select( selector.replace( rtrim, "$1" ), context, results, seed );\n
+}\n
+\n
+/**\n
+ * Create key-value caches of limited size\n
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with\n
+ *\tproperty name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)\n
+ *\tdeleting the oldest entry\n
+ */\n
+function createCache() {\n
+\tvar keys = [];\n
+\n
+\tfunction cache( key, value ) {\n
+\t\t// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)\n
+\t\tif ( keys.push( key += " " ) > Expr.cacheLength ) {\n
+\t\t\t// Only keep the most recent entries\n
+\t\t\tdelete cache[ keys.shift() ];\n
+\t\t}\n
+\t\treturn (cache[ key ] = value);\n
+\t}\n
+\treturn cache;\n
+}\n
+\n
+/**\n
+ * Mark a function for special use by Sizzle\n
+ * @param {Function} fn The function to mark\n
+ */\n
+function markFunction( fn ) {\n
+\tfn[ expando ] = true;\n
+\treturn fn;\n
+}\n
+\n
+/**\n
+ * Support testing using an element\n
+ * @param {Function} fn Passed the created div and expects a boolean result\n
+ */\n
+function assert( fn ) {\n
+\tvar div = document.createElement("div");\n
+\n
+\ttry {\n
+\t\treturn !!fn( div );\n
+\t} catch (e) {\n
+\t\treturn false;\n
+\t} finally {\n
+\t\t// Remove from its parent by default\n
+\t\tif ( div.parentNode ) {\n
+\t\t\tdiv.parentNode.removeChild( div );\n
+\t\t}\n
+\t\t// release memory in IE\n
+\t\tdiv = null;\n
+\t}\n
+}\n
+\n
+/**\n
+ * Adds the same handler for all of the specified attrs\n
+ * @param {String} attrs Pipe-separated list of attributes\n
+ * @param {Function} handler The method that will be applied\n
+ */\n
+function addHandle( attrs, handler ) {\n
+\tvar arr = attrs.split("|"),\n
+\t\ti = attrs.length;\n
+\n
+\twhile ( i-- ) {\n
+\t\tExpr.attrHandle[ arr[i] ] = handler;\n
+\t}\n
+}\n
+\n
+/**\n
+ * Checks document order of two siblings\n
+ * @param {Element} a\n
+ * @param {Element} b\n
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b\n
+ */\n
+function siblingCheck( a, b ) {\n
+\tvar cur = b && a,\n
+\t\tdiff = cur && a.nodeType === 1 && b.nodeType === 1 &&\n
+\t\t\t( ~b.sourceIndex || MAX_NEGATIVE ) -\n
+\t\t\t( ~a.sourceIndex || MAX_NEGATIVE );\n
+\n
+\t// Use IE sourceIndex if available on both nodes\n
+\tif ( diff ) {\n
+\t\treturn diff;\n
+\t}\n
+\n
+\t// Check if b follows a\n
+\tif ( cur ) {\n
+\t\twhile ( (cur = cur.nextSibling) ) {\n
+\t\t\tif ( cur === b ) {\n
+\t\t\t\treturn -1;\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\treturn a ? 1 : -1;\n
+}\n
+\n
+/**\n
+ * Returns a function to use in pseudos for input types\n
+ * @param {String} type\n
+ */\n
+function createInputPseudo( type ) {\n
+\treturn function( elem ) {\n
+\t\tvar name = elem.nodeName.toLowerCase();\n
+\t\treturn name === "input" && elem.type === type;\n
+\t};\n
+}\n
+\n
+/**\n
+ * Returns a function to use in pseudos for buttons\n
+ * @param {String} type\n
+ */\n
+function createButtonPseudo( type ) {\n
+\treturn function( elem ) {\n
+\t\tvar name = elem.nodeName.toLowerCase();\n
+\t\treturn (name === "input" || name === "button") && elem.type === type;\n
+\t};\n
+}\n
+\n
+/**\n
+ * Returns a function to use in pseudos for positionals\n
+ * @param {Function} fn\n
+ */\n
+function createPositionalPseudo( fn ) {\n
+\treturn markFunction(function( argument ) {\n
+\t\targument = +argument;\n
+\t\treturn markFunction(function( seed, matches ) {\n
+\t\t\tvar j,\n
+\t\t\t\tmatchIndexes = fn( [], seed.length, argument ),\n
+\t\t\t\ti = matchIndexes.length;\n
+\n
+\t\t\t// Match elements found at the specified indexes\n
+\t\t\twhile ( i-- ) {\n
+\t\t\t\tif ( seed[ (j = matchIndexes[i]) ] ) {\n
+\t\t\t\t\tseed[j] = !(matches[j] = seed[j]);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t});\n
+\t});\n
+}\n
+\n
+/**\n
+ * Detect xml\n
+ * @param {Element|Object} elem An element or a document\n
+ */\n
+isXML = Sizzle.isXML = function( elem ) {\n
+\t// documentElement is verified for cases where it doesn\'t yet exist\n
+\t// (such as loading iframes in IE - #4833)\n
+\tvar documentElement = elem && (elem.ownerDocument || elem).documentElement;\n
+\treturn documentElement ? documentElement.nodeName !== "HTML" : false;\n
+};\n
+\n
+// Expose support vars for convenience\n
+support = Sizzle.support = {};\n
+\n
+/**\n
+ * Sets document-related variables once based on the current document\n
+ * @param {Element|Object} [doc] An element or document object to use to set the document\n
+ * @returns {Object} Returns the current document\n
+ */\n
+setDocument = Sizzle.setDocument = function( node ) {\n
+\tvar doc = node ? node.ownerDocument || node : preferredDoc,\n
+\t\tparent = doc.defaultView;\n
+\n
+\t// If no document and documentElement is available, return\n
+\tif ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {\n
+\t\treturn document;\n
+\t}\n
+\n
+\t// Set our document\n
+\tdocument = doc;\n
+\tdocElem = doc.documentElement;\n
+\n
+\t// Support tests\n
+\tdocumentIsHTML = !isXML( doc );\n
+\n
+\t// Support: IE>8\n
+\t// If iframe document is assigned to "document" variable and if iframe has been reloaded,\n
+\t// IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936\n
+\t// IE6-8 do not support the defaultView property so parent will be undefined\n
+\tif ( parent && parent.attachEvent && parent !== parent.top ) {\n
+\t\tparent.attachEvent( "onbeforeunload", function() {\n
+\t\t\tsetDocument();\n
+\t\t});\n
+\t}\n
+\n
+\t/* Attributes\n
+\t---------------------------------------------------------------------- */\n
+\n
+\t// Support: IE<8\n
+\t// Verify that getAttribute really returns attributes and not properties (excepting IE8 booleans)\n
+\tsupport.attributes = assert(function( div ) {\n
+\t\tdiv.className = "i";\n
+\t\treturn !div.getAttribute("className");\n
+\t});\n
+\n
+\t/* getElement(s)By*\n
+\t---------------------------------------------------------------------- */\n
+\n
+\t// Check if getElementsByTagName("*") returns only elements\n
+\tsupport.getElementsByTagName = assert(function( div ) {\n
+\t\tdiv.appendChild( doc.createComment("") );\n
+\t\treturn !div.getElementsByTagName("*").length;\n
+\t});\n
+\n
+\t// Check if getElementsByClassName can be trusted\n
+\tsupport.getElementsByClassName = assert(function( div ) {\n
+\t\tdiv.innerHTML = "<div class=\'a\'></div><div class=\'a i\'></div>";\n
+\n
+\t\t// Support: Safari<4\n
+\t\t// Catch class over-caching\n
+\t\tdiv.firstChild.className = "i";\n
+\t\t// Support: Opera<10\n
+\t\t// Catch gEBCN failure to find non-leading classes\n
+\t\treturn div.getElementsByClassName("i").length === 2;\n
+\t});\n
+\n
+\t// Support: IE<10\n
+\t// Check if getElementById returns elements by name\n
+\t// The broken getElementById methods don\'t pick up programatically-set names,\n
+\t// so use a roundabout getElementsByName test\n
+\tsupport.getById = assert(function( div ) {\n
+\t\tdocElem.appendChild( div ).id = expando;\n
+\t\treturn !doc.getElementsByName || !doc.getElementsByName( expando ).length;\n
+\t});\n
+\n
+\t// ID find and filter\n
+\tif ( support.getById ) {\n
+\t\tExpr.find["ID"] = function( id, context ) {\n
+\t\t\tif ( typeof context.getElementById !== strundefined && documentIsHTML ) {\n
+\t\t\t\tvar m = context.getElementById( id );\n
+\t\t\t\t// Check parentNode to catch when Blackberry 4.6 returns\n
+\t\t\t\t// nodes that are no longer in the document #6963\n
+\t\t\t\treturn m && m.parentNode ? [m] : [];\n
+\t\t\t}\n
+\t\t};\n
+\t\tExpr.filter["ID"] = function( id ) {\n
+\t\t\tvar attrId = id.replace( runescape, funescape );\n
+\t\t\treturn function( elem ) {\n
+\t\t\t\treturn elem.getAttribute("id") === attrId;\n
+\t\t\t};\n
+\t\t};\n
+\t} else {\n
+\t\t// Support: IE6/7\n
+\t\t// getElementById is not reliable as a find shortcut\n
+\t\tdelete Expr.find["ID"];\n
+\n
+\t\tExpr.filter["ID"] =  function( id ) {\n
+\t\t\tvar attrId = id.replace( runescape, funescape );\n
+\t\t\treturn function( elem ) {\n
+\t\t\t\tvar node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id");\n
+\t\t\t\treturn node && node.value === attrId;\n
+\t\t\t};\n
+\t\t};\n
+\t}\n
+\n
+\t// Tag\n
+\tExpr.find["TAG"] = support.getElementsByTagName ?\n
+\t\tfunction( tag, context ) {\n
+\t\t\tif ( typeof context.getElementsByTagName !== strundefined ) {\n
+\t\t\t\treturn context.getElementsByTagName( tag );\n
+\t\t\t}\n
+\t\t} :\n
+\t\tfunction( tag, context ) {\n
+\t\t\tvar elem,\n
+\t\t\t\ttmp = [],\n
+\t\t\t\ti = 0,\n
+\t\t\t\tresults = context.getElementsByTagName( tag );\n
+\n
+\t\t\t// Filter out possible comments\n
+\t\t\tif ( tag === "*" ) {\n
+\t\t\t\twhile ( (elem = results[i++]) ) {\n
+\t\t\t\t\tif ( elem.nodeType === 1 ) {\n
+\t\t\t\t\t\ttmp.push( elem );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\treturn tmp;\n
+\t\t\t}\n
+\t\t\treturn results;\n
+\t\t};\n
+\n
+\t// Class\n
+\tExpr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {\n
+\t\tif ( typeof context.getElementsByClassName !== strundefined && documentIsHTML ) {\n
+\t\t\treturn context.getElementsByClassName( className );\n
+\t\t}\n
+\t};\n
+\n
+\t/* QSA/matchesSelector\n
+\t---------------------------------------------------------------------- */\n
+\n
+\t// QSA and matchesSelector support\n
+\n
+\t// matchesSelector(:active) reports false when true (IE9/Opera 11.5)\n
+\trbuggyMatches = [];\n
+\n
+\t// qSa(:focus) reports false when true (Chrome 21)\n
+\t// We allow this because of a bug in IE8/9 that throws an error\n
+\t// whenever `document.activeElement` is accessed on an iframe\n
+\t// So, we allow :focus to pass through QSA all the time to avoid the IE error\n
+\t// See http://bugs.jquery.com/ticket/13378\n
+\trbuggyQSA = [];\n
+\n
+\tif ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {\n
+\t\t// Build QSA regex\n
+\t\t// Regex strategy adopted from Diego Perini\n
+\t\tassert(function( div ) {\n
+\t\t\t// Select is set to empty string on purpose\n
+\t\t\t// This is to test IE\'s treatment of not explicitly\n
+\t\t\t// setting a boolean content attribute,\n
+\t\t\t// since its presence should be enough\n
+\t\t\t// http://bugs.jquery.com/ticket/12359\n
+\t\t\tdiv.innerHTML = "<select><option selected=\'\'></option></select>";\n
+\n
+\t\t\t// Support: IE8\n
+\t\t\t// Boolean attributes and "value" are not treated correctly\n
+\t\t\tif ( !div.querySelectorAll("[selected]").length ) {\n
+\t\t\t\trbuggyQSA.push( "\\\\[" + whitespace + "*(?:value|" + booleans + ")" );\n
+\t\t\t}\n
+\n
+\t\t\t// Webkit/Opera - :checked should return selected option elements\n
+\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n
+\t\t\t// IE8 throws error here and will not see later tests\n
+\t\t\tif ( !div.querySelectorAll(":checked").length ) {\n
+\t\t\t\trbuggyQSA.push(":checked");\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tassert(function( div ) {\n
+\n
+\t\t\t// Support: Opera 10-12/IE8\n
+\t\t\t// ^= $= *= and empty values\n
+\t\t\t// Should not select anything\n
+\t\t\t// Support: Windows 8 Native Apps\n
+\t\t\t// The type attribute is restricted during .innerHTML assignment\n
+\t\t\tvar input = doc.createElement("input");\n
+\t\t\tinput.setAttribute( "type", "hidden" );\n
+\t\t\tdiv.appendChild( input ).setAttribute( "t", "" );\n
+\n
+\t\t\tif ( div.querySelectorAll("[t^=\'\']").length ) {\n
+\t\t\t\trbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\'\'|\\"\\")" );\n
+\t\t\t}\n
+\n
+\t\t\t// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)\n
+\t\t\t// IE8 throws error here and will not see later tests\n
+\t\t\tif ( !div.querySelectorAll(":enabled").length ) {\n
+\t\t\t\trbuggyQSA.push( ":enabled", ":disabled" );\n
+\t\t\t}\n
+\n
+\t\t\t// Opera 10-11 does not throw on post-comma invalid pseudos\n
+\t\t\tdiv.querySelectorAll("*,:x");\n
+\t\t\trbuggyQSA.push(",.*:");\n
+\t\t});\n
+\t}\n
+\n
+\tif ( (support.matchesSelector = rnative.test( (matches = docElem.webkitMatchesSelector ||\n
+\t\tdocElem.mozMatchesSelector ||\n
+\t\tdocElem.oMatchesSelector ||\n
+\t\tdocElem.msMatchesSelector) )) ) {\n
+\n
+\t\tassert(function( div ) {\n
+\t\t\t// Check to see if it\'s possible to do matchesSelector\n
+\t\t\t// on a disconnected node (IE 9)\n
+\t\t\tsupport.disconnectedMatch = matches.call( div, "div" );\n
+\n
+\t\t\t// This should fail with an exception\n
+\t\t\t// Gecko does not error, returns false instead\n
+\t\t\tmatches.call( div, "[s!=\'\']:x" );\n
+\t\t\trbuggyMatches.push( "!=", pseudos );\n
+\t\t});\n
+\t}\n
+\n
+\trbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );\n
+\trbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );\n
+\n
+\t/* Contains\n
+\t---------------------------------------------------------------------- */\n
+\n
+\t// Element contains another\n
+\t// Purposefully does not implement inclusive descendent\n
+\t// As in, an element does not contain itself\n
+\tcontains = rnative.test( docElem.contains ) || docElem.compareDocumentPosition ?\n
+\t\tfunction( a, b ) {\n
+\t\t\tvar adown = a.nodeType === 9 ? a.documentElement : a,\n
+\t\t\t\tbup = b && b.parentNode;\n
+\t\t\treturn a === bup || !!( bup && bup.nodeType === 1 && (\n
+\t\t\t\tadown.contains ?\n
+\t\t\t\t\tadown.contains( bup ) :\n
+\t\t\t\t\ta.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16\n
+\t\t\t));\n
+\t\t} :\n
+\t\tfunction( a, b ) {\n
+\t\t\tif ( b ) {\n
+\t\t\t\twhile ( (b = b.parentNode) ) {\n
+\t\t\t\t\tif ( b === a ) {\n
+\t\t\t\t\t\treturn true;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\treturn false;\n
+\t\t};\n
+\n
+\t/* Sorting\n
+\t---------------------------------------------------------------------- */\n
+\n
+\t// Document order sorting\n
+\tsortOrder = docElem.compareDocumentPosition ?\n
+\tfunction( a, b ) {\n
+\n
+\t\t// Flag for duplicate removal\n
+\t\tif ( a === b ) {\n
+\t\t\thasDuplicate = true;\n
+\t\t\treturn 0;\n
+\t\t}\n
+\n
+\t\tvar compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b );\n
+\n
+\t\tif ( compare ) {\n
+\t\t\t// Disconnected nodes\n
+\t\t\tif ( compare & 1 ||\n
+\t\t\t\t(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {\n
+\n
+\t\t\t\t// Choose the first element that is related to our preferred document\n
+\t\t\t\tif ( a === doc || contains(preferredDoc, a) ) {\n
+\t\t\t\t\treturn -1;\n
+\t\t\t\t}\n
+\t\t\t\tif ( b === doc || contains(preferredDoc, b) ) {\n
+\t\t\t\t\treturn 1;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Maintain original order\n
+\t\t\t\treturn sortInput ?\n
+\t\t\t\t\t( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :\n
+\t\t\t\t\t0;\n
+\t\t\t}\n
+\n
+\t\t\treturn compare & 4 ? -1 : 1;\n
+\t\t}\n
+\n
+\t\t// Not directly comparable, sort on existence of method\n
+\t\treturn a.compareDocumentPosition ? -1 : 1;\n
+\t} :\n
+\tfunction( a, b ) {\n
+\t\tvar cur,\n
+\t\t\ti = 0,\n
+\t\t\taup = a.parentNode,\n
+\t\t\tbup = b.parentNode,\n
+\t\t\tap = [ a ],\n
+\t\t\tbp = [ b ];\n
+\n
+\t\t// Exit early if the nodes are identical\n
+\t\tif ( a === b ) {\n
+\t\t\thasDuplicate = true;\n
+\t\t\treturn 0;\n
+\n
+\t\t// Parentless nodes are either documents or disconnected\n
+\t\t} else if ( !aup || !bup ) {\n
+\t\t\treturn a === doc ? -1 :\n
+\t\t\t\tb === doc ? 1 :\n
+\t\t\t\taup ? -1 :\n
+\t\t\t\tbup ? 1 :\n
+\t\t\t\tsortInput ?\n
+\t\t\t\t( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) :\n
+\t\t\t\t0;\n
+\n
+\t\t// If the nodes are siblings, we can do a quick check\n
+\t\t} else if ( aup === bup ) {\n
+\t\t\treturn siblingCheck( a, b );\n
+\t\t}\n
+\n
+\t\t// Otherwise we need full lists of their ancestors for comparison\n
+\t\tcur = a;\n
+\t\twhile ( (cur = cur.parentNode) ) {\n
+\t\t\tap.unshift( cur );\n
+\t\t}\n
+\t\tcur = b;\n
+\t\twhile ( (cur = cur.parentNode) ) {\n
+\t\t\tbp.unshift( cur );\n
+\t\t}\n
+\n
+\t\t// Walk down the tree looking for a discrepancy\n
+\t\twhile ( ap[i] === bp[i] ) {\n
+\t\t\ti++;\n
+\t\t}\n
+\n
+\t\treturn i ?\n
+\t\t\t// Do a sibling check if the nodes have a common ancestor\n
+\t\t\tsiblingCheck( ap[i], bp[i] ) :\n
+\n
+\t\t\t// Otherwise nodes in our document sort first\n
+\t\t\tap[i] === preferredDoc ? -1 :\n
+\t\t\tbp[i] === preferredDoc ? 1 :\n
+\t\t\t0;\n
+\t};\n
+\n
+\treturn doc;\n
+};\n
+\n
+Sizzle.matches = function( expr, elements ) {\n
+\treturn Sizzle( expr, null, null, elements );\n
+};\n
+\n
+Sizzle.matchesSelector = function( elem, expr ) {\n
+\t// Set document vars if needed\n
+\tif ( ( elem.ownerDocument || elem ) !== document ) {\n
+\t\tsetDocument( elem );\n
+\t}\n
+\n
+\t// Make sure that attribute selectors are quoted\n
+\texpr = expr.replace( rattributeQuotes, "=\'$1\']" );\n
+\n
+\tif ( support.matchesSelector && documentIsHTML &&\n
+\t\t( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&\n
+\t\t( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {\n
+\n
+\t\ttry {\n
+\t\t\tvar ret = matches.call( elem, expr );\n
+\n
+\t\t\t// IE 9\'s matchesSelector returns false on disconnected nodes\n
+\t\t\tif ( ret || support.disconnectedMatch ||\n
+\t\t\t\t\t// As well, disconnected nodes are said to be in a document\n
+\t\t\t\t\t// fragment in IE 9\n
+\t\t\t\t\telem.document && elem.document.nodeType !== 11 ) {\n
+\t\t\t\treturn ret;\n
+\t\t\t}\n
+\t\t} catch(e) {}\n
+\t}\n
+\n
+\treturn Sizzle( expr, document, null, [elem] ).length > 0;\n
+};\n
+\n
+Sizzle.contains = function( context, elem ) {\n
+\t// Set document vars if needed\n
+\tif ( ( context.ownerDocument || context ) !== document ) {\n
+\t\tsetDocument( context );\n
+\t}\n
+\treturn contains( context, elem );\n
+};\n
+\n
+Sizzle.attr = function( elem, name ) {\n
+\t// Set document vars if needed\n
+\tif ( ( elem.ownerDocument || elem ) !== document ) {\n
+\t\tsetDocument( elem );\n
+\t}\n
+\n
+\tvar fn = Expr.attrHandle[ name.toLowerCase() ],\n
+\t\t// Don\'t get fooled by Object.prototype properties (jQuery #13807)\n
+\t\tval = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?\n
+\t\t\tfn( elem, name, !documentIsHTML ) :\n
+\t\t\tundefined;\n
+\n
+\treturn val === undefined ?\n
+\t\tsupport.attributes || !documentIsHTML ?\n
+\t\t\telem.getAttribute( name ) :\n
+\t\t\t(val = elem.getAttributeNode(name)) && val.specified ?\n
+\t\t\t\tval.value :\n
+\t\t\t\tnull :\n
+\t\tval;\n
+};\n
+\n
+Sizzle.error = function( msg ) {\n
+\tthrow new Error( "Syntax error, unrecognized expression: " + msg );\n
+};\n
+\n
+/**\n
+ * Document sorting and removing duplicates\n
+ * @param {ArrayLike} results\n
+ */\n
+Sizzle.uniqueSort = function( results ) {\n
+\tvar elem,\n
+\t\tduplicates = [],\n
+\t\tj = 0,\n
+\t\ti = 0;\n
+\n
+\t// Unless we *know* we can detect duplicates, assume their presence\n
+\thasDuplicate = !support.detectDuplicates;\n
+\tsortInput = !support.sortStable && results.slice( 0 );\n
+\tresults.sort( sortOrder );\n
+\n
+\tif ( hasDuplicate ) {\n
+\t\twhile ( (elem = results[i++]) ) {\n
+\t\t\tif ( elem === results[ i ] ) {\n
+\t\t\t\tj = duplicates.push( i );\n
+\t\t\t}\n
+\t\t}\n
+\t\twhile ( j-- ) {\n
+\t\t\tresults.splice( duplicates[ j ], 1 );\n
+\t\t}\n
+\t}\n
+\n
+\treturn results;\n
+};\n
+\n
+/**\n
+ * Utility function for retrieving the text value of an array of DOM nodes\n
+ * @param {Array|Element} elem\n
+ */\n
+getText = Sizzle.getText = function( elem ) {\n
+\tvar node,\n
+\t\tret = "",\n
+\t\ti = 0,\n
+\t\tnodeType = elem.nodeType;\n
+\n
+\tif ( !nodeType ) {\n
+\t\t// If no nodeType, this is expected to be an array\n
+\t\tfor ( ; (node = elem[i]); i++ ) {\n
+\t\t\t// Do not traverse comment nodes\n
+\t\t\tret += getText( node );\n
+\t\t}\n
+\t} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {\n
+\t\t// Use textContent for elements\n
+\t\t// innerText usage removed for consistency of new lines (see #11153)\n
+\t\tif ( typeof elem.textContent === "string" ) {\n
+\t\t\treturn elem.textContent;\n
+\t\t} else {\n
+\t\t\t// Traverse its children\n
+\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n
+\t\t\t\tret += getText( elem );\n
+\t\t\t}\n
+\t\t}\n
+\t} else if ( nodeType === 3 || nodeType === 4 ) {\n
+\t\treturn elem.nodeValue;\n
+\t}\n
+\t// Do not include comment or processing instruction nodes\n
+\n
+\treturn ret;\n
+};\n
+\n
+Expr = Sizzle.selectors = {\n
+\n
+\t// Can be adjusted by the user\n
+\tcacheLength: 50,\n
+\n
+\tcreatePseudo: markFunction,\n
+\n
+\tmatch: matchExpr,\n
+\n
+\tattrHandle: {},\n
+\n
+\tfind: {},\n
+\n
+\trelative: {\n
+\t\t">": { dir: "parentNode", first: true },\n
+\t\t" ": { dir: "parentNode" },\n
+\t\t"+": { dir: "previousSibling", first: true },\n
+\t\t"~": { dir: "previousSibling" }\n
+\t},\n
+\n
+\tpreFilter: {\n
+\t\t"ATTR": function( match ) {\n
+\t\t\tmatch[1] = match[1].replace( runescape, funescape );\n
+\n
+\t\t\t// Move the given value to match[3] whether quoted or unquoted\n
+\t\t\tmatch[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape );\n
+\n
+\t\t\tif ( match[2] === "~=" ) {\n
+\t\t\t\tmatch[3] = " " + match[3] + " ";\n
+\t\t\t}\n
+\n
+\t\t\treturn match.slice( 0, 4 );\n
+\t\t},\n
+\n
+\t\t"CHILD": function( match ) {\n
+\t\t\t/* matches from matchExpr["CHILD"]\n
+\t\t\t\t1 type (only|nth|...)\n
+\t\t\t\t2 what (child|of-type)\n
+\t\t\t\t3 argument (even|odd|\\d*|\\d*n([+-]\\d+)?|...)\n
+\t\t\t\t4 xn-component of xn+y argument ([+-]?\\d*n|)\n
+\t\t\t\t5 sign of xn-component\n
+\t\t\t\t6 x of xn-component\n
+\t\t\t\t7 sign of y-component\n
+\t\t\t\t8 y of y-component\n
+\t\t\t*/\n
+\t\t\tmatch[1] = match[1].toLowerCase();\n
+\n
+\t\t\tif ( match[1].slice( 0, 3 ) === "nth" ) {\n
+\t\t\t\t// nth-* requires argument\n
+\t\t\t\tif ( !match[3] ) {\n
+\t\t\t\t\tSizzle.error( match[0] );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// numeric x and y parameters for Expr.filter.CHILD\n
+\t\t\t\t// remember that false/true cast respectively to 0/1\n
+\t\t\t\tmatch[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );\n
+\t\t\t\tmatch[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );\n
+\n
+\t\t\t// other types prohibit arguments\n
+\t\t\t} else if ( match[3] ) {\n
+\t\t\t\tSizzle.error( match[0] );\n
+\t\t\t}\n
+\n
+\t\t\treturn match;\n
+\t\t},\n
+\n
+\t\t"PSEUDO": function( match ) {\n
+\t\t\tvar excess,\n
+\t\t\t\tunquoted = !match[5] && match[2];\n
+\n
+\t\t\tif ( matchExpr["CHILD"].test( match[0] ) ) {\n
+\t\t\t\treturn null;\n
+\t\t\t}\n
+\n
+\t\t\t// Accept quoted arguments as-is\n
+\t\t\tif ( match[3] && match[4] !== undefined ) {\n
+\t\t\t\tmatch[2] = match[4];\n
+\n
+\t\t\t// Strip excess characters from unquoted arguments\n
+\t\t\t} else if ( unquoted && rpseudo.test( unquoted ) &&\n
+\t\t\t\t// Get excess from tokenize (recursively)\n
+\t\t\t\t(excess = tokenize( unquoted, true )) &&\n
+\t\t\t\t// advance to the next closing parenthesis\n
+\t\t\t\t(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {\n
+\n
+\t\t\t\t// excess is a negative index\n
+\t\t\t\tmatch[0] = match[0].slice( 0, excess );\n
+\t\t\t\tmatch[2] = unquoted.slice( 0, excess );\n
+\t\t\t}\n
+\n
+\t\t\t// Return only captures needed by the pseudo filter method (type and argument)\n
+\t\t\treturn match.slice( 0, 3 );\n
+\t\t}\n
+\t},\n
+\n
+\tfilter: {\n
+\n
+\t\t"TAG": function( nodeNameSelector ) {\n
+\t\t\tvar nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();\n
+\t\t\treturn nodeNameSelector === "*" ?\n
+\t\t\t\tfunction() { return true; } :\n
+\t\t\t\tfunction( elem ) {\n
+\t\t\t\t\treturn elem.nodeName && elem.nodeName.toLowerCase() === nodeName;\n
+\t\t\t\t};\n
+\t\t},\n
+\n
+\t\t"CLASS": function( className ) {\n
+\t\t\tvar pattern = classCache[ className + " " ];\n
+\n
+\t\t\treturn pattern ||\n
+\t\t\t\t(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&\n
+\t\t\t\tclassCache( className, function( elem ) {\n
+\t\t\t\t\treturn pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== strundefined && elem.getAttribute("class") || "" );\n
+\t\t\t\t});\n
+\t\t},\n
+\n
+\t\t"ATTR": function( name, operator, check ) {\n
+\t\t\treturn function( elem ) {\n
+\t\t\t\tvar result = Sizzle.attr( elem, name );\n
+\n
+\t\t\t\tif ( result == null ) {\n
+\t\t\t\t\treturn operator === "!=";\n
+\t\t\t\t}\n
+\t\t\t\tif ( !operator ) {\n
+\t\t\t\t\treturn true;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tresult += "";\n
+\n
+\t\t\t\treturn operator === "=" ? result === check :\n
+\t\t\t\t\toperator === "!=" ? result !== check :\n
+\t\t\t\t\toperator === "^=" ? check && result.indexOf( check ) === 0 :\n
+\t\t\t\t\toperator === "*=" ? check && result.indexOf( check ) > -1 :\n
+\t\t\t\t\toperator === "$=" ? check && result.slice( -check.length ) === check :\n
+\t\t\t\t\toperator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 :\n
+\t\t\t\t\toperator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :\n
+\t\t\t\t\tfalse;\n
+\t\t\t};\n
+\t\t},\n
+\n
+\t\t"CHILD": function( type, what, argument, first, last ) {\n
+\t\t\tvar simple = type.slice( 0, 3 ) !== "nth",\n
+\t\t\t\tforward = type.slice( -4 ) !== "last",\n
+\t\t\t\tofType = what === "of-type";\n
+\n
+\t\t\treturn first === 1 && last === 0 ?\n
+\n
+\t\t\t\t// Shortcut for :nth-*(n)\n
+\t\t\t\tfunction( elem ) {\n
+\t\t\t\t\treturn !!elem.parentNode;\n
+\t\t\t\t} :\n
+\n
+\t\t\t\tfunction( elem, context, xml ) {\n
+\t\t\t\t\tvar cache, outerCache, node, diff, nodeIndex, start,\n
+\t\t\t\t\t\tdir = simple !== forward ? "nextSibling" : "previousSibling",\n
+\t\t\t\t\t\tparent = elem.parentNode,\n
+\t\t\t\t\t\tname = ofType && elem.nodeName.toLowerCase(),\n
+\t\t\t\t\t\tuseCache = !xml && !ofType;\n
+\n
+\t\t\t\t\tif ( parent ) {\n
+\n
+\t\t\t\t\t\t// :(first|last|only)-(child|of-type)\n
+\t\t\t\t\t\tif ( simple ) {\n
+\t\t\t\t\t\t\twhile ( dir ) {\n
+\t\t\t\t\t\t\t\tnode = elem;\n
+\t\t\t\t\t\t\t\twhile ( (node = node[ dir ]) ) {\n
+\t\t\t\t\t\t\t\t\tif ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {\n
+\t\t\t\t\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\t// Reverse direction for :only-* (if we haven\'t yet done so)\n
+\t\t\t\t\t\t\t\tstart = dir = type === "only" && !start && "nextSibling";\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\treturn true;\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\tstart = [ forward ? parent.firstChild : parent.lastChild ];\n
+\n
+\t\t\t\t\t\t// non-xml :nth-child(...) stores cache data on `parent`\n
+\t\t\t\t\t\tif ( forward && useCache ) {\n
+\t\t\t\t\t\t\t// Seek `elem` from a previously-cached index\n
+\t\t\t\t\t\t\touterCache = parent[ expando ] || (parent[ expando ] = {});\n
+\t\t\t\t\t\t\tcache = outerCache[ type ] || [];\n
+\t\t\t\t\t\t\tnodeIndex = cache[0] === dirruns && cache[1];\n
+\t\t\t\t\t\t\tdiff = cache[0] === dirruns && cache[2];\n
+\t\t\t\t\t\t\tnode = nodeIndex && parent.childNodes[ nodeIndex ];\n
+\n
+\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n
+\n
+\t\t\t\t\t\t\t\t// Fallback to seeking `elem` from the start\n
+\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n
+\n
+\t\t\t\t\t\t\t\t// When found, cache indexes on `parent` and break\n
+\t\t\t\t\t\t\t\tif ( node.nodeType === 1 && ++diff && node === elem ) {\n
+\t\t\t\t\t\t\t\t\touterCache[ type ] = [ dirruns, nodeIndex, diff ];\n
+\t\t\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\t// Use previously-cached element index if available\n
+\t\t\t\t\t\t} else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {\n
+\t\t\t\t\t\t\tdiff = cache[1];\n
+\n
+\t\t\t\t\t\t// xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)\n
+\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t// Use the same loop as above to seek `elem` from the start\n
+\t\t\t\t\t\t\twhile ( (node = ++nodeIndex && node && node[ dir ] ||\n
+\t\t\t\t\t\t\t\t(diff = nodeIndex = 0) || start.pop()) ) {\n
+\n
+\t\t\t\t\t\t\t\tif ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {\n
+\t\t\t\t\t\t\t\t\t// Cache the index of each encountered element\n
+\t\t\t\t\t\t\t\t\tif ( useCache ) {\n
+\t\t\t\t\t\t\t\t\t\t(node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];\n
+\t\t\t\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\t\t\t\tif ( node === elem ) {\n
+\t\t\t\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\t// Incorporate the offset, then check against cycle size\n
+\t\t\t\t\t\tdiff -= last;\n
+\t\t\t\t\t\treturn diff === first || ( diff % first === 0 && diff / first >= 0 );\n
+\t\t\t\t\t}\n
+\t\t\t\t};\n
+\t\t},\n
+\n
+\t\t"PSEUDO": function( pseudo, argument ) {\n
+\t\t\t// pseudo-class names are case-insensitive\n
+\t\t\t// http://www.w3.org/TR/selectors/#pseudo-classes\n
+\t\t\t// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters\n
+\t\t\t// Remember that setFilters inherits from pseudos\n
+\t\t\tvar args,\n
+\t\t\t\tfn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||\n
+\t\t\t\t\tSizzle.error( "unsupported pseudo: " + pseudo );\n
+\n
+\t\t\t// The user may use createPseudo to indicate that\n
+\t\t\t// arguments are needed to create the filter function\n
+\t\t\t// just as Sizzle does\n
+\t\t\tif ( fn[ expando ] ) {\n
+\t\t\t\treturn fn( argument );\n
+\t\t\t}\n
+\n
+\t\t\t// But maintain support for old signatures\n
+\t\t\tif ( fn.length > 1 ) {\n
+\t\t\t\targs = [ pseudo, pseudo, "", argument ];\n
+\t\t\t\treturn Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?\n
+\t\t\t\t\tmarkFunction(function( seed, matches ) {\n
+\t\t\t\t\t\tvar idx,\n
+\t\t\t\t\t\t\tmatched = fn( seed, argument ),\n
+\t\t\t\t\t\t\ti = matched.length;\n
+\t\t\t\t\t\twhile ( i-- ) {\n
+\t\t\t\t\t\t\tidx = indexOf.call( seed, matched[i] );\n
+\t\t\t\t\t\t\tseed[ idx ] = !( matches[ idx ] = matched[i] );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}) :\n
+\t\t\t\t\tfunction( elem ) {\n
+\t\t\t\t\t\treturn fn( elem, 0, args );\n
+\t\t\t\t\t};\n
+\t\t\t}\n
+\n
+\t\t\treturn fn;\n
+\t\t}\n
+\t},\n
+\n
+\tpseudos: {\n
+\t\t// Potentially complex pseudos\n
+\t\t"not": markFunction(function( selector ) {\n
+\t\t\t// Trim the selector passed to compile\n
+\t\t\t// to avoid treating leading and trailing\n
+\t\t\t// spaces as combinators\n
+\t\t\tvar input = [],\n
+\t\t\t\tresults = [],\n
+\t\t\t\tmatcher = compile( selector.replace( rtrim, "$1" ) );\n
+\n
+\t\t\treturn matcher[ expando ] ?\n
+\t\t\t\tmarkFunction(function( seed, matches, context, xml ) {\n
+\t\t\t\t\tvar elem,\n
+\t\t\t\t\t\tunmatched = matcher( seed, null, xml, [] ),\n
+\t\t\t\t\t\ti = seed.length;\n
+\n
+\t\t\t\t\t// Match elements unmatched by `matcher`\n
+\t\t\t\t\twhile ( i-- ) {\n
+\t\t\t\t\t\tif ( (elem = unmatched[i]) ) {\n
+\t\t\t\t\t\t\tseed[i] = !(matches[i] = elem);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}) :\n
+\t\t\t\tfunction( elem, context, xml ) {\n
+\t\t\t\t\tinput[0] = elem;\n
+\t\t\t\t\tmatcher( input, null, xml, results );\n
+\t\t\t\t\treturn !results.pop();\n
+\t\t\t\t};\n
+\t\t}),\n
+\n
+\t\t"has": markFunction(function( selector ) {\n
+\t\t\treturn function( elem ) {\n
+\t\t\t\treturn Sizzle( selector, elem ).length > 0;\n
+\t\t\t};\n
+\t\t}),\n
+\n
+\t\t"contains": markFunction(function( text ) {\n
+\t\t\treturn function( elem ) {\n
+\t\t\t\treturn ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;\n
+\t\t\t};\n
+\t\t}),\n
+\n
+\t\t// "Whether an element is represented by a :lang() selector\n
+\t\t// is based solely on the element\'s language value\n
+\t\t// being equal to the identifier C,\n
+\t\t// or beginning with the identifier C immediately followed by "-".\n
+\t\t// The matching of C against the element\'s language value is performed case-insensitively.\n
+\t\t// The identifier C does not have to be a valid language name."\n
+\t\t// http://www.w3.org/TR/selectors/#lang-pseudo\n
+\t\t"lang": markFunction( function( lang ) {\n
+\t\t\t// lang value must be a valid identifier\n
+\t\t\tif ( !ridentifier.test(lang || "") ) {\n
+\t\t\t\tSizzle.error( "unsupported lang: " + lang );\n
+\t\t\t}\n
+\t\t\tlang = lang.replace( runescape, funescape ).toLowerCase();\n
+\t\t\treturn function( elem ) {\n
+\t\t\t\tvar elemLang;\n
+\t\t\t\tdo {\n
+\t\t\t\t\tif ( (elemLang = documentIsHTML ?\n
+\t\t\t\t\t\telem.lang :\n
+\t\t\t\t\t\telem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {\n
+\n
+\t\t\t\t\t\telemLang = elemLang.toLowerCase();\n
+\t\t\t\t\t\treturn elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;\n
+\t\t\t\t\t}\n
+\t\t\t\t} while ( (elem = elem.parentNode) && elem.nodeType === 1 );\n
+\t\t\t\treturn false;\n
+\t\t\t};\n
+\t\t}),\n
+\n
+\t\t// Miscellaneous\n
+\t\t"target": function( elem ) {\n
+\t\t\tvar hash = window.location && window.location.hash;\n
+\t\t\treturn hash && hash.slice( 1 ) === elem.id;\n
+\t\t},\n
+\n
+\t\t"root": function( elem ) {\n
+\t\t\treturn elem === docElem;\n
+\t\t},\n
+\n
+\t\t"focus": function( elem ) {\n
+\t\t\treturn elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);\n
+\t\t},\n
+\n
+\t\t// Boolean properties\n
+\t\t"enabled": function( elem ) {\n
+\t\t\treturn elem.disabled === false;\n
+\t\t},\n
+\n
+\t\t"disabled": function( elem ) {\n
+\t\t\treturn elem.disabled === true;\n
+\t\t},\n
+\n
+\t\t"checked": function( elem ) {\n
+\t\t\t// In CSS3, :checked should return both checked and selected elements\n
+\t\t\t// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked\n
+\t\t\tvar nodeName = elem.nodeName.toLowerCase();\n
+\t\t\treturn (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);\n
+\t\t},\n
+\n
+\t\t"selected": function( elem ) {\n
+\t\t\t// Accessing this property makes selected-by-default\n
+\t\t\t// options in Safari work properly\n
+\t\t\tif ( elem.parentNode ) {\n
+\t\t\t\telem.parentNode.selectedIndex;\n
+\t\t\t}\n
+\n
+\t\t\treturn elem.selected === true;\n
+\t\t},\n
+\n
+\t\t// Contents\n
+\t\t"empty": function( elem ) {\n
+\t\t\t// http://www.w3.org/TR/selectors/#empty-pseudo\n
+\t\t\t// :empty is only affected by element nodes and content nodes(including text(3), cdata(4)),\n
+\t\t\t//   not comment, processing instructions, or others\n
+\t\t\t// Thanks to Diego Perini for the nodeName shortcut\n
+\t\t\t//   Greater than "@" means alpha characters (specifically not starting with "#" or "?")\n
+\t\t\tfor ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {\n
+\t\t\t\tif ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) {\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\treturn true;\n
+\t\t},\n
+\n
+\t\t"parent": function( elem ) {\n
+\t\t\treturn !Expr.pseudos["empty"]( elem );\n
+\t\t},\n
+\n
+\t\t// Element/input types\n
+\t\t"header": function( elem ) {\n
+\t\t\treturn rheader.test( elem.nodeName );\n
+\t\t},\n
+\n
+\t\t"input": function( elem ) {\n
+\t\t\treturn rinputs.test( elem.nodeName );\n
+\t\t},\n
+\n
+\t\t"button": function( elem ) {\n
+\t\t\tvar name = elem.nodeName.toLowerCase();\n
+\t\t\treturn name === "input" && elem.type === "button" || name === "button";\n
+\t\t},\n
+\n
+\t\t"text": function( elem ) {\n
+\t\t\tvar attr;\n
+\t\t\t// IE6 and 7 will map elem.type to \'text\' for new HTML5 types (search, etc)\n
+\t\t\t// use getAttribute instead to test this case\n
+\t\t\treturn elem.nodeName.toLowerCase() === "input" &&\n
+\t\t\t\telem.type === "text" &&\n
+\t\t\t\t( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type );\n
+\t\t},\n
+\n
+\t\t// Position-in-collection\n
+\t\t"first": createPositionalPseudo(function() {\n
+\t\t\treturn [ 0 ];\n
+\t\t}),\n
+\n
+\t\t"last": createPositionalPseudo(function( matchIndexes, length ) {\n
+\t\t\treturn [ length - 1 ];\n
+\t\t}),\n
+\n
+\t\t"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {\n
+\t\t\treturn [ argument < 0 ? argument + length : argument ];\n
+\t\t}),\n
+\n
+\t\t"even": createPositionalPseudo(function( matchIndexes, length ) {\n
+\t\t\tvar i = 0;\n
+\t\t\tfor ( ; i < length; i += 2 ) {\n
+\t\t\t\tmatchIndexes.push( i );\n
+\t\t\t}\n
+\t\t\treturn matchIndexes;\n
+\t\t}),\n
+\n
+\t\t"odd": createPositionalPseudo(function( matchIndexes, length ) {\n
+\t\t\tvar i = 1;\n
+\t\t\tfor ( ; i < length; i += 2 ) {\n
+\t\t\t\tmatchIndexes.push( i );\n
+\t\t\t}\n
+\t\t\treturn matchIndexes;\n
+\t\t}),\n
+\n
+\t\t"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {\n
+\t\t\tvar i = argument < 0 ? argument + length : argument;\n
+\t\t\tfor ( ; --i >= 0; ) {\n
+\t\t\t\tmatchIndexes.push( i );\n
+\t\t\t}\n
+\t\t\treturn matchIndexes;\n
+\t\t}),\n
+\n
+\t\t"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {\n
+\t\t\tvar i = argument < 0 ? argument + length : argument;\n
+\t\t\tfor ( ; ++i < length; ) {\n
+\t\t\t\tmatchIndexes.push( i );\n
+\t\t\t}\n
+\t\t\treturn matchIndexes;\n
+\t\t})\n
+\t}\n
+};\n
+\n
+Expr.pseudos["nth"] = Expr.pseudos["eq"];\n
+\n
+// Add button/input type pseudos\n
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {\n
+\tExpr.pseudos[ i ] = createInputPseudo( i );\n
+}\n
+for ( i in { submit: true, reset: true } ) {\n
+\tExpr.pseudos[ i ] = createButtonPseudo( i );\n
+}\n
+\n
+// Easy API for creating new setFilters\n
+function setFilters() {}\n
+setFilters.prototype = Expr.filters = Expr.pseudos;\n
+Expr.setFilters = new setFilters();\n
+\n
+function tokenize( selector, parseOnly ) {\n
+\tvar matched, match, tokens, type,\n
+\t\tsoFar, groups, preFilters,\n
+\t\tcached = tokenCache[ selector + " " ];\n
+\n
+\tif ( cached ) {\n
+\t\treturn parseOnly ? 0 : cached.slice( 0 );\n
+\t}\n
+\n
+\tsoFar = selector;\n
+\tgroups = [];\n
+\tpreFilters = Expr.preFilter;\n
+\n
+\twhile ( soFar ) {\n
+\n
+\t\t// Comma and first run\n
+\t\tif ( !matched || (match = rcomma.exec( soFar )) ) {\n
+\t\t\tif ( match ) {\n
+\t\t\t\t// Don\'t consume trailing commas as valid\n
+\t\t\t\tsoFar = soFar.slice( match[0].length ) || soFar;\n
+\t\t\t}\n
+\t\t\tgroups.push( tokens = [] );\n
+\t\t}\n
+\n
+\t\tmatched = false;\n
+\n
+\t\t// Combinators\n
+\t\tif ( (match = rcombinators.exec( soFar )) ) {\n
+\t\t\tmatched = match.shift();\n
+\t\t\ttokens.push({\n
+\t\t\t\tvalue: matched,\n
+\t\t\t\t// Cast descendant combinators to space\n
+\t\t\t\ttype: match[0].replace( rtrim, " " )\n
+\t\t\t});\n
+\t\t\tsoFar = soFar.slice( matched.length );\n
+\t\t}\n
+\n
+\t\t// Filters\n
+\t\tfor ( type in Expr.filter ) {\n
+\t\t\tif ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||\n
+\t\t\t\t(match = preFilters[ type ]( match ))) ) {\n
+\t\t\t\tmatched = match.shift();\n
+\t\t\t\ttokens.push({\n
+\t\t\t\t\tvalue: matched,\n
+\t\t\t\t\ttype: type,\n
+\t\t\t\t\tmatches: match\n
+\t\t\t\t});\n
+\t\t\t\tsoFar = soFar.slice( matched.length );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( !matched ) {\n
+\t\t\tbreak;\n
+\t\t}\n
+\t}\n
+\n
+\t// Return the length of the invalid excess\n
+\t// if we\'re just parsing\n
+\t// Otherwise, throw an error or return tokens\n
+\treturn parseOnly ?\n
+\t\tsoFar.length :\n
+\t\tsoFar ?\n
+\t\t\tSizzle.error( selector ) :\n
+\t\t\t// Cache the tokens\n
+\t\t\ttokenCache( selector, groups ).slice( 0 );\n
+}\n
+\n
+function toSelector( tokens ) {\n
+\tvar i = 0,\n
+\t\tlen = tokens.length,\n
+\t\tselector = "";\n
+\tfor ( ; i < len; i++ ) {\n
+\t\tselector += tokens[i].value;\n
+\t}\n
+\treturn selector;\n
+}\n
+\n
+function addCombinator( matcher, combinator, base ) {\n
+\tvar dir = combinator.dir,\n
+\t\tcheckNonElements = base && dir === "parentNode",\n
+\t\tdoneName = done++;\n
+\n
+\treturn combinator.first ?\n
+\t\t// Check against closest ancestor/preceding element\n
+\t\tfunction( elem, context, xml ) {\n
+\t\t\twhile ( (elem = elem[ dir ]) ) {\n
+\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n
+\t\t\t\t\treturn matcher( elem, context, xml );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t} :\n
+\n
+\t\t// Check against all ancestor/preceding elements\n
+\t\tfunction( elem, context, xml ) {\n
+\t\t\tvar data, cache, outerCache,\n
+\t\t\t\tdirkey = dirruns + " " + doneName;\n
+\n
+\t\t\t// We can\'t set arbitrary data on XML nodes, so they don\'t benefit from dir caching\n
+\t\t\tif ( xml ) {\n
+\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n
+\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n
+\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n
+\t\t\t\t\t\t\treturn true;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\twhile ( (elem = elem[ dir ]) ) {\n
+\t\t\t\t\tif ( elem.nodeType === 1 || checkNonElements ) {\n
+\t\t\t\t\t\touterCache = elem[ expando ] || (elem[ expando ] = {});\n
+\t\t\t\t\t\tif ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) {\n
+\t\t\t\t\t\t\tif ( (data = cache[1]) === true || data === cachedruns ) {\n
+\t\t\t\t\t\t\t\treturn data === true;\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\tcache = outerCache[ dir ] = [ dirkey ];\n
+\t\t\t\t\t\t\tcache[1] = matcher( elem, context, xml ) || cachedruns;\n
+\t\t\t\t\t\t\tif ( cache[1] === true ) {\n
+\t\t\t\t\t\t\t\treturn true;\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t};\n
+}\n
+\n
+function elementMatcher( matchers ) {\n
+\treturn matchers.length > 1 ?\n
+\t\tfunction( elem, context, xml ) {\n
+\t\t\tvar i = matchers.length;\n
+\t\t\twhile ( i-- ) {\n
+\t\t\t\tif ( !matchers[i]( elem, context, xml ) ) {\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\treturn true;\n
+\t\t} :\n
+\t\tmatchers[0];\n
+}\n
+\n
+function condense( unmatched, map, filter, context, xml ) {\n
+\tvar elem,\n
+\t\tnewUnmatched = [],\n
+\t\ti = 0,\n
+\t\tlen = unmatched.length,\n
+\t\tmapped = map != null;\n
+\n
+\tfor ( ; i < len; i++ ) {\n
+\t\tif ( (elem = unmatched[i]) ) {\n
+\t\t\tif ( !filter || filter( elem, context, xml ) ) {\n
+\t\t\t\tnewUnmatched.push( elem );\n
+\t\t\t\tif ( mapped ) {\n
+\t\t\t\t\tmap.push( i );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\treturn newUnmatched;\n
+}\n
+\n
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {\n
+\tif ( postFilter && !postFilter[ expando ] ) {\n
+\t\tpostFilter = setMatcher( postFilter );\n
+\t}\n
+\tif ( postFinder && !postFinder[ expando ] ) {\n
+\t\tpostFinder = setMatcher( postFinder, postSelector );\n
+\t}\n
+\treturn markFunction(function( seed, results, context, xml ) {\n
+\t\tvar temp, i, elem,\n
+\t\t\tpreMap = [],\n
+\t\t\tpostMap = [],\n
+\t\t\tpreexisting = results.length,\n
+\n
+\t\t\t// Get initial elements from seed or context\n
+\t\t\telems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),\n
+\n
+\t\t\t// Prefilter to get matcher input, preserving a map for seed-results synchronization\n
+\t\t\tmatcherIn = preFilter && ( seed || !selector ) ?\n
+\t\t\t\tcondense( elems, preMap, preFilter, context, xml ) :\n
+\t\t\t\telems,\n
+\n
+\t\t\tmatcherOut = matcher ?\n
+\t\t\t\t// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,\n
+\t\t\t\tpostFinder || ( seed ? preFilter : preexisting || postFilter ) ?\n
+\n
+\t\t\t\t\t// ...intermediate processing is necessary\n
+\t\t\t\t\t[] :\n
+\n
+\t\t\t\t\t// ...otherwise use results directly\n
+\t\t\t\t\tresults :\n
+\t\t\t\tmatcherIn;\n
+\n
+\t\t// Find primary matches\n
+\t\tif ( matcher ) {\n
+\t\t\tmatcher( matcherIn, matcherOut, context, xml );\n
+\t\t}\n
+\n
+\t\t// Apply postFilter\n
+\t\tif ( postFilter ) {\n
+\t\t\ttemp = condense( matcherOut, postMap );\n
+\t\t\tpostFilter( temp, [], context, xml );\n
+\n
+\t\t\t// Un-match failing elements by moving them back to matcherIn\n
+\t\t\ti = temp.length;\n
+\t\t\twhile ( i-- ) {\n
+\t\t\t\tif ( (elem = temp[i]) ) {\n
+\t\t\t\t\tmatcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( seed ) {\n
+\t\t\tif ( postFinder || preFilter ) {\n
+\t\t\t\tif ( postFinder ) {\n
+\t\t\t\t\t// Get the final matcherOut by condensing this intermediate into postFinder contexts\n
+\t\t\t\t\ttemp = [];\n
+\t\t\t\t\ti = matcherOut.length;\n
+\t\t\t\t\twhile ( i-- ) {\n
+\t\t\t\t\t\tif ( (elem = matcherOut[i]) ) {\n
+\t\t\t\t\t\t\t// Restore matcherIn since elem is not yet a final match\n
+\t\t\t\t\t\t\ttemp.push( (matcherIn[i] = elem) );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\tpostFinder( null, (matcherOut = []), temp, xml );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Move matched elements from seed to results to keep them synchronized\n
+\t\t\t\ti = matcherOut.length;\n
+\t\t\t\twhile ( i-- ) {\n
+\t\t\t\t\tif ( (elem = matcherOut[i]) &&\n
+\t\t\t\t\t\t(temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > -1 ) {\n
+\n
+\t\t\t\t\t\tseed[temp] = !(results[temp] = elem);\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t// Add elements to results, through postFinder if defined\n
+\t\t} else {\n
+\t\t\tmatcherOut = condense(\n
+\t\t\t\tmatcherOut === results ?\n
+\t\t\t\t\tmatcherOut.splice( preexisting, matcherOut.length ) :\n
+\t\t\t\t\tmatcherOut\n
+\t\t\t);\n
+\t\t\tif ( postFinder ) {\n
+\t\t\t\tpostFinder( null, results, matcherOut, xml );\n
+\t\t\t} else {\n
+\t\t\t\tpush.apply( results, matcherOut );\n
+\t\t\t}\n
+\t\t}\n
+\t});\n
+}\n
+\n
+function matcherFromTokens( tokens ) {\n
+\tvar checkContext, matcher, j,\n
+\t\tlen = tokens.length,\n
+\t\tleadingRelative = Expr.relative[ tokens[0].type ],\n
+\t\timplicitRelative = leadingRelative || Expr.relative[" "],\n
+\t\ti = leadingRelative ? 1 : 0,\n
+\n
+\t\t// The foundational matcher ensures that elements are reachable from top-level context(s)\n
+\t\tmatchContext = addCombinator( function( elem ) {\n
+\t\t\treturn elem === checkContext;\n
+\t\t}, implicitRelative, true ),\n
+\t\tmatchAnyContext = addCombinator( function( elem ) {\n
+\t\t\treturn indexOf.call( checkContext, elem ) > -1;\n
+\t\t}, implicitRelative, true ),\n
+\t\tmatchers = [ function( elem, context, xml ) {\n
+\t\t\treturn ( !leadingRelative && ( xml || context !== outermostContext ) ) || (\n
+\t\t\t\t(checkContext = context).nodeType ?\n
+\t\t\t\t\tmatchContext( elem, context, xml ) :\n
+\t\t\t\t\tmatchAnyContext( elem, context, xml ) );\n
+\t\t} ];\n
+\n
+\tfor ( ; i < len; i++ ) {\n
+\t\tif ( (matcher = Expr.relative[ tokens[i].type ]) ) {\n
+\t\t\tmatchers = [ addCombinator(elementMatcher( matchers ), matcher) ];\n
+\t\t} else {\n
+\t\t\tmatcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );\n
+\n
+\t\t\t// Return special upon seeing a positional matcher\n
+\t\t\tif ( matcher[ expando ] ) {\n
+\t\t\t\t// Find the next relative operator (if any) for proper handling\n
+\t\t\t\tj = ++i;\n
+\t\t\t\tfor ( ; j < len; j++ ) {\n
+\t\t\t\t\tif ( Expr.relative[ tokens[j].type ] ) {\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\treturn setMatcher(\n
+\t\t\t\t\ti > 1 && elementMatcher( matchers ),\n
+\t\t\t\t\ti > 1 && toSelector(\n
+\t\t\t\t\t\t// If the preceding token was a descendant combinator, insert an implicit any-element `*`\n
+\t\t\t\t\t\ttokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })\n
+\t\t\t\t\t).replace( rtrim, "$1" ),\n
+\t\t\t\t\tmatcher,\n
+\t\t\t\t\ti < j && matcherFromTokens( tokens.slice( i, j ) ),\n
+\t\t\t\t\tj < len && matcherFromTokens( (tokens = tokens.slice( j )) ),\n
+\t\t\t\t\tj < len && toSelector( tokens )\n
+\t\t\t\t);\n
+\t\t\t}\n
+\t\t\tmatchers.push( matcher );\n
+\t\t}\n
+\t}\n
+\n
+\treturn elementMatcher( matchers );\n
+}\n
+\n
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {\n
+\t// A counter to specify which element is currently being matched\n
+\tvar matcherCachedRuns = 0,\n
+\t\tbySet = setMatchers.length > 0,\n
+\t\tbyElement = elementMatchers.length > 0,\n
+\t\tsuperMatcher = function( seed, context, xml, results, expandContext ) {\n
+\t\t\tvar elem, j, matcher,\n
+\t\t\t\tsetMatched = [],\n
+\t\t\t\tmatchedCount = 0,\n
+\t\t\t\ti = "0",\n
+\t\t\t\tunmatched = seed && [],\n
+\t\t\t\toutermost = expandContext != null,\n
+\t\t\t\tcontextBackup = outermostContext,\n
+\t\t\t\t// We must always have either seed elements or context\n
+\t\t\t\telems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ),\n
+\t\t\t\t// Use integer dirruns iff this is the outermost matcher\n
+\t\t\t\tdirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1);\n
+\n
+\t\t\tif ( outermost ) {\n
+\t\t\t\toutermostContext = context !== document && context;\n
+\t\t\t\tcachedruns = matcherCachedRuns;\n
+\t\t\t}\n
+\n
+\t\t\t// Add elements passing elementMatchers directly to results\n
+\t\t\t// Keep `i` a string if there are no elements so `matchedCount` will be "00" below\n
+\t\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n
+\t\t\t\tif ( byElement && elem ) {\n
+\t\t\t\t\tj = 0;\n
+\t\t\t\t\twhile ( (matcher = elementMatchers[j++]) ) {\n
+\t\t\t\t\t\tif ( matcher( elem, context, xml ) ) {\n
+\t\t\t\t\t\t\tresults.push( elem );\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif ( outermost ) {\n
+\t\t\t\t\t\tdirruns = dirrunsUnique;\n
+\t\t\t\t\t\tcachedruns = ++matcherCachedRuns;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Track unmatched elements for set filters\n
+\t\t\t\tif ( bySet ) {\n
+\t\t\t\t\t// They will have gone through all possible matchers\n
+\t\t\t\t\tif ( (elem = !matcher && elem) ) {\n
+\t\t\t\t\t\tmatchedCount--;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// Lengthen the array for every element, matched or not\n
+\t\t\t\t\tif ( seed ) {\n
+\t\t\t\t\t\tunmatched.push( elem );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// Apply set filters to unmatched elements\n
+\t\t\tmatchedCount += i;\n
+\t\t\tif ( bySet && i !== matchedCount ) {\n
+\t\t\t\tj = 0;\n
+\t\t\t\twhile ( (matcher = setMatchers[j++]) ) {\n
+\t\t\t\t\tmatcher( unmatched, setMatched, context, xml );\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif ( seed ) {\n
+\t\t\t\t\t// Reintegrate element matches to eliminate the need for sorting\n
+\t\t\t\t\tif ( matchedCount > 0 ) {\n
+\t\t\t\t\t\twhile ( i-- ) {\n
+\t\t\t\t\t\t\tif ( !(unmatched[i] || setMatched[i]) ) {\n
+\t\t\t\t\t\t\t\tsetMatched[i] = pop.call( results );\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// Discard index placeholder values to get only actual matches\n
+\t\t\t\t\tsetMatched = condense( setMatched );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Add matches to results\n
+\t\t\t\tpush.apply( results, setMatched );\n
+\n
+\t\t\t\t// Seedless set matches succeeding multiple successful matchers stipulate sorting\n
+\t\t\t\tif ( outermost && !seed && setMatched.length > 0 &&\n
+\t\t\t\t\t( matchedCount + setMatchers.length ) > 1 ) {\n
+\n
+\t\t\t\t\tSizzle.uniqueSort( results );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// Override manipulation of globals by nested matchers\n
+\t\t\tif ( outermost ) {\n
+\t\t\t\tdirruns = dirrunsUnique;\n
+\t\t\t\toutermostContext = contextBackup;\n
+\t\t\t}\n
+\n
+\t\t\treturn unmatched;\n
+\t\t};\n
+\n
+\treturn bySet ?\n
+\t\tmarkFunction( superMatcher ) :\n
+\t\tsuperMatcher;\n
+}\n
+\n
+compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) {\n
+\tvar i,\n
+\t\tsetMatchers = [],\n
+\t\telementMatchers = [],\n
+\t\tcached = compilerCache[ selector + " " ];\n
+\n
+\tif ( !cached ) {\n
+\t\t// Generate a function of recursive functions that can be used to check each element\n
+\t\tif ( !group ) {\n
+\t\t\tgroup = tokenize( selector );\n
+\t\t}\n
+\t\ti = group.length;\n
+\t\twhile ( i-- ) {\n
+\t\t\tcached = matcherFromTokens( group[i] );\n
+\t\t\tif ( cached[ expando ] ) {\n
+\t\t\t\tsetMatchers.push( cached );\n
+\t\t\t} else {\n
+\t\t\t\telementMatchers.push( cached );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Cache the compiled function\n
+\t\tcached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );\n
+\t}\n
+\treturn cached;\n
+};\n
+\n
+function multipleContexts( selector, contexts, results ) {\n
+\tvar i = 0,\n
+\t\tlen = contexts.length;\n
+\tfor ( ; i < len; i++ ) {\n
+\t\tSizzle( selector, contexts[i], results );\n
+\t}\n
+\treturn results;\n
+}\n
+\n
+function select( selector, context, results, seed ) {\n
+\tvar i, tokens, token, type, find,\n
+\t\tmatch = tokenize( selector );\n
+\n
+\tif ( !seed ) {\n
+\t\t// Try to minimize operations if there is only one group\n
+\t\tif ( match.length === 1 ) {\n
+\n
+\t\t\t// Take a shortcut and set the context if the root selector is an ID\n
+\t\t\ttokens = match[0] = match[0].slice( 0 );\n
+\t\t\tif ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&\n
+\t\t\t\t\tsupport.getById && context.nodeType === 9 && documentIsHTML &&\n
+\t\t\t\t\tExpr.relative[ tokens[1].type ] ) {\n
+\n
+\t\t\t\tcontext = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];\n
+\t\t\t\tif ( !context ) {\n
+\t\t\t\t\treturn results;\n
+\t\t\t\t}\n
+\t\t\t\tselector = selector.slice( tokens.shift().value.length );\n
+\t\t\t}\n
+\n
+\t\t\t// Fetch a seed set for right-to-left matching\n
+\t\t\ti = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;\n
+\t\t\twhile ( i-- ) {\n
+\t\t\t\ttoken = tokens[i];\n
+\n
+\t\t\t\t// Abort if we hit a combinator\n
+\t\t\t\tif ( Expr.relative[ (type = token.type) ] ) {\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t\tif ( (find = Expr.find[ type ]) ) {\n
+\t\t\t\t\t// Search, expanding context for leading sibling combinators\n
+\t\t\t\t\tif ( (seed = find(\n
+\t\t\t\t\t\ttoken.matches[0].replace( runescape, funescape ),\n
+\t\t\t\t\t\trsibling.test( tokens[0].type ) && context.parentNode || context\n
+\t\t\t\t\t)) ) {\n
+\n
+\t\t\t\t\t\t// If seed is empty or no tokens remain, we can return early\n
+\t\t\t\t\t\ttokens.splice( i, 1 );\n
+\t\t\t\t\t\tselector = seed.length && toSelector( tokens );\n
+\t\t\t\t\t\tif ( !selector ) {\n
+\t\t\t\t\t\t\tpush.apply( results, seed );\n
+\t\t\t\t\t\t\treturn results;\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\t// Compile and execute a filtering function\n
+\t// Provide `match` to avoid retokenization if we modified the selector above\n
+\tcompile( selector, match )(\n
+\t\tseed,\n
+\t\tcontext,\n
+\t\t!documentIsHTML,\n
+\t\tresults,\n
+\t\trsibling.test( selector )\n
+\t);\n
+\treturn results;\n
+}\n
+\n
+// One-time assignments\n
+\n
+// Sort stability\n
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;\n
+\n
+// Support: Chrome<14\n
+// Always assume duplicates if they aren\'t passed to the comparison function\n
+support.detectDuplicates = hasDuplicate;\n
+\n
+// Initialize against the default document\n
+setDocument();\n
+\n
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)\n
+// Detached nodes confoundingly follow *each other*\n
+support.sortDetached = assert(function( div1 ) {\n
+\t// Should return 1, but returns 4 (following)\n
+\treturn div1.compareDocumentPosition( document.createElement("div") ) & 1;\n
+});\n
+\n
+// Support: IE<8\n
+// Prevent attribute/property "interpolation"\n
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx\n
+if ( !assert(function( div ) {\n
+\tdiv.innerHTML = "<a href=\'#\'></a>";\n
+\treturn div.firstChild.getAttribute("href") === "#" ;\n
+}) ) {\n
+\taddHandle( "type|href|height|width", function( elem, name, isXML ) {\n
+\t\tif ( !isXML ) {\n
+\t\t\treturn elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );\n
+\t\t}\n
+\t});\n
+}\n
+\n
+// Support: IE<9\n
+// Use defaultValue in place of getAttribute("value")\n
+if ( !support.attributes || !assert(function( div ) {\n
+\tdiv.innerHTML = "<input/>";\n
+\tdiv.firstChild.setAttribute( "value", "" );\n
+\treturn div.firstChild.getAttribute( "value" ) === "";\n
+}) ) {\n
+\taddHandle( "value", function( elem, name, isXML ) {\n
+\t\tif ( !isXML && elem.nodeName.toLowerCase() === "input" ) {\n
+\t\t\treturn elem.defaultValue;\n
+\t\t}\n
+\t});\n
+}\n
+\n
+// Support: IE<9\n
+// Use getAttributeNode to fetch booleans when getAttribute lies\n
+if ( !assert(function( div ) {\n
+\treturn div.getAttribute("disabled") == null;\n
+}) ) {\n
+\taddHandle( booleans, function( elem, name, isXML ) {\n
+\t\tvar val;\n
+\t\tif ( !isXML ) {\n
+\t\t\treturn (val = elem.getAttributeNode( name )) && val.specified ?\n
+\t\t\t\tval.value :\n
+\t\t\t\telem[ name ] === true ? name.toLowerCase() : null;\n
+\t\t}\n
+\t});\n
+}\n
+\n
+jQuery.find = Sizzle;\n
+jQuery.expr = Sizzle.selectors;\n
+jQuery.expr[":"] = jQuery.expr.pseudos;\n
+jQuery.unique = Sizzle.uniqueSort;\n
+jQuery.text = Sizzle.getText;\n
+jQuery.isXMLDoc = Sizzle.isXML;\n
+jQuery.contains = Sizzle.contains;\n
+\n
+\n
+})( window );\n
+// String to Object options format cache\n
+var optionsCache = {};\n
+\n
+// Convert String-formatted options into Object-formatted ones and store in cache\n
+function createOptions( options ) {\n
+\tvar object = optionsCache[ options ] = {};\n
+\tjQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) {\n
+\t\tobject[ flag ] = true;\n
+\t});\n
+\treturn object;\n
+}\n
+\n
+/*\n
+ * Create a callback list using the following parameters:\n
+ *\n
+ *\toptions: an optional list of space-separated options that will change how\n
+ *\t\t\tthe callback list behaves or a more traditional option object\n
+ *\n
+ * By default a callback list will act like an event callback list and can be\n
+ * "fired" multiple times.\n
+ *\n
+ * Possible options:\n
+ *\n
+ *\tonce:\t\t\twill ensure the callback list can only be fired once (like a Deferred)\n
+ *\n
+ *\tmemory:\t\t\twill keep track of previous values and will call any callback added\n
+ *\t\t\t\t\tafter the list has been fired right away with the latest "memorized"\n
+ *\t\t\t\t\tvalues (like a Deferred)\n
+ *\n
+ *\tunique:\t\t\twill ensure a callback can only be added once (no duplicate in the list)\n
+ *\n
+ *\tstopOnFalse:\tinterrupt callings when a callback returns false\n
+ *\n
+ */\n
+jQuery.Callbacks = function( options ) {\n
+\n
+\t// Convert options from String-formatted to Object-formatted if needed\n
+\t// (we check in cache first)\n
+\toptions = typeof options === "string" ?\n
+\t\t( optionsCache[ options ] || createOptions( options ) ) :\n
+\t\tjQuery.extend( {}, options );\n
+\n
+\tvar // Last fire value (for non-forgettable lists)\n
+\t\tmemory,\n
+\t\t// Flag to know if list was already fired\n
+\t\tfired,\n
+\t\t// Flag to know if list is currently firing\n
+\t\tfiring,\n
+\t\t// First callback to fire (used internally by add and fireWith)\n
+\t\tfiringStart,\n
+\t\t// End of the loop when firing\n
+\t\tfiringLength,\n
+\t\t// Index of currently firing callback (modified by remove if needed)\n
+\t\tfiringIndex,\n
+\t\t// Actual callback list\n
+\t\tlist = [],\n
+\t\t// Stack of fire calls for repeatable lists\n
+\t\tstack = !options.once && [],\n
+\t\t// Fire callbacks\n
+\t\tfire = function( data ) {\n
+\t\t\tmemory = options.memory && data;\n
+\t\t\tfired = true;\n
+\t\t\tfiringIndex = firingStart || 0;\n
+\t\t\tfiringStart = 0;\n
+\t\t\tfiringLength = list.length;\n
+\t\t\tfiring = true;\n
+\t\t\tfor ( ; list && firingIndex < firingLength; firingIndex++ ) {\n
+\t\t\t\tif ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {\n
+\t\t\t\t\tmemory = false; // To prevent further calls using add\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tfiring = false;\n
+\t\t\tif ( list ) {\n
+\t\t\t\tif ( stack ) {\n
+\t\t\t\t\tif ( stack.length ) {\n
+\t\t\t\t\t\tfire( stack.shift() );\n
+\t\t\t\t\t}\n
+\t\t\t\t} else if ( memory ) {\n
+\t\t\t\t\tlist = [];\n
+\t\t\t\t} else {\n
+\t\t\t\t\tself.disable();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t},\n
+\t\t// Actual Callbacks object\n
+\t\tself = {\n
+\t\t\t// Add a callback or a collection of callbacks to the list\n
+\t\t\tadd: function() {\n
+\t\t\t\tif ( list ) {\n
+\t\t\t\t\t// First, we save the current length\n
+\t\t\t\t\tvar start = list.length;\n
+\t\t\t\t\t(function add( args ) {\n
+\t\t\t\t\t\tjQuery.each( args, function( _, arg ) {\n
+\t\t\t\t\t\t\tvar type = jQuery.type( arg );\n
+\t\t\t\t\t\t\tif ( type === "function" ) {\n
+\t\t\t\t\t\t\t\tif ( !options.unique || !self.has( arg ) ) {\n
+\t\t\t\t\t\t\t\t\tlist.push( arg );\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t} else if ( arg && arg.length && type !== "string" ) {\n
+\t\t\t\t\t\t\t\t// Inspect recursively\n
+\t\t\t\t\t\t\t\tadd( arg );\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t})( arguments );\n
+\t\t\t\t\t// Do we need to add the callbacks to the\n
+\t\t\t\t\t// current firing batch?\n
+\t\t\t\t\tif ( firing ) {\n
+\t\t\t\t\t\tfiringLength = list.length;\n
+\t\t\t\t\t// With memory, if we\'re not firing then\n
+\t\t\t\t\t// we should call right away\n
+\t\t\t\t\t} else if ( memory ) {\n
+\t\t\t\t\t\tfiringStart = start;\n
+\t\t\t\t\t\tfire( memory );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\treturn this;\n
+\t\t\t},\n
+\t\t\t// Remove a callback from the list\n
+\t\t\tremove: function() {\n
+\t\t\t\tif ( list ) {\n
+\t\t\t\t\tjQuery.each( arguments, function( _, arg ) {\n
+\t\t\t\t\t\tvar index;\n
+\t\t\t\t\t\twhile( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {\n
+\t\t\t\t\t\t\tlist.splice( index, 1 );\n
+\t\t\t\t\t\t\t// Handle firing indexes\n
+\t\t\t\t\t\t\tif ( firing ) {\n
+\t\t\t\t\t\t\t\tif ( index <= firingLength ) {\n
+\t\t\t\t\t\t\t\t\tfiringLength--;\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\tif ( index <= firingIndex ) {\n
+\t\t\t\t\t\t\t\t\tfiringIndex--;\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t});\n
+\t\t\t\t}\n
+\t\t\t\treturn this;\n
+\t\t\t},\n
+\t\t\t// Check if a given callback is in the list.\n
+\t\t\t// If no argument is given, return whether or not list has callbacks attached.\n
+\t\t\thas: function( fn ) {\n
+\t\t\t\treturn fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );\n
+\t\t\t},\n
+\t\t\t// Remove all callbacks from the list\n
+\t\t\tempty: function() {\n
+\t\t\t\tlist = [];\n
+\t\t\t\tfiringLength = 0;\n
+\t\t\t\treturn this;\n
+\t\t\t},\n
+\t\t\t// Have the list do nothing anymore\n
+\t\t\tdisable: function() {\n
+\t\t\t\tlist = stack = memory = undefined;\n
+\t\t\t\treturn this;\n
+\t\t\t},\n
+\t\t\t// Is it disabled?\n
+\t\t\tdisabled: function() {\n
+\t\t\t\treturn !list;\n
+\t\t\t},\n
+\t\t\t// Lock the list in its current state\n
+\t\t\tlock: function() {\n
+\t\t\t\tstack = undefined;\n
+\t\t\t\tif ( !memory ) {\n
+\t\t\t\t\tself.disable();\n
+\t\t\t\t}\n
+\t\t\t\treturn this;\n
+\t\t\t},\n
+\t\t\t// Is it locked?\n
+\t\t\tlocked: function() {\n
+\t\t\t\treturn !stack;\n
+\t\t\t},\n
+\t\t\t// Call all callbacks with the given context and arguments\n
+\t\t\tfireWith: function( context, args ) {\n
+\t\t\t\tif ( list && ( !fired || stack ) ) {\n
+\t\t\t\t\targs = args || [];\n
+\t\t\t\t\targs = [ context, args.slice ? args.slice() : args ];\n
+\t\t\t\t\tif ( firing ) {\n
+\t\t\t\t\t\tstack.push( args );\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tfire( args );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\treturn this;\n
+\t\t\t},\n
+\t\t\t// Call all the callbacks with the given arguments\n
+\t\t\tfire: function() {\n
+\t\t\t\tself.fireWith( this, arguments );\n
+\t\t\t\treturn this;\n
+\t\t\t},\n
+\t\t\t// To know if the callbacks have already been called at least once\n
+\t\t\tfired: function() {\n
+\t\t\t\treturn !!fired;\n
+\t\t\t}\n
+\t\t};\n
+\n
+\treturn self;\n
+};\n
+jQuery.extend({\n
+\n
+\tDeferred: function( func ) {\n
+\t\tvar tuples = [\n
+\t\t\t\t// action, add listener, listener list, final state\n
+\t\t\t\t[ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],\n
+\t\t\t\t[ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],\n
+\t\t\t\t[ "notify", "progress", jQuery.Callbacks("memory") ]\n
+\t\t\t],\n
+\t\t\tstate = "pending",\n
+\t\t\tpromise = {\n
+\t\t\t\tstate: function() {\n
+\t\t\t\t\treturn state;\n
+\t\t\t\t},\n
+\t\t\t\talways: function() {\n
+\t\t\t\t\tdeferred.done( arguments ).fail( arguments );\n
+\t\t\t\t\treturn this;\n
+\t\t\t\t},\n
+\t\t\t\tthen: function( /* fnDone, fnFail, fnProgress */ ) {\n
+\t\t\t\t\tvar fns = arguments;\n
+\t\t\t\t\treturn jQuery.Deferred(function( newDefer ) {\n
+\t\t\t\t\t\tjQuery.each( tuples, function( i, tuple ) {\n
+\t\t\t\t\t\t\tvar action = tuple[ 0 ],\n
+\t\t\t\t\t\t\t\tfn = jQuery.isFunction( fns[ i ] ) && fns[ i ];\n
+\t\t\t\t\t\t\t// deferred[ done | fail | progress ] for forwarding actions to newDefer\n
+\t\t\t\t\t\t\tdeferred[ tuple[1] ](function() {\n
+\t\t\t\t\t\t\t\tvar returned = fn && fn.apply( this, arguments );\n
+\t\t\t\t\t\t\t\tif ( returned && jQuery.isFunction( returned.promise ) ) {\n
+\t\t\t\t\t\t\t\t\treturned.promise()\n
+\t\t\t\t\t\t\t\t\t\t.done( newDefer.resolve )\n
+\t\t\t\t\t\t\t\t\t\t.fail( newDefer.reject )\n
+\t\t\t\t\t\t\t\t\t\t.progress( newDefer.notify );\n
+\t\t\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t\t\tnewDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t});\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t\tfns = null;\n
+\t\t\t\t\t}).promise();\n
+\t\t\t\t},\n
+\t\t\t\t// Get a promise for this deferred\n
+\t\t\t\t// If obj is provided, the promise aspect is added to the object\n
+\t\t\t\tpromise: function( obj ) {\n
+\t\t\t\t\treturn obj != null ? jQuery.extend( obj, promise ) : promise;\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tdeferred = {};\n
+\n
+\t\t// Keep pipe for back-compat\n
+\t\tpromise.pipe = promise.then;\n
+\n
+\t\t// Add list-specific methods\n
+\t\tjQuery.each( tuples, function( i, tuple ) {\n
+\t\t\tvar list = tuple[ 2 ],\n
+\t\t\t\tstateString = tuple[ 3 ];\n
+\n
+\t\t\t// promise[ done | fail | progress ] = list.add\n
+\t\t\tpromise[ tuple[1] ] = list.add;\n
+\n
+\t\t\t// Handle state\n
+\t\t\tif ( stateString ) {\n
+\t\t\t\tlist.add(function() {\n
+\t\t\t\t\t// state = [ resolved | rejected ]\n
+\t\t\t\t\tstate = stateString;\n
+\n
+\t\t\t\t// [ reject_list | resolve_list ].disable; progress_list.lock\n
+\t\t\t\t}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );\n
+\t\t\t}\n
+\n
+\t\t\t// deferred[ resolve | reject | notify ]\n
+\t\t\tdeferred[ tuple[0] ] = function() {\n
+\t\t\t\tdeferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );\n
+\t\t\t\treturn this;\n
+\t\t\t};\n
+\t\t\tdeferred[ tuple[0] + "With" ] = list.fireWith;\n
+\t\t});\n
+\n
+\t\t// Make the deferred a promise\n
+\t\tpromise.promise( deferred );\n
+\n
+\t\t// Call given func if any\n
+\t\tif ( func ) {\n
+\t\t\tfunc.call( deferred, deferred );\n
+\t\t}\n
+\n
+\t\t// All done!\n
+\t\treturn deferred;\n
+\t},\n
+\n
+\t// Deferred helper\n
+\twhen: function( subordinate /* , ..., subordinateN */ ) {\n
+\t\tvar i = 0,\n
+\t\t\tresolveValues = core_slice.call( arguments ),\n
+\t\t\tlength = resolveValues.length,\n
+\n
+\t\t\t// the count of uncompleted subordinates\n
+\t\t\tremaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,\n
+\n
+\t\t\t// the master Deferred. If resolveValues consist of only a single Deferred, just use that.\n
+\t\t\tdeferred = remaining === 1 ? subordinate : jQuery.Deferred(),\n
+\n
+\t\t\t// Update function for both resolve and progress values\n
+\t\t\tupdateFunc = function( i, contexts, values ) {\n
+\t\t\t\treturn function( value ) {\n
+\t\t\t\t\tcontexts[ i ] = this;\n
+\t\t\t\t\tvalues[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value;\n
+\t\t\t\t\tif( values === progressValues ) {\n
+\t\t\t\t\t\tdeferred.notifyWith( contexts, values );\n
+\t\t\t\t\t} else if ( !( --remaining ) ) {\n
+\t\t\t\t\t\tdeferred.resolveWith( contexts, values );\n
+\t\t\t\t\t}\n
+\t\t\t\t};\n
+\t\t\t},\n
+\n
+\t\t\tprogressValues, progressContexts, resolveContexts;\n
+\n
+\t\t// add listeners to Deferred subordinates; treat others as resolved\n
+\t\tif ( length > 1 ) {\n
+\t\t\tprogressValues = new Array( length );\n
+\t\t\tprogressContexts = new Array( length );\n
+\t\t\tresolveContexts = new Array( length );\n
+\t\t\tfor ( ; i < length; i++ ) {\n
+\t\t\t\tif ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {\n
+\t\t\t\t\tresolveValues[ i ].promise()\n
+\t\t\t\t\t\t.done( updateFunc( i, resolveContexts, resolveValues ) )\n
+\t\t\t\t\t\t.fail( deferred.reject )\n
+\t\t\t\t\t\t.progress( updateFunc( i, progressContexts, progressValues ) );\n
+\t\t\t\t} else {\n
+\t\t\t\t\t--remaining;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// if we\'re not waiting on anything, resolve the master\n
+\t\tif ( !remaining ) {\n
+\t\t\tdeferred.resolveWith( resolveContexts, resolveValues );\n
+\t\t}\n
+\n
+\t\treturn deferred.promise();\n
+\t}\n
+});\n
+jQuery.support = (function( support ) {\n
+\tvar input = document.createElement("input"),\n
+\t\tfragment = document.createDocumentFragment(),\n
+\t\tdiv = document.createElement("div"),\n
+\t\tselect = document.createElement("select"),\n
+\t\topt = select.appendChild( document.createElement("option") );\n
+\n
+\t// Finish early in limited environments\n
+\tif ( !input.type ) {\n
+\t\treturn support;\n
+\t}\n
+\n
+\tinput.type = "checkbox";\n
+\n
+\t// Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3\n
+\t// Check the default checkbox/radio value ("" on old WebKit; "on" elsewhere)\n
+\tsupport.checkOn = input.value !== "";\n
+\n
+\t// Must access the parent to make an option select properly\n
+\t// Support: IE9, IE10\n
+\tsupport.optSelected = opt.selected;\n
+\n
+\t// Will be defined later\n
+\tsupport.reliableMarginRight = true;\n
+\tsupport.boxSizingReliable = true;\n
+\tsupport.pixelPosition = false;\n
+\n
+\t// Make sure checked status is properly cloned\n
+\t// Support: IE9, IE10\n
+\tinput.checked = true;\n
+\tsupport.noCloneChecked = input.cloneNode( true ).checked;\n
+\n
+\t// Make sure that the options inside disabled selects aren\'t marked as disabled\n
+\t// (WebKit marks them as disabled)\n
+\tselect.disabled = true;\n
+\tsupport.optDisabled = !opt.disabled;\n
+\n
+\t// Check if an input maintains its value after becoming a radio\n
+\t// Support: IE9, IE10\n
+\tinput = document.createElement("input");\n
+\tinput.value = "t";\n
+\tinput.type = "radio";\n
+\tsupport.radioValue = input.value === "t";\n
+\n
+\t// #11217 - WebKit loses check when the name is after the checked attribute\n
+\tinput.setAttribute( "checked", "t" );\n
+\tinput.setAttribute( "name", "t" );\n
+\n
+\tfragment.appendChild( input );\n
+\n
+\t// Support: Safari 5.1, Android 4.x, Android 2.3\n
+\t// old WebKit doesn\'t clone checked state correctly in fragments\n
+\tsupport.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;\n
+\n
+\t// Support: Firefox, Chrome, Safari\n
+\t// Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)\n
+\tsupport.focusinBubbles = "onfocusin" in window;\n
+\n
+\tdiv.style.backgroundClip = "content-box";\n
+\tdiv.cloneNode( true ).style.backgroundClip = "";\n
+\tsupport.clearCloneStyle = div.style.backgroundClip === "content-box";\n
+\n
+\t// Run tests that need a body at doc ready\n
+\tjQuery(function() {\n
+\t\tvar container, marginDiv,\n
+\t\t\t// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).\n
+\t\t\tdivReset = "padding:0;margin:0;border:0;display:block;-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box",\n
+\t\t\tbody = document.getElementsByTagName("body")[ 0 ];\n
+\n
+\t\tif ( !body ) {\n
+\t\t\t// Return for frameset docs that don\'t have a body\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tcontainer = document.createElement("div");\n
+\t\tcontainer.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px";\n
+\n
+\t\t// Check box-sizing and margin behavior.\n
+\t\tbody.appendChild( container ).appendChild( div );\n
+\t\tdiv.innerHTML = "";\n
+\t\t// Support: Firefox, Android 2.3 (Prefixed box-sizing versions).\n
+\t\tdiv.style.cssText = "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%";\n
+\n
+\t\t// Workaround failing boxSizing test due to offsetWidth returning wrong value\n
+\t\t// with some non-1 values of body zoom, ticket #13543\n
+\t\tjQuery.swap( body, body.style.zoom != null ? { zoom: 1 } : {}, function() {\n
+\t\t\tsupport.boxSizing = div.offsetWidth === 4;\n
+\t\t});\n
+\n
+\t\t// Use window.getComputedStyle because jsdom on node.js will break without it.\n
+\t\tif ( window.getComputedStyle ) {\n
+\t\t\tsupport.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";\n
+\t\t\tsupport.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";\n
+\n
+\t\t\t// Support: Android 2.3\n
+\t\t\t// Check if div with explicit width and no margin-right incorrectly\n
+\t\t\t// gets computed margin-right based on width of container. (#3333)\n
+\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n
+\t\t\tmarginDiv = div.appendChild( document.createElement("div") );\n
+\t\t\tmarginDiv.style.cssText = div.style.cssText = divReset;\n
+\t\t\tmarginDiv.style.marginRight = marginDiv.style.width = "0";\n
+\t\t\tdiv.style.width = "1px";\n
+\n
+\t\t\tsupport.reliableMarginRight =\n
+\t\t\t\t!parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight );\n
+\t\t}\n
+\n
+\t\tbody.removeChild( container );\n
+\t});\n
+\n
+\treturn support;\n
+})( {} );\n
+\n
+/*\n
+\tImplementation Summary\n
+\n
+\t1. Enforce API surface and semantic compatibility with 1.9.x branch\n
+\t2. Improve the module\'s maintainability by reducing the storage\n
+\t\tpaths to a single mechanism.\n
+\t3. Use the same single mechanism to support "private" and "user" data.\n
+\t4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)\n
+\t5. Avoid exposing implementation details on user objects (eg. expando properties)\n
+\t6. Provide a clear path for implementation upgrade to WeakMap in 2014\n
+*/\n
+var data_user, data_priv,\n
+\trbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n
+\trmultiDash = /([A-Z])/g;\n
+\n
+function Data() {\n
+\t// Support: Android < 4,\n
+\t// Old WebKit does not have Object.preventExtensions/freeze method,\n
+\t// return new empty object instead with no [[set]] accessor\n
+\tObject.defineProperty( this.cache = {}, 0, {\n
+\t\tget: function() {\n
+\t\t\treturn {};\n
+\t\t}\n
+\t});\n
+\n
+\tthis.expando = jQuery.expando + Math.random();\n
+}\n
+\n
+Data.uid = 1;\n
+\n
+Data.accepts = function( owner ) {\n
+\t// Accepts only:\n
+\t//  - Node\n
+\t//    - Node.ELEMENT_NODE\n
+\t//    - Node.DOCUMENT_NODE\n
+\t//  - Object\n
+\t//    - Any\n
+\treturn owner.nodeType ?\n
+\t\towner.nodeType === 1 || owner.nodeType === 9 : true;\n
+};\n
+\n
+Data.prototype = {\n
+\tkey: function( owner ) {\n
+\t\t// We can accept data for non-element nodes in modern browsers,\n
+\t\t// but we should not, see #8335.\n
+\t\t// Always return the key for a frozen object.\n
+\t\tif ( !Data.accepts( owner ) ) {\n
+\t\t\treturn 0;\n
+\t\t}\n
+\n
+\t\tvar descriptor = {},\n
+\t\t\t// Check if the owner object already has a cache key\n
+\t\t\tunlock = owner[ this.expando ];\n
+\n
+\t\t// If not, create one\n
+\t\tif ( !unlock ) {\n
+\t\t\tunlock = Data.uid++;\n
+\n
+\t\t\t// Secure it in a non-enumerable, non-writable property\n
+\t\t\ttry {\n
+\t\t\t\tdescriptor[ this.expando ] = { value: unlock };\n
+\t\t\t\tObject.defineProperties( owner, descriptor );\n
+\n
+\t\t\t// Support: Android < 4\n
+\t\t\t// Fallback to a less secure definition\n
+\t\t\t} catch ( e ) {\n
+\t\t\t\tdescriptor[ this.expando ] = unlock;\n
+\t\t\t\tjQuery.extend( owner, descriptor );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Ensure the cache object\n
+\t\tif ( !this.cache[ unlock ] ) {\n
+\t\t\tthis.cache[ unlock ] = {};\n
+\t\t}\n
+\n
+\t\treturn unlock;\n
+\t},\n
+\tset: function( owner, data, value ) {\n
+\t\tvar prop,\n
+\t\t\t// There may be an unlock assigned to this node,\n
+\t\t\t// if there is no entry for this "owner", create one inline\n
+\t\t\t// and set the unlock as though an owner entry had always existed\n
+\t\t\tunlock = this.key( owner ),\n
+\t\t\tcache = this.cache[ unlock ];\n
+\n
+\t\t// Handle: [ owner, key, value ] args\n
+\t\tif ( typeof data === "string" ) {\n
+\t\t\tcache[ data ] = value;\n
+\n
+\t\t// Handle: [ owner, { properties } ] args\n
+\t\t} else {\n
+\t\t\t// Fresh assignments by object are shallow copied\n
+\t\t\tif ( jQuery.isEmptyObject( cache ) ) {\n
+\t\t\t\tjQuery.extend( this.cache[ unlock ], data );\n
+\t\t\t// Otherwise, copy the properties one-by-one to the cache object\n
+\t\t\t} else {\n
+\t\t\t\tfor ( prop in data ) {\n
+\t\t\t\t\tcache[ prop ] = data[ prop ];\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn cache;\n
+\t},\n
+\tget: function( owner, key ) {\n
+\t\t// Either a valid cache is found, or will be created.\n
+\t\t// New caches will be created and the unlock returned,\n
+\t\t// allowing direct access to the newly created\n
+\t\t// empty data object. A valid owner object must be provided.\n
+\t\tvar cache = this.cache[ this.key( owner ) ];\n
+\n
+\t\treturn key === undefined ?\n
+\t\t\tcache : cache[ key ];\n
+\t},\n
+\taccess: function( owner, key, value ) {\n
+\t\tvar stored;\n
+\t\t// In cases where either:\n
+\t\t//\n
+\t\t//   1. No key was specified\n
+\t\t//   2. A string key was specified, but no value provided\n
+\t\t//\n
+\t\t// Take the "read" path and allow the get method to determine\n
+\t\t// which value to return, respectively either:\n
+\t\t//\n
+\t\t//   1. The entire cache object\n
+\t\t//   2. The data stored at the key\n
+\t\t//\n
+\t\tif ( key === undefined ||\n
+\t\t\t\t((key && typeof key === "string") && value === undefined) ) {\n
+\n
+\t\t\tstored = this.get( owner, key );\n
+\n
+\t\t\treturn stored !== undefined ?\n
+\t\t\t\tstored : this.get( owner, jQuery.camelCase(key) );\n
+\t\t}\n
+\n
+\t\t// [*]When the key is not a string, or both a key and value\n
+\t\t// are specified, set or extend (existing objects) with either:\n
+\t\t//\n
+\t\t//   1. An object of properties\n
+\t\t//   2. A key and value\n
+\t\t//\n
+\t\tthis.set( owner, key, value );\n
+\n
+\t\t// Since the "set" path can have two possible entry points\n
+\t\t// return the expected data based on which path was taken[*]\n
+\t\treturn value !== undefined ? value : key;\n
+\t},\n
+\tremove: function( owner, key ) {\n
+\t\tvar i, name, camel,\n
+\t\t\tunlock = this.key( owner ),\n
+\t\t\tcache = this.cache[ unlock ];\n
+\n
+\t\tif ( key === undefined ) {\n
+\t\t\tthis.cache[ unlock ] = {};\n
+\n
+\t\t} else {\n
+\t\t\t// Support array or space separated string of keys\n
+\t\t\tif ( jQuery.isArray( key ) ) {\n
+\t\t\t\t// If "name" is an array of keys...\n
+\t\t\t\t// When data is initially created, via ("key", "val") signature,\n
+\t\t\t\t// keys will be converted to camelCase.\n
+\t\t\t\t// Since there is no way to tell _how_ a key was added, remove\n
+\t\t\t\t// both plain key and camelCase key. #12786\n
+\t\t\t\t// This will only penalize the array argument path.\n
+\t\t\t\tname = key.concat( key.map( jQuery.camelCase ) );\n
+\t\t\t} else {\n
+\t\t\t\tcamel = jQuery.camelCase( key );\n
+\t\t\t\t// Try the string as a key before any manipulation\n
+\t\t\t\tif ( key in cache ) {\n
+\t\t\t\t\tname = [ key, camel ];\n
+\t\t\t\t} else {\n
+\t\t\t\t\t// If a key with the spaces exists, use it.\n
+\t\t\t\t\t// Otherwise, create an array by matching non-whitespace\n
+\t\t\t\t\tname = camel;\n
+\t\t\t\t\tname = name in cache ?\n
+\t\t\t\t\t\t[ name ] : ( name.match( core_rnotwhite ) || [] );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\ti = name.length;\n
+\t\t\twhile ( i-- ) {\n
+\t\t\t\tdelete cache[ name[ i ] ];\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\thasData: function( owner ) {\n
+\t\treturn !jQuery.isEmptyObject(\n
+\t\t\tthis.cache[ owner[ this.expando ] ] || {}\n
+\t\t);\n
+\t},\n
+\tdiscard: function( owner ) {\n
+\t\tif ( owner[ this.expando ] ) {\n
+\t\t\tdelete this.cache[ owner[ this.expando ] ];\n
+\t\t}\n
+\t}\n
+};\n
+\n
+// These may be used throughout the jQuery core codebase\n
+data_user = new Data();\n
+data_priv = new Data();\n
+\n
+\n
+jQuery.extend({\n
+\tacceptData: Data.accepts,\n
+\n
+\thasData: function( elem ) {\n
+\t\treturn data_user.hasData( elem ) || data_priv.hasData( elem );\n
+\t},\n
+\n
+\tdata: function( elem, name, data ) {\n
+\t\treturn data_user.access( elem, name, data );\n
+\t},\n
+\n
+\tremoveData: function( elem, name ) {\n
+\t\tdata_user.remove( elem, name );\n
+\t},\n
+\n
+\t// TODO: Now that all calls to _data and _removeData have been replaced\n
+\t// with direct calls to data_priv methods, these can be deprecated.\n
+\t_data: function( elem, name, data ) {\n
+\t\treturn data_priv.access( elem, name, data );\n
+\t},\n
+\n
+\t_removeData: function( elem, name ) {\n
+\t\tdata_priv.remove( elem, name );\n
+\t}\n
+});\n
+\n
+jQuery.fn.extend({\n
+\tdata: function( key, value ) {\n
+\t\tvar attrs, name,\n
+\t\t\telem = this[ 0 ],\n
+\t\t\ti = 0,\n
+\t\t\tdata = null;\n
+\n
+\t\t// Gets all values\n
+\t\tif ( key === undefined ) {\n
+\t\t\tif ( this.length ) {\n
+\t\t\t\tdata = data_user.get( elem );\n
+\n
+\t\t\t\tif ( elem.nodeType === 1 && !data_priv.get( elem, "hasDataAttrs" ) ) {\n
+\t\t\t\t\tattrs = elem.attributes;\n
+\t\t\t\t\tfor ( ; i < attrs.length; i++ ) {\n
+\t\t\t\t\t\tname = attrs[ i ].name;\n
+\n
+\t\t\t\t\t\tif ( name.indexOf( "data-" ) === 0 ) {\n
+\t\t\t\t\t\t\tname = jQuery.camelCase( name.slice(5) );\n
+\t\t\t\t\t\t\tdataAttr( elem, name, data[ name ] );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\tdata_priv.set( elem, "hasDataAttrs", true );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\treturn data;\n
+\t\t}\n
+\n
+\t\t// Sets multiple values\n
+\t\tif ( typeof key === "object" ) {\n
+\t\t\treturn this.each(function() {\n
+\t\t\t\tdata_user.set( this, key );\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\treturn jQuery.access( this, function( value ) {\n
+\t\t\tvar data,\n
+\t\t\t\tcamelKey = jQuery.camelCase( key );\n
+\n
+\t\t\t// The calling jQuery object (element matches) is not empty\n
+\t\t\t// (and therefore has an element appears at this[ 0 ]) and the\n
+\t\t\t// `value` parameter was not undefined. An empty jQuery object\n
+\t\t\t// will result in `undefined` for elem = this[ 0 ] which will\n
+\t\t\t// throw an exception if an attempt to read a data cache is made.\n
+\t\t\tif ( elem && value === undefined ) {\n
+\t\t\t\t// Attempt to get data from the cache\n
+\t\t\t\t// with the key as-is\n
+\t\t\t\tdata = data_user.get( elem, key );\n
+\t\t\t\tif ( data !== undefined ) {\n
+\t\t\t\t\treturn data;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Attempt to get data from the cache\n
+\t\t\t\t// with the key camelized\n
+\t\t\t\tdata = data_user.get( elem, camelKey );\n
+\t\t\t\tif ( data !== undefined ) {\n
+\t\t\t\t\treturn data;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Attempt to "discover" the data in\n
+\t\t\t\t// HTML5 custom data-* attrs\n
+\t\t\t\tdata = dataAttr( elem, camelKey, undefined );\n
+\t\t\t\tif ( data !== undefined ) {\n
+\t\t\t\t\treturn data;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// We tried really hard, but the data doesn\'t exist.\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// Set the data...\n
+\t\t\tthis.each(function() {\n
+\t\t\t\t// First, attempt to store a copy or reference of any\n
+\t\t\t\t// data that might\'ve been store with a camelCased key.\n
+\t\t\t\tvar data = data_user.get( this, camelKey );\n
+\n
+\t\t\t\t// For HTML5 data-* attribute interop, we have to\n
+\t\t\t\t// store property names with dashes in a camelCase form.\n
+\t\t\t\t// This might not apply to all properties...*\n
+\t\t\t\tdata_user.set( this, camelKey, value );\n
+\n
+\t\t\t\t// *... In the case of properties that might _actually_\n
+\t\t\t\t// have dashes, we need to also store a copy of that\n
+\t\t\t\t// unchanged property.\n
+\t\t\t\tif ( key.indexOf("-") !== -1 && data !== undefined ) {\n
+\t\t\t\t\tdata_user.set( this, key, value );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t}, null, value, arguments.length > 1, null, true );\n
+\t},\n
+\n
+\tremoveData: function( key ) {\n
+\t\treturn this.each(function() {\n
+\t\t\tdata_user.remove( this, key );\n
+\t\t});\n
+\t}\n
+});\n
+\n
+function dataAttr( elem, key, data ) {\n
+\tvar name;\n
+\n
+\t// If nothing was found internally, try to fetch any\n
+\t// data from the HTML5 data-* attribute\n
+\tif ( data === undefined && elem.nodeType === 1 ) {\n
+\t\tname = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();\n
+\t\tdata = elem.getAttribute( name );\n
+\n
+\t\tif ( typeof data === "string" ) {\n
+\t\t\ttry {\n
+\t\t\t\tdata = data === "true" ? true :\n
+\t\t\t\t\tdata === "false" ? false :\n
+\t\t\t\t\tdata === "null" ? null :\n
+\t\t\t\t\t// Only convert to a number if it doesn\'t change the string\n
+\t\t\t\t\t+data + "" === data ? +data :\n
+\t\t\t\t\trbrace.test( data ) ? JSON.parse( data ) :\n
+\t\t\t\t\tdata;\n
+\t\t\t} catch( e ) {}\n
+\n
+\t\t\t// Make sure we set the data so it isn\'t changed later\n
+\t\t\tdata_user.set( elem, key, data );\n
+\t\t} else {\n
+\t\t\tdata = undefined;\n
+\t\t}\n
+\t}\n
+\treturn data;\n
+}\n
+jQuery.extend({\n
+\tqueue: function( elem, type, data ) {\n
+\t\tvar queue;\n
+\n
+\t\tif ( elem ) {\n
+\t\t\ttype = ( type || "fx" ) + "queue";\n
+\t\t\tqueue = data_priv.get( elem, type );\n
+\n
+\t\t\t// Speed up dequeue by getting out quickly if this is just a lookup\n
+\t\t\tif ( data ) {\n
+\t\t\t\tif ( !queue || jQuery.isArray( data ) ) {\n
+\t\t\t\t\tqueue = data_priv.access( elem, type, jQuery.makeArray(data) );\n
+\t\t\t\t} else {\n
+\t\t\t\t\tqueue.push( data );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\treturn queue || [];\n
+\t\t}\n
+\t},\n
+\n
+\tdequeue: function( elem, type ) {\n
+\t\ttype = type || "fx";\n
+\n
+\t\tvar queue = jQuery.queue( elem, type ),\n
+\t\t\tstartLength = queue.length,\n
+\t\t\tfn = queue.shift(),\n
+\t\t\thooks = jQuery._queueHooks( elem, type ),\n
+\t\t\tnext = function() {\n
+\t\t\t\tjQuery.dequeue( elem, type );\n
+\t\t\t};\n
+\n
+\t\t// If the fx queue is dequeued, always remove the progress sentinel\n
+\t\tif ( fn === "inprogress" ) {\n
+\t\t\tfn = queue.shift();\n
+\t\t\tstartLength--;\n
+\t\t}\n
+\n
+\t\tif ( fn ) {\n
+\n
+\t\t\t// Add a progress sentinel to prevent the fx queue from being\n
+\t\t\t// automatically dequeued\n
+\t\t\tif ( type === "fx" ) {\n
+\t\t\t\tqueue.unshift( "inprogress" );\n
+\t\t\t}\n
+\n
+\t\t\t// clear up the last queue stop function\n
+\t\t\tdelete hooks.stop;\n
+\t\t\tfn.call( elem, next, hooks );\n
+\t\t}\n
+\n
+\t\tif ( !startLength && hooks ) {\n
+\t\t\thooks.empty.fire();\n
+\t\t}\n
+\t},\n
+\n
+\t// not intended for public consumption - generates a queueHooks object, or returns the current one\n
+\t_queueHooks: function( elem, type ) {\n
+\t\tvar key = type + "queueHooks";\n
+\t\treturn data_priv.get( elem, key ) || data_priv.access( elem, key, {\n
+\t\t\tempty: jQuery.Callbacks("once memory").add(function() {\n
+\t\t\t\tdata_priv.remove( elem, [ type + "queue", key ] );\n
+\t\t\t})\n
+\t\t});\n
+\t}\n
+});\n
+\n
+jQuery.fn.extend({\n
+\tqueue: function( type, data ) {\n
+\t\tvar setter = 2;\n
+\n
+\t\tif ( typeof type !== "string" ) {\n
+\t\t\tdata = type;\n
+\t\t\ttype = "fx";\n
+\t\t\tsetter--;\n
+\t\t}\n
+\n
+\t\tif ( arguments.length < setter ) {\n
+\t\t\treturn jQuery.queue( this[0], type );\n
+\t\t}\n
+\n
+\t\treturn data === undefined ?\n
+\t\t\tthis :\n
+\t\t\tthis.each(function() {\n
+\t\t\t\tvar queue = jQuery.queue( this, type, data );\n
+\n
+\t\t\t\t// ensure a hooks for this queue\n
+\t\t\t\tjQuery._queueHooks( this, type );\n
+\n
+\t\t\t\tif ( type === "fx" && queue[0] !== "inprogress" ) {\n
+\t\t\t\t\tjQuery.dequeue( this, type );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t},\n
+\tdequeue: function( type ) {\n
+\t\treturn this.each(function() {\n
+\t\t\tjQuery.dequeue( this, type );\n
+\t\t});\n
+\t},\n
+\t// Based off of the plugin by Clint Helfers, with permission.\n
+\t// http://blindsignals.com/index.php/2009/07/jquery-delay/\n
+\tdelay: function( time, type ) {\n
+\t\ttime = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;\n
+\t\ttype = type || "fx";\n
+\n
+\t\treturn this.queue( type, function( next, hooks ) {\n
+\t\t\tvar timeout = setTimeout( next, time );\n
+\t\t\thooks.stop = function() {\n
+\t\t\t\tclearTimeout( timeout );\n
+\t\t\t};\n
+\t\t});\n
+\t},\n
+\tclearQueue: function( type ) {\n
+\t\treturn this.queue( type || "fx", [] );\n
+\t},\n
+\t// Get a promise resolved when queues of a certain type\n
+\t// are emptied (fx is the type by default)\n
+\tpromise: function( type, obj ) {\n
+\t\tvar tmp,\n
+\t\t\tcount = 1,\n
+\t\t\tdefer = jQuery.Deferred(),\n
+\t\t\telements = this,\n
+\t\t\ti = this.length,\n
+\t\t\tresolve = function() {\n
+\t\t\t\tif ( !( --count ) ) {\n
+\t\t\t\t\tdefer.resolveWith( elements, [ elements ] );\n
+\t\t\t\t}\n
+\t\t\t};\n
+\n
+\t\tif ( typeof type !== "string" ) {\n
+\t\t\tobj = type;\n
+\t\t\ttype = undefined;\n
+\t\t}\n
+\t\ttype = type || "fx";\n
+\n
+\t\twhile( i-- ) {\n
+\t\t\ttmp = data_priv.get( elements[ i ], type + "queueHooks" );\n
+\t\t\tif ( tmp && tmp.empty ) {\n
+\t\t\t\tcount++;\n
+\t\t\t\ttmp.empty.add( resolve );\n
+\t\t\t}\n
+\t\t}\n
+\t\tresolve();\n
+\t\treturn defer.promise( obj );\n
+\t}\n
+});\n
+var nodeHook, boolHook,\n
+\trclass = /[\\t\\r\\n\\f]/g,\n
+\trreturn = /\\r/g,\n
+\trfocusable = /^(?:input|select|textarea|button)$/i;\n
+\n
+jQuery.fn.extend({\n
+\tattr: function( name, value ) {\n
+\t\treturn jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 );\n
+\t},\n
+\n
+\tremoveAttr: function( name ) {\n
+\t\treturn this.each(function() {\n
+\t\t\tjQuery.removeAttr( this, name );\n
+\t\t});\n
+\t},\n
+\n
+\tprop: function( name, value ) {\n
+\t\treturn jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 );\n
+\t},\n
+\n
+\tremoveProp: function( name ) {\n
+\t\treturn this.each(function() {\n
+\t\t\tdelete this[ jQuery.propFix[ name ] || name ];\n
+\t\t});\n
+\t},\n
+\n
+\taddClass: function( value ) {\n
+\t\tvar classes, elem, cur, clazz, j,\n
+\t\t\ti = 0,\n
+\t\t\tlen = this.length,\n
+\t\t\tproceed = typeof value === "string" && value;\n
+\n
+\t\tif ( jQuery.isFunction( value ) ) {\n
+\t\t\treturn this.each(function( j ) {\n
+\t\t\t\tjQuery( this ).addClass( value.call( this, j, this.className ) );\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tif ( proceed ) {\n
+\t\t\t// The disjunction here is for better compressibility (see removeClass)\n
+\t\t\tclasses = ( value || "" ).match( core_rnotwhite ) || [];\n
+\n
+\t\t\tfor ( ; i < len; i++ ) {\n
+\t\t\t\telem = this[ i ];\n
+\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n
+\t\t\t\t\t( " " + elem.className + " " ).replace( rclass, " " ) :\n
+\t\t\t\t\t" "\n
+\t\t\t\t);\n
+\n
+\t\t\t\tif ( cur ) {\n
+\t\t\t\t\tj = 0;\n
+\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n
+\t\t\t\t\t\tif ( cur.indexOf( " " + clazz + " " ) < 0 ) {\n
+\t\t\t\t\t\t\tcur += clazz + " ";\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\telem.className = jQuery.trim( cur );\n
+\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\tremoveClass: function( value ) {\n
+\t\tvar classes, elem, cur, clazz, j,\n
+\t\t\ti = 0,\n
+\t\t\tlen = this.length,\n
+\t\t\tproceed = arguments.length === 0 || typeof value === "string" && value;\n
+\n
+\t\tif ( jQuery.isFunction( value ) ) {\n
+\t\t\treturn this.each(function( j ) {\n
+\t\t\t\tjQuery( this ).removeClass( value.call( this, j, this.className ) );\n
+\t\t\t});\n
+\t\t}\n
+\t\tif ( proceed ) {\n
+\t\t\tclasses = ( value || "" ).match( core_rnotwhite ) || [];\n
+\n
+\t\t\tfor ( ; i < len; i++ ) {\n
+\t\t\t\telem = this[ i ];\n
+\t\t\t\t// This expression is here for better compressibility (see addClass)\n
+\t\t\t\tcur = elem.nodeType === 1 && ( elem.className ?\n
+\t\t\t\t\t( " " + elem.className + " " ).replace( rclass, " " ) :\n
+\t\t\t\t\t""\n
+\t\t\t\t);\n
+\n
+\t\t\t\tif ( cur ) {\n
+\t\t\t\t\tj = 0;\n
+\t\t\t\t\twhile ( (clazz = classes[j++]) ) {\n
+\t\t\t\t\t\t// Remove *all* instances\n
+\t\t\t\t\t\twhile ( cur.indexOf( " " + clazz + " " ) >= 0 ) {\n
+\t\t\t\t\t\t\tcur = cur.replace( " " + clazz + " ", " " );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\telem.className = value ? jQuery.trim( cur ) : "";\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\ttoggleClass: function( value, stateVal ) {\n
+\t\tvar type = typeof value;\n
+\n
+\t\tif ( typeof stateVal === "boolean" && type === "string" ) {\n
+\t\t\treturn stateVal ? this.addClass( value ) : this.removeClass( value );\n
+\t\t}\n
+\n
+\t\tif ( jQuery.isFunction( value ) ) {\n
+\t\t\treturn this.each(function( i ) {\n
+\t\t\t\tjQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\treturn this.each(function() {\n
+\t\t\tif ( type === "string" ) {\n
+\t\t\t\t// toggle individual class names\n
+\t\t\t\tvar className,\n
+\t\t\t\t\ti = 0,\n
+\t\t\t\t\tself = jQuery( this ),\n
+\t\t\t\t\tclassNames = value.match( core_rnotwhite ) || [];\n
+\n
+\t\t\t\twhile ( (className = classNames[ i++ ]) ) {\n
+\t\t\t\t\t// check each className given, space separated list\n
+\t\t\t\t\tif ( self.hasClass( className ) ) {\n
+\t\t\t\t\t\tself.removeClass( className );\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tself.addClass( className );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t// Toggle whole class name\n
+\t\t\t} else if ( type === core_strundefined || type === "boolean" ) {\n
+\t\t\t\tif ( this.className ) {\n
+\t\t\t\t\t// store className if set\n
+\t\t\t\t\tdata_priv.set( this, "__className__", this.className );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// If the element has a class name or if we\'re passed "false",\n
+\t\t\t\t// then remove the whole classname (if there was one, the above saved it).\n
+\t\t\t\t// Otherwise bring back whatever was previously saved (if anything),\n
+\t\t\t\t// falling back to the empty string if nothing was stored.\n
+\t\t\t\tthis.className = this.className || value === false ? "" : data_priv.get( this, "__className__" ) || "";\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\thasClass: function( selector ) {\n
+\t\tvar className = " " + selector + " ",\n
+\t\t\ti = 0,\n
+\t\t\tl = this.length;\n
+\t\tfor ( ; i < l; i++ ) {\n
+\t\t\tif ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {\n
+\t\t\t\treturn true;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn false;\n
+\t},\n
+\n
+\tval: function( value ) {\n
+\t\tvar hooks, ret, isFunction,\n
+\t\t\telem = this[0];\n
+\n
+\t\tif ( !arguments.length ) {\n
+\t\t\tif ( elem ) {\n
+\t\t\t\thooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];\n
+\n
+\t\t\t\tif ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {\n
+\t\t\t\t\treturn ret;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tret = elem.value;\n
+\n
+\t\t\t\treturn typeof ret === "string" ?\n
+\t\t\t\t\t// handle most common string cases\n
+\t\t\t\t\tret.replace(rreturn, "") :\n
+\t\t\t\t\t// handle cases where value is null/undef or number\n
+\t\t\t\t\tret == null ? "" : ret;\n
+\t\t\t}\n
+\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tisFunction = jQuery.isFunction( value );\n
+\n
+\t\treturn this.each(function( i ) {\n
+\t\t\tvar val;\n
+\n
+\t\t\tif ( this.nodeType !== 1 ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tif ( isFunction ) {\n
+\t\t\t\tval = value.call( this, i, jQuery( this ).val() );\n
+\t\t\t} else {\n
+\t\t\t\tval = value;\n
+\t\t\t}\n
+\n
+\t\t\t// Treat null/undefined as ""; convert numbers to string\n
+\t\t\tif ( val == null ) {\n
+\t\t\t\tval = "";\n
+\t\t\t} else if ( typeof val === "number" ) {\n
+\t\t\t\tval += "";\n
+\t\t\t} else if ( jQuery.isArray( val ) ) {\n
+\t\t\t\tval = jQuery.map(val, function ( value ) {\n
+\t\t\t\t\treturn value == null ? "" : value + "";\n
+\t\t\t\t});\n
+\t\t\t}\n
+\n
+\t\t\thooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];\n
+\n
+\t\t\t// If set returns undefined, fall back to normal setting\n
+\t\t\tif ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {\n
+\t\t\t\tthis.value = val;\n
+\t\t\t}\n
+\t\t});\n
+\t}\n
+});\n
+\n
+jQuery.extend({\n
+\tvalHooks: {\n
+\t\toption: {\n
+\t\t\tget: function( elem ) {\n
+\t\t\t\t// attributes.value is undefined in Blackberry 4.7 but\n
+\t\t\t\t// uses .value. See #6932\n
+\t\t\t\tvar val = elem.attributes.value;\n
+\t\t\t\treturn !val || val.specified ? elem.value : elem.text;\n
+\t\t\t}\n
+\t\t},\n
+\t\tselect: {\n
+\t\t\tget: function( elem ) {\n
+\t\t\t\tvar value, option,\n
+\t\t\t\t\toptions = elem.options,\n
+\t\t\t\t\tindex = elem.selectedIndex,\n
+\t\t\t\t\tone = elem.type === "select-one" || index < 0,\n
+\t\t\t\t\tvalues = one ? null : [],\n
+\t\t\t\t\tmax = one ? index + 1 : options.length,\n
+\t\t\t\t\ti = index < 0 ?\n
+\t\t\t\t\t\tmax :\n
+\t\t\t\t\t\tone ? index : 0;\n
+\n
+\t\t\t\t// Loop through all the selected options\n
+\t\t\t\tfor ( ; i < max; i++ ) {\n
+\t\t\t\t\toption = options[ i ];\n
+\n
+\t\t\t\t\t// IE6-9 doesn\'t update selected after form reset (#2551)\n
+\t\t\t\t\tif ( ( option.selected || i =
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+== index ) &&\n
+\t\t\t\t\t\t\t// Don\'t return options that are disabled or in a disabled optgroup\n
+\t\t\t\t\t\t\t( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&\n
+\t\t\t\t\t\t\t( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {\n
+\n
+\t\t\t\t\t\t// Get the specific value for the option\n
+\t\t\t\t\t\tvalue = jQuery( option ).val();\n
+\n
+\t\t\t\t\t\t// We don\'t need an array for one selects\n
+\t\t\t\t\t\tif ( one ) {\n
+\t\t\t\t\t\t\treturn value;\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\t// Multi-Selects return an array\n
+\t\t\t\t\t\tvalues.push( value );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\treturn values;\n
+\t\t\t},\n
+\n
+\t\t\tset: function( elem, value ) {\n
+\t\t\t\tvar optionSet, option,\n
+\t\t\t\t\toptions = elem.options,\n
+\t\t\t\t\tvalues = jQuery.makeArray( value ),\n
+\t\t\t\t\ti = options.length;\n
+\n
+\t\t\t\twhile ( i-- ) {\n
+\t\t\t\t\toption = options[ i ];\n
+\t\t\t\t\tif ( (option.selected = jQuery.inArray( jQuery(option).val(), values ) >= 0) ) {\n
+\t\t\t\t\t\toptionSet = true;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// force browsers to behave consistently when non-matching value is set\n
+\t\t\t\tif ( !optionSet ) {\n
+\t\t\t\t\telem.selectedIndex = -1;\n
+\t\t\t\t}\n
+\t\t\t\treturn values;\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\tattr: function( elem, name, value ) {\n
+\t\tvar hooks, ret,\n
+\t\t\tnType = elem.nodeType;\n
+\n
+\t\t// don\'t get/set attributes on text, comment and attribute nodes\n
+\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Fallback to prop when attributes are not supported\n
+\t\tif ( typeof elem.getAttribute === core_strundefined ) {\n
+\t\t\treturn jQuery.prop( elem, name, value );\n
+\t\t}\n
+\n
+\t\t// All attributes are lowercase\n
+\t\t// Grab necessary hook if one is defined\n
+\t\tif ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {\n
+\t\t\tname = name.toLowerCase();\n
+\t\t\thooks = jQuery.attrHooks[ name ] ||\n
+\t\t\t\t( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );\n
+\t\t}\n
+\n
+\t\tif ( value !== undefined ) {\n
+\n
+\t\t\tif ( value === null ) {\n
+\t\t\t\tjQuery.removeAttr( elem, name );\n
+\n
+\t\t\t} else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {\n
+\t\t\t\treturn ret;\n
+\n
+\t\t\t} else {\n
+\t\t\t\telem.setAttribute( name, value + "" );\n
+\t\t\t\treturn value;\n
+\t\t\t}\n
+\n
+\t\t} else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {\n
+\t\t\treturn ret;\n
+\n
+\t\t} else {\n
+\t\t\tret = jQuery.find.attr( elem, name );\n
+\n
+\t\t\t// Non-existent attributes return null, we normalize to undefined\n
+\t\t\treturn ret == null ?\n
+\t\t\t\tundefined :\n
+\t\t\t\tret;\n
+\t\t}\n
+\t},\n
+\n
+\tremoveAttr: function( elem, value ) {\n
+\t\tvar name, propName,\n
+\t\t\ti = 0,\n
+\t\t\tattrNames = value && value.match( core_rnotwhite );\n
+\n
+\t\tif ( attrNames && elem.nodeType === 1 ) {\n
+\t\t\twhile ( (name = attrNames[i++]) ) {\n
+\t\t\t\tpropName = jQuery.propFix[ name ] || name;\n
+\n
+\t\t\t\t// Boolean attributes get special treatment (#10870)\n
+\t\t\t\tif ( jQuery.expr.match.bool.test( name ) ) {\n
+\t\t\t\t\t// Set corresponding property to false\n
+\t\t\t\t\telem[ propName ] = false;\n
+\t\t\t\t}\n
+\n
+\t\t\t\telem.removeAttribute( name );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\tattrHooks: {\n
+\t\ttype: {\n
+\t\t\tset: function( elem, value ) {\n
+\t\t\t\tif ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {\n
+\t\t\t\t\t// Setting the type on a radio button after the value resets the value in IE6-9\n
+\t\t\t\t\t// Reset value to default in case type is set after value during creation\n
+\t\t\t\t\tvar val = elem.value;\n
+\t\t\t\t\telem.setAttribute( "type", value );\n
+\t\t\t\t\tif ( val ) {\n
+\t\t\t\t\t\telem.value = val;\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn value;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\tpropFix: {\n
+\t\t"for": "htmlFor",\n
+\t\t"class": "className"\n
+\t},\n
+\n
+\tprop: function( elem, name, value ) {\n
+\t\tvar ret, hooks, notxml,\n
+\t\t\tnType = elem.nodeType;\n
+\n
+\t\t// don\'t get/set properties on text, comment and attribute nodes\n
+\t\tif ( !elem || nType === 3 || nType === 8 || nType === 2 ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tnotxml = nType !== 1 || !jQuery.isXMLDoc( elem );\n
+\n
+\t\tif ( notxml ) {\n
+\t\t\t// Fix name and attach hooks\n
+\t\t\tname = jQuery.propFix[ name ] || name;\n
+\t\t\thooks = jQuery.propHooks[ name ];\n
+\t\t}\n
+\n
+\t\tif ( value !== undefined ) {\n
+\t\t\treturn hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?\n
+\t\t\t\tret :\n
+\t\t\t\t( elem[ name ] = value );\n
+\n
+\t\t} else {\n
+\t\t\treturn hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?\n
+\t\t\t\tret :\n
+\t\t\t\telem[ name ];\n
+\t\t}\n
+\t},\n
+\n
+\tpropHooks: {\n
+\t\ttabIndex: {\n
+\t\t\tget: function( elem ) {\n
+\t\t\t\treturn elem.hasAttribute( "tabindex" ) || rfocusable.test( elem.nodeName ) || elem.href ?\n
+\t\t\t\t\telem.tabIndex :\n
+\t\t\t\t\t-1;\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+});\n
+\n
+// Hooks for boolean attributes\n
+boolHook = {\n
+\tset: function( elem, value, name ) {\n
+\t\tif ( value === false ) {\n
+\t\t\t// Remove boolean attributes when set to false\n
+\t\t\tjQuery.removeAttr( elem, name );\n
+\t\t} else {\n
+\t\t\telem.setAttribute( name, name );\n
+\t\t}\n
+\t\treturn name;\n
+\t}\n
+};\n
+jQuery.each( jQuery.expr.match.bool.source.match( /\\w+/g ), function( i, name ) {\n
+\tvar getter = jQuery.expr.attrHandle[ name ] || jQuery.find.attr;\n
+\n
+\tjQuery.expr.attrHandle[ name ] = function( elem, name, isXML ) {\n
+\t\tvar fn = jQuery.expr.attrHandle[ name ],\n
+\t\t\tret = isXML ?\n
+\t\t\t\tundefined :\n
+\t\t\t\t/* jshint eqeqeq: false */\n
+\t\t\t\t// Temporarily disable this handler to check existence\n
+\t\t\t\t(jQuery.expr.attrHandle[ name ] = undefined) !=\n
+\t\t\t\t\tgetter( elem, name, isXML ) ?\n
+\n
+\t\t\t\t\tname.toLowerCase() :\n
+\t\t\t\t\tnull;\n
+\n
+\t\t// Restore handler\n
+\t\tjQuery.expr.attrHandle[ name ] = fn;\n
+\n
+\t\treturn ret;\n
+\t};\n
+});\n
+\n
+// Support: IE9+\n
+// Selectedness for an option in an optgroup can be inaccurate\n
+if ( !jQuery.support.optSelected ) {\n
+\tjQuery.propHooks.selected = {\n
+\t\tget: function( elem ) {\n
+\t\t\tvar parent = elem.parentNode;\n
+\t\t\tif ( parent && parent.parentNode ) {\n
+\t\t\t\tparent.parentNode.selectedIndex;\n
+\t\t\t}\n
+\t\t\treturn null;\n
+\t\t}\n
+\t};\n
+}\n
+\n
+jQuery.each([\n
+\t"tabIndex",\n
+\t"readOnly",\n
+\t"maxLength",\n
+\t"cellSpacing",\n
+\t"cellPadding",\n
+\t"rowSpan",\n
+\t"colSpan",\n
+\t"useMap",\n
+\t"frameBorder",\n
+\t"contentEditable"\n
+], function() {\n
+\tjQuery.propFix[ this.toLowerCase() ] = this;\n
+});\n
+\n
+// Radios and checkboxes getter/setter\n
+jQuery.each([ "radio", "checkbox" ], function() {\n
+\tjQuery.valHooks[ this ] = {\n
+\t\tset: function( elem, value ) {\n
+\t\t\tif ( jQuery.isArray( value ) ) {\n
+\t\t\t\treturn ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );\n
+\t\t\t}\n
+\t\t}\n
+\t};\n
+\tif ( !jQuery.support.checkOn ) {\n
+\t\tjQuery.valHooks[ this ].get = function( elem ) {\n
+\t\t\t// Support: Webkit\n
+\t\t\t// "" is returned instead of "on" if a value isn\'t specified\n
+\t\t\treturn elem.getAttribute("value") === null ? "on" : elem.value;\n
+\t\t};\n
+\t}\n
+});\n
+var rkeyEvent = /^key/,\n
+\trmouseEvent = /^(?:mouse|contextmenu)|click/,\n
+\trfocusMorph = /^(?:focusinfocus|focusoutblur)$/,\n
+\trtypenamespace = /^([^.]*)(?:\\.(.+)|)$/;\n
+\n
+function returnTrue() {\n
+\treturn true;\n
+}\n
+\n
+function returnFalse() {\n
+\treturn false;\n
+}\n
+\n
+function safeActiveElement() {\n
+\ttry {\n
+\t\treturn document.activeElement;\n
+\t} catch ( err ) { }\n
+}\n
+\n
+/*\n
+ * Helper functions for managing events -- not part of the public interface.\n
+ * Props to Dean Edwards\' addEvent library for many of the ideas.\n
+ */\n
+jQuery.event = {\n
+\n
+\tglobal: {},\n
+\n
+\tadd: function( elem, types, handler, data, selector ) {\n
+\n
+\t\tvar handleObjIn, eventHandle, tmp,\n
+\t\t\tevents, t, handleObj,\n
+\t\t\tspecial, handlers, type, namespaces, origType,\n
+\t\t\telemData = data_priv.get( elem );\n
+\n
+\t\t// Don\'t attach events to noData or text/comment nodes (but allow plain objects)\n
+\t\tif ( !elemData ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Caller can pass in an object of custom data in lieu of the handler\n
+\t\tif ( handler.handler ) {\n
+\t\t\thandleObjIn = handler;\n
+\t\t\thandler = handleObjIn.handler;\n
+\t\t\tselector = handleObjIn.selector;\n
+\t\t}\n
+\n
+\t\t// Make sure that the handler has a unique ID, used to find/remove it later\n
+\t\tif ( !handler.guid ) {\n
+\t\t\thandler.guid = jQuery.guid++;\n
+\t\t}\n
+\n
+\t\t// Init the element\'s event structure and main handler, if this is the first\n
+\t\tif ( !(events = elemData.events) ) {\n
+\t\t\tevents = elemData.events = {};\n
+\t\t}\n
+\t\tif ( !(eventHandle = elemData.handle) ) {\n
+\t\t\teventHandle = elemData.handle = function( e ) {\n
+\t\t\t\t// Discard the second event of a jQuery.event.trigger() and\n
+\t\t\t\t// when an event is called after a page has unloaded\n
+\t\t\t\treturn typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ?\n
+\t\t\t\t\tjQuery.event.dispatch.apply( eventHandle.elem, arguments ) :\n
+\t\t\t\t\tundefined;\n
+\t\t\t};\n
+\t\t\t// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events\n
+\t\t\teventHandle.elem = elem;\n
+\t\t}\n
+\n
+\t\t// Handle multiple events separated by a space\n
+\t\ttypes = ( types || "" ).match( core_rnotwhite ) || [""];\n
+\t\tt = types.length;\n
+\t\twhile ( t-- ) {\n
+\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n
+\t\t\ttype = origType = tmp[1];\n
+\t\t\tnamespaces = ( tmp[2] || "" ).split( "." ).sort();\n
+\n
+\t\t\t// There *must* be a type, no attaching namespace-only handlers\n
+\t\t\tif ( !type ) {\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\t// If event changes its type, use the special event handlers for the changed type\n
+\t\t\tspecial = jQuery.event.special[ type ] || {};\n
+\n
+\t\t\t// If selector defined, determine special event api type, otherwise given type\n
+\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n
+\n
+\t\t\t// Update special based on newly reset type\n
+\t\t\tspecial = jQuery.event.special[ type ] || {};\n
+\n
+\t\t\t// handleObj is passed to all event handlers\n
+\t\t\thandleObj = jQuery.extend({\n
+\t\t\t\ttype: type,\n
+\t\t\t\torigType: origType,\n
+\t\t\t\tdata: data,\n
+\t\t\t\thandler: handler,\n
+\t\t\t\tguid: handler.guid,\n
+\t\t\t\tselector: selector,\n
+\t\t\t\tneedsContext: selector && jQuery.expr.match.needsContext.test( selector ),\n
+\t\t\t\tnamespace: namespaces.join(".")\n
+\t\t\t}, handleObjIn );\n
+\n
+\t\t\t// Init the event handler queue if we\'re the first\n
+\t\t\tif ( !(handlers = events[ type ]) ) {\n
+\t\t\t\thandlers = events[ type ] = [];\n
+\t\t\t\thandlers.delegateCount = 0;\n
+\n
+\t\t\t\t// Only use addEventListener if the special events handler returns false\n
+\t\t\t\tif ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {\n
+\t\t\t\t\tif ( elem.addEventListener ) {\n
+\t\t\t\t\t\telem.addEventListener( type, eventHandle, false );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif ( special.add ) {\n
+\t\t\t\tspecial.add.call( elem, handleObj );\n
+\n
+\t\t\t\tif ( !handleObj.handler.guid ) {\n
+\t\t\t\t\thandleObj.handler.guid = handler.guid;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// Add to the element\'s handler list, delegates in front\n
+\t\t\tif ( selector ) {\n
+\t\t\t\thandlers.splice( handlers.delegateCount++, 0, handleObj );\n
+\t\t\t} else {\n
+\t\t\t\thandlers.push( handleObj );\n
+\t\t\t}\n
+\n
+\t\t\t// Keep track of which events have ever been used, for event optimization\n
+\t\t\tjQuery.event.global[ type ] = true;\n
+\t\t}\n
+\n
+\t\t// Nullify elem to prevent memory leaks in IE\n
+\t\telem = null;\n
+\t},\n
+\n
+\t// Detach an event or set of events from an element\n
+\tremove: function( elem, types, handler, selector, mappedTypes ) {\n
+\n
+\t\tvar j, origCount, tmp,\n
+\t\t\tevents, t, handleObj,\n
+\t\t\tspecial, handlers, type, namespaces, origType,\n
+\t\t\telemData = data_priv.hasData( elem ) && data_priv.get( elem );\n
+\n
+\t\tif ( !elemData || !(events = elemData.events) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Once for each type.namespace in types; type may be omitted\n
+\t\ttypes = ( types || "" ).match( core_rnotwhite ) || [""];\n
+\t\tt = types.length;\n
+\t\twhile ( t-- ) {\n
+\t\t\ttmp = rtypenamespace.exec( types[t] ) || [];\n
+\t\t\ttype = origType = tmp[1];\n
+\t\t\tnamespaces = ( tmp[2] || "" ).split( "." ).sort();\n
+\n
+\t\t\t// Unbind all events (on this namespace, if provided) for the element\n
+\t\t\tif ( !type ) {\n
+\t\t\t\tfor ( type in events ) {\n
+\t\t\t\t\tjQuery.event.remove( elem, type + types[ t ], handler, selector, true );\n
+\t\t\t\t}\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\tspecial = jQuery.event.special[ type ] || {};\n
+\t\t\ttype = ( selector ? special.delegateType : special.bindType ) || type;\n
+\t\t\thandlers = events[ type ] || [];\n
+\t\t\ttmp = tmp[2] && new RegExp( "(^|\\\\.)" + namespaces.join("\\\\.(?:.*\\\\.|)") + "(\\\\.|$)" );\n
+\n
+\t\t\t// Remove matching events\n
+\t\t\torigCount = j = handlers.length;\n
+\t\t\twhile ( j-- ) {\n
+\t\t\t\thandleObj = handlers[ j ];\n
+\n
+\t\t\t\tif ( ( mappedTypes || origType === handleObj.origType ) &&\n
+\t\t\t\t\t( !handler || handler.guid === handleObj.guid ) &&\n
+\t\t\t\t\t( !tmp || tmp.test( handleObj.namespace ) ) &&\n
+\t\t\t\t\t( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {\n
+\t\t\t\t\thandlers.splice( j, 1 );\n
+\n
+\t\t\t\t\tif ( handleObj.selector ) {\n
+\t\t\t\t\t\thandlers.delegateCount--;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif ( special.remove ) {\n
+\t\t\t\t\t\tspecial.remove.call( elem, handleObj );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// Remove generic event handler if we removed something and no more handlers exist\n
+\t\t\t// (avoids potential for endless recursion during removal of special event handlers)\n
+\t\t\tif ( origCount && !handlers.length ) {\n
+\t\t\t\tif ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {\n
+\t\t\t\t\tjQuery.removeEvent( elem, type, elemData.handle );\n
+\t\t\t\t}\n
+\n
+\t\t\t\tdelete events[ type ];\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Remove the expando if it\'s no longer used\n
+\t\tif ( jQuery.isEmptyObject( events ) ) {\n
+\t\t\tdelete elemData.handle;\n
+\t\t\tdata_priv.remove( elem, "events" );\n
+\t\t}\n
+\t},\n
+\n
+\ttrigger: function( event, data, elem, onlyHandlers ) {\n
+\n
+\t\tvar i, cur, tmp, bubbleType, ontype, handle, special,\n
+\t\t\teventPath = [ elem || document ],\n
+\t\t\ttype = core_hasOwn.call( event, "type" ) ? event.type : event,\n
+\t\t\tnamespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];\n
+\n
+\t\tcur = tmp = elem = elem || document;\n
+\n
+\t\t// Don\'t do events on text and comment nodes\n
+\t\tif ( elem.nodeType === 3 || elem.nodeType === 8 ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// focus/blur morphs to focusin/out; ensure we\'re not firing them right now\n
+\t\tif ( rfocusMorph.test( type + jQuery.event.triggered ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( type.indexOf(".") >= 0 ) {\n
+\t\t\t// Namespaced trigger; create a regexp to match event type in handle()\n
+\t\t\tnamespaces = type.split(".");\n
+\t\t\ttype = namespaces.shift();\n
+\t\t\tnamespaces.sort();\n
+\t\t}\n
+\t\tontype = type.indexOf(":") < 0 && "on" + type;\n
+\n
+\t\t// Caller can pass in a jQuery.Event object, Object, or just an event type string\n
+\t\tevent = event[ jQuery.expando ] ?\n
+\t\t\tevent :\n
+\t\t\tnew jQuery.Event( type, typeof event === "object" && event );\n
+\n
+\t\t// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)\n
+\t\tevent.isTrigger = onlyHandlers ? 2 : 3;\n
+\t\tevent.namespace = namespaces.join(".");\n
+\t\tevent.namespace_re = event.namespace ?\n
+\t\t\tnew RegExp( "(^|\\\\.)" + namespaces.join("\\\\.(?:.*\\\\.|)") + "(\\\\.|$)" ) :\n
+\t\t\tnull;\n
+\n
+\t\t// Clean up the event in case it is being reused\n
+\t\tevent.result = undefined;\n
+\t\tif ( !event.target ) {\n
+\t\t\tevent.target = elem;\n
+\t\t}\n
+\n
+\t\t// Clone any incoming data and prepend the event, creating the handler arg list\n
+\t\tdata = data == null ?\n
+\t\t\t[ event ] :\n
+\t\t\tjQuery.makeArray( data, [ event ] );\n
+\n
+\t\t// Allow special events to draw outside the lines\n
+\t\tspecial = jQuery.event.special[ type ] || {};\n
+\t\tif ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Determine event propagation path in advance, per W3C events spec (#9951)\n
+\t\t// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)\n
+\t\tif ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {\n
+\n
+\t\t\tbubbleType = special.delegateType || type;\n
+\t\t\tif ( !rfocusMorph.test( bubbleType + type ) ) {\n
+\t\t\t\tcur = cur.parentNode;\n
+\t\t\t}\n
+\t\t\tfor ( ; cur; cur = cur.parentNode ) {\n
+\t\t\t\teventPath.push( cur );\n
+\t\t\t\ttmp = cur;\n
+\t\t\t}\n
+\n
+\t\t\t// Only add window if we got to document (e.g., not plain obj or detached DOM)\n
+\t\t\tif ( tmp === (elem.ownerDocument || document) ) {\n
+\t\t\t\teventPath.push( tmp.defaultView || tmp.parentWindow || window );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Fire handlers on the event path\n
+\t\ti = 0;\n
+\t\twhile ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {\n
+\n
+\t\t\tevent.type = i > 1 ?\n
+\t\t\t\tbubbleType :\n
+\t\t\t\tspecial.bindType || type;\n
+\n
+\t\t\t// jQuery handler\n
+\t\t\thandle = ( data_priv.get( cur, "events" ) || {} )[ event.type ] && data_priv.get( cur, "handle" );\n
+\t\t\tif ( handle ) {\n
+\t\t\t\thandle.apply( cur, data );\n
+\t\t\t}\n
+\n
+\t\t\t// Native handler\n
+\t\t\thandle = ontype && cur[ ontype ];\n
+\t\t\tif ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t}\n
+\t\t}\n
+\t\tevent.type = type;\n
+\n
+\t\t// If nobody prevented the default action, do it now\n
+\t\tif ( !onlyHandlers && !event.isDefaultPrevented() ) {\n
+\n
+\t\t\tif ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&\n
+\t\t\t\tjQuery.acceptData( elem ) ) {\n
+\n
+\t\t\t\t// Call a native DOM method on the target with the same name name as the event.\n
+\t\t\t\t// Don\'t do default actions on window, that\'s where global variables be (#6170)\n
+\t\t\t\tif ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {\n
+\n
+\t\t\t\t\t// Don\'t re-trigger an onFOO event when we call its FOO() method\n
+\t\t\t\t\ttmp = elem[ ontype ];\n
+\n
+\t\t\t\t\tif ( tmp ) {\n
+\t\t\t\t\t\telem[ ontype ] = null;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// Prevent re-triggering of the same event, since we already bubbled it above\n
+\t\t\t\t\tjQuery.event.triggered = type;\n
+\t\t\t\t\telem[ type ]();\n
+\t\t\t\t\tjQuery.event.triggered = undefined;\n
+\n
+\t\t\t\t\tif ( tmp ) {\n
+\t\t\t\t\t\telem[ ontype ] = tmp;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn event.result;\n
+\t},\n
+\n
+\tdispatch: function( event ) {\n
+\n
+\t\t// Make a writable jQuery.Event from the native event object\n
+\t\tevent = jQuery.event.fix( event );\n
+\n
+\t\tvar i, j, ret, matched, handleObj,\n
+\t\t\thandlerQueue = [],\n
+\t\t\targs = core_slice.call( arguments ),\n
+\t\t\thandlers = ( data_priv.get( this, "events" ) || {} )[ event.type ] || [],\n
+\t\t\tspecial = jQuery.event.special[ event.type ] || {};\n
+\n
+\t\t// Use the fix-ed jQuery.Event rather than the (read-only) native event\n
+\t\targs[0] = event;\n
+\t\tevent.delegateTarget = this;\n
+\n
+\t\t// Call the preDispatch hook for the mapped type, and let it bail if desired\n
+\t\tif ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Determine handlers\n
+\t\thandlerQueue = jQuery.event.handlers.call( this, event, handlers );\n
+\n
+\t\t// Run delegates first; they may want to stop propagation beneath us\n
+\t\ti = 0;\n
+\t\twhile ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {\n
+\t\t\tevent.currentTarget = matched.elem;\n
+\n
+\t\t\tj = 0;\n
+\t\t\twhile ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {\n
+\n
+\t\t\t\t// Triggered event must either 1) have no namespace, or\n
+\t\t\t\t// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).\n
+\t\t\t\tif ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {\n
+\n
+\t\t\t\t\tevent.handleObj = handleObj;\n
+\t\t\t\t\tevent.data = handleObj.data;\n
+\n
+\t\t\t\t\tret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )\n
+\t\t\t\t\t\t\t.apply( matched.elem, args );\n
+\n
+\t\t\t\t\tif ( ret !== undefined ) {\n
+\t\t\t\t\t\tif ( (event.result = ret) === false ) {\n
+\t\t\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\t\t\tevent.stopPropagation();\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Call the postDispatch hook for the mapped type\n
+\t\tif ( special.postDispatch ) {\n
+\t\t\tspecial.postDispatch.call( this, event );\n
+\t\t}\n
+\n
+\t\treturn event.result;\n
+\t},\n
+\n
+\thandlers: function( event, handlers ) {\n
+\t\tvar i, matches, sel, handleObj,\n
+\t\t\thandlerQueue = [],\n
+\t\t\tdelegateCount = handlers.delegateCount,\n
+\t\t\tcur = event.target;\n
+\n
+\t\t// Find delegate handlers\n
+\t\t// Black-hole SVG <use> instance trees (#13180)\n
+\t\t// Avoid non-left-click bubbling in Firefox (#3861)\n
+\t\tif ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {\n
+\n
+\t\t\tfor ( ; cur !== this; cur = cur.parentNode || this ) {\n
+\n
+\t\t\t\t// Don\'t process clicks on disabled elements (#6911, #8165, #11382, #11764)\n
+\t\t\t\tif ( cur.disabled !== true || event.type !== "click" ) {\n
+\t\t\t\t\tmatches = [];\n
+\t\t\t\t\tfor ( i = 0; i < delegateCount; i++ ) {\n
+\t\t\t\t\t\thandleObj = handlers[ i ];\n
+\n
+\t\t\t\t\t\t// Don\'t conflict with Object.prototype properties (#13203)\n
+\t\t\t\t\t\tsel = handleObj.selector + " ";\n
+\n
+\t\t\t\t\t\tif ( matches[ sel ] === undefined ) {\n
+\t\t\t\t\t\t\tmatches[ sel ] = handleObj.needsContext ?\n
+\t\t\t\t\t\t\t\tjQuery( sel, this ).index( cur ) >= 0 :\n
+\t\t\t\t\t\t\t\tjQuery.find( sel, this, null, [ cur ] ).length;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\tif ( matches[ sel ] ) {\n
+\t\t\t\t\t\t\tmatches.push( handleObj );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif ( matches.length ) {\n
+\t\t\t\t\t\thandlerQueue.push({ elem: cur, handlers: matches });\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Add the remaining (directly-bound) handlers\n
+\t\tif ( delegateCount < handlers.length ) {\n
+\t\t\thandlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });\n
+\t\t}\n
+\n
+\t\treturn handlerQueue;\n
+\t},\n
+\n
+\t// Includes some event props shared by KeyEvent and MouseEvent\n
+\tprops: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),\n
+\n
+\tfixHooks: {},\n
+\n
+\tkeyHooks: {\n
+\t\tprops: "char charCode key keyCode".split(" "),\n
+\t\tfilter: function( event, original ) {\n
+\n
+\t\t\t// Add which for key events\n
+\t\t\tif ( event.which == null ) {\n
+\t\t\t\tevent.which = original.charCode != null ? original.charCode : original.keyCode;\n
+\t\t\t}\n
+\n
+\t\t\treturn event;\n
+\t\t}\n
+\t},\n
+\n
+\tmouseHooks: {\n
+\t\tprops: "button buttons clientX clientY offsetX offsetY pageX pageY screenX screenY toElement".split(" "),\n
+\t\tfilter: function( event, original ) {\n
+\t\t\tvar eventDoc, doc, body,\n
+\t\t\t\tbutton = original.button;\n
+\n
+\t\t\t// Calculate pageX/Y if missing and clientX/Y available\n
+\t\t\tif ( event.pageX == null && original.clientX != null ) {\n
+\t\t\t\teventDoc = event.target.ownerDocument || document;\n
+\t\t\t\tdoc = eventDoc.documentElement;\n
+\t\t\t\tbody = eventDoc.body;\n
+\n
+\t\t\t\tevent.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );\n
+\t\t\t\tevent.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );\n
+\t\t\t}\n
+\n
+\t\t\t// Add which for click: 1 === left; 2 === middle; 3 === right\n
+\t\t\t// Note: button is not normalized, so don\'t use it\n
+\t\t\tif ( !event.which && button !== undefined ) {\n
+\t\t\t\tevent.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );\n
+\t\t\t}\n
+\n
+\t\t\treturn event;\n
+\t\t}\n
+\t},\n
+\n
+\tfix: function( event ) {\n
+\t\tif ( event[ jQuery.expando ] ) {\n
+\t\t\treturn event;\n
+\t\t}\n
+\n
+\t\t// Create a writable copy of the event object and normalize some properties\n
+\t\tvar i, prop, copy,\n
+\t\t\ttype = event.type,\n
+\t\t\toriginalEvent = event,\n
+\t\t\tfixHook = this.fixHooks[ type ];\n
+\n
+\t\tif ( !fixHook ) {\n
+\t\t\tthis.fixHooks[ type ] = fixHook =\n
+\t\t\t\trmouseEvent.test( type ) ? this.mouseHooks :\n
+\t\t\t\trkeyEvent.test( type ) ? this.keyHooks :\n
+\t\t\t\t{};\n
+\t\t}\n
+\t\tcopy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;\n
+\n
+\t\tevent = new jQuery.Event( originalEvent );\n
+\n
+\t\ti = copy.length;\n
+\t\twhile ( i-- ) {\n
+\t\t\tprop = copy[ i ];\n
+\t\t\tevent[ prop ] = originalEvent[ prop ];\n
+\t\t}\n
+\n
+\t\t// Support: Cordova 2.5 (WebKit) (#13255)\n
+\t\t// All events should have a target; Cordova deviceready doesn\'t\n
+\t\tif ( !event.target ) {\n
+\t\t\tevent.target = document;\n
+\t\t}\n
+\n
+\t\t// Support: Safari 6.0+, Chrome < 28\n
+\t\t// Target should not be a text node (#504, #13143)\n
+\t\tif ( event.target.nodeType === 3 ) {\n
+\t\t\tevent.target = event.target.parentNode;\n
+\t\t}\n
+\n
+\t\treturn fixHook.filter? fixHook.filter( event, originalEvent ) : event;\n
+\t},\n
+\n
+\tspecial: {\n
+\t\tload: {\n
+\t\t\t// Prevent triggered image.load events from bubbling to window.load\n
+\t\t\tnoBubble: true\n
+\t\t},\n
+\t\tfocus: {\n
+\t\t\t// Fire native event if possible so blur/focus sequence is correct\n
+\t\t\ttrigger: function() {\n
+\t\t\t\tif ( this !== safeActiveElement() && this.focus ) {\n
+\t\t\t\t\tthis.focus();\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tdelegateType: "focusin"\n
+\t\t},\n
+\t\tblur: {\n
+\t\t\ttrigger: function() {\n
+\t\t\t\tif ( this === safeActiveElement() && this.blur ) {\n
+\t\t\t\t\tthis.blur();\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tdelegateType: "focusout"\n
+\t\t},\n
+\t\tclick: {\n
+\t\t\t// For checkbox, fire native event so checked state will be right\n
+\t\t\ttrigger: function() {\n
+\t\t\t\tif ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {\n
+\t\t\t\t\tthis.click();\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t},\n
+\n
+\t\t\t// For cross-browser consistency, don\'t fire native .click() on links\n
+\t\t\t_default: function( event ) {\n
+\t\t\t\treturn jQuery.nodeName( event.target, "a" );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\tbeforeunload: {\n
+\t\t\tpostDispatch: function( event ) {\n
+\n
+\t\t\t\t// Support: Firefox 20+\n
+\t\t\t\t// Firefox doesn\'t alert if the returnValue field is not set.\n
+\t\t\t\tif ( event.result !== undefined ) {\n
+\t\t\t\t\tevent.originalEvent.returnValue = event.result;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\tsimulate: function( type, elem, event, bubble ) {\n
+\t\t// Piggyback on a donor event to simulate a different one.\n
+\t\t// Fake originalEvent to avoid donor\'s stopPropagation, but if the\n
+\t\t// simulated event prevents default then we do the same on the donor.\n
+\t\tvar e = jQuery.extend(\n
+\t\t\tnew jQuery.Event(),\n
+\t\t\tevent,\n
+\t\t\t{\n
+\t\t\t\ttype: type,\n
+\t\t\t\tisSimulated: true,\n
+\t\t\t\toriginalEvent: {}\n
+\t\t\t}\n
+\t\t);\n
+\t\tif ( bubble ) {\n
+\t\t\tjQuery.event.trigger( e, null, elem );\n
+\t\t} else {\n
+\t\t\tjQuery.event.dispatch.call( elem, e );\n
+\t\t}\n
+\t\tif ( e.isDefaultPrevented() ) {\n
+\t\t\tevent.preventDefault();\n
+\t\t}\n
+\t}\n
+};\n
+\n
+jQuery.removeEvent = function( elem, type, handle ) {\n
+\tif ( elem.removeEventListener ) {\n
+\t\telem.removeEventListener( type, handle, false );\n
+\t}\n
+};\n
+\n
+jQuery.Event = function( src, props ) {\n
+\t// Allow instantiation without the \'new\' keyword\n
+\tif ( !(this instanceof jQuery.Event) ) {\n
+\t\treturn new jQuery.Event( src, props );\n
+\t}\n
+\n
+\t// Event object\n
+\tif ( src && src.type ) {\n
+\t\tthis.originalEvent = src;\n
+\t\tthis.type = src.type;\n
+\n
+\t\t// Events bubbling up the document may have been marked as prevented\n
+\t\t// by a handler lower down the tree; reflect the correct value.\n
+\t\tthis.isDefaultPrevented = ( src.defaultPrevented ||\n
+\t\t\tsrc.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse;\n
+\n
+\t// Event type\n
+\t} else {\n
+\t\tthis.type = src;\n
+\t}\n
+\n
+\t// Put explicitly provided properties onto the event object\n
+\tif ( props ) {\n
+\t\tjQuery.extend( this, props );\n
+\t}\n
+\n
+\t// Create a timestamp if incoming event doesn\'t have one\n
+\tthis.timeStamp = src && src.timeStamp || jQuery.now();\n
+\n
+\t// Mark it as fixed\n
+\tthis[ jQuery.expando ] = true;\n
+};\n
+\n
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding\n
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html\n
+jQuery.Event.prototype = {\n
+\tisDefaultPrevented: returnFalse,\n
+\tisPropagationStopped: returnFalse,\n
+\tisImmediatePropagationStopped: returnFalse,\n
+\n
+\tpreventDefault: function() {\n
+\t\tvar e = this.originalEvent;\n
+\n
+\t\tthis.isDefaultPrevented = returnTrue;\n
+\n
+\t\tif ( e && e.preventDefault ) {\n
+\t\t\te.preventDefault();\n
+\t\t}\n
+\t},\n
+\tstopPropagation: function() {\n
+\t\tvar e = this.originalEvent;\n
+\n
+\t\tthis.isPropagationStopped = returnTrue;\n
+\n
+\t\tif ( e && e.stopPropagation ) {\n
+\t\t\te.stopPropagation();\n
+\t\t}\n
+\t},\n
+\tstopImmediatePropagation: function() {\n
+\t\tthis.isImmediatePropagationStopped = returnTrue;\n
+\t\tthis.stopPropagation();\n
+\t}\n
+};\n
+\n
+// Create mouseenter/leave events using mouseover/out and event-time checks\n
+// Support: Chrome 15+\n
+jQuery.each({\n
+\tmouseenter: "mouseover",\n
+\tmouseleave: "mouseout"\n
+}, function( orig, fix ) {\n
+\tjQuery.event.special[ orig ] = {\n
+\t\tdelegateType: fix,\n
+\t\tbindType: fix,\n
+\n
+\t\thandle: function( event ) {\n
+\t\t\tvar ret,\n
+\t\t\t\ttarget = this,\n
+\t\t\t\trelated = event.relatedTarget,\n
+\t\t\t\thandleObj = event.handleObj;\n
+\n
+\t\t\t// For mousenter/leave call the handler if related is outside the target.\n
+\t\t\t// NB: No relatedTarget if the mouse left/entered the browser window\n
+\t\t\tif ( !related || (related !== target && !jQuery.contains( target, related )) ) {\n
+\t\t\t\tevent.type = handleObj.origType;\n
+\t\t\t\tret = handleObj.handler.apply( this, arguments );\n
+\t\t\t\tevent.type = fix;\n
+\t\t\t}\n
+\t\t\treturn ret;\n
+\t\t}\n
+\t};\n
+});\n
+\n
+// Create "bubbling" focus and blur events\n
+// Support: Firefox, Chrome, Safari\n
+if ( !jQuery.support.focusinBubbles ) {\n
+\tjQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {\n
+\n
+\t\t// Attach a single capturing handler while someone wants focusin/focusout\n
+\t\tvar attaches = 0,\n
+\t\t\thandler = function( event ) {\n
+\t\t\t\tjQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );\n
+\t\t\t};\n
+\n
+\t\tjQuery.event.special[ fix ] = {\n
+\t\t\tsetup: function() {\n
+\t\t\t\tif ( attaches++ === 0 ) {\n
+\t\t\t\t\tdocument.addEventListener( orig, handler, true );\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tteardown: function() {\n
+\t\t\t\tif ( --attaches === 0 ) {\n
+\t\t\t\t\tdocument.removeEventListener( orig, handler, true );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t};\n
+\t});\n
+}\n
+\n
+jQuery.fn.extend({\n
+\n
+\ton: function( types, selector, data, fn, /*INTERNAL*/ one ) {\n
+\t\tvar origFn, type;\n
+\n
+\t\t// Types can be a map of types/handlers\n
+\t\tif ( typeof types === "object" ) {\n
+\t\t\t// ( types-Object, selector, data )\n
+\t\t\tif ( typeof selector !== "string" ) {\n
+\t\t\t\t// ( types-Object, data )\n
+\t\t\t\tdata = data || selector;\n
+\t\t\t\tselector = undefined;\n
+\t\t\t}\n
+\t\t\tfor ( type in types ) {\n
+\t\t\t\tthis.on( type, selector, data, types[ type ], one );\n
+\t\t\t}\n
+\t\t\treturn this;\n
+\t\t}\n
+\n
+\t\tif ( data == null && fn == null ) {\n
+\t\t\t// ( types, fn )\n
+\t\t\tfn = selector;\n
+\t\t\tdata = selector = undefined;\n
+\t\t} else if ( fn == null ) {\n
+\t\t\tif ( typeof selector === "string" ) {\n
+\t\t\t\t// ( types, selector, fn )\n
+\t\t\t\tfn = data;\n
+\t\t\t\tdata = undefined;\n
+\t\t\t} else {\n
+\t\t\t\t// ( types, data, fn )\n
+\t\t\t\tfn = data;\n
+\t\t\t\tdata = selector;\n
+\t\t\t\tselector = undefined;\n
+\t\t\t}\n
+\t\t}\n
+\t\tif ( fn === false ) {\n
+\t\t\tfn = returnFalse;\n
+\t\t} else if ( !fn ) {\n
+\t\t\treturn this;\n
+\t\t}\n
+\n
+\t\tif ( one === 1 ) {\n
+\t\t\torigFn = fn;\n
+\t\t\tfn = function( event ) {\n
+\t\t\t\t// Can use an empty set, since event contains the info\n
+\t\t\t\tjQuery().off( event );\n
+\t\t\t\treturn origFn.apply( this, arguments );\n
+\t\t\t};\n
+\t\t\t// Use same guid so caller can remove using origFn\n
+\t\t\tfn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );\n
+\t\t}\n
+\t\treturn this.each( function() {\n
+\t\t\tjQuery.event.add( this, types, fn, data, selector );\n
+\t\t});\n
+\t},\n
+\tone: function( types, selector, data, fn ) {\n
+\t\treturn this.on( types, selector, data, fn, 1 );\n
+\t},\n
+\toff: function( types, selector, fn ) {\n
+\t\tvar handleObj, type;\n
+\t\tif ( types && types.preventDefault && types.handleObj ) {\n
+\t\t\t// ( event )  dispatched jQuery.Event\n
+\t\t\thandleObj = types.handleObj;\n
+\t\t\tjQuery( types.delegateTarget ).off(\n
+\t\t\t\thandleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,\n
+\t\t\t\thandleObj.selector,\n
+\t\t\t\thandleObj.handler\n
+\t\t\t);\n
+\t\t\treturn this;\n
+\t\t}\n
+\t\tif ( typeof types === "object" ) {\n
+\t\t\t// ( types-object [, selector] )\n
+\t\t\tfor ( type in types ) {\n
+\t\t\t\tthis.off( type, selector, types[ type ] );\n
+\t\t\t}\n
+\t\t\treturn this;\n
+\t\t}\n
+\t\tif ( selector === false || typeof selector === "function" ) {\n
+\t\t\t// ( types [, fn] )\n
+\t\t\tfn = selector;\n
+\t\t\tselector = undefined;\n
+\t\t}\n
+\t\tif ( fn === false ) {\n
+\t\t\tfn = returnFalse;\n
+\t\t}\n
+\t\treturn this.each(function() {\n
+\t\t\tjQuery.event.remove( this, types, fn, selector );\n
+\t\t});\n
+\t},\n
+\n
+\ttrigger: function( type, data ) {\n
+\t\treturn this.each(function() {\n
+\t\t\tjQuery.event.trigger( type, data, this );\n
+\t\t});\n
+\t},\n
+\ttriggerHandler: function( type, data ) {\n
+\t\tvar elem = this[0];\n
+\t\tif ( elem ) {\n
+\t\t\treturn jQuery.event.trigger( type, data, elem, true );\n
+\t\t}\n
+\t}\n
+});\n
+var isSimple = /^.[^:#\\[\\.,]*$/,\n
+\trparentsprev = /^(?:parents|prev(?:Until|All))/,\n
+\trneedsContext = jQuery.expr.match.needsContext,\n
+\t// methods guaranteed to produce a unique set when starting from a unique set\n
+\tguaranteedUnique = {\n
+\t\tchildren: true,\n
+\t\tcontents: true,\n
+\t\tnext: true,\n
+\t\tprev: true\n
+\t};\n
+\n
+jQuery.fn.extend({\n
+\tfind: function( selector ) {\n
+\t\tvar i,\n
+\t\t\tret = [],\n
+\t\t\tself = this,\n
+\t\t\tlen = self.length;\n
+\n
+\t\tif ( typeof selector !== "string" ) {\n
+\t\t\treturn this.pushStack( jQuery( selector ).filter(function() {\n
+\t\t\t\tfor ( i = 0; i < len; i++ ) {\n
+\t\t\t\t\tif ( jQuery.contains( self[ i ], this ) ) {\n
+\t\t\t\t\t\treturn true;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}) );\n
+\t\t}\n
+\n
+\t\tfor ( i = 0; i < len; i++ ) {\n
+\t\t\tjQuery.find( selector, self[ i ], ret );\n
+\t\t}\n
+\n
+\t\t// Needed because $( selector, context ) becomes $( context ).find( selector )\n
+\t\tret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );\n
+\t\tret.selector = this.selector ? this.selector + " " + selector : selector;\n
+\t\treturn ret;\n
+\t},\n
+\n
+\thas: function( target ) {\n
+\t\tvar targets = jQuery( target, this ),\n
+\t\t\tl = targets.length;\n
+\n
+\t\treturn this.filter(function() {\n
+\t\t\tvar i = 0;\n
+\t\t\tfor ( ; i < l; i++ ) {\n
+\t\t\t\tif ( jQuery.contains( this, targets[i] ) ) {\n
+\t\t\t\t\treturn true;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\tnot: function( selector ) {\n
+\t\treturn this.pushStack( winnow(this, selector || [], true) );\n
+\t},\n
+\n
+\tfilter: function( selector ) {\n
+\t\treturn this.pushStack( winnow(this, selector || [], false) );\n
+\t},\n
+\n
+\tis: function( selector ) {\n
+\t\treturn !!winnow(\n
+\t\t\tthis,\n
+\n
+\t\t\t// If this is a positional/relative selector, check membership in the returned set\n
+\t\t\t// so $("p:first").is("p:last") won\'t return true for a doc with two "p".\n
+\t\t\ttypeof selector === "string" && rneedsContext.test( selector ) ?\n
+\t\t\t\tjQuery( selector ) :\n
+\t\t\t\tselector || [],\n
+\t\t\tfalse\n
+\t\t).length;\n
+\t},\n
+\n
+\tclosest: function( selectors, context ) {\n
+\t\tvar cur,\n
+\t\t\ti = 0,\n
+\t\t\tl = this.length,\n
+\t\t\tmatched = [],\n
+\t\t\tpos = ( rneedsContext.test( selectors ) || typeof selectors !== "string" ) ?\n
+\t\t\t\tjQuery( selectors, context || this.context ) :\n
+\t\t\t\t0;\n
+\n
+\t\tfor ( ; i < l; i++ ) {\n
+\t\t\tfor ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {\n
+\t\t\t\t// Always skip document fragments\n
+\t\t\t\tif ( cur.nodeType < 11 && (pos ?\n
+\t\t\t\t\tpos.index(cur) > -1 :\n
+\n
+\t\t\t\t\t// Don\'t pass non-elements to Sizzle\n
+\t\t\t\t\tcur.nodeType === 1 &&\n
+\t\t\t\t\t\tjQuery.find.matchesSelector(cur, selectors)) ) {\n
+\n
+\t\t\t\t\tcur = matched.push( cur );\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );\n
+\t},\n
+\n
+\t// Determine the position of an element within\n
+\t// the matched set of elements\n
+\tindex: function( elem ) {\n
+\n
+\t\t// No argument, return index in parent\n
+\t\tif ( !elem ) {\n
+\t\t\treturn ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;\n
+\t\t}\n
+\n
+\t\t// index in selector\n
+\t\tif ( typeof elem === "string" ) {\n
+\t\t\treturn core_indexOf.call( jQuery( elem ), this[ 0 ] );\n
+\t\t}\n
+\n
+\t\t// Locate the position of the desired element\n
+\t\treturn core_indexOf.call( this,\n
+\n
+\t\t\t// If it receives a jQuery object, the first element is used\n
+\t\t\telem.jquery ? elem[ 0 ] : elem\n
+\t\t);\n
+\t},\n
+\n
+\tadd: function( selector, context ) {\n
+\t\tvar set = typeof selector === "string" ?\n
+\t\t\t\tjQuery( selector, context ) :\n
+\t\t\t\tjQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),\n
+\t\t\tall = jQuery.merge( this.get(), set );\n
+\n
+\t\treturn this.pushStack( jQuery.unique(all) );\n
+\t},\n
+\n
+\taddBack: function( selector ) {\n
+\t\treturn this.add( selector == null ?\n
+\t\t\tthis.prevObject : this.prevObject.filter(selector)\n
+\t\t);\n
+\t}\n
+});\n
+\n
+function sibling( cur, dir ) {\n
+\twhile ( (cur = cur[dir]) && cur.nodeType !== 1 ) {}\n
+\n
+\treturn cur;\n
+}\n
+\n
+jQuery.each({\n
+\tparent: function( elem ) {\n
+\t\tvar parent = elem.parentNode;\n
+\t\treturn parent && parent.nodeType !== 11 ? parent : null;\n
+\t},\n
+\tparents: function( elem ) {\n
+\t\treturn jQuery.dir( elem, "parentNode" );\n
+\t},\n
+\tparentsUntil: function( elem, i, until ) {\n
+\t\treturn jQuery.dir( elem, "parentNode", until );\n
+\t},\n
+\tnext: function( elem ) {\n
+\t\treturn sibling( elem, "nextSibling" );\n
+\t},\n
+\tprev: function( elem ) {\n
+\t\treturn sibling( elem, "previousSibling" );\n
+\t},\n
+\tnextAll: function( elem ) {\n
+\t\treturn jQuery.dir( elem, "nextSibling" );\n
+\t},\n
+\tprevAll: function( elem ) {\n
+\t\treturn jQuery.dir( elem, "previousSibling" );\n
+\t},\n
+\tnextUntil: function( elem, i, until ) {\n
+\t\treturn jQuery.dir( elem, "nextSibling", until );\n
+\t},\n
+\tprevUntil: function( elem, i, until ) {\n
+\t\treturn jQuery.dir( elem, "previousSibling", until );\n
+\t},\n
+\tsiblings: function( elem ) {\n
+\t\treturn jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );\n
+\t},\n
+\tchildren: function( elem ) {\n
+\t\treturn jQuery.sibling( elem.firstChild );\n
+\t},\n
+\tcontents: function( elem ) {\n
+\t\treturn elem.contentDocument || jQuery.merge( [], elem.childNodes );\n
+\t}\n
+}, function( name, fn ) {\n
+\tjQuery.fn[ name ] = function( until, selector ) {\n
+\t\tvar matched = jQuery.map( this, fn, until );\n
+\n
+\t\tif ( name.slice( -5 ) !== "Until" ) {\n
+\t\t\tselector = until;\n
+\t\t}\n
+\n
+\t\tif ( selector && typeof selector === "string" ) {\n
+\t\t\tmatched = jQuery.filter( selector, matched );\n
+\t\t}\n
+\n
+\t\tif ( this.length > 1 ) {\n
+\t\t\t// Remove duplicates\n
+\t\t\tif ( !guaranteedUnique[ name ] ) {\n
+\t\t\t\tjQuery.unique( matched );\n
+\t\t\t}\n
+\n
+\t\t\t// Reverse order for parents* and prev-derivatives\n
+\t\t\tif ( rparentsprev.test( name ) ) {\n
+\t\t\t\tmatched.reverse();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this.pushStack( matched );\n
+\t};\n
+});\n
+\n
+jQuery.extend({\n
+\tfilter: function( expr, elems, not ) {\n
+\t\tvar elem = elems[ 0 ];\n
+\n
+\t\tif ( not ) {\n
+\t\t\texpr = ":not(" + expr + ")";\n
+\t\t}\n
+\n
+\t\treturn elems.length === 1 && elem.nodeType === 1 ?\n
+\t\t\tjQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :\n
+\t\t\tjQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {\n
+\t\t\t\treturn elem.nodeType === 1;\n
+\t\t\t}));\n
+\t},\n
+\n
+\tdir: function( elem, dir, until ) {\n
+\t\tvar matched = [],\n
+\t\t\ttruncate = until !== undefined;\n
+\n
+\t\twhile ( (elem = elem[ dir ]) && elem.nodeType !== 9 ) {\n
+\t\t\tif ( elem.nodeType === 1 ) {\n
+\t\t\t\tif ( truncate && jQuery( elem ).is( until ) ) {\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t\tmatched.push( elem );\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn matched;\n
+\t},\n
+\n
+\tsibling: function( n, elem ) {\n
+\t\tvar matched = [];\n
+\n
+\t\tfor ( ; n; n = n.nextSibling ) {\n
+\t\t\tif ( n.nodeType === 1 && n !== elem ) {\n
+\t\t\t\tmatched.push( n );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn matched;\n
+\t}\n
+});\n
+\n
+// Implement the identical functionality for filter and not\n
+function winnow( elements, qualifier, not ) {\n
+\tif ( jQuery.isFunction( qualifier ) ) {\n
+\t\treturn jQuery.grep( elements, function( elem, i ) {\n
+\t\t\t/* jshint -W018 */\n
+\t\t\treturn !!qualifier.call( elem, i, elem ) !== not;\n
+\t\t});\n
+\n
+\t}\n
+\n
+\tif ( qualifier.nodeType ) {\n
+\t\treturn jQuery.grep( elements, function( elem ) {\n
+\t\t\treturn ( elem === qualifier ) !== not;\n
+\t\t});\n
+\n
+\t}\n
+\n
+\tif ( typeof qualifier === "string" ) {\n
+\t\tif ( isSimple.test( qualifier ) ) {\n
+\t\t\treturn jQuery.filter( qualifier, elements, not );\n
+\t\t}\n
+\n
+\t\tqualifier = jQuery.filter( qualifier, elements );\n
+\t}\n
+\n
+\treturn jQuery.grep( elements, function( elem ) {\n
+\t\treturn ( core_indexOf.call( qualifier, elem ) >= 0 ) !== not;\n
+\t});\n
+}\n
+var rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\\w:]+)[^>]*)\\/>/gi,\n
+\trtagName = /<([\\w:]+)/,\n
+\trhtml = /<|&#?\\w+;/,\n
+\trnoInnerhtml = /<(?:script|style|link)/i,\n
+\tmanipulation_rcheckableType = /^(?:checkbox|radio)$/i,\n
+\t// checked="checked" or checked\n
+\trchecked = /checked\\s*(?:[^=]|=\\s*.checked.)/i,\n
+\trscriptType = /^$|\\/(?:java|ecma)script/i,\n
+\trscriptTypeMasked = /^true\\/(.*)/,\n
+\trcleanScript = /^\\s*<!(?:\\[CDATA\\[|--)|(?:\\]\\]|--)>\\s*$/g,\n
+\n
+\t// We have to close these tags to support XHTML (#13200)\n
+\twrapMap = {\n
+\n
+\t\t// Support: IE 9\n
+\t\toption: [ 1, "<select multiple=\'multiple\'>", "</select>" ],\n
+\n
+\t\tthead: [ 1, "<table>", "</table>" ],\n
+\t\tcol: [ 2, "<table><colgroup>", "</colgroup></table>" ],\n
+\t\ttr: [ 2, "<table><tbody>", "</tbody></table>" ],\n
+\t\ttd: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],\n
+\n
+\t\t_default: [ 0, "", "" ]\n
+\t};\n
+\n
+// Support: IE 9\n
+wrapMap.optgroup = wrapMap.option;\n
+\n
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;\n
+wrapMap.th = wrapMap.td;\n
+\n
+jQuery.fn.extend({\n
+\ttext: function( value ) {\n
+\t\treturn jQuery.access( this, function( value ) {\n
+\t\t\treturn value === undefined ?\n
+\t\t\t\tjQuery.text( this ) :\n
+\t\t\t\tthis.empty().append( ( this[ 0 ] && this[ 0 ].ownerDocument || document ).createTextNode( value ) );\n
+\t\t}, null, value, arguments.length );\n
+\t},\n
+\n
+\tappend: function() {\n
+\t\treturn this.domManip( arguments, function( elem ) {\n
+\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n
+\t\t\t\tvar target = manipulationTarget( this, elem );\n
+\t\t\t\ttarget.appendChild( elem );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\tprepend: function() {\n
+\t\treturn this.domManip( arguments, function( elem ) {\n
+\t\t\tif ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {\n
+\t\t\t\tvar target = manipulationTarget( this, elem );\n
+\t\t\t\ttarget.insertBefore( elem, target.firstChild );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\tbefore: function() {\n
+\t\treturn this.domManip( arguments, function( elem ) {\n
+\t\t\tif ( this.parentNode ) {\n
+\t\t\t\tthis.parentNode.insertBefore( elem, this );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\tafter: function() {\n
+\t\treturn this.domManip( arguments, function( elem ) {\n
+\t\t\tif ( this.parentNode ) {\n
+\t\t\t\tthis.parentNode.insertBefore( elem, this.nextSibling );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t// keepData is for internal use only--do not document\n
+\tremove: function( selector, keepData ) {\n
+\t\tvar elem,\n
+\t\t\telems = selector ? jQuery.filter( selector, this ) : this,\n
+\t\t\ti = 0;\n
+\n
+\t\tfor ( ; (elem = elems[i]) != null; i++ ) {\n
+\t\t\tif ( !keepData && elem.nodeType === 1 ) {\n
+\t\t\t\tjQuery.cleanData( getAll( elem ) );\n
+\t\t\t}\n
+\n
+\t\t\tif ( elem.parentNode ) {\n
+\t\t\t\tif ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {\n
+\t\t\t\t\tsetGlobalEval( getAll( elem, "script" ) );\n
+\t\t\t\t}\n
+\t\t\t\telem.parentNode.removeChild( elem );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\tempty: function() {\n
+\t\tvar elem,\n
+\t\t\ti = 0;\n
+\n
+\t\tfor ( ; (elem = this[i]) != null; i++ ) {\n
+\t\t\tif ( elem.nodeType === 1 ) {\n
+\n
+\t\t\t\t// Prevent memory leaks\n
+\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n
+\n
+\t\t\t\t// Remove any remaining nodes\n
+\t\t\t\telem.textContent = "";\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\tclone: function( dataAndEvents, deepDataAndEvents ) {\n
+\t\tdataAndEvents = dataAndEvents == null ? false : dataAndEvents;\n
+\t\tdeepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;\n
+\n
+\t\treturn this.map( function () {\n
+\t\t\treturn jQuery.clone( this, dataAndEvents, deepDataAndEvents );\n
+\t\t});\n
+\t},\n
+\n
+\thtml: function( value ) {\n
+\t\treturn jQuery.access( this, function( value ) {\n
+\t\t\tvar elem = this[ 0 ] || {},\n
+\t\t\t\ti = 0,\n
+\t\t\t\tl = this.length;\n
+\n
+\t\t\tif ( value === undefined && elem.nodeType === 1 ) {\n
+\t\t\t\treturn elem.innerHTML;\n
+\t\t\t}\n
+\n
+\t\t\t// See if we can take a shortcut and just use innerHTML\n
+\t\t\tif ( typeof value === "string" && !rnoInnerhtml.test( value ) &&\n
+\t\t\t\t!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {\n
+\n
+\t\t\t\tvalue = value.replace( rxhtmlTag, "<$1></$2>" );\n
+\n
+\t\t\t\ttry {\n
+\t\t\t\t\tfor ( ; i < l; i++ ) {\n
+\t\t\t\t\t\telem = this[ i ] || {};\n
+\n
+\t\t\t\t\t\t// Remove element nodes and prevent memory leaks\n
+\t\t\t\t\t\tif ( elem.nodeType === 1 ) {\n
+\t\t\t\t\t\t\tjQuery.cleanData( getAll( elem, false ) );\n
+\t\t\t\t\t\t\telem.innerHTML = value;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\telem = 0;\n
+\n
+\t\t\t\t// If using innerHTML throws an exception, use the fallback method\n
+\t\t\t\t} catch( e ) {}\n
+\t\t\t}\n
+\n
+\t\t\tif ( elem ) {\n
+\t\t\t\tthis.empty().append( value );\n
+\t\t\t}\n
+\t\t}, null, value, arguments.length );\n
+\t},\n
+\n
+\treplaceWith: function() {\n
+\t\tvar\n
+\t\t\t// Snapshot the DOM in case .domManip sweeps something relevant into its fragment\n
+\t\t\targs = jQuery.map( this, function( elem ) {\n
+\t\t\t\treturn [ elem.nextSibling, elem.parentNode ];\n
+\t\t\t}),\n
+\t\t\ti = 0;\n
+\n
+\t\t// Make the changes, replacing each context element with the new content\n
+\t\tthis.domManip( arguments, function( elem ) {\n
+\t\t\tvar next = args[ i++ ],\n
+\t\t\t\tparent = args[ i++ ];\n
+\n
+\t\t\tif ( parent ) {\n
+\t\t\t\t// Don\'t use the snapshot next if it has moved (#13810)\n
+\t\t\t\tif ( next && next.parentNode !== parent ) {\n
+\t\t\t\t\tnext = this.nextSibling;\n
+\t\t\t\t}\n
+\t\t\t\tjQuery( this ).remove();\n
+\t\t\t\tparent.insertBefore( elem, next );\n
+\t\t\t}\n
+\t\t// Allow new content to include elements from the context set\n
+\t\t}, true );\n
+\n
+\t\t// Force removal if there was no new content (e.g., from empty arguments)\n
+\t\treturn i ? this : this.remove();\n
+\t},\n
+\n
+\tdetach: function( selector ) {\n
+\t\treturn this.remove( selector, true );\n
+\t},\n
+\n
+\tdomManip: function( args, callback, allowIntersection ) {\n
+\n
+\t\t// Flatten any nested arrays\n
+\t\targs = core_concat.apply( [], args );\n
+\n
+\t\tvar fragment, first, scripts, hasScripts, node, doc,\n
+\t\t\ti = 0,\n
+\t\t\tl = this.length,\n
+\t\t\tset = this,\n
+\t\t\tiNoClone = l - 1,\n
+\t\t\tvalue = args[ 0 ],\n
+\t\t\tisFunction = jQuery.isFunction( value );\n
+\n
+\t\t// We can\'t cloneNode fragments that contain checked, in WebKit\n
+\t\tif ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) {\n
+\t\t\treturn this.each(function( index ) {\n
+\t\t\t\tvar self = set.eq( index );\n
+\t\t\t\tif ( isFunction ) {\n
+\t\t\t\t\targs[ 0 ] = value.call( this, index, self.html() );\n
+\t\t\t\t}\n
+\t\t\t\tself.domManip( args, callback, allowIntersection );\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tif ( l ) {\n
+\t\t\tfragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, !allowIntersection && this );\n
+\t\t\tfirst = fragment.firstChild;\n
+\n
+\t\t\tif ( fragment.childNodes.length === 1 ) {\n
+\t\t\t\tfragment = first;\n
+\t\t\t}\n
+\n
+\t\t\tif ( first ) {\n
+\t\t\t\tscripts = jQuery.map( getAll( fragment, "script" ), disableScript );\n
+\t\t\t\thasScripts = scripts.length;\n
+\n
+\t\t\t\t// Use the original fragment for the last item instead of the first because it can end up\n
+\t\t\t\t// being emptied incorrectly in certain situations (#8070).\n
+\t\t\t\tfor ( ; i < l; i++ ) {\n
+\t\t\t\t\tnode = fragment;\n
+\n
+\t\t\t\t\tif ( i !== iNoClone ) {\n
+\t\t\t\t\t\tnode = jQuery.clone( node, true, true );\n
+\n
+\t\t\t\t\t\t// Keep references to cloned scripts for later restoration\n
+\t\t\t\t\t\tif ( hasScripts ) {\n
+\t\t\t\t\t\t\t// Support: QtWebKit\n
+\t\t\t\t\t\t\t// jQuery.merge because core_push.apply(_, arraylike) throws\n
+\t\t\t\t\t\t\tjQuery.merge( scripts, getAll( node, "script" ) );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tcallback.call( this[ i ], node, i );\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif ( hasScripts ) {\n
+\t\t\t\t\tdoc = scripts[ scripts.length - 1 ].ownerDocument;\n
+\n
+\t\t\t\t\t// Reenable scripts\n
+\t\t\t\t\tjQuery.map( scripts, restoreScript );\n
+\n
+\t\t\t\t\t// Evaluate executable scripts on first document insertion\n
+\t\t\t\t\tfor ( i = 0; i < hasScripts; i++ ) {\n
+\t\t\t\t\t\tnode = scripts[ i ];\n
+\t\t\t\t\t\tif ( rscriptType.test( node.type || "" ) &&\n
+\t\t\t\t\t\t\t!data_priv.access( node, "globalEval" ) && jQuery.contains( doc, node ) ) {\n
+\n
+\t\t\t\t\t\t\tif ( node.src ) {\n
+\t\t\t\t\t\t\t\t// Hope ajax is available...\n
+\t\t\t\t\t\t\t\tjQuery._evalUrl( node.src );\n
+\t\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t\tjQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t}\n
+});\n
+\n
+jQuery.each({\n
+\tappendTo: "append",\n
+\tprependTo: "prepend",\n
+\tinsertBefore: "before",\n
+\tinsertAfter: "after",\n
+\treplaceAll: "replaceWith"\n
+}, function( name, original ) {\n
+\tjQuery.fn[ name ] = function( selector ) {\n
+\t\tvar elems,\n
+\t\t\tret = [],\n
+\t\t\tinsert = jQuery( selector ),\n
+\t\t\tlast = insert.length - 1,\n
+\t\t\ti = 0;\n
+\n
+\t\tfor ( ; i <= last; i++ ) {\n
+\t\t\telems = i === last ? this : this.clone( true );\n
+\t\t\tjQuery( insert[ i ] )[ original ]( elems );\n
+\n
+\t\t\t// Support: QtWebKit\n
+\t\t\t// .get() because core_push.apply(_, arraylike) throws\n
+\t\t\tcore_push.apply( ret, elems.get() );\n
+\t\t}\n
+\n
+\t\treturn this.pushStack( ret );\n
+\t};\n
+});\n
+\n
+jQuery.extend({\n
+\tclone: function( elem, dataAndEvents, deepDataAndEvents ) {\n
+\t\tvar i, l, srcElements, destElements,\n
+\t\t\tclone = elem.cloneNode( true ),\n
+\t\t\tinPage = jQuery.contains( elem.ownerDocument, elem );\n
+\n
+\t\t// Support: IE >= 9\n
+\t\t// Fix Cloning issues\n
+\t\tif ( !jQuery.support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) {\n
+\n
+\t\t\t// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2\n
+\t\t\tdestElements = getAll( clone );\n
+\t\t\tsrcElements = getAll( elem );\n
+\n
+\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n
+\t\t\t\tfixInput( srcElements[ i ], destElements[ i ] );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Copy the events from the original to the clone\n
+\t\tif ( dataAndEvents ) {\n
+\t\t\tif ( deepDataAndEvents ) {\n
+\t\t\t\tsrcElements = srcElements || getAll( elem );\n
+\t\t\t\tdestElements = destElements || getAll( clone );\n
+\n
+\t\t\t\tfor ( i = 0, l = srcElements.length; i < l; i++ ) {\n
+\t\t\t\t\tcloneCopyEvent( srcElements[ i ], destElements[ i ] );\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\tcloneCopyEvent( elem, clone );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Preserve script evaluation history\n
+\t\tdestElements = getAll( clone, "script" );\n
+\t\tif ( destElements.length > 0 ) {\n
+\t\t\tsetGlobalEval( destElements, !inPage && getAll( elem, "script" ) );\n
+\t\t}\n
+\n
+\t\t// Return the cloned set\n
+\t\treturn clone;\n
+\t},\n
+\n
+\tbuildFragment: function( elems, context, scripts, selection ) {\n
+\t\tvar elem, tmp, tag, wrap, contains, j,\n
+\t\t\ti = 0,\n
+\t\t\tl = elems.length,\n
+\t\t\tfragment = context.createDocumentFragment(),\n
+\t\t\tnodes = [];\n
+\n
+\t\tfor ( ; i < l; i++ ) {\n
+\t\t\telem = elems[ i ];\n
+\n
+\t\t\tif ( elem || elem === 0 ) {\n
+\n
+\t\t\t\t// Add nodes directly\n
+\t\t\t\tif ( jQuery.type( elem ) === "object" ) {\n
+\t\t\t\t\t// Support: QtWebKit\n
+\t\t\t\t\t// jQuery.merge because core_push.apply(_, arraylike) throws\n
+\t\t\t\t\tjQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );\n
+\n
+\t\t\t\t// Convert non-html into a text node\n
+\t\t\t\t} else if ( !rhtml.test( elem ) ) {\n
+\t\t\t\t\tnodes.push( context.createTextNode( elem ) );\n
+\n
+\t\t\t\t// Convert html into DOM nodes\n
+\t\t\t\t} else {\n
+\t\t\t\t\ttmp = tmp || fragment.appendChild( context.createElement("div") );\n
+\n
+\t\t\t\t\t// Deserialize a standard representation\n
+\t\t\t\t\ttag = ( rtagName.exec( elem ) || ["", ""] )[ 1 ].toLowerCase();\n
+\t\t\t\t\twrap = wrapMap[ tag ] || wrapMap._default;\n
+\t\t\t\t\ttmp.innerHTML = wrap[ 1 ] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[ 2 ];\n
+\n
+\t\t\t\t\t// Descend through wrappers to the right content\n
+\t\t\t\t\tj = wrap[ 0 ];\n
+\t\t\t\t\twhile ( j-- ) {\n
+\t\t\t\t\t\ttmp = tmp.lastChild;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// Support: QtWebKit\n
+\t\t\t\t\t// jQuery.merge because core_push.apply(_, arraylike) throws\n
+\t\t\t\t\tjQuery.merge( nodes, tmp.childNodes );\n
+\n
+\t\t\t\t\t// Remember the top-level container\n
+\t\t\t\t\ttmp = fragment.firstChild;\n
+\n
+\t\t\t\t\t// Fixes #12346\n
+\t\t\t\t\t// Support: Webkit, IE\n
+\t\t\t\t\ttmp.textContent = "";\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Remove wrapper from fragment\n
+\t\tfragment.textContent = "";\n
+\n
+\t\ti = 0;\n
+\t\twhile ( (elem = nodes[ i++ ]) ) {\n
+\n
+\t\t\t// #4087 - If origin and destination elements are the same, and this is\n
+\t\t\t// that element, do not do anything\n
+\t\t\tif ( selection && jQuery.inArray( elem, selection ) !== -1 ) {\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\tcontains = jQuery.contains( elem.ownerDocument, elem );\n
+\n
+\t\t\t// Append to fragment\n
+\t\t\ttmp = getAll( fragment.appendChild( elem ), "script" );\n
+\n
+\t\t\t// Preserve script evaluation history\n
+\t\t\tif ( contains ) {\n
+\t\t\t\tsetGlobalEval( tmp );\n
+\t\t\t}\n
+\n
+\t\t\t// Capture executables\n
+\t\t\tif ( scripts ) {\n
+\t\t\t\tj = 0;\n
+\t\t\t\twhile ( (elem = tmp[ j++ ]) ) {\n
+\t\t\t\t\tif ( rscriptType.test( elem.type || "" ) ) {\n
+\t\t\t\t\t\tscripts.push( elem );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn fragment;\n
+\t},\n
+\n
+\tcleanData: function( elems ) {\n
+\t\tvar data, elem, events, type, key, j,\n
+\t\t\tspecial = jQuery.event.special,\n
+\t\t\ti = 0;\n
+\n
+\t\tfor ( ; (elem = elems[ i ]) !== undefined; i++ ) {\n
+\t\t\tif ( Data.accepts( elem ) ) {\n
+\t\t\t\tkey = elem[ data_priv.expando ];\n
+\n
+\t\t\t\tif ( key && (data = data_priv.cache[ key ]) ) {\n
+\t\t\t\t\tevents = Object.keys( data.events || {} );\n
+\t\t\t\t\tif ( events.length ) {\n
+\t\t\t\t\t\tfor ( j = 0; (type = events[j]) !== undefined; j++ ) {\n
+\t\t\t\t\t\t\tif ( special[ type ] ) {\n
+\t\t\t\t\t\t\t\tjQuery.event.remove( elem, type );\n
+\n
+\t\t\t\t\t\t\t// This is a shortcut to avoid jQuery.event.remove\'s overhead\n
+\t\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t\tjQuery.removeEvent( elem, type, data.handle );\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif ( data_priv.cache[ key ] ) {\n
+\t\t\t\t\t\t// Discard any remaining `private` data\n
+\t\t\t\t\t\tdelete data_priv.cache[ key ];\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\t// Discard any remaining `user` data\n
+\t\t\tdelete data_user.cache[ elem[ data_user.expando ] ];\n
+\t\t}\n
+\t},\n
+\n
+\t_evalUrl: function( url ) {\n
+\t\treturn jQuery.ajax({\n
+\t\t\turl: url,\n
+\t\t\ttype: "GET",\n
+\t\t\tdataType: "script",\n
+\t\t\tasync: false,\n
+\t\t\tglobal: false,\n
+\t\t\t"throws": true\n
+\t\t});\n
+\t}\n
+});\n
+\n
+// Support: 1.x compatibility\n
+// Manipulating tables requires a tbody\n
+function manipulationTarget( elem, content ) {\n
+\treturn jQuery.nodeName( elem, "table" ) &&\n
+\t\tjQuery.nodeName( content.nodeType === 1 ? content : content.firstChild, "tr" ) ?\n
+\n
+\t\telem.getElementsByTagName("tbody")[0] ||\n
+\t\t\telem.appendChild( elem.ownerDocument.createElement("tbody") ) :\n
+\t\telem;\n
+}\n
+\n
+// Replace/restore the type attribute of script elements for safe DOM manipulation\n
+function disableScript( elem ) {\n
+\telem.type = (elem.getAttribute("type") !== null) + "/" + elem.type;\n
+\treturn elem;\n
+}\n
+function restoreScript( elem ) {\n
+\tvar match = rscriptTypeMasked.exec( elem.type );\n
+\n
+\tif ( match ) {\n
+\t\telem.type = match[ 1 ];\n
+\t} else {\n
+\t\telem.removeAttribute("type");\n
+\t}\n
+\n
+\treturn elem;\n
+}\n
+\n
+// Mark scripts as having already been evaluated\n
+function setGlobalEval( elems, refElements ) {\n
+\tvar l = elems.length,\n
+\t\ti = 0;\n
+\n
+\tfor ( ; i < l; i++ ) {\n
+\t\tdata_priv.set(\n
+\t\t\telems[ i ], "globalEval", !refElements || data_priv.get( refElements[ i ], "globalEval" )\n
+\t\t);\n
+\t}\n
+}\n
+\n
+function cloneCopyEvent( src, dest ) {\n
+\tvar i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;\n
+\n
+\tif ( dest.nodeType !== 1 ) {\n
+\t\treturn;\n
+\t}\n
+\n
+\t// 1. Copy private data: events, handlers, etc.\n
+\tif ( data_priv.hasData( src ) ) {\n
+\t\tpdataOld = data_priv.access( src );\n
+\t\tpdataCur = data_priv.set( dest, pdataOld );\n
+\t\tevents = pdataOld.events;\n
+\n
+\t\tif ( events ) {\n
+\t\t\tdelete pdataCur.handle;\n
+\t\t\tpdataCur.events = {};\n
+\n
+\t\t\tfor ( type in events ) {\n
+\t\t\t\tfor ( i = 0, l = events[ type ].length; i < l; i++ ) {\n
+\t\t\t\t\tjQuery.event.add( dest, type, events[ type ][ i ] );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\t// 2. Copy user data\n
+\tif ( data_user.hasData( src ) ) {\n
+\t\tudataOld = data_user.access( src );\n
+\t\tudataCur = jQuery.extend( {}, udataOld );\n
+\n
+\t\tdata_user.set( dest, udataCur );\n
+\t}\n
+}\n
+\n
+\n
+function getAll( context, tag ) {\n
+\tvar ret = context.getElementsByTagName ? context.getElementsByTagName( tag || "*" ) :\n
+\t\t\tcontext.querySelectorAll ? context.querySelectorAll( tag || "*" ) :\n
+\t\t\t[];\n
+\n
+\treturn tag === undefined || tag && jQuery.nodeName( context, tag ) ?\n
+\t\tjQuery.merge( [ context ], ret ) :\n
+\t\tret;\n
+}\n
+\n
+// Support: IE >= 9\n
+function fixInput( src, dest ) {\n
+\tvar nodeName = dest.nodeName.toLowerCase();\n
+\n
+\t// Fails to persist the checked state of a cloned checkbox or radio button.\n
+\tif ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) {\n
+\t\tdest.checked = src.checked;\n
+\n
+\t// Fails to return the selected option to the default selected state when cloning options\n
+\t} else if ( nodeName === "input" || nodeName === "textarea" ) {\n
+\t\tdest.defaultValue = src.defaultValue;\n
+\t}\n
+}\n
+jQuery.fn.extend({\n
+\twrapAll: function( html ) {\n
+\t\tvar wrap;\n
+\n
+\t\tif ( jQuery.isFunction( html ) ) {\n
+\t\t\treturn this.each(function( i ) {\n
+\t\t\t\tjQuery( this ).wrapAll( html.call(this, i) );\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tif ( this[ 0 ] ) {\n
+\n
+\t\t\t// The elements to wrap the target around\n
+\t\t\twrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );\n
+\n
+\t\t\tif ( this[ 0 ].parentNode ) {\n
+\t\t\t\twrap.insertBefore( this[ 0 ] );\n
+\t\t\t}\n
+\n
+\t\t\twrap.map(function() {\n
+\t\t\t\tvar elem = this;\n
+\n
+\t\t\t\twhile ( elem.firstElementChild ) {\n
+\t\t\t\t\telem = elem.firstElementChild;\n
+\t\t\t\t}\n
+\n
+\t\t\t\treturn elem;\n
+\t\t\t}).append( this );\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\twrapInner: function( html ) {\n
+\t\tif ( jQuery.isFunction( html ) ) {\n
+\t\t\treturn this.each(function( i ) {\n
+\t\t\t\tjQuery( this ).wrapInner( html.call(this, i) );\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\treturn this.each(function() {\n
+\t\t\tvar self = jQuery( this ),\n
+\t\t\t\tcontents = self.contents();\n
+\n
+\t\t\tif ( contents.length ) {\n
+\t\t\t\tcontents.wrapAll( html );\n
+\n
+\t\t\t} else {\n
+\t\t\t\tself.append( html );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\twrap: function( html ) {\n
+\t\tvar isFunction = jQuery.isFunction( html );\n
+\n
+\t\treturn this.each(function( i ) {\n
+\t\t\tjQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );\n
+\t\t});\n
+\t},\n
+\n
+\tunwrap: function() {\n
+\t\treturn this.parent().each(function() {\n
+\t\t\tif ( !jQuery.nodeName( this, "body" ) ) {\n
+\t\t\t\tjQuery( this ).replaceWith( this.childNodes );\n
+\t\t\t}\n
+\t\t}).end();\n
+\t}\n
+});\n
+var curCSS, iframe,\n
+\t// swappable if display is none or starts with table except "table", "table-cell", or "table-caption"\n
+\t// see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display\n
+\trdisplayswap = /^(none|table(?!-c[ea]).+)/,\n
+\trmargin = /^margin/,\n
+\trnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ),\n
+\trnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ),\n
+\trrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ),\n
+\telemdisplay = { BODY: "block" },\n
+\n
+\tcssShow = { position: "absolute", visibility: "hidden", display: "block" },\n
+\tcssNormalTransform = {\n
+\t\tletterSpacing: 0,\n
+\t\tfontWeight: 400\n
+\t},\n
+\n
+\tcssExpand = [ "Top", "Right", "Bottom", "Left" ],\n
+\tcssPrefixes = [ "Webkit", "O", "Moz", "ms" ];\n
+\n
+// return a css property mapped to a potentially vendor prefixed property\n
+function vendorPropName( style, name ) {\n
+\n
+\t// shortcut for names that are not vendor prefixed\n
+\tif ( name in style ) {\n
+\t\treturn name;\n
+\t}\n
+\n
+\t// check for vendor prefixed names\n
+\tvar capName = name.charAt(0).toUpperCase() + name.slice(1),\n
+\t\torigName = name,\n
+\t\ti = cssPrefixes.length;\n
+\n
+\twhile ( i-- ) {\n
+\t\tname = cssPrefixes[ i ] + capName;\n
+\t\tif ( name in style ) {\n
+\t\t\treturn name;\n
+\t\t}\n
+\t}\n
+\n
+\treturn origName;\n
+}\n
+\n
+function isHidden( elem, el ) {\n
+\t// isHidden might be called from jQuery#filter function;\n
+\t// in that case, element will be second argument\n
+\telem = el || elem;\n
+\treturn jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );\n
+}\n
+\n
+// NOTE: we\'ve included the "window" in window.getComputedStyle\n
+// because jsdom on node.js will break without it.\n
+function getStyles( elem ) {\n
+\treturn window.getComputedStyle( elem, null );\n
+}\n
+\n
+function showHide( elements, show ) {\n
+\tvar display, elem, hidden,\n
+\t\tvalues = [],\n
+\t\tindex = 0,\n
+\t\tlength = elements.length;\n
+\n
+\tfor ( ; index < length; index++ ) {\n
+\t\telem = elements[ index ];\n
+\t\tif ( !elem.style ) {\n
+\t\t\tcontinue;\n
+\t\t}\n
+\n
+\t\tvalues[ index ] = data_priv.get( elem, "olddisplay" );\n
+\t\tdisplay = elem.style.display;\n
+\t\tif ( show ) {\n
+\t\t\t// Reset the inline display of this element to learn if it is\n
+\t\t\t// being hidden by cascaded rules or not\n
+\t\t\tif ( !values[ index ] && display === "none" ) {\n
+\t\t\t\telem.style.display = "";\n
+\t\t\t}\n
+\n
+\t\t\t// Set elements which have been overridden with display: none\n
+\t\t\t// in a stylesheet to whatever the default browser style is\n
+\t\t\t// for such an element\n
+\t\t\tif ( elem.style.display === "" && isHidden( elem ) ) {\n
+\t\t\t\tvalues[ index ] = data_priv.access( elem, "olddisplay", css_defaultDisplay(elem.nodeName) );\n
+\t\t\t}\n
+\t\t} else {\n
+\n
+\t\t\tif ( !values[ index ] ) {\n
+\t\t\t\thidden = isHidden( elem );\n
+\n
+\t\t\t\tif ( display && display !== "none" || !hidden ) {\n
+\t\t\t\t\tdata_priv.set( elem, "olddisplay", hidden ? display : jQuery.css(elem, "display") );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\t// Set the display of most of the elements in a second loop\n
+\t// to avoid the constant reflow\n
+\tfor ( index = 0; index < length; index++ ) {\n
+\t\telem = elements[ index ];\n
+\t\tif ( !elem.style ) {\n
+\t\t\tcontinue;\n
+\t\t}\n
+\t\tif ( !show || elem.style.display === "none" || elem.style.display === "" ) {\n
+\t\t\telem.style.display = show ? values[ index ] || "" : "none";\n
+\t\t}\n
+\t}\n
+\n
+\treturn elements;\n
+}\n
+\n
+jQuery.fn.extend({\n
+\tcss: function( name, value ) {\n
+\t\treturn jQuery.access( this, function( elem, name, value ) {\n
+\t\t\tvar styles, len,\n
+\t\t\t\tmap = {},\n
+\t\t\t\ti = 0;\n
+\n
+\t\t\tif ( jQuery.isArray( name ) ) {\n
+\t\t\t\tstyles = getStyles( elem );\n
+\t\t\t\tlen = name.length;\n
+\n
+\t\t\t\tfor ( ; i < len; i++ ) {\n
+\t\t\t\t\tmap[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );\n
+\t\t\t\t}\n
+\n
+\t\t\t\treturn map;\n
+\t\t\t}\n
+\n
+\t\t\treturn value !== undefined ?\n
+\t\t\t\tjQuery.style( elem, name, value ) :\n
+\t\t\t\tjQuery.css( elem, name );\n
+\t\t}, name, value, arguments.length > 1 );\n
+\t},\n
+\tshow: function() {\n
+\t\treturn showHide( this, true );\n
+\t},\n
+\thide: function() {\n
+\t\treturn showHide( this );\n
+\t},\n
+\ttoggle: function( state ) {\n
+\t\tif ( typeof state === "boolean" ) {\n
+\t\t\treturn state ? this.show() : this.hide();\n
+\t\t}\n
+\n
+\t\treturn this.each(function() {\n
+\t\t\tif ( isHidden( this ) ) {\n
+\t\t\t\tjQuery( this ).show();\n
+\t\t\t} else {\n
+\t\t\t\tjQuery( this ).hide();\n
+\t\t\t}\n
+\t\t});\n
+\t}\n
+});\n
+\n
+jQuery.extend({\n
+\t// Add in style property hooks for overriding the default\n
+\t// behavior of getting and setting a style property\n
+\tcssHooks: {\n
+\t\topacity: {\n
+\t\t\tget: function( elem, computed ) {\n
+\t\t\t\tif ( computed ) {\n
+\t\t\t\t\t// We should always get a number back from opacity\n
+\t\t\t\t\tvar ret = curCSS( elem, "opacity" );\n
+\t\t\t\t\treturn ret === "" ? "1" : ret;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t// Don\'t automatically add "px" to these possibly-unitless properties\n
+\tcssNumber: {\n
+\t\t"columnCount": true,\n
+\t\t"fillOpacity": true,\n
+\t\t"fontWeight": true,\n
+\t\t"lineHeight": true,\n
+\t\t"opacity": true,\n
+\t\t"order": true,\n
+\t\t"orphans": true,\n
+\t\t"widows": true,\n
+\t\t"zIndex": true,\n
+\t\t"zoom": true\n
+\t},\n
+\n
+\t// Add in properties whose names you wish to fix before\n
+\t// setting or getting the value\n
+\tcssProps: {\n
+\t\t// normalize float css property\n
+\t\t"float": "cssFloat"\n
+\t},\n
+\n
+\t// Get and set the style property on a DOM Node\n
+\tstyle: function( elem, name, value, extra ) {\n
+\t\t// Don\'t set styles on text and comment nodes\n
+\t\tif ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Make sure that we\'re working with the right name\n
+\t\tvar ret, type, hooks,\n
+\t\t\torigName = jQuery.camelCase( name ),\n
+\t\t\tstyle = elem.style;\n
+\n
+\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );\n
+\n
+\t\t// gets hook for the prefixed version\n
+\t\t// followed by the unprefixed version\n
+\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n
+\n
+\t\t// Check if we\'re setting a value\n
+\t\tif ( value !== undefined ) {\n
+\t\t\ttype = typeof value;\n
+\n
+\t\t\t// convert relative number strings (+= or -=) to relative numbers. #7345\n
+\t\t\tif ( type === "string" && (ret = rrelNum.exec( value )) ) {\n
+\t\t\t\tvalue = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );\n
+\t\t\t\t// Fixes bug #9237\n
+\t\t\t\ttype = "number";\n
+\t\t\t}\n
+\n
+\t\t\t// Make sure that NaN and null values aren\'t set. See: #7116\n
+\t\t\tif ( value == null || type === "number" && isNaN( value ) ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// If a number was passed in, add \'px\' to the (except for certain CSS properties)\n
+\t\t\tif ( type === "number" && !jQuery.cssNumber[ origName ] ) {\n
+\t\t\t\tvalue += "px";\n
+\t\t\t}\n
+\n
+\t\t\t// Fixes #8908, it can be done more correctly by specifying setters in cssHooks,\n
+\t\t\t// but it would mean to define eight (for every problematic property) identical functions\n
+\t\t\tif ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {\n
+\t\t\t\tstyle[ name ] = "inherit";\n
+\t\t\t}\n
+\n
+\t\t\t// If a hook was provided, use that value, otherwise just set the specified value\n
+\t\t\tif ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {\n
+\t\t\t\tstyle[ name ] = value;\n
+\t\t\t}\n
+\n
+\t\t} else {\n
+\t\t\t// If a hook was provided get the non-computed value from there\n
+\t\t\tif ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {\n
+\t\t\t\treturn ret;\n
+\t\t\t}\n
+\n
+\t\t\t// Otherwise just get the value from the style object\n
+\t\t\treturn style[ name ];\n
+\t\t}\n
+\t},\n
+\n
+\tcss: function( elem, name, extra, styles ) {\n
+\t\tvar val, num, hooks,\n
+\t\t\torigName = jQuery.camelCase( name );\n
+\n
+\t\t// Make sure that we\'re working with the right name\n
+\t\tname = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );\n
+\n
+\t\t// gets hook for the prefixed version\n
+\t\t// followed by the unprefixed version\n
+\t\thooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];\n
+\n
+\t\t// If a hook was provided get the computed value from there\n
+\t\tif ( hooks && "get" in hooks ) {\n
+\t\t\tval = hooks.get( elem, true, extra );\n
+\t\t}\n
+\n
+\t\t// Otherwise, if a way to get the computed value exists, use that\n
+\t\tif ( val === undefined ) {\n
+\t\t\tval = curCSS( elem, name, styles );\n
+\t\t}\n
+\n
+\t\t//convert "normal" to computed value\n
+\t\tif ( val === "normal" && name in cssNormalTransform ) {\n
+\t\t\tval = cssNormalTransform[ name ];\n
+\t\t}\n
+\n
+\t\t// Return, converting to number if forced or a qualifier was provided and val looks numeric\n
+\t\tif ( extra === "" || extra ) {\n
+\t\t\tnum = parseFloat( val );\n
+\t\t\treturn extra === true || jQuery.isNumeric( num ) ? num || 0 : val;\n
+\t\t}\n
+\t\treturn val;\n
+\t}\n
+});\n
+\n
+curCSS = function( elem, name, _computed ) {\n
+\tvar width, minWidth, maxWidth,\n
+\t\tcomputed = _computed || getStyles( elem ),\n
+\n
+\t\t// Support: IE9\n
+\t\t// getPropertyValue is only needed for .css(\'filter\') in IE9, see #12537\n
+\t\tret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined,\n
+\t\tstyle = elem.style;\n
+\n
+\tif ( computed ) {\n
+\n
+\t\tif ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {\n
+\t\t\tret = jQuery.style( elem, name );\n
+\t\t}\n
+\n
+\t\t// Support: Safari 5.1\n
+\t\t// A tribute to the "awesome hack by Dean Edwards"\n
+\t\t// Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels\n
+\t\t// this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values\n
+\t\tif ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {\n
+\n
+\t\t\t// Remember the original values\n
+\t\t\twidth = style.width;\n
+\t\t\tminWidth = style.minWidth;\n
+\t\t\tmaxWidth = style.maxWidth;\n
+\n
+\t\t\t// Put in the new values to get a computed value out\n
+\t\t\tstyle.minWidth = style.maxWidth = style.width = ret;\n
+\t\t\tret = computed.width;\n
+\n
+\t\t\t// Revert the changed values\n
+\t\t\tstyle.width = width;\n
+\t\t\tstyle.minWidth = minWidth;\n
+\t\t\tstyle.maxWidth = maxWidth;\n
+\t\t}\n
+\t}\n
+\n
+\treturn ret;\n
+};\n
+\n
+\n
+function setPositiveNumber( elem, value, subtract ) {\n
+\tvar matches = rnumsplit.exec( value );\n
+\treturn matches ?\n
+\t\t// Guard against undefined "subtract", e.g., when used as in cssHooks\n
+\t\tMath.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :\n
+\t\tvalue;\n
+}\n
+\n
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {\n
+\tvar i = extra === ( isBorderBox ? "border" : "content" ) ?\n
+\t\t// If we already have the right measurement, avoid augmentation\n
+\t\t4 :\n
+\t\t// Otherwise initialize for horizontal or vertical properties\n
+\t\tname === "width" ? 1 : 0,\n
+\n
+\t\tval = 0;\n
+\n
+\tfor ( ; i < 4; i += 2 ) {\n
+\t\t// both box models exclude margin, so add it if we want it\n
+\t\tif ( extra === "margin" ) {\n
+\t\t\tval += jQuery.css( elem, extra + cssExpand[ i ], true, styles );\n
+\t\t}\n
+\n
+\t\tif ( isBorderBox ) {\n
+\t\t\t// border-box includes padding, so remove it if we want content\n
+\t\t\tif ( extra === "content" ) {\n
+\t\t\t\tval -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );\n
+\t\t\t}\n
+\n
+\t\t\t// at this point, extra isn\'t border nor margin, so remove border\n
+\t\t\tif ( extra !== "margin" ) {\n
+\t\t\t\tval -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\t// at this point, extra isn\'t content, so add padding\n
+\t\t\tval += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );\n
+\n
+\t\t\t// at this point, extra isn\'t content nor padding, so add border\n
+\t\t\tif ( extra !== "padding" ) {\n
+\t\t\t\tval += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\treturn val;\n
+}\n
+\n
+function getWidthOrHeight( elem, name, extra ) {\n
+\n
+\t// Start with offset property, which is equivalent to the border-box value\n
+\tvar valueIsBorderBox = true,\n
+\t\tval = name === "width" ? elem.offsetWidth : elem.offsetHeight,\n
+\t\tstyles = getStyles( elem ),\n
+\t\tisBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";\n
+\n
+\t// some non-html elements return undefined for offsetWidth, so check for null/undefined\n
+\t// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285\n
+\t// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668\n
+\tif ( val <= 0 || val == null ) {\n
+\t\t// Fall back to computed then uncomputed css if necessary\n
+\t\tval = curCSS( elem, name, styles );\n
+\t\tif ( val < 0 || val == null ) {\n
+\t\t\tval = elem.style[ name ];\n
+\t\t}\n
+\n
+\t\t// Computed unit is not pixels. Stop here and return.\n
+\t\tif ( rnumnonpx.test(val) ) {\n
+\t\t\treturn val;\n
+\t\t}\n
+\n
+\t\t// we need the check for style in case a browser which returns unreliable values\n
+\t\t// for getComputedStyle silently falls back to the reliable elem.style\n
+\t\tvalueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] );\n
+\n
+\t\t// Normalize "", auto, and prepa
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+re for extra\n
+\t\tval = parseFloat( val ) || 0;\n
+\t}\n
+\n
+\t// use the active box-sizing model to add/subtract irrelevant styles\n
+\treturn ( val +\n
+\t\taugmentWidthOrHeight(\n
+\t\t\telem,\n
+\t\t\tname,\n
+\t\t\textra || ( isBorderBox ? "border" : "content" ),\n
+\t\t\tvalueIsBorderBox,\n
+\t\t\tstyles\n
+\t\t)\n
+\t) + "px";\n
+}\n
+\n
+// Try to determine the default display value of an element\n
+function css_defaultDisplay( nodeName ) {\n
+\tvar doc = document,\n
+\t\tdisplay = elemdisplay[ nodeName ];\n
+\n
+\tif ( !display ) {\n
+\t\tdisplay = actualDisplay( nodeName, doc );\n
+\n
+\t\t// If the simple way fails, read from inside an iframe\n
+\t\tif ( display === "none" || !display ) {\n
+\t\t\t// Use the already-created iframe if possible\n
+\t\t\tiframe = ( iframe ||\n
+\t\t\t\tjQuery("<iframe frameborder=\'0\' width=\'0\' height=\'0\'/>")\n
+\t\t\t\t.css( "cssText", "display:block !important" )\n
+\t\t\t).appendTo( doc.documentElement );\n
+\n
+\t\t\t// Always write a new HTML skeleton so Webkit and Firefox don\'t choke on reuse\n
+\t\t\tdoc = ( iframe[0].contentWindow || iframe[0].contentDocument ).document;\n
+\t\t\tdoc.write("<!doctype html><html><body>");\n
+\t\t\tdoc.close();\n
+\n
+\t\t\tdisplay = actualDisplay( nodeName, doc );\n
+\t\t\tiframe.detach();\n
+\t\t}\n
+\n
+\t\t// Store the correct default display\n
+\t\telemdisplay[ nodeName ] = display;\n
+\t}\n
+\n
+\treturn display;\n
+}\n
+\n
+// Called ONLY from within css_defaultDisplay\n
+function actualDisplay( name, doc ) {\n
+\tvar elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),\n
+\t\tdisplay = jQuery.css( elem[0], "display" );\n
+\telem.remove();\n
+\treturn display;\n
+}\n
+\n
+jQuery.each([ "height", "width" ], function( i, name ) {\n
+\tjQuery.cssHooks[ name ] = {\n
+\t\tget: function( elem, computed, extra ) {\n
+\t\t\tif ( computed ) {\n
+\t\t\t\t// certain elements can have dimension info if we invisibly show them\n
+\t\t\t\t// however, it must have a current display style that would benefit from this\n
+\t\t\t\treturn elem.offsetWidth === 0 && rdisplayswap.test( jQuery.css( elem, "display" ) ) ?\n
+\t\t\t\t\tjQuery.swap( elem, cssShow, function() {\n
+\t\t\t\t\t\treturn getWidthOrHeight( elem, name, extra );\n
+\t\t\t\t\t}) :\n
+\t\t\t\t\tgetWidthOrHeight( elem, name, extra );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\tset: function( elem, value, extra ) {\n
+\t\t\tvar styles = extra && getStyles( elem );\n
+\t\t\treturn setPositiveNumber( elem, value, extra ?\n
+\t\t\t\taugmentWidthOrHeight(\n
+\t\t\t\t\telem,\n
+\t\t\t\t\tname,\n
+\t\t\t\t\textra,\n
+\t\t\t\t\tjQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",\n
+\t\t\t\t\tstyles\n
+\t\t\t\t) : 0\n
+\t\t\t);\n
+\t\t}\n
+\t};\n
+});\n
+\n
+// These hooks cannot be added until DOM ready because the support test\n
+// for it is not run until after DOM ready\n
+jQuery(function() {\n
+\t// Support: Android 2.3\n
+\tif ( !jQuery.support.reliableMarginRight ) {\n
+\t\tjQuery.cssHooks.marginRight = {\n
+\t\t\tget: function( elem, computed ) {\n
+\t\t\t\tif ( computed ) {\n
+\t\t\t\t\t// Support: Android 2.3\n
+\t\t\t\t\t// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right\n
+\t\t\t\t\t// Work around by temporarily setting element display to inline-block\n
+\t\t\t\t\treturn jQuery.swap( elem, { "display": "inline-block" },\n
+\t\t\t\t\t\tcurCSS, [ elem, "marginRight" ] );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t};\n
+\t}\n
+\n
+\t// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084\n
+\t// getComputedStyle returns percent when specified for top/left/bottom/right\n
+\t// rather than make the css module depend on the offset module, we just check for it here\n
+\tif ( !jQuery.support.pixelPosition && jQuery.fn.position ) {\n
+\t\tjQuery.each( [ "top", "left" ], function( i, prop ) {\n
+\t\t\tjQuery.cssHooks[ prop ] = {\n
+\t\t\t\tget: function( elem, computed ) {\n
+\t\t\t\t\tif ( computed ) {\n
+\t\t\t\t\t\tcomputed = curCSS( elem, prop );\n
+\t\t\t\t\t\t// if curCSS returns percentage, fallback to offset\n
+\t\t\t\t\t\treturn rnumnonpx.test( computed ) ?\n
+\t\t\t\t\t\t\tjQuery( elem ).position()[ prop ] + "px" :\n
+\t\t\t\t\t\t\tcomputed;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t};\n
+\t\t});\n
+\t}\n
+\n
+});\n
+\n
+if ( jQuery.expr && jQuery.expr.filters ) {\n
+\tjQuery.expr.filters.hidden = function( elem ) {\n
+\t\t// Support: Opera <= 12.12\n
+\t\t// Opera reports offsetWidths and offsetHeights less than zero on some elements\n
+\t\treturn elem.offsetWidth <= 0 && elem.offsetHeight <= 0;\n
+\t};\n
+\n
+\tjQuery.expr.filters.visible = function( elem ) {\n
+\t\treturn !jQuery.expr.filters.hidden( elem );\n
+\t};\n
+}\n
+\n
+// These hooks are used by animate to expand properties\n
+jQuery.each({\n
+\tmargin: "",\n
+\tpadding: "",\n
+\tborder: "Width"\n
+}, function( prefix, suffix ) {\n
+\tjQuery.cssHooks[ prefix + suffix ] = {\n
+\t\texpand: function( value ) {\n
+\t\t\tvar i = 0,\n
+\t\t\t\texpanded = {},\n
+\n
+\t\t\t\t// assumes a single number if not a string\n
+\t\t\t\tparts = typeof value === "string" ? value.split(" ") : [ value ];\n
+\n
+\t\t\tfor ( ; i < 4; i++ ) {\n
+\t\t\t\texpanded[ prefix + cssExpand[ i ] + suffix ] =\n
+\t\t\t\t\tparts[ i ] || parts[ i - 2 ] || parts[ 0 ];\n
+\t\t\t}\n
+\n
+\t\t\treturn expanded;\n
+\t\t}\n
+\t};\n
+\n
+\tif ( !rmargin.test( prefix ) ) {\n
+\t\tjQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;\n
+\t}\n
+});\n
+var r20 = /%20/g,\n
+\trbracket = /\\[\\]$/,\n
+\trCRLF = /\\r?\\n/g,\n
+\trsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,\n
+\trsubmittable = /^(?:input|select|textarea|keygen)/i;\n
+\n
+jQuery.fn.extend({\n
+\tserialize: function() {\n
+\t\treturn jQuery.param( this.serializeArray() );\n
+\t},\n
+\tserializeArray: function() {\n
+\t\treturn this.map(function(){\n
+\t\t\t// Can add propHook for "elements" to filter or add form elements\n
+\t\t\tvar elements = jQuery.prop( this, "elements" );\n
+\t\t\treturn elements ? jQuery.makeArray( elements ) : this;\n
+\t\t})\n
+\t\t.filter(function(){\n
+\t\t\tvar type = this.type;\n
+\t\t\t// Use .is(":disabled") so that fieldset[disabled] works\n
+\t\t\treturn this.name && !jQuery( this ).is( ":disabled" ) &&\n
+\t\t\t\trsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&\n
+\t\t\t\t( this.checked || !manipulation_rcheckableType.test( type ) );\n
+\t\t})\n
+\t\t.map(function( i, elem ){\n
+\t\t\tvar val = jQuery( this ).val();\n
+\n
+\t\t\treturn val == null ?\n
+\t\t\t\tnull :\n
+\t\t\t\tjQuery.isArray( val ) ?\n
+\t\t\t\t\tjQuery.map( val, function( val ){\n
+\t\t\t\t\t\treturn { name: elem.name, value: val.replace( rCRLF, "\\r\\n" ) };\n
+\t\t\t\t\t}) :\n
+\t\t\t\t\t{ name: elem.name, value: val.replace( rCRLF, "\\r\\n" ) };\n
+\t\t}).get();\n
+\t}\n
+});\n
+\n
+//Serialize an array of form elements or a set of\n
+//key/values into a query string\n
+jQuery.param = function( a, traditional ) {\n
+\tvar prefix,\n
+\t\ts = [],\n
+\t\tadd = function( key, value ) {\n
+\t\t\t// If value is a function, invoke it and return its value\n
+\t\t\tvalue = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );\n
+\t\t\ts[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );\n
+\t\t};\n
+\n
+\t// Set traditional to true for jQuery <= 1.3.2 behavior.\n
+\tif ( traditional === undefined ) {\n
+\t\ttraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;\n
+\t}\n
+\n
+\t// If an array was passed in, assume that it is an array of form elements.\n
+\tif ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {\n
+\t\t// Serialize the form elements\n
+\t\tjQuery.each( a, function() {\n
+\t\t\tadd( this.name, this.value );\n
+\t\t});\n
+\n
+\t} else {\n
+\t\t// If traditional, encode the "old" way (the way 1.3.2 or older\n
+\t\t// did it), otherwise encode params recursively.\n
+\t\tfor ( prefix in a ) {\n
+\t\t\tbuildParams( prefix, a[ prefix ], traditional, add );\n
+\t\t}\n
+\t}\n
+\n
+\t// Return the resulting serialization\n
+\treturn s.join( "&" ).replace( r20, "+" );\n
+};\n
+\n
+function buildParams( prefix, obj, traditional, add ) {\n
+\tvar name;\n
+\n
+\tif ( jQuery.isArray( obj ) ) {\n
+\t\t// Serialize array item.\n
+\t\tjQuery.each( obj, function( i, v ) {\n
+\t\t\tif ( traditional || rbracket.test( prefix ) ) {\n
+\t\t\t\t// Treat each array item as a scalar.\n
+\t\t\t\tadd( prefix, v );\n
+\n
+\t\t\t} else {\n
+\t\t\t\t// Item is non-scalar (array or object), encode its numeric index.\n
+\t\t\t\tbuildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t} else if ( !traditional && jQuery.type( obj ) === "object" ) {\n
+\t\t// Serialize object item.\n
+\t\tfor ( name in obj ) {\n
+\t\t\tbuildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );\n
+\t\t}\n
+\n
+\t} else {\n
+\t\t// Serialize scalar item.\n
+\t\tadd( prefix, obj );\n
+\t}\n
+}\n
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +\n
+\t"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +\n
+\t"change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {\n
+\n
+\t// Handle event binding\n
+\tjQuery.fn[ name ] = function( data, fn ) {\n
+\t\treturn arguments.length > 0 ?\n
+\t\t\tthis.on( name, null, data, fn ) :\n
+\t\t\tthis.trigger( name );\n
+\t};\n
+});\n
+\n
+jQuery.fn.extend({\n
+\thover: function( fnOver, fnOut ) {\n
+\t\treturn this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );\n
+\t},\n
+\n
+\tbind: function( types, data, fn ) {\n
+\t\treturn this.on( types, null, data, fn );\n
+\t},\n
+\tunbind: function( types, fn ) {\n
+\t\treturn this.off( types, null, fn );\n
+\t},\n
+\n
+\tdelegate: function( selector, types, data, fn ) {\n
+\t\treturn this.on( types, selector, data, fn );\n
+\t},\n
+\tundelegate: function( selector, types, fn ) {\n
+\t\t// ( namespace ) or ( selector, types [, fn] )\n
+\t\treturn arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );\n
+\t}\n
+});\n
+var\n
+\t// Document location\n
+\tajaxLocParts,\n
+\tajaxLocation,\n
+\n
+\tajax_nonce = jQuery.now(),\n
+\n
+\tajax_rquery = /\\?/,\n
+\trhash = /#.*$/,\n
+\trts = /([?&])_=[^&]*/,\n
+\trheaders = /^(.*?):[ \\t]*([^\\r\\n]*)$/mg,\n
+\t// #7653, #8125, #8152: local protocol detection\n
+\trlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,\n
+\trnoContent = /^(?:GET|HEAD)$/,\n
+\trprotocol = /^\\/\\//,\n
+\trurl = /^([\\w.+-]+:)(?:\\/\\/([^\\/?#:]*)(?::(\\d+)|)|)/,\n
+\n
+\t// Keep a copy of the old load method\n
+\t_load = jQuery.fn.load,\n
+\n
+\t/* Prefilters\n
+\t * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)\n
+\t * 2) These are called:\n
+\t *    - BEFORE asking for a transport\n
+\t *    - AFTER param serialization (s.data is a string if s.processData is true)\n
+\t * 3) key is the dataType\n
+\t * 4) the catchall symbol "*" can be used\n
+\t * 5) execution will start with transport dataType and THEN continue down to "*" if needed\n
+\t */\n
+\tprefilters = {},\n
+\n
+\t/* Transports bindings\n
+\t * 1) key is the dataType\n
+\t * 2) the catchall symbol "*" can be used\n
+\t * 3) selection will start with transport dataType and THEN go to "*" if needed\n
+\t */\n
+\ttransports = {},\n
+\n
+\t// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression\n
+\tallTypes = "*/".concat("*");\n
+\n
+// #8138, IE may throw an exception when accessing\n
+// a field from window.location if document.domain has been set\n
+try {\n
+\tajaxLocation = location.href;\n
+} catch( e ) {\n
+\t// Use the href attribute of an A element\n
+\t// since IE will modify it given document.location\n
+\tajaxLocation = document.createElement( "a" );\n
+\tajaxLocation.href = "";\n
+\tajaxLocation = ajaxLocation.href;\n
+}\n
+\n
+// Segment location into parts\n
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];\n
+\n
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport\n
+function addToPrefiltersOrTransports( structure ) {\n
+\n
+\t// dataTypeExpression is optional and defaults to "*"\n
+\treturn function( dataTypeExpression, func ) {\n
+\n
+\t\tif ( typeof dataTypeExpression !== "string" ) {\n
+\t\t\tfunc = dataTypeExpression;\n
+\t\t\tdataTypeExpression = "*";\n
+\t\t}\n
+\n
+\t\tvar dataType,\n
+\t\t\ti = 0,\n
+\t\t\tdataTypes = dataTypeExpression.toLowerCase().match( core_rnotwhite ) || [];\n
+\n
+\t\tif ( jQuery.isFunction( func ) ) {\n
+\t\t\t// For each dataType in the dataTypeExpression\n
+\t\t\twhile ( (dataType = dataTypes[i++]) ) {\n
+\t\t\t\t// Prepend if requested\n
+\t\t\t\tif ( dataType[0] === "+" ) {\n
+\t\t\t\t\tdataType = dataType.slice( 1 ) || "*";\n
+\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).unshift( func );\n
+\n
+\t\t\t\t// Otherwise append\n
+\t\t\t\t} else {\n
+\t\t\t\t\t(structure[ dataType ] = structure[ dataType ] || []).push( func );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t};\n
+}\n
+\n
+// Base inspection function for prefilters and transports\n
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {\n
+\n
+\tvar inspected = {},\n
+\t\tseekingTransport = ( structure === transports );\n
+\n
+\tfunction inspect( dataType ) {\n
+\t\tvar selected;\n
+\t\tinspected[ dataType ] = true;\n
+\t\tjQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {\n
+\t\t\tvar dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );\n
+\t\t\tif( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {\n
+\t\t\t\toptions.dataTypes.unshift( dataTypeOrTransport );\n
+\t\t\t\tinspect( dataTypeOrTransport );\n
+\t\t\t\treturn false;\n
+\t\t\t} else if ( seekingTransport ) {\n
+\t\t\t\treturn !( selected = dataTypeOrTransport );\n
+\t\t\t}\n
+\t\t});\n
+\t\treturn selected;\n
+\t}\n
+\n
+\treturn inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );\n
+}\n
+\n
+// A special extend for ajax options\n
+// that takes "flat" options (not to be deep extended)\n
+// Fixes #9887\n
+function ajaxExtend( target, src ) {\n
+\tvar key, deep,\n
+\t\tflatOptions = jQuery.ajaxSettings.flatOptions || {};\n
+\n
+\tfor ( key in src ) {\n
+\t\tif ( src[ key ] !== undefined ) {\n
+\t\t\t( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];\n
+\t\t}\n
+\t}\n
+\tif ( deep ) {\n
+\t\tjQuery.extend( true, target, deep );\n
+\t}\n
+\n
+\treturn target;\n
+}\n
+\n
+jQuery.fn.load = function( url, params, callback ) {\n
+\tif ( typeof url !== "string" && _load ) {\n
+\t\treturn _load.apply( this, arguments );\n
+\t}\n
+\n
+\tvar selector, type, response,\n
+\t\tself = this,\n
+\t\toff = url.indexOf(" ");\n
+\n
+\tif ( off >= 0 ) {\n
+\t\tselector = url.slice( off );\n
+\t\turl = url.slice( 0, off );\n
+\t}\n
+\n
+\t// If it\'s a function\n
+\tif ( jQuery.isFunction( params ) ) {\n
+\n
+\t\t// We assume that it\'s the callback\n
+\t\tcallback = params;\n
+\t\tparams = undefined;\n
+\n
+\t// Otherwise, build a param string\n
+\t} else if ( params && typeof params === "object" ) {\n
+\t\ttype = "POST";\n
+\t}\n
+\n
+\t// If we have elements to modify, make the request\n
+\tif ( self.length > 0 ) {\n
+\t\tjQuery.ajax({\n
+\t\t\turl: url,\n
+\n
+\t\t\t// if "type" variable is undefined, then "GET" method will be used\n
+\t\t\ttype: type,\n
+\t\t\tdataType: "html",\n
+\t\t\tdata: params\n
+\t\t}).done(function( responseText ) {\n
+\n
+\t\t\t// Save response for use in complete callback\n
+\t\t\tresponse = arguments;\n
+\n
+\t\t\tself.html( selector ?\n
+\n
+\t\t\t\t// If a selector was specified, locate the right elements in a dummy div\n
+\t\t\t\t// Exclude scripts to avoid IE \'Permission Denied\' errors\n
+\t\t\t\tjQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :\n
+\n
+\t\t\t\t// Otherwise use the full result\n
+\t\t\t\tresponseText );\n
+\n
+\t\t}).complete( callback && function( jqXHR, status ) {\n
+\t\t\tself.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );\n
+\t\t});\n
+\t}\n
+\n
+\treturn this;\n
+};\n
+\n
+// Attach a bunch of functions for handling common AJAX events\n
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ){\n
+\tjQuery.fn[ type ] = function( fn ){\n
+\t\treturn this.on( type, fn );\n
+\t};\n
+});\n
+\n
+jQuery.extend({\n
+\n
+\t// Counter for holding the number of active queries\n
+\tactive: 0,\n
+\n
+\t// Last-Modified header cache for next request\n
+\tlastModified: {},\n
+\tetag: {},\n
+\n
+\tajaxSettings: {\n
+\t\turl: ajaxLocation,\n
+\t\ttype: "GET",\n
+\t\tisLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),\n
+\t\tglobal: true,\n
+\t\tprocessData: true,\n
+\t\tasync: true,\n
+\t\tcontentType: "application/x-www-form-urlencoded; charset=UTF-8",\n
+\t\t/*\n
+\t\ttimeout: 0,\n
+\t\tdata: null,\n
+\t\tdataType: null,\n
+\t\tusername: null,\n
+\t\tpassword: null,\n
+\t\tcache: null,\n
+\t\tthrows: false,\n
+\t\ttraditional: false,\n
+\t\theaders: {},\n
+\t\t*/\n
+\n
+\t\taccepts: {\n
+\t\t\t"*": allTypes,\n
+\t\t\ttext: "text/plain",\n
+\t\t\thtml: "text/html",\n
+\t\t\txml: "application/xml, text/xml",\n
+\t\t\tjson: "application/json, text/javascript"\n
+\t\t},\n
+\n
+\t\tcontents: {\n
+\t\t\txml: /xml/,\n
+\t\t\thtml: /html/,\n
+\t\t\tjson: /json/\n
+\t\t},\n
+\n
+\t\tresponseFields: {\n
+\t\t\txml: "responseXML",\n
+\t\t\ttext: "responseText",\n
+\t\t\tjson: "responseJSON"\n
+\t\t},\n
+\n
+\t\t// Data converters\n
+\t\t// Keys separate source (or catchall "*") and destination types with a single space\n
+\t\tconverters: {\n
+\n
+\t\t\t// Convert anything to text\n
+\t\t\t"* text": String,\n
+\n
+\t\t\t// Text to html (true = no transformation)\n
+\t\t\t"text html": true,\n
+\n
+\t\t\t// Evaluate text as a json expression\n
+\t\t\t"text json": jQuery.parseJSON,\n
+\n
+\t\t\t// Parse text as xml\n
+\t\t\t"text xml": jQuery.parseXML\n
+\t\t},\n
+\n
+\t\t// For options that shouldn\'t be deep extended:\n
+\t\t// you can add your own custom options here if\n
+\t\t// and when you create one that shouldn\'t be\n
+\t\t// deep extended (see ajaxExtend)\n
+\t\tflatOptions: {\n
+\t\t\turl: true,\n
+\t\t\tcontext: true\n
+\t\t}\n
+\t},\n
+\n
+\t// Creates a full fledged settings object into target\n
+\t// with both ajaxSettings and settings fields.\n
+\t// If target is omitted, writes into ajaxSettings.\n
+\tajaxSetup: function( target, settings ) {\n
+\t\treturn settings ?\n
+\n
+\t\t\t// Building a settings object\n
+\t\t\tajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :\n
+\n
+\t\t\t// Extending ajaxSettings\n
+\t\t\tajaxExtend( jQuery.ajaxSettings, target );\n
+\t},\n
+\n
+\tajaxPrefilter: addToPrefiltersOrTransports( prefilters ),\n
+\tajaxTransport: addToPrefiltersOrTransports( transports ),\n
+\n
+\t// Main method\n
+\tajax: function( url, options ) {\n
+\n
+\t\t// If url is an object, simulate pre-1.5 signature\n
+\t\tif ( typeof url === "object" ) {\n
+\t\t\toptions = url;\n
+\t\t\turl = undefined;\n
+\t\t}\n
+\n
+\t\t// Force options to be an object\n
+\t\toptions = options || {};\n
+\n
+\t\tvar transport,\n
+\t\t\t// URL without anti-cache param\n
+\t\t\tcacheURL,\n
+\t\t\t// Response headers\n
+\t\t\tresponseHeadersString,\n
+\t\t\tresponseHeaders,\n
+\t\t\t// timeout handle\n
+\t\t\ttimeoutTimer,\n
+\t\t\t// Cross-domain detection vars\n
+\t\t\tparts,\n
+\t\t\t// To know if global events are to be dispatched\n
+\t\t\tfireGlobals,\n
+\t\t\t// Loop variable\n
+\t\t\ti,\n
+\t\t\t// Create the final options object\n
+\t\t\ts = jQuery.ajaxSetup( {}, options ),\n
+\t\t\t// Callbacks context\n
+\t\t\tcallbackContext = s.context || s,\n
+\t\t\t// Context for global events is callbackContext if it is a DOM node or jQuery collection\n
+\t\t\tglobalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?\n
+\t\t\t\tjQuery( callbackContext ) :\n
+\t\t\t\tjQuery.event,\n
+\t\t\t// Deferreds\n
+\t\t\tdeferred = jQuery.Deferred(),\n
+\t\t\tcompleteDeferred = jQuery.Callbacks("once memory"),\n
+\t\t\t// Status-dependent callbacks\n
+\t\t\tstatusCode = s.statusCode || {},\n
+\t\t\t// Headers (they are sent all at once)\n
+\t\t\trequestHeaders = {},\n
+\t\t\trequestHeadersNames = {},\n
+\t\t\t// The jqXHR state\n
+\t\t\tstate = 0,\n
+\t\t\t// Default abort message\n
+\t\t\tstrAbort = "canceled",\n
+\t\t\t// Fake xhr\n
+\t\t\tjqXHR = {\n
+\t\t\t\treadyState: 0,\n
+\n
+\t\t\t\t// Builds headers hashtable if needed\n
+\t\t\t\tgetResponseHeader: function( key ) {\n
+\t\t\t\t\tvar match;\n
+\t\t\t\t\tif ( state === 2 ) {\n
+\t\t\t\t\t\tif ( !responseHeaders ) {\n
+\t\t\t\t\t\t\tresponseHeaders = {};\n
+\t\t\t\t\t\t\twhile ( (match = rheaders.exec( responseHeadersString )) ) {\n
+\t\t\t\t\t\t\t\tresponseHeaders[ match[1].toLowerCase() ] = match[ 2 ];\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\tmatch = responseHeaders[ key.toLowerCase() ];\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn match == null ? null : match;\n
+\t\t\t\t},\n
+\n
+\t\t\t\t// Raw string\n
+\t\t\t\tgetAllResponseHeaders: function() {\n
+\t\t\t\t\treturn state === 2 ? responseHeadersString : null;\n
+\t\t\t\t},\n
+\n
+\t\t\t\t// Caches the header\n
+\t\t\t\tsetRequestHeader: function( name, value ) {\n
+\t\t\t\t\tvar lname = name.toLowerCase();\n
+\t\t\t\t\tif ( !state ) {\n
+\t\t\t\t\t\tname = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;\n
+\t\t\t\t\t\trequestHeaders[ name ] = value;\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn this;\n
+\t\t\t\t},\n
+\n
+\t\t\t\t// Overrides response content-type header\n
+\t\t\t\toverrideMimeType: function( type ) {\n
+\t\t\t\t\tif ( !state ) {\n
+\t\t\t\t\t\ts.mimeType = type;\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn this;\n
+\t\t\t\t},\n
+\n
+\t\t\t\t// Status-dependent callbacks\n
+\t\t\t\tstatusCode: function( map ) {\n
+\t\t\t\t\tvar code;\n
+\t\t\t\t\tif ( map ) {\n
+\t\t\t\t\t\tif ( state < 2 ) {\n
+\t\t\t\t\t\t\tfor ( code in map ) {\n
+\t\t\t\t\t\t\t\t// Lazy-add the new callback in a way that preserves old ones\n
+\t\t\t\t\t\t\t\tstatusCode[ code ] = [ statusCode[ code ], map[ code ] ];\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t// Execute the appropriate callbacks\n
+\t\t\t\t\t\t\tjqXHR.always( map[ jqXHR.status ] );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn this;\n
+\t\t\t\t},\n
+\n
+\t\t\t\t// Cancel the request\n
+\t\t\t\tabort: function( statusText ) {\n
+\t\t\t\t\tvar finalText = statusText || strAbort;\n
+\t\t\t\t\tif ( transport ) {\n
+\t\t\t\t\t\ttransport.abort( finalText );\n
+\t\t\t\t\t}\n
+\t\t\t\t\tdone( 0, finalText );\n
+\t\t\t\t\treturn this;\n
+\t\t\t\t}\n
+\t\t\t};\n
+\n
+\t\t// Attach deferreds\n
+\t\tdeferred.promise( jqXHR ).complete = completeDeferred.add;\n
+\t\tjqXHR.success = jqXHR.done;\n
+\t\tjqXHR.error = jqXHR.fail;\n
+\n
+\t\t// Remove hash character (#7531: and string promotion)\n
+\t\t// Add protocol if not provided (prefilters might expect it)\n
+\t\t// Handle falsy url in the settings object (#10093: consistency with old signature)\n
+\t\t// We also use the url parameter if available\n
+\t\ts.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" )\n
+\t\t\t.replace( rprotocol, ajaxLocParts[ 1 ] + "//" );\n
+\n
+\t\t// Alias method option to type as per ticket #12004\n
+\t\ts.type = options.method || options.type || s.method || s.type;\n
+\n
+\t\t// Extract dataTypes list\n
+\t\ts.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( core_rnotwhite ) || [""];\n
+\n
+\t\t// A cross-domain request is in order when we have a protocol:host:port mismatch\n
+\t\tif ( s.crossDomain == null ) {\n
+\t\t\tparts = rurl.exec( s.url.toLowerCase() );\n
+\t\t\ts.crossDomain = !!( parts &&\n
+\t\t\t\t( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||\n
+\t\t\t\t\t( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==\n
+\t\t\t\t\t\t( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )\n
+\t\t\t);\n
+\t\t}\n
+\n
+\t\t// Convert data if not already a string\n
+\t\tif ( s.data && s.processData && typeof s.data !== "string" ) {\n
+\t\t\ts.data = jQuery.param( s.data, s.traditional );\n
+\t\t}\n
+\n
+\t\t// Apply prefilters\n
+\t\tinspectPrefiltersOrTransports( prefilters, s, options, jqXHR );\n
+\n
+\t\t// If request was aborted inside a prefilter, stop there\n
+\t\tif ( state === 2 ) {\n
+\t\t\treturn jqXHR;\n
+\t\t}\n
+\n
+\t\t// We can fire global events as of now if asked to\n
+\t\tfireGlobals = s.global;\n
+\n
+\t\t// Watch for a new set of requests\n
+\t\tif ( fireGlobals && jQuery.active++ === 0 ) {\n
+\t\t\tjQuery.event.trigger("ajaxStart");\n
+\t\t}\n
+\n
+\t\t// Uppercase the type\n
+\t\ts.type = s.type.toUpperCase();\n
+\n
+\t\t// Determine if request has content\n
+\t\ts.hasContent = !rnoContent.test( s.type );\n
+\n
+\t\t// Save the URL in case we\'re toying with the If-Modified-Since\n
+\t\t// and/or If-None-Match header later on\n
+\t\tcacheURL = s.url;\n
+\n
+\t\t// More options handling for requests with no content\n
+\t\tif ( !s.hasContent ) {\n
+\n
+\t\t\t// If data is available, append data to url\n
+\t\t\tif ( s.data ) {\n
+\t\t\t\tcacheURL = ( s.url += ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + s.data );\n
+\t\t\t\t// #9682: remove data so that it\'s not used in an eventual retry\n
+\t\t\t\tdelete s.data;\n
+\t\t\t}\n
+\n
+\t\t\t// Add anti-cache in url if needed\n
+\t\t\tif ( s.cache === false ) {\n
+\t\t\t\ts.url = rts.test( cacheURL ) ?\n
+\n
+\t\t\t\t\t// If there is already a \'_\' parameter, set its value\n
+\t\t\t\t\tcacheURL.replace( rts, "$1_=" + ajax_nonce++ ) :\n
+\n
+\t\t\t\t\t// Otherwise add one to the end\n
+\t\t\t\t\tcacheURL + ( ajax_rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ajax_nonce++;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n
+\t\tif ( s.ifModified ) {\n
+\t\t\tif ( jQuery.lastModified[ cacheURL ] ) {\n
+\t\t\t\tjqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );\n
+\t\t\t}\n
+\t\t\tif ( jQuery.etag[ cacheURL ] ) {\n
+\t\t\t\tjqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Set the correct header, if data is being sent\n
+\t\tif ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {\n
+\t\t\tjqXHR.setRequestHeader( "Content-Type", s.contentType );\n
+\t\t}\n
+\n
+\t\t// Set the Accepts header for the server, depending on the dataType\n
+\t\tjqXHR.setRequestHeader(\n
+\t\t\t"Accept",\n
+\t\t\ts.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?\n
+\t\t\t\ts.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :\n
+\t\t\t\ts.accepts[ "*" ]\n
+\t\t);\n
+\n
+\t\t// Check for headers option\n
+\t\tfor ( i in s.headers ) {\n
+\t\t\tjqXHR.setRequestHeader( i, s.headers[ i ] );\n
+\t\t}\n
+\n
+\t\t// Allow custom headers/mimetypes and early abort\n
+\t\tif ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {\n
+\t\t\t// Abort if not done already and return\n
+\t\t\treturn jqXHR.abort();\n
+\t\t}\n
+\n
+\t\t// aborting is no longer a cancellation\n
+\t\tstrAbort = "abort";\n
+\n
+\t\t// Install callbacks on deferreds\n
+\t\tfor ( i in { success: 1, error: 1, complete: 1 } ) {\n
+\t\t\tjqXHR[ i ]( s[ i ] );\n
+\t\t}\n
+\n
+\t\t// Get transport\n
+\t\ttransport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );\n
+\n
+\t\t// If no transport, we auto-abort\n
+\t\tif ( !transport ) {\n
+\t\t\tdone( -1, "No Transport" );\n
+\t\t} else {\n
+\t\t\tjqXHR.readyState = 1;\n
+\n
+\t\t\t// Send global event\n
+\t\t\tif ( fireGlobals ) {\n
+\t\t\t\tglobalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );\n
+\t\t\t}\n
+\t\t\t// Timeout\n
+\t\t\tif ( s.async && s.timeout > 0 ) {\n
+\t\t\t\ttimeoutTimer = setTimeout(function() {\n
+\t\t\t\t\tjqXHR.abort("timeout");\n
+\t\t\t\t}, s.timeout );\n
+\t\t\t}\n
+\n
+\t\t\ttry {\n
+\t\t\t\tstate = 1;\n
+\t\t\t\ttransport.send( requestHeaders, done );\n
+\t\t\t} catch ( e ) {\n
+\t\t\t\t// Propagate exception as error if not done\n
+\t\t\t\tif ( state < 2 ) {\n
+\t\t\t\t\tdone( -1, e );\n
+\t\t\t\t// Simply rethrow otherwise\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthrow e;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// Callback for when everything is done\n
+\t\tfunction done( status, nativeStatusText, responses, headers ) {\n
+\t\t\tvar isSuccess, success, error, response, modified,\n
+\t\t\t\tstatusText = nativeStatusText;\n
+\n
+\t\t\t// Called once\n
+\t\t\tif ( state === 2 ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// State is "done" now\n
+\t\t\tstate = 2;\n
+\n
+\t\t\t// Clear timeout if it exists\n
+\t\t\tif ( timeoutTimer ) {\n
+\t\t\t\tclearTimeout( timeoutTimer );\n
+\t\t\t}\n
+\n
+\t\t\t// Dereference transport for early garbage collection\n
+\t\t\t// (no matter how long the jqXHR object will be used)\n
+\t\t\ttransport = undefined;\n
+\n
+\t\t\t// Cache response headers\n
+\t\t\tresponseHeadersString = headers || "";\n
+\n
+\t\t\t// Set readyState\n
+\t\t\tjqXHR.readyState = status > 0 ? 4 : 0;\n
+\n
+\t\t\t// Determine if successful\n
+\t\t\tisSuccess = status >= 200 && status < 300 || status === 304;\n
+\n
+\t\t\t// Get response data\n
+\t\t\tif ( responses ) {\n
+\t\t\t\tresponse = ajaxHandleResponses( s, jqXHR, responses );\n
+\t\t\t}\n
+\n
+\t\t\t// Convert no matter what (that way responseXXX fields are always set)\n
+\t\t\tresponse = ajaxConvert( s, response, jqXHR, isSuccess );\n
+\n
+\t\t\t// If successful, handle type chaining\n
+\t\t\tif ( isSuccess ) {\n
+\n
+\t\t\t\t// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.\n
+\t\t\t\tif ( s.ifModified ) {\n
+\t\t\t\t\tmodified = jqXHR.getResponseHeader("Last-Modified");\n
+\t\t\t\t\tif ( modified ) {\n
+\t\t\t\t\t\tjQuery.lastModified[ cacheURL ] = modified;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tmodified = jqXHR.getResponseHeader("etag");\n
+\t\t\t\t\tif ( modified ) {\n
+\t\t\t\t\t\tjQuery.etag[ cacheURL ] = modified;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// if no content\n
+\t\t\t\tif ( status === 204 || s.type === "HEAD" ) {\n
+\t\t\t\t\tstatusText = "nocontent";\n
+\n
+\t\t\t\t// if not modified\n
+\t\t\t\t} else if ( status === 304 ) {\n
+\t\t\t\t\tstatusText = "notmodified";\n
+\n
+\t\t\t\t// If we have data, let\'s convert it\n
+\t\t\t\t} else {\n
+\t\t\t\t\tstatusText = response.state;\n
+\t\t\t\t\tsuccess = response.data;\n
+\t\t\t\t\terror = response.error;\n
+\t\t\t\t\tisSuccess = !error;\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\t// We extract error from statusText\n
+\t\t\t\t// then normalize statusText and status for non-aborts\n
+\t\t\t\terror = statusText;\n
+\t\t\t\tif ( status || !statusText ) {\n
+\t\t\t\t\tstatusText = "error";\n
+\t\t\t\t\tif ( status < 0 ) {\n
+\t\t\t\t\t\tstatus = 0;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// Set data for the fake xhr object\n
+\t\t\tjqXHR.status = status;\n
+\t\t\tjqXHR.statusText = ( nativeStatusText || statusText ) + "";\n
+\n
+\t\t\t// Success/Error\n
+\t\t\tif ( isSuccess ) {\n
+\t\t\t\tdeferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );\n
+\t\t\t} else {\n
+\t\t\t\tdeferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );\n
+\t\t\t}\n
+\n
+\t\t\t// Status-dependent callbacks\n
+\t\t\tjqXHR.statusCode( statusCode );\n
+\t\t\tstatusCode = undefined;\n
+\n
+\t\t\tif ( fireGlobals ) {\n
+\t\t\t\tglobalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",\n
+\t\t\t\t\t[ jqXHR, s, isSuccess ? success : error ] );\n
+\t\t\t}\n
+\n
+\t\t\t// Complete\n
+\t\t\tcompleteDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );\n
+\n
+\t\t\tif ( fireGlobals ) {\n
+\t\t\t\tglobalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );\n
+\t\t\t\t// Handle the global AJAX counter\n
+\t\t\t\tif ( !( --jQuery.active ) ) {\n
+\t\t\t\t\tjQuery.event.trigger("ajaxStop");\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn jqXHR;\n
+\t},\n
+\n
+\tgetJSON: function( url, data, callback ) {\n
+\t\treturn jQuery.get( url, data, callback, "json" );\n
+\t},\n
+\n
+\tgetScript: function( url, callback ) {\n
+\t\treturn jQuery.get( url, undefined, callback, "script" );\n
+\t}\n
+});\n
+\n
+jQuery.each( [ "get", "post" ], function( i, method ) {\n
+\tjQuery[ method ] = function( url, data, callback, type ) {\n
+\t\t// shift arguments if data argument was omitted\n
+\t\tif ( jQuery.isFunction( data ) ) {\n
+\t\t\ttype = type || callback;\n
+\t\t\tcallback = data;\n
+\t\t\tdata = undefined;\n
+\t\t}\n
+\n
+\t\treturn jQuery.ajax({\n
+\t\t\turl: url,\n
+\t\t\ttype: method,\n
+\t\t\tdataType: type,\n
+\t\t\tdata: data,\n
+\t\t\tsuccess: callback\n
+\t\t});\n
+\t};\n
+});\n
+\n
+/* Handles responses to an ajax request:\n
+ * - finds the right dataType (mediates between content-type and expected dataType)\n
+ * - returns the corresponding response\n
+ */\n
+function ajaxHandleResponses( s, jqXHR, responses ) {\n
+\n
+\tvar ct, type, finalDataType, firstDataType,\n
+\t\tcontents = s.contents,\n
+\t\tdataTypes = s.dataTypes;\n
+\n
+\t// Remove auto dataType and get content-type in the process\n
+\twhile( dataTypes[ 0 ] === "*" ) {\n
+\t\tdataTypes.shift();\n
+\t\tif ( ct === undefined ) {\n
+\t\t\tct = s.mimeType || jqXHR.getResponseHeader("Content-Type");\n
+\t\t}\n
+\t}\n
+\n
+\t// Check if we\'re dealing with a known content-type\n
+\tif ( ct ) {\n
+\t\tfor ( type in contents ) {\n
+\t\t\tif ( contents[ type ] && contents[ type ].test( ct ) ) {\n
+\t\t\t\tdataTypes.unshift( type );\n
+\t\t\t\tbreak;\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\t// Check to see if we have a response for the expected dataType\n
+\tif ( dataTypes[ 0 ] in responses ) {\n
+\t\tfinalDataType = dataTypes[ 0 ];\n
+\t} else {\n
+\t\t// Try convertible dataTypes\n
+\t\tfor ( type in responses ) {\n
+\t\t\tif ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {\n
+\t\t\t\tfinalDataType = type;\n
+\t\t\t\tbreak;\n
+\t\t\t}\n
+\t\t\tif ( !firstDataType ) {\n
+\t\t\t\tfirstDataType = type;\n
+\t\t\t}\n
+\t\t}\n
+\t\t// Or just use first one\n
+\t\tfinalDataType = finalDataType || firstDataType;\n
+\t}\n
+\n
+\t// If we found a dataType\n
+\t// We add the dataType to the list if needed\n
+\t// and return the corresponding response\n
+\tif ( finalDataType ) {\n
+\t\tif ( finalDataType !== dataTypes[ 0 ] ) {\n
+\t\t\tdataTypes.unshift( finalDataType );\n
+\t\t}\n
+\t\treturn responses[ finalDataType ];\n
+\t}\n
+}\n
+\n
+/* Chain conversions given the request and the original response\n
+ * Also sets the responseXXX fields on the jqXHR instance\n
+ */\n
+function ajaxConvert( s, response, jqXHR, isSuccess ) {\n
+\tvar conv2, current, conv, tmp, prev,\n
+\t\tconverters = {},\n
+\t\t// Work with a copy of dataTypes in case we need to modify it for conversion\n
+\t\tdataTypes = s.dataTypes.slice();\n
+\n
+\t// Create converters map with lowercased keys\n
+\tif ( dataTypes[ 1 ] ) {\n
+\t\tfor ( conv in s.converters ) {\n
+\t\t\tconverters[ conv.toLowerCase() ] = s.converters[ conv ];\n
+\t\t}\n
+\t}\n
+\n
+\tcurrent = dataTypes.shift();\n
+\n
+\t// Convert to each sequential dataType\n
+\twhile ( current ) {\n
+\n
+\t\tif ( s.responseFields[ current ] ) {\n
+\t\t\tjqXHR[ s.responseFields[ current ] ] = response;\n
+\t\t}\n
+\n
+\t\t// Apply the dataFilter if provided\n
+\t\tif ( !prev && isSuccess && s.dataFilter ) {\n
+\t\t\tresponse = s.dataFilter( response, s.dataType );\n
+\t\t}\n
+\n
+\t\tprev = current;\n
+\t\tcurrent = dataTypes.shift();\n
+\n
+\t\tif ( current ) {\n
+\n
+\t\t// There\'s only work to do if current dataType is non-auto\n
+\t\t\tif ( current === "*" ) {\n
+\n
+\t\t\t\tcurrent = prev;\n
+\n
+\t\t\t// Convert response if prev dataType is non-auto and differs from current\n
+\t\t\t} else if ( prev !== "*" && prev !== current ) {\n
+\n
+\t\t\t\t// Seek a direct converter\n
+\t\t\t\tconv = converters[ prev + " " + current ] || converters[ "* " + current ];\n
+\n
+\t\t\t\t// If none found, seek a pair\n
+\t\t\t\tif ( !conv ) {\n
+\t\t\t\t\tfor ( conv2 in converters ) {\n
+\n
+\t\t\t\t\t\t// If conv2 outputs current\n
+\t\t\t\t\t\ttmp = conv2.split( " " );\n
+\t\t\t\t\t\tif ( tmp[ 1 ] === current ) {\n
+\n
+\t\t\t\t\t\t\t// If prev can be converted to accepted input\n
+\t\t\t\t\t\t\tconv = converters[ prev + " " + tmp[ 0 ] ] ||\n
+\t\t\t\t\t\t\t\tconverters[ "* " + tmp[ 0 ] ];\n
+\t\t\t\t\t\t\tif ( conv ) {\n
+\t\t\t\t\t\t\t\t// Condense equivalence converters\n
+\t\t\t\t\t\t\t\tif ( conv === true ) {\n
+\t\t\t\t\t\t\t\t\tconv = converters[ conv2 ];\n
+\n
+\t\t\t\t\t\t\t\t// Otherwise, insert the intermediate dataType\n
+\t\t\t\t\t\t\t\t} else if ( converters[ conv2 ] !== true ) {\n
+\t\t\t\t\t\t\t\t\tcurrent = tmp[ 0 ];\n
+\t\t\t\t\t\t\t\t\tdataTypes.unshift( tmp[ 1 ] );\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Apply converter (if not an equivalence)\n
+\t\t\t\tif ( conv !== true ) {\n
+\n
+\t\t\t\t\t// Unless errors are allowed to bubble, catch and return them\n
+\t\t\t\t\tif ( conv && s[ "throws" ] ) {\n
+\t\t\t\t\t\tresponse = conv( response );\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\ttry {\n
+\t\t\t\t\t\t\tresponse = conv( response );\n
+\t\t\t\t\t\t} catch ( e ) {\n
+\t\t\t\t\t\t\treturn { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\treturn { state: "success", data: response };\n
+}\n
+// Install script dataType\n
+jQuery.ajaxSetup({\n
+\taccepts: {\n
+\t\tscript: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"\n
+\t},\n
+\tcontents: {\n
+\t\tscript: /(?:java|ecma)script/\n
+\t},\n
+\tconverters: {\n
+\t\t"text script": function( text ) {\n
+\t\t\tjQuery.globalEval( text );\n
+\t\t\treturn text;\n
+\t\t}\n
+\t}\n
+});\n
+\n
+// Handle cache\'s special case and crossDomain\n
+jQuery.ajaxPrefilter( "script", function( s ) {\n
+\tif ( s.cache === undefined ) {\n
+\t\ts.cache = false;\n
+\t}\n
+\tif ( s.crossDomain ) {\n
+\t\ts.type = "GET";\n
+\t}\n
+});\n
+\n
+// Bind script tag hack transport\n
+jQuery.ajaxTransport( "script", function( s ) {\n
+\t// This transport only deals with cross domain requests\n
+\tif ( s.crossDomain ) {\n
+\t\tvar script, callback;\n
+\t\treturn {\n
+\t\t\tsend: function( _, complete ) {\n
+\t\t\t\tscript = jQuery("<script>").prop({\n
+\t\t\t\t\tasync: true,\n
+\t\t\t\t\tcharset: s.scriptCharset,\n
+\t\t\t\t\tsrc: s.url\n
+\t\t\t\t}).on(\n
+\t\t\t\t\t"load error",\n
+\t\t\t\t\tcallback = function( evt ) {\n
+\t\t\t\t\t\tscript.remove();\n
+\t\t\t\t\t\tcallback = null;\n
+\t\t\t\t\t\tif ( evt ) {\n
+\t\t\t\t\t\t\tcomplete( evt.type === "error" ? 404 : 200, evt.type );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t);\n
+\t\t\t\tdocument.head.appendChild( script[ 0 ] );\n
+\t\t\t},\n
+\t\t\tabort: function() {\n
+\t\t\t\tif ( callback ) {\n
+\t\t\t\t\tcallback();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t};\n
+\t}\n
+});\n
+var oldCallbacks = [],\n
+\trjsonp = /(=)\\?(?=&|$)|\\?\\?/;\n
+\n
+// Default jsonp settings\n
+jQuery.ajaxSetup({\n
+\tjsonp: "callback",\n
+\tjsonpCallback: function() {\n
+\t\tvar callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );\n
+\t\tthis[ callback ] = true;\n
+\t\treturn callback;\n
+\t}\n
+});\n
+\n
+// Detect, normalize options and install callbacks for jsonp requests\n
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {\n
+\n
+\tvar callbackName, overwritten, responseContainer,\n
+\t\tjsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?\n
+\t\t\t"url" :\n
+\t\t\ttypeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"\n
+\t\t);\n
+\n
+\t// Handle iff the expected data type is "jsonp" or we have a parameter to set\n
+\tif ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {\n
+\n
+\t\t// Get callback name, remembering preexisting value associated with it\n
+\t\tcallbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?\n
+\t\t\ts.jsonpCallback() :\n
+\t\t\ts.jsonpCallback;\n
+\n
+\t\t// Insert callback into url or form data\n
+\t\tif ( jsonProp ) {\n
+\t\t\ts[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );\n
+\t\t} else if ( s.jsonp !== false ) {\n
+\t\t\ts.url += ( ajax_rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;\n
+\t\t}\n
+\n
+\t\t// Use data converter to retrieve json after script execution\n
+\t\ts.converters["script json"] = function() {\n
+\t\t\tif ( !responseContainer ) {\n
+\t\t\t\tjQuery.error( callbackName + " was not called" );\n
+\t\t\t}\n
+\t\t\treturn responseContainer[ 0 ];\n
+\t\t};\n
+\n
+\t\t// force json dataType\n
+\t\ts.dataTypes[ 0 ] = "json";\n
+\n
+\t\t// Install callback\n
+\t\toverwritten = window[ callbackName ];\n
+\t\twindow[ callbackName ] = function() {\n
+\t\t\tresponseContainer = arguments;\n
+\t\t};\n
+\n
+\t\t// Clean-up function (fires after converters)\n
+\t\tjqXHR.always(function() {\n
+\t\t\t// Restore preexisting value\n
+\t\t\twindow[ callbackName ] = overwritten;\n
+\n
+\t\t\t// Save back as free\n
+\t\t\tif ( s[ callbackName ] ) {\n
+\t\t\t\t// make sure that re-using the options doesn\'t screw things around\n
+\t\t\t\ts.jsonpCallback = originalSettings.jsonpCallback;\n
+\n
+\t\t\t\t// save the callback name for future use\n
+\t\t\t\toldCallbacks.push( callbackName );\n
+\t\t\t}\n
+\n
+\t\t\t// Call if it was a function and we have a response\n
+\t\t\tif ( responseContainer && jQuery.isFunction( overwritten ) ) {\n
+\t\t\t\toverwritten( responseContainer[ 0 ] );\n
+\t\t\t}\n
+\n
+\t\t\tresponseContainer = overwritten = undefined;\n
+\t\t});\n
+\n
+\t\t// Delegate to script\n
+\t\treturn "script";\n
+\t}\n
+});\n
+jQuery.ajaxSettings.xhr = function() {\n
+\ttry {\n
+\t\treturn new XMLHttpRequest();\n
+\t} catch( e ) {}\n
+};\n
+\n
+var xhrSupported = jQuery.ajaxSettings.xhr(),\n
+\txhrSuccessStatus = {\n
+\t\t// file protocol always yields status code 0, assume 200\n
+\t\t0: 200,\n
+\t\t// Support: IE9\n
+\t\t// #1450: sometimes IE returns 1223 when it should be 204\n
+\t\t1223: 204\n
+\t},\n
+\t// Support: IE9\n
+\t// We need to keep track of outbound xhr and abort them manually\n
+\t// because IE is not smart enough to do it all by itself\n
+\txhrId = 0,\n
+\txhrCallbacks = {};\n
+\n
+if ( window.ActiveXObject ) {\n
+\tjQuery( window ).on( "unload", function() {\n
+\t\tfor( var key in xhrCallbacks ) {\n
+\t\t\txhrCallbacks[ key ]();\n
+\t\t}\n
+\t\txhrCallbacks = undefined;\n
+\t});\n
+}\n
+\n
+jQuery.support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );\n
+jQuery.support.ajax = xhrSupported = !!xhrSupported;\n
+\n
+jQuery.ajaxTransport(function( options ) {\n
+\tvar callback;\n
+\t// Cross domain only allowed if supported through XMLHttpRequest\n
+\tif ( jQuery.support.cors || xhrSupported && !options.crossDomain ) {\n
+\t\treturn {\n
+\t\t\tsend: function( headers, complete ) {\n
+\t\t\t\tvar i, id,\n
+\t\t\t\t\txhr = options.xhr();\n
+\t\t\t\txhr.open( options.type, options.url, options.async, options.username, options.password );\n
+\t\t\t\t// Apply custom fields if provided\n
+\t\t\t\tif ( options.xhrFields ) {\n
+\t\t\t\t\tfor ( i in options.xhrFields ) {\n
+\t\t\t\t\t\txhr[ i ] = options.xhrFields[ i ];\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\t// Override mime type if needed\n
+\t\t\t\tif ( options.mimeType && xhr.overrideMimeType ) {\n
+\t\t\t\t\txhr.overrideMimeType( options.mimeType );\n
+\t\t\t\t}\n
+\t\t\t\t// X-Requested-With header\n
+\t\t\t\t// For cross-domain requests, seeing as conditions for a preflight are\n
+\t\t\t\t// akin to a jigsaw puzzle, we simply never set it to be sure.\n
+\t\t\t\t// (it can always be set on a per-request basis or even using ajaxSetup)\n
+\t\t\t\t// For same-domain requests, won\'t change header if already provided.\n
+\t\t\t\tif ( !options.crossDomain && !headers["X-Requested-With"] ) {\n
+\t\t\t\t\theaders["X-Requested-With"] = "XMLHttpRequest";\n
+\t\t\t\t}\n
+\t\t\t\t// Set headers\n
+\t\t\t\tfor ( i in headers ) {\n
+\t\t\t\t\txhr.setRequestHeader( i, headers[ i ] );\n
+\t\t\t\t}\n
+\t\t\t\t// Callback\n
+\t\t\t\tcallback = function( type ) {\n
+\t\t\t\t\treturn function() {\n
+\t\t\t\t\t\tif ( callback ) {\n
+\t\t\t\t\t\t\tdelete xhrCallbacks[ id ];\n
+\t\t\t\t\t\t\tcallback = xhr.onload = xhr.onerror = null;\n
+\t\t\t\t\t\t\tif ( type === "abort" ) {\n
+\t\t\t\t\t\t\t\txhr.abort();\n
+\t\t\t\t\t\t\t} else if ( type === "error" ) {\n
+\t\t\t\t\t\t\t\tcomplete(\n
+\t\t\t\t\t\t\t\t\t// file protocol always yields status 0, assume 404\n
+\t\t\t\t\t\t\t\t\txhr.status || 404,\n
+\t\t\t\t\t\t\t\t\txhr.statusText\n
+\t\t\t\t\t\t\t\t);\n
+\t\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t\tcomplete(\n
+\t\t\t\t\t\t\t\t\txhrSuccessStatus[ xhr.status ] || xhr.status,\n
+\t\t\t\t\t\t\t\t\txhr.statusText,\n
+\t\t\t\t\t\t\t\t\t// Support: IE9\n
+\t\t\t\t\t\t\t\t\t// #11426: When requesting binary data, IE9 will throw an exception\n
+\t\t\t\t\t\t\t\t\t// on any attempt to access responseText\n
+\t\t\t\t\t\t\t\t\ttypeof xhr.responseText === "string" ? {\n
+\t\t\t\t\t\t\t\t\t\ttext: xhr.responseText\n
+\t\t\t\t\t\t\t\t\t} : undefined,\n
+\t\t\t\t\t\t\t\t\txhr.getAllResponseHeaders()\n
+\t\t\t\t\t\t\t\t);\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t};\n
+\t\t\t\t};\n
+\t\t\t\t// Listen to events\n
+\t\t\t\txhr.onload = callback();\n
+\t\t\t\txhr.onerror = callback("error");\n
+\t\t\t\t// Create the abort callback\n
+\t\t\t\tcallback = xhrCallbacks[( id = xhrId++ )] = callback("abort");\n
+\t\t\t\t// Do send the request\n
+\t\t\t\t// This may raise an exception which is actually\n
+\t\t\t\t// handled in jQuery.ajax (so no try/catch here)\n
+\t\t\t\txhr.send( options.hasContent && options.data || null );\n
+\t\t\t},\n
+\t\t\tabort: function() {\n
+\t\t\t\tif ( callback ) {\n
+\t\t\t\t\tcallback();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t};\n
+\t}\n
+});\n
+var fxNow, timerId,\n
+\trfxtypes = /^(?:toggle|show|hide)$/,\n
+\trfxnum = new RegExp( "^(?:([+-])=|)(" + core_pnum + ")([a-z%]*)$", "i" ),\n
+\trrun = /queueHooks$/,\n
+\tanimationPrefilters = [ defaultPrefilter ],\n
+\ttweeners = {\n
+\t\t"*": [function( prop, value ) {\n
+\t\t\tvar tween = this.createTween( prop, value ),\n
+\t\t\t\ttarget = tween.cur(),\n
+\t\t\t\tparts = rfxnum.exec( value ),\n
+\t\t\t\tunit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),\n
+\n
+\t\t\t\t// Starting value computation is required for potential unit mismatches\n
+\t\t\t\tstart = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&\n
+\t\t\t\t\trfxnum.exec( jQuery.css( tween.elem, prop ) ),\n
+\t\t\t\tscale = 1,\n
+\t\t\t\tmaxIterations = 20;\n
+\n
+\t\t\tif ( start && start[ 3 ] !== unit ) {\n
+\t\t\t\t// Trust units reported by jQuery.css\n
+\t\t\t\tunit = unit || start[ 3 ];\n
+\n
+\t\t\t\t// Make sure we update the tween properties later on\n
+\t\t\t\tparts = parts || [];\n
+\n
+\t\t\t\t// Iteratively approximate from a nonzero starting point\n
+\t\t\t\tstart = +target || 1;\n
+\n
+\t\t\t\tdo {\n
+\t\t\t\t\t// If previous iteration zeroed out, double until we get *something*\n
+\t\t\t\t\t// Use a string for doubling factor so we don\'t accidentally see scale as unchanged below\n
+\t\t\t\t\tscale = scale || ".5";\n
+\n
+\t\t\t\t\t// Adjust and apply\n
+\t\t\t\t\tstart = start / scale;\n
+\t\t\t\t\tjQuery.style( tween.elem, prop, start + unit );\n
+\n
+\t\t\t\t// Update scale, tolerating zero or NaN from tween.cur()\n
+\t\t\t\t// And breaking the loop if scale is unchanged or perfect, or if we\'ve just had enough\n
+\t\t\t\t} while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );\n
+\t\t\t}\n
+\n
+\t\t\t// Update tween properties\n
+\t\t\tif ( parts ) {\n
+\t\t\t\tstart = tween.start = +start || +target || 0;\n
+\t\t\t\ttween.unit = unit;\n
+\t\t\t\t// If a +=/-= token was provided, we\'re doing a relative animation\n
+\t\t\t\ttween.end = parts[ 1 ] ?\n
+\t\t\t\t\tstart + ( parts[ 1 ] + 1 ) * parts[ 2 ] :\n
+\t\t\t\t\t+parts[ 2 ];\n
+\t\t\t}\n
+\n
+\t\t\treturn tween;\n
+\t\t}]\n
+\t};\n
+\n
+// Animations created synchronously will run synchronously\n
+function createFxNow() {\n
+\tsetTimeout(function() {\n
+\t\tfxNow = undefined;\n
+\t});\n
+\treturn ( fxNow = jQuery.now() );\n
+}\n
+\n
+function createTween( value, prop, animation ) {\n
+\tvar tween,\n
+\t\tcollection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),\n
+\t\tindex = 0,\n
+\t\tlength = collection.length;\n
+\tfor ( ; index < length; index++ ) {\n
+\t\tif ( (tween = collection[ index ].call( animation, prop, value )) ) {\n
+\n
+\t\t\t// we\'re done with this property\n
+\t\t\treturn tween;\n
+\t\t}\n
+\t}\n
+}\n
+\n
+function Animation( elem, properties, options ) {\n
+\tvar result,\n
+\t\tstopped,\n
+\t\tindex = 0,\n
+\t\tlength = animationPrefilters.length,\n
+\t\tdeferred = jQuery.Deferred().always( function() {\n
+\t\t\t// don\'t match elem in the :animated selector\n
+\t\t\tdelete tick.elem;\n
+\t\t}),\n
+\t\ttick = function() {\n
+\t\t\tif ( stopped ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t\tvar currentTime = fxNow || createFxNow(),\n
+\t\t\t\tremaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),\n
+\t\t\t\t// archaic crash bug won\'t allow us to use 1 - ( 0.5 || 0 ) (#12497)\n
+\t\t\t\ttemp = remaining / animation.duration || 0,\n
+\t\t\t\tpercent = 1 - temp,\n
+\t\t\t\tindex = 0,\n
+\t\t\t\tlength = animation.tweens.length;\n
+\n
+\t\t\tfor ( ; index < length ; index++ ) {\n
+\t\t\t\tanimation.tweens[ index ].run( percent );\n
+\t\t\t}\n
+\n
+\t\t\tdeferred.notifyWith( elem, [ animation, percent, remaining ]);\n
+\n
+\t\t\tif ( percent < 1 && length ) {\n
+\t\t\t\treturn remaining;\n
+\t\t\t} else {\n
+\t\t\t\tdeferred.resolveWith( elem, [ animation ] );\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t},\n
+\t\tanimation = deferred.promise({\n
+\t\t\telem: elem,\n
+\t\t\tprops: jQuery.extend( {}, properties ),\n
+\t\t\topts: jQuery.extend( true, { specialEasing: {} }, options ),\n
+\t\t\toriginalProperties: properties,\n
+\t\t\toriginalOptions: options,\n
+\t\t\tstartTime: fxNow || createFxNow(),\n
+\t\t\tduration: options.duration,\n
+\t\t\ttweens: [],\n
+\t\t\tcreateTween: function( prop, end ) {\n
+\t\t\t\tvar tween = jQuery.Tween( elem, animation.opts, prop, end,\n
+\t\t\t\t\t\tanimation.opts.specialEasing[ prop ] || animation.opts.easing );\n
+\t\t\t\tanimation.tweens.push( tween );\n
+\t\t\t\treturn tween;\n
+\t\t\t},\n
+\t\t\tstop: function( gotoEnd ) {\n
+\t\t\t\tvar index = 0,\n
+\t\t\t\t\t// if we are going to the end, we want to run all the tweens\n
+\t\t\t\t\t// otherwise we skip this part\n
+\t\t\t\t\tlength = gotoEnd ? animation.tweens.length : 0;\n
+\t\t\t\tif ( stopped ) {\n
+\t\t\t\t\treturn this;\n
+\t\t\t\t}\n
+\t\t\t\tstopped = true;\n
+\t\t\t\tfor ( ; index < length ; index++ ) {\n
+\t\t\t\t\tanimation.tweens[ index ].run( 1 );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// resolve when we played the last frame\n
+\t\t\t\t// otherwise, reject\n
+\t\t\t\tif ( gotoEnd ) {\n
+\t\t\t\t\tdeferred.resolveWith( elem, [ animation, gotoEnd ] );\n
+\t\t\t\t} else {\n
+\t\t\t\t\tdeferred.rejectWith( elem, [ animation, gotoEnd ] );\n
+\t\t\t\t}\n
+\t\t\t\treturn this;\n
+\t\t\t}\n
+\t\t}),\n
+\t\tprops = animation.props;\n
+\n
+\tpropFilter( props, animation.opts.specialEasing );\n
+\n
+\tfor ( ; index < length ; index++ ) {\n
+\t\tresult = animationPrefilters[ index ].call( animation, elem, props, animation.opts );\n
+\t\tif ( result ) {\n
+\t\t\treturn result;\n
+\t\t}\n
+\t}\n
+\n
+\tjQuery.map( props, createTween, animation );\n
+\n
+\tif ( jQuery.isFunction( animation.opts.start ) ) {\n
+\t\tanimation.opts.start.call( elem, animation );\n
+\t}\n
+\n
+\tjQuery.fx.timer(\n
+\t\tjQuery.extend( tick, {\n
+\t\t\telem: elem,\n
+\t\t\tanim: animation,\n
+\t\t\tqueue: animation.opts.queue\n
+\t\t})\n
+\t);\n
+\n
+\t// attach callbacks from options\n
+\treturn animation.progress( animation.opts.progress )\n
+\t\t.done( animation.opts.done, animation.opts.complete )\n
+\t\t.fail( animation.opts.fail )\n
+\t\t.always( animation.opts.always );\n
+}\n
+\n
+function propFilter( props, specialEasing ) {\n
+\tvar index, name, easing, value, hooks;\n
+\n
+\t// camelCase, specialEasing and expand cssHook pass\n
+\tfor ( index in props ) {\n
+\t\tname = jQuery.camelCase( index );\n
+\t\teasing = specialEasing[ name ];\n
+\t\tvalue = props[ index ];\n
+\t\tif ( jQuery.isArray( value ) ) {\n
+\t\t\teasing = value[ 1 ];\n
+\t\t\tvalue = props[ index ] = value[ 0 ];\n
+\t\t}\n
+\n
+\t\tif ( index !== name ) {\n
+\t\t\tprops[ name ] = value;\n
+\t\t\tdelete props[ index ];\n
+\t\t}\n
+\n
+\t\thooks = jQuery.cssHooks[ name ];\n
+\t\tif ( hooks && "expand" in hooks ) {\n
+\t\t\tvalue = hooks.expand( value );\n
+\t\t\tdelete props[ name ];\n
+\n
+\t\t\t// not quite $.extend, this wont overwrite keys already present.\n
+\t\t\t// also - reusing \'index\' from above because we have the correct "name"\n
+\t\t\tfor ( index in value ) {\n
+\t\t\t\tif ( !( index in props ) ) {\n
+\t\t\t\t\tprops[ index ] = value[ index ];\n
+\t\t\t\t\tspecialEasing[ index ] = easing;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tspecialEasing[ name ] = easing;\n
+\t\t}\n
+\t}\n
+}\n
+\n
+jQuery.Animation = jQuery.extend( Animation, {\n
+\n
+\ttweener: function( props, callback ) {\n
+\t\tif ( jQuery.isFunction( props ) ) {\n
+\t\t\tcallback = props;\n
+\t\t\tprops = [ "*" ];\n
+\t\t} else {\n
+\t\t\tprops = props.split(" ");\n
+\t\t}\n
+\n
+\t\tvar prop,\n
+\t\t\tindex = 0,\n
+\t\t\tlength = props.length;\n
+\n
+\t\tfor ( ; index < length ; index++ ) {\n
+\t\t\tprop = props[ index ];\n
+\t\t\ttweeners[ prop ] = tweeners[ prop ] || [];\n
+\t\t\ttweeners[ prop ].unshift( callback );\n
+\t\t}\n
+\t},\n
+\n
+\tprefilter: function( callback, prepend ) {\n
+\t\tif ( prepend ) {\n
+\t\t\tanimationPrefilters.unshift( callback );\n
+\t\t} else {\n
+\t\t\tanimationPrefilters.push( callback );\n
+\t\t}\n
+\t}\n
+});\n
+\n
+function defaultPrefilter( elem, props, opts ) {\n
+\t/* jshint validthis: true */\n
+\tvar prop, value, toggle, tween, hooks, oldfire,\n
+\t\tanim = this,\n
+\t\torig = {},\n
+\t\tstyle = elem.style,\n
+\t\thidden = elem.nodeType && isHidden( elem ),\n
+\t\tdataShow = data_priv.get( elem, "fxshow" );\n
+\n
+\t// handle queue: false promises\n
+\tif ( !opts.queue ) {\n
+\t\thooks = jQuery._queueHooks( elem, "fx" );\n
+\t\tif ( hooks.unqueued == null ) {\n
+\t\t\thooks.unqueued = 0;\n
+\t\t\toldfire = hooks.empty.fire;\n
+\t\t\thooks.empty.fire = function() {\n
+\t\t\t\tif ( !hooks.unqueued ) {\n
+\t\t\t\t\toldfire();\n
+\t\t\t\t}\n
+\t\t\t};\n
+\t\t}\n
+\t\thooks.unqueued++;\n
+\n
+\t\tanim.always(function() {\n
+\t\t\t// doing this makes sure that the complete handler will be called\n
+\t\t\t// before this completes\n
+\t\t\tanim.always(function() {\n
+\t\t\t\thooks.unqueued--;\n
+\t\t\t\tif ( !jQuery.queue( elem, "fx" ).length ) {\n
+\t\t\t\t\thooks.empty.fire();\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t});\n
+\t}\n
+\n
+\t// height/width overflow pass\n
+\tif ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {\n
+\t\t// Make sure that nothing sneaks out\n
+\t\t// Record all 3 overflow attributes because IE9-10 do not\n
+\t\t// change the overflow attribute when overflowX and\n
+\t\t// overflowY are set to the same value\n
+\t\topts.overflow = [ style.overflow, style.overflowX, style.overflowY ];\n
+\n
+\t\t// Set display property to inline-block for height/width\n
+\t\t// animations on inline elements that are having width/height animated\n
+\t\tif ( jQuery.css( elem, "display" ) === "inline" &&\n
+\t\t\t\tjQuery.css( elem, "float" ) === "none" ) {\n
+\n
+\t\t\tstyle.display = "inline-block";\n
+\t\t}\n
+\t}\n
+\n
+\tif ( opts.overflow ) {\n
+\t\tstyle.overflow = "hidden";\n
+\t\tanim.always(function() {\n
+\t\t\tstyle.overflow = opts.overflow[ 0 ];\n
+\t\t\tstyle.overflowX = opts.overflow[ 1 ];\n
+\t\t\tstyle.overflowY = opts.overflow[ 2 ];\n
+\t\t});\n
+\t}\n
+\n
+\n
+\t// show/hide pass\n
+\tfor ( prop in props ) {\n
+\t\tvalue = props[ prop ];\n
+\t\tif ( rfxtypes.exec( value ) ) {\n
+\t\t\tdelete props[ prop ];\n
+\t\t\ttoggle = toggle || value === "toggle";\n
+\t\t\tif ( value === ( hidden ? "hide" : "show" ) ) {\n
+\n
+\t\t\t\t// If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden\n
+\t\t\t\tif ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {\n
+\t\t\t\t\thidden = true;\n
+\t\t\t\t} else {\n
+\t\t\t\t\tcontinue;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\torig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );\n
+\t\t}\n
+\t}\n
+\n
+\tif ( !jQuery.isEmptyObject( orig ) ) {\n
+\t\tif ( dataShow ) {\n
+\t\t\tif ( "hidden" in dataShow ) {\n
+\t\t\t\thidden = dataShow.hidden;\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tdataShow = data_priv.access( elem, "fxshow", {} );\n
+\t\t}\n
+\n
+\t\t// store state if its toggle - enables .stop().toggle() to "reverse"\n
+\t\tif ( toggle ) {\n
+\t\t\tdataShow.hidden = !hidden;\n
+\t\t}\n
+\t\tif ( hidden ) {\n
+\t\t\tjQuery( elem ).show();\n
+\t\t} else {\n
+\t\t\tanim.done(function() {\n
+\t\t\t\tjQuery( elem ).hide();\n
+\t\t\t});\n
+\t\t}\n
+\t\tanim.done(function() {\n
+\t\t\tvar prop;\n
+\n
+\t\t\tdata_priv.remove( elem, "fxshow" );\n
+\t\t\tfor ( prop in orig ) {\n
+\t\t\t\tjQuery.style( elem, prop, orig[ prop ] );\n
+\t\t\t}\n
+\t\t});\n
+\t\tfor ( prop in orig ) {\n
+\t\t\ttween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );\n
+\n
+\t\t\tif ( !( prop in dataShow ) ) {\n
+\t\t\t\tdataShow[ prop ] = tween.start;\n
+\t\t\t\tif ( hidden ) {\n
+\t\t\t\t\ttween.end = tween.start;\n
+\t\t\t\t\ttween.start = prop === "width" || prop === "height" ? 1 : 0;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+}\n
+\n
+function Tween( elem, options, prop, end, easing ) {\n
+\treturn new Tween.prototype.init( elem, options, prop, end, easing );\n
+}\n
+jQuery.Tween = Tween;\n
+\n
+Tween.prototype = {\n
+\tconstructor: Tween,\n
+\tinit: function( elem, options, prop, end, easing, unit ) {\n
+\t\tthis.elem = elem;\n
+\t\tthis.prop = prop;\n
+\t\tthis.easing = easing || "swing";\n
+\t\tthis.options = options;\n
+\t\tthis.start = this.now = this.cur();\n
+\t\tthis.end = end;\n
+\t\tthis.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );\n
+\t},\n
+\tcur: function() {\n
+\t\tvar hooks = Tween.propHooks[ this.prop ];\n
+\n
+\t\treturn hooks && hooks.get ?\n
+\t\t\thooks.get( this ) :\n
+\t\t\tTween.propHooks._default.get( this );\n
+\t},\n
+\trun: function( percent ) {\n
+\t\tvar eased,\n
+\t\t\thooks = Tween.propHooks[ this.prop ];\n
+\n
+\t\tif ( this.options.duration ) {\n
+\t\t\tthis.pos = eased = jQuery.easing[ this.easing ](\n
+\t\t\t\tpercent, this.options.duration * percent, 0, 1, this.options.duration\n
+\t\t\t);\n
+\t\t} else {\n
+\t\t\tthis.pos = eased = percent;\n
+\t\t}\n
+\t\tthis.now = ( this.end - this.start ) * eased + this.start;\n
+\n
+\t\tif ( this.options.step ) {\n
+\t\t\tthis.options.step.call( this.elem, this.now, this );\n
+\t\t}\n
+\n
+\t\tif ( hooks && hooks.set ) {\n
+\t\t\thooks.set( this );\n
+\t\t} else {\n
+\t\t\tTween.propHooks._default.set( this );\n
+\t\t}\n
+\t\treturn this;\n
+\t}\n
+};\n
+\n
+Tween.prototype.init.prototype = Tween.prototype;\n
+\n
+Tween.propHooks = {\n
+\t_default: {\n
+\t\tget: function( tween ) {\n
+\t\t\tvar result;\n
+\n
+\t\t\tif ( tween.elem[ tween.prop ] != null &&\n
+\t\t\t\t(!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {\n
+\t\t\t\treturn tween.elem[ tween.prop ];\n
+\t\t\t}\n
+\n
+\t\t\t// passing an empty string as a 3rd parameter to .css will automatically\n
+\t\t\t// attempt a parseFloat and fallback to a string if the parse fails\n
+\t\t\t// so, simple values such as "10px" are parsed to Float.\n
+\t\t\t// complex values such as "rotate(1rad)" are returned as is.\n
+\t\t\tresult = jQuery.css( tween.elem, tween.prop, "" );\n
+\t\t\t// Empty strings, null, undefined and "auto" are converted to 0.\n
+\t\t\treturn !result || result === "auto" ? 0 : result;\n
+\t\t},\n
+\t\tset: function( tween ) {\n
+\t\t\t// use step hook for back compat - use cssHook if its there - use .style if its\n
+\t\t\t// available and use plain properties where available\n
+\t\t\tif ( jQuery.fx.step[ tween.prop ] ) {\n
+\t\t\t\tjQuery.fx.step[ tween.prop ]( tween );\n
+\t\t\t} else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {\n
+\t\t\t\tjQuery.style( tween.elem, tween.prop, tween.now + tween.unit );\n
+\t\t\t} else {\n
+\t\t\t\ttween.elem[ tween.prop ] = tween.now;\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+};\n
+\n
+// Support: IE9\n
+// Panic based approach to setting things on disconnected nodes\n
+\n
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {\n
+\tset: function( tween ) {\n
+\t\tif ( tween.elem.nodeType && tween.elem.parentNode ) {\n
+\t\t\ttween.elem[ tween.prop ] = tween.now;\n
+\t\t}\n
+\t}\n
+};\n
+\n
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {\n
+\tvar cssFn = jQuery.fn[ name ];\n
+\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n
+\t\treturn speed == null || typeof speed === "boolean" ?\n
+\t\t\tcssFn.apply( this, arguments ) :\n
+\t\t\tthis.animate( genFx( name, true ), speed, easing, callback );\n
+\t};\n
+});\n
+\n
+jQuery.fn.extend({\n
+\tfadeTo: function( speed, to, easing, callback ) {\n
+\n
+\t\t// show any hidden elements after setting opacity to 0\n
+\t\treturn this.filter( isHidden ).css( "opacity", 0 ).show()\n
+\n
+\t\t\t// animate to the value specified\n
+\t\t\t.end().animate({ opacity: to }, speed, easing, callback );\n
+\t},\n
+\tanimate: function( prop, speed, easing, callback ) {\n
+\t\tvar empty = jQuery.isEmptyObject( prop ),\n
+\t\t\toptall = jQuery.speed( speed, easing, callback ),\n
+\t\t\tdoAnimation = function() {\n
+\t\t\t\t// Operate on a copy of prop so per-property easing won\'t be lost\n
+\t\t\t\tvar anim = Animation( this, jQuery.extend( {}, prop ), optall );\n
+\n
+\t\t\t\t// Empty animations, or finishing resolves immediately\n
+\t\t\t\tif ( empty || data_priv.get( this, "finish" ) ) {\n
+\t\t\t\t\tanim.stop( true );\n
+\t\t\t\t}\n
+\t\t\t};\n
+\t\t\tdoAnimation.finish = doAnimation;\n
+\n
+\t\treturn empty || optall.queue === false ?\n
+\t\t\tthis.each( doAnimation ) :\n
+\t\t\tthis.queue( optall.queue, doAnimation );\n
+\t},\n
+\tstop: function( type, clearQueue, gotoEnd ) {\n
+\t\tvar stopQueue = function( hooks ) {\n
+\t\t\tvar stop = hooks.stop;\n
+\t\t\tdelete hooks.stop;\n
+\t\t\tstop( gotoEnd );\n
+\t\t};\n
+\n
+\t\tif ( typeof type !== "string" ) {\n
+\t\t\tgotoEnd = clearQueue;\n
+\t\t\tclearQueue = type;\n
+\t\t\ttype = undefined;\n
+\t\t}\n
+\t\tif ( clearQueue && type !== false ) {\n
+\t\t\tthis.queue( type || "fx", [] );\n
+\t\t}\n
+\n
+\t\treturn this.each(function() {\n
+\t\t\tvar dequeue = true,\n
+\t\t\t\tindex = type != null && type + "queueHooks",\n
+\t\t\t\ttimers = jQuery.timers,\n
+\t\t\t\tdata = data_priv.get( this );\n
+\n
+\t\t\tif ( index ) {\n
+\t\t\t\tif ( data[ index ] && data[ index ].stop ) {\n
+\t\t\t\t\tstopQueue( data[ index ] );\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\tfor ( index in data ) {\n
+\t\t\t\t\tif ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {\n
+\t\t\t\t\t\tstopQueue( data[ index ] );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tfor ( index = timers.length; index--; ) {\n
+\t\t\t\tif ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {\n
+\t\t\t\t\ttimers[ index ].anim.stop( gotoEnd );\n
+\t\t\t\t\tdequeue = false;\n
+\t\t\t\t\ttimers.splice( index, 1 );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// start the next in the queue if the last step wasn\'t forced\n
+\t\t\t// timers currently will call their complete callbacks, which will dequeue\n
+\t\t\t// but only if they were gotoEnd\n
+\t\t\tif ( dequeue || !gotoEnd ) {\n
+\t\t\t\tjQuery.dequeue( this, type );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\tfinish: function( type ) {\n
+\t\tif ( type !== false ) {\n
+\t\t\ttype = type || "fx";\n
+\t\t}\n
+\t\treturn this.each(function() {\n
+\t\t\tvar index,\n
+\t\t\t\tdata = data_priv.get( this ),\n
+\t\t\t\tqueue = data[ type + "queue" ],\n
+\t\t\t\thooks = data[ type + "queueHooks" ],\n
+\t\t\t\ttimers = jQuery.timers,\n
+\t\t\t\tlength = queue ? queue.length : 0;\n
+\n
+\t\t\t// enable finishing flag on private data\n
+\t\t\tdata.finish = true;\n
+\n
+\t\t\t// empty the queue first\n
+\t\t\tjQuery.queue( this, type, [] );\n
+\n
+\t\t\tif ( hooks && hooks.stop ) {\n
+\t\t\t\thooks.stop.call( this, true );\n
+\t\t\t}\n
+\n
+\t\t\t// look for any active animations, and finish them\n
+\t\t\tfor ( index = timers.length; index--; ) {\n
+\t\t\t\tif ( timers[ index ].elem === this && timers[ index ].queue === type ) {\n
+\t\t\t\t\ttimers[ index ].anim.stop( true );\n
+\t\t\t\t\ttimers.splice( index, 1 );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// look for any animations in the old queue and finish them\n
+\t\t\tfor ( index = 0; index < length; index++ ) {\n
+\t\t\t\tif ( queue[ index ] && queue[ index ].finish ) {\n
+\t\t\t\t\tqueue[ index ].finish.call( this );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// turn off finishing flag\n
+\t\t\tdelete data.finish;\n
+\t\t});\n
+\t}\n
+});\n
+\n
+// Generate parameters to create a standard animation\n
+function genFx( type, includeWidth ) {\n
+\tvar which,\n
+\t\tattrs = { height: type },\n
+\t\ti = 0;\n
+\n
+\t// if we include width, step value is 1 to do all cssExpand values,\n
+\t// if we don\'t include width, step value is 2 to skip over Left and Right\n
+\tincludeWidth = includeWidth? 1 : 0;\n
+\tfor( ; i < 4 ; i += 2 - includeWidth ) {\n
+\t\twhich = cssExpand[ i ];\n
+\t\tattrs[ "margin" + which ] = attrs[ "padding" + which ] = type;\n
+\t}\n
+\n
+\tif ( includeWidth ) {\n
+\t\tattrs.opacity = attrs.width = type;\n
+\t}\n
+\n
+\treturn attrs;\n
+}\n
+\n
+// Generate shortcuts for custom animations\n
+jQuery.each({\n
+\tslideDown: genFx("show"),\n
+\tslideUp: genFx("hide"),\n
+\tslideToggle: genFx("toggle"),\n
+\tfadeIn: { opacity: "show" },\n
+\tfadeOut: { opacity: "hide" },\n
+\tfadeToggle: { opacity: "toggle" }\n
+}, function( name, props ) {\n
+\tjQuery.fn[ name ] = function( speed, easing, callback ) {\n
+\t\treturn this.animate( props, speed, easing, callback );\n
+\t};\n
+});\n
+\n
+jQuery.speed = function( speed, easing, fn ) {\n
+\tvar opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {\n
+\t\tcomplete: fn || !fn && easing ||\n
+\t\t\tjQuery.isFunction( speed ) && speed,\n
+\t\tduration: speed,\n
+\t\teasing: fn && easing || easing && !jQuery.isFunction( easing ) && easing\n
+\t};\n
+\n
+\topt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :\n
+\t\topt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;\n
+\n
+\t// normalize opt.queue - true/undefined/null -> "fx"\n
+\tif ( opt.queue == null || opt.queue === true ) {\n
+\t\topt.queue = "fx";\n
+\t}\n
+\n
+\t// Queueing\n
+\topt.old = opt.complete;\n
+\n
+\topt.complete = function() {\n
+\t\tif ( jQuery.isFunction( opt.old ) ) {\n
+\t\t\topt.old.call( this );\n
+\t\t}\n
+\n
+\t\tif ( opt.queue ) {\n
+\t\t\tjQuery.dequeue( this, opt.queue );\n
+\t\t}\n
+\t};\n
+\n
+\treturn opt;\n
+};\n
+\n
+jQuery.easing = {\n
+\tlinear: function( p ) {\n
+\t\treturn p;\n
+\t},\n
+\tswing: function( p ) {\n
+\t\treturn 0.5 - Math.cos( p*Math.PI ) / 2;\n
+\t}\n
+};\n
+\n
+jQuery.timers = [];\n
+jQuery.fx = Tween.prototype.init;\n
+jQuery.fx.tick = function() {\n
+\tvar timer,\n
+\t\ttimers = jQuery.timers,\n
+\t\ti = 0;\n
+\n
+\tfxNow = jQuery.now();\n
+\n
+\tfor ( ; i < timers.length; i++ ) {\n
+\t\ttimer = timers[ i ];\n
+\t\t// Checks the timer has not already been removed\n
+\t\tif ( !timer() && timers[ i ] === timer ) {\n
+\t\t\ttimers.splice( i--, 1 );\n
+\t\t}\n
+\t}\n
+\n
+\tif ( !timers.length ) {\n
+\t\tjQuery.fx.stop();\n
+\t}\n
+\tfxNow = undefined;\n
+};\n
+\n
+jQuery.fx.timer = function( timer ) {\n
+\tif ( timer() && jQuery.timers.push( timer ) ) {\n
+\t\tjQuery.fx.start();\n
+\t}\n
+};\n
+\n
+jQuery.fx.interval = 13;\n
+\n
+jQuery.fx.start = function() {\n
+\tif ( !timerId ) {\n
+\t\ttimerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );\n
+\t}\n
+};\n
+\n
+jQuery.fx.stop = function() {\n
+\tclearInterval( timerId );\n
+\ttimerId = null;\n
+};\n
+\n
+jQuery.fx.speeds = {\n
+\tslow: 600,\n
+\tfast: 200,\n
+\t// Default speed\n
+\t_default: 400\n
+};\n
+\n
+// Back Compat <1.8 extension point\n
+jQuery.fx.step = {};\n
+\n
+if ( jQuery.expr && jQuery.expr.filters ) {\n
+\tjQuery.expr.filters.animated = function( elem ) {\n
+\t\treturn jQuery.grep(jQuery.timers, function( fn ) {\n
+\t\t\treturn elem === fn.elem;\n
+\t\t}).length;\n
+\t};\n
+}\n
+jQuery.fn.offset = function( options ) {\n
+\tif ( arguments.length ) {\n
+\t\treturn options === undefined ?\n
+\t\t\tthis :\n
+\t\t\tthis.each(function( i ) {\n
+\t\t\t\tjQuery.offset.setOffset( this, options, i );\n
+\t\t\t});\n
+\t}\n
+\n
+\tvar docElem, win,\n
+\t\telem = this[ 0 ],\n
+\t\tbox = { top: 0, left: 0 },\n
+\t\tdoc = elem && elem.ownerDocument;\n
+\n
+\tif ( !doc ) {\n
+\t\treturn;\n
+\t}\n
+\n
+\tdocElem = doc.documentElement;\n
+\n
+\t// Make sure it\'s not a disconnected DOM node\n
+\tif ( !jQuery.contains( docElem, elem ) ) {\n
+\t\treturn box;\n
+\t}\n
+\n
+\t// If we don\'t have gBCR, just use 0,0 rather than error\n
+\t// BlackBerry 5, iOS 3 (original iPhone)\n
+\tif ( typeof elem.getBoundingClientRect !== core_strundefined ) {\n
+\t\tbox = elem.getBoundingClientRect();\n
+\t}\n
+\twin = getWindow( doc );\n
+\treturn {\n
+\t\ttop: box.top + win.pageYOffset - docElem.clientTop,\n
+\t\tleft: box.left + win.pageXOffset - docElem.clientLeft\n
+\t};\n
+};\n
+\n
+jQuery.offset = {\n
+\n
+\tsetOffset: function( elem, options, i ) {\n
+\t\tvar curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,\n
+\t\t\tposition = jQuery.css( elem, "position" ),\n
+\t\t\tcurElem = jQuery( elem ),\n
+\t\t\tprops = {};\n
+\n
+\t\t// Set position first, in-case top/left are set even on static elem\n
+\t\tif ( position === "static" ) {\n
+\t\t\telem.style.position = "relative";\n
+\t\t}\n
+\n
+\t\tcurOffset = curElem.offset();\n
+\t\tcurCSSTop = jQuery.css( elem, "top" );\n
+\t\tcurCSSLeft = jQuery.css( elem, "left" );\n
+\t\tcalculatePosition = ( position === "absolute" || position === "fixed" ) && ( curCSSTop + curCSSLeft ).indexOf("auto") > -1;\n
+\n
+\t\t// Need to be able to calculate position if either top or left is auto and position is either absolute or fixed\n
+\t\tif ( calculatePosition ) {\n
+\t\t\tcurPosition = curElem.position();\n
+\t\t\tcurTop = curPosition.top;\n
+\t\t\tcurLeft = curPosition.left;\n
+\n
+\t\t} else {\n
+\t\t\tcurTop = parseFloat( curCSSTop ) || 0;\n
+\t\t\tcurLeft = parseFloat( curCSSLeft ) || 0;\n
+\t\t}\n
+\n
+\t\tif ( jQuery.isFunction( options ) ) {\n
+\t\t\toptions = options.call( elem, i, curOffset );\n
+\t\t}\n
+\n
+\t\tif ( options.top != null ) {\n
+\t\t\tprops.top = ( options.top - curOffset.top ) + curTop;\n
+\t\t}\n
+\t\tif ( options.left != null ) {\n
+\t\t\tprops.left = ( options.left - curOffset.left ) + curLeft;\n
+\t\t}\n
+\n
+\t\tif ( "using" in options ) {\n
+\t\t\toptions.using.call( elem, props );\n
+\n
+\t\t} else {\n
+\t\t\tcurElem.css( props );\n
+\t\t}\n
+\t}\n
+};\n
+\n
+\n
+jQuery.fn.extend({\n
+\n
+\tposition: function() {\n
+\t\tif ( !this[ 0 ] ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tvar offsetParent, offset,\n
+\t\t\telem = this[ 0 ],\n
+\t\t\tparentOffset = { top: 0, left: 0 };\n
+\n
+\t\t// Fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is it\'s only offset parent\n
+\t\tif ( jQuery.css( elem, "position" ) === "fixed" ) {\n
+\t\t\t// We assume that getBoundingClientRect is available when computed position is fixed\n
+\t\t\toffset = elem.getBoundingClientRect();\n
+\n
+\t\t} else {\n
+\t\t\t// Get *real* offsetParent\n
+\t\t\toffsetParent = this.offsetParent();\n
+\n
+\t\t\t// Get correct offsets\n
+\t\t\toffset = this.offset();\n
+\t\t\tif ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {\n
+\t\t\t\tparentOffset = offsetParent.offset();\n
+\t\t\t}\n
+\n
+\t\t\t// Add offsetParent borders\n
+\t\t\tparentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );\n
+\t\t\tparentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );\n
+\t\t}\n
+\n
+\t\t// Subtract parent offsets and element margins\n
+\t\treturn {\n
+\t\t\ttop: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),\n
+\t\t\tleft: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )\n
+\t\t};\n
+\t},\n
+\n
+\toffsetParent: function() {\n
+\t\treturn this.map(function() {\n
+\t\t\tvar offsetParent = this.offsetParent || docElem;\n
+\n
+\t\t\twhile ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position") === "static" ) ) {\n
+\t\t\t\toffsetParent = offsetParent.offsetParent;\n
+\t\t\t}\n
+\n
+\t\t\treturn offsetParent || docElem;\n
+\t\t});\n
+\t}\n
+});\n
+\n
+\n
+// Create scrollLeft and scrollTop methods\n
+jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) {\n
+\tvar top = "pageYOffset" === prop;\n
+\n
+\tjQuery.fn[ method ] = function( val ) {\n
+\t\treturn jQuery.access( this, function( elem, method, val ) {\n
+\t\t\tvar win = getWindow( elem );\n
+\n
+\t\t\tif ( val === undefined ) {\n
+\t\t\t\treturn win ? win[ prop ] : elem[ method ];\n
+\t\t\t}\n
+\n
+\t\t\tif ( win ) {\n
+\t\t\t\twin.scrollTo(\n
+\t\t\t\t\t!top ? val : window.pageXOffset,\n
+\t\t\t\t\ttop ? val : window.pageYOffset\n
+\t\t\t\t);\n
+\n
+\t\t\t} else {\n
+\t\t\t\telem[ method ] = val;\n
+\t\t\t}\n
+\t\t}, method, val, arguments.length, null );\n
+\t};\n
+});\n
+\n
+function getWindow( elem ) {\n
+\treturn jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;\n
+}\n
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods\n
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {\n
+\tjQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {\n
+\t\t// margin is only for outerHeight, outerWidth\n
+\t\tjQuery.fn[ funcName ] = function( margin, value ) {\n
+\t\t\tvar chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),\n
+\t\t\t\textra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );\n
+\n
+\t\t\treturn jQuery.access( this, function( elem, type, value ) {\n
+\t\t\t\tvar doc;\n
+\n
+\t\t\t\tif ( jQuery.isWindow( elem ) ) {\n
+\t\t\t\t\t// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there\n
+\t\t\t\t\t// isn\'t a whole lot we can do. See pull request at this URL for discussion:\n
+\t\t\t\t\t// https://github.com/jquery/jquery/pull/764\n
+\t\t\t\t\treturn elem.document.documentElement[ "client" + name ];\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Get document width or height\n
+\t\t\t\tif ( elem.nodeType === 9 ) {\n
+\t\t\t\t\tdoc = elem.documentElement;\n
+\n
+\t\t\t\t\t// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],\n
+\t\t\t\t\t// whichever is greatest\n
+\t\t\t\t\treturn Math.max(\n
+\t\t\t\t\t\telem.body[ "scroll" + name ], doc[ "scroll" + name ],\n
+\t\t\t\t\t\telem.body[ "offset" + name ], doc[ "offset" + name ],\n
+\t\t\t\t\t\tdoc[ "client" + name ]\n
+\t\t\t\t\t);\n
+\t\t\t\t}\n
+\n
+\t\t\t\treturn value === undefined ?\n
+\t\t\t\t\t// Get width or height on the element, requesting but not forcing parseFloat\n
+\t\t\t\t\tjQuery.css( elem, type, extra ) :\n
+\n
+\t\t\t\t\t// Set width or height on the element\n
+\t\t\t\t\tjQuery.style( elem, type, value, extra );\n
+\t\t\t}, type, chainable ? margin : undefined, chainable, null );\n
+\t\t};\n
+\t});\n
+});\n
+// Limit scope pollution from any deprecated API\n
+// (function() {\n
+\n
+// The number of elements contained in the matched element set\n
+jQuery.fn.size = function() {\n
+\treturn this.length;\n
+};\n
+\n
+jQuery.fn.andSelf = jQuery.fn.addBack;\n
+\n
+// })();\n
+if ( typeof module === "object" && module && typeof module.exports === "object" ) {\n
+\t// Expose jQuery as module.exports in loaders that implement the Node\n
+\t// module pattern (including browserify). Do not create the global, since\n
+\t// the user will be storing it themselves locally, and globals are frowned\n
+\t// upon in the Node module world.\n
+\tmodule.exports = jQuery;\n
+} else {\n
+\t// Register as a named AMD module, since jQuery can be concatenated with other\n
+\t// files that may use define, but not via a proper concatenation script that\n
+\t// understands anonymous AMD modules. A named AMD is safest and most robust\n
+\t// way to register. Lowercase jquery is used because AMD module names are\n
+\t// derived from file names, and jQuery is normally delivered in a lowercase\n
+\t// file name. Do this after creating the global so that if an AMD module wants\n
+\t// to call noConflict to hide this version of jQuery, it will work.\n
+\tif ( typeof define === "function" && define.amd ) {\n
+\t\tdefine( "jquery", [], function () { return jQuery; } );\n
+\t}\n
+}\n
+\n
+// If there is a window object, that at least has a document property,\n
+// define jQuery and $ identifiers\n
+if ( typeof window === "object" && typeof window.document === "object" ) {\n
+\twindow.jQuery = window.$ = jQuery;\n
+}\n
+\n
+})( window );\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.jsplumb.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.jsplumb.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..efcd5f2a42659afad737eaf9de0139f3170bad25
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.jsplumb.js.xml
@@ -0,0 +1,10681 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681770.91</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jquery.jsplumb.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>444752</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/**\n
+* jsBezier-0.6\n
+*\n
+* Copyright (c) 2010 - 2013 Simon Porritt (simon.porritt@gmail.com)\n
+*\n
+* licensed under the MIT license.\n
+* \n
+* a set of Bezier curve functions that deal with Beziers, used by jsPlumb, and perhaps useful for other people.  These functions work with Bezier\n
+* curves of arbitrary degree.\n
+*\n
+* - functions are all in the \'jsBezier\' namespace.  \n
+* \n
+* - all input points should be in the format {x:.., y:..}. all output points are in this format too.\n
+* \n
+* - all input curves should be in the format [ {x:.., y:..}, {x:.., y:..}, {x:.., y:..}, {x:.., y:..} ]\n
+* \n
+* - \'location\' as used as an input here refers to a decimal in the range 0-1 inclusive, which indicates a point some proportion along the length\n
+* of the curve.  location as output has the same format and meaning.\n
+* \n
+* \n
+* Function List:\n
+* --------------\n
+* \n
+* distanceFromCurve(point, curve)\n
+* \n
+* \tCalculates the distance that the given point lies from the given Bezier.  Note that it is computed relative to the center of the Bezier,\n
+* so if you have stroked the curve with a wide pen you may wish to take that into account!  The distance returned is relative to the values \n
+* of the curve and the point - it will most likely be pixels.\n
+* \n
+* gradientAtPoint(curve, location)\n
+* \n
+* \tCalculates the gradient to the curve at the given location, as a decimal between 0 and 1 inclusive.\n
+*\n
+* gradientAtPointAlongCurveFrom (curve, location)\n
+*\n
+*\tCalculates the gradient at the point on the given curve that is \'distance\' units from location. \n
+* \n
+* nearestPointOnCurve(point, curve) \n
+* \n
+*\tCalculates the nearest point to the given point on the given curve.  The return value of this is a JS object literal, containing both the\n
+*point\'s coordinates and also the \'location\' of the point (see above), for example:  { point:{x:551,y:150}, location:0.263365 }.\n
+* \n
+* pointOnCurve(curve, location)\n
+* \n
+* \tCalculates the coordinates of the point on the given Bezier curve at the given location.  \n
+* \t\t\n
+* pointAlongCurveFrom(curve, location, distance)\n
+* \n
+* \tCalculates the coordinates of the point on the given curve that is \'distance\' units from location.  \'distance\' should be in the same coordinate\n
+* space as that used to construct the Bezier curve.  For an HTML Canvas usage, for example, distance would be a measure of pixels.\n
+*\n
+* locationAlongCurveFrom(curve, location, distance)\n
+* \n
+* \tCalculates the location on the given curve that is \'distance\' units from location.  \'distance\' should be in the same coordinate\n
+* space as that used to construct the Bezier curve.  For an HTML Canvas usage, for example, distance would be a measure of pixels.\n
+* \n
+* perpendicularToCurveAt(curve, location, length, distance)\n
+* \n
+* \tCalculates the perpendicular to the given curve at the given location.  length is the length of the line you wish for (it will be centered\n
+* on the point at \'location\'). distance is optional, and allows you to specify a point along the path from the given location as the center of\n
+* the perpendicular returned.  The return value of this is an array of two points: [ {x:...,y:...}, {x:...,y:...} ].  \n
+*  \n
+* \n
+*/\n
+\n
+(function() {\n
+\t\n
+\tif(typeof Math.sgn == "undefined") {\n
+\t\tMath.sgn = function(x) { return x == 0 ? 0 : x > 0 ? 1 :-1; };\n
+\t}\n
+\t\n
+\tvar Vectors = {\n
+\t\t\tsubtract \t: \tfunction(v1, v2) { return {x:v1.x - v2.x, y:v1.y - v2.y }; },\n
+\t\t\tdotProduct\t: \tfunction(v1, v2) { return (v1.x * v2.x)  + (v1.y * v2.y); },\n
+\t\t\tsquare\t\t:\tfunction(v) { return Math.sqrt((v.x * v.x) + (v.y * v.y)); },\n
+\t\t\tscale\t\t:\tfunction(v, s) { return {x:v.x * s, y:v.y * s }; }\n
+\t\t},\n
+\t\t\n
+\t\tmaxRecursion = 64, \n
+\t\tflatnessTolerance = Math.pow(2.0,-maxRecursion-1);\n
+\n
+\t/**\n
+\t * Calculates the distance that the point lies from the curve.\n
+\t * \n
+\t * @param point a point in the form {x:567, y:3342}\n
+\t * @param curve a Bezier curve in the form [{x:..., y:...}, {x:..., y:...}, {x:..., y:...}, {x:..., y:...}].  note that this is currently\n
+\t * hardcoded to assume cubiz beziers, but would be better off supporting any degree. \n
+\t * @return a JS object literal containing location and distance, for example: {location:0.35, distance:10}.  Location is analogous to the location\n
+\t * argument you pass to the pointOnPath function: it is a ratio of distance travelled along the curve.  Distance is the distance in pixels from\n
+\t * the point to the curve. \n
+\t */\n
+\tvar _distanceFromCurve = function(point, curve) {\n
+\t\tvar candidates = [],     \n
+\t    \tw = _convertToBezier(point, curve),\n
+\t    \tdegree = curve.length - 1, higherDegree = (2 * degree) - 1,\n
+\t    \tnumSolutions = _findRoots(w, higherDegree, candidates, 0),\n
+\t\t\tv = Vectors.subtract(point, curve[0]), dist = Vectors.square(v), t = 0.0;\n
+\n
+\t    for (var i = 0; i < numSolutions; i++) {\n
+\t\t\tv = Vectors.subtract(point, _bezier(curve, degree, candidates[i], null, null));\n
+\t    \tvar newDist = Vectors.square(v);\n
+\t    \tif (newDist < dist) {\n
+\t            dist = newDist;\n
+\t        \tt = candidates[i];\n
+\t\t    }\n
+\t    }\n
+\t    v = Vectors.subtract(point, curve[degree]);\n
+\t\tnewDist = Vectors.square(v);\n
+\t    if (newDist < dist) {\n
+\t        dist = newDist;\n
+\t    \tt = 1.0;\n
+\t    }\n
+\t\treturn {location:t, distance:dist};\n
+\t};\n
+\t/**\n
+\t * finds the nearest point on the curve to the given point.\n
+\t */\n
+\tvar _nearestPointOnCurve = function(point, curve) {    \n
+\t\tvar td = _distanceFromCurve(point, curve);\n
+\t    return {point:_bezier(curve, curve.length - 1, td.location, null, null), location:td.location};\n
+\t};\n
+\tvar _convertToBezier = function(point, curve) {\n
+\t\tvar degree = curve.length - 1, higherDegree = (2 * degree) - 1,\n
+\t    \tc = [], d = [], cdTable = [], w = [],\n
+\t    \tz = [ [1.0, 0.6, 0.3, 0.1], [0.4, 0.6, 0.6, 0.4], [0.1, 0.3, 0.6, 1.0] ];\t\n
+\t    \t\n
+\t    for (var i = 0; i <= degree; i++) c[i] = Vectors.subtract(curve[i], point);\n
+\t    for (var i = 0; i <= degree - 1; i++) { \n
+\t\t\td[i] = Vectors.subtract(curve[i+1], curve[i]);\n
+\t\t\td[i] = Vectors.scale(d[i], 3.0);\n
+\t    }\n
+\t    for (var row = 0; row <= degree - 1; row++) {\n
+\t\t\tfor (var column = 0; column <= degree; column++) {\n
+\t\t\t\tif (!cdTable[row]) cdTable[row] = [];\n
+\t\t    \tcdTable[row][column] = Vectors.dotProduct(d[row], c[column]);\n
+\t\t\t}\n
+\t    }\n
+\t    for (i = 0; i <= higherDegree; i++) {\n
+\t\t\tif (!w[i]) w[i] = [];\n
+\t\t\tw[i].y = 0.0;\n
+\t\t\tw[i].x = parseFloat(i) / higherDegree;\n
+\t    }\n
+\t    var n = degree, m = degree-1;\n
+\t    for (var k = 0; k <= n + m; k++) {\n
+\t\t\tvar lb = Math.max(0, k - m),\n
+\t\t\t\tub = Math.min(k, n);\n
+\t\t\tfor (i = lb; i <= ub; i++) {\n
+\t\t    \tj = k - i;\n
+\t\t    \tw[i+j].y += cdTable[j][i] * z[j][i];\n
+\t\t\t}\n
+\t    }\n
+\t    return w;\n
+\t};\n
+\t/**\n
+\t * counts how many roots there are.\n
+\t */\n
+\tvar _findRoots = function(w, degree, t, depth) {  \n
+\t    var left = [], right = [],\t\n
+\t    \tleft_count, right_count,\t\n
+\t    \tleft_t = [], right_t = [];\n
+\t    \t\n
+\t    switch (_getCrossingCount(w, degree)) {\n
+\t       \tcase 0 : {\t\n
+\t       \t\treturn 0;\t\n
+\t       \t}\n
+\t       \tcase 1 : {\t\n
+\t       \t\tif (depth >= maxRecursion) {\n
+\t       \t\t\tt[0] = (w[0].x + w[degree].x) / 2.0;\n
+\t       \t\t\treturn 1;\n
+\t       \t\t}\n
+\t       \t\tif (_isFlatEnough(w, degree)) {\n
+\t       \t\t\tt[0] = _computeXIntercept(w, degree);\n
+\t       \t\t\treturn 1;\n
+\t       \t\t}\n
+\t       \t\tbreak;\n
+\t       \t}\n
+\t    }\n
+\t    _bezier(w, degree, 0.5, left, right);\n
+\t    left_count  = _findRoots(left,  degree, left_t, depth+1);\n
+\t    right_count = _findRoots(right, degree, right_t, depth+1);\n
+\t    for (var i = 0; i < left_count; i++) t[i] = left_t[i];\n
+\t    for (var i = 0; i < right_count; i++) t[i+left_count] = right_t[i];    \n
+\t\treturn (left_count+right_count);\n
+\t};\n
+\tvar _getCrossingCount = function(curve, degree) {\n
+\t    var n_crossings = 0, sign, old_sign;\t\t    \t\n
+\t    sign = old_sign = Math.sgn(curve[0].y);\n
+\t    for (var i = 1; i <= degree; i++) {\n
+\t\t\tsign = Math.sgn(curve[i].y);\n
+\t\t\tif (sign != old_sign) n_crossings++;\n
+\t\t\told_sign = sign;\n
+\t    }\n
+\t    return n_crossings;\n
+\t};\n
+\tvar _isFlatEnough = function(curve, degree) {\n
+\t    var  error,\n
+\t    \tintercept_1, intercept_2, left_intercept, right_intercept,\n
+\t    \ta, b, c, det, dInv, a1, b1, c1, a2, b2, c2;\n
+\t    a = curve[0].y - curve[degree].y;\n
+\t    b = curve[degree].x - curve[0].x;\n
+\t    c = curve[0].x * curve[degree].y - curve[degree].x * curve[0].y;\n
+\t\n
+\t    var max_distance_above = max_distance_below = 0.0;\n
+\t    \n
+\t    for (var i = 1; i < degree; i++) {\n
+\t        var value = a * curve[i].x + b * curve[i].y + c;       \n
+\t        if (value > max_distance_above)\n
+\t            max_distance_above = value;\n
+\t        else if (value < max_distance_below)\n
+\t        \tmax_distance_below = value;\n
+\t    }\n
+\t    \n
+\t    a1 = 0.0; b1 = 1.0; c1 = 0.0; a2 = a; b2 = b;\n
+\t    c2 = c - max_distance_above;\n
+\t    det = a1 * b2 - a2 * b1;\n
+\t    dInv = 1.0/det;\n
+\t    intercept_1 = (b1 * c2 - b2 * c1) * dInv;\n
+\t    a2 = a; b2 = b; c2 = c - max_distance_below;\n
+\t    det = a1 * b2 - a2 * b1;\n
+\t    dInv = 1.0/det;\n
+\t    intercept_2 = (b1 * c2 - b2 * c1) * dInv;\n
+\t    left_intercept = Math.min(intercept_1, intercept_2);\n
+\t    right_intercept = Math.max(intercept_1, intercept_2);\n
+\t    error = right_intercept - left_intercept;\n
+\t    return (error < flatnessTolerance)? 1 : 0;\n
+\t};\n
+\tvar _computeXIntercept = function(curve, degree) {\n
+\t    var XLK = 1.0, YLK = 0.0,\n
+\t    \tXNM = curve[degree].x - curve[0].x, YNM = curve[degree].y - curve[0].y,\n
+\t    \tXMK = curve[0].x - 0.0, YMK = curve[0].y - 0.0,\n
+\t    \tdet = XNM*YLK - YNM*XLK, detInv = 1.0/det,\n
+\t    \tS = (XNM*YMK - YNM*XMK) * detInv; \n
+\t    return 0.0 + XLK * S;\n
+\t};\n
+\tvar _bezier = function(curve, degree, t, left, right) {\n
+\t    var temp = [[]];\n
+\t    for (var j =0; j <= degree; j++) temp[0][j] = curve[j];\n
+\t    for (var i = 1; i <= degree; i++) {\t\n
+\t\t\tfor (var j =0 ; j <= degree - i; j++) {\n
+\t\t\t\tif (!temp[i]) temp[i] = [];\n
+\t\t\t\tif (!temp[i][j]) temp[i][j] = {};\n
+\t\t    \ttemp[i][j].x = (1.0 - t) * temp[i-1][j].x + t * temp[i-1][j+1].x;\n
+\t\t    \ttemp[i][j].y = (1.0 - t) * temp[i-1][j].y + t * temp[i-1][j+1].y;\n
+\t\t\t}\n
+\t    }    \n
+\t    if (left != null) \n
+\t    \tfor (j = 0; j <= degree; j++) left[j]  = temp[j][0];\n
+\t    if (right != null)\n
+\t\t\tfor (j = 0; j <= degree; j++) right[j] = temp[degree-j][j];\n
+\t    \n
+\t    return (temp[degree][0]);\n
+\t};\n
+\t\n
+\tvar _curveFunctionCache = {};\n
+\tvar _getCurveFunctions = function(order) {\n
+\t\tvar fns = _curveFunctionCache[order];\n
+\t\tif (!fns) {\n
+\t\t\tfns = [];\t\t\t\n
+\t\t\tvar f_term = function() { return function(t) { return Math.pow(t, order); }; },\n
+\t\t\t\tl_term = function() { return function(t) { return Math.pow((1-t), order); }; },\n
+\t\t\t\tc_term = function(c) { return function(t) { return c; }; },\n
+\t\t\t\tt_term = function() { return function(t) { return t; }; },\n
+\t\t\t\tone_minus_t_term = function() { return function(t) { return 1-t; }; },\n
+\t\t\t\t_termFunc = function(terms) {\n
+\t\t\t\t\treturn function(t) {\n
+\t\t\t\t\t\tvar p = 1;\n
+\t\t\t\t\t\tfor (var i = 0; i < terms.length; i++) p = p * terms[i](t);\n
+\t\t\t\t\t\treturn p;\n
+\t\t\t\t\t};\n
+\t\t\t\t};\n
+\t\t\t\n
+\t\t\tfns.push(new f_term());  // first is t to the power of the curve order\t\t\n
+\t\t\tfor (var i = 1; i < order; i++) {\n
+\t\t\t\tvar terms = [new c_term(order)];\n
+\t\t\t\tfor (var j = 0 ; j < (order - i); j++) terms.push(new t_term());\n
+\t\t\t\tfor (var j = 0 ; j < i; j++) terms.push(new one_minus_t_term());\n
+\t\t\t\tfns.push(new _termFunc(terms));\n
+\t\t\t}\n
+\t\t\tfns.push(new l_term());  // last is (1-t) to the power of the curve order\n
+\t\t\n
+\t\t\t_curveFunctionCache[order] = fns;\n
+\t\t}\n
+\t\t\t\n
+\t\treturn fns;\n
+\t};\n
+\t\n
+\t\n
+\t/**\n
+\t * calculates a point on the curve, for a Bezier of arbitrary order.\n
+\t * @param curve an array of control points, eg [{x:10,y:20}, {x:50,y:50}, {x:100,y:100}, {x:120,y:100}].  For a cubic bezier this should have four points.\n
+\t * @param location a decimal indicating the distance along the curve the point should be located at.  this is the distance along the curve as it travels, taking the way it bends into account.  should be a number from 0 to 1, inclusive.\n
+\t */\n
+\tvar _pointOnPath = function(curve, location) {\t\t\n
+\t\tvar cc = _getCurveFunctions(curve.length - 1),\n
+\t\t\t_x = 0, _y = 0;\n
+\t\tfor (var i = 0; i < curve.length ; i++) {\n
+\t\t\t_x = _x + (curve[i].x * cc[i](location));\n
+\t\t\t_y = _y + (curve[i].y * cc[i](location));\n
+\t\t}\n
+\t\t\n
+\t\treturn {x:_x, y:_y};\n
+\t};\n
+\t\n
+\tvar _dist = function(p1,p2) {\n
+\t\treturn Math.sqrt(Math.pow(p1.x - p2.x, 2) + Math.pow(p1.y - p2.y, 2));\n
+\t};\n
+\n
+\tvar _isPoint = function(curve) {\n
+\t\treturn curve[0].x == curve[1].x && curve[0].y == curve[1].y;\n
+\t};\n
+\t\n
+\t/**\n
+\t * finds the point that is \'distance\' along the path from \'location\'.  this method returns both the x,y location of the point and also\n
+\t * its \'location\' (proportion of travel along the path); the method below - _pointAlongPathFrom - calls this method and just returns the\n
+\t * point.\n
+\t */\n
+\tvar _pointAlongPath = function(curve, location, distance) {\n
+\n
+\t\tif (_isPoint(curve)) {\n
+\t\t\treturn {\n
+\t\t\t\tpoint:curve[0],\n
+\t\t\t\tlocation:location\n
+\t\t\t};\n
+\t\t}\n
+\n
+\t\tvar prev = _pointOnPath(curve, location), \n
+\t\t\ttally = 0, \n
+\t\t\tcurLoc = location, \n
+\t\t\tdirection = distance > 0 ? 1 : -1, \n
+\t\t\tcur = null;\n
+\t\t\t\n
+\t\twhile (tally < Math.abs(distance)) {\n
+\t\t\tcurLoc += (0.005 * direction);\n
+\t\t\tcur = _pointOnPath(curve, curLoc);\n
+\t\t\ttally += _dist(cur, prev);\t\n
+\t\t\tprev = cur;\n
+\t\t}\n
+\t\treturn {point:cur, location:curLoc};        \t\n
+\t};\n
+\t\n
+\tvar _length = function(curve) {\n
+\t\tif (_isPoint(curve)) return 0;\n
+\n
+\t\tvar prev = _pointOnPath(curve, 0),\n
+\t\t\ttally = 0,\n
+\t\t\tcurLoc = 0,\n
+\t\t\tdirection = 1,\n
+\t\t\tcur = null;\n
+\t\t\t\n
+\t\twhile (curLoc < 1) {\n
+\t\t\tcurLoc += (0.005 * direction);\n
+\t\t\tcur = _pointOnPath(curve, curLoc);\n
+\t\t\ttally += _dist(cur, prev);\t\n
+\t\t\tprev = cur;\n
+\t\t}\n
+\t\treturn tally;\n
+\t};\n
+\t\n
+\t/**\n
+\t * finds the point that is \'distance\' along the path from \'location\'.  \n
+\t */\n
+\tvar _pointAlongPathFrom = function(curve, location, distance) {\n
+\t\treturn _pointAlongPath(curve, location, distance).point;\n
+\t};\n
+\n
+\t/**\n
+\t * finds the location that is \'distance\' along the path from \'location\'.  \n
+\t */\n
+\tvar _locationAlongPathFrom = function(curve, location, distance) {\n
+\t\treturn _pointAlongPath(curve, location, distance).location;\n
+\t};\n
+\t\n
+\t/**\n
+\t * returns the gradient of the curve at the given location, which is a decimal between 0 and 1 inclusive.\n
+\t * \n
+\t * thanks // http://bimixual.org/AnimationLibrary/beziertangents.html\n
+\t */\n
+\tvar _gradientAtPoint = function(curve, location) {\n
+\t\tvar p1 = _pointOnPath(curve, location),\t\n
+\t\t\tp2 = _pointOnPath(curve.slice(0, curve.length - 1), location),\n
+\t\t\tdy = p2.y - p1.y, dx = p2.x - p1.x;\n
+\t\treturn dy == 0 ? Infinity : Math.atan(dy / dx);\t\t\n
+\t};\n
+\t\n
+\t/**\n
+\treturns the gradient of the curve at the point which is \'distance\' from the given location.\n
+\tif this point is greater than location 1, the gradient at location 1 is returned.\n
+\tif this point is less than location 0, the gradient at location 0 is returned.\n
+\t*/\n
+\tvar _gradientAtPointAlongPathFrom = function(curve, location, distance) {\n
+\t\tvar p = _pointAlongPath(curve, location, distance);\n
+\t\tif (p.location > 1) p.location = 1;\n
+\t\tif (p.location < 0) p.location = 0;\t\t\n
+\t\treturn _gradientAtPoint(curve, p.location);\t\t\n
+\t};\n
+\n
+\t/**\n
+\t * calculates a line that is \'length\' pixels long, perpendicular to, and centered on, the path at \'distance\' pixels from the given location.\n
+\t * if distance is not supplied, the perpendicular for the given location is computed (ie. we set distance to zero).\n
+\t */\n
+\tvar _perpendicularToPathAt = function(curve, location, length, distance) {\n
+\t\tdistance = distance == null ? 0 : distance;\n
+\t\tvar p = _pointAlongPath(curve, location, distance),\n
+\t\t\tm = _gradientAtPoint(curve, p.location),\n
+\t\t\t_theta2 = Math.atan(-1 / m),\n
+\t\t\ty =  length / 2 * Math.sin(_theta2),\n
+\t\t\tx =  length / 2 * Math.cos(_theta2);\n
+\t\treturn [{x:p.point.x + x, y:p.point.y + y}, {x:p.point.x - x, y:p.point.y - y}];\n
+\t};\n
+\t\n
+\tvar jsBezier = window.jsBezier = {\n
+\t\tdistanceFromCurve : _distanceFromCurve,\n
+\t\tgradientAtPoint : _gradientAtPoint,\n
+\t\tgradientAtPointAlongCurveFrom : _gradientAtPointAlongPathFrom,\n
+\t\tnearestPointOnCurve : _nearestPointOnCurve,\n
+\t\tpointOnCurve : _pointOnPath,\t\t\n
+\t\tpointAlongCurveFrom : _pointAlongPathFrom,\n
+\t\tperpendicularToCurveAt : _perpendicularToPathAt,\n
+\t\tlocationAlongCurveFrom:_locationAlongPathFrom,\n
+\t\tgetLength:_length\n
+\t};\n
+})();\n
+\n
+/**\n
+ * Biltong v0.2\n
+ *\n
+ * Various geometry functions written as part of jsPlumb and perhaps useful for others.\n
+ *\n
+ * Copyright (c) 2014 Simon Porritt\n
+ *\n
+ * Permission is hereby granted, free of charge, to any person\n
+ * obtaining a copy of this software and associated documentation\n
+ * files (the "Software"), to deal in the Software without\n
+ * restriction, including without limitation the rights to use,\n
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell\n
+ * copies of the Software, and to permit persons to whom the\n
+ * Software is furnished to do so, subject to the following\n
+ * conditions:\n
+ *\n
+ * The above copyright notice and this permission notice shall be\n
+ * included in all copies or substantial portions of the Software.\n
+ *\n
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\n
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n
+ * OTHER DEALINGS IN THE SOFTWARE.\n
+ */\n
+;(function() {\n
+\n
+\t\n
+\t"use strict";\n
+\n
+\tvar Biltong = this.Biltong = {};\n
+\n
+\tvar _isa = function(a) { return Object.prototype.toString.call(a) === "[object Array]"; },\n
+\t\t_pointHelper = function(p1, p2, fn) {\n
+\t\t    p1 = _isa(p1) ? p1 : [p1.x, p1.y];\n
+\t\t    p2 = _isa(p2) ? p2 : [p2.x, p2.y];    \n
+\t\t    return fn(p1, p2);\n
+\t\t},\n
+\t\t/**\n
+\t\t* @name Biltong.gradient\n
+\t\t* @function\n
+\t\t* @desc Calculates the gradient of a line between the two points.\n
+\t\t* @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @return {Float} The gradient of a line between the two points.\n
+\t\t*/\n
+\t\t_gradient = Biltong.gradient = function(p1, p2) {\n
+\t\t    return _pointHelper(p1, p2, function(_p1, _p2) { \n
+\t\t        if (_p2[0] == _p1[0])\n
+\t\t            return _p2[1] > _p1[1] ? Infinity : -Infinity;\n
+\t\t        else if (_p2[1] == _p1[1]) \n
+\t\t            return _p2[0] > _p1[0] ? 0 : -0;\n
+\t\t        else \n
+\t\t            return (_p2[1] - _p1[1]) / (_p2[0] - _p1[0]); \n
+\t\t    });\t\t\n
+\t\t},\n
+\t\t/**\n
+\t\t* @name Biltong.normal\n
+\t\t* @function\n
+\t\t* @desc Calculates the gradient of a normal to a line between the two points.\n
+\t\t* @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @return {Float} The gradient of a normal to a line between the two points.\n
+\t\t*/\n
+\t\t_normal = Biltong.normal = function(p1, p2) {\n
+\t\t    return -1 / _gradient(p1, p2);\n
+\t\t},\n
+\t\t/**\n
+\t\t* @name Biltong.lineLength\n
+\t\t* @function\n
+\t\t* @desc Calculates the length of a line between the two points.\n
+\t\t* @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @return {Float} The length of a line between the two points.\n
+\t\t*/\n
+\t\t_lineLength = Biltong.lineLength = function(p1, p2) {\n
+\t\t    return _pointHelper(p1, p2, function(_p1, _p2) {\n
+\t\t        return Math.sqrt(Math.pow(_p2[1] - _p1[1], 2) + Math.pow(_p2[0] - _p1[0], 2));\t\t\t\n
+\t\t    });\n
+\t\t},\n
+\t\t/**\n
+\t\t* @name Biltong.quadrant\n
+\t\t* @function\n
+\t\t* @desc Calculates the quadrant in which the angle between the two points lies. \n
+\t\t* @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @return {Integer} The quadrant - 1 for upper right, 2 for lower right, 3 for lower left, 4 for upper left.\n
+\t\t*/\n
+\t\t_quadrant = Biltong.quadrant = function(p1, p2) {\n
+\t\t    return _pointHelper(p1, p2, function(_p1, _p2) {\n
+\t\t        if (_p2[0] > _p1[0]) {\n
+\t\t            return (_p2[1] > _p1[1]) ? 2 : 1;\n
+\t\t        }\n
+\t\t        else if (_p2[0] == _p1[0]) {\n
+\t\t            return _p2[1] > _p1[1] ? 2 : 1;    \n
+\t\t        }\n
+\t\t        else {\n
+\t\t            return (_p2[1] > _p1[1]) ? 3 : 4;\n
+\t\t        }\n
+\t\t    });\n
+\t\t},\n
+\t\t/**\n
+\t\t* @name Biltong.theta\n
+\t\t* @function\n
+\t\t* @desc Calculates the angle between the two points. \n
+\t\t* @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @return {Float} The angle between the two points.\n
+\t\t*/\n
+\t\t_theta = Biltong.theta = function(p1, p2) {\n
+\t\t    return _pointHelper(p1, p2, function(_p1, _p2) {\n
+\t\t        var m = _gradient(_p1, _p2),\n
+\t\t            t = Math.atan(m),\n
+\t\t            s = _quadrant(_p1, _p2);\n
+\t\t        if ((s == 4 || s== 3)) t += Math.PI;\n
+\t\t        if (t < 0) t += (2 * Math.PI);\n
+\t\t    \n
+\t\t        return t;\n
+\t\t    });\n
+\t\t},\n
+\t\t/**\n
+\t\t* @name Biltong.intersects\n
+\t\t* @function\n
+\t\t* @desc Calculates whether or not the two rectangles intersect.\n
+\t\t* @param {Rectangle} r1 First rectangle, as a js object in the form `{x:.., y:.., w:.., h:..}`\n
+\t\t* @param {Rectangle} r2 Second rectangle, as a js object in the form `{x:.., y:.., w:.., h:..}`\n
+\t\t* @return {Boolean} True if the rectangles intersect, false otherwise.\n
+\t\t*/\n
+\t\t_intersects = Biltong.intersects = function(r1, r2) {\n
+\t\t    var x1 = r1.x, x2 = r1.x + r1.w, y1 = r1.y, y2 = r1.y + r1.h,\n
+\t\t        a1 = r2.x, a2 = r2.x + r2.w, b1 = r2.y, b2 = r2.y + r2.h;\n
+\t\t\n
+\t\t\treturn  ( (x1 <= a1 && a1 <= x2) && (y1 <= b1 && b1 <= y2) ) ||\n
+\t\t\t        ( (x1 <= a2 && a2 <= x2) && (y1 <= b1 && b1 <= y2) ) ||\n
+\t\t\t        ( (x1 <= a1 && a1 <= x2) && (y1 <= b2 && b2 <= y2) ) ||\n
+\t\t\t        ( (x1 <= a2 && a1 <= x2) && (y1 <= b2 && b2 <= y2) ) ||\t\n
+\t\t\t        ( (a1 <= x1 && x1 <= a2) && (b1 <= y1 && y1 <= b2) ) ||\n
+\t\t\t        ( (a1 <= x2 && x2 <= a2) && (b1 <= y1 && y1 <= b2) ) ||\n
+\t\t\t        ( (a1 <= x1 && x1 <= a2) && (b1 <= y2 && y2 <= b2) ) ||\n
+\t\t\t        ( (a1 <= x2 && x1 <= a2) && (b1 <= y2 && y2 <= b2) );\n
+\t\t},\n
+\t\t/**\n
+\t\t* @name Biltong.encloses\n
+\t\t* @function\n
+\t\t* @desc Calculates whether or not r2 is completely enclosed by r1.\n
+\t\t* @param {Rectangle} r1 First rectangle, as a js object in the form `{x:.., y:.., w:.., h:..}`\n
+\t\t* @param {Rectangle} r2 Second rectangle, as a js object in the form `{x:.., y:.., w:.., h:..}`\n
+\t\t* @param {Boolean} [allowSharedEdges=false] If true, the concept of enclosure allows for one or more edges to be shared by the two rectangles.\n
+\t\t* @return {Boolean} True if r1 encloses r2, false otherwise.\n
+\t\t*/\n
+\t\t_encloses = Biltong.encloses = function(r1, r2, allowSharedEdges) {\n
+\t\t\tvar x1 = r1.x, x2 = r1.x + r1.w, y1 = r1.y, y2 = r1.y + r1.h,\n
+\t\t        a1 = r2.x, a2 = r2.x + r2.w, b1 = r2.y, b2 = r2.y + r2.h,\n
+\t\t\t\tc = function(v1, v2, v3, v4) { return allowSharedEdges ? v1 <= v2 && v3>= v4 : v1 < v2 && v3 > v4; };\n
+\t\t\t\t\n
+\t\t\treturn c(x1,a1,x2,a2) && c(y1,b1,y2,b2);\n
+\t\t},\n
+\t\t_segmentMultipliers = [null, [1, -1], [1, 1], [-1, 1], [-1, -1] ],\n
+\t\t_inverseSegmentMultipliers = [null, [-1, -1], [-1, 1], [1, 1], [1, -1] ],\n
+\t\t/**\n
+\t\t* @name Biltong.pointOnLine\n
+\t\t* @function\n
+\t\t* @desc Calculates a point on the line from `fromPoint` to `toPoint` that is `distance` units along the length of the line.\n
+\t\t* @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @return {Point} Point on the line, in the form `{ x:..., y:... }`.\n
+\t\t*/\n
+\t\t_pointOnLine = Biltong.pointOnLine = function(fromPoint, toPoint, distance) {\n
+\t\t    var m = _gradient(fromPoint, toPoint),\n
+\t\t        s = _quadrant(fromPoint, toPoint),\n
+\t\t        segmentMultiplier = distance > 0 ? _segmentMultipliers[s] : _inverseSegmentMultipliers[s],\n
+\t\t        theta = Math.atan(m),\n
+\t\t        y = Math.abs(distance * Math.sin(theta)) * segmentMultiplier[1],\n
+\t\t        x =  Math.abs(distance * Math.cos(theta)) * segmentMultiplier[0];\n
+\t\t    return { x:fromPoint.x + x, y:fromPoint.y + y };\n
+\t\t},\n
+\t\t/**\n
+\t\t* @name Biltong.perpendicularLineTo\n
+\t\t* @function\n
+\t\t* @desc Calculates a line of length `length` that is perpendicular to the line from `fromPoint` to `toPoint` and passes through `toPoint`.\n
+\t\t* @param {Point} p1 First point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @param {Point} p2 Second point, either as a 2 entry array or object with `left` and `top` properties.\n
+\t\t* @return {Line} Perpendicular line, in the form `[ { x:..., y:... }, { x:..., y:... } ]`.\n
+\t\t*/        \n
+\t\t_perpendicularLineTo = Biltong.perpendicularLineTo = function(fromPoint, toPoint, length) {\n
+\t\t    var m = _gradient(fromPoint, toPoint),\n
+\t\t        theta2 = Math.atan(-1 / m),\n
+\t\t        y =  length / 2 * Math.sin(theta2),\n
+\t\t        x =  length / 2 * Math.cos(theta2);\n
+\t\t    return [{x:toPoint.x + x, y:toPoint.y + y}, {x:toPoint.x - x, y:toPoint.y - y}];\n
+\t\t};\t\n
+}).call(this);\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the utility functions.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+;(function() {\n
+\n
+\n
+    var _isa = function(a) { return Object.prototype.toString.call(a) === "[object Array]"; },\n
+        _isnum = function(n) { return Object.prototype.toString.call(n) === "[object Number]"; },\n
+        _iss = function(s) { return typeof s === "string"; },\n
+        _isb = function(s) { return typeof s === "boolean"; },\n
+        _isnull = function(s) { return s == null; },  \n
+        _iso = function(o) { return o == null ? false : Object.prototype.toString.call(o) === "[object Object]"; },\n
+        _isd = function(o) { return Object.prototype.toString.call(o) === "[object Date]"; },\n
+        _isf = function(o) { return Object.prototype.toString.call(o) === "[object Function]"; },\n
+        _ise = function(o) {\n
+            for (var i in o) { if (o.hasOwnProperty(i)) return false; }\n
+            return true;\n
+        },\n
+        pointHelper = function(p1, p2, fn) {\n
+            p1 = _isa(p1) ? p1 : [p1.x, p1.y];\n
+            p2 = _isa(p2) ? p2 : [p2.x, p2.y];    \n
+            return fn(p1, p2);\n
+        };\n
+    \n
+    jsPlumbUtil = {        \n
+        isArray : _isa,        \n
+        isString : _iss,        \n
+        isBoolean: _isb,        \n
+        isNull : _isnull,        \n
+        isObject : _iso,\n
+        isDate : _isd,\n
+        isFunction: _isf,\n
+        isEmpty:_ise,\n
+        isNumber:_isnum,\n
+        clone : function(a) {\n
+            if (_iss(a)) return "" + a;\n
+            else if (_isb(a)) return !!a;\n
+            else if (_isd(a)) return new Date(a.getTime());\n
+            else if (_isf(a)) return a;\n
+            else if (_isa(a)) {\n
+                var b = [];\n
+                for (var i = 0; i < a.length; i++)\n
+                    b.push(this.clone(a[i]));\n
+                return b;\n
+            }\n
+            else if (_iso(a)) {\n
+                var c = {};\n
+                for (var j in a)\n
+                    c[j] = this.clone(a[j]);\n
+                return c;\n
+            }\n
+            else return a;\n
+        },\n
+        matchesSelector : function(el, selector, ctx) {\n
+            ctx = ctx || el.parentNode;\n
+            var possibles = ctx.querySelectorAll(selector);\n
+            for (var i = 0; i < possibles.length; i++) {\n
+                if (possibles[i] === el)\n
+                    return true;\n
+            }\n
+            return false;\n
+        },\n
+        merge : function(a, b) {\n
+            var c = this.clone(a);\n
+            for (var i in b) {\n
+                if (c[i] == null || _iss(b[i]) || _isb(b[i]))\n
+                    c[i] = b[i];\n
+                else {\n
+                    if (_isa(b[i])) {\n
+                        var ar = [];\n
+                        // if c\'s object is also an array we can keep its values.\n
+                        if (_isa(c[i])) ar.push.apply(ar, c[i]);\n
+                        ar.push.apply(ar, b[i]);\n
+                        c[i] = ar;\n
+                    }\n
+                    else if(_iso(b[i])) {\n
+                        // overwite c\'s value with an object if it is not already one.\n
+                        if (!_iso(c[i])) \n
+                            c[i] = {};\n
+                        for (var j in b[i])\n
+                            c[i][j] = b[i][j];\n
+                    }\n
+                }\n
+            }\n
+            return c;\n
+        },\n
+        replace:function(inObj, path, value) {\n
+            var q = inObj, t = q;\n
+            path.replace(/([^\\.])+/g, function(term, lc, pos, str) {             \n
+                var array = term.match(/([^\\[0-9]+){1}(\\[)([0-9+])/),\n
+                    last = pos + term.length >= str.length,\n
+                    _getArray = function() {\n
+                        return t[array[1]] || (function() {  t[array[1]] = []; return t[array[1]]; })();\n
+                    };\n
+                \n
+                if (last) {\n
+                    // set term = value on current t, creating term as array if necessary.\n
+                    if (array)\n
+                        _getArray()[array[3]] = value;\n
+                    else\n
+                        t[term] = value;\n
+                }\n
+                else {\n
+                    // set to current t[term], creating t[term] if necessary.\n
+                    if (array) {\n
+                        var a = _getArray();\n
+                        t = a[array[3]] || (function() { a[array[3]] = {}; return a[array[3]]; })();\n
+                    }\n
+                    else\n
+                        t = t[term] || (function() { t[term] = {}; return t[term]; })();\n
+                }\n
+            });\n
+\n
+            return inObj;\n
+        },\n
+        //\n
+        // chain a list of functions, supplied by [ object, method name, args ], and return on the first\n
+        // one that returns the failValue. if none return the failValue, return the successValue.\n
+        //\n
+        functionChain : function(successValue, failValue, fns) {\n
+            for (var i = 0; i < fns.length; i++) {\n
+                var o = fns[i][0][fns[i][1]].apply(fns[i][0], fns[i][2]);\n
+                if (o === failValue) {\n
+                    return o;\n
+                }\n
+            }\n
+            return successValue;\n
+        },\n
+        // take the given model and expand out any parameters.\n
+        populate : function(model, values) {\n
+            // for a string, see if it has parameter matches, and if so, try to make the substitutions.\n
+            var getValue = function(fromString) {\n
+                    var matches = fromString.match(/(\\${.*?})/g);\n
+                    if (matches != null) {\n
+                        for (var i = 0; i < matches.length; i++) {\n
+                            var val = values[matches[i].substring(2, matches[i].length - 1)];\n
+                            if (val != null) {\n
+                                fromString = fromString.replace(matches[i], val);\n
+                            }\n
+                        }\n
+                    }\n
+                    return fromString;\n
+                },\t\t\n
+                // process one entry.\n
+                _one = function(d) {\n
+                    if (d != null) {\n
+                        if (_iss(d)) {\n
+                            return getValue(d);\n
+                        }\n
+                        else if (_isa(d)) {\n
+                            var r = [];\t\n
+                            for (var i = 0; i < d.length; i++)\n
+                                r.push(_one(d[i]));\n
+                            return r;\n
+                        }\n
+                        else if (_iso(d)) {\n
+                            var s = {};\n
+                            for (var j in d) {\n
+                                s[j] = _one(d[j]);\n
+                            }\n
+                            return s;\n
+                        }\n
+                        else {\n
+                            return d;\n
+                        }\n
+                    }\n
+                };\n
+            \n
+            return _one(model);\t\n
+        },\n
+        convertStyle : function(s, ignoreAlpha) {\n
+            // TODO: jsPlumb should support a separate \'opacity\' style member.\n
+            if ("transparent" === s) return s;\n
+            var o = s,\n
+                pad = function(n) { return n.length == 1 ? "0" + n : n; },\n
+                hex = function(k) { return pad(Number(k).toString(16)); },\n
+                pattern = /(rgb[a]?\\()(.*)(\\))/;\n
+            if (s.match(pattern)) {\n
+                var parts = s.match(pattern)[2].split(",");\n
+                o = "#" + hex(parts[0]) + hex(parts[1]) + hex(parts[2]);\n
+                if (!ignoreAlpha && parts.length == 4) \n
+                    o = o + hex(parts[3]);\n
+            }\n
+            return o;\n
+        },\n
+        findWithFunction : function(a, f) {\n
+            if (a)\n
+                for (var i = 0; i < a.length; i++) if (f(a[i])) return i;\n
+            return -1;\n
+\t\t},\n
+\t\tindexOf : function(l, v) {\n
+\t\t\treturn l.indexOf ? l.indexOf(v) : jsPlumbUtil.findWithFunction(l, function(_v) { return _v == v; });\n
+\t\t},\n
+\t\tremoveWithFunction : function(a, f) {\n
+\t\t\tvar idx = jsPlumbUtil.findWithFunction(a, f);\n
+\t\t\tif (idx > -1) a.splice(idx, 1);\n
+\t\t\treturn idx != -1;\n
+\t\t},\n
+\t\tremove : function(l, v) {\n
+\t\t\tvar idx = jsPlumbUtil.indexOf(l, v);\n
+\t\t\tif (idx > -1) l.splice(idx, 1);\n
+\t\t\treturn idx != -1;\n
+\t\t},\n
+        // TODO support insert index\n
+        addWithFunction : function(list, item, hashFunction) {\n
+            if (jsPlumbUtil.findWithFunction(list, hashFunction) == -1) list.push(item);\n
+        },\n
+        addToList : function(map, key, value, insertAtStart) {\n
+            var l = map[key];\n
+            if (l == null) {\n
+                l = []; \n
+\t\t\t\tmap[key] = l;\n
+            }\n
+            l[insertAtStart ? "unshift" : "push"](value);\n
+            return l;\n
+        },\n
+        consume : function(e, doNotPreventDefault) {\n
+            if (e.stopPropagation)\n
+                e.stopPropagation();\n
+            else \n
+                e.returnValue = false;\n
+            \n
+            if (!doNotPreventDefault && e.preventDefault)\n
+                 e.preventDefault();\n
+        },\n
+        //\n
+        // extends the given obj (which can be an array) with the given constructor function, prototype functions, and\n
+        // class members, any of which may be null.\n
+        //\n
+        extend : function(child, parent, _protoFn) {\n
+\t\t\tvar i;\n
+            parent = _isa(parent) ? parent : [ parent ];\n
+\n
+            for (i = 0; i < parent.length; i++) {\n
+                for (var j in parent[i].prototype) {\n
+                    if(parent[i].prototype.hasOwnProperty(j)) {\n
+                        child.prototype[j] = parent[i].prototype[j];\n
+                    }\n
+                }\n
+            }\n
+\n
+            var _makeFn = function(name, protoFn) {\n
+                return function() {\n
+                    for (i = 0; i < parent.length; i++) {\n
+                        if (parent[i].prototype[name])\n
+                            parent[i].prototype[name].apply(this, arguments);\n
+                    }                    \n
+                    return protoFn.apply(this, arguments);\n
+                };\n
+            };\n
+\t\t\t\n
+\t\t\tvar _oneSet = function(fns) {\n
+\t\t\t\tfor (var k in fns) {\n
+\t\t\t\t\tchild.prototype[k] = _makeFn(k, fns[k]);\n
+\t\t\t\t}\n
+\t\t\t};\n
+\n
+\t\t\tif (arguments.length > 2) {\n
+\t\t\t\tfor (i = 2; i < arguments.length; i++)\n
+\t\t\t\t\t_oneSet(arguments[i]);\n
+\t\t\t}\n
+\n
+            return child;\n
+        },\n
+        uuid : function() {\n
+            return (\'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\'.replace(/[xy]/g, function(c) {\n
+                var r = Math.random()*16|0, v = c == \'x\' ? r : (r&0x3|0x8);\n
+                return v.toString(16);\n
+            }));\n
+        },\n
+        logEnabled : true,\n
+        log : function() {\n
+            if (jsPlumbUtil.logEnabled && typeof console != "undefined") {\n
+                try {\n
+                    var msg = arguments[arguments.length - 1];\n
+                    console.log(msg);\n
+                }\n
+                catch (e) {} \n
+            }\n
+        },\n
+        /*\n
+         * Function: sizeElement \n
+         * Helper to size and position an element. You would typically use\n
+         * this when writing your own Connector or Endpoint implementation.\n
+         * \n
+         * Parameters: \n
+         *  x - [int] x position for the element origin \n
+         *  y - [int] y position for the element origin \n
+         *  w - [int] width of the element \n
+         *  h - [int] height of the element\n
+         *  \n
+         */\n
+        sizeElement : function(el, x, y, w, h) {\n
+            if (el) {\n
+                el.style.height = h + "px";\n
+                el.height = h;\n
+                el.style.width = w + "px";\n
+                el.width = w;\n
+                el.style.left = x + "px";\n
+                el.style.top = y + "px";\n
+            }\n
+        },\n
+        /**\n
+        * Wraps one function with another, creating a placeholder for the\n
+        * wrapped function if it was null. this is used to wrap the various\n
+        * drag/drop event functions - to allow jsPlumb to be notified of\n
+        * important lifecycle events without imposing itself on the user\'s\n
+        * drag/drop functionality. \n
+        * @method jsPlumbUtil.wrap\n
+        * @param {Function} wrappedFunction original function to wrap; may be null.\n
+        * @param {Function} newFunction function to wrap the original with.\n
+        * @param {Object} [returnOnThisValue] Optional. Indicates that the wrappedFunction should \n
+        * not be executed if the newFunction returns a value matching \'returnOnThisValue\'.\n
+        * note that this is a simple comparison and only works for primitives right now.\n
+        */        \n
+        wrap : function(wrappedFunction, newFunction, returnOnThisValue) {\n
+            wrappedFunction = wrappedFunction || function() { };\n
+            newFunction = newFunction || function() { };\n
+            return function() {\n
+                var r = null;\n
+                try {\n
+                    r = newFunction.apply(this, arguments);\n
+                } catch (e) {\n
+                    jsPlumbUtil.log("jsPlumb function failed : " + e);\n
+                }\n
+                if (returnOnThisValue == null || (r !== returnOnThisValue)) {\n
+                    try {\n
+                        r = wrappedFunction.apply(this, arguments);\n
+                    } catch (e) {\n
+                        jsPlumbUtil.log("wrapped function failed : " + e);\n
+                    }\n
+                }\n
+                return r;\n
+            };\n
+        },\n
+        ieVersion : /MSIE\\s([\\d.]+)/.test(navigator.userAgent) ? (new Number(RegExp.$1)) : -1\n
+    };\n
+\n
+    jsPlumbUtil.oldIE = jsPlumbUtil.ieVersion > -1 && jsPlumbUtil.ieVersion < 9;\n
+\n
+\tjsPlumbUtil.EventGenerator = function() {\n
+\t\tvar _listeners = {}, \n
+\t\t\teventsSuspended = false,\n
+\t\t\t// this is a list of events that should re-throw any errors that occur during their dispatch. it is current private.\n
+\t\t\teventsToDieOn = { "ready":true };\n
+\n
+\t\tthis.bind = function(event, listener, insertAtStart) {\n
+\t\t\tjsPlumbUtil.addToList(_listeners, event, listener, insertAtStart);\n
+\t\t\treturn this;\n
+\t\t};\n
+\n
+\t\tthis.fire = function(event, value, originalEvent) {\n
+\t\t\tif (!eventsSuspended && _listeners[event]) {\n
+\t\t\t\tvar l = _listeners[event].length, i = 0, _gone = false, ret = null;\n
+\t\t\t\tif (!this.shouldFireEvent || this.shouldFireEvent(event, value, originalEvent)) {\n
+\t\t\t\t\twhile (!_gone && i < l && ret !== false) {\n
+\t\t\t\t\t\t// doing it this way rather than catching and then possibly re-throwing means that an error propagated by this\n
+\t\t\t\t\t\t// method will have the whole call stack available in the debugger.\n
+\t\t\t\t\t\tif (eventsToDieOn[event]) \n
+\t\t\t\t\t\t\t_listeners[event][i].apply(this, [ value, originalEvent]);\n
+\t\t\t\t\t\telse {\n
+\t\t\t\t\t\t\ttry {\n
+\t\t\t\t\t\t\t\tret = _listeners[event][i].apply(this, [ value, originalEvent ]);\n
+\t\t\t\t\t\t\t} catch (e) {\n
+\t\t\t\t\t\t\t\tjsPlumbUtil.log("jsPlumb: fire failed for event " + event + " : " + e);\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\ti++;\n
+\t\t\t\t\t\tif (_listeners == null || _listeners[event] == null) \n
+\t\t\t\t\t\t\t_gone = true;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\treturn this;\n
+\t\t};\n
+\n
+\t\tthis.unbind = function(event) {\n
+\t\t\tif (event)\n
+\t\t\t\tdelete _listeners[event];\n
+\t\t\telse {\n
+\t\t\t\t_listeners = {};\n
+\t\t\t}\n
+\t\t\treturn this;\n
+\t\t};\n
+\n
+\t\tthis.getListener = function(forEvent) { return _listeners[forEvent]; };\n
+\t\tthis.setSuspendEvents = function(val) { eventsSuspended = val; };\n
+\t\tthis.isSuspendEvents = function() { return eventsSuspended; };\n
+\t\tthis.cleanupListeners = function() {\n
+\t\t\tfor (var i in _listeners) {\n
+\t\t\t\t_listeners[i] = null;\n
+\t\t\t}\n
+\t\t};\n
+\t};\n
+\n
+\tjsPlumbUtil.EventGenerator.prototype = {\n
+\t\tcleanup:function() {\n
+\t\t\tthis.cleanupListeners();\n
+\t\t}\n
+\t};\n
+\n
+    // thanks MDC\n
+    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FFunction%2Fbind\n
+    if (!Function.prototype.bind) {\n
+      Function.prototype.bind = function (oThis) {\n
+        if (typeof this !== "function") {\n
+          // closest thing possible to the ECMAScript 5 internal IsCallable function\n
+          throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");\n
+        }\n
+\n
+        var aArgs = Array.prototype.slice.call(arguments, 1), \n
+            fToBind = this, \n
+            fNOP = function () {},\n
+            fBound = function () {\n
+              return fToBind.apply(this instanceof fNOP && oThis ? this : oThis,\n
+                                   aArgs.concat(Array.prototype.slice.call(arguments)));\n
+            };\n
+\n
+        fNOP.prototype = this.prototype;\n
+        fBound.prototype = new fNOP();\n
+\n
+        return fBound;\n
+      };\n
+    }\n
+\n
+})();\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the base functionality for DOM type adapters. \n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+;(function() {\n
+    \n
+\tvar svgAvailable = !!window.SVGAngle || document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1"),\n
+\t\tvmlAvailable = function() {\t\t    \n
+\t        if (vmlAvailable.vml === undefined) { \n
+\t            var a = document.body.appendChild(document.createElement(\'div\'));\n
+\t        \ta.innerHTML = \'<v:shape id="vml_flag1" adj="1" />\';\n
+\t        \tvar b = a.firstChild;\n
+\t        \tif (b != null && b.style != null) {\n
+\t            \tb.style.behavior = "url(#default#VML)";\n
+\t            \tvmlAvailable.vml = b ? typeof b.adj == "object": true;\n
+\t            }\n
+\t            else\n
+\t            \tvmlAvailable.vml = false;\n
+\t        \ta.parentNode.removeChild(a);\n
+\t        }\n
+\t        return vmlAvailable.vml;\n
+\t\t},\n
+\t\t// TODO: remove this once we remove all library adapter versions and have only vanilla jsplumb: this functionality\n
+\t\t// comes from Mottle.\n
+\t\tiev = (function() {\n
+\t\t\tvar rv = -1; \n
+\t\t\tif (navigator.appName == \'Microsoft Internet Explorer\') {\n
+\t\t\t\tvar ua = navigator.userAgent,\n
+\t\t\t\t\tre = new RegExp("MSIE ([0-9]{1,}[\\.0-9]{0,})");\n
+\t\t\t\tif (re.exec(ua) != null)\n
+\t\t\t\t\trv = parseFloat(RegExp.$1);\n
+\t\t\t}\n
+\t\t\treturn rv;\n
+\t\t})(),\n
+\t\tisIELT9 = iev > -1 && iev < 9, \n
+\t\t_genLoc = function(e, prefix) {\n
+\t\t\tif (e == null) return [ 0, 0 ];\n
+\t\t\tvar ts = _touches(e), t = _getTouch(ts, 0);\n
+\t\t\treturn [t[prefix + "X"], t[prefix + "Y"]];\n
+\t\t},\n
+\t\t_pageLocation = function(e) {\n
+\t\t\tif (e == null) return [ 0, 0 ];\n
+\t\t\tif (isIELT9) {\n
+\t\t\t\treturn [ e.clientX + document.documentElement.scrollLeft, e.clientY + document.documentElement.scrollTop ];\n
+\t\t\t}\n
+\t\t\telse {\n
+\t\t\t\treturn _genLoc(e, "page");\n
+\t\t\t}\n
+\t\t},\n
+\t\t_screenLocation = function(e) {\n
+\t\t\treturn _genLoc(e, "screen");\n
+\t\t},\n
+\t\t_clientLocation = function(e) {\n
+\t\t\treturn _genLoc(e, "client");\n
+\t\t},\n
+\t\t_getTouch = function(touches, idx) { return touches.item ? touches.item(idx) : touches[idx]; },\n
+\t\t_touches = function(e) {\n
+\t\t\treturn e.touches && e.touches.length > 0 ? e.touches : \n
+\t\t\t\t   e.changedTouches && e.changedTouches.length > 0 ? e.changedTouches :\n
+\t\t\t\t   e.targetTouches && e.targetTouches.length > 0 ? e.targetTouches :\n
+\t\t\t\t   [ e ];\n
+\t\t};\n
+        \n
+    /**\n
+\t\tManages dragging for some instance of jsPlumb.\n
+\t*/\n
+\tvar DragManager = function(_currentInstance) {\t\t\n
+\t\tvar _draggables = {}, _dlist = [], _delements = {}, _elementsWithEndpoints = {},\t\t\t\n
+\t\t\t// elementids mapped to the draggable to which they belong.\n
+\t\t\t_draggablesForElements = {};\t\t\t\n
+\n
+        /**\n
+            register some element as draggable.  right now the drag init stuff is done elsewhere, and it is\n
+            possible that will continue to be the case.\n
+        */\n
+\t\tthis.register = function(el) {\n
+            var id = _currentInstance.getId(el),\n
+                parentOffset = jsPlumbAdapter.getOffset(el, _currentInstance);\n
+                    \n
+            if (!_draggables[id]) {\n
+                _draggables[id] = el;\n
+                _dlist.push(el);\n
+                _delements[id] = {};\n
+            }\n
+\t\t\t\t\n
+\t\t\t// look for child elements that have endpoints and register them against this draggable.\n
+\t\t\tvar _oneLevel = function(p, startOffset) {\n
+\t\t\t\tif (p) {\n
+\t\t\t\t\tfor (var i = 0; i < p.childNodes.length; i++) {\n
+\t\t\t\t\t\tif (p.childNodes[i].nodeType != 3 && p.childNodes[i].nodeType != 8) {\n
+\t\t\t\t\t\t\tvar cEl = jsPlumb.getElementObject(p.childNodes[i]),\n
+\t\t\t\t\t\t\t\tcid = _currentInstance.getId(p.childNodes[i], null, true);\n
+\t\t\t\t\t\t\tif (cid && _elementsWithEndpoints[cid] && _elementsWithEndpoints[cid] > 0) {\n
+\t\t\t\t\t\t\t\tvar cOff = jsPlumbAdapter.getOffset(cEl, _currentInstance);\n
+\t\t\t\t\t\t\t\t_delements[id][cid] = {\n
+\t\t\t\t\t\t\t\t\tid:cid,\n
+\t\t\t\t\t\t\t\t\toffset:{\n
+\t\t\t\t\t\t\t\t\t\tleft:cOff.left - parentOffset.left,\n
+\t\t\t\t\t\t\t\t\t\ttop:cOff.top - parentOffset.top\n
+\t\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\t};\n
+\t\t\t\t\t\t\t\t_draggablesForElements[cid] = id;\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t_oneLevel(p.childNodes[i]);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t};\n
+\n
+\t\t\t_oneLevel(el);\n
+\t\t};\n
+\t\t\n
+\t\t// refresh the offsets for child elements of this element. \n
+\t\tthis.updateOffsets = function(elId) {\n
+\t\t\tif (elId != null) {\n
+\t\t\t\tvar domEl = jsPlumb.getDOMElement(elId),\n
+\t\t\t\t\tid = _currentInstance.getId(domEl),\n
+\t\t\t\t\tchildren = _delements[id],\n
+\t\t\t\t\tparentOffset = jsPlumbAdapter.getOffset(domEl, _currentInstance);\n
+\t\t\t\t\t\n
+\t\t\t\tif (children) {\n
+\t\t\t\t\tfor (var i in children) {\n
+\t\t\t\t\t\tvar cel = jsPlumb.getElementObject(i),\n
+\t\t\t\t\t\t\tcOff = jsPlumbAdapter.getOffset(cel, _currentInstance);\n
+\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t_delements[id][i] = {\n
+\t\t\t\t\t\t\tid:i,\n
+\t\t\t\t\t\t\toffset:{\n
+\t\t\t\t\t\t\t\tleft:cOff.left - parentOffset.left,\n
+\t\t\t\t\t\t\t\ttop:cOff.top - parentOffset.top\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t};\n
+\t\t\t\t\t\t_draggablesForElements[i] = id;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t};\n
+\n
+\t\t/**\n
+\t\t\tnotification that an endpoint was added to the given el.  we go up from that el\'s parent\n
+\t\t\tnode, looking for a parent that has been registered as a draggable. if we find one, we add this\n
+\t\t\tel to that parent\'s list of elements to update on drag (if it is not there already)\n
+\t\t*/\n
+\t\tthis.endpointAdded = function(el) {\n
+\t\t\tvar b = document.body, id = _currentInstance.getId(el), \n
+\t\t\t\tcLoc = jsPlumbAdapter.getOffset(el, _currentInstance),\n
+\t\t\t\tp = el.parentNode, done = p == b;\n
+\n
+\t\t\t_elementsWithEndpoints[id] = _elementsWithEndpoints[id] ? _elementsWithEndpoints[id] + 1 : 1;\n
+\n
+\t\t\twhile (p != null && p != b) {\n
+\t\t\t\tvar pid = _currentInstance.getId(p, null, true);\n
+\t\t\t\tif (pid && _draggables[pid]) {\n
+\t\t\t\t\tvar idx = -1, pLoc = jsPlumbAdapter.getOffset(p, _currentInstance);\n
+\t\t\t\t\t\n
+\t\t\t\t\tif (_delements[pid][id] == null) {\t\t\t\t\t\t\n
+\t\t\t\t\t\t_delements[pid][id] = {\n
+\t\t\t\t\t\t\tid:id,\n
+\t\t\t\t\t\t\toffset:{\n
+\t\t\t\t\t\t\t\tleft:cLoc.left - pLoc.left,\n
+\t\t\t\t\t\t\t\ttop:cLoc.top - pLoc.top\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t};\n
+\t\t\t\t\t\t_draggablesForElements[id] = pid;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t\tp = p.parentNode;\n
+\t\t\t}\t\n
+\t\t};\n
+\n
+\t\tthis.endpointDeleted = function(endpoint) {\n
+\t\t\tif (_elementsWithEndpoints[endpoint.elementId]) {\n
+\t\t\t\t_elementsWithEndpoints[endpoint.elementId]--;\n
+\t\t\t\tif (_elementsWithEndpoints[endpoint.elementId] <= 0) {\n
+\t\t\t\t\tfor (var i in _delements) {\n
+\t\t\t\t\t\tif (_delements[i]) {\n
+                            delete _delements[i][endpoint.elementId];\n
+                            delete _draggablesForElements[endpoint.elementId];\n
+                        }\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\t\t\n
+\t\t};\t\n
+\t\t\n
+\t\tthis.changeId = function(oldId, newId) {\t\t\t\t\n
+\t\t\t_delements[newId] = _delements[oldId];\t\t\t\n
+\t\t\t_delements[oldId] = {};\n
+\t\t\t_draggablesForElements[newId] = _draggablesForElements[oldId];\n
+\t\t\t_draggablesForElements[oldId] = null;\t\t\t\n
+\t\t};\n
+\n
+\t\tthis.getElementsForDraggable = function(id) {\n
+\t\t\treturn _delements[id];\t\n
+\t\t};\n
+\n
+\t\tthis.elementRemoved = function(elementId) {\n
+\t\t\tvar elId = _draggablesForElements[elementId];\n
+\t\t\tif (elId) {\n
+\t\t\t\tdelete _delements[elId][elementId];\n
+\t\t\t\tdelete _draggablesForElements[elementId];\n
+\t\t\t}\n
+\t\t};\n
+\n
+\t\tthis.reset = function() {\n
+\t\t\t_draggables = {};\n
+\t\t\t_dlist = [];\n
+\t\t\t_delements = {};\n
+\t\t\t_elementsWithEndpoints = {};\n
+\t\t};\n
+\n
+\t\t//\n
+\t\t// notification drag ended. We check automatically if need to update some\n
+\t\t// ancestor\'s offsets.\n
+\t\t//\n
+\t\tthis.dragEnded = function(el) {\t\t\t\n
+\t\t\tvar id = _currentInstance.getId(el),\n
+\t\t\t\tancestor = _draggablesForElements[id];\n
+\n
+\t\t\tif (ancestor) this.updateOffsets(ancestor);\n
+\t\t};\n
+\n
+\t\tthis.setParent = function(el, elId, p, pId) {\n
+\t\t\tvar current = _draggablesForElements[elId];\n
+\t\t\tif (current) {\n
+\t\t\t\tif (!_delements[pId])\n
+\t\t\t\t\t_delements[pId] = {};\n
+\t\t\t\t_delements[pId][elId] = _delements[current][elId];\n
+\t\t\t\tdelete _delements[current][elId];\n
+\t\t\t\tvar pLoc = jsPlumbAdapter.getOffset(p, _currentInstance),\n
+\t\t\t\t\tcLoc = jsPlumbAdapter.getOffset(el, _currentInstance);\n
+\t\t\t\t_delements[pId][elId].offset = {\n
+\t\t\t\t\tleft:cLoc.left - pLoc.left,\n
+\t\t\t\t\ttop:cLoc.top - pLoc.top\n
+\t\t\t\t};\t\t\t\t\n
+\t\t\t\t_draggablesForElements[elId] = pId;\n
+\t\t\t}\t\t\t\n
+\t\t};\n
+\t\t\n
+\t};\n
+        \n
+    // for those browsers that dont have it.  they still don\'t have it! but at least they won\'t crash.\n
+\tif (!window.console)\n
+\t\twindow.console = { time:function(){}, timeEnd:function(){}, group:function(){}, groupEnd:function(){}, log:function(){} };\n
+\t\t\n
+\t\t\n
+\t// TODO: katavorio default helper uses this stuff.  should i extract to a support lib?\t\n
+\tvar trim = function(str) {\n
+\t\t\treturn str == null ? null : (str.replace(/^\\s\\s*/, \'\').replace(/\\s\\s*$/, \'\'));\n
+\t\t},\n
+\t\t_setClassName = function(el, cn) {\n
+\t\t\tcn = trim(cn);\n
+\t\t\tif (typeof el.className.baseVal != "undefined")  // SVG\n
+\t\t\t\tel.className.baseVal = cn;\n
+\t\t\telse\n
+\t\t\t\tel.className = cn;\n
+\t\t},\n
+\t\t_getClassName = function(el) {\n
+\t\t\treturn (typeof el.className.baseVal == "undefined") ? el.className : el.className.baseVal;\t\n
+\t\t},\n
+\t\t_classManip = function(el, add, clazz) {\n
+\t\t\t\n
+\t\t\t// TODO if classList exists, use it.\n
+\t\t\t\n
+\t\t\tvar classesToAddOrRemove = clazz.split(/\\s+/),\n
+\t\t\t\tclassName = _getClassName(el),\n
+\t\t\t\tcurClasses = className.split(/\\s+/);\n
+\t\t\t\t\n
+\t\t\tfor (var i = 0; i < classesToAddOrRemove.length; i++) {\n
+\t\t\t\tif (add) {\n
+\t\t\t\t\tif (jsPlumbUtil.indexOf(curClasses, classesToAddOrRemove[i]) == -1)\n
+\t\t\t\t\t\tcurClasses.push(classesToAddOrRemove[i]);\n
+\t\t\t\t}\n
+\t\t\t\telse {\n
+\t\t\t\t\tvar idx = jsPlumbUtil.indexOf(curClasses, classesToAddOrRemove[i]);\n
+\t\t\t\t\tif (idx != -1)\n
+\t\t\t\t\t\tcurClasses.splice(idx, 1);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\t_setClassName(el, curClasses.join(" "));\n
+\t\t},\n
+\t\t_each = function(spec, fn) {\n
+\t\t\tif (spec == null) return;\n
+\t\t\tif (typeof spec === "string") \n
+\t\t\t\tfn(jsPlumb.getDOMElement(spec));\n
+\t\t\telse if (spec.length != null) {\n
+\t\t\t\tfor (var i = 0; i < spec.length; i++)\n
+\t\t\t\t\tfn(jsPlumb.getDOMElement(spec[i]));\n
+\t\t\t}\n
+\t\t\telse\n
+\t\t\t\tfn(spec); // assume it\'s an element.\n
+\t\t};\n
+\n
+    window.jsPlumbAdapter = {\n
+        \n
+        headless:false,\n
+\n
+        pageLocation:_pageLocation,\n
+        screenLocation:_screenLocation,\n
+        clientLocation:_clientLocation,\n
+\n
+        getAttribute:function(el, attName) {\n
+        \treturn el.getAttribute(attName);\n
+        },\n
+\n
+        setAttribute:function(el, a, v) {\n
+        \tel.setAttribute(a, v);\n
+        },\n
+        \n
+        appendToRoot : function(node) {\n
+            document.body.appendChild(node);\n
+        },\n
+        getRenderModes : function() {\n
+            return [ "svg", "vml" ];\n
+        },\n
+        isRenderModeAvailable : function(m) {\n
+            return {\n
+                "svg":svgAvailable,\n
+                "vml":vmlAvailable()\n
+            }[m];\n
+        },\n
+        getDragManager : function(_jsPlumb) {\n
+            return new DragManager(_jsPlumb);\n
+        },\n
+        setRenderMode : function(mode) {\n
+            var renderMode;\n
+            \n
+            if (mode) {\n
+\t\t\t\tmode = mode.toLowerCase();            \n
+\t\t\t            \n
+                var svgAvailable = this.isRenderModeAvailable("svg"),\n
+                    vmlAvailable = this.isRenderModeAvailable("vml");\n
+                \n
+                // now test we actually have the capability to do this.\n
+                if (mode === "svg") {\n
+                    if (svgAvailable) renderMode = "svg";\n
+                    else if (vmlAvailable) renderMode = "vml";\n
+                }\n
+                else if (vmlAvailable) renderMode = "vml";\n
+            }\n
+\n
+\t\t\treturn renderMode;\n
+        },\n
+\t\taddClass:function(el, clazz) {\n
+\t\t\t_each(el, function(e) {\n
+\t\t\t\t_classManip(e, true, clazz);\n
+\t\t\t});\n
+\t\t},\n
+\t\thasClass:function(el, clazz) {\n
+\t\t\tel = jsPlumb.getDOMElement(el);\n
+\t\t\tif (el.classList) return el.classList.contains(clazz);\n
+\t\t\telse {\n
+\t\t\t\treturn _getClassName(el).indexOf(clazz) != -1;\n
+\t\t\t}\n
+\t\t},\n
+\t\tremoveClass:function(el, clazz) {\n
+\t\t\t_each(el, function(e) {\n
+\t\t\t\t_classManip(e, false, clazz);\n
+\t\t\t});\n
+\t\t},\n
+\t\tsetClass:function(el, clazz) {\n
+\t\t\t_each(el, function(e) {\n
+\t\t\t\t_setClassName(e, clazz);\n
+\t\t\t});\n
+\t\t},\n
+\t\tsetPosition:function(el, p) {\n
+\t\t\tel.style.left = p.left + "px";\n
+\t\t\tel.style.top = p.top + "px";\n
+\t\t},\n
+\t\tgetPosition:function(el) {\n
+\t\t\tvar _one = function(prop) {\n
+\t\t\t\tvar v = el.style[prop];\n
+\t\t\t\treturn v ? v.substring(0, v.length - 2) : 0;\n
+\t\t\t};\n
+\t\t\treturn {\n
+\t\t\t\tleft:_one("left"),\n
+\t\t\t\ttop:_one("top")\n
+\t\t\t};\n
+\t\t},\n
+\t\tgetOffset:function(el, _instance, relativeToRoot) {\n
+\t\t\tel = jsPlumb.getDOMElement(el);\n
+\t\t\tvar container = _instance.getContainer();\n
+\t\t\tvar l = el.offsetLeft, t = el.offsetTop, op = (relativeToRoot  || (container != null && el.offsetParent != container)) ?  el.offsetParent : null;\n
+\t\t\twhile (op != null) {\n
+\t\t\t\tl += op.offsetLeft;\n
+\t\t\t\tt += op.offsetTop;\n
+\t\t\t\top = relativeToRoot ? op.offsetParent : \n
+\t\t\t\t\top.offsetParent == container ? null : op.offsetParent;\n
+\t\t\t}\n
+\t\t\treturn {\n
+\t\t\t\tleft:l, top:t\n
+\t\t\t};\n
+\t\t},\n
+\t\t//\n
+\t\t// return x+y proportion of the given element\'s size corresponding to the location of the given event.\n
+\t\t//\n
+\t\tgetPositionOnElement:function(evt, el, zoom) {\n
+\t\t\tvar box = typeof el.getBoundingClientRect !== "undefined" ? el.getBoundingClientRect() : { left:0, top:0, width:0, height:0 },\n
+\t\t\t\tbody = document.body,\n
+    \t\t\tdocElem = document.documentElement,\n
+    \t\t\toffPar = el.offsetParent,\n
+    \t\t\tscrollTop = window.pageYOffset || docElem.scrollTop || body.scrollTop,\n
+\t\t\t\tscrollLeft = window.pageXOffset || docElem.scrollLeft || body.scrollLeft,\n
+\t\t\t\tclientTop = docElem.clientTop || body.clientTop || 0,\n
+\t\t\t\tclientLeft = docElem.clientLeft || body.clientLeft || 0,\n
+\t\t\t\tpst = 0,//offPar ? offPar.scrollTop : 0,\n
+\t\t\t\tpsl = 0,//offPar ? offPar.scrollLeft : 0,\n
+\t\t\t\ttop  = box.top +  scrollTop - clientTop + (pst * zoom),\n
+\t\t\t\tleft = box.left + scrollLeft - clientLeft + (psl * zoom),\n
+\t\t\t\tcl = jsPlumbAdapter.pageLocation(evt),\n
+\t\t\t\tw = box.width || (el.offsetWidth * zoom),\n
+\t\t\t\th = box.height || (el.offsetHeight * zoom),\n
+\t\t\t\tx = (cl[0] - left) / w,\n
+\t\t\t\ty = (cl[1] - top) / h;\n
+\n
+\t\t\treturn [ x, y ];\n
+\t\t}\n
+    };\n
+   \n
+})();\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the core code.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+;(function() {\n
+\t\n
+\t"use strict";\n
+\t\t\t\n
+    var _ju = jsPlumbUtil,\n
+    \t_getOffset = function(el, _instance, relativeToRoot) {\n
+            return jsPlumbAdapter.getOffset(el, _instance, relativeToRoot);\n
+        },\n
+\t\t\n
+\t\t/**\n
+\t\t * creates a timestamp, using milliseconds since 1970, but as a string.\n
+\t\t */\n
+\t\t_timestamp = function() { return "" + (new Date()).getTime(); },\n
+\n
+\t\t// helper method to update the hover style whenever it, or paintStyle, changes.\n
+\t\t// we use paintStyle as the foundation and merge hoverPaintStyle over the\n
+\t\t// top.\n
+\t\t_updateHoverStyle = function(component) {\n
+\t\t\tif (component._jsPlumb.paintStyle && component._jsPlumb.hoverPaintStyle) {\n
+\t\t\t\tvar mergedHoverStyle = {};\n
+\t\t\t\tjsPlumb.extend(mergedHoverStyle, component._jsPlumb.paintStyle);\n
+\t\t\t\tjsPlumb.extend(mergedHoverStyle, component._jsPlumb.hoverPaintStyle);\n
+\t\t\t\tdelete component._jsPlumb.hoverPaintStyle;\n
+\t\t\t\t// we want the fillStyle of paintStyle to override a gradient, if possible.\n
+\t\t\t\tif (mergedHoverStyle.gradient && component._jsPlumb.paintStyle.fillStyle)\n
+\t\t\t\t\tdelete mergedHoverStyle.gradient;\n
+\t\t\t\tcomponent._jsPlumb.hoverPaintStyle = mergedHoverStyle;\n
+\t\t\t}\n
+\t\t},\t\t\n
+\t\tevents = [ "click", "dblclick", "mouseenter", "mouseout", "mousemove", "mousedown", "mouseup", "contextmenu" ],\n
+\t\teventFilters = { "mouseout":"mouseleave", "mouseexit":"mouseleave" },\n
+\t\t_updateAttachedElements = function(component, state, timestamp, sourceElement) {\n
+\t\t\tvar affectedElements = component.getAttachedElements();\n
+\t\t\tif (affectedElements) {\n
+\t\t\t\tfor (var i = 0, j = affectedElements.length; i < j; i++) {\n
+\t\t\t\t\tif (!sourceElement || sourceElement != affectedElements[i])\n
+\t\t\t\t\t\taffectedElements[i].setHover(state, true, timestamp);\t\t\t// tell the attached elements not to inform their own attached elements.\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t},\n
+\t\t_splitType = function(t) { return t == null ? null : t.split(" "); },\t\t\n
+\t\t_applyTypes = function(component, params, doNotRepaint) {\n
+\t\t\tif (component.getDefaultType) {\n
+\t\t\t\tvar td = component.getTypeDescriptor();\n
+\t\t\t\t\t\n
+\t\t\t\tvar o = _ju.merge({}, component.getDefaultType());\n
+\t\t\t\tfor (var i = 0, j = component._jsPlumb.types.length; i < j; i++)\n
+\t\t\t\t\to = _ju.merge(o, component._jsPlumb.instance.getType(component._jsPlumb.types[i], td));\t\t\t\t\t\t\n
+\t\t\t\t\t\n
+\t\t\t\tif (params) {\n
+\t\t\t\t\to = _ju.populate(o, params);\n
+\t\t\t\t}\n
+\t\t\t\n
+\t\t\t\tcomponent.applyType(o, doNotRepaint);\t\t\t\t\t\n
+\t\t\t\tif (!doNotRepaint) component.repaint();\n
+\t\t\t}\n
+\t\t},\t\t\n
+\n
+// ------------------------------ BEGIN jsPlumbUIComponent --------------------------------------------\n
+\n
+\t\tjsPlumbUIComponent = window.jsPlumbUIComponent = function(params) {\n
+\n
+\t\t\tjsPlumbUtil.EventGenerator.apply(this, arguments);\n
+\n
+\t\t\tvar self = this, \n
+\t\t\t\ta = arguments, \t\t\t\t \t\t\t\t\n
+\t\t\t\tidPrefix = self.idPrefix,\n
+\t\t\t\tid = idPrefix + (new Date()).getTime();\n
+\n
+\t\t\tthis._jsPlumb = { \n
+\t\t\t\tinstance: params._jsPlumb,\n
+\t\t\t\tparameters:params.parameters || {},\n
+\t\t\t\tpaintStyle:null,\n
+\t\t\t\thoverPaintStyle:null,\n
+\t\t\t\tpaintStyleInUse:null,\n
+\t\t\t\thover:false,\n
+\t\t\t\tbeforeDetach:params.beforeDetach,\n
+\t\t\t\tbeforeDrop:params.beforeDrop,\n
+\t\t\t\toverlayPlacements : [],\n
+\t\t\t\thoverClass: params.hoverClass || params._jsPlumb.Defaults.HoverClass,\n
+\t\t\t\ttypes:[]\n
+\t\t\t};\n
+\n
+\t\t\tthis.getId = function() { return id; };\t\n
+\t\t\t\n
+\t\t\t// all components can generate events\n
+\t\t\t\n
+\t\t\tif (params.events) {\n
+\t\t\t\tfor (var i in params.events)\n
+\t\t\t\t\tself.bind(i, params.events[i]);\n
+\t\t\t}\n
+\n
+\t\t\t// all components get this clone function.\n
+\t\t\t// TODO issue 116 showed a problem with this - it seems \'a\' that is in\n
+\t\t\t// the clone function\'s scope is shared by all invocations of it, the classic\n
+\t\t\t// JS closure problem.  for now, jsPlumb does a version of this inline where \n
+\t\t\t// it used to call clone.  but it would be nice to find some time to look\n
+\t\t\t// further at this.\n
+\t\t\tthis.clone = function() {\n
+\t\t\t\tvar o = {};//new Object();\n
+\t\t\t\tthis.constructor.apply(o, a);\n
+\t\t\t\treturn o;\n
+\t\t\t}.bind(this);\t\t\t\t\n
+\t\t\t\t\t\t\n
+\t\t\t// user can supply a beforeDetach callback, which will be executed before a detach\n
+\t\t\t// is performed; returning false prevents the detach.\t\t\t\n
+\t\t\tthis.isDetachAllowed = function(connection) {\n
+\t\t\t\tvar r = true;\n
+\t\t\t\tif (this._jsPlumb.beforeDetach) {\n
+\t\t\t\t\ttry { \n
+\t\t\t\t\t\tr = this._jsPlumb.beforeDetach(connection); \n
+\t\t\t\t\t}\n
+\t\t\t\t\tcatch (e) { _ju.log("jsPlumb: beforeDetach callback failed", e); }\n
+\t\t\t\t}\n
+\t\t\t\treturn r;\n
+\t\t\t};\n
+\t\t\t\n
+\t\t\t// user can supply a beforeDrop callback, which will be executed before a dropped\n
+\t\t\t// connection is confirmed. user can return false to reject connection.\t\t\t\n
+\t\t\tthis.isDropAllowed = function(sourceId, targetId, scope, connection, dropEndpoint, source, target) {\n
+\t\t\t\t\tvar r = this._jsPlumb.instance.checkCondition("beforeDrop", { \n
+\t\t\t\t\t\tsourceId:sourceId, \n
+\t\t\t\t\t\ttargetId:targetId, \n
+\t\t\t\t\t\tscope:scope,\n
+\t\t\t\t\t\tconnection:connection,\n
+\t\t\t\t\t\tdropEndpoint:dropEndpoint,\n
+\t\t\t\t\t\tsource:source, target:target\n
+\t\t\t\t\t});\n
+\t\t\t\t\tif (this._jsPlumb.beforeDrop) {\n
+\t\t\t\t\t\ttry { \n
+\t\t\t\t\t\t\tr = this._jsPlumb.beforeDrop({ \n
+\t\t\t\t\t\t\t\tsourceId:sourceId, \n
+\t\t\t\t\t\t\t\ttargetId:targetId, \n
+\t\t\t\t\t\t\t\tscope:scope, \n
+\t\t\t\t\t\t\t\tconnection:connection,\n
+\t\t\t\t\t\t\t\tdropEndpoint:dropEndpoint,\n
+\t\t\t\t\t\t\t\tsource:source, target:target\n
+\t\t\t\t\t\t\t}); \n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\tcatch (e) { _ju.log("jsPlumb: beforeDrop callback failed", e); }\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn r;\n
+\t\t\t\t};\t\t\t\t\t\t\t\t\t\t\t\t\t\n
+\n
+\t\t    var boundListeners = [],\n
+\t\t    \tbindAListener = function(obj, type, fn) {\n
+\t\t\t    \tboundListeners.push([obj, type, fn]);\n
+\t\t\t    \tobj.bind(type, fn);\n
+\t\t\t    },\n
+\t\t    \tdomListeners = [],\n
+            \tbindOne = function(o, c, evt, override) {\n
+\t\t\t\t\tvar filteredEvent = eventFilters[evt] || evt,\n
+\t\t\t\t\t\tfn = function(ee) {\n
+\t\t\t\t\t\t\tif (override && override(ee) === false) return;\n
+\t\t\t\t\t\t\tc.fire(filteredEvent, c, ee);\n
+\t\t\t\t\t\t};\n
+\t\t\t\t\tdomListeners.push([o, evt, fn, c]);\n
+\t\t\t\t\tc._jsPlumb.instance.on(o, evt, fn);\n
+\t\t\t\t},\n
+\t\t\t\tunbindOne = function(o, evt, fn, c) {\n
+\t\t\t\t\tvar filteredEvent = eventFilters[evt] || evt;\n
+\t\t\t\t\tc._jsPlumb.instance.off(o, evt, fn);\n
+\t\t\t\t};\n
+\n
+            this.bindListeners = function(obj, _self, _hoverFunction) {\n
+                bindAListener(obj, "click", function(ep, e) { _self.fire("click", _self, e); });             \n
+             \tbindAListener(obj, "dblclick", function(ep, e) { _self.fire("dblclick", _self, e); });\n
+                bindAListener(obj, "contextmenu", function(ep, e) { _self.fire("contextmenu", _self, e); });\n
+                bindAListener(obj, "mouseleave", function(ep, e) {\n
+                    if (_self.isHover()) {\n
+                        _hoverFunction(false);\n
+                        _self.fire("mouseleave", _self, e);\n
+                    }\n
+                });\n
+                bindAListener(obj, "mouseenter", function(ep, e) {\n
+                    if (!_self.isHover()) {\n
+                        _hoverFunction(true);\n
+                        _self.fire("mouseenter", _self, e);\n
+                    }\n
+                });\n
+                bindAListener(obj, "mousedown", function(ep, e) { _self.fire("mousedown", _self, e); });\n
+                bindAListener(obj, "mouseup", function(ep, e) { _self.fire("mouseup", _self, e); });\n
+            };\n
+\n
+            this.unbindListeners = function() {\n
+            \tfor (var i = 0; i < boundListeners.length; i++) {\n
+            \t\tvar o = boundListeners[i];\n
+            \t\to[0].unbind(o[1], o[2]);\n
+            \t}            \t\n
+            \tboundListeners = null;\n
+            };            \n
+\t\t    \n
+\t\t    this.attachListeners = function(o, c, overrides) {\n
+\t\t\t\toverrides = overrides || {};\n
+\t\t\t\tfor (var i = 0, j = events.length; i < j; i++) {\n
+\t\t\t\t\tbindOne(o, c, events[i], overrides[events[i]]); \t\t\t\n
+\t\t\t\t}\n
+\t\t\t};\t\n
+\t\t\tthis.detachListeners = function() {\n
+\t\t\t\tfor (var i = 0; i < domListeners.length; i++) {\n
+\t\t\t\t\tunbindOne(domListeners[i][0], domListeners[i][1], domListeners[i][2], domListeners[i][3]);\n
+\t\t\t\t}\n
+\t\t\t\tdomListeners = null;\n
+\t\t\t};\t   \t\t    \n
+\t\t    \n
+\t\t    this.reattachListenersForElement = function(o) {\n
+\t\t\t    if (arguments.length > 1) {\n
+\t\t    \t\tfor (var i = 0, j = events.length; i < j; i++)\n
+\t\t    \t\t\tunbindOne(o, events[i]);\n
+\t\t\t    \tfor (i = 1, j = arguments.length; i < j; i++)\n
+\t\t    \t\t\tthis.attachListeners(o, arguments[i]);\n
+\t\t    \t}\n
+\t\t    };\t\t    \t    \t\t\t                      \n
+\t\t};\n
+\n
+\t\tjsPlumbUtil.extend(jsPlumbUIComponent, jsPlumbUtil.EventGenerator, {\n
+\t\t\t\n
+\t\t\tgetParameter : function(name) { \n
+\t\t\t\treturn this._jsPlumb.parameters[name]; \n
+\t\t\t},\n
+\t\t\t\n
+\t\t\tsetParameter : function(name, value) { \n
+\t\t\t\tthis._jsPlumb.parameters[name] = value; \n
+\t\t\t},\n
+\t\t\t\n
+\t\t\tgetParameters : function() { \n
+\t\t\t\treturn this._jsPlumb.parameters; \n
+\t\t\t},\t\t\t\n
+\t\t\t\n
+\t\t\tsetParameters : function(p) { \n
+\t\t\t\tthis._jsPlumb.parameters = p; \n
+\t\t\t},\t\t\t\n
+\t\t\t\n
+\t\t\taddClass : function(clazz) {\n
+\t\t\t    jsPlumbAdapter.addClass(this.canvas, clazz);\n
+\t\t\t},\n
+\t\t\t\t\t\t\n
+\t\t\tremoveClass : function(clazz) {\n
+\t\t\t    jsPlumbAdapter.removeClass(this.canvas, clazz);\n
+\t\t\t},\n
+\t\t\t\n
+\t\t\tsetType : function(typeId, params, doNotRepaint) {\t\t\t\t\n
+\t\t\t\tthis._jsPlumb.types = _splitType(typeId) || [];\n
+\t\t\t\t_applyTypes(this, params, doNotRepaint);\t\t\t\t\t\t\t\t\t\n
+\t\t\t},\n
+\t\t\t\n
+\t\t\tgetType : function() {\n
+\t\t\t\treturn this._jsPlumb.types;\n
+\t\t\t},\n
+\t\t\t\n
+\t\t\treapplyTypes : function(params, doNotRepaint) {\n
+\t\t\t\t_applyTypes(this, params, doNotRepaint);\n
+\t\t\t},\n
+\t\t\t\n
+\t\t\thasType : function(typeId) {\n
+\t\t\t\treturn jsPlumbUtil.indexOf(this._jsPlumb.types, typeId) != -1;\n
+\t\t\t},\n
+\t\t\t\n
+\t\t\taddType : function(typeId, params, doNotRepaint) {\n
+\t\t\t\tvar t = _splitType(typeId), _cont = false;\n
+\t\t\t\tif (t != null) {\n
+\t\t\t\t\tfor (var i = 0, j = t.length; i < j; i++) {\n
+\t\t\t\t\t\tif (!this.hasType(t[i])) {\n
+\t\t\t\t\t\t\tthis._jsPlumb.types.push(t[i]);\n
+\t\t\t\t\t\t\t_cont = true;\t\t\t\t\t\t\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif (_cont) _applyTypes(this, params, doNotRepaint);\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\t\n
+\t\t\tremoveType : function(typeId, doNotRepaint) {\n
+\t\t\t\tvar t = _splitType(typeId), _cont = false, _one = function(tt) {\n
+\t\t\t\t\t\tvar idx = _ju.indexOf(this._jsPlumb.types, tt);\n
+\t\t\t\t\t\tif (idx != -1) {\n
+\t\t\t\t\t\t\tthis._jsPlumb.types.splice(idx, 1);\n
+\t\t\t\t\t\t\treturn true;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t}.bind(this);\n
+\t\t\t\t\n
+\t\t\t\tif (t != null) {\n
+\t\t\t\t\tfor (var i = 0,j = t.length; i < j; i++) {\n
+\t\t\t\t\t\t_cont = _one(t[i]) || _cont;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif (_cont) _applyTypes(this, null, doNotRepaint);\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\t\n
+\t\t\ttoggleType : function(typeId, params, doNotRepaint) {\n
+\t\t\t\tvar t = _splitType(typeId);\n
+\t\t\t\tif (t != null) {\n
+\t\t\t\t\tfor (var i = 0, j = t.length; i < j; i++) {\n
+\t\t\t\t\t\tvar idx = jsPlumbUtil.indexOf(this._jsPlumb.types, t[i]);\n
+\t\t\t\t\t\tif (idx != -1)\n
+\t\t\t\t\t\t\tthis._jsPlumb.types.splice(idx, 1);\n
+\t\t\t\t\t\telse\n
+\t\t\t\t\t\t\tthis._jsPlumb.types.push(t[i]);\n
+\t\t\t\t\t}\n
+\t\t\t\t\t\t\n
+\t\t\t\t\t_applyTypes(this, params, doNotRepaint);\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tapplyType : function(t, doNotRepaint) {\n
+\t\t\t\tthis.setPaintStyle(t.paintStyle, doNotRepaint);\t\t\t\t\n
+\t\t\t\tthis.setHoverPaintStyle(t.hoverPaintStyle, doNotRepaint);\n
+\t\t\t\tif (t.parameters){\n
+\t\t\t\t\tfor (var i in t.parameters)\n
+\t\t\t\t\t\tthis.setParameter(i, t.parameters[i]);\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tsetPaintStyle : function(style, doNotRepaint) {\n
+//\t\t    \tthis._jsPlumb.paintStyle = jsPlumb.extend({}, style);\n
+// TODO figure out if we want components to clone paintStyle so as not to share it.\n
+\t\t\t\tthis._jsPlumb.paintStyle = style;\n
+\t\t    \tthis._jsPlumb.paintStyleInUse = this._jsPlumb.paintStyle;\n
+\t\t    \t_updateHoverStyle(this);\n
+\t\t    \tif (!doNotRepaint) this.repaint();\n
+\t\t    },\n
+\t\t    getPaintStyle : function() {\n
+\t\t    \treturn this._jsPlumb.paintStyle;\n
+\t\t    },\n
+\t\t    setHoverPaintStyle : function(style, doNotRepaint) {\t\t    \t\n
+\t\t    \t//this._jsPlumb.hoverPaintStyle = jsPlumb.extend({}, style);\n
+// TODO figure out if we want components to clone paintStyle so as not to share it.\t\t    \t\n
+\t\t    \tthis._jsPlumb.hoverPaintStyle = style;\n
+\t\t    \t_updateHoverStyle(this);\n
+\t\t    \tif (!doNotRepaint) this.repaint();\n
+\t\t    },\n
+\t\t    getHoverPaintStyle : function() {\n
+\t\t    \treturn this._jsPlumb.hoverPaintStyle;\n
+\t\t    },\n
+\t\t\tcleanup:function() {\n
+\t\t\t\tthis.unbindListeners();\n
+\t\t\t\tthis.detachListeners();\n
+\t\t\t},\n
+\t\t\tdestroy:function() {\n
+\t\t\t\tthis.cleanupListeners();\n
+\t\t\t\tthis.clone = null;\n
+\t\t\t\tthis._jsPlumb = null;\n
+\t\t\t},\n
+\t\t\t\n
+\t\t\tisHover : function() { return this._jsPlumb.hover; },\n
+\t\t\t\n
+\t\t\tsetHover : function(hover, ignoreAttachedElements, timestamp) {\n
+\t\t\t\t// while dragging, we ignore these events.  this keeps the UI from flashing and\n
+\t\t    \t// swishing and whatevering.\n
+\t\t\t\tif (this._jsPlumb && !this._jsPlumb.instance.currentlyDragging && !this._jsPlumb.instance.isHoverSuspended()) {\n
+\t\t    \n
+\t\t\t    \tthis._jsPlumb.hover = hover;\n
+                        \n
+                    if (this.canvas != null) {\n
+                        if (this._jsPlumb.instance.hoverClass != null) {\n
+                        \tvar method = hover ? "addClass" : "removeClass";\n
+\t\t\t\t\t\t\tthis._jsPlumb.instance[method](this.canvas, this._jsPlumb.instance.hoverClass);\n
+                        }\n
+                        if (this._jsPlumb.hoverClass != null) {\n
+\t\t\t\t\t\t\tthis._jsPlumb.instance[method](this.canvas, this._jsPlumb.hoverClass);\n
+                        }\n
+                    }\n
+\t\t   \t\t \tif (this._jsPlumb.hoverPaintStyle != null) {\n
+\t\t\t\t\t\tthis._jsPlumb.paintStyleInUse = hover ? this._jsPlumb.hoverPaintStyle : this._jsPlumb.paintStyle;\n
+\t\t\t\t\t\tif (!this._jsPlumb.instance.isSuspendDrawing()) {\n
+\t\t\t\t\t\t\ttimestamp = timestamp || _timestamp();\n
+\t\t\t\t\t\t\tthis.repaint({timestamp:timestamp, recalc:false});\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\t// get the list of other affected elements, if supported by this component.\n
+\t\t\t\t\t// for a connection, its the endpoints.  for an endpoint, its the connections! surprise.\n
+\t\t\t\t\tif (this.getAttachedElements && !ignoreAttachedElements)\n
+\t\t\t\t\t\t_updateAttachedElements(this, hover, _timestamp(), this);\n
+\t\t\t\t}\n
+\t\t    }\n
+\t\t});\n
+\n
+// ------------------------------ END jsPlumbUIComponent --------------------------------------------\n
+\n
+// ------------------------------ BEGIN OverlayCapablejsPlumbUIComponent --------------------------------------------\n
+\n
+\t\tvar _internalLabelOverlayId = "__label",\n
+\t\t\t// helper to get the index of some overlay\n
+\t\t\t_getOverlayIndex = function(component, id) {\n
+\t\t\t\tvar idx = -1;\n
+\t\t\t\tfor (var i = 0, j = component._jsPlumb.overlays.length; i < j; i++) {\n
+\t\t\t\t\tif (id === component._jsPlumb.overlays[i].id) {\n
+\t\t\t\t\t\tidx = i;\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\treturn idx;\n
+\t\t\t},\n
+\t\t\t// this is a shortcut helper method to let people add a label as\n
+\t\t\t// overlay.\n
+\t\t\t_makeLabelOverlay = function(component, params) {\n
+\n
+\t\t\t\tvar _params = {\n
+\t\t\t\t\tcssClass:params.cssClass,\n
+\t\t\t\t\tlabelStyle : component.labelStyle,\n
+\t\t\t\t\tid:_internalLabelOverlayId,\n
+\t\t\t\t\tcomponent:component,\n
+\t\t\t\t\t_jsPlumb:component._jsPlumb.instance  // TODO not necessary, since the instance can be accessed through the component.\n
+\t\t\t\t},\n
+\t\t\t\tmergedParams = jsPlumb.extend(_params, params);\n
+\n
+\t\t\t\treturn new jsPlumb.Overlays[component._jsPlumb.instance.getRenderMode()].Label( mergedParams );\n
+\t\t\t},\n
+\t\t\t_processOverlay = function(component, o) {\n
+\t\t\t\tvar _newOverlay = null;\n
+\t\t\t\tif (_ju.isArray(o)) {\t// this is for the shorthand ["Arrow", { width:50 }] syntax\n
+\t\t\t\t\t// there\'s also a three arg version:\n
+\t\t\t\t\t// ["Arrow", { width:50 }, {location:0.7}] \n
+\t\t\t\t\t// which merges the 3rd arg into the 2nd.\n
+\t\t\t\t\tvar type = o[0],\n
+\t\t\t\t\t\t// make a copy of the object so as not to mess up anyone else\'s reference...\n
+\t\t\t\t\t\tp = jsPlumb.extend({component:component, _jsPlumb:component._jsPlumb.instance}, o[1]);\n
+\t\t\t\t\tif (o.length == 3) jsPlumb.extend(p, o[2]);\n
+\t\t\t\t\t_newOverlay = new jsPlumb.Overlays[component._jsPlumb.instance.getRenderMode()][type](p);\t\t\t\t\t\n
+\t\t\t\t} else if (o.constructor == String) {\n
+\t\t\t\t\t_newOverlay = new jsPlumb.Overlays[component._jsPlumb.instance.getRenderMode()][o]({component:component, _jsPlumb:component._jsPlumb.instance});\n
+\t\t\t\t} else {\n
+\t\t\t\t\t_newOverlay = o;\n
+\t\t\t\t}\t\t\t\t\t\t\t\t\t\t\n
+\t\t\t\t\t\n
+\t\t\t\tcomponent._jsPlumb.overlays.push(_newOverlay);\n
+\t\t\t},\n
+\t\t\t_calculateOverlaysToAdd = function(component, params) {\n
+\t\t\t\tvar defaultKeys = component.defaultOverlayKeys || [], o = params.overlays,\n
+\t\t\t\t\tcheckKey = function(k) {\n
+\t\t\t\t\t\treturn component._jsPlumb.instance.Defaults[k] || jsPlumb.Defaults[k] || [];\n
+\t\t\t\t\t};\n
+\t\t\t\t\n
+\t\t\t\tif (!o) o = [];\n
+\n
+\t\t\t\tfor (var i = 0, j = defaultKeys.length; i < j; i++)\n
+\t\t\t\t\to.unshift.apply(o, checkKey(defaultKeys[i]));\n
+\t\t\t\t\n
+\t\t\t\treturn o;\n
+\t\t\t},\t\t\n
+\t\t\tOverlayCapableJsPlumbUIComponent = window.OverlayCapableJsPlumbUIComponent = function(params) {\n
+\n
+\t\t\t\tjsPlumbUIComponent.apply(this, arguments);\n
+\t\t\t\tthis._jsPlumb.overlays = [];\t\t\t\n
+\n
+\t\t\t\tvar _overlays = _calculateOverlaysToAdd(this, params);\n
+\t\t\t\tif (_overlays) {\n
+\t\t\t\t\tfor (var i = 0, j = _overlays.length; i < j; i++) {\n
+\t\t\t\t\t\t_processOverlay(this, _overlays[i]);\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\t\n
+\t\t\t\tif (params.label) {\n
+\t\t\t\t\tvar loc = params.labelLocation || this.defaultLabelLocation || 0.5,\n
+\t\t\t\t\t\tlabelStyle = params.labelStyle || this._jsPlumb.instance.Defaults.LabelStyle;\n
+\n
+\t\t\t\t\tthis._jsPlumb.overlays.push(_makeLabelOverlay(this, {\n
+\t\t\t\t\t\tlabel:params.label,\n
+\t\t\t\t\t\tlocation:loc,\n
+\t\t\t\t\t\tlabelStyle:labelStyle\n
+\t\t\t\t\t}));\n
+\t\t\t\t}\t\t\t                                  \n
+\t\t\t};\n
+\n
+\t\tjsPlumbUtil.extend(OverlayCapableJsPlumbUIComponent, jsPlumbUIComponent, {\n
+\t\t\tapplyType : function(t, doNotRepaint) {\t\t\t\n
+\t\t\t\tthis.removeAllOverlays(doNotRepaint);\n
+\t\t\t\tif (t.overlays) {\n
+\t\t\t\t\tfor (var i = 0, j = t.overlays.length; i < j; i++)\n
+\t\t\t\t\t\tthis.addOverlay(t.overlays[i], true);\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tsetHover : function(hover, ignoreAttachedElements, timestamp) {            \n
+\t\t\t\tif (this._jsPlumb && !this._jsPlumb.instance.isConnectionBeingDragged()) {\n
+\t                for (var i = 0, j = this._jsPlumb.overlays.length; i < j; i++) {\n
+\t\t\t\t\t\tthis._jsPlumb.overlays[i][hover ? "addClass":"removeClass"](this._jsPlumb.instance.hoverClass);\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+            },\n
+            addOverlay : function(overlay, doNotRepaint) { \n
+\t\t\t\t_processOverlay(this, overlay); \n
+\t\t\t\tif (!doNotRepaint) this.repaint();\n
+\t\t\t},\n
+\t\t\tgetOverlay : function(id) {\n
+\t\t\t\tvar idx = _getOverlayIndex(this, id);\n
+\t\t\t\treturn idx >= 0 ? this._jsPlumb.overlays[idx] : null;\n
+\t\t\t},\t\t\t\n
+\t\t\tgetOverlays : function() {\n
+\t\t\t\treturn this._jsPlumb.overlays;\n
+\t\t\t},\t\t\t\n
+\t\t\thideOverlay : function(id) {\n
+\t\t\t\tvar o = this.getOverlay(id);\n
+\t\t\t\tif (o) o.hide();\n
+\t\t\t},\n
+\t\t\thideOverlays : function() {\n
+\t\t\t\tfor (var i = 0, j = this._jsPlumb.overlays.length; i < j; i++)\n
+\t\t\t\t\tthis._jsPlumb.overlays[i].hide();\n
+\t\t\t},\n
+\t\t\tshowOverlay : function(id) {\n
+\t\t\t\tvar o = this.getOverlay(id);\n
+\t\t\t\tif (o) o.show();\n
+\t\t\t},\n
+\t\t\tshowOverlays : function() {\n
+\t\t\t\tfor (var i = 0, j = this._jsPlumb.overlays.length; i < j; i++)\n
+\t\t\t\t\tthis._jsPlumb.overlays[i].show();\n
+\t\t\t},\n
+\t\t\tremoveAllOverlays : function(doNotRepaint) {\n
+\t\t\t\tfor (var i = 0, j = this._jsPlumb.overlays.length; i < j; i++) {\n
+\t\t\t\t\tif (this._jsPlumb.overlays[i].cleanup) this._jsPlumb.overlays[i].cleanup();\n
+\t\t\t\t}\n
+\n
+\t\t\t\tthis._jsPlumb.overlays.splice(0, this._jsPlumb.overlays.length);\n
+\t\t\t\tthis._jsPlumb.overlayPositions = null;\n
+\t\t\t\tif (!doNotRepaint)\n
+\t\t\t\t\tthis.repaint();\n
+\t\t\t},\n
+\t\t\tremoveOverlay : function(overlayId) {\n
+\t\t\t\tvar idx = _getOverlayIndex(this, overlayId);\n
+\t\t\t\tif (idx != -1) {\n
+\t\t\t\t\tvar o = this._jsPlumb.overlays[idx];\n
+\t\t\t\t\tif (o.cleanup) o.cleanup();\n
+\t\t\t\t\tthis._jsPlumb.overlays.splice(idx, 1);\n
+\t\t\t\t\tif (this._jsPlumb.overlayPositions)  \n
+\t\t\t\t\t\tdelete this._jsPlumb.overlayPositions[overlayId];\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tremoveOverlays : function() {\n
+\t\t\t\tfor (var i = 0, j = arguments.length; i < j; i++)\n
+\t\t\t\t\tthis.removeOverlay(arguments[i]);\n
+\t\t\t},\n
+\t\t\tmoveParent:function(newParent) {\n
+\t\t\t\tif (this.bgCanvas) {\n
+\t\t\t\t    this.bgCanvas.parentNode.removeChild(this.bgCanvas);\n
+\t\t\t\t    newParent.appendChild(this.bgCanvas);\n
+\t\t\t\t}\n
+\t\t\t\t\n
+\t\t\t\tthis.canvas.parentNode.removeChild(this.canvas);\n
+\t\t\t\tnewParent.appendChild(this.canvas);\n
+\n
+\t\t\t\tfor (var i = 0; i < this._jsPlumb.overlays.length; i++) {\n
+\t\t\t\t    if (this._jsPlumb.overlays[i].isAppendedAtTopLevel) {\n
+\t\t\t\t        this._jsPlumb.overlays[i].canvas.parentNode.removeChild(this._jsPlumb.overlays[i].canvas);\n
+\t\t\t\t        newParent.appendChild(this._jsPlumb.overlays[i].canvas);  \n
+\t\t\t\t    }\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tgetLabel : function() {\n
+\t\t\t\tvar lo = this.getOverlay(_internalLabelOverlayId);\n
+\t\t\t\treturn lo != null ? lo.getLabel() : null;\n
+\t\t\t},\t\t\n
+\t\t\tgetLabelOverlay : function() {\n
+\t\t\t\treturn this.getOverlay(_internalLabelOverlayId);\n
+\t\t\t},\n
+\t\t\tsetLabel : function(l) {\n
+\t\t\t\tvar lo = this.getOverlay(_internalLabelOverlayId);\n
+\t\t\t\tif (!lo) {\n
+\t\t\t\t\tvar params = l.constructor == String || l.constructor == Function ? { label:l } : l;\n
+\t\t\t\t\tlo = _makeLabelOverlay(this, params);\t\n
+\t\t\t\t\tthis._jsPlumb.overlays.push(lo);\n
+\t\t\t\t}\n
+\t\t\t\telse {\n
+\t\t\t\t\tif (l.constructor == String || l.constructor == Function) lo.setLabel(l);\n
+\t\t\t\t\telse {\n
+\t\t\t\t\t\tif (l.label) lo.setLabel(l.label);\n
+\t\t\t\t\t\tif (l.location) lo.setLocation(l.location);\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\t\n
+\t\t\t\tif (!this._jsPlumb.instance.isSuspendDrawing()) \n
+\t\t\t\t\tthis.repaint();\n
+\t\t\t},\n
+\t\t\tcleanup:function() {\n
+\t\t\t\tfor (var i = 0; i < this._jsPlumb.overlays.length; i++) {\n
+\t\t\t\t\tthis._jsPlumb.overlays[i].cleanup();\n
+\t\t\t\t\tthis._jsPlumb.overlays[i].destroy();\n
+\t\t\t\t}\n
+\t\t\t\tthis._jsPlumb.overlays.splice(0);\n
+\t\t\t\tthis._jsPlumb.overlayPositions = null;\n
+\t\t\t},\n
+\t\t\tsetVisible:function(v) {\n
+\t\t\t\tthis[v ? "showOverlays" : "hideOverlays"]();\n
+\t\t\t},\n
+\t\t\tsetAbsoluteOverlayPosition:function(overlay, xy) {\n
+\t\t\t\tthis._jsPlumb.overlayPositions = this._jsPlumb.overlayPositions || {};\n
+\t\t\t\tthis._jsPlumb.overlayPositions[overlay.id] = xy;\n
+\t\t\t},\n
+\t\t\tgetAbsoluteOverlayPosition:function(overlay) {\n
+\t\t\t\treturn this._jsPlumb.overlayPositions ? this._jsPlumb.overlayPositions[overlay.id] : null;\n
+\t\t\t}\n
+\t\t});\t\t\n
+\n
+// ------------------------------ END OverlayCapablejsPlumbUIComponent --------------------------------------------\n
+\t\t\n
+\t\tvar _jsPlumbInstanceIndex = 0,\n
+\t\t\tgetInstanceIndex = function() {\n
+\t\t\t\tvar i = _jsPlumbInstanceIndex + 1;\n
+\t\t\t\t_jsPlumbInstanceIndex++;\n
+\t\t\t\treturn i;\n
+\t\t\t};\n
+\n
+\t\tvar jsPlumbInstance = window.jsPlumbInstance = function(_defaults) {\n
+\t\t\t\t\n
+\t\t\tthis.Defaults = {\n
+\t\t\t\tAnchor : "BottomCenter",\n
+\t\t\t\tAnchors : [ null, null ],\n
+\t            ConnectionsDetachable : true,\n
+\t            ConnectionOverlays : [ ],\n
+\t            Connector : "Bezier",\n
+\t\t\t\tContainer : null,\n
+\t\t\t\tDoNotThrowErrors:false,\n
+\t\t\t\tDragOptions : { },\n
+\t\t\t\tDropOptions : { },\n
+\t\t\t\tEndpoint : "Dot",\n
+\t\t\t\tEndpointOverlays : [ ],\n
+\t\t\t\tEndpoints : [ null, null ],\n
+\t\t\t\tEndpointStyle : { fillStyle : "#456" },\n
+\t\t\t\tEndpointStyles : [ null, null ],\n
+\t\t\t\tEndpointHoverStyle : null,\n
+\t\t\t\tEndpointHoverStyles : [ null, null ],\n
+\t\t\t\tHoverPaintStyle : null,\n
+\t\t\t\tLabelStyle : { color : "black" },\n
+\t\t\t\tLogEnabled : false,\n
+\t\t\t\tOverlays : [ ],\n
+\t\t\t\tMaxConnections : 1, \n
+\t\t\t\tPaintStyle : { lineWidth : 8, strokeStyle : "#456" },            \n
+\t\t\t\tReattachConnections:false,\n
+\t\t\t\tRenderMode : "svg",\n
+\t\t\t\tScope : "jsPlumb_DefaultScope"\n
+\t\t\t};\n
+\t\t\tif (_defaults) jsPlumb.extend(this.Defaults, _defaults);\n
+\t\t\n
+\t\t\tthis.logEnabled = this.Defaults.LogEnabled;\n
+\t\t\tthis._connectionTypes = {};\n
+\t\t\tthis._endpointTypes = {};\n
+\n
+\t\t\tjsPlumbUtil.EventGenerator.apply(this);\n
+\n
+\t\t\tvar _currentInstance = this,\n
+\t\t\t\t_instanceIndex = getInstanceIndex(),\n
+\t\t\t\t_bb = _currentInstance.bind,\n
+\t\t\t\t_initialDefaults = {},\n
+\t            _zoom = 1,\n
+\t            _info = function(el) {\n
+\t            \tvar _el = _currentInstance.getDOMElement(el);\t\n
+\t            \treturn { el:_el, id:(jsPlumbUtil.isString(el) && _el == null) ? el : _getId(_el) };\n
+\t            };\n
+            \n
+\t        this.getInstanceIndex = function() { return _instanceIndex; };\n
+\n
+        \tthis.setZoom = function(z, repaintEverything) {\n
+        \t\tif (!jsPlumbUtil.oldIE) {\n
+\t            \t_zoom = z;\n
+\t\t\t\t\t_currentInstance.fire("zoom", _zoom);\n
+\t            \tif (repaintEverything) _currentInstance.repaintEverything();\n
+\t            }\n
+\t            return !jsPlumbUtil.oldIE;\n
+\n
+        \t};\n
+        \tthis.getZoom = function() { return _zoom; };\n
+                        \n
+\t\t\tfor (var i in this.Defaults)\n
+\t\t\t\t_initialDefaults[i] = this.Defaults[i];\n
+\n
+\t\t\tvar _container;\n
+\t\t\tthis.setContainer = function(c) {\n
+\t\t\t\tc = this.getDOMElement(c);\n
+\t\t\t\tthis.select().each(function(conn) {\n
+\t\t\t\t\tconn.moveParent(c);\n
+\t\t\t\t});\n
+\t\t\t\tthis.selectEndpoints().each(function(ep) {\n
+\t\t\t\t\tep.moveParent(c);\n
+\t\t\t\t});\n
+\t\t\t\t_container = c;\n
+\t\t\t};\n
+\t\t\tthis.getContainer = function() {\n
+\t\t\t\treturn _container;\n
+\t\t\t};\n
+\t\t\t\n
+\t\t\tthis.bind = function(event, fn) {\t\t\n
+\t\t\t\tif ("ready" === event && initialized) fn();\n
+\t\t\t\telse _bb.apply(_currentInstance,[event, fn]);\n
+\t\t\t};\n
+\n
+\t\t\t_currentInstance.importDefaults = function(d) {\n
+\t\t\t\tfor (var i in d) {\n
+\t\t\t\t\t_currentInstance.Defaults[i] = d[i];\n
+\t\t\t\t}\n
+\t\t\t\tif (d.Container)\n
+\t\t\t\t\tthis.setContainer(d.Container);\n
+\n
+\t\t\t\treturn _currentInstance;\n
+\t\t\t};\t\t\n
+\t\t\t\n
+\t\t\t_currentInstance.restoreDefaults = function() {\n
+\t\t\t\t_currentInstance.Defaults = jsPlumb.extend({}, _initialDefaults);\n
+\t\t\t\treturn _currentInstance;\n
+\t\t\t};\n
+\t\t\n
+\t\t    var log = null,\n
+\t\t        resizeTimer = null,\n
+\t\t        initialized = false,\n
+\t\t        // TODO remove from window scope       \n
+\t\t        connections = [],\n
+\t\t        // map of element id -> endpoint lists. an element can have an arbitrary\n
+\t\t        // number of endpoints on it, and not all of them have to be connected\n
+\t\t        // to anything.         \n
+\t\t        endpointsByElement = {},\n
+\t\t        endpointsByUUID = {},\n
+\t\t        offsets = {},\n
+\t\t        offsetTimestamps = {},\n
+\t\t        floatingConnections = {},\n
+\t\t        draggableStates = {},\t\t\n
+\t\t        connectionBeingDragged = false,\n
+\t\t        sizes = [],\n
+\t\t        _suspendDrawing = false,\n
+\t\t        _suspendedAt = null,\n
+\t\t        DEFAULT_SCOPE = this.Defaults.Scope,\n
+\t\t        renderMode = null,  // will be set in init()\t\t\n
+\t\t        _curIdStamp = 1,\n
+\t\t        _idstamp = function() { return "" + _curIdStamp++; },\t\t\t\t\t\t\t\n
+\t\t\n
+\t\t\t\t//\n
+\t\t\t\t// appends an element to some other element, which is calculated as follows:\n
+\t\t\t\t// \n
+\t\t\t\t// 1. if Container exists, use that element.\n
+\t\t\t\t// 2. if the \'parent\' parameter exists, use that.\n
+\t\t\t\t// 3. otherwise just use the root element (for DOM usage, the document body).\n
+\t\t\t\t// \n
+\t\t\t\t//\n
+\t\t\t\t_appendElement = function(el, parent) {\n
+\t\t\t\t\tif (_container)\n
+\t\t\t\t\t\t_container.appendChild(el);\n
+\t\t\t\t\telse if (!parent)\n
+\t\t\t\t\t\t_currentInstance.appendToRoot(el);\n
+\t\t\t\t\telse\n
+\t\t\t\t\t\tjsPlumb.getDOMElement(parent).appendChild(el);\n
+\t\t\t\t},\t\t\n
+\t\t\t\t\n
+\t\t\t\t//\n
+\t\t\t\t// YUI, for some reason, put the result of a Y.all call into an object that contains\n
+\t\t\t\t// a \'_nodes\' array, instead of handing back an array-like object like the other\n
+\t\t\t\t// libraries do.\n
+\t\t\t\t//\n
+\t\t\t\t_convertYUICollection = function(c) {\n
+\t\t\t\t\treturn c._nodes ? c._nodes : c;\n
+\t\t\t\t},                \n
+\n
+\t\t\t//\n
+\t\t\t// Draws an endpoint and its connections. this is the main entry point into drawing connections as well\n
+\t\t\t// as endpoints, since jsPlumb is endpoint-centric under the hood.\n
+\t\t\t// \n
+\t\t\t// @param element element to draw (of type library specific element object)\n
+\t\t\t// @param ui UI object from current library\'s event system. optional.\n
+\t\t\t// @param timestamp timestamp for this paint cycle. used to speed things up a little by cutting down the amount of offset calculations we do.\n
+\t\t\t// @param clearEdits defaults to false; indicates that mouse edits for connectors should be cleared\n
+\t\t\t///\n
+\t\t\t_draw = function(element, ui, timestamp, clearEdits) {\n
+\n
+\t\t\t\t// TODO is it correct to filter by headless at this top level? how would a headless adapter ever repaint?\n
+\t            if (!jsPlumbAdapter.headless && !_suspendDrawing) {\n
+\t\t\t\t    var id = _getId(element),\n
+\t\t\t\t    \trepaintEls = _currentInstance.dragManager.getElementsForDraggable(id);\t\t\t    \n
+\n
+\t\t\t\t    if (timestamp == null) timestamp = _timestamp();\n
+\n
+\t\t\t\t    // update the offset of everything _before_ we try to draw anything.\n
+\t\t\t\t    var o = _updateOffset( { elId : id, offset : ui, recalc : false, timestamp : timestamp });\n
+\n
+\t\t\t        if (repaintEls) {\n
+\t\t\t    \t    for (var i in repaintEls) {\n
+\t\t\t    \t    \t// TODO this seems to cause a lag, but we provide the offset, so in theory it \n
+\t\t\t    \t    \t// should not.  is the timestamp failing?\n
+\t\t\t\t    \t\t_updateOffset( { \n
+\t\t\t\t    \t\t\telId : repaintEls[i].id, \n
+\t\t\t\t    \t\t\toffset : {\n
+\t\t\t\t\t\t\t\t\tleft:o.o.left + repaintEls[i].offset.left,\n
+\t\t\t\t\t    \t\t\ttop:o.o.top + repaintEls[i].offset.top\n
+\t\t\t\t\t    \t\t}, \n
+\t\t\t\t    \t\t\trecalc : false, \n
+\t\t\t\t    \t\t\ttimestamp : timestamp \n
+\t\t\t\t    \t\t});\n
+\t\t\t\t    \t}\n
+\t\t\t\t    }\t\n
+\t\t\t\t    \t\t          \n
+\n
+\t\t\t\t    _currentInstance.anchorManager.redraw(id, ui, timestamp, null, clearEdits);\n
+\t\t\t\t    \n
+\t\t\t\t    if (repaintEls) {\n
+\t\t\t\t\t    for (var j in repaintEls) {\n
+\t\t\t\t\t\t\t_currentInstance.anchorManager.redraw(repaintEls[j].id, ui, timestamp, repaintEls[j].offset, clearEdits, true);\t\t\t    \t\n
+\t\t\t\t\t    }\n
+\t\t\t\t\t}\t\t\n
+\t            }\n
+\t\t\t},\n
+\n
+\t\t\t//\n
+\t\t\t// executes the given function against the given element if the first\n
+\t\t\t// argument is an object, or the list of elements, if the first argument\n
+\t\t\t// is a list. the function passed in takes (element, elementId) as\n
+\t\t\t// arguments.\n
+\t\t\t//\n
+\t\t\t_elementProxy = function(element, fn) {\n
+\t\t\t\tvar retVal = null, el, id, del;\n
+\t\t\t\tif (_ju.isArray(element)) {\n
+\t\t\t\t\tretVal = [];\n
+\t\t\t\t\tfor ( var i = 0, j = element.length; i < j; i++) {\n
+\t\t\t\t\t\tel = _currentInstance.getElementObject(element[i]);\n
+\t\t\t\t\t\tdel = _currentInstance.getDOMElement(el);\n
+\t\t\t\t\t\tid = _currentInstance.getAttribute(del, "id");\n
+\t\t\t\t\t\t//retVal.push(fn(el, id)); // append return values to what we will return\n
+\t\t\t\t\t\tretVal.push(fn.apply(_currentInstance, [del, id])); // append return values to what we will return\n
+\t\t\t\t\t}\n
+\t\t\t\t} else {\n
+\t\t\t\t\tel = _currentInstance.getDOMElement(element);\n
+\t\t\t\t\tid = _currentInstance.getId(el);\n
+\t\t\t\t\tretVal = fn.apply(_currentInstance, [el, id]);\n
+\t\t\t\t}\n
+\t\t\t\treturn retVal;\n
+\t\t\t},\t\t\t\t\n
+\n
+\t\t\t//\n
+\t\t\t// gets an Endpoint by uuid.\n
+\t\t\t//\n
+\t\t\t_getEndpoint = function(uuid) { return endpointsByUUID[uuid]; },\n
+\n
+\t\t/**\n
+\t\t * inits a draggable if it\'s not already initialised.\n
+\t\t * TODO: somehow abstract this to the adapter, because the concept of "draggable" has no\n
+\t\t * place on the server.\n
+\t\t */\n
+\t\t_initDraggableIfNecessary = function(element, isDraggable, dragOptions) {\n
+\t\t\t// TODO move to DragManager?\n
+\t\t\tif (!jsPlumbAdapter.headless) {\n
+\t\t\t\tvar _draggable = isDraggable == null ? false : isDraggable;\n
+\t\t\t\tif (_draggable) {\n
+\t\t\t\t\tif (jsPlumb.isDragSupported(element, _currentInstance) && !jsPlumb.isAlreadyDraggable(element, _currentInstance)) {\n
+\t\t\t\t\t\tvar options = dragOptions || _currentInstance.Defaults.DragOptions;\n
+\t\t\t\t\t\toptions = jsPlumb.extend( {}, options); // make a copy.\n
+\t\t\t\t\t\tvar dragEvent = jsPlumb.dragEvents.drag,\n
+\t\t\t\t\t\t\tstopEvent = jsPlumb.dragEvents.stop,\n
+\t\t\t\t\t\t\tstartEvent = jsPlumb.dragEvents.start;\n
+\t\n
+\t\t\t\t\t\toptions[startEvent] = _ju.wrap(options[startEvent], function() {\n
+\t\t\t\t\t\t\t_currentInstance.setHoverSuspended(true);\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t\t_currentInstance.select({source:element}).addClass(_currentInstance.elementDraggingClass + " " + _currentInstance.sourceElementDraggingClass, true);\n
+\t\t\t\t\t\t\t_currentInstance.select({target:element}).addClass(_currentInstance.elementDraggingClass + " " + _currentInstance.targetElementDraggingClass, true);\n
+\t\t\t\t\t\t\t_currentInstance.setConnectionBeingDragged(true);\n
+\t\t\t\t\t\t\tif (options.canDrag) return dragOptions.canDrag();\n
+\t\t\t\t\t\t}, false);\n
+\t\n
+\t\t\t\t\t\toptions[dragEvent] = _ju.wrap(options[dragEvent], function() {\n
+\t\t\t\t\t\t\t// TODO: here we could actually use getDragObject, and then compute it ourselves,\n
+\t\t\t\t\t\t\t// since every adapter does the same thing. but i\'m not sure why YUI\'s getDragObject\n
+\t\t\t\t\t\t\t// differs from getUIPosition so much\n
+\t\t\t\t\t\t\tvar ui = _currentInstance.getUIPosition(arguments, _currentInstance.getZoom());\n
+\t\t\t\t\t\t\t_draw(element, ui, null, true);\n
+\t\t\t\t\t\t\t_currentInstance.addClass(element, "jsPlumb_dragged");\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t\toptions[stopEvent] = _ju.wrap(options[stopEvent], function() {\n
+\t\t\t\t\t\t\tvar ui = _currentInstance.getUIPosition(arguments, _currentInstance.getZoom(), true);\n
+\t\t\t\t\t\t\t_draw(element, ui);\n
+\t\t\t\t\t\t\t_currentInstance.removeClass(element, "jsPlumb_dragged");\n
+\t\t\t\t\t\t\t_currentInstance.setHoverSuspended(false);\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t\t_currentInstance.select({source:element}).removeClass(_currentInstance.elementDraggingClass + " " + _currentInstance.sourceElementDraggingClass, true);\n
+\t\t\t\t\t\t\t_currentInstance.select({target:element}).removeClass(_currentInstance.elementDraggingClass + " " + _currentInstance.targetElementDraggingClass, true);\n
+\t\t\t\t\t\t\t_currentInstance.setConnectionBeingDragged(false);\n
+\t\t\t\t\t\t\t_currentInstance.dragManager.dragEnded(element);\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t\tvar elId = _getId(element); // need ID\n
+\t\t\t\t\t\tdraggableStates[elId] = true;  \n
+\t\t\t\t\t\tvar draggable = draggableStates[elId];\n
+\t\t\t\t\t\toptions.disabled = draggable == null ? false : !draggable;\n
+\t\t\t\t\t\t_currentInstance.initDraggable(element, options, false);\n
+\t\t\t\t\t\t_currentInstance.dragManager.register(element);\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t},\n
+\t\t\n
+\t\t/*\n
+\t\t* prepares a final params object that can be passed to _newConnection, taking into account defaults, events, etc.\n
+\t\t*/\n
+\t\t_prepareConnectionParams = function(params, referenceParams) {\n
+\t\t\tvar _p = jsPlumb.extend( { }, params);\n
+\t\t\tif (referenceParams) jsPlumb.extend(_p, referenceParams);\n
+\t\t\t\n
+\t\t\t// hotwire endpoints passed as source or target to sourceEndpoint/targetEndpoint, respectively.\n
+\t\t\tif (_p.source) {\n
+\t\t\t\tif (_p.source.endpoint) \n
+\t\t\t\t\t_p.sourceEndpoint = _p.source;\n
+\t\t\t\telse\n
+\t\t\t\t\t_p.source = _currentInstance.getDOMElement(_p.source);\n
+\t\t\t}\n
+\t\t\tif (_p.target) {\n
+\t\t\t\tif (_p.target.endpoint) \n
+\t\t\t\t\t_p.targetEndpoint = _p.target;\n
+\t\t\t\telse\n
+\t\t\t\t\t_p.target = _currentInstance.getDOMElement(_p.target);\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\t// test for endpoint uuids to connect\n
+\t\t\tif (params.uuids) {\n
+\t\t\t\t_p.sourceEndpoint = _getEndpoint(params.uuids[0]);\n
+\t\t\t\t_p.targetEndpoint = _getEndpoint(params.uuids[1]);\n
+\t\t\t}\t\t\t\t\t\t\n
+\n
+\t\t\t// now ensure that if we do have Endpoints already, they\'re not full.\n
+\t\t\t// source:\n
+\t\t\tif (_p.sourceEndpoint && _p.sourceEndpoint.isFull()) {\n
+\t\t\t\t_ju.log(_currentInstance, "could not add connection; source endpoint is full");\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// target:\n
+\t\t\tif (_p.targetEndpoint && _p.targetEndpoint.isFull()) {\n
+\t\t\t\t_ju.log(_currentInstance, "could not add connection; target endpoint is full");\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\t// if source endpoint mandates connection type and nothing specified in our params, use it.\n
+\t\t\tif (!_p.type && _p.sourceEndpoint)\n
+\t\t\t\t_p.type = _p.sourceEndpoint.connectionType;\n
+\t\t\t\n
+\t\t\t// copy in any connectorOverlays that were specified on the source endpoint.\n
+\t\t\t// it doesnt copy target endpoint overlays.  i\'m not sure if we want it to or not.\n
+\t\t\tif (_p.sourceEndpoint && _p.sourceEndpoint.connectorOverlays) {\n
+\t\t\t\t_p.overlays = _p.overlays || [];\n
+\t\t\t\tfor (var i = 0, j = _p.sourceEndpoint.connectorOverlays.length; i < j; i++) {\n
+\t\t\t\t\t_p.overlays.push(_p.sourceEndpoint.connectorOverlays[i]);\n
+\t\t\t\t}\n
+\t\t\t}\t\t\n
+            \n
+            // pointer events\n
+            if (!_p["pointer-events"] && _p.sourceEndpoint && _p.sourceEndpoint.connectorPointerEvents)\n
+                _p["pointer-events"] = _p.sourceEndpoint.connectorPointerEvents;\n
+\t\t\t\t\t\t\t\t\t\n
+\t\t\t// if there\'s a target specified (which of course there should be), and there is no\n
+\t\t\t// target endpoint specified, and \'newConnection\' was not set to true, then we check to\n
+\t\t\t// see if a prior call to makeTarget has provided us with the specs for the target endpoint, and\n
+\t\t\t// we use those if so.  additionally, if the makeTarget call was specified with \'uniqueEndpoint\' set\n
+\t\t\t// to true, then if that target endpoint has already been created, we re-use it.\n
+\n
+\t\t\tvar tid, tep, existingUniqueEndpoint, newEndpoint;\n
+\n
+\t\t\t// TODO: this code can be refactored to be a little dry.\n
+\t\t\tif (_p.target && !_p.target.endpoint && !_p.targetEndpoint && !_p.newConnection) {\n
+\t\t\t\ttid = _getId(_p.target);\n
+\t\t\t\ttep = this.targetEndpointDefinitions[tid];\n
+\n
+\t\t\t\tif (tep) {\n
+\t\t\t\t\t\n
+\t\t\t\t\t// if target not enabled, return.\n
+\t\t\t\t\tif (!tep.enabled) return;\n
+\n
+\t\t\t\t\t// TODO this is dubious. i think it is there so that the endpoint can subsequently\n
+\t\t\t\t\t// be dragged (ie it kicks off the draggable registration). but it is dubious.\n
+\t\t\t\t\ttep.isTarget = true;\n
+\n
+\t\t\t\t\t// check for max connections??\t\t\t\t\t\t\n
+\t\t\t\t\tnewEndpoint = tep.endpoint != null && tep.endpoint._jsPlumb ? tep.endpoint : _currentInstance.addEndpoint(_p.target, tep.def);\n
+\t\t\t\t\tif (tep.uniqueEndpoint) tep.endpoint = newEndpoint;\n
+\t\t\t\t\t _p.targetEndpoint = newEndpoint;\n
+\t\t\t\t\t // TODO test options to makeTarget to see if we should do this?\n
+\t\t\t\t\t newEndpoint._doNotDeleteOnDetach = false; // reset.\n
+\t\t\t\t\t newEndpoint._deleteOnDetach = true;\t\t\t\t\t \n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// same thing, but for source.\n
+\t\t\tif (_p.source && !_p.source.endpoint && !_p.sourceEndpoint && !_p.newConnection) {\n
+\t\t\t\ttid = _getId(_p.source);\n
+\t\t\t\ttep = this.sourceEndpointDefinitions[tid];\n
+\n
+\t\t\t\tif (tep) {\n
+\t\t\t\t\t// if source not enabled, return.\t\t\t\t\t\n
+\t\t\t\t\tif (!tep.enabled) return;\n
+\n
+\t\t\t\t\t// TODO this is dubious. i think it is there so that the endpoint can subsequently\n
+\t\t\t\t\t// be dragged (ie it kicks off the draggable registration). but it is dubious.\n
+\t\t\t\t\t//tep.isSource = true;\n
+\t\t\t\t\n
+\t\t\t\t\tnewEndpoint = tep.endpoint != null && tep.endpoint._jsPlumb ? tep.endpoint : _currentInstance.addEndpoint(_p.source, tep.def);\n
+\t\t\t\t\tif (tep.uniqueEndpoint) tep.endpoint = newEndpoint;\n
+\t\t\t\t\t _p.sourceEndpoint = newEndpoint;\n
+\t\t\t\t\t // TODO test options to makeSource to see if we should do this?\n
+\t\t\t\t\t newEndpoint._doNotDeleteOnDetach = false; // reset.\n
+\t\t\t\t\t newEndpoint._deleteOnDetach = true;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\treturn _p;\n
+\t\t}.bind(_currentInstance),\n
+\t\t\n
+\t\t_newConnection = function(params) {\n
+\t\t\tvar connectionFunc = _currentInstance.Defaults.ConnectionType || _currentInstance.getDefaultConnectionType(),\n
+\t\t\t    endpointFunc = _currentInstance.Defaults.EndpointType || jsPlumb.Endpoint;\t\t\t    \t\t\t\n
+\t\t\t\n
+\t\t\tparams._jsPlumb = _currentInstance;\n
+            params.newConnection = _newConnection;\n
+            params.newEndpoint = _newEndpoint;\n
+            params.endpointsByUUID = endpointsByUUID;             \n
+            params.endpointsByElement = endpointsByElement;  \n
+            params.finaliseConnection = _finaliseConnection;\n
+\t\t\tvar con = new connectionFunc(params);\n
+\t\t\tcon.id = "con_" + _idstamp();\n
+\t\t\t_eventFireProxy("click", "click", con);\n
+\t\t\t_eventFireProxy("dblclick", "dblclick", con);\n
+            _eventFireProxy("contextmenu", "contextmenu", con);\n
+\n
+            // if the connection is draggable, then maybe we need to tell the target endpoint to init the\n
+            // dragging code. it won\'t run again if it already configured to be draggable.\n
+            if (con.isDetachable()) {\n
+            \tcon.endpoints[0].initDraggable();\n
+            \tcon.endpoints[1].initDraggable();\n
+            }\n
+\n
+\t\t\treturn con;\n
+\t\t},\n
+\t\t\n
+\t\t//\n
+\t\t// adds the connection to the backing model, fires an event if necessary and then redraws\n
+\t\t//\n
+\t\t_finaliseConnection = function(jpc, params, originalEvent, doInformAnchorManager) {\n
+            params = params || {};\n
+\t\t\t// add to list of connections (by scope).\n
+            if (!jpc.suspendedEndpoint)\n
+\t\t\t    connections.push(jpc);\n
+\t\t\t\n
+            // always inform the anchor manager\n
+            // except that if jpc has a suspended endpoint it\'s not true to say the\n
+            // connection is new; it has just (possibly) moved. the question is whether\n
+            // to make that call here or in the anchor manager.  i think perhaps here.\n
+            if (jpc.suspendedEndpoint == null || doInformAnchorManager)\n
+            \t_currentInstance.anchorManager.newConnection(jpc);\n
+\n
+\t\t\t// force a paint\n
+\t\t\t_draw(jpc.source);\n
+\t\t\t\n
+\t\t\t// fire an event\n
+\t\t\tif (!params.doNotFireConnectionEvent && params.fireEvent !== false) {\n
+\t\t\t\n
+\t\t\t\tvar eventArgs = {\n
+\t\t\t\t\tconnection:jpc,\n
+\t\t\t\t\tsource : jpc.source, target : jpc.target,\n
+\t\t\t\t\tsourceId : jpc.sourceId, targetId : jpc.targetId,\n
+\t\t\t\t\tsourceEndpoint : jpc.endpoints[0], targetEndpoint : jpc.endpoints[1]\n
+\t\t\t\t};\n
+\t\t\t\n
+\t\t\t\t_currentInstance.fire("connection", eventArgs, originalEvent);\n
+\t\t\t}\n
+\t\t},\n
+\t\t\n
+\t\t_eventFireProxy = function(event, proxyEvent, obj) {\n
+\t\t\tobj.bind(event, function(originalObject, originalEvent) {\n
+\t\t\t\t_currentInstance.fire(proxyEvent, obj, originalEvent);\n
+\t\t\t});\n
+\t\t},\n
+\t\t\n
+\t\t\n
+\t\t/*\n
+\t\t\tfactory method to prepare a new endpoint.  this should always be used instead of creating Endpoints\n
+\t\t\tmanually, since this method attaches event listeners and an id.\n
+\t\t*/\n
+\t\t_newEndpoint = function(params) {\n
+\t\t\t\tvar endpointFunc = _currentInstance.Defaults.EndpointType || jsPlumb.Endpoint;\n
+\t\t\t\tvar _p = jsPlumb.extend({}, params);\n
+\t\t\t\t_p._jsPlumb = _currentInstance;\n
+                _p.newConnection = _newConnection;\n
+                _p.newEndpoint = _newEndpoint;                \n
+                _p.endpointsByUUID = endpointsByUUID;             \n
+                _p.endpointsByElement = endpointsByElement;  \n
+                _p.finaliseConnection = _finaliseConnection;\n
+                _p.fireDetachEvent = fireDetachEvent;\n
+                _p.fireMoveEvent = fireMoveEvent;\n
+                _p.floatingConnections = floatingConnections;\n
+                _p.elementId = _getId(_p.source);                \n
+\t\t\t\tvar ep = new endpointFunc(_p);\t\t\t\n
+\t\t\t\tep.id = "ep_" + _idstamp();\n
+\t\t\t\t_eventFireProxy("click", "endpointClick", ep);\n
+\t\t\t\t_eventFireProxy("dblclick", "endpointDblClick", ep);\n
+\t\t\t\t_eventFireProxy("contextmenu", "contextmenu", ep);\n
+\t\t\t\tif (!jsPlumbAdapter.headless)\n
+\t\t\t\t\t_currentInstance.dragManager.endpointAdded(_p.source);\n
+\t\t\treturn ep;\n
+\t\t},\n
+\t\t\n
+\t\t/*\n
+\t\t * performs the given function operation on all the connections found\n
+\t\t * for the given element id; this means we find all the endpoints for\n
+\t\t * the given element, and then for each endpoint find the connectors\n
+\t\t * connected to it. then we pass each connection in to the given\n
+\t\t * function.\t\t \n
+\t\t */\n
+\t\t_operation = function(elId, func, endpointFunc) {\n
+\t\t\tvar endpoints = endpointsByElement[elId];\n
+\t\t\tif (endpoints && endpoints.length) {\n
+\t\t\t\tfor ( var i = 0, ii = endpoints.length; i < ii; i++) {\n
+\t\t\t\t\tfor ( var j = 0, jj = endpoints[i].connections.length; j < jj; j++) {\n
+\t\t\t\t\t\tvar retVal = func(endpoints[i].connections[j]);\n
+\t\t\t\t\t\t// if the function passed in returns true, we exit.\n
+\t\t\t\t\t\t// most functions return false.\n
+\t\t\t\t\t\tif (retVal) return;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif (endpointFunc) endpointFunc(endpoints[i]);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t},\t\n
+\t\t\n
+\t\t_setDraggable = function(element, draggable) {\n
+\t\t\treturn _elementProxy(element, function(el, id) {\n
+\t\t\t\tdraggableStates[id] = draggable;\n
+\t\t\t\tif (this.isDragSupported(el)) {\n
+\t\t\t\t\tthis.setElementDraggable(el, draggable);\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t},\n
+\t\t/*\n
+\t\t * private method to do the business of hiding/showing.\n
+\t\t * \n
+\t\t * @param el\n
+\t\t *            either Id of the element in question or a library specific\n
+\t\t *            object for the element.\n
+\t\t * @param state\n
+\t\t *            String specifying a value for the css \'display\' property\n
+\t\t *            (\'block\' or \'none\').\n
+\t\t */\n
+\t\t_setVisible = function(el, state, alsoChangeEndpoints) {\n
+\t\t\tstate = state === "block";\n
+\t\t\tvar endpointFunc = null;\n
+\t\t\tif (alsoChangeEndpoints) {\n
+\t\t\t\tif (state) endpointFunc = function(ep) {\n
+\t\t\t\t\tep.setVisible(true, true, true);\n
+\t\t\t\t};\n
+\t\t\t\telse endpointFunc = function(ep) {\n
+\t\t\t\t\tep.setVisible(false, true, true);\n
+\t\t\t\t};\n
+\t\t\t}\n
+\t\t\tvar info = _info(el);\n
+\t\t\t_operation(info.id, function(jpc) {\n
+\t\t\t\tif (state && alsoChangeEndpoints) {\t\t\n
+\t\t\t\t\t// this test is necessary because this functionality is new, and i wanted to maintain backwards compatibility.\n
+\t\t\t\t\t// this block will only set a connection to be visible if the other endpoint in the connection is also visible.\n
+\t\t\t\t\tvar oidx = jpc.sourceId === info.id ? 1 : 0;\n
+\t\t\t\t\tif (jpc.endpoints[oidx].isVisible()) jpc.setVisible(true);\n
+\t\t\t\t}\n
+\t\t\t\telse  // the default behaviour for show, and what always happens for hide, is to just set the visibility without getting clever.\n
+\t\t\t\t\tjpc.setVisible(state);\n
+\t\t\t}, endpointFunc);\n
+\t\t},\n
+\t\t/*\n
+\t\t * toggles the draggable state of the given element(s).\n
+\t\t * el is either an id, or an element object, or a list of ids/element objects.\n
+\t\t */\n
+\t\t_toggleDraggable = function(el) {\n
+\t\t\treturn _elementProxy(el, function(el, elId) {\n
+\t\t\t\tvar state = draggableStates[elId] == null ? false : draggableStates[elId];\n
+\t\t\t\tstate = !state;\n
+\t\t\t\tdraggableStates[elId] = state;\n
+\t\t\t\tthis.setDraggable(el, state);\n
+\t\t\t\treturn state;\n
+\t\t\t});\n
+\t\t},\n
+\t\t/**\n
+\t\t * private method to do the business of toggling hiding/showing.\n
+\t\t */\n
+\t\t_toggleVisible = function(elId, changeEndpoints) {\n
+\t\t\tvar endpointFunc = null;\n
+\t\t\tif (changeEndpoints) {\n
+\t\t\t\tendpointFunc = function(ep) {\n
+\t\t\t\t\tvar state = ep.isVisible();\n
+\t\t\t\t\tep.setVisible(!state);\n
+\t\t\t\t};\n
+\t\t\t}\n
+\t\t\t_operation(elId, function(jpc) {\n
+\t\t\t\tvar state = jpc.isVisible();\n
+\t\t\t\tjpc.setVisible(!state);\t\t\t\t\n
+\t\t\t}, endpointFunc);\n
+\t\t\t// todo this should call _elementProxy, and pass in the\n
+\t\t\t// _operation(elId, f) call as a function. cos _toggleDraggable does\n
+\t\t\t// that.\n
+\t\t},\n
+\t\t/**\n
+\t\t * updates the offset and size for a given element, and stores the\n
+\t\t * values. if \'offset\' is not null we use that (it would have been\n
+\t\t * passed in from a drag call) because it\'s faster; but if it is null,\n
+\t\t * or if \'recalc\' is true in order to force a recalculation, we get the current values.\n
+\t\t */\n
+\t\t_updateOffset = this.updateOffset = function(params) {\n
+\t\t\tvar timestamp = params.timestamp, recalc = params.recalc, offset = params.offset, elId = params.elId, s;\n
+\t\t\tif (_suspendDrawing && !timestamp) timestamp = _suspendedAt;\n
+\t\t\tif (!recalc) {\n
+\t\t\t\tif (timestamp && timestamp === offsetTimestamps[elId]) {\t\t\t\n
+\t\t\t\t\treturn {o:params.offset || offsets[elId], s:sizes[elId]};\n
+\t\t\t\t}\n
+\t\t\t}\t\t\t\n
+\t\t\tif (recalc || !offset) { // if forced repaint or no offset available, we recalculate.\n
+\t\t\t\t// get the current size and offset, and store them\n
+\t\t\t\ts = document.getElementById(elId);\n
+\t\t\t\tif (s != null) {\t\t\t\t\t\t\n
+\t\t\t\t\tsizes[elId] = _currentInstance.getSize(s);\n
+\t\t\t\t\toffsets[elId] = _getOffset(s, _currentInstance);\n
+\t\t\t\t\toffsetTimestamps[elId] = timestamp;\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\toffsets[elId] = offset;\n
+                if (sizes[elId] == null) {\n
+                    s = document.getElementById(elId);\n
+                    if (s != null) sizes[elId] = _currentInstance.getSize(s);\n
+                }\n
+                offsetTimestamps[elId] = timestamp;\n
+            }\n
+\t\t\t\n
+\t\t\tif(offsets[elId] && !offsets[elId].right) {\n
+\t\t\t\toffsets[elId].right = offsets[elId].left + sizes[elId][0];\n
+\t\t\t\toffsets[elId].bottom = offsets[elId].top + sizes[elId][1];\t\n
+\t\t\t\toffsets[elId].width = sizes[elId][0];\n
+\t\t\t\toffsets[elId].height = sizes[elId][1];\t\n
+\t\t\t\toffsets[elId].centerx = offsets[elId].left + (offsets[elId].width / 2);\n
+\t\t\t\toffsets[elId].centery = offsets[elId].top + (offsets[elId].height / 2);\t\t\t\t\n
+\t\t\t}\n
+\t\t\treturn {o:offsets[elId], s:sizes[elId]};\n
+\t\t},\n
+\n
+\t\t// TODO comparison performance\n
+\t\t_getCachedData = function(elId) {\n
+\t\t\tvar o = offsets[elId];\n
+\t\t\tif (!o) \n
+                return _updateOffset({elId:elId});\n
+\t\t\telse\n
+                return {o:o, s:sizes[elId]};\n
+\t\t},\n
+\n
+\t\t/**\n
+\t\t * gets an id for the given element, creating and setting one if\n
+\t\t * necessary.  the id is of the form\n
+\t\t *\n
+\t\t *\tjsPlumb_<instance index>_<index in instance>\n
+\t\t *\n
+\t\t * where "index in instance" is a monotonically increasing integer that starts at 0,\n
+\t\t * for each instance.  this method is used not only to assign ids to elements that do not\n
+\t\t * have them but also to connections and endpoints.\n
+\t\t */\n
+\t\t_getId = function(element, uuid, doNotCreateIfNotFound) {\n
+\t\t\tif (jsPlumbUtil.isString(element)) return element;\t\t\t\n
+\t\t\tif (element == null) return null;\t\t\t\n
+\t\t\tvar id = _currentInstance.getAttribute(element, "id");\n
+\t\t\tif (!id || id === "undefined") {\n
+\t\t\t\t// check if fixed uuid parameter is given\n
+\t\t\t\tif (arguments.length == 2 && arguments[1] !== undefined)\n
+\t\t\t\t\tid = uuid;\n
+\t\t\t\telse if (arguments.length == 1 || (arguments.length == 3 && !arguments[2]))\n
+\t\t\t\t\tid = "jsPlumb_" + _instanceIndex + "_" + _idstamp();\n
+\t\t\t\t\n
+                if (!doNotCreateIfNotFound) _currentInstance.setAttribute(element, "id", id);\n
+\t\t\t}\n
+\t\t\treturn id;\n
+\t\t};\n
+\n
+\t\tthis.setConnectionBeingDragged = function(v) {\n
+\t\t\tconnectionBeingDragged = v;\n
+\t\t};\n
+\t\tthis.isConnectionBeingDragged = function() {\n
+\t\t\treturn connectionBeingDragged;\n
+\t\t};\n
+    \n
+\t\tthis.connectorClass = "_jsPlumb_connector";            \t\t\n
+\t\tthis.hoverClass = "_jsPlumb_hover";            \t\t\n
+\t\tthis.endpointClass = "_jsPlumb_endpoint";\t\t\n
+\t\tthis.endpointConnectedClass = "_jsPlumb_endpoint_connected";\t\t\n
+\t\tthis.endpointFullClass = "_jsPlumb_endpoint_full";\t\t\n
+\t\tthis.endpointDropAllowedClass = "_jsPlumb_endpoint_drop_allowed";\t\t\n
+\t\tthis.endpointDropForbiddenClass = "_jsPlumb_endpoint_drop_forbidden";\t\t\n
+\t\tthis.overlayClass = "_jsPlumb_overlay";\t\t\t\t\n
+\t\tthis.draggingClass = "_jsPlumb_dragging";\t\t\n
+\t\tthis.elementDraggingClass = "_jsPlumb_element_dragging";\t\t\t\n
+\t\tthis.sourceElementDraggingClass = "_jsPlumb_source_element_dragging";\n
+\t\tthis.targetElementDraggingClass = "_jsPlumb_target_element_dragging";\n
+\t\tthis.endpointAnchorClassPrefix = "_jsPlumb_endpoint_anchor";\n
+\t\tthis.hoverSourceClass = "_jsPlumb_source_hover";\t\n
+\t\tthis.hoverTargetClass = "_jsPlumb_target_hover";\n
+\t\tthis.dragSelectClass = "_jsPlumb_drag_select";\n
+\n
+\t\tthis.Anchors = {};\t\t\n
+\t\tthis.Connectors = {  "svg":{}, "vml":{} };\t\t\t\t\n
+\t\tthis.Endpoints = { "svg":{}, "vml":{} };\n
+\t\tthis.Overlays = { "svg":{}, "vml":{}};\t\t\n
+\t\tthis.ConnectorRenderers = {};\t\t\t\t\n
+\t\tthis.SVG = "svg";\n
+\t\tthis.VML = "vml";\t\t\t\t\n
+\n
+// --------------------------- jsPLumbInstance public API ---------------------------------------------------------\n
+\t\t\t\t\t\n
+\t\t\n
+\t\tthis.addEndpoint = function(el, params, referenceParams) {\n
+\t\t\treferenceParams = referenceParams || {};\n
+\t\t\tvar p = jsPlumb.extend({}, referenceParams);\n
+\t\t\tjsPlumb.extend(p, params);\n
+\t\t\tp.endpoint = p.endpoint || _currentInstance.Defaults.Endpoint;\n
+\t\t\tp.paintStyle = p.paintStyle || _currentInstance.Defaults.EndpointStyle;\n
+            // YUI wrapper\n
+\t\t\tel = _convertYUICollection(el);\t\t\t\t\t\t\t\n
+\n
+\t\t\tvar results = [], \n
+\t\t\t\tinputs = (_ju.isArray(el) || (el.length != null && !_ju.isString(el))) ? el : [ el ];\n
+\t\t\t\t\t\t\n
+\t\t\tfor (var i = 0, j = inputs.length; i < j; i++) {\n
+\t\t\t\tvar _el = _currentInstance.getDOMElement(inputs[i]), id = _getId(_el);\n
+\t\t\t\tp.source = _el;\n
+\n
+\t\t\t\t_ensureContainer(p.source);\n
+                _updateOffset({ elId : id, timestamp:_suspendedAt });\n
+\t\t\t\tvar e = _newEndpoint(p);\n
+\t\t\t\tif (p.parentAnchor) e.parentAnchor = p.parentAnchor;\n
+\t\t\t\t_ju.addToList(endpointsByElement, id, e);\n
+\t\t\t\tvar myOffset = offsets[id], \n
+\t\t\t\t\tmyWH = sizes[id],\n
+\t\t\t\t\tanchorLoc = e.anchor.compute( { xy : [ myOffset.left, myOffset.top ], wh : myWH, element : e, timestamp:_suspendedAt }),\n
+\t\t\t\t\tendpointPaintParams = { anchorLoc : anchorLoc, timestamp:_suspendedAt };\n
+\t\t\t\t\n
+\t\t\t\tif (_suspendDrawing) endpointPaintParams.recalc = false;\n
+\t\t\t\tif (!_suspendDrawing) e.paint(endpointPaintParams);\n
+\t\t\t\t\n
+\t\t\t\tresults.push(e);\n
+\t\t\t\te._doNotDeleteOnDetach = true; // mark this as being added via addEndpoint.\t\t\t\t\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\treturn results.length == 1 ? results[0] : results;\n
+\t\t};\n
+\t\t\n
+\t\t\n
+\t\tthis.addEndpoints = function(el, endpoints, referenceParams) {\n
+\t\t\tvar results = [];\n
+\t\t\tfor ( var i = 0, j = endpoints.length; i < j; i++) {\n
+\t\t\t\tvar e = _currentInstance.addEndpoint(el, endpoints[i], referenceParams);\n
+\t\t\t\tif (_ju.isArray(e))\n
+\t\t\t\t\tArray.prototype.push.apply(results, e);\n
+\t\t\t\telse results.push(e);\n
+\t\t\t}\n
+\t\t\treturn results;\n
+\t\t};\n
+\t\t\n
+\t\tthis.animate = function(el, properties, options) {\n
+\t\t\toptions = options || {};\n
+\t\t\tvar ele = this.getElementObject(el), \n
+\t\t\t\tdel = this.getDOMElement(el),\n
+\t\t\t\tid = _getId(del),\n
+\t\t\t\tstepFunction = jsPlumb.animEvents.step,\n
+\t\t\t\tcompleteFunction = jsPlumb.animEvents.complete;\n
+\n
+\t\t\toptions[stepFunction] = _ju.wrap(options[stepFunction], function() {\n
+\t\t\t\t_currentInstance.repaint(id);\n
+\t\t\t});\n
+\n
+\t\t\t// onComplete repaints, just to make sure everything looks good at the end of the animation.\n
+\t\t\toptions[completeFunction] = _ju.wrap(options[completeFunction], function() {\n
+\t\t\t\t_currentInstance.repaint(id);\n
+\t\t\t});\n
+\n
+\t\t\t_currentInstance.doAnimate(ele, properties, options);\n
+\t\t};\n
+\t\t\n
+\t\t/**\n
+\t\t* checks for a listener for the given condition, executing it if found, passing in the given value.\n
+\t\t* condition listeners would have been attached using "bind" (which is, you could argue, now overloaded, since\n
+\t\t* firing click events etc is a bit different to what this does).  i thought about adding a "bindCondition"\n
+\t\t* or something, but decided against it, for the sake of simplicity. jsPlumb will never fire one of these\n
+\t\t* condition events anyway.\n
+\t\t*/\n
+\t\tthis.checkCondition = function(conditionName, value) {\n
+\t\t\tvar l = _currentInstance.getListener(conditionName),\n
+\t\t\t\tr = true;\n
+\t\t\t\t\n
+\t\t\tif (l && l.length > 0) {\n
+\t\t\t\ttry {\n
+\t\t\t\t\tfor (var i = 0, j = l.length; i < j; i++) {\n
+\t\t\t\t\t\tr = r && l[i](value); \n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\tcatch (e) { \n
+\t\t\t\t\t_ju.log(_currentInstance, "cannot check condition [" + conditionName + "]" + e); \n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\treturn r;\n
+\t\t};\n
+\t\t\n
+\t\t/**\n
+\t\t * checks a condition asynchronously: fires the event handler and passes the handler\n
+\t\t * a \'proceed\' function and a \'stop\' function. The handler MUST execute one or other\n
+\t\t * of these once it has made up its mind.\n
+\t\t *\n
+\t\t * Note that although this reads the listener list for the given condition, it\n
+\t\t * does not loop through and hit each listener, because that, with asynchronous\n
+\t\t * callbacks, would be messy. so it uses only the first listener registered.\n
+\t\t */ \n
+\t\tthis.checkASyncCondition = function(conditionName, value, proceed, stop) {\n
+\t\t\tvar l = _currentInstance.getListener(conditionName);\n
+\t\t\t\t\n
+\t\t\tif (l && l.length > 0) {\n
+\t\t\t\ttry {\n
+\t\t\t\t\tl[0](value, proceed, stop); \t\t\t\t\t\n
+\t\t\t\t}\n
+\t\t\t\tcatch (e) { \n
+\t\t\t\t\t_ju.log(_currentInstance, "cannot asynchronously check condition [" + conditionName + "]" + e); \n
+\t\t\t\t}\n
+\t\t\t}\t\n
+\t\t};\n
+\n
+\t\t\n
+\t\tthis.connect = function(params, referenceParams) {\n
+\t\t\t// prepare a final set of parameters to create connection with\n
+\t\t\tvar _p = _prepareConnectionParams(params, referenceParams), jpc;\n
+\t\t\t// TODO probably a nicer return value if the connection was not made.  _prepareConnectionParams\n
+\t\t\t// will return null (and log something) if either endpoint was full.  what would be nicer is to \n
+\t\t\t// create a dedicated \'error\' object.\n
+\t\t\tif (_p) {\n
+\t\t\t\t_ensureContainer(_p.source);\n
+\t\t\t\t// create the connection.  it is not yet registered \n
+\t\t\t\tjpc = _newConnection(_p);\n
+\t\t\t\t// now add it the model, fire an event, and redraw\n
+\t\t\t\t_finaliseConnection(jpc, _p);\t\t\t\t\t\t\t\t\t\t\n
+\t\t\t}\n
+\t\t\treturn jpc;\n
+\t\t};\t\t\n
+\t\t\n
+\t\tvar stTypes = [\n
+\t\t\t{ el:"source", elId:"sourceId", epDefs:"sourceEndpointDefinitions" },\n
+\t\t\t{ el:"target", elId:"targetId", epDefs:"targetEndpointDefinitions" }\n
+\t\t];\n
+\t\t\n
+\t\tvar _set = function(c, el, idx, doNotRepaint) {\n
+\t\t\tvar ep, _st = stTypes[idx], cId = c[_st.elId], cEl = c[_st.el], sid, sep,\n
+\t\t\t\toldEndpoint = c.endpoints[idx];\n
+\t\t\t\n
+\t\t\tvar evtParams = {\n
+\t\t\t\tindex:idx,\n
+\t\t\t\toriginalSourceId:idx === 0 ? cId : c.sourceId,\n
+\t\t\t\tnewSourceId:c.sourceId,\n
+\t\t\t\toriginalTargetId:idx == 1 ? cId : c.targetId,\n
+\t\t\t\tnewTargetId:c.targetId,\n
+\t\t\t\tconnection:c\n
+\t\t\t};\n
+\n
+\t\t\tif (el.constructor == jsPlumb.Endpoint) { // TODO here match the current endpoint class; users can change it {\n
+\t\t\t\tep = el;\n
+\t\t\t\tep.addConnection(c);\n
+\t\t\t}\n
+\t\t\telse {\n
+\t\t\t\tsid = _getId(el);\n
+\t\t\t\tsep = this[_st.epDefs][sid];\n
+\n
+\t\t\t\tif (sid === c[_st.elId]) \n
+\t\t\t\t\tep = null;  // dont change source/target if the element is already the one given.\n
+\t\t\t\telse if (sep) {\n
+\t\t\t\t\tif (!sep.enabled) return;\n
+\t\t\t\t\tep = sep.endpoint != null && sep.endpoint._jsPlumb ? sep.endpoint : this.addEndpoint(el, sep.def);\n
+\t\t\t\t\tif (sep.uniqueEndpoint) sep.endpoint = ep;\n
+\t\t\t\t\tep._doNotDeleteOnDetach = false;\n
+\t\t\t\t\tep._deleteOnDetach = true;\n
+\t\t\t\t\tep.addConnection(c);\n
+\t\t\t\t}\n
+\t\t\t\telse {\n
+\t\t\t\t\tep = c.makeEndpoint(idx === 0, el, sid);\n
+\t\t\t\t\tep._doNotDeleteOnDetach = false;\n
+\t\t\t\t\tep._deleteOnDetach = true;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\tif (ep != null) {\n
+\t\t\t\toldEndpoint.detachFromConnection(c);\n
+\t\t\t\tc.endpoints[idx] = ep;\n
+\t\t\t\tc[_st.el] = ep.element;\n
+\t\t\t\tc[_st.elId] = ep.elementId;\t\t\t\n
+\t\t\t\tevtParams[idx === 0 ? "newSourceId" : "newTargetId"] = ep.elementId;\n
+\n
+\t\t\t\tfireMoveEvent(evtParams);\n
+\t\t\t\t\n
+\t\t\t\tif (!doNotRepaint)\n
+\t\t\t\t\tc.repaint();\n
+\t\t\t}\n
+\n
+\t\t\treturn evtParams;\n
+\t\t\t\n
+\t\t}.bind(this);\n
+\n
+\t\tthis.setSource = function(connection, el, doNotRepaint) { \n
+\t\t\tvar p = _set(connection, el, 0, doNotRepaint); \n
+\t\t\tthis.anchorManager.sourceChanged(p.originalSourceId, p.newSourceId, connection);\n
+\t\t};\n
+\t\tthis.setTarget = function(connection, el, doNotRepaint) { \n
+\t\t\tvar p = _set(connection, el, 1, doNotRepaint); \n
+\t\t\tthis.anchorManager.updateOtherEndpoint(p.originalSourceId, p.originalTargetId, p.newTargetId, connection);\n
+\t\t};\n
+\t\t\n
+\t\tthis.deleteEndpoint = function(object, doNotRepaintAfterwards) {\n
+\t\t\tvar _is = _currentInstance.setSuspendDrawing(true);\n
+\t\t\tvar endpoint = (typeof object == "string") ? endpointsByUUID[object] : object;\n
+\t\t\tif (endpoint) {\t\t\n
+\t\t\t\t_currentInstance.deleteObject({\n
+\t\t\t\t\tendpoint:endpoint\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t\tif(!_is) _currentInstance.setSuspendDrawing(false, doNotRepaintAfterwards);\n
+\t\t\treturn _currentInstance;\n
+\t\t};\t\t\n
+\t\t\n
+\t\tthis.deleteEveryEndpoint = function() {\n
+\t\t\tvar _is = _currentInstance.setSuspendDrawing(true);\n
+\t\t\tfor ( var id in endpointsByElement) {\n
+\t\t\t\tvar endpoints = endpointsByElement[id];\n
+\t\t\t\tif (endpoints && endpoints.length) {\n
+\t\t\t\t\tfor ( var i = 0, j = endpoints.length; i < j; i++) {\n
+\t\t\t\t\t\t_currentInstance.deleteEndpoint(endpoints[i], true);\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\t\t\t\n
+\t\t\tendpointsByElement = {};\t\t\t\n
+\t\t\tendpointsByUUID = {};\n
+\t\t\t_currentInstance.anchorManager.reset();\n
+\t\t\t_currentInstance.dragManager.reset();\t\t\t\t\t\t\t\n
+\t\t\tif(!_is) _currentInstance.setSuspendDrawing(false);\n
+\t\t\treturn _currentInstance;\n
+\t\t};\n
+\n
+\t\tvar fireDetachEvent = function(jpc, doFireEvent, originalEvent) {\n
+            // may have been given a connection, or in special cases, an object\n
+            var connType =  _currentInstance.Defaults.ConnectionType || _currentInstance.getDefaultConnectionType(),\n
+                argIsConnection = jpc.constructor == connType,\n
+                params = argIsConnection ? {\n
+                    connection:jpc,\n
+\t\t\t\t    source : jpc.source, target : jpc.target,\n
+\t\t\t\t    sourceId : jpc.sourceId, targetId : jpc.targetId,\n
+\t\t\t\t    sourceEndpoint : jpc.endpoints[0], targetEndpoint : jpc.endpoints[1]\n
+                } : jpc;\n
+\n
+\t\t\tif (doFireEvent)\n
+\t\t\t\t_currentInstance.fire("connectionDetached", params, originalEvent);\n
+\t\t\t\n
+            _currentInstance.anchorManager.connectionDetached(params);\n
+\t\t};\t\n
+\n
+\t\tvar fireMoveEvent = function(params, evt) {\n
+\t\t\t_currentInstance.fire("connectionMoved", params, evt);\n
+\t\t};\n
+\n
+\t\tthis.unregisterEndpoint = function(endpoint) {\n
+\t\t\t//if (endpoint._jsPlumb == null) return;\n
+\t\t\tif (endpoint._jsPlumb.uuid) endpointsByUUID[endpoint._jsPlumb.uuid] = null;\t\t\t\t\n
+\t\t\t_currentInstance.anchorManager.deleteEndpoint(endpoint);\t\t\t\n
+\t\t\t// TODO at least replace this with a removeWithFunction call.\t\t\t\n
+\t\t\tfor (var e in endpointsByElement) {\n
+\t\t\t\tvar endpoints = endpointsByElement[e];\n
+\t\t\t\tif (endpoints) {\n
+\t\t\t\t\tvar newEndpoints = [];\n
+\t\t\t\t\tfor (var i = 0, j = endpoints.length; i < j; i++)\n
+\t\t\t\t\t\tif (endpoints[i] != endpoint) newEndpoints.push(endpoints[i]);\n
+\t\t\t\t\t\n
+\t\t\t\t\tendpointsByElement[e] = newEndpoints;\n
+\t\t\t\t}\n
+\t\t\t\tif(endpointsByElement[e].length <1){\n
+\t\t\t\t\tdelete endpointsByElement[e];\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t};\n
+\t\t\t\t\n
+\t\tthis.detach = function() {\n
+\n
+            if (arguments.length === 0) return;\n
+            var connType =  _currentInstance.Defaults.ConnectionType || _currentInstance.getDefaultConnectionType(),\n
+                firstArgIsConnection = arguments[0].constructor == connType,\n
+                params = arguments.length == 2 ? firstArgIsConnection ? (arguments[1] || {}) : arguments[0] : arguments[0],\n
+                fireEvent = (params.fireEvent !== false),\n
+                forceDetach = params.forceDetach,\n
+                conn = firstArgIsConnection ? arguments[0] : params.connection;\n
+                                                    \n
+\t\t\t\tif (conn) {             \n
+                    if (forceDetach || jsPlumbUtil.functionChain(true, false, [\n
+                            [ conn.endpoints[0], "isDetachAllowed", [ conn ] ],    \n
+                            [ conn.endpoints[1], "isDetachAllowed", [ conn ] ],\n
+                            [ conn, "isDetachAllowed", [ conn ] ],\n
+                            [ _currentInstance, "checkCondition", [ "beforeDetach", conn ] ] ])) {\n
+                        \n
+                        conn.endpoints[0].detach(conn, false, true, fireEvent); \n
+                    }\n
+                }\n
+                else {\n
+\t\t\t\t\tvar _p = jsPlumb.extend( {}, params); // a backwards compatibility hack: source should be thought of as \'params\' in this case.\n
+\t\t\t\t\t// test for endpoint uuids to detach\n
+\t\t\t\t\tif (_p.uuids) {\n
+\t\t\t\t\t\t_getEndpoint(_p.uuids[0]).detachFrom(_getEndpoint(_p.uuids[1]), fireEvent);\n
+\t\t\t\t\t} else if (_p.sourceEndpoint && _p.targetEndpoint) {\n
+\t\t\t\t\t\t_p.sourceEndpoint.detachFrom(_p.targetEndpoint);\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tvar sourceId = _getId(_currentInstance.getDOMElement(_p.source)),\n
+\t\t\t\t\t\t    targetId = _getId(_currentInstance.getDOMElement(_p.target));\n
+\t\t\t\t\t\t_operation(sourceId, function(jpc) {\n
+\t\t\t\t\t\t    if ((jpc.sourceId == sourceId && jpc.targetId == targetId) || (jpc.targetId == sourceId && jpc.sourceId == targetId)) {\n
+\t\t\t\t\t\t\t    if (_currentInstance.checkCondition("beforeDetach", jpc)) {\n
+                                    jpc.endpoints[0].detach(jpc, false, true, fireEvent);\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t};\n
+\n
+\t\tthis.detachAllConnections = function(el, params) {\n
+            params = params || {};\n
+            el = _currentInstance.getDOMElement(el);\n
+\t\t\tvar id = _getId(el),\n
+                endpoints = endpointsByElement[id];\n
+\t\t\tif (endpoints && endpoints.length) {\n
+\t\t\t\tfor ( var i = 0, j = endpoints.length; i < j; i++) {\n
+\t\t\t\t\tendpoints[i].detachAll(params.fireEvent !== false);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\treturn _currentInstance;\n
+\t\t};\n
+\n
+\t\tthis.detachEveryConnection = function(params) {\n
+            params = params || {};\n
+            _currentInstance.doWhileSuspended(function() {\n
+\t\t\t\tfor ( var id in endpointsByElement) {\n
+\t\t\t\t\tvar endpoints = endpointsByElement[id];\n
+\t\t\t\t\tif (endpoints && endpoints.length) {\n
+\t\t\t\t\t\tfor ( var i = 0, j = endpoints.length; i < j; i++) {\n
+\t\t\t\t\t\t\tendpoints[i].detachAll(params.fireEvent !== false);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\tconnections.splice(0);\n
+\t\t\t});\n
+\t\t\treturn _currentInstance;\n
+\t\t};\n
+\n
+\t\t/// not public.  but of course its exposed. how to change this.\n
+\t\tthis.deleteObject = function(params) {\n
+\t\t\tvar result = {\n
+\t\t\t\t\tendpoints : {}, \n
+\t\t\t\t\tconnections : {},\n
+\t\t\t\t\tendpointCount:0,\n
+\t\t\t\t\tconnectionCount:0\n
+\t\t\t\t},\n
+\t\t\t\tfireEvent = params.fireEvent !== false,\n
+\t\t\t\tdeleteAttachedObjects = params.deleteAttachedObjects !== false;\n
+\n
+\t\t\tvar unravelConnection = function(connection) {\n
+\t\t\t\tif(connection != null && resul
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+t.connections[connection.id] == null) {\n
+\t\t\t\t\tif (connection._jsPlumb != null) connection.setHover(false);\n
+\t\t\t\t\tresult.connections[connection.id] = connection;\n
+\t\t\t\t\tresult.connectionCount++;\n
+\t\t\t\t\tif (deleteAttachedObjects) {\n
+\t\t\t\t\t\tfor (var j = 0; j < connection.endpoints.length; j++) {\n
+\t\t\t\t\t\t\tif (connection.endpoints[j]._deleteOnDetach)\n
+\t\t\t\t\t\t\t\tunravelEndpoint(connection.endpoints[j]);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\t\t\t\t\t\n
+\t\t\t\t}\n
+\t\t\t};\n
+\t\t\tvar unravelEndpoint = function(endpoint) {\n
+\t\t\t\tif(endpoint != null && result.endpoints[endpoint.id] == null) {\n
+\t\t\t\t\tif (endpoint._jsPlumb != null) endpoint.setHover(false);\n
+\t\t\t\t\tresult.endpoints[endpoint.id] = endpoint;\n
+\t\t\t\t\tresult.endpointCount++;\n
+\n
+\t\t\t\t\tif (deleteAttachedObjects) {\n
+\t\t\t\t\t\tfor (var i = 0; i < endpoint.connections.length; i++) {\n
+\t\t\t\t\t\t\tvar c = endpoint.connections[i];\n
+\t\t\t\t\t\t\tunravelConnection(c);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t};\n
+\n
+\t\t\tif (params.connection) \n
+\t\t\t\tunravelConnection(params.connection);\n
+\t\t\telse unravelEndpoint(params.endpoint);\n
+\n
+\t\t\t// loop through connections\n
+\t\t\tfor (var i in result.connections) {\n
+\t\t\t\tvar c = result.connections[i];\n
+\t\t\t\tif (c._jsPlumb) {\n
+\t\t\t\t\tjsPlumbUtil.removeWithFunction(connections, function(_c) {\n
+\t\t\t\t\t\treturn c.id == _c.id;\n
+\t\t\t\t\t});\n
+\t\t\t\t\tfireDetachEvent(c, fireEvent, params.originalEvent);\n
+\t\t\t\t\t\n
+\t\t\t\t\tc.endpoints[0].detachFromConnection(c);\n
+\t\t\t\t\tc.endpoints[1].detachFromConnection(c);\n
+\t\t\t\t\t// sp was ere\n
+\t\t\t\t\tc.cleanup();\n
+\t\t\t\t\tc.destroy();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// loop through endpoints\n
+\t\t\tfor (var j in result.endpoints) {\n
+\t\t\t\tvar e = result.endpoints[j];\t\n
+\t\t\t\tif (e._jsPlumb) {\n
+\t\t\t\t\t_currentInstance.unregisterEndpoint(e);\n
+\t\t\t\t\t// FIRE some endpoint deleted event?\n
+\t\t\t\t\te.cleanup();\n
+\t\t\t\t\te.destroy();\n
+\t\t\t\t}\n
+\t\t\t}\t\n
+\n
+\t\t\treturn result;\n
+\t\t};\n
+ \n
+\t\tthis.draggable = function(el, options) {\n
+\t\t\tvar i,j,ele;\n
+\t\t\t// allows for array or jquery/mootools selector\n
+\t\t\tif (typeof el == \'object\' && el.length) {\n
+\t\t\t\tfor (i = 0, j = el.length; i < j; i++) {\n
+\t\t\t\t\tele = _currentInstance.getDOMElement(el[i]);\n
+\t\t\t\t\tif (ele) _initDraggableIfNecessary(ele, true, options);\n
+\t\t\t\t}\n
+\t\t\t} \n
+\t\t\t// allows for YUI selector\n
+\t\t\telse if (el._nodes) { \t// TODO this is YUI specific; really the logic should be forced\n
+\t\t\t\t// into the library adapters (for jquery and mootools aswell)\n
+\t\t\t\tfor (i = 0, j = el._nodes.length; i < j; i++) {\n
+\t\t\t\t\tele = _currentInstance.getDOMElement(el._nodes[i]);\n
+\t\t\t\t\tif (ele) _initDraggableIfNecessary(ele, true, options);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\telse {\t\t\t\t\n
+\t\t\t\tele = _currentInstance.getDOMElement(el);\n
+\t\t\t\tif (ele) _initDraggableIfNecessary(ele, true, options);\n
+\t\t\t}\n
+\t\t\treturn _currentInstance;\n
+\t\t};\n
+\n
+\t\t// helpers for select/selectEndpoints\n
+\t\tvar _setOperation = function(list, func, args, selector) {\n
+\t\t\t\tfor (var i = 0, j = list.length; i < j; i++) {\n
+\t\t\t\t\tlist[i][func].apply(list[i], args);\n
+\t\t\t\t}\t\n
+\t\t\t\treturn selector(list);\n
+\t\t\t},\n
+\t\t\t_getOperation = function(list, func, args) {\n
+\t\t\t\tvar out = [];\n
+\t\t\t\tfor (var i = 0, j = list.length; i < j; i++) {\n
+\t\t\t\t\tout.push([ list[i][func].apply(list[i], args), list[i] ]);\n
+\t\t\t\t}\t\n
+\t\t\t\treturn out;\n
+\t\t\t},\n
+\t\t\tsetter = function(list, func, selector) {\n
+\t\t\t\treturn function() {\n
+\t\t\t\t\treturn _setOperation(list, func, arguments, selector);\n
+\t\t\t\t};\n
+\t\t\t},\n
+\t\t\tgetter = function(list, func) {\n
+\t\t\t\treturn function() {\n
+\t\t\t\t\treturn _getOperation(list, func, arguments);\n
+\t\t\t\t};\t\n
+\t\t\t},\n
+\t\t\tprepareList = function(input, doNotGetIds) {\n
+\t\t\t\tvar r = [];\n
+\t\t\t\tif (input) {\n
+\t\t\t\t\tif (typeof input == \'string\') {\n
+\t\t\t\t\t\tif (input === "*") return input;\n
+\t\t\t\t\t\tr.push(input);\n
+\t\t\t\t\t}\n
+\t\t\t\t\telse {\n
+\t\t\t\t\t\tif (doNotGetIds) r = input;\n
+\t\t\t\t\t\telse { \n
+\t\t\t\t\t\t\tif (input.length) {\n
+\t\t\t\t\t\t\t\t//input = _currentInstance.getElementObject(input);\n
+\t\t\t\t\t\t\t\tfor (var i = 0, j = input.length; i < j; i++) \n
+\t\t\t\t\t\t\t\t\tr.push(_info(input[i]).id);\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\telse\n
+\t\t\t\t\t\t\t\tr.push(_info(input).id);\n
+\t\t\t\t\t\t}\t\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\treturn r;\n
+\t\t\t},\n
+\t\t\tfilterList = function(list, value, missingIsFalse) {\n
+\t\t\t\tif (list === "*") return true;\n
+\t\t\t\treturn list.length > 0 ? jsPlumbUtil.indexOf(list, value) != -1 : !missingIsFalse;\n
+\t\t\t};\n
+\n
+\t\t// get some connections, specifying source/target/scope\n
+\t\tthis.getConnections = function(options, flat) {\n
+\t\t\tif (!options) {\n
+\t\t\t\toptions = {};\n
+\t\t\t} else if (options.constructor == String) {\n
+\t\t\t\toptions = { "scope": options };\n
+\t\t\t}\n
+\t\t\tvar scope = options.scope || _currentInstance.getDefaultScope(),\n
+\t\t\t\tscopes = prepareList(scope, true),\n
+\t\t\t\tsources = prepareList(options.source),\n
+\t\t\t\ttargets = prepareList(options.target),\t\t\t\n
+\t\t\t\tresults = (!flat && scopes.length > 1) ? {} : [],\n
+\t\t\t\t_addOne = function(scope, obj) {\n
+\t\t\t\t\tif (!flat && scopes.length > 1) {\n
+\t\t\t\t\t\tvar ss = results[scope];\n
+\t\t\t\t\t\tif (ss == null) {\n
+\t\t\t\t\t\t\tss = results[scope] = [];\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\tss.push(obj);\n
+\t\t\t\t\t} else results.push(obj);\n
+\t\t\t\t};\n
+\t\t\t\n
+\t\t\tfor ( var j = 0, jj = connections.length; j < jj; j++) {\n
+\t\t\t\tvar c = connections[j];\n
+\t\t\t\tif (filterList(scopes, c.scope) && filterList(sources, c.sourceId) && filterList(targets, c.targetId))\n
+\t\t\t\t\t_addOne(c.scope, c);\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\treturn results;\n
+\t\t};\n
+\t\t\n
+\t\tvar _curryEach = function(list, executor) {\n
+\t\t\t\treturn function(f) {\n
+\t\t\t\t\tfor (var i = 0, ii = list.length; i < ii; i++) {\n
+\t\t\t\t\t\tf(list[i]);\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn executor(list);\n
+\t\t\t\t};\t\t\n
+\t\t\t},\n
+\t\t\t_curryGet = function(list) {\n
+\t\t\t\treturn function(idx) {\n
+\t\t\t\t\treturn list[idx];\n
+\t\t\t\t};\n
+\t\t\t};\n
+\t\t\t\n
+\t\tvar _makeCommonSelectHandler = function(list, executor) {\n
+            var out = {\n
+                    length:list.length,\n
+\t\t\t\t    each:_curryEach(list, executor),\n
+\t\t\t\t    get:_curryGet(list)\n
+                },\n
+                setters = ["setHover", "removeAllOverlays", "setLabel", "addClass", "addOverlay", "removeOverlay", \n
+                           "removeOverlays", "showOverlay", "hideOverlay", "showOverlays", "hideOverlays", "setPaintStyle",\n
+                           "setHoverPaintStyle", "setSuspendEvents", "setParameter", "setParameters", "setVisible", \n
+                           "repaint", "addType", "toggleType", "removeType", "removeClass", "setType", "bind", "unbind" ],\n
+                \n
+                getters = ["getLabel", "getOverlay", "isHover", "getParameter", "getParameters", "getPaintStyle",\n
+                           "getHoverPaintStyle", "isVisible", "hasType", "getType", "isSuspendEvents" ],\n
+                i, ii;\n
+            \n
+            for (i = 0, ii = setters.length; i < ii; i++)\n
+                out[setters[i]] = setter(list, setters[i], executor);\n
+            \n
+            for (i = 0, ii = getters.length; i < ii; i++)\n
+                out[getters[i]] = getter(list, getters[i]);       \n
+            \n
+            return out;\n
+\t\t};\n
+\t\t\n
+\t\tvar\t_makeConnectionSelectHandler = function(list) {\n
+\t\t\tvar common = _makeCommonSelectHandler(list, _makeConnectionSelectHandler);\n
+\t\t\treturn jsPlumb.extend(common, {\n
+\t\t\t\t// setters\n
+\t\t\t\tsetDetachable:setter(list, "setDetachable", _makeConnectionSelectHandler),\n
+\t\t\t\tsetReattach:setter(list, "setReattach", _makeConnectionSelectHandler),\n
+\t\t\t\tsetConnector:setter(list, "setConnector", _makeConnectionSelectHandler),\t\t\t\n
+\t\t\t\tdetach:function() {\n
+\t\t\t\t\tfor (var i = 0, ii = list.length; i < ii; i++)\n
+\t\t\t\t\t\t_currentInstance.detach(list[i]);\n
+\t\t\t\t},\t\t\t\t\n
+\t\t\t\t// getters\n
+\t\t\t\tisDetachable:getter(list, "isDetachable"),\n
+\t\t\t\tisReattach:getter(list, "isReattach")\n
+\t\t\t});\n
+\t\t};\n
+\t\t\n
+\t\tvar\t_makeEndpointSelectHandler = function(list) {\n
+\t\t\tvar common = _makeCommonSelectHandler(list, _makeEndpointSelectHandler);\n
+\t\t\treturn jsPlumb.extend(common, {\n
+\t\t\t\tsetEnabled:setter(list, "setEnabled", _makeEndpointSelectHandler),\t\t\t\t\n
+\t\t\t\tsetAnchor:setter(list, "setAnchor", _makeEndpointSelectHandler),\n
+\t\t\t\tisEnabled:getter(list, "isEnabled"),\n
+\t\t\t\tdetachAll:function() {\n
+\t\t\t\t\tfor (var i = 0, ii = list.length; i < ii; i++)\n
+\t\t\t\t\t\tlist[i].detachAll();\n
+\t\t\t\t},\n
+\t\t\t\t"remove":function() {\n
+\t\t\t\t\tfor (var i = 0, ii = list.length; i < ii; i++)\n
+\t\t\t\t\t\t_currentInstance.deleteObject({endpoint:list[i]});\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t};\n
+\t\t\t\n
+\n
+\t\tthis.select = function(params) {\n
+\t\t\tparams = params || {};\n
+\t\t\tparams.scope = params.scope || "*";\n
+\t\t\treturn _makeConnectionSelectHandler(params.connections || _currentInstance.getConnections(params, true));\t\t\t\t\t\t\t\n
+\t\t};\t\t\n
+\n
+\t\tthis.selectEndpoints = function(params) {\n
+\t\t\tparams = params || {};\n
+\t\t\tparams.scope = params.scope || "*";\n
+\t\t\tvar noElementFilters = !params.element && !params.source && !params.target,\t\t\t\n
+\t\t\t\telements = noElementFilters ? "*" : prepareList(params.element),\n
+\t\t\t\tsources = noElementFilters ? "*" : prepareList(params.source),\n
+\t\t\t\ttargets = noElementFilters ? "*" : prepareList(params.target),\n
+\t\t\t\tscopes = prepareList(params.scope, true);\n
+\t\t\t\n
+\t\t\tvar ep = [];\n
+\t\t\t\n
+\t\t\tfor (var el in endpointsByElement) {\n
+\t\t\t\tvar either = filterList(elements, el, true),\n
+\t\t\t\t\tsource = filterList(sources, el, true),\n
+\t\t\t\t\tsourceMatchExact = sources != "*",\n
+\t\t\t\t\ttarget = filterList(targets, el, true),\n
+\t\t\t\t\ttargetMatchExact = targets != "*"; \n
+\t\t\t\t\t\n
+\t\t\t\t// if they requested \'either\' then just match scope. otherwise if they requested \'source\' (not as a wildcard) then we have to match only endpoints that have isSource set to to true, and the same thing with isTarget.  \n
+\t\t\t\tif ( either || source  || target ) {\n
+\t\t\t\t\tinner:\n
+\t\t\t\t\tfor (var i = 0, ii = endpointsByElement[el].length; i < ii; i++) {\n
+\t\t\t\t\t\tvar _ep = endpointsByElement[el][i];\n
+\t\t\t\t\t\tif (filterList(scopes, _ep.scope, true)) {\n
+\t\t\t\t\t\t\n
+\t\t\t\t\t\t\tvar noMatchSource = (sourceMatchExact && sources.length > 0 && !_ep.isSource),\n
+\t\t\t\t\t\t\t\tnoMatchTarget = (targetMatchExact && targets.length > 0 && !_ep.isTarget);\n
+\t\t\t\t\t\t\n
+\t\t\t\t\t\t\tif (noMatchSource || noMatchTarget)\t\t\t\t\t\t\t\t  \n
+\t\t\t\t\t\t\t\t  continue inner; \n
+\t\t\t\t\t\t\t \t\t\t\t\t\t\t\n
+\t\t\t\t\t\t\tep.push(_ep);\t\t\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\t\t\t\t\t\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\treturn _makeEndpointSelectHandler(ep);\n
+\t\t};\n
+\n
+\t\t// get all connections managed by the instance of jsplumb.\n
+\t\tthis.getAllConnections = function() { return connections; };\n
+\t\tthis.getDefaultScope = function() { return DEFAULT_SCOPE; };\n
+\t\t// get an endpoint by uuid.\n
+\t\tthis.getEndpoint = _getEndpoint;\t\t\t\t\n
+\t\t// get endpoints for some element.\n
+\t\tthis.getEndpoints = function(el) { return endpointsByElement[_info(el).id]; };\t\t\n
+\t\t// gets the default endpoint type. used when subclassing. see wiki.\n
+\t\tthis.getDefaultEndpointType = function() { return jsPlumb.Endpoint; };\t\t\n
+\t\t// gets the default connection type. used when subclassing.  see wiki.\n
+\t\tthis.getDefaultConnectionType = function() { return jsPlumb.Connection; };\n
+\t\t/*\n
+\t\t * Gets an element\'s id, creating one if necessary. really only exposed\n
+\t\t * for the lib-specific functionality to access; would be better to pass\n
+\t\t * the current instance into the lib-specific code (even though this is\n
+\t\t * a static call. i just don\'t want to expose it to the public API).\n
+\t\t */\n
+\t\tthis.getId = _getId;\n
+\t\tthis.getOffset = function(id) { \n
+\t\t\tvar o = offsets[id]; \n
+\t\t\treturn _updateOffset({elId:id});\n
+\t\t};\n
+\t\t\n
+\t\tthis.appendElement = _appendElement;\n
+\t\t\n
+\t\tvar _hoverSuspended = false;\n
+\t\tthis.isHoverSuspended = function() { return _hoverSuspended; };\n
+\t\tthis.setHoverSuspended = function(s) { _hoverSuspended = s; };\n
+\n
+\t\tvar _isAvailable = function(m) {\n
+\t\t\treturn function() {\n
+\t\t\t\treturn jsPlumbAdapter.isRenderModeAvailable(m);\n
+\t\t\t};\n
+\t\t};\n
+\n
+\t\tthis.isSVGAvailable = _isAvailable("svg");\n
+\t\tthis.isVMLAvailable = _isAvailable("vml");\n
+\n
+\t\t// set an element\'s connections to be hidden\n
+\t\tthis.hide = function(el, changeEndpoints) {\n
+\t\t\t_setVisible(el, "none", changeEndpoints);\n
+\t\t\treturn _currentInstance;\n
+\t\t};\n
+\t\t\n
+\t\t// exposed for other objects to use to get a unique id.\n
+\t\tthis.idstamp = _idstamp;\n
+\n
+\t\tthis.connectorsInitialized = false;\n
+\t\tvar connectorTypes = [], rendererTypes = ["svg", "vml"];\n
+\t\tthis.registerConnectorType = function(connector, name) {\n
+\t\t\tconnectorTypes.push([connector, name]);\n
+\t\t};\n
+\t\t\n
+\t\t// ensure that, if the current container exists, it is a DOM element and not a selector.\n
+\t\t// if it does not exist and `candidate` is supplied, the offset parent of that element will be set as the Container.\n
+\t\t// this is used to do a better default behaviour for the case that the user has not set a container:\n
+\t\t// addEndpoint, makeSource, makeTarget and connect all call this method with the offsetParent of the \n
+\t\t// element in question (for connect it is the source element). So if no container is set, it is inferred\n
+\t\t// to be the offsetParent of the first element the user tries to connect.\n
+\t\tvar _ensureContainer = function(candidate) {\n
+\t\t\tif (!_container && candidate) {\n
+\t\t\t\tvar can = _currentInstance.getDOMElement(candidate);\n
+\t\t\t\tif (can.offsetParent) _container = can.offsetParent;\n
+\t\t\t}\n
+\t\t};\n
+\n
+\t\tvar _getContainerFromDefaults = function() {\n
+\t\t\tif (_currentInstance.Defaults.Container)\n
+\t\t\t\t_container = _currentInstance.getDOMElement(_currentInstance.Defaults.Container);\n
+\t\t};\n
+\t\t\n
+\t\t/**\n
+\t\t * callback from the current library to tell us to prepare ourselves (attach\n
+\t\t * mouse listeners etc; can\'t do that until the library has provided a bind method)\t\t \n
+\t\t */\n
+\t\tthis.init = function() {\n
+\t\t\tvar _oneType = function(renderer, name, fn) {\n
+\t\t\t\tjsPlumb.Connectors[renderer][name] = function() {\n
+\t\t\t\t\tfn.apply(this, arguments);\n
+\t\t\t\t\tjsPlumb.ConnectorRenderers[renderer].apply(this, arguments);\t\t\n
+\t\t\t\t};\n
+\t\t\t\tjsPlumbUtil.extend(jsPlumb.Connectors[renderer][name], [ fn, jsPlumb.ConnectorRenderers[renderer]]);\n
+\t\t\t};\n
+\n
+\t\t\tif (!jsPlumb.connectorsInitialized) {\n
+\t\t\t\tfor (var i = 0; i < connectorTypes.length; i++) {\n
+\t\t\t\t\tfor (var j = 0; j < rendererTypes.length; j++) {\n
+\t\t\t\t\t\t_oneType(rendererTypes[j], connectorTypes[i][1], connectorTypes[i][0]);\t\t\t\t\t\t\t\t\t\t\t\t\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t}\n
+\t\t\t\tjsPlumb.connectorsInitialized = true;\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\tif (!initialized) {                \n
+\t\t\t\t_getContainerFromDefaults();\t\n
+                _currentInstance.anchorManager = new jsPlumb.AnchorManager({jsPlumbInstance:_currentInstance});                \n
+\t\t\t\t_currentInstance.setRenderMode(_currentInstance.Defaults.RenderMode);  // calling the method forces the capability logic to be run.\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n
+\t\t\t\tinitialized = true;\n
+\t\t\t\t_currentInstance.fire("ready", _currentInstance);\n
+\t\t\t}\n
+\t\t}.bind(this);\t\t\n
+\t\t\n
+\t\tthis.log = log;\n
+\t\tthis.jsPlumbUIComponent = jsPlumbUIComponent;\t\t\n
+\n
+\t\t/*\n
+\t\t * Creates an anchor with the given params.\n
+\t\t * \n
+\t\t * \n
+\t\t * Returns: The newly created Anchor.\n
+\t\t * Throws: an error if a named anchor was not found.\n
+\t\t */\n
+\t\tthis.makeAnchor = function() {\n
+\t\t\tvar pp, _a = function(t, p) {\n
+\t\t\t\tif (jsPlumb.Anchors[t]) return new jsPlumb.Anchors[t](p);\n
+\t\t\t\tif (!_currentInstance.Defaults.DoNotThrowErrors)\n
+\t\t\t\t\tthrow { msg:"jsPlumb: unknown anchor type \'" + t + "\'" };\n
+\t\t\t};\n
+\t\t\tif (arguments.length === 0) return null;\n
+\t\t\tvar specimen = arguments[0], elementId = arguments[1], jsPlumbInstance = arguments[2], newAnchor = null;\t\t\t\n
+\t\t\t// if it appears to be an anchor already...\n
+\t\t\tif (specimen.compute && specimen.getOrientation) return specimen;  //TODO hazy here about whether it should be added or is already added somehow.\n
+\t\t\t// is it the name of an anchor type?\n
+\t\t\telse if (typeof specimen == "string") {\n
+\t\t\t\tnewAnchor = _a(arguments[0], {elementId:elementId, jsPlumbInstance:_currentInstance});\n
+\t\t\t}\n
+\t\t\t// is it an array? it will be one of:\n
+\t\t\t// \t\tan array of [spec, params] - this defines a single anchor, which may be dynamic, but has parameters.\n
+\t\t\t//\t\tan array of arrays - this defines some dynamic anchors\n
+\t\t\t//\t\tan array of numbers - this defines a single anchor.\t\t\t\t\n
+\t\t\telse if (_ju.isArray(specimen)) {\n
+\t\t\t\tif (_ju.isArray(specimen[0]) || _ju.isString(specimen[0])) {\n
+\t\t\t\t\t// if [spec, params] format\n
+\t\t\t\t\tif (specimen.length == 2 && _ju.isObject(specimen[1])) {\n
+\t\t\t\t\t\t// if first arg is a string, its a named anchor with params\n
+\t\t\t\t\t\tif (_ju.isString(specimen[0])) {\n
+\t\t\t\t\t\t\tpp = jsPlumb.extend({elementId:elementId, jsPlumbInstance:_currentInstance}, specimen[1]);\n
+\t\t\t\t\t\t\tnewAnchor = _a(specimen[0], pp);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\t// otherwise first arg is array, second is params. we treat as a dynamic anchor, which is fine\n
+\t\t\t\t\t\t// even if the first arg has only one entry. you could argue all anchors should be implicitly dynamic in fact.\n
+\t\t\t\t\t\telse {\n
+\t\t\t\t\t\t\tpp = jsPlumb.extend({elementId:elementId, jsPlumbInstance:_currentInstance, anchors:specimen[0]}, specimen[1]);\n
+\t\t\t\t\t\t\tnewAnchor = new jsPlumb.DynamicAnchor(pp);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\telse\n
+\t\t\t\t\t\tnewAnchor = new jsPlumb.DynamicAnchor({anchors:specimen, selector:null, elementId:elementId, jsPlumbInstance:jsPlumbInstance});\n
+\n
+\t\t\t\t}\n
+\t\t\t\telse {\n
+\t\t\t\t\tvar anchorParams = {\n
+\t\t\t\t\t\tx:specimen[0], y:specimen[1],\n
+\t\t\t\t\t\torientation : (specimen.length >= 4) ? [ specimen[2], specimen[3] ] : [0,0],\n
+\t\t\t\t\t\toffsets : (specimen.length >= 6) ? [ specimen[4], specimen[5] ] : [ 0, 0 ],\n
+\t\t\t\t\t\telementId:elementId,\n
+                        jsPlumbInstance:jsPlumbInstance,\n
+                        cssClass:specimen.length == 7 ? specimen[6] : null\n
+\t\t\t\t\t};\t\t\t\t\t\t\n
+\t\t\t\t\tnewAnchor = new jsPlumb.Anchor(anchorParams);\n
+\t\t\t\t\tnewAnchor.clone = function() { return new jsPlumb.Anchor(anchorParams); };\t\t\t\t\t\t \t\t\t\t\t\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\tif (!newAnchor.id) newAnchor.id = "anchor_" + _idstamp();\n
+\t\t\treturn newAnchor;\n
+\t\t};\n
+\n
+\t\t/**\n
+\t\t * makes a list of anchors from the given list of types or coords, eg\n
+\t\t * ["TopCenter", "RightMiddle", "BottomCenter", [0, 1, -1, -1] ]\n
+\t\t */\n
+\t\tthis.makeAnchors = function(types, elementId, jsPlumbInstance) {\n
+\t\t\tvar r = [];\n
+\t\t\tfor ( var i = 0, ii = types.length; i < ii; i++) {\n
+\t\t\t\tif (typeof types[i] == "string")\n
+\t\t\t\t\tr.push(jsPlumb.Anchors[types[i]]({elementId:elementId, jsPlumbInstance:jsPlumbInstance}));\n
+\t\t\t\telse if (_ju.isArray(types[i]))\n
+\t\t\t\t\tr.push(_currentInstance.makeAnchor(types[i], elementId, jsPlumbInstance));\n
+\t\t\t}\n
+\t\t\treturn r;\n
+\t\t};\n
+\n
+\t\t/**\n
+\t\t * Makes a dynamic anchor from the given list of anchors (which may be in shorthand notation as strings or dimension arrays, or Anchor\n
+\t\t * objects themselves) and the given, optional, anchorSelector function (jsPlumb uses a default if this is not provided; most people will\n
+\t\t * not need to provide this - i think). \n
+\t\t */\n
+\t\tthis.makeDynamicAnchor = function(anchors, anchorSelector) {\n
+\t\t\treturn new jsPlumb.DynamicAnchor({anchors:anchors, selector:anchorSelector, elementId:null, jsPlumbInstance:_currentInstance});\n
+\t\t};\n
+\t\t\n
+// --------------------- makeSource/makeTarget ---------------------------------------------- \n
+\t\t\n
+\t\tthis.targetEndpointDefinitions = {};\n
+\t\tvar _setEndpointPaintStylesAndAnchor = function(ep, epIndex, _instance) {\n
+\t\t\t\tep.paintStyle = ep.paintStyle ||\n
+\t\t\t\t \t\t\t\t_instance.Defaults.EndpointStyles[epIndex] ||\n
+\t                            _instance.Defaults.EndpointStyle;\n
+\t\t\t\t\t\t\t\t\n
+\t\t\t\tep.hoverPaintStyle = ep.hoverPaintStyle ||\n
+\t                           _instance.Defaults.EndpointHoverStyles[epIndex] ||\n
+\t                           _instance.Defaults.EndpointHoverStyle;                            \n
+\n
+\t\t\t\tep.anchor = ep.anchor ||\n
+\t                      \t_instance.Defaults.Anchors[epIndex] ||\n
+\t                      \t_instance.Defaults.Anchor;\n
+\t\t\t\t\t\n
+\t\t\t\tep.endpoint = ep.endpoint ||\n
+\t\t\t\t\t\t\t  _instance.Defaults.Endpoints[epIndex] ||\n
+\t\t\t\t\t\t\t  _instance.Defaults.Endpoint;\n
+\t\t\t};\n
+\t\t\t\n
+\t\t\t// TODO put all the source stuff inside one parent, keyed by id.\n
+\t\t\tthis.sourceEndpointDefinitions = {};\n
+\t\t\t\n
+\t\t\tvar selectorFilter = function(evt, _el, selector, _instance, negate) {\n
+                var t = evt.target || evt.srcElement, ok = false, \n
+                    sel = _instance.getSelector(_el, selector);\n
+                for (var j = 0; j < sel.length; j++) {\n
+                    if (sel[j] == t) {\n
+                        ok = true;\n
+                        break;\n
+                    }\n
+                }\n
+                return negate ? !ok : ok;\n
+\t        };\n
+\n
+\t\t// see API docs\n
+\t\tthis.makeTarget = function(el, params, referenceParams) {\n
+\n
+\t\t\t// put jsplumb ref into params without altering the params passed in\n
+\t\t\tvar p = jsPlumb.extend({_jsPlumb:this}, referenceParams);\n
+\t\t\tjsPlumb.extend(p, params);\n
+\n
+\t\t\t// calculate appropriate paint styles and anchor from the params given\n
+\t\t\t_setEndpointPaintStylesAndAnchor(p, 1, this);\n
+\n
+\t\t\tvar targetScope = p.scope || _currentInstance.Defaults.Scope,\n
+\t\t\t\tdeleteEndpointsOnDetach = !(p.deleteEndpointsOnDetach === false),\n
+\t\t\t\tmaxConnections = p.maxConnections || -1,\n
+\t\t\t\tonMaxConnections = p.onMaxConnections,\n
+\n
+\t\t\t\t_doOne = function(el) {\n
+\t\t\t\t\t\n
+\t\t\t\t\t// get the element\'s id and store the endpoint definition for it.  jsPlumb.connect calls will look for one of these,\n
+\t\t\t\t\t// and use the endpoint definition if found.\n
+\t\t\t\t\t// decode the info for this element (id and element)\n
+\t\t\t\t\tvar elInfo = _info(el), \n
+\t\t\t\t\t\telid = elInfo.id,\n
+\t\t\t\t\t\tproxyComponent = new jsPlumbUIComponent(p),\n
+\t\t\t\t\t\tdropOptions = jsPlumb.extend({}, p.dropOptions || {});\n
+\n
+\t\t\t\t\t_ensureContainer(elid);\n
+\n
+\t\t\t\t\t// store the definitions keyed against the element id.\n
+\t\t\t\t\t// TODO why not just store inside the element itself?\n
+\t\t\t\t\tthis.targetEndpointDefinitions[elid] = {\n
+\t\t\t\t\t\tdef:p,\n
+\t\t\t\t\t\tuniqueEndpoint:p.uniqueEndpoint,\n
+\t\t\t\t\t\tmaxConnections:maxConnections,\n
+\t\t\t\t\t\tenabled:true\n
+\t\t\t\t\t};\n
+\n
+\t\t\t\t\tvar _drop = function() {\n
+\t\t\t\t\t\tthis.currentlyDragging = false;\n
+\t\t\t\t\t\tvar originalEvent = this.getDropEvent(arguments),\n
+\t\t\t\t\t\t\ttargetCount = this.select({target:elid}).length,\n
+\t\t\t\t\t\t\tdraggable = this.getDOMElement(this.getDragObject(arguments)),\n
+\t\t\t\t\t\t\tid = this.getAttribute(draggable, "dragId"),\n
+\t\t\t\t\t\t\tscope = this.getAttribute(draggable, "originalScope"),\n
+\t\t\t\t\t\t\tjpc = floatingConnections[id],\n
+\t\t\t\t\t\t\tidx = jpc.endpoints[0].isFloating() ? 0 : 1,\n
+\t\t\t\t\t\t\t// this is not necessarily correct. if the source is being dragged,\n
+\t\t\t\t\t\t\t// then the source endpoint is actually the currently suspended endpoint.\n
+\t\t\t\t\t\t\tsource = jpc.endpoints[0],\n
+\t\t\t\t\t\t\t_endpoint = p.endpoint ? jsPlumb.extend({}, p.endpoint) : {},\n
+\t\t\t\t\t\t\tdef = this.targetEndpointDefinitions[elid];\n
+\t\t\t\t\t\t\t\n
+\t\t\t\t\t\tif (!def.enabled || def.maxConnections > 0 && targetCount >= def.maxConnections){\n
+\t\t\t\t\t\t\tif (onMaxConnections) {\n
+\t\t\t\t\t\t\t\t// TODO here we still have the id of the floating element, not the\n
+\t\t\t\t\t\t\t\t// actual target.\n
+\t\t\t\t\t\t\t\tonMaxConnections({\n
+\t\t\t\t\t\t\t\t\telement:elInfo.el,\n
+\t\t\t\t\t\t\t\t\tconnection:jpc\n
+\t\t\t\t\t\t\t\t}, originalEvent);\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\t// unlock the source anchor to allow it to refresh its position if necessary\n
+\t\t\t\t\t\tsource.anchor.locked = false;\n
+\n
+\t\t\t\t\t\t// restore the original scope if necessary (issue 57)\n
+\t\t\t\t\t\tif (scope) this.setDragScope(draggable, scope);\t\t\n
+\n
+\t\t\t\t\t\t// if no suspendedEndpoint and not pending, it is likely there was a drop on two \n
+\t\t\t\t\t\t// elements that are on top of each other. abort.\n
+\t\t\t\t\t\tif (jpc.suspendedEndpoint == null && !jpc.pending)\n
+\t\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t\t\n
+\t\t\t\t\t\t// check if drop is allowed here.\n
+\t\t\t\t\t\t// if the source is being dragged then in fact\n
+\t\t\t\t\t\t// the source and target ids to pass into the drop interceptor are\n
+\t\t\t\t\t\t// source - elid\n
+\t\t\t\t\t\t// target - jpc\'s targetId\n
+\t\t\t\t\t\t// \n
+\t\t\t\t\t\t// otherwise the ids are\n
+\t\t\t\t\t\t// source - jpc.sourceId\n
+\t\t\t\t\t\t// target - elid\n
+\t\t\t\t\t\t//\n
+\t\t\t\t\t\tvar _continue = proxyComponent.isDropAllowed(idx === 0 ? elid : jpc.sourceId, idx === 0 ? jpc.targetId : elid, jpc.scope, jpc, null, idx === 0 ? elInfo.el : jpc.source, idx === 0 ? jpc.target : elInfo.el);\n
+\n
+\t\t\t\t\t\t// reinstate any suspended endpoint; this just puts the connection back into\n
+\t\t\t\t\t\t// a state in which it will report sensible values if someone asks it about\n
+\t\t\t\t\t\t// its target.  we\'re going to throw this connection away shortly so it doesnt matter\n
+\t\t\t\t\t\t// if we manipulate it a bit.\n
+\t\t\t\t\t\tif (jpc.suspendedEndpoint) {\n
+\t\t\t\t\t\t\tjpc[idx ? "targetId" : "sourceId"] = jpc.suspendedEndpoint.elementId;\n
+\t\t\t\t\t\t\tjpc[idx ? "target" : "source"] = jpc.suspendedEndpoint.element;\n
+\t\t\t\t\t\t\tjpc.endpoints[idx] = jpc.suspendedEndpoint;\n
+\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t\t// TODO this and the normal endpoint drop should\n
+\t\t\t\t\t\t\t// be refactored to share more of the common code.\n
+\t\t\t\t\t\t\tvar suspendedElement = jpc.suspendedEndpoint.getElement(), suspendedElementId = jpc.suspendedEndpoint.elementId;\n
+\t\t\t\t\t\t\tfireMoveEvent({\n
+\t\t\t\t\t\t\t\tindex:idx,\n
+\t\t\t\t\t\t\t\toriginalSourceId:idx === 0 ? suspendedElementId : jpc.sourceId,\n
+\t\t\t\t\t\t\t\tnewSourceId:idx === 0 ? elid : jpc.sourceId,\n
+\t\t\t\t\t\t\t\toriginalTargetId:idx == 1 ? suspendedElementId : jpc.targetId,\n
+\t\t\t\t\t\t\t\tnewTargetId:idx == 1 ? elid : jpc.targetId,\n
+\t\t\t\t\t\t\t\tconnection:jpc\n
+\t\t\t\t\t\t\t}, originalEvent);\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\tif (_continue) {\n
+\t\t\t\t\t\t\t// make a new Endpoint for the target, or get it from the cache if uniqueEndpoint\n
+                            // is set.\n
+\t\t\t\t\t\t\tvar _el = this.getElementObject(elInfo.el),\n
+\t\t\t\t\t\t\t\tnewEndpoint = def.endpoint;\n
+\n
+                            // if no cached endpoint, or there was one but it has been cleaned up\n
+                            // (ie. detached), then create a new one.\n
+                            if (newEndpoint == null || newEndpoint._jsPlumb == null)\n
+                                newEndpoint = this.addEndpoint(_el, p);\n
+\n
+\t\t\t\t\t\t\tif (p.uniqueEndpoint) def.endpoint = newEndpoint;  // may of course just store what it just pulled out. that\'s ok.\n
+\t\t\t\t\t\t\t// TODO test options to makeTarget to see if we should do this?\n
+\t\t\t\t\t\t\tnewEndpoint._doNotDeleteOnDetach = false; // reset.\n
+\t\t\t\t\t\t\tnewEndpoint._deleteOnDetach = true;\n
+\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t\t// if the anchor has a \'positionFinder\' set, then delegate to that function to find\n
+\t\t\t\t\t\t\t// out where to locate the anchor.\n
+\t\t\t\t\t\t\tif (newEndpoint.anchor.positionFinder != null) {\n
+\t\t\t\t\t\t\t\tvar dropPosition = this.getUIPosition(arguments, this.getZoom()),\n
+\t\t\t\t\t\t\t\telPosition = _getOffset(_el, this),\n
+\t\t\t\t\t\t\t\telSize = this.getSize(_el),\n
+\t\t\t\t\t\t\t\tap = newEndpoint.anchor.positionFinder(dropPosition, elPosition, elSize, newEndpoint.anchor.constructorParams);\n
+\t\t\t\t\t\t\t\tnewEndpoint.anchor.x = ap[0];\n
+\t\t\t\t\t\t\t\tnewEndpoint.anchor.y = ap[1];\n
+\t\t\t\t\t\t\t\t// now figure an orientation for it..kind of hard to know what to do actually. probably the best thing i can do is to\n
+\t\t\t\t\t\t\t\t// support specifying an orientation in the anchor\'s spec. if one is not supplied then i will make the orientation \n
+\t\t\t\t\t\t\t\t// be what will cause the most natural link to the source: it will be pointing at the source, but it needs to be\n
+\t\t\t\t\t\t\t\t// specified in one axis only, and so how to make that choice? i think i will use whichever axis is the one in which\n
+\t\t\t\t\t\t\t\t// the target is furthest away from the source.\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t\t// change the target endpoint and target element information. really this should be \n
+\t\t\t\t\t\t\t// done on a method on connection\n
+\t\t\t\t\t\t\tjpc[idx ? "target" : "source"] = newEndpoint.element;\n
+\t\t\t\t\t\t\tjpc[idx ? "targetId" : "sourceId"] = newEndpoint.elementId;\n
+\t\t\t\t\t\t\tjpc.endpoints[idx].detachFromConnection(jpc);\n
+\t\t\t\t\t\t\tif (jpc.endpoints[idx]._deleteOnDetach)\n
+\t\t\t\t\t\t\t\tjpc.endpoints[idx].deleteAfterDragStop = true; // tell this endpoint to delet itself after drag stop.\n
+\t\t\t\t\t\t\t// set new endpoint, and configure the settings for endpoints to delete on detach\n
+\t\t\t\t\t\t\tnewEndpoint.addConnection(jpc);\n
+\t\t\t\t\t\t\tjpc.endpoints[idx] = newEndpoint;\n
+\t\t\t\t\t\t\tjpc.deleteEndpointsOnDetach = deleteEndpointsOnDetach;\n
+\n
+\t\t\t\t\t\t\t// inform the anchor manager to update its target endpoint for this connection.\n
+\t\t\t\t\t\t\t// TODO refactor to make this a single method.\n
+\t\t\t\t\t\t\tif (idx == 1)\n
+\t\t\t\t\t\t\t\tthis.anchorManager.updateOtherEndpoint(jpc.sourceId, jpc.suspendedElementId, jpc.targetId, jpc);\n
+\t\t\t\t\t\t\telse\n
+\t\t\t\t\t\t\t\tthis.anchorManager.sourceChanged(jpc.suspendedEndpoint.elementId, jpc.sourceId, jpc);\n
+\n
+\t\t\t\t\t\t\t_finaliseConnection(jpc, null, originalEvent);\n
+\t\t\t\t\t\t\tjpc.pending = false;\n
+\n
+\t\t\t\t\t\t}\t\t\t\t\n
+\t\t\t\t\t\t// if not allowed to drop...\n
+\t\t\t\t\t\telse {\n
+\t\t\t\t\t\t\t// TODO this code is identical (pretty much) to what happens when a connection\n
+\t\t\t\t\t\t\t// dragged from a normal endpoint is in this situation. refactor.\n
+\t\t\t\t\t\t\t// is this an existing connection, and will we reattach?\n
+\t\t\t\t\t\t\t// TODO also this assumes the source needs to detach - is that always valid?\n
+\t\t\t\t\t\t\tif (jpc.suspendedEndpoint) {\n
+\t\t\t\t\t\t\t\tif (jpc.isReattach()) {\n
+\t\t\t\t\t\t\t\t\tjpc.setHover(false);\n
+\t\t\t\t\t\t\t\t\tjpc.floatingAnchorIndex = null;\n
+\t\t\t\t\t\t\t\t\tjpc.suspendedEndpoint.addConnection(jpc);\n
+\t\t\t\t\t\t\t\t\tthis.repaint(source.elementId);\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\telse\n
+\t\t\t\t\t\t\t\t\tsource.detach(jpc, false, true, true, originalEvent);  // otherwise, detach the connection and tell everyone about it.\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}.bind(this);\n
+\t\t\t\t\t\n
+\t\t\t\t\t// wrap drop events as needed and initialise droppable\n
+\t\t\t\t\tvar dropEvent = jsPlumb.dragEvents.drop;\n
+\t\t\t\t\tdropOptions.scope = dropOptions.scope || targetScope;\n
+\t\t\t\t\tdropOptions[dropEvent] = _ju.wrap(dropOptions[dropEvent], _drop);\t\t\t\t\n
+\t\t\t\t\tthis.initDroppable(this.getElementObject(elInfo.el), dropOptions, true);\n
+\t\t\t\t}.bind(this);\n
+\t\t\t\n
+\t\t\t// YUI collection fix\n
+\t\t\tel = _convertYUICollection(el);\t\t\t\n
+\t\t\t// make an array if only given one element\n
+\t\t\tvar inputs = el.length && el.constructor != String ? el : [ el ];\n
+\t\t\t\t\t\t\n
+\t\t\t// register each one in the list.\n
+\t\t\tfor (var i = 0, ii = inputs.length; i < ii; i++) {\t\t\t\t\t\t\t\n
+\t\t\t\t_doOne(inputs[i]);\n
+\t\t\t}\n
+\n
+\t\t\treturn this;\n
+\t\t};\n
+\n
+\t\t// see api docs\n
+\t\tthis.unmakeTarget = function(el, doNotClearArrays) {\n
+\t\t\tvar info = _info(el);\n
+\n
+\t\t\tjsPlumb.destroyDroppable(info.el);\n
+\t\t\t// TODO this is not an exhaustive unmake of a target, since it does not remove the droppable stuff from\n
+\t\t\t// the element.  the effect will be to prevent it from behaving as a target, but it\'s not completely purged.\n
+\t\t\tif (!doNotClearArrays) {\n
+\t\t\t\tdelete this.targetEndpointDefinitions[info.id];\n
+\t\t\t}\n
+\n
+\t\t\treturn this;\n
+\t\t};\t\t\t\t\t\t\n
+\n
+\t    // see api docs\n
+\t\tthis.makeSource = function(el, params, referenceParams) {\n
+\t\t\tvar p = jsPlumb.extend({}, referenceParams);\n
+\t\t\tjsPlumb.extend(p, params);\n
+\t\t\t_setEndpointPaintStylesAndAnchor(p, 0, this);\n
+\t\t\tvar maxConnections = p.maxConnections || -1,\n
+\t\t\t\tonMaxConnections = p.onMaxConnections,\n
+\t\t\t\t_doOne = function(elInfo) {\n
+\t\t\t\t\t// get the element\'s id and store the endpoint definition for it.  jsPlumb.connect calls will look for one of these,\n
+\t\t\t\t\t// and use the endpoint definition if found.\n
+\t\t\t\t\tvar elid = elInfo.id,\n
+\t\t\t\t\t\t_el = this.getElementObject(elInfo.el),\n
+\t\t\t\t\t\t_del = this.getDOMElement(_el),\n
+\t\t\t\t\t\tparentElement = function() {\n
+\t\t\t\t\t\t\treturn p.parent == null ? null : p.parent === "parent" ? elInfo.el.parentNode : _currentInstance.getDOMElement(p.parent);\n
+\t\t\t\t\t\t},\n
+\t\t\t\t\t\tidToRegisterAgainst = p.parent != null ? this.getId(parentElement()) : elid;\n
+\n
+\t\t\t\t\t_ensureContainer(idToRegisterAgainst);\n
+\t\t\t\t\t\n
+\t\t\t\t\tthis.sourceEndpointDefinitions[idToRegisterAgainst] = {\n
+\t\t\t\t\t\tdef:p,\n
+\t\t\t\t\t\tuniqueEndpoint:p.uniqueEndpoint,\n
+\t\t\t\t\t\tmaxConnections:maxConnections,\n
+\t\t\t\t\t\tenabled:true\n
+\t\t\t\t\t};\n
+\t\t\t\t\tvar stopEvent = jsPlumb.dragEvents.stop,\n
+\t\t\t\t\t\tdragEvent = jsPlumb.dragEvents.drag,\n
+\t\t\t\t\t\tdragOptions = jsPlumb.extend({ }, p.dragOptions || {}),\n
+\t\t\t\t\t\texistingDrag = dragOptions.drag,\n
+\t\t\t\t\t\texistingStop = dragOptions.stop,\n
+\t\t\t\t\t\tep = null,\n
+\t\t\t\t\t\tendpointAddedButNoDragYet = false;\n
+\n
+\t\t\t\t\t// set scope if its not set in dragOptions but was passed in in params\n
+\t\t\t\t\tdragOptions.scope = dragOptions.scope || p.scope;\n
+\n
+\t\t\t\t\tdragOptions[dragEvent] = _ju.wrap(dragOptions[dragEvent], function() {\n
+\t\t\t\t\t\tif (existingDrag) existingDrag.apply(this, arguments);\n
+\t\t\t\t\t\tendpointAddedButNoDragYet = false;\n
+\t\t\t\t\t});\n
+\t\t\t\t\t\n
+\t\t\t\t\tdragOptions[stopEvent] = _ju.wrap(dragOptions[stopEvent], function() { \n
+\n
+\t\t\t\t\t\tif (existingStop) existingStop.apply(this, arguments);\n
+\t                    this.currentlyDragging = false;\n
+\t\t\t\t\t\tif (ep._jsPlumb != null) { // if not cleaned up...\n
+\t\t\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t\t// reset the anchor to the anchor that was initially provided. the one we were using to drag\n
+\t\t\t\t\t\t\t// the connection was just a placeholder that was located at the place the user pressed the\n
+\t\t\t\t\t\t\t// mouse button to initiate the drag.\n
+\t\t\t\t\t\t\tvar anchorDef = p.anchor || this.Defaults.Anchor,\n
+\t\t\t\t\t\t\t\toldAnchor = ep.anchor,\n
+\t\t\t\t\t\t\t\toldConnection = ep.connections[0],\n
+\t\t\t\t\t\t\t\tnewAnchor = this.makeAnchor(anchorDef, elid, this),\n
+\t\t\t\t\t\t\t\t_el = ep.element;\n
+\n
+\t\t\t\t\t\t\t// if the anchor has a \'positionFinder\' set, then delegate to that function to find\n
+\t\t\t\t\t\t\t// out where to locate the anchor. issue 117.\n
+\t\t\t\t\t\t\tif (newAnchor.positionFinder != null) {\n
+\t\t\t\t\t\t\t\tvar elPosition = _getOffset(_el, this),\n
+\t\t\t\t\t\t\t\t\telSize = this.getSize(_el),\n
+\t\t\t\t\t\t\t\t\tdropPosition = { left:elPosition.left + (oldAnchor.x * elSize[0]), top:elPosition.top + (oldAnchor.y * elSize[1]) },\n
+\t\t\t\t\t\t\t\t\tap = newAnchor.positionFinder(dropPosition, elPosition, elSize, newAnchor.constructorParams);\n
+\n
+\t\t\t\t\t\t\t\tnewAnchor.x = ap[0];\n
+\t\t\t\t\t\t\t\tnewAnchor.y = ap[1];\n
+\t\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\t\tep.setAnchor(newAnchor, true);\n
+\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t\tif (p.parent) {\n
+\t\t\t\t\t\t\t\tvar parent = parentElement();\n
+\t\t\t\t\t\t\t\tif (parent) {\t\n
+\t\t\t\t\t\t\t\t\tvar potentialParent = p.container || _container;\n
+\t\t\t\t\t\t\t\t\tep.setElement(parent, potentialParent);\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t\tep.repaint();\n
+\t\t\t\t\t\t\tthis.repaint(ep.elementId);\n
+\t\t\t\t\t\t\tthis.repaint(oldConnection.targetId);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}.bind(this));\n
+\t\t\t\t\t\n
+\t\t\t\t\t// when the user presses the mouse, add an Endpoint, if we are enabled.\n
+\t\t\t\t\tvar mouseDownListener = function(e) {\n
+\t\t\t\t\t\tvar evt = this.getOriginalEvent(e);\n
+\t\t\t\t\t\tvar def = this.sourceEndpointDefinitions[idToRegisterAgainst];\n
+\t\t\t\t\t\telid = this.getId(this.getDOMElement(_el)); // elid might have changed since this method was called to configure the element.\n
+\t\t\t\t\t\t\n
+\t\t\t\t\t\t// if disabled, return.\n
+\t\t\t\t\t\tif (!def.enabled) return;\n
+\t                    \n
+\t                    // if a filter was given, run it, and return if it says no.\n
+\t\t\t\t\t\tif (p.filter) {\n
+\t\t\t\t\t\t\tvar r = jsPlumbUtil.isString(p.filter) ? selectorFilter(evt, _el, p.filter, this, p.filterExclude) : p.filter(evt, _el);\n
+\t\t\t\t\t\t\tif (r === false) return;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\n
+\t\t\t\t\t\t// if maxConnections reached\n
+\t\t\t\t\t\tvar sourceCount = this.select({source:idToRegisterAgainst}).length;\n
+\t\t\t\t\t\tif (def.maxConnections >= 0 && sourceCount >= def.maxConnections) {\n
+\t\t\t\t\t\t\tif (onMaxConnections) {\n
+\t\t\t\t\t\t\t\tonMaxConnections({\n
+\t\t\t\t\t\t\t\t\telement:_el,\n
+\t\t\t\t\t\t\t\t\tmaxConnections:maxConnections\n
+\t\t\t\t\t\t\t\t}, e);\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\t// find the position on the element at which the mouse was pressed; this is where the endpoint \n
+\t\t\t\t\t\t// will be located.\n
+\t\t\t\t\t\tvar elxy = jsPlumbAdapter.getPositionOnElement(evt, _del, _zoom), pelxy = elxy;\n
+\t\t\t\t\t\t// for mootools/YUI..this parent stuff should be deprecated.\n
+\t\t\t\t\t\tif (p.parent) {\n
+\t\t\t\t\t\t\tpelxy = jsPlumbAdapter.getPositionOnElement(evt, parentElement(), _zoom);\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t// we need to override the anchor in here, and force \'isSource\', but we don\'t want to mess with\n
+\t\t\t\t\t\t// the params passed in, because after a connection is established we\'re going to reset the endpoint\n
+\t\t\t\t\t\t// to have the anchor we were given.\n
+\t\t\t\t\t\tvar tempEndpointParams = {};\n
+\t\t\t\t\t\tjsPlumb.extend(tempEndpointParams, p);\n
+\t\t\t\t\t\ttempEndpointParams.isSource = true;\n
+\t\t\t\t\t\ttempEndpointParams.anchor = [ elxy[0], elxy[1] , 0,0];\n
+\t\t\t\t\t\ttempEndpointParams.parentAnchor = [ pelxy[0], pelxy[1], 0, 0 ];\n
+\t\t\t\t\t\ttempEndpointParams.dragOptions = dragOptions;\n
+\t\t\t\t\t\tep = this.addEndpoint(elid, tempEndpointParams);\n
+\t\t\t\t\t\tendpointAddedButNoDragYet = true;\n
+\t\t\t\t\t\tep.endpointWillMoveTo = p.parent ? parentElement() : null;\n
+\t\t\t\t\t\t// TODO test options to makeSource to see if we should do this?\n
+\t\t\t\t\t\tep._doNotDeleteOnDetach = false; // reset.\n
+\t\t\t\t\t\tep._deleteOnDetach = true;\n
+\n
+\t                    var _delTempEndpoint = function() {\n
+\t\t\t\t\t\t\t// this mouseup event is fired only if no dragging occurred, by jquery and yui, but for mootools\n
+\t\t\t\t\t\t\t// it is fired even if dragging has occurred, in which case we would blow away a perfectly\n
+\t\t\t\t\t\t\t// legitimate endpoint, were it not for this check.  the flag is set after adding an\n
+\t\t\t\t\t\t\t// endpoint and cleared in a drag listener we set in the dragOptions above.\n
+\t\t\t\t\t\t\tif(endpointAddedButNoDragYet) {\n
+\t\t\t\t\t\t\t\t endpointAddedButNoDragYet = false;\n
+\t\t\t\t\t\t\t\t_currentInstance.deleteEndpoint(ep);\n
+\t                        }\n
+\t\t\t\t\t\t};\n
+\n
+\t\t\t\t\t\t_currentInstance.registerListener(ep.canvas, "mouseup", _delTempEndpoint);\n
+\t                    _currentInstance.registerListener(_el, "mouseup", _delTempEndpoint);\n
+\t\t\t\t\t\t\n
+\t\t\t\t\t\t// and then trigger its mousedown event, which will kick off a drag, which will start dragging\n
+\t\t\t\t\t\t// a new connection from this endpoint.\n
+\t\t\t\t\t\t_currentInstance.trigger(ep.canvas, "mousedown", e);\n
+\n
+\t\t\t\t\t\tjsPlumbUtil.consume(e);\n
+\t\t\t\t\t\t\n
+\t\t\t\t\t}.bind(this);\n
+\t               \n
+\t                // register this on jsPlumb so that it can be cleared by a reset.\n
+\t                this.registerListener(_el, "mousedown", mouseDownListener);\n
+\t                this.sourceEndpointDefinitions[idToRegisterAgainst].trigger = mouseDownListener;\n
+\n
+\t                // lastly, if a filter was provided, set it as a dragFilter on the element,\n
+\t                // to prevent the element drag function from kicking in when we want to\n
+\t                // drag a new connection\n
+\t                if (p.filter && jsPlumbUtil.isString(p.filter)) {\n
+\t                \t_currentInstance.setDragFilter(_el, p.filter);\n
+\t                }\n
+\t\t\t\t}.bind(this);\n
+\t\t\t\n
+\t\t\tel = _convertYUICollection(el);\n
+\t\t\t\n
+\t\t\tvar inputs = el.length && el.constructor != String ? el : [ el ];\n
+\t\t\tfor (var i = 0, ii = inputs.length; i < ii; i++) {\n
+\t\t\t\t_doOne(_info(inputs[i]));\n
+\t\t\t}\n
+\n
+\t\t\treturn this;\n
+\t\t};\n
+\t\n
+\t\t// see api docs\t\t\n
+\t\tthis.unmakeSource = function(el, doNotClearArrays) {\n
+\t\t\tvar info = _info(el),\n
+\t\t\t\tmouseDownListener = this.sourceEndpointDefinitions[info.id].trigger;\n
+\t\t\t\n
+\t\t\tif (mouseDownListener) \n
+\t\t\t\t_currentInstance.unregisterListener(info.el, "mousedown", mouseDownListener);\n
+\n
+\t\t\tif (!doNotClearArrays) {\n
+\t\t\t\tdelete this.sourceEndpointDefinitions[info.id];\n
+\t\t\t}\n
+\n
+\t\t\treturn this;\n
+\t\t};\n
+\n
+\t\t// see api docs\n
+\t\tthis.unmakeEverySource = function() {\n
+\t\t\tfor (var i in this.sourceEndpointDefinitions)\n
+\t\t\t\t_currentInstance.unmakeSource(i, true);\n
+\n
+\t\t\tthis.sourceEndpointDefinitions = {};\n
+\t\t\treturn this;\n
+\t\t};\n
+\t\t\n
+\t\t// see api docs\n
+\t\tthis.unmakeEveryTarget = function() {\n
+\t\t\tfor (var i in this.targetEndpointDefinitions)\n
+\t\t\t\t_currentInstance.unmakeTarget(i, true);\n
+\t\t\t\n
+\t\t\tthis.targetEndpointDefinitions = {};\n
+\t\t\treturn this;\n
+\t\t};\n
+\n
+\t\t// does the work of setting a source enabled or disabled.\n
+\t\tvar _setEnabled = function(type, el, state, toggle) {\n
+\t\t\tvar a = type == "source" ? this.sourceEndpointDefinitions : this.targetEndpointDefinitions;\n
+\t\t\tel = _convertYUICollection(el);\n
+\n
+\t\t\tif (_ju.isString(el)) a[el].enabled = toggle ? !a[el].enabled : state;\n
+\t\t\telse if (el.length) {\t\t\t\t\n
+\t\t\t\tfor (var i = 0, ii = el.length; i < ii; i++) {\n
+\t\t\t\t\tvar info = _info(el[i]);\n
+\t\t\t\t\tif (a[info.id])\n
+\t\t\t\t\t\ta[info.id].enabled = toggle ? !a[info.id].enabled : state;\n
+\t\t\t\t}\n
+\t\t\t}\t\n
+\t\t\t// otherwise a DOM element\n
+\t\t\telse {\n
+\t\t\t\tvar id = _info(el).id;\n
+\t\t\t\ta[id].enabled = toggle ? !a[id].enabled : state;\n
+\t\t\t}\n
+\t\t\treturn this;\n
+\t\t}.bind(this);\n
+\t\t\n
+\t\tvar _first = function(el, fn) {\n
+\t\t\tel = _convertYUICollection(el);\n
+\t\t\tif (_ju.isString(el) || !el.length) \n
+\t\t\t\treturn fn.apply(this, [ el ]);\n
+\t\t\telse if (el.length) \n
+\t\t\t\treturn fn.apply(this, [ el[0] ]);\n
+\t\t\t\t\n
+\t\t}.bind(this);\n
+\n
+\t\tthis.toggleSourceEnabled = function(el) {\n
+\t\t\t_setEnabled("source", el, null, true);\n
+\t\t\treturn this.isSourceEnabled(el);\n
+\t\t};\n
+\n
+\t\tthis.setSourceEnabled = function(el, state) { return _setEnabled("source", el, state); };\n
+\t\tthis.isSource = function(el) { \n
+\t\t\treturn _first(el, function(_el) { \n
+\t\t\t\treturn this.sourceEndpointDefinitions[_info(_el).id] != null; \n
+\t\t\t});\n
+\t\t};\n
+\t\tthis.isSourceEnabled = function(el) { \n
+\t\t\treturn _first(el, function(_el) {\n
+\t\t\t\tvar sep = this.sourceEndpointDefinitions[_info(_el).id];\n
+\t\t\t\treturn sep && sep.enabled === true;\n
+\t\t\t});\n
+\t\t};\n
+\n
+\t\tthis.toggleTargetEnabled = function(el) {\n
+\t\t\t_setEnabled("target", el, null, true);\n
+\t\t\treturn this.isTargetEnabled(el);\n
+\t\t};\n
+\t\t\n
+\t\tthis.isTarget = function(el) { \n
+\t\t\treturn _first(el, function(_el) {\n
+\t\t\t\treturn this.targetEndpointDefinitions[_info(_el).id] != null; \n
+\t\t\t});\n
+\t\t};\n
+\t\tthis.isTargetEnabled = function(el) { \n
+\t\t\treturn _first(el, function(_el) {\n
+\t\t\t\tvar tep = this.targetEndpointDefinitions[_info(_el).id];\n
+\t\t\t\treturn tep && tep.enabled === true;\n
+\t\t\t});\n
+\t\t};\n
+\t\tthis.setTargetEnabled = function(el, state) { return _setEnabled("target", el, state); };\n
+\n
+// --------------------- end makeSource/makeTarget ---------------------------------------------- \t\t\t\t\n
+\t\t\t\t\n
+\t\tthis.ready = function(fn) {\n
+\t\t\t_currentInstance.bind("ready", fn);\n
+\t\t};\n
+\n
+\t\t// repaint some element\'s endpoints and connections\n
+\t\tthis.repaint = function(el, ui, timestamp) {\n
+\t\t\t// support both lists...\n
+\t\t\tif (typeof el == \'object\' && el.length)\n
+\t\t\t\tfor ( var i = 0, ii = el.length; i < ii; i++) {\n
+\t\t\t\t\t_draw(el[i], ui, timestamp);\n
+\t\t\t\t}\n
+\t\t\telse // ...and single strings.\n
+\t\t\t\t_draw(el, ui, timestamp);\n
+\t\t\t\t\n
+\t\t\treturn _currentInstance;\n
+\t\t};\n
+\n
+\t\t// repaint every endpoint and connection.\n
+\t\tthis.repaintEverything = function(clearEdits) {\t\n
+\t\t\t// TODO this timestamp causes continuous anchors to not repaint properly.\n
+\t\t\t// fix this. do not just take out the timestamp. it runs a lot faster with \n
+\t\t\t// the timestamp included.\n
+\t\t\t//var timestamp = null;\n
+\t\t\tvar timestamp = _timestamp();\n
+\t\t\tfor ( var elId in endpointsByElement) {\n
+\t\t\t\t_draw(elId, null, timestamp, clearEdits);\n
+\t\t\t}\n
+\t\t\treturn this;\n
+\t\t};\n
+\n
+\t\tthis.removeAllEndpoints = function(el, recurse) {\n
+            var _one = function(_el) {\n
+                var info = _info(_el),\n
+                    ebe = endpointsByElement[info.id],\n
+                    i, ii;\n
+\n
+                if (ebe) {\n
+                    for ( i = 0, ii = ebe.length; i < ii; i++) \n
+                        _currentInstance.deleteEndpoint(ebe[i]);\n
+                }\n
+                delete endpointsByElement[info.id];\n
+                \n
+                if (recurse) {\n
+                    if (info.el && info.el.nodeType != 3 && info.el.nodeType != 8 ) {\n
+                        for ( i = 0, ii = info.el.childNodes.length; i < ii; i++) {\n
+                            _one(info.el.childNodes[i]);\n
+                        }\n
+                    }\n
+                }\n
+                \n
+            };\n
+            _one(el);\n
+\t\t\treturn this;\n
+\t\t};\n
+                    \n
+        /**\n
+        * Remove the given element, including cleaning up all endpoints registered for it.\n
+        * This is exposed in the public API but also used internally by jsPlumb when removing the\n
+        * element associated with a connection drag.\n
+        */\n
+        this.remove = function(el, doNotRepaint) {\n
+        \tvar info = _info(el);        \t\n
+            _currentInstance.doWhileSuspended(function() {\n
+            \t_currentInstance.removeAllEndpoints(info.id, true);\n
+            \t_currentInstance.dragManager.elementRemoved(info.id);\n
+            \tdelete floatingConnections[info.id];     \n
+            \t_currentInstance.anchorManager.clearFor(info.id);\t\t\t\t\t\t\n
+            \t_currentInstance.anchorManager.removeFloatingConnection(info.id);\n
+            }, doNotRepaint === false);\n
+            if (info.el) _currentInstance.removeElement(info.el);\n
+\t\t\treturn _currentInstance;\n
+        };\n
+\n
+\t\tvar _registeredListeners = {},\n
+\t\t\t_unbindRegisteredListeners = function() {\n
+\t\t\t\tfor (var i in _registeredListeners) {\n
+\t\t\t\t\tfor (var j = 0, jj = _registeredListeners[i].length; j < jj; j++) {\n
+\t\t\t\t\t\tvar info = _registeredListeners[i][j];\n
+\t\t\t\t\t\t_currentInstance.off(info.el, info.event, info.listener);\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\t_registeredListeners = {};\n
+\t\t\t};\n
+\n
+        // internal register listener method.  gives us a hook to clean things up\n
+        // with if the user calls jsPlumb.reset.\n
+        this.registerListener = function(el, type, listener) {\n
+            _currentInstance.on(el, type, listener);\n
+            jsPlumbUtil.addToList(_registeredListeners, type, {el:el, event:type, listener:listener});\n
+        };\n
+\n
+        this.unregisterListener = function(el, type, listener) {\n
+        \t_currentInstance.off(el, type, listener);\n
+        \tjsPlumbUtil.removeWithFunction(_registeredListeners, function(rl) {\n
+        \t\treturn rl.type == type && rl.listener == listener;\n
+        \t});\n
+        };\n
+\t\t\n
+\t\tthis.reset = function() {\n
+\t\t\t_currentInstance.deleteEveryEndpoint();\n
+\t\t\t_currentInstance.unbind();\n
+\t\t\tthis.targetEndpointDefinitions = {};\n
+\t\t\tthis.sourceEndpointDefinitions = {};\n
+\t\t\tconnections.splice(0);\n
+\t\t\t_unbindRegisteredListeners();\n
+\t\t\t_currentInstance.anchorManager.reset();\n
+\t\t\tif (!jsPlumbAdapter.headless)\n
+\t\t\t\t_currentInstance.dragManager.reset();\n
+\t\t};\n
+\t\t\n
+\n
+\t\tthis.setDefaultScope = function(scope) {\n
+\t\t\tDEFAULT_SCOPE = scope;\n
+\t\t\treturn _currentInstance;\n
+\t\t};\n
+\n
+\t\t// sets whether or not some element should be currently draggable.\n
+\t\tthis.setDraggable = _setDraggable;\n
+\n
+\t\t// sets the id of some element, changing whatever we need to to keep track.\n
+\t\tthis.setId = function(el, newId, doNotSetAttribute) {\n
+\t\t\t// \n
+\t\t\tvar id;\n
+\n
+\t\t\tif (jsPlumbUtil.isString(el)) {\n
+\t\t\t\tid = el;\n
+\t\t\t}\n
+\t\t\telse {\n
+\t\t\t\tel = this.getDOMElement(el);\n
+\t\t\t\tid = this.getId(el);\n
+\t\t\t}\n
+\n
+\t\t\tvar sConns = this.getConnections({source:id, scope:\'*\'}, true),\n
+\t\t\t\ttConns = this.getConnections({target:id, scope:\'*\'}, true);\n
+\n
+\t\t\tnewId = "" + newId;\n
+\n
+\t\t\tif (!doNotSetAttribute) {\n
+\t\t\t\tel = this.getDOMElement(id);\n
+\t\t\t\tthis.setAttribute(el, "id", newId);\n
+\t\t\t}\n
+\t\t\telse\n
+\t\t\t\tel = this.getDOMElement(newId);\n
+\n
+\t\t\tendpointsByElement[newId] = endpointsByElement[id] || [];\n
+\t\t\tfor (var i = 0, ii = endpointsByElement[newId].length; i < ii; i++) {\n
+\t\t\t\tendpointsByElement[newId][i].setElementId(newId);\n
+\t\t\t\tendpointsByElement[newId][i].setReferenceElement(el);\n
+\t\t\t}\n
+\t\t\tdelete endpointsByElement[id];\n
+\n
+\t\t\tthis.anchorManager.changeId(id, newId);\n
+\t\t\tif (this.dragManager) this.dragManager.changeId(id, newId);\n
+\n
+\t\t\tvar _conns = function(list, epIdx, type) {\n
+\t\t\t\tfor (var i = 0, ii = list.length; i < ii; i++) {\n
+\t\t\t\t\tlist[i].endpoints[epIdx].setElementId(newId);\n
+\t\t\t\t\tlist[i].endpoints[epIdx].setReferenceElement(el);\n
+\t\t\t\t\tlist[i][type + "Id"] = newId;\n
+\t\t\t\t\tlist[i][type] = el;\n
+\t\t\t\t}\n
+\t\t\t};\n
+\t\t\t_conns(sConns, 0, "source");\n
+\t\t\t_conns(tConns, 1, "target");\n
+\n
+\t\t\tthis.repaint(newId);\n
+\t\t};\n
+\n
+\t\tthis.setDebugLog = function(debugLog) {\n
+\t\t\tlog = debugLog;\n
+\t\t};\n
+\n
+\t\tthis.setSuspendDrawing = function(val, repaintAfterwards) {\n
+\t\t\tvar curVal = _suspendDrawing;\n
+\t\t    _suspendDrawing = val;\n
+\t\t\t\tif (val) _suspendedAt = new Date().getTime(); else _suspendedAt = null;\n
+\t\t    if (repaintAfterwards) this.repaintEverything();\n
+\t\t    return curVal;\n
+\t\t};\n
+\n
+        // returns whether or not drawing is currently suspended.\n
+\t\tthis.isSuspendDrawing = function() {\n
+\t\t\treturn _suspendDrawing;\n
+\t\t};\n
+\n
+        // return timestamp for when drawing was suspended.\n
+        this.getSuspendedAt = function() { return _suspendedAt; };\n
+\n
+        this.doWhileSuspended = function(fn, doNotRepaintAfterwards) {\n
+        \tvar _wasSuspended = this.isSuspendDrawing();\n
+        \tif (!_wasSuspended)\n
+\t\t\t\tthis.setSuspendDrawing(true);\n
+\t\t\ttry {\n
+\t\t\t\tfn();\n
+\t\t\t}\n
+\t\t\tcatch (e) {\n
+\t\t\t\t_ju.log("Function run while suspended failed", e);\n
+\t\t\t}\n
+\t\t\tif (!_wasSuspended)\n
+\t\t\t\tthis.setSuspendDrawing(false, !doNotRepaintAfterwards);\n
+\t\t};\n
+\n
+\t\tthis.getOffset = function(elId) { return offsets[elId]; };\n
+\t\tthis.getCachedData = _getCachedData;\n
+\t\tthis.timestamp = _timestamp;\n
+\t\tthis.setRenderMode = function(mode) {\n
+\t\t\tif (mode !== jsPlumb.SVG && mode !== jsPlumb.VML) throw new TypeError("Render mode [" + mode + "] not supported");\n
+\t\t\trenderMode = jsPlumbAdapter.setRenderMode(mode);\n
+\t\t\treturn renderMode;\n
+\t\t};\n
+\t\tthis.getRenderMode = function() { return renderMode; };\n
+\t\tthis.show = function(el, changeEndpoints) {\n
+\t\t\t_setVisible(el, "block", changeEndpoints);\n
+\t\t\treturn _currentInstance;\n
+\t\t};\n
+\n
+\t\t// TODO: update this method to return the current state.\n
+\t\tthis.toggleVisible = _toggleVisible;\n
+\t\tthis.toggleDraggable = _toggleDraggable;\n
+\t\tthis.addListener = this.bind;\n
+\n
+\t\tif (!jsPlumbAdapter.headless) {\n
+\t\t\t_currentInstance.dragManager = jsPlumbAdapter.getDragManager(_currentInstance);\n
+\t\t\t_currentInstance.recalculateOffsets = _currentInstance.dragManager.updateOffsets;\n
+\t\t}\n
+\t};\n
+\n
+    jsPlumbUtil.extend(jsPlumbInstance, jsPlumbUtil.EventGenerator, {\n
+    \tsetAttribute : function(el, a, v) {\n
+    \t\tthis.setAttribute(el, a, v);\n
+    \t},\n
+    \tgetAttribute : function(el, a) {\n
+    \t\treturn this.getAttribute(jsPlumb.getDOMElement(el), a);\n
+    \t},    \t\n
+    \tregisterConnectionType : function(id, type) {\n
+    \t\tthis._connectionTypes[id] = jsPlumb.extend({}, type);\n
+    \t},    \t\n
+    \tregisterConnectionTypes : function(types) {\n
+    \t\tfor (var i in types)\n
+    \t\t\tthis._connectionTypes[i] = jsPlumb.extend({}, types[i]);\n
+    \t},\n
+    \tregisterEndpointType : function(id, type) {\n
+    \t\tthis._endpointTypes[id] = jsPlumb.extend({}, type);\n
+    \t},    \t\n
+    \tregisterEndpointTypes : function(types) {\n
+    \t\tfor (var i in types)\n
+    \t\t\tthis._endpointTypes[i] = jsPlumb.extend({}, types[i]);\n
+    \t},    \t\n
+    \tgetType : function(id, typeDescriptor) {\n
+    \t\treturn typeDescriptor ===  "connection" ? this._connectionTypes[id] : this._endpointTypes[id];\n
+    \t},\n
+    \tsetIdChanged : function(oldId, newId) {\n
+    \t\tthis.setId(oldId, newId, true);\n
+    \t},\n
+    \t// set parent: change the parent for some node and update all the registrations we need to.\n
+    \tsetParent : function(el, newParent) {\n
+    \t\tvar _el = this.getElementObject(el),\n
+    \t\t\t_dom = this.getDOMElement(_el),\n
+    \t\t\t_id = this.getId(_dom),\n
+    \t\t\t_pel = this.getElementObject(newParent),\n
+    \t\t\t_pdom = this.getDOMElement(_pel),\n
+    \t\t\t_pid = this.getId(_pdom);\n
+\n
+    \t\t_dom.parentNode.removeChild(_dom);\n
+    \t\t_pdom.appendChild(_dom);\n
+    \t\tthis.dragManager.setParent(_el, _id, _pel, _pid);\n
+    \t},\n
+\t\t/**\n
+\t\t * gets the size for the element, in an array : [ width, height ].\n
+\t\t */\n
+\t\tgetSize : function(el) {\n
+\t\t\treturn [ el.offsetWidth, el.offsetHeight ];\n
+\t\t},\n
+\t\tgetWidth : function(el) {\n
+\t\t\treturn el.offsetWidth;\n
+\t\t},\n
+\t\tgetHeight : function(el) {\n
+\t\t\treturn el.offsetHeight;\n
+\t\t},\n
+\t\textend : function(o1, o2, names) {\n
+\t\t\tvar i;\n
+\t\t\tif (names) {\n
+\t\t\t\tfor (i = 0; i < names.length; i++)\n
+\t\t\t\t\to1[names[i]] = o2[names[i]];\n
+\t\t\t}\n
+\t\t\telse\n
+\t\t\t\tfor (i in o2) o1[i] = o2[i];\n
+\t\t\treturn o1;\n
+\t\t}\n
+    }, jsPlumbAdapter);\n
+\n
+// --------------------- static instance + AMD registration -------------------------------------------\t\n
+\t\n
+// create static instance and assign to window if window exists.\t\n
+\tvar jsPlumb = new jsPlumbInstance();\n
+\t// register on window if defined (lets us run on server)\n
+\tif (typeof window != \'undefined\') window.jsPlumb = jsPlumb;\t\n
+\t// add \'getInstance\' method to static instance\n
+\tjsPlumb.getInstance = function(_defaults) {\n
+\t\tvar j = new jsPlumbInstance(_defaults);\n
+\t\tj.init();\n
+\t\treturn j;\n
+\t};\n
+// maybe register static instance as an AMD module, and getInstance method too.\n
+\tif ( typeof define === "function") {\n
+\t\tdefine( "jsplumb", [], function () { return jsPlumb; } );\n
+\t\tdefine( "jsplumbinstance", [], function () { return jsPlumb.getInstance(); } );\n
+\t}\n
+ // CommonJS \n
+\tif (typeof exports !== \'undefined\') {\n
+      exports.jsPlumb = jsPlumb;\n
+  \t}\n
+\t\n
+\t\n
+// --------------------- end static instance + AMD registration -------------------------------------------\t\t\n
+\t\n
+})();\n
+\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the code for Endpoints.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+;(function() {\n
+    \n
+    "use strict";\n
+        \n
+    // create the drag handler for a connection\n
+    var _makeConnectionDragHandler = function(placeholder, _jsPlumb) {\n
+        var stopped = false;\n
+        return {\n
+            drag : function() {\n
+                if (stopped) {\n
+                    stopped = false;\n
+                    return true;\n
+                }\n
+                var _ui = jsPlumb.getUIPosition(arguments, _jsPlumb.getZoom());\n
+        \n
+                if (placeholder.element) {\n
+                    jsPlumbAdapter.setPosition(placeholder.element, _ui);                    \n
+                    _jsPlumb.repaint(placeholder.element, _ui);\n
+                }\n
+            },\n
+            stopDrag : function() {\n
+                stopped = true;\n
+            }\n
+        };\n
+    };\n
+        \n
+    // creates a placeholder div for dragging purposes, adds it to the DOM, and pre-computes its offset.    \n
+    var _makeDraggablePlaceholder = function(placeholder, _jsPlumb) {\n
+        var n = document.createElement("div");\n
+        n.style.position = "absolute";\n
+        var parent = _jsPlumb.getContainer() || document.body;\n
+        parent.appendChild(n);\n
+        var id = _jsPlumb.getId(n);\n
+        _jsPlumb.updateOffset( { elId : id });\n
+        // create and assign an id, and initialize the offset.\n
+        placeholder.id = id;\n
+        placeholder.element = n;\n
+    };\n
+    \n
+    // create a floating endpoint (for drag connections)\n
+    var _makeFloatingEndpoint = function(paintStyle, referenceAnchor, endpoint, referenceCanvas, sourceElement, _jsPlumb, _newEndpoint) {\t\t\t\n
+        var floatingAnchor = new jsPlumb.FloatingAnchor( { reference : referenceAnchor, referenceCanvas : referenceCanvas, jsPlumbInstance:_jsPlumb });\n
+        //setting the scope here should not be the way to fix that mootools issue.  it should be fixed by not\n
+        // adding the floating endpoint as a droppable.  that makes more sense anyway!\n
+        return _newEndpoint({ paintStyle : paintStyle, endpoint : endpoint, anchor : floatingAnchor, source : sourceElement, scope:"__floating" });\n
+    };\n
+\n
+    var typeParameters = [ "connectorStyle", "connectorHoverStyle", "connectorOverlays",\n
+                "connector", "connectionType", "connectorClass", "connectorHoverClass" ];\n
+\n
+    // a helper function that tries to find a connection to the given element, and returns it if so. if elementWithPrecedence is null,\n
+    // or no connection to it is found, we return the first connection in our list.\n
+    var findConnectionToUseForDynamicAnchor = function(ep, elementWithPrecedence) {\n
+        var idx = 0;\n
+        if (elementWithPrecedence != null) {\n
+            for (var i = 0; i < ep.connections.length; i++) {\n
+                if (ep.connections[i].sourceId == elementWithPrecedence || ep.connections[i].targetId == elementWithPrecedence) {\n
+                    idx = i;\n
+                    break;\n
+                }\n
+            }\n
+        }\n
+        \n
+        return ep.connections[idx];\n
+    };\n
+\n
+    var findConnectionIndex = function(conn, ep) {\n
+        return jsPlumbUtil.findWithFunction(ep.connections, function(c) { return c.id == conn.id; });\n
+    };\n
+\n
+    jsPlumb.Endpoint = function(params) {\n
+        var _jsPlumb = params._jsPlumb,\n
+            _att = jsPlumbAdapter.getAttribute,\n
+            _gel = jsPlumb.getElementObject,            \n
+            _ju = jsPlumbUtil,            \n
+            _newConnection = params.newConnection,\n
+            _newEndpoint = params.newEndpoint,\n
+            _finaliseConnection = params.finaliseConnection,\n
+            _fireDetachEvent = params.fireDetachEvent,\n
+            _fireMoveEvent = params.fireMoveEvent,\n
+            floatingConnections = params.floatingConnections;\n
+        \n
+        this.idPrefix = "_jsplumb_e_";\t\t\t\n
+        this.defaultLabelLocation = [ 0.5, 0.5 ];\n
+        this.defaultOverlayKeys = ["Overlays", "EndpointOverlays"];\n
+        OverlayCapableJsPlumbUIComponent.apply(this, arguments);        \n
+        \n
+// TYPE\t\t\n
+                \n
+        this.getDefaultType = function() {\t\t\t\t\t\t\t\t\n
+            return {\n
+                parameters:{},\n
+                scope:null,\n
+                maxConnections:this._jsPlumb.instance.Defaults.MaxConnections,\n
+                paintStyle:this._jsPlumb.instance.Defaults.EndpointStyle || jsPlumb.Defaults.EndpointStyle,\n
+                endpoint:this._jsPlumb.instance.Defaults.Endpoint || jsPlumb.Defaults.Endpoint,\n
+                hoverPaintStyle:this._jsPlumb.instance.Defaults.EndpointHoverStyle || jsPlumb.Defaults.EndpointHoverStyle,\t\t\t\t\n
+                overlays:this._jsPlumb.instance.Defaults.EndpointOverlays || jsPlumb.Defaults.EndpointOverlays,\n
+                connectorStyle:params.connectorStyle,\t\t\t\t\n
+                connectorHoverStyle:params.connectorHoverStyle,\n
+                connectorClass:params.connectorClass,\n
+                connectorHoverClass:params.connectorHoverClass,\n
+                connectorOverlays:params.connectorOverlays,\n
+                connector:params.connector,\n
+                connectorTooltip:params.connectorTooltip\n
+            };\n
+        };\n
+        \t\t\t\n
+// END TYPE\n
+            \n
+        this._jsPlumb.enabled = !(params.enabled === false);\n
+        this._jsPlumb.visible = true;        \n
+        this.element = jsPlumb.getDOMElement(params.source);  \n
+        this._jsPlumb.uuid = params.uuid;\n
+        this._jsPlumb.floatingEndpoint = null;  \n
+        var inPlaceCopy = null;\n
+        if (this._jsPlumb.uuid) params.endpointsByUUID[this._jsPlumb.uuid] = this;\n
+        this.elementId = params.elementId;\n
+        \n
+        this._jsPlumb.connectionCost = params.connectionCost;\n
+        this._jsPlumb.connectionsDirected = params.connectionsDirected;        \n
+        this._jsPlumb.currentAnchorClass = "";\n
+        this._jsPlumb.events = {};\n
+            \n
+        var  _updateAnchorClass = function() {\n
+            jsPlumbAdapter.removeClass(this.element, _jsPlumb.endpointAnchorClassPrefix + "_" + this._jsPlumb.currentAnchorClass);\n
+            this.removeClass(_jsPlumb.endpointAnchorClassPrefix + "_" + this._jsPlumb.currentAnchorClass);\n
+            this._jsPlumb.currentAnchorClass = this.anchor.getCssClass();\n
+            this.addClass(_jsPlumb.endpointAnchorClassPrefix + "_" + this._jsPlumb.currentAnchorClass);\n
+            jsPlumbAdapter.addClass(this.element, _jsPlumb.endpointAnchorClassPrefix + "_" + this._jsPlumb.currentAnchorClass);\n
+        }.bind(this);\n
+        \n
+        this.setAnchor = function(anchorParams, doNotRepaint) {\n
+            this._jsPlumb.instance.continuousAnchorFactory.clear(this.elementId);\n
+            this.anchor = this._jsPlumb.instance.makeAnchor(anchorParams, this.elementId, _jsPlumb);\n
+            _updateAnchorClass();\n
+            this.anchor.bind("anchorChanged", function(currentAnchor) {\n
+                this.fire("anchorChanged", {endpoint:this, anchor:currentAnchor});\n
+                _updateAnchorClass();\n
+            }.bind(this));\n
+            if (!doNotRepaint)\n
+                this._jsPlumb.instance.repaint(this.elementId);\n
+            return this;\n
+        };\n
+\n
+        var anchorParamsToUse = params.anchor ? params.anchor : params.anchors ? params.anchors : (_jsPlumb.Defaults.Anchor || "Top");\n
+        this.setAnchor(anchorParamsToUse, true);\n
+\n
+        // endpoint delegates to first connection for hover, if there is one.\n
+        var internalHover = function(state) {\n
+          if (this.connections.length > 0)\n
+            this.connections[0].setHover(state, false);\n
+          else\n
+            this.setHover(state);\n
+        }.bind(this);\n
+            \n
+        // ANCHOR MANAGER\n
+        if (!params._transient) // in place copies, for example, are transient.  they will never need to be retrieved during a paint cycle, because they dont move, and then they are deleted.\n
+            this._jsPlumb.instance.anchorManager.add(this, this.elementId);\n
+        \n
+        this.setEndpoint = function(ep) {\n
+\n
+            if (this.endpoint != null) {\n
+                this.endpoint.cleanup();\n
+                this.endpoint.destroy();\n
+            }\n
+\n
+            var _e = function(t, p) {\n
+                var rm = _jsPlumb.getRenderMode();\n
+                if (jsPlumb.Endpoints[rm][t]) return new jsPlumb.Endpoints[rm][t](p);\n
+                if (!_jsPlumb.Defaults.DoNotThrowErrors)\n
+                    throw { msg:"jsPlumb: unknown endpoint type \'" + t + "\'" };\n
+            };            \n
+\n
+            var endpointArgs = {\n
+                _jsPlumb:this._jsPlumb.instance,\n
+                cssClass:params.cssClass,\n
+                container:params.container,\n
+                tooltip:params.tooltip,\n
+                connectorTooltip:params.connectorTooltip,\n
+                endpoint:this\n
+            };\n
+            if (_ju.isString(ep)) \n
+                this.endpoint = _e(ep, endpointArgs);\n
+            else if (_ju.isArray(ep)) {\n
+                endpointArgs = _ju.merge(ep[1], endpointArgs);\n
+                this.endpoint = _e(ep[0], endpointArgs);\n
+            }\n
+            else {\n
+                this.endpoint = ep.clone();\n
+            }\n
+\n
+            // assign a clone function using a copy of endpointArgs. this is used when a drag starts: the endpoint that was dragged is cloned,\n
+            // and the clone is left in its place while the original one goes off on a magical journey. \n
+            // the copy is to get around a closure problem, in which endpointArgs ends up getting shared by\n
+            // the whole world.\n
+            var argsForClone = jsPlumb.extend({}, endpointArgs);\t\t\t\t\t\t\n
+            this.endpoint.clone = function() {\n
+                // TODO this, and the code above, can be refactored to be more dry.\n
+                if (_ju.isString(ep)) \n
+                    return _e(ep, endpointArgs);\n
+                else if (_ju.isArray(ep)) {\n
+                    endpointArgs = _ju.merge(ep[1], endpointArgs);\n
+                    return _e(ep[0], endpointArgs);\n
+                }\n
+            }.bind(this);\n
+\n
+            this.type = this.endpoint.type;\n
+            // bind listeners from endpoint to self, with the internal hover function defined above.\n
+            this.bindListeners(this.endpoint, this, internalHover);\n
+        };\n
+         \n
+        this.setEndpoint(params.endpoint || _jsPlumb.Defaults.Endpoint || jsPlumb.Defaults.Endpoint || "Dot");\t\t\t\t\t\t\t                    \n
+        this.setPaintStyle(params.paintStyle || params.style || _jsPlumb.Defaults.EndpointStyle || jsPlumb.Defaults.EndpointStyle, true);\n
+        this.setHoverPaintStyle(params.hoverPaintStyle || _jsPlumb.Defaults.EndpointHoverStyle || jsPlumb.Defaults.EndpointHoverStyle, true);\n
+        this._jsPlumb.paintStyleInUse = this.getPaintStyle();\n
+\n
+        jsPlumb.extend(this, params, typeParameters);\n
+\n
+        this.isSource = params.isSource || false;\n
+        this.isTarget = params.isTarget || false;        \n
+        this._jsPlumb.maxConnections = params.maxConnections || _jsPlumb.Defaults.MaxConnections; // maximum number of connections this endpoint can be the source of.                \n
+        this.canvas = this.endpoint.canvas;\t\t\n
+        // add anchor class (need to do this on construction because we set anchor first)\n
+        this.addClass(_jsPlumb.endpointAnchorClassPrefix + "_" + this._jsPlumb.currentAnchorClass);\t\n
+        jsPlumbAdapter.addClass(this.element, _jsPlumb.endpointAnchorClassPrefix + "_" + this._jsPlumb.currentAnchorClass);\n
+        this.connections = params.connections || [];\n
+        this.connectorPointerEvents = params["connector-pointer-events"];\n
+        \n
+        this.scope = params.scope || _jsPlumb.getDefaultScope();        \n
+        this.timestamp = null;\n
+        this.reattachConnections = params.reattach || _jsPlumb.Defaults.ReattachConnections;\n
+        this.connectionsDetachable = _jsPlumb.Defaults.ConnectionsDetachable;\n
+        if (params.connectionsDetachable === false || params.detachable === false)\n
+            this.connectionsDetachable = false;\n
+        this.dragAllowedWhenFull = params.dragAllowedWhenFull || true;\n
+        \n
+        if (params.onMaxConnections)\n
+            this.bind("maxConnections", params.onMaxConnections);        \n
+        \n
+        //\n
+        // add a connection. not part of public API.\n
+        //\n
+        this.addConnection = function(connection) {\n
+            this.connections.push(connection);                  \n
+            this[(this.connections.length > 0 ? "add" : "remove") + "Class"](_jsPlumb.endpointConnectedClass);       \n
+            this[(this.isFull() ? "add" : "remove") + "Class"](_jsPlumb.endpointFullClass); \n
+        };\t\n
+\n
+        this.detachFromConnection = function(connection, idx, doNotCleanup) {\n
+            idx = idx == null ? findConnectionIndex(connection, this) : idx;\n
+            if (idx >= 0) {\n
+                this.connections.splice(idx, 1);\n
+                this[(this.connections.length > 0 ? "add" : "remove") + "Class"](_jsPlumb.endpointConnectedClass);       \n
+                this[(this.isFull() ? "add" : "remove") + "Class"](_jsPlumb.endpointFullClass);\n
+            }\n
+            \n
+            if (!doNotCleanup && this._deleteOnDetach && this.connections.length === 0) {\n
+                _jsPlumb.deleteObject({\n
+                    endpoint:this,\n
+                    fireEvent:false,\n
+                    deleteAttachedObjects:false\n
+                });\n
+            }\n
+        };\n
+\n
+        this.detach = function(connection, ignoreTarget, forceDetach, fireEvent, originalEvent, endpointBeingDeleted, connectionIndex) {\n
+\n
+            var idx = connectionIndex == null ? findConnectionIndex(connection, this) : connectionIndex,\n
+                actuallyDetached = false;\n
+                fireEvent = (fireEvent !== false);\n
+\n
+            if (idx >= 0) {\t\t                \n
+                if (forceDetach || connection._forceDetach || (connection.isDetachable() && connection.isDetachAllowed(connection) && this.isDetachAllowed(connection) )) {\n
+\n
+                    _jsPlumb.deleteObject({\n
+                        connection:connection, \n
+                        fireEvent:(!ignoreTarget && fireEvent), \n
+                        originalEvent:originalEvent,\n
+                        deleteAttachedObjects:false\n
+                    });\n
+                    actuallyDetached = true;                       \n
+                }\n
+            }\n
+            return actuallyDetached;\n
+        };\t\n
+\n
+        this.detachAll = function(fireEvent, originalEvent) {\n
+            while (this.connections.length > 0) {\n
+                // TODO this could pass the index in to the detach method to save some time (index will always be zero in this while loop)\n
+                this.detach(this.connections[0], false, true, fireEvent !== false, originalEvent, this, 0);\n
+            }\n
+            return this;\n
+        };                \n
+        this.detachFrom = function(targetEndpoint, fireEvent, originalEvent) {\n
+            var c = [];\n
+            for ( var i = 0; i < this.connections.length; i++) {\n
+                if (this.connections[i].endpoints[1] == targetEndpoint || this.connections[i]
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+.endpoints[0] == targetEndpoint) {\n
+                    c.push(this.connections[i]);\n
+                }\n
+            }\n
+            for ( var j = 0; j < c.length; j++) {\n
+                this.detach(c[j], false, true, fireEvent, originalEvent);\t\t\t\t\n
+            }\n
+            return this;\n
+        };\t        \n
+        \n
+        this.getElement = function() {\n
+            return this.element;\n
+        };\t\t\n
+                 \n
+        this.setElement = function(el) {\n
+            var parentId = this._jsPlumb.instance.getId(el),\n
+                curId = this.elementId;\n
+            // remove the endpoint from the list for the current endpoint\'s element\n
+            _ju.removeWithFunction(params.endpointsByElement[this.elementId], function(e) {\n
+                return e.id == this.id;\n
+            }.bind(this));\n
+            this.element = jsPlumb.getDOMElement(el);\n
+            this.elementId = _jsPlumb.getId(this.element);                         \n
+            _jsPlumb.anchorManager.rehomeEndpoint(this, curId, this.element);\n
+            _jsPlumb.dragManager.endpointAdded(this.element);            \n
+            _ju.addToList(params.endpointsByElement, parentId, this);            \n
+            return this;\n
+        };\n
+                \n
+        /**\n
+         * private but must be exposed.\n
+         */\n
+        this.makeInPlaceCopy = function() {\n
+            var loc = this.anchor.getCurrentLocation({element:this}),\n
+                o = this.anchor.getOrientation(this),\n
+                acc = this.anchor.getCssClass(),\n
+                inPlaceAnchor = {\n
+                    bind:function() { },\n
+                    compute:function() { return [ loc[0], loc[1] ]; },\n
+                    getCurrentLocation : function() { return [ loc[0], loc[1] ]; },\n
+                    getOrientation:function() { return o; },\n
+                    getCssClass:function() { return acc; }\n
+                };\n
+\n
+            return _newEndpoint( { \n
+                dropOptions:params.dropOptions,\n
+                anchor : inPlaceAnchor, \n
+                source : this.element, \n
+                paintStyle : this.getPaintStyle(), \n
+                endpoint : params.hideOnDrag ? "Blank" : this.endpoint,\n
+                _transient:true,\n
+                scope:this.scope\n
+            });\n
+        };            \n
+        \n
+        /**\n
+         * returns a connection from the pool; used when dragging starts.  just gets the head of the array if it can.\n
+         */\n
+        this.connectorSelector = function() {\n
+            var candidate = this.connections[0];\n
+            if (this.isTarget && candidate) return candidate;\n
+            else {\n
+                return (this.connections.length < this._jsPlumb.maxConnections) || this._jsPlumb.maxConnections == -1 ? null : candidate;\n
+            }\n
+        };        \n
+        \n
+        this.setStyle = this.setPaintStyle;        \n
+        \n
+        this.paint = function(params) {\n
+            params = params || {};\n
+            var timestamp = params.timestamp, recalc = !(params.recalc === false);\t\t\t\t\t\t\t\t\n
+            if (!timestamp || this.timestamp !== timestamp) {\t\t\t\t\t\t\n
+                \n
+                // TODO check: is this is a safe performance enhancement?\n
+                var info = _jsPlumb.updateOffset({ elId:this.elementId, timestamp:timestamp/*, recalc:recalc*/ });                \n
+\n
+                var xy = params.offset ? params.offset.o : info.o;\n
+                if(xy != null) {\n
+                    var ap = params.anchorPoint,connectorPaintStyle = params.connectorPaintStyle;\n
+                    if (ap == null) {\n
+                        var wh = params.dimensions || info.s,                       \n
+                            anchorParams = { xy : [ xy.left, xy.top ], wh : wh, element : this, timestamp : timestamp };\n
+                        if (recalc && this.anchor.isDynamic && this.connections.length > 0) {\n
+                            var c = findConnectionToUseForDynamicAnchor(this, params.elementWithPrecedence),\n
+                                oIdx = c.endpoints[0] == this ? 1 : 0,\n
+                                oId = oIdx === 0 ? c.sourceId : c.targetId,\n
+                                oInfo = _jsPlumb.getCachedData(oId),\n
+                                oOffset = oInfo.o, oWH = oInfo.s;\n
+                            anchorParams.txy = [ oOffset.left, oOffset.top ];\n
+                            anchorParams.twh = oWH;\n
+                            anchorParams.tElement = c.endpoints[oIdx];\n
+                        }\n
+                        ap = this.anchor.compute(anchorParams);\n
+                    }\n
+                                        \n
+                    this.endpoint.compute(ap, this.anchor.getOrientation(this), this._jsPlumb.paintStyleInUse, connectorPaintStyle || this.paintStyleInUse);\n
+                    this.endpoint.paint(this._jsPlumb.paintStyleInUse, this.anchor);\t\t\t\t\t\n
+                    this.timestamp = timestamp;\n
+\n
+                    // paint overlays\n
+                    for ( var i = 0; i < this._jsPlumb.overlays.length; i++) {\n
+                        var o = this._jsPlumb.overlays[i];\n
+                        if (o.isVisible()) { \n
+                            this._jsPlumb.overlayPlacements[i] = o.draw(this.endpoint, this._jsPlumb.paintStyleInUse);\n
+                            o.paint(this._jsPlumb.overlayPlacements[i]);    \n
+                        }\n
+                    }\n
+                }\n
+            }\n
+        };\n
+\n
+        this.repaint = this.paint; \n
+\n
+        var draggingInitialised = false;\n
+        this.initDraggable = function() {\n
+            // is this a connection source? we make it draggable and have the\n
+            // drag listener maintain a connection with a floating endpoint.\n
+            if (!draggingInitialised && jsPlumb.isDragSupported(this.element)) {\n
+                var placeholderInfo = { id:null, element:null },\n
+                    jpc = null,\n
+                    existingJpc = false,\n
+                    existingJpcParams = null,\n
+                    _dragHandler = _makeConnectionDragHandler(placeholderInfo, _jsPlumb);\n
+\n
+                var start = function() {    \n
+                // drag might have started on an endpoint that is not actually a source, but which has\n
+                // one or more connections.\n
+                    jpc = this.connectorSelector();\n
+                    var _continue = true;\n
+                    // if not enabled, return\n
+                    if (!this.isEnabled()) _continue = false;\n
+                    // if no connection and we\'re not a source, return.\n
+                    if (jpc == null && !this.isSource) _continue = false;\n
+                    // otherwise if we\'re full and not allowed to drag, also return false.\n
+                    if (this.isSource && this.isFull() && !this.dragAllowedWhenFull) _continue = false;\n
+                    // if the connection was setup as not detachable or one of its endpoints\n
+                    // was setup as connectionsDetachable = false, or Defaults.ConnectionsDetachable\n
+                    // is set to false...\n
+                    if (jpc != null && !jpc.isDetachable()) _continue = false;\n
+\n
+                    if (_continue === false) {\n
+                        // this is for mootools and yui. returning false from this causes jquery to stop drag.\n
+                        // the events are wrapped in both mootools and yui anyway, but i don\'t think returning\n
+                        // false from the start callback would stop a drag.\n
+                        if (_jsPlumb.stopDrag) _jsPlumb.stopDrag(this.canvas);\n
+                        _dragHandler.stopDrag();\n
+                        return false;\n
+                    }\n
+\n
+                    // clear hover for all connections for this endpoint before continuing.\n
+                    for (var i = 0; i < this.connections.length; i++)\n
+                        this.connections[i].setHover(false);\n
+\n
+                    this.addClass("endpointDrag");\n
+                    _jsPlumb.setConnectionBeingDragged(true);\n
+\n
+                    // if we\'re not full but there was a connection, make it null. we\'ll create a new one.\n
+                    if (jpc && !this.isFull() && this.isSource) jpc = null;\n
+\n
+                    _jsPlumb.updateOffset( { elId : this.elementId });\n
+                    inPlaceCopy = this.makeInPlaceCopy();\n
+                    inPlaceCopy.referenceEndpoint = this;\n
+                    inPlaceCopy.paint();                                                                \n
+                    \n
+                    _makeDraggablePlaceholder(placeholderInfo, _jsPlumb);\n
+                    \n
+                    // set the offset of this div to be where \'inPlaceCopy\' is, to start with.\n
+                    // TODO merge this code with the code in both Anchor and FloatingAnchor, because it\n
+                    // does the same stuff.\n
+                    var ipcoel = _gel(inPlaceCopy.canvas),\n
+                        ipco = jsPlumbAdapter.getOffset(ipcoel, this._jsPlumb.instance),                        \n
+                        canvasElement = _gel(this.canvas);                               \n
+                        \n
+                    jsPlumbAdapter.setPosition(placeholderInfo.element, ipco);\n
+                    \n
+                    // when using makeSource and a parent, we first draw the source anchor on the source element, then\n
+                    // move it to the parent.  note that this happens after drawing the placeholder for the\n
+                    // first time.\n
+                    if (this.parentAnchor) this.anchor = _jsPlumb.makeAnchor(this.parentAnchor, this.elementId, _jsPlumb);\n
+                    \n
+                    // store the id of the dragging div and the source element. the drop function will pick these up.                   \n
+                    _jsPlumb.setAttribute(this.canvas, "dragId", placeholderInfo.id);\n
+                    _jsPlumb.setAttribute(this.canvas, "elId", this.elementId);\n
+\n
+                    this._jsPlumb.floatingEndpoint = _makeFloatingEndpoint(this.getPaintStyle(), this.anchor, this.endpoint, this.canvas, placeholderInfo.element, _jsPlumb, _newEndpoint);\n
+                    // TODO we should not know about DOM here. make the library adapter do this (or the \n
+                        // dom adapter)\n
+                    this.canvas.style.visibility = "hidden";            \n
+                    \n
+                    if (jpc == null) {                                                                                                                                                         \n
+                        this.anchor.locked = true;\n
+                        this.setHover(false, false);                        \n
+                        // create a connection. one end is this endpoint, the other is a floating endpoint.                    \n
+                        jpc = _newConnection({\n
+                            sourceEndpoint : this,\n
+                            targetEndpoint : this._jsPlumb.floatingEndpoint,\n
+                            source : this.endpointWillMoveTo || this.element,  // for makeSource with parent option.  ensure source element is represented correctly.\n
+                            target : placeholderInfo.element,\n
+                            anchors : [ this.anchor, this._jsPlumb.floatingEndpoint.anchor ],\n
+                            paintStyle : params.connectorStyle, // this can be null. Connection will use the default.\n
+                            hoverPaintStyle:params.connectorHoverStyle,\n
+                            connector : params.connector, // this can also be null. Connection will use the default.\n
+                            overlays : params.connectorOverlays,\n
+                            type:this.connectionType,\n
+                            cssClass:this.connectorClass,\n
+                            hoverClass:this.connectorHoverClass\n
+                        });\n
+                        jpc.pending = true; // mark this connection as not having been established.\n
+                        jpc.addClass(_jsPlumb.draggingClass);\n
+                        this._jsPlumb.floatingEndpoint.addClass(_jsPlumb.draggingClass);\n
+                        // fire an event that informs that a connection is being dragged\n
+                        _jsPlumb.fire("connectionDrag", jpc);\n
+\n
+                    } else {\n
+                        existingJpc = true;\n
+                        jpc.setHover(false);\n
+                        // new anchor idx\n
+                        var anchorIdx = jpc.endpoints[0].id == this.id ? 0 : 1;\n
+                        jpc.floatingAnchorIndex = anchorIdx;                    // save our anchor index as the connection\'s floating index.                        \n
+                        this.detachFromConnection(jpc, null, true);                         // detach from the connection while dragging is occurring. but dont cleanup automatically.\n
+                        \n
+                        //*\n
+                        // store the original scope (issue 57)\n
+                        var dragScope = _jsPlumb.getDragScope(canvasElement);\n
+                        _jsPlumb.setAttribute(this.canvas, "originalScope", dragScope);\n
+                        // now we want to get this endpoint\'s DROP scope, and set it for now: we can only be dropped on drop zones\n
+                        // that have our drop scope (issue 57).\n
+                        var dropScope = _jsPlumb.getDropScope(canvasElement);\n
+                        _jsPlumb.setDragScope(canvasElement, dropScope);\n
+                        //*/\n
+\n
+                        // fire an event that informs that a connection is being dragged. we do this before\n
+                        // replacing the original target with the floating element info.\n
+                        _jsPlumb.fire("connectionDrag", jpc);\n
+                \n
+                        // now we replace ourselves with the temporary div we created above:\n
+                        if (anchorIdx === 0) {\n
+                            existingJpcParams = [ jpc.source, jpc.sourceId, canvasElement, dragScope ];\n
+                            jpc.source = placeholderInfo.element;\n
+                            jpc.sourceId = placeholderInfo.id;\n
+                        } else {\n
+                            existingJpcParams = [ jpc.target, jpc.targetId, canvasElement, dragScope ];\n
+                            jpc.target = placeholderInfo.element;\n
+                            jpc.targetId = placeholderInfo.id;\n
+                        }\n
+\n
+                        // lock the other endpoint; if it is dynamic it will not move while the drag is occurring.\n
+                        jpc.endpoints[anchorIdx === 0 ? 1 : 0].anchor.locked = true;\n
+                        // store the original endpoint and assign the new floating endpoint for the drag.\n
+                        jpc.suspendedEndpoint = jpc.endpoints[anchorIdx];\n
+                        \n
+                        // PROVIDE THE SUSPENDED ELEMENT, BE IT A SOURCE OR TARGET (ISSUE 39)\n
+                        jpc.suspendedElement = jpc.endpoints[anchorIdx].getElement();\n
+                        jpc.suspendedElementId = jpc.endpoints[anchorIdx].elementId;\n
+                        jpc.suspendedElementType = anchorIdx === 0 ? "source" : "target";\n
+                        \n
+                        jpc.suspendedEndpoint.setHover(false);\n
+                        this._jsPlumb.floatingEndpoint.referenceEndpoint = jpc.suspendedEndpoint;\n
+                        jpc.endpoints[anchorIdx] = this._jsPlumb.floatingEndpoint;\n
+\n
+                        jpc.addClass(_jsPlumb.draggingClass);\n
+                        this._jsPlumb.floatingEndpoint.addClass(_jsPlumb.draggingClass);                    \n
+\n
+                    }\n
+                    // register it and register connection on it.\n
+                    floatingConnections[placeholderInfo.id] = jpc;\n
+                    _jsPlumb.anchorManager.addFloatingConnection(placeholderInfo.id, jpc);               \n
+                    // only register for the target endpoint; we will not be dragging the source at any time\n
+                    // before this connection is either discarded or made into a permanent connection.\n
+                    _ju.addToList(params.endpointsByElement, placeholderInfo.id, this._jsPlumb.floatingEndpoint);\n
+                    // tell jsplumb about it\n
+                    _jsPlumb.currentlyDragging = true;\n
+                }.bind(this);\n
+\n
+                var dragOptions = params.dragOptions || {},\n
+                    defaultOpts = {},\n
+                    startEvent = jsPlumb.dragEvents.start,\n
+                    stopEvent = jsPlumb.dragEvents.stop,\n
+                    dragEvent = jsPlumb.dragEvents.drag;\n
+                \n
+                dragOptions = jsPlumb.extend(defaultOpts, dragOptions);\n
+                dragOptions.scope = dragOptions.scope || this.scope;\n
+                dragOptions[startEvent] = _ju.wrap(dragOptions[startEvent], start, false);\n
+                // extracted drag handler function so can be used by makeSource\n
+                dragOptions[dragEvent] = _ju.wrap(dragOptions[dragEvent], _dragHandler.drag);\n
+                dragOptions[stopEvent] = _ju.wrap(dragOptions[stopEvent],\n
+                    function() {        \n
+\n
+                        _jsPlumb.setConnectionBeingDragged(false);  \n
+                        // if no endpoints, jpc already cleaned up.\n
+                        if (jpc && jpc.endpoints != null) {          \n
+                            // get the actual drop event (decode from library args to stop function)\n
+                            var originalEvent = _jsPlumb.getDropEvent(arguments);                                       \n
+                            // unlock the other endpoint (if it is dynamic, it would have been locked at drag start)\n
+                            var idx = jpc.floatingAnchorIndex == null ? 1 : jpc.floatingAnchorIndex;\n
+                            jpc.endpoints[idx === 0 ? 1 : 0].anchor.locked = false;\n
+                            // WHY does this need to happen?  i suppose because the connection might not get \n
+                            // deleted.  TODO: i dont want to know about css classes inside jsplumb, ideally.\n
+                            jpc.removeClass(_jsPlumb.draggingClass);   \n
+                        \n
+                            // if we have the floating endpoint then the connection has not been dropped\n
+                            // on another endpoint.  If it is a new connection we throw it away. If it is an \n
+                            // existing connection we check to see if we should reattach it, throwing it away \n
+                            // if not.\n
+                            if (jpc.endpoints[idx] == this._jsPlumb.floatingEndpoint) {\n
+                                // 6a. if the connection was an existing one...\n
+                                if (existingJpc && jpc.suspendedEndpoint) {\n
+                                    // fix for issue35, thanks Sylvain Gizard: when firing the detach event make sure the\n
+                                    // floating endpoint has been replaced.\n
+                                    if (idx === 0) {\n
+                                        jpc.source = existingJpcParams[0];\n
+                                        jpc.sourceId = existingJpcParams[1];\n
+                                    } else {\n
+                                        jpc.target = existingJpcParams[0];\n
+                                        jpc.targetId = existingJpcParams[1];\n
+                                    }\n
+                                    \n
+                                    // restore the original scope (issue 57)\n
+                                    _jsPlumb.setDragScope(existingJpcParams[2], existingJpcParams[3]);\n
+                                    jpc.endpoints[idx] = jpc.suspendedEndpoint;\n
+                                    // IF the connection should be reattached, or the other endpoint refuses detach, then\n
+                                    // reset the connection to its original state\n
+                                    if (jpc.isReattach() || jpc._forceReattach || jpc._forceDetach || !jpc.endpoints[idx === 0 ? 1 : 0].detach(jpc, false, false, true, originalEvent)) {                                   \n
+                                        jpc.setHover(false);\n
+                                        jpc.floatingAnchorIndex = null;\n
+                                        jpc._forceDetach = null;\n
+                                        jpc._forceReattach = null;\n
+                                        this._jsPlumb.floatingEndpoint.detachFromConnection(jpc);\n
+                                        jpc.suspendedEndpoint.addConnection(jpc);\n
+                                        _jsPlumb.repaint(existingJpcParams[1]);\n
+                                    }\n
+                                    else\n
+                                        jpc.suspendedEndpoint.detachFromConnection(jpc);  // confirm we want it to detach; it may decide to self-destruct\n
+                                }                                                               \n
+                            }\n
+\n
+                            // remove the element associated with the floating endpoint \n
+                            // (and its associated floating endpoint and visual artefacts)                                        \n
+                            _jsPlumb.remove(placeholderInfo.element, false);\n
+                            // remove the inplace copy\n
+                            //_jsPlumb.remove(inPlaceCopy.canvas, false);\n
+                            _jsPlumb.deleteObject({endpoint:inPlaceCopy});\n
+    \n
+                            // makeTargets sets this flag, to tell us we have been replaced and should delete ourself.\n
+                            if (this.deleteAfterDragStop) {                        \n
+                                _jsPlumb.deleteObject({endpoint:this});\n
+                            }\n
+                            else {\n
+                                if (this._jsPlumb) {\n
+                                    this._jsPlumb.floatingEndpoint = null;\n
+                                    // repaint this endpoint.\n
+                                    // make our canvas visible (TODO: hand off to library; we should not know about DOM)\n
+                                    this.canvas.style.visibility = "visible";\n
+                                    // unlock our anchor\n
+                                    this.anchor.locked = false;\n
+                                    this.paint({recalc:false});                        \n
+                                }\n
+                            }                                                    \n
+    \n
+                            // although the connection is no longer valid, there are use cases where this is useful.\n
+                            _jsPlumb.fire("connectionDragStop", jpc, originalEvent);\n
+    \n
+                            // tell jsplumb that dragging is finished.\n
+                            _jsPlumb.currentlyDragging = false;\n
+    \n
+                            jpc = null;\n
+                        }\n
+\n
+                    }.bind(this));\n
+                \n
+                var i = _gel(this.canvas);              \n
+                _jsPlumb.initDraggable(i, dragOptions, true);\n
+\n
+                draggingInitialised = true;\n
+            }\n
+        };\n
+\n
+        // if marked as source or target at create time, init the dragging.\n
+        if (this.isSource || this.isTarget)\n
+            this.initDraggable();        \n
+\n
+        // pulled this out into a function so we can reuse it for the inPlaceCopy canvas; you can now drop detached connections\n
+        // back onto the endpoint you detached it from.\n
+        var _initDropTarget = function(canvas, forceInit, isTransient, endpoint) {\n
+            if ((this.isTarget || forceInit) && jsPlumb.isDropSupported(this.element)) {\n
+                var dropOptions = params.dropOptions || _jsPlumb.Defaults.DropOptions || jsPlumb.Defaults.DropOptions;\n
+                dropOptions = jsPlumb.extend( {}, dropOptions);\n
+                dropOptions.scope = dropOptions.scope || this.scope;\n
+                var dropEvent = jsPlumb.dragEvents.drop,\n
+                    overEvent = jsPlumb.dragEvents.over,\n
+                    outEvent = jsPlumb.dragEvents.out,\n
+                    drop = function() {                        \n
+\n
+                        this.removeClass(_jsPlumb.endpointDropAllowedClass);\n
+                        this.removeClass(_jsPlumb.endpointDropForbiddenClass);\n
+                                                    \n
+                        var originalEvent = _jsPlumb.getDropEvent(arguments),\n
+                            draggable = _jsPlumb.getDOMElement(_jsPlumb.getDragObject(arguments)),\n
+                            id = _jsPlumb.getAttribute(draggable, "dragId"),\n
+                            elId = _jsPlumb.getAttribute(draggable, "elId"),\t\t\t\t\t\t\n
+                            scope = _jsPlumb.getAttribute(draggable, "originalScope"),\n
+                            jpc = floatingConnections[id];\n
+                            \n
+                        if (jpc != null) {\n
+                            // if this is a drop back where the connection came from, mark it force rettach and\n
+                        // return; the stop handler will reattach. without firing an event.\n
+                        var redrop = jpc.suspendedEndpoint && (jpc.suspendedEndpoint.id == this.id ||\n
+                                        this.referenceEndpoint && jpc.suspendedEndpoint.id == this.referenceEndpoint.id) ;\t\t\t\t\t\t\t\n
+                        if (redrop) {\t\t\t\t\t\t\t\t\n
+                            jpc._forceReattach = true;\n
+                            return;\n
+                        }\n
+                            var idx = jpc.floatingAnchorIndex == null ? 1 : jpc.floatingAnchorIndex, oidx = idx === 0 ? 1 : 0;\n
+                            \n
+                            // restore the original scope if necessary (issue 57)\t\t\t\t\t\t\n
+                            if (scope) _jsPlumb.setDragScope(draggable, scope);\t\t\t\t\t\t\t\n
+                            \n
+                            var endpointEnabled = endpoint != null ? endpoint.isEnabled() : true;\n
+                            \n
+                            if (this.isFull()) {\n
+                                this.fire("maxConnections", { \n
+                                    endpoint:this, \n
+                                    connection:jpc, \n
+                                    maxConnections:this._jsPlumb.maxConnections \n
+                                }, originalEvent);\n
+                            }\n
+                                                            \n
+                            if (!this.isFull() && !(idx === 0 && !this.isSource) && !(idx == 1 && !this.isTarget) && endpointEnabled) {\n
+                                var _doContinue = true;\n
+\n
+                                // the second check here is for the case that the user is dropping it back\n
+                                // where it came from.\n
+                                if (jpc.suspendedEndpoint && jpc.suspendedEndpoint.id != this.id) {\n
+                                    if (idx === 0) {\n
+                                        jpc.source = jpc.suspendedEndpoint.element;\n
+                                        jpc.sourceId = jpc.suspendedEndpoint.elementId;\n
+                                    } else {\n
+                                        jpc.target = jpc.suspendedEndpoint.element;\n
+                                        jpc.targetId = jpc.suspendedEndpoint.elementId;\n
+                                    }\n
+\n
+                                    if (!jpc.isDetachAllowed(jpc) || !jpc.endpoints[idx].isDetachAllowed(jpc) || !jpc.suspendedEndpoint.isDetachAllowed(jpc) || !_jsPlumb.checkCondition("beforeDetach", jpc))\n
+                                        _doContinue = false;\t\t\t\t\t\t\t\t\n
+                                }\n
+            \n
+                                // these have to be set before testing for beforeDrop.\n
+                                if (idx === 0) {\n
+                                    jpc.source = this.element;\n
+                                    jpc.sourceId = this.elementId;\n
+                                } else {\n
+                                    jpc.target = this.element;\n
+                                    jpc.targetId = this.elementId;\n
+                                }\n
+                                                            \n
+// ------------ wrap the execution path in a function so we can support asynchronous beforeDrop\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n
+                                    \n
+                                // we want to execute this regardless.\n
+                                var commonFunction = function() {\n
+                                    jpc.floatingAnchorIndex = null;\n
+                                };\t\n
+                                                                                                \n
+                                var continueFunction = function() {\n
+                                    jpc.pending = false;\n
+\n
+                                    // remove this jpc from the current endpoint\n
+                                    jpc.endpoints[idx].detachFromConnection(jpc);\n
+                                    if (jpc.suspendedEndpoint) jpc.suspendedEndpoint.detachFromConnection(jpc);\n
+                                    jpc.endpoints[idx] = this;\n
+                                    this.addConnection(jpc);\n
+                                    \n
+                                    // copy our parameters in to the connection:\n
+                                    var params = this.getParameters();\n
+                                    for (var aParam in params)\n
+                                        jpc.setParameter(aParam, params[aParam]);\n
+\n
+                                    if (!jpc.suspendedEndpoint) {  \n
+                                        // if not an existing connection and\n
+                                        if (params.draggable)\n
+                                            jsPlumb.initDraggable(this.element, dragOptions, true, _jsPlumb);\n
+                                    }\n
+                                    else {\n
+                                        var suspendedElement = jpc.suspendedEndpoint.getElement(), suspendedElementId = jpc.suspendedEndpoint.elementId;\n
+                                        _fireMoveEvent({\n
+                                            index:idx,\n
+                                            originalSourceId:idx === 0 ? suspendedElementId : jpc.sourceId,\n
+                                            newSourceId:idx === 0 ? this.elementId : jpc.sourceId,\n
+                                            originalTargetId:idx == 1 ? suspendedElementId : jpc.targetId,\n
+                                            newTargetId:idx == 1 ? this.elementId : jpc.targetId,\n
+                                            originalSourceEndpoint:idx === 0 ? jpc.suspendedEndpoint : jpc.endpoints[0],\n
+                                            newSourceEndpoint:idx === 0 ? this : jpc.endpoints[0],\n
+                                            originalTargetEndpoint:idx == 1 ? jpc.suspendedEndpoint : jpc.endpoints[1],\n
+                                            newTargetEndpoint:idx == 1 ? this : jpc.endpoints[1],\n
+                                            connection:jpc\n
+                                        }, originalEvent);\n
+                                    }\n
+\n
+                                    // TODO this is like the makeTarget drop code.\n
+                                    if (idx == 1)\n
+                                        _jsPlumb.anchorManager.updateOtherEndpoint(jpc.sourceId, jpc.suspendedElementId, jpc.targetId, jpc);\n
+                                    else\n
+                                        _jsPlumb.anchorManager.sourceChanged(jpc.suspendedEndpoint.elementId, jpc.sourceId, jpc);\n
+\n
+                                    // finalise will inform the anchor manager and also add to\n
+                                    // connectionsByScope if necessary.\n
+                                    // TODO if this is not set to true, then dragging a connection\'s target to a new\n
+                                    // target causes the connection to be forgotten. however if it IS set to true, then\n
+                                    // the opposite happens: dragging by source causes the connection to get forgotten\n
+                                    // about and then if you delete it jsplumb breaks.\n
+                                    _finaliseConnection(jpc, null, originalEvent/*, true*/);\n
+                                    \n
+                                    commonFunction();\n
+                                }.bind(this);\n
+                                \n
+                                var dontContinueFunction = function() {\n
+                                    // otherwise just put it back on the endpoint it was on before the drag.\n
+                                    if (jpc.suspendedEndpoint) {\t\t\t\t\t\t\t\t\t\n
+                                        jpc.endpoints[idx] = jpc.suspendedEndpoint;\n
+                                        jpc.setHover(false);\n
+                                        jpc._forceDetach = true;\n
+                                        if (idx === 0) {\n
+                                            jpc.source = jpc.suspendedEndpoint.element;\n
+                                            jpc.sourceId = jpc.suspendedEndpoint.elementId;\n
+                                        } else {\n
+                                            jpc.target = jpc.suspendedEndpoint.element;\n
+                                            jpc.targetId = jpc.suspendedEndpoint.elementId;\n
+                                        }\n
+                                        jpc.suspendedEndpoint.addConnection(jpc);\n
+\n
+                                        jpc.endpoints[0].repaint();\n
+                                        jpc.repaint();\n
+                                        _jsPlumb.repaint(jpc.sourceId);\n
+                                        jpc._forceDetach = false;\n
+                                    }\n
+                                    \n
+                                    commonFunction();\n
+                                };\n
+                                \n
+// --------------------------------------\n
+                                // now check beforeDrop.  this will be available only on Endpoints that are setup to\n
+                                // have a beforeDrop condition (although, secretly, under the hood all Endpoints and \n
+                                // the Connection have them, because they are on jsPlumbUIComponent.  shhh!), because\n
+                                // it only makes sense to have it on a target endpoint.\n
+                                _doContinue = _doContinue && this.isDropAllowed(jpc.sourceId, jpc.targetId, jpc.scope, jpc, this);\n
+                                                                                                                    \n
+                                if (_doContinue) {\n
+                                    continueFunction();\n
+                                }\n
+                                else {\n
+                                    dontContinueFunction();\n
+                                }\n
+                            }\n
+                            _jsPlumb.currentlyDragging = false;\n
+                        }\n
+                    }.bind(this);\n
+                \n
+                dropOptions[dropEvent] = _ju.wrap(dropOptions[dropEvent], drop);\n
+                dropOptions[overEvent] = _ju.wrap(dropOptions[overEvent], function() {\t\t\t\t\t\n
+                    var draggable = jsPlumb.getDragObject(arguments),\n
+                        id = _jsPlumb.getAttribute(jsPlumb.getDOMElement(draggable), "dragId"),\n
+                        _jpc = floatingConnections[id];\n
+                        \n
+                    if (_jpc != null) {\t\t\t\t\t\t\t\t\n
+                        var idx = _jpc.floatingAnchorIndex == null ? 1 : _jpc.floatingAnchorIndex;\n
+                        // here we should fire the \'over\' event if we are a target and this is a new connection,\n
+                        // or we are the same as the floating endpoint.\t\t\t\t\t\t\t\t\n
+                        var _cont = (this.isTarget && _jpc.floatingAnchorIndex !== 0) || (_jpc.suspendedEndpoint && this.referenceEndpoint && this.referenceEndpoint.id == _jpc.suspendedEndpoint.id);\n
+                        if (_cont) {\n
+                            var bb = _jsPlumb.checkCondition("checkDropAllowed", { \n
+                                sourceEndpoint:_jpc.endpoints[idx], \n
+                                targetEndpoint:this,\n
+                                connection:_jpc\n
+                            }); \n
+                            this[(bb ? "add" : "remove") + "Class"](_jsPlumb.endpointDropAllowedClass);\n
+                            this[(bb ? "remove" : "add") + "Class"](_jsPlumb.endpointDropForbiddenClass);\n
+                            _jpc.endpoints[idx].anchor.over(this.anchor, this);\n
+                        }\n
+                    }\t\t\t\t\t\t\n
+                }.bind(this));\t\n
+\n
+                dropOptions[outEvent] = _ju.wrap(dropOptions[outEvent], function() {\t\t\t\t\t\n
+                    var draggable = jsPlumb.getDragObject(arguments),\n
+                        id = draggable == null ? null : _jsPlumb.getAttribute( jsPlumb.getDOMElement(draggable), "dragId"),\n
+                        _jpc = id? floatingConnections[id] : null;\n
+                        \n
+                    if (_jpc != null) {\n
+                        var idx = _jpc.floatingAnchorIndex == null ? 1 : _jpc.floatingAnchorIndex;\n
+                        var _cont = (this.isTarget && _jpc.floatingAnchorIndex !== 0) || (_jpc.suspendedEndpoint && this.referenceEndpoint && this.referenceEndpoint.id == _jpc.suspendedEndpoint.id);\n
+                        if (_cont) {\n
+                            this.removeClass(_jsPlumb.endpointDropAllowedClass);\n
+                            this.removeClass(_jsPlumb.endpointDropForbiddenClass);\n
+                            _jpc.endpoints[idx].anchor.out();\n
+                        }\n
+                    }\n
+                }.bind(this));\n
+                _jsPlumb.initDroppable(canvas, dropOptions, true, isTransient);\n
+            }\n
+        }.bind(this);\n
+        \n
+        // initialise the endpoint\'s canvas as a drop target.  this will be ignored if the endpoint is not a target or drag is not supported.\n
+        if (!this.anchor.isFloating)\n
+            _initDropTarget(_gel(this.canvas), true, !(params._transient || this.anchor.isFloating), this);\n
+        \n
+         // finally, set type if it was provided\n
+         if (params.type)\n
+            this.addType(params.type, params.data, _jsPlumb.isSuspendDrawing());\n
+\n
+        return this;        \t\t\t\t\t\n
+    };\n
+\n
+    jsPlumbUtil.extend(jsPlumb.Endpoint, OverlayCapableJsPlumbUIComponent, {\n
+        getTypeDescriptor : function() { return "endpoint"; },        \n
+        isVisible : function() { return this._jsPlumb.visible; },\n
+        setVisible : function(v, doNotChangeConnections, doNotNotifyOtherEndpoint) {\n
+            this._jsPlumb.visible = v;\n
+            if (this.canvas) this.canvas.style.display = v ? "block" : "none";\n
+            this[v ? "showOverlays" : "hideOverlays"]();\n
+            if (!doNotChangeConnections) {\n
+                for (var i = 0; i < this.connections.length; i++) {\n
+                    this.connections[i].setVisible(v);\n
+                    if (!doNotNotifyOtherEndpoint) {\n
+                        var oIdx = this === this.connections[i].endpoints[0] ? 1 : 0;\n
+                        // only change the other endpoint if this is its only connection.\n
+                        if (this.connections[i].endpoints[oIdx].connections.length == 1) this.connections[i].endpoints[oIdx].setVisible(v, true, true);\n
+                    }\n
+                }\n
+            }\n
+        },\n
+        getAttachedElements : function() {\n
+            return this.connections;\n
+        },\n
+        applyType : function(t, doNotRepaint) {         \n
+            if (t.maxConnections != null) this._jsPlumb.maxConnections = t.maxConnections;\n
+            if (t.scope) this.scope = t.scope;\n
+            jsPlumb.extend(this, t, typeParameters);\n
+            if (t.anchor) {\n
+                this.anchor = this._jsPlumb.instance.makeAnchor(t.anchor);\n
+            }\n
+        },\n
+        isEnabled : function() { return this._jsPlumb.enabled; },\n
+        setEnabled : function(e) { this._jsPlumb.enabled = e; },\n
+        cleanup : function() {            \n
+            jsPlumbAdapter.removeClass(this.element, this._jsPlumb.instance.endpointAnchorClassPrefix + "_" + this._jsPlumb.currentAnchorClass);            \n
+            this.anchor = null;\n
+            this.endpoint.cleanup();\n
+            this.endpoint.destroy();\n
+            this.endpoint = null;\n
+            // drag/drop\n
+            var i = jsPlumb.getElementObject(this.canvas);              \n
+            this._jsPlumb.instance.destroyDraggable(i);\n
+            this._jsPlumb.instance.destroyDroppable(i);\n
+        },\n
+        setHover : function(h) {\n
+            if (this.endpoint && this._jsPlumb && !this._jsPlumb.instance.isConnectionBeingDragged())\n
+                this.endpoint.setHover(h);            \n
+        },\n
+        isFull : function() {\n
+            return !(this.isFloating() || this._jsPlumb.maxConnections < 1 || this.connections.length < this._jsPlumb.maxConnections);              \n
+        },\n
+        /**\n
+         * private but needs to be exposed.\n
+         */\n
+        isFloating : function() {\n
+            return this.anchor != null && this.anchor.isFloating;\n
+        },\n
+        getConnectionCost : function() { return this._jsPlumb.connectionCost; },\n
+        setConnectionCost : function(c) {\n
+            this._jsPlumb.connectionCost = c; \n
+        },\n
+        areConnectionsDirected : function() { return this._jsPlumb.connectionsDirected; },\n
+        setConnectionsDirected : function(b) { this._jsPlumb.connectionsDirected = b; },\n
+        setElementId : function(_elId) {\n
+            this.elementId = _elId;\n
+            this.anchor.elementId = _elId;\n
+        },        \n
+        setReferenceElement : function(_el) {\n
+            this.element = jsPlumb.getDOMElement(_el);\n
+        },\n
+        setDragAllowedWhenFull : function(allowed) {\n
+            this.dragAllowedWhenFull = allowed;\n
+        },\n
+        equals : function(endpoint) {\n
+            return this.anchor.equals(endpoint.anchor);\n
+        },\n
+        getUuid : function() {\n
+            return this._jsPlumb.uuid;\n
+        },\n
+        computeAnchor : function(params) {\n
+            return this.anchor.compute(params);\n
+        }\n
+    });\n
+})();\n
+\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the code for Connections.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+;(function() {\n
+    \n
+    "use strict";\n
+\n
+    var makeConnector = function(_jsPlumb, renderMode, connectorName, connectorArgs) {\n
+            if (!_jsPlumb.Defaults.DoNotThrowErrors && jsPlumb.Connectors[renderMode][connectorName] == null)\n
+                    throw { msg:"jsPlumb: unknown connector type \'" + connectorName + "\'" };\n
+\n
+            return new jsPlumb.Connectors[renderMode][connectorName](connectorArgs);  \n
+        },\n
+        _makeAnchor = function(anchorParams, elementId, _jsPlumb) {\n
+            return (anchorParams) ? _jsPlumb.makeAnchor(anchorParams, elementId, _jsPlumb) : null;\n
+        };\n
+    \n
+    jsPlumb.Connection = function(params) {\n
+        var _newConnection = params.newConnection,\n
+            _newEndpoint = params.newEndpoint,\n
+            _gel = jsPlumb.getElementObject,\n
+            _ju = jsPlumbUtil;\n
+\n
+        this.connector = null;\n
+        this.idPrefix = "_jsplumb_c_";\n
+        this.defaultLabelLocation = 0.5;\n
+        this.defaultOverlayKeys = ["Overlays", "ConnectionOverlays"];\n
+        // if a new connection is the result of moving some existing connection, params.previousConnection\n
+        // will have that Connection in it. listeners for the jsPlumbConnection event can look for that\n
+        // member and take action if they need to.\n
+        this.previousConnection = params.previousConnection;\n
+        this.source = jsPlumb.getDOMElement(params.source);\n
+        this.target = jsPlumb.getDOMElement(params.target);\n
+        // sourceEndpoint and targetEndpoint override source/target, if they are present. but \n
+        // source is not overridden if the Endpoint has declared it is not the final target of a connection;\n
+        // instead we use the source that the Endpoint declares will be the final source element.\n
+        if (params.sourceEndpoint) this.source = params.sourceEndpoint.endpointWillMoveTo || params.sourceEndpoint.getElement();            \n
+        if (params.targetEndpoint) this.target = params.targetEndpoint.getElement();        \n
+\n
+        OverlayCapableJsPlumbUIComponent.apply(this, arguments);\n
+\n
+        this.sourceId = this._jsPlumb.instance.getId(this.source);\n
+        this.targetId = this._jsPlumb.instance.getId(this.target);\n
+        this.scope = params.scope; // scope may have been passed in to the connect call. if it wasn\'t, we will pull it from the source endpoint, after having initialised the endpoints.            \n
+        this.endpoints = [];\n
+        this.endpointStyles = [];\n
+            \n
+        var _jsPlumb = this._jsPlumb.instance;\n
+        this._jsPlumb.visible = true;\n
+        this._jsPlumb.editable = params.editable === true;    \n
+        this._jsPlumb.params = {\n
+            cssClass:params.cssClass,\n
+            container:params.container,\n
+            "pointer-events":params["pointer-events"],\n
+            editorParams:params.editorParams\n
+        };   \n
+        this._jsPlumb.lastPaintedAt = null;\n
+        this.getDefaultType = function() {\n
+            return {\n
+                parameters:{},\n
+                scope:null,\n
+                detachable:this._jsPlumb.instance.Defaults.ConnectionsDetachable,\n
+                rettach:this._jsPlumb.instance.Defaults.ReattachConnections,\n
+                paintStyle:this._jsPlumb.instance.Defaults.PaintStyle || jsPlumb.Defaults.PaintStyle,\n
+                connector:this._jsPlumb.instance.Defaults.Connector || jsPlumb.Defaults.Connector,\n
+                hoverPaintStyle:this._jsPlumb.instance.Defaults.HoverPaintStyle || jsPlumb.Defaults.HoverPaintStyle,\n
+                overlays:this._jsPlumb.instance.Defaults.ConnectorOverlays || jsPlumb.Defaults.ConnectorOverlays\n
+            };\n
+        };\n
+        \n
+// INITIALISATION CODE\t\t\t\n
+                            \n
+        // wrapped the main function to return null if no input given. this lets us cascade defaults properly.\n
+        \n
+        this.makeEndpoint = function(isSource, el, elId, ep) {\n
+            elId = elId ||  this._jsPlumb.instance.getId(el);\n
+            return this.prepareEndpoint(_jsPlumb, _newEndpoint, this, ep, isSource ? 0 : 1, params, el, elId);\n
+        };\n
+        \n
+        var eS = this.makeEndpoint(true, this.source, this.sourceId, params.sourceEndpoint),\n
+            eT = this.makeEndpoint(false, this.target, this.targetId, params.targetEndpoint);\n
+        \n
+        if (eS) _ju.addToList(params.endpointsByElement, this.sourceId, eS);\n
+        if (eT) _ju.addToList(params.endpointsByElement, this.targetId, eT);\n
+        // if scope not set, set it to be the scope for the source endpoint.\n
+        if (!this.scope) this.scope = this.endpoints[0].scope;\n
+                \n
+        // if explicitly told to (or not to) delete endpoints on detach, override endpoint\'s preferences\n
+        if (params.deleteEndpointsOnDetach != null) {\n
+            this.endpoints[0]._deleteOnDetach = params.deleteEndpointsOnDetach;\n
+            this.endpoints[1]._deleteOnDetach = params.deleteEndpointsOnDetach;\n
+        }\n
+        else {\n
+            // otherwise, unless the endpoints say otherwise, mark them for deletion.\n
+            if (!this.endpoints[0]._doNotDeleteOnDetach) this.endpoints[0]._deleteOnDetach = true;\n
+            if (!this.endpoints[1]._doNotDeleteOnDetach) this.endpoints[1]._deleteOnDetach = true;\n
+        }   \n
+                    \n
+        // TODO these could surely be refactored into some method that tries them one at a time until something exists\n
+        this.setConnector(this.endpoints[0].connector || \n
+                          this.endpoints[1].connector || \n
+                          params.connector || \n
+                          _jsPlumb.Defaults.Connector || \n
+                          jsPlumb.Defaults.Connector, true);\n
+\n
+        if (params.path)\n
+            this.connector.setPath(params.path);\n
+        \n
+        this.setPaintStyle(this.endpoints[0].connectorStyle || \n
+                           this.endpoints[1].connectorStyle || \n
+                           params.paintStyle || \n
+                           _jsPlumb.Defaults.PaintStyle || \n
+                           jsPlumb.Defaults.PaintStyle, true);\n
+                    \n
+        this.setHoverPaintStyle(this.endpoints[0].connectorHoverStyle || \n
+                                this.endpoints[1].connectorHoverStyle || \n
+                                params.hoverPaintStyle || \n
+                                _jsPlumb.Defaults.HoverPaintStyle || \n
+                                jsPlumb.Defaults.HoverPaintStyle, true);\n
+        \n
+        this._jsPlumb.paintStyleInUse = this.getPaintStyle();\n
+        \n
+        var _suspendedAt = _jsPlumb.getSuspendedAt();\n
+        _jsPlumb.updateOffset( { elId : this.sourceId, timestamp:_suspendedAt });\n
+        _jsPlumb.updateOffset( { elId : this.targetId, timestamp:_suspendedAt });\n
+\n
+//*\n
+        if(!_jsPlumb.isSuspendDrawing()) {                    \n
+            // paint the endpoints\n
+            var myInfo = _jsPlumb.getCachedData(this.sourceId),\n
+                myOffset = myInfo.o, myWH = myInfo.s,\n
+                otherInfo = _jsPlumb.getCachedData(this.targetId),\n
+                otherOffset = otherInfo.o,\n
+                otherWH = otherInfo.s,\n
+                initialTimestamp = _suspendedAt || _jsPlumb.timestamp(),\n
+                anchorLoc = this.endpoints[0].anchor.compute( {\n
+                    xy : [ myOffset.left, myOffset.top ], wh : myWH, element : this.endpoints[0],\n
+                    elementId:this.endpoints[0].elementId,\n
+                    txy : [ otherOffset.left, otherOffset.top ], twh : otherWH, tElement : this.endpoints[1],\n
+                    timestamp:initialTimestamp\n
+                });\n
+\n
+            this.endpoints[0].paint( { anchorLoc : anchorLoc, timestamp:initialTimestamp });\n
+\n
+            anchorLoc = this.endpoints[1].anchor.compute( {\n
+                xy : [ otherOffset.left, otherOffset.top ], wh : otherWH, element : this.endpoints[1],\n
+                elementId:this.endpoints[1].elementId,\t\t\t\t\n
+                txy : [ myOffset.left, myOffset.top ], twh : myWH, tElement : this.endpoints[0],\n
+                timestamp:initialTimestamp\t\t\t\t\n
+            });\n
+            this.endpoints[1].paint({ anchorLoc : anchorLoc, timestamp:initialTimestamp });\n
+        }\n
+        //*/\n
+                                \n
+// END INITIALISATION CODE\t\t\t\n
+        \n
+// DETACHABLE \t\t\t\t\n
+        this._jsPlumb.detachable = _jsPlumb.Defaults.ConnectionsDetachable;\n
+        if (params.detachable === false) this._jsPlumb.detachable = false;\n
+        if(this.endpoints[0].connectionsDetachable === false) this._jsPlumb.detachable = false;\n
+        if(this.endpoints[1].connectionsDetachable === false) this._jsPlumb.detachable = false;                \n
+// REATTACH\n
+        this._jsPlumb.reattach = params.reattach || this.endpoints[0].reattachConnections || this.endpoints[1].reattachConnections || _jsPlumb.Defaults.ReattachConnections;\n
+// COST + DIRECTIONALITY\n
+        // if cost not supplied, try to inherit from source endpoint\n
+        this._jsPlumb.cost = params.cost || this.endpoints[0].getConnectionCost();\t\t\t        \n
+        this._jsPlumb.directed = params.directed;\n
+        // inherit directed flag if set no source endpoint\n
+        if (params.directed == null) this._jsPlumb.directed = this.endpoints[0].areConnectionsDirected();        \n
+// END COST + DIRECTIONALITY\n
+                    \n
+// PARAMETERS\t\t\t\t\t\t\n
+        // merge all the parameters objects into the connection.  parameters set\n
+        // on the connection take precedence; then source endpoint params, then\n
+        // finally target endpoint params.\n
+        // TODO jsPlumb.extend could be made to take more than two args, and it would\n
+        // apply the second through nth args in order.\n
+        var _p = jsPlumb.extend({}, this.endpoints[1].getParameters());\n
+        jsPlumb.extend(_p, this.endpoints[0].getParameters());\n
+        jsPlumb.extend(_p, this.getParameters());\n
+        this.setParameters(_p);\n
+// END PARAMETERS\n
+\n
+// PAINTING\n
+                  \n
+        // the very last thing we do is apply types, if there are any.\n
+        var _types = [params.type, this.endpoints[0].connectionType, this.endpoints[1].connectionType ].join(" ");\n
+        if (/[^\\s]/.test(_types))\n
+            this.addType(_types, params.data, true);        \n
+\n
+        \n
+// END PAINTING    \n
+    };\n
+\n
+    jsPlumbUtil.extend(jsPlumb.Connection, OverlayCapableJsPlumbUIComponent, {\n
+        applyType : function(t, doNotRepaint) {            \n
+            if (t.detachable != null) this.setDetachable(t.detachable);\n
+            if (t.reattach != null) this.setReattach(t.reattach);\n
+            if (t.scope) this.scope = t.scope;\n
+            //editable = t.editable;  // TODO\n
+            this.setConnector(t.connector, doNotRepaint);\n
+        },\n
+        getTypeDescriptor : function() { return "connection"; },\n
+        getAttachedElements : function() {\n
+            return this.endpoints;\n
+        },\n
+        addClass : function(c, informEndpoints) {        \n
+            if (informEndpoints) {\n
+                this.endpoints[0].addClass(c);\n
+                this.endpoints[1].addClass(c); \n
+                if (this.suspendedEndpoint) this.suspendedEndpoint.addClass(c);                   \n
+            }\n
+            if (this.connector) {\n
+                this.connector.addClass(c);\n
+            }\n
+        },\n
+        removeClass : function(c, informEndpoints) {            \n
+            if (informEndpoints) {\n
+                this.endpoints[0].removeClass(c);\n
+                this.endpoints[1].removeClass(c);                    \n
+                if (this.suspendedEndpoint) this.suspendedEndpoint.removeClass(c);\n
+            }\n
+            if (this.connector) {\n
+                this.connector.removeClass(c);\n
+            }\n
+        },\n
+        isVisible : function() { return this._jsPlumb.visible; },\n
+        setVisible : function(v) {\n
+            this._jsPlumb.visible = v;\n
+            if (this.connector) \n
+                this.connector.setVisible(v);\n
+            this.repaint();\n
+        },\n
+        cleanup:function() {\n
+            this.endpoints = null;\n
+            this.source = null;\n
+            this.target = null;                    \n
+            if (this.connector != null) {\n
+                this.connector.cleanup();            \n
+                this.connector.destroy();\n
+            }\n
+            this.connector = null;\n
+        },\n
+        isDetachable : function() {\n
+            return this._jsPlumb.detachable === true;\n
+        },\n
+        setDetachable : function(detachable) {\n
+          this._jsPlumb.detachable = detachable === true;\n
+        },\n
+        isReattach : function() {\n
+            return this._jsPlumb.reattach === true;\n
+        },        \n
+        setReattach : function(reattach) {\n
+          this._jsPlumb.reattach = reattach === true;\n
+        },\n
+        setHover : function(state) {\n
+            if (this.connector && this._jsPlumb && !this._jsPlumb.instance.isConnectionBeingDragged()) {\n
+                this.connector.setHover(state);\n
+                jsPlumbAdapter[state ? "addClass" : "removeClass"](this.source, this._jsPlumb.instance.hoverSourceClass);\n
+                jsPlumbAdapter[state ? "addClass" : "removeClass"](this.target, this._jsPlumb.instance.hoverTargetClass);\n
+            }\n
+        },\n
+        getCost : function() { return this._jsPlumb.cost; },\n
+        setCost : function(c) { this._jsPlumb.cost = c; },\n
+        isDirected : function() { return this._jsPlumb.directed === true; },\n
+        getConnector : function() { return this.connector; },\n
+        setConnector : function(connectorSpec, doNotRepaint) {\n
+            var _ju = jsPlumbUtil;\n
+            if (this.connector != null) {\n
+                this.connector.cleanup();\n
+                this.connector.destroy();\n
+            }\n
+\n
+            var connectorArgs = { \n
+                    _jsPlumb:this._jsPlumb.instance, \n
+                    cssClass:this._jsPlumb.params.cssClass, \n
+                    container:this._jsPlumb.params.container,                 \n
+                    "pointer-events":this._jsPlumb.params["pointer-events"]\n
+                },\n
+                renderMode = this._jsPlumb.instance.getRenderMode();\n
+            \n
+            if (_ju.isString(connectorSpec)) \n
+                this.connector = makeConnector(this._jsPlumb.instance, renderMode, connectorSpec, connectorArgs); // lets you use a string as shorthand.\n
+            else if (_ju.isArray(connectorSpec)) {\n
+                if (connectorSpec.length == 1)\n
+                    this.connector = makeConnector(this._jsPlumb.instance, renderMode, connectorSpec[0], connectorArgs);\n
+                else\n
+                    this.connector = makeConnector(this._jsPlumb.instance, renderMode, connectorSpec[0], _ju.merge(connectorSpec[1], connectorArgs));\n
+            }\n
+            // binds mouse listeners to the current connector.\n
+            this.bindListeners(this.connector, this, function(state) {                \n
+                this.setHover(state, false);                \n
+            }.bind(this));\n
+            \n
+            this.canvas = this.connector.canvas;\n
+            this.bgCanvas = this.connector.bgCanvas;\n
+\n
+            if (this._jsPlumb.editable && jsPlumb.ConnectorEditors != null && jsPlumb.ConnectorEditors[this.connector.type] && this.connector.isEditable()) {\n
+                new jsPlumb.ConnectorEditors[this.connector.type]({\n
+                    connector:this.connector,\n
+                    connection:this,\n
+                    params:this._jsPlumb.params.editorParams || { }\n
+                });\n
+            }\n
+            else {                    \n
+                this._jsPlumb.editable = false;\n
+            }                \n
+                \n
+            if (!doNotRepaint) this.repaint();\n
+        },\n
+        paint : function(params) {\n
+                    \n
+            if (!this._jsPlumb.instance.isSuspendDrawing() && this._jsPlumb.visible) {\n
+                    \n
+                params = params || {};\n
+                var elId = params.elId, ui = params.ui, recalc = params.recalc, timestamp = params.timestamp,\n
+                    // if the moving object is not the source we must transpose the two references.\n
+                    swap = false,\n
+                    tId = swap ? this.sourceId : this.targetId, sId = swap ? this.targetId : this.sourceId,                    \n
+                    tIdx = swap ? 0 : 1, sIdx = swap ? 1 : 0;\n
+\n
+                if (timestamp == null || timestamp != this._jsPlumb.lastPaintedAt) {                        \n
+                    var sourceInfo = this._jsPlumb.instance.updateOffset( { elId : sId, offset : ui, recalc : recalc, timestamp : timestamp }).o,\n
+                        targetInfo = this._jsPlumb.instance.updateOffset( { elId : tId, timestamp : timestamp }).o, // update the target if this is a forced repaint. otherwise, only the source has been moved.\n
+                        sE = this.endpoints[sIdx], tE = this.endpoints[tIdx];\n
+\n
+                    if (params.clearEdits) {\n
+                        this._jsPlumb.overlayPositions = null;\n
+                        sE.anchor.clearUserDefinedLocation();\n
+                        tE.anchor.clearUserDefinedLocation();\n
+                        this.connector.setEdited(false);\n
+                    }\n
+                    \n
+                    var sAnchorP = sE.anchor.getCurrentLocation({xy:[sourceInfo.left,sourceInfo.top], wh:[sourceInfo.width, sourceInfo.height], element:sE, timestamp:timestamp}),              \n
+                        tAnchorP = tE.anchor.getCurrentLocation({xy:[targetInfo.left,targetInfo.top], wh:[targetInfo.width, targetInfo.height], element:tE, timestamp:timestamp});                                                 \n
+                        \n
+                    this.connector.resetBounds();\n
+\n
+                    this.connector.compute({\n
+                        sourcePos:sAnchorP,\n
+                        targetPos:tAnchorP, \n
+                        sourceEndpoint:this.endpoints[sIdx],\n
+                        targetEndpoint:this.endpoints[tIdx],\n
+                        lineWidth:this._jsPlumb.paintStyleInUse.lineWidth,                                          \n
+                        sourceInfo:sourceInfo,\n
+                        targetInfo:targetInfo,\n
+                        clearEdits:params.clearEdits === true\n
+                    });                                                                                        \n
+\n
+                    var overlayExtents = { minX:Infinity, minY:Infinity, maxX:-Infinity, maxY:-Infinity };\n
+                                        \n
+                    // compute overlays. we do this first so we can get their placements, and adjust the\n
+                    // container if needs be (if an overlay would be clipped)\n
+                    for ( var i = 0; i < this._jsPlumb.overlays.length; i++) {\n
+                        var o = this._jsPlumb.overlays[i];\n
+                        if (o.isVisible()) {                            \n
+                            this._jsPlumb.overlayPlacements[i] = o.draw(this.connector, this._jsPlumb.paintStyleInUse, this.getAbsoluteOverlayPosition(o));\n
+                            overlayExtents.minX = Math.min(overlayExtents.minX, this._jsPlumb.overlayPlacements[i].minX);\n
+                            overlayExtents.maxX = Math.max(overlayExtents.maxX, this._jsPlumb.overlayPlacements[i].maxX);\n
+                            overlayExtents.minY = Math.min(overlayExtents.minY, this._jsPlumb.overlayPlacements[i].minY);\n
+                            overlayExtents.maxY = Math.max(overlayExtents.maxY, this._jsPlumb.overlayPlacements[i].maxY);\n
+                        }\n
+                    }\n
+\n
+                    var lineWidth = parseFloat(this._jsPlumb.paintStyleInUse.lineWidth || 1) / 2,\n
+                        outlineWidth = parseFloat(this._jsPlumb.paintStyleInUse.lineWidth || 0),\n
+                        extents = {\n
+                            xmin : Math.min(this.connector.bounds.minX - (lineWidth + outlineWidth), overlayExtents.minX),\n
+                            ymin : Math.min(this.connector.bounds.minY - (lineWidth + outlineWidth), overlayExtents.minY),\n
+                            xmax : Math.max(this.connector.bounds.maxX + (lineWidth + outlineWidth), overlayExtents.maxX),\n
+                            ymax : Math.max(this.connector.bounds.maxY + (lineWidth + outlineWidth), overlayExtents.maxY)\n
+                        };\n
+\n
+                    // paint the connector.\n
+                    this.connector.paint(this._jsPlumb.paintStyleInUse, null, extents);  \n
+                    // and then the overlays\n
+                    for ( var j = 0; j < this._jsPlumb.overlays.length; j++) {\n
+                        var p = this._jsPlumb.overlays[j];\n
+                        if (p.isVisible()) {\n
+                            p.paint(this._jsPlumb.overlayPlacements[j], extents);    \n
+                        }\n
+                    }\n
+                }\n
+                this._jsPlumb.lastPaintedAt = timestamp;\n
+            }\n
+        },\n
+        /*\n
+         * Function: repaint\n
+         * Repaints the Connection. No parameters exposed to public API.\n
+         */\n
+        repaint : function(params) {\n
+            params = params || {};            \n
+            this.paint({ elId : this.sourceId, recalc : !(params.recalc === false), timestamp:params.timestamp, clearEdits:params.clearEdits });\n
+        },\n
+        prepareEndpoint : function(_jsPlumb, _newEndpoint, conn, existing, index, params, element, elementId) {\n
+            var e;\n
+            if (existing) {\n
+                conn.endpoints[index] = existing;\n
+                existing.addConnection(conn);                   \n
+            } else {\n
+                if (!params.endpoints) params.endpoints = [ null, null ];\n
+                var ep = params.endpoints[index]  || params.endpoint || _jsPlumb.Defaults.Endpoints[index] || jsPlumb.Defaults.Endpoints[index] || _jsPlumb.Defaults.Endpoint || jsPlumb.Defaults.Endpoint;\n
+                if (!params.endpointStyles) params.endpointStyles = [ null, null ];\n
+                if (!params.endpointHoverStyles) params.endpointHoverStyles = [ null, null ];\n
+                var es = params.endpointStyles[index] || params.endpointStyle || _jsPlumb.Defaults.EndpointStyles[index] || jsPlumb.Defaults.EndpointStyles[index] || _jsPlumb.Defaults.EndpointStyle || jsPlumb.Defaults.EndpointStyle;\n
+                // Endpoints derive their fillStyle from the connector\'s strokeStyle, if no fillStyle was specified.\n
+                if (es.fillStyle == null && params.paintStyle != null)\n
+                    es.fillStyle = params.paintStyle.strokeStyle;\n
+                \n
+                // TODO: decide if the endpoint should derive the connection\'s outline width and color.  currently it does:\n
+                //*\n
+                if (es.outlineColor == null && params.paintStyle !
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="5" aka="AAAAAAAAAAU=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+= null) \n
+                    es.outlineColor = params.paintStyle.outlineColor;\n
+                if (es.outlineWidth == null && params.paintStyle != null) \n
+                    es.outlineWidth = params.paintStyle.outlineWidth;\n
+                //*/\n
+                \n
+                var ehs = params.endpointHoverStyles[index] || params.endpointHoverStyle || _jsPlumb.Defaults.EndpointHoverStyles[index] || jsPlumb.Defaults.EndpointHoverStyles[index] || _jsPlumb.Defaults.EndpointHoverStyle || jsPlumb.Defaults.EndpointHoverStyle;\n
+                // endpoint hover fill style is derived from connector\'s hover stroke style.  TODO: do we want to do this by default? for sure?\n
+                if (params.hoverPaintStyle != null) {\n
+                    if (ehs == null) ehs = {};\n
+                    if (ehs.fillStyle == null) {\n
+                        ehs.fillStyle = params.hoverPaintStyle.strokeStyle;\n
+                    }\n
+                }\n
+                var a = params.anchors ? params.anchors[index] : \n
+                        params.anchor ? params.anchor :\n
+                        _makeAnchor(_jsPlumb.Defaults.Anchors[index], elementId, _jsPlumb) || \n
+                        _makeAnchor(jsPlumb.Defaults.Anchors[index], elementId,_jsPlumb) || \n
+                        _makeAnchor(_jsPlumb.Defaults.Anchor, elementId,_jsPlumb) || \n
+                        _makeAnchor(jsPlumb.Defaults.Anchor, elementId, _jsPlumb),                  \n
+                    u = params.uuids ? params.uuids[index] : null;\n
+                    \n
+                e = _newEndpoint({ \n
+                    paintStyle : es,  hoverPaintStyle:ehs,  endpoint : ep,  connections : [ conn ], \n
+                    uuid : u,  anchor : a,  source : element, scope  : params.scope,\n
+                    reattach:params.reattach || _jsPlumb.Defaults.ReattachConnections,\n
+                    detachable:params.detachable || _jsPlumb.Defaults.ConnectionsDetachable\n
+                });\n
+                conn.endpoints[index] = e;\n
+                \n
+                if (params.drawEndpoints === false) e.setVisible(false, true, true);\n
+                                    \n
+            }\n
+            return e;\n
+        }\n
+        \n
+    }); // END Connection class            \n
+})();\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the code for creating and manipulating anchors.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+;(function() {\t\n
+    \n
+    //\n
+\t// manages anchors for all elements.\n
+\t//\n
+\tjsPlumb.AnchorManager = function(params) {\n
+\t\tvar _amEndpoints = {},\n
+            continuousAnchors = {},\n
+            continuousAnchorLocations = {},\n
+            userDefinedContinuousAnchorLocations = {},        \n
+            continuousAnchorOrientations = {},\n
+            Orientation = { HORIZONTAL : "horizontal", VERTICAL : "vertical", DIAGONAL : "diagonal", IDENTITY:"identity" },\n
+\t\t\tconnectionsByElementId = {},\n
+\t\t\tself = this,\n
+            anchorLists = {},\n
+            jsPlumbInstance = params.jsPlumbInstance,\n
+            floatingConnections = {},\n
+            // TODO this functions uses a crude method of determining orientation between two elements.\n
+            // \'diagonal\' should be chosen when the angle of the line between the two centers is around\n
+            // one of 45, 135, 225 and 315 degrees. maybe +- 15 degrees.\n
+            // used by AnchorManager.redraw\n
+            calculateOrientation = function(sourceId, targetId, sd, td, sourceAnchor, targetAnchor) {\n
+        \n
+                if (sourceId === targetId) return {\n
+                    orientation:Orientation.IDENTITY,\n
+                    a:["top", "top"]\n
+                };\n
+        \n
+                var theta = Math.atan2((td.centery - sd.centery) , (td.centerx - sd.centerx)),\n
+                    theta2 = Math.atan2((sd.centery - td.centery) , (sd.centerx - td.centerx)),\n
+                    h = ((sd.left <= td.left && sd.right >= td.left) || (sd.left <= td.right && sd.right >= td.right) ||\n
+                        (sd.left <= td.left && sd.right >= td.right) || (td.left <= sd.left && td.right >= sd.right)),\n
+                    v = ((sd.top <= td.top && sd.bottom >= td.top) || (sd.top <= td.bottom && sd.bottom >= td.bottom) ||\n
+                        (sd.top <= td.top && sd.bottom >= td.bottom) || (td.top <= sd.top && td.bottom >= sd.bottom)),\n
+                    possiblyTranslateEdges = function(edges) {\n
+                        // this function checks to see if either anchor is Continuous, and if so, runs the suggested edge\n
+                        // through the anchor: Continuous anchors can say which faces they support, and they get to choose \n
+                        // whether a certain face is honoured, or, if not, which face to replace it with. the behaviour when\n
+                        // choosing an alternate face is to try for the opposite face first, then the next one clockwise, and then\n
+                        // the opposite of that one.\n
+                        return [\n
+                            sourceAnchor.isContinuous ? sourceAnchor.verifyEdge(edges[0]) : edges[0],    \n
+                            targetAnchor.isContinuous ? targetAnchor.verifyEdge(edges[1]) : edges[1]\n
+                        ];\n
+                    },\n
+                    out = {\n
+                        orientation:Orientation.DIAGONAL,\n
+                        theta:theta,\n
+                        theta2:theta2\n
+                    };                        \n
+                \n
+                if (! (h || v)) {                    \n
+                    if (td.left > sd.left && td.top > sd.top)\n
+                        out.a = ["right", "top"];\n
+                    else if (td.left > sd.left && sd.top > td.top)\n
+                        out.a = [ "top", "left"];\n
+                    else if (td.left < sd.left && td.top < sd.top)\n
+                        out.a = [ "top", "right"];\n
+                    else if (td.left < sd.left && td.top > sd.top)\n
+                        out.a = ["left", "top" ];                            \n
+                }\n
+                else if (h) {\n
+                    out.orientation = Orientation.HORIZONTAL;\n
+                    out.a = sd.top < td.top ? ["bottom", "top"] : ["top", "bottom"];                    \n
+                }\n
+                else {\n
+                    out.orientation = Orientation.VERTICAL;\n
+                    out.a = sd.left < td.left ? ["right", "left"] : ["left", "right"];\n
+                }\n
+                \n
+                out.a = possiblyTranslateEdges(out.a);\n
+                return out;\n
+            },\n
+                // used by placeAnchors function\n
+            placeAnchorsOnLine = function(desc, elementDimensions, elementPosition,\n
+                            connections, horizontal, otherMultiplier, reverse) {\n
+                var a = [], step = elementDimensions[horizontal ? 0 : 1] / (connections.length + 1);\n
+        \n
+                for (var i = 0; i < connections.length; i++) {\n
+                    var val = (i + 1) * step, other = otherMultiplier * elementDimensions[horizontal ? 1 : 0];\n
+                    if (reverse)\n
+                      val = elementDimensions[horizontal ? 0 : 1] - val;\n
+        \n
+                    var dx = (horizontal ? val : other), x = elementPosition[0] + dx,  xp = dx / elementDimensions[0],\n
+                        dy = (horizontal ? other : val), y = elementPosition[1] + dy, yp = dy / elementDimensions[1];\n
+        \n
+                    a.push([ x, y, xp, yp, connections[i][1], connections[i][2] ]);\n
+                }\n
+        \n
+                return a;\n
+            },\n
+            // used by edgeSortFunctions        \n
+            currySort = function(reverseAngles) {\n
+                return function(a,b) {\n
+                    var r = true;\n
+                    if (reverseAngles) {\n
+                        /*if (a[0][0] < b[0][0])\n
+                            r = true;\n
+                        else\n
+                            r = a[0][1] > b[0][1];*/\n
+                        r = a[0][0] < b[0][0];\n
+                    }\n
+                    else {\n
+                        /*if (a[0][0] > b[0][0])\n
+                            r= true;\n
+                        else\n
+                            r =a[0][1] > b[0][1];\n
+                        */\n
+                        r = a[0][0] > b[0][0];\n
+                    }\n
+                    return r === false ? -1 : 1;\n
+                };\n
+            },\n
+                // used by edgeSortFunctions\n
+            leftSort = function(a,b) {\n
+                // first get adjusted values\n
+                var p1 = a[0][0] < 0 ? -Math.PI - a[0][0] : Math.PI - a[0][0],\n
+                p2 = b[0][0] < 0 ? -Math.PI - b[0][0] : Math.PI - b[0][0];\n
+                if (p1 > p2) return 1;\n
+                else return a[0][1] > b[0][1] ? 1 : -1;\n
+            },\n
+                // used by placeAnchors\n
+            edgeSortFunctions = {\n
+                "top":function(a, b) { return a[0] > b[0] ? 1 : -1; },\n
+                "right":currySort(true),\n
+                "bottom":currySort(true),\n
+                "left":leftSort\n
+            },\n
+                // used by placeAnchors\n
+            _sortHelper = function(_array, _fn) { return _array.sort(_fn); },\n
+                // used by AnchorManager.redraw\n
+            placeAnchors = function(elementId, _anchorLists) {\t\t\n
+                var cd = jsPlumbInstance.getCachedData(elementId), sS = cd.s, sO = cd.o,\n
+                placeSomeAnchors = function(desc, elementDimensions, elementPosition, unsortedConnections, isHorizontal, otherMultiplier, orientation) {\n
+                    if (unsortedConnections.length > 0) {\n
+                        var sc = _sortHelper(unsortedConnections, edgeSortFunctions[desc]), // puts them in order based on the target element\'s pos on screen\n
+                            reverse = desc === "right" || desc === "top",\n
+                            anchors = placeAnchorsOnLine(desc, elementDimensions,\n
+                                                     elementPosition, sc,\n
+                                                     isHorizontal, otherMultiplier, reverse );\n
+        \n
+                        // takes a computed anchor position and adjusts it for parent offset and scroll, then stores it.\n
+                        var _setAnchorLocation = function(endpoint, anchorPos) {                            \n
+                            continuousAnchorLocations[endpoint.id] = [ anchorPos[0], anchorPos[1], anchorPos[2], anchorPos[3] ];\n
+                            continuousAnchorOrientations[endpoint.id] = orientation;\n
+                        };\n
+        \n
+                        for (var i = 0; i < anchors.length; i++) {\n
+                            var c = anchors[i][4], weAreSource = c.endpoints[0].elementId === elementId, weAreTarget = c.endpoints[1].elementId === elementId;\n
+                            if (weAreSource)\n
+                                _setAnchorLocation(c.endpoints[0], anchors[i]);\n
+                            else if (weAreTarget)\n
+                                _setAnchorLocation(c.endpoints[1], anchors[i]);\n
+                        }\n
+                    }\n
+                };\n
+        \n
+                placeSomeAnchors("bottom", sS, [sO.left,sO.top], _anchorLists.bottom, true, 1, [0,1]);\n
+                placeSomeAnchors("top", sS, [sO.left,sO.top], _anchorLists.top, true, 0, [0,-1]);\n
+                placeSomeAnchors("left", sS, [sO.left,sO.top], _anchorLists.left, false, 0, [-1,0]);\n
+                placeSomeAnchors("right", sS, [sO.left,sO.top], _anchorLists.right, false, 1, [1,0]);\n
+            };\n
+\n
+        this.reset = function() {\n
+            _amEndpoints = {};\n
+            connectionsByElementId = {};\n
+            anchorLists = {};\n
+        };\t\t\t\n
+        this.addFloatingConnection = function(key, conn) {\n
+            floatingConnections[key] = conn;\n
+        };\n
+        this.removeFloatingConnection = function(key) {\n
+            delete floatingConnections[key];\n
+        };                                                 \n
+        this.newConnection = function(conn) {\n
+\t\t\tvar sourceId = conn.sourceId, targetId = conn.targetId,\n
+\t\t\t\tep = conn.endpoints,\n
+                doRegisterTarget = true,\n
+                registerConnection = function(otherIndex, otherEndpoint, otherAnchor, elId, c) {\n
+\t\t\t\t\tif ((sourceId == targetId) && otherAnchor.isContinuous){\n
+                       // remove the target endpoint\'s canvas.  we dont need it.\n
+                        conn._jsPlumb.instance.removeElement(ep[1].canvas);\n
+                        doRegisterTarget = false;\n
+                    }\n
+\t\t\t\t\tjsPlumbUtil.addToList(connectionsByElementId, elId, [c, otherEndpoint, otherAnchor.constructor == jsPlumb.DynamicAnchor]);\n
+\t\t\t    };\n
+\n
+\t\t\tregisterConnection(0, ep[0], ep[0].anchor, targetId, conn);\n
+            if (doRegisterTarget)\n
+            \tregisterConnection(1, ep[1], ep[1].anchor, sourceId, conn);\n
+\t\t};\n
+        var removeEndpointFromAnchorLists = function(endpoint) {\n
+            (function(list, eId) {\n
+                if (list) {  // transient anchors dont get entries in this list.\n
+                    var f = function(e) { return e[4] == eId; };\n
+                    jsPlumbUtil.removeWithFunction(list.top, f);\n
+                    jsPlumbUtil.removeWithFunction(list.left, f);\n
+                    jsPlumbUtil.removeWithFunction(list.bottom, f);\n
+                    jsPlumbUtil.removeWithFunction(list.right, f);\n
+                }\n
+            })(anchorLists[endpoint.elementId], endpoint.id);\n
+        };\n
+\t\tthis.connectionDetached = function(connInfo) {\n
+            var connection = connInfo.connection || connInfo,\n
+\t\t\t    sourceId = connInfo.sourceId,\n
+                targetId = connInfo.targetId,\n
+\t\t\t\tep = connection.endpoints,\n
+\t\t\t\tremoveConnection = function(otherIndex, otherEndpoint, otherAnchor, elId, c) {\n
+\t\t\t\t\tif (otherAnchor != null && otherAnchor.constructor == jsPlumb.FloatingAnchor) {\n
+\t\t\t\t\t\t// no-op\n
+\t\t\t\t\t}\n
+\t\t\t\t\telse {\n
+\t\t\t\t\t\tjsPlumbUtil.removeWithFunction(connectionsByElementId[elId], function(_c) {\n
+\t\t\t\t\t\t\treturn _c[0].id == c.id;\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t}\n
+\t\t\t\t};\n
+\t\t\t\t\n
+\t\t\tremoveConnection(1, ep[1], ep[1].anchor, sourceId, connection);\n
+\t\t\tremoveConnection(0, ep[0], ep[0].anchor, targetId, connection);\n
+\n
+            // remove from anchorLists            \n
+            removeEndpointFromAnchorLists(connection.endpoints[0]);\n
+            removeEndpointFromAnchorLists(connection.endpoints[1]);\n
+\n
+            self.redraw(connection.sourceId);\n
+            self.redraw(connection.targetId);\n
+\t\t};\n
+\t\tthis.add = function(endpoint, elementId) {\n
+\t\t\tjsPlumbUtil.addToList(_amEndpoints, elementId, endpoint);\n
+\t\t};\n
+\t\tthis.changeId = function(oldId, newId) {\n
+\t\t\tconnectionsByElementId[newId] = connectionsByElementId[oldId];\n
+\t\t\t_amEndpoints[newId] = _amEndpoints[oldId];\n
+\t\t\tdelete connectionsByElementId[oldId];\n
+\t\t\tdelete _amEndpoints[oldId];\t\n
+\t\t};\n
+\t\tthis.getConnectionsFor = function(elementId) {\n
+\t\t\treturn connectionsByElementId[elementId] || [];\n
+\t\t};\n
+\t\tthis.getEndpointsFor = function(elementId) {\n
+\t\t\treturn _amEndpoints[elementId] || [];\n
+\t\t};\n
+\t\tthis.deleteEndpoint = function(endpoint) {\n
+\t\t\tjsPlumbUtil.removeWithFunction(_amEndpoints[endpoint.elementId], function(e) {\n
+\t\t\t\treturn e.id == endpoint.id;\n
+\t\t\t});\n
+            removeEndpointFromAnchorLists(endpoint);\n
+\t\t};\n
+\t\tthis.clearFor = function(elementId) {\n
+\t\t\tdelete _amEndpoints[elementId];\n
+\t\t\t_amEndpoints[elementId] = [];\n
+\t\t};\n
+        // updates the given anchor list by either updating an existing anchor\'s info, or adding it. this function\n
+        // also removes the anchor from its previous list, if the edge it is on has changed.\n
+        // all connections found along the way (those that are connected to one of the faces this function\n
+        // operates on) are added to the connsToPaint list, as are their endpoints. in this way we know to repaint\n
+        // them wthout having to calculate anything else about them.\n
+        var _updateAnchorList = function(lists, theta, order, conn, aBoolean, otherElId, idx, reverse, edgeId, elId, connsToPaint, endpointsToPaint) {        \n
+            // first try to find the exact match, but keep track of the first index of a matching element id along the way.s\n
+            var exactIdx = -1,\n
+                firstMatchingElIdx = -1,\n
+                endpoint = conn.endpoints[idx],\n
+                endpointId = endpoint.id,\n
+                oIdx = [1,0][idx],\n
+                values = [ [ theta, order ], conn, aBoolean, otherElId, endpointId ],\n
+                listToAddTo = lists[edgeId],\n
+                listToRemoveFrom = endpoint._continuousAnchorEdge ? lists[endpoint._continuousAnchorEdge] : null;\n
+\n
+            if (listToRemoveFrom) {\n
+                var rIdx = jsPlumbUtil.findWithFunction(listToRemoveFrom, function(e) { return e[4] == endpointId; });\n
+                if (rIdx != -1) {\n
+                    listToRemoveFrom.splice(rIdx, 1);\n
+                    // get all connections from this list\n
+                    for (var i = 0; i < listToRemoveFrom.length; i++) {\n
+                        jsPlumbUtil.addWithFunction(connsToPaint, listToRemoveFrom[i][1], function(c) { return c.id == listToRemoveFrom[i][1].id; });\n
+                        jsPlumbUtil.addWithFunction(endpointsToPaint, listToRemoveFrom[i][1].endpoints[idx], function(e) { return e.id == listToRemoveFrom[i][1].endpoints[idx].id; });\n
+                        jsPlumbUtil.addWithFunction(endpointsToPaint, listToRemoveFrom[i][1].endpoints[oIdx], function(e) { return e.id == listToRemoveFrom[i][1].endpoints[oIdx].id; });\n
+                    }\n
+                }\n
+            }\n
+\n
+            for (i = 0; i < listToAddTo.length; i++) {\n
+                if (params.idx == 1 && listToAddTo[i][3] === otherElId && firstMatchingElIdx == -1)\n
+                    firstMatchingElIdx = i;\n
+                jsPlumbUtil.addWithFunction(connsToPaint, listToAddTo[i][1], function(c) { return c.id == listToAddTo[i][1].id; });                \n
+                jsPlumbUtil.addWithFunction(endpointsToPaint, listToAddTo[i][1].endpoints[idx], function(e) { return e.id == listToAddTo[i][1].endpoints[idx].id; });\n
+                jsPlumbUtil.addWithFunction(endpointsToPaint, listToAddTo[i][1].endpoints[oIdx], function(e) { return e.id == listToAddTo[i][1].endpoints[oIdx].id; });\n
+            }\n
+            if (exactIdx != -1) {\n
+                listToAddTo[exactIdx] = values;\n
+            }\n
+            else {\n
+                var insertIdx = reverse ? firstMatchingElIdx != -1 ? firstMatchingElIdx : 0 : listToAddTo.length; // of course we will get this from having looked through the array shortly.\n
+                listToAddTo.splice(insertIdx, 0, values);\n
+            }\n
+\n
+            // store this for next time.\n
+            endpoint._continuousAnchorEdge = edgeId;\n
+        };\n
+\n
+        //\n
+        // find the entry in an endpoint\'s list for this connection and update its target endpoint\n
+        // with the current target in the connection.\n
+        // \n
+        //\n
+        this.updateOtherEndpoint = function(elId, oldTargetId, newTargetId, connection) {\n
+            var sIndex = jsPlumbUtil.findWithFunction(connectionsByElementId[elId], function(i) {\n
+                    return i[0].id === connection.id;\n
+                }),\n
+                tIndex = jsPlumbUtil.findWithFunction(connectionsByElementId[oldTargetId], function(i) {\n
+                    return i[0].id === connection.id;\n
+                });\n
+\n
+            // update or add data for source\n
+            if (sIndex != -1) {\n
+                connectionsByElementId[elId][sIndex][0] = connection;\n
+                connectionsByElementId[elId][sIndex][1] = connection.endpoints[1];\n
+                connectionsByElementId[elId][sIndex][2] = connection.endpoints[1].anchor.constructor == jsPlumb.DynamicAnchor;\n
+            }\n
+\n
+            // remove entry for previous target (if there)\n
+            if (tIndex > -1) {\n
+\n
+                connectionsByElementId[oldTargetId].splice(tIndex, 1);\n
+                // add entry for new target\n
+                jsPlumbUtil.addToList(connectionsByElementId, newTargetId, [connection, connection.endpoints[0], connection.endpoints[0].anchor.constructor == jsPlumb.DynamicAnchor]);         \n
+            }\n
+        };       \n
+        \n
+        //\n
+        // notification that the connection given has changed source from the originalId to the newId.\n
+        // This involves:\n
+        // 1. removing the connection from the list of connections stored for the originalId\n
+        // 2. updating the source information for the target of the connection\n
+        // 3. re-registering the connection in connectionsByElementId with the newId\n
+        //\n
+        this.sourceChanged = function(originalId, newId, connection) {        \n
+            if (originalId !== newId) {    \n
+                // remove the entry that points from the old source to the target\n
+                jsPlumbUtil.removeWithFunction(connectionsByElementId[originalId], function(info) {\n
+                    return info[0].id === connection.id;\n
+                });\n
+                // find entry for target and update it\n
+                var tIdx = jsPlumbUtil.findWithFunction(connectionsByElementId[connection.targetId], function(i) {\n
+                    return i[0].id === connection.id;\n
+                });\n
+                if (tIdx > -1) {\n
+                    connectionsByElementId[connection.targetId][tIdx][0] = connection;\n
+                    connectionsByElementId[connection.targetId][tIdx][1] = connection.endpoints[0];\n
+                    connectionsByElementId[connection.targetId][tIdx][2] = connection.endpoints[0].anchor.constructor == jsPlumb.DynamicAnchor;\n
+                }\n
+                // add entry for new source\n
+                jsPlumbUtil.addToList(connectionsByElementId, newId, [connection, connection.endpoints[1], connection.endpoints[1].anchor.constructor == jsPlumb.DynamicAnchor]);         \n
+            }\n
+        };\n
+\n
+        //\n
+        // moves the given endpoint from `currentId` to `element`.\n
+        // This involves:\n
+        //\n
+        // 1. changing the key in _amEndpoints under which the endpoint is stored\n
+        // 2. changing the source or target values in all of the endpoint\'s connections\n
+        // 3. changing the array in connectionsByElementId in which the endpoint\'s connections\n
+        //    are stored (done by either sourceChanged or updateOtherEndpoint)\n
+        //\n
+        this.rehomeEndpoint = function(ep, currentId, element) {\n
+            var eps = _amEndpoints[currentId] || [], \n
+                elementId = jsPlumbInstance.getId(element);\n
+                \n
+            if (elementId !== currentId) {\n
+                var idx = jsPlumbUtil.indexOf(eps, ep);\n
+                if (idx > -1) {\n
+                    var _ep = eps.splice(idx, 1)[0];\n
+                    self.add(_ep, elementId);\n
+                }\n
+            }\n
+\n
+            for (var i = 0; i < ep.connections.length; i++) {                \n
+                if (ep.connections[i].sourceId == currentId) {\n
+                    ep.connections[i].sourceId = ep.elementId;\n
+                    ep.connections[i].source = ep.element;                  \n
+                    self.sourceChanged(currentId, ep.elementId, ep.connections[i]);\n
+                }\n
+                else if(ep.connections[i].targetId == currentId) {\n
+                    ep.connections[i].targetId = ep.elementId;\n
+                    ep.connections[i].target = ep.element;   \n
+                    self.updateOtherEndpoint(ep.connections[i].sourceId, currentId, ep.elementId, ep.connections[i]);               \n
+                }\n
+            }   \n
+        };\n
+\n
+\t\tthis.redraw = function(elementId, ui, timestamp, offsetToUI, clearEdits, doNotRecalcEndpoint) {\n
+\t\t\n
+\t\t\tif (!jsPlumbInstance.isSuspendDrawing()) {\n
+\t\t\t\t// get all the endpoints for this element\n
+\t\t\t\tvar ep = _amEndpoints[elementId] || [],\n
+\t\t\t\t\tendpointConnections = connectionsByElementId[elementId] || [],\n
+\t\t\t\t\tconnectionsToPaint = [],\n
+\t\t\t\t\tendpointsToPaint = [],\n
+\t                anchorsToUpdate = [];\n
+\t            \n
+\t\t\t\ttimestamp = timestamp || jsPlumbInstance.timestamp();\n
+\t\t\t\t// offsetToUI are values that would have been calculated in the dragManager when registering\n
+\t\t\t\t// an endpoint for an element that had a parent (somewhere in the hierarchy) that had been\n
+\t\t\t\t// registered as draggable.\n
+\t\t\t\toffsetToUI = offsetToUI || {left:0, top:0};\n
+\t\t\t\tif (ui) {\n
+\t\t\t\t\tui = {\n
+\t\t\t\t\t\tleft:ui.left + offsetToUI.left,\n
+\t\t\t\t\t\ttop:ui.top + offsetToUI.top\n
+\t\t\t\t\t};\n
+\t\t\t\t}\n
+\t\t\t\t\t\t\t\t\t\n
+\t\t\t\t// valid for one paint cycle.\n
+\t\t\t\tvar myOffset = jsPlumbInstance.updateOffset( { elId : elementId, offset : ui, recalc : false, timestamp : timestamp }),\n
+\t                orientationCache = {};\n
+\t\t\t\t\n
+\t\t\t\t// actually, first we should compute the orientation of this element to all other elements to which\n
+\t\t\t\t// this element is connected with a continuous anchor (whether both ends of the connection have\n
+\t\t\t\t// a continuous anchor or just one)\n
+\t                        \n
+\t            for (var i = 0; i < endpointConnections.length; i++) {\n
+\t                var conn = endpointConnections[i][0],\n
+\t\t\t\t\t\tsourceId = conn.sourceId,\n
+\t                    targetId = conn.targetId,\n
+\t                    sourceContinuous = conn.endpoints[0].anchor.isContinuous,\n
+\t                    targetContinuous = conn.endpoints[1].anchor.isContinuous;\n
+\t\n
+\t                if (sourceContinuous || targetContinuous) {\n
+\t\t                var oKey = sourceId + "_" + targetId,\n
+\t\t                    oKey2 = targetId + "_" + sourceId,\n
+\t\t                    o = orientationCache[oKey],\n
+\t\t                    oIdx = conn.sourceId == elementId ? 1 : 0;\n
+\t\n
+\t\t                if (sourceContinuous && !anchorLists[sourceId]) anchorLists[sourceId] = { top:[], right:[], bottom:[], left:[] };\n
+\t\t                if (targetContinuous && !anchorLists[targetId]) anchorLists[targetId] = { top:[], right:[], bottom:[], left:[] };\n
+\t\n
+\t\t                if (elementId != targetId) jsPlumbInstance.updateOffset( { elId : targetId, timestamp : timestamp }); \n
+\t\t                if (elementId != sourceId) jsPlumbInstance.updateOffset( { elId : sourceId, timestamp : timestamp }); \n
+\t\n
+\t\t                var td = jsPlumbInstance.getCachedData(targetId),\n
+\t\t\t\t\t\t\tsd = jsPlumbInstance.getCachedData(sourceId);\n
+\t\n
+\t\t                if (targetId == sourceId && (sourceContinuous || targetContinuous)) {\n
+\t\t                    // here we may want to improve this by somehow determining the face we\'d like\n
+\t\t\t\t\t\t    // to put the connector on.  ideally, when drawing, the face should be calculated\n
+\t\t\t\t\t\t    // by determining which face is closest to the point at which the mouse button\n
+\t\t\t\t\t\t\t// was released.  for now, we\'re putting it on the top face.                            \n
+\t\t                    _updateAnchorList(\n
+                                anchorLists[sourceId], \n
+                                -Math.PI / 2, \n
+                                0, \n
+                                conn, \n
+                                false, \n
+                                targetId, \n
+                                0, false, "top", sourceId, connectionsToPaint, endpointsToPaint);\n
+\t\t\t\t\t\t}\n
+\t\t                else {\n
+\t\t                    if (!o) {\n
+\t\t                        o = calculateOrientation(sourceId, targetId, sd.o, td.o, conn.endpoints[0].anchor, conn.endpoints[1].anchor);\n
+\t\t                        orientationCache[oKey] = o;\n
+\t\t                        // this would be a performance enhancement, but the computed angles need to be clamped to\n
+\t\t                        //the (-PI/2 -> PI/2) range in order for the sorting to work properly.\n
+\t\t                    /*  orientationCache[oKey2] = {\n
+\t\t                            orientation:o.orientation,\n
+\t\t                            a:[o.a[1], o.a[0]],\n
+\t\t                            theta:o.theta + Math.PI,\n
+\t\t                            theta2:o.theta2 + Math.PI\n
+\t\t                        };*/\n
+\t\t                    }\n
+\t\t                    if (sourceContinuous) _updateAnchorList(anchorLists[sourceId], o.theta, 0, conn, false, targetId, 0, false, o.a[0], sourceId, connectionsToPaint, endpointsToPaint);\n
+\t\t                    if (targetContinuous) _updateAnchorList(anchorLists[targetId], o.theta2, -1, conn, true, sourceId, 1, true, o.a[1], targetId, connectionsToPaint, endpointsToPaint);\n
+\t\t                }\n
+\t\n
+\t\t                if (sourceContinuous) jsPlumbUtil.addWithFunction(anchorsToUpdate, sourceId, function(a) { return a === sourceId; });\n
+\t\t                if (targetContinuous) jsPlumbUtil.addWithFunction(anchorsToUpdate, targetId, function(a) { return a === targetId; });\n
+\t\t                jsPlumbUtil.addWithFunction(connectionsToPaint, conn, function(c) { return c.id == conn.id; });\n
+\t\t                if ((sourceContinuous && oIdx === 0) || (targetContinuous && oIdx === 1))\n
+\t\t                \tjsPlumbUtil.addWithFunction(endpointsToPaint, conn.endpoints[oIdx], function(e) { return e.id == conn.endpoints[oIdx].id; });\n
+\t\t            }\n
+\t            }\t\t\t\t\n
+\t\t\t\t// place Endpoints whose anchors are continuous but have no Connections\n
+\t\t\t\tfor (i = 0; i < ep.length; i++) {\n
+\t\t\t\t\tif (ep[i].connections.length === 0 && ep[i].anchor.isContinuous) {\n
+\t\t\t\t\t\tif (!anchorLists[elementId]) anchorLists[elementId] = { top:[], right:[], bottom:[], left:[] };\n
+\t\t\t\t\t\t_updateAnchorList(anchorLists[elementId], -Math.PI / 2, 0, {endpoints:[ep[i], ep[i]], paint:function(){}}, false, elementId, 0, false, "top", elementId, connectionsToPaint, endpointsToPaint);\n
+\t\t\t\t\t\tjsPlumbUtil.addWithFunction(anchorsToUpdate, elementId, function(a) { return a === elementId; });\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t            // now place all the continuous anchors we need to;\n
+\t            for (i = 0; i < anchorsToUpdate.length; i++) {\n
+\t\t\t\t\tplaceAnchors(anchorsToUpdate[i], anchorLists[anchorsToUpdate[i]]);\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// now that continuous anchors have been placed, paint all the endpoints for this element\n
+\t            // TODO performance: add the endpoint ids to a temp array, and then when iterating in the next\n
+\t            // loop, check that we didn\'t just paint that endpoint. we can probably shave off a few more milliseconds this way.\n
+\t\t\t\tfor (i = 0; i < ep.length; i++) {\t\t\t\t\n
+                    ep[i].paint( { timestamp : timestamp, offset : myOffset, dimensions : myOffset.s, recalc:doNotRecalcEndpoint !== true });\n
+\t\t\t\t}\n
+\t            // ... and any other endpoints we came across as a result of the continuous anchors.\n
+\t            for (i = 0; i < endpointsToPaint.length; i++) {\n
+                    var cd = jsPlumbInstance.getCachedData(endpointsToPaint[i].elementId);\n
+                    // dont use timestamp for this endpoint, as it is not for the current element and we may \n
+                    // have needed to recalculate anchor position due to the element for the endpoint moving.\n
+                    //endpointsToPaint[i].paint( { timestamp : null, offset : cd, dimensions : cd.s });\n
+\n
+                    endpointsToPaint[i].paint( { timestamp : timestamp, offset : cd, dimensions : cd.s });\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// paint all the standard and "dynamic connections", which are connections whose other anchor is\n
+\t\t\t\t// static and therefore does need to be recomputed; we make sure that happens only one time.\n
+\t\n
+\t\t\t\t// TODO we could have compiled a list of these in the first pass through connections; might save some time.\n
+\t\t\t\tfor (i = 0; i < endpointConnections.length; i++) {\n
+\t\t\t\t\tvar otherEndpoint = endpointConnections[i][1];\n
+\t\t\t\t\tif (otherEndpoint.anchor.constructor == jsPlumb.DynamicAnchor) {\t\t\t \t\t\t\t\t\t\t\n
+\t\t\t\t\t\totherEndpoint.paint({ elementWithPrecedence:elementId, timestamp:timestamp });\t\t\t\t\t\t\t\t\n
+\t                    jsPlumbUtil.addWithFunction(connectionsToPaint, endpointConnections[i][0], function(c) { return c.id == endpointConnections[i][0].id; });\n
+\t\t\t\t\t\t// all the connections for the other endpoint now need to be repainted\n
+\t\t\t\t\t\tfor (var k = 0; k < otherEndpoint.connections.length; k++) {\n
+\t\t\t\t\t\t\tif (otherEndpoint.connections[k] !== endpointConnections[i][0])\t\t\t\t\t\t\t\n
+\t                            jsPlumbUtil.addWithFunction(connectionsToPaint, otherEndpoint.connections[k], function(c) { return c.id == otherEndpoint.connections[k].id; });\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t} else if (otherEndpoint.anchor.constructor == jsPlumb.Anchor) {\t\t\t\t\t\n
+\t                    jsPlumbUtil.addWithFunction(connectionsToPaint, endpointConnections[i][0], function(c) { return c.id == endpointConnections[i][0].id; });\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\t// paint current floating connection for this element, if there is one.\n
+\t\t\t\tvar fc = floatingConnections[elementId];\n
+\t\t\t\tif (fc) \n
+\t\t\t\t\tfc.paint({timestamp:timestamp, recalc:false, elId:elementId});\n
+\t\t\t\t                \n
+\t\t\t\t// paint all the connections\n
+\t\t\t\tfor (i = 0; i < connectionsToPaint.length; i++) {\n
+\t\t\t\t\t// if not a connection between the two elements in question dont use the timestamp.\n
+                    var ts  =timestamp;// ((connectionsToPaint[i].sourceId == sourceId && connectionsToPaint[i].targetId == targetId) ||\n
+                               //(connectionsToPaint[i].sourceId == targetId && connectionsToPaint[i].targetId == sourceId)) ? timestamp : null;\n
+                    connectionsToPaint[i].paint({elId:elementId, timestamp:ts, recalc:false, clearEdits:clearEdits});\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t};        \n
+        \n
+        var ContinuousAnchor = function(anchorParams) {\n
+            jsPlumbUtil.EventGenerator.apply(this);\n
+            this.type = "Continuous";\n
+            this.isDynamic = true;\n
+            this.isContinuous = true;\n
+            var faces = anchorParams.faces || ["top", "right", "bottom", "left"],\n
+                clockwise = !(anchorParams.clockwise === false),\n
+                availableFaces = { },\n
+                opposites = { "top":"bottom", "right":"left","left":"right","bottom":"top" },\n
+                clockwiseOptions = { "top":"right", "right":"bottom","left":"top","bottom":"left" },\n
+                antiClockwiseOptions = { "top":"left", "right":"top","left":"bottom","bottom":"right" },\n
+                secondBest = clockwise ? clockwiseOptions : antiClockwiseOptions,\n
+                lastChoice = clockwise ? antiClockwiseOptions : clockwiseOptions,\n
+                cssClass = anchorParams.cssClass || "";\n
+            \n
+            for (var i = 0; i < faces.length; i++) { availableFaces[faces[i]] = true; }\n
+          \n
+            // if the given edge is supported, returns it. otherwise looks for a substitute that _is_\n
+            // supported. if none supported we also return the request edge.\n
+            this.verifyEdge = function(edge) {\n
+                if (availableFaces[edge]) return edge;\n
+                else if (availableFaces[opposites[edge]]) return opposites[edge];\n
+                else if (availableFaces[secondBest[edge]]) return secondBest[edge];\n
+                else if (availableFaces[lastChoice[edge]]) return lastChoice[edge];\n
+                return edge; // we have to give them something.\n
+            };\n
+            \n
+            this.compute = function(params) {\n
+                return userDefinedContinuousAnchorLocations[params.element.id] || continuousAnchorLocations[params.element.id] || [0,0];\n
+            };\n
+            this.getCurrentLocation = function(params) {\n
+                return userDefinedContinuousAnchorLocations[params.element.id] || continuousAnchorLocations[params.element.id] || [0,0];\n
+            };\n
+            this.getOrientation = function(endpoint) {\n
+                return continuousAnchorOrientations[endpoint.id] || [0,0];\n
+            };\n
+            this.clearUserDefinedLocation = function() { \n
+                delete userDefinedContinuousAnchorLocations[anchorParams.elementId]; \n
+            };\n
+            this.setUserDefinedLocation = function(loc) { \n
+                userDefinedContinuousAnchorLocations[anchorParams.elementId] = loc; \n
+            };            \n
+            this.getCssClass = function() { return cssClass; };\n
+            this.setCssClass = function(c) { cssClass = c; };\n
+        };        \n
+        \n
+        // continuous anchors\n
+        jsPlumbInstance.continuousAnchorFactory = {\n
+            get:function(params) {\n
+                var existing = continuousAnchors[params.elementId];\n
+                if (!existing) {\n
+                    existing = new ContinuousAnchor(params);                    \n
+                    continuousAnchors[params.elementId] = existing;\n
+                }\n
+                return existing;\n
+            },\n
+            clear:function(elementId) {\n
+                delete continuousAnchors[elementId];\n
+            }\n
+        };\n
+\t};\n
+    \n
+    /**\n
+     * Anchors model a position on some element at which an Endpoint may be located.  They began as a first class citizen of jsPlumb, ie. a user\n
+     * was required to create these themselves, but over time this has been replaced by the concept of referring to them either by name (eg. "TopMiddle"),\n
+     * or by an array describing their coordinates (eg. [ 0, 0.5, 0, -1 ], which is the same as "TopMiddle").  jsPlumb now handles all of the\n
+     * creation of Anchors without user intervention.\n
+     */\n
+    jsPlumb.Anchor = function(params) {       \n
+        this.x = params.x || 0;\n
+        this.y = params.y || 0;\n
+        this.elementId = params.elementId;  \n
+        this.cssClass = params.cssClass || "";      \n
+        this.userDefinedLocation = null;\n
+        this.orientation = params.orientation || [ 0, 0 ];\n
+\n
+        jsPlumbUtil.EventGenerator.apply(this);\n
+        \n
+        var jsPlumbInstance = params.jsPlumbInstance;//,\n
+            //lastTimestamp = null;//, lastReturnValue = null;\n
+        \n
+        this.lastReturnValue = null;\n
+        this.offsets = params.offsets || [ 0, 0 ];\n
+        this.timestamp = null;        \n
+        this.compute = function(params) {\n
+\n
+\t\t\tvar xy = params.xy, wh = params.wh, element = params.element, timestamp = params.timestamp; \n
+\n
+\t\t\tif(params.clearUserDefinedLocation)\n
+\t\t\t\tthis.userDefinedLocation = null;\n
+\n
+\t\t\tif (timestamp && timestamp === self.timestamp)\n
+\t\t\t\treturn this.lastReturnValue;\n
+\n
+\t\t\tif (this.userDefinedLocation != null) {\n
+\t\t\t\tthis.lastReturnValue = this.userDefinedLocation;\n
+\t\t\t}\n
+\t\t\telse {\n
+\t\t\t\tthis.lastReturnValue = [ xy[0] + (this.x * wh[0]) + this.offsets[0], xy[1] + (this.y * wh[1]) + this.offsets[1] ];\n
+\t\t\t}\n
+\n
+\t\t\tthis.timestamp = timestamp;\n
+\t\t\treturn this.lastReturnValue;\n
+\t\t};\n
+\n
+        this.getCurrentLocation = function(params) { \n
+            return (this.lastReturnValue == null || (params.timestamp != null && this.timestamp != params.timestamp)) ? this.compute(params) : this.lastReturnValue; \n
+        };\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Anchor, jsPlumbUtil.EventGenerator, {\n
+        equals : function(anchor) {\n
+            if (!anchor) return false;\n
+            var ao = anchor.getOrientation(),\n
+                o = this.getOrientation();\n
+            return this.x == anchor.x && this.y == anchor.y && this.offsets[0] == anchor.offsets[0] && this.offsets[1] == anchor.offsets[1] && o[0] == ao[0] && o[1] == ao[1];\n
+        },\n
+        getUserDefinedLocation : function() { \n
+            return this.userDefinedLocation;\n
+        },        \n
+        setUserDefinedLocation : function(l) {\n
+            this.userDefinedLocation = l;\n
+        },\n
+        clearUserDefinedLocation : function() {\n
+            this.userDefinedLocation = null;\n
+        },\n
+        getOrientation : function(_endpoint) { return this.orientation; },\n
+        getCssClass : function() { return this.cssClass; }\n
+    });\n
+\n
+    /**\n
+     * An Anchor that floats. its orientation is computed dynamically from\n
+     * its position relative to the anchor it is floating relative to.  It is used when creating \n
+     * a connection through drag and drop.\n
+     * \n
+     * TODO FloatingAnchor could totally be refactored to extend Anchor just slightly.\n
+     */\n
+    jsPlumb.FloatingAnchor = function(params) {\n
+        \n
+        jsPlumb.Anchor.apply(this, arguments);\n
+\n
+        // this is the anchor that this floating anchor is referenced to for\n
+        // purposes of calculating the orientation.\n
+        var ref = params.reference,\n
+            jsPlumbInstance = params.jsPlumbInstance,\n
+            // the canvas this refers to.\n
+            refCanvas = params.referenceCanvas,\n
+            size = jsPlumb.getSize(refCanvas),\n
+            // these are used to store the current relative position of our\n
+            // anchor wrt the reference anchor. they only indicate\n
+            // direction, so have a value of 1 or -1 (or, very rarely, 0). these\n
+            // values are written by the compute method, and read\n
+            // by the getOrientation method.\n
+            xDir = 0, yDir = 0,\n
+            // temporary member used to store an orientation when the floating\n
+            // anchor is hovering over another anchor.\n
+            orientation = null,\n
+            _lastResult = null;\n
+\n
+        // clear from parent. we want floating anchor orientation to always be computed.\n
+        this.orientation = null;\n
+\n
+        // set these to 0 each; they are used by certain types of connectors in the loopback case,\n
+        // when the connector is trying to clear the element it is on. but for floating anchor it\'s not\n
+        // very important.\n
+        this.x = 0; this.y = 0;\n
+\n
+        this.isFloating = true;\n
+\n
+\t\tthis.compute = function(params) {\n
+\t\t\tvar xy = params.xy, element = params.element,\n
+\t\t\t\tresult = [ xy[0] + (size[0] / 2), xy[1] + (size[1] / 2) ]; // return origin of the element. we may wish to improve this so that any object can be the drag proxy.\n
+\t\t\t_lastResult = result;\n
+\t\t\treturn result;\n
+\t\t};\n
+\n
+        this.getOrientation = function(_endpoint) {\n
+            if (orientation) return orientation;\n
+            else {\n
+                var o = ref.getOrientation(_endpoint);\n
+                // here we take into account the orientation of the other\n
+                // anchor: if it declares zero for some direction, we declare zero too. this might not be the most awesome. perhaps we can come\n
+                // up with a better way. it\'s just so that the line we draw looks like it makes sense. maybe this wont make sense.\n
+                return [ Math.abs(o[0]) * xDir * -1,\n
+                        Math.abs(o[1]) * yDir * -1 ];\n
+            }\n
+        };\n
+\n
+        /**\n
+         * notification the endpoint associated with this anchor is hovering\n
+         * over another anchor; we want to assume that anchor\'s orientation\n
+         * for the duration of the hover.\n
+         */\n
+        this.over = function(anchor, endpoint) { \n
+            orientation = anchor.getOrientation(endpoint); \n
+        };\n
+\n
+        /**\n
+         * notification the endpoint associated with this anchor is no\n
+         * longer hovering over another anchor; we should resume calculating\n
+         * orientation as we normally do.\n
+         */\n
+        this.out = function() { orientation = null; };\n
+\n
+        this.getCurrentLocation = function(params) { return _lastResult == null ? this.compute(params) : _lastResult; };\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.FloatingAnchor, jsPlumb.Anchor);\n
+\n
+    var _convertAnchor = function(anchor, jsPlumbInstance, elementId) { \n
+        return anchor.constructor == jsPlumb.Anchor ? anchor: jsPlumbInstance.makeAnchor(anchor, elementId, jsPlumbInstance); \n
+    };\n
+\n
+    /* \n
+     * A DynamicAnchor is an Anchor that contains a list of other Anchors, which it cycles\n
+     * through at compute time to find the one that is located closest to\n
+     * the center of the target element, and returns that Anchor\'s compute\n
+     * method result. this causes endpoints to follow each other with\n
+     * respect to the orientation of their target elements, which is a useful\n
+     * feature for some applications.\n
+     * \n
+     */\n
+    jsPlumb.DynamicAnchor = function(params) {\n
+        jsPlumb.Anchor.apply(this, arguments);\n
+        \n
+        this.isSelective = true;\n
+        this.isDynamic = true;\t\t\t\n
+        this.anchors = [];\n
+        this.elementId = params.elementId;\n
+        this.jsPlumbInstance = params.jsPlumbInstance;\n
+\n
+        for (var i = 0; i < params.anchors.length; i++) \n
+            this.anchors[i] = _convertAnchor(params.anchors[i], this.jsPlumbInstance, this.elementId);\t\t\t\n
+        this.addAnchor = function(anchor) { this.anchors.push(_convertAnchor(anchor, this.jsPlumbInstance, this.elementId)); };\n
+        this.getAnchors = function() { return this.anchors; };\n
+        this.locked = false;\n
+        var _curAnchor = this.anchors.length > 0 ? this.anchors[0] : null,\n
+            _curIndex = this.anchors.length > 0 ? 0 : -1,\n
+            _lastAnchor = _curAnchor,\n
+            self = this,\n
+        \n
+            // helper method to calculate the distance between the centers of the two elements.\n
+            _distance = function(anchor, cx, cy, xy, wh) {\n
+                var ax = xy[0] + (anchor.x * wh[0]), ay = xy[1] + (anchor.y * wh[1]),\t\t\t\t\n
+                    acx = xy[0] + (wh[0] / 2), acy = xy[1] + (wh[1] / 2);\n
+                return (Math.sqrt(Math.pow(cx - ax, 2) + Math.pow(cy - ay, 2)) +\n
+                        Math.sqrt(Math.pow(acx - ax, 2) + Math.pow(acy - ay, 2)));\n
+            },        \n
+            // default method uses distance between element centers.  you can provide your own method in the dynamic anchor\n
+            // constructor (and also to jsPlumb.makeDynamicAnchor). the arguments to it are four arrays: \n
+            // xy - xy loc of the anchor\'s element\n
+            // wh - anchor\'s element\'s dimensions\n
+            // txy - xy loc of the element of the other anchor in the connection\n
+            // twh - dimensions of the element of the other anchor in the connection.\n
+            // anchors - the list of selectable anchors\n
+            _anchorSelector = params.selector || function(xy, wh, txy, twh, anchors) {\n
+                var cx = txy[0] + (twh[0] / 2), cy = txy[1] + (twh[1] / 2);\n
+                var minIdx = -1, minDist = Infinity;\n
+                for ( var i = 0; i < anchors.length; i++) {\n
+                    var d = _distance(anchors[i], cx, cy, xy, wh);\n
+                    if (d < minDist) {\n
+                        minIdx = i + 0;\n
+                        minDist = d;\n
+                    }\n
+                }\n
+                return anchors[minIdx];\n
+            };\n
+        \n
+        this.compute = function(params) {\t\t\t\t\n
+            var xy = params.xy, wh = params.wh, timestamp = params.timestamp, txy = params.txy, twh = params.twh;\t\t\t\t\n
+            \n
+            if(params.clearUserDefinedLocation)\n
+                userDefinedLocation = null;\n
+\n
+            this.timestamp = timestamp;            \n
+            \n
+            var udl = self.getUserDefinedLocation();\n
+            if (udl != null) {\n
+                return udl;\n
+            }\n
+            \n
+            // if anchor is locked or an opposite element was not given, we\n
+            // maintain our state. anchor will be locked\n
+            // if it is the source of a drag and drop.\n
+            if (this.locked || txy == null || twh == null)\n
+                return _curAnchor.compute(params);\t\t\t\t\n
+            else\n
+                params.timestamp = null; // otherwise clear this, i think. we want the anchor to compute.\n
+            \n
+            _curAnchor = _anchorSelector(xy, wh, txy, twh, this.anchors);\n
+            this.x = _curAnchor.x;\n
+            this.y = _curAnchor.y;        \n
+\n
+            if (_curAnchor != _lastAnchor)\n
+                this.fire("anchorChanged", _curAnchor);\n
+\n
+            _lastAnchor = _curAnchor;\n
+            \n
+            return _curAnchor.compute(params);\n
+        };\n
+\n
+        this.getCurrentLocation = function(params) {\n
+            return this.getUserDefinedLocation() || (_curAnchor != null ? _curAnchor.getCurrentLocation(params) : null);\n
+        };\n
+\n
+        this.getOrientation = function(_endpoint) { return _curAnchor != null ? _curAnchor.getOrientation(_endpoint) : [ 0, 0 ]; };\n
+        this.over = function(anchor, endpoint) { if (_curAnchor != null) _curAnchor.over(anchor, endpoint); };\n
+        this.out = function() { if (_curAnchor != null) _curAnchor.out(); };\n
+\n
+        this.getCssClass = function() { return (_curAnchor && _curAnchor.getCssClass()) || ""; };\n
+    };    \n
+    jsPlumbUtil.extend(jsPlumb.DynamicAnchor, jsPlumb.Anchor);        \n
+    \n
+// -------- basic anchors ------------------    \n
+    var _curryAnchor = function(x, y, ox, oy, type, fnInit) {\n
+        jsPlumb.Anchors[type] = function(params) {\n
+            var a = params.jsPlumbInstance.makeAnchor([ x, y, ox, oy, 0, 0 ], params.elementId, params.jsPlumbInstance);\n
+            a.type = type;\n
+            if (fnInit) fnInit(a, params);\n
+            return a;\n
+        };\n
+    };\n
+    \t\n
+\t_curryAnchor(0.5, 0, 0,-1, "TopCenter");\n
+    _curryAnchor(0.5, 1, 0, 1, "BottomCenter");\n
+    _curryAnchor(0, 0.5, -1, 0, "LeftMiddle");\n
+    _curryAnchor(1, 0.5, 1, 0, "RightMiddle");\n
+    // from 1.4.2: Top, Right, Bottom, Left\n
+    _curryAnchor(0.5, 0, 0,-1, "Top");\n
+    _curryAnchor(0.5, 1, 0, 1, "Bottom");\n
+    _curryAnchor(0, 0.5, -1, 0, "Left");\n
+    _curryAnchor(1, 0.5, 1, 0, "Right");\n
+    _curryAnchor(0.5, 0.5, 0, 0, "Center");\n
+    _curryAnchor(1, 0, 0,-1, "TopRight");\n
+    _curryAnchor(1, 1, 0, 1, "BottomRight");\n
+    _curryAnchor(0, 0, 0, -1, "TopLeft");\n
+    _curryAnchor(0, 1, 0, 1, "BottomLeft");\n
+    \n
+// ------- dynamic anchors -------------------    \n
+\t\t\t\n
+    // default dynamic anchors chooses from Top, Right, Bottom, Left\n
+\tjsPlumb.Defaults.DynamicAnchors = function(params) {\n
+\t\treturn params.jsPlumbInstance.makeAnchors(["TopCenter", "RightMiddle", "BottomCenter", "LeftMiddle"], params.elementId, params.jsPlumbInstance);\n
+\t};\n
+    \n
+    // default dynamic anchors bound to name \'AutoDefault\'\n
+\tjsPlumb.Anchors.AutoDefault  = function(params) { \n
+\t\tvar a = params.jsPlumbInstance.makeDynamicAnchor(jsPlumb.Defaults.DynamicAnchors(params));\n
+\t\ta.type = "AutoDefault";\n
+\t\treturn a;\n
+\t};\t\n
+    \n
+// ------- continuous anchors -------------------    \n
+    \n
+    var _curryContinuousAnchor = function(type, faces) {\n
+        jsPlumb.Anchors[type] = function(params) {\n
+            var a = params.jsPlumbInstance.makeAnchor(["Continuous", { faces:faces }], params.elementId, params.jsPlumbInstance);\n
+            a.type = type;\n
+            return a;\n
+        };\n
+    };\n
+    \n
+    jsPlumb.Anchors.Continuous = function(params) {\n
+\t\treturn params.jsPlumbInstance.continuousAnchorFactory.get(params);\n
+\t};\n
+                \n
+    _curryContinuousAnchor("ContinuousLeft", ["left"]);    \n
+    _curryContinuousAnchor("ContinuousTop", ["top"]);                 \n
+    _curryContinuousAnchor("ContinuousBottom", ["bottom"]);                 \n
+    _curryContinuousAnchor("ContinuousRight", ["right"]); \n
+    \n
+// ------- position assign anchors -------------------    \n
+    \n
+    // this anchor type lets you assign the position at connection time.\n
+\t_curryAnchor(0, 0, 0, 0, "Assign", function(anchor, params) {\n
+\t\t// find what to use as the "position finder". the user may have supplied a String which represents\n
+\t\t// the id of a position finder in jsPlumb.AnchorPositionFinders, or the user may have supplied the\n
+\t\t// position finder as a function.  we find out what to use and then set it on the anchor.\n
+\t\tvar pf = params.position || "Fixed";\n
+\t\tanchor.positionFinder = pf.constructor == String ? params.jsPlumbInstance.AnchorPositionFinders[pf] : pf;\n
+\t\t// always set the constructor params; the position finder might need them later (the Grid one does,\n
+\t\t// for example)\n
+\t\tanchor.constructorParams = params;\n
+\t});\t\n
+\n
+    // these are the default anchor positions finders, which are used by the makeTarget function.  supplying\n
+    // a position finder argument to that function allows you to specify where the resulting anchor will\n
+    // be located\n
+\tjsPlumbInstance.prototype.AnchorPositionFinders = {\n
+\t\t"Fixed": function(dp, ep, es, params) {\n
+\t\t\treturn [ (dp.left - ep.left) / es[0], (dp.top - ep.top) / es[1] ];\t\n
+\t\t},\n
+\t\t"Grid":function(dp, ep, es, params) {\n
+\t\t\tvar dx = dp.left - ep.left, dy = dp.top - ep.top,\n
+\t\t\t\tgx = es[0] / (params.grid[0]), gy = es[1] / (params.grid[1]),\n
+\t\t\t\tmx = Math.floor(dx / gx), my = Math.floor(dy / gy);\n
+\t\t\treturn [ ((mx * gx) + (gx / 2)) / es[0], ((my * gy) + (gy / 2)) / es[1] ];\n
+\t\t}\n
+\t};\n
+    \n
+// ------- perimeter anchors -------------------    \n
+\t\t\n
+\tjsPlumb.Anchors.Perimeter = function(params) {\n
+\t\tparams = params || {};\n
+\t\tvar anchorCount = params.anchorCount || 60,\n
+\t\t\tshape = params.shape;\n
+\t\t\n
+\t\tif (!shape) throw new Error("no shape supplied to Perimeter Anchor type");\t\t\n
+\t\t\n
+\t\tvar _circle = function() {\n
+                var r = 0.5, step = Math.PI * 2 / anchorCount, current = 0, a = [];\n
+                for (var i = 0; i < anchorCount; i++) {\n
+                    var x = r + (r * Math.sin(current)),\n
+                        y = r + (r * Math.cos(current));                                \n
+                    a.push( [ x, y, 0, 0 ] );\n
+                    current += step;\n
+                }\n
+                return a;\t\n
+            },\n
+            _path = function(segments) {\n
+                var anchorsPerFace = anchorCount / segments.length, a = [],\n
+                    _computeFace = function(x1, y1, x2, y2, fractionalLength) {\n
+                        anchorsPerFace = anchorCount * fractionalLength;\n
+                        var dx = (x2 - x1) / anchorsPerFace, dy = (y2 - y1) / anchorsPerFace;\n
+                        for (var i = 0; i < anchorsPerFace; i++) {\n
+                            a.push( [\n
+                                x1 + (dx * i),\n
+                                y1 + (dy * i),\n
+                                0,\n
+                                0\n
+                            ]);\n
+                        }\n
+                    };\n
+\t\t\t\t\t\t\t\t\n
+                for (var i = 0; i < segments.length; i++)\n
+                    _computeFace.apply(null, segments[i]);\n
+\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n
+                return a;\t\t\t\t\t\n
+            },\n
+\t\t\t_shape = function(faces) {\t\t\t\t\t\t\t\t\t\t\t\t\n
+                var s = [];\n
+                for (var i = 0; i < faces.length; i++) {\n
+                    s.push([faces[i][0], faces[i][1], faces[i][2], faces[i][3], 1 / faces.length]);\n
+                }\n
+                return _path(s);\n
+\t\t\t},\n
+\t\t\t_rectangle = function() {\n
+\t\t\t\treturn _shape([\n
+\t\t\t\t\t[ 0, 0, 1, 0 ], [ 1, 0, 1, 1 ], [ 1, 1, 0, 1 ], [ 0, 1, 0, 0 ]\n
+\t\t\t\t]);\t\t\n
+\t\t\t};\n
+\t\t\n
+\t\tvar _shapes = {\n
+\t\t\t"Circle":_circle,\n
+\t\t\t"Ellipse":_circle,\n
+\t\t\t"Diamond":function() {\n
+\t\t\t\treturn _shape([\n
+\t\t\t\t\t\t[ 0.5, 0, 1, 0.5 ], [ 1, 0.5, 0.5, 1 ], [ 0.5, 1, 0, 0.5 ], [ 0, 0.5, 0.5, 0 ]\n
+\t\t\t\t]);\n
+\t\t\t},\n
+\t\t\t"Rectangle":_rectangle,\n
+\t\t\t"Square":_rectangle,\n
+\t\t\t"Triangle":function() {\n
+\t\t\t\treturn _shape([\n
+\t\t\t\t\t\t[ 0.5, 0, 1, 1 ], [ 1, 1, 0, 1 ], [ 0, 1, 0.5, 0]\n
+\t\t\t\t]);\t\n
+\t\t\t},\n
+\t\t\t"Path":function(params) {\n
+                var points = params.points, p = [], tl = 0;\n
+\t\t\t\tfor (var i = 0; i < points.length - 1; i++) {\n
+                    var l = Math.sqrt(Math.pow(points[i][2] - points[i][0]) + Math.pow(points[i][3] - points[i][1]));\n
+                    tl += l;\n
+\t\t\t\t\tp.push([points[i][0], points[i][1], points[i+1][0], points[i+1][1], l]);\t\t\t\t\t\t\n
+\t\t\t\t}\n
+                for (var j = 0; j < p.length; j++) {\n
+                    p[j][4] = p[j][4] / tl;\n
+                }\n
+\t\t\t\treturn _path(p);\n
+\t\t\t}\n
+\t\t},\n
+        _rotate = function(points, amountInDegrees) {\n
+            var o = [], theta = amountInDegrees / 180 * Math.PI ;\n
+            for (var i = 0; i < points.length; i++) {\n
+                var _x = points[i][0] - 0.5,\n
+                    _y = points[i][1] - 0.5;\n
+                    \n
+                o.push([\n
+                    0.5 + ((_x * Math.cos(theta)) - (_y * Math.sin(theta))),\n
+                    0.5 + ((_x * Math.sin(theta)) + (_y * Math.cos(theta))),\n
+                    points[i][2],\n
+                    points[i][3]\n
+                ]);\n
+            }\n
+            return o;\n
+        };\n
+\t\t\n
+\t\tif (!_shapes[shape]) throw new Error("Shape [" + shape + "] is unknown by Perimeter Anchor type");\n
+\t\t\n
+\t\tvar da = _shapes[shape](params);\n
+        if (params.rotation) da = _rotate(da, params.rotation);\n
+        var a = params.jsPlumbInstance.makeDynamicAnchor(da);\n
+\t\ta.type = "Perimeter";\n
+\t\treturn a;\n
+\t};\n
+})();\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the default Connectors, Endpoint and Overlay definitions.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */  \n
+;(function() {\t\n
+\n
+\t"use strict";\n
+\t\t\t\t\n
+\t/**\n
+\t * \n
+\t * Helper class to consume unused mouse events by components that are DOM elements and\n
+\t * are used by all of the different rendering modes.\n
+\t * \n
+\t */\n
+\tjsPlumb.DOMElementComponent = jsPlumbUtil.extend(jsPlumb.jsPlumbUIComponent, function(params) {\t\t\n
+\t\t// this component is safe to pipe this stuff to /dev/null.\n
+\t\tthis.mousemove = \n
+\t\tthis.dblclick  = \n
+\t\tthis.click = \n
+\t\tthis.mousedown = \n
+\t\tthis.mouseup = function(e) { };\n
+\t});\n
+\n
+\tjsPlumb.Segments = {\n
+\n
+        /*\n
+         * Class: AbstractSegment\n
+         * A Connector is made up of 1..N Segments, each of which has a Type, such as \'Straight\', \'Arc\',\n
+         * \'Bezier\'. This is new from 1.4.2, and gives us a lot more flexibility when drawing connections: things such\n
+         * as rounded corners for flowchart connectors, for example, or a straight line stub for Bezier connections, are\n
+         * much easier to do now.\n
+         *\n
+         * A Segment is responsible for providing coordinates for painting it, and also must be able to report its length.\n
+         * \n
+         */ \n
+        AbstractSegment : function(params) { \n
+            this.params = params;\n
+            \n
+            /**\n
+            * Function: findClosestPointOnPath\n
+            * Finds the closest point on this segment to the given [x, y], \n
+            * returning both the x and y of the point plus its distance from\n
+            * the supplied point, and its location along the length of the\n
+            * path inscribed by the segment.  This implementation returns\n
+            * Infinity for distance and null values for everything else;\n
+            * subclasses are expected to override.\n
+            */\n
+            this.findClosestPointOnPath = function(x, y) {\n
+                return {\n
+                    d:Infinity,\n
+                    x:null,\n
+                    y:null,\n
+                    l:null\n
+                };\n
+            };\n
+\n
+            this.getBounds = function() {\n
+                return {\n
+                    minX:Math.min(params.x1, params.x2),\n
+                    minY:Math.min(params.y1, params.y2),\n
+                    maxX:Math.max(params.x1, params.x2),\n
+                    maxY:Math.max(params.y1, params.y2)\n
+                };\n
+            };\n
+        },\n
+        Straight : function(params) {\n
+            var _super = jsPlumb.Segments.AbstractSegment.apply(this, arguments),\n
+                length, m, m2, x1, x2, y1, y2,\n
+                _recalc = function() {\n
+                    length = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));\n
+                    m = Biltong.gradient({x:x1, y:y1}, {x:x2, y:y2});\n
+                    m2 = -1 / m;                \n
+                };\n
+                \n
+            this.type = "Straight";\n
+            \n
+            this.getLength = function() { return length; };\n
+            this.getGradient = function() { return m; };\n
+                \n
+            this.getCoordinates = function() {\n
+                return { x1:x1,y1:y1,x2:x2,y2:y2 };\n
+            };\n
+            this.setCoordinates = function(coords) {\n
+                x1 = coords.x1; y1 = coords.y1; x2 = coords.x2; y2 = coords.y2;\n
+                _recalc();\n
+            };\n
+            this.setCoordinates({x1:params.x1, y1:params.y1, x2:params.x2, y2:params.y2});\n
+\n
+            this.getBounds = function() {\n
+                return {\n
+                    minX:Math.min(x1, x2),\n
+                    minY:Math.min(y1, y2),\n
+                    maxX:Math.max(x1, x2),\n
+                    maxY:Math.max(y1, y2)\n
+                };\n
+            };\n
+            \n
+            /**\n
+             * returns the point on the segment\'s path that is \'location\' along the length of the path, where \'location\' is a decimal from\n
+             * 0 to 1 inclusive. for the straight line segment this is simple maths.\n
+             */\n
+             this.pointOnPath = function(location, absolute) {\n
+                if (location === 0 && !absolute)\n
+                    return { x:x1, y:y1 };\n
+                else if (location == 1 && !absolute)\n
+                    return { x:x2, y:y2 };\n
+                else {\n
+                    var l = absolute ? location > 0 ? location : length + location : location * length;\n
+                    return Biltong.pointOnLine({x:x1, y:y1}, {x:x2, y:y2}, l);\n
+                }\n
+            };\n
+            \n
+            /**\n
+             * returns the gradient of the segment at the given point - which for us is constant.\n
+             */\n
+            this.gradientAtPoint = function(_) {\n
+                return m;\n
+            };\n
+            \n
+            /**\n
+             * returns the point on the segment\'s path that is \'distance\' along the length of the path from \'location\', where \n
+             * \'location\' is a decimal from 0 to 1 inclusive, and \'distance\' is a number of pixels.\n
+             * this hands off to jsPlumbUtil to do the maths, supplying two points and the distance.\n
+             */            \n
+            this.pointAlongPathFrom = function(location, distance, absolute) {            \n
+                var p = this.pointOnPath(location, absolute),\n
+                    farAwayPoint = distance <= 0 ? {x:x1, y:y1} : {x:x2, y:y2 };\n
+\n
+                /*\n
+                location == 1 ? {\n
+                                        x:x1 + ((x2 - x1) * 10),\n
+                                        y:y1 + ((y1 - y2) * 10)\n
+                                    } : \n
+                */\n
+    \n
+                if (distance <= 0 && Math.abs(distance) > 1) distance *= -1;\n
+    \n
+                return Biltong.pointOnLine(p, farAwayPoint, distance);\n
+            };\n
+            \n
+            // is c between a and b?\n
+            var within = function(a,b,c) {\n
+                return c >= Math.min(a,b) && c <= Math.max(a,b); \n
+            };\n
+            // find which of a and b is closest to c\n
+            var closest = function(a,b,c) {\n
+                return Math.abs(c - a) < Math.abs(c - b) ? a : b;\n
+            };\n
+            \n
+            /**\n
+                Function: findClosestPointOnPath\n
+                Finds the closest point on this segment to [x,y]. See\n
+                notes on this method in AbstractSegment.\n
+            */\n
+            this.findClosestPointOnPath = function(x, y) {\n
+                var out = {\n
+                    d:Infinity,\n
+                    x:null,\n
+                    y:null,\n
+                    l:null,\n
+                    x1:x1,\n
+                    x2:x2,\n
+                    y1:y1,\n
+                    y2:y2\n
+                };\n
+\n
+                if (m === 0) {                  \n
+                    out.y = y1;\n
+                    out.x = within(x1, x2, x) ? x : closest(x1, x2, x);\n
+                }\n
+                else if (m == Infinity || m == -Infinity) {\n
+                    out.x = x1;                \n
+                    out.y = within(y1, y2, y) ? y : closest(y1, y2, y);\n
+                }\n
+                else {\n
+                    // closest point lies on normal from given point to this line.  \n
+                    var b = y1 - (m * x1),\n
+                        b2 = y - (m2 * x),                    \n
+                    // y1 = m.x1 + b and y1 = m2.x1 + b2\n
+                    // so m.x1 + b = m2.x1 + b2\n
+                    // x1(m - m2) = b2 - b\n
+                    // x1 = (b2 - b) / (m - m2)\n
+                        _x1 = (b2 -b) / (m - m2),\n
+                        _y1 = (m * _x1) + b;\n
+                                        \n
+                    out.x = within(x1,x2,_x1) ? _x1 : closest(x1,x2,_x1);//_x1;\n
+                    out.y = within(y1,y2,_y1) ? _y1 : closest(y1,y2,_y1);//_y1;                    \n
+                }\n
+\n
+                var fractionInSegment = Biltong.lineLength([ out.x, out.y ], [ x1, y1 ]);\n
+                out.d = Biltong.lineLength([x,y], [out.x, out.y]);\n
+                out.l = fractionInSegment / length;            \n
+                return out;\n
+            };        \n
+        },\n
+\t\n
+        /*\n
+            Arc Segment. You need to supply:\n
+    \n
+            r   -   radius\n
+            cx  -   center x for the arc\n
+            cy  -   center y for the arc\n
+            ac  -   whether the arc is anticlockwise or not. default is clockwise.\n
+    \n
+            and then either:\n
+    \n
+            startAngle  -   startAngle for the arc.\n
+            endAngle    -   endAngle for the arc.\n
+    \n
+            or:\n
+    \n
+            x1          -   x for start point\n
+            y1          -   y for start point\n
+            x2          -   x for end point\n
+            y2          -   y for end point\n
+    \n
+        */\n
+        Arc : function(params) {\n
+            var _super = jsPlumb.Segments.AbstractSegment.apply(this, arguments),\n
+                _calcAngle = function(_x, _y) {\n
+                    return Biltong.theta([params.cx, params.cy], [_x, _y]);    \n
+                },\n
+                _calcAngleForLocation = function(segment, location) {\n
+                    if (segment.anticlockwise) {\n
+                        var sa = segment.startAngle < segment.endAngle ? segment.startAngle + TWO_PI : segment.startAngle,\n
+                            s = Math.abs(sa - segment.endAngle);\n
+                        return sa - (s * location);                    \n
+                    }\n
+                    else {\n
+                        var ea = segment.endAngle < segment.startAngle ? segment.endAngle + TWO_PI : segment.endAngle,\n
+                            ss = Math.abs (e
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="6" aka="AAAAAAAAAAY=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+a - segment.startAngle);\n
+                    \n
+                        return segment.startAngle + (ss * location);\n
+                    }\n
+                },\n
+                TWO_PI = 2 * Math.PI;\n
+            \n
+            this.radius = params.r;\n
+            this.anticlockwise = params.ac;\t\t\t\n
+            this.type = "Arc";\n
+                \n
+            if (params.startAngle && params.endAngle) {\n
+                this.startAngle = params.startAngle;\n
+                this.endAngle = params.endAngle;            \n
+                this.x1 = params.cx + (this.radius * Math.cos(params.startAngle));     \n
+                this.y1 = params.cy + (this.radius * Math.sin(params.startAngle));            \n
+                this.x2 = params.cx + (this.radius * Math.cos(params.endAngle));     \n
+                this.y2 = params.cy + (this.radius * Math.sin(params.endAngle));                        \n
+            }\n
+            else {\n
+                this.startAngle = _calcAngle(params.x1, params.y1);\n
+                this.endAngle = _calcAngle(params.x2, params.y2);            \n
+                this.x1 = params.x1;\n
+                this.y1 = params.y1;\n
+                this.x2 = params.x2;\n
+                this.y2 = params.y2;            \n
+            }\n
+            \n
+            if (this.endAngle < 0) this.endAngle += TWO_PI;\n
+            if (this.startAngle < 0) this.startAngle += TWO_PI;   \n
+\n
+            // segment is used by vml     \n
+            this.segment = Biltong.quadrant([this.x1, this.y1], [this.x2, this.y2]);\n
+            \n
+            // we now have startAngle and endAngle as positive numbers, meaning the\n
+            // absolute difference (|d|) between them is the sweep (s) of this arc, unless the\n
+            // arc is \'anticlockwise\' in which case \'s\' is given by 2PI - |d|.\n
+            \n
+            var ea = this.endAngle < this.startAngle ? this.endAngle + TWO_PI : this.endAngle;\n
+            this.sweep = Math.abs (ea - this.startAngle);\n
+            if (this.anticlockwise) this.sweep = TWO_PI - this.sweep;\n
+            var circumference = 2 * Math.PI * this.radius,\n
+                frac = this.sweep / TWO_PI,\n
+                length = circumference * frac;\n
+            \n
+            this.getLength = function() {\n
+                return length;\n
+            };\n
+\n
+            this.getBounds = function() {\n
+                return {\n
+                    minX:params.cx - params.r,\n
+                    maxX:params.cx + params.r,\n
+                    minY:params.cy - params.r,\n
+                    maxY:params.cy + params.r\n
+                };\n
+            };\n
+            \n
+            var VERY_SMALL_VALUE = 0.0000000001,\n
+                gentleRound = function(n) {\n
+                    var f = Math.floor(n), r = Math.ceil(n);\n
+                    if (n - f < VERY_SMALL_VALUE) \n
+                        return f;    \n
+                    else if (r - n < VERY_SMALL_VALUE)\n
+                        return r;\n
+                    return n;\n
+                };\n
+            \n
+            /**\n
+             * returns the point on the segment\'s path that is \'location\' along the length of the path, where \'location\' is a decimal from\n
+             * 0 to 1 inclusive. \n
+             */\n
+            this.pointOnPath = function(location, absolute) {            \n
+                \n
+                if (location === 0) {\n
+                    return { x:this.x1, y:this.y1, theta:this.startAngle };    \n
+                }\n
+                else if (location == 1) {\n
+                    return { x:this.x2, y:this.y2, theta:this.endAngle };                    \n
+                }\n
+                \n
+                if (absolute) {\n
+                    location = location / length;\n
+                }\n
+    \n
+                var angle = _calcAngleForLocation(this, location),\n
+                    _x = params.cx + (params.r * Math.cos(angle)),\n
+                    _y  = params.cy + (params.r * Math.sin(angle));\t\t\t\t\t\n
+    \n
+                return { x:gentleRound(_x), y:gentleRound(_y), theta:angle };\n
+            };\n
+            \n
+            /**\n
+             * returns the gradient of the segment at the given point.\n
+             */\n
+            this.gradientAtPoint = function(location, absolute) {\n
+                var p = this.pointOnPath(location, absolute);\n
+                var m = Biltong.normal( [ params.cx, params.cy ], [p.x, p.y ] );\n
+                if (!this.anticlockwise && (m == Infinity || m == -Infinity)) m *= -1;\n
+                return m;\n
+            };\t              \n
+                    \n
+            this.pointAlongPathFrom = function(location, distance, absolute) {\n
+                var p = this.pointOnPath(location, absolute),\n
+                    arcSpan = distance / circumference * 2 * Math.PI,\n
+                    dir = this.anticlockwise ? -1 : 1,\n
+                    startAngle = p.theta + (dir * arcSpan),\t\t\t\t\n
+                    startX = params.cx + (this.radius * Math.cos(startAngle)),\n
+                    startY = params.cy + (this.radius * Math.sin(startAngle));\t\n
+    \n
+                return {x:startX, y:startY};\n
+            };\t            \n
+        },\n
+\t\n
+        Bezier : function(params) {\n
+            var _super = jsPlumb.Segments.AbstractSegment.apply(this, arguments),\n
+                curve = [\t\n
+                    { x:params.x1, y:params.y1},\n
+                    { x:params.cp1x, y:params.cp1y },\n
+                    { x:params.cp2x, y:params.cp2y },\n
+                    { x:params.x2, y:params.y2 }\n
+                ],\n
+                // although this is not a strictly rigorous determination of bounds\n
+                // of a bezier curve, it works for the types of curves that this segment\n
+                // type produces.\n
+                bounds = {\n
+                    minX:Math.min(params.x1, params.x2, params.cp1x, params.cp2x),\n
+                    minY:Math.min(params.y1, params.y2, params.cp1y, params.cp2y),\n
+                    maxX:Math.max(params.x1, params.x2, params.cp1x, params.cp2x),\n
+                    maxY:Math.max(params.y1, params.y2, params.cp1y, params.cp2y)\n
+                };\n
+                \n
+            this.type = "Bezier";            \n
+            \n
+            var _translateLocation = function(_curve, location, absolute) {\n
+                if (absolute)\n
+                    location = jsBezier.locationAlongCurveFrom(_curve, location > 0 ? 0 : 1, location);\n
+    \n
+                return location;\n
+            };\t\t\n
+            \n
+            /**\n
+             * returns the point on the segment\'s path that is \'location\' along the length of the path, where \'location\' is a decimal from\n
+             * 0 to 1 inclusive. \n
+             */\n
+            this.pointOnPath = function(location, absolute) {\n
+                location = _translateLocation(curve, location, absolute);                \n
+                return jsBezier.pointOnCurve(curve, location);\n
+            };\n
+            \n
+            /**\n
+             * returns the gradient of the segment at the given point.\n
+             */\n
+            this.gradientAtPoint = function(location, absolute) {\n
+                location = _translateLocation(curve, location, absolute);\n
+                return jsBezier.gradientAtPoint(curve, location);        \t\n
+            };\t              \n
+            \n
+            this.pointAlongPathFrom = function(location, distance, absolute) {\n
+                location = _translateLocation(curve, location, absolute);\n
+                return jsBezier.pointAlongCurveFrom(curve, location, distance);\n
+            };\n
+            \n
+            this.getLength = function() {\n
+                return jsBezier.getLength(curve);\t\t\t\t\n
+            };\n
+\n
+            this.getBounds = function() {\n
+                return bounds;\n
+            };\n
+        }\n
+    };\n
+\n
+\t/*\n
+\t\tClass: AbstractComponent\n
+\t\tSuperclass for AbstractConnector and AbstractEndpoint.\n
+\t*/\n
+\tvar AbstractComponent = function() {\n
+\t\tthis.resetBounds = function() {\n
+\t\t\tthis.bounds = { minX:Infinity, minY:Infinity, maxX:-Infinity, maxY:-Infinity };\n
+\t\t};\n
+\t\tthis.resetBounds();\n
+\t};\n
+\n
+\t/*\n
+\t * Class: AbstractConnector\n
+\t * Superclass for all Connectors; here is where Segments are managed.  This is exposed on jsPlumb just so it\n
+\t * can be accessed from other files. You should not try to instantiate one of these directly.\n
+\t *\n
+\t * When this class is asked for a pointOnPath, or gradient etc, it must first figure out which segment to dispatch\n
+\t * that request to. This is done by keeping track of the total connector length as segments are added, and also\n
+\t * their cumulative ratios to the total length.  Then when the right segment is found it is a simple case of dispatching\n
+\t * the request to it (and adjusting \'location\' so that it is relative to the beginning of that segment.)\n
+\t */ \n
+\tjsPlumb.Connectors.AbstractConnector = function(params) {\n
+\t\t\n
+\t\tAbstractComponent.apply(this, arguments);\n
+\n
+\t\tvar segments = [],\n
+\t\t\tediting = false,\n
+\t\t\ttotalLength = 0,\n
+\t\t\tsegmentProportions = [],\n
+\t\t\tsegmentProportionalLengths = [],\n
+\t\t\tstub = params.stub || 0, \n
+\t\t\tsourceStub = jsPlumbUtil.isArray(stub) ? stub[0] : stub,\n
+\t\t\ttargetStub = jsPlumbUtil.isArray(stub) ? stub[1] : stub,\n
+\t\t\tgap = params.gap || 0,\n
+\t\t\tsourceGap = jsPlumbUtil.isArray(gap) ? gap[0] : gap,\n
+\t\t\ttargetGap = jsPlumbUtil.isArray(gap) ? gap[1] : gap,\n
+\t\t\tuserProvidedSegments = null,\n
+\t\t\tedited = false,\n
+\t\t\tpaintInfo = null;\n
+\n
+\t\t// subclasses should override.\n
+\t\tthis.isEditable = function() { return false; };\n
+\t\tthis.setEdited = function(ed) { edited = ed; };\n
+\n
+\t\t// to be overridden by subclasses.\n
+\t\tthis.getPath = function() { };\n
+\t\tthis.setPath = function(path) { };\n
+        \n
+        /**\n
+        * Function: findSegmentForPoint\n
+        * Returns the segment that is closest to the given [x,y],\n
+        * null if nothing found.  This function returns a JS \n
+        * object with:\n
+        *\n
+        *   d   -   distance from segment\n
+        *   l   -   proportional location in segment\n
+        *   x   -   x point on the segment\n
+        *   y   -   y point on the segment\n
+        *   s   -   the segment itself.\n
+        */ \n
+        this.findSegmentForPoint = function(x, y) {\n
+            var out = { d:Infinity, s:null, x:null, y:null, l:null };\n
+            for (var i = 0; i < segments.length; i++) {\n
+                var _s = segments[i].findClosestPointOnPath(x, y);\n
+                if (_s.d < out.d) {\n
+                    out.d = _s.d; \n
+                    out.l = _s.l; \n
+                    out.x = _s.x;\n
+                    out.y = _s.y; \n
+                    out.s = segments[i];\n
+                    out.x1 = _s.x1;\n
+                    out.x2 = _s.x2;\n
+                    out.y1 = _s.y1;\n
+                    out.y2 = _s.y2;\n
+                    out.index = i;\n
+                }\n
+            }\n
+            \n
+            return out;\n
+        };\n
+\n
+\t\tvar _updateSegmentProportions = function() {\n
+                var curLoc = 0;\n
+                for (var i = 0; i < segments.length; i++) {\n
+                    var sl = segments[i].getLength();\n
+                    segmentProportionalLengths[i] = sl / totalLength;\n
+                    segmentProportions[i] = [curLoc, (curLoc += (sl / totalLength)) ];\n
+                }\n
+            },\n
+\t\t\n
+            /**\n
+             * returns [segment, proportion of travel in segment, segment index] for the segment \n
+             * that contains the point which is \'location\' distance along the entire path, where \n
+             * \'location\' is a decimal between 0 and 1 inclusive. in this connector type, paths \n
+             * are made up of a list of segments, each of which contributes some fraction to\n
+             * the total length. \n
+             * From 1.3.10 this also supports the \'absolute\' property, which lets us specify a location\n
+             * as the absolute distance in pixels, rather than a proportion of the total path. \n
+             */\n
+            _findSegmentForLocation = function(location, absolute) {\n
+\t\t\t\tif (absolute) {\n
+\t\t\t\t\tlocation = location > 0 ? location / totalLength : (totalLength + location) / totalLength;\n
+\t\t\t\t}\n
+\t\t\t\tvar idx = segmentProportions.length - 1, inSegmentProportion = 1;\n
+\t\t\t\tfor (var i = 0; i < segmentProportions.length; i++) {\n
+\t\t\t\t\tif (segmentProportions[i][1] >= location) {\n
+\t\t\t\t\t\tidx = i;\n
+\t\t\t\t\t\t// todo is this correct for all connector path types?\n
+\t\t\t\t\t\tinSegmentProportion = location == 1 ? 1 : location === 0 ? 0 : (location - segmentProportions[i][0]) / segmentProportionalLengths[i];                    \n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\treturn { segment:segments[idx], proportion:inSegmentProportion, index:idx };\n
+\t\t\t},\n
+\t\t\t_addSegment = function(conn, type, params) {\n
+\t\t\t\tif (params.x1 == params.x2 && params.y1 == params.y2) return;\n
+\t\t\t\tvar s = new jsPlumb.Segments[type](params);\n
+\t\t\t\tsegments.push(s);\n
+\t\t\t\ttotalLength += s.getLength();\n
+\t\t\t\tconn.updateBounds(s);\n
+\t\t\t},\n
+\t\t\t_clearSegments = function() {\n
+\t\t\t\ttotalLength = segments.length = segmentProportions.length = segmentProportionalLengths.length = 0;\n
+\t\t\t};\n
+\n
+\t\tthis.setSegments = function(_segs) {\n
+\t\t\tuserProvidedSegments = [];\n
+\t\t\ttotalLength = 0;\n
+\t\t\tfor (var i = 0; i < _segs.length; i++) {\n
+\t\t\t\tuserProvidedSegments.push(_segs[i]);\n
+\t\t\t\ttotalLength += _segs[i].getLength();\n
+\t\t\t}\n
+\t\t};\n
+\n
+        var _prepareCompute = function(params) {\n
+            this.lineWidth = params.lineWidth;\n
+            var segment = Biltong.quadrant(params.sourcePos, params.targetPos),\n
+                swapX = params.targetPos[0] < params.sourcePos[0],\n
+                swapY = params.targetPos[1] < params.sourcePos[1],\n
+                lw = params.lineWidth || 1,       \n
+                so = params.sourceEndpoint.anchor.getOrientation(params.sourceEndpoint), \n
+                to = params.targetEndpoint.anchor.getOrientation(params.targetEndpoint),\n
+                x = swapX ? params.targetPos[0] : params.sourcePos[0], \n
+                y = swapY ? params.targetPos[1] : params.sourcePos[1],\n
+                w = Math.abs(params.targetPos[0] - params.sourcePos[0]),\n
+                h = Math.abs(params.targetPos[1] - params.sourcePos[1]);\n
+\t\t\t\n
+            // SP: an early attempy at fixing #162; this fix caused #177, so reverted.\t\n
+\t\t\t//if (w == 0) w = 1;\n
+\t\t\t//if (h == 0) h = 1;\n
+            \n
+            // if either anchor does not have an orientation set, we derive one from their relative\n
+            // positions.  we fix the axis to be the one in which the two elements are further apart, and\n
+            // point each anchor at the other element.  this is also used when dragging a new connection.\n
+            if (so[0] === 0 && so[1] === 0 || to[0] === 0 && to[1] === 0) {\n
+                var index = w > h ? 0 : 1, oIndex = [1,0][index];\n
+                so = []; to = [];\n
+                so[index] = params.sourcePos[index] > params.targetPos[index] ? -1 : 1;\n
+                to[index] = params.sourcePos[index] > params.targetPos[index] ? 1 : -1;\n
+                so[oIndex] = 0; to[oIndex] = 0;\n
+            }                    \n
+            \n
+            var sx = swapX ? w + (sourceGap * so[0])  : sourceGap * so[0], \n
+                sy = swapY ? h + (sourceGap * so[1])  : sourceGap * so[1], \n
+                tx = swapX ? targetGap * to[0] : w + (targetGap * to[0]),\n
+                ty = swapY ? targetGap * to[1] : h + (targetGap * to[1]),\n
+                oProduct = ((so[0] * to[0]) + (so[1] * to[1]));        \n
+            \n
+            var result = {\n
+                sx:sx, sy:sy, tx:tx, ty:ty, lw:lw, \n
+                xSpan:Math.abs(tx - sx),\n
+                ySpan:Math.abs(ty - sy),                \n
+                mx:(sx + tx) / 2,\n
+                my:(sy + ty) / 2,                \n
+                so:so, to:to, x:x, y:y, w:w, h:h,\n
+                segment : segment,\n
+                startStubX : sx + (so[0] * sourceStub), \n
+                startStubY : sy + (so[1] * sourceStub),\n
+                endStubX : tx + (to[0] * targetStub), \n
+                endStubY : ty + (to[1] * targetStub),\n
+                isXGreaterThanStubTimes2 : Math.abs(sx - tx) > (sourceStub + targetStub),\n
+                isYGreaterThanStubTimes2 : Math.abs(sy - ty) > (sourceStub + targetStub),\n
+                opposite:oProduct == -1,\n
+                perpendicular:oProduct === 0,\n
+                orthogonal:oProduct == 1,\n
+                sourceAxis : so[0] === 0 ? "y" : "x",\n
+                points:[x, y, w, h, sx, sy, tx, ty ]\n
+            };\n
+            result.anchorOrientation = result.opposite ? "opposite" : result.orthogonal ? "orthogonal" : "perpendicular";\n
+            return result;\n
+        };\n
+\t\t\n
+\t\tthis.getSegments = function() { return segments; };\n
+\n
+        this.updateBounds = function(segment) {\n
+            var segBounds = segment.getBounds();\n
+            this.bounds.minX = Math.min(this.bounds.minX, segBounds.minX);\n
+            this.bounds.maxX = Math.max(this.bounds.maxX, segBounds.maxX);\n
+            this.bounds.minY = Math.min(this.bounds.minY, segBounds.minY);\n
+            this.bounds.maxY = Math.max(this.bounds.maxY, segBounds.maxY);              \n
+        };\n
+        \n
+        var dumpSegmentsToConsole = function() {\n
+            console.log("SEGMENTS:");\n
+            for (var i = 0; i < segments.length; i++) {\n
+                console.log(segments[i].type, segments[i].getLength(), segmentProportions[i]);\n
+            }\n
+        };\n
+\n
+\t\tthis.pointOnPath = function(location, absolute) {\n
+            var seg = _findSegmentForLocation(location, absolute);\n
+            return seg.segment && seg.segment.pointOnPath(seg.proportion, false) || [0,0];\n
+        };\n
+        \n
+        this.gradientAtPoint = function(location, absolute) {\n
+            var seg = _findSegmentForLocation(location, absolute);          \n
+            return seg.segment && seg.segment.gradientAtPoint(seg.proportion, false) || 0;\n
+        };\n
+        \n
+        this.pointAlongPathFrom = function(location, distance, absolute) {\n
+            var seg = _findSegmentForLocation(location, absolute);\n
+            // TODO what happens if this crosses to the next segment?\n
+            return seg.segment && seg.segment.pointAlongPathFrom(seg.proportion, distance, false) || [0,0];\n
+        };\n
+\t\t\n
+\t\tthis.compute = function(params)  {\n
+            if (!edited)\n
+                paintInfo = _prepareCompute.call(this, params);\n
+            \n
+            _clearSegments();\n
+            this._compute(paintInfo, params);\n
+            this.x = paintInfo.points[0];\n
+            this.y = paintInfo.points[1];\n
+            this.w = paintInfo.points[2];\n
+            this.h = paintInfo.points[3];               \n
+            this.segment = paintInfo.segment;         \n
+            _updateSegmentProportions();            \n
+\t\t};\n
+\t\t\n
+\t\treturn {\n
+\t\t\taddSegment:_addSegment,\n
+            prepareCompute:_prepareCompute,\n
+            sourceStub:sourceStub,\n
+            targetStub:targetStub,\n
+            maxStub:Math.max(sourceStub, targetStub),            \n
+            sourceGap:sourceGap,\n
+            targetGap:targetGap,\n
+            maxGap:Math.max(sourceGap, targetGap)\n
+\t\t};\t\t\n
+\t};\n
+    jsPlumbUtil.extend(jsPlumb.Connectors.AbstractConnector, AbstractComponent);\n
+\t\n
+    /**\n
+     * Class: Connectors.Straight\n
+     * The Straight connector draws a simple straight line between the two anchor points.  It does not have any constructor parameters.\n
+     */\n
+    var Straight = jsPlumb.Connectors.Straight = function() {\n
+    \tthis.type = "Straight";\n
+\t\tvar _super =  jsPlumb.Connectors.AbstractConnector.apply(this, arguments);\t\t\n
+\n
+        this._compute = function(paintInfo, _) {                        \n
+            _super.addSegment(this, "Straight", {x1:paintInfo.sx, y1:paintInfo.sy, x2:paintInfo.startStubX, y2:paintInfo.startStubY});                                                \n
+            _super.addSegment(this, "Straight", {x1:paintInfo.startStubX, y1:paintInfo.startStubY, x2:paintInfo.endStubX, y2:paintInfo.endStubY});                        \n
+            _super.addSegment(this, "Straight", {x1:paintInfo.endStubX, y1:paintInfo.endStubY, x2:paintInfo.tx, y2:paintInfo.ty});                                    \n
+        };                    \n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Connectors.Straight, jsPlumb.Connectors.AbstractConnector);\n
+    jsPlumb.registerConnectorType(Straight, "Straight");\n
+\n
+\n
+ // ********************************* END OF CONNECTOR TYPES *******************************************************************\n
+    \n
+ // ********************************* ENDPOINT TYPES *******************************************************************\n
+    \n
+    jsPlumb.Endpoints.AbstractEndpoint = function(params) {\n
+        AbstractComponent.apply(this, arguments);\n
+        var compute = this.compute = function(anchorPoint, orientation, endpointStyle, connectorPaintStyle) {    \n
+            var out = this._compute.apply(this, arguments);\n
+            this.x = out[0];\n
+            this.y = out[1];\n
+            this.w = out[2];\n
+            this.h = out[3];\n
+            this.bounds.minX = this.x;\n
+            this.bounds.minY = this.y;\n
+            this.bounds.maxX = this.x + this.w;\n
+            this.bounds.maxY = this.y + this.h;\n
+            return out;\n
+        };\n
+        return {\n
+            compute:compute,\n
+            cssClass:params.cssClass\n
+        };\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Endpoints.AbstractEndpoint, AbstractComponent);\n
+    \n
+    /**\n
+     * Class: Endpoints.Dot\n
+     * A round endpoint, with default radius 10 pixels.\n
+     */    \t\n
+    \t\n
+\t/**\n
+\t * Function: Constructor\n
+\t * \n
+\t * Parameters:\n
+\t * \n
+\t * \tradius\t-\tradius of the endpoint.  defaults to 10 pixels.\n
+\t */\n
+\tjsPlumb.Endpoints.Dot = function(params) {        \n
+\t\tthis.type = "Dot";\n
+\t\tvar _super = jsPlumb.Endpoints.AbstractEndpoint.apply(this, arguments);\n
+\t\tparams = params || {};\t\t\t\t\n
+\t\tthis.radius = params.radius || 10;\n
+\t\tthis.defaultOffset = 0.5 * this.radius;\n
+\t\tthis.defaultInnerRadius = this.radius / 3;\t\t\t\n
+\t\t\n
+\t\tthis._compute = function(anchorPoint, orientation, endpointStyle, connectorPaintStyle) {\n
+\t\t\tthis.radius = endpointStyle.radius || this.radius;\n
+\t\t\tvar\tx = anchorPoint[0] - this.radius,\n
+\t\t\t\ty = anchorPoint[1] - this.radius,\n
+                w = this.radius * 2,\n
+                h = this.radius * 2;\n
+\n
+            if (endpointStyle.strokeStyle) {\n
+                var lw = endpointStyle.lineWidth || 1;\n
+                x -= lw;\n
+                y -= lw;\n
+                w += (lw * 2);\n
+                h += (lw * 2);\n
+            }\n
+\t\t\treturn [ x, y, w, h, this.radius ];\n
+\t\t};\n
+\t};\n
+    jsPlumbUtil.extend(jsPlumb.Endpoints.Dot, jsPlumb.Endpoints.AbstractEndpoint);\n
+\n
+\tjsPlumb.Endpoints.Rectangle = function(params) {\n
+\t\tthis.type = "Rectangle";\n
+\t\tvar _super = jsPlumb.Endpoints.AbstractEndpoint.apply(this, arguments);\n
+\t\tparams = params || {};\n
+\t\tthis.width = params.width || 20;\n
+\t\tthis.height = params.height || 20;\n
+\n
+\t\tthis._compute = function(anchorPoint, orientation, endpointStyle, connectorPaintStyle) {\n
+\t\t\tvar width = endpointStyle.width || this.width,\n
+\t\t\t\theight = endpointStyle.height || this.height,\n
+\t\t\t\tx = anchorPoint[0] - (width/2),\n
+\t\t\t\ty = anchorPoint[1] - (height/2);\n
+\n
+\t\t\treturn [ x, y, width, height];\n
+\t\t};\n
+\t};\n
+\tjsPlumbUtil.extend(jsPlumb.Endpoints.Rectangle, jsPlumb.Endpoints.AbstractEndpoint);\n
+\n
+\tvar DOMElementEndpoint = function(params) {\n
+\t\tjsPlumb.DOMElementComponent.apply(this, arguments);\n
+\t\tthis._jsPlumb.displayElements = [];\n
+\t};\n
+\tjsPlumbUtil.extend(DOMElementEndpoint, jsPlumb.DOMElementComponent, {\n
+\t\tgetDisplayElements : function() { \n
+\t\t\treturn this._jsPlumb.displayElements; \n
+\t\t},\n
+\t\tappendDisplayElement : function(el) {\n
+\t\t\tthis._jsPlumb.displayElements.push(el);\n
+\t\t}\n
+\t});\n
+\n
+\t/**\n
+\t * Class: Endpoints.Image\n
+\t * Draws an image as the Endpoint.\n
+\t */\n
+\t/**\n
+\t * Function: Constructor\n
+\t * \n
+\t * Parameters:\n
+\t * \n
+\t * \tsrc\t-\tlocation of the image to use.\n
+\n
+    TODO: multiple references to self. not sure quite how to get rid of them entirely. perhaps self = null in the cleanup\n
+    function will suffice\n
+\n
+    TODO this class still leaks memory.\n
+\n
+\t */\n
+\tjsPlumb.Endpoints.Image = function(params) {\n
+\n
+\t\tthis.type = "Image";\n
+\t\tDOMElementEndpoint.apply(this, arguments);\n
+\t\tjsPlumb.Endpoints.AbstractEndpoint.apply(this, arguments);\n
+\n
+\t\tvar _onload = params.onload, \n
+\t\t\tsrc = params.src || params.url,\n
+\t\t\tclazz = params.cssClass ? " " + params.cssClass : "";\n
+\n
+\t\tthis._jsPlumb.img = new Image();\n
+\t\tthis._jsPlumb.ready = false;\n
+\t\tthis._jsPlumb.initialized = false;\n
+\t\tthis._jsPlumb.deleted = false;\n
+\t\tthis._jsPlumb.widthToUse = params.width;\n
+\t\tthis._jsPlumb.heightToUse = params.height;\n
+\t\tthis._jsPlumb.endpoint = params.endpoint;\n
+\n
+\t\tthis._jsPlumb.img.onload = function() {\n
+\t\t\tif (this._jsPlumb != null) {\n
+\t\t\t\tthis._jsPlumb.ready = true;\n
+\t\t\t\tthis._jsPlumb.widthToUse = this._jsPlumb.widthToUse || this._jsPlumb.img.width;\n
+\t\t\t\tthis._jsPlumb.heightToUse = this._jsPlumb.heightToUse || this._jsPlumb.img.height;\n
+\t\t\t\tif (_onload) {\n
+\t\t\t\t\t_onload(this);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}.bind(this);\n
+\n
+        /*\n
+            Function: setImage\n
+            Sets the Image to use in this Endpoint.  \n
+\n
+            Parameters:\n
+            img         -   may be a URL or an Image object\n
+            onload      -   optional; a callback to execute once the image has loaded.\n
+        */\n
+        this._jsPlumb.endpoint.setImage = function(_img, onload) {\n
+            var s = _img.constructor == String ? _img : _img.src;\n
+            _onload = onload; \n
+            this._jsPlumb.img.src = s;\n
+\n
+            if (this.canvas != null)\n
+                this.canvas.setAttribute("src", this._jsPlumb.img.src);\n
+        }.bind(this);\n
+\n
+\t\tthis._jsPlumb.endpoint.setImage(src, _onload);\n
+\t\tthis._compute = function(anchorPoint, orientation, endpointStyle, connectorPaintStyle) {\n
+\t\t\tthis.anchorPoint = anchorPoint;\n
+\t\t\tif (this._jsPlumb.ready) return [anchorPoint[0] - this._jsPlumb.widthToUse / 2, anchorPoint[1] - this._jsPlumb.heightToUse / 2, \n
+\t\t\t\t\t\t\t\t\tthis._jsPlumb.widthToUse, this._jsPlumb.heightToUse];\n
+\t\t\telse return [0,0,0,0];\n
+\t\t};\n
+\t\t\n
+\t\tthis.canvas = document.createElement("img");\n
+\t\tthis.canvas.style.margin = 0;\n
+\t\tthis.canvas.style.padding = 0;\n
+\t\tthis.canvas.style.outline = 0;\n
+\t\tthis.canvas.style.position = "absolute";\t\t\n
+\t\tthis.canvas.className = this._jsPlumb.instance.endpointClass + clazz;\n
+\t\tif (this._jsPlumb.widthToUse) this.canvas.setAttribute("width", this._jsPlumb.widthToUse);\n
+\t\tif (this._jsPlumb.heightToUse) this.canvas.setAttribute("height", this._jsPlumb.heightToUse);\t\t\n
+\t\tthis._jsPlumb.instance.appendElement(this.canvas);\n
+\t\tthis.attachListeners(this.canvas, this);\n
+\t\t\n
+\t\tthis.actuallyPaint = function(d, style, anchor) {\n
+\t\t\tif (!this._jsPlumb.deleted) {\n
+\t\t\t\tif (!this._jsPlumb.initialized) {\n
+\t\t\t\t\tthis.canvas.setAttribute("src", this._jsPlumb.img.src);\n
+\t\t\t\t\tthis.appendDisplayElement(this.canvas);\n
+\t\t\t\t\tthis._jsPlumb.initialized = true;\n
+\t\t\t\t}\n
+\t\t\t\tvar x = this.anchorPoint[0] - (this._jsPlumb.widthToUse / 2),\n
+\t\t\t\t\ty = this.anchorPoint[1] - (this._jsPlumb.heightToUse / 2);\n
+\t\t\t\tjsPlumbUtil.sizeElement(this.canvas, x, y, this._jsPlumb.widthToUse, this._jsPlumb.heightToUse);\n
+\t\t\t}\n
+\t\t};\n
+\t\t\n
+\t\tthis.paint = function(style, anchor) {\n
+            if (this._jsPlumb != null) {  // may have been deleted\n
+    \t\t\tif (this._jsPlumb.ready) {\n
+        \t\t\tthis.actuallyPaint(style, anchor);\n
+    \t\t\t}\n
+    \t\t\telse { \n
+    \t\t\t\twindow.setTimeout(function() {\n
+    \t\t\t\t\tthis.paint(style, anchor);\n
+    \t\t\t\t}.bind(this), 200);\n
+    \t\t\t}\n
+            }\n
+\t\t};\t\t\t\t\n
+\t};\n
+    jsPlumbUtil.extend(jsPlumb.Endpoints.Image, [ DOMElementEndpoint, jsPlumb.Endpoints.AbstractEndpoint ], {\n
+        cleanup : function() {            \n
+            this._jsPlumb.deleted = true;\n
+            if (this.canvas) this.canvas.parentNode.removeChild(this.canvas);\n
+            this.canvas = null;\n
+        } \n
+    });\n
+\t\n
+\t/*\n
+\t * Class: Endpoints.Blank\n
+\t * An Endpoint that paints nothing (visible) on the screen.  Supports cssClass and hoverClass parameters like all Endpoints.\n
+\t */\n
+\tjsPlumb.Endpoints.Blank = function(params) {\n
+\t\tvar _super = jsPlumb.Endpoints.AbstractEndpoint.apply(this, arguments);\n
+\t\tthis.type = "Blank";\n
+\t\tDOMElementEndpoint.apply(this, arguments);\t\t\n
+\t\tthis._compute = function(anchorPoint, orientation, endpointStyle, connectorPaintStyle) {\n
+\t\t\treturn [anchorPoint[0], anchorPoint[1],10,0];\n
+\t\t};\n
+\t\t\n
+\t\tthis.canvas = document.createElement("div");\n
+\t\tthis.canvas.style.display = "block";\n
+\t\tthis.canvas.style.width = "1px";\n
+\t\tthis.canvas.style.height = "1px";\n
+\t\tthis.canvas.style.background = "transparent";\n
+\t\tthis.canvas.style.position = "absolute";\n
+\t\tthis.canvas.className = this._jsPlumb.endpointClass;\n
+\t\tjsPlumb.appendElement(this.canvas);\n
+\t\t\n
+\t\tthis.paint = function(style, anchor) {\n
+\t\t\tjsPlumbUtil.sizeElement(this.canvas, this.x, this.y, this.w, this.h);\t\n
+\t\t};\n
+\t};\n
+    jsPlumbUtil.extend(jsPlumb.Endpoints.Blank, [jsPlumb.Endpoints.AbstractEndpoint, DOMElementEndpoint], {\n
+        cleanup:function() {\n
+            if (this.canvas && this.canvas.parentNode) {\n
+                this.canvas.parentNode.removeChild(this.canvas);\n
+            }\n
+        }\n
+    });\n
+\t\n
+\t/*\n
+\t * Class: Endpoints.Triangle\n
+\t * A triangular Endpoint.  \n
+\t */\n
+\t/*\n
+\t * Function: Constructor\n
+\t * \n
+\t * Parameters:\n
+\t * \n
+\t * \twidth\t-\twidth of the triangle\'s base.  defaults to 55 pixels.\n
+\t * \theight\t-\theight of the triangle from base to apex.  defaults to 55 pixels.\n
+\t */\n
+\tjsPlumb.Endpoints.Triangle = function(params) {        \n
+\t\tthis.type = "Triangle";\n
+        var _super = jsPlumb.Endpoints.AbstractEndpoint.apply(this, arguments);\n
+\t\tparams = params || {  };\n
+\t\tparams.width = params.width || 55;\n
+\t\tparams.height = params.height || 55;\n
+\t\tthis.width = params.width;\n
+\t\tthis.height = params.height;\n
+\t\tthis._compute = function(anchorPoint, orientation, endpointStyle, connectorPaintStyle) {\n
+\t\t\tvar width = endpointStyle.width || self.width,\n
+\t\t\theight = endpointStyle.height || self.height,\n
+\t\t\tx = anchorPoint[0] - (width/2),\n
+\t\t\ty = anchorPoint[1] - (height/2);\n
+\t\t\treturn [ x, y, width, height ];\n
+\t\t};\n
+\t};\n
+// ********************************* END OF ENDPOINT TYPES *******************************************************************\n
+\t\n
+\n
+// ********************************* OVERLAY DEFINITIONS ***********************************************************************    \n
+\n
+\tvar AbstractOverlay = jsPlumb.Overlays.AbstractOverlay = function(params) {\n
+\t\tthis.visible = true;\n
+        this.isAppendedAtTopLevel = true;\n
+\t\tthis.component = params.component;\n
+\t\tthis.loc = params.location == null ? 0.5 : params.location;\n
+        this.endpointLoc = params.endpointLocation == null ? [ 0.5, 0.5] : params.endpointLocation;\t\t\n
+\t};\n
+    AbstractOverlay.prototype = {\n
+        cleanup:function() {  \n
+           this.component = null;\n
+           this.canvas = null;\n
+           this.endpointLoc = null;\n
+        },\n
+        setVisible : function(val) { \n
+            this.visible = val;\n
+            this.component.repaint();\n
+        },\n
+        isVisible : function() { return this.visible; },\n
+        hide : function() { this.setVisible(false); },\n
+        show : function() { this.setVisible(true); },        \n
+        incrementLocation : function(amount) {\n
+            this.loc += amount;\n
+            this.component.repaint();\n
+        },\n
+        setLocation : function(l) {\n
+            this.loc = l;\n
+            this.component.repaint();\n
+        },\n
+        getLocation : function() {\n
+            return this.loc;\n
+        }\n
+    };\n
+\t\n
+\t\n
+\t/*\n
+\t * Class: Overlays.Arrow\n
+\t * \n
+\t * An arrow overlay, defined by four points: the head, the two sides of the tail, and a \'foldback\' point at some distance along the length\n
+\t * of the arrow that lines from each tail point converge into.  The foldback point is defined using a decimal that indicates some fraction\n
+\t * of the length of the arrow and has a default value of 0.623.  A foldback point value of 1 would mean that the arrow had a straight line\n
+\t * across the tail.  \n
+\t */\n
+\t/*\n
+\t * Function: Constructor\n
+\t * \n
+\t * Parameters:\n
+\t * \n
+\t * \tlength - distance in pixels from head to tail baseline. default 20.\n
+\t * \twidth - width in pixels of the tail baseline. default 20.\n
+\t * \tfillStyle - style to use when filling the arrow.  defaults to "black".\n
+\t * \tstrokeStyle - style to use when stroking the arrow. defaults to null, which means the arrow is not stroked.\n
+\t * \tlineWidth - line width to use when stroking the arrow. defaults to 1, but only used if strokeStyle is not null.\n
+\t * \tfoldback - distance (as a decimal from 0 to 1 inclusive) along the length of the arrow marking the point the tail points should fold back to.  defaults to 0.623.\n
+\t * \tlocation - distance (as a decimal from 0 to 1 inclusive) marking where the arrow should sit on the connector. defaults to 0.5.\n
+\t * \tdirection - indicates the direction the arrow points in. valid values are -1 and 1; 1 is default.\n
+\t */\n
+\tjsPlumb.Overlays.Arrow = function(params) {\n
+\t\tthis.type = "Arrow";\n
+\t\tAbstractOverlay.apply(this, arguments);\n
+        this.isAppendedAtTopLevel = false;\n
+\t\tparams = params || {};\n
+\t\tvar _ju = jsPlumbUtil, _jg = Biltong;\n
+\t\t\n
+    \tthis.length = params.length || 20;\n
+    \tthis.width = params.width || 20;\n
+    \tthis.id = params.id;\n
+    \tvar direction = (params.direction || 1) < 0 ? -1 : 1,\n
+    \t    paintStyle = params.paintStyle || { lineWidth:1 },\n
+    \t    // how far along the arrow the lines folding back in come to. default is 62.3%.\n
+    \t    foldback = params.foldback || 0.623;\n
+    \t    \t\n
+    \tthis.computeMaxSize = function() { return self.width * 1.5; };    \t\n
+    \t//this.cleanup = function() { };  // nothing to clean up for Arrows    \n
+    \tthis.draw = function(component, currentConnectionPaintStyle) {\n
+\n
+            var hxy, mid, txy, tail, cxy;\n
+            if (component.pointAlongPathFrom) {\n
+\n
+                if (_ju.isString(this.loc) || this.loc > 1 || this.loc < 0) {                    \n
+                    var l = parseInt(this.loc, 10),\n
+                        fromLoc = this.loc < 0 ? 1 : 0;\n
+                    hxy = component.pointAlongPathFrom(fromLoc, l, false);\n
+                    mid = component.pointAlongPathFrom(fromLoc, l - (direction * this.length / 2), false);\n
+                    txy = _jg.pointOnLine(hxy, mid, this.length);\n
+                }\n
+                else if (this.loc == 1) {                \n
+\t\t\t\t\thxy = component.pointOnPath(this.loc);\t\t\t\t\t           \n
+                    mid = component.pointAlongPathFrom(this.loc, -(this.length));\n
+\t\t\t\t\ttxy = _jg.pointOnLine(hxy, mid, this.length);\n
+\t\t\t\t\t\n
+\t\t\t\t\tif (direction == -1) {\n
+\t\t\t\t\t\tvar _ = txy;\n
+\t\t\t\t\t\ttxy = hxy;\n
+\t\t\t\t\t\thxy = _;\n
+\t\t\t\t\t}\n
+                }\n
+                else if (this.loc === 0) {\t\t\t\t\t                    \n
+\t\t\t\t\ttxy = component.pointOnPath(this.loc);                    \n
+\t\t\t\t\tmid = component.pointAlongPathFrom(this.loc, this.length);                    \n
+\t\t\t\t\thxy = _jg.pointOnLine(txy, mid, this.length);                    \n
+\t\t\t\t\tif (direction == -1) {\n
+\t\t\t\t\t\tvar __ = txy;\n
+\t\t\t\t\t\ttxy = hxy;\n
+\t\t\t\t\t\thxy = __;\n
+\t\t\t\t\t}\n
+                }\n
+                else {                    \n
+    \t\t\t    hxy = component.pointAlongPathFrom(this.loc, direction * this.length / 2);\n
+                    mid = component.pointOnPath(this.loc);\n
+                    txy = _jg.pointOnLine(hxy, mid, this.length);\n
+                }\n
+\n
+                tail = _jg.perpendicularLineTo(hxy, txy, this.width);\n
+                cxy = _jg.pointOnLine(hxy, txy, foldback * this.length);    \t\t\t\n
+    \t\t\t\n
+    \t\t\tvar d = { hxy:hxy, tail:tail, cxy:cxy },\n
+    \t\t\t    strokeStyle = paintStyle.strokeStyle || currentConnectionPaintStyle.strokeStyle,\n
+    \t\t\t    fillStyle = paintStyle.fillStyle || currentConnectionPaintStyle.strokeStyle,\n
+    \t\t\t    lineWidth = paintStyle.lineWidth || currentConnectionPaintStyle.lineWidth,\n
+                    info = {\n
+                        component:component, \n
+                        d:d, \n
+                        lineWidth:lineWidth, \n
+                        strokeStyle:strokeStyle, \n
+                        fillStyle:fillStyle,\n
+                        minX:Math.min(hxy.x, tail[0].x, tail[1].x),\n
+                        maxX:Math.max(hxy.x, tail[0].x, tail[1].x),\n
+                        minY:Math.min(hxy.y, tail[0].y, tail[1].y),\n
+                        maxY:Math.max(hxy.y, tail[0].y, tail[1].y)\n
+                    };    \t\t\t\n
+\t\t\t\t\t\t    \n
+                return info;\n
+            }\n
+            else return {component:component, minX:0,maxX:0,minY:0,maxY:0};\n
+    \t};\n
+    };    \n
+    jsPlumbUtil.extend(jsPlumb.Overlays.Arrow, AbstractOverlay);      \n
+    \n
+    /*\n
+     * Class: Overlays.PlainArrow\n
+\t * \n
+\t * A basic arrow.  This is in fact just one instance of the more generic case in which the tail folds back on itself to some\n
+\t * point along the length of the arrow: in this case, that foldback point is the full length of the arrow.  so it just does\n
+\t * a \'call\' to Arrow with foldback set appropriately.       \n
+\t */\n
+    /*\n
+     * Function: Constructor\n
+     * See <Overlays.Arrow> for allowed parameters for this overlay.\n
+     */\n
+    jsPlumb.Overlays.PlainArrow = function(params) {\n
+    \tparams = params || {};    \t\n
+    \tvar p = jsPlumb.extend(params, {foldback:1});\n
+    \tjsPlumb.Overlays.Arrow.call(this, p);\n
+    \tthis.type = "PlainArrow";\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.PlainArrow, jsPlumb.Overlays.Arrow);\n
+        \n
+    /*\n
+     * Class: Overlays.Diamond\n
+     * \n
+\t * A diamond. Like PlainArrow, this is a concrete case of the more generic case of the tail points converging on some point...it just\n
+\t * happens that in this case, that point is greater than the length of the the arrow.    \n
+\t * \n
+\t *      this could probably do with some help with positioning...due to the way it reuses the Arrow paint code, what Arrow thinks is the\n
+\t *      center is actually 1/4 of the way along for this guy.  but we don\'t have any knowledge of pixels at this point, so we\'re kind of\n
+\t *      stuck when it comes to helping out the Arrow class. possibly we could pass in a \'transpose\' parameter or something. the value\n
+\t *      would be -l/4 in this case - move along one quarter of the total length.\n
+\t */\n
+    /*\n
+     * Function: Constructor\n
+     * See <Overlays.Arrow> for allowed parameters for this overlay.\n
+     */\n
+    jsPlumb.Overlays.Diamond = function(params) {\n
+    \tparams = params || {};    \t\n
+    \tvar l = params.length || 40,\n
+    \t    p = jsPlumb.extend(params, {length:l/2, foldback:2});\n
+    \tjsPlumb.Overlays.Arrow.call(this, p);\n
+    \tthis.type = "Diamond";\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.Diamond, jsPlumb.Overlays.Arrow);\n
+\n
+    var _getDimensions = function(component) {\n
+        if (component._jsPlumb.cachedDimensions == null)\n
+            component._jsPlumb.cachedDimensions = component.getDimensions();\n
+        return component._jsPlumb.cachedDimensions;\n
+    };      \n
+\t\n
+\t// abstract superclass for overlays that add an element to the DOM.\n
+    var AbstractDOMOverlay = function(params) {\n
+\t\tjsPlumb.DOMElementComponent.apply(this, arguments);\n
+    \tAbstractOverlay.apply(this, arguments);\n
+\n
+\t\tthis.id = params.id;\n
+        this._jsPlumb.div = null;\n
+        this._jsPlumb.initialised = false;\n
+        this._jsPlumb.component = params.component;\n
+        this._jsPlumb.cachedDimensions = null;\n
+        this._jsPlumb.create = params.create;\n
+\n
+\t\tthis.getElement = function() {\n
+\t\t\tif (this._jsPlumb.div == null) {\n
+                var div = this._jsPlumb.div = jsPlumb.getDOMElement(this._jsPlumb.create(this._jsPlumb.component));\n
+                div.style.position   =   "absolute";     \n
+                var clazz = this._jsPlumb.instance.overlayClass + " " + \n
+                    (this.cssClass ? this.cssClass : \n
+                    params.cssClass ? params.cssClass : "");\n
+                div.className = clazz;\n
+                this._jsPlumb.instance.appendElement(div);\n
+                this._jsPlumb.instance.getId(div);\n
+                this.attachListeners(div, this);\n
+                this.canvas = div;\n
+\t\t\t}\n
+    \t\treturn this._jsPlumb.div;\n
+    \t};\n
+\n
+\t\tthis.draw = function(component, currentConnectionPaintStyle, absolutePosition) {\n
+\t    \tvar td = _getDimensions(this);\n
+\t    \tif (td != null && td.length == 2) {\n
+\t\t\t\tvar cxy = { x:0,y:0 };\n
+\n
+                // absolutePosition would have been set by a call to connection.setAbsoluteOverlayPosition.\n
+                if (absolutePosition) {\n
+                    cxy = { x:absolutePosition[0], y:absolutePosition[1] };\n
+                }\n
+                else if (component.pointOnPath) {\n
+                    var loc = this.loc, absolute = false;\n
+                    if (jsPlumbUtil.isString(this.loc) || this.loc < 0 || this.loc > 1) {\n
+                        loc = parseInt(this.loc, 10);\n
+                        absolute = true;\n
+                    }\n
+                    cxy = component.pointOnPath(loc, absolute);  // a connection\n
+                }\n
+                else {\n
+                    var locToUse = this.loc.constructor == Array ? this.loc : this.endpointLoc;\n
+                    cxy = { x:locToUse[0] * component.w,\n
+                            y:locToUse[1] * component.h };\n
+                } \n
+\n
+\t\t\t\tvar minx = cxy.x - (td[0] / 2),\n
+\t\t\t\t    miny = cxy.y - (td[1] / 2);\n
+\n
+                return {\n
+                    component:component, \n
+                    d:{ minx:minx, miny:miny, td:td, cxy:cxy },\n
+                    minX:minx, \n
+                    maxX:minx + td[0], \n
+                    minY:miny, \n
+                    maxY:miny + td[1]\n
+                };\n
+        \t}\n
+\t    \telse return {minX:0,maxX:0,minY:0,maxY:0};\n
+\t    };\n
+\t};\n
+    jsPlumbUtil.extend(AbstractDOMOverlay, [jsPlumb.DOMElementComponent, AbstractOverlay], {\n
+        getDimensions : function() {\n
+            return jsPlumb.getSize(this.getElement());\n
+        },\n
+        setVisible : function(state) {\n
+            this._jsPlumb.div.style.display = state ? "block" : "none";\n
+        },\n
+        /*\n
+         * Function: clearCachedDimensions\n
+         * Clears the cached dimensions for the label. As a performance enhancement, label dimensions are\n
+         * cached from 1.3.12 onwards. The cache is cleared when you change the label text, of course, but\n
+         * there are other reasons why the text dimensions might change - if you make a change through CSS, for\n
+         * example, you might change the font size.  in that case you should explicitly call this method.\n
+         */\n
+        clearCachedDimensions : function() {\n
+            this._jsPlumb.cachedDimensions = null;\n
+        },\n
+        cleanup : function() {\n
+            if (this._jsPlumb.div != null) \n
+                this._jsPlumb.instance.removeElement(this._jsPlumb.div);\n
+        },\n
+        computeMaxSize : function() {\n
+            var td = _getDimensions(this);\n
+            return Math.max(td[0], td[1]);\n
+        },\n
+        reattachListeners : function(connector) {\n
+            if (this._jsPlumb.div) {\n
+                this.reattachListenersForElement(this._jsPlumb.div, this, connector);\n
+            }\n
+        },\n
+        paint : function(p, containerExtents) {\n
+            if (!this._jsPlumb.initialised) {\n
+                this.getElement();\n
+                p.component.appendDisplayElement(this._jsPlumb.div);\n
+                this.attachListeners(this._jsPlumb.div, p.component);\n
+                this._jsPlumb.initialised = true;\n
+            }\n
+            this._jsPlumb.div.style.left = (p.component.x + p.d.minx) + "px";\n
+            this._jsPlumb.div.style.top = (p.component.y + p.d.miny) + "px";\n
+        }\n
+    });\n
+\t\n
+\t/*\n
+     * Class: Overlays.Custom\n
+     * A Custom overlay. You supply a \'create\' function which returns some DOM element, and jsPlumb positions it.\n
+     * The \'create\' function is passed a Connection or Endpoint.\n
+     */\n
+    /*\n
+     * Function: Constructor\n
+     * \n
+     * Parameters:\n
+     * \tcreate - function for jsPlumb to call that returns a DOM element.\n
+     * \tlocation - distance (as a decimal from 0 to 1 inclusive) marking where the label should sit on the connector. defaults to 0.5.\n
+     * \tid - optional id to use for later retrieval of this overlay.\n
+     * \t\n
+     */\n
+    jsPlumb.Overlays.Custom = function(params) {\n
+    \tthis.type = "Custom";    \t\n
+    \tAbstractDOMOverlay.apply(this, arguments);\t\t    \t        \t\t    \t    \t\t\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.Custom, AbstractDOMOverlay);\n
+\n
+    jsPlumb.Overlays.GuideLines = function() {\n
+        var self = this;\n
+        self.length = 50;\n
+        self.lineWidth = 5;\n
+        this.type = "GuideLines";\n
+        AbstractOverlay.apply(this, arguments);\n
+        jsPlumb.jsPlumbUIComponent.apply(this, arguments);\n
+        this.draw = function(connector, currentConnectionPaintStyle) {\n
+\n
+            var head = connector.pointAlongPathFrom(self.loc, self.length / 2),\n
+                mid = connector.pointOnPath(self.loc),\n
+                tail = Biltong.pointOnLine(head, mid, self.length),\n
+                tailLine = Biltong.perpendicularLineTo(head, tail, 40),\n
+                headLine = Biltong.perpendicularLineTo(tail, head, 20);\n
+\n
+            return {\n
+                connector:connector,\n
+                head:head,\n
+                tail:tail,\n
+                headLine:headLine,\n
+                tailLine:tailLine,                \n
+                minX:Math.min(head.x, tail.x, headLine[0].x, headLine[1].x), \n
+                minY:Math.min(head.y, tail.y, headLine[0].y, headLine[1].y), \n
+                maxX:Math.max(head.x, tail.x, headLine[0].x, headLine[1].x), \n
+                maxY:Math.max(head.y, tail.y, headLine[0].y, headLine[1].y)\n
+            };\n
+        };\n
+\n
+       // this.cleanup = function() { };  // nothing to clean up for GuideLines\n
+    };\n
+    \n
+    /*\n
+     * Class: Overlays.Label\n
+     \n
+     */\n
+    /*\n
+     * Function: Constructor\n
+     * \n
+     * Parameters:\n
+     * \tcssClass - optional css class string to append to css class. This string is appended "as-is", so you can of course have multiple classes\n
+     *             defined.  This parameter is preferred to using labelStyle, borderWidth and borderStyle.\n
+     * \tlabel - the label to paint.  May be a string or a function that returns a string.  Nothing will be painted if your label is null or your\n
+     *         label function returns null.  empty strings _will_ be painted.\n
+     * \tlocation - distance (as a decimal from 0 to 1 inclusive) marking where the label should sit on the connector. defaults to 0.5.\n
+     * \tid - optional id to use for later retrieval of this overlay.\n
+     * \n
+     * \t\n
+     */\n
+    jsPlumb.Overlays.Label =  function(params) {\t\t   \n
+\t\tthis.labelStyle = params.labelStyle;\n
+        \n
+        var labelWidth = null, labelHeight =  null, labelText = null, labelPadding = null;\n
+\t\tthis.cssClass = this.labelStyle != null ? this.labelStyle.cssClass : null;\n
+\t\tvar p = jsPlumb.extend({\n
+            create : function() {\n
+                return document.createElement("div");\n
+            }}, params);\n
+    \tjsPlumb.Overlays.Custom.call(this, p);\n
+\t\tthis.type = "Label";    \t\n
+        this.label = params.label || "";\n
+        this.labelText = null;\n
+        if (this.labelStyle) {\n
+            var el = this.getElement();            \n
+            this.labelStyle.font = this.labelStyle.font || "12px sans-serif";\n
+            el.style.font = this.labelStyle.font;\n
+            el.style.color = this.labelStyle.color || "black";\n
+            if (this.labelStyle.fillStyle) el.style.background = this.labelStyle.fillStyle;\n
+            if (this.labelStyle.borderWidth > 0) {\n
+                var dStyle = this.labelStyle.borderStyle ? this.labelStyle.borderStyle : "black";\n
+                el.style.border = this.labelStyle.borderWidth  + "px solid " + dStyle;\n
+            }\n
+            if (this.labelStyle.padding) el.style.padding = this.labelStyle.padding;            \n
+        }\n
+\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.Label, jsPlumb.Overlays.Custom, {\n
+        cleanup:function() {\n
+            this.div = null;\n
+            this.label = null;\n
+            this.labelText = null;\n
+            this.cssClass = null;\n
+            this.labelStyle = null;\n
+        },\n
+        getLabel : function() {\n
+            return this.label;\n
+        },\n
+        /*\n
+         * Function: setLabel\n
+         * sets the label\'s, um, label.  you would think i\'d call this function\n
+         * \'setText\', but you can pass either a Function or a String to this, so\n
+         * it makes more sense as \'setLabel\'. This uses innerHTML on the label div, so keep\n
+         * that in mind if you need escaped HTML.\n
+         */\n
+        setLabel : function(l) {\n
+            this.label = l;\n
+            this.labelText = null;\n
+            this.clearCachedDimensions();\n
+            this.update();\n
+            this.component.repaint();\n
+        },\n
+        getDimensions : function() {                \n
+            this.update();\n
+            return AbstractDOMOverlay.prototype.getDimensions.apply(this, arguments);\n
+        },\n
+        update : function() {\n
+            if (typeof this.label == "function") {\n
+                var lt = this.label(this);\n
+                this.getElement().innerHTML = lt.replace(/\\r\\n/g, "<br/>");\n
+            }\n
+            else {\n
+                if (this.labelText == null) {\n
+                    this.labelText = this.label;\n
+                    this.getElement().innerHTML = this.labelText.replace(/\\r\\n/g, "<br/>");\n
+                }\n
+            }\n
+        }\n
+    });\t\t\n
+\n
+ // ********************************* END OF OVERLAY DEFINITIONS ***********************************************************************\n
+    \n
+})();\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the \'flowchart\' connectors, consisting of vertical and horizontal line segments.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+;(function() {\n
+    \n
+    "use strict";\n
+   \n
+    /**\n
+     * Function: Constructor\n
+     * \n
+     * Parameters:\n
+     * \tstub - minimum length for the stub at each end of the connector. This can be an integer, giving a value for both ends of the connections, \n
+     * or an array of two integers, giving separate values for each end. The default is an integer with value 30 (pixels). \n
+     *  gap  - gap to leave between the end of the connector and the element on which the endpoint resides. if you make this larger than stub then you will see some odd looking behaviour.  \n
+                Like stub, this can be an array or a single value. defaults to 0 pixels for each end.     \n
+     * cornerRadius - optional, defines the radius of corners between segments. defaults to 0 (hard edged corners).\n
+     * alwaysRespectStubs - defaults to false. whether or not the connectors should always draw the stub, or, if the two elements\n
+                            are in close proximity to each other (closer than the sum of the two stubs), to adjust the stubs.\n
+     */\n
+    var Flowchart = function(params) {\n
+        this.type = "Flowchart";\n
+        params = params || {};\n
+        params.stub = params.stub == null ? 30 : params.stub;\n
+        var self = this,\n
+            _super =  jsPlumb.Connectors.AbstractConnector.apply(this, arguments),\t\t\n
+            midpoint = params.midpoint == null ? 0.5 : params.midpoint,\n
+            points = [], segments = [],\n
+            grid = params.grid,\n
+            alwaysRespectStubs = params.alwaysRespectStubs,\n
+            userSuppliedSegments = null,\n
+            lastx = null, lasty = null, lastOrientation,\t\n
+            cornerRadius = params.cornerRadius != null ? params.cornerRadius : 0,\t\n
+            sgn = function(n) { return n < 0 ? -1 : n === 0 ? 0 : 1; },            \n
+            /**\n
+             * helper method to add a segment.\n
+             */\n
+            addSegment = function(segments, x, y, paintInfo) {\n
+                if (lastx == x && lasty == y) return;\n
+                var lx = lastx == null ? paintInfo.sx : lastx,\n
+                    ly = lasty == null ? paintInfo.sy : lasty,\n
+                    o = lx == x ? "v" : "h",\n
+                    sgnx = sgn(x - lx),\n
+                    sgny = sgn(y - ly);\n
+                    \n
+                lastx = x;\n
+                lasty = y;\t\t\t\t    \t\t                \n
+                segments.push([lx, ly, x, y, o, sgnx, sgny]);\n
+            },\n
+            segLength = function(s) {\n
+                return Math.sqrt(Math.pow(s[0] - s[2], 2) + Math.pow(s[1] - s[3], 2));    \n
+            },\n
+            _cloneArray = function(a) { var _a = []; _a.push.apply(_a, a); return _a;},\n
+            updateMinMax = function(a1) {\n
+                self.bounds.minX = Math.min(self.bounds.minX, a1[2]);\n
+                self.bounds.maxX = Math.max(self.bounds.maxX, a1[2]);\n
+                self.bounds.minY = Math.min(self.bounds.minY, a1[3]);\n
+                self.bounds.maxY = Math.max(self.bounds.maxY, a1[3]);    \n
+            },\n
+            writeSegments = function(conn, segments, paintInfo) {\n
+                var current, next;                \n
+                for (var i = 0; i < segments.length - 1; i++) {\n
+                    \n
+                    current = current || _cloneArray(segments[i]);\n
+                    next = _cloneArray(segments[i + 1]);\n
+                    if (cornerRadius > 0 && current[4] != next[4]) {\n
+                        var radiusToUse = Math.min(cornerRadius, segLength(current), segLength(next));\n
+                        // right angle. adjust current segment\'s end point, and next segment\'s start point.\n
+                        current[2] -= current[5] * radiusToUse;\n
+                        current[3] -= current[6] * radiusToUse;\n
+                        next[0] += next[5] * radiusToUse;\n
+                        next[1] += next[6] * radiusToUse;\t\t\t\t\t\t\t\t\t\t\t\t\t\t                         \t\t\t\n
+                        var ac = (current[6] == next[5] && next[5] == 1) ||\n
+                                 ((current[6] == next[5] && next[5] === 0) && current[5] != next[6]) ||\n
+                                 (current[6] == next[5] && next[5] == -1),\n
+                            sgny = next[1] > current[3] ? 1 : -1,\n
+                            sgnx = next[0] > current[2] ? 1 : -1,\n
+                            sgnEqual = sgny == sgnx,\n
+                            cx = (sgnEqual && ac || (!sgnEqual && !ac)) ? next[0] : current[2],\n
+                            cy = (sgnEqual && ac || (!sgnEqual && !ac)) ? current[3] : next[1];                                                        \n
+                        \n
+                        _super.addSegment(conn, "Straight", {\n
+                            x1:current[0], y1:current[1], x2:current[2], y2:current[3]\n
+                        });\n
+                            \n
+                        _super.addSegment(conn, "Arc", {\n
+                            r:radiusToUse, \n
+                            x1:current[2], \n
+                            y1:current[3], \n
+                            x2:next[0], \n
+                            y2:next[1],\n
+                            cx:cx,\n
+                            cy:cy,\n
+                            ac:ac\n
+                        });\t                                            \n
+                    }\n
+                    else {                 \n
+                        // dx + dy are used to adjust for line width.\n
+                        var dx = (current[2] == current[0]) ? 0 : (current[2] > current[0]) ? (paintInfo.lw / 2) : -(paintInfo.lw / 2),\n
+                            dy = (current[3] == current[1]) ? 0 : (current[3] > current[1]) ? (paintInfo.lw / 2) : -(paintInfo.lw / 2);\n
+                        _super.addSegment(conn, "Straight", {\n
+                            x1:current[0]- dx, y1:current[1]-dy, x2:current[2] + dx, y2:current[3] + dy\n
+                        });\n
+                    }                    \n
+                    current = next;\n
+                }\n
+                if (next != null) {\n
+                    // last segment\n
+                    _super.addSegment(conn, "Straight", {\n
+                        x1:next[0], y1:next[1], x2:next[2], y2:next[3]\n
+                    });                             \n
+                }\n
+            };\n
+        \n
+        this.setSegments = function(s) {\n
+            userSuppliedSegments = s;\n
+        };\n
+        \n
+        this.isEditable = function() { return true; };\n
+        \n
+        /*\n
+            Function: getOriginalSegments\n
+            Gets the segments before the addition of rounded corners. This is used by the flowchart\n
+            connector editor, since it only wants to concern itself with the original segments.\n
+        */\n
+        this.getOriginalSegments = function() {\n
+            return userSuppliedSegments || segments;\n
+        };\n
+        \n
+        this._compute = function(paintInfo, params) {\n
+            \n
+            if (params.clearEdits)\n
+                userSuppliedSegments = null;\n
+            \n
+            if (userSuppliedSegments != null) {\n
+                writeSegments(this, userSuppliedSegments, paintInfo);                \n
+                return;\n
+            }\n
+            \n
+            segments = [];\n
+            lastx = null; lasty = null;\n
+            lastOrientation = null;          \n
+            \n
+            var midx = paintInfo.startStubX + ((paintInfo.endStubX - paintInfo.startStubX) * midpoint),\n
+                midy = paintInfo.startStubY + ((paintInfo.endStubY - paintInfo.startStubY) * midpoint);                                                                                                    \n
+    \n
+            var findClearedLine = function(start, mult, anchorPos, dimension) {\n
+                    return start + (mult * (( 1 - anchorPos) * dimension) + _super.maxStub);\n
+                },\n
+                orientations = { x:[ 0, 1 ], y:[ 1, 0 ] },\n
+                commonStubCalculator = function(axis) {\n
+                    return [ paintInfo.startStubX, paintInfo.startStubY, paintInfo.endStubX, paintInfo.endStubY ];                    \n
+                },\n
+                stubCalculators = {\n
+                    perpendicular:commonStubCalculator,\n
+                    orthogonal:commonStubCalculator,\n
+                    opposite:function(axis) {  \n
+                        var pi = paintInfo,\n
+                            idx = axis == "x" ? 0 : 1, \n
+                            areInProximity = {\n
+                                "x":function() {                                    \n
+                                    return ( (pi.so[idx] == 1 && ( \n
+                                        ( (pi.startStubX > pi.endStubX) && (pi.tx > pi.startStubX) ) ||\n
+                                        ( (pi.sx > pi.endStubX) && (pi.tx > pi.sx))))) ||\n
+\n
+                                        ( (pi.so[idx] == -1 && ( \n
+                                            ( (pi.startStubX < pi.endStubX) && (pi.tx < pi.startStubX) ) ||\n
+                                            ( (pi.sx < pi.endStubX) && (pi.tx < pi.sx)))));\n
+                                },\n
+                                "y":function() {                                     \n
+                                    return ( (pi.so[idx] == 1 && ( \n
+                                        ( (pi.startStubY > pi.endStubY) && (pi.ty > pi.startStubY) ) ||\n
+                                        ( (pi.sy > pi.endStubY) && (pi.ty > pi.sy))))) ||\n
+\n
+                                        ( (pi.so[idx] == -1 && ( \n
+                                        ( (pi.startStubY < pi.endStubY) && (pi.ty < pi.startStubY) ) ||\n
+                                        ( (pi.sy < pi.endStubY) && (pi.ty < pi.sy)))));\n
+                                }\n
+                            };\n
+\n
+                        if (!alwaysRespectStubs && areInProximity[axis]()) {                   \n
+                            return {\n
+                                "x":[(paintInfo.sx + paintInfo.tx) / 2, paintInfo.startStubY, (paintInfo.sx + paintInfo.tx) / 2, paintInfo.endStubY],\n
+                                "y":[paintInfo.startStubX, (paintInfo.sy + paintInfo.ty) / 2, paintInfo.endStubX, (paintInfo.sy + paintInfo.ty) / 2]\n
+                            }[axis];\n
+                        }\n
+                        else {\n
+                            return [ paintInfo.startStubX, paintInfo.startStubY, paintInfo.endStubX, paintInfo.endStubY ];   \n
+                        }\n
+                    }\n
+                },\n
+                lineCalculators = {\n
+                    perpendicular : function(axis, ss, oss, es, oes) {\n
+                        var pi = paintInfo, \n
+                            sis = {\n
+                                x:[ [ [ 1,2,3,4 ], null, [ 2,1,4,3 ] ], null, [ [ 4,3,2,1 ], null, [ 3,4,1,2 ] ] ],\n
+                                y:[ [ [ 3,2,1,4 ], null, [ 2,3,4,1 ] ], null, [ [ 4,1,2,3 ], null, [ 1,4,3,2 ] ] ]\n
+                            },\n
+                            stubs = { \n
+                                x:[ [ pi.startStubX, pi.endStubX ] , null, [ pi.endStubX, pi.startStubX ] ],\n
+                                y:[ [ pi.startStubY, pi.endStubY ] , null, [ pi.endStubY, pi.startStubY ] ]\n
+                            },\n
+                            midLines = {\n
+                                x:[ [ midx, pi.startStubY ], [ midx, pi.endStubY ] ],\n
+                                y:[ [ pi.startStubX, midy ], [ pi.endStubX, midy ] ]\n
+                            },\n
+                            linesToEnd = {\n
+                                x:[ [ pi.endStubX, pi.startStubY ] ],\n
+                                y:[ [ pi.startStubX, pi.endStubY ] ]\n
+                            },\n
+                            startToEnd = {\n
+                                x:[ [ pi.startStubX, pi.endStubY ], [ pi.endStubX, pi.endStubY ] ],        \n
+                                y:[ [ pi.endStubX, pi.startStubY ], [ pi.endStubX, pi.endStubY ] ]\n
+                            },\n
+                            startToMidToEnd = {\n
+                                x:[ [ pi.startStubX, midy ], [ pi.endStubX, midy ], [ pi.endStubX, pi.endStubY ] ],\n
+                                y:[ [ midx, pi.startStubY ], [ midx, pi.endStubY ], [ pi.endStubX, pi.endStubY ] ]\n
+                            },\n
+                            otherStubs = {\n
+                                x:[ pi.startStubY, pi.endStubY ],\n
+                                y:[ pi.startStubX, pi.endStubX ]                                    \n
+                            },\n
+                            soIdx = orientations[axis][0], toIdx = orientations[axis][1],\n
+                            _so = pi.so[soIdx] + 1,\n
+                            _to = pi.to[toIdx] + 1,\n
+                            otherFlipped = (pi.to[toIdx] == -1 && (otherStubs[axis][1] < otherStubs[axis][0])) || (pi.to[toIdx] == 1 && (otherStubs[axis][1] > otherStubs[axis][0])),\n
+                            stub1 = stubs[axis][_so][0],\n
+                            stub2 = stubs[axis][_so][1],\n
+                            segmentIndexes = sis[axis][_so][_to];\n
+\n
+                        if (pi.segment == segmentIndexes[3] || (pi.segment == segmentIndexes[2] && otherFlipped)) {\n
+                            return midLines[axis];       \n
+                        }\n
+                        else if (pi.segment == segmentIndexes[2] && stub2 < stub1) {\n
+                            return linesToEnd[axis];\n
+                        }\n
+                        else if ((pi.segment == segmentIndexes[2] && stub2 >= stub1) || (pi.segment == segmentIndexes[1] && !otherFlipped)) {\n
+                            return startToMidToEnd[axis];\n
+                        }\n
+                        else if (pi.segment == segmentIndexes[0] || (pi.segment == segmentIndexes[1] && otherFlipped)) {\n
+                            return startToEnd[axis];  \n
+                        }                                \n
+                    },\n
+                    orthogonal : function(axis, startStub, otherStartStub, endStub, otherEndStub) {                    \n
+                        var pi = paintInfo,                                            \n
+                            extent = {\n
+                                "x":pi.so[0] == -1 ? Math.min(startStub, endStub) : Math.max(startStub, endStub),\n
+                                "y":pi.so[1] == -1 ? Math.min(startStub, endStub) : Math.max(startStub, endStub)\n
+                            }[axis];\n
+                                                \n
+                        return {\n
+                            "x":[ [ extent, otherStartStub ],[ extent, otherEndStub ], [ endStub, otherEndStub ] ],\n
+                            "y":[ [ otherStartStub, extent ], [ otherEndStub, extent ], [ otherEndStub, endStub ] ]\n
+                        }[axis];                    \n
+                    },\n
+                    opposite : function(axis, ss, oss, es, oes) {                                                \n
+                        var pi = paintInfo,\n
+                            otherAxis = {"x":"y","y":"x"}[axis], \n
+                            dim = {"x":"height","y":"width"}[axis],\n
+                            comparator = pi["is" + axis.toUpperCase() + "GreaterThanStubTimes2"];\n
+\n
+                        if (params.sourceEndpoint.elementId == params.targetEndpoint.elementId) {\n
+                            var _val = oss + ((1 - params.sourceEndpoint.anchor[otherAxis]) * params.sourceInfo[dim]) + _super.maxStub;\n
+                            return {\n
+                                "x":[ [ ss, _val ], [ es, _val ] ],\n
+                                "y":[ [ _val, ss ], [ _val, es ] ]\n
+                            }[axis];\n
+                            \n
+                        }                                                        \n
+                        else if (!comparator || (pi.so[idx] == 1 && ss > es) || (pi.so[idx] == -1 && ss < es)) {                                            \n
+                            return {\n
+                                "x":[[ ss, midy ], [ es, midy ]],\n
+                                "y":[[ midx, ss ], [ midx, es ]]\n
+                            }[axis];\n
+                        }\n
+                        else if ((pi.so[idx] == 1 && ss < es) || (pi.so[idx] == -1 && ss > es)) {\n
+                            return {\n
+                                "x":[[ midx, pi.sy ], [ midx, pi.ty ]],\n
+                                "y":[[ pi.sx, midy ], [ pi.tx, midy ]]\n
+                            }[axis
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAc=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="7" aka="AAAAAAAAAAc=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+];\n
+                        }                        \n
+                    }\n
+                };\n
+\n
+            var stubs = stubCalculators[paintInfo.anchorOrientation](paintInfo.sourceAxis),\n
+                idx = paintInfo.sourceAxis == "x" ? 0 : 1,\n
+                oidx = paintInfo.sourceAxis == "x" ? 1 : 0,                            \n
+                ss = stubs[idx],\n
+                oss = stubs[oidx],\n
+                es = stubs[idx + 2],\n
+                oes = stubs[oidx + 2];\n
+\n
+            // add the start stub segment.\n
+            addSegment(segments, stubs[0], stubs[1], paintInfo);           \n
+\n
+            // compute the rest of the line\n
+            var p = lineCalculators[paintInfo.anchorOrientation](paintInfo.sourceAxis, ss, oss, es, oes);            \n
+            if (p) {\n
+                for (var i = 0; i < p.length; i++) {                \t\n
+                    addSegment(segments, p[i][0], p[i][1], paintInfo);\n
+                }\n
+            }          \n
+            \n
+            // line to end stub\n
+            addSegment(segments, stubs[2], stubs[3], paintInfo);\n
+    \n
+            // end stub to end\n
+            addSegment(segments, paintInfo.tx, paintInfo.ty, paintInfo);               \n
+            \n
+            writeSegments(this, segments, paintInfo);                            \n
+        };\t\n
+\n
+        this.getPath = function() {\n
+            var _last = null, _lastAxis = null, s = [], segs = userSuppliedSegments || segments;\n
+            for (var i = 0; i < segs.length; i++) {\n
+                var seg = segs[i], axis = seg[4], axisIndex = (axis == "v" ? 3 : 2);\n
+                if (_last != null && _lastAxis === axis) {\n
+                    _last[axisIndex] = seg[axisIndex];                            \n
+                }\n
+                else {\n
+                    if (seg[0] != seg[2] || seg[1] != seg[3]) {\n
+                        s.push({\n
+                            start:[ seg[0], seg[1] ],\n
+                            end:[ seg[2], seg[3] ]\n
+                        });                    \n
+                        _last = seg;\n
+                        _lastAxis = seg[4];\n
+                    }\n
+                }\n
+            }\n
+            return s;\n
+        };\t\n
+\n
+        this.setPath = function(path) {\n
+            userSuppliedSegments = [];\n
+            for (var i = 0; i < path.length; i++) {\n
+                 var lx = path[i].start[0],\n
+                    ly = path[i].start[1],\n
+                    x = path[i].end[0],\n
+                    y = path[i].end[1],\n
+                    o = lx == x ? "v" : "h",\n
+                    sgnx = sgn(x - lx),\n
+                    sgny = sgn(y - ly);\n
+\n
+                userSuppliedSegments.push([lx, ly, x, y, o, sgnx, sgny]);\n
+            }\n
+        };\n
+    };\n
+\n
+    jsPlumbUtil.extend(Flowchart, jsPlumb.Connectors.AbstractConnector);\n
+    jsPlumb.registerConnectorType(Flowchart, "Flowchart");\n
+})();\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the state machine connectors.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+ ;(function() {\n
+\t \n
+\t"use strict";\n
+\n
+\tvar Line = function(x1, y1, x2, y2) {\n
+\n
+\t\tthis.m = (y2 - y1) / (x2 - x1);\n
+\t\tthis.b = -1 * ((this.m * x1) - y1);\n
+\t\n
+\t\tthis.rectIntersect = function(x,y,w,h) {\n
+\t\t\tvar results = [], xInt, yInt;\n
+\t\t\n
+\t\t\t// \ttry top face\n
+\t\t\t// \tthe equation of the top face is y = (0 * x) + b; y = b.\n
+\t\t\txInt = (y - this.b) / this.m;\n
+\t\t\t// test that the X value is in the line\'s range.\n
+\t\t\tif (xInt >= x && xInt <= (x + w)) results.push([ xInt, (this.m * xInt) + this.b ]);\n
+\t\t\n
+\t\t\t// try right face\n
+\t\t\tyInt = (this.m * (x + w)) + this.b;\n
+\t\t\tif (yInt >= y && yInt <= (y + h)) results.push([ (yInt - this.b) / this.m, yInt ]);\n
+\t\t\n
+\t\t\t// \tbottom face\n
+\t\t\txInt = ((y + h) - this.b) / this.m;\n
+\t\t\t// test that the X value is in the line\'s range.\n
+\t\t\tif (xInt >= x && xInt <= (x + w)) results.push([ xInt, (this.m * xInt) + this.b ]);\n
+\t\t\n
+\t\t\t// try left face\n
+\t\t\tyInt = (this.m * x) + this.b;\n
+\t\t\tif (yInt >= y && yInt <= (y + h)) results.push([ (yInt - this.b) / this.m, yInt ]);\n
+\n
+\t\t\tif (results.length == 2) {\n
+\t\t\t\tvar midx = (results[0][0] + results[1][0]) / 2, midy = (results[0][1] + results[1][1]) / 2;\n
+\t\t\t\tresults.push([ midx,midy ]);\n
+\t\t\t\t// now calculate the segment inside the rectangle where the midpoint lies.\n
+\t\t\t\tvar xseg = midx <= x + (w / 2) ? -1 : 1,\n
+\t\t\t\t\tyseg = midy <= y + (h / 2) ? -1 : 1;\n
+\t\t\t\tresults.push([xseg, yseg]);\n
+\t\t\t\treturn results;\n
+\t\t\t}\n
+\t\t\n
+\t\t\treturn null;\n
+\n
+\t\t};\n
+\t},\n
+\t_segment = function(x1, y1, x2, y2) {\n
+\t\tif (x1 <= x2 && y2 <= y1) return 1;\n
+\t\telse if (x1 <= x2 && y1 <= y2) return 2;\n
+\t\telse if (x2 <= x1 && y2 >= y1) return 3;\n
+\t\treturn 4;\n
+\t},\n
+\t\t\n
+\t\t// the control point we will use depends on the faces to which each end of the connection is assigned, specifically whether or not the\n
+\t\t// two faces are parallel or perpendicular.  if they are parallel then the control point lies on the midpoint of the axis in which they\n
+\t\t// are parellel and varies only in the other axis; this variation is proportional to the distance that the anchor points lie from the\n
+\t\t// center of that face.  if the two faces are perpendicular then the control point is at some distance from both the midpoints; the amount and\n
+\t\t// direction are dependent on the orientation of the two elements. \'seg\', passed in to this method, tells you which segment the target element\n
+\t\t// lies in with respect to the source: 1 is top right, 2 is bottom right, 3 is bottom left, 4 is top left.\n
+\t\t//\n
+\t\t// sourcePos and targetPos are arrays of info about where on the source and target each anchor is located.  their contents are:\n
+\t\t//\n
+\t\t// 0 - absolute x\n
+\t\t// 1 - absolute y\n
+\t\t// 2 - proportional x in element (0 is left edge, 1 is right edge)\n
+\t\t// 3 - proportional y in element (0 is top edge, 1 is bottom edge)\n
+\t\t// \t\n
+\t_findControlPoint = function(midx, midy, segment, sourceEdge, targetEdge, dx, dy, distance, proximityLimit) {\n
+        // TODO (maybe)\n
+        // - if anchor pos is 0.5, make the control point take into account the relative position of the elements.\n
+        if (distance <= proximityLimit) return [midx, midy];\n
+\n
+        if (segment === 1) {\n
+            if (sourceEdge[3] <= 0 && targetEdge[3] >= 1) return [ midx + (sourceEdge[2] < 0.5 ? -1 * dx : dx), midy ];\n
+            else if (sourceEdge[2] >= 1 && targetEdge[2] <= 0) return [ midx, midy + (sourceEdge[3] < 0.5 ? -1 * dy : dy) ];\n
+            else return [ midx + (-1 * dx) , midy + (-1 * dy) ];\n
+        }\n
+        else if (segment === 2) {\n
+            if (sourceEdge[3] >= 1 && targetEdge[3] <= 0) return [ midx + (sourceEdge[2] < 0.5 ? -1 * dx : dx), midy ];\n
+            else if (sourceEdge[2] >= 1 && targetEdge[2] <= 0) return [ midx, midy + (sourceEdge[3] < 0.5 ? -1 * dy : dy) ];\n
+            else return [ midx + (1 * dx) , midy + (-1 * dy) ];\n
+        }\n
+        else if (segment === 3) {\n
+            if (sourceEdge[3] >= 1 && targetEdge[3] <= 0) return [ midx + (sourceEdge[2] < 0.5 ? -1 * dx : dx), midy ];\n
+            else if (sourceEdge[2] <= 0 && targetEdge[2] >= 1) return [ midx, midy + (sourceEdge[3] < 0.5 ? -1 * dy : dy) ];\n
+            else return [ midx + (-1 * dx) , midy + (-1 * dy) ];\n
+        }\n
+        else if (segment === 4) {\n
+            if (sourceEdge[3] <= 0 && targetEdge[3] >= 1) return [ midx + (sourceEdge[2] < 0.5 ? -1 * dx : dx), midy ];\n
+            else if (sourceEdge[2] <= 0 && targetEdge[2] >= 1) return [ midx, midy + (sourceEdge[3] < 0.5 ? -1 * dy : dy) ];\n
+            else return [ midx + (1 * dx) , midy + (-1 * dy) ];\n
+        }\n
+\n
+\t};\t\n
+\t\n
+\t/**\n
+     * Class: Connectors.StateMachine\n
+     * Provides \'state machine\' connectors.\n
+     */\n
+\t/*\n
+\t * Function: Constructor\n
+\t * \n
+\t * Parameters:\n
+\t * curviness -\tmeasure of how "curvy" the connectors will be.  this is translated as the distance that the\n
+     *                Bezier curve\'s control point is from the midpoint of the straight line connecting the two\n
+     *              endpoints, and does not mean that the connector is this wide.  The Bezier curve never reaches\n
+     *              its control points; they act as gravitational masses. defaults to 10.\n
+\t * margin\t-\tdistance from element to start and end connectors, in pixels.  defaults to 5.\n
+\t * proximityLimit  -   sets the distance beneath which the elements are consider too close together to bother\n
+\t *\t\t\t\t\t\twith fancy curves. by default this is 80 pixels.\n
+\t * loopbackRadius\t-\tthe radius of a loopback connector.  optional; defaults to 25.\n
+\t * showLoopback   -   If set to false this tells the connector that it is ok to paint connections whose source and target is the same element with a connector running through the element. The default value for this is true; the connector always makes a loopback connection loop around the element rather than passing through it.\n
+\t*/\n
+\tvar StateMachine = function(params) {\n
+\t\tparams = params || {};\n
+\t\tthis.type = "StateMachine";\n
+\n
+\t\tvar self = this,\n
+\t\t\t_super =  jsPlumb.Connectors.AbstractConnector.apply(this, arguments),\n
+\t\t\tcurviness = params.curviness || 10,\n
+\t\t\tmargin = params.margin || 5,\n
+\t\t\tproximityLimit = params.proximityLimit || 80,\n
+\t\t\tclockwise = params.orientation && params.orientation === "clockwise",\n
+\t\t\tloopbackRadius = params.loopbackRadius || 25,\n
+\t\t\tshowLoopback = params.showLoopback !== false;\n
+\t\t\n
+\t\tthis._compute = function(paintInfo, params) {\n
+\t\t\tvar w = Math.abs(params.sourcePos[0] - params.targetPos[0]),\n
+\t\t\t\th = Math.abs(params.sourcePos[1] - params.targetPos[1]),\n
+\t\t\t\tx = Math.min(params.sourcePos[0], params.targetPos[0]),\n
+\t\t\t\ty = Math.min(params.sourcePos[1], params.targetPos[1]);\t\t\t\t\n
+\t\t\n
+\t\t\tif (!showLoopback || (params.sourceEndpoint.elementId !== params.targetEndpoint.elementId)) {                            \n
+\t\t\t\tvar _sx = params.sourcePos[0] < params.targetPos[0] ? 0  : w,\n
+\t\t\t\t\t_sy = params.sourcePos[1] < params.targetPos[1] ? 0:h,\n
+\t\t\t\t\t_tx = params.sourcePos[0] < params.targetPos[0] ? w : 0,\n
+\t\t\t\t\t_ty = params.sourcePos[1] < params.targetPos[1] ? h : 0;\n
+            \n
+\t\t\t\t// now adjust for the margin\n
+\t\t\t\tif (params.sourcePos[2] === 0) _sx -= margin;\n
+            \tif (params.sourcePos[2] === 1) _sx += margin;\n
+            \tif (params.sourcePos[3] === 0) _sy -= margin;\n
+            \tif (params.sourcePos[3] === 1) _sy += margin;\n
+            \tif (params.targetPos[2] === 0) _tx -= margin;\n
+            \tif (params.targetPos[2] === 1) _tx += margin;\n
+            \tif (params.targetPos[3] === 0) _ty -= margin;\n
+            \tif (params.targetPos[3] === 1) _ty += margin;\n
+\n
+            \t//\n
+\t            // these connectors are quadratic bezier curves, having a single control point. if both anchors \n
+    \t        // are located at 0.5 on their respective faces, the control point is set to the midpoint and you\n
+        \t    // get a straight line.  this is also the case if the two anchors are within \'proximityLimit\', since\n
+           \t \t// it seems to make good aesthetic sense to do that. outside of that, the control point is positioned \n
+           \t \t// at \'curviness\' pixels away along the normal to the straight line connecting the two anchors.\n
+\t            // \n
+   \t        \t// there may be two improvements to this.  firstly, we might actually support the notion of avoiding nodes\n
+            \t// in the UI, or at least making a good effort at doing so.  if a connection would pass underneath some node,\n
+            \t// for example, we might increase the distance the control point is away from the midpoint in a bid to\n
+            \t// steer it around that node.  this will work within limits, but i think those limits would also be the likely\n
+            \t// limits for, once again, aesthetic good sense in the layout of a chart using these connectors.\n
+            \t//\n
+            \t// the second possible change is actually two possible changes: firstly, it is possible we should gradually\n
+            \t// decrease the \'curviness\' as the distance between the anchors decreases; start tailing it off to 0 at some\n
+            \t// point (which should be configurable).  secondly, we might slightly increase the \'curviness\' for connectors\n
+            \t// with respect to how far their anchor is from the center of its respective face. this could either look cool,\n
+            \t// or stupid, and may indeed work only in a way that is so subtle as to have been a waste of time.\n
+            \t//\n
+\n
+\t\t\t\tvar _midx = (_sx + _tx) / 2, _midy = (_sy + _ty) / 2, \n
+            \t    m2 = (-1 * _midx) / _midy, theta2 = Math.atan(m2),\n
+            \t    dy =  (m2 == Infinity || m2 == -Infinity) ? 0 : Math.abs(curviness / 2 * Math.sin(theta2)),\n
+\t\t\t\t    dx =  (m2 == Infinity || m2 == -Infinity) ? 0 : Math.abs(curviness / 2 * Math.cos(theta2)),\n
+\t\t\t\t    segment = _segment(_sx, _sy, _tx, _ty),\n
+\t\t\t\t    distance = Math.sqrt(Math.pow(_tx - _sx, 2) + Math.pow(_ty - _sy, 2)),\t\t\t\n
+\t            \t// calculate the control point.  this code will be where we\'ll put in a rudimentary element avoidance scheme; it\n
+\t            \t// will work by extending the control point to force the curve to be, um, curvier.\n
+\t\t\t\t\t_controlPoint = _findControlPoint(_midx,\n
+                                                  _midy,\n
+                                                  segment,\n
+                                                  params.sourcePos,\n
+                                                  params.targetPos,\n
+                                                  curviness, curviness,\n
+                                                  distance,\n
+                                                  proximityLimit);\n
+\n
+\t\t\t\t_super.addSegment(this, "Bezier", {\n
+\t\t\t\t\tx1:_tx, y1:_ty, x2:_sx, y2:_sy,\n
+\t\t\t\t\tcp1x:_controlPoint[0], cp1y:_controlPoint[1],\n
+\t\t\t\t\tcp2x:_controlPoint[0], cp2y:_controlPoint[1]\n
+\t\t\t\t});\t\t\t\t\n
+            }\n
+            else {\n
+            \t// a loopback connector.  draw an arc from one anchor to the other.            \t\n
+        \t\tvar x1 = params.sourcePos[0], x2 = params.sourcePos[0], y1 = params.sourcePos[1] - margin, y2 = params.sourcePos[1] - margin, \t\t\t\t\n
+\t\t\t\t\tcx = x1, cy = y1 - loopbackRadius,\t\t\t\t\n
+\t\t\t\t\t// canvas sizing stuff, to ensure the whole painted area is visible.\n
+\t\t\t\t\t_w = 2 * loopbackRadius, \n
+\t\t\t\t\t_h = 2 * loopbackRadius,\n
+\t\t\t\t\t_x = cx - loopbackRadius, \n
+\t\t\t\t\t_y = cy - loopbackRadius;\n
+\n
+\t\t\t\tpaintInfo.points[0] = _x;\n
+\t\t\t\tpaintInfo.points[1] = _y;\n
+\t\t\t\tpaintInfo.points[2] = _w;\n
+\t\t\t\tpaintInfo.points[3] = _h;\n
+\t\t\t\t\n
+\t\t\t\t// ADD AN ARC SEGMENT.\n
+\t\t\t\t_super.addSegment(this, "Arc", {\n
+\t\t\t\t\tloopback:true,\n
+\t\t\t\t\tx1:(x1 - _x) + 4,\n
+\t\t\t\t\ty1:y1 - _y,\n
+\t\t\t\t\tstartAngle:0,\n
+\t\t\t\t\tendAngle: 2 * Math.PI,\n
+\t\t\t\t\tr:loopbackRadius,\n
+\t\t\t\t\tac:!clockwise,\n
+\t\t\t\t\tx2:(x1 - _x) - 4,\n
+\t\t\t\t\ty2:y1 - _y,\n
+\t\t\t\t\tcx:cx - _x,\n
+\t\t\t\t\tcy:cy - _y\n
+\t\t\t\t});\n
+            }                           \n
+        };                        \n
+\t};\n
+\tjsPlumb.registerConnectorType(StateMachine, "StateMachine");\n
+})();\n
+\n
+/*\n
+    \t// a possible rudimentary avoidance scheme, old now, perhaps not useful.\n
+        //      if (avoidSelector) {\n
+\t\t//\t\t    var testLine = new Line(sourcePos[0] + _sx,sourcePos[1] + _sy,sourcePos[0] + _tx,sourcePos[1] + _ty);\n
+\t\t//\t\t    var sel = jsPlumb.getSelector(avoidSelector);\n
+\t\t//\t\t    for (var i = 0; i < sel.length; i++) {\n
+\t\t//\t\t\t    var id = jsPlumb.getId(sel[i]);\n
+\t\t//\t\t\t    if (id != sourceEndpoint.elementId && id != targetEndpoint.elementId) {\n
+\t\t//\t\t\t\t    o = jsPlumb.getOffset(id), s = jsPlumb.getSize(id);\n
+//\n
+//\t\t\t\t\t\t    if (o && s) {\n
+//\t\t\t\t\t\t\t    var collision = testLine.rectIntersect(o.left,o.top,s[0],s[1]);\n
+//\t\t\t\t\t\t\t    if (collision) {\n
+\t\t\t\t\t\t\t\t    // set the control point to be a certain distance from the midpoint of the two points that\n
+\t\t\t\t\t\t\t\t    // the line crosses on the rectangle.\n
+\t\t\t\t\t\t\t\t    // TODO where will this 75 number come from?\n
+\t\t\t\t\t//\t\t\t    _controlX = collision[2][0] + (75 * collision[3][0]);\n
+\t\t\t\t//\t/\t\t\t    _controlY = collision[2][1] + (75 * collision[3][1]);\n
+//\t\t\t\t\t\t\t    }\n
+//\t\t\t\t\t\t    }\n
+\t\t\t\t\t//  }\n
+\t//\t\t\t    }\n
+              //}\n
+    */\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the code for the Bezier connector type.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+;(function() {\n
+\n
+\tvar Bezier = function(params) {\n
+\t\tparams = params || {};\n
+\n
+\t\tvar _super =  jsPlumb.Connectors.AbstractConnector.apply(this, arguments),\n
+\t\t\tstub = params.stub || 50,\n
+\t\t\tmajorAnchor = params.curviness || 150,\n
+\t\t\tminorAnchor = 10;\n
+\n
+\t\tthis.type = "Bezier";\n
+\t\tthis.getCurviness = function() { return majorAnchor; };\n
+\n
+\t\tthis._findControlPoint = function(point, sourceAnchorPosition, targetAnchorPosition, sourceEndpoint, targetEndpoint) {\n
+\t\t\t// determine if the two anchors are perpendicular to each other in their orientation.  we swap the control \n
+\t\t\t// points around if so (code could be tightened up)\n
+\t\t\tvar soo = sourceEndpoint.anchor.getOrientation(sourceEndpoint), \n
+\t\t\t\ttoo = targetEndpoint.anchor.getOrientation(targetEndpoint),\n
+\t\t\t\tperpendicular = soo[0] != too[0] || soo[1] == too[1],\n
+\t\t\t\tp = [];\n
+\n
+\t\t\tif (!perpendicular) {\n
+\t\t\t\tif (soo[0] === 0) // X\n
+\t\t\t\t\tp.push(sourceAnchorPosition[0] < targetAnchorPosition[0] ? point[0] + minorAnchor : point[0] - minorAnchor);\n
+\t\t\t\telse p.push(point[0] - (majorAnchor * soo[0]));\n
+\n
+\t\t\t\tif (soo[1] === 0) // Y\n
+\t\t\t\t\tp.push(sourceAnchorPosition[1] < targetAnchorPosition[1] ? point[1] + minorAnchor : point[1] - minorAnchor);\n
+\t\t\t\telse p.push(point[1] + (majorAnchor * too[1]));\n
+\t\t\t}\n
+\t\t\telse {\n
+\t\t\t\tif (too[0] === 0) // X\n
+\t\t\t\t\tp.push(targetAnchorPosition[0] < sourceAnchorPosition[0] ? point[0] + minorAnchor : point[0] - minorAnchor);\n
+\t\t\t\telse p.push(point[0] + (majorAnchor * too[0]));\n
+\n
+\t\t\t\tif (too[1] === 0) // Y\n
+\t\t\t\t\tp.push(targetAnchorPosition[1] < sourceAnchorPosition[1] ? point[1] + minorAnchor : point[1] - minorAnchor);\n
+\t\t\t\telse p.push(point[1] + (majorAnchor * soo[1]));\n
+\t\t\t}\n
+\n
+\t\t\treturn p;\n
+\t\t};\n
+\n
+\t\tthis._compute = function(paintInfo, p) {\n
+\t\t\tvar sp = p.sourcePos,\n
+\t\t\t\ttp = p.targetPos,\n
+\t\t\t\t_w = Math.abs(sp[0] - tp[0]),\n
+\t\t\t\t_h = Math.abs(sp[1] - tp[1]),\n
+\t\t\t\t_sx = sp[0] < tp[0] ? _w : 0,\n
+\t\t\t\t_sy = sp[1] < tp[1] ? _h : 0,\n
+\t\t\t\t_tx = sp[0] < tp[0] ? 0 : _w,\n
+\t\t\t\t_ty = sp[1] < tp[1] ? 0 : _h,\n
+\t\t\t\t_CP = this._findControlPoint([_sx, _sy], sp, tp, p.sourceEndpoint, p.targetEndpoint),\n
+\t\t\t\t_CP2 = this._findControlPoint([_tx, _ty], tp, sp, p.targetEndpoint, p.sourceEndpoint);\n
+\n
+\t\t\t_super.addSegment(this, "Bezier", {\n
+\t\t\t\tx1:_sx, y1:_sy, x2:_tx, y2:_ty,\n
+\t\t\t\tcp1x:_CP[0], cp1y:_CP[1], cp2x:_CP2[0], cp2y:_CP2[1]\n
+\t\t\t});\n
+\t\t};\n
+\t};\n
+\n
+\tjsPlumbUtil.extend(Bezier, jsPlumb.Connectors.AbstractConnector);\n
+\tjsPlumb.registerConnectorType(Bezier, "Bezier");\n
+\n
+})();\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the SVG renderers.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+;(function() {\n
+\t\n
+// ************************** SVG utility methods ********************************************\t\n
+\n
+\t"use strict";\n
+\t\n
+\tvar svgAttributeMap = {\n
+\t\t"joinstyle":"stroke-linejoin",\n
+\t\t"stroke-linejoin":"stroke-linejoin",\t\t\n
+\t\t"stroke-dashoffset":"stroke-dashoffset",\n
+\t\t"stroke-linecap":"stroke-linecap"\n
+\t},\n
+\tSTROKE_DASHARRAY = "stroke-dasharray",\n
+\tDASHSTYLE = "dashstyle",\n
+\tLINEAR_GRADIENT = "linearGradient",\n
+\tRADIAL_GRADIENT = "radialGradient",\n
+\tDEFS = "defs",\n
+\tFILL = "fill",\n
+\tSTOP = "stop",\n
+\tSTROKE = "stroke",\n
+\tSTROKE_WIDTH = "stroke-width",\n
+\tSTYLE = "style",\n
+\tNONE = "none",\n
+\tJSPLUMB_GRADIENT = "jsplumb_gradient_",\n
+\tLINE_WIDTH = "lineWidth",\n
+\tns = {\n
+\t\tsvg:"http://www.w3.org/2000/svg",\n
+\t\txhtml:"http://www.w3.org/1999/xhtml"\n
+\t},\n
+\t_attr = function(node, attributes) {\n
+\t\tfor (var i in attributes)\n
+\t\t\tnode.setAttribute(i, "" + attributes[i]);\n
+\t},\t\n
+\t_node = function(name, attributes) {\n
+\t\tvar n = document.createElementNS(ns.svg, name);\n
+\t\tattributes = attributes || {};\n
+\t\tattributes.version = "1.1";\n
+\t\tattributes.xmlns = ns.xhtml;\n
+\t\t_attr(n, attributes);\n
+\t\treturn n;\n
+\t},\n
+\t_pos = function(d) { return "position:absolute;left:" + d[0] + "px;top:" + d[1] + "px"; },\t\n
+\t_clearGradient = function(parent) {\n
+\t\tfor (var i = 0; i < parent.childNodes.length; i++) {\n
+\t\t\tif (parent.childNodes[i].tagName == DEFS || parent.childNodes[i].tagName == LINEAR_GRADIENT || parent.childNodes[i].tagName == RADIAL_GRADIENT)\n
+\t\t\t\tparent.removeChild(parent.childNodes[i]);\n
+\t\t}\n
+\t},\t\t\n
+\t_updateGradient = function(parent, node, style, dimensions, uiComponent) {\n
+\t\tvar id = JSPLUMB_GRADIENT + uiComponent._jsPlumb.instance.idstamp();\n
+\t\t// first clear out any existing gradient\n
+\t\t_clearGradient(parent);\n
+\t\t// this checks for an \'offset\' property in the gradient, and in the absence of it, assumes\n
+\t\t// we want a linear gradient. if it\'s there, we create a radial gradient.\n
+\t\t// it is possible that a more explicit means of defining the gradient type would be\n
+\t\t// better. relying on \'offset\' means that we can never have a radial gradient that uses\n
+\t\t// some default offset, for instance.\n
+\t\t// issue 244 suggested the \'gradientUnits\' attribute; without this, straight/flowchart connectors with gradients would\n
+\t\t// not show gradients when the line was perfectly horizontal or vertical.\n
+\t\tvar g;\n
+\t\tif (!style.gradient.offset) {\n
+\t\t\tg = _node(LINEAR_GRADIENT, {id:id, gradientUnits:"userSpaceOnUse"});\n
+\t\t}\n
+\t\telse {\n
+\t\t\tg = _node(RADIAL_GRADIENT, {\n
+\t\t\t\tid:id\n
+\t\t\t});\t\t\t\n
+\t\t}\n
+\t\t\n
+\t\tvar defs = _node(DEFS);\n
+\t\tparent.appendChild(defs);\n
+\t\tdefs.appendChild(g);\n
+\t\t//parent.appendChild(g);\n
+\t\t\n
+\t\t// the svg radial gradient seems to treat stops in the reverse \n
+\t\t// order to how canvas does it.  so we want to keep all the maths the same, but\n
+\t\t// iterate the actual style declarations in reverse order, if the x indexes are not in order.\n
+\t\tfor (var i = 0; i < style.gradient.stops.length; i++) {\n
+\t\t\tvar styleToUse = uiComponent.segment == 1 ||  uiComponent.segment == 2 ? i: style.gradient.stops.length - 1 - i,\t\t\t\n
+\t\t\t\tstopColor = jsPlumbUtil.convertStyle(style.gradient.stops[styleToUse][1], true),\n
+\t\t\t\ts = _node(STOP, {"offset":Math.floor(style.gradient.stops[i][0] * 100) + "%", "stop-color":stopColor});\n
+\n
+\t\t\tg.appendChild(s);\n
+\t\t}\n
+\t\tvar applyGradientTo = style.strokeStyle ? STROKE : FILL;\n
+        //node.setAttribute(STYLE, applyGradientTo + ":url(" + /[^#]+/.exec(document.location.toString()) + "#" + id + ")");\n
+\t\t//node.setAttribute(STYLE, applyGradientTo + ":url(#" + id + ")");\n
+\t\t//node.setAttribute(applyGradientTo,  "url(" + /[^#]+/.exec(document.location.toString()) + "#" + id + ")");\n
+\t\tnode.setAttribute(applyGradientTo,  "url(#" + id + ")");\n
+\t},\n
+\t_applyStyles = function(parent, node, style, dimensions, uiComponent) {\n
+\t\t\n
+\t\tnode.setAttribute(FILL, style.fillStyle ? jsPlumbUtil.convertStyle(style.fillStyle, true) : NONE);\n
+\t\t\tnode.setAttribute(STROKE, style.strokeStyle ? jsPlumbUtil.convertStyle(style.strokeStyle, true) : NONE);\n
+\t\t\t\n
+\t\tif (style.gradient) {\n
+\t\t\t_updateGradient(parent, node, style, dimensions, uiComponent);\t\t\t\n
+\t\t}\n
+\t\telse {\n
+\t\t\t// make sure we clear any existing gradient\n
+\t\t\t_clearGradient(parent);\n
+\t\t\tnode.setAttribute(STYLE, "");\n
+\t\t}\n
+\t\t\n
+\t\t\n
+\t\tif (style.lineWidth) {\n
+\t\t\tnode.setAttribute(STROKE_WIDTH, style.lineWidth);\n
+\t\t}\n
+\t\n
+\t\t// in SVG there is a stroke-dasharray attribute we can set, and its syntax looks like\n
+\t\t// the syntax in VML but is actually kind of nasty: values are given in the pixel\n
+\t\t// coordinate space, whereas in VML they are multiples of the width of the stroked\n
+\t\t// line, which makes a lot more sense.  for that reason, jsPlumb is supporting both\n
+\t\t// the native svg \'stroke-dasharray\' attribute, and also the \'dashstyle\' concept from\n
+\t\t// VML, which will be the preferred method.  the code below this converts a dashstyle\n
+\t\t// attribute given in terms of stroke width into a pixel representation, by using the\n
+\t\t// stroke\'s lineWidth. \n
+\t\tif (style[DASHSTYLE] && style[LINE_WIDTH] && !style[STROKE_DASHARRAY]) {\n
+\t\t\tvar sep = style[DASHSTYLE].indexOf(",") == -1 ? " " : ",",\n
+\t\t\tparts = style[DASHSTYLE].split(sep),\n
+\t\t\tstyleToUse = "";\n
+\t\t\tparts.forEach(function(p) {\n
+\t\t\t\tstyleToUse += (Math.floor(p * style.lineWidth) + sep);\n
+\t\t\t});\n
+\t\t\tnode.setAttribute(STROKE_DASHARRAY, styleToUse);\n
+\t\t}\t\t\n
+\t\telse if(style[STROKE_DASHARRAY]) {\n
+\t\t\tnode.setAttribute(STROKE_DASHARRAY, style[STROKE_DASHARRAY]);\n
+\t\t}\n
+\t\t\n
+\t\t// extra attributes such as join type, dash offset.\n
+\t\tfor (var i in svgAttributeMap) {\n
+\t\t\tif (style[i]) {\n
+\t\t\t\tnode.setAttribute(svgAttributeMap[i], style[i]);\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\t_decodeFont = function(f) {\n
+\t\tvar r = /([0-9].)(p[xt])\\s(.*)/, \n
+\t\t\tbits = f.match(r);\n
+\n
+\t\treturn {size:bits[1] + bits[2], font:bits[3]};\t\t\n
+\t},\n
+\t_appendAtIndex = function(svg, path, idx) {\n
+\t\tif (svg.childNodes.length > idx) {\n
+\t\t\tsvg.insertBefore(path, svg.childNodes[idx]);\n
+\t\t}\n
+\t\telse svg.appendChild(path);\n
+\t};\n
+\t\n
+\t/**\n
+\t\tutility methods for other objects to use.\n
+\t*/\n
+\tjsPlumbUtil.svg = {\n
+\t\tnode:_node,\n
+\t\tattr:_attr,\n
+\t\tpos:_pos\n
+\t};\n
+\t\n
+ // ************************** / SVG utility methods ********************************************\t\n
+\t\n
+\t/*\n
+\t * Base class for SVG components.\n
+\t */\t\n
+\tvar SvgComponent = function(params) {\n
+\t\tvar pointerEventsSpec = params.pointerEventsSpec || "all", renderer = {};\n
+\t\t\t\n
+\t\tjsPlumb.jsPlumbUIComponent.apply(this, params.originalArgs);\n
+\t\tthis.canvas = null;this.path = null;this.svg = null; this.bgCanvas = null;\n
+\t\n
+\t\tvar clazz = params.cssClass + " " + (params.originalArgs[0].cssClass || ""),\t\t\n
+\t\t\tsvgParams = {\n
+\t\t\t\t"style":"",\n
+\t\t\t\t"width":0,\n
+\t\t\t\t"height":0,\n
+\t\t\t\t"pointer-events":pointerEventsSpec,\n
+\t\t\t\t"position":"absolute"\n
+\t\t\t};\t\t\t\t\n
+\t\t\n
+\t\tthis.svg = _node("svg", svgParams);\n
+\t\t\n
+\t\tif (params.useDivWrapper) {\n
+\t\t\tthis.canvas = document.createElement("div");\n
+\t\t\tthis.canvas.style.position = "absolute";\n
+\t\t\tjsPlumbUtil.sizeElement(this.canvas,0,0,1,1);\n
+\t\t\tthis.canvas.className = clazz;\n
+\t\t}\n
+\t\telse {\n
+\t\t\t_attr(this.svg, { "class":clazz });\n
+\t\t\tthis.canvas = this.svg;\n
+\t\t}\n
+\t\t\t\n
+\t\tparams._jsPlumb.appendElement(this.canvas, params.originalArgs[0].parent);\n
+\t\tif (params.useDivWrapper) this.canvas.appendChild(this.svg);\n
+\t\t\n
+\t\t// TODO this displayElement stuff is common between all components, across all\n
+\t\t// renderers.  would be best moved to jsPlumbUIComponent.\n
+\t\tvar displayElements = [ this.canvas ];\n
+\t\tthis.getDisplayElements = function() { \n
+\t\t\treturn displayElements; \n
+\t\t};\n
+\t\t\n
+\t\tthis.appendDisplayElement = function(el) {\n
+\t\t\tdisplayElements.push(el);\n
+\t\t};\t\n
+\t\t\n
+\t\tthis.paint = function(style, anchor, extents) {\t   \t\t\t\n
+\t\t\tif (style != null) {\n
+\t\t\t\t\n
+\t\t\t\tvar xy = [ this.x, this.y ], wh = [ this.w, this.h ], p;\n
+\t\t\t\tif (extents != null) {\n
+\t\t\t\t\tif (extents.xmin < 0) xy[0] += extents.xmin;\n
+\t\t\t\t\tif (extents.ymin < 0) xy[1] += extents.ymin;\n
+\t\t\t\t\twh[0] = extents.xmax + ((extents.xmin < 0) ? -extents.xmin : 0);\n
+\t\t\t\t\twh[1] = extents.ymax + ((extents.ymin < 0) ? -extents.ymin : 0);\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif (params.useDivWrapper) {\t\t\t\t\t\n
+\t\t\t\t\tjsPlumbUtil.sizeElement(this.canvas, xy[0], xy[1], wh[0], wh[1]);\n
+\t\t\t\t\txy[0] = 0; xy[1] = 0;\n
+\t\t\t\t\tp = _pos([ 0, 0 ]);\n
+\t\t\t\t}\n
+\t\t\t\telse\n
+\t\t\t\t\tp = _pos([ xy[0], xy[1] ]);\n
+                \n
+                renderer.paint.apply(this, arguments);\t\t    \t\t\t    \t\n
+                \n
+\t\t    \t_attr(this.svg, {\n
+\t    \t\t\t"style":p,\n
+\t    \t\t\t"width": wh[0],\n
+\t    \t\t\t"height": wh[1]\n
+\t    \t\t});\t\t    \t\t    \t\t    \t\n
+\t\t\t}\n
+\t    };\n
+\t\t\n
+\t\treturn {\n
+\t\t\trenderer:renderer\n
+\t\t};\n
+\t};\n
+\t\n
+\tjsPlumbUtil.extend(SvgComponent, jsPlumb.jsPlumbUIComponent, {\n
+\t\tcleanup:function() {\n
+\t\t\tif (this.canvas && this.canvas.parentNode) this.canvas.parentNode.removeChild(this.canvas);\n
+\t\t\tthis.svg = null;\n
+\t\t\tthis.canvas = null;\n
+\t\t\tthis.bgCanvas = null;\n
+\t\t\tthis.path = null;\t\t\t\n
+\t\t\tthis.group = null;\n
+\t\t},\n
+\t\tsetVisible:function(v) {\n
+\t\t\tif (this.canvas) {\n
+\t\t\t\tthis.canvas.style.display = v ? "block" : "none";\n
+\t\t\t}\n
+\t\t\tif (this.bgCanvas) {\n
+\t\t\t\tthis.bgCanvas.style.display = v ? "block" : "none";\n
+\t\t\t}\n
+\t\t}\n
+\t});\n
+\t\n
+\t/*\n
+\t * Base class for SVG connectors.\n
+\t */ \n
+\tvar SvgConnector = jsPlumb.ConnectorRenderers.svg = function(params) {\n
+\t\tvar self = this,\n
+\t\t\t_super = SvgComponent.apply(this, [ { \n
+\t\t\t\tcssClass:params._jsPlumb.connectorClass, \n
+\t\t\t\toriginalArgs:arguments, \n
+\t\t\t\tpointerEventsSpec:"none", \n
+\t\t\t\t_jsPlumb:params._jsPlumb\n
+\t\t\t} ]);\t\n
+\n
+\t\t/*this.pointOnPath = function(location, absolute) {\n
+\t\t\tif (!self.path) return [0,0];\n
+\t\t\tvar p = absolute ? location : location * self.path.getTotalLength();\n
+\t\t\treturn self.path.getPointAtLength(p);\n
+\t\t};*/\t\t\t\n
+\n
+\t\t_super.renderer.paint = function(style, anchor, extents) {\n
+\t\t\t\n
+\t\t\tvar segments = self.getSegments(), p = "", offset = [0,0];\t\t\t\n
+\t\t\tif (extents.xmin < 0) offset[0] = -extents.xmin;\n
+\t\t\tif (extents.ymin < 0) offset[1] = -extents.ymin;\t\t\t\n
+\n
+\t\t\tif (segments.length > 0) {\n
+\t\t\t\n
+\t\t\t\t// create path from segments.\t\n
+\t\t\t\tfor (var i = 0; i < segments.length; i++) {\n
+\t\t\t\t\tp += jsPlumb.Segments.svg.SegmentRenderer.getPath(segments[i]);\n
+\t\t\t\t\tp += " ";\n
+\t\t\t\t}\t\t\t\n
+\t\t\t\t\n
+\t\t\t\tvar a = { \n
+\t\t\t\t\t\td:p,\n
+\t\t\t\t\t\ttransform:"translate(" + offset[0] + "," + offset[1] + ")",\n
+\t\t\t\t\t\t"pointer-events":params["pointer-events"] || "visibleStroke"\n
+\t\t\t\t\t}, \n
+\t                outlineStyle = null,\n
+\t                d = [self.x,self.y,self.w,self.h];\n
+\t\t\t\t\t\n
+\t\t\t\tvar mouseInOutFilters = {\n
+\t\t\t\t\t"mouseenter":function(e) {\n
+\t\t\t\t\t\tvar rt = e.relatedTarget;\n
+\t\t\t\t\t\treturn rt == null || (rt != self.path && rt != self.bgPath);\n
+\t\t\t\t\t},\n
+\t\t\t\t\t"mouseout":function(e) {\n
+\t\t\t\t\t\tvar rt = e.relatedTarget;\n
+\t\t\t\t\t\treturn rt == null || (rt != self.path && rt != self.bgPath);\n
+\t\t\t\t\t}\n
+\t\t\t\t};\n
+\t\t\t\t\n
+\t\t\t\t// outline style.  actually means drawing an svg object underneath the main one.\n
+\t\t\t\tif (style.outlineColor) {\n
+\t\t\t\t\tvar outlineWidth = style.outlineWidth || 1,\n
+\t\t\t\t\t\toutlineStrokeWidth = style.lineWidth + (2 * outlineWidth);\n
+\t\t\t\t\toutlineStyle = jsPlumb.extend({}, style);\n
+\t\t\t\t\toutlineStyle.strokeStyle = jsPlumbUtil.convertStyle(style.outlineColor);\n
+\t\t\t\t\toutlineStyle.lineWidth = outlineStrokeWidth;\n
+\t\t\t\t\t\n
+\t\t\t\t\tif (self.bgPath == null) {\n
+\t\t\t\t\t\tself.bgPath = _node("path", a);\n
+\t\t\t\t    \t_appendAtIndex(self.svg, self.bgPath, 0);\n
+\t\t\t    \t\tself.attachListeners(self.bgPath, self, mouseInOutFilters);\n
+\t\t\t\t\t}\n
+\t\t\t\t\telse {\n
+\t\t\t\t\t\t_attr(self.bgPath, a);\n
+\t\t\t\t\t}\n
+\t\t\t\t\t\n
+\t\t\t\t\t_applyStyles(self.svg, self.bgPath, outlineStyle, d, self);\n
+\t\t\t\t}\t\t\t\n
+\t\t\t\t\n
+\t\t    \tif (self.path == null) {\n
+\t\t\t    \tself.path = _node("path", a);\n
+\t\t\t\t\t_appendAtIndex(self.svg, self.path, style.outlineColor ? 1 : 0);\n
+\t\t\t    \tself.attachListeners(self.path, self, mouseInOutFilters);\t    \t\t    \t\t\n
+\t\t    \t}\n
+\t\t    \telse {\n
+\t\t    \t\t_attr(self.path, a);\n
+\t\t    \t}\n
+\t\t    \t\t    \t\n
+\t\t    \t_applyStyles(self.svg, self.path, style, d, self);\n
+\t\t    }\n
+\t\t};\n
+\t\t\n
+\t\tthis.reattachListeners = function() {\n
+\t\t\tif (this.bgPath) this.reattachListenersForElement(this.bgPath, this);\n
+\t\t\tif (this.path) this.reattachListenersForElement(this.path, this);\n
+\t\t};\n
+\t};\n
+\tjsPlumbUtil.extend(jsPlumb.ConnectorRenderers.svg, SvgComponent);\n
+\n
+// ******************************* svg segment renderer *****************************************************\t\n
+\t\t\n
+\tjsPlumb.Segments.svg = {\n
+\t\tSegmentRenderer : {\t\t\n
+\t\t\tgetPath : function(segment) {\n
+\t\t\t\treturn ({\n
+\t\t\t\t\t"Straight":function() {\n
+\t\t\t\t\t\tvar d = segment.getCoordinates();\n
+\t\t\t\t\t\treturn "M " + d.x1 + " " + d.y1 + " L " + d.x2 + " " + d.y2;\t\n
+\t\t\t\t\t},\n
+\t\t\t\t\t"Bezier":function() {\n
+\t\t\t\t\t\tvar d = segment.params;\n
+\t\t\t\t\t\treturn "M " + d.x1 + " " + d.y1 + \n
+\t\t\t\t\t\t\t" C " + d.cp1x + " " + d.cp1y + " " + d.cp2x + " " + d.cp2y + " " + d.x2 + " " + d.y2;\t\t\t\n
+\t\t\t\t\t},\n
+\t\t\t\t\t"Arc":function() {\n
+\t\t\t\t\t\tvar d = segment.params,\n
+\t\t\t\t\t\t\tlaf = segment.sweep > Math.PI ? 1 : 0,\n
+\t\t\t\t\t\t\tsf = segment.anticlockwise ? 0 : 1;\t\t\t\n
+\n
+\t\t\t\t\t\treturn "M" + segment.x1 + " " + segment.y1 + " A " + segment.radius + " " + d.r + " 0 " + laf + "," + sf + " " + segment.x2 + " " + segment.y2;\n
+\t\t\t\t\t}\n
+\t\t\t\t})[segment.type]();\t\n
+\t\t\t}\n
+\t\t}\n
+\t};\n
+\t\n
+// ******************************* /svg segments *****************************************************\n
+   \n
+    /*\n
+\t * Base class for SVG endpoints.\n
+\t */\n
+\tvar SvgEndpoint = window.SvgEndpoint = function(params) {\n
+\t\tvar _super = SvgComponent.apply(this, [ {\n
+\t\t\t\tcssClass:params._jsPlumb.endpointClass, \n
+\t\t\t\toriginalArgs:arguments, \n
+\t\t\t\tpointerEventsSpec:"all",\n
+\t\t\t\tuseDivWrapper:true,\n
+\t\t\t\t_jsPlumb:params._jsPlumb\n
+\t\t\t} ]);\n
+\t\t\t\n
+\t\t_super.renderer.paint = function(style) {\n
+\t\t\tvar s = jsPlumb.extend({}, style);\n
+\t\t\tif (s.outlineColor) {\n
+\t\t\t\ts.strokeWidth = s.outlineWidth;\n
+\t\t\t\ts.strokeStyle = jsPlumbUtil.convertStyle(s.outlineColor, true);\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\tif (this.node == null) {\n
+\t\t\t\tthis.node = this.makeNode(s);\n
+\t\t\t\tthis.svg.appendChild(this.node);\n
+\t\t\t\tthis.attachListeners(this.node, this);\n
+\t\t\t}\n
+\t\t\telse if (this.updateNode != null) {\n
+\t\t\t\tthis.updateNode(this.node);\n
+\t\t\t}\n
+\t\t\t_applyStyles(this.svg, this.node, s, [ this.x, this.y, this.w, this.h ], this);\n
+\t\t\t_pos(this.node, [ this.x, this.y ]);\n
+\t\t}.bind(this);\n
+\t\t\t\t\n
+\t};\n
+\tjsPlumbUtil.extend(SvgEndpoint, SvgComponent, {\n
+\t\treattachListeners : function() {\n
+\t\t\tif (this.node) this.reattachListenersForElement(this.node, this);\n
+\t\t}\n
+\t});\n
+\t\n
+\t/*\n
+\t * SVG Dot Endpoint\n
+\t */\n
+\tjsPlumb.Endpoints.svg.Dot = function() {\n
+\t\tjsPlumb.Endpoints.Dot.apply(this, arguments);\n
+\t\tSvgEndpoint.apply(this, arguments);\t\t\n
+\t\tthis.makeNode = function(style) { \n
+\t\t\treturn _node("circle", {\n
+                "cx"\t:\tthis.w / 2,\n
+                "cy"\t:\tthis.h / 2,\n
+                "r"\t\t:\tthis.radius\n
+            });\t\t\t\n
+\t\t};\n
+\t\tthis.updateNode = function(node) {\n
+\t\t\t_attr(node, {\n
+\t\t\t\t"cx":this.w / 2,\n
+\t\t\t\t"cy":this.h  / 2,\n
+\t\t\t\t"r":this.radius\n
+\t\t\t});\n
+\t\t};\n
+\t};\n
+\tjsPlumbUtil.extend(jsPlumb.Endpoints.svg.Dot, [jsPlumb.Endpoints.Dot, SvgEndpoint]);\n
+\t\n
+\t/*\n
+\t * SVG Rectangle Endpoint \n
+\t */\n
+\tjsPlumb.Endpoints.svg.Rectangle = function() {\n
+\t\tjsPlumb.Endpoints.Rectangle.apply(this, arguments);\n
+\t\tSvgEndpoint.apply(this, arguments);\t\t\n
+\t\tthis.makeNode = function(style) {\n
+\t\t\treturn _node("rect", {\n
+\t\t\t\t"width"     :   this.w,\n
+\t\t\t\t"height"    :   this.h\n
+\t\t\t});\n
+\t\t};\n
+\t\tthis.updateNode = function(node) {\n
+\t\t\t_attr(node, {\n
+\t\t\t\t"width":this.w,\n
+\t\t\t\t"height":this.h\n
+\t\t\t});\n
+\t\t};\t\t\t\n
+\t};\t\t\n
+\tjsPlumbUtil.extend(jsPlumb.Endpoints.svg.Rectangle, [jsPlumb.Endpoints.Rectangle, SvgEndpoint]);\n
+\t\n
+\t/*\n
+\t * SVG Image Endpoint is the default image endpoint.\n
+\t */\n
+\tjsPlumb.Endpoints.svg.Image = jsPlumb.Endpoints.Image;\n
+\t/*\n
+\t * Blank endpoint in svg renderer is the default Blank endpoint.\n
+\t */\n
+\tjsPlumb.Endpoints.svg.Blank = jsPlumb.Endpoints.Blank;\t\n
+\t/*\n
+\t * Label overlay in svg renderer is the default Label overlay.\n
+\t */\n
+\tjsPlumb.Overlays.svg.Label = jsPlumb.Overlays.Label;\n
+\t/*\n
+\t * Custom overlay in svg renderer is the default Custom overlay.\n
+\t */\n
+\tjsPlumb.Overlays.svg.Custom = jsPlumb.Overlays.Custom;\n
+\t\t\n
+\tvar AbstractSvgArrowOverlay = function(superclass, originalArgs) {\n
+    \tsuperclass.apply(this, originalArgs);\n
+    \tjsPlumb.jsPlumbUIComponent.apply(this, originalArgs);\n
+        this.isAppendedAtTopLevel = false;\n
+    \tvar self = this;\n
+    \tthis.path = null;\n
+    \tthis.paint = function(params, containerExtents) {\n
+    \t\t// only draws on connections, not endpoints.\n
+    \t\tif (params.component.svg && containerExtents) {\n
+\t    \t\tif (this.path == null) {\n
+\t    \t\t\tthis.path = _node("path", {\n
+\t    \t\t\t\t"pointer-events":"all"\t\n
+\t    \t\t\t});\n
+\t    \t\t\tparams.component.svg.appendChild(this.path);\n
+\t    \t\t\t\n
+\t    \t\t\tthis.canvas = params.component.svg; // for the sake of completeness; this behaves the same as other overlays\n
+\t    \t\t\tthis.attachListeners(this.path, params.component);\n
+\t    \t\t\tthis.attachListeners(this.path, this);\n
+\t    \t\t}\n
+\t    \t\tvar clazz = originalArgs && (originalArgs.length == 1) ? (originalArgs[0].cssClass || "") : "",\n
+\t    \t\t\toffset = [0,0];\n
+\n
+\t    \t\tif (containerExtents.xmin < 0) offset[0] = -containerExtents.xmin;\n
+\t    \t\tif (containerExtents.ymin < 0) offset[1] = -containerExtents.ymin;\n
+\t    \t\t\n
+\t    \t\t_attr(this.path, { \n
+\t    \t\t\t"d"\t\t\t:\tmakePath(params.d),\n
+\t    \t\t\t"class" \t:\tclazz,\n
+\t    \t\t\tstroke \t\t: \tparams.strokeStyle ? params.strokeStyle : null,\n
+\t    \t\t\tfill \t\t: \tparams.fillStyle ? params.fillStyle : null,\n
+\t    \t\t\ttransform\t: \t"translate(" + offset[0] + "," + offset[1] + ")"\n
+\t    \t\t});    \t\t\n
+\t    \t}\n
+    \t};\n
+    \tvar makePath = function(d) {\n
+    \t\treturn "M" + d.hxy.x + "," + d.hxy.y +\n
+    \t\t\t\t" L" + d.tail[0].x + "," + d.tail[0].y + \n
+    \t\t\t\t" L" + d.cxy.x + "," + d.cxy.y + \n
+    \t\t\t\t" L" + d.tail[1].x + "," + d.tail[1].y + \n
+    \t\t\t\t" L" + d.hxy.x + "," + d.hxy.y;\n
+    \t};\n
+    \tthis.reattachListeners = function() {\n
+\t\t\tif (this.path) this.reattachListenersForElement(this.path, this);\n
+\t\t};\t\t\n
+    };\n
+    jsPlumbUtil.extend(AbstractSvgArrowOverlay, [jsPlumb.jsPlumbUIComponent, jsPlumb.Overlays.AbstractOverlay], {\n
+    \tcleanup : function() {\n
+    \t\tif (this.path != null) this._jsPlumb.instance.removeElement(this.path);\n
+    \t},\n
+    \tsetVisible:function(v) {\n
+    \t\tif(this.path != null) (this.path.style.display = (v ? "block" : "none"));\n
+    \t}\n
+    });\n
+    \n
+    jsPlumb.Overlays.svg.Arrow = function() {\n
+    \tAbstractSvgArrowOverlay.apply(this, [jsPlumb.Overlays.Arrow, arguments]);    \t\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.svg.Arrow, [ jsPlumb.Overlays.Arrow, AbstractSvgArrowOverlay ]);\n
+    \n
+    jsPlumb.Overlays.svg.PlainArrow = function() {\n
+    \tAbstractSvgArrowOverlay.apply(this, [jsPlumb.Overlays.PlainArrow, arguments]);    \t\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.svg.PlainArrow, [ jsPlumb.Overlays.PlainArrow, AbstractSvgArrowOverlay ]);\n
+    \n
+    jsPlumb.Overlays.svg.Diamond = function() {\n
+    \tAbstractSvgArrowOverlay.apply(this, [jsPlumb.Overlays.Diamond, arguments]);    \t\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.svg.Diamond, [ jsPlumb.Overlays.Diamond, AbstractSvgArrowOverlay ]);\n
+\n
+    // a test\n
+    jsPlumb.Overlays.svg.GuideLines = function() {\n
+        var path = null, self = this, p1_1, p1_2;        \n
+        jsPlumb.Overlays.GuideLines.apply(this, arguments);\n
+        this.paint = function(params, containerExtents) {\n
+    \t\tif (path == null) {\n
+    \t\t\tpath = _node("path");\n
+    \t\t\tparams.connector.svg.appendChild(path);\n
+    \t\t\tself.attachListeners(path, params.connector);\n
+    \t\t\tself.attachListeners(path, self);\n
+\n
+                p1_1 = _node("path");\n
+    \t\t\tparams.connector.svg.appendChild(p1_1);\n
+    \t\t\tself.attachListeners(p1_1, params.connector);\n
+    \t\t\tself.attachListeners(p1_1, self);\n
+\n
+                p1_2 = _node("path");\n
+    \t\t\tparams.connector.svg.appendChild(p1_2);\n
+    \t\t\tself.attachListeners(p1_2, params.connector);\n
+    \t\t\tself.attachListeners(p1_2, self);\n
+    \t\t}\n
+\n
+    \t\tvar offset =[0,0];\n
+    \t\tif (containerExtents.xmin < 0) offset[0] = -containerExtents.xmin;\n
+    \t\tif (containerExtents.ymin < 0) offset[1] = -containerExtents.ymin;\n
+\n
+    \t\t_attr(path, {\n
+    \t\t\t"d"\t\t:\tmakePath(params.head, params.tail),\n
+    \t\t\tstroke \t: \t"red",\n
+    \t\t\tfill \t: \tnull,\n
+    \t\t\ttransform:"translate(" + offset[0] + "," + offset[1] + ")"\n
+    \t\t});\n
+\n
+            _attr(p1_1, {\n
+    \t\t\t"d"\t\t:\tmakePath(params.tailLine[0], params.tailLine[1]),\n
+    \t\t\tstroke \t: \t"blue",\n
+    \t\t\tfill \t: \tnull,\n
+    \t\t\ttransform:"translate(" + offset[0] + "," + offset[1] + ")"\n
+    \t\t});\n
+\n
+            _attr(p1_2, {\n
+    \t\t\t"d"\t\t:\tmakePath(params.headLine[0], params.headLine[1]),\n
+    \t\t\tstroke \t: \t"green",\n
+    \t\t\tfill \t: \tnull,\n
+    \t\t\ttransform:"translate(" + offset[0] + "," + offset[1] + ")"\n
+    \t\t});\n
+    \t};\n
+\n
+        var makePath = function(d1, d2) {\n
+            return "M " + d1.x + "," + d1.y +\n
+                   " L" + d2.x + "," + d2.y;\n
+        };        \n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.svg.GuideLines, jsPlumb.Overlays.GuideLines);\n
+})();\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the VML renderers.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */\n
+\n
+;(function() {\n
+\t\n
+\t"use strict";\n
+\t\n
+\t// http://ajaxian.com/archives/the-vml-changes-in-ie-8\n
+\t// http://www.nczonline.net/blog/2010/01/19/internet-explorer-8-document-and-browser-modes/\n
+\t// http://www.louisremi.com/2009/03/30/changes-in-vml-for-ie8-or-what-feature-can-the-ie-dev-team-break-for-you-today/\n
+\t\n
+\tvar vmlAttributeMap = {\n
+\t\t"stroke-linejoin":"joinstyle",\n
+\t\t"joinstyle":"joinstyle",\t\t\n
+\t\t"endcap":"endcap",\n
+\t\t"miterlimit":"miterlimit"\n
+\t},\n
+\tjsPlumbStylesheet = null;\n
+\t\n
+\tif (document.createStyleSheet && document.namespaces) {\t\t\t\n
+\t\t\n
+\t\tvar ruleClasses = [\n
+\t\t\t\t".jsplumb_vml", "jsplumb\\\\:textbox", "jsplumb\\\\:oval", "jsplumb\\\\:rect", \n
+\t\t\t\t"jsplumb\\\\:stroke", "jsplumb\\\\:shape", "jsplumb\\\\:group"\n
+\t\t\t],\n
+\t\t\trule = "behavior:url(#default#VML);position:absolute;";\n
+\n
+\t\tjsPlumbStylesheet = document.createStyleSheet();\n
+\n
+\t\tfor (var i = 0; i < ruleClasses.length; i++)\n
+\t\t\tjsPlumbStylesheet.addRule(ruleClasses[i], rule);\n
+\n
+\t\t// in this page it is also mentioned that IE requires the extra arg to the namespace\n
+\t\t// http://www.louisremi.com/2009/03/30/changes-in-vml-for-ie8-or-what-feature-can-the-ie-dev-team-break-for-you-today/\n
+\t\t// but someone commented saying they didn\'t need it, and it seems jsPlumb doesnt need it either.\n
+\t\t// var iev = document.documentMode;\n
+\t\t//if (!iev || iev < 8)\n
+\t\t\tdocument.namespaces.add("jsplumb", "urn:schemas-microsoft-com:vml");\n
+\t\t//else\n
+\t\t//\tdocument.namespaces.add("jsplumb", "urn:schemas-microsoft-com:vml", "#default#VML");\n
+\t}\n
+\t\n
+\tjsPlumb.vml = {};\n
+\t\n
+\tvar scale = 1000,\n
+    \n
+\t_atts = function(o, atts) {\n
+\t\tfor (var i in atts) { \n
+\t\t\t// IE8 fix: setattribute does not work after an element has been added to the dom!\n
+\t\t\t// http://www.louisremi.com/2009/03/30/changes-in-vml-for-ie8-or-what-feature-can-the-ie-dev-team-break-for-you-today/\n
+\t\t\t//o.setAttribute(i, atts[i]);\n
+\n
+\t\t\t/*There is an additional problem when accessing VML elements by using get/setAttribute. The simple solution is following:\n
+\n
+\t\t\tif (document.documentMode==8) {\n
+\t\t\tele.opacity=1;\n
+\t\t\t} else {\n
+\t\t\tele.setAttribute(‘opacity’,1);\n
+\t\t\t}\n
+\t\t\t*/\n
+\n
+\t\t\to[i] = atts[i];\n
+\t\t}\n
+\t},\n
+\t_node = function(name, d, atts, parent, _jsPlumb, deferToJsPlumbContainer) {\n
+\t\tatts = atts || {};\n
+\t\tvar o = document.createElement("jsplumb:" + name);\n
+\t\tif (deferToJsPlumbContainer)\n
+\t\t\t_jsPlumb.appendElement(o, parent);\n
+\t\telse\n
+\t\t\t// TODO is this failing? that would be because parent is not a plain DOM element.\n
+\t\t\t// IF SO, uncomment the line below this one and remove this one.\n
+\t\t\tparent.appendChild(o);\n
+\t\t\t//jsPlumb.getDOMElement(parent).appendChild(o);\n
+\t\t\t\n
+\t\to.className = (atts["class"] ? atts["class"] + " " : "") + "jsplumb_vml";\n
+\t\t_pos(o, d);\n
+\t\t_atts(o, atts);\n
+\t\treturn o;\n
+\t},\n
+\t_pos = function(o,d, zIndex) {\n
+\t\to.style.left = d[0] + "px";\t\t\n
+\t\to.style.top =  d[1] + "px";\n
+\t\to.style.width= d[2] + "px";\n
+\t\to.style.height= d[3] + "px";\n
+\t\to.style.position = "absolute";\n
+\t\tif (zIndex)\n
+\t\t\to.style.zIndex = zIndex;\n
+\t},\n
+\t_conv = jsPlumb.vml.convertValue = function(v) {\n
+\t\treturn Math.floor(v * scale);\n
+\t},\t\n
+\t// tests if the given style is "transparent" and then sets the appropriate opacity node to 0 if so,\n
+\t// or 1 if not.  TODO in the future, support variable opacity.\n
+\t_maybeSetOpacity = function(styleToWrite, styleToCheck, type, component) {\n
+\t\tif ("transparent" === styleToCheck)\n
+\t\t\tcomponent.setOpacity(type, "0.0");\n
+\t\telse\n
+\t\t\tcomponent.setOpacity(type, "1.0");\n
+\t},\n
+\t_applyStyles = function(node, style, component, _jsPlumb) {\n
+\t\tvar styleToWrite = {};\n
+\t\tif (style.strokeStyle) {\n
+\t\t\tstyleToWrite.stroked = "true";\n
+\t\t\tvar strokeColor = jsPlumbUtil.convertStyle(style.strokeStyle, true);\n
+\t\t\tstyleToWrite.strokecolor = strokeColor;\n
+\t\t\t_maybeSetOpacity(styleToWrite, strokeColor, "stroke", component);\n
+\t\t\tstyleToWrite.strokeweight = style.lineWidth + "px";\n
+\t\t}\n
+\t\telse styleToWrite.stroked = "false";\n
+\t\t\n
+\t\tif (style.fillStyle) {\n
+\t\t\tstyleToWrite.filled = "true";\n
+\t\t\tvar fillColor = jsPlumbUtil.convertStyle(style.fillStyle, true);\n
+\t\t\tstyleToWrite.fillcolor = fillColor;\n
+\t\t\t_maybeSetOpacity(styleToWrite, fillColor, "fill", component);\n
+\t\t}\n
+\t\telse styleToWrite.filled = "false";\n
+\t\t\n
+\t\tif(style.dashstyle) {\n
+\t\t\tif (component.strokeNode == null) {\n
+\t\t\t\tcomponent.strokeNode = _node("stroke", [0,0,0,0], { dashstyle:style.dashstyle }, node, _jsPlumb);\t\t\t\t\n
+\t\t\t}\n
+\t\t\telse\n
+\t\t\t\tcomponent.strokeNode.dashstyle = style.dashstyle;\n
+\t\t}\t\t\t\t\t\n
+\t\telse if (style["stroke-dasharray"] && style.lineWidth) {\n
+\t\t\tvar sep = style["stroke-dasharray"].indexOf(",") == -1 ? " " : ",",\n
+\t\t\tparts = style["stroke-dasharray"].split(sep),\n
+\t\t\tstyleToUse = "";\n
+\t\t\tfor(var i = 0; i < parts.length; i++) {\n
+\t\t\t\tstyleToUse += (Math.floor(parts[i] / style.lineWidth) + sep);\n
+\t\t\t}\n
+\t\t\tif (component.strokeNode == null) {\n
+\t\t\t\tcomponent.strokeNode = _node("stroke", [0,0,0,0], { dashstyle:styleToUse }, node, _jsPlumb);\t\t\t\t\n
+\t\t\t}\n
+\t\t\telse\n
+\t\t\t\tcomponent.strokeNode.dashstyle = styleToUse;\n
+\t\t}\n
+\t\t\n
+\t\t_atts(node, styleToWrite);\n
+\t},\n
+\t/*\n
+\t * Base class for Vml endpoints and connectors. Extends jsPlumbUIComponent. \n
+\t */\n
+\tVmlComponent = function() {\t\t\t\t\n
+\t\tvar self = this, renderer = {};\n
+\t\tjsPlumb.jsPlumbUIComponent.apply(this, arguments);\t\n
+\n
+\t\tthis.opacityNodes = {\n
+\t\t\t"stroke":null,\n
+\t\t\t"fill":null\n
+\t\t};\n
+\t\tthis.initOpacityNodes = function(vml) {\n
+\t\t\tself.opacityNodes.stroke = _node("stroke", [0,0,1,1], {opacity:"0.0"}, vml, self._jsPlumb.instance);\n
+\t\t\tself.opacityNodes.fill = _node("fill", [0,0,1,1], {opacity:"0.0"}, vml, self._jsPlumb.instance);\t\t\t\t\t\t\t\n
+\t\t};\n
+\t\tthis.setOpacity = function(type, value) {\n
+\t\t\tvar node = self.opacityNodes[type];\n
+\t\t\tif (node) node.opacity = "" + value;\n
+\t\t};\n
+\t\tvar displayElements = [ ];\n
+\t\tthis.getDisplayElements = function() { \n
+\t\t\treturn displayElements; \n
+\t\t};\n
+\t\t\n
+\t\tthis.appendDisplayElement = function(el, doNotAppendToCanvas) {\n
+\t\t\tif (!doNotAppendToCanvas) self.canvas.parentNode.appendChild(el);\n
+\t\t\tdisplayElements.push(el);\n
+\t\t};\n
+\t};\n
+\tjsPlumbUtil.extend(VmlComponent, jsPlumb.jsPlumbUIComponent, {\n
+\t\tcleanup:function() {\t\t\t\n
+\t\t\tif (this.bgCanvas) this.bgCanvas.parentNode.removeChild(this.bgCanvas);\n
+\t\t\tif (this.canvas) this.canvas.parentNode.removeChild(this.canvas);\n
+\t\t}\n
+\t});\n
+\n
+\t/*\n
+\t * Base class for Vml connectors. extends VmlComponent.\n
+\t */\n
+\tvar VmlConnector = jsPlumb.ConnectorRenderers.vml = function(params) {\t\t\n
+\t\tthis.strokeNode = null;\n
+\t\tthis.canvas = null;\n
+\t\tVmlComponent.apply(this, arguments);\n
+\t\tvar clazz = this._jsPlumb.instance.connectorClass + (params.cssClass ? (" " + params.cssClass) : "");\n
+\t\tthis.paint = function(style) {\t\t\n
+\t\t\tif (style !== null) {\t\t\t\n
+\n
+\t\t\t\t// we need to be at least 1 pixel in each direction, because otherwise coordsize gets set to\n
+\t\t\t\t// 0 and overlays cannot paint.\n
+\t\t\t\tthis.w = Math.max(this.w, 1);\n
+\t\t\t\tthis.h = Math.max(this.h, 1);\n
+\n
+\t\t\t\tvar segments = this.getSegments(), p = { "path":"" },\n
+                    d = [this.x, this.y, this.w, this.h];\n
+\t\t\t\t\n
+\t\t\t\t// create path from segments.\t\n
+\t\t\t\tfor (var i = 0; i < segments.length; i++) {\n
+\t\t\t\t\tp.path += jsPlumb.Segments.vml.SegmentRenderer.getPath(segments[i]);\n
+\t\t\t\t\tp.path += " ";\n
+\t\t\t\t}\n
+\n
+                //*\n
+\t\t\t\tif (style.outlineColor) {\n
+\t\t\t\t\tvar outlineWidth = style.outlineWidth || 1,\n
+\t\t\t\t\toutlineStrokeWidth = style.lineWidth + (2 * outlineWidth),\n
+\t\t\t\t\toutlineStyle = {\n
+\t\t\t\t\t\tstrokeStyle : jsPlumbUtil.convertStyle(style.outlineColor),\n
+\t\t\t\t\t\tlineWidth : outlineStrokeWidth\n
+\t\t\t\t\t};\n
+\t\t\t\t\tfor (var aa in vmlAttributeMap) outlineStyle[aa] = style[aa];\n
+\t\t\t\t\t\n
+\t\t\t\t\tif (this.bgCanvas == null) {\t\t\t\t\t\t\n
+\t\t\t\t\t\tp["class"] = clazz;\n
+\t\t\t\t\t\tp.coordsize = (d[2] * scale) + "," + (d[3] * scale);\n
+\t\t\t\t\t\tthis.bgCanvas = _node("shape", d, p, params.parent, this._jsPlumb.instance, true);\t\t\t\t\t\t\n
+\t\t\t\t\t\t_pos(this.bgCanvas, d);\n
+\t\t\t\t\t\tthis.appendDisplayElement(this.bgCanvas, true);\t\n
+\t\t\t\t\t\tthis.attachListeners(this.bgCanvas, this);\t\t\t\t\t\n
+\t\t\t\t\t\tthis.initOpacityNodes(this.bgCanvas, ["stroke"]);\t\t\n
+\t\t\t\t\t}\n
+\t\t\t\t\telse {\n
+\t\t\t\t\t\tp.coordsize = (d[2] * scale) + "," + (d[3] * scale);\n
+\t\t\t\t\t\t_pos(this.bgCanvas, d);\n
+\t\t\t\t\t\t_atts(this.bgCanvas, p);\n
+\t\t\t\t\t}\n
+\t\t\t\t\t\n
+\t\t\t\t\t_applyStyles(this.bgCanvas, outlineStyle, this);\n
+\t\t\t\t}\n
+\t\t\t\t//*/\n
+\t\t\t\t\n
+\t\t\t\tif (this.canvas == null) {\t\t\t\t\t\t\t\t\t\t\n
+\t\t\t\t\tp["class"] = clazz;\n
+\t\t\t\t\tp.coordsize = (d[2] * scale) + "," + (d[3] * scale);\t\t\t\t\t\n
+\t\t\t\t\tthis.canvas = _node("shape", d, p, params.parent, this._jsPlumb.instance, true);\t\t\t\t\t                                    \n
+\t\t\t\t\tthis.appendDisplayElement(this.canvas, true);\t\t\t\t\t\t\t\t\t\t\n
+\t\t\t\t\tthis.attachListeners(this.canvas, this);\t\t\t\t\t\n
+\t\t\t\t\tthis.initOpacityNodes(this.canvas, ["stroke"]);\t\t\n
+\t\t\t\t}\n
+\t\t\t\telse {\n
+\t\t\t\t\tp.coordsize = (d[2] * scale) + "," + (d[3] * scale);\n
+\t\t\t\t\t_pos(this.canvas, d);\n
+\t\t\t\t\t_atts(this.canvas, p);\n
+\t\t\t\t}\n
+\t\t\t\t\n
+\t\t\t\t_applyStyles(this.canvas, style, this, this._jsPlumb.instance);\n
+\t\t\t}\n
+\t\t};\t\n
+\t\t\t\t\n
+\t};\n
+\tjsPlumbUtil.extend(VmlConnector, VmlComponent, {\n
+\t\treattachListeners : function() {\n
+\t\t\tif (this.canvas) this.reattachListenersForElement(this.canvas, this);\n
+\t\t},\n
+\t\tsetVisible:function(v) {\n
+\t\t\tif (this.canvas) {\n
+\t\t\t\tthis.canvas.style.display = v ? "block" : "none";\n
+\t\t\t}\n
+\t\t\tif (this.bgCanvas) {\n
+\t\t\t\tthis.bgCanvas.style.display = v ? "block" : "none";\n
+\t\t\t}\n
+\t\t}\n
+\t});\t\n
+\t\n
+\t/*\n
+\t * \n
+\t * Base class for Vml Endpoints. extends VmlComponent.\n
+\t * \n
+\t */\n
+\tvar VmlEndpoint = window.VmlEndpoint = function(params) {\n
+\t\tVmlComponent.apply(this, arguments);\n
+\t\tthis._jsPlumb.vml = null;//, opacityStrokeNode = null, opacityFillNode = null;\n
+\t\tthis.canvas = document.createElement("div");\n
+\t\tthis.canvas.style.position = "absolute";\n
+\t\tthis._jsPlumb.clazz = this._jsPlumb.instance.endpointClass + (params.cssClass ? (" " + params.cssClass) : "");\n
+\n
+\t\t// TODO vml endpoint adds class to VML at constructor time.  but the addClass method adds VML\n
+\t\t// to the enclosing DIV. what to do?  seems like it would be better to just target the div.\n
+\t\t// HOWEVER...vml connection has no containing div.  why not? it feels like it should.\n
+\n
+\t\tparams._jsPlumb.appendElement(this.canvas, params.parent);\n
+\n
+\t\tthis.paint = function(style, anchor) {\n
+\t\t\tvar p = { }, vml = this._jsPlumb.vml;\t\t\t\t\n
+\t\t\t\n
+\t\t\tjsPlumbUtil.sizeElement(this.canvas, this.x, this.y, this.w, this.h);\n
+\t\t\tif (this._jsPlumb.vml == null) {\n
+\t\t\t\tp["class"] = this._jsPlumb.clazz;\n
+\t\t\t\tvml = this._jsPlumb.vml = this.getVml([0,0, this.w, this.h], p, anchor, this.canvas, this._jsPlumb.instance);\t\t\t\t\n
+\t\t\t\tthis.attachListeners(vml, this);\n
+\n
+\t\t\t\tthis.appendDisplayElement(vml, true);\n
+\t\t\t\tthis.appendDisplayElement(this.canvas, true);\n
+\t\t\t\t\n
+\t\t\t\tthis.initOpacityNodes(vml, ["fill"]);\t\t\t\n
+\t\t\t}\n
+\t\t\telse {\t\t\t\t\n
+\t\t\t\t_pos(vml, [0,0, this.w, this.h]);\n
+\t\t\t\t_atts(vml, p);\n
+\t\t\t}\n
+\t\t\t\n
+\t\t\t_applyStyles(vml, style, this);\n
+\t\t};\t\t\n
+\t};\n
+\tjsPlumbUtil.extend(VmlEndpoint, VmlComponent, {\n
+\t\treattachListeners : function() {\n
+\t\t\tif (this._jsPlumb.vml) this.reattachListenersForElement(this._jsPlumb.vml, this);\n
+\t\t}\n
+\t});\n
+\t\n
+// ******************************* vml segments *****************************************************\t\n
+\t\t\n
+\tjsPlumb.Segments.vml = {\n
+\t\tSegmentRenderer : {\t\t\n
+\t\t\tgetPath : function(segment) {\n
+\t\t\t\treturn ({\n
+\t\t\t\t\t"Straight":function(segment) {\n
+\t\t\t\t\t\tvar d = segment.params;\n
+\t\t\t\t\t\treturn "m" + _conv(d.x1) + "," + _conv(d.y1) + " l" + _conv(d.x2) + "," + _conv(d.y2) + " e";\n
+\t\t\t\t\t},\n
+\t\t\t\t\t"Bezier":function(segment) {\n
+\t\t\t\t\t\tvar d = segment.params;\n
+\t\t\t\t\t\treturn "m" + _conv(d.x1) + "," + _conv(d.y1) + \n
+\t\t\t\t   \t\t\t" c" + _conv(d.cp1x) + "," + _conv(d.cp1y) + "," + _conv(d.cp2x) + "," + _conv(d.cp2y) + "," + _conv(d.x2) + "," + _conv(d.y2) + " e";\n
+\t\t\t\t\t},\n
+\t\t\t\t\t"Arc":function(segment) {\t\t\t\t\t\n
+\t\t\t\t\t\tvar d = segment.params,\n
+\t\t\t\t\t\t\txmin = Math.min(d.x1, d.x2),\n
+\t\t\t\t\t\t\txmax = Math.max(d.x1, d.x2),\n
+\t\t\t\t\t\t\tymin = Math.min(d.y1, d.y2),\n
+\t\t\t\t\t\t\tymax = Math.max(d.y1, d.y2),\t\t\t\t\t\t\t\t\t\t\t\t\t\t\n
+\t\t\t\t\t\t\tsf = segment.anticlockwise ? 1 : 0,\n
+\t\t\t\t\t\t\tpathType = (segment.anticlockwise ? "at " : "wa "),\n
+\t\t\t\t\t\t\tmakePosString = function() {\n
+\t\t\t\t\t\t\t\tif (d.loopback)\n
+\t\t\t\t\t\t\t\t\treturn "0,0," + _conv(2*d.r) + "," + _conv(2 * d.r);\n
+\n
+\t\t\t\t\t\t\t\tvar xy = [\n
+\t\t\t\t\t\t\t\t\t\tnull,\n
+\t\t\t\t\t\t\t\t\t\t[ function() { return [xmin, ymin ];}, function() { return [xmin - d.r, ymin - d.r ];}],\n
+\t\t\t\t\t\t\t\t\t\t[ function() { return [xmin - d.r, ymin ];}, function() { return [xmin, ymin - d.r ];}],\n
+\t\t\t\t\t\t\t\t\t\t[ function() { return [xmin - d.r, ymin - d.r ];}, function() { return [xmin, ymin ];}],\n
+\t\t\t\t\t\t\t\t\t\t[ function() { return [xmin, ymin - d.r ];}, function() { return [xmin - d.r, ymin ];}]\n
+\t\t\t\t\t\t\t\t\t][segment.segment][sf]();\n
+\n
+\t\t\t\t\t\t\t\treturn _conv(xy[0]) + "," + _conv(xy[1]) + "," + _conv(xy[0] + (2*d.r)) + "," + _conv(xy[1] + (2*d.r));\n
+\t\t\t\t\t\t\t};\n
+\n
+\t\t\t\t\t\treturn pathType + " " + makePosString() + "," + _conv(d.x1) + "," + _conv(d.y1) + "," + _conv(d.x2) + "," + _conv(d.y2) + " e";\t\t\t\t\t\t\t\t\t\t\t\t\n
+\t\t\t\t\t}\n
+\t\t\t\t\t\t\n
+\t\t\t\t})[segment.type](segment);\t\n
+\t\t\t}\n
+\t\t}\n
+\t};\n
+\t\n
+// ******************************* /vml segments *****************************************************\t\n
+\n
+// ******************************* vml endpoints *****************************************************\n
+\t\n
+\tjsPlumb.Endpoints.vml.Dot = function() {\n
+\t\tjsPlumb.Endpoints.Dot.apply(this, arguments);\n
+\t\tVmlEndpoint.apply(this, arguments);\n
+\t\tthis.getVml = function(d, atts, anchor, parent, _jsPlumb) { return _node("oval", d, atts, parent, _jsPlumb); };\n
+\t};\n
+\tjsPlumbUtil.extend(jsPlumb.Endpoints.vml.Dot, VmlEndpoint);\n
+\t\n
+\tjsPlumb.Endpoints.vml.Rectangle = function() {\n
+\t\tjsPlumb.Endpoints.Rectangle.apply(this, arguments);\n
+\t\tVmlEndpoint.apply(this, arguments);\n
+\t\tthis.getVml = function(d, atts, anchor, parent, _jsPlumb) { return _node("rect", d, atts, parent, _jsPlumb); };\n
+\t};\n
+\tjsPlumbUtil.extend(jsPlumb.Endpoints.vml.Rectangle, VmlEndpoint);\n
+\t\n
+\t/*\n
+\t * VML Image Endpoint is the same as the default image endpoint.\n
+\t */\n
+\tjsPlumb.Endpoints.vml.Image = jsPlumb.Endpoints.Image;\n
+\t\n
+\t/**\n
+\t * placeholder for Blank endpoint in vml renderer.\n
+\t */\n
+\tjsPlumb.Endpoints.vml.Blank = jsPlumb.Endpoints.Blank;\n
+\t\n
+// ******************************* /vml endpoints *****************************************************\t\n
+\n
+// ******************************* vml overlays *****************************************************\n
+\t\n
+\t/**\n
+\t * VML Label renderer. uses the default label renderer (which adds an element to the DOM)\n
+\t */\n
+\tjsPlumb.Overlays.vml.Label  = jsPlumb.Overlays.Label;\n
+\t\n
+\t/**\n
+\t * VML Custom renderer. uses the default Custom renderer (which adds an element to the DOM)\n
+\t */\n
+\tjsPlumb.Overlays.vml.Custom = jsPlumb.Overlays.Custom;\n
+\t\n
+\t/**\n
+\t * Abstract VML arrow superclass\n
+\t */\n
+\tvar AbstractVmlArrowOverlay = function(superclass, originalArgs) {\n
+    \tsuperclass.apply(this, originalArgs);\n
+    \tVmlComponent.apply(this, originalArgs);\n
+    \tvar self = this, path = null;\n
+    \tthis.canvas = null; \n
+    \tthis.isAppendedAtTopLevel = true;\n
+    \tvar getPath = function(d) {    \t\t\n
+    \t\treturn "m " + _conv(d.hxy.x) + "," + _conv(d.hxy.y) +\n
+    \t\t       " l " + _conv(d.tail[0].x) + "," + _conv(d.tail[0].y) + \n
+    \t\t       " " + _conv(d.cxy.x) + "," + _conv(d.cxy.y) + \n
+    \t\t       " " + _conv(d.tail[1].x) + "," + _conv(d.tail[1].y) + \n
+    \t\t       " x e";\n
+    \t};\n
+    \tthis.paint = function(params, containerExtents) {\n
+    \t\t// only draws for connectors, not endpoints.\n
+    \t\tif (params.component.canvas && containerExtents) {\n
+\t    \t\tvar p = {}, d = params.d, connector = params.component;\n
+\t\t\t\tif (params.strokeStyle) {\n
+\t\t\t\t\tp.stroked = "true";\n
+\t\t\t\t\tp.strokecolor = jsPlumbUtil.convertStyle(params.strokeStyle, true);    \t\t\t\t\n
+\t\t\t\t}\n
+\t\t\t\tif (params.lineWidth) p.strokeweight = params.lineWidth + "px";\n
+\t\t\t\tif (params.fillStyle) {\n
+\t\t\t\t\tp.filled = "true";\n
+\t\t\t\t\tp.fillcolor = params.fillStyle;\n
+\t\t\t\t}\t\t\t\n
+\n
+\t\t\t\tvar xmin = Math.min(d.hxy.x, d.tail[0].x, d.tail[1].x, d.cxy.x),\n
+\t\t\t\t\tymin = Math.min(d.hxy.y, d.tail[0].y, d.tail[1].y, d.cxy.y),\n
+\t\t\t\t\txmax = Math.max(d.hxy.x, d.tail[0].x, d.tail[1].x, d.cxy.x),\n
+\t\t\t\t\tymax = Math.max(d.hxy.y, d.tail[0].y, d.tail[1].y, d.cxy.y),\n
+\t\t\t\t\tw = Math.abs(xmax - xmin),\n
+\t\t\t\t\th = Math.abs(ymax - ymin),\n
+\t\t\t\t\tdim = [xmin, ymin, w, h];\n
+\n
+\t\t\t\t// for VML, we create overlays using shapes that have the same dimensions and\n
+\t\t\t\t// coordsize as their connector - overlays calculate themselves relative to the\n
+\t\t\t\t// connector (it\'s how it\'s been done since the original canvas implementation, because\n
+\t\t\t\t// for canvas that makes sense).\n
+\t\t\t\tp.path = getPath(d);\n
+\t\t\t\tp.coordsize = (connector.w * scale) + "," + (connector.h * scale);\t\t\t\n
+\t\t\t\t\n
+\t\t\t\tdim[0] = connector.x;\n
+\t\t\t\tdim[1] = connector.y;\n
+\t\t\t\tdim[2] = connector.w;\n
+\t\t\t\tdim[3] = connector.h;\n
+\t\t\t\t\n
+\t    \t\tif (self.canvas == null) {\n
+\t    \t\t\tvar overlayClass = connector._jsPlumb.overlayClass || "";\n
+\t    \t\t\tvar clazz = originalArgs && (originalArgs.length == 1) ? (originalArgs[0].cssClass || "") : "";\n
+\t    \t\t\tp["class"] = clazz + " " + overlayClass;\n
+\t\t\t\t\tself.canvas = _node("shape", dim, p, connector.canvas.parentNode, connector._jsPlumb.instance, true);\t\t\t\t\t\t\t\t\n
+\t\t\t\t\tconnector.appendDisplayElement(self.canvas, true);\n
+\t\t\t\t\tself.attachListeners(self.canvas, connector);\n
+\t\t\t\t\tself.attachListeners(self.canvas, self);\n
+\t\t\t\t}\n
+\t\t\t\telse {\t\t\t\t\n
+\t\t\t\t\t_pos(self.canvas, dim);\n
+\t\t\t\t\t_atts(self.canvas, p);\n
+\t\t\t\t}    \t\t\n
+\t\t\t}\n
+    \t};\n
+    \t\n
+    \tthis.reattachListeners = function() {\n
+\t\t\tif (this.canvas) this.reattachListenersForElement(self.canvas, this);\n
+\t\t};\n
+\n
+\t\tthis.cleanup = function() {\n
+    \t\tif (this.canvas != null) this._jsPlumb.instance.removeElement(this.canvas);\n
+    \t};\n
+    };\n
+    jsPlumbUtil.extend(AbstractVmlArrowOverlay, [VmlComponent, jsPlumb.Overlays.AbstractOverlay], {\n
+    \tsetVisible : function(state) {\n
+    \t    this.canvas.style.display = state ? "block" : "none";\n
+    \t}\n
+    });\n
+\t\n
+\tjsPlumb.Overlays.vml.Arrow = function() {\n
+    \tAbstractVmlArrowOverlay.apply(this, [jsPlumb.Overlays.Arrow, arguments]);    \t\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.vml.Arrow, [ jsPlumb.Overlays.Arrow, AbstractVmlArrowOverlay ]);\n
+    \n
+    jsPlumb.Overlays.vml.PlainArrow = function() {\n
+    \tAbstractVmlArrowOverlay.apply(this, [jsPlumb.Overlays.PlainArrow, arguments]);    \t\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.vml.PlainArrow, [ jsPlumb.Overlays.PlainArrow, AbstractVmlArrowOverlay ]);\n
+    \n
+    jsPlumb.Overlays.vml.Diamond = function() {\n
+    \tAbstractVmlArrowOverlay.apply(this, [jsPlumb.Overlays.Diamond, arguments]);    \t\n
+    };\n
+    jsPlumbUtil.extend(jsPlumb.Overlays.vml.Diamond, [ jsPlumb.Overlays.Diamond, AbstractVmlArrowOverlay ]);\n
+    \n
+// ******************************* /vml overlays *****************************************************    \n
+    \n
+})();\n
+/*\n
+ * jsPlumb\n
+ * \n
+ * Title:jsPlumb 1.6.2\n
+ * \n
+ * Provides a way to visually connect elements on an HTML page, using SVG or VML.  \n
+ * \n
+ * This file contains the jQuery adapter.\n
+ *\n
+ * Copyright (c) 2010 - 2014 Simon Porritt (simon@jsplumbtoolkit.com)\n
+ * \n
+ * http://jsplumbtoolkit.com\n
+ * http://github.com/sporritt/jsplumb\n
+ * \n
+ * Dual licensed under the MIT and GPL2 licenses.\n
+ */  \n
+;(function($) {\n
+\t\n
+\t"use strict";\n
+\n
+\tvar _getElementObject = function(el) {\n
+\t\treturn typeof(el) == "string" ? $("#" + el) : $(el);\n
+\t};\n
+\n
+\t$.extend(jsPlumbInstance.prototype, {\n
+\n
+// ---------------------------- DOM MANIPULATION ---------------------------------------\t\t\n
+\t\t\t\t\n
+\t\t\n
+\t\t/**\n
+\t\t* gets a DOM element from the given input, which might be a string (in which case we just do document.getElementById),\n
+\t\t* a selector (in which case we return el[0]), or a DOM element already (we assume this if it\'s not either of the other\n
+\t\t* two cases).  this is the opposite of getElementObject below.\n
+\t\t*/\n
+\t\tgetDOMElement : function(el) {\n
+\t\t\tif (el == null) return null;\n
+\t\t\tif (typeof(el) == "string") return document.getElementById(el);\n
+\t\t\telse if (el.context || el.length != null) return el[0];\n
+\t\t\telse return el;\n
+\t\t},\n
+\t\t\n
+\t\t/**\n
+\t\t * gets an "element object" from the given input.  this means an object that is used by the\n
+\t\t * underlying library on which jsPlumb is running.  \'el\' may already be one of these objects,\n
+\t\t * in which case it is returned as-is.  otherwise, \'el\' is a String, the library\'s lookup \n
+\t\t * function is used to find the element, using the given String as the element\'s id.\n
+\t\t * \n
+\t\t */\n
+\t\tgetElementObject : _getElementObject,\n
+\n
+\t\t/**\n
+\t\t* removes an element from the DOM.  doing it via the library is\n
+\t\t* safer from a memory perspective, as it ix expected that the library\'s \n
+\t\t* remove method will unbind any event listeners before removing the element from the DOM.\n
+\t\t*/\n
+\t\tremoveElement:function(element) {\n
+\t\t\t_getElementObject(element).remove();\n
+\t\t},\n
+\n
+// ---------------------------- END DOM MANIPULATION ---------------------------------------\n
+\n
+// ---------------------------- MISCELLANEOUS ---------------------------------------\n
+\n
+\t\t/**\n
+\t\t * animates the given element.\n
+\t\t */\n
+\t\tdoAnimate : function(el, properties, options) {\n
+\t\t\tel.animate(properties, options);\n
+\t\t},\t\n
+\t\tgetSelector : function(context, spec) {\n
+            if (arguments.length == 2)\n
+                return _getElementObject(context).find(spec);\n
+            else\n
+                return $(context);\n
+\t\t},\n
+\n
+// ---------------------------- END MISCELLANEOUS ---------------------------------------\t\t\n
+\n
+// -------------------------------------- DRAG/DROP\t---------------------------------\n
+\t\t\n
+\t\tdestroyDraggable : function(el) {\n
+\t\t\tif ($(el).data("draggable"))\n
+\t\t\t\t$(el).draggable("destroy");\n
+\t\t},\n
+\n
+\t\tdestroyDroppable : function(el) {\n
+\t\t\tif ($(el).data("droppable"))\n
+\t\t\t\t$(el).droppable("destroy");\n
+\t\t},\n
+\t\t/**\n
+\t\t * initialises the given element to be draggable.\n
+\t\t */\n
+\t\tinitDraggable : function(el, options, isPlumbedComponent) {\n
+\t\t\toptions = options || {};\n
+\t\t\tel = $(el);\n
+\n
+\t\t\toptions.start = jsPlumbUtil.wrap(options.start, function() {\n
+\t\t\t\t$("body").addClass(this.dragSelectClass);\n
+\t\t\t}, false);\n
+\n
+\t\t\toptions.stop = jsPlumbUtil.wrap(options.stop, function() {\n
+\t\t\t\t$("body").removeClass(this.dragSelectClass);\n
+\t\t\t});\n
+\n
+\t\t\t// remove helper directive if present and no override\n
+\t\t\tif (!options.doNotRemoveHelper)\n
+\t\t\t\toptions.helper = null;\n
+\t\t\tif (isPlumbedComponent)\n
+\t\t\t\toptions.scope = options.scope || jsPlumb.Defaults.Scope;\n
+\t\t\tel.draggable(options);\n
+\t\t},\n
+\t\t\n
+\t\t/**\n
+\t\t * initialises the given element to be droppable.\n
+\t\t */\n
+\t\tinitDroppable : function(el, options) {\n
+\t\t\toptions.scope = options.scope || jsPlumb.Defaults.Scope;\n
+\t\t\t$(el).droppable(options);\n
+\t\t},\n
+\t\t\n
+\t\tisAlreadyDraggable : function(el) {\n
+\t\t\treturn $(el).hasClass("ui-draggable");\n
+\t\t},\n
+\t\t\n
+\t\t/**\n
+\t\t * returns whether or not drag is supported (by the library, not whether or not it is disabled) for the given element.\n
+\t\t */\n
+\t\tisDragSupported : function(el, options) {\n
+\t\t\treturn $(el).draggable;\n
+\t\t},\n
+\n
+\t\t/**\n
+\t\t * returns whether or not drop is supported (by the library, not whether or not it is disabled) for the given element.\n
+\t\t */\n
+\t\tisDropSupported : function(el, options) {\n
+\t\t\treturn $(el).droppable;\n
+\t\t},\n
+\t\t/**\n
+\t\t * takes the args passed to an event function and returns you an object representing that which is being dragged.\n
+\t\t */\n
+\t\tgetDragObject : function(eventArgs) {\n
+\t\t\t//return eventArgs[1].draggable || eventArgs[1].helper;\n
+\t\t\treturn eventArgs[1].helper || eventArgs[1].draggable;\n
+\t\t},\n
+\t\t\n
+\t\tgetDragScope : function(el) {\n
+\t\t\treturn $(el).draggable("option", "scope");\n
+\t\t},\n
+\n
+\t\tgetDropEvent : function(args) {\n
+\t\t\treturn args[0];\n
+\t\t},\n
+\t\t\n
+\t\tgetDropScope : function(el) {\n
+\t\t\treturn $(el).droppable("option", "scope");\n
+\t\t},\n
+\t\t/**\n
+\t\t * takes the args passed to an event function and returns you an object that gives the\n
+\t\t * position of the object being moved, as a js object with the same params as the result of\n
+\t\t * getOffset, ie: { left: xxx, top: xxx }.\n
+\t\t * \n
+\t\t * different libraries have different signatures for their event callbacks.  \n
+\t\t * see getDragObject as well\n
+\t\t */\n
+\t\tgetUIPosition : function(eventArgs, zoom, dontAdjustHelper) {\n
+\t\t\tvar ret;\n
+\t\t\tzoom = zoom || 1;\n
+\t\t\tif (eventArgs.length == 1) {\n
+\t\t\t\tret = { left: eventArgs[0].pageX, top:eventArgs[0].pageY };\n
+\t\t\t}\n
+\t\t\telse {\n
+\t\t\t\tvar ui = eventArgs[1],\n
+\t\t\t\t  _offset = ui.position;//ui.offset;\n
+\t\t\t\t  \n
+\t\t\t\tret = _offset || ui.absolutePosition;\n
+\t\t\t\t\n
+\t\t\t\t// adjust ui position to account for zoom, because jquery ui does not do this.\n
+\t\t\t\tif (!dontAdjustHelper) {\n
+\t\t\t\t\tui.position.left /= zoom;\n
+\t\t\t\t\tui.position.top /= zoom;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\treturn { left:ret.left, top: ret.top  };\n
+\t\t},\n
+\t\t\n
+\t\tisDragFilterSupported:function() { return true; },\n
+\t\t\n
+\t\tsetDragFilter : function(el, filter) {\n
+\t\t\tif (jsPlumb.isAlreadyDraggable(el))\n
+\t\t\t\t$(el).draggable("option", "cancel", filter);\n
+\t\t},\n
+\t\t\n
+\t\tsetElementDraggable : function(el, draggable) {\n
+\t\t\t$(el).draggable("option", "disabled", !draggable);\n
+\t\t},\n
+\t\t\n
+\t\tsetDragScope : function(el, scope) {\n
+\t\t\t$(el).draggable("option", "scope", scope);\n
+\t\t},\n
+\t\t/**\n
+         * mapping of drag events for jQuery\n
+         */\n
+\t\tdragEvents : {\n
+\t\t\t\'start\':\'start\', \'stop\':\'stop\', \'drag\':\'drag\', \'step\':\'step\',\n
+\t\t\t\'over\':\'over\', \'out\':\'out\', \'drop\':\'drop\', \'complete\':\'complete\'\n
+\t\t},\n
+\t\tanimEvents:{\n
+\t\t\t\'step\':"step", \'complete\':\'complete\'\n
+\t\t},\n
+\t\t\n
+// -------------------------------------- END DRAG/DROP\t---------------------------------\t\t\n
+\n
+// -------------------------------------- EVENTS\t---------------------------------\t\t\n
+\n
+\t\t/**\n
+\t\t * note that jquery ignores the name of the event you wanted to trigger, and figures it out for itself.\n
+\t\t * the other libraries do not.  yui, in fact, cannot even pass an original event.  we have to pull out stuff\n
+\t\t * from the originalEvent to put in an options object for YUI. \n
+\t\t * @param el\n
+\t\t * @param event\n
+\t\t * @param originalEvent\n
+\t\t */\n
+\t\ttrigger : function(el, event, originalEvent) {\n
+\t\t\tvar h = jQuery._data(_getElementObject(el)[0], "handle");\n
+            h(originalEvent);\n
+\t\t},\n
+\t\tgetOriginalEvent : function(e) {\n
+\t\t\treturn e.originalEvent;\n
+\t\t},\n
+\n
+\t\t// note: for jquery we support the delegation stuff here\n
+\t\ton : function(el, event, callback) {\n
+\t\t\tel = _getElementObject(el);\n
+\t\t\tvar a = []; a.push.apply(a, arguments);\n
+\t\t\tel.on.apply(el, a.slice(1));\n
+\t\t},\t\t\t\t\n
+\t\t\n
+\t\t// note: for jquery we support the delegation stuff here\n
+\t\toff : function(el, event, callback) {\n
+\t\t\tel = _getElementObject(el);\n
+\t\t\tvar a = []; a.push.apply(a, arguments);\n
+\t\t\tel.off.apply(el, a.slice(1));\n
+\t\t}\n
+\n
+// -------------------------------------- END EVENTS\t---------------------------------\t\t\n
+\n
+\t});\n
+\n
+\t$(document).ready(jsPlumb.init);\n
+\n
+})(jQuery);\n
+\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.simulate.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.simulate.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7e9af19ad3932d16197a7326cbcb840851bd51f8
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquery.simulate.js.xml
@@ -0,0 +1,196 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681770.53</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jquery.simulate.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*\n
+ * jquery.simulate - simulate browser mouse and keyboard events\n
+ *\n
+ * Copyright (c) 2009 Eduardo Lundgren (eduardolundgren@gmail.com)\n
+ * and Richard D. Worth (rdworth@gmail.com)\n
+ *\n
+ * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) \n
+ * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.\n
+ *\n
+ */\n
+\n
+;(function($) {\n
+\n
+$.fn.extend({\n
+\tsimulate: function(type, options) {\n
+\t\treturn this.each(function() {\n
+\t\t\tvar opt = $.extend({}, $.simulate.defaults, options || {});\n
+\t\t\tnew $.simulate(this, type, opt);\n
+\t\t});\n
+\t}\n
+});\n
+\n
+$.simulate = function(el, type, options) {\n
+\tthis.target = el;\n
+\tthis.options = options;\n
+\n
+\tif (/^drag$/.test(type)) {\n
+\t\tthis[type].apply(this, [this.target, options]);\n
+\t} else {\n
+\t\tthis.simulateEvent(el, type, options);\n
+\t}\n
+};\n
+\n
+$.extend($.simulate.prototype, {\n
+\tsimulateEvent: function(el, type, options) {\n
+\t\tvar evt = this.createEvent(type, options);\n
+\t\tthis.dispatchEvent(el, type, evt, options);\n
+\t\treturn evt;\n
+\t},\n
+\tcreateEvent: function(type, options) {\n
+\t\tif (/^mouse(over|out|down|up|move)|(dbl)?click$/.test(type)) {\n
+\t\t\treturn this.mouseEvent(type, options);\n
+\t\t} else if (/^key(up|down|press)$/.test(type)) {\n
+\t\t\treturn this.keyboardEvent(type, options);\n
+\t\t}\n
+\t},\n
+\tmouseEvent: function(type, options) {\n
+\t\tvar evt;\n
+\t\tvar e = $.extend({\n
+\t\t\tbubbles: true, cancelable: (type != "mousemove"), view: window, detail: 0,\n
+\t\t\tscreenX: 0, screenY: 0, clientX: 0, clientY: 0,\n
+\t\t\tctrlKey: false, altKey: false, shiftKey: false, metaKey: false,\n
+\t\t\tbutton: 0, relatedTarget: undefined\n
+\t\t}, options);\n
+\n
+\t\tvar relatedTarget = $(e.relatedTarget)[0];\n
+\n
+\t\tif ($.isFunction(document.createEvent)) {\n
+\t\t\tevt = document.createEvent("MouseEvents");\n
+\t\t\tevt.initMouseEvent(type, e.bubbles, e.cancelable, e.view, e.detail,\n
+\t\t\t\te.screenX, e.screenY, e.clientX, e.clientY,\n
+\t\t\t\te.ctrlKey, e.altKey, e.shiftKey, e.metaKey,\n
+\t\t\t\te.button, e.relatedTarget || document.body.parentNode);\n
+\t\t} else if (document.createEventObject) {\n
+\t\t\tevt = document.createEventObject();\n
+\t\t\t$.extend(evt, e);\n
+\t\t\tevt.button = { 0:1, 1:4, 2:2 }[evt.button] || evt.button;\n
+\t\t}\n
+\t\treturn evt;\n
+\t},\n
+\tkeyboardEvent: function(type, options) {\n
+\t\tvar evt;\n
+\n
+\t\tvar e = $.extend({ bubbles: true, cancelable: true, view: window,\n
+\t\t\tctrlKey: false, altKey: false, shiftKey: false, metaKey: false,\n
+\t\t\tkeyCode: 0, charCode: 0\n
+\t\t}, options);\n
+\n
+\t\tif ($.isFunction(document.createEvent)) {\n
+\t\t\ttry {\n
+\t\t\t\tevt = document.createEvent("KeyEvents");\n
+\t\t\t\tevt.initKeyEvent(type, e.bubbles, e.cancelable, e.view,\n
+\t\t\t\t\te.ctrlKey, e.altKey, e.shiftKey, e.metaKey,\n
+\t\t\t\t\te.keyCode, e.charCode);\n
+\t\t\t} catch(err) {\n
+\t\t\t\tevt = document.createEvent("Events");\n
+\t\t\t\tevt.initEvent(type, e.bubbles, e.cancelable);\n
+\t\t\t\t$.extend(evt, { view: e.view,\n
+\t\t\t\t\tctrlKey: e.ctrlKey, altKey: e.altKey, shiftKey: e.shiftKey, metaKey: e.metaKey,\n
+\t\t\t\t\tkeyCode: e.keyCode, charCode: e.charCode\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t} else if (document.createEventObject) {\n
+\t\t\tevt = document.createEventObject();\n
+\t\t\t$.extend(evt, e);\n
+\t\t}\n
+\t\tif (($.browser !== undefined) && ($.browser.msie || $.browser.opera)) {\n
+\t\t\tevt.keyCode = (e.charCode > 0) ? e.charCode : e.keyCode;\n
+\t\t\tevt.charCode = undefined;\n
+\t\t}\n
+\t\treturn evt;\n
+\t},\n
+\n
+\tdispatchEvent: function(el, type, evt) {\n
+\t\tif (el.dispatchEvent) {\n
+\t\t\tel.dispatchEvent(evt);\n
+\t\t} else if (el.fireEvent) {\n
+\t\t\tel.fireEvent(\'on\' + type, evt);\n
+\t\t}\n
+\t\treturn evt;\n
+\t},\n
+\n
+\tdrag: function(el) {\n
+\t\tvar self = this, center = this.findCenter(this.target), \n
+\t\t\toptions = this.options,\tx = Math.floor(center.x), y = Math.floor(center.y), \n
+\t\t\tdx = options.dx || 0, dy = options.dy || 0, target = this.target;\n
+\t\tvar coord = { clientX: x, clientY: y };\n
+\t\tthis.simulateEvent(target, "mousedown", coord);\n
+\t\tcoord = { clientX: x + 1, clientY: y + 1 };\n
+\t\tthis.simulateEvent(document, "mousemove", coord);\n
+\t\tcoord = { clientX: x + dx, clientY: y + dy };\n
+\t\tthis.simulateEvent(document, "mousemove", coord);\n
+\t\tthis.simulateEvent(document, "mousemove", coord);\n
+\t\tthis.simulateEvent(target, "mouseup", coord);\n
+\t},\n
+\tfindCenter: function(el) {\n
+\t\tvar el = $(this.target), o = el.offset();\n
+\t\treturn {\n
+\t\t\tx: o.left + el.outerWidth() / 2,\n
+\t\t\ty: o.top + el.outerHeight() / 2\n
+\t\t};\n
+\t}\n
+});\n
+\n
+$.extend($.simulate, {\n
+\tdefaults: {\n
+\t\tspeed: \'sync\'\n
+\t},\n
+\tVK_TAB: 9,\n
+\tVK_ENTER: 13,\n
+\tVK_ESC: 27,\n
+\tVK_PGUP: 33,\n
+\tVK_PGDN: 34,\n
+\tVK_END: 35,\n
+\tVK_HOME: 36,\n
+\tVK_LEFT: 37,\n
+\tVK_UP: 38,\n
+\tVK_RIGHT: 39,\n
+\tVK_DOWN: 40\n
+});\n
+\n
+})(jQuery);\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>4340</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquerymobile.css.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquerymobile.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2e00a33a748da16ae82c7c85013a7aff11b95078
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquerymobile.css.xml
@@ -0,0 +1,4864 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681770.19</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jquerymobile.css</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/css</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>254355</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*!\n
+* jQuery Mobile 1.4.0-alpha.2\n
+* Git HEAD hash: 1e27844a1c0b9103a0948480637e6a67f5212dfd <> Date: Thu Aug 15 2013 13:53:49 UTC\n
+* http://jquerymobile.com\n
+*\n
+* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors\n
+* Released under the MIT license.\n
+* http://jquery.org/license\n
+*\n
+*/\n
+\n
+\n
+/* SVG icons */\n
+.ui-icon-action:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2213px%22%20viewBox%3D%220%200%2014%2013%22%20style%3D%22enable-background%3Anew%200%200%2014%2013%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C11H2V5h1l2-2H0v10h13V7l-2%2C2V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-arrow-d-l:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-arrow-d-r:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-arrow-d:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-arrow-l:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-arrow-r:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-arrow-u-l:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-arrow-u-r:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-arrow-u:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-audio:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-calendar:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-camera:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2211px%22%20viewBox%3D%220%200%2014%2011%22%20style%3D%22enable-background%3Anew%200%200%2014%2011%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12%2C1H9.908C9.702%2C0.419%2C9.152%2C0%2C8.5%2C0h-3C4.848%2C0%2C4.298%2C0.419%2C4.092%2C1H2C0.896%2C1%2C0%2C1.896%2C0%2C3v6c0%2C1.104%2C0.896%2C2%2C2%2C2h10%20c1.104%2C0%2C2-0.896%2C2-2V3C14%2C1.896%2C13.104%2C1%2C12%2C1z%20M7%2C9C5.343%2C9%2C4%2C7.657%2C4%2C6s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C9%2C7%2C9z%20M7%2C4%20C5.896%2C4%2C5%2C4.896%2C5%2C6s0.896%2C2%2C2%2C2s2-0.896%2C2-2S8.104%2C4%2C7%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-carat-d:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%228px%22%20viewBox%3D%220%200%2012%208%22%20style%3D%22enable-background%3Anew%200%200%2012%208%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2210%2C0%206%2C4%202%2C0%200%2C2%206%2C8%2012%2C2%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-carat-l:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%228px%22%20height%3D%2212px%22%20viewBox%3D%220%200%208%2012%22%20style%3D%22enable-background%3Anew%200%200%208%2012%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%228%2C2%206%2C0%200%2C6%206%2C12%208%2C10%204%2C6%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-carat-r:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%228px%22%20height%3D%2212px%22%20viewBox%3D%220%200%208%2012%22%20style%3D%22enable-background%3Anew%200%200%208%2012%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%222%2C0%200%2C2%204%2C6%200%2C10%202%2C12%208%2C6%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-carat-u:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%228px%22%20viewBox%3D%220%200%2012%208%22%20style%3D%22enable-background%3Anew%200%200%2012%208%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%226%2C0%200%2C6%202%2C8%206%2C4%2010%2C8%2012%2C6%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-check:after,\n
+.ui-icon-checkbox-on:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2212px%22%20viewBox%3D%220%200%2014%2012%22%20style%3D%22enable-background%3Anew%200%200%2014%2012%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%205.003%2C5.997%203%2C4%200%2C7%204.966%2C12%204.983%2C11.983%205%2C12%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-clock:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-cloud:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%229px%22%20viewBox%3D%220%200%2014%209%22%20style%3D%22enable-background%3Anew%200%200%2014%209%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M14%2C7c0-0.793-0.465-1.472-1.134-1.795C12.949%2C4.984%2C13%2C4.749%2C13%2C4.5c0-1.104-0.896-2-2-2c-0.158%2C0-0.31%2C0.023-0.457%2C0.058%20C9.816%2C1.049%2C8.286%2C0%2C6.5%2C0C4.17%2C0%2C2.276%2C1.777%2C2.046%2C4.046C0.883%2C4.26%2C0%2C5.274%2C0%2C6.5C0%2C7.881%2C1.119%2C9%2C2.5%2C9h10V8.93%20C13.361%2C8.706%2C14%2C7.931%2C14%2C7z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-grid:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-mail:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2210px%22%20viewBox%3D%220%200%2014%2010%22%20style%3D%22enable-background%3Anew%200%200%2014%2010%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M0%2C1.75V10h14V1.75L7%2C7L0%2C1.75z%20M14%2C0H0l7%2C5L14%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-eye:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2210px%22%20viewBox%3D%220%200%2014%2010%22%20style%3D%22enable-background%3Anew%200%200%2014%2010%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3%2C0%2C0%2C5%2C0%2C5s3%2C5%2C7%2C5s7-5%2C7-5S11%2C0%2C7%2C0z%20M7%2C8C5.343%2C8%2C4%2C6.657%2C4%2C5s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C8%2C7%2C8z%20M7%2C4%20C6.448%2C4%2C6%2C4.447%2C6%2C5s0.448%2C1%2C1%2C1s1-0.447%2C1-1S7.552%2C4%2C7%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-gear:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-heart:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2213.744px%22%20viewBox%3D%220%200%2014%2013.744%22%20style%3D%22enable-background%3Anew%200%200%2014%2013.744%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C1.744c-2-3-7-2-7%2C2c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.479%2C3%2C3c0.583-0.521%2C3-3%2C3-3s4-4%2C4-7C14-0.256%2C9-1.256%2C7%2C1.744z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-home:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-info:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-bullets:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2210px%22%20viewBox%3D%220%200%2014%2010%22%20style%3D%22enable-background%3Anew%200%200%2014%2010%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M5%2C2h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C0%2C4%2C0.447%2C4%2C1S4.447%2C2%2C5%2C2z%20M13%2C4H5C4.447%2C4%2C4%2C4.447%2C4%2C5s0.447%2C1%2C1%2C1h8%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C4%2C13%2C4z%20M13%2C8H5C4.447%2C8%2C4%2C8.447%2C4%2C9s0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1S13.553%2C8%2C13%2C8z%20M1%2C0%20C0.447%2C0%2C0%2C0.447%2C0%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C0%2C1%2C0z%20M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C4%2C1%2C4z%20M1%2C8%20C0.447%2C8%2C0%2C8.447%2C0%2C9s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C8%2C1%2C8z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-bars:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2210px%22%20viewBox%3D%220%200%2014%2010%22%20style%3D%22enable-background%3Anew%200%200%2014%2010%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C2h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C0%2C0%2C0.447%2C0%2C1S0.447%2C2%2C1%2C2z%20M13%2C4H1C0.447%2C4%2C0%2C4.447%2C0%2C5s0.447%2C1%2C1%2C1h12%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C4%2C13%2C4z%20M13%2C8H1C0.447%2C8%2C0%2C8.447%2C0%2C9s0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1S13.553%2C8%2C13%2C8z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-navigation:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C0%200%2C6%208%2C6%208%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-lock:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M11%2C6V5c0-2.762-2.239-5-5-5S1%2C2.238%2C1%2C5v1H0v8h12V6H11z%20M6.5%2C9.847V12h-1V9.847C5.207%2C9.673%2C5%2C9.366%2C5%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C7%2C9.366%2C6.793%2C9.673%2C6.5%2C9.847z%20M9%2C6H3V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-search:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2213.701px%22%20height%3D%2213.721px%22%20viewBox%3D%220%200%2013.701%2013.721%22%20style%3D%22enable-background%3Anew%200%200%2013.701%2013.721%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M10.021%2C8.626C10.638%2C7.738%2C11%2C6.662%2C11%2C5.5C11%2C2.463%2C8.537%2C0%2C5.5%2C0S0%2C2.463%2C0%2C5.5S2.463%2C11%2C5.5%2C11%20c1.152%2C0%2C2.221-0.356%2C3.105-0.962l3.682%2C3.683l1.414-1.414L10.021%2C8.626z%20M5.5%2C9C3.567%2C9%2C2%2C7.433%2C2%2C5.5S3.567%2C2%2C5.5%2C2S9%2C3.567%2C9%2C5.5%20S7.433%2C9%2C5.5%2C9z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-location:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%228px%22%20height%3D%2214px%22%20viewBox%3D%220%200%208%2014%22%20style%3D%22enable-background%3Anew%200%200%208%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M4%2C0C1.791%2C0%2C0%2C1.791%2C0%2C4c0%2C2%2C4%2C10%2C4%2C10S8%2C6%2C8%2C4C8%2C1.791%2C6.209%2C0%2C4%2C0z%20M4%2C6C2.896%2C6%2C2%2C5.104%2C2%2C4s0.896-2%2C2-2s2%2C0.896%2C2%2C2%20S5.104%2C6%2C4%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-minus:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%224px%22%20viewBox%3D%220%200%2014%204%22%20style%3D%22enable-background%3Anew%200%200%2014%204%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20fill%3D%22%23FFF%22%20width%3D%2214%22%20height%3D%224%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-forbidden:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-edit:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-user:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-phone:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2213.979px%22%20height%3D%2214.016px%22%20viewBox%3D%220%200%2013.979%2014.016%22%20style%3D%22enable-background%3Anew%200%200%2013.979%2014.016%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M6.939%2C9.189C6.165%2C8.557%2C5.271%2C7.705%2C4.497%2C6.744C3.953%2C6.071%2C3.473%2C5.363%2C3.969%2C4.866l-3.482-3.48%20C-0.021%2C2.02-1.146%2C5.04%2C3.675%2C9.984c5.08%2C5.211%2C8.356%2C4.096%2C8.92%2C3.51l-3.396-3.4C8.725%2C10.568%2C8.113%2C10.146%2C6.939%2C9.189z%20%20M13.82%2C11.519v-0.004c0%2C0-2.649-2.646-2.65-2.648c-0.21-0.21-0.546-0.205-0.754%2C0.002L9.455%2C9.831l3.404%2C3.408%20c0%2C0%2C0.962-0.96%2C0.961-0.961l0.002-0.001C14.043%2C12.056%2C14.021%2C11.721%2C13.82%2C11.519z%20M5.192%2C3.644V3.642%20c0.221-0.222%2C0.2-0.557%2C0-0.758V2.881c0%2C0-2.726-2.724-2.727-2.725C2.255-0.055%2C1.92-0.05%2C1.712%2C0.157L0.751%2C1.121l3.48%2C3.483%20C4.231%2C4.604%2C5.192%2C3.645%2C5.192%2C3.644z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-plus:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-power:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2213.896px%22%20viewBox%3D%220%200%2012%2013.896%22%20style%3D%22enable-background%3Anew%200%200%2012%2013.896%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M10.243%2C3.356c-0.392-0.401-1.024-0.401-1.415%2C0c-0.39%2C0.402-0.39%2C1.054%2C0%2C1.455C9.584%2C5.59%2C10%2C6.623%2C10%2C7.722%20c0%2C1.1-0.416%2C2.133-1.172%2C2.911c-1.511%2C1.556-4.145%2C1.556-5.656%2C0C2.416%2C9.854%2C2%2C8.821%2C2%2C7.722c0-1.099%2C0.416-2.132%2C1.172-2.91%20c0.39-0.401%2C0.39-1.053%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C0.624%2C4.522%2C0%2C6.073%2C0%2C7.722c0%2C1.649%2C0.624%2C3.2%2C1.757%2C4.366%20C2.891%2C13.254%2C4.397%2C13.896%2C6%2C13.896s3.109-0.643%2C4.243-1.809C11.376%2C10.922%2C12%2C9.371%2C12%2C7.722C12%2C6.073%2C11.376%2C4.522%2C10.243%2C3.356z%20%20M6%2C8c0.553%2C0%2C1-0.447%2C1-1V1c0-0.553-0.447-1-1-1S5%2C0.447%2C5%2C1v6C5%2C7.553%2C5.447%2C8%2C6%2C8z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-recycle:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2212px%22%20viewBox%3D%220%200%2014%2012%22%20style%3D%22enable-background%3Anew%200%200%2014%2012%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M3%2C6h1L2%2C3L0%2C6h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.349V9.445C8.41%2C9.789%2C7.732%2C10%2C7%2C10C4.791%2C10%2C3%2C8.209%2C3%2C6z%20%20M13%2C6c0-3.313-2.687-6-6-6C6.298%2C0%2C5.626%2C0.127%2C5%2C0.349v2.206C5.59%2C2.211%2C6.268%2C2%2C7%2C2c2.209%2C0%2C4%2C1.791%2C4%2C4h-1l2%2C3l2-3H13z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-forward:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12%2C4L8%2C0v3C5%2C3%2C0%2C4%2C0%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L12%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-refresh:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-shop:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M9%2C4V3c0-1.657-1.343-3-3-3S3%2C1.343%2C3%2C3v1H0v10h12V4H9z%20M3.5%2C6C3.224%2C6%2C3%2C5.776%2C3%2C5.5S3.224%2C5%2C3.5%2C5S4%2C5.224%2C4%2C5.5%20S3.776%2C6%2C3.5%2C6z%20M4%2C3c0-1.104%2C0.896-2%2C2-2s2%2C0.896%2C2%2C2v1H4V3z%20M8.5%2C6C8.224%2C6%2C8%2C5.776%2C8%2C5.5S8.224%2C5%2C8.5%2C5S9%2C5.224%2C9%2C5.5%20S8.776%2C6%2C8.5%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-comment:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-star:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2213px%22%20viewBox%3D%220%200%2014%2013%22%20style%3D%22enable-background%3Anew%200%200%2014%2013%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-tag:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-back:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M4%2C3V0L0%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C12%2C4%2C7%2C3%2C4%2C3z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-video:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2210px%22%20viewBox%3D%220%200%2014%2010%22%20style%3D%22enable-background%3Anew%200%200%2014%2010%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alert:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2212px%22%20viewBox%3D%220%200%2014%2012%22%20style%3D%22enable-background%3Anew%200%200%2014%2012%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20fill%3D%22%23FFF%22%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1s1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8C6.447%2C8%2C6%2C7.553%2C6%2C7V5%20c0-0.553%2C0.447-1%2C1-1s1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-delete:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20fill%3D%22%23FFF%22%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+/* Alt icons */\n
+.ui-icon-alt.ui-icon-action:after,\n
+.ui-icon-alt .ui-icon-action:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2213px%22%20viewBox%3D%220%200%2014%2013%22%20style%3D%22enable-background%3Anew%200%200%2014%2013%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M9%2C5v3l5-4L9%2C0v3c0%2C0-5%2C0-5%2C7C6%2C5%2C9%2C5%2C9%2C5z%20M11%2C11H2V5h1l2-2H0v10h13V7l-2%2C2V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-arrow-d:after,\n
+.ui-icon-alt .ui-icon-arrow-d:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%229%2C7%209%2C0%205%2C0%205%2C7%200%2C7%207%2C14%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-arrow-d-l:after,\n
+.ui-icon-alt .ui-icon-arrow-d-l:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%203.5%2C7.5%200%2C4%200%2C14%2010%2C14%206.5%2C10.5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-arrow-d-r:after,\n
+.ui-icon-alt .ui-icon-arrow-d-r:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210.5%2C7.5%203%2C0%200%2C3%207.5%2C10.5%204%2C14%2014%2C14%2014%2C4%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-arrow-l:after,\n
+.ui-icon-alt .ui-icon-arrow-l:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C5%207%2C0%200%2C7%207%2C14%207%2C9%2014%2C9%2014%2C5%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-arrow-r:after,\n
+.ui-icon-alt .ui-icon-arrow-r:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C7%207%2C0%207%2C5%200%2C5%200%2C9%207%2C9%207%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-arrow-u:after,\n
+.ui-icon-alt .ui-icon-arrow-u:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%205%2C7%205%2C14%209%2C14%209%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-arrow-u-l:after,\n
+.ui-icon-alt .ui-icon-arrow-u-l:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C11%206.5%2C3.5%2010%2C0%200%2C0%200%2C10%203.5%2C6.5%2011%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-arrow-u-r:after,\n
+.ui-icon-alt .ui-icon-arrow-u-r:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C0%204%2C0%207.5%2C3.5%200%2C11%203%2C14%2010.5%2C6.5%2014%2C10%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-audio:after,\n
+.ui-icon-alt .ui-icon-audio:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.018px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014.018%2014%22%20style%3D%22enable-background%3Anew%200%200%2014.018%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5v4c0%2C0.553%2C0.447%2C1%2C1%2C1h1l4%2C4V0L2%2C4H1z%20M10.346%2C7c0-1.699-1.042-3.154-2.546-3.867L6.982%2C4.68%20C7.885%2C5.107%2C8.51%2C5.98%2C8.51%2C7S7.885%2C8.893%2C6.982%2C9.32L7.8%2C10.867C9.304%2C10.154%2C10.346%2C8.699%2C10.346%2C7z%20M9.447%2C0.017L8.618%2C1.586%20C10.723%2C2.584%2C12.182%2C4.621%2C12.182%2C7s-1.459%2C4.416-3.563%2C5.414l0.829%2C1.569c2.707-1.283%2C4.57-3.925%2C4.57-6.983%20S12.154%2C1.3%2C9.447%2C0.017z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-calendar:after,\n
+.ui-icon-alt .ui-icon-calendar:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C8h2V6H0V8z%20M3%2C8h2V6H3V8z%20M6%2C8h2V6H6V8z%20M9%2C8h2V6H9V8z%20M12%2C8h2V6h-2V8z%20M0%2C11h2V9H0V11z%20M3%2C11h2V9H3V11z%20M6%2C11h2V9H6V11z%20%20M9%2C11h2V9H9V11z%20M12%2C11h2V9h-2V11z%20M0%2C14h2v-2H0V14z%20M3%2C14h2v-2H3V14z%20M6%2C14h2v-2H6V14z%20M9%2C14h2v-2H9V14z%20M12%2C1%20c0-0.553-0.447-1-1-1s-1%2C0.447-1%2C1H4c0-0.553-0.447-1-1-1S2%2C0.447%2C2%2C1H0v4h14V1H12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-camera:after,\n
+.ui-icon-alt .ui-icon-camera:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2211px%22%20viewBox%3D%220%200%2014%2011%22%20style%3D%22enable-background%3Anew%200%200%2014%2011%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C1H9.908C9.702%2C0.419%2C9.152%2C0%2C8.5%2C0h-3C4.848%2C0%2C4.298%2C0.419%2C4.092%2C1H2C0.896%2C1%2C0%2C1.896%2C0%2C3v6c0%2C1.104%2C0.896%2C2%2C2%2C2h10%20c1.104%2C0%2C2-0.896%2C2-2V3C14%2C1.896%2C13.104%2C1%2C12%2C1z%20M7%2C9C5.343%2C9%2C4%2C7.657%2C4%2C6s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C9%2C7%2C9z%20M7%2C4%20C5.896%2C4%2C5%2C4.896%2C5%2C6s0.896%2C2%2C2%2C2s2-0.896%2C2-2S8.104%2C4%2C7%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-carat-d:after,\n
+.ui-icon-alt .ui-icon-carat-d:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%228px%22%20viewBox%3D%220%200%2012%208%22%20style%3D%22enable-background%3Anew%200%200%2012%208%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2210%2C0%206%2C4%202%2C0%200%2C2%206%2C8%2012%2C2%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-carat-l:after,\n
+.ui-icon-alt .ui-icon-carat-l:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%228px%22%20height%3D%2212px%22%20viewBox%3D%220%200%208%2012%22%20style%3D%22enable-background%3Anew%200%200%208%2012%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%228%2C2%206%2C0%200%2C6%206%2C12%208%2C10%204%2C6%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-carat-r:after,\n
+.ui-icon-alt .ui-icon-carat-r:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%228px%22%20height%3D%2212px%22%20viewBox%3D%220%200%208%2012%22%20style%3D%22enable-background%3Anew%200%200%208%2012%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%222%2C0%200%2C2%204%2C6%200%2C10%202%2C12%208%2C6%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-carat-u:after,\n
+.ui-icon-alt .ui-icon-carat-u:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%228px%22%20viewBox%3D%220%200%2012%208%22%20style%3D%22enable-background%3Anew%200%200%2012%208%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%226%2C0%200%2C6%202%2C8%206%2C4%2010%2C8%2012%2C6%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-check:after,\n
+.ui-icon-alt .ui-icon-check:after,\n
+.ui-icon-alt.ui-icon-checkbox-on:after,\n
+.ui-icon-alt .ui-icon-checkbox-on:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2212px%22%20viewBox%3D%220%200%2014%2012%22%20style%3D%22enable-background%3Anew%200%200%2014%2012%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%205.003%2C5.997%203%2C4%200%2C7%204.966%2C12%204.983%2C11.983%205%2C12%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-clock:after,\n
+.ui-icon-alt .ui-icon-clock:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C12c-2.762%2C0-5-2.238-5-5s2.238-5%2C5-5s5%2C2.238%2C5%2C5%20S9.762%2C12%2C7%2C12z%20M9%2C6H8V4c0-0.553-0.447-1-1-1S6%2C3.447%2C6%2C4v3c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1S9.553%2C6%2C9%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-cloud:after,\n
+.ui-icon-alt .ui-icon-cloud:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%229px%22%20viewBox%3D%220%200%2014%209%22%20style%3D%22enable-background%3Anew%200%200%2014%209%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14%2C7c0-0.793-0.465-1.472-1.134-1.795C12.949%2C4.984%2C13%2C4.749%2C13%2C4.5c0-1.104-0.896-2-2-2c-0.158%2C0-0.31%2C0.023-0.457%2C0.058%20C9.816%2C1.049%2C8.286%2C0%2C6.5%2C0C4.17%2C0%2C2.276%2C1.777%2C2.046%2C4.046C0.883%2C4.26%2C0%2C5.274%2C0%2C6.5C0%2C7.881%2C1.119%2C9%2C2.5%2C9h10V8.93%20C13.361%2C8.706%2C14%2C7.931%2C14%2C7z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-grid:after,\n
+.ui-icon-alt .ui-icon-grid:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C0H1C0.447%2C0%2C0%2C0.447%2C0%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C4%2C0.447%2C3.553%2C0%2C3%2C0z%20M8%2C0H6%20C5.447%2C0%2C5%2C0.447%2C5%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C9%2C0.447%2C8.553%2C0%2C8%2C0z%20M13%2C0h-2c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V1C14%2C0.447%2C13.553%2C0%2C13%2C0z%20M3%2C5H1C0.447%2C5%2C0%2C5.447%2C0%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1V6C4%2C5.447%2C3.553%2C5%2C3%2C5z%20M8%2C5H6C5.447%2C5%2C5%2C5.447%2C5%2C6v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6%20C9%2C5.447%2C8.553%2C5%2C8%2C5z%20M13%2C5h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1V6C14%2C5.447%2C13.553%2C5%2C13%2C5z%20M3%2C10%20H1c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C4%2C10.447%2C3.553%2C10%2C3%2C10z%20M8%2C10H6c-0.553%2C0-1%2C0.447-1%2C1v2%20c0%2C0.553%2C0.447%2C1%2C1%2C1h2c0.553%2C0%2C1-0.447%2C1-1v-2C9%2C10.447%2C8.553%2C10%2C8%2C10z%20M13%2C10h-2c-0.553%2C0-1%2C0.447-1%2C1v2c0%2C0.553%2C0.447%2C1%2C1%2C1h2%20c0.553%2C0%2C1-0.447%2C1-1v-2C14%2C10.447%2C13.553%2C10%2C13%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-mail:after,\n
+.ui-icon-alt .ui-icon-mail:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2210px%22%20viewBox%3D%220%200%2014%2010%22%20style%3D%22enable-background%3Anew%200%200%2014%2010%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M0%2C1.75V10h14V1.75L7%2C7L0%2C1.75z%20M14%2C0H0l7%2C5L14%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-eye:after,\n
+.ui-icon-alt .ui-icon-eye:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2210px%22%20viewBox%3D%220%200%2014%2010%22%20style%3D%22enable-background%3Anew%200%200%2014%2010%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3%2C0%2C0%2C5%2C0%2C5s3%2C5%2C7%2C5s7-5%2C7-5S11%2C0%2C7%2C0z%20M7%2C8C5.343%2C8%2C4%2C6.657%2C4%2C5s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C8%2C7%2C8z%20M7%2C4%20C6.448%2C4%2C6%2C4.447%2C6%2C5s0.448%2C1%2C1%2C1s1-0.447%2C1-1S7.552%2C4%2C7%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-gear:after,\n
+.ui-icon-alt .ui-icon-gear:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M13.621%2C5.904l-1.036-0.259c-0.168-0.042-0.303-0.168-0.355-0.332c-0.092-0.284-0.205-0.559-0.339-0.82%20c-0.079-0.153-0.073-0.337%2C0.017-0.486l0.549-0.915c0.118-0.196%2C0.088-0.448-0.075-0.61l-0.862-0.863%20c-0.162-0.163-0.414-0.193-0.611-0.075l-0.916%2C0.55C9.844%2C2.182%2C9.659%2C2.188%2C9.506%2C2.109C9.244%2C1.975%2C8.97%2C1.861%2C8.686%2C1.77%20c-0.165-0.052-0.29-0.187-0.332-0.354L8.095%2C0.379C8.039%2C0.156%2C7.839%2C0%2C7.609%2C0H6.391c-0.229%2C0-0.43%2C0.156-0.485%2C0.379L5.646%2C1.415%20C5.604%2C1.582%2C5.479%2C1.718%2C5.313%2C1.77c-0.284%2C0.092-0.559%2C0.206-0.82%2C0.34C4.339%2C2.188%2C4.155%2C2.182%2C4.007%2C2.093L3.092%2C1.544%20c-0.196-0.118-0.448-0.087-0.61%2C0.075L1.619%2C2.481C1.457%2C2.644%2C1.426%2C2.896%2C1.544%2C3.093l0.549%2C0.914%20c0.089%2C0.148%2C0.095%2C0.332%2C0.017%2C0.486C1.975%2C4.755%2C1.861%2C5.029%2C1.77%2C5.314c-0.053%2C0.164-0.188%2C0.29-0.354%2C0.332L0.379%2C5.905%20C0.156%2C5.961%2C0%2C6.161%2C0%2C6.391v1.219c0%2C0.229%2C0.156%2C0.43%2C0.379%2C0.485l1.036%2C0.26C1.582%2C8.396%2C1.717%2C8.521%2C1.77%2C8.687%20c0.092%2C0.284%2C0.205%2C0.559%2C0.34%2C0.82C2.188%2C9.66%2C2.182%2C9.844%2C2.093%2C9.993l-0.549%2C0.915c-0.118%2C0.195-0.087%2C0.448%2C0.075%2C0.61%20l0.862%2C0.862c0.162%2C0.163%2C0.414%2C0.193%2C0.61%2C0.075l0.915-0.549c0.148-0.089%2C0.332-0.095%2C0.486-0.017%20c0.262%2C0.135%2C0.536%2C0.248%2C0.82%2C0.34c0.165%2C0.053%2C0.291%2C0.187%2C0.332%2C0.354l0.259%2C1.036C5.96%2C13.844%2C6.16%2C14%2C6.39%2C14h1.22%20c0.229%2C0%2C0.43-0.156%2C0.485-0.379l0.259-1.036c0.042-0.167%2C0.168-0.302%2C0.333-0.354c0.284-0.092%2C0.559-0.205%2C0.82-0.34%20c0.154-0.078%2C0.338-0.072%2C0.486%2C0.017l0.914%2C0.549c0.197%2C0.118%2C0.449%2C0.088%2C0.611-0.074l0.862-0.863%20c0.163-0.162%2C0.193-0.415%2C0.075-0.611l-0.549-0.915c-0.089-0.148-0.096-0.332-0.017-0.485c0.134-0.263%2C0.248-0.536%2C0.339-0.82%20c0.053-0.165%2C0.188-0.291%2C0.355-0.333l1.036-0.259C13.844%2C8.039%2C14%2C7.839%2C14%2C7.609V6.39C14%2C6.16%2C13.844%2C5.96%2C13.621%2C5.904z%20M7%2C10%20c-1.657%2C0-3-1.343-3-3s1.343-3%2C3-3s3%2C1.343%2C3%2C3S8.657%2C10%2C7%2C10z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-heart:after,\n
+.ui-icon-alt .ui-icon-heart:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2213.744px%22%20viewBox%3D%220%200%2014%2013.744%22%20style%3D%22enable-background%3Anew%200%200%2014%2013.744%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C1.744c-2-3-7-2-7%2C2c0%2C3%2C4%2C7%2C4%2C7s2.417%2C2.479%2C3%2C3c0.583-0.521%2C3-3%2C3-3s4-4%2C4-7C14-0.256%2C9-1.256%2C7%2C1.744z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-home:after,\n
+.ui-icon-alt .ui-icon-home:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%227%2C0%200%2C7%202%2C7%202%2C14%205%2C14%205%2C9%209%2C9%209%2C14%2012%2C14%2012%2C7%2014%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-info:after,\n
+.ui-icon-alt .ui-icon-info:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0C3.134%2C0%2C0%2C3.134%2C0%2C7s3.134%2C7%2C7%2C7s7-3.134%2C7-7S10.866%2C0%2C7%2C0z%20M7%2C2c0.552%2C0%2C1%2C0.447%2C1%2C1S7.552%2C4%2C7%2C4S6%2C3.553%2C6%2C3%20S6.448%2C2%2C7%2C2z%20M9%2C11H5v-1h1V6H5V5h3v5h1V11z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-bars:after,\n
+.ui-icon-alt .ui-icon-bars:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2210px%22%20viewBox%3D%220%200%2014%2010%22%20style%3D%22enable-background%3Anew%200%200%2014%2010%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C2h12c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H1C0.447%2C0%2C0%2C0.447%2C0%2C1S0.447%2C2%2C1%2C2z%20M13%2C4H1C0.447%2C4%2C0%2C4.447%2C0%2C5s0.447%2C1%2C1%2C1h12%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C4%2C13%2C4z%20M13%2C8H1C0.447%2C8%2C0%2C8.447%2C0%2C9s0.447%2C1%2C1%2C1h12c0.553%2C0%2C1-0.447%2C1-1S13.553%2C8%2C13%2C8z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-bullets:after,\n
+.ui-icon-alt .ui-icon-bullets:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2210px%22%20viewBox%3D%220%200%2014%2010%22%20style%3D%22enable-background%3Anew%200%200%2014%2010%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C2h8c0.553%2C0%2C1-0.447%2C1-1s-0.447-1-1-1H5C4.447%2C0%2C4%2C0.447%2C4%2C1S4.447%2C2%2C5%2C2z%20M13%2C4H5C4.447%2C4%2C4%2C4.447%2C4%2C5s0.447%2C1%2C1%2C1h8%20c0.553%2C0%2C1-0.447%2C1-1S13.553%2C4%2C13%2C4z%20M13%2C8H5C4.447%2C8%2C4%2C8.447%2C4%2C9s0.447%2C1%2C1%2C1h8c0.553%2C0%2C1-0.447%2C1-1S13.553%2C8%2C13%2C8z%20M1%2C0%20C0.447%2C0%2C0%2C0.447%2C0%2C1s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C0%2C1%2C0z%20M1%2C4C0.447%2C4%2C0%2C4.447%2C0%2C5s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C4%2C1%2C4z%20M1%2C8%20C0.447%2C8%2C0%2C8.447%2C0%2C9s0.447%2C1%2C1%2C1s1-0.447%2C1-1S1.553%2C8%2C1%2C8z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-navigation:after,\n
+.ui-icon-alt .ui-icon-navigation:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C0%200%2C6%208%2C6%208%2C14%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-lock:after,\n
+.ui-icon-alt .ui-icon-lock:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M11%2C6V5c0-2.762-2.239-5-5-5S1%2C2.238%2C1%2C5v1H0v8h12V6H11z%20M6.5%2C9.847V12h-1V9.847C5.207%2C9.673%2C5%2C9.366%2C5%2C9%20c0-0.553%2C0.448-1%2C1-1s1%2C0.447%2C1%2C1C7%2C9.366%2C6.793%2C9.673%2C6.5%2C9.847z%20M9%2C6H3V5c0-1.657%2C1.343-3%2C3-3s3%2C1.343%2C3%2C3V6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-search:after,\n
+.ui-icon-alt .ui-icon-search:after,\n
+.ui-input-search:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2213.701px%22%20height%3D%2213.721px%22%20viewBox%3D%220%200%2013.701%2013.721%22%20style%3D%22enable-background%3Anew%200%200%2013.701%2013.721%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10.021%2C8.626C10.638%2C7.738%2C11%2C6.662%2C11%2C5.5C11%2C2.463%2C8.537%2C0%2C5.5%2C0S0%2C2.463%2C0%2C5.5S2.463%2C11%2C5.5%2C11%20c1.152%2C0%2C2.221-0.356%2C3.105-0.962l3.682%2C3.683l1.414-1.414L10.021%2C8.626z%20M5.5%2C9C3.567%2C9%2C2%2C7.433%2C2%2C5.5S3.567%2C2%2C5.5%2C2S9%2C3.567%2C9%2C5.5%20S7.433%2C9%2C5.5%2C9z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-location:after,\n
+.ui-icon-alt .ui-icon-location:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%228px%22%20height%3D%2214px%22%20viewBox%3D%220%200%208%2014%22%20style%3D%22enable-background%3Anew%200%200%208%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M4%2C0C1.791%2C0%2C0%2C1.791%2C0%2C4c0%2C2%2C4%2C10%2C4%2C10S8%2C6%2C8%2C4C8%2C1.791%2C6.209%2C0%2C4%2C0z%20M4%2C6C2.896%2C6%2C2%2C5.104%2C2%2C4s0.896-2%2C2-2s2%2C0.896%2C2%2C2%20S5.104%2C6%2C4%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-minus:after,\n
+.ui-icon-alt .ui-icon-minus:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%224px%22%20viewBox%3D%220%200%2014%204%22%20style%3D%22enable-background%3Anew%200%200%2014%204%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Crect%20width%3D%2214%22%20height%3D%224%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-forbidden:after,\n
+.ui-icon-alt .ui-icon-forbidden:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12.601%2C11.187C13.476%2C10.018%2C14%2C8.572%2C14%2C7c0-3.866-3.134-7-7-7C5.428%2C0%2C3.982%2C0.524%2C2.813%2C1.399L2.757%2C1.343L2.053%2C2.048%20L2.048%2C2.053L1.343%2C2.758l0.056%2C0.056C0.524%2C3.982%2C0%2C5.428%2C0%2C7c0%2C3.866%2C3.134%2C7%2C7%2C7c1.572%2C0%2C3.018-0.524%2C4.187-1.399l0.056%2C0.057%20l0.705-0.705l0.005-0.005l0.705-0.705L12.601%2C11.187z%20M7%2C2c2.761%2C0%2C5%2C2.238%2C5%2C5c0%2C1.019-0.308%2C1.964-0.832%2C2.754L4.246%2C2.832%20C5.036%2C2.308%2C5.981%2C2%2C7%2C2z%20M7%2C12c-2.761%2C0-5-2.238-5-5c0-1.019%2C0.308-1.964%2C0.832-2.754l6.922%2C6.922C8.964%2C11.692%2C8.019%2C12%2C7%2C12z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-edit:after,\n
+.ui-icon-alt .ui-icon-edit:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M1%2C10l-1%2C4l4-1l7-7L8%2C3L1%2C10z%20M11%2C0L9%2C2l3%2C3l2-2L11%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-user:after,\n
+.ui-icon-alt .ui-icon-user:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8.851%2C10.101c-0.18-0.399-0.2-0.763-0.153-1.104C9.383%2C8.49%2C9.738%2C7.621%2C9.891%2C6.465C10.493%2C6.355%2C10.5%2C5.967%2C10.5%2C5.5%20c0-0.437-0.008-0.804-0.502-0.94C9.999%2C4.539%2C10%2C4.521%2C10%2C4.5c0-2.103-1-4-2-4C8%2C0.5%2C7.5%2C0%2C6.5%2C0C5%2C0%2C4%2C1.877%2C4%2C4.5%20c0%2C0.021%2C0.001%2C0.039%2C0.002%2C0.06C3.508%2C4.696%2C3.5%2C5.063%2C3.5%2C5.5c0%2C0.467%2C0.007%2C0.855%2C0.609%2C0.965%20C4.262%2C7.621%2C4.617%2C8.49%2C5.303%2C8.997c0.047%2C0.341%2C0.026%2C0.704-0.153%2C1.104C1.503%2C10.503%2C0%2C12%2C0%2C12v2h14v-2%20C14%2C12%2C12.497%2C10.503%2C8.851%2C10.101z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-phone:after,\n
+.ui-icon-alt .ui-icon-phone:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2213.979px%22%20height%3D%2214.016px%22%20viewBox%3D%220%200%2013.979%2014.016%22%20style%3D%22enable-background%3Anew%200%200%2013.979%2014.016%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M6.939%2C9.189C6.165%2C8.557%2C5.271%2C7.705%2C4.497%2C6.744C3.953%2C6.071%2C3.473%2C5.363%2C3.969%2C4.866l-3.482-3.48%20C-0.021%2C2.02-1.146%2C5.04%2C3.675%2C9.984c5.08%2C5.211%2C8.356%2C4.096%2C8.92%2C3.51l-3.396-3.4C8.725%2C10.568%2C8.113%2C10.146%2C6.939%2C9.189z%20%20M13.82%2C11.519v-0.004c0%2C0-2.649-2.646-2.65-2.648c-0.21-0.21-0.546-0.205-0.754%2C0.002L9.455%2C9.831l3.404%2C3.408%20c0%2C0%2C0.962-0.96%2C0.961-0.961l0.002-0.001C14.043%2C12.056%2C14.021%2C11.721%2C13.82%2C11.519z%20M5.192%2C3.644V3.642%20c0.221-0.222%2C0.2-0.557%2C0-0.758V2.881c0%2C0-2.726-2.724-2.727-2.725C2.255-0.055%2C1.92-0.05%2C1.712%2C0.157L0.751%2C1.121l3.48%2C3.483%20C4.231%2C4.604%2C5.192%2C3.645%2C5.192%2C3.644z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-plus:after,\n
+.ui-icon-alt .ui-icon-plus:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%209%2C0%205%2C0%205%2C5%200%2C5%200%2C9%205%2C9%205%2C14%209%2C14%209%2C9%2014%2C9%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-power:after,\n
+.ui-icon-alt .ui-icon-power:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2213.896px%22%20viewBox%3D%220%200%2012%2013.896%22%20style%3D%22enable-background%3Anew%200%200%2012%2013.896%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M10.243%2C3.356c-0.392-0.401-1.024-0.401-1.415%2C0c-0.39%2C0.402-0.39%2C1.054%2C0%2C1.455C9.584%2C5.59%2C10%2C6.623%2C10%2C7.722%20c0%2C1.1-0.416%2C2.133-1.172%2C2.911c-1.511%2C1.556-4.145%2C1.556-5.656%2C0C2.416%2C9.854%2C2%2C8.821%2C2%2C7.722c0-1.099%2C0.416-2.132%2C1.172-2.91%20c0.39-0.401%2C0.39-1.053%2C0-1.455c-0.391-0.401-1.024-0.401-1.415%2C0C0.624%2C4.522%2C0%2C6.073%2C0%2C7.722c0%2C1.649%2C0.624%2C3.2%2C1.757%2C4.366%20C2.891%2C13.254%2C4.397%2C13.896%2C6%2C13.896s3.109-0.643%2C4.243-1.809C11.376%2C10.922%2C12%2C9.371%2C12%2C7.722C12%2C6.073%2C11.376%2C4.522%2C10.243%2C3.356z%20%20M6%2C8c0.553%2C0%2C1-0.447%2C1-1V1c0-0.553-0.447-1-1-1S5%2C0.447%2C5%2C1v6C5%2C7.553%2C5.447%2C8%2C6%2C8z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-recycle:after,\n
+.ui-icon-alt .ui-icon-recycle:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2212px%22%20viewBox%3D%220%200%2014%2012%22%20style%3D%22enable-background%3Anew%200%200%2014%2012%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M3%2C6h1L2%2C3L0%2C6h1c0%2C3.313%2C2.687%2C6%2C6%2C6c0.702%2C0%2C1.374-0.127%2C2-0.349V9.445C8.41%2C9.789%2C7.732%2C10%2C7%2C10C4.791%2C10%2C3%2C8.209%2C3%2C6z%20%20M13%2C6c0-3.313-2.687-6-6-6C6.298%2C0%2C5.626%2C0.127%2C5%2C0.349v2.206C5.59%2C2.211%2C6.268%2C2%2C7%2C2c2.209%2C0%2C4%2C1.791%2C4%2C4h-1l2%2C3l2-3H13z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-forward:after,\n
+.ui-icon-alt .ui-icon-forward:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C4L8%2C0v3C5%2C3%2C0%2C4%2C0%2C8c0%2C5%2C7%2C6%2C7%2C6v-2c0%2C0-5-1-5-4s6-3%2C6-3v3L12%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-refresh:after,\n
+.ui-icon-alt .ui-icon-refresh:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214.001px%22%20height%3D%2214.002px%22%20viewBox%3D%220%200%2014.001%2014.002%22%20style%3D%22enable-background%3Anew%200%200%2014.001%2014.002%3B%22%20%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M14.001%2C6.001v-6l-2.06%2C2.06c-0.423-0.424-0.897-0.809-1.44-1.122C7.153-0.994%2C2.872%2C0.153%2C0.939%2C3.501%20c-1.933%2C3.348-0.786%2C7.629%2C2.562%2C9.562c3.348%2C1.933%2C7.629%2C0.785%2C9.562-2.562l-1.732-1c-1.381%2C2.392-4.438%2C3.211-6.83%2C1.83%20s-3.211-4.438-1.83-6.83s4.438-3.211%2C6.83-1.83c0.389%2C0.225%2C0.718%2C0.506%2C1.02%2C0.81l-2.52%2C2.52H14.001z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-shop:after,\n
+.ui-icon-alt .ui-icon-shop:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M9%2C4V3c0-1.657-1.343-3-3-3S3%2C1.343%2C3%2C3v1H0v10h12V4H9z%20M3.5%2C6C3.224%2C6%2C3%2C5.776%2C3%2C5.5S3.224%2C5%2C3.5%2C5S4%2C5.224%2C4%2C5.5%20S3.776%2C6%2C3.5%2C6z%20M4%2C3c0-1.104%2C0.896-2%2C2-2s2%2C0.896%2C2%2C2v1H4V3z%20M8.5%2C6C8.224%2C6%2C8%2C5.776%2C8%2C5.5S8.224%2C5%2C8.5%2C5S9%2C5.224%2C9%2C5.5%20S8.776%2C6%2C8.5%2C6z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-comment:after,\n
+.ui-icon-alt .ui-icon-comment:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M12%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v7c0%2C1.104%2C0.896%2C2%2C2%2C2h1v3l3-3h6c1.104%2C0%2C2-0.896%2C2-2V2C14%2C0.896%2C13.104%2C0%2C12%2C0z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-star:after,\n
+.ui-icon-alt .ui-icon-star:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2213px%22%20viewBox%3D%220%200%2014%2013%22%20style%3D%22enable-background%3Anew%200%200%2014%2013%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C5%209%2C5%207%2C0%205%2C5%200%2C5%204%2C8%202.625%2C13%207%2C10%2011.375%2C13%2010%2C8%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-tag:after,\n
+.ui-icon-alt .ui-icon-tag:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M5%2C0H0v5l9%2C9l5-5L5%2C0z%20M3%2C4C2.447%2C4%2C2%2C3.553%2C2%2C3s0.447-1%2C1-1s1%2C0.447%2C1%2C1S3.553%2C4%2C3%2C4z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-back:after,\n
+.ui-icon-alt .ui-icon-back:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2212px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2012%2014%22%20style%3D%22enable-background%3Anew%200%200%2012%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M4%2C3V0L0%2C4l4%2C4V5c0%2C0%2C6%2C0%2C6%2C3s-5%2C4-5%2C4v2c0%2C0%2C7-1%2C7-6C12%2C4%2C7%2C3%2C4%2C3z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-video:after,\n
+.ui-icon-alt .ui-icon-video:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2210px%22%20viewBox%3D%220%200%2014%2010%22%20style%3D%22enable-background%3Anew%200%200%2014%2010%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M8%2C0H2C0.896%2C0%2C0%2C0.896%2C0%2C2v6c0%2C1.104%2C0.896%2C2%2C2%2C2h6c1.104%2C0%2C2-0.896%2C2-2V5V2C10%2C0.896%2C9.104%2C0%2C8%2C0z%20M10%2C5l4%2C4V1L10%2C5z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-alert:after,\n
+.ui-icon-alt .ui-icon-alert:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2212px%22%20viewBox%3D%220%200%2014%2012%22%20style%3D%22enable-background%3Anew%200%200%2014%2012%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpath%20d%3D%22M7%2C0L0%2C12h14L7%2C0z%20M7%2C11c-0.553%2C0-1-0.447-1-1s0.447-1%2C1-1s1%2C0.447%2C1%2C1S7.553%2C11%2C7%2C11z%20M7%2C8C6.447%2C8%2C6%2C7.553%2C6%2C7V5%20c0-0.553%2C0.447-1%2C1-1s1%2C0.447%2C1%2C1v2C8%2C7.553%2C7.553%2C8%2C7%2C8z%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+.ui-icon-alt.ui-icon-delete:after,\n
+.ui-icon-alt .ui-icon-delete:after {\n
+\tbackground-image: url(\'data:image/svg+xml;charset=US-ASCII,%3C%3Fxml%20version%3D%221.0%22%20encoding%3D%22iso-8859-1%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E%3Csvg%20version%3D%221.1%22%20id%3D%22Layer_1%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20xmlns%3Axlink%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxlink%22%20x%3D%220px%22%20y%3D%220px%22%20%20width%3D%2214px%22%20height%3D%2214px%22%20viewBox%3D%220%200%2014%2014%22%20style%3D%22enable-background%3Anew%200%200%2014%2014%3B%22%20xml%3Aspace%3D%22preserve%22%3E%3Cpolygon%20points%3D%2214%2C3%2011%2C0%207%2C4%203%2C0%200%2C3%204%2C7%200%2C11%203%2C14%207%2C10%2011%2C14%2014%2C11%2010%2C7%20%22%2F%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3Cg%3E%3C%2Fg%3E%3C%2Fsvg%3E\');\n
+}\n
+/* PNG icons */\n
+.ui-nosvg .ui-icon-action:after {\n
+\tbackground-image: url(images/icons-png/action-white.png);\n
+}\n
+.ui-nosvg .ui-icon-arrow-d-l:after {\n
+\tbackground-image: url(images/icons-png/arrow-d-l-white.png);\n
+}\n
+.ui-nosvg .ui-icon-arrow-d-r:after {\n
+\tbackground-image: url(images/icons-png/arrow-d-r-white.png);\n
+}\n
+.ui-nosvg .ui-icon-arrow-d:after {\n
+\tbackground-image: url(images/icons-png/arrow-d-white.png);\n
+}\n
+.ui-nosvg .ui-icon-arrow-l:after {\n
+\tbackground-image: url(images/icons-png/arrow-l-white.png);\n
+}\n
+.ui-nosvg .ui-icon-arrow-r:after {\n
+\tbackground-image: url(images/icons-png/arrow-r-white.png);\n
+}\n
+.ui-nosvg .ui-icon-arrow-u-l:after {\n
+\tbackground-image: url(images/icons-png/arrow-u-l-white.png);\n
+}\n
+.ui-nosvg .ui-icon-arrow-u-r:after {\n
+\tbackground-image: url(images/icons-png/arrow-u-r-white.png);\n
+}\n
+.ui-nosvg .ui-icon-arrow-u:after {\n
+\tbackground-image: url(images/icons-png/arrow-u-white.png);\n
+}\n
+.ui-nosvg .ui-icon-audio:after {\n
+\tbackground-image: url(images/icons-png/audio-white.png);\n
+}\n
+.ui-nosvg .ui-icon-calendar:after {\n
+\tbackground-image: url(images/icons-png/calendar-white.png);\n
+}\n
+.ui-nosvg .ui-icon-camera:after {\n
+\tbackground-image: url(images/icons-png/camera-white.png);\n
+}\n
+.ui-nosvg .ui-icon-carat-d:after {\n
+\tbackground-image: url(images/icons-png/carat-d-white.png);\n
+}\n
+.ui-nosvg .ui-icon-carat-l:after {\n
+\tbackground-image: url(images/icons-png/carat-l-white.png);\n
+}\n
+.ui-nosvg .ui-icon-carat-r:after {\n
+\tbackground-image: url(images/icons-png/carat-r-white.png);\n
+}\n
+.ui-nosvg .ui-icon-carat-u:after {\n
+\tbackground-image: url(images/icons-png/carat-u-white.png);\n
+}\n
+.ui-nosvg .ui-icon-check:after,\n
+.ui-nosvg .ui-icon-checkbox-on:after {\n
+\tbackground-image: url(images/icons-png/check-white.png);\n
+}\n
+.ui-nosvg .ui-icon-clock:after {\n
+\tbackground-image: url(images/icons-png/clock-white.png);\n
+}\n
+.ui-nosvg .ui-icon-cloud:after {\n
+\tbackground-image: url(images/icons-png/cloud-white.png);\n
+}\n
+.ui-nosvg .ui-icon-grid:after {\n
+\tbackground-image: url(images/icons-png/grid-white.png);\n
+}\n
+.ui-nosvg .ui-icon-mail:after {\n
+\tbackground-image: url(images/icons-png/mail-white.png);\n
+}\n
+.ui-nosvg .ui-icon-eye:after {\n
+\tbackground-image: url(images/icons-png/eye-white.png);\n
+}\n
+.ui-nosvg .ui-icon-gear:after {\n
+\tbackground-image: url(images/icons-png/gear-white.png);\n
+}\n
+.ui-nosvg .ui-icon-heart:after {\n
+\tbackground-image: url(images/icons-png/heart-white.png);\n
+}\n
+.ui-nosvg .ui-icon-home:after {\n
+\tbackground-image: url(images/icons-png/home-white.png);\n
+}\n
+.ui-nosvg .ui-icon-info:after {\n
+\tbackground-image: url(images/icons-png/info-white.png);\n
+}\n
+.ui-nosvg .ui-icon-bullets:after {\n
+\tbackground-image: url(images/icons-png/bullets-white.png);\n
+}\n
+.ui-nosvg .ui-icon-bars:after {\n
+\tbackground-image: url(images/icons-png/bars-white.png);\n
+}\n
+.ui-nosvg .ui-icon-navigation:after {\n
+\tbackground-image: url(images/icons-png/navigation-white.png);\n
+}\n
+.ui-nosvg .ui-icon-lock:after {\n
+\tbackground-image: url(images/icons-png/lock-white.png);\n
+}\n
+.ui-nosvg .ui-icon-search:after {\n
+\tbackground-image: url(images/icons-png/search-white.png);\n
+}\n
+.ui-nosvg .ui-icon-location:after {\n
+\tbackground-image: url(images/icons-png/location-white.png);\n
+}\n
+.ui-nosvg .ui-icon-minus:after {\n
+\tbackground-image: url(images/icons-png/minus-white.png);\n
+}\n
+.ui-nosvg .ui-icon-forbidden:after {\n
+\tbackground-image: url(images/icons-png/forbidden-white.png);\n
+}\n
+.ui-nosvg .ui-icon-edit:after {\n
+\tbackground-image: url(images/icons-png/edit-white.png);\n
+}\n
+.ui-nosvg .ui-icon-user:after {\n
+\tbackground-image: url(images/icons-png/user-white.png);\n
+}\n
+.ui-nosvg .ui-icon-phone:after {\n
+\tbackground-image: url(images/icons-png/phone-white.png);\n
+}\n
+.ui-nosvg .ui-icon-plus:after {\n
+\tbackground-image: url(images/icons-png/plus-white.png);\n
+}\n
+.ui-nosvg .ui-icon-power:after {\n
+\tbackground-image: url(images/icons-png/power-white.png);\n
+}\n
+.ui-nosvg .ui-icon-recycle:after {\n
+\tbackground-image: url(images/icons-png/recycle-white.png);\n
+}\n
+.ui-nosvg .ui-icon-forward:after {\n
+\tbackground-image: url(images/icons-png/forward-white.png);\n
+}\n
+.ui-nosvg .ui-icon-refresh:after {\n
+\tbackground-image: url(images/icons-png/refresh-white.png);\n
+}\n
+.ui-nosvg .ui-icon-shop:after {\n
+\tbackground-image: url(images/icons-png/shop-white.png);\n
+}\n
+.ui-nosvg .ui-icon-comment:after {\n
+\tbackground-image: url(images/icons-png/comment-white.png);\n
+}\n
+.ui-nosvg .ui-icon-star:after {\n
+\tbackground-image: url(images/icons-png/star-white.png);\n
+}\n
+.ui-nosvg .ui-icon-tag:after {\n
+\tbackground-image: url(images/icons-png/tag-white.png);\n
+}\n
+.ui-nosvg .ui-icon-back:after {\n
+\tbackground-image: url(images/icons-png/back-white.png);\n
+}\n
+.ui-nosvg .ui-icon-video:after {\n
+\tbackground-image: url(images/icons-png/video-white.png);\n
+}\n
+.ui-nosvg .ui-icon-alert:after {\n
+\tbackground-image: url(images/icons-png/alert-white.png);\n
+}\n
+.ui-nosvg .ui-icon-delete:after {\n
+\tbackground-image: url(images/icons-png/delete-white.png);\n
+}\n
+/* Alt icons */\n
+.ui-nosvg .ui-icon-alt.ui-icon-action:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-action:after {\n
+\tbackground-image: url(images/icons-png/action-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-arrow-d:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-arrow-d:after {\n
+\tbackground-image: url(images/icons-png/arrow-d-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-arrow-d-l:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-arrow-d-l:after {\n
+\tbackground-image: url(images/icons-png/arrow-d-l-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-arrow-d-r:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-arrow-d-r:after {\n
+\tbackground-image: url(images/icons-png/arrow-d-r-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-arrow-l:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-arrow-l:after {\n
+\tbackground-image: url(images/icons-png/arrow-l-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-arrow-r:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-arrow-r:after {\n
+\tbackground-image: url(images/icons-png/arrow-r-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-arrow-u:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-arrow-u:after {\n
+\tbackground-image: url(images/icons-png/arrow-u-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-arrow-u-l:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-arrow-u-l:after {\n
+\tbackground-image: url(images/icons-png/arrow-u-l-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-arrow-u-r:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-arrow-u-r:after {\n
+\tbackground-image: url(images/icons-png/arrow-u-r-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-audio:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-audio:after {\n
+\tbackground-image: url(images/icons-png/audio-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-calendar:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-calendar:after {\n
+\tbackground-image: url(images/icons-png/calendar-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-camera:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-camera:after {\n
+\tbackground-image: url(images/icons-png/camera-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-carat-d:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-carat-d:after {\n
+\tbackground-image: url(images/icons-png/carat-d-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-carat-l:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-carat-l:after {\n
+\tbackground-image: url(images/icons-png/carat-l-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-carat-r:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-carat-r:after {\n
+\tbackground-image: url(images/icons-png/carat-r-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-carat-u:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-carat-u:after {\n
+\tbackground-image: url(images/icons-png/carat-u-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-check:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-check:after,\n
+.ui-nosvg .ui-icon-alt.ui-icon-checkbox-on:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-checkbox-on:after {\n
+\tbackground-image: url(images/icons-png/check-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-clock:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-clock:after {\n
+\tbackground-image: url(images/icons-png/clock-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-cloud:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-cloud:after {\n
+\tbackground-image: url(images/icons-png/cloud-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-grid:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-grid:after {\n
+\tbackground-image: url(images/icons-png/grid-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-mail:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-mail:after {\n
+\tbackground-image: url(images/icons-png/mail-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-eye:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-eye:after {\n
+\tbackground-image: url(images/icons-png/eye-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-gear:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-gear:after {\n
+\tbackground-image: url(images/icons-png/gear-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-heart:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-heart:after {\n
+\tbackground-image: url(images/icons-png/heart-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-home:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-home:after {\n
+\tbackground-image: url(images/icons-png/home-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-info:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-info:after {\n
+\tbackground-image: url(images/icons-png/info-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-bars:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-bars:after {\n
+\tbackground-image: url(images/icons-png/bars-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-bullets:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-bullets:after {\n
+\tbackground-image: url(images/icons-png/bullets-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-navigation:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-navigation:after {\n
+\tbackground-image: url(images/icons-png/navigation-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-lock:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-lock:after {\n
+\tbackground-image: url(images/icons-png/lock-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-search:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-search:after,\n
+.ui-nosvg .ui-input-search:after {\n
+\tbackground-image: url(images/icons-png/search-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-location:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-location:after {\n
+\tbackground-image: url(images/icons-png/location-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-minus:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-minus:after {\n
+\tbackground-image: url(images/icons-png/minus-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-forbidden:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-forbidden:after {\n
+\tbackground-image: url(images/icons-png/forbidden-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-edit:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-edit:after {\n
+\tbackground-image: url(images/icons-png/edit-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-user:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-user:after {\n
+\tbackground-image: url(images/icons-png/user-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-phone:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-phone:after {\n
+\tbackground-image: url(images/icons-png/phone-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-plus:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-plus:after {\n
+\tbackground-image: url(images/icons-png/plus-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-power:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-power:after {\n
+\tbackground-image: url(images/icons-png/power-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-recycle:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-recycle:after {\n
+\tbackground-image: url(images/icons-png/recycle-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-forward:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-forward:after {\n
+\tbackground-image: url(images/icons-png/forward-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-refresh:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-refresh:after {\n
+\tbackground-image: url(images/icons-png/refresh-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-shop:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-shop:after {\n
+\tbackground-image: url(images/icons-png/shop-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-comment:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-comment:after {\n
+\tbackground-image: url(images/icons-png/comment-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-star:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-star:after {\n
+\tbackground-image: url(images/icons-png/star-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-tag:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-tag:after {\n
+\tbackground-image: url(images/icons-png/tag-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-back:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-back:after {\n
+\tbackground-image: url(images/icons-png/back-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-video:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-video:after {\n
+\tbackground-image: url(images/icons-png/video-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-alert:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-alert:after {\n
+\tbackground-image: url(images/icons-png/alert-black.png);\n
+}\n
+.ui-nosvg .ui-icon-alt.ui-icon-delete:after,\n
+.ui-nosvg .ui-icon-alt .ui-icon-delete:after {\n
+\tbackground-image: url(images/icons-png/delete-black.png);\n
+}\n
+/* Globals */\n
+/* Font\n
+-----------------------------------------------------------------------------------------------------------*/\n
+html {\n
+\tfont-size: 100%;\n
+}\n
+body,\n
+input,\n
+select,\n
+textarea,\n
+button,\n
+.ui-btn {\n
+\tfont-size: 1em;\n
+\tline-height: 1.3;\n
+\tfont-family: sans-serif /*{global-font-family}*/;\n
+}\n
+legend,\n
+.ui-input-text input,\n
+.ui-input-search input {\n
+\tcolor: inherit;\n
+\ttext-shadow: inherit;\n
+}\n
+/* Form labels (overrides font-weight bold in bars, and mini font-size) */\n
+.ui-mobile label,\n
+div.ui-controlgroup-label {\n
+\tfont-weight: normal;\n
+\tfont-size: 16px;\n
+}\n
+/* Field contain separator (< 28em)\n
+-----------------------------------------------------------------------------------------------------------*/\n
+.ui-field-contain {\n
+\tborder-bottom-color: #828282;\n
+\tborder-bottom-color: rgba(0,0,0,.15);\n
+\tborder-bottom-width: 1px;\n
+\tborder-bottom-style: solid;\n
+}\n
+/* Buttons\n
+-----------------------------------------------------------------------------------------------------------*/\n
+.ui-btn,\n
+label.ui-btn {\n
+\tfont-weight: bold;\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+}\n
+.ui-btn:link {\n
+\ttext-decoration: none !important;\n
+}\n
+.ui-btn-active {\n
+\tcursor: pointer;\n
+}\n
+/* Corner rounding\n
+-----------------------------------------------------------------------------------------------------------*/\n
+/* Class ui-btn-corner-all deprecated in 1.4 */\n
+.ui-corner-all {\n
+\t-webkit-border-radius: \t\t\t\t.6em /*{global-radii-blocks}*/;\n
+\tborder-radius: \t\t\t\t\t\t.6em /*{global-radii-blocks}*/;\n
+}\n
+/* Buttons */\n
+.ui-btn-corner-all,\n
+.ui-btn.ui-corner-all,\n
+/* Slider track */\n
+.ui-slider-track.ui-corner-all,\n
+/* Flipswitch */\n
+.ui-flipswitch.ui-corner-all,\n
+/* Count bubble */\n
+.ui-li-count {\n
+\t-webkit-border-radius: \t\t\t\t.3125em /*{global-radii-buttons}*/;\n
+\tborder-radius: \t\t\t\t\t\t.3125em /*{global-radii-buttons}*/;\n
+}\n
+/* Icon-only buttons */\n
+.ui-btn-icon-notext.ui-btn-corner-all,\n
+.ui-btn-icon-notext.ui-corner-all {\n
+\t-webkit-border-radius: 1em;\n
+\tborder-radius: 1em;\n
+}\n
+/* Radius clip workaround for cleaning up corner trapping */\n
+.ui-btn-corner-all,\n
+.ui-corner-all {\n
+\t-webkit-background-clip: padding;\n
+\tbackground-clip: padding-box;\n
+}\n
+/* Popup arrow */\n
+.ui-popup.ui-corner-all > .ui-popup-arrow-guide {\n
+\tleft: .6em /*{global-radii-blocks}*/;\n
+\tright: .6em /*{global-radii-blocks}*/;\n
+\ttop: .6em /*{global-radii-blocks}*/;\n
+\tbottom: .6em /*{global-radii-blocks}*/;\n
+}\n
+/* Shadow\n
+-----------------------------------------------------------------------------------------------------------*/\n
+.ui-shadow {\n
+\t-webkit-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n
+\t-moz-box-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/;\n
+\tbox-shadow: 0 1px 3px /*{global-box-shadow-size}*/ \t\t\t\trgba(0,0,0,.15) /*{global-box-shadow-color}*/\n
+}\n
+.ui-shadow-inset {\n
+\t-webkit-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n
+\t-moz-box-shadow: inset 0 1px 3px /*{global-box-shadow-size}*/ \t\trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n
+\tbox-shadow: inset 0 1px 3px 0 1px 3px /*{global-box-shadow-size}*/ \trgba(0,0,0,.2) /*{global-box-shadow-color}*/;\n
+}\n
+.ui-overlay-shadow {\n
+\t-webkit-box-shadow: 0 0 12px \t\trgba(0,0,0,.6);\n
+\t-moz-box-shadow: 0 0 12px \t\t\trgba(0,0,0,.6);\n
+\tbox-shadow: 0 0 12px \t\t\t\trgba(0,0,0,.6);\n
+}\n
+/* Icons\n
+-----------------------------------------------------------------------------------------------------------*/\n
+.ui-btn-icon-left:after,\n
+.ui-btn-icon-right:after,\n
+.ui-btn-icon-top:after,\n
+.ui-btn-icon-bottom:after,\n
+.ui-btn-icon-notext:after,\n
+html .ui-btn.ui-icon-checkbox-off:after,\n
+html .ui-btn.ui-icon-radio-off:after {\n
+\tbackground-color: \t\t\t\t\t#999 /*{global-icon-color}*/;\n
+\tbackground-color: \t\t\t\t\trgba(0,0,0,.3) /*{global-icon-disc}*/;\n
+\tbackground-position: center center;\n
+\tbackground-repeat: no-repeat;\n
+\t-webkit-border-radius: 1em;\n
+\tborder-radius: 1em;\n
+}\n
+/* Alt icons */\n
+.ui-icon-alt.ui-btn:after,\n
+.ui-icon-alt .ui-btn:after,\n
+html .ui-icon-alt.ui-icon-checkbox-off:after,\n
+html .ui-icon-alt.ui-icon-radio-off:after,\n
+html .ui-icon-alt .ui-icon-checkbox-off:after,\n
+html .ui-icon-alt .ui-icon-radio-off:after {\n
+\tbackground-color: \t\t\t\t\t#999 /*{global-icon-color}*/;\n
+\tbackground-color: \t\t\t\t\trgba(255,255,255,.3) /*{global-icon-disc-alt}*/;\n
+}\n
+/* No disc */\n
+.ui-icon-nodisc.ui-btn:after,\n
+.ui-icon-nodisc .ui-btn:after {\n
+\tbackground-color: transparent;\n
+}\n
+/* Icon shadow */\n
+.ui-shadow-icon.ui-btn:after,\n
+.ui-shadow-icon .ui-btn:after {\n
+\t-webkit-box-shadow: 0 1px 0 \t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n
+\t-moz-box-shadow: 0 1px 0 \t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n
+\tbox-shadow: 0 1px 0 \t\t\t\t\trgba(255,255,255,.3) /*{global-icon-shadow}*/;\n
+}\n
+/* Checkbox and radio */\n
+html .ui-btn.ui-icon-checkbox-off:after,\n
+html .ui-btn.ui-icon-checkbox-on:after,\n
+html .ui-btn.ui-icon-radio-off:after,\n
+html .ui-btn.ui-icon-radio-on:after {\n
+\tdisplay: block;\n
+\twidth: 18px;\n
+\theight: 18px;\n
+\tmargin: -9px 2px 0 2px;\n
+}\n
+.ui-btn.ui-icon-checkbox-off:after,\n
+.ui-btn.ui-icon-radio-off:after {\n
+\tbackground-image: none;\n
+\tfilter: Alpha(Opacity=30);\n
+\topacity: .3;\n
+}\n
+html .ui-btn.ui-icon-checkbox-off:after,\n
+html .ui-btn.ui-icon-checkbox-on:after {\n
+\t-webkit-border-radius: .1875em;\n
+\tborder-radius: .1875em;\n
+}\n
+.ui-radio .ui-btn.ui-icon-radio-on:after {\n
+\tbackground-image: none;\n
+\tbackground-color: #fff;\n
+\twidth: 8px;\n
+\theight: 8px;\n
+\tborder-width: 5px;\n
+\tborder-style: solid; \n
+}\n
+.ui-icon-alt.ui-btn.ui-icon-radio-on:after,\n
+.ui-icon-alt .ui-btn.ui-icon-radio-on:after {\n
+\tbackground-color: #000;\n
+}\n
+/* Loader */\n
+.ui-icon-loading {\n
+\tbackground: url(images/ajax-loader.gif);\n
+\tbackground-size: 2.875em 2.875em;\n
+}\n
+/* Swatches */\n
+/* A\n
+-----------------------------------------------------------------------------------------------------------*/\n
+/* Bar: Toolbars, dividers, slider track */\n
+.ui-bar-a,\n
+.ui-overlay-a .ui-bar-inherit,\n
+.ui-page-theme-a .ui-bar-inherit,\n
+html .ui-bar-a .ui-bar-inherit,\n
+html .ui-body-a .ui-bar-inherit,\n
+html body .ui-group-theme-a .ui-bar-inherit {\n
+\tbackground: \t\t\t#f1f1f1 /*{a-bar-background-color}*/;\n
+\tborder-color:\t \t\t#ddd /*{a-bar-border}*/;\n
+\tcolor: \t\t\t\t\t#111 /*{a-bar-color}*/;\n
+\ttext-shadow: 0 /*{a-bar-shadow-x}*/ 1px /*{a-bar-shadow-y}*/ 0 /*{a-bar-shadow-radius}*/ \t#eee /*{a-bar-shadow-color}*/;\n
+\tfont-weight: bold;\n
+}\n
+.ui-bar-a {\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+}\n
+/* Page and overlay */\n
+.ui-overlay-a,\n
+.ui-page-theme-a,\n
+.ui-page-theme-a .ui-panel-wrapper {\n
+\tbackground: \t\t\t#f9f9f9 /*{a-page-background-color}*/;\n
+\tborder-color:\t \t\t#bbb /*{a-page-border}*/;\n
+\tcolor: \t\t\t\t\t#111 /*{a-page-color}*/;\n
+\ttext-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ \t#eee /*{a-body-shadow-color}*/;\n
+}\n
+/* Body: Read-only lists, text inputs, collapsible content */\n
+.ui-body-a,\n
+.ui-overlay-a .ui-body-inherit,\n
+.ui-page-theme-a .ui-body-inherit,\n
+html .ui-bar-a .ui-body-inherit,\n
+html .ui-body-a .ui-body-inherit,\n
+html body .ui-group-theme-a .ui-body-inherit,\n
+html .ui-panel-page-container-a {\n
+\tbackground: \t\t\t#fff /*{a-body-background-color}*/;\n
+\tborder-color:\t \t\t#ddd /*{a-body-border}*/;\n
+\tcolor: \t\t\t\t\t#111 /*{a-body-color}*/;\n
+\ttext-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 0 /*{a-body-shadow-radius}*/ \t#eee /*{a-body-shadow-color}*/;\n
+}\n
+.ui-body-a {\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+}\n
+/* Links */\n
+.ui-overlay-a a,\n
+.ui-page-theme-a a,\n
+html .ui-bar-a a,\n
+html .ui-body-a a,\n
+html body .ui-group-theme-a a {\n
+\tcolor: #0066ff /*{a-link-color}*/;\n
+\tfont-weight: bold;\n
+}\n
+.ui-overlay-a a:visited,\n
+.ui-page-theme-a a:visited,\n
+html .ui-bar-a a:visited,\n
+html .ui-body-a a:visited,\n
+html body .ui-group-theme-a a:visited {\n
+    color: #0066ff /*{a-link-visited}*/;\n
+}\n
+.ui-overlay-a a:hover,\n
+.ui-page-theme-a a:hover,\n
+html .ui-bar-a a:hover,\n
+html .ui-body-a a:hover,\n
+html body .ui-group-theme-a a:hover {\n
+\tcolor: #0033ff /*{a-link-hover}*/;\n
+}\n
+.ui-overlay-a a:active,\n
+.ui-page-theme-a a:active,\n
+html .ui-bar-a a:active,\n
+html .ui-body-a a:active,\n
+html body .ui-group-theme-a a:active {\n
+\tcolor: #0033ff /*{a-link-active}*/;\n
+}\n
+/* Button up */\n
+.ui-overlay-a .ui-btn,\n
+.ui-page-theme-a .ui-btn,\n
+html .ui-bar-a .ui-btn,\n
+html .ui-body-a .ui-btn,\n
+html body .ui-group-theme-a .ui-btn,\n
+html head + body .ui-btn.ui-btn-a,\n
+/* Button visited */\n
+.ui-overlay-a .ui-btn:visited,\n
+.ui-page-theme-a .ui-btn:visited,\n
+html .ui-bar-a .ui-btn:visited,\n
+html .ui-body-a .ui-btn:visited,\n
+html body .ui-group-theme-a .ui-btn:visited,\n
+html head + body .ui-btn.ui-btn-a:visited {\n
+\tbackground: \t\t\t#f6f6f6 /*{a-bup-background-color}*/;\n
+\tborder-color:\t \t\t#ddd /*{a-bup-border}*/;\n
+\tcolor: \t\t\t\t\t#111 /*{a-bup-color}*/;\n
+\ttext-shadow: 0 /*{a-bup-shadow-x}*/ 1px /*{a-bup-shadow-y}*/ 0 /*{a-bup-shadow-radius}*/ #eee /*{a-bup-shadow-color}*/;\n
+}\n
+/* Button hover */\n
+.ui-overlay-a .ui-btn:hover,\n
+.ui-page-theme-a .ui-btn:hover,\n
+html .ui-bar-a .ui-btn:hover,\n
+html .ui-body-a .ui-btn:hover,\n
+html body .ui-group-theme-a .ui-btn:hover,\n
+html head + body .ui-btn.ui-btn-a:hover {\n
+\tbackground: \t\t\t#ededed /*{a-bhover-background-color}*/;\n
+\tborder-color:\t \t\t#ddd /*{a-bhover-border}*/;\n
+\tcolor: \t\t\t\t\t#111 /*{a-bhover-color}*/;\n
+\ttext-shadow: 0 /*{a-bhover-shadow-x}*/ 1px /*{a-bhover-shadow-y}*/ 0 /*{a-bhover-shadow-radius}*/ #eee /*{a-bhover-shadow-color}*/;\n
+}\n
+/* Button down */\n
+.ui-overlay-a .ui-btn:active,\n
+.ui-page-theme-a .ui-btn:active,\n
+html .ui-bar-a .ui-btn:active,\n
+html .ui-body-a .ui-btn:active,\n
+html body .ui-group-theme-a .ui-btn:active,\n
+html head + body .ui-btn.ui-btn-a:active {\n
+\tbackground: \t\t\t#e8e8e8 /*{a-bdown-background-color}*/;\n
+\tborder-color:\t \t\t#ddd /*{a-bdown-border}*/;\n
+\tcolor: \t\t\t\t\t#111 /*{a-bdown-color}*/;\n
+\ttext-shadow: 0 /*{a-bdown-shadow-x}*/ 1px /*{a-bdown-shadow-y}*/ 0 /*{a-bdown-shadow-radius}*/ #eee /*{a-bdown-shadow-color}*/;\n
+}\n
+/* Active button */\n
+.ui-overlay-a .ui-btn.ui-btn-active,\n
+.ui-page-theme-a .ui-btn.ui-btn-active,\n
+html .ui-bar-a .ui-btn.ui-btn-active,\n
+html .ui-body-a .ui-btn.ui-btn-active,\n
+html body .ui-group-theme-a .ui-btn.ui-btn-active,\n
+html head + body .ui-btn.ui-btn-a.ui-btn-active,\n
+/* Active checkbox icon */\n
+.ui-overlay-a .ui-icon-checkbox-on:after,\n
+.ui-page-theme-a .ui-icon-checkbox-on:after,\n
+html .ui-bar-a .ui-icon-checkbox-on:after,\n
+html .ui-body-a .ui-icon-checkbox-on:after,\n
+html body .ui-group-theme-a .ui-icon-checkbox-on:after,\n
+.ui-btn.ui-icon-checkbox-on.ui-btn-a:after,\n
+/* Active flipswitch background */\n
+.ui-overlay-a .ui-flipswitch-active,\n
+.ui-page-theme-a .ui-flipswitch-active,\n
+html .ui-bar-a .ui-flipswitch-active,\n
+html .ui-body-a .ui-flipswitch-active,\n
+html body .ui-group-theme-a .ui-flipswitch-active,\n
+html body .ui-flipswitch.ui-bar-a.ui-flipswitch-active,\n
+/* Active slider track */\n
+.ui-overlay-a .ui-slider-track .ui-btn-active,\n
+.ui-page-theme-a .ui-slider-track .ui-btn-active,\n
+html .ui-bar-a .ui-slider-track .ui-btn-active,\n
+html .ui-body-a .ui-slider-track .ui-btn-active,\n
+html body .ui-group-theme-a .ui-slider-track .ui-btn-active,\n
+html body div.ui-slider-track.ui-body-a .ui-btn-active {\n
+\tbackground-color: \t\t#0066ff /*{a-active-background-color}*/;\n
+\tborder-color:\t \t\t#0033ff /*{a-active-border}*/;\n
+\tcolor: \t\t\t\t\t#fff /*{a-active-color}*/;\n
+\ttext-shadow: 0 /*{a-active-shadow-x}*/ 1px /*{a-active-shadow-y}*/ 0 /*{a-active-shadow-radius}*/ #0033ff /*{a-active-shadow-color}*/;\n
+}\n
+/* Active radio button icon */\n
+.ui-overlay-a .ui-icon-radio-on:after,\n
+.ui-page-theme-a .ui-icon-radio-on:after,\n
+html .ui-bar-a .ui-icon-radio-on:after,\n
+html .ui-body-a .ui-icon-radio-on:after,\n
+html body .ui-group-theme-a .ui-icon-radio-on:after,\n
+.ui-btn.ui-icon-radio-on.ui-btn-a:after {\n
+\tborder-color:\t\t\t#0066ff /*{a-active-background-color}*/;\n
+}\n
+/* Focus */\n
+.ui-overlay-a .ui-btn:focus,\n
+.ui-page-theme-a .ui-btn:focus,\n
+html .ui-bar-a .ui-btn:focus,\n
+html .ui-body-a .ui-btn:focus,\n
+html body .ui-group-theme-a .ui-btn:focus,\n
+html head + body .ui-btn.ui-btn-a:focus,\n
+/* Focus buttons and text inputs with div wrap */\n
+.ui-overlay-a .ui-focus,\n
+.ui-page-theme-a .ui-focus,\n
+html .ui-bar-a .ui-focus,\n
+html .ui-body-a .ui-focus,\n
+html body .ui-group-theme-a .ui-focus,\n
+html head + body .ui-btn-a.ui-focus,\n
+html head + body .ui-body-a.ui-focus {\n
+\t-webkit-box-shadow: 0 0 12px \t#0066ff /*{a-active-background-color}*/;\n
+\t-moz-box-shadow: 0 0 12px \t\t#0066ff /*{a-active-background-color}*/;\n
+\tbox-shadow: 0 0 12px \t\t\t#0066ff /*{a-active-background-color}*/;\n
+}\n
+/* B\n
+-----------------------------------------------------------------------------------------------------------*/\n
+/* Bar: Toolbars, dividers, slider track */\n
+.ui-bar-b,\n
+.ui-overlay-b .ui-bar-inherit,\n
+.ui-page-theme-b .ui-bar-inherit,\n
+html .ui-bar-b .ui-bar-inherit,\n
+html .ui-body-b .ui-bar-inherit,\n
+html body .ui-group-theme-b .ui-bar-inherit {\n
+\tbackground: \t\t\t#1d1d1d /*{b-bar-background-color}*/;\n
+\tborder-color:\t \t\t#1b1b1b /*{b-bar-border}*/;\n
+\tcolor: \t\t\t\t\t#fff /*{b-bar-color}*/;\n
+\ttext-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 0 /*{b-bar-shadow-radius}*/ \t#111 /*{b-bar-shadow-color}*/;\n
+\tfont-weight: bold;\n
+}\n
+.ui-bar-b {\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+}\n
+/* Page and overlay */\n
+.ui-overlay-b,\n
+.ui-page-theme-b,\n
+.ui-page-theme-b .ui-panel-wrapper {\n
+\tbackground: \t\t\t#252525 /*{b-page-background-color}*/;\n
+\tborder-color:\t \t\t#454545 /*{b-page-border}*/;\n
+\tcolor: \t\t\t\t\t#fff /*{b-page-color}*/;\n
+\ttext-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ \t#111 /*{b-body-shadow-color}*/;\n
+}\n
+/* Body: Read-only lists, text inputs, collapsible content */\n
+.ui-body-b,\n
+.ui-overlay-b .ui-body-inherit,\n
+.ui-page-theme-b .ui-body-inherit,\n
+html .ui-bar-b .ui-body-inherit,\n
+html .ui-body-b .ui-body-inherit,\n
+html body .ui-group-theme-b .ui-body-inherit,\n
+html .ui-panel-page-container-b {\n
+\tbackground: \t\t\t#2a2a2a /*{b-body-background-color}*/;\n
+\tborder-color:\t \t\t#1d1d1d /*{b-body-border}*/;\n
+\tcolor: \t\t\t\t\t#fff /*{b-body-color}*/;\n
+\ttext-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ \t#111 /*{b-body-shadow-color}*/;\n
+}\n
+.ui-body-b {\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+}\n
+/* Links */\n
+.ui-overlay-b a,\n
+.ui-page-theme-b a,\n
+html .ui-bar-b a,\n
+html .ui-body-b a,\n
+html body .ui-group-theme-b a {\n
+\tcolor: #33ccff /*{b-link-color}*/;\n
+\tfont-weight: bold;\n
+}\n
+.ui-overlay-b a:visited,\n
+.ui-page-theme-b a:visited,\n
+html .ui-bar-b a:visited,\n
+html .ui-body-b a:visited,\n
+html body .ui-group-theme-b a:visited {\n
+    color: #33ccff /*{b-link-visited}*/;\n
+}\n
+.ui-overlay-b a:hover,\n
+.ui-page-theme-b a:hover,\n
+html .ui-bar-b a:hover,\n
+html .ui-body-b a:hover,\n
+html body .ui-group-theme-b a:hover {\n
+\tcolor: #3399ff /*{b-link-hover}*/;\n
+}\n
+.ui-overlay-b a:active,\n
+.ui-page-theme-b a:active,\n
+html .ui-bar-b a:active,\n
+html .ui-body-b a:active,\n
+html body .ui-group-theme-b a:active {\n
+\tcolor: #3399ff /*{b-link-active}*/;\n
+}\n
+/* Button up */\n
+.ui-overlay-b .ui-btn,\n
+.ui-page-theme-b .ui-btn,\n
+html .ui-bar-b .ui-btn,\n
+html .ui-body-b .ui-btn,\n
+html body .ui-group-theme-b .ui-btn,\n
+html head + body .ui-btn.ui-btn-b,\n
+/* Button visited */\n
+.ui-overlay-b .ui-btn:visited,\n
+.ui-page-theme-b .ui-btn:visited,\n
+html .ui-bar-b .ui-btn:visited,\n
+html .ui-body-b .ui-btn:visited,\n
+html body .ui-group-theme-b .ui-btn:visited,\n
+html head + body .ui-btn.ui-btn-b:visited {\n
+\tbackground: \t\t\t#333 /*{b-bup-background-color}*/;\n
+\tborder-color:\t \t\t#1f1f1f /*{b-bup-border}*/;\n
+\tcolor: \t\t\t\t\t#fff /*{b-bup-color}*/;\n
+\ttext-shadow: 0 /*{b-bup-shadow-x}*/ 1px /*{b-bup-shadow-y}*/ 0 /*{b-bup-shadow-radius}*/ #111 /*{b-bup-shadow-color}*/;\n
+}\n
+/* Button hover */\n
+.ui-overlay-b .ui-btn:hover,\n
+.ui-page-theme-b .ui-btn:hover,\n
+html .ui-bar-b .ui-btn:hover,\n
+html .ui-body-b .ui-btn:hover,\n
+html body .ui-group-theme-b .ui-btn:hover,\n
+html head + body .ui-btn.ui-btn-b:hover {\n
+\tbackground: \t\t\t#373737 /*{b-bhover-background-color}*/;\n
+\tborder-color:\t \t\t#1f1f1f /*{b-bhover-border}*/;\n
+\tcolor: \t\t\t\t\t#fff /*{b-bhover-color}*/;\n
+\ttext-shadow: 0 /*{b-bhover-shadow-x}*/ 1px /*{b-bhover-shadow-y}*/ 0 /*{b-bhover-shadow-radius}*/ #111 /*{b-bhover-shadow-color}*/;\n
+}\n
+/* Button down */\n
+.ui-overlay-b .ui-btn:active,\n
+.ui-page-theme-b .ui-btn:active,\n
+html .ui-bar-b .ui-btn:active,\n
+html .ui-body-b .ui-btn:active,\n
+html body .ui-group-theme-b .ui-btn:active,\n
+html head + body .ui-btn.ui-btn-b:active {\n
+\tbackground: \t\t\t#404040 /*{b-bdown-background-color}*/;\n
+\tborder-color:\t \t\t#1f1f1f /*{b-bdown-border}*/;\n
+\tcolor: \t\t\t\t\t#fff /*{b-bdown-color}*/;\n
+\ttext-shadow: 0 /*{b-bdown-shadow-x}*/ 1px /*{b-bdown-shadow-y}*/ 0 /*{b-bdown-shadow-radius}*/ #111 /*{b-bdown-shadow-color}*/;\n
+}\n
+/* Active button */\n
+.ui-overlay-b .ui-btn.ui-btn-active,\n
+.ui-page-theme-b .ui-btn.ui-btn-active,\n
+html .ui-bar-b .ui-btn.ui-btn-active,\n
+html .ui-body-b .ui-btn.ui-btn-active,\n
+html body .ui-group-theme-b .ui-btn.ui-btn-active,\n
+html head + body .ui-btn.ui-btn-b.ui-btn-active,\n
+/* Active checkbox icon */\n
+.ui-overlay-b .ui-icon-checkbox-on:after,\n
+.ui-page-theme-b .ui-icon-checkbox-on:after,\n
+html .ui-bar-b .ui-icon-checkbox-on:after,\n
+html .ui-body-b .ui-icon-checkbox-on:after,\n
+html body .ui-group-theme-b .ui-icon-checkbox-on:after,\n
+.ui-btn.ui-icon-checkbox-on.ui-btn-b:after,\n
+/* Active flipswitch background */\n
+.ui-overlay-b .ui-flipswitch-active,\n
+.ui-page-theme-b .ui-flipswitch-active,\n
+html .ui-bar-b .ui-flipswitch-active,\n
+html .ui-body-b .ui-flipswitch-active,\n
+html body .ui-group-theme-b .ui-flipswitch-active,\n
+html body .ui-flipswitch.ui-bar-b.ui-flipswitch-active,\n
+/* Active slider track */\n
+.ui-overlay-b .ui-slider-track .ui-btn-active,\n
+.ui-page-theme-b .ui-slider-track .ui-btn-active,\n
+html .ui-bar-b .ui-slider-track .ui-btn-active,\n
+html .ui-body-b .ui-slider-track .ui-btn-active,\n
+html body .ui-group-theme-b .ui-slider-track .ui-btn-active,\n
+html body div.ui-slider-track.ui-body-b .ui-btn-active {\n
+\tbackground-color: \t\t#33ccff /*{b-active-background-color}*/;\n
+\tborder-color:\t \t\t#3399ff /*{b-active-border}*/;\n
+\tcolor: \t\t\t\t\t#fff /*{b-active-color}*/;\n
+\ttext-shadow: 0 /*{b-active-shadow-x}*/ 1px /*{b-active-shadow-y}*/ 0 /*{b-active-shadow-radius}*/ #3399ff /*{b-active-shadow-color}*/;\n
+}\n
+/* Active radio button icon */\n
+.ui-overlay-b .ui-icon-radio-on:after,\n
+.ui-page-theme-b .ui-icon-radio-on:after,\n
+html .ui-bar-b .ui-icon-radio-on:after,\n
+html .ui-body-b .ui-icon-radio-on:after,\n
+html body .ui-group-theme-b .ui-icon-radio-on:after,\n
+.ui-btn.ui-icon-radio-on.ui-btn-b:after {\n
+\tborder-color:\t\t\t#33ccff /*{b-active-background-color}*/;\n
+}\n
+/* Focus */\n
+.ui-overlay-b .ui-btn:focus,\n
+.ui-page-theme-b .ui-btn:focus,\n
+html .ui-bar-b .ui-btn:focus,\n
+html .ui-body-b .ui-btn:focus,\n
+html body .ui-group-theme-b .ui-btn:focus,\n
+html head + body .ui-btn.ui-btn-b:focus,\n
+/* Focus buttons and text inputs with div wrap */\n
+.ui-overlay-b .ui-focus,\n
+.ui-page-theme-b .ui-focus,\n
+html .ui-bar-b .ui-focus,\n
+html .ui-body-b .ui-focus,\n
+html body .ui-group-theme-b .ui-focus,\n
+html head + body .ui-btn-b.ui-focus,\n
+html head + body .ui-body-b.ui-focus {\n
+\t-webkit-box-shadow: 0 0 12px \t#33ccff /*{b-active-background-color}*/;\n
+\t-moz-box-shadow: 0 0 12px \t\t#33ccff /*{b-active-background-color}*/;\n
+\tbox-shadow: 0 0 12px \t\t\t#33ccff /*{b-active-background-color}*/;\n
+}\n
+/* Disabled\n
+-----------------------------------------------------------------------------------------------------------*/\n
+/* Class ui-disabled deprecated in 1.4. :disabled not supported by IE8 so we use [disabled] */\n
+.ui-disabled,\n
+.ui-state-disabled,\n
+button[disabled],\n
+.ui-select .ui-btn.ui-state-disabled {\n
+\tfilter: Alpha(Opacity=30);\n
+\topacity: .3;\n
+\tcursor: default !important;\n
+\tpointer-events: none;\n
+}\n
+/* Focus state outline\n
+-----------------------------------------------------------------------------------------------------------*/\n
+.ui-btn:focus,\n
+.ui-btn.ui-focus {\n
+\toutline: 0;\n
+}\n
+/* Unset box-shadow in browsers that don\'t do it right */\n
+.ui-noboxshadow .ui-shadow,\n
+.ui-noboxshadow .ui-shadow-inset,\n
+.ui-noboxshadow .ui-overlay-shadow,\n
+.ui-noboxshadow .ui-shadow-icon.ui-btn:after,\n
+.ui-noboxshadow .ui-shadow-icon .ui-btn:after,\n
+.ui-noboxshadow .ui-focus,\n
+.ui-noboxshadow .ui-btn:focus,\n
+.ui-noboxshadow  input:focus,\n
+.ui-noboxshadow .ui-panel {\n
+\t-webkit-box-shadow: none !important;\n
+\t-moz-box-shadow: none !important;\n
+\tbox-shadow: none !important;\n
+}\n
+.ui-noboxshadow .ui-btn:focus,\n
+.ui-noboxshadow .ui-focus {\n
+\toutline-width: 1px;\n
+\toutline-style: auto;\n
+}\n
+/* Some unsets */\n
+.ui-mobile,\n
+.ui-mobile body {\n
+\theight: 99.9%;\n
+}\n
+.ui-mobile fieldset,\n
+.ui-page {\n
+\tpadding: 0;\n
+\tmargin: 0;\n
+}\n
+.ui-mobile a img,\n
+.ui-mobile fieldset {\n
+\tborder-width: 0;\n
+}\n
+/* Fixes for fieldset issues on IE10 and FF (see #6077) */\n
+.ui-mobile fieldset {\n
+\tmin-width: 0;\n
+}\n
+@-moz-document url-prefix() {\n
+\t.ui-mobile fieldset {\n
+\t\tdisplay: table-column;\n
+\t\tvertical-align: middle;\n
+\t}\n
+}\n
+/* Viewport */\n
+.ui-mobile-viewport {\n
+\tmargin: 0;\n
+\toverflow-x: visible;\n
+\t-webkit-text-size-adjust: 100%;\n
+\t-ms-text-size-adjust:none;\n
+\t-webkit-tap-highlight-color: rgba(0, 0, 0, 0);\n
+}\n
+/* Issue #2066 */\n
+body.ui-mobile-viewport,\n
+div.ui-mobile-viewport {\n
+\toverflow-x: hidden;\n
+}\n
+/* "page" containers - full-screen views, one should always be in view post-pageload */\n
+.ui-mobile [data-role=page],\n
+.ui-mobile [data-role=dialog],\n
+.ui-page {\n
+\ttop: 0;\n
+\tleft: 0;\n
+\twidth: 100%;\n
+\tmin-height: 100%;\n
+\tposition: absolute;\n
+\tdisplay: none;\n
+\tborder: 0;\n
+}\n
+/* On ios4, setting focus on the page element causes flashing during transitions when there is an outline, so we turn off outlines */\n
+.ui-page {\n
+\toutline: none;\n
+}\n
+.ui-mobile .ui-page-active {\n
+\tdisplay: block;\n
+\toverflow: visible;\n
+\toverflow-x: hidden;\n
+}\n
+@media screen and (orientation: portrait) {\n
+\t.ui-mobile .ui-page {\n
+\t\tmin-height: 420px;\n
+\t}\n
+}\n
+@media screen and (orientation: landscape) {\n
+\t.ui-mobile .ui-page {\n
+\t\tmin-height: 300px;\n
+\t}\n
+}\n
+/* Fouc */\n
+.ui-mobile-rendering > * {\n
+\tvisibility: hidden;\n
+}\n
+/* Non-js content hiding */\n
+.ui-nojs {\n
+\tposition: absolute !important;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+/* Loading screen */\n
+.ui-loading .ui-loader {\n
+\tdisplay: block;\n
+}\n
+.ui-loader {\n
+\tdisplay: none;\n
+\tz-index: 9999999;\n
+\tposition: fixed;\n
+\ttop: 50%;\n
+\tleft: 50%;\n
+\tborder:0;\n
+}\n
+.ui-loader-default {\n
+\tbackground: none;\n
+\tfilter: Alpha(Opacity=18);\n
+\topacity: .18;\n
+\twidth: 2.875em;\n
+\theight: 2.875em;\n
+\tmargin-left: -1.4375em;\n
+\tmargin-top: -1.4375em;\n
+}\n
+.ui-loader-verbose {\n
+\twidth: 12.5em;\n
+\tfilter: Alpha(Opacity=88);\n
+\topacity: .88;\n
+\tbox-shadow: 0 1px 1px -1px #fff;\n
+\theight: auto;\n
+\tmargin-left: -6.875em;\n
+\tmargin-top: -2.6875em;\n
+\tpadding: .625em;\n
+}\n
+.ui-loader-default h1 {\n
+\tfont-size: 0;\n
+\twidth: 0;\n
+\theight: 0;\n
+\toverflow: hidden;\n
+}\n
+.ui-loader-verbose h1 {\n
+\tfont-size: 1em;\n
+\tmargin: 0;\n
+\ttext-align: center;\n
+}\n
+.ui-loader .ui-icon-loading {\n
+\tbackground-color: #000;\n
+\tdisplay: block;\n
+\tmargin: 0;\n
+\twidth: 2.75em;\n
+\theight: 2.75em;\n
+\tpadding: .0625em;\n
+\t-webkit-border-radius: 2.25em;\n
+\tborder-radius: 2.25em;\n
+}\n
+.ui-loader-verbose .ui-icon-loading {\n
+\tmargin: 0 auto .625em;\n
+\tfilter: Alpha(Opacity=75);\n
+\topacity: .75;\n
+}\n
+.ui-loader-textonly {\n
+\tpadding: .9375em;\n
+\tmargin-left: -7.1875em;\n
+}\n
+.ui-loader-textonly .ui-icon-loading {\n
+\tdisplay: none;\n
+}\n
+.ui-loader-fakefix {\n
+\tposition: absolute;\n
+}\n
+/* Headers, content panels */\n
+.ui-bar,\n
+.ui-body {\n
+\tposition: relative;\n
+\tpadding: .4em 1em;\n
+\toverflow: hidden;\n
+\tdisplay: block;\n
+\tclear: both;\n
+}\n
+.ui-bar h1,\n
+.ui-bar h2,\n
+.ui-bar h3,\n
+.ui-bar h4,\n
+.ui-bar h5,\n
+.ui-bar h6 {\n
+\tmargin: 0;\n
+\tpadding: 0;\n
+\tfont-size: 1em;\n
+\tdisplay: inline-block;\n
+}\n
+.ui-header,\n
+.ui-footer {\n
+\tborder-width: 1px 0;\n
+\tborder-style: solid;\n
+\tposition: relative;\n
+}\n
+.ui-header:empty,\n
+.ui-footer:empty {\n
+\tmin-height: 2.6875em;\n
+}\n
+.ui-header .ui-title,\n
+.ui-footer .ui-title {\n
+\tfont-size: 1em;\n
+\tmin-height: 1.1em;\n
+\ttext-align: center;\n
+\tdisplay: block;\n
+\tmargin: 0 30%;\n
+\tpadding: .7em 0;\n
+\ttext-overflow: ellipsis;\n
+\toverflow: hidden;\n
+\twhite-space: nowrap;\n
+\toutline: 0 !important;\n
+}\n
+.ui-footer .ui-title {\n
+\tmargin: 0 1em;\n
+}\n
+.ui-content {\n
+\tborder-width: 0;\n
+\toverflow: visible;\n
+\toverflow-x: hidden;\n
+\tpadding: 1em;\n
+}\n
+/* Corner styling for dialogs and popups */\n
+.ui-corner-all > .ui-header:first-child,\n
+.ui-corner-all > .ui-content:first-child,\n
+.ui-corner-all > .ui-footer:first-child {\n
+\t-webkit-border-top-left-radius: inherit;\n
+\tborder-top-left-radius: inherit;\n
+\t-webkit-border-top-right-radius: inherit;\n
+\tborder-top-right-radius: inherit;\n
+}\n
+.ui-corner-all > .ui-header:last-child,\n
+.ui-corner-all > .ui-content:last-child,\n
+.ui-corner-all > .ui-footer:last-child {\n
+\t-webkit-border-bottom-left-radius: inherit;\n
+\tborder-bottom-left-radius: inherit;\n
+\t-webkit-border-bottom-right-radius: inherit;\n
+\tborder-bottom-right-radius: inherit;\n
+}\n
+/* Buttons and icons */\n
+.ui-btn {\n
+\tfont-size: 16px;\n
+\tmargin: .5em 0;\n
+\tpadding: .7em 1em;\n
+\tdisplay: block;\n
+\tposition: relative;\n
+\ttext-align: center;\n
+\ttext-overflow: ellipsis;\n
+\toverflow: hidden;\n
+\twhite-space: nowrap;\n
+\tcursor: pointer;\n
+\t-webkit-user-select: none;\n
+\t-moz-user-select: none;\n
+\t-ms-user-select: none;\n
+\tuser-select: none;\n
+}\n
+.ui-btn-icon-notext {\n
+\tpadding: 0;\n
+\twidth: 1.75em;\n
+\theight: 1.75em;\n
+\ttext-indent: -9999px;\n
+\twhite-space: nowrap !important;\n
+}\n
+.ui-mini {\n
+\tfont-size: 12.5px;\n
+}\n
+.ui-mini .ui-btn {\n
+\tfont-size: inherit;\n
+}\n
+/* Make buttons in toolbars default to mini and inline. */\n
+.ui-header .ui-btn,\n
+.ui-footer .ui-btn {\n
+\tfont-size: 12.5px;\n
+\tdisplay: inline-block;\n
+\tvertical-align: middle;\n
+}\n
+/* To ensure same top and left/right position when ui-btn-left/right are added to something other than buttons. */\n
+.ui-header .ui-btn-left,\n
+.ui-header .ui-btn-right {\n
+\tfont-size: 12.5px;\n
+}\n
+.ui-mini.ui-btn-icon-notext,\n
+.ui-mini .ui-btn-icon-notext,\n
+.ui-header .ui-btn-icon-notext,\n
+.ui-footer .ui-btn-icon-notext {\n
+\tfont-size: 16px;\t\n
+\tpadding: 0;\n
+}\n
+.ui-btn-inline {\n
+\tdisplay: inline-block;\n
+\tvertical-align: middle;\n
+\tmargin-right: .625em;\n
+}\n
+.ui-btn-icon-left {\n
+\tpadding-left: 2.5em;\n
+}\n
+.ui-btn-icon-right {\n
+\tpadding-right: 2.5em;\n
+}\n
+.ui-btn-icon-top {\n
+\tpadding-top: 2.5em;\n
+}\n
+.ui-btn-icon-bottom {\n
+\tpadding-bottom: 2.5em;\n
+}\n
+.ui-header .ui-btn-icon-top,\n
+.ui-footer .ui-btn-icon-top,\n
+.ui-header .ui-btn-icon-bottom,\n
+.ui-footer .ui-btn-icon-bottom {\n
+\tpadding-left: .3125em;\n
+\tpadding-right: .3125em;\n
+}\n
+.ui-btn-icon-left:after,\n
+.ui-btn-icon-right:after,\n
+.ui-btn-icon-top:after,\n
+.ui-btn-icon-bottom:after,\n
+.ui-btn-icon-notext:after {\n
+\tcontent: "";\n
+\tposition: absolute;\n
+\tdisplay: block;\n
+\twidth: 22px;\n
+\theight: 22px;\n
+}\n
+.ui-btn-icon-notext:after,\n
+.ui-btn-icon-left:after,\n
+.ui-btn-icon-right:after {\n
+\ttop: 50%;\n
+\tmargin-top: -11px;\n
+}\n
+.ui-btn-icon-left:after {\n
+\tleft: .5625em;\n
+}\n
+.ui-btn-icon-right:after {\n
+\tright: .5625em;\n
+}\n
+.ui-mini.ui-btn-icon-left:after,\n
+.ui-mini .ui-btn-icon-left:after,\n
+.ui-header .ui-btn-icon-left:after,\n
+.ui-footer .ui-btn-icon-left:after {\n
+\tleft: .37em;\n
+}\n
+.ui-mini.ui-btn-icon-right:after,\n
+.ui-mini .ui-btn-icon-right:after,\n
+.ui-header .ui-btn-icon-right:after,\n
+.ui-footer .ui-btn-icon-right:after {\n
+\tright: .37em;\n
+}\n
+.ui-btn-icon-notext:after,\n
+.ui-btn-icon-top:after,\n
+.ui-btn-icon-bottom:after {\n
+\tleft: 50%;\n
+\tmargin-left: -11px;\n
+}\n
+.ui-btn-icon-top:after {\n
+\ttop: .5625em;\n
+}\n
+.ui-btn-icon-bottom:after {\n
+\ttop: auto;\n
+\tbottom: .5625em;\n
+}\n
+/* Buttons in header position classes */\n
+.ui-header .ui-btn-left,\n
+.ui-header .ui-btn-right,\n
+.ui-btn-left > [class*="ui-"],\n
+.ui-btn-right > [class*="ui-"] {\n
+\tmargin: 0;\n
+}\n
+.ui-btn-left,\n
+.ui-btn-right {\n
+\tposition: absolute;\n
+\ttop: .24em;\n
+}\n
+.ui-btn-left {\n
+\tleft: .4em;\n
+}\n
+.ui-btn-right {\n
+\tright: .4em;\n
+}\n
+.ui-btn-icon-notext.ui-btn-left {\n
+\ttop: .3125em;\n
+\tleft: .3125em;\n
+}\n
+.ui-btn-icon-notext.ui-btn-right {\n
+\ttop: .3125em;\n
+\tright: .3125em;\n
+}\n
+/* Button elements */\n
+button.ui-btn,\n
+.ui-controlgroup-controls button.ui-btn-icon-notext {\n
+\t-webkit-box-sizing: border-box;\n
+\t-moz-box-sizing: border-box;\n
+\tbox-sizing: border-box;\n
+\t-webkit-appearance: none;\n
+\t-moz-appearance: none;\n
+\twidth: 100%;\n
+}\n
+/* Firefox adds a 1px border in a button element. We negate this to make sure they have the same height as other buttons in controlgroups. */\n
+button.ui-btn::-moz-focus-inner {\n
+\tborder: 0;\n
+}\n
+button.ui-btn-inline {\n
+\twidth: auto;\n
+}\n
+button.ui-btn-icon-notext,\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn {\n
+\t-webkit-box-sizing: content-box;\n
+\t-moz-box-sizing: content-box;\n
+\tbox-sizing: content-box;\n
+\twidth: 1.75em;\n
+}\n
+/* Form labels */\n
+.ui-mobile label,\n
+.ui-controlgroup-label {\n
+\tdisplay: block;\n
+\tmargin: 0 0 .4em;\n
+}\n
+/* Accessible content hiding */\n
+.ui-hide-label > label,\n
+.ui-hide-label .ui-controlgroup-label,\n
+.ui-hide-label .ui-rangeslider label,\n
+.ui-hidden-accessible {\n
+\tposition: absolute !important;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+/* Used for hiding elements by the filterable widget. You can also use this class to hide list items or buttons in controlgroups; this ensures correct corner styling. */\n
+.ui-screen-hidden {\n
+\tdisplay: none !important;\n
+}\n
+/* Transitions originally inspired by those from jQtouch, nice work, folks */\n
+.ui-mobile-viewport-transitioning,\n
+.ui-mobile-viewport-transitioning .ui-page {\n
+\twidth: 100%;\n
+\theight: 100%;\n
+\toverflow: hidden;\n
+\t-webkit-box-sizing: border-box;\n
+\t-moz-box-sizing: border-box;\n
+\tbox-sizing: border-box;\n
+}\n
+.ui-page-pre-in {\n
+\topacity: 0;\n
+}\n
+.in {\n
+\t-webkit-animation-timing-function: ease-out;\n
+\t-webkit-animation-duration: 350ms;\n
+\t-moz-animation-timing-function: ease-out;\n
+\t-moz-animation-duration: 350ms;\n
+\tanimation-timing-function: ease-out;\n
+\tanimation-duration: 350ms;\n
+}\n
+.out {\n
+\t-webkit-animation-timing-function: ease-in;\n
+\t-webkit-animation-duration: 225ms;\n
+\t-moz-animation-timing-function: ease-in;\n
+\t-moz-animation-duration: 225ms;\n
+\tanimation-timing-function: ease-in;\n
+\tanimation-duration: 225ms;\n
+}\n
+@-webkit-keyframes fadein {\n
+    from { opacity: 0; }\n
+    to { opacity: 1; }\n
+}\n
+@-moz-keyframes fadein {\n
+    from { opacity: 0; }\n
+    to { opacity: 1; }\n
+}\n
+@keyframes fadein {\n
+    from { opacity: 0; }\n
+    to { opacity: 1; }\n
+}\n
+@-webkit-keyframes fadeout {\n
+    from { opacity: 1; }\n
+    to { opacity: 0; }\n
+}\n
+@-moz-keyframes fadeout {\n
+    from { opacity: 1; }\n
+    to { opacity: 0; }\n
+}\n
+@keyframes fadeout {\n
+    from { opacity: 1; }\n
+    to { opacity: 0; }\n
+}\n
+.fade.out {\n
+\topacity: 0;\n
+\t-webkit-animation-duration: 125ms;\n
+\t-webkit-animation-name: fadeout;\n
+\t-moz-animation-duration: 125ms;\n
+\t-moz-animation-name: fadeout;\n
+\tanimation-duration: 125ms;\n
+\tanimation-name: fadeout;\n
+}\n
+.fade.in {\n
+\topacity: 1;\n
+\t-webkit-animation-duration: 225ms;\n
+\t-webkit-animation-name: fadein;\n
+\t-moz-animation-duration: 225ms;\n
+\t-moz-animation-name: fadein;\n
+\tanimation-duration: 225ms;\n
+\tanimation-name: fadein;\n
+}\n
+.pop {\n
+\t-webkit-transform-origin: 50% 50%;\n
+\t-moz-transform-origin: 50% 50%;\n
+\ttransform-origin: 50% 50%;\n
+}\n
+.pop.in {\n
+\t-webkit-transform: scale(1);\n
+\t-webkit-animation-name: popin;\n
+\t-webkit-animation-duration: 350ms;\n
+\t-moz-transform: scale(1);\n
+\t-moz-animation-name: popin;\n
+\t-moz-animation-duration: 350ms;\n
+\ttransform: scale(1);\n
+\tanimation-name: popin;\n
+\tanimation-duration: 350ms;\n
+    opacity: 1;\n
+}\n
+.pop.out {\n
+\t-webkit-animation-name: fadeout;\n
+\t-webkit-animation-duration: 100ms;\n
+\t-moz-animation-name: fadeout;\n
+\t-moz-animation-duration: 100ms;\n
+\tanimation-name: fadeout;\n
+\tanimation-duration: 100ms;\n
+\topacity: 0;\n
+}\n
+.pop.in.reverse {\n
+\t-webkit-animation-name: fadein;\n
+\t-moz-animation-name: fadein;\n
+\tanimation-name: fadein;\n
+}\n
+.pop.out.reverse {\n
+\t-webkit-transform: scale(.8);\n
+\t-webkit-animation-name: popout;\n
+\t-moz-transform: scale(.8);\n
+\t-moz-animation-name: popout;\n
+\ttransform: scale(.8);\n
+\tanimation-name: popout;\n
+}\n
+@-webkit-keyframes popin {\n
+    from {\n
+        -webkit-transform: scale(.8);\n
+        opacity: 0;\n
+    }\n
+    to {\n
+        -webkit-transform: scale(1);\n
+        opacity: 1;\n
+    }\n
+}\n
+@-moz-keyframes popin {\n
+    from {\n
+        -moz-transform: scale(.8);\n
+        opacity: 0;\n
+    }\n
+    to {\n
+        -moz-transform: scale(1);\n
+        opacity: 1;\n
+    }\n
+}\n
+@keyframes popin {\n
+    from {\n
+        transform: scale(.8);\n
+        opacity: 0;\n
+    }\n
+    to {\n
+        transform: scale(1);\n
+        opacity: 1;\n
+    }\n
+}\n
+@-webkit-keyframes popout {\n
+    from {\n
+        -webkit-transform: scale(1);\n
+        opacity: 1;\n
+    }\n
+    to {\n
+        -webkit-transform: scale(.8);\n
+        opacity: 0;\n
+    }\n
+}\n
+@-moz-keyframes popout {\n
+    from {\n
+        -moz-transform: scale(1);\n
+        opacity: 1;\n
+    }\n
+    to {\n
+        -moz-transform: scale(.8);\n
+        opacity: 0;\n
+    }\n
+}\n
+@keyframes popout {\n
+    from {\n
+        transform: scale(1);\n
+        opacity: 1;\n
+    }\n
+    to {\n
+        transform: scale(.8);\n
+        opacity: 0;\n
+    }\n
+}\n
+/* keyframes for slidein from sides */\n
+@-webkit-keyframes slideinfromright {\n
+    from { -webkit-transform: translate3d(100%,0,0); }\n
+    to { -webkit-transform: translate3d(0,0,0); }\n
+}\n
+@-moz-keyframes slideinfromright {\n
+    from { -moz-transform: translateX(100%); }\n
+    to { -moz-transform: translateX(0); }\n
+}\n
+@keyframes slideinfromright {\n
+    from { transform: translateX(100%); }\n
+    to { transform: translateX(0); }\n
+}\n
+@-webkit-keyframes slideinfromleft {\n
+    from { -webkit-transform: translate3d(-100%,0,0); }\n
+    to { -webkit-transform: translate3d(0,0,0); }\n
+}\n
+@-moz-keyframes slideinfromleft {\n
+    from { -moz-transform: translateX(-100%); }\n
+    to { -moz-transform: translateX(0); }\n
+}\n
+@keyframes slideinfromleft {\n
+    from { transform: translateX(-100%); }\n
+    to { transform: translateX(0); }\n
+}\n
+/* keyframes for slideout to sides */\n
+@-webkit-keyframes slideouttoleft {\n
+    from { -webkit-transform: translate3d(0,0,0); }\n
+    to { -webkit-transform: translate3d(-100%,0,0); }\n
+}\n
+@-moz-keyframes slideouttoleft {\n
+    from { -moz-transform: translateX(0); }\n
+    to { -moz-transform: translateX(-100%); }\n
+}\n
+@keyframes slideouttoleft {\n
+    from { transform: translateX(0); }\n
+    to { transform: translateX(-100%); }\n
+}\n
+@-webkit-keyframes slideouttoright {\n
+    from { -webkit-transform: translate3d(0,0,0); }\n
+    to { -webkit-transform: translate3d(100%,0,0); }\n
+}\n
+@-moz-keyframes slideouttoright {\n
+    from { -moz-transform: translateX(0); }\n
+    to { -moz-transform: translateX(100%); }\n
+}\n
+@keyframes slideouttoright {\n
+    from { transform: translateX(0); }\n
+    to { transform: translateX(100%); }\n
+}\n
+.slide.out, .slide.in {\n
+\t-webkit-animation-timing-function: ease-out;\n
+\t-webkit-animation-duration: 350ms;\n
+\t-moz-animation-timing-function: ease-out;\n
+\t-moz-animation-duration: 350ms;\n
+\tanimation-timing-function: ease-out;\n
+\tanimation-duration: 350ms;\n
+}\n
+.slide.out {\n
+\t-webkit-transform: translate3d(-100%,0,0);\n
+\t-webkit-animation-name: slideouttoleft;\n
+\t-moz-transform: translateX(-100%);\n
+\t-moz-animation-name: slideouttoleft;\n
+\ttransform: translateX(-100%);\n
+\tanimation-name: slideouttoleft;\n
+}\n
+.slide.in {\n
+\t-webkit-transform: translate3d(0,0,0);\n
+\t-webkit-animation-name: slideinfromright;\n
+\t-moz-transform: translateX(0);\n
+\t-moz-animation-name: slideinfromright;\n
+\ttransform: translateX(0);\n
+\tanimation-name: slideinfromright;\n
+}\n
+.slide.out.reverse {\n
+\t-webkit-transform: translate3d(100%,0,0);\n
+\t-webkit-animation-name: slideouttoright;\n
+\t-moz-transform: translateX(100%);\n
+\t-moz-animation-name: slideouttoright;\n
+\ttransform: translateX(100%);\n
+\tanimation-name: slideouttoright;\n
+}\n
+.slide.in.reverse {\n
+\t-webkit-transform: translate3d(0,0,0);\n
+\t-webkit-animation-name: slideinfromleft;\n
+\t-moz-transform: translateX(0);\n
+\t-moz-animation-name: slideinfromleft;\n
+\ttransform: translateX(0);\n
+\tanimation-name: slideinfromleft;\n
+}\n
+.slidefade.out {\n
+\t-webkit-transform: translateX(-100%);\n
+\t-webkit-animation-name: slideouttoleft;\n
+\t-webkit-animation-duration: 225ms;\n
+\t-moz-transform: translateX(-100%);\n
+\t-moz-animation-name: slideouttoleft;\n
+\t-moz-animation-duration: 225ms;\n
+\ttransform: translateX(-100%);\n
+\tanimation-name: slideouttoleft;\n
+\tanimation-duration: 225ms;\n
+}\n
+.slidefade.in {\n
+\t-webkit-transform: translateX(0);\n
+\t-webkit-animation-name: fadein;\n
+\t-webkit-animation-duration: 200ms;\n
+\t-moz-transform: translateX(0);\n
+\t-moz-animation-name: fadein;\n
+\t-moz-animation-duration: 200ms;\n
+\ttransform: translateX(0);\n
+\tanimation-name: fadein;\n
+\tanimation-duration: 200ms;\n
+}\n
+.slidefade.out.reverse {\n
+\t-webkit-transform: translateX(100%);\n
+\t-webkit-animation-name: slideouttoright;\n
+\t-webkit-animation-duration: 200ms;\n
+\t-moz-transform: translateX(100%);\n
+\t-moz-animation-name: slideouttoright;\n
+\t-moz-animation-duration: 200ms;\n
+\ttransform: translateX(100%);\n
+\tanimation-name: slideouttoright;\n
+\tanimation-duration: 200ms;\n
+}\n
+.slidefade.in.reverse {\n
+\t-webkit-transform: translateX(0);\n
+\t-webkit-animation-name: fadein;\n
+\t-webkit-animation-duration: 200ms;\n
+\t-moz-transform: translateX(0);\n
+\t-moz-animation-name: fadein;\n
+\t-moz-animation-duration: 200ms;\n
+\ttransform: translateX(0);\n
+\tanimation-name: fadein;\n
+\tanimation-duration: 200ms;\n
+}\n
+/* slide down */\n
+.slidedown.out {\n
+\t-webkit-animation-name: fadeout;\n
+\t-webkit-animation-duration: 100ms;\n
+\t-moz-animation-name: fadeout;\n
+\t-moz-animation-duration: 100ms;\n
+\tanimation-name: fadeout;\n
+\tanimation-duration: 100ms;\n
+}\n
+.slidedown.in {\n
+\t-webkit-transform: translateY(0);\n
+\t-webkit-animation-name: slideinfromtop;\n
+\t-webkit-animation-duration: 250ms;\n
+\t-moz-transform: translateY(0);\n
+\t-moz-animation-name: slideinfromtop;\n
+\t-moz-animation-duration: 250ms;\n
+\ttransform: translateY(0);\n
+\tanimation-name: slideinfromtop;\n
+\tanimation-duration: 250ms;\n
+}\n
+.slidedown.in.reverse {\n
+\t-webkit-animation-name: fadein;\n
+\t-webkit-animation-duration: 150ms;\n
+\t-moz-animation-name: fadein;\n
+\t-moz-animation-duration: 150ms;\n
+\tanimation-name: fadein;\n
+\tanimation-duration: 150ms;\n
+}\n
+.slidedown.out.reverse {\n
+\t-webkit-transform: translateY(-100%);\n
+\t-webkit-animation-name: slideouttotop;\n
+\t-webkit-animation-duration: 200ms;\n
+\t-moz-transform: translateY(-100%);\n
+\t-moz-animation-name: slideouttotop;\n
+\t-moz-animation-duration: 200ms;\n
+\ttransform: translateY(-100%);\n
+\tanimation-name: slideouttotop;\n
+\tanimation-duration: 200ms;\n
+}\n
+@-webkit-keyframes slideinfromtop {\n
+    from { -webkit-transform: translateY(-100%); }\n
+    to { -webkit-transform: translateY(0); }\n
+}\n
+@-moz-keyframes slideinfromtop {\n
+    from { -moz-transform: translateY(-100%); }\n
+    to { -moz-transform: translateY(0); }\n
+}\n
+@keyframes slideinfromtop {\n
+    from { transform: translateY(-100%); }\n
+    to { transform: translateY(0); }\n
+}\n
+@-webkit-keyframes slideouttotop {\n
+    from { -webkit-transform: translateY(0); }\n
+    to { -webkit-transform: translateY(-100%); }\n
+}\n
+@-moz-keyframes slideouttotop {\n
+    from { -moz-transform: translateY(0); }\n
+    to { -moz-transform: translateY(-100%); }\n
+}\n
+@keyframes slideouttotop {\n
+    from { transform: translateY(0); }\n
+    to { transform: translateY(-100%); }\n
+}\n
+/* slide up */\n
+.slideup.out {\n
+\t-webkit-animation-name: fadeout;\n
+\t-webkit-animation-duration: 100ms;\n
+\t-moz-animation-name: fadeout;\n
+\t-moz-animation-duration: 100ms;\n
+\tanimation-name: fadeout;\n
+\tanimation-duration: 100ms;\n
+}\n
+.slideup.in {\n
+\t-webkit-transform: translateY(0);\n
+\t-webkit-animation-name: slideinfrombottom;\n
+\t-webkit-animation-duration: 250ms;\n
+\t-moz-transform: translateY(0);\n
+\t-moz-animation-name: slideinfrombottom;\n
+\t-moz-animation-duration: 250ms;\n
+\ttransform: translateY(0);\n
+\tanimation-name: slideinfrombottom;\n
+\tanimation-duration: 250ms;\n
+}\n
+.slideup.in.reverse {\n
+\t-webkit-animation-name: fadein;\n
+\t-webkit-animation-duration: 150ms;\n
+\t-moz-animation-name: fadein;\n
+\t-moz-animation-duration: 150ms;\n
+\tanimation-name: fadein;\n
+\tanimation-duration: 150ms;\n
+}\n
+.slideup.out.reverse {\n
+\t-webkit-transform: translateY(100%);\n
+\t-webkit-animation-name: slideouttobottom;\n
+\t-webkit-animation-duration: 200ms;\n
+\t-moz-transform: translateY(100%);\n
+\t-moz-animation-name: slideouttobottom;\n
+\t-moz-animation-duration: 200ms;\n
+\ttransform: translateY(100%);\n
+\tanimation-name: slideouttobottom;\n
+\tanimation-duration: 200ms;\n
+}\n
+@-webkit-keyframes slideinfrombottom {\n
+    from { -webkit-transform: translateY(100%); }\n
+    to { -webkit-transform: translateY(0); }\n
+}\n
+@-moz-keyframes slideinfrombottom {\n
+    from { -moz-transform: translateY(100%); }\n
+    to { -moz-transform: translateY(0); }\n
+}\n
+@keyframes slideinfrombottom {\n
+    from { transform: translateY(100%); }\n
+    to { transform: translateY(0); }\n
+}\n
+@-webkit-keyframes slideouttobottom {\n
+    from { -webkit-transform: translateY(0); }\n
+    to { -webkit-transform: translateY(100%); }\n
+}\n
+@-moz-keyframes slideouttobottom {\n
+    from { -moz-transform: translateY(0); }\n
+    to { -moz-transform: translateY(100%); }\n
+}\n
+@keyframes slideouttobottom {\n
+    from { transform: translateY(0); }\n
+    to { transform: translateY(100%); }\n
+}\n
+/* The properties in this rule are only necessary for the \'flip\' transition.\n
+ * We need specify the perspective to create a projection matrix. This will add\n
+ * some depth as the element flips. The depth number represents the distance of\n
+ * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n
+ * value.\n
+ */\n
+.viewport-flip {\n
+\t-webkit-perspective: 1000;\n
+\t-moz-perspective: 1000;\n
+\tperspective: 1000;\n
+\tposition: absolute;\n
+}\n
+.flip {\n
+\t-webkit-backface-visibility: hidden;\n
+\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n
+\t-moz-backface-visibility: hidden;\n
+\t-moz-transform: translateX(0);\n
+\tbackface-visibility: hidden;\n
+\ttransform: translateX(0);\n
+}\n
+.flip.out {\n
+\t-webkit-transform: rotateY(-90deg) scale(.9);\n
+\t-webkit-animation-name: flipouttoleft;\n
+\t-webkit-animation-duration: 175ms;\n
+\t-moz-transform: rotateY(-90deg) scale(.9);\n
+\t-moz-animation-name: flipouttoleft;\n
+\t-moz-animation-duration: 175ms;\n
+\ttransform: rotateY(-90deg) scale(.9);\n
+\tanimation-name: flipouttoleft;\n
+\tanimation-duration: 175ms;\n
+}\n
+.flip.in {\n
+\t-webkit-animation-name: flipintoright;\n
+\t-webkit-animation-duration: 225ms;\n
+\t-moz-animation-name: flipintoright;\n
+\t-moz-animation-duration: 225ms;\n
+\tanimation-name: flipintoright;\n
+\tanimation-duration: 225ms;\n
+}\n
+.flip.out.reverse {\n
+\t-webkit-transform: rotateY(90deg) scale(.9);\n
+\t-webkit-animation-name: flipouttoright;\n
+\t-moz-transform: rotateY(90deg) scale(.9);\n
+\t-moz-animation-name: flipouttoright;\n
+\ttransform: rotateY(90deg) scale(.9);\n
+\tanimation-name: flipouttoright;\n
+}\n
+.flip.in.reverse {\n
+\t-webkit-animation-name: flipintoleft;\n
+\t-moz-animation-name: flipintoleft;\n
+\tanimation-name: flipintoleft;\n
+}\n
+@-webkit-keyframes flipouttoleft {\n
+    from { -webkit-transform: rotateY(0); }\n
+    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n
+}\n
+@-moz-keyframes flipouttoleft {\n
+    from { -moz-transform: rotateY(0); }\n
+    to { -moz-transform: rotateY(-90deg) scale(.9); }\n
+}\n
+@keyframes flipouttoleft {\n
+    from { transform: rotateY(0); }\n
+    to { transform: rotateY(-90deg) scale(.9); }\n
+}\n
+@-webkit-keyframes flipouttoright {\n
+    from { -webkit-transform: rotateY(0) ; }\n
+    to { -webkit-transform: rotateY(90deg) scale(.9); }\n
+}\n
+@-moz-keyframes flipouttoright {\n
+    from { -moz-transform: rotateY(0); }\n
+    to { -moz-transform: rotateY(90deg) scale(.9); }\n
+}\n
+@keyframes flipouttoright {\n
+    from { transform: rotateY(0); }\n
+    to { transform: rotateY(90deg) scale(.9); }\n
+}\n
+@-webkit-keyframes flipintoleft {\n
+    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n
+    to { -webkit-transform: rotateY(0); }\n
+}\n
+@-moz-keyframes flipintoleft {\n
+    from { -moz-transform: rotateY(-90deg) scale(.9); }\n
+    to { -moz-transform: rotateY(0); }\n
+}\n
+@keyframes flipintoleft {\n
+    from { transform: rotateY(-90deg) scale(.9); }\n
+    to { transform: rotateY(0); }\n
+}\n
+@-webkit-keyframes flipintoright {\n
+    from { -webkit-transform: rotateY(90deg) scale(.9); }\n
+    to { -webkit-transform: rotateY(0); }\n
+}\n
+@-moz-keyframes flipintoright {\n
+    from { -moz-transform: rotateY(90deg) scale(.9); }\n
+    to { -moz-transform: rotateY(0); }\n
+}\n
+@keyframes flipintoright {\n
+    from { transform: rotateY(90deg) scale(.9); }\n
+    to { transform: rotateY(0); }\n
+}\n
+/* The properties in this rule are only necessary for the \'flip\' transition.\n
+ * We need specify the perspective to create a projection matrix. This will add\n
+ * some depth as the element flips. The depth number represents the distance of\n
+ * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate\n
+ * value.\n
+ */\n
+.viewport-turn {\n
+\t-webkit-perspective: 200px;\n
+\t-moz-perspective: 200px;\n
+\t-ms-perspective: 200px;\n
+\tperspective: 200px;\n
+\tposition: absolute;\n
+}\n
+.turn {\n
+\t-webkit-backface-visibility: hidden;\n
+\t-webkit-transform: translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */\n
+\t-webkit-transform-origin: 0;\n
+\t\n
+\t-moz-backface-visibility: hidden;\n
+\t-moz-transform: translateX(0);\n
+\t-moz-transform-origin: 0;\n
+\t\n
+\tbackface-visibility :hidden;\n
+\ttransform: translateX(0);\n
+\ttransform-origin: 0;\n
+}\n
+.turn.out {\n
+\t-webkit-transform: rotateY(-90deg) scale(.9);\n
+\t-webkit-animation-name: flipouttoleft;\n
+\t-webkit-animation-duration: 125ms;\n
+\t-moz-transform: rotateY(-90deg) scale(.9);\n
+\t-moz-animation-name: flipouttoleft;\n
+\t-moz-animation-duration: 125ms;\n
+\ttransform: rotateY(-90deg) scale(.9);\n
+\tanimation-name: flipouttoleft;\n
+\tanimation-duration: 125ms;\n
+}\n
+.turn.in {\n
+\t-webkit-animation-name: flipintoright;\n
+\t-webkit-animation-duration: 250ms;\n
+\t-moz-animation-name: flipintoright;\n
+\t-moz-animation-duration: 250ms;\n
+\tanimation-name: flipintoright;\n
+\tanimation-duration: 250ms;\n
+\t\n
+}\n
+.turn.out.reverse {\n
+\t-webkit-transform: rotateY(90deg) scale(.9);\n
+\t-webkit-animation-name: flipouttoright;\n
+\t-moz-transform: rotateY(90deg) scale(.9);\n
+\t-moz-animation-name: flipouttoright;\n
+\ttransform: rotateY(90deg) scale(.9);\n
+\tanimation-name: flipouttoright;\n
+}\n
+.turn.in.reverse {\n
+\t-webkit-animation-name: flipintoleft;\n
+\t-moz-animation-name: flipintoleft;\n
+\tanimation-name: flipintoleft;\n
+}\n
+@-webkit-keyframes flipouttoleft {\n
+    from { -webkit-transform: rotateY(0); }\n
+    to { -webkit-transform: rotateY(-90deg) scale(.9); }\n
+}\n
+@-moz-keyframes flipouttoleft {\n
+    from { -moz-transform: rotateY(0); }\n
+    to { -moz-transform: rotateY(-90deg) scale(.9); }\n
+}\n
+@keyframes flipouttoleft {\n
+    from { transform: rotateY(0); }\n
+    to { transform: rotateY(-90deg) scale(.9); }\n
+}\n
+@-webkit-keyframes flipouttoright {\n
+    from { -webkit-transform: rotateY(0) ; }\n
+    to { -webkit-transform: rotateY(90deg) scale(.9); }\n
+}\n
+@-moz-keyframes flipouttoright {\n
+    from { -moz-transform: rotateY(0); }\n
+    to { -moz-transform: rotateY(90deg) scale(.9); }\n
+}\n
+@keyframes flipouttoright {\n
+    from { transform: rotateY(0); }\n
+    to { transform: rotateY(90deg) scale(.9); }\n
+}\n
+@-webkit-keyframes flipintoleft {\n
+    from { -webkit-transform: rotateY(-90deg) scale(.9); }\n
+    to { -webkit-transform: rotateY(0); }\n
+}\n
+@-moz-keyframes flipintoleft {\n
+    from { -moz-transform: rotateY(-90deg) scale(.9); }\n
+    to { -moz-transform: rotateY(0); }\n
+}\n
+@keyframes flipintoleft {\n
+    from { transform: rotateY(-90deg) scale(.9); }\n
+    to { transform: rotateY(0); }\n
+}\n
+@-webkit-keyframes flipintoright {\n
+    from { -webkit-transform: rotateY(90deg) scale(.9); }\n
+    to { -webkit-transform: rotateY(0); }\n
+}\n
+@-moz-keyframes flipintoright {\n
+    from { -moz-transform: rotateY(90deg) scale(.9); }\n
+    to { -moz-transform: rotateY(0); }\n
+}\n
+@keyframes flipintoright {\n
+    from { transform: rotateY(90deg) scale(.9); }\n
+    to { transform: rotateY(0); }\n
+}\n
+/* flow transition */\n
+.flow {\n
+\t-webkit-transform-origin: 50% 30%;\n
+\t-webkit-box-shadow: 0 0 20px rgba(0,0,0,.4);\n
+\t-moz-transform-origin: 50% 30%;\t\n
+\t-moz-box-shadow: 0 0 20px rgba(0,0,0,.4);\n
+\ttransform-origin: 50% 30%;\t\n
+\tbox-shadow: 0 0 20px rgba(0,0,0,.4);\n
+}\n
+.ui-dialog.flow {\n
+\t-webkit-transform-origin: none;\n
+\t-webkit-box-shadow: none;\n
+\t-moz-transform-origin: none;\t\n
+\t-moz-box-shadow: none;\n
+\ttransform-origin: none;\t\n
+\tbox-shadow: none;\n
+}\n
+.flow.out {\n
+\t-webkit-transform: translateX(-100%) scale(.7);\n
+\t-webkit-animation-name: flowouttoleft;\n
+\t-webkit-animation-timing-function: ease;\n
+\t-webkit-animation-duration: 350ms;\n
+\t-moz-transform: translateX(-100%) scale(.7);\n
+\t-moz-animation-name: flowouttoleft;\n
+\t-moz-animation-timing-function: ease;\n
+\t-moz-animation-duration: 350ms;\n
+\ttransform: translateX(-100%) scale(.7);\n
+\tanimation-name: flowouttoleft;\n
+\tanimation-timing-function: ease;\n
+\tanimation-duration: 350ms;\n
+}\n
+.flow.in {\n
+\t-webkit-transform: translateX(0) scale(1);\n
+\t-webkit-animation-name: flowinfromright;\n
+\t-webkit-animation-timing-function: ease;\n
+\t-webkit-animation-duration: 350ms;\n
+\t-moz-transform: translateX(0) scale(1);\n
+\t-moz-animation-name: flowinfromright;\n
+\t-moz-animation-timing-function: ease;\n
+\t-moz-animation-duration: 350ms;\n
+\ttransform: translateX(0) scale(1);\n
+\tanimation-name: flowinfromright;\n
+\tanimation-timing-function: ease;\n
+\tanimation-duration: 350ms;\n
+}\n
+.flow.out.reverse {\n
+\t-webkit-transform: translateX(100%);\n
+\t-webkit-animat
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+ion-name: flowouttoright;\n
+\t-moz-transform: translateX(100%);\n
+\t-moz-animation-name: flowouttoright;\n
+\ttransform: translateX(100%);\n
+\tanimation-name: flowouttoright;\n
+}\n
+.flow.in.reverse {\n
+\t-webkit-animation-name: flowinfromleft;\n
+\t-moz-animation-name: flowinfromleft;\n
+\tanimation-name: flowinfromleft;\n
+}\n
+@-webkit-keyframes flowouttoleft {\n
+    0% { -webkit-transform: translateX(0) scale(1); }\n
+\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n
+    100% { -webkit-transform: translateX(-100%) scale(.7); }\n
+}\n
+@-moz-keyframes flowouttoleft {\n
+    0% { -moz-transform: translateX(0) scale(1); }\n
+\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n
+    100% { -moz-transform:  translateX(-100%) scale(.7); }\n
+}\n
+@keyframes flowouttoleft {\n
+    0% { transform: translateX(0) scale(1); }\n
+\t60%, 70% { transform: translateX(0) scale(.7); }\n
+    100% { transform:  translateX(-100%) scale(.7); }\n
+}\n
+@-webkit-keyframes flowouttoright {\n
+    0% { -webkit-transform: translateX(0) scale(1); }\n
+\t60%, 70% { -webkit-transform: translateX(0) scale(.7); }\n
+    100% { -webkit-transform:  translateX(100%) scale(.7); }\n
+}\n
+@-moz-keyframes flowouttoright {\n
+    0% { -moz-transform: translateX(0) scale(1); }\n
+\t60%, 70% { -moz-transform: translateX(0) scale(.7); }\n
+    100% { -moz-transform:  translateX(100%) scale(.7); }\n
+}\n
+@keyframes flowouttoright {\n
+    0% { transform: translateX(0) scale(1); }\n
+\t60%, 70% { transform: translateX(0) scale(.7); }\n
+    100% { transform:  translateX(100%) scale(.7); }\n
+}\n
+@-webkit-keyframes flowinfromleft {\n
+    0% { -webkit-transform: translateX(-100%) scale(.7); }\n
+\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n
+    100% { -webkit-transform: translateX(0) scale(1); }\n
+}\n
+@-moz-keyframes flowinfromleft {\n
+    0% { -moz-transform: translateX(-100%) scale(.7); }\n
+\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n
+    100% { -moz-transform: translateX(0) scale(1); }\n
+}\n
+@keyframes flowinfromleft {\n
+    0% { transform: translateX(-100%) scale(.7); }\n
+\t30%, 40% { transform: translateX(0) scale(.7); }\n
+    100% { transform: translateX(0) scale(1); }\n
+}\n
+@-webkit-keyframes flowinfromright {\n
+    0% { -webkit-transform: translateX(100%) scale(.7); }\n
+\t30%, 40% { -webkit-transform: translateX(0) scale(.7); }\n
+    100% { -webkit-transform: translateX(0) scale(1); }\n
+}\n
+@-moz-keyframes flowinfromright {\n
+    0% { -moz-transform: translateX(100%) scale(.7); }\n
+\t30%, 40% { -moz-transform: translateX(0) scale(.7); }\n
+    100% { -moz-transform: translateX(0) scale(1); }\n
+}\n
+@keyframes flowinfromright {\n
+    0% { transform: translateX(100%) scale(.7); }\n
+\t30%, 40% { transform: translateX(0) scale(.7); }\n
+    100% { transform: translateX(0) scale(1); }\n
+}\n
+.ui-field-contain,\n
+.ui-mobile fieldset.ui-field-contain {\n
+\tdisplay: block;\n
+\tposition: relative;\n
+\toverflow: visible;\n
+\tclear: both;\n
+\tpadding: .8em 0;\n
+}\n
+.ui-field-contain > label + [class*="ui-"],\n
+.ui-field-contain .ui-controlgroup-controls {\n
+\tmargin: 0;\n
+}\n
+.ui-field-contain:last-child {\n
+\tborder-bottom-width: 0;\n
+}\n
+@media (min-width: 28em) {\n
+\t.ui-field-contain,\n
+\t.ui-mobile fieldset.ui-field-contain {\n
+\t\tpadding: 0;\n
+\t\tmargin: 1em 0;\n
+\t\tborder-bottom-width: 0;\n
+\t}\n
+\t.ui-field-contain:before,\n
+\t.ui-field-contain:after {\n
+\t\tcontent: "";\n
+\t\tdisplay: table;\n
+\t}\n
+\t.ui-field-contain:after {\n
+\t\tclear: both;\n
+\t}\n
+\t.ui-field-contain > label,\n
+\t.ui-field-contain .ui-controlgroup-label,\n
+\t.ui-field-contain > .ui-rangeslider > label {\n
+\t\tfloat: left;\n
+\t\twidth: 20%;\n
+\t\tmargin: .5em 2% 0 0;\n
+\t}\n
+\t.ui-popup .ui-field-contain > label,\n
+\t.ui-popup .ui-field-contain .ui-controlgroup-label,\n
+\t.ui-popup .ui-field-contain > .ui-rangeslider > label {\n
+\t\tfloat: none;\n
+\t\twidth: auto;\n
+\t\tmargin: 0 0 .4em;\n
+\t}\n
+\t.ui-field-contain > label + [class*="ui-"],\n
+\t.ui-field-contain .ui-controlgroup-controls {\n
+\t\tfloat: left;\n
+\t\twidth: 78%;\n
+\t\t-webkit-box-sizing: border-box;\n
+\t\t-moz-box-sizing: border-box;\n
+\t\t-ms-box-sizing: border-box;\n
+\t\tbox-sizing: border-box;\n
+\t}\n
+\t.ui-hide-label > label + [class*="ui-"],\n
+\t.ui-hide-label .ui-controlgroup-controls,\n
+\t.ui-popup .ui-field-contain > label + [class*="ui-"],\n
+\t.ui-popup .ui-field-contain .ui-controlgroup-controls {\n
+\t\tfloat: none;\n
+\t\twidth: 100%;\n
+\t}\n
+}\n
+/* content configurations. */\n
+.ui-grid-a,\n
+.ui-grid-b,\n
+.ui-grid-c,\n
+.ui-grid-d,\n
+.ui-grid-solo {\n
+\toverflow: hidden;\n
+}\n
+.ui-block-a,\n
+.ui-block-b,\n
+.ui-block-c,\n
+.ui-block-d,\n
+.ui-block-e {\n
+\tmargin: 0;\n
+\tpadding: 0;\n
+\tborder: 0;\n
+\tfloat: left;\n
+\tmin-height: 1px;\n
+\t-webkit-box-sizing: border-box;\n
+\t-moz-box-sizing: border-box;\n
+\tbox-sizing: border-box;\n
+}\n
+/* force new row */\n
+.ui-block-a {\n
+\tclear: left;\n
+}\n
+ul.ui-grid-a,\n
+ul.ui-grid-b,\n
+ul.ui-grid-c,\n
+ul.ui-grid-d,\n
+ul.ui-grid-solo,\n
+li.ui-block-a,\n
+li.ui-block-b,\n
+li.ui-block-c,\n
+li.ui-block-d,\n
+li.ui-block-e {\n
+\tmargin-left: 0;\n
+\tmargin-right: 0;\n
+\tpadding: 0;\n
+\tlist-style: none;\n
+}\n
+/* No margin in grids for 100% width button elements until we can use max-width: fill-available; */\n
+[class*="ui-block-"] > button.ui-btn {\n
+\tmargin-right: 0;\n
+\tmargin-left: 0;\n
+}\n
+[class*="ui-block-"] > .ui-btn,\n
+[class*="ui-block-"] > .ui-select,\n
+[class*="ui-block-"] > .ui-checkbox,\n
+[class*="ui-block-"] > .ui-radio,\n
+[class*="ui-block-"] > button.ui-btn-inline,\n
+[class*="ui-block-"] > button.ui-btn-icon-notext {\n
+\tmargin-right: .3125em;\n
+\tmargin-left: .3125em;\n
+}\n
+.ui-grid-a > .ui-block-a,\n
+.ui-grid-a > .ui-block-b {\n
+\t/* width: 49.95%; IE7 */\n
+\t/* margin-right: -.5px; BB5 */\n
+\twidth: 50%;\n
+}\n
+.ui-grid-b > .ui-block-a,\n
+.ui-grid-b > .ui-block-b,\n
+.ui-grid-b > .ui-block-c {\n
+\t/* width: 33.25%; IE7 */\n
+\t/* margin-right: -.5px; BB5 */\n
+\twidth: 33.333%;\n
+}\n
+.ui-grid-c > .ui-block-a,\n
+.ui-grid-c > .ui-block-b,\n
+.ui-grid-c > .ui-block-c,\n
+.ui-grid-c > .ui-block-d {\n
+\t/* width: 24.925%; IE7 */\n
+\t/* margin-right: -.5px; BB5 */\n
+\twidth: 25%;\n
+}\n
+.ui-grid-d > .ui-block-a,\n
+.ui-grid-d > .ui-block-b,\n
+.ui-grid-d > .ui-block-c,\n
+.ui-grid-d > .ui-block-d,\n
+.ui-grid-d > .ui-block-e {\n
+\t/* width: 19.925%; IE7 */\n
+\twidth: 20%;\n
+}\n
+.ui-grid-solo > .ui-block-a {\n
+\twidth: 100%;\n
+\tfloat: none; \n
+}\n
+/* preset breakpoint to switch to stacked grid styles below 35em (560px) */\n
+@media (max-width: 35em) {\n
+\t.ui-responsive > .ui-block-a,\n
+\t.ui-responsive > .ui-block-b,\n
+\t.ui-responsive > .ui-block-c,\n
+\t.ui-responsive > .ui-block-d,\n
+\t.ui-responsive > .ui-block-e {\n
+\t\twidth: 100%; \n
+\t\tfloat: none; \n
+\t}\n
+}\n
+/* fixed page header & footer configuration */\n
+.ui-header-fixed,\n
+.ui-footer-fixed {\n
+\tleft: 0;\n
+\tright: 0;\n
+\twidth: 100%;\n
+\tposition: fixed;\n
+\tz-index: 1000;\n
+}\n
+.ui-header-fixed {\n
+\ttop: -1px;\n
+\tpadding-top: 1px;\n
+}\n
+.ui-header-fixed.ui-fixed-hidden {\n
+\ttop: 0;\n
+\tpadding-top: 0;\n
+}\n
+.ui-header-fixed .ui-btn-left,\n
+.ui-header-fixed .ui-btn-right {\n
+\tmargin-top: 1px;\n
+}\n
+.ui-header-fixed.ui-fixed-hidden .ui-btn-left,\n
+.ui-header-fixed.ui-fixed-hidden .ui-btn-right {\n
+\tmargin-top: 0;\n
+}\n
+.ui-footer-fixed {\n
+\tbottom: -1px;\n
+\tpadding-bottom: 1px;\n
+}\n
+.ui-footer-fixed.ui-fixed-hidden {\n
+\tbottom: 0;\n
+\tpadding-bottom: 0;\n
+}\n
+.ui-header-fullscreen,\n
+.ui-footer-fullscreen {\n
+\tfilter: Alpha(Opacity=90);\n
+\topacity: .9;\n
+}\n
+/* updatePagePadding() will update the padding to actual height of header and footer. */\n
+.ui-page-header-fixed {\n
+\tpadding-top: 2.8125em;\n
+}\n
+.ui-page-footer-fixed {\n
+\tpadding-bottom: 2.8125em;\n
+}\n
+.ui-page-header-fullscreen > .ui-content,\n
+.ui-page-footer-fullscreen > .ui-content {\n
+\tpadding: 0;\n
+}\n
+.ui-fixed-hidden {\n
+\tposition: absolute;\n
+}\n
+.ui-page-header-fullscreen .ui-fixed-hidden,\n
+.ui-page-footer-fullscreen .ui-fixed-hidden {\n
+\tposition: absolute !important;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+.ui-header-fixed .ui-btn,\n
+.ui-footer-fixed .ui-btn { \n
+\tz-index: 10;\n
+}\n
+/* workarounds for other widgets */\n
+.ui-android-2x-fixed .ui-li-has-thumb {\n
+\t-webkit-transform: translate3d(0,0,0);\n
+}\n
+.ui-navbar {\n
+\tmax-width: 100%;\n
+}\n
+.ui-navbar ul:before,\n
+.ui-navbar ul:after {\n
+\tcontent: "";\n
+\tdisplay: table;\n
+}\n
+.ui-navbar ul:after {\n
+\tclear: both;\n
+}\n
+.ui-navbar ul {\n
+\tlist-style: none;\n
+\tmargin: 0;\n
+\tpadding: 0;\n
+\tposition: relative;\n
+\tdisplay: block;\n
+\tborder: 0;\n
+\tmax-width: 100%;\n
+\toverflow: visible;\n
+}\n
+.ui-navbar li .ui-btn {\n
+\tfont-size: 12.5px;\n
+\tdisplay: block;\n
+\tmargin: 0;\n
+\tborder-right-width: 0;\n
+}\n
+.ui-navbar .ui-btn:focus {\n
+\tz-index: 1;\n
+}\n
+/* fixes gaps caused by subpixel problem */\n
+.ui-navbar li:last-child .ui-btn {\n
+\tmargin-right: -4px;\n
+}\n
+.ui-navbar li:last-child .ui-btn:after {\n
+\tmargin-right: 4px;\n
+}\n
+.ui-content .ui-navbar li:last-child .ui-btn,\n
+.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn {\n
+\tborder-right-width: 1px;\n
+\tmargin-right: 0;\n
+}\n
+.ui-content .ui-navbar li:last-child .ui-btn:after,\n
+.ui-content .ui-navbar .ui-grid-duo .ui-block-b .ui-btn:after {\n
+\tmargin-right: 0;\n
+}\n
+.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn {\n
+\tborder-right-width: 1px;\n
+\tmargin-right: -1px;\n
+}\n
+.ui-navbar .ui-grid-duo .ui-block-a:last-child .ui-btn:after {\n
+\tmargin-right: 1px;\n
+}\n
+.ui-navbar .ui-grid-duo .ui-btn {\n
+\tborder-top-width: 0;\n
+}\n
+.ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n
+.ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n
+\tborder-top-width: 1px;\n
+}\n
+.ui-header .ui-navbar .ui-btn,\n
+.ui-footer .ui-navbar .ui-btn {\n
+\tborder-top-width: 0;\n
+\tborder-bottom-width: 0;\n
+}\n
+.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n
+.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n
+.ui-header .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n
+.ui-footer .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n
+\tborder-top-width: 0;\n
+}\n
+.ui-header .ui-title ~ .ui-navbar .ui-btn,\n
+.ui-footer .ui-title ~ .ui-navbar .ui-btn,\n
+.ui-header .ui-navbar .ui-grid-duo .ui-btn,\n
+.ui-footer .ui-navbar .ui-grid-duo .ui-btn,\n
+.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n
+.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child .ui-btn,\n
+.ui-header .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn,\n
+.ui-footer .ui-title ~ .ui-navbar .ui-grid-duo .ui-block-a:first-child + .ui-block-b .ui-btn {\n
+\tborder-top-width: 1px;\n
+}\n
+/* Hide the native input element */\n
+.ui-input-btn input {\n
+\tposition: absolute;\n
+\ttop: 0;\n
+\tleft: 0;\n
+\twidth: 100%;\n
+\theight: 100%;\n
+\tpadding: 0;\n
+\tborder: 0;\n
+\toutline: 0;\n
+\t-webkit-border-radius: inherit;\n
+\tborder-bottom-radius: inherit;\t\n
+\t-webkit-appearance: none;\n
+\t-moz-appearance: none;\n
+\tcursor: pointer;\n
+\tbackground: #fff;\n
+\tbackground: rgba(255,255,255,0);\n
+\tfilter: Alpha(Opacity=0);\n
+\topacity: .1;\n
+\tfont-size: 1px;\n
+\ttext-indent: -9999px;\n
+\tz-index: 2;\n
+}\n
+/* Fixes IE/WP filter alpha opacity bugs */\n
+.ui-input-btn.ui-state-disabled input {\n
+\tposition: absolute !important;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+.ui-collapsible {\n
+\tmargin: .5em -1em;\n
+}\n
+.ui-collapsible-inset,\n
+.ui-collapsible-set {\n
+\tmargin: .5em 0;\n
+}\n
+.ui-collapsible + .ui-collapsible {\n
+\tmargin-top: -.5em;\n
+}\n
+.ui-collapsible-heading {\n
+\tdisplay: block;\n
+\tmargin: 0;\n
+\tpadding: 0;\n
+\tposition: relative;\n
+}\n
+.ui-collapsible-heading .ui-btn {\n
+\ttext-align: left;\n
+\tmargin: 0;\n
+\tborder-left-width: 0;\n
+\tborder-right-width: 0;\n
+}\n
+.ui-collapsible-heading .ui-btn-icon-top,\n
+.ui-collapsible-heading .ui-btn-icon-bottom {\n
+\ttext-align: center;\n
+}\n
+.ui-collapsible-inset .ui-collapsible-heading .ui-btn {\n
+\tborder-right-width: 1px;\n
+\tborder-left-width: 1px;\n
+}\n
+.ui-collapsible-collapsed + .ui-collapsible:not(.ui-collapsible-inset) > .ui-collapsible-heading .ui-btn {\n
+\tborder-top-width: 0;\n
+}\n
+.ui-collapsible-set .ui-collapsible:not(.ui-collapsible-inset) .ui-collapsible-heading .ui-btn {\n
+\tborder-top-width: 1px;\n
+}\n
+.ui-collapsible-heading-status {\n
+\tposition: absolute !important;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+.ui-collapsible-content {\n
+\tdisplay: block;\n
+\tmargin: 0;\t\n
+\tpadding: .5em 1em;\n
+\tbackground-image: none;\n
+}\n
+.ui-collapsible-themed-content .ui-collapsible-content {\n
+\tborder-left-width: 0;\n
+\tborder-right-width: 0;\n
+\tborder-top-width: 0;\n
+\tborder-bottom-width: 1px;\n
+\tborder-style: solid;\n
+}\n
+.ui-collapsible-inset.ui-collapsible-themed-content .ui-collapsible-content {\n
+\tborder-left-width: 1px;\n
+\tborder-right-width: 1px;\n
+}\n
+.ui-collapsible-inset .ui-collapsible-content {\n
+\tmargin: 0;\n
+}\n
+.ui-collapsible-content-collapsed {\n
+\tdisplay: none;\n
+}\n
+.ui-collapsible-set > .ui-collapsible.ui-corner-all {\n
+\t-webkit-border-radius: 0;\n
+\tborder-radius: 0;\n
+}\n
+.ui-collapsible-heading,\n
+.ui-collapsible-heading > .ui-btn {\n
+\t-webkit-border-radius: inherit;\t\n
+\tborder-radius: inherit;\t\n
+}\n
+.ui-collapsible-set .ui-collapsible.ui-first-child {\n
+\t-webkit-border-top-right-radius: inherit;\t\n
+\tborder-top-right-radius: inherit;\n
+\t-webkit-border-top-left-radius: inherit;\t\n
+\tborder-top-left-radius: inherit;\t\t\n
+}\n
+.ui-collapsible-content,\n
+.ui-collapsible-set .ui-collapsible.ui-last-child {\n
+\t-webkit-border-bottom-right-radius: inherit;\t\n
+\tborder-bottom-right-radius: inherit;\n
+\t-webkit-border-bottom-left-radius: inherit;\t\n
+\tborder-bottom-left-radius: inherit;\t\t\n
+}\n
+.ui-collapsible-themed-content:not(.ui-collapsible-collapsed) > .ui-collapsible-heading {\n
+\t-webkit-border-bottom-right-radius: 0;\t\n
+\tborder-bottom-right-radius: 0;\n
+\t-webkit-border-bottom-left-radius: 0;\t\n
+\tborder-bottom-left-radius: 0;\t\t\n
+}\n
+.ui-collapsible-set .ui-collapsible {\n
+\tmargin: -1px -1em 0;\n
+}\n
+.ui-collapsible-set .ui-collapsible-inset {\n
+\tmargin: -1px 0 0;\n
+}\n
+.ui-collapsible-set .ui-collapsible.ui-first-child {\n
+\tmargin-top: 0;\n
+}\n
+.ui-controlgroup,\n
+fieldset.ui-controlgroup {\n
+\tpadding: 0;\n
+\tmargin: .5em 0;\n
+}\n
+.ui-field-contain .ui-controlgroup,\n
+.ui-field-contain fieldset.ui-controlgroup {\n
+\tmargin: 0;\n
+}\n
+.ui-mini .ui-controlgroup-label {\n
+\tfont-size: 16px;\n
+}\n
+.ui-controlgroup.ui-mini .ui-btn-icon-notext,\n
+.ui-controlgroup .ui-mini.ui-btn-icon-notext {\n
+\tfont-size: inherit;\n
+}\n
+.ui-controlgroup-controls .ui-btn,\n
+.ui-controlgroup-controls .ui-checkbox,\n
+.ui-controlgroup-controls .ui-radio,\n
+.ui-controlgroup-controls .ui-select {\n
+\tmargin: 0;\n
+}\n
+.ui-controlgroup-controls .ui-btn:focus,\n
+.ui-controlgroup-controls .ui-btn.ui-focus {\n
+\tz-index: 1;\n
+}\n
+.ui-controlgroup-controls li {\n
+\tlist-style: none;\n
+}\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls {\n
+\tdisplay: inline-block;\n
+\tvertical-align: middle;\n
+}\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls:before,\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n
+\tcontent: "";\n
+\tdisplay: table;\n
+}\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls:after {\n
+\tclear: both;\n
+}\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls > .ui-btn,\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls li > .ui-btn,\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-checkbox,\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-radio,\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-select {\n
+\tfloat: left;\n
+\tclear: none;\n
+}\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn,\n
+.ui-controlgroup-controls .ui-btn-icon-notext {\n
+\twidth: auto;\n
+}\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn-icon-notext,\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls button.ui-btn-icon-notext {\n
+\twidth: 1.5em;\n
+}\n
+ .ui-controlgroup-controls .ui-btn-icon-notext {\n
+\theight: auto;\n
+\tpadding: .7em 1em;\n
+}\n
+.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn {\n
+\tborder-bottom-width: 0;\n
+}\n
+.ui-controlgroup-vertical .ui-controlgroup-controls .ui-btn.ui-last-child {\n
+\tborder-bottom-width: 1px;\n
+}\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn {\n
+\tborder-right-width: 0;\n
+}\n
+.ui-controlgroup-horizontal .ui-controlgroup-controls .ui-btn.ui-last-child {\n
+\tborder-right-width: 1px;\n
+}\n
+.ui-controlgroup-controls .ui-btn-corner-all,\n
+.ui-controlgroup-controls .ui-btn.ui-corner-all {\n
+\t-webkit-border-radius: 0;\n
+\tborder-radius: 0;\n
+}\n
+.ui-controlgroup-controls,\n
+.ui-controlgroup-controls .ui-radio,\n
+.ui-controlgroup-controls .ui-checkbox,\n
+.ui-controlgroup-controls .ui-select,\n
+.ui-controlgroup-controls li {\n
+\t-webkit-border-radius: inherit;\n
+\tborder-radius: inherit;\n
+}\n
+.ui-controlgroup-vertical .ui-btn.ui-first-child {\n
+\t-webkit-border-top-left-radius: inherit;\n
+\tborder-top-left-radius: inherit;\n
+\t-webkit-border-top-right-radius: inherit;\n
+\tborder-top-right-radius: inherit;\n
+}\n
+.ui-controlgroup-vertical .ui-btn.ui-last-child {\n
+\t-webkit-border-bottom-left-radius: inherit;\n
+\tborder-bottom-left-radius: inherit;\n
+\t-webkit-border-bottom-right-radius: inherit;\n
+\tborder-bottom-right-radius: inherit;\n
+}\n
+.ui-controlgroup-horizontal .ui-btn.ui-first-child {\n
+\t-webkit-border-top-left-radius: inherit;\n
+\tborder-top-left-radius: inherit;\n
+\t-webkit-border-bottom-left-radius: inherit;\n
+\tborder-bottom-left-radius: inherit;\n
+}\n
+.ui-controlgroup-horizontal .ui-btn.ui-last-child {\n
+\t-webkit-border-top-right-radius: inherit;\n
+\tborder-top-right-radius: inherit;\n
+\t-webkit-border-bottom-right-radius: inherit;\n
+\tborder-bottom-right-radius: inherit;\n
+}\n
+.ui-controlgroup-controls a.ui-shadow:not(:focus),\n
+.ui-controlgroup-controls button.ui-shadow:not(:focus),\n
+.ui-controlgroup-controls div.ui-shadow:not(.ui-focus) {\n
+\t-moz-box-shadow: none;\n
+\t-webkit-box-shadow: none;\n
+\tbox-shadow: none;\n
+}\n
+/* Fixes legend not wrapping on IE10 */\n
+.ui-controlgroup-label legend {\n
+\tmax-width: 100%;\n
+}\n
+.ui-controlgroup-controls > label {\n
+\tposition: absolute !important;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+.ui-dialog {\n
+\t background: none !important; /* this is to ensure that dialog theming does not apply (by default at least) on the page div */\n
+}\n
+.ui-dialog-contain {\n
+\twidth: 92.5%;\n
+\tmax-width: 500px;\n
+\tmargin: 10% auto 1em auto;\n
+\tpadding: 0;\n
+\tposition: relative;\n
+\ttop: -1em;\n
+}\n
+.ui-dialog-contain > .ui-header, \n
+.ui-dialog-contain > .ui-content, \n
+.ui-dialog-contain > .ui-footer { \n
+\tdisplay: block;\n
+\tposition: relative; \n
+\twidth: auto;\n
+\tmargin: 0;\n
+}\n
+.ui-dialog-contain > .ui-header {\n
+\toverflow: hidden;\n
+\tz-index: 10; \n
+\tpadding: 0;\n
+\tborder-top-width: 0;\n
+}\n
+.ui-dialog-contain > .ui-footer {\n
+\tz-index: 10; \n
+\tpadding: 0 1em; \n
+\tborder-bottom-width: 0;\n
+}\n
+.ui-popup-open .ui-header-fixed,\n
+.ui-popup-open .ui-footer-fixed {\n
+\tposition: absolute !important; /* See issues #4816, #4844 and #4874 and popup.js */\n
+}\n
+.ui-popup-screen {\n
+\tbackground-image: url(data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==); /* Necessary to set some form of background to ensure element is clickable in IE6/7. While legacy IE won\'t understand the data-URI\'d image, it ensures no additional requests occur in all other browsers with little overhead. */\n
+\ttop: 0;\n
+\tleft: 0;\n
+\tright: 0;\n
+\tbottom: 1px;\n
+\tposition: absolute;\n
+\tfilter: Alpha(Opacity=0);\n
+\topacity: 0;\n
+\tz-index: 1099;\n
+}\n
+.ui-popup-screen.in {\n
+\topacity: 0.5;\n
+\tfilter: Alpha(Opacity=50);\n
+}\n
+.ui-popup-screen.out {\n
+\topacity: 0;\n
+\tfilter: Alpha(Opacity=0);\n
+}\n
+.ui-popup-container {\n
+\tz-index: 1100;\n
+\tdisplay: inline-block;\n
+\tposition: absolute;\n
+\tpadding: 0;\n
+\toutline: 0;\n
+}\n
+.ui-popup {\n
+\tposition: relative;\n
+}\n
+.ui-popup.ui-body-inherit {\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+}\n
+.ui-popup-hidden {\n
+\tleft: 0;\n
+\ttop: 0;\n
+\tposition: absolute !important;\n
+\tvisibility: hidden;\n
+}\n
+.ui-popup-truncate {\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\tmargin: -1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+.ui-popup.ui-content,\n
+.ui-popup .ui-content {\n
+\toverflow: visible;\n
+}\n
+.ui-popup > .ui-header {\n
+\tborder-top-width: 0;\n
+}\n
+.ui-popup > .ui-footer {\n
+\tborder-bottom-width: 0;\n
+}\n
+.ui-popup > p,\n
+.ui-popup > h1,\n
+.ui-popup > h2,\n
+.ui-popup > h3,\n
+.ui-popup > h4,\n
+.ui-popup > h5,\n
+.ui-popup > h6 {\n
+\tmargin: .5em .4375em;\n
+}\n
+.ui-popup > span {\n
+\tdisplay: block;\n
+\tmargin: .5em .4375em;\n
+}\n
+.ui-popup-container .ui-content > p,\n
+.ui-popup-container .ui-content > h1,\n
+.ui-popup-container .ui-content > h2,\n
+.ui-popup-container .ui-content > h3,\n
+.ui-popup-container .ui-content > h4,\n
+.ui-popup-container .ui-content > h5,\n
+.ui-popup-container .ui-content > h6 {\n
+\tmargin: .5em 0;\n
+}\n
+.ui-popup-container .ui-content > span {\n
+\tmargin: 0;\n
+}\n
+.ui-popup-container .ui-content > p:first-child,\n
+.ui-popup-container .ui-content > h1:first-child,\n
+.ui-popup-container .ui-content > h2:first-child,\n
+.ui-popup-container .ui-content > h3:first-child,\n
+.ui-popup-container .ui-content > h4:first-child,\n
+.ui-popup-container .ui-content > h5:first-child,\n
+.ui-popup-container .ui-content > h6:first-child {\n
+\tmargin-top: 0;\n
+}\n
+.ui-popup-container .ui-content > p:last-child,\n
+.ui-popup-container .ui-content > h1:last-child,\n
+.ui-popup-container .ui-content > h2:last-child,\n
+.ui-popup-container .ui-content > h3:last-child,\n
+.ui-popup-container .ui-content > h4:last-child,\n
+.ui-popup-container .ui-content > h5:last-child,\n
+.ui-popup-container .ui-content > h6:last-child {\n
+\tmargin-bottom: 0;\n
+}\n
+.ui-popup > img {\n
+\tmax-width: 100%;\n
+\tmax-height: 100%;\n
+\tvertical-align: middle;\n
+}\n
+.ui-popup:not(.ui-content) > img:only-child,\n
+.ui-popup:not(.ui-content) > .ui-btn-left:first-child + img:last-child,\n
+.ui-popup:not(.ui-content) > .ui-btn-right:first-child + img:last-child {\n
+\t-webkit-border-radius: inherit;\n
+\tborder-radius: inherit;\n
+}\n
+.ui-popup iframe {\n
+\tvertical-align: middle;\n
+}\n
+.ui-popup > .ui-btn-left,\n
+.ui-popup > .ui-btn-right {\n
+\tposition: absolute; \n
+\ttop: -11px;\n
+\tmargin: 0;\n
+\tz-index: 1101;\n
+}\n
+.ui-popup > .ui-btn-left {\n
+\tleft: -11px;\n
+}\n
+.ui-popup > .ui-btn-right {\n
+\tright: -11px;\n
+}\n
+/* Dimensions related to the popup arrow\n
+-----------------------------------------------------------------------------------------------------------*/\n
+/* desired triangle height: 10px */\n
+/**\n
+ * guide for the arrow - its width, height, and offset are theme-dependent and\n
+ * should be expessed as left, right, top, bottom, so that the element bearing\n
+ * such a class becomes stretched inside its parent position: relative element.\n
+ * The left/top/right/bottom specified below should reflect the corresponding\n
+ * border radii and so it leaves room for the shadow:\n
+ *     ..--------------------..\n
+ *   ."        ^ top           ".\n
+ *  /          v                 \\\n
+ * |     +------------------+     |\n
+ * |     |                  |     |\n
+ * | left|                  |right|\n
+ * |<--->|                  |<--->|\n
+ * |     +------------------+     |\n
+ *  \\          ^                 /\n
+ *   `.        v bottom        .\'\n
+ *     ""--------------------""\n
+ * The idea is that the top/left of the arrow container box does not move to a\n
+ * coordinate smaller than the top/left of the guide and the right/bottom of\n
+ * the arrow container box does not move to a coordinate larger than the\n
+ * bottom/right of the guide. This will help us avoid the following situation:\n
+ *        ..--------------------..\n
+ *      ."        ^ top           ".\n
+ *   /|/          v                 \\\n
+ *  / |     +------------------+     |\n
+ *  \\ |     |                  |     |\n
+ *   \\| left|                  |right|\n
+ *    |<--->|                  |<--->|\n
+ *    |     +------------------+     |\n
+ *     \\          ^                 /\n
+ *      `.        v bottom        .\'\n
+ *        ""--------------------""\n
+ * The arrow should not receive a top/left coordinate such that it is too close\n
+ * to one of the corners, because then at first the shadow of the arrow and,\n
+ * given a coordinate even closer to the corner, even the body of the arrow will\n
+ * "stick out" of the corner of the popup. The guide provides a hint to the\n
+ * arrow positioning code as to which range of values is acceptable for the\n
+ * arrow container\'s top/left coordinate.\n
+ **/\n
+.ui-popup-arrow-container {\n
+\twidth: 20px;\n
+\theight: 20px;\n
+}\n
+/* aside from the "infinities" (-1000,2000), triangle height is used */\n
+.ui-popup-arrow-container.ui-popup-arrow-l {\n
+\tleft: -10px;\n
+\tclip: rect(-1000px,10px,2000px,-1000px);\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-t {\n
+\ttop: -10px;\n
+\tclip: rect(-1000px,2000px,10px,-1000px);\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-r {\n
+\tright: -10px;\n
+\tclip: rect(-1000px,2000px,2000px,10px);\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-b {\n
+\tbottom: -10px;\n
+\tclip: rect(10px,2000px,1000px,-1000px);\n
+}\n
+/**\n
+ * For each side, the arrow is twice the desired size and its corner is aligned\n
+ * with the edge of the container:\n
+ *                                           \n
+ *           /\\         /\\                +----+\t     /\\\n
+ *          /  \\       /  \\ \t\t\t\t\t    | /\\ |top   /  \\\n
+ *      +----+  \\     /  +----+       +-->|/  \\|     /    \\\n
+ *  left| /  |   \\   /   |  \\ |right  |   |    |    /      \\\n
+ *      |/   |    \\ /    |   \\| \t\t\t|  /|    |\\  /        \\\n
+ *      |\\   |    / \\    |   /| \t\t\t| / +----+ \\ \\ +----+ /\n
+ *      | \\  |   /   \\   |  / |       | \\        /  \\|    |/\n
+ *      +----+  /     \\  +----+       |  \\      /    |    |\n
+ *       ^  \\  /       \\  /  ^        |   \\    /  +->|\\  /|\n
+ *       |   \\/         \\/   |        |    \\  /   |  | \\/ |bottom\n
+ *       |                   |        |     \\/    |  +----+\n
+ *       +-------------------+--------+-----------+\n
+ *                           |\n
+ *                    arrow container\n
+ *                     (clips arrow)\n
+ **/\n
+.ui-popup-arrow-container .ui-popup-arrow {\n
+\t/* (4*desired triangle height)/sqrt(2) - does not account for border - centred within the outer rectangle */\n
+\twidth: 28.284271247px;\n
+\theight: 28.284271247px;\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-t .ui-popup-arrow {\n
+\tleft: -4.142135623px;\n
+\ttop: 5.857864376px;\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-b .ui-popup-arrow {\n
+\tleft: -4.142135623px;\n
+\ttop: -14.142135623px;\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-l .ui-popup-arrow {\n
+\tleft: 5.857864376px;\n
+\ttop: -4.142135623px;\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-r .ui-popup-arrow {\n
+\tleft: -14.142135623px;\n
+\ttop: -4.142135623px;\n
+}\n
+/* Fix rotation center for oldIE - see http://www.useragentman.com/IETransformsTranslator/ */\n
+.ui-popup-arrow-container.ui-popup-arrow-t.ie .ui-popup-arrow {\n
+    margin-left: -5.857864376269049px;\n
+    margin-top: -7.0710678118654755px;\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-b.ie .ui-popup-arrow {\n
+    margin-left: -5.857864376269049px;\n
+    margin-top: -4.142135623730951px;\n
+}\n
+ \n
+.ui-popup-arrow-container.ui-popup-arrow-l.ie .ui-popup-arrow {\n
+    margin-left: -7.0710678118654755px;\n
+    margin-top: -5.857864376269049px;\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-r.ie .ui-popup-arrow {\n
+    margin-left: -4.142135623730951px;\n
+    margin-top: -5.857864376269049px;\n
+}\n
+.ui-popup-arrow-background {\n
+\t/* desired triangle height is used here */\n
+\twidth: 20px;\n
+\theight: 20px;\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-t .ui-popup-arrow-background\n
+.ui-popup-arrow-container.ui-popup-arrow-b .ui-popup-arrow-background {\n
+\tbackground-position: 0 10px;\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-l .ui-popup-arrow-background,\n
+.ui-popup-arrow-container.ui-popup-arrow-r .ui-popup-arrow-background {\n
+\tbackground-position: 10px 0;\n
+}\n
+/* structure */\n
+.ui-popup > .ui-popup-arrow-guide {\n
+\tposition: absolute;\n
+\tleft: 0;\n
+\tright: 0;\n
+\ttop: 0;\n
+\tbottom: 0;\n
+\tvisibility: hidden;\n
+}\n
+.ui-popup-arrow-container {\n
+\tposition: absolute;\n
+}\n
+.ui-popup-arrow {\n
+\t-webkit-transform: rotate(45deg);\n
+\t-moz-transform: rotate(45deg);\n
+\t-ms-transform: rotate(45deg);\n
+\ttransform: rotate(45deg);\n
+\tposition: absolute;\n
+\toverflow: hidden;\n
+\tbox-sizing: border-box;\n
+}\n
+.ui-popup-arrow-container.ie .ui-popup-arrow {\n
+\t-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067811865474, M12=-0.7071067811865477, M21=0.7071067811865477, M22=0.7071067811865474, SizingMethod=\'auto expand\')";\n
+\tfilter: progid:DXImageTransform.Microsoft.Matrix(\n
+\t      \tM11=0.7071067811865474,\n
+        \tM12=-0.7071067811865477,\n
+        \tM21=0.7071067811865477,\n
+        \tM22=0.7071067811865474,\n
+        \tSizingMethod=\'auto expand\');\n
+}\n
+.ui-popup-arrow-background {\n
+\tposition: absolute;\n
+\tborder: 0;\n
+}\n
+.ui-popup-arrow-container.ie .ui-popup-arrow-background {\n
+\tbackground: none;\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-t .ui-popup-arrow-background,\n
+.ui-popup-arrow-container.ui-popup-arrow-b .ui-popup-arrow-background {\n
+\t/* Undo rotation and reflect in x axis */\n
+\t-webkit-transform: rotate(-45deg) scale(1, -1);\n
+\t-moz-transform: rotate(-45deg) scale(1, -1);\n
+\t-ms-transform: rotate(-45deg) scale(1, -1);\n
+\ttransform: rotate(-45deg) scale(1, -1);\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-t.ie .ui-popup-arrow-background,\n
+.ui-popup-arrow-container.ui-popup-arrow-b.ie .ui-popup-arrow-background {\n
+   -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.7071067811865483, M12=-0.7071067811865467, M21=-0.7071067811865467, M22=-0.7071067811865483, SizingMethod=\'auto expand\')";\n
+   filter: progid:DXImageTransform.Microsoft.Matrix(\n
+            M11=0.7071067811865483,\n
+            M12=-0.7071067811865467,\n
+            M21=-0.7071067811865467,\n
+            M22=-0.7071067811865483,\n
+            SizingMethod=\'auto expand\');\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-l .ui-popup-arrow-background,\n
+.ui-popup-arrow-container.ui-popup-arrow-r .ui-popup-arrow-background {\n
+\t/* Undo rotation and reflect in y axis */\n
+\t-webkit-transform: rotate(-45deg) scale(-1, 1);\n
+\t-moz-transform: rotate(-45deg) scale(-1, 1);\n
+\t-ms-transform: rotate(-45deg) scale(-1, 1);\n
+\ttransform: rotate(-45deg) scale(-1, 1);\n
+}\n
+.ui-popup-arrow-container.ui-popup-arrow-l.ie .ui-popup-arrow-background,\n
+.ui-popup-arrow-container.ui-popup-arrow-r.ie .ui-popup-arrow-background {\n
+   -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=-0.7071067811865483, M12=0.7071067811865467, M21=0.7071067811865467, M22=0.7071067811865483, SizingMethod=\'auto expand\')";\n
+   filter: progid:DXImageTransform.Microsoft.Matrix(\n
+            M11=-0.7071067811865483,\n
+            M12=0.7071067811865467,\n
+            M21=0.7071067811865467,\n
+            M22=0.7071067811865483,\n
+            SizingMethod=\'auto expand\');\n
+}\n
+.ui-checkbox,\n
+.ui-radio {\n
+\tmargin: .5em 0;\n
+\tposition: relative;\n
+}\n
+.ui-checkbox .ui-btn,\n
+.ui-radio .ui-btn {\n
+\tmargin: 0;\n
+\ttext-align: left;\n
+\twhite-space: normal; /* Nowrap + ellipsis doesn\'t work on label. Issue #1419. */\n
+\tz-index: 2;\n
+}\n
+.ui-controlgroup .ui-checkbox .ui-btn.ui-focus,\n
+.ui-controlgroup .ui-radio .ui-btn.ui-focus {\n
+\tz-index: 3;\n
+}\n
+.ui-checkbox .ui-btn-icon-top,\n
+.ui-radio .ui-btn-icon-top,\n
+.ui-checkbox .ui-btn-icon-bottom,\n
+.ui-radio .ui-btn-icon-bottom {\n
+\ttext-align: center;\n
+}\n
+.ui-controlgroup-horizontal .ui-checkbox .ui-btn:after,\n
+.ui-controlgroup-horizontal .ui-radio .ui-btn:after {\n
+\tcontent: none;\n
+\tdisplay: none;\n
+}\n
+/* Native input positioning */\n
+.ui-checkbox input,\n
+.ui-radio input {\n
+\tposition: absolute;\n
+\tleft: .466em;\n
+\ttop: 50%;\n
+\twidth: 22px;\n
+\theight: 22px;\n
+\tmargin: -11px 0 0 0;\n
+\toutline: 0 !important;\n
+\tz-index: 1;\n
+}\n
+.ui-controlgroup-horizontal .ui-checkbox input,\n
+.ui-controlgroup-horizontal .ui-radio input {\n
+\tleft: 50%;\n
+\tmargin-left: -9px;\n
+}\n
+.ui-checkbox input:disabled,\n
+.ui-radio input:disabled {\n
+\tposition: absolute !important;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+.ui-select {\n
+\tmargin-top: .5em;\n
+\tmargin-bottom: .5em; /* no shorthand for margin because it would override margin-right for inline selects */\n
+\tposition: relative;\n
+}\n
+.ui-select > select {\n
+\tposition: absolute !important;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+.ui-select .ui-btn {\n
+\tmargin: 0;\n
+\topacity: 1; /* Fixes #2588: When Windows Phone 7.5 (Mango) tries to calculate a numeric opacity for a select (including "inherit") without explicitly specifying an opacity on the parent to give it context, a bug appears where clicking elsewhere on the page after opening the select will open the select again. */\n
+}\n
+.ui-select .ui-btn select {\n
+\tposition: absolute;\n
+\ttop: 0;\n
+\tleft: 0;\n
+\twidth: 100%;\n
+\tmin-height: 1.5em;\n
+\tmin-height: 100%;\n
+\theight: 3em;\n
+\tmax-height: 100%;\n
+\toutline: 0;\n
+\t-webkit-border-radius: inherit;\n
+\tborder-radius: inherit;\t\n
+\t-webkit-appearance: none;\n
+\t-moz-appearance: none;\n
+\tcursor: pointer;\n
+\tfilter: Alpha(Opacity=0);\n
+\topacity: 0;\n
+\tz-index: 2;\n
+}\n
+@-moz-document url-prefix() {\n
+\t.ui-select .ui-btn select {\n
+\t\topacity: 0.0001;\n
+\t}\n
+}\n
+/* Display none because of issues with IE/WP\'s filter alpha opacity */\n
+.ui-select .ui-state-disabled select {\n
+\tdisplay: none;\n
+}\n
+/* Because we add all classes of the select and option elements to the span... */ \n
+.ui-select span.ui-state-disabled {\n
+\tfilter: Alpha(Opacity=100);\n
+\topacity: 1;\n
+}\n
+.ui-select .ui-btn.ui-select-nativeonly {\n
+\tborder-radius: 0;\n
+\tborder: 0;\n
+}\n
+.ui-select .ui-btn.ui-select-nativeonly select {\n
+\topacity: 1;\n
+\ttext-indent: 0;\n
+\tdisplay: block;\n
+}\n
+/* ui-li-count is styled in the listview CSS. We set padding and offset here because select supports icon position while listview doesn\'t. */\n
+.ui-select .ui-li-has-count.ui-btn {\n
+\tpadding-right: 2.8125em;\n
+}\n
+.ui-select .ui-li-has-count.ui-btn-icon-right {\n
+\tpadding-right: 4.6875em;\n
+}\n
+.ui-select .ui-btn-icon-right .ui-li-count {\n
+\tright: 3.2em;\n
+}\n
+/* We set the rules for the span as well to fix an issue on Chrome with text-overflow ellipsis for the button in combination with text-align center. */\n
+.ui-select .ui-btn > span:not(.ui-li-count) {\n
+\tdisplay: block;\n
+\ttext-overflow: ellipsis;\n
+\toverflow: hidden !important;\n
+\twhite-space: nowrap;\n
+}\n
+.ui-selectmenu.ui-popup {\n
+\tmin-width: 11em;\n
+}\n
+.ui-selectmenu .ui-dialog-contain {\n
+\toverflow: hidden;\n
+}\n
+.ui-selectmenu .ui-header {\n
+\tmargin: 0;\n
+\tpadding: 0;\n
+\tborder-width: 0;\n
+}\n
+.ui-selectmenu.ui-dialog .ui-header {\n
+\tz-index: 1;\n
+\tposition: relative;\n
+}\n
+.ui-selectmenu.ui-popup .ui-header {\n
+\t-webkit-border-bottom-right-radius: 0;\n
+\tborder-bottom-right-radius: 0;\n
+\t-webkit-border-bottom-left-radius: 0;\n
+\tborder-bottom-left-radius: 0;\n
+}\n
+/* when no placeholder is defined in a multiple select, the header height doesn\'t even extend past the close button.  this shim\'s content in there */\n
+.ui-selectmenu.ui-popup .ui-header h1:after {\n
+\tcontent: \'.\';\n
+\tvisibility: hidden;\n
+}\n
+.ui-selectmenu .ui-header .ui-title {\n
+\tmargin: 0 2.875em;\n
+}\n
+.ui-selectmenu.ui-dialog .ui-content {\n
+\toverflow: visible;\n
+\tz-index: 1;\n
+}\n
+.ui-selectmenu .ui-selectmenu-list {\n
+\tmargin: 0;\n
+\t-webkit-border-radius: inherit;\n
+\tborder-radius: inherit;\t\n
+}\n
+.ui-header:not(.ui-screen-hidden) + .ui-selectmenu-list {\n
+\t-webkit-border-top-right-radius: 0;\n
+\tborder-top-right-radius: 0;\n
+\t-webkit-border-top-left-radius: 0;\n
+\tborder-top-left-radius: 0;\n
+}\n
+.ui-header.ui-screen-hidden + .ui-selectmenu-list li.ui-first-child .ui-btn {\n
+\tborder-top-width: 0;\n
+}\n
+.ui-selectmenu .ui-selectmenu-list li.ui-last-child .ui-btn {\n
+\tborder-bottom-width: 0;\n
+}\n
+.ui-selectmenu .ui-btn.ui-li-divider {\n
+\tcursor: default;\n
+}\n
+.ui-selectmenu .ui-selectmenu-placeholder {\n
+\tdisplay: none;\n
+}\n
+.ui-listview,\n
+.ui-listview > li {\n
+\tmargin: 0;\n
+\tpadding: 0;\n
+\tlist-style: none;\n
+}\n
+.ui-content .ui-listview,\n
+.ui-panel-inner > .ui-listview {\n
+\tmargin: -1em;\n
+}\n
+.ui-content .ui-listview-inset,\n
+.ui-panel-inner > .ui-listview-inset {\n
+\tmargin: 1em 0;\n
+}\n
+.ui-collapsible-content > .ui-listview {\n
+\tmargin: -.5em -1em;\n
+}\n
+.ui-collapsible-content > .ui-listview-inset {\n
+\tmargin: .5em 0;\n
+}\n
+.ui-listview > li {\n
+\tdisplay: block;\n
+\tposition: relative;\n
+\toverflow: visible;\n
+}\n
+.ui-listview .ui-li-static,\n
+.ui-listview .ui-li-divider,\n
+.ui-listview > li > a.ui-btn {\n
+\tmargin: 0;\n
+\tdisplay: block;\n
+\tposition: relative;\n
+\ttext-align: left;\n
+\ttext-overflow: ellipsis;\n
+\toverflow: hidden;\n
+\twhite-space: nowrap;\n
+}\n
+.ui-listview > li > .ui-btn:focus {\n
+\tz-index: 1;\n
+}\n
+.ui-listview .ui-li-static,\n
+.ui-listview .ui-li-divider,\n
+.ui-listview > li > a.ui-btn {\n
+\tborder-width: 1px 0 0 0;\n
+\tborder-style: solid;\n
+}\n
+.ui-listview-inset .ui-li-static,\n
+.ui-listview-inset .ui-li-divider,\n
+.ui-listview-inset > li > a.ui-btn {\n
+\tborder-right-width: 1px;\n
+\tborder-left-width: 1px;\n
+}\n
+.ui-listview .ui-li-static.ui-last-child,\n
+.ui-listview .ui-li-divider.ui-last-child,\n
+.ui-listview > li.ui-last-child > a.ui-btn {\n
+\tborder-bottom-width: 1px;\n
+}\n
+.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n
+.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n
+\tborder-top-width: 0;\n
+}\n
+.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child,\n
+.ui-collapsible-themed-content .ui-listview:not(.ui-listview-inset) > li.ui-last-child > a.ui-btn {\n
+\tborder-bottom-width: 0;\n
+}\n
+.ui-listview > li.ui-first-child,\n
+.ui-listview > li.ui-first-child > a.ui-btn {\n
+\t-webkit-border-top-right-radius: inherit;\t\n
+\tborder-top-right-radius: inherit;\n
+\t-webkit-border-top-left-radius: inherit;\n
+\tborder-top-left-radius: inherit;\n
+}\n
+.ui-listview > li.ui-last-child,\n
+.ui-listview > li.ui-last-child > a.ui-btn {\n
+\t-webkit-border-bottom-right-radius: inherit;\n
+\tborder-bottom-right-radius: inherit;\n
+\t-webkit-border-bottom-left-radius: inherit;\n
+\tborder-bottom-left-radius: inherit;\n
+}\n
+.ui-listview > li.ui-li-has-alt > a.ui-btn {\n
+\t-webkit-border-top-right-radius: 0;\n
+\tborder-top-right-radius: 0;\n
+\t-webkit-border-bottom-right-radius: 0;\n
+\tborder-bottom-right-radius: 0;\n
+}\n
+.ui-listview > li.ui-first-child > a.ui-btn + a.ui-btn {\n
+\t-webkit-border-top-left-radius: 0;\t\n
+\tborder-top-left-radius: 0;\n
+\t-webkit-border-top-right-radius: inherit;\n
+\tborder-top-right-radius: inherit;\n
+}\n
+.ui-listview > li.ui-last-child > a.ui-btn + a.ui-btn {\n
+\t-webkit-border-bottom-left-radius: 0;\n
+\tborder-bottom-left-radius: 0;\n
+\t-webkit-border-bottom-right-radius: inherit;\n
+\tborder-bottom-right-radius: inherit;\n
+}\n
+.ui-listview > li.ui-first-child img:first-child:not(.ui-li-icon) {\n
+\t-webkit-border-top-left-radius: inherit;\n
+\tborder-top-left-radius: inherit;\t\n
+}\n
+.ui-listview > li.ui-last-child img:first-child:not(.ui-li-icon) {\n
+\t-webkit-border-bottom-left-radius: inherit;\n
+\tborder-bottom-left-radius: inherit;\t\n
+}\n
+.ui-collapsible-content > .ui-listview:not(.ui-listview-inset) {\n
+\t-webkit-border-radius: inherit;\n
+\tborder-bottom-radius: inherit;\t\n
+}\n
+.ui-listview .ui-li-static {\n
+\tpadding: .7em 1em;\n
+}\n
+.ui-listview .ui-li-divider {\n
+\tpadding: .5em 1.143em;\n
+\tfont-size: 14px;\n
+\tfont-weight: bold;\n
+\tcursor: default;\n
+\toutline: 0; /* Dividers in custom selectmenus have tabindex */\n
+}\n
+.ui-listview .ui-li-has-count > .ui-btn,\n
+.ui-listview .ui-li-static.ui-li-has-count,\n
+.ui-listview .ui-li-divider.ui-li-has-count {\n
+\tpadding-right: 2.8125em;\n
+}\n
+.ui-listview .ui-li-has-count > .ui-btn-icon-right {\n
+\tpadding-right: 4.6875em;\n
+}\n
+.ui-listview .ui-li-has-thumb > .ui-btn,\n
+.ui-listview .ui-li-static.ui-li-has-thumb {\n
+\tmin-height: 3.625em;\n
+\tpadding-left: 6.25em;\n
+}\n
+/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n
+.ui-listview .ui-li-has-icon > .ui-btn,\n
+.ui-listview .ui-li-static.ui-li-has-icon {\n
+\tmin-height: 1.25em;\n
+\tpadding-left: 2.5em;\n
+}\n
+/* Used by both listview and custom multiple select button */\n
+.ui-li-count {\n
+\tposition: absolute;\n
+\tfont-size: 12.5px;\n
+\tfont-weight: bold;\n
+\ttext-align: center;\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+\tpadding: 0 .48em;\n
+\tline-height: 1.6em;\n
+\tmin-height: 1.6em;\n
+\tmin-width: .64em;\n
+\tright: .8em;\n
+\ttop: 50%;\n
+\tmargin-top: -.88em;\n
+}\n
+.ui-listview .ui-btn-icon-right .ui-li-count {\n
+\tright: 3.2em;\n
+}\n
+.ui-listview .ui-li-has-thumb > img:first-child,\n
+.ui-listview .ui-li-has-thumb > .ui-btn > img:first-child,\n
+.ui-listview .ui-li-has-thumb .ui-li-thumb {\n
+\tposition: absolute;\n
+\tleft: 0;\n
+\ttop: 0;\n
+\tmax-height: 5em;\n
+\tmax-width: 5em;\n
+}\n
+/* ui-li-has-icon deprecated in 1.4. TODO: remove in 1.5 */\n
+.ui-listview .ui-li-has-icon > img:first-child,\n
+.ui-listview .ui-li-has-icon > .ui-btn > img:first-child {\n
+\tposition: absolute;\n
+\tleft: .625em;\n
+\ttop: .9em;\n
+\tmax-height: 1em;\n
+\tmax-width: 1em;\n
+}\n
+.ui-listview > li h1,\n
+.ui-listview > li h2,\n
+.ui-listview > li h3,\n
+.ui-listview > li h4,\n
+.ui-listview > li h5,\n
+.ui-listview > li h6 {\n
+\tfont-size: 1em;\n
+\tfont-weight: bold;\n
+\tdisplay: block;\n
+\tmargin: .45em 0;\n
+\ttext-overflow: ellipsis;\n
+\toverflow: hidden;\n
+\twhite-space: nowrap;\n
+}\n
+.ui-listview > li p {\n
+\tfont-size: .75em;\n
+\tfont-weight: normal;\n
+\tdisplay: block;\n
+\tmargin: .6em 0;\n
+\ttext-overflow: ellipsis;\n
+\toverflow: hidden;\n
+\twhite-space: nowrap;\n
+}\n
+.ui-listview .ui-li-aside {\n
+\tposition: absolute;\n
+\ttop: 1em;\n
+\tright: 3.333em;\n
+\tmargin: 0;\n
+\ttext-align: right;\n
+}\n
+.ui-listview > li.ui-li-has-alt > .ui-btn {\n
+\tmargin-right: 2.5em;\n
+\tborder-right-width: 0;\n
+}\n
+.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn {\n
+\tposition: absolute;\n
+\twidth: 2.5em;\n
+\theight: 100%;\n
+\tmin-height: auto;\n
+\t-webkit-box-sizing: border-box;\n
+\t-moz-box-sizing: border-box;\n
+\tbox-sizing: border-box;\n
+\tborder-left-width: 1px;\n
+\ttop: 0;\n
+\tright: 0;\n
+\tmargin: 0;\n
+\tpadding: 0;\n
+\tz-index: 2;\n
+}\n
+.ui-listview-inset > li.ui-li-has-alt > .ui-btn + .ui-btn {\n
+\tborder-right-width: 1px;\n
+}\n
+.ui-listview > li.ui-li-has-alt > .ui-btn + .ui-btn:focus {\n
+\tz-index: 3;\n
+}\n
+ol.ui-listview,\n
+ol.ui-listview .ui-li-divider {\n
+\tcounter-reset: listnumbering;\n
+}\n
+ol.ui-listview > li > .ui-btn,\n
+ol.ui-listview > li.ui-li-static {\n
+\tvertical-align: middle;\n
+}\n
+ol.ui-listview > li > .ui-btn:before,\n
+ol.ui-listview > li.ui-li-static:before,\n
+ol.ui-listview > li.ui-field-contain > label:before,\n
+ol.ui-listview > li.ui-field-contain > .ui-controlgroup-label:before {\n
+\tdisplay: inline-block;\n
+\tfont-size: .9em;\n
+\tfont-weight: normal;\n
+\tpadding-right: .3em;\n
+\tmin-width: 1.4em;\n
+\tline-height: 1.5;\n
+\tvertical-align: middle;\n
+\tcounter-increment: listnumbering;\n
+\tcontent: counter(listnumbering) ".";\n
+}\n
+ol.ui-listview > li.ui-field-contain:before {\n
+\tcontent: none;\n
+\tdisplay: none;\n
+}\n
+ol.ui-listview > li h1:first-child,\n
+ol.ui-listview > li h2:first-child,\n
+ol.ui-listview > li h3:first-child,\n
+ol.ui-listview > li h4:first-child,\n
+ol.ui-listview > li h5:first-child,\n
+ol.ui-listview > li h6:first-child,\n
+ol.ui-listview > li p:first-child,\n
+ol.ui-listview > li img:first-child + * {\n
+\tdisplay: inline-block;\n
+\tvertical-align: middle;\n
+}\n
+ol.ui-listview > li h1:first-child ~ *,\n
+ol.ui-listview > li h2:first-child ~ *,\n
+ol.ui-listview > li h3:first-child ~ *,\n
+ol.ui-listview > li h4:first-child ~ *,\n
+ol.ui-listview > li h5:first-child ~ *,\n
+ol.ui-listview > li h6:first-child ~ *,\n
+ol.ui-listview > li p:first-child ~ *,\n
+ol.ui-listview > li img:first-child + * ~ * {\n
+\tmargin-top: 0;\n
+\ttext-indent: 2.04em; /* (1.4em + .3em) * .9em / .75em */\n
+}\n
+html .ui-filterable + .ui-listview,\n
+html .ui-filterable.ui-listview {\n
+\tmargin-top: .5em;\n
+}\n
+.ui-collapsible-content > form.ui-filterable {\n
+\tmargin-top: -.5em;\n
+}\n
+.ui-collapsible-content > .ui-input-search.ui-filterable {\n
+\tmargin-top: 0;\n
+}\n
+.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n
+.ui-collapsible-content > .ui-filterable + .ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn,\n
+.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child,\n
+.ui-collapsible-content > .ui-filterable.ui-listview:not(.ui-listview-inset) > li.ui-first-child > a.ui-btn {\n
+\tborder-top-width: 1px;\n
+}\n
+div.ui-slider {\n
+\theight: 30px;\n
+\tmargin: .5em 0;\n
+\tpadding: 0;\n
+\t-ms-touch-action: pan-y pinch-zoom double-tap-zoom;\n
+}\n
+div.ui-slider:before,\n
+div.ui-slider:after {\n
+\tcontent: "";\n
+\tdisplay: table;\n
+}\n
+div.ui-slider:after {\n
+\tclear: both;\n
+}\n
+input.ui-slider-input {\n
+\tdisplay: block;\n
+\tfloat: left;\n
+\tfont-size: 14px;\n
+\tfont-weight: bold;\n
+\tmargin: 0;\n
+\tpadding: 4px;\n
+\twidth: 40px;\n
+\theight: 20px;\n
+\tline-height: 20px;\n
+\tbackground-image: none;\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+\toutline: 0;\n
+\ttext-align: center;\n
+\tvertical-align: text-bottom;\n
+\t-webkit-appearance: none;\n
+\t-moz-appearance: none;\n
+\tappearance: none;\n
+\t-webkit-box-sizing: content-box;\n
+\t-moz-box-sizing: content-box;\n
+\t-ms-box-sizing: content-box;\n
+\tbox-sizing: content-box;\n
+}\n
+.ui-slider-input::-webkit-outer-spin-button,\n
+.ui-slider-input::-webkit-inner-spin-button {\n
+\t-webkit-appearance: none;\n
+\tmargin: 0;\n
+}\n
+.ui-slider-track {\n
+\tposition: relative;\n
+\toverflow: visible;\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+\theight: 15px;\n
+\tmargin: 0 15px 0 68px;\n
+\ttop: 6px;\n
+}\n
+.ui-slider-track.ui-mini {\n
+\theight: 12px;\n
+\ttop: 8px;\n
+}\n
+.ui-slider-track .ui-slider-bg {\n
+\theight: 100%;\n
+}\n
+/* High level of specificity to override button margins in grids */\n
+.ui-slider-track .ui-btn.ui-slider-handle {\n
+\tposition: absolute;\n
+\tz-index: 1;\n
+\ttop: 50%;\n
+\twidth: 28px;\n
+\theight: 28px;\n
+\tmargin: -15px 0 0 -15px;\n
+\toutline: 0;\n
+\tpadding: 0;\n
+}\n
+.ui-slider-track.ui-mini .ui-slider-handle {\n
+\theight: 14px;\n
+\twidth: 14px;\n
+\tmargin: -8px 0 0 -8px;\n
+}\n
+select.ui-slider-switch {\n
+\tposition: absolute !important;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+div.ui-slider-switch {\n
+\tdisplay: inline-block;\n
+\theight: 32px;\n
+\twidth: 5.8em;\n
+\ttop: 0;\n
+}\n
+/* reset the clearfix */\n
+div.ui-slider-switch:before,\n
+div.ui-slider-switch:after {\n
+\tdisplay: none;\n
+\tclear: none;\n
+}\n
+div.ui-slider-switch.ui-mini {\n
+\theight: 29px;\n
+\ttop: 0;\n
+}\n
+.ui-slider-inneroffset {\n
+\tmargin: 0 16px;\n
+\tposition: relative;\n
+\tz-index: 1;\n
+}\n
+.ui-slider-switch.ui-mini .ui-slider-inneroffset {\n
+\tmargin: 0 15px 0 14px;\n
+}\n
+.ui-slider-switch .ui-btn.ui-slider-handle {\n
+\tmargin: 1px 0 0 -15px;\n
+}\n
+.ui-slider-switch.ui-mini .ui-slider-handle {\n
+\twidth: 25px;\n
+\theight: 25px;\n
+\tmargin: 1px 0 0 -13px;\n
+\tpadding: 0;\n
+}\n
+.ui-slider-handle-snapping {\n
+\t-webkit-transition: left 70ms linear;\n
+\t-moz-transition: left 70ms linear;\n
+}\n
+.ui-slider-switch .ui-slider-label {\n
+\tposition: absolute;\n
+\ttext-align: center;\n
+\twidth: 100%;\n
+\toverflow: hidden;\n
+\tfont-size: 16px;\n
+\ttop: 0;\n
+\tline-height: 2;\n
+\tmin-height: 100%;\n
+\twhite-space: nowrap;\n
+\tcursor: pointer;\n
+}\n
+.ui-slider-switch.ui-mini .ui-slider-label {\n
+\tfont-size: 14px;\n
+}\n
+.ui-slider-switch .ui-slider-label-a {\n
+\tz-index: 1;\n
+\tleft: 0;\n
+\ttext-indent: -1.5em;\n
+}\n
+.ui-slider-switch .ui-slider-label-b {\n
+\tz-index: 0;\n
+\tright: 0;\n
+\ttext-indent: 1.5em;\n
+}\n
+/* The corner radii for ui-slider-switch/track can be specified in theme CSS. The bg and handle inherits. */\n
+.ui-slider-track .ui-slider-bg,\n
+.ui-slider-switch .ui-slider-label,\n
+.ui-slider-switch .ui-slider-inneroffset,\n
+.ui-slider-handle {\n
+\t-webkit-border-radius: inherit;\n
+\tborder-radius: inherit;\n
+}\n
+.ui-field-contain div.ui-slider-switch {\n
+\tmargin: 0;\n
+}\n
+@media (min-width: 28em) {\n
+\t.ui-field-contain div.ui-slider-switch,\n
+\t.ui-field-contain.ui-hide-label div.ui-slider-switch {\n
+\t\tdisplay: inline-block;\n
+\t\twidth: 5.8em;\n
+\t}\n
+}\t\n
+/* slider tooltip\n
+-----------------------------------------------------------------------------------------------------------*/\n
+.ui-slider-popup {\n
+\twidth: 64px;\n
+\theight: 64px;\n
+\tfont-size: 36px;\n
+\tpadding-top: 14px;\n
+\topacity: 0.8;\n
+}\n
+.ui-slider-popup {\n
+\tposition: absolute !important;\n
+\ttext-align: center;\n
+\tz-index: 100;\n
+}\n
+.ui-slider-track .ui-btn.ui-slider-handle {\n
+\tfont-size: .9em;\n
+\tline-height: 30px;\n
+}\n
+.ui-rangeslider {\n
+\tmargin: .5em 0;\n
+}\n
+.ui-rangeslider:before,\n
+.ui-rangeslider:after {\n
+\tcontent: "";\n
+\tdisplay: table;\n
+}\n
+.ui-rangeslider:after {\n
+\tclear: both;\n
+}\n
+.ui-rangeslider .ui-slider-input.ui-rangeslider-last {\n
+\tfloat: right;\n
+}\n
+.ui-rangeslider .ui-rangeslider-sliders {\n
+\tposition: relative;\n
+\toverflow: visible;\n
+\theight: 30px;\n
+\tmargin: 0 68px;\n
+}\n
+.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track {\n
+\tposition: absolute;\n
+\ttop: 6px;\n
+\tright: 0;\n
+\tleft: 0;\n
+\tmargin: 0;\n
+}\n
+.ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track {\n
+\ttop: 8px;\n
+}\n
+.ui-rangeslider .ui-slider-track:first-child .ui-slider-bg {\n
+\tdisplay: none;\n
+}\n
+.ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n
+\tbackground-color: transparent;\n
+\tbackground: none;\n
+\tborder-width: 0;\n
+\theight: 0;\n
+}\n
+/* this makes ie6 and ie7 set height to 0 to fix z-index problem */\n
+html >/**/body .ui-rangeslider .ui-rangeslider-sliders .ui-slider-track:first-child {\n
+\theight: 15px;\n
+\tborder-width: 1px;\n
+}\n
+html >/**/body .ui-rangeslider.ui-mini .ui-rangeslider-sliders .ui-slider-track:first-child {\n
+\theight: 12px;\n
+}\n
+/* Hide the second label (the first is moved outside the div) */\n
+div.ui-rangeslider label {\n
+\tposition: absolute !important;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+}\n
+.ui-field-contain .ui-rangeslider input.ui-slider-input,\n
+.ui-field-contain .ui-rangeslider.ui-mini input.ui-slider-input,\n
+.ui-field-contain .ui-rangeslider .ui-rangeslider-sliders,\n
+.ui-field-contain .ui-rangeslider.ui-mini .ui-rangeslider-sliders {\n
+\tmargin-top: 0;\n
+\tmargin-bottom: 0;\n
+}\n
+.ui-input-text,\n
+.ui-input-search {\n
+\tmargin: .5em 0;\n
+\tbackground-image: none;\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+}\n
+.ui-input-text input,\n
+.ui-input-search input,\n
+textarea.ui-input-text {\n
+\tpadding: .4em;\n
+\tline-height: 1.4em;\n
+\tdisplay: block;\n
+\twidth: 100%;\n
+\t-webkit-box-sizing: border-box;\n
+\t-moz-box-sizing: border-box;\n
+\t-ms-box-sizing: border-box;\n
+\tbox-sizing: border-box;\n
+\toutline: 0;\n
+}\n
+.ui-input-text input,\n
+.ui-input-search input {\n
+\tmargin: 0;\n
+\tmin-height: 2.2em;\n
+\ttext-align: left; /* Opera aligns type="date" right by default */\n
+\tborder: 0;\n
+\tbackground: transparent none;\n
+\t-webkit-appearance: none;\n
+\t-webkit-border-radius: inherit;\n
+\tborder-radius: inherit;\n
+}\n
+textarea.ui-input-text {\n
+\toverflow: auto;\n
+\tresize: vertical;\n
+}\n
+.ui-mini .ui-input-text input,\n
+.ui-mini .ui-input-search input,\n
+.ui-input-text.ui-mini input,\n
+.ui-input-search.ui-mini input,\n
+.ui-mini textarea.ui-input-text,\n
+textarea.ui-mini {\n
+\tfont-size: 14px;\n
+}\n
+/* Same margin for mini textareas as other mini sized widgets (12.5/14 * 0.5em) */\n
+.ui-mini textarea.ui-input-text,\n
+textarea.ui-mini {\n
+\tmargin: .446em 0;\n
+}\n
+.ui-input-has-clear,\n
+.ui-input-search {\n
+\tposition: relative;\n
+}\n
+/* Padding on the div instead of input because of browser spinners etc. */\n
+.ui-input-has-clear {\n
+\tpadding-right: 2.25em;\n
+}\n
+.ui-input-has-clear input {\n
+\tpadding-right: 0;\n
+\t/* Autofill on Chrome has bg color so we unset corners right as well. */\n
+\t-webkit-border-top-right-radius: 0;\n
+\tborder-top-right-radius: 0;\n
+\t-webkit-border-bottom-right-radius: 0;\n
+\tborder-bottom-right-radius: 0;\n
+}\n
+/* Search icon */\n
+.ui-input-search input {\n
+\tpadding-left: 1.75em;\n
+}\n
+.ui-input-search:after {\n
+\tposition: absolute;\n
+\tleft: .3125em;\n
+\ttop: 50%;\n
+\tmargin-top: -7px;\n
+\tcontent: "";\n
+\tbackground-position: center center;\n
+\tbackground-repeat: no-repeat;\n
+\twidth: 14px;\n
+\theight: 14px;\n
+\tfilter: Alpha(Opacity=50);\n
+\topacity: .5;\n
+}\n
+.ui-input-search.ui-input-has-clear .ui-btn.ui-input-clear,\n
+.ui-input-text.ui-input-has-clear .ui-btn.ui-input-clear {\n
+\tposition: absolute;\n
+\tright: 0;\n
+\ttop: 50%;\n
+\tmargin: -14px .3125em 0;\n
+\tborder: 0;\n
+\tbackground-color: transparent;\n
+}\n
+.ui-input-search .ui-input-clear-hidden,\n
+.ui-input-text .ui-input-clear-hidden {\n
+\tdisplay: none;\n
+}\n
+/* Resolves issue #5166: Added to support issue introduced in Firefox 15. We can likely remove this in the future. */\n
+.ui-input-text input::-moz-placeholder,\n
+.ui-input-search input::-moz-placeholder,\n
+textarea.ui-input-text::-moz-placeholder {\n
+\tcolor: #aaa;\n
+}\n
+/* Same for IE10 */\n
+.ui-input-text input:-ms-input-placeholder,\n
+.ui-input-search input:-ms-input-placeholder,\n
+textarea.ui-input-text:-ms-input-placeholder {\n
+\tcolor: #aaa;\n
+}\n
+/* Resolves issue #5131: Width of textinput depends on its type,\n
+for Android 4.1 */\n
+.ui-input-text input[type=number]::-webkit-outer-spin-button {\n
+\tmargin: 0;\n
+}\n
+/* Resolves issue #5756: Textinput in IE10 has a default clear button */\n
+.ui-input-text input::-ms-clear,\n
+.ui-input-search input::-ms-clear {\n
+\tdisplay: none;\n
+}\n
+.ui-input-text input:focus,\n
+.ui-input-search input:focus {\n
+\t-webkit-box-shadow: none;\n
+\t-moz-box-shadow: none;\n
+\tbox-shadow: none;\n
+}\n
+.ui-flipswitch {\n
+\tdisplay: inline-block;\n
+\tvertical-align: middle;\n
+\twidth: 5.875em; /* Override this and padding-left in next rule if you use labels other than "on/off" and need more space */\n
+\theight: 1.875em;\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+\tmargin: .5em 0;\n
+\toverflow: hidden;\n
+\t-webkit-transition-property: padding, width, background-color, color, border-color;\n
+\t-moz-transition-property: padding, width, background-color, color, border-color;\n
+\t-o-transition-property: padding, width, background-color, color, border-color;\n
+\ttransition-property: padding, width, background-color, color, border-color;\n
+\t-webkit-transition-duration: 100ms;\n
+\t-moz-transition-duration: 100ms;\n
+\t-o-transition-duration: 100ms;\n
+\ttransition-duration: 100ms;\n
+\t-webkit-touch-callout: none;\n
+\t-webkit-user-select: none;\n
+\t-moz-user-select: none;\n
+\t-ms-user-select: none;\n
+\tuser-select: none;\n
+\tcursor: pointer;\n
+}\n
+.ui-flipswitch.ui-flipswitch-active {\n
+\tpadding-left: 4em;  /* Override this and width in previous rule if you use labels other than "on/off" and need more space */\n
+\twidth: 1.875em;\n
+}\n
+.ui-flipswitch-input {\n
+\tposition: absolute;\n
+\theight: 1px;\n
+\twidth: 1px;\n
+\tmargin: -1px;\n
+\toverflow: hidden;\n
+\tclip: rect(1px,1px,1px,1px);\n
+\tborder: 0;\n
+\toutline: 0;\n
+\tfilter: Alpha(Opacity=0);\n
+\topacity: 0;\n
+}\n
+.ui-flipswitch .ui-btn.ui-flipswitch-on,\n
+.ui-flipswitch .ui-flipswitch-off {\n
+\tfloat: left;\n
+\theight: 1.75em;\n
+\tmargin: .0625em;\n
+\tline-height: 1.65em;\n
+}\n
+.ui-flipswitch .ui-btn.ui-flipswitch-on {\n
+\twidth: 1.75em;\n
+\tpadding: 0;\n
+\ttext-indent: -2.6em; /* Override this to center text if you use a label other than "on" */\n
+\ttext-align: left;\n
+\tborder-width: 1px;\n
+\tborder-style: solid;\n
+\t-webkit-box-sizing: border-box;\n
+\t-moz-box-sizing: border-box;\n
+\t-ms-box-sizing: border-box;\n
+\tbox-sizing: border-box;\n
+\tborder-radius: inherit;\n
+\toverflow: visible;\n
+\tcolor: inherit;\n
+\ttext-shadow: inherit;\n
+}\n
+.ui-flipswitch .ui-flipswitch-off {\n
+\tpadding: 1px;\n
+\ttext-indent: 1em; /* Override this to center text if you use a label other than "off" */\n
+}\n
+@media (min-width: 28em) {\n
+\t.ui-field-contain > label + .ui-flipswitch {\n
+\t\tdisplay: inline-block;\n
+\t\twidth: 5.875em; /* If you override the width for .ui-flipswitch you should repeat the same value here */\n
+\t\t-webkit-box-sizing: content-box;\n
+\t\t-moz-box-sizing: content-box;\n
+\t\t-ms-box-sizing: content-box;\n
+\t\tbox-sizing: content-box;\n
+\t}\n
+\t.ui-field-contain .ui-flipswitch.ui-flipswitch-active {\n
+\t\twidth: 1.875em;\n
+\t}\n
+}\t\n
+.ui-table {\n
+\tborder: 0;\n
+\tborder-collapse: collapse;\n
+\tpadding: 0;\n
+\twidth: 100%;\n
+}\n
+.ui-table th,\n
+.ui-table td {\n
+\tline-height: 1.5em;\n
+\ttext-align: left;\n
+\tpadding: .4em .5em;\n
+\tvertical-align:top;\n
+}\n
+.ui-table th .ui-btn,\n
+.ui-table td .ui-btn {\n
+\tline-height: normal;\n
+}\n
+.ui-table th {\n
+\tfont-weight: bold;\n
+}\n
+.ui-table caption {\n
+\ttext-align: left;\n
+\tmargin-bottom: 1.4em;\n
+\topacity: .5;\n
+}\n
+/* Add strokes between each row */\n
+.table-stroke thead th {\n
+\tborder-bottom: 1px solid #d6d6d6; /* non-RGBA fallback */\n
+\tborder-bottom: 1px solid rgba(0, 0, 0, .1);\n
+}\n
+.table-stroke tbody th,\n
+.table-stroke tbody td {\n
+\tborder-bottom: 1px solid #e6e6e6; /* non-RGBA fallback  */\n
+\tborder-bottom: 1px solid rgba(0, 0, 0, .05);\n
+}\n
+/* Add alternating row stripes */\n
+.table-stripe tbody tr:nth-child(odd) td,\n
+.table-stripe tbody tr:nth-child(odd) th {\n
+  background-color: #eeeeee; /* non-RGBA fallback  */\n
+  background-color: rgba(0,0,0,0.04);\n
+}\n
+/* Add stroke to the header and last item */\n
+.table-stripe thead th,\n
+.table-stripe tbody tr:last-child {\n
+  border-bottom: 1px solid #d6d6d6; /* non-RGBA fallback  */\n
+  border-bottom: 1px solid rgba(0, 0, 0, .1);\n
+}\n
+/*\n
+ Styles for the table columntoggle mode\n
+*/\n
+.ui-table-columntoggle-btn {\n
+\tfloat: right;\n
+\tmargin-bottom: .8em;\n
+}\n
+/* Remove top/bottom margins around the fieldcontain on check list */\n
+.ui-table-columntoggle-popup fieldset {\n
+\tmargin:0;\n
+}\n
+/* Hide all prioritized columns by default */\n
+@media only all {\n
+\tth.ui-table-priority-6,\n
+\ttd.ui-table-priority-6,\n
+\tth.ui-table-priority-5,\n
+\ttd.ui-table-priority-5,\n
+\tth.ui-table-priority-4,\n
+\ttd.ui-table-priority-4,\n
+\tth.ui-table-priority-3,\n
+\ttd.ui-table-priority-3,\n
+\tth.ui-table-priority-2,\n
+\ttd.ui-table-priority-2,\n
+\tth.ui-table-priority-1,\n
+\ttd.ui-table-priority-1 {\n
+\t\tdisplay: none;\n
+\t}\n
+}\n
+/* Preset breakpoints if ".ui-responsive" class added to table */\n
+/* Show priority 1 at 320px (20em x 16px) */\n
+@media screen and (min-width: 20em) {\n
+\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-1,\n
+\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-1 {\n
+\t\tdisplay: table-cell;\n
+\t}\n
+}\n
+/* Show priority 2 at 480px (30em x 16px) */\n
+@media screen and (min-width: 30em) {\n
+\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-2,\n
+\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-2 {\n
+\t\tdisplay: table-cell;\n
+\t}\n
+}\n
+/* Show priority 3 at 640px (40em x 16px) */\n
+@media screen and (min-width: 40em) {\n
+\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-3,\n
+\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-3 {\n
+\t\tdisplay: table-cell;\n
+\t}\n
+}\n
+/* Show priority 4 at 800px (50em x 16px) */\n
+@media screen and (min-width: 50em) {\n
+\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-4,\n
+\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-4 {\n
+\t\tdisplay: table-cell;\n
+\t}\n
+}\n
+/* Show priority 5 at 960px (60em x 16px) */\n
+@media screen and (min-width: 60em) {\n
+\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-5,\n
+\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-5 {\n
+\t\tdisplay: table-cell;\n
+\t}\n
+}\n
+/* Show priority 6 at 1,120px (70em x 16px) */\n
+@media screen and (min-width: 70em) {\n
+\t.ui-table-columntoggle.ui-responsive th.ui-table-priority-6,\n
+\t.ui-table-columntoggle.ui-responsive td.ui-table-priority-6 {\n
+\t\tdisplay: table-cell;\n
+\t}\n
+}\n
+/* Unchecked manually: Always hide */\n
+.ui-table-columntoggle th.ui-table-cell-hidden,\n
+.ui-table-columntoggle td.ui-table-cell-hidden,\n
+.ui-table-columntoggle.ui-responsive th.ui-table-cell-hidden,\n
+.ui-table-columntoggle.ui-responsive td.ui-table-cell-hidden {\n
+\tdisplay: none;\n
+}\n
+/* Checked manually: Always show */\n
+.ui-table-columntoggle th.ui-table-cell-visible,\n
+.ui-table-columntoggle td.ui-table-cell-visible,\n
+.ui-table-columntoggle.ui-responsive th.ui-table-cell-visible,\n
+.ui-table-columntoggle.ui-responsive td.ui-table-cell-visible {\n
+\tdisplay: table-cell;\n
+}\n
+/*\n
+ Styles for the table columntoggle mode\n
+*/\n
+.ui-table-reflow td .ui-table-cell-label,\n
+.ui-table-reflow th .ui-table-cell-label { \n
+\tdisplay: none;\n
+}\n
+/* Mobile first styles: Begin with the stacked presentation at narrow widths */ \n
+@media only all {\n
+\t/* Hide the table headers */ \n
+\t.ui-table-reflow thead td, \n
+\t.ui-table-reflow thead th {\n
+\t\tdisplay: none;\n
+\t}\n
+\t/* Show the table cells as a block level element */ \n
+\t.ui-table-reflow td,\n
+\t.ui-table-reflow th { \n
+\t\ttext-align: left;\n
+\t\tdisplay: block;\n
+\t}\n
+\t/* Add a fair amount of top margin to visually separate each row when stacked */  \n
+\t.ui-table-reflow tbody th {\n
+\t\tmargin-top: 3em;\n
+\t}\n
+\t/* Make the label elements a percentage width */ \n
+\t.ui-table-reflow td .ui-table-cell-label,\n
+\t.ui-table-reflow th .ui-table-cell-label { \n
+\t\tpadding: .4em; \n
+\t\tmin-width: 30%; \n
+\t\tdisplay: inline-block;\n
+\t\tmargin: -.4em 1em -.4em -.4em;\n
+\t}\n
+\t/* For grouped headers, have a different style to visually separate the levels by classing the first label in each col group */ \n
+\t.ui-table-reflow th .ui-table-cell-label-top,\n
+\t.ui-table-reflow td .ui-table-cell-label-top {\n
+\t\tdisplay: block;\n
+\t\tpadding: .4em 0;\n
+\t\tmargin: .4em 0;\n
+\t\ttext-transform: uppercase;\n
+\t\tfont-size: .9em;\n
+\t\tfont-weight: normal;\n
+\t}\n
+}\n
+/* Breakpoint to show as a standard table at 560px (35em x 16px) or wider */ \n
+@media ( min-width: 35em ) {\n
+\t/* Fixes table rendering when switching between breakpoints in Safari <= 5. See https://github.com/jquery/jquery-mobile/issues/5380 */\n
+\t.ui-table-reflow.ui-responsive {\n
+\t\tdisplay: table-row-group;\n
+\t}\n
+\t/* Show the table header rows */ \n
+\t.ui-table-reflow.ui-responsive td,\n
+\t.ui-table-reflow.ui-responsive th,\n
+\t.ui-table-reflow.ui-responsive tbody th,\n
+\t.ui-table-reflow.ui-responsive tbody td,\n
+\t.ui-table-reflow.ui-responsive thead td,\n
+\t.ui-table-reflow.ui-responsive thead th {\n
+\t\tdisplay: table-cell;\n
+\t\tmargin: 0;\n
+\t}\n
+\t/* Hide the labels in each cell */ \n
+\t.ui-table-reflow.ui-responsive td .ui-table-cell-label,\n
+\t.ui-table-reflow.ui-responsive th .ui-table-cell-label { \n
+\t\tdisplay: none;\n
+\t}\n
+}\n
+/* Hack to make IE9 and WP7.5 treat cells like block level elements, scoped to ui-responsive class */ \n
+/* Applied in a max-width media query up to the table layout breakpoint so we don\'t need to negate this*/ \n
+@media ( max-width: 35em ) {\n
+\t.ui-table-reflow.ui-responsive td,\n
+\t.ui-table-reflow.ui-responsive th {\n
+\t\twidth: 100%;\n
+\t\t-webkit-box-sizing: border-box;\n
+\t\t-moz-box-sizing: border-box;\n
+\t\tbox-sizing: border-box;\n
+\t\tfloat: left;\n
+\t\tclear: left;\n
+\t}\n
+}\n
+/* panel */\n
+.ui-panel {\n
+\twidth: 17em;\n
+\tmin-height: 100%;\n
+\tmax-height: none;\n
+\tborder-width: 0;\n
+\tposition: absolute;\n
+\ttop: 0;\n
+\tdisplay: block;\n
+}\n
+.ui-panel-closed {\n
+\twidth: 0;\n
+\tmax-height: 100%;\n
+\toverflow: hidden;\n
+\tvisibility: hidden;\n
+}\n
+.ui-panel-fixed {\n
+\tposition: fixed;\n
+\tbottom: -1px; /* fixes gap on Chrome for Android */\n
+\tpadding-bottom: 1px;\n
+}\n
+.ui-panel-display-reveal {\n
+\tz-index: 1;\n
+}\n
+.ui-panel-display-push {\n
+\tz-index: 999;\n
+}\n
+.ui-panel-display-overlay {\n
+\tz-index: 1001; /* fixed toolbars have z-index 1000 */\n
+}\n
+.ui-panel-inner {\n
+\tpadding: 1em;\n
+}\n
+/* container */\n
+.ui-panel-page-container {\n
+\toverflow-x: visible;\n
+}\n
+/* page */\n
+.ui-panel-page-container-themed .ui-page-active {\n
+\tbackground: none;\n
+}\n
+/* wrapper */\n
+.ui-panel-wrapper {\n
+\tposition: relative;\n
+\tmin-height: inherit;\n
+\tborder: 0;\n
+\toverflow-x: hidden;\n
+\tz-index: 999;\n
+}\n
+/* fixed toolbars */\n
+.ui-panel-fixed-toolbar {\n
+\toverflow-x: hidden;\n
+}\n
+/* dismiss */\n
+.ui-panel-dismiss {\n
+\tposition: absolute;\n
+\ttop: 0;\n
+\tleft: 0;\n
+\theight: 100%;\n
+\twidth: 100%;\n
+\tz-index: 1002;\n
+\tdisplay: none;\n
+}\n
+.ui-panel-dismiss-open {\n
+\tdisplay: block;\n
+}\n
+/* animate class is added to panel, wrapper and fixed toolbars */\n
+.ui-panel-animate {\n
+\t-webkit-transition: -webkit-transform 300ms ease;\n
+\t-moz-transition: -moz-transform 300ms ease;\n
+\ttransition: transform 300ms ease;\n
+}\n
+/* hardware acceleration for smoother transitions on WebKit browsers */\n
+.ui-panel-animate.ui-panel-page-container,\n
+.ui-panel-animate.ui-panel:not(.ui-panel-display-reveal) {\n
+\t-webkit-backface-visibility: hidden;\n
+\t-webkit-transform: translate3d(0,0,0);\n
+}\n
+/* positioning: panel */\n
+/* panel left  */\n
+.ui-panel-position-left {\n
+\tleft: -17em;\n
+}\n
+/* animated: panel left (for overlay and push) */\n
+.ui-panel-animate.ui-panel-position-left.ui-panel-display-overlay,\n
+.ui-panel-animate.ui-panel-position-left.ui-panel-display-push {\n
+\tleft: 0;\n
+\t-webkit-transform: translate3d(-17em,0,0);\n
+\t-moz-transform: translate3d(-17em,0,0);\n
+\ttransform: translate3d(-17em,0,0);\n
+}\n
+/* panel left open */\n
+.ui-panel-position-left.ui-panel-display-reveal, /* negate "panel left" for reveal */\n
+.ui-panel-open.ui-panel-position-left {\n
+\tleft: 0;\n
+}\n
+/* animated: panel left open (for overlay and push) */\n
+.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-overlay,\n
+.ui-panel-animate.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n
+\t-webkit-transform: translate3d(0,0,0);\n
+\ttransform: translate3d(0,0,0);\n
+\t-moz-transform: none;\n
+}\n
+/* panel right */\n
+.ui-panel-position-right {\n
+\tright: -17em;\n
+}\n
+/* animated: panel right (for overlay and push) */\n
+.ui-panel-animate.ui-panel-position-right.ui-panel-display-overlay,\n
+.ui-panel-animate.ui-panel-position-right.ui-panel-display-push {\n
+\tright: 0;\n
+\t-webkit-transform: translate3d(17em,0,0);\n
+\t-moz-transform: translate3d(17em,0,0);\n
+\ttransform: translate3d(17em,0,0);\n
+}\n
+/* panel right open */\n
+.ui-panel-position-right.ui-panel-display-reveal,  /* negate "panel right" for reveal */\n
+.ui-panel-position-right.ui-panel-open {\n
+\tright: 0;\n
+}\n
+/* animated: panel right open (for overlay and push) */\n
+.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-overlay,\n
+.ui-panel-animate.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n
+\t-webkit-transform: translate3d(0,0,0);\n
+\ttransform: translate3d(0,0,0);\n
+\t-moz-transform: none;\n
+}\n
+/* positioning: pages, fixed toolbars and dismiss */\n
+/* panel left open */\n
+.ui-panel-page-content-position-left,\n
+.ui-panel-dismiss-open.ui-panel-dismiss-position-left {\n
+\tleft: 17em;\n
+\tright: -17em;\n
+}\n
+/* animated: panel left open (for reveal and push) */\n
+.ui-panel-animate.ui-panel-page-content-position-left.ui-panel-page-content-display-reveal,\n
+.ui-panel-animate.ui-panel-page-content-position-left.ui-panel-page-content-display-push {\n
+\tleft: 0;\n
+\tright: 0;\n
+\t-webkit-transform: translate3d(17em,0,0);\n
+\t-moz-transform: translate3d(17em,0,0);\n
+\ttransform: translate3d(17em,0,0);\n
+}\n
+/* panel right open */\n
+.ui-panel-page-content-position-right,\n
+.ui-panel-dismiss-open.ui-panel-dismiss-position-right {\n
+\tleft: -17em;\n
+\tright: 17em;\n
+}\n
+/* animated: panel right open (for reveal and push) */\n
+.ui-panel-animate.ui-panel-page-content-position-right.ui-panel-page-content-display-reveal, \n
+.ui-panel-animate.ui-panel-page-content-position-right.ui-panel-page-content-display-push {\n
+\tleft: 0;\n
+\tright: 0;\n
+\t-webkit-transform: translate3d(-17em,0,0);\n
+\t-moz-transform: translate3d(-17em,0,0);\n
+\ttransform: translate3d(-17em,0,0);\n
+}\n
+/* negate "panel left/right open" for overlay */\n
+.ui-panel-page-content-display-overlay {\n
+\tleft: 0;\n
+}\n
+/* shadows and borders */\n
+.ui-panel-display-reveal {\n
+\t-webkit-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n
+\t-moz-box-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n
+\tbox-shadow: inset -5px 0 5px rgba(0,0,0,.15);\n
+}\n
+.ui-panel-position-right.ui-panel-display-reveal {\n
+\t-webkit-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n
+\t-moz-box-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n
+\tbox-shadow: inset 5px 0 5px rgba(0,0,0,.15);\n
+}\n
+.ui-panel-display-overlay {\n
+\t-webkit-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n
+\t-moz-box-shadow: 5px 0 5px rgba(0,0,0,.15);\n
+\tbox-shadow: 5px 0 5px rgba(0,0,0,.15);\n
+}\n
+.ui-panel-position-right.ui-panel-display-overlay {\n
+\t-webkit-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n
+\t-moz-box-shadow: -5px 0 5px rgba(0,0,0,.15);\n
+\tbox-shadow: -5px 0 5px rgba(0,0,0,.15);\n
+}\n
+.ui-panel-open.ui-panel-position-left.ui-panel-display-push {\n
+\tborder-right-width: 1px;\n
+\tmargin-right: -1px;\n
+}\n
+.ui-panel-page-content-position-left.ui-panel-page-content-display-push {\n
+\tmargin-left: 1px;\n
+\twidth: auto;\n
+}\n
+.ui-panel-open.ui-panel-position-right.ui-panel-display-push {\n
+\tborder-left-width: 1px;\n
+\tmargin-left: -1px;\n
+}\n
+.ui-panel-page-content-position-right.ui-panel-page-content-display-push {\n
+\tmargin-right: 1px;\n
+\twidth: auto;\n
+}\n
+/* wrap on wide viewports once open */\n
+@media (min-width:55em) {\n
+\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-left.ui-panel-page-content-display-push,\n
+\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-left.ui-panel-page-content-display-reveal {\n
+\t\tmargin-right: 17em;\n
+\t}\n
+\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-right.ui-panel-page-content-display-push,\n
+\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-position-right.ui-panel-page-content-display-reveal {\n
+\t\tmargin-left: 17em;\n
+\t}\n
+\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-display-push,\n
+\t.ui-responsive-panel .ui-panel-page-content-open.ui-panel-page-content-display-reveal {\n
+\t\twidth: auto;\t\n
+\t}\n
+\t.ui-responsive-panel .ui-panel-dismiss-display-push,\n
+\t.ui-responsive-panel.ui-page-active ~ .ui-panel-dismiss-display-push {\n
+\t\tdisplay: none;\n
+\t}\n
+}\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquerymobile.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquerymobile.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bf07c29a7bbccc0c12561135614128b234a6b855
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/jquerymobile.js.xml
@@ -0,0 +1,14269 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681770.3</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>jquerymobile.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>427307</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*!\n
+* jQuery Mobile 1.4.0-alpha.2\n
+* Git HEAD hash: 1e27844a1c0b9103a0948480637e6a67f5212dfd <> Date: Thu Aug 15 2013 13:53:49 UTC\n
+* http://jquerymobile.com\n
+*\n
+* Copyright 2010, 2013 jQuery Foundation, Inc. and other contributors\n
+* Released under the MIT license.\n
+* http://jquery.org/license\n
+*\n
+*/\n
+\n
+\n
+(function ( root, doc, factory ) {\n
+\tif ( typeof define === "function" && define.amd ) {\n
+\t\t// AMD. Register as an anonymous module.\n
+\t\tdefine( [ "jquery" ], function ( $ ) {\n
+\t\t\tfactory( $, root, doc );\n
+\t\t\treturn $.mobile;\n
+\t\t});\n
+\t} else {\n
+\t\t// Browser globals\n
+\t\tfactory( root.jQuery, root, doc );\n
+\t}\n
+}( this, document, function ( jQuery, window, document, undefined ) {\n
+(function( $ ) {\n
+\t$.mobile = {};\n
+}( jQuery ));\n
+(function( $, window, undefined ) {\n
+\t$.extend( $.mobile, {\n
+\n
+\t\t// Version of the jQuery Mobile Framework\n
+\t\tversion: "1.4.0-alpha.2",\n
+\n
+\t\t// Deprecated and no longer used in 1.4 remove in 1.5\n
+\t\t// Define the url parameter used for referencing widget-generated sub-pages.\n
+\t\t// Translates to example.html&ui-page=subpageIdentifier\n
+\t\t// hash segment before &ui-page= is used to make Ajax request\n
+\t\tsubPageUrlKey: "ui-page",\n
+\n
+\t\thideUrlBar: true,\n
+\n
+\t\t// Keepnative Selector\n
+\t\tkeepNative: ":jqmData(role=\'none\'), :jqmData(role=\'nojs\')",\n
+\n
+\t\t// Deprecated in 1.4 remove in 1.5\n
+\t\t// Class assigned to page currently in view, and during transitions\n
+\t\tactivePageClass: "ui-page-active",\n
+\n
+\t\t// Deprecated in 1.4 remove in 1.5\n
+\t\t// Class used for "active" button state, from CSS framework\n
+\t\tactiveBtnClass: "ui-btn-active",\n
+\n
+\t\t// Deprecated in 1.4 remove in 1.5\n
+\t\t// Class used for "focus" form element state, from CSS framework\n
+\t\tfocusClass: "ui-focus",\n
+\n
+\t\t// Automatically handle clicks and form submissions through Ajax, when same-domain\n
+\t\tajaxEnabled: true,\n
+\n
+\t\t// Automatically load and show pages based on location.hash\n
+\t\thashListeningEnabled: true,\n
+\n
+\t\t// disable to prevent jquery from bothering with links\n
+\t\tlinkBindingEnabled: true,\n
+\n
+\t\t// Set default page transition - \'none\' for no transitions\n
+\t\tdefaultPageTransition: "fade",\n
+\n
+\t\t// Set maximum window width for transitions to apply - \'false\' for no limit\n
+\t\tmaxTransitionWidth: false,\n
+\n
+\t\t// Minimum scroll distance that will be remembered when returning to a page\n
+\t\t// Deprecated remove in 1.5 \n
+\t\tminScrollBack: 0,\n
+\n
+\t\t// DEPRECATED: the following property is no longer in use, but defined until 2.0 to prevent conflicts\n
+\t\ttouchOverflowEnabled: false,\n
+\n
+\t\t// Set default dialog transition - \'none\' for no transitions\n
+\t\tdefaultDialogTransition: "pop",\n
+\n
+\t\t// Error response message - appears when an Ajax page request fails\n
+\t\tpageLoadErrorMessage: "Error Loading Page",\n
+\n
+\t\t// For error messages, which theme does the box uses?\n
+\t\tpageLoadErrorMessageTheme: "a",\n
+\n
+\t\t// replace calls to window.history.back with phonegaps navigation helper\n
+\t\t// where it is provided on the window object\n
+\t\tphonegapNavigationEnabled: false,\n
+\n
+\t\t//automatically initialize the DOM when it\'s ready\n
+\t\tautoInitializePage: true,\n
+\n
+\t\tpushStateEnabled: true,\n
+\n
+\t\t// allows users to opt in to ignoring content by marking a parent element as\n
+\t\t// data-ignored\n
+\t\tignoreContentEnabled: false,\n
+\n
+\t\tbuttonMarkup: {\n
+\t\t\thoverDelay: 200\n
+\t\t},\n
+\n
+\t\t// disable the alteration of the dynamic base tag or links in the case\n
+\t\t// that a dynamic base tag isn\'t supported\n
+\t\tdynamicBaseEnabled: true,\n
+\n
+\t\t// default the property to remove dependency on assignment in init module\n
+\t\tpageContainer: $()\n
+\t});\n
+})( jQuery, this );\n
+\n
+(function( $, window, undefined ) {\n
+\tvar nsNormalizeDict = {},\n
+\t\toldFind = $.find,\n
+\t\trbrace = /(?:\\{[\\s\\S]*\\}|\\[[\\s\\S]*\\])$/,\n
+\t\tjqmDataRE = /:jqmData\\(([^)]*)\\)/g;\n
+\n
+\t$.extend( $.mobile, {\n
+\n
+\t\t// Namespace used framework-wide for data-attrs. Default is no namespace\n
+\n
+\t\tns: "",\n
+\n
+\t\t// Retrieve an attribute from an element and perform some massaging of the value\n
+\n
+\t\tgetAttribute: function( element, key ) {\n
+\t\t\tvar data;\n
+\n
+\t\t\telement = element.jquery ? element[0] : element;\n
+\n
+\t\t\tif( element && element.getAttribute ){\n
+\t\t\t\tdata = element.getAttribute( "data-" + $.mobile.ns + key );\n
+\t\t\t}\n
+\n
+\t\t\t// Copied from core\'s src/data.js:dataAttr()\n
+\t\t\t// Convert from a string to a proper data type\n
+\t\t\ttry {\n
+\t\t\t\tdata = data === "true" ? true :\n
+\t\t\t\t\tdata === "false" ? false :\n
+\t\t\t\t\tdata === "null" ? null :\n
+\t\t\t\t\t// Only convert to a number if it doesn\'t change the string\n
+\t\t\t\t\t+data + "" === data ? +data :\n
+\t\t\t\t\trbrace.test( data ) ? JSON.parse( data ) :\n
+\t\t\t\t\tdata;\n
+\t\t\t} catch( err ) {}\n
+\n
+\t\t\treturn data;\n
+\t\t},\n
+\n
+\t\t// Expose our cache for testing purposes.\n
+\t\tnsNormalizeDict: nsNormalizeDict,\n
+\n
+\t\t// Take a data attribute property, prepend the namespace\n
+\t\t// and then camel case the attribute string. Add the result\n
+\t\t// to our nsNormalizeDict so we don\'t have to do this again.\n
+\t\tnsNormalize: function( prop ) {\n
+\t\t\treturn nsNormalizeDict[ prop ] ||\n
+\t\t\t\t( nsNormalizeDict[ prop ] = $.camelCase( $.mobile.ns + prop ) );\n
+\t\t},\n
+\n
+\t\t// Find the closest javascript page element to gather settings data jsperf test\n
+\t\t// http://jsperf.com/single-complex-selector-vs-many-complex-selectors/edit\n
+\t\t// possibly naive, but it shows that the parsing overhead for *just* the page selector vs\n
+\t\t// the page and dialog selector is negligable. This could probably be speed up by\n
+\t\t// doing a similar parent node traversal to the one found in the inherited theme code above\n
+\t\tclosestPageData: function( $target ) {\n
+\t\t\treturn $target\n
+\t\t\t\t.closest( ":jqmData(role=\'page\'), :jqmData(role=\'dialog\')" )\n
+\t\t\t\t.data( "mobile-page" );\n
+\t\t}\n
+\n
+\t});\n
+\n
+\t// Mobile version of data and removeData and hasData methods\n
+\t// ensures all data is set and retrieved using jQuery Mobile\'s data namespace\n
+\t$.fn.jqmData = function( prop, value ) {\n
+\t\tvar result;\n
+\t\tif ( typeof prop !== "undefined" ) {\n
+\t\t\tif ( prop ) {\n
+\t\t\t\tprop = $.mobile.nsNormalize( prop );\n
+\t\t\t}\n
+\n
+\t\t\t// undefined is permitted as an explicit input for the second param\n
+\t\t\t// in this case it returns the value and does not set it to undefined\n
+\t\t\tif ( arguments.length < 2 || value === undefined ){\n
+\t\t\t\tresult = this.data( prop );\n
+\t\t\t} else {\n
+\t\t\t\tresult = this.data( prop, value );\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn result;\n
+\t};\n
+\n
+\t$.jqmData = function( elem, prop, value ) {\n
+\t\tvar result;\n
+\t\tif ( typeof prop !== "undefined" ) {\n
+\t\t\tresult = $.data( elem, prop ? $.mobile.nsNormalize( prop ) : prop, value );\n
+\t\t}\n
+\t\treturn result;\n
+\t};\n
+\n
+\t$.fn.jqmRemoveData = function( prop ) {\n
+\t\treturn this.removeData( $.mobile.nsNormalize( prop ) );\n
+\t};\n
+\n
+\t$.jqmRemoveData = function( elem, prop ) {\n
+\t\treturn $.removeData( elem, $.mobile.nsNormalize( prop ) );\n
+\t};\n
+\n
+\t$.find = function( selector, context, ret, extra ) {\n
+\t\tif ( selector.indexOf( ":jqmData" ) > -1 ) {\n
+\t\t\tselector = selector.replace( jqmDataRE, "[data-" + ( $.mobile.ns || "" ) + "$1]" );\n
+\t\t}\n
+\n
+\t\treturn oldFind.call( this, selector, context, ret, extra );\n
+\t};\n
+\n
+\t$.extend( $.find, oldFind );\n
+\n
+})( jQuery, this );\n
+\n
+/*!\n
+ * jQuery UI Core @VERSION\n
+ * http://jqueryui.com\n
+ *\n
+ * Copyright 2013 jQuery Foundation and other contributors\n
+ * Released under the MIT license.\n
+ * http://jquery.org/license\n
+ *\n
+ * http://api.jqueryui.com/category/ui-core/\n
+ */\n
+(function( $, undefined ) {\n
+\n
+var uuid = 0,\n
+\truniqueId = /^ui-id-\\d+$/;\n
+\n
+// $.ui might exist from components with no dependencies, e.g., $.ui.position\n
+$.ui = $.ui || {};\n
+\n
+$.extend( $.ui, {\n
+\tversion: "@VERSION",\n
+\n
+\tkeyCode: {\n
+\t\tBACKSPACE: 8,\n
+\t\tCOMMA: 188,\n
+\t\tDELETE: 46,\n
+\t\tDOWN: 40,\n
+\t\tEND: 35,\n
+\t\tENTER: 13,\n
+\t\tESCAPE: 27,\n
+\t\tHOME: 36,\n
+\t\tLEFT: 37,\n
+\t\tPAGE_DOWN: 34,\n
+\t\tPAGE_UP: 33,\n
+\t\tPERIOD: 190,\n
+\t\tRIGHT: 39,\n
+\t\tSPACE: 32,\n
+\t\tTAB: 9,\n
+\t\tUP: 38\n
+\t}\n
+});\n
+\n
+// plugins\n
+$.fn.extend({\n
+\tfocus: (function( orig ) {\n
+\t\treturn function( delay, fn ) {\n
+\t\t\treturn typeof delay === "number" ?\n
+\t\t\t\tthis.each(function() {\n
+\t\t\t\t\tvar elem = this;\n
+\t\t\t\t\tsetTimeout(function() {\n
+\t\t\t\t\t\t$( elem ).focus();\n
+\t\t\t\t\t\tif ( fn ) {\n
+\t\t\t\t\t\t\tfn.call( elem );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}, delay );\n
+\t\t\t\t}) :\n
+\t\t\t\torig.apply( this, arguments );\n
+\t\t};\n
+\t})( $.fn.focus ),\n
+\n
+\tscrollParent: function() {\n
+\t\tvar scrollParent;\n
+\t\tif (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {\n
+\t\t\tscrollParent = this.parents().filter(function() {\n
+\t\t\t\treturn (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));\n
+\t\t\t}).eq(0);\n
+\t\t} else {\n
+\t\t\tscrollParent = this.parents().filter(function() {\n
+\t\t\t\treturn (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));\n
+\t\t\t}).eq(0);\n
+\t\t}\n
+\n
+\t\treturn ( /fixed/ ).test( this.css( "position") ) || !scrollParent.length ? $( this[ 0 ].ownerDocument || document ) : scrollParent;\n
+\t},\n
+\n
+\tuniqueId: function() {\n
+\t\treturn this.each(function() {\n
+\t\t\tif ( !this.id ) {\n
+\t\t\t\tthis.id = "ui-id-" + (++uuid);\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\tremoveUniqueId: function() {\n
+\t\treturn this.each(function() {\n
+\t\t\tif ( runiqueId.test( this.id ) ) {\n
+\t\t\t\t$( this ).removeAttr( "id" );\n
+\t\t\t}\n
+\t\t});\n
+\t}\n
+});\n
+\n
+// selectors\n
+function focusable( element, isTabIndexNotNaN ) {\n
+\tvar map, mapName, img,\n
+\t\tnodeName = element.nodeName.toLowerCase();\n
+\tif ( "area" === nodeName ) {\n
+\t\tmap = element.parentNode;\n
+\t\tmapName = map.name;\n
+\t\tif ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\timg = $( "img[usemap=#" + mapName + "]" )[0];\n
+\t\treturn !!img && visible( img );\n
+\t}\n
+\treturn ( /input|select|textarea|button|object/.test( nodeName ) ?\n
+\t\t!element.disabled :\n
+\t\t"a" === nodeName ?\n
+\t\t\telement.href || isTabIndexNotNaN :\n
+\t\t\tisTabIndexNotNaN) &&\n
+\t\t// the element and all of its ancestors must be visible\n
+\t\tvisible( element );\n
+}\n
+\n
+function visible( element ) {\n
+\treturn $.expr.filters.visible( element ) &&\n
+\t\t!$( element ).parents().addBack().filter(function() {\n
+\t\t\treturn $.css( this, "visibility" ) === "hidden";\n
+\t\t}).length;\n
+}\n
+\n
+$.extend( $.expr[ ":" ], {\n
+\tdata: $.expr.createPseudo ?\n
+\t\t$.expr.createPseudo(function( dataName ) {\n
+\t\t\treturn function( elem ) {\n
+\t\t\t\treturn !!$.data( elem, dataName );\n
+\t\t\t};\n
+\t\t}) :\n
+\t\t// support: jQuery <1.8\n
+\t\tfunction( elem, i, match ) {\n
+\t\t\treturn !!$.data( elem, match[ 3 ] );\n
+\t\t},\n
+\n
+\tfocusable: function( element ) {\n
+\t\treturn focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );\n
+\t},\n
+\n
+\ttabbable: function( element ) {\n
+\t\tvar tabIndex = $.attr( element, "tabindex" ),\n
+\t\t\tisTabIndexNaN = isNaN( tabIndex );\n
+\t\treturn ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );\n
+\t}\n
+});\n
+\n
+// support: jQuery <1.8\n
+if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {\n
+\t$.each( [ "Width", "Height" ], function( i, name ) {\n
+\t\tvar side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],\n
+\t\t\ttype = name.toLowerCase(),\n
+\t\t\torig = {\n
+\t\t\t\tinnerWidth: $.fn.innerWidth,\n
+\t\t\t\tinnerHeight: $.fn.innerHeight,\n
+\t\t\t\touterWidth: $.fn.outerWidth,\n
+\t\t\t\touterHeight: $.fn.outerHeight\n
+\t\t\t};\n
+\n
+\t\tfunction reduce( elem, size, border, margin ) {\n
+\t\t\t$.each( side, function() {\n
+\t\t\t\tsize -= parseFloat( $.css( elem, "padding" + this ) ) || 0;\n
+\t\t\t\tif ( border ) {\n
+\t\t\t\t\tsize -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;\n
+\t\t\t\t}\n
+\t\t\t\tif ( margin ) {\n
+\t\t\t\t\tsize -= parseFloat( $.css( elem, "margin" + this ) ) || 0;\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t\treturn size;\n
+\t\t}\n
+\n
+\t\t$.fn[ "inner" + name ] = function( size ) {\n
+\t\t\tif ( size === undefined ) {\n
+\t\t\t\treturn orig[ "inner" + name ].call( this );\n
+\t\t\t}\n
+\n
+\t\t\treturn this.each(function() {\n
+\t\t\t\t$( this ).css( type, reduce( this, size ) + "px" );\n
+\t\t\t});\n
+\t\t};\n
+\n
+\t\t$.fn[ "outer" + name] = function( size, margin ) {\n
+\t\t\tif ( typeof size !== "number" ) {\n
+\t\t\t\treturn orig[ "outer" + name ].call( this, size );\n
+\t\t\t}\n
+\n
+\t\t\treturn this.each(function() {\n
+\t\t\t\t$( this).css( type, reduce( this, size, true, margin ) + "px" );\n
+\t\t\t});\n
+\t\t};\n
+\t});\n
+}\n
+\n
+// support: jQuery <1.8\n
+if ( !$.fn.addBack ) {\n
+\t$.fn.addBack = function( selector ) {\n
+\t\treturn this.add( selector == null ?\n
+\t\t\tthis.prevObject : this.prevObject.filter( selector )\n
+\t\t);\n
+\t};\n
+}\n
+\n
+// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)\n
+if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {\n
+\t$.fn.removeData = (function( removeData ) {\n
+\t\treturn function( key ) {\n
+\t\t\tif ( arguments.length ) {\n
+\t\t\t\treturn removeData.call( this, $.camelCase( key ) );\n
+\t\t\t} else {\n
+\t\t\t\treturn removeData.call( this );\n
+\t\t\t}\n
+\t\t};\n
+\t})( $.fn.removeData );\n
+}\n
+\n
+\n
+\n
+\n
+\n
+// deprecated\n
+$.ui.ie = !!/msie [\\w.]+/.exec( navigator.userAgent.toLowerCase() );\n
+\n
+$.support.selectstart = "onselectstart" in document.createElement( "div" );\n
+$.fn.extend({\n
+\tdisableSelection: function() {\n
+\t\treturn this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +\n
+\t\t\t".ui-disableSelection", function( event ) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t});\n
+\t},\n
+\n
+\tenableSelection: function() {\n
+\t\treturn this.unbind( ".ui-disableSelection" );\n
+\t},\n
+\n
+\tzIndex: function( zIndex ) {\n
+\t\tif ( zIndex !== undefined ) {\n
+\t\t\treturn this.css( "zIndex", zIndex );\n
+\t\t}\n
+\n
+\t\tif ( this.length ) {\n
+\t\t\tvar elem = $( this[ 0 ] ), position, value;\n
+\t\t\twhile ( elem.length && elem[ 0 ] !== document ) {\n
+\t\t\t\t// Ignore z-index if position is set to a value where z-index is ignored by the browser\n
+\t\t\t\t// This makes behavior of this function consistent across browsers\n
+\t\t\t\t// WebKit always returns auto if the element is positioned\n
+\t\t\t\tposition = elem.css( "position" );\n
+\t\t\t\tif ( position === "absolute" || position === "relative" || position === "fixed" ) {\n
+\t\t\t\t\t// IE returns 0 when zIndex is not specified\n
+\t\t\t\t\t// other browsers return a string\n
+\t\t\t\t\t// we ignore the case of nested elements with an explicit value of 0\n
+\t\t\t\t\t// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>\n
+\t\t\t\t\tvalue = parseInt( elem.css( "zIndex" ), 10 );\n
+\t\t\t\t\tif ( !isNaN( value ) && value !== 0 ) {\n
+\t\t\t\t\t\treturn value;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\telem = elem.parent();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn 0;\n
+\t}\n
+});\n
+\n
+// $.ui.plugin is deprecated. Use $.widget() extensions instead.\n
+$.ui.plugin = {\n
+\tadd: function( module, option, set ) {\n
+\t\tvar i,\n
+\t\t\tproto = $.ui[ module ].prototype;\n
+\t\tfor ( i in set ) {\n
+\t\t\tproto.plugins[ i ] = proto.plugins[ i ] || [];\n
+\t\t\tproto.plugins[ i ].push( [ option, set[ i ] ] );\n
+\t\t}\n
+\t},\n
+\tcall: function( instance, name, args, allowDisconnected ) {\n
+\t\tvar i,\n
+\t\t\tset = instance.plugins[ name ];\n
+\n
+\t\tif ( !set ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( !allowDisconnected && ( !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tfor ( i = 0; i < set.length; i++ ) {\n
+\t\t\tif ( instance.options[ set[ i ][ 0 ] ] ) {\n
+\t\t\t\tset[ i ][ 1 ].apply( instance.element, args );\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+};\n
+\n
+})( jQuery );\n
+(function( $, window, undefined ) {\n
+\n
+\t$.extend( $.mobile, {\n
+\t\t// define the window and the document objects\n
+\t\twindow: $( window ),\n
+\t\tdocument: $( document ),\n
+\n
+\t\t// TODO: Remove and use $.ui.keyCode directly\n
+\t\tkeyCode: $.ui.keyCode,\n
+\n
+\t\t// Place to store various widget extensions\n
+\t\tbehaviors: {},\n
+\n
+\t\t// Scroll page vertically: scroll to 0 to hide iOS address bar, or pass a Y value\n
+\t\tsilentScroll: function( ypos ) {\n
+\t\t\tif ( $.type( ypos ) !== "number" ) {\n
+\t\t\t\typos = $.mobile.defaultHomeScroll;\n
+\t\t\t}\n
+\n
+\t\t\t// prevent scrollstart and scrollstop events\n
+\t\t\t$.event.special.scrollstart.enabled = false;\n
+\n
+\t\t\tsetTimeout(function() {\n
+\t\t\t\twindow.scrollTo( 0, ypos );\n
+\t\t\t\t$.mobile.document.trigger( "silentscroll", { x: 0, y: ypos });\n
+\t\t\t}, 20 );\n
+\n
+\t\t\tsetTimeout(function() {\n
+\t\t\t\t$.event.special.scrollstart.enabled = true;\n
+\t\t\t}, 150 );\n
+\t\t},\n
+\n
+\t\t// DEPRECATED in 1.4\n
+\t\t// Find the closest parent with a theme class on it. Note that\n
+\t\t// we are not using $.fn.closest() on purpose here because this\n
+\t\t// method gets called quite a bit and we need it to be as fast\n
+\t\t// as possible.\n
+\t\tgetInheritedTheme: function( el, defaultTheme ) {\n
+\t\t\tvar e = el[ 0 ],\n
+\t\t\t\tltr = "",\n
+\t\t\t\tre = /ui-(bar|body|overlay)-([a-z])\\b/,\n
+\t\t\t\tc, m;\n
+\t\t\twhile ( e ) {\n
+\t\t\t\tc = e.className || "";\n
+\t\t\t\tif ( c && ( m = re.exec( c ) ) && ( ltr = m[ 2 ] ) ) {\n
+\t\t\t\t\t// We found a parent with a theme class\n
+\t\t\t\t\t// on it so bail from this loop.\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\n
+\t\t\t\te = e.parentNode;\n
+\t\t\t}\n
+\t\t\t// Return the theme letter we found, if none, return the\n
+\t\t\t// specified default.\n
+\t\t\treturn ltr || defaultTheme || "a";\n
+\t\t},\n
+\n
+\t\tenhanceable: function( elements ) {\n
+\t\t\treturn this.haveParents( elements, "enhance" );\n
+\t\t},\n
+\n
+\t\thijackable: function( elements ) {\n
+\t\t\treturn this.haveParents( elements, "ajax" );\n
+\t\t},\n
+\n
+\t\thaveParents: function( elements, attr ) {\n
+\t\t\tif ( !$.mobile.ignoreContentEnabled ) {\n
+\t\t\t\treturn elements;\n
+\t\t\t}\n
+\n
+\t\t\tvar count = elements.length,\n
+\t\t\t\t$newSet = $(),\n
+\t\t\t\te, $element, excluded,\n
+\t\t\t\ti, c;\n
+\n
+\t\t\tfor ( i = 0; i < count; i++ ) {\n
+\t\t\t\t$element = elements.eq( i );\n
+\t\t\t\texcluded = false;\n
+\t\t\t\te = elements[ i ];\n
+\n
+\t\t\t\twhile ( e ) {\n
+\t\t\t\t\tc = e.getAttribute ? e.getAttribute( "data-" + $.mobile.ns + attr ) : "";\n
+\n
+\t\t\t\t\tif ( c === "false" ) {\n
+\t\t\t\t\t\texcluded = true;\n
+\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\te = e.parentNode;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif ( !excluded ) {\n
+\t\t\t\t\t$newSet = $newSet.add( $element );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\treturn $newSet;\n
+\t\t},\n
+\n
+\t\tgetScreenHeight: function() {\n
+\t\t\t// Native innerHeight returns more accurate value for this across platforms,\n
+\t\t\t// jQuery version is here as a normalized fallback for platforms like Symbian\n
+\t\t\treturn window.innerHeight || $.mobile.window.height();\n
+\t\t},\n
+\n
+\t\t//simply set the active page\'s minimum height to screen height, depending on orientation\n
+\t\tresetActivePageHeight: function( height ) {\n
+\t\t\tvar page = $( "." + $.mobile.activePageClass ),\n
+\t\t\t\tpageHeight = page.height(),\n
+\t\t\t\tpageOuterHeight = page.outerHeight( true );\n
+\n
+\t\t\theight = ( typeof height === "number" ) ? height : $.mobile.getScreenHeight();\n
+\n
+\t\t\tpage.css( "min-height", height - ( pageOuterHeight - pageHeight ) );\n
+\t\t}\n
+\t});\n
+\n
+\t$.addDependents = function( elem, newDependents ) {\n
+\t\tvar $elem = $( elem ),\n
+\t\t\tdependents = $elem.jqmData( "dependents" ) || $();\n
+\n
+\t\t$elem.jqmData( "dependents", $( dependents ).add( newDependents ) );\n
+\t};\n
+\n
+\t// plugins\n
+\t$.fn.extend({\n
+\t\tremoveWithDependents: function() {\n
+\t\t\t$.removeWithDependents( this );\n
+\t\t},\n
+\n
+\t\t// Enhance child elements\n
+\t\tenhanceWithin: function() {\n
+\t\t\tvar widgetElements,\n
+\t\t\t\tthat = this;\n
+\n
+\t\t\t// Add no js class to elements\n
+\t\t\tif ( $.mobile.nojs ) {\n
+\t\t\t\t$.mobile.nojs( this );\n
+\t\t\t}\n
+\n
+\t\t\t// Bind links for ajax nav\n
+\t\t\tif ( $.mobile.links ) {\n
+\t\t\t\t$.mobile.links( this );\n
+\t\t\t}\n
+\n
+\t\t\t// Degrade inputs for styleing\n
+\t\t\tif ( $.mobile.degradeInputsWithin ) {\n
+\t\t\t\t$.mobile.degradeInputsWithin( this );\n
+\t\t\t}\n
+\n
+\t\t\t// Run buttonmarkup\n
+\t\t\tif ( $.fn.buttonMarkup ) {\n
+\t\t\t\t$( $.fn.buttonMarkup.initSelector ).buttonMarkup();\n
+\t\t\t}\n
+\n
+\t\t\t// Add classes for fieldContain\n
+\t\t\tif ( $.fn.fieldcontain ) {\n
+\t\t\t\tthis.find( ":jqmData(role=\'fieldcontain\')" ).jqmEnhanceable().fieldcontain();\n
+\t\t\t}\n
+\n
+\t\t\t// Enhance widgets\n
+\t\t\t$.each( $.mobile.widgets, function( name, constructor ) {\n
+\n
+\t\t\t\t// If initSelector not false find elements\n
+\t\t\t\tif ( constructor.initSelector ) {\n
+\n
+\t\t\t\t\t// Filter elements that should not be enhanced based on parents\n
+\t\t\t\t\twidgetElements = $.mobile.enhanceable( that.find( constructor.initSelector ) );\n
+\n
+\t\t\t\t\t// If any matching elements remain filter ones with keepNativeSelector\n
+\t\t\t\t\tif ( widgetElements.length ) {\n
+\n
+\t\t\t\t\t\t// $.mobile.page.prototype.keepNativeSelector is deprecated this is just for backcompt\n
+\t\t\t\t\t\t// Switch to $.mobile.keepNativeSelector in 1.5 which is just a value not a function\n
+\t\t\t\t\t\twidgetElements = widgetElements.not( $.mobile.page.prototype.keepNativeSelector() );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// Enhance whatever is left\n
+\t\t\t\t\twidgetElements[ constructor.prototype.widgetName ]();\n
+\t\t\t\t}\n
+\t\t\t});\n
+\n
+\t\t\treturn this;\n
+\t\t},\n
+\n
+\t\taddDependents: function( newDependents ) {\n
+\t\t\t$.addDependents( this, newDependents );\n
+\t\t},\n
+\n
+\t\t// note that this helper doesn\'t attempt to handle the callback\n
+\t\t// or setting of an html element\'s text, its only purpose is\n
+\t\t// to return the html encoded version of the text in all cases. (thus the name)\n
+\t\tgetEncodedText: function() {\n
+\t\t\treturn $( "<a>" ).text( this.text() ).html();\n
+\t\t},\n
+\n
+\t\t// fluent helper function for the mobile namespaced equivalent\n
+\t\tjqmEnhanceable: function() {\n
+\t\t\treturn $.mobile.enhanceable( this );\n
+\t\t},\n
+\n
+\t\tjqmHijackable: function() {\n
+\t\t\treturn $.mobile.hijackable( this );\n
+\t\t}\n
+\t});\n
+\n
+\t$.removeWithDependents = function( nativeElement ) {\n
+\t\tvar element = $( nativeElement );\n
+\n
+\t\t( element.jqmData( "dependents" ) || $() ).remove();\n
+\t\telement.remove();\n
+\t};\n
+\t$.addDependents = function( nativeElement, newDependents ) {\n
+\t\tvar element = $( nativeElement ),\n
+\t\t\tdependents = element.jqmData( "dependents" ) || $();\n
+\n
+\t\telement.jqmData( "dependents", $( dependents ).add( newDependents ) );\n
+\t};\n
+\n
+\t$.find.matches = function( expr, set ) {\n
+\t\treturn $.find( expr, null, null, set );\n
+\t};\n
+\n
+\t$.find.matchesSelector = function( node, expr ) {\n
+\t\treturn $.find( expr, null, null, [ node ] ).length > 0;\n
+\t};\n
+\n
+})( jQuery, this );\n
+\n
+\n
+/*!\n
+ * jQuery UI Widget @VERSION\n
+ * http://jqueryui.com\n
+ *\n
+ * Copyright 2013 jQuery Foundation and other contributors\n
+ * Released under the MIT license.\n
+ * http://jquery.org/license\n
+ *\n
+ * http://api.jqueryui.com/jQuery.widget/\n
+ */\n
+(function( $, undefined ) {\n
+\n
+var uuid = 0,\n
+\tslice = Array.prototype.slice,\n
+\t_cleanData = $.cleanData;\n
+$.cleanData = function( elems ) {\n
+\tfor ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {\n
+\t\ttry {\n
+\t\t\t$( elem ).triggerHandler( "remove" );\n
+\t\t// http://bugs.jquery.com/ticket/8235\n
+\t\t} catch( e ) {}\n
+\t}\n
+\t_cleanData( elems );\n
+};\n
+\n
+$.widget = function( name, base, prototype ) {\n
+\tvar fullName, existingConstructor, constructor, basePrototype,\n
+\t\t// proxiedPrototype allows the provided prototype to remain unmodified\n
+\t\t// so that it can be used as a mixin for multiple widgets (#8876)\n
+\t\tproxiedPrototype = {},\n
+\t\tnamespace = name.split( "." )[ 0 ];\n
+\n
+\tname = name.split( "." )[ 1 ];\n
+\tfullName = namespace + "-" + name;\n
+\n
+\tif ( !prototype ) {\n
+\t\tprototype = base;\n
+\t\tbase = $.Widget;\n
+\t}\n
+\n
+\t// create selector for plugin\n
+\t$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {\n
+\t\treturn !!$.data( elem, fullName );\n
+\t};\n
+\n
+\t$[ namespace ] = $[ namespace ] || {};\n
+\texistingConstructor = $[ namespace ][ name ];\n
+\tconstructor = $[ namespace ][ name ] = function( options, element ) {\n
+\t\t// allow instantiation without "new" keyword\n
+\t\tif ( !this._createWidget ) {\n
+\t\t\treturn new constructor( options, element );\n
+\t\t}\n
+\n
+\t\t// allow instantiation without initializing for simple inheritance\n
+\t\t// must use "new" keyword (the code above always passes args)\n
+\t\tif ( arguments.length ) {\n
+\t\t\tthis._createWidget( options, element );\n
+\t\t}\n
+\t};\n
+\t// extend with the existing constructor to carry over any static properties\n
+\t$.extend( constructor, existingConstructor, {\n
+\t\tversion: prototype.version,\n
+\t\t// copy the object used to create the prototype in case we need to\n
+\t\t// redefine the widget later\n
+\t\t_proto: $.extend( {}, prototype ),\n
+\t\t// track widgets that inherit from this widget in case this widget is\n
+\t\t// redefined after a widget inherits from it\n
+\t\t_childConstructors: []\n
+\t});\n
+\n
+\tbasePrototype = new base();\n
+\t// we need to make the options hash a property directly on the new instance\n
+\t// otherwise we\'ll modify the options hash on the prototype that we\'re\n
+\t// inheriting from\n
+\tbasePrototype.options = $.widget.extend( {}, basePrototype.options );\n
+\t$.each( prototype, function( prop, value ) {\n
+\t\tif ( !$.isFunction( value ) ) {\n
+\t\t\tproxiedPrototype[ prop ] = value;\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tproxiedPrototype[ prop ] = (function() {\n
+\t\t\tvar _super = function() {\n
+\t\t\t\t\treturn base.prototype[ prop ].apply( this, arguments );\n
+\t\t\t\t},\n
+\t\t\t\t_superApply = function( args ) {\n
+\t\t\t\t\treturn base.prototype[ prop ].apply( this, args );\n
+\t\t\t\t};\n
+\t\t\treturn function() {\n
+\t\t\t\tvar __super = this._super,\n
+\t\t\t\t\t__superApply = this._superApply,\n
+\t\t\t\t\treturnValue;\n
+\n
+\t\t\t\tthis._super = _super;\n
+\t\t\t\tthis._superApply = _superApply;\n
+\n
+\t\t\t\treturnValue = value.apply( this, arguments );\n
+\n
+\t\t\t\tthis._super = __super;\n
+\t\t\t\tthis._superApply = __superApply;\n
+\n
+\t\t\t\treturn returnValue;\n
+\t\t\t};\n
+\t\t})();\n
+\t});\n
+\tconstructor.prototype = $.widget.extend( basePrototype, {\n
+\t\t// TODO: remove support for widgetEventPrefix\n
+\t\t// always use the name + a colon as the prefix, e.g., draggable:start\n
+\t\t// don\'t prefix for widgets that aren\'t DOM-based\n
+\t\twidgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name\n
+\t}, proxiedPrototype, {\n
+\t\tconstructor: constructor,\n
+\t\tnamespace: namespace,\n
+\t\twidgetName: name,\n
+\t\twidgetFullName: fullName\n
+\t});\n
+\n
+\t// If this widget is being redefined then we need to find all widgets that\n
+\t// are inheriting from it and redefine all of them so that they inherit from\n
+\t// the new version of this widget. We\'re essentially trying to replace one\n
+\t// level in the prototype chain.\n
+\tif ( existingConstructor ) {\n
+\t\t$.each( existingConstructor._childConstructors, function( i, child ) {\n
+\t\t\tvar childPrototype = child.prototype;\n
+\n
+\t\t\t// redefine the child widget using the same prototype that was\n
+\t\t\t// originally used, but inherit from the new version of the base\n
+\t\t\t$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );\n
+\t\t});\n
+\t\t// remove the list of existing child constructors from the old constructor\n
+\t\t// so the old child constructors can be garbage collected\n
+\t\tdelete existingConstructor._childConstructors;\n
+\t} else {\n
+\t\tbase._childConstructors.push( constructor );\n
+\t}\n
+\n
+\t$.widget.bridge( name, constructor );\n
+\n
+\treturn constructor;\n
+};\n
+\n
+$.widget.extend = function( target ) {\n
+\tvar input = slice.call( arguments, 1 ),\n
+\t\tinputIndex = 0,\n
+\t\tinputLength = input.length,\n
+\t\tkey,\n
+\t\tvalue;\n
+\tfor ( ; inputIndex < inputLength; inputIndex++ ) {\n
+\t\tfor ( key in input[ inputIndex ] ) {\n
+\t\t\tvalue = input[ inputIndex ][ key ];\n
+\t\t\tif ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {\n
+\t\t\t\t// Clone objects\n
+\t\t\t\tif ( $.isPlainObject( value ) ) {\n
+\t\t\t\t\ttarget[ key ] = $.isPlainObject( target[ key ] ) ?\n
+\t\t\t\t\t\t$.widget.extend( {}, target[ key ], value ) :\n
+\t\t\t\t\t\t// Don\'t extend strings, arrays, etc. with objects\n
+\t\t\t\t\t\t$.widget.extend( {}, value );\n
+\t\t\t\t// Copy everything else by reference\n
+\t\t\t\t} else {\n
+\t\t\t\t\ttarget[ key ] = value;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\treturn target;\n
+};\n
+\n
+$.widget.bridge = function( name, object ) {\n
+\tvar fullName = object.prototype.widgetFullName || name;\n
+\t$.fn[ name ] = function( options ) {\n
+\t\tvar isMethodCall = typeof options === "string",\n
+\t\t\targs = slice.call( arguments, 1 ),\n
+\t\t\treturnValue = this;\n
+\n
+\t\t// allow multiple hashes to be passed on init\n
+\t\toptions = !isMethodCall && args.length ?\n
+\t\t\t$.widget.extend.apply( null, [ options ].concat(args) ) :\n
+\t\t\toptions;\n
+\n
+\t\tif ( isMethodCall ) {\n
+\t\t\tthis.each(function() {\n
+\t\t\t\tvar methodValue,\n
+\t\t\t\t\tinstance = $.data( this, fullName );\n
+\t\t\t\tif ( options === "instance" ) {\n
+\t\t\t\t\treturnValue = instance;\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t\tif ( !instance ) {\n
+\t\t\t\t\treturn $.error( "cannot call methods on " + name + " prior to initialization; " +\n
+\t\t\t\t\t\t"attempted to call method \'" + options + "\'" );\n
+\t\t\t\t}\n
+\t\t\t\tif ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {\n
+\t\t\t\t\treturn $.error( "no such method \'" + options + "\' for " + name + " widget instance" );\n
+\t\t\t\t}\n
+\t\t\t\tmethodValue = instance[ options ].apply( instance, args );\n
+\t\t\t\tif ( methodValue !== instance && methodValue !== undefined ) {\n
+\t\t\t\t\treturnValue = methodValue && methodValue.jquery ?\n
+\t\t\t\t\t\treturnValue.pushStack( methodValue.get() ) :\n
+\t\t\t\t\t\tmethodValue;\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t} else {\n
+\t\t\tthis.each(function() {\n
+\t\t\t\tvar instance = $.data( this, fullName );\n
+\t\t\t\tif ( instance ) {\n
+\t\t\t\t\tinstance.option( options || {} )._init();\n
+\t\t\t\t} else {\n
+\t\t\t\t\t$.data( this, fullName, new object( options, this ) );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\treturn returnValue;\n
+\t};\n
+};\n
+\n
+$.Widget = function( /* options, element */ ) {};\n
+$.Widget._childConstructors = [];\n
+\n
+$.Widget.prototype = {\n
+\twidgetName: "widget",\n
+\twidgetEventPrefix: "",\n
+\tdefaultElement: "<div>",\n
+\toptions: {\n
+\t\tdisabled: false,\n
+\n
+\t\t// callbacks\n
+\t\tcreate: null\n
+\t},\n
+\t_createWidget: function( options, element ) {\n
+\t\telement = $( element || this.defaultElement || this )[ 0 ];\n
+\t\tthis.element = $( element );\n
+\t\tthis.uuid = uuid++;\n
+\t\tthis.eventNamespace = "." + this.widgetName + this.uuid;\n
+\t\tthis.options = $.widget.extend( {},\n
+\t\t\tthis.options,\n
+\t\t\tthis._getCreateOptions(),\n
+\t\t\toptions );\n
+\n
+\t\tthis.bindings = $();\n
+\t\tthis.hoverable = $();\n
+\t\tthis.focusable = $();\n
+\n
+\t\tif ( element !== this ) {\n
+\t\t\t$.data( element, this.widgetFullName, this );\n
+\t\t\tthis._on( true, this.element, {\n
+\t\t\t\tremove: function( event ) {\n
+\t\t\t\t\tif ( event.target === element ) {\n
+\t\t\t\t\t\tthis.destroy();\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t\tthis.document = $( element.style ?\n
+\t\t\t\t// element within the document\n
+\t\t\t\telement.ownerDocument :\n
+\t\t\t\t// element is window or document\n
+\t\t\t\telement.document || element );\n
+\t\t\tthis.window = $( this.document[0].defaultView || this.document[0].parentWindow );\n
+\t\t}\n
+\n
+\t\tthis._create();\n
+\t\tthis._trigger( "create", null, this._getCreateEventData() );\n
+\t\tthis._init();\n
+\t},\n
+\t_getCreateOptions: $.noop,\n
+\t_getCreateEventData: $.noop,\n
+\t_create: $.noop,\n
+\t_init: $.noop,\n
+\n
+\tdestroy: function() {\n
+\t\tthis._destroy();\n
+\t\t// we can probably remove the unbind calls in 2.0\n
+\t\t// all event bindings should go through this._on()\n
+\t\tthis.element\n
+\t\t\t.unbind( this.eventNamespace )\n
+\t\t\t.removeData( this.widgetFullName )\n
+\t\t\t// support: jquery <1.6.3\n
+\t\t\t// http://bugs.jquery.com/ticket/9413\n
+\t\t\t.removeData( $.camelCase( this.widgetFullName ) );\n
+\t\tthis.widget()\n
+\t\t\t.unbind( this.eventNamespace )\n
+\t\t\t.removeAttr( "aria-disabled" )\n
+\t\t\t.removeClass(\n
+\t\t\t\tthis.widgetFullName + "-disabled " +\n
+\t\t\t\t"ui-state-disabled" );\n
+\n
+\t\t// clean up events and states\n
+\t\tthis.bindings.unbind( this.eventNamespace );\n
+\t\tthis.hoverable.removeClass( "ui-state-hover" );\n
+\t\tthis.focusable.removeClass( "ui-state-focus" );\n
+\t},\n
+\t_destroy: $.noop,\n
+\n
+\twidget: function() {\n
+\t\treturn this.element;\n
+\t},\n
+\n
+\toption: function( key, value ) {\n
+\t\tvar options = key,\n
+\t\t\tparts,\n
+\t\t\tcurOption,\n
+\t\t\ti;\n
+\n
+\t\tif ( arguments.length === 0 ) {\n
+\t\t\t// don\'t return a reference to the internal hash\n
+\t\t\treturn $.widget.extend( {}, this.options );\n
+\t\t}\n
+\n
+\t\tif ( typeof key === "string" ) {\n
+\t\t\t// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }\n
+\t\t\toptions = {};\n
+\t\t\tparts = key.split( "." );\n
+\t\t\tkey = parts.shift();\n
+\t\t\tif ( parts.length ) {\n
+\t\t\t\tcurOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );\n
+\t\t\t\tfor ( i = 0; i < parts.length - 1; i++ ) {\n
+\t\t\t\t\tcurOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};\n
+\t\t\t\t\tcurOption = curOption[ parts[ i ] ];\n
+\t\t\t\t}\n
+\t\t\t\tkey = parts.pop();\n
+\t\t\t\tif ( value === undefined ) {\n
+\t\t\t\t\treturn curOption[ key ] === undefined ? null : curOption[ key ];\n
+\t\t\t\t}\n
+\t\t\t\tcurOption[ key ] = value;\n
+\t\t\t} else {\n
+\t\t\t\tif ( value === undefined ) {\n
+\t\t\t\t\treturn this.options[ key ] === undefined ? null : this.options[ key ];\n
+\t\t\t\t}\n
+\t\t\t\toptions[ key ] = value;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis._setOptions( options );\n
+\n
+\t\treturn this;\n
+\t},\n
+\t_setOptions: function( options ) {\n
+\t\tvar key;\n
+\n
+\t\tfor ( key in options ) {\n
+\t\t\tthis._setOption( key, options[ key ] );\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\t_setOption: function( key, value ) {\n
+\t\tthis.options[ key ] = value;\n
+\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\tthis.widget()\n
+\t\t\t\t.toggleClass( this.widgetFullName + "-disabled", !!value );\n
+\t\t\tthis.hoverable.removeClass( "ui-state-hover" );\n
+\t\t\tthis.focusable.removeClass( "ui-state-focus" );\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\tenable: function() {\n
+\t\treturn this._setOptions({ disabled: false });\n
+\t},\n
+\tdisable: function() {\n
+\t\treturn this._setOptions({ disabled: true });\n
+\t},\n
+\n
+\t_on: function( suppressDisabledCheck, element, handlers ) {\n
+\t\tvar delegateElement,\n
+\t\t\tinstance = this;\n
+\n
+\t\t// no suppressDisabledCheck flag, shuffle arguments\n
+\t\tif ( typeof suppressDisabledCheck !== "boolean" ) {\n
+\t\t\thandlers = element;\n
+\t\t\telement = suppressDisabledCheck;\n
+\t\t\tsuppressDisabledCheck = false;\n
+\t\t}\n
+\n
+\t\t// no element argument, shuffle and use this.element\n
+\t\tif ( !handlers ) {\n
+\t\t\thandlers = element;\n
+\t\t\telement = this.element;\n
+\t\t\tdelegateElement = this.widget();\n
+\t\t} else {\n
+\t\t\t// accept selectors, DOM elements\n
+\t\t\telement = delegateElement = $( element );\n
+\t\t\tthis.bindings = this.bindings.add( element );\n
+\t\t}\n
+\n
+\t\t$.each( handlers, function( event, handler ) {\n
+\t\t\tfunction handlerProxy() {\n
+\t\t\t\t// allow widgets to customize the disabled handling\n
+\t\t\t\t// - disabled as an array instead of boolean\n
+\t\t\t\t// - disabled class as method for disabling individual parts\n
+\t\t\t\tif ( !suppressDisabledCheck &&\n
+\t\t\t\t\t\t( instance.options.disabled === true ||\n
+\t\t\t\t\t\t\t$( this ).hasClass( "ui-state-disabled" ) ) ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\treturn ( typeof handler === "string" ? instance[ handler ] : handler )\n
+\t\t\t\t\t.apply( instance, arguments );\n
+\t\t\t}\n
+\n
+\t\t\t// copy the guid so direct unbinding works\n
+\t\t\tif ( typeof handler !== "string" ) {\n
+\t\t\t\thandlerProxy.guid = handler.guid =\n
+\t\t\t\t\thandler.guid || handlerProxy.guid || $.guid++;\n
+\t\t\t}\n
+\n
+\t\t\tvar match = event.match( /^(\\w+)\\s*(.*)$/ ),\n
+\t\t\t\teventName = match[1] + instance.eventNamespace,\n
+\t\t\t\tselector = match[2];\n
+\t\t\tif ( selector ) {\n
+\t\t\t\tdelegateElement.delegate( selector, eventName, handlerProxy );\n
+\t\t\t} else {\n
+\t\t\t\telement.bind( eventName, handlerProxy );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_off: function( element, eventName ) {\n
+\t\teventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;\n
+\t\telement.unbind( eventName ).undelegate( eventName );\n
+\t},\n
+\n
+\t_delay: function( handler, delay ) {\n
+\t\tfunction handlerProxy() {\n
+\t\t\treturn ( typeof handler === "string" ? instance[ handler ] : handler )\n
+\t\t\t\t.apply( instance, arguments );\n
+\t\t}\n
+\t\tvar instance = this;\n
+\t\treturn setTimeout( handlerProxy, delay || 0 );\n
+\t},\n
+\n
+\t_hoverable: function( element ) {\n
+\t\tthis.hoverable = this.hoverable.add( element );\n
+\t\tthis._on( element, {\n
+\t\t\tmouseenter: function( event ) {\n
+\t\t\t\t$( event.currentTarget ).addClass( "ui-state-hover" );\n
+\t\t\t},\n
+\t\t\tmouseleave: function( event ) {\n
+\t\t\t\t$( event.currentTarget ).removeClass( "ui-state-hover" );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_focusable: function( element ) {\n
+\t\tthis.focusable = this.focusable.add( element );\n
+\t\tthis._on( element, {\n
+\t\t\tfocusin: function( event ) {\n
+\t\t\t\t$( event.currentTarget ).addClass( "ui-state-focus" );\n
+\t\t\t},\n
+\t\t\tfocusout: function( event ) {\n
+\t\t\t\t$( event.currentTarget ).removeClass( "ui-state-focus" );\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_trigger: function( type, event, data ) {\n
+\t\tvar prop, orig,\n
+\t\t\tcallback = this.options[ type ];\n
+\n
+\t\tdata = data || {};\n
+\t\tevent = $.Event( event );\n
+\t\tevent.type = ( type === this.widgetEventPrefix ?\n
+\t\t\ttype :\n
+\t\t\tthis.widgetEventPrefix + type ).toLowerCase();\n
+\t\t// the original event may come from any element\n
+\t\t// so we need to reset the target on the new event\n
+\t\tevent.target = this.element[ 0 ];\n
+\n
+\t\t// copy original event properties over to the new event\n
+\t\torig = event.originalEvent;\n
+\t\tif ( orig ) {\n
+\t\t\tfor ( prop in orig ) {\n
+\t\t\t\tif ( !( prop in event ) ) {\n
+\t\t\t\t\tevent[ prop ] = orig[ prop ];\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis.element.trigger( event, data );\n
+\t\treturn !( $.isFunction( callback ) &&\n
+\t\t\tcallback.apply( this.element[0], [ event ].concat( data ) ) === false ||\n
+\t\t\tevent.isDefaultPrevented() );\n
+\t}\n
+};\n
+\n
+$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {\n
+\t$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {\n
+\t\tif ( typeof options === "string" ) {\n
+\t\t\toptions = { effect: options };\n
+\t\t}\n
+\t\tvar hasOptions,\n
+\t\t\teffectName = !options ?\n
+\t\t\t\tmethod :\n
+\t\t\t\toptions === true || typeof options === "number" ?\n
+\t\t\t\t\tdefaultEffect :\n
+\t\t\t\t\toptions.effect || defaultEffect;\n
+\t\toptions = options || {};\n
+\t\tif ( typeof options === "number" ) {\n
+\t\t\toptions = { duration: options };\n
+\t\t}\n
+\t\thasOptions = !$.isEmptyObject( options );\n
+\t\toptions.complete = callback;\n
+\t\tif ( options.delay ) {\n
+\t\t\telement.delay( options.delay );\n
+\t\t}\n
+\t\tif ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {\n
+\t\t\telement[ method ]( options );\n
+\t\t} else if ( effectName !== method && element[ effectName ] ) {\n
+\t\t\telement[ effectName ]( options.duration, options.easing, callback );\n
+\t\t} else {\n
+\t\t\telement.queue(function( next ) {\n
+\t\t\t\t$( this )[ method ]();\n
+\t\t\t\tif ( callback ) {\n
+\t\t\t\t\tcallback.call( element[ 0 ] );\n
+\t\t\t\t}\n
+\t\t\t\tnext();\n
+\t\t\t});\n
+\t\t}\n
+\t};\n
+});\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+var rcapitals = /[A-Z]/g,\n
+\treplaceFunction = function( c ) {\n
+\t\treturn "-" + c.toLowerCase();\n
+\t};\n
+\n
+$.extend( $.Widget.prototype, {\n
+\t_getCreateOptions: function() {\n
+\t\tvar option, value,\n
+\t\t\telem = this.element[ 0 ],\n
+\t\t\toptions = {};\n
+\n
+\t\tfor ( option in this.options ) {\n
+\t\t\tvalue = $.mobile.getAttribute( elem, option.replace( rcapitals, replaceFunction ) );\n
+\t\t\tif ( value != null ) {\n
+\t\t\t\toptions[ option ] = value;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn options;\n
+\t},\n
+\n
+\tenhanceWithin: function( target, useKeepNative ) {\n
+\t\tthis.enhance( $( $[ this.namespace ][ this.widgetName ].initSelector, $( target ) ), useKeepNative );\n
+\t},\n
+\n
+\tenhance: function( targets, useKeepNative ) {\n
+\t\tvar page, keepNative, $widgetElements = $( targets );\n
+\n
+\t\t// if ignoreContentEnabled is set to true the framework should\n
+\t\t// only enhance the selected elements when they do NOT have a\n
+\t\t// parent with the data-namespace-ignore attribute\n
+\t\t$widgetElements = $.mobile.enhanceable( $widgetElements );\n
+\n
+\t\tif ( useKeepNative && $widgetElements.length ) {\n
+\t\t\t// TODO remove dependency on the page widget for the keepNative.\n
+\t\t\t// Currently the keepNative value is defined on the page prototype so\n
+\t\t\t// the method is as well\n
+\t\t\tpage = $.mobile.closestPageData( $widgetElements );\n
+\t\t\tkeepNative = ( page && page.keepNativeSelector()) || "";\n
+\n
+\t\t\t$widgetElements = $widgetElements.not( keepNative );\n
+\t\t}\n
+\n
+\t\t$widgetElements[ this.widgetName ]();\n
+\t}\n
+});\n
+\n
+//TODO: Remove in 1.5 for backcompat only\n
+$.mobile.widget = $.Widget;\n
+\n
+})( jQuery );\n
+\n
+\n
+(function( $ ) {\n
+\t// DEPRECATED\n
+\t// NOTE global mobile object settings\n
+\t$.extend( $.mobile, {\n
+\t\t// DEPRECATED Should the text be visble in the loading message?\n
+\t\tloadingMessageTextVisible: undefined,\n
+\n
+\t\t// DEPRECATED When the text is visible, what theme does the loading box use?\n
+\t\tloadingMessageTheme: undefined,\n
+\n
+\t\t// DEPRECATED default message setting\n
+\t\tloadingMessage: undefined,\n
+\n
+\t\t// DEPRECATED\n
+\t\t// Turn on/off page loading message. Theme doubles as an object argument\n
+\t\t// with the following shape: { theme: \'\', text: \'\', html: \'\', textVisible: \'\' }\n
+\t\t// NOTE that the $.mobile.loading* settings and params past the first are deprecated\n
+\t\tshowPageLoadingMsg: function( theme, msgText, textonly ) {\n
+\t\t\t$.mobile.loading( "show", theme, msgText, textonly );\n
+\t\t},\n
+\n
+\t\t// DEPRECATED\n
+\t\thidePageLoadingMsg: function() {\n
+\t\t\t$.mobile.loading( "hide" );\n
+\t\t},\n
+\n
+\t\tloading: function() {\n
+\t\t\tthis.loaderWidget.loader.apply( this.loaderWidget, arguments );\n
+\t\t}\n
+\t});\n
+\n
+\t// TODO move loader class down into the widget settings\n
+\tvar loaderClass = "ui-loader", $html = $( "html" ), $window = $.mobile.window;\n
+\n
+\t$.widget( "mobile.loader", {\n
+\t\t// NOTE if the global config settings are defined they will override these\n
+\t\t//      options\n
+\t\toptions: {\n
+\t\t\t// the theme for the loading message\n
+\t\t\ttheme: "a",\n
+\n
+\t\t\t// whether the text in the loading message is shown\n
+\t\t\ttextVisible: false,\n
+\n
+\t\t\t// custom html for the inner content of the loading message\n
+\t\t\thtml: "",\n
+\n
+\t\t\t// the text to be displayed when the popup is shown\n
+\t\t\ttext: "loading"\n
+\t\t},\n
+\n
+\t\tdefaultHtml: "<div class=\'" + loaderClass + "\'>" +\n
+\t\t\t"<span class=\'ui-icon-loading\'></span>" +\n
+\t\t\t"<h1></h1>" +\n
+\t\t\t"</div>",\n
+\n
+\t\t// For non-fixed supportin browsers. Position at y center (if scrollTop supported), above the activeBtn (if defined), or just 100px from top\n
+\t\tfakeFixLoader: function() {\n
+\t\t\tvar activeBtn = $( "." + $.mobile.activeBtnClass ).first();\n
+\n
+\t\t\tthis.element\n
+\t\t\t\t.css({\n
+\t\t\t\t\ttop: $.support.scrollTop && $window.scrollTop() + $window.height() / 2 ||\n
+\t\t\t\t\t\tactiveBtn.length && activeBtn.offset().top || 100\n
+\t\t\t\t});\n
+\t\t},\n
+\n
+\t\t// check position of loader to see if it appears to be "fixed" to center\n
+\t\t// if not, use abs positioning\n
+\t\tcheckLoaderPosition: function() {\n
+\t\t\tvar offset = this.element.offset(),\n
+\t\t\t\tscrollTop = $window.scrollTop(),\n
+\t\t\t\tscreenHeight = $.mobile.getScreenHeight();\n
+\n
+\t\t\tif ( offset.top < scrollTop || ( offset.top - scrollTop ) > screenHeight ) {\n
+\t\t\t\tthis.element.addClass( "ui-loader-fakefix" );\n
+\t\t\t\tthis.fakeFixLoader();\n
+\t\t\t\t$window\n
+\t\t\t\t\t.unbind( "scroll", this.checkLoaderPosition )\n
+\t\t\t\t\t.bind( "scroll", $.proxy( this.fakeFixLoader, this ) );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\tresetHtml: function() {\n
+\t\t\tthis.element.html( $( this.defaultHtml ).html() );\n
+\t\t},\n
+\n
+\t\t// Turn on/off page loading message. Theme doubles as an object argument\n
+\t\t// with the following shape: { theme: \'\', text: \'\', html: \'\', textVisible: \'\' }\n
+\t\t// NOTE that the $.mobile.loading* settings and params past the first are deprecated\n
+\t\t// TODO sweet jesus we need to break some of this out\n
+\t\tshow: function( theme, msgText, textonly ) {\n
+\t\t\tvar textVisible, message, loadSettings;\n
+\n
+\t\t\tthis.resetHtml();\n
+\n
+\t\t\t// use the prototype options so that people can set them globally at\n
+\t\t\t// mobile init. Consistency, it\'s what\'s for dinner\n
+\t\t\tif ( $.type(theme) === "object" ) {\n
+\t\t\t\tloadSettings = $.extend( {}, this.options, theme );\n
+\n
+\t\t\t\t// prefer object property from the param then the old theme setting\n
+\t\t\t\ttheme = loadSettings.theme || $.mobile.loadingMessageTheme;\n
+\t\t\t} else {\n
+\t\t\t\tloadSettings = this.options;\n
+\n
+\t\t\t\t// here we prefer the them value passed as a string argument, then\n
+\t\t\t\t// we prefer the global option because we can\'t use undefined default\n
+\t\t\t\t// prototype options, then the prototype option\n
+\t\t\t\ttheme = theme || $.mobile.loadingMessageTheme || loadSettings.theme;\n
+\t\t\t}\n
+\n
+\t\t\t// set the message text, prefer the param, then the settings object\n
+\t\t\t// then loading message\n
+\t\t\tmessage = msgText || $.mobile.loadingMessage || loadSettings.text;\n
+\n
+\t\t\t// prepare the dom\n
+\t\t\t$html.addClass( "ui-loading" );\n
+\n
+\t\t\tif ( $.mobile.loadingMessage !== false || loadSettings.html ) {\n
+\t\t\t\t// boolean values require a bit more work :P, supports object properties\n
+\t\t\t\t// and old settings\n
+\t\t\t\tif ( $.mobile.loadingMessageTextVisible !== undefined ) {\n
+\t\t\t\t\ttextVisible = $.mobile.loadingMessageTextVisible;\n
+\t\t\t\t} else {\n
+\t\t\t\t\ttextVisible = loadSettings.textVisible;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// add the proper css given the options (theme, text, etc)\n
+\t\t\t\t// Force text visibility if the second argument was supplied, or\n
+\t\t\t\t// if the text was explicitly set in the object args\n
+\t\t\t\tthis.element.attr("class", loaderClass +\n
+\t\t\t\t\t" ui-corner-all ui-body-" + theme +\n
+\t\t\t\t\t" ui-loader-" + ( textVisible || msgText || theme.text ? "verbose" : "default" ) +\n
+\t\t\t\t\t( loadSettings.textonly || textonly ? " ui-loader-textonly" : "" ) );\n
+\n
+\t\t\t\t// TODO verify that jquery.fn.html is ok to use in both cases here\n
+\t\t\t\t//      this might be overly defensive in preventing unknowing xss\n
+\t\t\t\t// if the html attribute is defined on the loading settings, use that\n
+\t\t\t\t// otherwise use the fallbacks from above\n
+\t\t\t\tif ( loadSettings.html ) {\n
+\t\t\t\t\tthis.element.html( loadSettings.html );\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthis.element.find( "h1" ).text( message );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// attach the loader to the DOM\n
+\t\t\t\tthis.element.appendTo( $.mobile.pageContainer );\n
+\n
+\t\t\t\t// check that the loader is visible\n
+\t\t\t\tthis.checkLoaderPosition();\n
+\n
+\t\t\t\t// on scroll check the loader position\n
+\t\t\t\t$window.bind( "scroll", $.proxy( this.checkLoaderPosition, this ) );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\thide: function() {\n
+\t\t\t$html.removeClass( "ui-loading" );\n
+\n
+\t\t\tif ( $.mobile.loadingMessage ) {\n
+\t\t\t\tthis.element.removeClass( "ui-loader-fakefix" );\n
+\t\t\t}\n
+\n
+\t\t\t$.mobile.window.unbind( "scroll", this.fakeFixLoader );\n
+\t\t\t$.mobile.window.unbind( "scroll", this.checkLoaderPosition );\n
+\t\t}\n
+\t});\n
+\n
+\t$window.bind( "pagecontainercreate", function() {\n
+\t\t$.mobile.loaderWidget = $.mobile.loaderWidget || $( $.mobile.loader.prototype.defaultHtml ).loader();\n
+\t});\n
+})(jQuery, this);\n
+\n
+\n
+// Script: jQuery hashchange event\n
+// \n
+// *Version: 1.3, Last updated: 7/21/2010*\n
+// \n
+// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/\n
+// GitHub       - http://github.com/cowboy/jquery-hashchange/\n
+// Source       - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js\n
+// (Minified)   - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped)\n
+// \n
+// About: License\n
+// \n
+// Copyright (c) 2010 "Cowboy" Ben Alman,\n
+// Dual licensed under the MIT and GPL licenses.\n
+// http://benalman.com/about/license/\n
+// \n
+// About: Examples\n
+// \n
+// These working examples, complete with fully commented code, illustrate a few\n
+// ways in which this plugin can be used.\n
+// \n
+// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/\n
+// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/\n
+// \n
+// About: Support and Testing\n
+// \n
+// Information about what version or versions of jQuery this plugin has been\n
+// tested with, what browsers it has been tested in, and where the unit tests\n
+// reside (so you can test it yourself).\n
+// \n
+// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2\n
+// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5,\n
+//                   Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5.\n
+// Unit Tests      - http://benalman.com/code/projects/jquery-hashchange/unit/\n
+// \n
+// About: Known issues\n
+// \n
+// While this jQuery hashchange event implementation is quite stable and\n
+// robust, there are a few unfortunate browser bugs surrounding expected\n
+// hashchange event-based behaviors, independent of any JavaScript\n
+// window.onhashchange abstraction. See the following examples for more\n
+// information:\n
+// \n
+// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/\n
+// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/\n
+// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/\n
+// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/\n
+// \n
+// Also note that should a browser natively support the window.onhashchange \n
+// event, but not report that it does, the fallback polling loop will be used.\n
+// \n
+// About: Release History\n
+// \n
+// 1.3   - (7/21/2010) Reorganized IE6/7 Iframe code to make it more\n
+//         "removable" for mobile-only development. Added IE6/7 document.title\n
+//         support. Attempted to make Iframe as hidden as possible by using\n
+//         techniques from http://www.paciellogroup.com/blog/?p=604. Added \n
+//         support for the "shortcut" format $(window).hashchange( fn ) and\n
+//         $(window).hashchange() like jQuery provides for built-in events.\n
+//         Renamed jQuery.hashchangeDelay to <jQuery.fn.hashchange.delay> and\n
+//         lowered its default value to 50. Added <jQuery.fn.hashchange.domain>\n
+//         and <jQuery.fn.hashchange.src> properties plus document-domain.html\n
+//         file to address access denied issues when setting document.domain in\n
+//         IE6/7.\n
+// 1.2   - (2/11/2010) Fixed a bug where coming back to a page using this plugin\n
+//         from a page on another domain would cause an error in Safari 4. Also,\n
+//         IE6/7 Iframe is now inserted after the body (this actually works),\n
+//         which prevents the page from scrolling when the event is first bound.\n
+//         Event can also now be bound before DOM ready, but it won\'t be usable\n
+//         before then in IE6/7.\n
+// 1.1   - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug\n
+//         where browser version is incorrectly reported as 8.0, despite\n
+//         inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag.\n
+// 1.0   - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special\n
+//         window.onhashchange functionality into a separate plugin for users\n
+//         who want just the basic event & back button support, without all the\n
+//         extra awesomeness that BBQ provides. This plugin will be included as\n
+//         part of jQuery BBQ, but also be available separately.\n
+\n
+(function( $, window, undefined ) {\n
+  // Reused string.\n
+  var str_hashchange = \'hashchange\',\n
+    \n
+    // Method / object references.\n
+    doc = document,\n
+    fake_onhashchange,\n
+    special = $.event.special,\n
+    \n
+    // Does the browser support window.onhashchange? Note that IE8 running in\n
+    // IE7 compatibility mode reports true for \'onhashchange\' in window, even\n
+    // though the event isn\'t supported, so also test document.documentMode.\n
+    doc_mode = doc.documentMode,\n
+    supports_onhashchange = \'on\' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 );\n
+  \n
+  // Get location.hash (or what you\'d expect location.hash to be) sans any\n
+  // leading #. Thanks for making this necessary, Firefox!\n
+  function get_fragment( url ) {\n
+    url = url || location.href;\n
+    return \'#\' + url.replace( /^[^#]*#?(.*)$/, \'$1\' );\n
+  };\n
+  \n
+  // Method: jQuery.fn.hashchange\n
+  // \n
+  // Bind a handler to the window.onhashchange event or trigger all bound\n
+  // window.onhashchange event handlers. This behavior is consistent with\n
+  // jQuery\'s built-in event handlers.\n
+  // \n
+  // Usage:\n
+  // \n
+  // > jQuery(window).hashchange( [ handler ] );\n
+  // \n
+  // Arguments:\n
+  // \n
+  //  handler - (Function) Optional handler to be bound to the hashchange\n
+  //    event. This is a "shortcut" for the more verbose form:\n
+  //    jQuery(window).bind( \'hashchange\', handler ). If handler is omitted,\n
+  //    all bound window.onhashchange event handlers will be triggered. This\n
+  //    is a shortcut for the more verbose\n
+  //    jQuery(window).trigger( \'hashchange\' ). These forms are described in\n
+  //    the <hashchange event> section.\n
+  // \n
+  // Returns:\n
+  // \n
+  //  (jQuery) The initial jQuery collection of elements.\n
+  \n
+  // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and\n
+  // $(elem).hashchange() for triggering, like jQuery does for built-in events.\n
+  $.fn[ str_hashchange ] = function( fn ) {\n
+    return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange );\n
+  };\n
+  \n
+  // Property: jQuery.fn.hashchange.delay\n
+  // \n
+  // The numeric interval (in milliseconds) at which the <hashchange event>\n
+  // polling loop executes. Defaults to 50.\n
+  \n
+  // Property: jQuery.fn.hashchange.domain\n
+  // \n
+  // If you\'re setting document.domain in your JavaScript, and you want hash\n
+  // history to work in IE6/7, not only must this property be set, but you must\n
+  // also set document.domain BEFORE jQuery is loaded into the page. This\n
+  // property is only applicable if you are supporting IE6/7 (or IE8 operating\n
+  // in "IE7 compatibility" mode).\n
+  // \n
+  // In addition, the <jQuery.fn.hashchange.src> property must be set to the\n
+  // path of the included "document-domain.html" file, which can be renamed or\n
+  // modified if necessary (note that the document.domain specified must be the\n
+  // same in both your main JavaScript as well as in this file).\n
+  // \n
+  // Usage:\n
+  // \n
+  // jQuery.fn.hashchange.domain = document.domain;\n
+  \n
+  // Property: jQuery.fn.hashchange.src\n
+  // \n
+  // If, for some reason, you need to specify an Iframe src file (for example,\n
+  // when setting document.domain as in <jQuery.fn.hashchange.domain>), you can\n
+  // do so using this property. Note that when using this property, history\n
+  // won\'t be recorded in IE6/7 until the Iframe src file loads. This property\n
+  // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7\n
+  // compatibility" mode).\n
+  // \n
+  // Usage:\n
+  // \n
+  // jQuery.fn.hashchange.src = \'path/to/file.html\';\n
+  \n
+  $.fn[ str_hashchange ].delay = 50;\n
+  /*\n
+  $.fn[ str_hashchange ].domain = null;\n
+  $.fn[ str_hashchange ].src = null;\n
+  */\n
+  \n
+  // Event: hashchange event\n
+  // \n
+  // Fired when location.hash changes. In browsers that support it, the native\n
+  // HTML5 window.onhashchange event is used, otherwise a polling loop is\n
+  // initialized, running every <jQuery.fn.hashchange.delay> milliseconds to\n
+  // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7\n
+  // compatibility" mode), a hidden Iframe is created to allow the back button\n
+  // and hash-based history to work.\n
+  // \n
+  // Usage as described in <jQuery.fn.hashchange>:\n
+  // \n
+  // > // Bind an event handler.\n
+  // > jQuery(window).hashchange( function(e) {\n
+  // >   var hash = location.hash;\n
+  // >   ...\n
+  // > });\n
+  // > \n
+  // > // Manually trigger the event handler.\n
+  // > jQuery(window).hashchange();\n
+  // \n
+  // A more verbose usage that allows for event namespacing:\n
+  // \n
+  // > // Bind an event handler.\n
+  // > jQuery(window).bind( \'hashchange\', function(e) {\n
+  // >   var hash = location.hash;\n
+  // >   ...\n
+  // > });\n
+  // > \n
+  // > // Manually trigger the event handler.\n
+  // > jQuery(window).trigger( \'hashchange\' );\n
+  // \n
+  // Additional Notes:\n
+  // \n
+  // * The polling loop and Iframe are not created until at least one handler\n
+  //   is actually bound to the \'hashchange\' event.\n
+  // * If you need the bound handler(s) to execute immediately, in cases where\n
+  //   a location.hash exists on page load, via bookmark or page refresh for\n
+  //   example, use jQuery(window).hashchange() or the more verbose \n
+  //   jQuery(window).trigger( \'hashchange\' ).\n
+  // * The event can be bound before DOM ready, but since it won\'t be usable\n
+  //   before then in IE6/7 (due to the necessary Iframe), recommended usage is\n
+  //   to bind it inside a DOM ready handler.\n
+  \n
+  // Override existing $.event.special.hashchange methods (allowing this plugin\n
+  // to be defined after jQuery BBQ in BBQ\'s source code).\n
+  special[ str_hashchange ] = $.extend( special[ str_hashchange ], {\n
+    \n
+    // Called only when the first \'hashchange\' event is bound to window.\n
+    setup: function() {\n
+      // If window.onhashchange is supported natively, there\'s nothing to do..\n
+      if ( supports_onhashchange ) { return false; }\n
+      \n
+      // Otherwise, we need to create our own. And we don\'t want to call this\n
+      // until the user binds to the event, just in case they never do, since it\n
+      // will create a polling loop and possibly even a hidden Iframe.\n
+      $( fake_onhashchange.start );\n
+    },\n
+    \n
+    // Called only when the last \'hashchange\' event is unbound from window.\n
+    teardown: function() {\n
+      // If window.onhashchange is supported natively, there\'s nothing to do..\n
+      if ( supports_onhashchange ) { return false; }\n
+      \n
+      // Otherwise, we need to stop ours (if possible).\n
+      $( fake_onhashchange.stop );\n
+    }\n
+    \n
+  });\n
+  \n
+  // fake_onhashchange does all the work of triggering the window.onhashchange\n
+  // event for browsers that don\'t natively support it, including creating a\n
+  // polling loop to watch for hash changes and in IE 6/7 creating a hidden\n
+  // Iframe to enable back and forward.\n
+  fake_onhashchange = (function() {\n
+    var self = {},\n
+      timeout_id,\n
+      \n
+      // Remember the initial hash so it doesn\'t get triggered immediately.\n
+      last_hash = get_fragment(),\n
+      \n
+      fn_retval = function( val ) { return val; },\n
+      history_set = fn_retval,\n
+      history_get = fn_retval;\n
+    \n
+    // Start the polling loop.\n
+    self.start = function() {\n
+      timeout_id || poll();\n
+    };\n
+    \n
+    // Stop the polling loop.\n
+    self.stop = function() {\n
+      timeout_id && clearTimeout( timeout_id );\n
+      timeout_id = undefined;\n
+    };\n
+    \n
+    // This polling loop checks every $.fn.hashchange.delay milliseconds to see\n
+    // if location.hash has changed, and triggers the \'hashchange\' event on\n
+    // window when necessary.\n
+    function poll() {\n
+      var hash = get_fragment(),\n
+        history_hash = history_get( last_hash );\n
+      \n
+      if ( hash !== last_hash ) {\n
+        history_set( last_hash = hash, history_hash );\n
+        \n
+        $(window).trigger( str_hashchange );\n
+        \n
+      } else if ( history_hash !== last_hash ) {\n
+        location.href = location.href.replace( /#.*/, \'\' ) + history_hash;\n
+      }\n
+      \n
+      timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay );\n
+    };\n
+    \n
+    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n
+    // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv\n
+    // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n
+    window.attachEvent && !window.addEventListener && !supports_onhashchange && (function() {\n
+      // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8\n
+      // when running in "IE7 compatibility" mode.\n
+      \n
+      var iframe,\n
+        iframe_src;\n
+      \n
+      // When the event is bound and polling starts in IE 6/7, create a hidden\n
+      // Iframe for history handling.\n
+      self.start = function() {\n
+        if ( !iframe ) {\n
+          iframe_src = $.fn[ str_hashchange ].src;\n
+          iframe_src = iframe_src && iframe_src + get_fragment();\n
+          \n
+          // Create hidden Iframe. Attempt to make Iframe as hidden as possible\n
+          // by using techniques from http://www.paciellogroup.com/blog/?p=604.\n
+          iframe = $(\'<iframe tabindex="-1" title="empty"/>\').hide()\n
+            \n
+            // When Iframe has completely loaded, initialize the history and\n
+            // start polling.\n
+            .one( \'load\', function() {\n
+              iframe_src || history_set( get_fragment() );\n
+              poll();\n
+            })\n
+            \n
+            // Load Iframe src if specified, otherwise nothing.\n
+            .attr( \'src\', iframe_src || \'javascript:0\' )\n
+            \n
+            // Append Iframe after the end of the body to prevent unnecessary\n
+            // initial page scrolling (yes, this works).\n
+            .insertAfter( \'body\' )[0].contentWindow;\n
+          \n
+          // Whenever `document.title` changes, update the Iframe\'s title to\n
+          // prettify the back/next history menu entries. Since IE sometimes\n
+          // errors with "Unspecified error" the very first time this is set\n
+          // (yes, very useful) wrap this with a try/catch block.\n
+          doc.onpropertychange = function() {\n
+            try {\n
+              if ( event.propertyName === \'title\' ) {\n
+                iframe.document.title = doc.title;\n
+              }\n
+            } catch(e) {}\n
+          };\n
+          \n
+        }\n
+      };\n
+      \n
+      // Override the "stop" method since an IE6/7 Iframe was created. Even\n
+      // if there are no longer any bound event handlers, the polling loop\n
+      // is still necessary for back/next to work at all!\n
+      self.stop = fn_retval;\n
+      \n
+      // Get history by looking at the hidden Iframe\'s location.hash.\n
+      history_get = function() {\n
+        return get_fragment( iframe.location.href );\n
+      };\n
+      \n
+      // Set a new history item by opening and then closing the Iframe\n
+      // document, *then* setting its location.hash. If document.domain has\n
+      // been set, update that as well.\n
+      history_set = function( hash, history_hash ) {\n
+        var iframe_doc = iframe.document,\n
+          domain = $.fn[ str_hashchange ].domain;\n
+        \n
+        if ( hash !== history_hash ) {\n
+          // Update Iframe with any initial `document.title` that might be set.\n
+          iframe_doc.title = doc.title;\n
+          \n
+          // Opening the Iframe\'s document after it has been closed is what\n
+          // actually adds a history entry.\n
+          iframe_doc.open();\n
+          \n
+          // Set document.domain for the Iframe document as well, if necessary.\n
+          domain && iframe_doc.write( \'<script>document.domain="\' + domain + \'"</script>\' );\n
+          \n
+          iframe_doc.close();\n
+          \n
+          // Update the Iframe\'s hash, for great justice.\n
+          iframe.location.hash = hash;\n
+        }\n
+      };\n
+      \n
+    })();\n
+    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n
+    // ^^^^^^^^^^^^^^^^^^^ REMOVE IF NOT SUPPORTING IE6/7/8 ^^^^^^^^^^^^^^^^^^^\n
+    // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n
+    \n
+    return self;\n
+  })();\n
+  \n
+})(jQuery,this);\n
+\n
+(function( $, undefined ) {\n
+\n
+\t/*! matchMedia() polyfill - Test a CSS media type/query in JS. Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas. Dual MIT/BSD license */\n
+\twindow.matchMedia = window.matchMedia || (function( doc, undefined ) {\n
+\n
+\t\t\n
+\n
+\t\tvar bool,\n
+\t\t\tdocElem = doc.documentElement,\n
+\t\t\trefNode = docElem.firstElementChild || docElem.firstChild,\n
+\t\t\t// fakeBody required for <FF4 when executed in <head>\n
+\t\t\tfakeBody = doc.createElement( "body" ),\n
+\t\t\tdiv = doc.createElement( "div" );\n
+\n
+\t\tdiv.id = "mq-test-1";\n
+\t\tdiv.style.cssText = "position:absolute;top:-100em";\n
+\t\tfakeBody.style.background = "none";\n
+\t\tfakeBody.appendChild(div);\n
+\n
+\t\treturn function(q){\n
+\n
+\t\t\tdiv.innerHTML = "&shy;<style media=\\"" + q + "\\"> #mq-test-1 { width: 42px; }</style>";\n
+\n
+\t\t\tdocElem.insertBefore( fakeBody, refNode );\n
+\t\t\tbool = div.offsetWidth === 42;\n
+\t\t\tdocElem.removeChild( fakeBody );\n
+\n
+\t\t\treturn {\n
+\t\t\t\tmatches: bool,\n
+\t\t\t\tmedia: q\n
+\t\t\t};\n
+\n
+\t\t};\n
+\n
+\t}( document ));\n
+\n
+\t// $.mobile.media uses matchMedia to return a boolean.\n
+\t$.mobile.media = function( q ) {\n
+\t\treturn window.matchMedia( q ).matches;\n
+\t};\n
+\n
+})(jQuery);\n
+\n
+\t(function( $, undefined ) {\n
+\t\tvar support = {\n
+\t\t\ttouch: "ontouchend" in document\n
+\t\t};\n
+\n
+\t\t$.mobile.support = $.mobile.support || {};\n
+\t\t$.extend( $.support, support );\n
+\t\t$.extend( $.mobile.support, support );\n
+\t}( jQuery ));\n
+\n
+\t(function( $, undefined ) {\n
+\t\t$.extend( $.support, {\n
+\t\t\torientation: "orientation" in window && "onorientationchange" in window\n
+\t\t});\n
+\t}( jQuery ));\n
+\n
+(function( $, undefined ) {\n
+\n
+// thx Modernizr\n
+function propExists( prop ) {\n
+\tvar uc_prop = prop.charAt( 0 ).toUpperCase() + prop.substr( 1 ),\n
+\t\tprops = ( prop + " " + vendors.join( uc_prop + " " ) + uc_prop ).split( " " ),\n
+\t\tv;\n
+\n
+\tfor ( v in props ) {\n
+\t\tif ( fbCSS[ props[ v ] ] !== undefined ) {\n
+\t\t\treturn true;\n
+\t\t}\n
+\t}\n
+}\n
+\n
+var fakeBody = $( "<body>" ).prependTo( "html" ),\n
+\tfbCSS = fakeBody[ 0 ].style,\n
+\tvendors = [ "Webkit", "Moz", "O" ],\n
+\twebos = "palmGetResource" in window, //only used to rule out scrollTop\n
+\topera = window.opera,\n
+\toperamini = window.operamini && ({}).toString.call( window.operamini ) === "[object OperaMini]",\n
+\tbb = window.blackberry && !propExists( "-webkit-transform" ), //only used to rule out box shadow, as it\'s filled opaque on BB 5 and lower\n
+\tnokiaLTE7_3;\n
+\n
+\n
+function validStyle( prop, value, check_vend ) {\n
+\tvar div = document.createElement( "div" ),\n
+\t\tuc = function( txt ) {\n
+\t\t\treturn txt.charAt( 0 ).toUpperCase() + txt.substr( 1 );\n
+\t\t},\n
+\t\tvend_pref = function( vend ) {\n
+\t\t\tif ( vend === "" ) {\n
+\t\t\t\treturn "";\n
+\t\t\t} else {\n
+\t\t\t\treturn  "-" + vend.charAt( 0 ).toLowerCase() + vend.substr( 1 ) + "-";\n
+\t\t\t}\n
+\t\t},\n
+\t\tcheck_style = function( vend ) {\n
+\t\t\tvar vend_prop = vend_pref( vend ) + prop + ": " + value + ";",\n
+\t\t\t\tuc_vend = uc( vend ),\n
+\t\t\t\tpropStyle = uc_vend + ( uc_vend === "" ? prop : uc( prop ) );\n
+\n
+\t\t\tdiv.setAttribute( "style", vend_prop );\n
+\n
+\t\t\tif ( !!div.style[ propStyle ] ) {\n
+\t\t\t\tret = true;\n
+\t\t\t}\n
+\t\t},\n
+\t\tcheck_vends = check_vend ? check_vend : vendors,\n
+\t\ti, ret;\n
+\n
+\tfor( i = 0; i < check_vends.length; i++ ) {\n
+\t\tcheck_style( check_vends[i] );\n
+\t}\n
+\treturn !!ret;\n
+}\n
+\n
+// inline SVG support test\n
+function inlineSVG() {\n
+\t// Thanks Modernizr & Erik Dahlstrom\n
+\tvar w = window,\n
+\t\tsvg = !!w.document.createElementNS && !!w.document.createElementNS( "http://www.w3.org/2000/svg", "svg" ).createSVGRect && !( w.opera && navigator.userAgent.indexOf( "Chrome" ) === -1 ),\n
+\t\tsupport = function( data ) {\n
+\t\t\tif ( !( data && svg ) ) {\n
+\t\t\t\t$( "html" ).addClass( "ui-nosvg" );\n
+\t\t\t}\n
+\t\t},\n
+\t\timg = new w.Image();\n
+\n
+\timg.onerror = function() {\n
+\t\tsupport( false );\n
+\t};\n
+\timg.onload = function() {\n
+\t\tsupport( img.width === 1 && img.height === 1 );\n
+\t};\n
+\timg.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";\n
+}\n
+\n
+function transform3dTest() {\n
+\tvar mqProp = "transform-3d",\n
+\t\t// Because the `translate3d` test below throws false positives in Android:\n
+\t\tret = $.mobile.media( "(-" + vendors.join( "-" + mqProp + "),(-" ) + "-" + mqProp + "),(" + mqProp + ")" ),\n
+\t\tel, transforms, t;\n
+\n
+\tif ( ret ) {\n
+\t\treturn !!ret;\n
+\t}\n
+\n
+\tel = document.createElement( "div" );\n
+\ttransforms = {\n
+\t\t// We’re omitting Opera for the time being; MS uses unprefixed.\n
+\t\t"MozTransform": "-moz-transform",\n
+\t\t"transform": "transform"\n
+\t};\n
+\n
+\tfakeBody.append( el );\n
+\n
+\tfor ( t in transforms ) {\n
+\t\tif ( el.style[ t ] !== undefined ){\n
+\t\t\tel.style[ t ] = "translate3d( 100px, 1px, 1px )";\n
+\t\t\tret = window.getComputedStyle( el ).getPropertyValue( transforms[ t ] );\n
+\t\t}\n
+\t}\n
+\treturn ( !!ret && ret !== "none" );\n
+}\n
+\n
+// Test for dynamic-updating base tag support ( allows us to avoid href,src attr rewriting )\n
+function baseTagTest() {\n
+\tvar fauxBase = location.protocol + "//" + location.host + location.pathname + "ui-dir/",\n
+\t\tbase = $( "head base" ),\n
+\t\tfauxEle = null,\n
+\t\thref = "",\n
+\t\tlink, rebase;\n
+\n
+\tif ( !base.length ) {\n
+\t\tbase = fauxEle = $( "<base>", { "href": fauxBase }).appendTo( "head" );\n
+\t} else {\n
+\t\thref = base.attr( "href" );\n
+\t}\n
+\n
+\tlink = $( "<a href=\'testurl\' />" ).prependTo( fakeBody );\n
+\trebase = link[ 0 ].href;\n
+\tbase[ 0 ].href = href || location.pathname;\n
+\n
+\tif ( fauxEle ) {\n
+\t\tfauxEle.remove();\n
+\t}\n
+\treturn rebase.indexOf( fauxBase ) === 0;\n
+}\n
+\n
+// Thanks Modernizr\n
+function cssPointerEventsTest() {\n
+\tvar element = document.createElement( "x" ),\n
+\t\tdocumentElement = document.documentElement,\n
+\t\tgetComputedStyle = window.getComputedStyle,\n
+\t\tsupports;\n
+\n
+\tif ( !( "pointerEvents" in element.style ) ) {\n
+\t\treturn false;\n
+\t}\n
+\n
+\telement.style.pointerEvents = "auto";\n
+\telement.style.pointerEvents = "x";\n
+\tdocumentElement.appendChild( element );\n
+\tsupports = getComputedStyle &&\n
+\tgetComputedStyle( element, "" ).pointerEvents === "auto";\n
+\tdocumentElement.removeChild( element );\n
+\treturn !!supports;\n
+}\n
+\n
+function boundingRect() {\n
+\tvar div = document.createElement( "div" );\n
+\treturn typeof div.getBoundingClientRect !== "undefined";\n
+}\n
+\n
+// non-UA-based IE version check by James Padolsey, modified by jdalton - from http://gist.github.com/527683\n
+// allows for inclusion of IE 6+, including Windows Mobile 7\n
+$.extend( $.mobile, { browser: {} } );\n
+$.mobile.browser.oldIE = (function() {\n
+\tvar v = 3,\n
+\t\tdiv = document.createElement( "div" ),\n
+\t\ta = div.all || [];\n
+\n
+\tdo {\n
+\t\tdiv.innerHTML = "<!--[if gt IE " + ( ++v ) + "]><br><![endif]-->";\n
+\t} while( a[0] );\n
+\n
+\treturn v > 4 ? v : !v;\n
+})();\n
+\n
+function fixedPosition() {\n
+\tvar w = window,\n
+\t\tua = navigator.userAgent,\n
+\t\tplatform = navigator.platform,\n
+\t\t// Rendering engine is Webkit, and capture major version\n
+\t\twkmatch = ua.match( /AppleWebKit\\/([0-9]+)/ ),\n
+\t\twkversion = !!wkmatch && wkmatch[ 1 ],\n
+\t\tffmatch = ua.match( /Fennec\\/([0-9]+)/ ),\n
+\t\tffversion = !!ffmatch && ffmatch[ 1 ],\n
+\t\toperammobilematch = ua.match( /Opera Mobi\\/([0-9]+)/ ),\n
+\t\tomversion = !!operammobilematch && operammobilematch[ 1 ];\n
+\n
+\tif (\n
+\t\t// iOS 4.3 and older : Platform is iPhone/Pad/Touch and Webkit version is less than 534 (ios5)\n
+\t\t( ( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1  || platform.indexOf( "iPod" ) > -1 ) && wkversion && wkversion < 534 ) ||\n
+\t\t// Opera Mini\n
+\t\t( w.operamini && ({}).toString.call( w.operamini ) === "[object OperaMini]" ) ||\n
+\t\t( operammobilematch && omversion < 7458 )\t||\n
+\t\t//Android lte 2.1: Platform is Android and Webkit version is less than 533 (Android 2.2)\n
+\t\t( ua.indexOf( "Android" ) > -1 && wkversion && wkversion < 533 ) ||\n
+\t\t// Firefox Mobile before 6.0 -\n
+\t\t( ffversion && ffversion < 6 ) ||\n
+\t\t// WebOS less than 3\n
+\t\t( "palmGetResource" in window && wkversion && wkversion < 534 )\t||\n
+\t\t// MeeGo\n
+\t\t( ua.indexOf( "MeeGo" ) > -1 && ua.indexOf( "NokiaBrowser/8.5.0" ) > -1 ) ) {\n
+\t\treturn false;\n
+\t}\n
+\n
+\treturn true;\n
+}\n
+\n
+$.extend( $.support, {\n
+\tcssTransitions: "WebKitTransitionEvent" in window ||\n
+\t\tvalidStyle( "transition", "height 100ms linear", [ "Webkit", "Moz", "" ] ) &&\n
+\t\t!$.mobile.browser.oldIE && !opera,\n
+\n
+\t// Note, Chrome for iOS has an extremely quirky implementation of popstate.\n
+\t// We\'ve chosen to take the shortest path to a bug fix here for issue #5426\n
+\t// See the following link for information about the regex chosen\n
+\t// https://developers.google.com/chrome/mobile/docs/user-agent#chrome_for_ios_user-agent\n
+\tpushState: "pushState" in history &&\n
+\t\t"replaceState" in history &&\n
+\t\t// When running inside a FF iframe, calling replaceState causes an error\n
+\t\t!( window.navigator.userAgent.indexOf( "Firefox" ) >= 0 && window.top !== window ) &&\n
+\t\t( window.navigator.userAgent.search(/CriOS/) === -1 ),\n
+\n
+\tmediaquery: $.mobile.media( "only all" ),\n
+\tcssPseudoElement: !!propExists( "content" ),\n
+\ttouchOverflow: !!propExists( "overflowScrolling" ),\n
+\tcssTransform3d: transform3dTest(),\n
+\tboxShadow: !!propExists( "boxShadow" ) && !bb,\n
+\tfixedPosition: fixedPosition(),\n
+\tscrollTop: ("pageXOffset" in window ||\n
+\t\t"scrollTop" in document.documentElement ||\n
+\t\t"scrollTop" in fakeBody[ 0 ]) && !webos && !operamini,\n
+\n
+\tdynamicBaseTag: baseTagTest(),\n
+\tcssPointerEvents: cssPointerEventsTest(),\n
+\tboundingRect: boundingRect(),\n
+\tinlineSVG: inlineSVG\n
+});\n
+\n
+fakeBody.remove();\n
+\n
+\n
+// $.mobile.ajaxBlacklist is used to override ajaxEnabled on platforms that have known conflicts with hash history updates (BB5, Symbian)\n
+// or that generally work better browsing in regular http for full page refreshes (Opera Mini)\n
+// Note: This detection below is used as a last resort.\n
+// We recommend only using these detection methods when all other more reliable/forward-looking approaches are not possible\n
+nokiaLTE7_3 = (function() {\n
+\n
+\tvar ua = window.navigator.userAgent;\n
+\n
+\t//The following is an attempt to match Nokia browsers that are running Symbian/s60, with webkit, version 7.3 or older\n
+\treturn ua.indexOf( "Nokia" ) > -1 &&\n
+\t\t\t( ua.indexOf( "Symbian/3" ) > -1 || ua.indexOf( "Series60/5" ) > -1 ) &&\n
+\t\t\tua.indexOf( "AppleWebKit" ) > -1 &&\n
+\t\t\tua.match( /(BrowserNG|NokiaBrowser)\\/7\\.[0-3]/ );\n
+})();\n
+\n
+// Support conditions that must be met in order to proceed\n
+// default enhanced qualifications are media query support OR IE 7+\n
+\n
+$.mobile.gradeA = function() {\n
+\treturn ( ( $.support.mediaquery && $.support.cssPseudoElement ) || $.mobile.browser.oldIE && $.mobile.browser.oldIE >= 8 ) && ( $.support.boundingRect || $.fn.jquery.match(/1\\.[0-7+]\\.[0-9+]?/) !== null );\n
+};\n
+\n
+$.mobile.ajaxBlacklist =\n
+\t\t\t// BlackBerry browsers, pre-webkit\n
+\t\t\twindow.blackberry && !window.WebKitPoint ||\n
+\t\t\t// Opera Mini\n
+\t\t\toperamini ||\n
+\t\t\t// Symbian webkits pre 7.3\n
+\t\t\tnokiaLTE7_3;\n
+\n
+// Lastly, this workaround is the only way we\'ve found so far to get pre 7.3 Symbian webkit devices\n
+// to render the stylesheets when they\'re referenced before this script, as we\'d recommend doing.\n
+// This simply reappends the CSS in place, which for some reason makes it apply\n
+if ( nokiaLTE7_3 ) {\n
+\t$(function() {\n
+\t\t$( "head link[rel=\'stylesheet\']" ).attr( "rel", "alternate stylesheet" ).attr( "rel", "stylesheet" );\n
+\t});\n
+}\n
+\n
+// For ruling out shadows via css\n
+if ( !$.support.boxShadow ) {\n
+\t$( "html" ).addClass( "ui-noboxshadow" );\n
+}\n
+\n
+})( jQuery );\n
+\n
+\n
+(function( $, undefined ) {\n
+\tvar $win = $.mobile.window, self,\n
+\t\tdummyFnToInitNavigate = function() {\n
+\t\t};\n
+\n
+\t$.event.special.beforenavigate = {\n
+\t\tsetup: function() {\n
+\t\t\t$win.on( "navigate", dummyFnToInitNavigate );\n
+\t\t},\n
+\n
+\t\tteardown: function() {\n
+\t\t\t$win.off( "navigate", dummyFnToInitNavigate );\n
+\t\t}\n
+\t};\n
+\n
+\t$.event.special.navigate = self = {\n
+\t\tbound: false,\n
+\n
+\t\tpushStateEnabled: true,\n
+\n
+\t\toriginalEventName: undefined,\n
+\n
+\t\t// If pushstate support is present and push state support is defined to\n
+\t\t// be true on the mobile namespace.\n
+\t\tisPushStateEnabled: function() {\n
+\t\t\treturn $.support.pushState &&\n
+\t\t\t\t$.mobile.pushStateEnabled === true &&\n
+\t\t\t\tthis.isHashChangeEnabled();\n
+\t\t},\n
+\n
+\t\t// !! assumes mobile namespace is present\n
+\t\tisHashChangeEnabled: function() {\n
+\t\t\treturn $.mobile.hashListeningEnabled === true;\n
+\t\t},\n
+\n
+\t\t// TODO a lot of duplication between popstate and hashchange\n
+\t\tpopstate: function( event ) {\n
+\t\t\tvar newEvent = new $.Event( "navigate" ),\n
+\t\t\t\tbeforeNavigate = new $.Event( "beforenavigate" ),\n
+\t\t\t\tstate = event.originalEvent.state || {};\n
+\n
+\t\t\tbeforeNavigate.originalEvent = event;\n
+\t\t\t$win.trigger( beforeNavigate );\n
+\n
+\t\t\tif ( beforeNavigate.isDefaultPrevented() ){\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tif ( event.historyState ){\n
+\t\t\t\t$.extend(state, event.historyState);\n
+\t\t\t}\n
+\n
+\t\t\t// Make sure the original event is tracked for the end\n
+\t\t\t// user to inspect incase they want to do something special\n
+\t\t\tnewEvent.originalEvent = event;\n
+\n
+\t\t\t// NOTE we let the current stack unwind because any assignment to\n
+\t\t\t//      location.hash will stop the world and run this event handler. By\n
+\t\t\t//      doing this we create a similar behavior to hashchange on hash\n
+\t\t\t//      assignment\n
+\t\t\tsetTimeout(function() {\n
+\t\t\t\t$win.trigger( newEvent, {\n
+\t\t\t\t\tstate: state\n
+\t\t\t\t});\n
+\t\t\t}, 0);\n
+\t\t},\n
+\n
+\t\thashchange: function( event /*, data */ ) {\n
+\t\t\tvar newEvent = new $.Event( "navigate" ),\n
+\t\t\t\tbeforeNavigate = new $.Event( "beforenavigate" );\n
+\n
+\t\t\tbeforeNavigate.originalEvent = event;\n
+\t\t\t$win.trigger( beforeNavigate );\n
+\n
+\t\t\tif ( beforeNavigate.isDefaultPrevented() ){\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// Make sure the original event is tracked for the end\n
+\t\t\t// user to inspect incase they want to do something special\n
+\t\t\tnewEvent.originalEvent = event;\n
+\n
+\t\t\t// Trigger the hashchange with state provided by the user\n
+\t\t\t// that altered the hash\n
+\t\t\t$win.trigger( newEvent, {\n
+\t\t\t\t// Users that want to fully normalize the two events\n
+\t\t\t\t// will need to do history management down the stack and\n
+\t\t\t\t// add the state to the event before this binding is fired\n
+\t\t\t\t// TODO consider allowing for the explicit addition of callbacks\n
+\t\t\t\t//      to be fired before this value is set to avoid event timing issues\n
+\t\t\t\tstate: event.hashchangeState || {}\n
+\t\t\t});\n
+\t\t},\n
+\n
+\t\t// TODO We really only want to set this up once\n
+\t\t//      but I\'m not clear if there\'s a beter way to achieve\n
+\t\t//      this with the jQuery special event structure\n
+\t\tsetup: function( /* data, namespaces */ ) {\n
+\t\t\tif ( self.bound ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tself.bound = true;\n
+\n
+\t\t\tif ( self.isPushStateEnabled() ) {\n
+\t\t\t\tself.originalEventName = "popstate";\n
+\t\t\t\t$win.bind( "popstate.navigate", self.popstate );\n
+\t\t\t} else if ( self.isHashChangeEnabled() ){\n
+\t\t\t\tself.originalEventName = "hashchange";\n
+\t\t\t\t$win.bind( "hashchange.navigate", self.hashchange );\n
+\t\t\t}\n
+\t\t}\n
+\t};\n
+})( jQuery );\n
+\n
+\n
+\n
+(function( $, undefined ) {\n
+\t\tvar path, $base, dialogHashKey = "&ui-state=dialog";\n
+\n
+\t\t$.mobile.path = path = {\n
+\t\t\tuiStateKey: "&ui-state",\n
+\n
+\t\t\t// This scary looking regular expression parses an absolute URL or its relative\n
+\t\t\t// variants (protocol, site, document, query, and hash), into the various\n
+\t\t\t// components (protocol, host, path, query, fragment, etc that make up the\n
+\t\t\t// URL as well as some other commonly used sub-parts. When used with RegExp.exec()\n
+\t\t\t// or String.match, it parses the URL into a results array that looks like this:\n
+\t\t\t//\n
+\t\t\t//     [0]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread#msg-content\n
+\t\t\t//     [1]: http://jblas:password@mycompany.com:8080/mail/inbox?msg=1234&type=unread\n
+\t\t\t//     [2]: http://jblas:password@mycompany.com:8080/mail/inbox\n
+\t\t\t//     [3]: http://jblas:password@mycompany.com:8080\n
+\t\t\t//     [4]: http:\n
+\t\t\t//     [5]: //\n
+\t\t\t//     [6]: jblas:password@mycompany.com:8080\n
+\t\t\t//     [7]: jblas:password\n
+\t\t\t//     [8]: jblas\n
+\t\t\t//     [9]: password\n
+\t\t\t//    [10]: mycompany.com:8080\n
+\t\t\t//    [11]: mycompany.com\n
+\t\t\t//    [12]: 8080\n
+\t\t\t//    [13]: /mail/inbox\n
+\t\t\t//    [14]: /mail/\n
+\t\t\t//    [15]: inbox\n
+\t\t\t//    [16]: ?msg=1234&type=unread\n
+\t\t\t//    [17]: #msg-content\n
+\t\t\t//\n
+\t\t\turlParseRE: /^\\s*(((([^:\\/#\\?]+:)?(?:(\\/\\/)((?:(([^:@\\/#\\?]+)(?:\\:([^:@\\/#\\?]+))?)@)?(([^:\\/#\\?\\]\\[]+|\\[[^\\/\\]@#?]+\\])(?:\\:([0-9]+))?))?)?)?((\\/?(?:[^\\/\\?#]+\\/+)*)([^\\?#]*)))?(\\?[^#]+)?)(#.*)?/,\n
+\n
+\t\t\t// Abstraction to address xss (Issue #4787) by removing the authority in\n
+\t\t\t// browsers that auto\tdecode it. All references to location.href should be\n
+\t\t\t// replaced with a call to this method so that it can be dealt with properly here\n
+\t\t\tgetLocation: function( url ) {\n
+\t\t\t\tvar uri = url ? this.parseUrl( url ) : location,\n
+\t\t\t\t\thash = this.parseUrl( url || location.href ).hash;\n
+\n
+\t\t\t\t// mimic the browser with an empty string when the hash is empty\n
+\t\t\t\thash = hash === "#" ? "" : hash;\n
+\n
+\t\t\t\t// Make sure to parse the url or the location object for the hash because using location.hash\n
+\t\t\t\t// is autodecoded in firefox, the rest of the url should be from the object (location unless\n
+\t\t\t\t// we\'re testing) to avoid the inclusion of the authority\n
+\t\t\t\treturn uri.protocol + "//" + uri.host + uri.pathname + uri.search + hash;\n
+\t\t\t},\n
+\n
+\t\t\tparseLocation: function() {\n
+\t\t\t\treturn this.parseUrl( this.getLocation() );\n
+\t\t\t},\n
+\n
+\t\t\t//Parse a URL into a structure that allows easy access to\n
+\t\t\t//all of the URL components by name.\n
+\t\t\tparseUrl: function( url ) {\n
+\t\t\t\t// If we\'re passed an object, we\'ll assume that it is\n
+\t\t\t\t// a parsed url object and just return it back to the caller.\n
+\t\t\t\tif ( $.type( url ) === "object" ) {\n
+\t\t\t\t\treturn url;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tvar matches = path.urlParseRE.exec( url || "" ) || [];\n
+\n
+\t\t\t\t\t// Create an object that allows the caller to access the sub-matches\n
+\t\t\t\t\t// by name. Note that IE returns an empty string instead of undefined,\n
+\t\t\t\t\t// like all other browsers do, so we normalize everything so its consistent\n
+\t\t\t\t\t// no matter what browser we\'re running on.\n
+\t\t\t\t\treturn {\n
+\t\t\t\t\t\thref:         matches[  0 ] || "",\n
+\t\t\t\t\t\threfNoHash:   matches[  1 ] || "",\n
+\t\t\t\t\t\threfNoSearch: matches[  2 ] || "",\n
+\t\t\t\t\t\tdomain:       matches[  3 ] || "",\n
+\t\t\t\t\t\tprotocol:     matches[  4 ] || "",\n
+\t\t\t\t\t\tdoubleSlash:  matches[  5 ] || "",\n
+\t\t\t\t\t\tauthority:    matches[  6 ] || "",\n
+\t\t\t\t\t\tusername:     matches[  8 ] || "",\n
+\t\t\t\t\t\tpassword:     matches[  9 ] || "",\n
+\t\t\t\t\t\thost:         matches[ 10 ] || "",\n
+\t\t\t\t\t\thostname:     matches[ 11 ] || "",\n
+\t\t\t\t\t\tport:         matches[ 12 ] || "",\n
+\t\t\t\t\t\tpathname:     matches[ 13 ] || "",\n
+\t\t\t\t\t\tdirectory:    matches[ 14 ] || "",\n
+\t\t\t\t\t\tfilename:     matches[ 15 ] || "",\n
+\t\t\t\t\t\tsearch:       matches[ 16 ] || "",\n
+\t\t\t\t\t\thash:         matches[ 17 ] || ""\n
+\t\t\t\t\t};\n
+\t\t\t},\n
+\n
+\t\t\t//Turn relPath into an asbolute path. absPath is\n
+\t\t\t//an optional absolute path which describes what\n
+\t\t\t//relPath is relative to.\n
+\t\t\tmakePathAbsolute: function( relPath, absPath ) {\n
+\t\t\t\tvar absStack,\n
+\t\t\t\t\trelStack,\n
+\t\t\t\t\ti, d;\n
+\n
+\t\t\t\tif ( relPath && relPath.charAt( 0 ) === "/" ) {\n
+\t\t\t\t\treturn relPath;\n
+\t\t\t\t}\n
+\n
+\t\t\t\trelPath = relPath || "";\n
+\t\t\t\tabsPath = absPath ? absPath.replace( /^\\/|(\\/[^\\/]*|[^\\/]+)$/g, "" ) : "";\n
+\n
+\t\t\t\tabsStack = absPath ? absPath.split( "/" ) : [];\n
+\t\t\t\trelStack = relPath.split( "/" );\n
+\n
+\t\t\t\tfor ( i = 0; i < relStack.length; i++ ) {\n
+\t\t\t\t\td = relStack[ i ];\n
+\t\t\t\t\tswitch ( d ) {\n
+\t\t\t\t\t\tcase ".":\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tcase "..":\n
+\t\t\t\t\t\t\tif ( absStack.length ) {\n
+\t\t\t\t\t\t\t\tabsStack.pop();\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\tdefault:\n
+\t\t\t\t\t\t\tabsStack.push( d );\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\treturn "/" + absStack.join( "/" );\n
+\t\t\t},\n
+\n
+\t\t\t//Returns true if both urls have the same domain.\n
+\t\t\tisSameDomain: function( absUrl1, absUrl2 ) {\n
+\t\t\t\treturn path.parseUrl( absUrl1 ).domain === path.parseUrl( absUrl2 ).domain;\n
+\t\t\t},\n
+\n
+\t\t\t//Returns true for any relative variant.\n
+\t\t\tisRelativeUrl: function( url ) {\n
+\t\t\t\t// All relative Url variants have one thing in common, no protocol.\n
+\t\t\t\treturn path.parseUrl( url ).protocol === "";\n
+\t\t\t},\n
+\n
+\t\t\t//Returns true for an absolute url.\n
+\t\t\tisAbsoluteUrl: function( url ) {\n
+\t\t\t\treturn path.parseUrl( url ).protocol !== "";\n
+\t\t\t},\n
+\n
+\t\t\t//Turn the specified realtive URL into an absolute one. This function\n
+\t\t\t//can handle all relative variants (protocol, site, document, query, fragment).\n
+\t\t\tmakeUrlAbsolute: function( relUrl, absUrl ) {\n
+\t\t\t\tif ( !path.isRelativeUrl( relUrl ) ) {\n
+\t\t\t\t\treturn relUrl;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif ( absUrl === undefined ) {\n
+\t\t\t\t\tabsUrl = this.documentBase;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tvar relObj = path.parseUrl( relUrl ),\n
+\t\t\t\t\tabsObj = path.parseUrl( absUrl ),\n
+\t\t\t\t\tprotocol = relObj.protocol || absObj.protocol,\n
+\t\t\t\t\tdoubleSlash = relObj.protocol ? relObj.doubleSlash : ( relObj.doubleSlash || absObj.doubleSlash ),\n
+\t\t\t\t\tauthority = relObj.authority || absObj.authority,\n
+\t\t\t\t\thasPath = relObj.pathname !== "",\n
+\t\t\t\t\tpathname = path.makePathAbsolute( relObj.pathname || absObj.filename, absObj.pathname ),\n
+\t\t\t\t\tsearch = relObj.search || ( !hasPath && absObj.search ) || "",\n
+\t\t\t\t\thash = relObj.hash;\n
+\n
+\t\t\t\treturn protocol + doubleSlash + authority + pathname + search + hash;\n
+\t\t\t},\n
+\n
+\t\t\t//Add search (aka query) params to the specified url.\n
+\t\t\taddSearchParams: function( url, params ) {\n
+\t\t\t\tvar u = path.parseUrl( url ),\n
+\t\t\t\t\tp = ( typeof params === "object" ) ? $.param( params ) : params,\n
+\t\t\t\t\ts = u.search || "?";\n
+\t\t\t\treturn u.hrefNoSearch + s + ( s.charAt( s.length - 1 ) !== "?" ? "&" : "" ) + p + ( u.hash || "" );\n
+\t\t\t},\n
+\n
+\t\t\tconvertUrlToDataUrl: function( absUrl ) {\n
+\t\t\t\tvar u = path.parseUrl( absUrl );\n
+\t\t\t\tif ( path.isEmbeddedPage( u ) ) {\n
+\t\t\t\t\t// For embedded pages, remove the dialog hash key as in getFilePath(),\n
+\t\t\t\t\t// and remove otherwise the Data Url won\'t match the id of the embedded Page.\n
+\t\t\t\t\treturn u.hash\n
+\t\t\t\t\t\t.split( dialogHashKey )[0]\n
+\t\t\t\t\t\t.replace( /^#/, "" )\n
+\t\t\t\t\t\t.replace( /\\?.*$/, "" );\n
+\t\t\t\t} else if ( path.isSameDomain( u, this.documentBase ) ) {\n
+\t\t\t\t\treturn u.hrefNoHash.replace( this.documentBase.domain, "" ).split( dialogHashKey )[0];\n
+\t\t\t\t}\n
+\n
+\t\t\t\treturn window.decodeURIComponent(absUrl);\n
+\t\t\t},\n
+\n
+\t\t\t//get path from current hash, or from a file path\n
+\t\t\tget: function( newPath ) {\n
+\t\t\t\tif ( newPath === undefined ) {\n
+\t\t\t\t\tnewPath = path.parseLocation().hash;\n
+\t\t\t\t}\n
+\t\t\t\treturn path.stripHash( newPath ).replace( /[^\\/]*\\.[^\\/*]+$/, "" );\n
+\t\t\t},\n
+\n
+\t\t\t//set location hash to path\n
+\t\t\tset: function( path ) {\n
+\t\t\t\tlocation.hash = path;\n
+\t\t\t},\n
+\n
+\t\t\t//test if a given url (string) is a path\n
+\t\t\t//NOTE might be exceptionally naive\n
+\t\t\tisPath: function( url ) {\n
+\t\t\t\treturn ( /\\// ).test( url );\n
+\t\t\t},\n
+\n
+\t\t\t//return a url path with the window\'s location protocol/hostname/pathname removed\n
+\t\t\tclean: function( url ) {\n
+\t\t\t\treturn url.replace( this.documentBase.domain, "" );\n
+\t\t\t},\n
+\n
+\t\t\t//just return the url without an initial #\n
+\t\t\tstripHash: function( url ) {\n
+\t\t\t\treturn url.replace( /^#/, "" );\n
+\t\t\t},\n
+\n
+\t\t\tstripQueryParams: function( url ) {\n
+\t\t\t\treturn url.replace( /\\?.*$/, "" );\n
+\t\t\t},\n
+\n
+\t\t\t//remove the preceding hash, any query params, and dialog notations\n
+\t\t\tcleanHash: function( hash ) {\n
+\t\t\t\treturn path.stripHash( hash.replace( /\\?.*$/, "" ).replace( dialogHashKey, "" ) );\n
+\t\t\t},\n
+\n
+\t\t\tisHashValid: function( hash ) {\n
+\t\t\t\treturn ( /^#[^#]+$/ ).test( hash );\n
+\t\t\t},\n
+\n
+\t\t\t//check whether a url is referencing the same domain, or an external domain or different protocol\n
+\t\t\t//could be mailto, etc\n
+\t\t\tisExternal: function( url ) {\n
+\t\t\t\tvar u = path.parseUrl( url );\n
+\t\t\t\treturn u.protocol && u.domain !== this.documentUrl.domain ? true : false;\n
+\t\t\t},\n
+\n
+\t\t\thasProtocol: function( url ) {\n
+\t\t\t\treturn ( /^(:?\\w+:)/ ).test( url );\n
+\t\t\t},\n
+\n
+\t\t\tisEmbeddedPage: function( url ) {\n
+\t\t\t\tvar u = path.parseUrl( url );\n
+\n
+\t\t\t\t//if the path is absolute, then we need to compare the url against\n
+\t\t\t\t//both the this.documentUrl and the documentBase. The main reason for this\n
+\t\t\t\t//is that links embedded within external documents will refer to the\n
+\t\t\t\t//application document, whereas links embedded within the application\n
+\t\t\t\t//document will be resolved against the document base.\n
+\t\t\t\tif ( u.protocol !== "" ) {\n
+\t\t\t\t\treturn ( !this.isPath(u.hash) && u.hash && ( u.hrefNoHash === this.documentUrl.hrefNoHash || ( this.documentBaseDiffers && u.hrefNoHash === this.documentBase.hrefNoHash ) ) );\n
+\t\t\t\t}\n
+\t\t\t\treturn ( /^#/ ).test( u.href );\n
+\t\t\t},\n
+\n
+\t\t\tsquash: function( url, resolutionUrl ) {\n
+\t\t\t\tvar href, cleanedUrl, search, stateIndex,\n
+\t\t\t\t\tisPath = this.isPath( url ),\n
+\t\t\t\t\turi = this.parseUrl( url ),\n
+\t\t\t\t\tpreservedHash = uri.hash,\n
+\t\t\t\t\tuiState = "";\n
+\n
+\t\t\t\t// produce a url against which we can resole the provided path\n
+\t\t\t\tresolutionUrl = resolutionUrl || (path.isPath(url) ? path.getLocation() : path.getDocumentUrl());\n
+\n
+\t\t\t\t// If the url is anything but a simple string, remove any preceding hash\n
+\t\t\t\t// eg #foo/bar -> foo/bar\n
+\t\t\t\t//    #foo -> #foo\n
+\t\t\t\tcleanedUrl = isPath ? path.stripHash( url ) : url;\n
+\n
+\t\t\t\t// If the url is a full url with a hash check if the parsed hash is a path\n
+\t\t\t\t// if it is, strip the #, and use it otherwise continue without change\n
+\t\t\t\tcleanedUrl = path.isPath( uri.hash ) ? path.stripHash( uri.hash ) : cleanedUrl;\n
+\n
+\t\t\t\t// Split the UI State keys off the href\n
+\t\t\t\tstateIndex = cleanedUrl.indexOf( this.uiStateKey );\n
+\n
+\t\t\t\t// store the ui state keys for use\n
+\t\t\t\tif ( stateIndex > -1 ){\n
+\t\t\t\t\tuiState = cleanedUrl.slice( stateIndex );\n
+\t\t\t\t\tcleanedUrl = cleanedUrl.slice( 0, stateIndex );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// make the cleanedUrl absolute relative to the resolution url\n
+\t\t\t\thref = path.makeUrlAbsolute( cleanedUrl, resolutionUrl );\n
+\n
+\t\t\t\t// grab the search from the resolved url since parsing from\n
+\t\t\t\t// the passed url may not yield the correct result\n
+\t\t\t\tsearch = this.parseUrl( href ).search;\n
+\n
+\t\t\t\t// TODO all this crap is terrible, clean it up\n
+\t\t\t\tif ( isPath ) {\n
+\t\t\t\t\t// reject the hash if it\'s a path or it\'s just a dialog key\n
+\t\t\t\t\tif ( path.isPath( preservedHash ) || preservedHash.replace("#", "").indexOf( this.uiStateKey ) === 0) {\n
+\t\t\t\t\t\tpreservedHash = "";\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// Append the UI State keys where it exists and it\'s been removed\n
+\t\t\t\t\t// from the url\n
+\t\t\t\t\tif ( uiState && preservedHash.indexOf( this.uiStateKey ) === -1){\n
+\t\t\t\t\t\tpreservedHash += uiState;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// make sure that pound is on the front of the hash\n
+\t\t\t\t\tif ( preservedHash.indexOf( "#" ) === -1 && preservedHash !== "" ){\n
+\t\t\t\t\t\tpreservedHash = "#" + preservedHash;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// reconstruct each of the pieces with the new search string and hash\n
+\t\t\t\t\thref = path.parseUrl( href );\n
+\t\t\t\t\thref = href.protocol + "//" + href.host + href.pathname + search + preservedHash;\n
+\t\t\t\t} else {\n
+\t\t\t\t\thref += href.indexOf( "#" ) > -1 ? uiState : "#" + uiState;\n
+\t\t\t\t}\n
+\n
+\t\t\t\treturn href;\n
+\t\t\t},\n
+\n
+\t\t\tisPreservableHash: function( hash ) {\n
+\t\t\t\treturn hash.replace( "#", "" ).indexOf( this.uiStateKey ) === 0;\n
+\t\t\t},\n
+\n
+\t\t\t// Escape weird characters in the hash if it is to be used as a selector\n
+\t\t\thashToSelector: function( hash ) {\n
+\t\t\t\tvar hasHash = ( hash.substring( 0, 1 ) === "#" );\n
+\t\t\t\tif ( hasHash ) {\n
+\t\t\t\t\thash = hash.substring( 1 );\n
+\t\t\t\t}\n
+\t\t\t\treturn ( hasHash ? "#" : "" ) + hash.replace( /([!"#$%&\'()*+,./:;<=>?@[\\]^`{|}~])/g, "\\\\$1" );\n
+\t\t\t}\n
+\t\t};\n
+\n
+\t\tpath.documentUrl = path.parseLocation();\n
+\n
+\t\t$base = $( "head" ).find( "base" );\n
+\n
+\t\tpath.documentBase = $base.length ?\n
+\t\t\tpath.parseUrl( path.makeUrlAbsolute( $base.attr( "href" ), path.documentUrl.href ) ) :\n
+\t\t\tpath.documentUrl;\n
+\n
+\t\tpath.documentBaseDiffers = (path.documentUrl.hrefNoHash !== path.documentBase.hrefNoHash);\n
+\n
+\t\t//return the original document url\n
+\t\tpath.getDocumentUrl = function( asParsedObject ) {\n
+\t\t\treturn asParsedObject ? $.extend( {}, path.documentUrl ) : path.documentUrl.href;\n
+\t\t};\n
+\n
+\t\t//return the original document base url\n
+\t\tpath.getDocumentBase = function( asParsedObject ) {\n
+\t\t\treturn asParsedObject ? $.extend( {}, path.documentBase ) : path.documentBase.href;\n
+\t\t};\n
+})( jQuery );\n
+\n
+\n
+\n
+(function( $, undefined ) {\n
+\t$.mobile.History = function( stack, index ) {\n
+\t\tthis.stack = stack || [];\n
+\t\tthis.activeIndex = index || 0;\n
+\t};\n
+\n
+\t$.extend($.mobile.History.prototype, {\n
+\t\tgetActive: function() {\n
+\t\t\treturn this.stack[ this.activeIndex ];\n
+\t\t},\n
+\n
+\t\tgetLast: function() {\n
+\t\t\treturn this.stack[ this.previousIndex ];\n
+\t\t},\n
+\n
+\t\tgetNext: function() {\n
+\t\t\treturn this.stack[ this.activeIndex + 1 ];\n
+\t\t},\n
+\n
+\t\tgetPrev: function() {\n
+\t\t\treturn this.stack[ this.activeIndex - 1 ];\n
+\t\t},\n
+\n
+\t\t// addNew is used whenever a new page is added\n
+\t\tadd: function( url, data ){\n
+\t\t\tdata = data || {};\n
+\n
+\t\t\t//if there\'s forward history, wipe it\n
+\t\t\tif ( this.getNext() ) {\n
+\t\t\t\tthis.clearForward();\n
+\t\t\t}\n
+\n
+\t\t\t// if the hash is included in the data make sure the shape\n
+\t\t\t// is consistent for comparison\n
+\t\t\tif ( data.hash && data.hash.indexOf( "#" ) === -1) {\n
+\t\t\t\tdata.hash = "#" + data.hash;\n
+\t\t\t}\n
+\n
+\t\t\tdata.url = url;\n
+\t\t\tthis.stack.push( data );\n
+\t\t\tthis.activeIndex = this.stack.length - 1;\n
+\t\t},\n
+\n
+\t\t//wipe urls ahead of active index\n
+\t\tclearForward: function() {\n
+\t\t\tthis.stack = this.stack.slice( 0, this.activeIndex + 1 );\n
+\t\t},\n
+\n
+\t\tfind: function( url, stack, earlyReturn ) {\n
+\t\t\tstack = stack || this.stack;\n
+\n
+\t\t\tvar entry, i, length = stack.length, index;\n
+\n
+\t\t\tfor ( i = 0; i < length; i++ ) {\n
+\t\t\t\tentry = stack[i];\n
+\n
+\t\t\t\tif ( decodeURIComponent(url) === decodeURIComponent(entry.url) ||\n
+\t\t\t\t\tdecodeURIComponent(url) === decodeURIComponent(entry.hash) ) {\n
+\t\t\t\t\tindex = i;\n
+\n
+\t\t\t\t\tif ( earlyReturn ) {\n
+\t\t\t\t\t\treturn index;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\treturn index;\n
+\t\t},\n
+\n
+\t\tclosest: function( url ) {\n
+\t\t\tvar closest, a = this.activeIndex;\n
+\n
+\t\t\t// First, take the slice of the history stack before the current index and search\n
+\t\t\t// for a url match. If one is found, we\'ll avoid avoid looking through forward history\n
+\t\t\t// NOTE the preference for backward history movement is driven by the fact that\n
+\t\t\t//      most mobile browsers only have a dedicated back button, and users rarely use\n
+\t\t\t//      the forward button in desktop browser anyhow\n
+\t\t\tclosest = this.find( url, this.stack.slice(0, a) );\n
+\n
+\t\t\t// If nothing was found in backward history check forward. The `true`\n
+\t\t\t// value passed as the third parameter causes the find method to break\n
+\t\t\t// on the first match in the forward history slice. The starting index\n
+\t\t\t// of the slice must then be added to the result to get the element index\n
+\t\t\t// in the original history stack :( :(\n
+\t\t\t//\n
+\t\t\t// TODO this is hyper confusing and should be cleaned up (ugh so bad)\n
+\t\t\tif ( closest === undefined ) {\n
+\t\t\t\tclosest = this.find( url, this.stack.slice(a), true );\n
+\t\t\t\tclosest = closest === undefined ? closest : closest + a;\n
+\t\t\t}\n
+\n
+\t\t\treturn closest;\n
+\t\t},\n
+\n
+\t\tdirect: function( opts ) {\n
+\t\t\tvar newActiveIndex = this.closest( opts.url ), a = this.activeIndex;\n
+\n
+\t\t\t// save new page index, null check to prevent falsey 0 result\n
+\t\t\t// record the previous index for reference\n
+\t\t\tif ( newActiveIndex !== undefined ) {\n
+\t\t\t\tthis.activeIndex = newActiveIndex;\n
+\t\t\t\tthis.previousIndex = a;\n
+\t\t\t}\n
+\n
+\t\t\t// invoke callbacks where appropriate\n
+\t\t\t//\n
+\t\t\t// TODO this is also convoluted and confusing\n
+\t\t\tif ( newActiveIndex < a ) {\n
+\t\t\t\t( opts.present || opts.back || $.noop )( this.getActive(), "back" );\n
+\t\t\t} else if ( newActiveIndex > a ) {\n
+\t\t\t\t( opts.present || opts.forward || $.noop )( this.getActive(), "forward" );\n
+\t\t\t} else if ( newActiveIndex === undefined && opts.missing ){\n
+\t\t\t\topts.missing( this.getActive() );\n
+\t\t\t}\n
+\t\t}\n
+\t});\n
+})( jQuery );\n
+\n
+\n
+(function( $, undefined ) {\n
+\tvar path = $.mobile.path,\n
+\t\tinitialHref = location.href;\n
+\n
+\t$.mobile.Navigator = function( history ) {\n
+\t\tthis.history = history;\n
+\t\tthis.ignoreInitialHashChange = true;\n
+\n
+\t\t$.mobile.window.bind({\n
+\t\t\t"popstate.history": $.proxy( this.popstate, this ),\n
+\t\t\t"hashchange.history": $.proxy( this.hashchange, this )\n
+\t\t});\n
+\t};\n
+\n
+\t$.extend($.mobile.Navigator.prototype, {\n
+\t\tsquash: function( url, data ) {\n
+\t\t\tvar state, href, hash = path.isPath(url) ? path.stripHash(url) : url;\n
+\n
+\t\t\thref = path.squash( url );\n
+\n
+\t\t\t// make sure to provide this information when it isn\'t explicitly set in the\n
+\t\t\t// data object that was passed to the squash method\n
+\t\t\tstate = $.extend({\n
+\t\t\t\thash: hash,\n
+\t\t\t\turl: href\n
+\t\t\t}, data);\n
+\n
+\t\t\t// replace the current url with the new href and store the state\n
+\t\t\t// Note that in some cases we might be replacing an url with the\n
+\t\t\t// same url. We do this anyways because we need to make sure that\n
+\t\t\t// all of our history entries have a state object associated with\n
+\t\t\t// them. This allows us to work around the case where $.mobile.back()\n
+\t\t\t// is called to transition from an external page to an embedded page.\n
+\t\t\t// In that particular case, a hashchange event is *NOT* generated by the browser.\n
+\t\t\t// Ensuring each history entry has a state object means that onPopState()\n
+\t\t\t// will always trigger our hashchange callback even when a hashchange event\n
+\t\t\t// is not fired.\n
+\t\t\twindow.history.replaceState( state, state.title || document.title, href );\n
+\n
+\t\t\treturn state;\n
+\t\t},\n
+\n
+\t\thash: function( url, href ) {\n
+\t\t\tvar parsed, loc, hash, resolved;\n
+\n
+\t\t\t// Grab the hash for recording. If the passed url is a path\n
+\t\t\t// we used the parsed version of the squashed url to reconstruct,\n
+\t\t\t// otherwise we assume it\'s a hash and store it directly\n
+\t\t\tparsed = path.parseUrl( url );\n
+\t\t\tloc = path.parseLocation();\n
+\n
+\t\t\tif ( loc.pathname + loc.search === parsed.pathname + parsed.search ) {\n
+\t\t\t\t// If the pathname and search of the passed url is identical to the current loc\n
+\t\t\t\t// then we must use the hash. Otherwise there will be no event\n
+\t\t\t\t// eg, url = "/foo/bar?baz#bang", location.href = "http://example.com/foo/bar?baz"\n
+\t\t\t\thash = parsed.hash ? parsed.hash : parsed.pathname + parsed.search;\n
+\t\t\t} else if ( path.isPath(url) ) {\n
+\t\t\t\tresolved = path.parseUrl( href );\n
+\t\t\t\t// If the passed url is a path, make it domain relative and remove any trailing hash\n
+\t\t\t\thash = resolved.pathname + resolved.search + (path.isPreservableHash( resolved.hash )? resolved.hash.replace( "#", "" ) : "");\n
+\t\t\t} else {\n
+\t\t\t\thash = url;\n
+\t\t\t}\n
+\n
+\t\t\treturn hash;\n
+\t\t},\n
+\n
+\t\t// TODO reconsider name\n
+\t\tgo: function( url, data, noEvents ) {\n
+\t\t\tvar state, href, hash, popstateEvent,\n
+\t\t\t\tisPopStateEvent = $.event.special.navigate.isPushStateEnabled();\n
+\n
+\t\t\t// Get the url as it would look squashed on to the current resolution url\n
+\t\t\thref = path.squash( url );\n
+\n
+\t\t\t// sort out what the hash sould be from the url\n
+\t\t\thash = this.hash( url, href );\n
+\n
+\t\t\t// Here we prevent the next hash change or popstate event from doing any\n
+\t\t\t// history management. In the case of hashchange we don\'t swallow it\n
+\t\t\t// if there will be no hashchange fired (since that won\'t reset the value)\n
+\t\t\t// and will swallow the following hashchange\n
+\t\t\tif ( noEvents && hash !== path.stripHash(path.parseLocation().hash) ) {\n
+\t\t\t\tthis.preventNextHashChange = noEvents;\n
+\t\t\t}\n
+\n
+\t\t\t// IMPORTANT in the case where popstate is supported the event will be triggered\n
+\t\t\t//      directly, stopping further execution - ie, interupting the flow of this\n
+\t\t\t//      method call to fire bindings at this expression. Below the navigate method\n
+\t\t\t//      there is a binding to catch this event and stop its propagation.\n
+\t\t\t//\n
+\t\t\t//      We then trigger a new popstate event on the window with a null state\n
+\t\t\t//      so that the navigate events can conclude their work properly\n
+\t\t\t//\n
+\t\t\t// if the url is a path we want to preserve the query params that are available on\n
+\t\t\t// the current url.\n
+\t\t\tthis.preventHashAssignPopState = true;\n
+\t\t\twindow.location.hash = hash;\n
+\n
+\t\t\t// If popstate is enabled and the browser triggers `popstate` events when the hash\n
+\t\t\t// is set (this often happens immediately in browsers like Chrome), then the\n
+\t\t\t// this flag will be set to false already. If it\'s a browser that does not trigger\n
+\t\t\t// a `popstate` on hash assignement or `replaceState` then we need avoid the branch\n
+\t\t\t// that swallows the event created by the popstate generated by the hash assignment\n
+\t\t\t// At the time of this writing this happens with Opera 12 and some version of IE\n
+\t\t\tthis.preventHashAssignPopState = false;\n
+\n
+\t\t\tstate = $.extend({\n
+\t\t\t\turl: href,\n
+\t\t\t\thash: hash,\n
+\t\t\t\ttitle: document.title\n
+\t\t\t}, data);\n
+\n
+\t\t\tif ( isPopStateEvent ) {\n
+\t\t\t\tpopstateEvent = new $.Event( "popstate" );\n
+\t\t\t\tpopstateEvent.originalEvent = {\n
+\t\t\t\t\ttype: "popstate",\n
+\t\t\t\t\tstate: null\n
+\t\t\t\t};\n
+\n
+\t\t\t\tthis.squash( url, state );\n
+\n
+\t\t\t\t// Trigger a new faux popstate event to replace the one that we\n
+\t\t\t\t// caught that was triggered by the hash setting above.\n
+\t\t\t\tif ( !noEvents ) {\n
+\t\t\t\t\tthis.ignorePopState = true;\n
+\t\t\t\t\t$.mobile.window.trigger( popstateEvent );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// record the history entry so that the information can be included\n
+\t\t\t// in hashchange event driven navigate events in a similar fashion to\n
+\t\t\t// the state that\'s provided by popstate\n
+\t\t\tthis.history.add( state.url, state );\n
+\t\t},\n
+\n
+\n
+\t\t// This binding is intended to catch the popstate events that are fired\n
+\t\t// when execution of the `$.navigate` method stops at window.location.hash = url;\n
+\t\t// and completely prevent them from propagating. The popstate event will then be\n
+\t\t// retriggered after execution resumes\n
+\t\t//\n
+\t\t// TODO grab the original event here and use it for the synthetic event in the\n
+\t\t//      second half of the navigate execution that will follow this binding\n
+\t\tpopstate: function( event ) {\n
+\t\t\tvar hash, state;\n
+\n
+\t\t\t// Partly to support our test suite which manually alters the support\n
+\t\t\t// value to test hashchange. Partly to prevent all around weirdness\n
+\t\t\tif ( !$.event.special.navigate.isPushStateEnabled() ){\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// If this is the popstate triggered by the actual alteration of the hash\n
+\t\t\t// prevent it completely. History is tracked manually\n
+\t\t\tif ( this.preventHashAssignPopState ) {\n
+\t\t\t\tthis.preventHashAssignPopState = false;\n
+\t\t\t\tevent.stopImmediatePropagation();\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// if this is the popstate triggered after the `replaceState` call in the go\n
+\t\t\t// method, then simply ignore it. The history entry has already been captured\n
+\t\t\tif ( this.ignorePopState ) {\n
+\t\t\t\tthis.ignorePopState = false;\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// If there is no state, and the history stack length is one were\n
+\t\t\t// probably getting the page load popstate fired by browsers like chrome\n
+\t\t\t// avoid it and set the one time flag to false.\n
+\t\t\t// TODO: Do we really need all these conditions? Comparing location hrefs\n
+\t\t\t// should be sufficient.\n
+\t\t\tif ( !event.originalEvent.state &&\n
+\t\t\t\tthis.history.stack.length === 1 &&\n
+\t\t\t\tthis.ignoreInitialHashChange ) {\n
+\t\t\t\tthis.ignoreInitialHashChange = false;\n
+\n
+\t\t\t\tif ( location.href === initialHref ) {\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// account for direct manipulation of the hash. That is, we will receive a popstate\n
+\t\t\t// when the hash is changed by assignment, and it won\'t have a state associated. We\n
+\t\t\t// then need to squash the hash. See below for handling of hash assignment that\n
+\t\t\t// matches an existing history entry\n
+\t\t\t// TODO it might be better to only add to the history stack\n
+\t\t\t//      when the hash is adjacent to the active history entry\n
+\t\t\thash = path.parseLocation().hash;\n
+\t\t\tif ( !event.originalEvent.state && hash ) {\n
+\t\t\t\t// squash the hash that\'s been assigned on the URL with replaceState\n
+\t\t\t\t// also grab the resulting state object for storage\n
+\t\t\t\tstate = this.squash( hash );\n
+\n
+\t\t\t\t// record the new hash as an additional history entry\n
+\t\t\t\t// to match the browser\'s treatment of hash assignment\n
+\t\t\t\tthis.history.add( state.url, state );\n
+\n
+\t\t\t\t// pass the newly created state information\n
+\t\t\t\t// along with the event\n
+\t\t\t\tevent.historyState = state;\n
+\n
+\t\t\t\t// do not alter history, we\'ve added a new history entry\n
+\t\t\t\t// so we know where we are\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// If all else fails this is a popstate that comes from the back or forward buttons\n
+\t\t\t// make sure to set the state of our history stack properly, and record the directionality\n
+\t\t\tthis.history.direct({\n
+\t\t\t\turl: (event.originalEvent.state || {}).url || hash,\n
+\n
+\t\t\t\t// When the url is either forward or backward in history include the entry\n
+\t\t\t\t// as data on the event object for merging as data in the navigate event\n
+\t\t\t\tpresent: function( historyEntry, direction ) {\n
+\t\t\t\t\t// make sure to create a new object to pass down as the navigate event data\n
+\t\t\t\t\tevent.historyState = $.extend({}, historyEntry);\n
+\t\t\t\t\tevent.historyState.direction = direction;\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t},\n
+\n
+\t\t// NOTE must bind before `navigate` special event hashchange binding otherwise the\n
+\t\t//      navigation data won\'t be attached to the hashchange event in time for those\n
+\t\t//      bindings to attach it to the `navigate` special event\n
+\t\t// TODO add a check here that `hashchange.navigate` is bound already otherwise it\'s\n
+\t\t//      broken (exception?)\n
+\t\thashchange: function( event ) {\n
+\t\t\tvar history, hash;\n
+\n
+\t\t\t// If hashchange listening is explicitly disabled or pushstate is supported\n
+\t\t\t// avoid making use of the hashchange handler.\n
+\t\t\tif (!$.event.special.navigate.isHashChangeEnabled() ||\n
+\t\t\t\t$.event.special.navigate.isPushStateEnabled() ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// On occasion explicitly want to prevent the next hash from propogating because we only\n
+\t\t\t// with to alter the url to represent the new state do so here\n
+\t\t\tif ( this.preventNextHashChange ){\n
+\t\t\t\tthis.preventNextHashChange = false;\n
+\t\t\t\tevent.stopImmediatePropagation();\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\thistory = this.history;\n
+\t\t\thash = path.parseLocation().hash;\n
+\n
+\t\t\t// If this is a hashchange caused by the back or forward button\n
+\t\t\t// make sure to set the state of our history stack properly\n
+\t\t\tthis.history.direct({\n
+\t\t\t\turl: hash,\n
+\n
+\t\t\t\t// When the url is either forward or backward in history include the entry\n
+\t\t\t\t// as data on the event obj
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="3" aka="AAAAAAAAAAM=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+ect for merging as data in the navigate event\n
+\t\t\t\tpresent: function( historyEntry, direction ) {\n
+\t\t\t\t\t// make sure to create a new object to pass down as the navigate event data\n
+\t\t\t\t\tevent.hashchangeState = $.extend({}, historyEntry);\n
+\t\t\t\t\tevent.hashchangeState.direction = direction;\n
+\t\t\t\t},\n
+\n
+\t\t\t\t// When we don\'t find a hash in our history clearly we\'re aiming to go there\n
+\t\t\t\t// record the entry as new for future traversal\n
+\t\t\t\t//\n
+\t\t\t\t// NOTE it\'s not entirely clear that this is the right thing to do given that we\n
+\t\t\t\t//      can\'t know the users intention. It might be better to explicitly _not_\n
+\t\t\t\t//      support location.hash assignment in preference to $.navigate calls\n
+\t\t\t\t// TODO first arg to add should be the href, but it causes issues in identifying\n
+\t\t\t\t//      embeded pages\n
+\t\t\t\tmissing: function() {\n
+\t\t\t\t\thistory.add( hash, {\n
+\t\t\t\t\t\thash: hash,\n
+\t\t\t\t\t\ttitle: document.title\n
+\t\t\t\t\t});\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t}\n
+\t});\n
+})( jQuery );\n
+\n
+\n
+\n
+(function( $, undefined ) {\n
+\t// TODO consider queueing navigation activity until previous activities have completed\n
+\t//      so that end users don\'t have to think about it. Punting for now\n
+\t// TODO !! move the event bindings into callbacks on the navigate event\n
+\t$.mobile.navigate = function( url, data, noEvents ) {\n
+\t\t$.mobile.navigate.navigator.go( url, data, noEvents );\n
+\t};\n
+\n
+\t// expose the history on the navigate method in anticipation of full integration with\n
+\t// existing navigation functionalty that is tightly coupled to the history information\n
+\t$.mobile.navigate.history = new $.mobile.History();\n
+\n
+\t// instantiate an instance of the navigator for use within the $.navigate method\n
+\t$.mobile.navigate.navigator = new $.mobile.Navigator( $.mobile.navigate.history );\n
+\n
+\tvar loc = $.mobile.path.parseLocation();\n
+\t$.mobile.navigate.history.add( loc.href, {hash: loc.hash} );\n
+})( jQuery );\n
+\n
+\n
+// This plugin is an experiment for abstracting away the touch and mouse\n
+// events so that developers don\'t have to worry about which method of input\n
+// the device their document is loaded on supports.\n
+//\n
+// The idea here is to allow the developer to register listeners for the\n
+// basic mouse events, such as mousedown, mousemove, mouseup, and click,\n
+// and the plugin will take care of registering the correct listeners\n
+// behind the scenes to invoke the listener at the fastest possible time\n
+// for that device, while still retaining the order of event firing in\n
+// the traditional mouse environment, should multiple handlers be registered\n
+// on the same element for different events.\n
+//\n
+// The current version exposes the following virtual events to jQuery bind methods:\n
+// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel"\n
+\n
+(function( $, window, document, undefined ) {\n
+\n
+var dataPropertyName = "virtualMouseBindings",\n
+\ttouchTargetPropertyName = "virtualTouchID",\n
+\tvirtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ),\n
+\ttouchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ),\n
+\tmouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [],\n
+\tmouseEventProps = $.event.props.concat( mouseHookProps ),\n
+\tactiveDocHandlers = {},\n
+\tresetTimerID = 0,\n
+\tstartX = 0,\n
+\tstartY = 0,\n
+\tdidScroll = false,\n
+\tclickBlockList = [],\n
+\tblockMouseTriggers = false,\n
+\tblockTouchTriggers = false,\n
+\teventCaptureSupported = "addEventListener" in document,\n
+\t$document = $( document ),\n
+\tnextTouchID = 1,\n
+\tlastTouchID = 0, threshold,\n
+\ti;\n
+\n
+$.vmouse = {\n
+\tmoveDistanceThreshold: 10,\n
+\tclickDistanceThreshold: 10,\n
+\tresetTimerDuration: 1500\n
+};\n
+\n
+function getNativeEvent( event ) {\n
+\n
+\twhile ( event && typeof event.originalEvent !== "undefined" ) {\n
+\t\tevent = event.originalEvent;\n
+\t}\n
+\treturn event;\n
+}\n
+\n
+function createVirtualEvent( event, eventType ) {\n
+\n
+\tvar t = event.type,\n
+\t\toe, props, ne, prop, ct, touch, i, j, len;\n
+\n
+\tevent = $.Event( event );\n
+\tevent.type = eventType;\n
+\n
+\toe = event.originalEvent;\n
+\tprops = $.event.props;\n
+\n
+\t// addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280\n
+\t// https://github.com/jquery/jquery-mobile/issues/3280\n
+\tif ( t.search( /^(mouse|click)/ ) > -1 ) {\n
+\t\tprops = mouseEventProps;\n
+\t}\n
+\n
+\t// copy original event properties over to the new event\n
+\t// this would happen if we could call $.event.fix instead of $.Event\n
+\t// but we don\'t have a way to force an event to be fixed multiple times\n
+\tif ( oe ) {\n
+\t\tfor ( i = props.length, prop; i; ) {\n
+\t\t\tprop = props[ --i ];\n
+\t\t\tevent[ prop ] = oe[ prop ];\n
+\t\t}\n
+\t}\n
+\n
+\t// make sure that if the mouse and click virtual events are generated\n
+\t// without a .which one is defined\n
+\tif ( t.search(/mouse(down|up)|click/) > -1 && !event.which ) {\n
+\t\tevent.which = 1;\n
+\t}\n
+\n
+\tif ( t.search(/^touch/) !== -1 ) {\n
+\t\tne = getNativeEvent( oe );\n
+\t\tt = ne.touches;\n
+\t\tct = ne.changedTouches;\n
+\t\ttouch = ( t && t.length ) ? t[0] : ( ( ct && ct.length ) ? ct[ 0 ] : undefined );\n
+\n
+\t\tif ( touch ) {\n
+\t\t\tfor ( j = 0, len = touchEventProps.length; j < len; j++) {\n
+\t\t\t\tprop = touchEventProps[ j ];\n
+\t\t\t\tevent[ prop ] = touch[ prop ];\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\treturn event;\n
+}\n
+\n
+function getVirtualBindingFlags( element ) {\n
+\n
+\tvar flags = {},\n
+\t\tb, k;\n
+\n
+\twhile ( element ) {\n
+\n
+\t\tb = $.data( element, dataPropertyName );\n
+\n
+\t\tfor (  k in b ) {\n
+\t\t\tif ( b[ k ] ) {\n
+\t\t\t\tflags[ k ] = flags.hasVirtualBinding = true;\n
+\t\t\t}\n
+\t\t}\n
+\t\telement = element.parentNode;\n
+\t}\n
+\treturn flags;\n
+}\n
+\n
+function getClosestElementWithVirtualBinding( element, eventType ) {\n
+\tvar b;\n
+\twhile ( element ) {\n
+\n
+\t\tb = $.data( element, dataPropertyName );\n
+\n
+\t\tif ( b && ( !eventType || b[ eventType ] ) ) {\n
+\t\t\treturn element;\n
+\t\t}\n
+\t\telement = element.parentNode;\n
+\t}\n
+\treturn null;\n
+}\n
+\n
+function enableTouchBindings() {\n
+\tblockTouchTriggers = false;\n
+}\n
+\n
+function disableTouchBindings() {\n
+\tblockTouchTriggers = true;\n
+}\n
+\n
+function enableMouseBindings() {\n
+\tlastTouchID = 0;\n
+\tclickBlockList.length = 0;\n
+\tblockMouseTriggers = false;\n
+\n
+\t// When mouse bindings are enabled, our\n
+\t// touch bindings are disabled.\n
+\tdisableTouchBindings();\n
+}\n
+\n
+function disableMouseBindings() {\n
+\t// When mouse bindings are disabled, our\n
+\t// touch bindings are enabled.\n
+\tenableTouchBindings();\n
+}\n
+\n
+function startResetTimer() {\n
+\tclearResetTimer();\n
+\tresetTimerID = setTimeout( function() {\n
+\t\tresetTimerID = 0;\n
+\t\tenableMouseBindings();\n
+\t}, $.vmouse.resetTimerDuration );\n
+}\n
+\n
+function clearResetTimer() {\n
+\tif ( resetTimerID ) {\n
+\t\tclearTimeout( resetTimerID );\n
+\t\tresetTimerID = 0;\n
+\t}\n
+}\n
+\n
+function triggerVirtualEvent( eventType, event, flags ) {\n
+\tvar ve;\n
+\n
+\tif ( ( flags && flags[ eventType ] ) ||\n
+\t\t\t\t( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {\n
+\n
+\t\tve = createVirtualEvent( event, eventType );\n
+\n
+\t\t$( event.target).trigger( ve );\n
+\t}\n
+\n
+\treturn ve;\n
+}\n
+\n
+function mouseEventCallback( event ) {\n
+\tvar touchID = $.data( event.target, touchTargetPropertyName ),\n
+\t\tve;\n
+\n
+\tif ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ) {\n
+\t\tve = triggerVirtualEvent( "v" + event.type, event );\n
+\t\tif ( ve ) {\n
+\t\t\tif ( ve.isDefaultPrevented() ) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t}\n
+\t\t\tif ( ve.isPropagationStopped() ) {\n
+\t\t\t\tevent.stopPropagation();\n
+\t\t\t}\n
+\t\t\tif ( ve.isImmediatePropagationStopped() ) {\n
+\t\t\t\tevent.stopImmediatePropagation();\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+}\n
+\n
+function handleTouchStart( event ) {\n
+\n
+\tvar touches = getNativeEvent( event ).touches,\n
+\t\ttarget, flags, t;\n
+\n
+\tif ( touches && touches.length === 1 ) {\n
+\n
+\t\ttarget = event.target;\n
+\t\tflags = getVirtualBindingFlags( target );\n
+\n
+\t\tif ( flags.hasVirtualBinding ) {\n
+\n
+\t\t\tlastTouchID = nextTouchID++;\n
+\t\t\t$.data( target, touchTargetPropertyName, lastTouchID );\n
+\n
+\t\t\tclearResetTimer();\n
+\n
+\t\t\tdisableMouseBindings();\n
+\t\t\tdidScroll = false;\n
+\n
+\t\t\tt = getNativeEvent( event ).touches[ 0 ];\n
+\t\t\tstartX = t.pageX;\n
+\t\t\tstartY = t.pageY;\n
+\n
+\t\t\ttriggerVirtualEvent( "vmouseover", event, flags );\n
+\t\t\ttriggerVirtualEvent( "vmousedown", event, flags );\n
+\t\t}\n
+\t}\n
+}\n
+\n
+function handleScroll( event ) {\n
+\tif ( blockTouchTriggers ) {\n
+\t\treturn;\n
+\t}\n
+\n
+\tif ( !didScroll ) {\n
+\t\ttriggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) );\n
+\t}\n
+\n
+\tdidScroll = true;\n
+\tstartResetTimer();\n
+}\n
+\n
+function handleTouchMove( event ) {\n
+\tif ( blockTouchTriggers ) {\n
+\t\treturn;\n
+\t}\n
+\n
+\tvar t = getNativeEvent( event ).touches[ 0 ],\n
+\t\tdidCancel = didScroll,\n
+\t\tmoveThreshold = $.vmouse.moveDistanceThreshold,\n
+\t\tflags = getVirtualBindingFlags( event.target );\n
+\n
+\t\tdidScroll = didScroll ||\n
+\t\t\t( Math.abs( t.pageX - startX ) > moveThreshold ||\n
+\t\t\t\tMath.abs( t.pageY - startY ) > moveThreshold );\n
+\n
+\n
+\tif ( didScroll && !didCancel ) {\n
+\t\ttriggerVirtualEvent( "vmousecancel", event, flags );\n
+\t}\n
+\n
+\ttriggerVirtualEvent( "vmousemove", event, flags );\n
+\tstartResetTimer();\n
+}\n
+\n
+function handleTouchEnd( event ) {\n
+\tif ( blockTouchTriggers ) {\n
+\t\treturn;\n
+\t}\n
+\n
+\tdisableTouchBindings();\n
+\n
+\tvar flags = getVirtualBindingFlags( event.target ),\n
+\t\tve, t;\n
+\ttriggerVirtualEvent( "vmouseup", event, flags );\n
+\n
+\tif ( !didScroll ) {\n
+\t\tve = triggerVirtualEvent( "vclick", event, flags );\n
+\t\tif ( ve && ve.isDefaultPrevented() ) {\n
+\t\t\t// The target of the mouse events that follow the touchend\n
+\t\t\t// event don\'t necessarily match the target used during the\n
+\t\t\t// touch. This means we need to rely on coordinates for blocking\n
+\t\t\t// any click that is generated.\n
+\t\t\tt = getNativeEvent( event ).changedTouches[ 0 ];\n
+\t\t\tclickBlockList.push({\n
+\t\t\t\ttouchID: lastTouchID,\n
+\t\t\t\tx: t.clientX,\n
+\t\t\t\ty: t.clientY\n
+\t\t\t});\n
+\n
+\t\t\t// Prevent any mouse events that follow from triggering\n
+\t\t\t// virtual event notifications.\n
+\t\t\tblockMouseTriggers = true;\n
+\t\t}\n
+\t}\n
+\ttriggerVirtualEvent( "vmouseout", event, flags);\n
+\tdidScroll = false;\n
+\n
+\tstartResetTimer();\n
+}\n
+\n
+function hasVirtualBindings( ele ) {\n
+\tvar bindings = $.data( ele, dataPropertyName ),\n
+\t\tk;\n
+\n
+\tif ( bindings ) {\n
+\t\tfor ( k in bindings ) {\n
+\t\t\tif ( bindings[ k ] ) {\n
+\t\t\t\treturn true;\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\treturn false;\n
+}\n
+\n
+function dummyMouseHandler() {}\n
+\n
+function getSpecialEventObject( eventType ) {\n
+\tvar realType = eventType.substr( 1 );\n
+\n
+\treturn {\n
+\t\tsetup: function(/* data, namespace */) {\n
+\t\t\t// If this is the first virtual mouse binding for this element,\n
+\t\t\t// add a bindings object to its data.\n
+\n
+\t\t\tif ( !hasVirtualBindings( this ) ) {\n
+\t\t\t\t$.data( this, dataPropertyName, {} );\n
+\t\t\t}\n
+\n
+\t\t\t// If setup is called, we know it is the first binding for this\n
+\t\t\t// eventType, so initialize the count for the eventType to zero.\n
+\t\t\tvar bindings = $.data( this, dataPropertyName );\n
+\t\t\tbindings[ eventType ] = true;\n
+\n
+\t\t\t// If this is the first virtual mouse event for this type,\n
+\t\t\t// register a global handler on the document.\n
+\n
+\t\t\tactiveDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;\n
+\n
+\t\t\tif ( activeDocHandlers[ eventType ] === 1 ) {\n
+\t\t\t\t$document.bind( realType, mouseEventCallback );\n
+\t\t\t}\n
+\n
+\t\t\t// Some browsers, like Opera Mini, won\'t dispatch mouse/click events\n
+\t\t\t// for elements unless they actually have handlers registered on them.\n
+\t\t\t// To get around this, we register dummy handlers on the elements.\n
+\n
+\t\t\t$( this ).bind( realType, dummyMouseHandler );\n
+\n
+\t\t\t// For now, if event capture is not supported, we rely on mouse handlers.\n
+\t\t\tif ( eventCaptureSupported ) {\n
+\t\t\t\t// If this is the first virtual mouse binding for the document,\n
+\t\t\t\t// register our touchstart handler on the document.\n
+\n
+\t\t\t\tactiveDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0) + 1;\n
+\n
+\t\t\t\tif ( activeDocHandlers[ "touchstart" ] === 1 ) {\n
+\t\t\t\t\t$document.bind( "touchstart", handleTouchStart )\n
+\t\t\t\t\t\t.bind( "touchend", handleTouchEnd )\n
+\n
+\t\t\t\t\t\t// On touch platforms, touching the screen and then dragging your finger\n
+\t\t\t\t\t\t// causes the window content to scroll after some distance threshold is\n
+\t\t\t\t\t\t// exceeded. On these platforms, a scroll prevents a click event from being\n
+\t\t\t\t\t\t// dispatched, and on some platforms, even the touchend is suppressed. To\n
+\t\t\t\t\t\t// mimic the suppression of the click event, we need to watch for a scroll\n
+\t\t\t\t\t\t// event. Unfortunately, some platforms like iOS don\'t dispatch scroll\n
+\t\t\t\t\t\t// events until *AFTER* the user lifts their finger (touchend). This means\n
+\t\t\t\t\t\t// we need to watch both scroll and touchmove events to figure out whether\n
+\t\t\t\t\t\t// or not a scroll happenens before the touchend event is fired.\n
+\n
+\t\t\t\t\t\t.bind( "touchmove", handleTouchMove )\n
+\t\t\t\t\t\t.bind( "scroll", handleScroll );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\tteardown: function(/* data, namespace */) {\n
+\t\t\t// If this is the last virtual binding for this eventType,\n
+\t\t\t// remove its global handler from the document.\n
+\n
+\t\t\t--activeDocHandlers[ eventType ];\n
+\n
+\t\t\tif ( !activeDocHandlers[ eventType ] ) {\n
+\t\t\t\t$document.unbind( realType, mouseEventCallback );\n
+\t\t\t}\n
+\n
+\t\t\tif ( eventCaptureSupported ) {\n
+\t\t\t\t// If this is the last virtual mouse binding in existence,\n
+\t\t\t\t// remove our document touchstart listener.\n
+\n
+\t\t\t\t--activeDocHandlers[ "touchstart" ];\n
+\n
+\t\t\t\tif ( !activeDocHandlers[ "touchstart" ] ) {\n
+\t\t\t\t\t$document.unbind( "touchstart", handleTouchStart )\n
+\t\t\t\t\t\t.unbind( "touchmove", handleTouchMove )\n
+\t\t\t\t\t\t.unbind( "touchend", handleTouchEnd )\n
+\t\t\t\t\t\t.unbind( "scroll", handleScroll );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tvar $this = $( this ),\n
+\t\t\t\tbindings = $.data( this, dataPropertyName );\n
+\n
+\t\t\t// teardown may be called when an element was\n
+\t\t\t// removed from the DOM. If this is the case,\n
+\t\t\t// jQuery core may have already stripped the element\n
+\t\t\t// of any data bindings so we need to check it before\n
+\t\t\t// using it.\n
+\t\t\tif ( bindings ) {\n
+\t\t\t\tbindings[ eventType ] = false;\n
+\t\t\t}\n
+\n
+\t\t\t// Unregister the dummy event handler.\n
+\n
+\t\t\t$this.unbind( realType, dummyMouseHandler );\n
+\n
+\t\t\t// If this is the last virtual mouse binding on the\n
+\t\t\t// element, remove the binding data from the element.\n
+\n
+\t\t\tif ( !hasVirtualBindings( this ) ) {\n
+\t\t\t\t$this.removeData( dataPropertyName );\n
+\t\t\t}\n
+\t\t}\n
+\t};\n
+}\n
+\n
+// Expose our custom events to the jQuery bind/unbind mechanism.\n
+\n
+for ( i = 0; i < virtualEventNames.length; i++ ) {\n
+\t$.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );\n
+}\n
+\n
+// Add a capture click handler to block clicks.\n
+// Note that we require event capture support for this so if the device\n
+// doesn\'t support it, we punt for now and rely solely on mouse events.\n
+if ( eventCaptureSupported ) {\n
+\tdocument.addEventListener( "click", function( e ) {\n
+\t\tvar cnt = clickBlockList.length,\n
+\t\t\ttarget = e.target,\n
+\t\t\tx, y, ele, i, o, touchID;\n
+\n
+\t\tif ( cnt ) {\n
+\t\t\tx = e.clientX;\n
+\t\t\ty = e.clientY;\n
+\t\t\tthreshold = $.vmouse.clickDistanceThreshold;\n
+\n
+\t\t\t// The idea here is to run through the clickBlockList to see if\n
+\t\t\t// the current click event is in the proximity of one of our\n
+\t\t\t// vclick events that had preventDefault() called on it. If we find\n
+\t\t\t// one, then we block the click.\n
+\t\t\t//\n
+\t\t\t// Why do we have to rely on proximity?\n
+\t\t\t//\n
+\t\t\t// Because the target of the touch event that triggered the vclick\n
+\t\t\t// can be different from the target of the click event synthesized\n
+\t\t\t// by the browser. The target of a mouse/click event that is syntehsized\n
+\t\t\t// from a touch event seems to be implementation specific. For example,\n
+\t\t\t// some browsers will fire mouse/click events for a link that is near\n
+\t\t\t// a touch event, even though the target of the touchstart/touchend event\n
+\t\t\t// says the user touched outside the link. Also, it seems that with most\n
+\t\t\t// browsers, the target of the mouse/click event is not calculated until the\n
+\t\t\t// time it is dispatched, so if you replace an element that you touched\n
+\t\t\t// with another element, the target of the mouse/click will be the new\n
+\t\t\t// element underneath that point.\n
+\t\t\t//\n
+\t\t\t// Aside from proximity, we also check to see if the target and any\n
+\t\t\t// of its ancestors were the ones that blocked a click. This is necessary\n
+\t\t\t// because of the strange mouse/click target calculation done in the\n
+\t\t\t// Android 2.1 browser, where if you click on an element, and there is a\n
+\t\t\t// mouse/click handler on one of its ancestors, the target will be the\n
+\t\t\t// innermost child of the touched element, even if that child is no where\n
+\t\t\t// near the point of touch.\n
+\n
+\t\t\tele = target;\n
+\n
+\t\t\twhile ( ele ) {\n
+\t\t\t\tfor ( i = 0; i < cnt; i++ ) {\n
+\t\t\t\t\to = clickBlockList[ i ];\n
+\t\t\t\t\ttouchID = 0;\n
+\n
+\t\t\t\t\tif ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||\n
+\t\t\t\t\t\t\t\t$.data( ele, touchTargetPropertyName ) === o.touchID ) {\n
+\t\t\t\t\t\t// XXX: We may want to consider removing matches from the block list\n
+\t\t\t\t\t\t//      instead of waiting for the reset timer to fire.\n
+\t\t\t\t\t\te.preventDefault();\n
+\t\t\t\t\t\te.stopPropagation();\n
+\t\t\t\t\t\treturn;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t\tele = ele.parentNode;\n
+\t\t\t}\n
+\t\t}\n
+\t}, true);\n
+}\n
+})( jQuery, window, document );\n
+\n
+\n
+(function( $, window, undefined ) {\n
+\tvar $document = $( document ),\n
+\t\tsupportTouch = $.mobile.support.touch,\n
+\t\tscrollEvent = "touchmove scroll",\n
+\t\ttouchStartEvent = supportTouch ? "touchstart" : "mousedown",\n
+\t\ttouchStopEvent = supportTouch ? "touchend" : "mouseup",\n
+\t\ttouchMoveEvent = supportTouch ? "touchmove" : "mousemove";\n
+\n
+\t// setup new event shortcuts\n
+\t$.each( ( "touchstart touchmove touchend " +\n
+\t\t"tap taphold " +\n
+\t\t"swipe swipeleft swiperight " +\n
+\t\t"scrollstart scrollstop" ).split( " " ), function( i, name ) {\n
+\n
+\t\t$.fn[ name ] = function( fn ) {\n
+\t\t\treturn fn ? this.bind( name, fn ) : this.trigger( name );\n
+\t\t};\n
+\n
+\t\t// jQuery < 1.8\n
+\t\tif ( $.attrFn ) {\n
+\t\t\t$.attrFn[ name ] = true;\n
+\t\t}\n
+\t});\n
+\n
+\tfunction triggerCustomEvent( obj, eventType, event ) {\n
+\t\tvar originalType = event.type;\n
+\t\tevent.type = eventType;\n
+\t\t$.event.dispatch.call( obj, event );\n
+\t\tevent.type = originalType;\n
+\t}\n
+\n
+\t// also handles scrollstop\n
+\t$.event.special.scrollstart = {\n
+\n
+\t\tenabled: true,\n
+\t\tsetup: function() {\n
+\n
+\t\t\tvar thisObject = this,\n
+\t\t\t\t$this = $( thisObject ),\n
+\t\t\t\tscrolling,\n
+\t\t\t\ttimer;\n
+\n
+\t\t\tfunction trigger( event, state ) {\n
+\t\t\t\tscrolling = state;\n
+\t\t\t\ttriggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event );\n
+\t\t\t}\n
+\n
+\t\t\t// iPhone triggers scroll after a small delay; use touchmove instead\n
+\t\t\t$this.bind( scrollEvent, function( event ) {\n
+\n
+\t\t\t\tif ( !$.event.special.scrollstart.enabled ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif ( !scrolling ) {\n
+\t\t\t\t\ttrigger( event, true );\n
+\t\t\t\t}\n
+\n
+\t\t\t\tclearTimeout( timer );\n
+\t\t\t\ttimer = setTimeout( function() {\n
+\t\t\t\t\ttrigger( event, false );\n
+\t\t\t\t}, 50 );\n
+\t\t\t});\n
+\t\t},\n
+\t\tteardown: function() {\n
+\t\t\t$( this ).unbind( scrollEvent );\n
+\t\t}\n
+\t};\n
+\n
+\t// also handles taphold\n
+\t$.event.special.tap = {\n
+\t\ttapholdThreshold: 750,\n
+\t\temitTapOnTaphold: true,\n
+\t\tsetup: function() {\n
+\t\t\tvar thisObject = this,\n
+\t\t\t\t$this = $( thisObject ),\n
+\t\t\t\tisTaphold = false;\n
+\n
+\t\t\t$this.bind( "vmousedown", function( event ) {\n
+\t\t\t\tisTaphold = false;\n
+\t\t\t\tif ( event.which && event.which !== 1 ) {\n
+\t\t\t\t\treturn false;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tvar origTarget = event.target,\n
+\t\t\t\t\ttimer;\n
+\n
+\t\t\t\tfunction clearTapTimer() {\n
+\t\t\t\t\tclearTimeout( timer );\n
+\t\t\t\t}\n
+\n
+\t\t\t\tfunction clearTapHandlers() {\n
+\t\t\t\t\tclearTapTimer();\n
+\n
+\t\t\t\t\t$this.unbind( "vclick", clickHandler )\n
+\t\t\t\t\t\t.unbind( "vmouseup", clearTapTimer );\n
+\t\t\t\t\t$document.unbind( "vmousecancel", clearTapHandlers );\n
+\t\t\t\t}\n
+\n
+\t\t\t\tfunction clickHandler( event ) {\n
+\t\t\t\t\tclearTapHandlers();\n
+\n
+\t\t\t\t\t// ONLY trigger a \'tap\' event if the start target is\n
+\t\t\t\t\t// the same as the stop target.\n
+\t\t\t\t\tif ( !isTaphold && origTarget === event.target ) {\n
+\t\t\t\t\t\ttriggerCustomEvent( thisObject, "tap", event );\n
+\t\t\t\t\t} else if ( isTaphold ) {\n
+\t\t\t\t\t\tevent.stopPropagation();\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\t$this.bind( "vmouseup", clearTapTimer )\n
+\t\t\t\t\t.bind( "vclick", clickHandler );\n
+\t\t\t\t$document.bind( "vmousecancel", clearTapHandlers );\n
+\n
+\t\t\t\ttimer = setTimeout( function() {\n
+\t\t\t\t\tif ( !$.event.special.tap.emitTapOnTaphold ) {\n
+\t\t\t\t\t\tisTaphold = true;\n
+\t\t\t\t\t}\n
+\t\t\t\t\ttriggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );\n
+\t\t\t\t}, $.event.special.tap.tapholdThreshold );\n
+\t\t\t});\n
+\t\t},\n
+\t\tteardown: function() {\n
+\t\t\t$( this ).unbind( "vmousedown" ).unbind( "vclick" ).unbind( "vmouseup" );\n
+\t\t\t$document.unbind( "vmousecancel" );\n
+\t\t}\n
+\t};\n
+\n
+\t// also handles swipeleft, swiperight\n
+\t$.event.special.swipe = {\n
+\t\tscrollSupressionThreshold: 30, // More than this horizontal displacement, and we will suppress scrolling.\n
+\n
+\t\tdurationThreshold: 1000, // More time than this, and it isn\'t a swipe.\n
+\n
+\t\thorizontalDistanceThreshold: 10,  // Swipe horizontal displacement must be more than this.\n
+\n
+\t\tverticalDistanceThreshold: 75,  // Swipe vertical displacement must be less than this.\n
+\n
+\t\tstart: function( event ) {\n
+\t\t\tvar data = event.originalEvent.touches ?\n
+\t\t\t\t\tevent.originalEvent.touches[ 0 ] : event;\n
+\t\t\treturn {\n
+\t\t\t\t\t\ttime: ( new Date() ).getTime(),\n
+\t\t\t\t\t\tcoords: [ data.pageX, data.pageY ],\n
+\t\t\t\t\t\torigin: $( event.target )\n
+\t\t\t\t\t};\n
+\t\t},\n
+\n
+\t\tstop: function( event ) {\n
+\t\t\tvar data = event.originalEvent.touches ?\n
+\t\t\t\t\tevent.originalEvent.touches[ 0 ] : event;\n
+\t\t\treturn {\n
+\t\t\t\t\t\ttime: ( new Date() ).getTime(),\n
+\t\t\t\t\t\tcoords: [ data.pageX, data.pageY ]\n
+\t\t\t\t\t};\n
+\t\t},\n
+\n
+\t\thandleSwipe: function( start, stop, thisObject, origTarget ) {\n
+\t\t\tif ( stop.time - start.time < $.event.special.swipe.durationThreshold &&\n
+\t\t\t\tMath.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold &&\n
+\t\t\t\tMath.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) {\n
+\t\t\t\tvar direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight";\n
+\n
+\t\t\t\ttriggerCustomEvent( thisObject, "swipe", $.Event( "swipe", { target: origTarget, swipestart: start, swipestop: stop }) );\n
+\t\t\t\ttriggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ) );\n
+\t\t\t\treturn true;\n
+\t\t\t}\n
+\t\t\treturn false;\n
+\n
+\t\t},\n
+\n
+\t\tsetup: function() {\n
+\t\t\tvar thisObject = this,\n
+\t\t\t\t$this = $( thisObject );\n
+\n
+\t\t\t$this.bind( touchStartEvent, function( event ) {\n
+\t\t\t\tvar stop,\n
+\t\t\t\t\tstart = $.event.special.swipe.start( event ),\n
+\t\t\t\t\torigTarget = event.target,\n
+\t\t\t\t\temitted = false;\n
+\n
+\t\t\t\tfunction moveHandler( event ) {\n
+\t\t\t\t\tif ( !start ) {\n
+\t\t\t\t\t\treturn;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tstop = $.event.special.swipe.stop( event );\n
+\t\t\t\t\tif ( !emitted ){\n
+\t\t\t\t\t\temitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget );\n
+\t\t\t\t\t}\n
+\t\t\t\t\t// prevent scrolling\n
+\t\t\t\t\tif ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {\n
+\t\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\t$this.bind( touchMoveEvent, moveHandler )\n
+\t\t\t\t\t.one( touchStopEvent, function() {\n
+\t\t\t\t\t\temitted = true;\n
+\t\t\t\t});\n
+\t\t\t});\n
+\t\t},\n
+\n
+\t\tteardown: function() {\n
+\t\t\t$( this ).unbind( touchStartEvent ).unbind( touchMoveEvent ).unbind( touchStopEvent );\n
+\t\t}\n
+\t};\n
+\t$.each({\n
+\t\tscrollstop: "scrollstart",\n
+\t\ttaphold: "tap",\n
+\t\tswipeleft: "swipe",\n
+\t\tswiperight: "swipe"\n
+\t}, function( event, sourceEvent ) {\n
+\n
+\t\t$.event.special[ event ] = {\n
+\t\t\tsetup: function() {\n
+\t\t\t\t$( this ).bind( sourceEvent, $.noop );\n
+\t\t\t},\n
+\t\t\tteardown: function() {\n
+\t\t\t\t$( this ).unbind( sourceEvent );\n
+\t\t\t}\n
+\t\t};\n
+\t});\n
+\n
+})( jQuery, this );\n
+\n
+\n
+\t// throttled resize event\n
+\t(function( $ ) {\n
+\t\t$.event.special.throttledresize = {\n
+\t\t\tsetup: function() {\n
+\t\t\t\t$( this ).bind( "resize", handler );\n
+\t\t\t},\n
+\t\t\tteardown: function() {\n
+\t\t\t\t$( this ).unbind( "resize", handler );\n
+\t\t\t}\n
+\t\t};\n
+\n
+\t\tvar throttle = 250,\n
+\t\t\thandler = function() {\n
+\t\t\t\tcurr = ( new Date() ).getTime();\n
+\t\t\t\tdiff = curr - lastCall;\n
+\n
+\t\t\t\tif ( diff >= throttle ) {\n
+\n
+\t\t\t\t\tlastCall = curr;\n
+\t\t\t\t\t$( this ).trigger( "throttledresize" );\n
+\n
+\t\t\t\t} else {\n
+\n
+\t\t\t\t\tif ( heldCall ) {\n
+\t\t\t\t\t\tclearTimeout( heldCall );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// Promise a held call will still execute\n
+\t\t\t\t\theldCall = setTimeout( handler, throttle - diff );\n
+\t\t\t\t}\n
+\t\t\t},\n
+\t\t\tlastCall = 0,\n
+\t\t\theldCall,\n
+\t\t\tcurr,\n
+\t\t\tdiff;\n
+\t})( jQuery );\n
+\n
+(function( $, window ) {\n
+\tvar win = $( window ),\n
+\t\tevent_name = "orientationchange",\n
+\t\tget_orientation,\n
+\t\tlast_orientation,\n
+\t\tinitial_orientation_is_landscape,\n
+\t\tinitial_orientation_is_default,\n
+\t\tportrait_map = { "0": true, "180": true },\n
+\t\tww, wh, landscape_threshold;\n
+\n
+\t// It seems that some device/browser vendors use window.orientation values 0 and 180 to\n
+\t// denote the "default" orientation. For iOS devices, and most other smart-phones tested,\n
+\t// the default orientation is always "portrait", but in some Android and RIM based tablets,\n
+\t// the default orientation is "landscape". The following code attempts to use the window\n
+\t// dimensions to figure out what the current orientation is, and then makes adjustments\n
+\t// to the to the portrait_map if necessary, so that we can properly decode the\n
+\t// window.orientation value whenever get_orientation() is called.\n
+\t//\n
+\t// Note that we used to use a media query to figure out what the orientation the browser\n
+\t// thinks it is in:\n
+\t//\n
+\t//     initial_orientation_is_landscape = $.mobile.media("all and (orientation: landscape)");\n
+\t//\n
+\t// but there was an iPhone/iPod Touch bug beginning with iOS 4.2, up through iOS 5.1,\n
+\t// where the browser *ALWAYS* applied the landscape media query. This bug does not\n
+\t// happen on iPad.\n
+\n
+\tif ( $.support.orientation ) {\n
+\n
+\t\t// Check the window width and height to figure out what the current orientation\n
+\t\t// of the device is at this moment. Note that we\'ve initialized the portrait map\n
+\t\t// values to 0 and 180, *AND* we purposely check for landscape so that if we guess\n
+\t\t// wrong, , we default to the assumption that portrait is the default orientation.\n
+\t\t// We use a threshold check below because on some platforms like iOS, the iPhone\n
+\t\t// form-factor can report a larger width than height if the user turns on the\n
+\t\t// developer console. The actual threshold value is somewhat arbitrary, we just\n
+\t\t// need to make sure it is large enough to exclude the developer console case.\n
+\n
+\t\tww = window.innerWidth || win.width();\n
+\t\twh = window.innerHeight || win.height();\n
+\t\tlandscape_threshold = 50;\n
+\n
+\t\tinitial_orientation_is_landscape = ww > wh && ( ww - wh ) > landscape_threshold;\n
+\n
+\n
+\t\t// Now check to see if the current window.orientation is 0 or 180.\n
+\t\tinitial_orientation_is_default = portrait_map[ window.orientation ];\n
+\n
+\t\t// If the initial orientation is landscape, but window.orientation reports 0 or 180, *OR*\n
+\t\t// if the initial orientation is portrait, but window.orientation reports 90 or -90, we\n
+\t\t// need to flip our portrait_map values because landscape is the default orientation for\n
+\t\t// this device/browser.\n
+\t\tif ( ( initial_orientation_is_landscape && initial_orientation_is_default ) || ( !initial_orientation_is_landscape && !initial_orientation_is_default ) ) {\n
+\t\t\tportrait_map = { "-90": true, "90": true };\n
+\t\t}\n
+\t}\n
+\n
+\t$.event.special.orientationchange = $.extend( {}, $.event.special.orientationchange, {\n
+\t\tsetup: function() {\n
+\t\t\t// If the event is supported natively, return false so that jQuery\n
+\t\t\t// will bind to the event using DOM methods.\n
+\t\t\tif ( $.support.orientation && !$.event.special.orientationchange.disabled ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\n
+\t\t\t// Get the current orientation to avoid initial double-triggering.\n
+\t\t\tlast_orientation = get_orientation();\n
+\n
+\t\t\t// Because the orientationchange event doesn\'t exist, simulate the\n
+\t\t\t// event by testing window dimensions on resize.\n
+\t\t\twin.bind( "throttledresize", handler );\n
+\t\t},\n
+\t\tteardown: function() {\n
+\t\t\t// If the event is not supported natively, return false so that\n
+\t\t\t// jQuery will unbind the event using DOM methods.\n
+\t\t\tif ( $.support.orientation && !$.event.special.orientationchange.disabled ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\n
+\t\t\t// Because the orientationchange event doesn\'t exist, unbind the\n
+\t\t\t// resize event handler.\n
+\t\t\twin.unbind( "throttledresize", handler );\n
+\t\t},\n
+\t\tadd: function( handleObj ) {\n
+\t\t\t// Save a reference to the bound event handler.\n
+\t\t\tvar old_handler = handleObj.handler;\n
+\n
+\n
+\t\t\thandleObj.handler = function( event ) {\n
+\t\t\t\t// Modify event object, adding the .orientation property.\n
+\t\t\t\tevent.orientation = get_orientation();\n
+\n
+\t\t\t\t// Call the originally-bound event handler and return its result.\n
+\t\t\t\treturn old_handler.apply( this, arguments );\n
+\t\t\t};\n
+\t\t}\n
+\t});\n
+\n
+\t// If the event is not supported natively, this handler will be bound to\n
+\t// the window resize event to simulate the orientationchange event.\n
+\tfunction handler() {\n
+\t\t// Get the current orientation.\n
+\t\tvar orientation = get_orientation();\n
+\n
+\t\tif ( orientation !== last_orientation ) {\n
+\t\t\t// The orientation has changed, so trigger the orientationchange event.\n
+\t\t\tlast_orientation = orientation;\n
+\t\t\twin.trigger( event_name );\n
+\t\t}\n
+\t}\n
+\n
+\t// Get the current page orientation. This method is exposed publicly, should it\n
+\t// be needed, as jQuery.event.special.orientationchange.orientation()\n
+\t$.event.special.orientationchange.orientation = get_orientation = function() {\n
+\t\tvar isPortrait = true, elem = document.documentElement;\n
+\n
+\t\t// prefer window orientation to the calculation based on screensize as\n
+\t\t// the actual screen resize takes place before or after the orientation change event\n
+\t\t// has been fired depending on implementation (eg android 2.3 is before, iphone after).\n
+\t\t// More testing is required to determine if a more reliable method of determining the new screensize\n
+\t\t// is possible when orientationchange is fired. (eg, use media queries + element + opacity)\n
+\t\tif ( $.support.orientation ) {\n
+\t\t\t// if the window orientation registers as 0 or 180 degrees report\n
+\t\t\t// portrait, otherwise landscape\n
+\t\t\tisPortrait = portrait_map[ window.orientation ];\n
+\t\t} else {\n
+\t\t\tisPortrait = elem && elem.clientWidth / elem.clientHeight < 1.1;\n
+\t\t}\n
+\n
+\t\treturn isPortrait ? "portrait" : "landscape";\n
+\t};\n
+\n
+\t$.fn[ event_name ] = function( fn ) {\n
+\t\treturn fn ? this.bind( event_name, fn ) : this.trigger( event_name );\n
+\t};\n
+\n
+\t// jQuery < 1.8\n
+\tif ( $.attrFn ) {\n
+\t\t$.attrFn[ event_name ] = true;\n
+\t}\n
+\n
+}( jQuery, this ));\n
+\n
+\n
+\n
+(function( $, undefined ) {\n
+$.mobile.widgets = {};\n
+\n
+var originalWidget = $.widget;\n
+\n
+$.widget = (function( orig ) {\n
+\treturn function() {\n
+\t\tvar constructor = orig.apply( this, arguments ),\n
+\t\t\tname = constructor.prototype.widgetName;\n
+\n
+\t\tconstructor.initSelector = ( ( constructor.prototype.initSelector !== undefined ) ?\n
+\t\t\tconstructor.prototype.initSelector : ":jqmData(role=\'" + name + "\')" );\n
+\n
+\t\t$.mobile.widgets[ name ] = constructor;\n
+\n
+\t\treturn constructor;\n
+\t};\n
+})( $.widget );\n
+\n
+// Make sure $.widget still has bridge and extend methods\n
+$.extend( $.widget, originalWidget );\n
+\n
+// For backcompat remove in 1.5\n
+$.mobile.document.on( "create", function( event ){\n
+\t$( event.target ).enhanceWithin();\n
+});\n
+\n
+$.widget( "mobile.page", {\n
+\toptions: {\n
+\t\ttheme: "a",\n
+\t\tdomCache: false,\n
+\n
+\t\t// Deprecated in 1.4 remove in 1.5\n
+\t\tkeepNativeDefault: $.mobile.keepNative,\n
+\t\tcontentTheme: null,\n
+\t\tenhanced: false\n
+\t},\n
+\n
+\t// DEPRECATED for > 1.4\n
+\t// TODO remove at 1.5\n
+\t_createWidget: function() {\n
+\t\t$.Widget.prototype._createWidget.apply( this, arguments );\n
+\t\tthis._trigger( "init" );\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\t// If false is returned by the callbacks do not create the page\n
+\t\tif ( this._trigger( "beforecreate" ) === false ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\n
+\t\tif ( !this.options.enhanced ) {\n
+\t\t\tthis._enhance();\n
+\t\t}\n
+\n
+\t\tthis._on( this.element, {\n
+\t\t\tpagebeforehide: "removeContainerBackground",\n
+\t\t\tpagebeforeshow: "_handlePageBeforeShow"\n
+\t\t});\n
+\n
+\t\tthis.element.enhanceWithin();\n
+\t\t// Dialog widget is deprecated in 1.4 remove this in 1.5\n
+\t\tif( $.mobile.getAttribute( this.element[0], "role" ) === "dialog" && $.mobile.dialog ){\n
+\t\t\tthis.element.dialog();\n
+\t\t}\n
+\t},\n
+\n
+\t_enhance: function (){\n
+\t\tvar attrPrefix = "data-" + $.mobile.ns,\n
+\t\t\tself = this;\n
+\n
+\t\tif ( this.options.role ) {\n
+\t\t\tthis.element.attr( "data-" + $.mobile.ns + "role", this.options.role );\n
+\t\t}\n
+\n
+\t\tthis.element\n
+\t\t\t.attr( "tabindex", "0" )\n
+\t\t\t.addClass( "ui-page ui-page-theme-" + this.options.theme );\n
+\n
+\t\t// Manipulation of content os Deprecated as of 1.4 remove in 1.5\n
+\t\tthis.element.find( "[" + attrPrefix + "role=\'content\']" ).each( function() {\n
+\t\t\tvar $this = $( this ),\n
+\t\t\t\ttheme = this.getAttribute( attrPrefix + "theme" ) || undefined;\n
+\t\t\t\tself.options.contentTheme = theme || self.options.contentTheme || ( self.options.dialog && self.options.theme ) || ( self.element.jqmData("role") === "dialog" &&  self.options.theme );\n
+\t\t\t\t$this.addClass( "ui-content" );\n
+\t\t\t\tif ( self.options.contentTheme ) {\n
+\t\t\t\t\t$this.addClass( "ui-body-" + ( self.options.contentTheme ) );\n
+\t\t\t\t}\n
+\t\t\t\t// Add ARIA role\n
+\t\t\t\t$this.attr( "role", "main" ).addClass( "ui-content" );\n
+\t\t});\n
+\t},\n
+\n
+\tbindRemove: function( callback ) {\n
+\t\tvar page = this.element;\n
+\n
+\t\t// when dom caching is not enabled or the page is embedded bind to remove the page on hide\n
+\t\tif ( !page.data( "mobile-page" ).options.domCache &&\n
+\t\t\tpage.is( ":jqmData(external-page=\'true\')" ) ) {\n
+\n
+\t\t\t// TODO use _on - that is, sort out why it doesn\'t work in this case\n
+\t\t\tpage.bind( "pagehide.remove", callback || function(/* e */) {\n
+\t\t\t\tvar $this = $( this ),\n
+\t\t\t\t\tprEvent = new $.Event( "pageremove" );\n
+\n
+\t\t\t\t$this.trigger( prEvent );\n
+\n
+\t\t\t\tif ( !prEvent.isDefaultPrevented() ) {\n
+\t\t\t\t\t$this.removeWithDependents();\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t}\n
+\t},\n
+\n
+\t_setOptions: function( o ) {\n
+\t\tif ( o.theme !== undefined ) {\n
+\t\t\tthis.element.removeClass( "ui-body-" + this.options.theme ).addClass( "ui-body-" + o.theme );\n
+\t\t}\n
+\n
+\t\tif ( o.contentTheme !== undefined ) {\n
+\t\t\tthis.element.find( "[data-" + $.mobile.ns + "=\'content\']" ).removeClass( "ui-body-" + this.options.contentTheme )\n
+\t\t\t\t.addClass( "ui-body-" + o.contentTheme );\n
+\t\t}\n
+\t},\n
+\n
+\t_handlePageBeforeShow: function(/* e */) {\n
+\t\tthis.setContainerBackground();\n
+\t},\n
+\t// Deprecated in 1.4 remove in 1.5\n
+\tremoveContainerBackground: function() {\n
+\t\tthis.element.closest( ":mobile-content" ).content({ "theme": "none" });\n
+\t},\n
+\t// Deprecated in 1.4 remove in 1.5\n
+\t// set the page container background to the page theme\n
+\tsetContainerBackground: function( theme ) {\n
+\t\tthis.element.parent().content( { "theme": theme || this.options.theme } );\n
+\t},\n
+\t// Deprecated in 1.4 remove in 1.5\n
+\tkeepNativeSelector: function() {\n
+\t\tvar options = this.options,\n
+\t\t\tkeepNativeDefined = options.keepNative && $.trim( options.keepNative );\n
+\n
+\t\tif ( keepNativeDefined && options.keepNative !== options.keepNativeDefault ) {\n
+\t\t\treturn [options.keepNative, options.keepNativeDefault].join( ", " );\n
+\t\t}\n
+\n
+\t\treturn options.keepNativeDefault;\n
+\t}\n
+});\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+\t$.widget( "mobile.content", {\n
+\t\toptions: {\n
+\t\t\ttheme: "a"\n
+\t\t},\n
+\n
+\t\tinitSelector: false,\n
+\n
+\t\t_create: function() {\n
+\t\t\tvar $window = $( window );\n
+\n
+\t\t\tthis.setLastScrollEnabled = true;\n
+\n
+\t\t\t// TODO consider moving the navigation handler OUT of widget into\n
+\t\t\t//      some other object as glue between the navigate event and the\n
+\t\t\t//      content widget load and change methods\n
+\t\t\tthis._on( $window, { navigate: "_filterNavigateEvents" });\n
+\n
+\t\t\tthis._on( $window, {\n
+\t\t\t\t// disable an scroll setting when a hashchange has been fired,\n
+\t\t\t\t// this only works because the recording of the scroll position\n
+\t\t\t\t// is delayed for 100ms after the browser might have changed the\n
+\t\t\t\t// position because of the hashchange\n
+\t\t\t\tnavigate: "_disableRecordScroll",\n
+\n
+\t\t\t\t// bind to scrollstop for the first page, "pagechange" won\'t be\n
+\t\t\t\t// fired in that case\n
+\t\t\t\tscrollstop: "_delayedRecordScroll"\n
+\t\t\t});\n
+\n
+\t\t\t// TODO move from page* events to content* events\n
+\t\t\tthis._on({ pagechange: "_afterContentChange" });\n
+\n
+\t\t\t// handle initial hashchange from chrome :(\n
+\t\t\t$window.one( "navigate", $.proxy(function() {\n
+\t\t\t\tthis.setLastScrollEnabled = true;\n
+\t\t\t}, this));\n
+\t\t},\n
+\n
+\t\t_setOptions: function( options ){\n
+\t\t\tif ( options.theme !== undefined && options.theme !== "none" ) {\n
+\t\t\t\tthis.element.removeClass( "ui-overlay-" + this.options.theme )\n
+\t\t\t\t\t.addClass( "ui-overlay-" + options.theme );\n
+\t\t\t} else if ( options.theme !== undefined ) {\n
+\t\t\t\tthis.element.removeClass( "ui-overlay-" + this.options.theme );\n
+\t\t\t}\n
+\n
+\t\t\tthis._super( options );\n
+\t\t},\n
+\n
+\t\t_disableRecordScroll: function() {\n
+\t\t\tthis.setLastScrollEnabled = false;\n
+\t\t},\n
+\n
+\t\t_enableRecordScroll: function() {\n
+\t\t\tthis.setLastScrollEnabled = true;\n
+\t\t},\n
+\n
+\t\t// TODO consider the name here, since it\'s purpose specific\n
+\t\t_afterContentChange:  function() {\n
+\t\t\t// once the page has changed, re-enable the scroll recording\n
+\t\t\tthis.setLastScrollEnabled = true;\n
+\n
+\t\t\t// remove any binding that previously existed on the get scroll\n
+\t\t\t// which may or may not be different than the scroll element\n
+\t\t\t// determined for this page previously\n
+\t\t\tthis._off( $window, "scrollstop" );\n
+\n
+\t\t\t// determine and bind to the current scoll element which may be the\n
+\t\t\t// window or in the case of touch overflow the element touch overflow\n
+\t\t\tthis._on( $window, { scrollstop: "_delayedRecordScroll" });\n
+\t\t},\n
+\n
+\t\t_recordScroll: function() {\n
+\t\t\t// this barrier prevents setting the scroll value based on\n
+\t\t\t// the browser scrolling the window based on a hashchange\n
+\t\t\tif ( !this.setLastScrollEnabled ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tvar active = this._getActiveHistory(),\n
+\t\t\t\tcurrentScroll, minScroll, defaultScroll;\n
+\n
+\t\t\tif ( active ) {\n
+\t\t\t\tcurrentScroll = this._getScroll();\n
+\t\t\t\tminScroll = this._getMinScroll();\n
+\t\t\t\tdefaultScroll = this._getDefaultScroll();\n
+\n
+\t\t\t\t// Set active page\'s lastScroll prop. If the location we\'re\n
+\t\t\t\t// scrolling to is less than minScrollBack, let it go.\n
+\t\t\t\tactive.lastScroll = currentScroll < minScroll ? defaultScroll : currentScroll;\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_delayedRecordScroll: function() {\n
+\t\t\tsetTimeout( $.proxy(this, "_recordScroll"), 100 );\n
+\t\t},\n
+\n
+\t\t_getScroll: function() {\n
+\t\t\treturn $window.scrollTop();\n
+\t\t},\n
+\n
+\t\t_getMinScroll: function() {\n
+\t\t\treturn $.mobile.minScrollBack;\n
+\t\t},\n
+\n
+\t\t_getDefaultScroll: function() {\n
+\t\t\treturn $.mobile.defaultHomeScroll;\n
+\t\t},\n
+\n
+\t\t_filterNavigateEvents: function( e, data ) {\n
+\t\t\tvar url;\n
+\n
+\t\t\tif ( e.originalEvent && e.originalEvent.isDefaultPrevented() ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\turl = e.originalEvent.type.indexOf( "hashchange" ) > -1 ? data.state.hash : data.state.url;\n
+\n
+\t\t\tif ( !url ) {\n
+\t\t\t\turl = this._getHash();\n
+\t\t\t}\n
+\n
+\t\t\tif ( !url || url === "#" || url.indexOf( "#" + $.mobile.path.uiStateKey ) === 0 ){\n
+\t\t\t\turl = location.href;\n
+\t\t\t}\n
+\n
+\t\t\tthis._handleNavigate( url, data.state );\n
+\t\t},\n
+\n
+\t\t_getHash: function() {\n
+\t\t\treturn $.mobile.path.parseLocation().hash;\n
+\t\t},\n
+\n
+\t\t// TODO active page should be managed by the container (ie, it should be a property)\n
+\t\t_getActiveContent: function() {\n
+\t\t\treturn $.mobile.activePage;\n
+\t\t},\n
+\n
+\t\t// TODO the first page should be a property set during creat using the logic\n
+\t\t//      that currently resides in init\n
+\t\t_getInitialContent: function() {\n
+\t\t\treturn $.mobile.firstPage;\n
+\t\t},\n
+\n
+\t\t// TODO each content container should have a history object\n
+\t\t_getHistory: function() {\n
+\t\t\treturn urlHistory;\n
+\t\t},\n
+\n
+\t\t// TODO use _getHistory\n
+\t\t_getActiveHistory: function() {\n
+\t\t\treturn $.mobile.urlHistory.getActive();\n
+\t\t},\n
+\n
+\t\t// TODO the document base should be determined at creation\n
+\t\t_getDocumentBase: function() {\n
+\t\t\treturn documentBase;\n
+\t\t},\n
+\n
+\t\t_back: function() {\n
+\t\t\t$.mobile.back();\n
+\t\t},\n
+\n
+\t\t_forward: function() {\n
+\t\t\twindow.history.forward();\n
+\t\t},\n
+\n
+\t\t// TODO rename _handleDestination\n
+\t\t_handleDestination: function( to ) {\n
+\t\t\tvar history, documentBase;\n
+\n
+\t\t\t// clean the hash for comparison if it\'s a url\n
+\t\t\tif ( $.type(to) === "string" ) {\n
+\t\t\t\tto = path.stripHash(to);\n
+\t\t\t}\n
+\n
+\t\t\tif ( to ) {\n
+\t\t\t\thistory = this._getHistory(),\n
+\t\t\t\tdocumentBase = this._getDocumentBase();\n
+\n
+\t\t\t\t// At this point, \'to\' can be one of 3 things, a cached page\n
+\t\t\t\t// element from a history stack entry, an id, or site-relative /\n
+\t\t\t\t// absolute URL. If \'to\' is an id, we need to resolve it against\n
+\t\t\t\t// the documentBase, not the location.href, since the hashchange\n
+\t\t\t\t// could\'ve been the result of a forward/backward navigation\n
+\t\t\t\t// that crosses from an external page/dialog to an internal\n
+\t\t\t\t// page/dialog.\n
+\t\t\t\t//\n
+\t\t\t\t// TODO move check to history object or path object?\n
+\t\t\t\tto = !path.isPath( to ) ? ( path.makeUrlAbsolute( "#" + to, documentBase ) ) : to;\n
+\n
+\t\t\t\t// If we\'re about to go to an initial URL that contains a\n
+\t\t\t\t// reference to a non-existent internal page, go to the first\n
+\t\t\t\t// page instead. We know that the initial hash refers to a\n
+\t\t\t\t// non-existent page, because the initial hash did not end\n
+\t\t\t\t// up in the initial history entry\n
+\t\t\t\t// TODO move check to history object?\n
+\t\t\t\tif ( to === path.makeUrlAbsolute( "#" + history.initialDst, documentBase ) &&\n
+\t\t\t\t\thistory.stack.length &&\n
+\t\t\t\t\thistory.stack[0].url !== history.initialDst.replace( dialogHashKey, "" ) ) {\n
+\t\t\t\t\tto = this._getInitialContent();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\treturn to || this._getInitialContent();\n
+\t\t},\n
+\n
+\t\t_handleDialog: function( changePageOptions, data ) {\n
+\t\t\tvar to, active, activeContent = this._getActiveContent();\n
+\n
+\t\t\t// If current active page is not a dialog skip the dialog and continue\n
+\t\t\t// in the same direction\n
+\t\t\tif ( activeContent && !activeContent.hasClass( "ui-dialog" ) ) {\n
+\t\t\t\t// determine if we\'re heading forward or backward and continue\n
+\t\t\t\t// accordingly past the current dialog\n
+\t\t\t\tif ( data.direction === "back" ) {\n
+\t\t\t\t\tthis._back();\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthis._forward();\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// prevent changePage call\n
+\t\t\t\treturn false;\n
+\t\t\t} else {\n
+\t\t\t\t// if the current active page is a dialog and we\'re navigating\n
+\t\t\t\t// to a dialog use the dialog objected saved in the stack\n
+\t\t\t\tto = data.pageUrl;\n
+\t\t\t\tactive = this._getActiveHistory();\n
+\n
+\t\t\t\t// make sure to set the role, transition and reversal\n
+\t\t\t\t// as most of this is lost by the domCache cleaning\n
+\t\t\t\t$.extend( changePageOptions, {\n
+\t\t\t\t\trole: active.role,\n
+\t\t\t\t\ttransition: active.transition,\n
+\t\t\t\t\treverse: data.direction === "back"\n
+\t\t\t\t});\n
+\t\t\t}\n
+\n
+\t\t\treturn to;\n
+\t\t},\n
+\n
+\t\t_handleNavigate: function( url, data ) {\n
+\t\t\t//find first page via hash\n
+\t\t\t// TODO striping the hash twice with handleUrl\n
+\t\t\tvar to = path.stripHash(url), history = this._getHistory(),\n
+\n
+\t\t\t\t// transition is false if it\'s the first page, undefined\n
+\t\t\t\t// otherwise (and may be overridden by default)\n
+\t\t\t\ttransition = history.stack.length === 0 ? "none" : undefined,\n
+\n
+\t\t\t\t// default options for the changPage calls made after examining\n
+\t\t\t\t// the current state of the page and the hash, NOTE that the\n
+\t\t\t\t// transition is derived from the previous history entry\n
+\t\t\t\tchangePageOptions = {\n
+\t\t\t\t\tchangeHash: false,\n
+\t\t\t\t\tfromHashChange: true,\n
+\t\t\t\t\treverse: data.direction === "back"\n
+\t\t\t\t};\n
+\n
+\t\t\t$.extend( changePageOptions, data, {\n
+\t\t\t\ttransition: (history.getLast() || {}).transition || transition\n
+\t\t\t});\n
+\n
+\t\t\t// TODO move to _handleDestination ?\n
+\t\t\t// If this isn\'t the first page, if the current url is a dialog hash\n
+\t\t\t// key, and the initial destination isn\'t equal to the current target\n
+\t\t\t// page, use the special dialog handling\n
+\t\t\tif ( history.activeIndex > 0 &&\n
+\t\t\t\tto.indexOf( dialogHashKey ) > -1 &&\n
+\t\t\t\thistory.initialDst !== to ) {\n
+\n
+\t\t\t\tto = this._handleDialog( changePageOptions, data );\n
+\n
+\t\t\t\tif ( to === false ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tthis._changeContent( this._handleDestination(to), changePageOptions );\n
+\t\t},\n
+\n
+\t\t_changeContent: function( to, opts ) {\n
+\t\t\t$.mobile.changePage( to, opts );\n
+\t\t},\n
+\n
+\t\t_getBase: function() {\n
+\t\t\treturn base;\n
+\t\t},\n
+\n
+\t\t_getBaseWithDefault: function() {\n
+\t\t\treturn findBaseWithDefault();\n
+\t\t},\n
+\n
+\t\t_getNs: function() {\n
+\t\t\treturn $.mobile.ns;\n
+\t\t},\n
+\n
+\t\t_enhance: function( content, role ) {\n
+\t\t\t// TODO consider supporting a custom callback, and passing in\n
+\t\t\t// the settings which includes the role\n
+\t\t\treturn content.page({ role: role });\n
+\t\t},\n
+\n
+\t\t_include: function( page, settings ) {\n
+\t\t\t// append to page and enhance\n
+\t\t\tpage.appendTo( this.element );\n
+\n
+\t\t\t// use the page widget to enhance\n
+\t\t\tthis._enhance( page, settings.role );\n
+\n
+\t\t\t// remove page on hide\n
+\t\t\tpage.page( "bindRemove" );\n
+\t\t},\n
+\n
+\t\t_find: function( absUrl ) {\n
+\t\t\t// TODO consider supporting a custom callback\n
+\t\t\tvar fileUrl = this._createFileUrl( absUrl ),\n
+\t\t\t\tdataUrl = this._createDataUrl( absUrl ),\n
+\t\t\t\tpage, initialContent = this._getInitialContent();\n
+\n
+\t\t\t// Check to see if the page already exists in the DOM.\n
+\t\t\t// NOTE do _not_ use the :jqmData psuedo selector because parenthesis\n
+\t\t\t//      are a valid url char and it breaks on the first occurence\n
+\t\t\tpage = this.element\n
+\t\t\t\t.children( "[data-" + this._getNs() +"url=\'" + dataUrl + "\']" );\n
+\n
+\t\t\t// If we failed to find the page, check to see if the url is a\n
+\t\t\t// reference to an embedded page. If so, it may have been dynamically\n
+\t\t\t// injected by a developer, in which case it would be lacking a\n
+\t\t\t// data-url attribute and in need of enhancement.\n
+\t\t\tif ( page.length === 0 && dataUrl && !path.isPath( dataUrl ) ) {\n
+\t\t\t\tpage = this.element.children( path.hashToSelector("#" + dataUrl) )\n
+\t\t\t\t\t.attr( "data-" + this._getNs() + "url", dataUrl )\n
+\t\t\t\t\t.jqmData( "url", dataUrl );\n
+\t\t\t}\n
+\n
+\n
+\t\t\t// If we failed to find a page in the DOM, check the URL to see if it\n
+\t\t\t// refers to the first page in the application. Also Check to make sure\n
+\t\t\t// our cached-first-page is actually in the DOM. Some user deployed\n
+\t\t\t// apps are pruning the first page from the DOM for various reasons,\n
+\t\t\t// we check for this case here because we don\'t want a first-page with\n
+\t\t\t// an id falling through to the non-existent embedded page error case.\n
+\t\t\tif ( page.length === 0 &&\n
+\t\t\t\tpath.isFirstPageUrl(fileUrl) &&\n
+\t\t\t\tinitialContent &&\n
+\t\t\t\tinitialContent.parent().length ) {\n
+\t\t\t\tpage = $( initialContent );\n
+\t\t\t}\n
+\n
+\t\t\treturn page;\n
+\t\t},\n
+\n
+\t\t_getLoader: function() {\n
+\t\t\treturn $.mobile.loaderWidget;\n
+\t\t},\n
+\n
+\t\t_showLoading: function( delay, theme, msg, textonly ) {\n
+\t\t\t// This configurable timeout allows cached pages a brief\n
+\t\t\t// delay to load without showing a message\n
+\t\t\tthis._loadMsg = setTimeout($.proxy(function() {\n
+\t\t\t\tthis._getLoader().loader( "show", theme, msg, textonly );\n
+\t\t\t}, this), delay );\n
+\t\t},\n
+\n
+\t\t_hideLoading: function() {\n
+\t\t\t// Stop message show timer\n
+\t\t\tclearTimeout( this._loadMsg );\n
+\n
+\t\t\t// Hide loading message\n
+\t\t\tthis._getLoader().loader( "hide" );\n
+\t\t},\n
+\n
+\t\t_showError: function() {\n
+\t\t\t// make sure to remove the current loading message\n
+\t\t\tthis._hideLoading();\n
+\n
+\t\t\t// show the error message\n
+\t\t\tthis._showLoading( 0, $.mobile.pageLoadErrorMessageTheme, $.mobile.pageLoadErrorMessage, true );\n
+\n
+\t\t\t// hide the error message after a delay\n
+\t\t\t// TODO configuration\n
+\t\t\tsetTimeout( $.proxy(this, "_hideLoading"), 1500 );\n
+\t\t},\n
+\n
+\t\t_parse: function( html, fileUrl ) {\n
+\t\t\t// TODO consider allowing customization of this method. It\'s very JQM specific\n
+\t\t\tvar page, all = $( "<div></div>" );\n
+\n
+\t\t\t//workaround to allow scripts to execute when included in page divs\n
+\t\t\tall.get( 0 ).innerHTML = html;\n
+\n
+\t\t\tpage = all.find( ":jqmData(role=\'page\'), :jqmData(role=\'dialog\')" ).first();\n
+\n
+\t\t\t//if page elem couldn\'t be found, create one and insert the body element\'s contents\n
+\t\t\tif ( !page.length ) {\n
+\t\t\t\tpage = $( "<div data-" + this._getNs() + "role=\'page\'>" +\n
+\t\t\t\t\t( html.split( /<\\/?body[^>]*>/gmi )[1] || "" ) +\n
+\t\t\t\t\t"</div>" );\n
+\t\t\t}\n
+\n
+\t\t\t// TODO taging a page with external to make sure that embedded pages aren\'t\n
+\t\t\t// removed by the various page handling code is bad. Having page handling code\n
+\t\t\t// in many places is bad. Solutions post 1.0\n
+\t\t\tpage.attr( "data-" + this._getNs() + "url", path.convertUrlToDataUrl(fileUrl) )\n
+\t\t\t\t.attr( "data-" + this._getNs() + "external-page", true );\n
+\n
+\t\t\treturn page;\n
+\t\t},\n
+\n
+\t\t_setLoadedTitle: function( page, html ) {\n
+\t\t\t//page title regexp\n
+\t\t\tvar newPageTitle = html.match( /<title[^>]*>([^<]*)/ ) && RegExp.$1;\n
+\n
+\t\t\tif ( newPageTitle && !page.jqmData("title") ) {\n
+\t\t\t\tnewPageTitle = $( "<div>" + newPageTitle + "</div>" ).text();\n
+\t\t\t\tpage.jqmData( "title", newPageTitle );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_isRewritableBaseTag: function() {\n
+\t\t\treturn $.mobile.dynamicBaseEnabled && !$.support.dynamicBaseTag;\n
+\t\t},\n
+\n
+\t\t_createDataUrl: function( absoluteUrl ) {\n
+\t\t\treturn path.convertUrlToDataUrl( absoluteUrl );\n
+\t\t},\n
+\n
+\t\t_createFileUrl: function( absoluteUrl ) {\n
+\t\t\treturn path.getFilePath( absoluteUrl );\n
+\t\t},\n
+\n
+\t\t_triggerWithDeprecated: function( name, data, page ) {\n
+\t\t\tvar deprecatedEvent = $.Event( "page" + name ),\n
+\t\t\t\tnewEvent = $.Event( this.widgetName + name );\n
+\n
+\t\t\t// DEPRECATED\n
+\t\t\t// trigger the old deprecated event on the page if it\'s provided\n
+\t\t\t(page || this.element).trigger( deprecatedEvent, data );\n
+\n
+\t\t\t// use the widget trigger method for the new content* event\n
+\t\t\tthis.element.trigger( newEvent, data );\n
+\n
+\t\t\treturn {\n
+\t\t\t\tdeprecatedEvent: deprecatedEvent,\n
+\t\t\t\tevent: newEvent\n
+\t\t\t};\n
+\t\t},\n
+\n
+\t\t// TODO it would be nice to split this up more but everything appears to be "one off"\n
+\t\t//      or require ordering such that other bits are sprinkled in between parts that\n
+\t\t//      could be abstracted out as a group\n
+\t\t_loadSuccess: function( absUrl, triggerData, settings, deferred ) {\n
+\t\t\tvar fileUrl = this._createFileUrl( absUrl ),\n
+\t\t\t\tdataUrl = this._createDataUrl( absUrl );\n
+\n
+\t\t\treturn $.proxy(function( html, textStatus, xhr ) {\n
+\t\t\t\t//pre-parse html to check for a data-url,\n
+\t\t\t\t//use it as the new fileUrl, base path, etc\n
+\t\t\t\tvar content,\n
+\n
+\t\t\t\t\t// TODO handle dialogs again\n
+\t\t\t\t\tpageElemRegex = new RegExp( "(<[^>]+\\\\bdata-" + this._getNs() + "role=[\\"\']?page[\\"\']?[^>]*>)" ),\n
+\n
+\t\t\t\t\tdataUrlRegex = new RegExp( "\\\\bdata-" + this._getNs() + "url=[\\"\']?([^\\"\'>]*)[\\"\']?" );\n
+\n
+\t\t\t\t// data-url must be provided for the base tag so resource requests\n
+\t\t\t\t// can be directed to the correct url. loading into a temprorary\n
+\t\t\t\t// element makes these requests immediately\n
+\t\t\t\tif ( pageElemRegex.test( html ) &&\n
+\t\t\t\t\tRegExp.$1 &&\n
+\t\t\t\t\tdataUrlRegex.test( RegExp.$1 ) &&\n
+\t\t\t\t\tRegExp.$1 ) {\n
+\t\t\t\t\tfileUrl = path.getFilePath( $("<div>" + RegExp.$1 + "</div>").text() );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t//dont update the base tag if we are prefetching\n
+\t\t\t\tif ( settings.prefetch === undefined ){\n
+\t\t\t\t\tthis._getBase().set( fileUrl );\n
+\t\t\t\t}\n
+\n
+\t\t\t\tcontent = this._parse( html, fileUrl );\n
+\n
+\t\t\t\tthis._setLoadedTitle( content, html );\n
+\n
+\t\t\t\t// rewrite src and href attrs to use a base url if the base tag won\'t work\n
+\t\t\t\tif ( this._isRewritableBaseTag() && content ) {\n
+\t\t\t\t\tthis._getBase().rewrite( fileUrl, content );\n
+\t\t\t\t}\n
+\n
+\t\t\t\tthis._include( content, settings );\n
+\n
+\t\t\t\t// Enhancing the content may result in new dialogs/sub content being inserted\n
+\t\t\t\t// into the DOM. If the original absUrl refers to a sub-content, that is the\n
+\t\t\t\t// real content we are interested in.\n
+\t\t\t\tif ( absUrl.indexOf( "&" + $.mobile.subPageUrlKey ) > -1 ) {\n
+\t\t\t\t\tcontent = this.element.children( "[data-" + this._getNs() +"url=\'" + dataUrl + "\']" );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Remove loading message.\n
+\t\t\t\tif ( settings.showLoadMsg ) {\n
+\t\t\t\t\tthis._hideLoading();\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Add the content reference and xhr to our triggerData.\n
+\t\t\t\ttriggerData.xhr = xhr;\n
+\t\t\t\ttriggerData.textStatus = textStatus;\n
+\n
+\t\t\t\t// DEPRECATED\n
+\t\t\t\ttriggerData.page = content;\n
+\n
+\t\t\t\ttriggerData.content = content;\n
+\n
+\t\t\t\t// Let listeners know the content loaded successfully.\n
+\t\t\t\tthis._triggerWithDeprecated( "load", triggerData );\n
+\n
+\t\t\t\tdeferred.resolve( absUrl, settings, content );\n
+\t\t\t}, this);\n
+\t\t},\n
+\n
+\t\t_loadDefaults: {\n
+\t\t\ttype: "get",\n
+\t\t\tdata: undefined,\n
+\n
+\t\t\t// DEPRECATED\n
+\t\t\treloadPage: false,\n
+\n
+\t\t\treload: false,\n
+\n
+\t\t\t// By default we rely on the role defined by the @data-role attribute.\n
+\t\t\trole: undefined,\n
+\n
+\t\t\tshowLoadMsg: false,\n
+\n
+\t\t\t// This delay allows loads that pull from browser cache to\n
+\t\t\t// occur without showing the loading message.\n
+\t\t\tloadMsgDelay: 50\n
+\t\t},\n
+\n
+\t\tload: function( url, options ) {\n
+\t\t\t// This function uses deferred notifications to let callers\n
+\t\t\t// know when the content is done loading, or if an error has occurred.\n
+\t\t\tvar deferred = options.deferred || $.Deferred(),\n
+\n
+\t\t\t\t// The default load options with overrides specified by the caller.\n
+\t\t\t\tsettings = $.extend( {}, this._loadDefaults, options ),\n
+\n
+\t\t\t\t// The DOM element for the content after it has been loaded.\n
+\t\t\t\tcontent = null,\n
+\n
+\t\t\t\t// The absolute version of the URL passed into the function. This\n
+\t\t\t\t// version of the URL may contain dialog/subcontent params in it.\n
+\t\t\t\tabsUrl = path.makeUrlAbsolute( url, this._getBaseWithDefault() ),\n
+\t\t\t\tfileUrl, dataUrl, pblEvent, triggerData;\n
+\n
+\t\t\t// DEPRECATED reloadPage\n
+\t\t\tsettings.reload = settings.reloadPage;\n
+\n
+\t\t\t// If the caller provided data, and we\'re using "get" request,\n
+\t\t\t// append the data to the URL.\n
+\t\t\tif ( settings.data && settings.type === "get" ) {\n
+\t\t\t\tabsUrl = path.addSearchParams( absUrl, settings.data );\n
+\t\t\t\tsettings.data = undefined;\n
+\t\t\t}\n
+\n
+\t\t\t// If the caller is using a "post" request, reload must be true\n
+\t\t\tif ( settings.data && settings.type === "post" ) {\n
+\t\t\t\tsettings.reload = true;\n
+\t\t\t}\n
+\n
+\t\t\t// The absolute version of the URL minus any dialog/subcontent params.\n
+\t\t\t// In otherwords the real URL of the content to be loaded.\n
+\t\t\tfileUrl = this._createFileUrl( absUrl );\n
+\n
+\t\t\t// The version of the Url actually stored in the data-url attribute of\n
+\t\t\t// the content. For embedded content, it is just the id of the page. For content\n
+\t\t\t// within the same domain as the document base, it is the site relative\n
+\t\t\t// path. For cross-domain content (Phone Gap only) the entire absolute Url\n
+\t\t\t// used to load the content.\n
+\t\t\tdataUrl = this._createDataUrl( absUrl );\n
+\n
+\t\t\tcontent = this._find( absUrl );\n
+\n
+\t\t\t// If it isn\'t a reference to the first content and refers to missing embedded content\n
+\t\t\t// reject the deferred and return\n
+\t\t\tif ( content.length === 0 &&\n
+\t\t\t\tpath.isEmbeddedPage(fileUrl) &&\n
+\t\t\t\t!path.isFirstPageUrl(fileUrl) ) {\n
+\t\t\t\tdeferred.reject( absUrl, settings );\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// Reset base to the default document base\n
+\t\t\t// TODO figure out why we doe this\n
+\t\t\tthis._getBase().reset();\n
+\n
+\t\t\t// If the content we are interested in is already in the DOM,\n
+\t\t\t// and the caller did not indicate that we should force a\n
+\t\t\t// reload of the file, we are done. Resolve the deferrred so that\n
+\t\t\t// users can bind to .done on the promise\n
+\t\t\tif ( content.length && !settings.reload ) {\n
+\t\t\t\tthis._enhance( content, settings.role );\n
+\t\t\t\tdeferred.resolve( absUrl, settings, content );\n
+\n
+\t\t\t\t//if we are reloading the content make sure we update\n
+\t\t\t\t// the base if its not a prefetch\n
+\t\t\t\tif ( !settings.prefetch ){\n
+\t\t\t\t\tthis._getBase().set(url);\n
+\t\t\t\t}\n
+\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\ttriggerData = {\n
+\t\t\t\turl: url,\n
+\t\t\t\tabsUrl: absUrl,\n
+\t\t\t\tdataUrl: dataUrl,\n
+\t\t\t\tdeferred: deferred,\n
+\t\t\t\toptions: settings\n
+\t\t\t};\n
+\n
+\t\t\t// Let listeners know we\'re about to load a content.\n
+\t\t\tpblEvent = this._triggerWithDeprecated( "beforeload", triggerData );\n
+\n
+\t\t\t// If the default behavior is prevented, stop here!\n
+\t\t\tif ( pblEvent.deprecatedEvent.isDefaultPrevented() ||\n
+\t\t\t\t pblEvent.event.isDefaultPrevented() ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tif ( settings.showLoadMsg ) {\n
+\t\t\t\tthis._showLoading( settings.loadMsgDelay );\n
+\t\t\t}\n
+\n
+\t\t\t// Reset base to the default document base.\n
+\t\t\t// only reset if we are not prefetching\n
+\t\t\tif ( settings.prefetch === undefined ) {\n
+\t\t\t\tthis._getBase().reset();\n
+\t\t\t}\n
+\n
+\t\t\tif ( !($.mobile.allowCrossDomainPages ||\n
+\t\t\t\tpath.isSameDomain(documentUrl, absUrl)) ) {\n
+\t\t\t\tdeferred.reject( absUrl, settings );\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// Load the new content.\n
+\t\t\t$.ajax({\n
+\t\t\t\turl: fileUrl,\n
+\t\t\t\ttype: settings.type,\n
+\t\t\t\tdata: settings.data,\n
+\t\t\t\tcontentType: settings.contentType,\n
+\t\t\t\tdataType: "html",\n
+\t\t\t\tsuccess: this._loadSuccess( absUrl, triggerData, settings, deferred ),\n
+\t\t\t\terror: this._loadError( absUrl, triggerData, settings, deferred )\n
+\t\t\t});\n
+\t\t},\n
+\n
+\t\t_loadError: function( absUrl, triggerData, settings, deferred ) {\n
+\t\t\treturn $.proxy(function( xhr, textStatus, errorThrown ) {\n
+\t\t\t\t//set base back to current path\n
+\t\t\t\tthis._getBase().set( path.get() );\n
+\n
+\t\t\t\t// Add error info to our triggerData.\n
+\t\t\t\ttriggerData.xhr = xhr;\n
+\t\t\t\ttriggerData.textStatus = textStatus;\n
+\t\t\t\ttriggerData.errorThrown = errorThrown;\n
+\n
+\t\t\t\t// Let listeners know the page load failed.\n
+\t\t\t\tvar plfEvent = this._triggerWithDeprecated( "loadfailed", triggerData );\n
+\n
+\t\t\t\t// If the default behavior is prevented, stop here!\n
+\t\t\t\t// Note that it is the responsibility of the listener/handler\n
+\t\t\t\t// that called preventDefault(), to resolve/reject the\n
+\t\t\t\t// deferred object within the triggerData.\n
+\t\t\t\tif ( plfEvent.deprecatedEvent.isDefaultPrevented() ||\n
+\t\t\t\t\tplfEvent.event.isDefaultPrevented() ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Remove loading message.\n
+\t\t\t\tif ( settings.showLoadMsg ) {\n
+\t\t\t\t\tthis._showError();\n
+\t\t\t\t}\n
+\n
+\t\t\t\tdeferred.reject( absUrl, settings );\n
+\t\t\t}, this);\n
+\t\t},\n
+\n
+\t\t_getTransitionHandler: function( transition ) {\n
+\t\t\ttransition = $.mobile._maybeDegradeTransition( transition );\n
+\n
+\t\t\t//find the transition handler for the specified transition. If there\n
+\t\t\t//isn\'t one in our transitionHandlers dictionary, use the default one.\n
+\t\t\t//call the handler immediately to kick-off the transition.\n
+\t\t\treturn $.mobile.transitionHandlers[ transition ] || $.mobile.defaultTransitionHandler;\n
+\t\t},\n
+\n
+\t\t// TODO move into transition handlers?\n
+\t\t_triggerCssTransitionEvents: function( to, from, prefix ) {\n
+\t\t\tprefix = prefix || "";\n
+\n
+\t\t\t// TODO decide if these events should in fact be triggered on the container\n
+\t\t\tif ( from ) {\n
+\t\t\t\t//trigger before show/hide events\n
+\t\t\t\t// TODO deprecate nextPage in favor of next\n
+\t\t\t\tthis._triggerWithDeprecated( prefix + "hide", {nextPage: to}, from );\n
+\t\t\t}\n
+\n
+\t\t\t// TODO deprecate prevPage in favor of previous\n
+\t\t\tthis._triggerWithDeprecated( prefix + "show", {prevPage: from || $( "" )}, to );\n
+\t\t},\n
+\n
+\t\t// TODO make private once change has been defined in the widget\n
+\t\t_cssTransition: function( to, from, options ) {\n
+\t\t\tvar transition = options.transition,\n
+\t\t\t\treverse = options.reverse,\n
+\t\t\t\tdeferred = options.deferred,\n
+\t\t\t\tTransitionHandler,\n
+\t\t\t\tpromise;\n
+\n
+\t\t\tthis._triggerCssTransitionEvents( to, from, "before" );\n
+\n
+\t\t\t// TODO put this in a binding to events *outside* the widget\n
+\t\t\tthis._hideLoading();\n
+\n
+\t\t\tTransitionHandler = this._getTransitionHandler( transition );\n
+\n
+\t\t\tpromise = (new TransitionHandler( transition, reverse, to, from )).transition();\n
+\n
+\t\t\t// TODO temporary accomodation of argument deferred\n
+\t\t\tpromise.done(function() {\n
+\t\t\t\tdeferred.resolve.apply(deferred, arguments);\n
+\t\t\t});\n
+\n
+\t\t\tpromise.done($.proxy(function() {\n
+\t\t\t\tthis._triggerCssTransitionEvents( to, from );\n
+\t\t\t}, this));\n
+\t\t},\n
+\n
+\t\t_releaseTransitionLock: function() {\n
+\t\t\t//release transition lock so navigation is free again\n
+\t\t\treleasePageTransitionLock();\n
+\t\t},\n
+\n
+\t\t_removeActiveLinkClass: function( force ) {\n
+\t\t\t//clear out the active button state\n
+\t\t\tremoveActiveLinkClass( force );\n
+\t\t},\n
+\n
+\t\t_loadUrl: function( to, triggerData, settings ) {\n
+\t\t\t// preserve the original target as the dataUrl value will be\n
+\t\t\t// simplified eg, removing ui-state, and removing query params\n
+\t\t\t// from the hash this is so that users who want to use query\n
+\t\t\t// params have access to them in the event bindings for the page\n
+\t\t\t// life cycle See issue #5085\n
+\t\t\tsettings.target = to;\n
+\t\t\tsettings.deferred = $.Deferred();\n
+\n
+\t\t\tthis.load( to, settings );\n
+\n
+\t\t\tsettings.deferred.done($.proxy(function( url, options, content ) {\n
+\t\t\t\tisPageTransitioning = false;\n
+\n
+\t\t\t\t// store the original absolute url so that it can be provided\n
+\t\t\t\t// to events in the triggerData of the subsequent changePage call\n
+\t\t\t\toptions.absUrl = triggerData.absUrl;\n
+\n
+\t\t\t\tthis.transition( content, triggerData, options );\n
+\t\t\t}, this));\n
+\n
+\t\t\tsettings.deferred.fail($.proxy(function(/* url, options */) {\n
+\t\t\t\tthis._removeActiveLinkClass( true );\n
+\t\t\t\tthis._releaseTransitionLock();\n
+\t\t\t\tthis._triggerWithDeprecated( "changefailed", triggerData );\n
+\t\t\t}, this));\n
+\t\t},\n
+\n
+\t\t_triggerPageBeforeChange: function( to, triggerData, settings ) {\n
+\t\t\tvar pbcEvent = new $.Event( "pagebeforechange" );\n
+\n
+\t\t\t$.extend(triggerData, { toPage: to, options: settings });\n
+\n
+\t\t\t// NOTE: preserve the original target as the dataUrl value will be\n
+\t\t\t// simplified eg, removing ui-state, and removing query params from\n
+\t\t\t// the hash this is so that users who want to use query params have\n
+\t\t\t// access to them in the event bindings for the page life cycle\n
+\t\t\t// See issue #5085\n
+\t\t\tif ( $.type(to) === "string" ) {\n
+\t\t\t\t// if the toPage is a string simply convert it\n
+\t\t\t\ttriggerData.absUrl = path.makeUrlAbsolute( to, findBaseWithDefault() );\n
+\t\t\t} else {\n
+\t\t\t\t// if the toPage is a jQuery object grab the absolute url stored\n
+\t\t\t\t// in the loadPage callback where it exists\n
+\t\t\t\ttriggerData.absUrl = settings.absUrl;\n
+\t\t\t}\n
+\n
+\t\t\t// Let listeners know we\'re about to change the current page.\n
+\t\t\tthis.element.trigger( pbcEvent, triggerData );\n
+\n
+\t\t\t// If the default behavior is prevented, stop here!\n
+\t\t\tif ( pbcEvent.isDefaultPrevented() ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\n
+\t\t\treturn true;\n
+\t\t},\n
+\n
+\t\tchange: function( to, options ) {\n
+\t\t\t// If we are in the midst of a transition, queue the current request.\n
+\t\t\t// We\'ll call changePage() once we\'re done with the current transition\n
+\t\t\t// to service the request.\n
+\t\t\tif ( isPageTransitioning ) {\n
+\t\t\t\tpageTransitionQueue.unshift( arguments );\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tvar settings = $.extend( {}, $.mobile.changePage.defaults, options ),\n
+\t\t\t\ttriggerData = {};\n
+\n
+\t\t\t// Make sure we have a fromPage.\n
+\t\t\tsettings.fromPage = settings.fromPage || $.mobile.activePage;\n
+\n
+\t\t\t// if the page beforechange default is prevented return early\n
+\t\t\tif ( !this._triggerPageBeforeChange(to, triggerData, settings) ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// We allow "pagebeforechange" observers to modify the to in\n
+\t\t\t// the trigger data to allow for redirects. Make sure our to is\n
+\t\t\t// updated. We also need to re-evaluate whether it is a string,\n
+\t\t\t// because an object can also be replaced by a string\n
+\t\t\tto = triggerData.toPage;\n
+\n
+\t\t\t// If the caller passed us a url, call loadPage()\n
+\t\t\t// to make sure it is loaded into the DOM. We\'ll listen\n
+\t\t\t// to the promise object it returns so we know when\n
+\t\t\t// it is done loading or if an error ocurred.\n
+\t\t\tif ( $.type(to) === "string" ) {\n
+\t\t\t\t// Set the isPageTransitioning flag to prevent any requests from\n
+\t\t\t\t// entering this method while we are in the midst of loading a page\n
+\t\t\t\t// or transitioning.\n
+\t\t\t\tisPageTransitioning = true;\n
+\n
+\t\t\t\tthis._loadUrl( to, triggerData, settings );\n
+\t\t\t} else {\n
+\t\t\t\tthis.transition( to, triggerData, settings );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\ttransition: function( toPage, triggerData, settings ) {\n
+\t\t\tvar fromPage, url, pageUrl, fileUrl,\n
+\t\t\t\tactive, activeIsInitialPage,\n
+\t\t\t\thistoryDir, pageTitle, isDialog,\n
+\t\t\t\talreadyThere, newPageTitle,\n
+\t\t\t\tparams,\tcssTransitionDeferred,\n
+\t\t\t\tbeforeTransition;\n
+\n
+\t\t\t// If we are in the midst of a transition, queue the current request.\n
+\t\t\t// We\'ll call changePage() once we\'re done with the current transition\n
+\t\t\t// to service the request.\n
+\t\t\tif ( isPageTransitioning ) {\n
+\t\t\t\t// make sure to only queue the to and settings values so the arguments\n
+\t\t\t\t// work with a call to the change method\n
+\t\t\t\tpageTransitionQueue.unshift( [toPage, settings] );\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// DEPRECATED - this call only, in favor of the before transition\n
+\t\t\t// if the page beforechange default is prevented return early\n
+\t\t\tif ( !this._triggerPageBeforeChange(toPage, triggerData, settings) ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// if the (content|page)beforetransition default is prevented return early\n
+\t\t\t// Note, we have to check for both the deprecated and new events\n
+\t\t\tbeforeTransition = this._triggerWithDeprecated( "beforetransition", triggerData );\n
+\t\t\tif (beforeTransition.deprecatedEvent.isDefaultPrevented() ||\n
+\t\t\t\tbeforeTransition.event.isDefaultPrevented() ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// Set the isPageTransitioning flag to prevent any requests from\n
+\t\t\t// entering this method while we are in the midst of loading a page\n
+\t\t\t// or transitioning.\n
+\t\t\tisPageTransitioning = true;\n
+\n
+\t\t\t// If we are going to the first-page of the application, we need to make\n
+\t\t\t// sure settings.dataUrl is set to the application document url. This allows\n
+\t\t\t// us to avoid generating a document url with an id hash in the case where the\n
+\t\t\t// first-page of the document has an id attribute specified.\n
+\t\t\tif ( toPage[ 0 ] === $.mobile.firstPage[ 0 ] && !settings.dataUrl ) {\n
+\t\t\t\tsettings.dataUrl = documentUrl.hrefNoHash;\n
+\t\t\t}\n
+\n
+\t\t\t// The caller passed us a real page DOM element. Update our\n
+\t\t\t// internal state and then trigger a transition to the page.\n
+\t\t\tfromPage = settings.fromPage;\n
+\t\t\turl = ( settings.dataUrl && path.convertUrlToDataUrl(settings.dataUrl) ) ||\n
+\t\t\t\ttoPage.jqmData( "url" );\n
+\n
+\t\t\t// The pageUrl var is usually the same as url, except when url is obscured\n
+\t\t\t// as a dialog url. pageUrl always contains the file path\n
+\t\t\tpageUrl = url;\n
+\t\t\tfileUrl = path.getFilePath( url );\n
+\t\t\tactive = urlHistory.getActive();\n
+\t\t\tactiveIsInitialPage = urlHistory.activeIndex === 0;\n
+\t\t\thistoryDir = 0;\n
+\t\t\tpageTitle = document.title;\n
+\t\t\tisDialog = ( settings.role === "dialog" || toPage.jqmData( "role" ) === "dialog" ) && toPage.jqmData( "dialog" ) !== true;\n
+\n
+\t\t\t// By default, we prevent changePage requests when the fromPage and toPage\n
+\t\t\t// are the same element, but folks that generate content manually/dynamically\n
+\t\t\t// and reuse pages want to be able to transition to the same page. To allow\n
+\t\t\t// this, they will need to change the default value of allowSamePageTransition\n
+\t\t\t// to true, *OR*, pass it in as an option when they manually call changePage().\n
+\t\t\t// It should be noted that our default transition animations assume that the\n
+\t\t\t// formPage and toPage are different elements, so they may behave unexpectedly.\n
+\t\t\t// It is up to the developer that turns on the allowSamePageTransitiona option\n
+\t\t\t// to either turn off transition animations, or make sure that an appropriate\n
+\t\t\t// animation transition is used.\n
+\t\t\tif ( fromPage && fromPage[0] === toPage[0] && !settings.allowSamePageTransition ) {\n
+\t\t\t\tisPageTransitioning = false;\n
+\t\t\t\tthis._triggerWithDeprecated( "transition", triggerData );\n
+\t\t\t\tthis.element.trigger( "pagechange", triggerData );\n
+\n
+\t\t\t\t// Even if there is no page change to be done, we should keep the urlHistory\n
+\t\t\t\t// in sync with the hash changes\n
+\t\t\t\tif ( settings.fromHashChange ) {\n
+\t\t\t\t\turlHistory.direct({ url: url });\n
+\t\t\t\t}\n
+\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// We need to make sure the page we are given has already been enhanced.\n
+\t\t\ttoPage.page({ role: settings.role });\n
+\n
+\t\t\t// If the changePage request was sent from a hashChange event, check to see if the\n
+\t\t\t// page is already within the urlHistory stack. If so, we\'ll assume the user hit\n
+\t\t\t// the forward/back button and will try to match the transition accordingly.\n
+\t\t\tif ( settings.fromHashChange ) {\n
+\t\t\t\thistoryDir = settings.direction === "back" ? -1 : 1;\n
+\t\t\t}\n
+\n
+\t\t\t// Kill the keyboard.\n
+\t\t\t// XXX_jblas: We need to stop crawling the entire document to kill focus. Instead,\n
+\t\t\t//            we should be tracking focus with a delegate() handler so we already have\n
+\t\t\t//            the element in hand at this point.\n
+\t\t\t// Wrap this in a try/catch block since IE9 throw "Unspecified error" if document.activeElement\n
+\t\t\t// 
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="4" aka="AAAAAAAAAAQ=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+is undefined when we are in an IFrame.\n
+\t\t\ttry {\n
+\t\t\t\tif ( document.activeElement && document.activeElement.nodeName.toLowerCase() !== "body" ) {\n
+\t\t\t\t\t$( document.activeElement ).blur();\n
+\t\t\t\t} else {\n
+\t\t\t\t\t$( "input:focus, textarea:focus, select:focus" ).blur();\n
+\t\t\t\t}\n
+\t\t\t} catch( e ) {}\n
+\n
+\t\t\t// Record whether we are at a place in history where a dialog used to be - if so, do not add a new history entry and do not change the hash either\n
+\t\t\talreadyThere = false;\n
+\n
+\t\t\t// If we\'re displaying the page as a dialog, we don\'t want the url\n
+\t\t\t// for the dialog content to be used in the hash. Instead, we want\n
+\t\t\t// to append the dialogHashKey to the url of the current page.\n
+\t\t\tif ( isDialog && active ) {\n
+\t\t\t\t// on the initial page load active.url is undefined and in that case should\n
+\t\t\t\t// be an empty string. Moving the undefined -> empty string back into\n
+\t\t\t\t// urlHistory.addNew seemed imprudent given undefined better represents\n
+\t\t\t\t// the url state\n
+\n
+\t\t\t\t// If we are at a place in history that once belonged to a dialog, reuse\n
+\t\t\t\t// this state without adding to urlHistory and without modifying the hash.\n
+\t\t\t\t// However, if a dialog is already displayed at this point, and we\'re\n
+\t\t\t\t// about to display another dialog, then we must add another hash and\n
+\t\t\t\t// history entry on top so that one may navigate back to the original dialog\n
+\t\t\t\tif ( active.url &&\n
+\t\t\t\t\t active.url.indexOf( dialogHashKey ) > -1 &&\n
+\t\t\t\t\t $.mobile.activePage &&\n
+\t\t\t\t\t !$.mobile.activePage.hasClass( "ui-dialog" ) &&\n
+\t\t\t\t\t urlHistory.activeIndex > 0 ) {\n
+\t\t\t\t\tsettings.changeHash = false;\n
+\t\t\t\t\talreadyThere = true;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Normally, we tack on a dialog hash key, but if this is the location of a stale dialog,\n
+\t\t\t\t// we reuse the URL from the entry\n
+\t\t\t\turl = ( active.url || "" );\n
+\n
+\t\t\t\t// account for absolute urls instead of just relative urls use as hashes\n
+\t\t\t\tif ( !alreadyThere && url.indexOf("#") > -1 ) {\n
+\t\t\t\t\turl += dialogHashKey;\n
+\t\t\t\t} else {\n
+\t\t\t\t\turl += "#" + dialogHashKey;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// tack on another dialogHashKey if this is the same as the initial hash\n
+\t\t\t\t// this makes sure that a history entry is created for this dialog\n
+\t\t\t\tif ( urlHistory.activeIndex === 0 && url === urlHistory.initialDst ) {\n
+\t\t\t\t\turl += dialogHashKey;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// if title element wasn\'t found, try the page div data attr too\n
+\t\t\t// If this is a deep-link or a reload ( active === undefined ) then just use pageTitle\n
+\t\t\tnewPageTitle = ( !active )? pageTitle : toPage.jqmData( "title" ) || toPage.children( ":jqmData(role=\'header\')" ).find( ".ui-title" ).text();\n
+\t\t\tif ( !!newPageTitle && pageTitle === document.title ) {\n
+\t\t\t\tpageTitle = newPageTitle;\n
+\t\t\t}\n
+\t\t\tif ( !toPage.jqmData( "title" ) ) {\n
+\t\t\t\ttoPage.jqmData( "title", pageTitle );\n
+\t\t\t}\n
+\n
+\t\t\t// Make sure we have a transition defined.\n
+\t\t\tsettings.transition = settings.transition ||\n
+\t\t\t\t( ( historyDir && !activeIsInitialPage ) ? active.transition : undefined ) ||\n
+\t\t\t\t( isDialog ? $.mobile.defaultDialogTransition : $.mobile.defaultPageTransition );\n
+\n
+\t\t\t//add page to history stack if it\'s not back or forward\n
+\t\t\tif ( !historyDir && alreadyThere ) {\n
+\t\t\t\turlHistory.getActive().pageUrl = pageUrl;\n
+\t\t\t}\n
+\n
+\t\t\t// Set the location hash.\n
+\t\t\tif ( url && !settings.fromHashChange ) {\n
+\n
+\t\t\t\t// rebuilding the hash here since we loose it earlier on\n
+\t\t\t\t// TODO preserve the originally passed in path\n
+\t\t\t\tif ( !path.isPath( url ) && url.indexOf( "#" ) < 0 ) {\n
+\t\t\t\t\turl = "#" + url;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// TODO the property names here are just silly\n
+\t\t\t\tparams = {\n
+\t\t\t\t\ttransition: settings.transition,\n
+\t\t\t\t\ttitle: pageTitle,\n
+\t\t\t\t\tpageUrl: pageUrl,\n
+\t\t\t\t\trole: settings.role\n
+\t\t\t\t};\n
+\n
+\t\t\t\tif ( settings.changeHash !== false && $.mobile.hashListeningEnabled ) {\n
+\t\t\t\t\t$.mobile.navigate( url, params, true);\n
+\t\t\t\t} else if ( toPage[ 0 ] !== $.mobile.firstPage[ 0 ] ) {\n
+\t\t\t\t\t$.mobile.navigate.history.add( url, params );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t//set page title\n
+\t\t\tdocument.title = pageTitle;\n
+\n
+\t\t\t//set "toPage" as activePage\n
+\t\t\t$.mobile.activePage = toPage;\n
+\n
+\t\t\t// If we\'re navigating back in the URL history, set reverse accordingly.\n
+\t\t\tsettings.reverse = settings.reverse || historyDir < 0;\n
+\n
+\t\t\tcssTransitionDeferred = $.Deferred();\n
+\n
+\t\t\tthis._cssTransition(toPage, fromPage, {\n
+\t\t\t\ttransition: settings.transition,\n
+\t\t\t\treverse: settings.reverse,\n
+\t\t\t\tdeferred: cssTransitionDeferred\n
+\t\t\t});\n
+\n
+\t\t\tcssTransitionDeferred.done($.proxy(function( name, reverse, $to, $from, alreadyFocused ) {\n
+\t\t\t\tremoveActiveLinkClass();\n
+\n
+\t\t\t\t//if there\'s a duplicateCachedPage, remove it from the DOM now that it\'s hidden\n
+\t\t\t\tif ( settings.duplicateCachedPage ) {\n
+\t\t\t\t\tsettings.duplicateCachedPage.remove();\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// despite visibility: hidden addresses issue #2965\n
+\t\t\t\t// https://github.com/jquery/jquery-mobile/issues/2965\n
+\t\t\t\tif ( !alreadyFocused ) {\n
+\t\t\t\t\t$.mobile.focusPage( toPage );\n
+\t\t\t\t}\n
+\n
+\t\t\t\treleasePageTransitionLock();\n
+\t\t\t\tthis.element.trigger( "pagechange", triggerData );\n
+\t\t\t\tthis._triggerWithDeprecated( "transition", triggerData );\n
+\t\t\t}, this));\n
+\t\t}\n
+\t\t// TODO resetActivePageHeight\n
+\t\t// TODO changePage\n
+\t});\n
+\n
+\t$.mobile.loadPage = function( url, opts ) {\n
+\t\tvar container;\n
+\n
+\t\topts = opts || {};\n
+\t\tcontainer = ( opts.pageContainer || $.mobile.pageContainer );\n
+\n
+\t\t// create the deferred that will be supplied to loadPage callers\n
+\t\t// and resolved by the content widget\'s load method\n
+\t\topts.deferred = $.Deferred();\n
+\n
+\t\t// Preferring to allow exceptions for uninitialized opts.pageContainer\n
+\t\t// widgets so we know if we need to force init here for users\n
+\t\tcontainer.content( "load", url, opts );\n
+\n
+\t\t// provide the deferred\n
+\t\treturn opts.deferred.promise();\n
+\t};\n
+\n
+\t//define vars for interal use\n
+\tvar $window = $.mobile.window,\n
+\t\t$head = $( "head" ),\n
+\n
+\t\t// NOTE: path extensions dependent on core attributes. Moved here to remove deps from\n
+\t\t//       $.mobile.path definition\n
+\t\tpath = $.extend($.mobile.path, {\n
+\n
+\t\t\t//return the substring of a filepath before the sub-page key, for making a server request\n
+\t\t\tgetFilePath: function( path ) {\n
+\t\t\t\tvar splitkey = "&" + $.mobile.subPageUrlKey;\n
+\t\t\t\treturn path && path.split( splitkey )[0].split( dialogHashKey )[0];\n
+\t\t\t},\n
+\n
+\t\t\t//check if the specified url refers to the first page in the main application document.\n
+\t\t\tisFirstPageUrl: function( url ) {\n
+\t\t\t\t// We only deal with absolute paths.\n
+\t\t\t\tvar u = path.parseUrl( path.makeUrlAbsolute( url, this.documentBase ) ),\n
+\n
+\t\t\t\t\t// Does the url have the same path as the document?\n
+\t\t\t\t\tsamePath = u.hrefNoHash === this.documentUrl.hrefNoHash || ( this.documentBaseDiffers && u.hrefNoHash === this.documentBase.hrefNoHash ),\n
+\n
+\t\t\t\t\t// Get the first page element.\n
+\t\t\t\t\tfp = $.mobile.firstPage,\n
+\n
+\n
+\n
+\t\t\t\t\t// Get the id of the first page element if it has one.\n
+\t\t\t\t\tfpId = fp && fp[0] ? fp[0].id : undefined;\n
+\n
+\t\t\t\t// The url refers to the first page if the path matches the document and\n
+\t\t\t\t// it either has no hash value, or the hash is exactly equal to the id of the\n
+\t\t\t\t// first page element.\n
+\t\t\t\treturn samePath && ( !u.hash || u.hash === "#" || ( fpId && u.hash.replace( /^#/, "" ) === fpId ) );\n
+\t\t\t},\n
+\n
+\t\t\t// Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR\n
+\t\t\t// requests if the document doing the request was loaded via the file:// protocol.\n
+\t\t\t// This is usually to allow the application to "phone home" and fetch app specific\n
+\t\t\t// data. We normally let the browser handle external/cross-domain urls, but if the\n
+\t\t\t// allowCrossDomainPages option is true, we will allow cross-domain http/https\n
+\t\t\t// requests to go through our page loading logic.\n
+\t\t\tisPermittedCrossDomainRequest: function( docUrl, reqUrl ) {\n
+\t\t\t\treturn $.mobile.allowCrossDomainPages &&\n
+\t\t\t\t\t(docUrl.protocol === "file:" || docUrl.protocol === "content:") &&\n
+\t\t\t\t\treqUrl.search( /^https?:/ ) !== -1;\n
+\t\t\t}\n
+\t\t}),\n
+\n
+\t\t// used to track last vclicked element to make sure its value is added to form data\n
+\t\t$lastVClicked = null,\n
+\n
+\t\t//will be defined when a link is clicked and given an active class\n
+\t\t$activeClickedLink = null,\n
+\n
+\t\t// resolved on domready\n
+\t\tdomreadyDeferred = $.Deferred(),\n
+\n
+\t\t//urlHistory is purely here to make guesses at whether the back or forward button was clicked\n
+\t\t//and provide an appropriate transition\n
+\t\turlHistory = $.mobile.navigate.history,\n
+\n
+\t\t//queue to hold simultanious page transitions\n
+\t\tpageTransitionQueue = [],\n
+\n
+\t\t//indicates whether or not page is in process of transitioning\n
+\t\tisPageTransitioning = false,\n
+\n
+\t\t//nonsense hash change key for dialogs, so they create a history entry\n
+\t\tdialogHashKey = "&ui-state=dialog",\n
+\n
+\t\t//existing base tag?\n
+\t\t$base = $head.children( "base" ),\n
+\n
+\t\t//tuck away the original document URL minus any fragment.\n
+\t\tdocumentUrl = path.documentUrl,\n
+\n
+\t\t//if the document has an embedded base tag, documentBase is set to its\n
+\t\t//initial value. If a base tag does not exist, then we default to the documentUrl.\n
+\t\tdocumentBase = path.documentBase,\n
+\n
+\t\t// base element management, defined depending on dynamic base tag support\n
+\t\t// TODO move to external widget\n
+\t\tbase = {\n
+\t\t\t//define base element, for use in routing asset urls that are referenced in Ajax-requested markup\n
+\t\t\telement: ( $base.length ? $base : $( "<base>", { href: documentBase.hrefNoHash } ).prependTo( $head ) ),\n
+\n
+\t\t\tlinkSelector: "[src], link[href], a[rel=\'external\'], :jqmData(ajax=\'false\'), a[target]",\n
+\n
+\t\t\t//set the generated BASE element\'s href attribute to a new page\'s base path\n
+\t\t\tset: function( href ) {\n
+\t\t\t\t// we should do nothing if the user wants to manage their url base manually\n
+\t\t\t\tif ( !$.mobile.dynamicBaseEnabled ){\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// we should use the base tag if we can manipulate it dynamically\n
+\t\t\t\tif ( $.support.dynamicBaseTag ){\n
+\t\t\t\t\tbase.element.attr( "href", path.makeUrlAbsolute( href, documentBase ) );\n
+\t\t\t\t}\n
+\t\t\t},\n
+\n
+\t\t\trewrite: function( href, page ) {\n
+\t\t\t\tvar newPath = path.get( href );\n
+\n
+\t\t\t\tpage.find( base.linkSelector ).each(function( i, link ) {\n
+\t\t\t\t\tvar thisAttr = $( link ).is( "[href]" ) ? "href" : $( link ).is( "[src]" ) ? "src" : "action",\n
+\t\t\t\t\tthisUrl = $( link ).attr( thisAttr );\n
+\n
+\t\t\t\t\t// XXX_jblas: We need to fix this so that it removes the document\n
+\t\t\t\t\t//            base URL, and then prepends with the new page URL.\n
+\t\t\t\t\t//if full path exists and is same, chop it - helps IE out\n
+\t\t\t\t\tthisUrl = thisUrl.replace( location.protocol + "//" + location.host + location.pathname, "" );\n
+\n
+\t\t\t\t\tif ( !/^(\\w+:|#|\\/)/.test( thisUrl ) ) {\n
+\t\t\t\t\t\t$( link ).attr( thisAttr, newPath + thisUrl );\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t},\n
+\n
+\t\t\t//set the generated BASE element\'s href attribute to a new page\'s base path\n
+\t\t\treset: function(/* href */) {\n
+\t\t\t\tbase.element.attr( "href", documentBase.hrefNoSearch );\n
+\t\t\t}\n
+\t\t};\n
+\n
+\t//return the original document url\n
+\t$.mobile.getDocumentUrl = path.getDocumentUrl;\n
+\n
+\t//return the original document base url\n
+\t$.mobile.getDocumentBase = path.getDocumentBase;\n
+\n
+\t/* internal utility functions */\n
+\n
+\t// NOTE Issue #4950 Android phonegap doesn\'t navigate back properly\n
+\t//      when a full page refresh has taken place. It appears that hashchange\n
+\t//      and replacestate history alterations work fine but we need to support\n
+\t//      both forms of history traversal in our code that uses backward history\n
+\t//      movement\n
+\t$.mobile.back = function() {\n
+\t\tvar nav = window.navigator;\n
+\n
+\t\t// if the setting is on and the navigator object is\n
+\t\t// available use the phonegap navigation capability\n
+\t\tif ( this.phonegapNavigationEnabled &&\n
+\t\t\tnav &&\n
+\t\t\tnav.app &&\n
+\t\t\tnav.app.backHistory ){\n
+\t\t\tnav.app.backHistory();\n
+\t\t} else {\n
+\t\t\twindow.history.back();\n
+\t\t}\n
+\t};\n
+\n
+\t//direct focus to the page title, or otherwise first focusable element\n
+\t$.mobile.focusPage = function ( page ) {\n
+\t\tvar autofocus = page.find( "[autofocus]" ),\n
+\t\t\tpageTitle = page.find( ".ui-title:eq(0)" );\n
+\n
+\t\tif ( autofocus.length ) {\n
+\t\t\tautofocus.focus();\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( pageTitle.length ) {\n
+\t\t\tpageTitle.focus();\n
+\t\t} else{\n
+\t\t\tpage.focus();\n
+\t\t}\n
+\t};\n
+\n
+\t//remove active classes after page transition or error\n
+\tfunction removeActiveLinkClass( forceRemoval ) {\n
+\t\tif ( !!$activeClickedLink && ( !$activeClickedLink.closest( "." + $.mobile.activePageClass ).length || forceRemoval ) ) {\n
+\t\t\t$activeClickedLink.removeClass( $.mobile.activeBtnClass );\n
+\t\t}\n
+\t\t$activeClickedLink = null;\n
+\t}\n
+\n
+\tfunction releasePageTransitionLock() {\n
+\t\tisPageTransitioning = false;\n
+\t\tif ( pageTransitionQueue.length > 0 ) {\n
+\t\t\t$.mobile.changePage.apply( null, pageTransitionQueue.pop() );\n
+\t\t}\n
+\t}\n
+\n
+\t// No-op implementation of transition degradation\n
+\t$.mobile._maybeDegradeTransition = $.mobile._maybeDegradeTransition || function( transition ) {\n
+\t\treturn transition;\n
+\t};\n
+\n
+\t// determine the current base url\n
+\tfunction findBaseWithDefault() {\n
+\t\tvar closestBase = ( $.mobile.activePage && getClosestBaseUrl( $.mobile.activePage ) );\n
+\t\treturn closestBase || documentBase.hrefNoHash;\n
+\t}\n
+\n
+\t/* exposed $.mobile methods */\n
+\n
+\t//animation complete callback\n
+\t$.fn.animationComplete = function( callback ) {\n
+\t\tif ( $.support.cssTransitions ) {\n
+\t\t\treturn $( this ).one( "webkitAnimationEnd animationend", callback );\n
+\t\t}\n
+\t\telse{\n
+\t\t\t// defer execution for consistency between webkit/non webkit\n
+\t\t\tsetTimeout( callback, 0 );\n
+\t\t\treturn $( this );\n
+\t\t}\n
+\t};\n
+\n
+\t//expose path object on $.mobile\n
+\t$.mobile.path = path;\n
+\n
+\t//expose base object on $.mobile\n
+\t$.mobile.base = base;\n
+\n
+\t//history stack\n
+\t$.mobile.urlHistory = urlHistory;\n
+\n
+\t$.mobile.dialogHashKey = dialogHashKey;\n
+\n
+\t//enable cross-domain page support\n
+\t$.mobile.allowCrossDomainPages = false;\n
+\n
+\t$.mobile.changePage = function( to, options ) {\n
+\t\t$.mobile.pageContainer.content( "change", to, options );\n
+\t};\n
+\n
+\t$.mobile.changePage.defaults = {\n
+\t\ttransition: undefined,\n
+\t\treverse: false,\n
+\t\tchangeHash: true,\n
+\t\tfromHashChange: false,\n
+\t\trole: undefined, // By default we rely on the role defined by the @data-role attribute.\n
+\t\tduplicateCachedPage: undefined,\n
+\t\tpageContainer: undefined,\n
+\t\tshowLoadMsg: true, //loading message shows by default when pages are being fetched during changePage\n
+\t\tdataUrl: undefined,\n
+\t\tfromPage: undefined,\n
+\t\tallowSamePageTransition: false\n
+\t};\n
+\n
+\t/* Event Bindings - hashchange, submit, and click */\n
+\tfunction findClosestLink( ele )\t{\n
+\t\twhile ( ele ) {\n
+\t\t\t// Look for the closest element with a nodeName of "a".\n
+\t\t\t// Note that we are checking if we have a valid nodeName\n
+\t\t\t// before attempting to access it. This is because the\n
+\t\t\t// node we get called with could have originated from within\n
+\t\t\t// an embedded SVG document where some symbol instance elements\n
+\t\t\t// don\'t have nodeName defined on them, or strings are of type\n
+\t\t\t// SVGAnimatedString.\n
+\t\t\tif ( ( typeof ele.nodeName === "string" ) && ele.nodeName.toLowerCase() === "a" ) {\n
+\t\t\t\tbreak;\n
+\t\t\t}\n
+\t\t\tele = ele.parentNode;\n
+\t\t}\n
+\t\treturn ele;\n
+\t}\n
+\n
+\t// The base URL for any given element depends on the page it resides in.\n
+\tfunction getClosestBaseUrl( ele )\t{\n
+\t\t// Find the closest page and extract out its url.\n
+\t\tvar url = $( ele ).closest( ".ui-page" ).jqmData( "url" ),\n
+\t\t\tbase = documentBase.hrefNoHash;\n
+\n
+\t\tif ( !$.mobile.dynamicBaseEnabled || !url || !path.isPath( url ) ) {\n
+\t\t\turl = base;\n
+\t\t}\n
+\n
+\t\treturn path.makeUrlAbsolute( url, base );\n
+\t}\n
+\n
+\t//The following event bindings should be bound after mobileinit has been triggered\n
+\t//the following deferred is resolved in the init file\n
+\t$.mobile.navreadyDeferred = $.Deferred();\n
+\t$.mobile._registerInternalEvents = function() {\n
+\t\tvar getAjaxFormData = function( $form, calculateOnly ) {\n
+\t\t\tvar url, ret = true, formData, vclickedName, method;\n
+\t\t\tif ( !$.mobile.ajaxEnabled ||\n
+\t\t\t\t\t// test that the form is, itself, ajax false\n
+\t\t\t\t\t$form.is( ":jqmData(ajax=\'false\')" ) ||\n
+\t\t\t\t\t// test that $.mobile.ignoreContentEnabled is set and\n
+\t\t\t\t\t// the form or one of it\'s parents is ajax=false\n
+\t\t\t\t\t!$form.jqmHijackable().length ||\n
+\t\t\t\t\t$form.attr( "target" ) ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\n
+\t\t\turl = ( $lastVClicked && $lastVClicked.attr( "formaction" ) ) ||\n
+\t\t\t\t$form.attr( "action" );\n
+\t\t\tmethod = ( $form.attr( "method" ) || "get" ).toLowerCase();\n
+\n
+\t\t\t// If no action is specified, browsers default to using the\n
+\t\t\t// URL of the document containing the form. Since we dynamically\n
+\t\t\t// pull in pages from external documents, the form should submit\n
+\t\t\t// to the URL for the source document of the page containing\n
+\t\t\t// the form.\n
+\t\t\tif ( !url ) {\n
+\t\t\t\t// Get the @data-url for the page containing the form.\n
+\t\t\t\turl = getClosestBaseUrl( $form );\n
+\n
+\t\t\t\t// NOTE: If the method is "get", we need to strip off the query string\n
+\t\t\t\t// because it will get replaced with the new form data. See issue #5710.\n
+\t\t\t\tif ( method === "get" ) {\n
+\t\t\t\t\turl = path.parseUrl( url ).hrefNoSearch;\n
+\t\t\t\t}\n
+\n
+\t\t\t\tif ( url === documentBase.hrefNoHash ) {\n
+\t\t\t\t\t// The url we got back matches the document base,\n
+\t\t\t\t\t// which means the page must be an internal/embedded page,\n
+\t\t\t\t\t// so default to using the actual document url as a browser\n
+\t\t\t\t\t// would.\n
+\t\t\t\t\turl = documentUrl.hrefNoSearch;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\turl = path.makeUrlAbsolute(  url, getClosestBaseUrl( $form ) );\n
+\n
+\t\t\tif ( ( path.isExternal( url ) && !path.isPermittedCrossDomainRequest( documentUrl, url ) ) ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\n
+\t\t\tif ( !calculateOnly ) {\n
+\t\t\t\tformData = $form.serializeArray();\n
+\n
+\t\t\t\tif ( $lastVClicked && $lastVClicked[ 0 ].form === $form[ 0 ] ) {\n
+\t\t\t\t\tvclickedName = $lastVClicked.attr( "name" );\n
+\t\t\t\t\tif ( vclickedName ) {\n
+\t\t\t\t\t\t// Make sure the last clicked element is included in the form\n
+\t\t\t\t\t\t$.each( formData, function( key, value ) {\n
+\t\t\t\t\t\t\tif ( value.name === vclickedName ) {\n
+\t\t\t\t\t\t\t\t// Unset vclickedName - we\'ve found it in the serialized data already\n
+\t\t\t\t\t\t\t\tvclickedName = "";\n
+\t\t\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t});\n
+\t\t\t\t\t\tif ( vclickedName ) {\n
+\t\t\t\t\t\t\tformData.push( { name: vclickedName, value: $lastVClicked.attr( "value" ) } );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\tret = {\n
+\t\t\t\t\turl: url,\n
+\t\t\t\t\toptions: {\n
+\t\t\t\t\t\ttype:\t\tmethod,\n
+\t\t\t\t\t\tdata:\t\t$.param( formData ),\n
+\t\t\t\t\t\ttransition:\t$form.jqmData( "transition" ),\n
+\t\t\t\t\t\treverse:\t$form.jqmData( "direction" ) === "reverse",\n
+\t\t\t\t\t\treloadPage:\ttrue\n
+\t\t\t\t\t}\n
+\t\t\t\t};\n
+\t\t\t}\n
+\n
+\t\t\treturn ret;\n
+\t\t};\n
+\n
+\t\t//bind to form submit events, handle with Ajax\n
+\t\t$.mobile.document.delegate( "form", "submit", function( event ) {\n
+\t\t\tvar formData;\n
+\n
+\t\t\tif ( !event.isDefaultPrevented() ) {\n
+\t\t\t\tformData = getAjaxFormData( $( this ) );\n
+\t\t\t\tif ( formData ) {\n
+\t\t\t\t\t$.mobile.changePage( formData.url, formData.options );\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\t//add active state on vclick\n
+\t\t$.mobile.document.bind( "vclick", function( event ) {\n
+\t\t\tvar $btn, btnEls, target = event.target, needClosest = false;\n
+\t\t\t// if this isn\'t a left click we don\'t care. Its important to note\n
+\t\t\t// that when the virtual event is generated it will create the which attr\n
+\t\t\tif ( event.which > 1 || !$.mobile.linkBindingEnabled ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// Record that this element was clicked, in case we need it for correct\n
+\t\t\t// form submission during the "submit" handler above\n
+\t\t\t$lastVClicked = $( target );\n
+\n
+\t\t\t// Try to find a target element to which the active class will be applied\n
+\t\t\tif ( $.data( target, "mobile-button" ) ) {\n
+\t\t\t\t// If the form will not be submitted via AJAX, do not add active class\n
+\t\t\t\tif ( !getAjaxFormData( $( target ).closest( "form" ), true ) ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\t// We will apply the active state to this button widget - the parent\n
+\t\t\t\t// of the input that was clicked will have the associated data\n
+\t\t\t\tif ( target.parentNode ) {\n
+\t\t\t\t\ttarget = target.parentNode;\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\ttarget = findClosestLink( target );\n
+\t\t\t\tif ( !( target && path.parseUrl( target.getAttribute( "href" ) || "#" ).hash !== "#" ) ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// TODO teach $.mobile.hijackable to operate on raw dom elements so the\n
+\t\t\t\t// link wrapping can be avoided\n
+\t\t\t\tif ( !$( target ).jqmHijackable().length ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// Avoid calling .closest by using the data set during .buttonMarkup()\n
+\t\t\t// List items have the button data in the parent of the element clicked\n
+\t\t\tif ( !!~target.className.indexOf( "ui-link-inherit" ) ) {\n
+\t\t\t\tif ( target.parentNode ) {\n
+\t\t\t\t\tbtnEls = $.data( target.parentNode, "buttonElements" );\n
+\t\t\t\t}\n
+\t\t\t// Otherwise, look for the data on the target itself\n
+\t\t\t} else {\n
+\t\t\t\tbtnEls = $.data( target, "buttonElements" );\n
+\t\t\t}\n
+\t\t\t// If found, grab the button\'s outer element\n
+\t\t\tif ( btnEls ) {\n
+\t\t\t\ttarget = btnEls.outer;\n
+\t\t\t} else {\n
+\t\t\t\tneedClosest = true;\n
+\t\t\t}\n
+\n
+\t\t\t$btn = $( target );\n
+\t\t\t// If the outer element wasn\'t found by the our heuristics, use .closest()\n
+\t\t\tif ( needClosest ) {\n
+\t\t\t\t$btn = $btn.closest( ".ui-btn" );\n
+\t\t\t}\n
+\n
+\t\t\tif ( $btn.length > 0 && !$btn.hasClass( "ui-disabled" ) ) {\n
+\t\t\t\tremoveActiveLinkClass( true );\n
+\t\t\t\t$activeClickedLink = $btn;\n
+\t\t\t\t$activeClickedLink.addClass( $.mobile.activeBtnClass );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\t// click routing - direct to HTTP or Ajax, accordingly\n
+\t\t$.mobile.document.bind( "click", function( event ) {\n
+\t\t\tif ( !$.mobile.linkBindingEnabled || event.isDefaultPrevented() ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tvar link = findClosestLink( event.target ),\n
+\t\t\t\t$link = $( link ),\n
+\t\t\t\thttpCleanup,\n
+\t\t\t\tbaseUrl, href,\n
+\t\t\t\tuseDefaultUrlHandling, isExternal,\n
+\t\t\t\ttransition, reverse, role;\n
+\n
+\t\t\t// If there is no link associated with the click or its not a left\n
+\t\t\t// click we want to ignore the click\n
+\t\t\t// TODO teach $.mobile.hijackable to operate on raw dom elements so the link wrapping\n
+\t\t\t// can be avoided\n
+\t\t\tif ( !link || event.which > 1 || !$link.jqmHijackable().length ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t//remove active link class if external (then it won\'t be there if you come back)\n
+\t\t\thttpCleanup = function() {\n
+\t\t\t\twindow.setTimeout(function() { removeActiveLinkClass( true ); }, 200 );\n
+\t\t\t};\n
+\n
+\t\t\t//if there\'s a data-rel=back attr, go back in history\n
+\t\t\tif ( $link.is( ":jqmData(rel=\'back\')" ) ) {\n
+\t\t\t\t$.mobile.back();\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\n
+\t\t\tbaseUrl = getClosestBaseUrl( $link );\n
+\n
+\t\t\t//get href, if defined, otherwise default to empty hash\n
+\t\t\thref = path.makeUrlAbsolute( $link.attr( "href" ) || "#", baseUrl );\n
+\n
+\t\t\t//if ajax is disabled, exit early\n
+\t\t\tif ( !$.mobile.ajaxEnabled && !path.isEmbeddedPage( href ) ) {\n
+\t\t\t\thttpCleanup();\n
+\t\t\t\t//use default click handling\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t// XXX_jblas: Ideally links to application pages should be specified as\n
+\t\t\t//            an url to the application document with a hash that is either\n
+\t\t\t//            the site relative path or id to the page. But some of the\n
+\t\t\t//            internal code that dynamically generates sub-pages for nested\n
+\t\t\t//            lists and select dialogs, just write a hash in the link they\n
+\t\t\t//            create. This means the actual URL path is based on whatever\n
+\t\t\t//            the current value of the base tag is at the time this code\n
+\t\t\t//            is called. For now we are just assuming that any url with a\n
+\t\t\t//            hash in it is an application page reference.\n
+\t\t\tif ( href.search( "#" ) !== -1 ) {\n
+\t\t\t\thref = href.replace( /[^#]*#/, "" );\n
+\t\t\t\tif ( !href ) {\n
+\t\t\t\t\t//link was an empty hash meant purely\n
+\t\t\t\t\t//for interaction, so we ignore it.\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t\treturn;\n
+\t\t\t\t} else if ( path.isPath( href ) ) {\n
+\t\t\t\t\t//we have apath so make it the href we want to load.\n
+\t\t\t\t\thref = path.makeUrlAbsolute( href, baseUrl );\n
+\t\t\t\t} else {\n
+\t\t\t\t\t//we have a simple id so use the documentUrl as its base.\n
+\t\t\t\t\thref = path.makeUrlAbsolute( "#" + href, documentUrl.hrefNoHash );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// Should we handle this link, or let the browser deal with it?\n
+\t\t\tuseDefaultUrlHandling = $link.is( "[rel=\'external\']" ) || $link.is( ":jqmData(ajax=\'false\')" ) || $link.is( "[target]" );\n
+\n
+\t\t\t// Some embedded browsers, like the web view in Phone Gap, allow cross-domain XHR\n
+\t\t\t// requests if the document doing the request was loaded via the file:// protocol.\n
+\t\t\t// This is usually to allow the application to "phone home" and fetch app specific\n
+\t\t\t// data. We normally let the browser handle external/cross-domain urls, but if the\n
+\t\t\t// allowCrossDomainPages option is true, we will allow cross-domain http/https\n
+\t\t\t// requests to go through our page loading logic.\n
+\n
+\t\t\t//check for protocol or rel and its not an embedded page\n
+\t\t\t//TODO overlap in logic from isExternal, rel=external check should be\n
+\t\t\t//     moved into more comprehensive isExternalLink\n
+\t\t\tisExternal = useDefaultUrlHandling || ( path.isExternal( href ) && !path.isPermittedCrossDomainRequest( documentUrl, href ) );\n
+\n
+\t\t\tif ( isExternal ) {\n
+\t\t\t\thttpCleanup();\n
+\t\t\t\t//use default click handling\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\t//use ajax\n
+\t\t\ttransition = $link.jqmData( "transition" );\n
+\t\t\treverse = $link.jqmData( "direction" ) === "reverse" ||\n
+\t\t\t\t\t\t// deprecated - remove by 1.0\n
+\t\t\t\t\t\t$link.jqmData( "back" );\n
+\n
+\t\t\t//this may need to be more specific as we use data-rel more\n
+\t\t\trole = $link.attr( "data-" + $.mobile.ns + "rel" ) || undefined;\n
+\n
+\t\t\t$.mobile.changePage( href, { transition: transition, reverse: reverse, role: role, link: $link } );\n
+\t\t\tevent.preventDefault();\n
+\t\t});\n
+\n
+\t\t//prefetch pages when anchors with data-prefetch are encountered\n
+\t\t$.mobile.document.delegate( ".ui-page", "pageshow.prefetch", function() {\n
+\t\t\tvar urls = [];\n
+\t\t\t$( this ).find( "a:jqmData(prefetch)" ).each(function() {\n
+\t\t\t\tvar $link = $( this ),\n
+\t\t\t\t\turl = $link.attr( "href" );\n
+\n
+\t\t\t\tif ( url && $.inArray( url, urls ) === -1 ) {\n
+\t\t\t\t\turls.push( url );\n
+\n
+\t\t\t\t\t$.mobile.loadPage( url, { role: $link.attr( "data-" + $.mobile.ns + "rel" ),prefetch: true } );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t});\n
+\n
+\t\t// TODO ensure that the navigate binding in the content widget happens at the right time\n
+\t\t$.mobile.pageContainer.content();\n
+\n
+\t\t//set page min-heights to be device specific\n
+\t\t$.mobile.document.bind( "pageshow", $.mobile.resetActivePageHeight );\n
+\t\t$.mobile.window.bind( "throttledresize", $.mobile.resetActivePageHeight );\n
+\n
+\t};//navreadyDeferred done callback\n
+\n
+\t$( function() { domreadyDeferred.resolve(); } );\n
+\n
+\t$.when( domreadyDeferred, $.mobile.navreadyDeferred ).done( function() { $.mobile._registerInternalEvents(); } );\n
+})( jQuery );\n
+\n
+\n
+(function( $, window, undefined ) {\n
+\n
+\t// TODO remove direct references to $.mobile and properties, we should\n
+\t//      favor injection with params to the constructor\n
+\t$.mobile.Transition = function() {\n
+\t\tthis.init.apply( this, arguments );\n
+\t};\n
+\n
+\t$.extend($.mobile.Transition.prototype, {\n
+\t\ttoPreClass: " ui-page-pre-in",\n
+\n
+\t\tinit: function( name, reverse, $to, $from ) {\n
+\t\t\t$.extend(this, {\n
+\t\t\t\tname: name,\n
+\t\t\t\treverse: reverse,\n
+\t\t\t\t$to: $to,\n
+\t\t\t\t$from: $from,\n
+\t\t\t\tdeferred: new $.Deferred()\n
+\t\t\t});\n
+\t\t},\n
+\n
+\t\tcleanFrom: function() {\n
+\t\t\tthis.$from\n
+\t\t\t\t.removeClass( $.mobile.activePageClass + " out in reverse " + this.name )\n
+\t\t\t\t.height( "" );\n
+\t\t},\n
+\n
+\t\t// NOTE overridden by child object prototypes, noop\'d here as defaults\n
+\t\tbeforeDoneIn: function() {},\n
+\t\tbeforeDoneOut: function() {},\n
+\t\tbeforeStartOut: function() {},\n
+\n
+\t\tdoneIn: function() {\n
+\t\t\tthis.beforeDoneIn();\n
+\n
+\t\t\tthis.$to.removeClass( "out in reverse " + this.name ).height( "" );\n
+\n
+\t\t\tthis.toggleViewportClass();\n
+\n
+\t\t\t// In some browsers (iOS5), 3D transitions block the ability to scroll to the desired location during transition\n
+\t\t\t// This ensures we jump to that spot after the fact, if we aren\'t there already.\n
+\t\t\tif ( $.mobile.window.scrollTop() !== this.toScroll ) {\n
+\t\t\t\tthis.scrollPage();\n
+\t\t\t}\n
+\n
+\t\t\tthis.deferred.resolve( this.name, this.reverse, this.$to, this.$from, true );\n
+\t\t},\n
+\n
+\t\tdoneOut: function( screenHeight, reverseClass, none, preventFocus ) {\n
+\t\t\tthis.beforeDoneOut();\n
+\t\t\tthis.startIn( screenHeight, reverseClass, none, preventFocus );\n
+\t\t},\n
+\n
+\t\thideIn: function( callback ) {\n
+\t\t\t// Prevent flickering in phonegap container: see comments at #4024 regarding iOS\n
+\t\t\tthis.$to.css( "z-index", -10 );\n
+\t\t\tcallback.call( this );\n
+\t\t\tthis.$to.css( "z-index", "" );\n
+\t\t},\n
+\n
+\t\tscrollPage: function() {\n
+\t\t\t// By using scrollTo instead of silentScroll, we can keep things better in order\n
+\t\t\t// Just to be precautios, disable scrollstart listening like silentScroll would\n
+\t\t\t$.event.special.scrollstart.enabled = false;\n
+\t\t\t//if we are hiding the url bar or the page was previously scrolled scroll to hide or return to position\n
+\t\t\tif ( $.mobile.hideUrlBar || this.toScroll !== $.mobile.defaultHomeScroll ) {\n
+\t\t\t\twindow.scrollTo( 0, this.toScroll );\n
+\t\t\t}\n
+\n
+\t\t\t// reenable scrollstart listening like silentScroll would\n
+\t\t\tsetTimeout( function() {\n
+\t\t\t\t$.event.special.scrollstart.enabled = true;\n
+\t\t\t}, 150 );\n
+\t\t},\n
+\n
+\t\tstartIn: function( screenHeight, reverseClass, none, preventFocus ) {\n
+\t\t\tthis.hideIn(function() {\n
+\t\t\t\tthis.$to.addClass( $.mobile.activePageClass + this.toPreClass );\n
+\n
+\t\t\t\t// Send focus to page as it is now display: block\n
+\t\t\t\tif( !preventFocus ){\n
+\t\t\t\t\t$.mobile.focusPage( this.$to );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Set to page height\n
+\t\t\t\tthis.$to.height( screenHeight + this.toScroll );\n
+\n
+                if ( !none ) {\n
+                    this.scrollPage();\n
+                }\n
+\t\t\t});\n
+\n
+\t\t\tif ( !none ) {\n
+\t\t\t\tthis.$to.animationComplete( $.proxy(function() {\n
+\t\t\t\t\tthis.doneIn();\n
+\t\t\t\t}, this ));\n
+\t\t\t}\n
+\n
+\t\t\tthis.$to\n
+\t\t\t\t.removeClass( this.toPreClass )\n
+\t\t\t\t.addClass( this.name + " in " + reverseClass );\n
+\n
+\t\t\tif ( none ) {\n
+\t\t\t\tthis.doneIn();\n
+\t\t\t}\n
+\n
+\t\t},\n
+\n
+\t\tstartOut: function( screenHeight, reverseClass, none ) {\n
+\t\t\tthis.beforeStartOut( screenHeight, reverseClass, none );\n
+\n
+\t\t\t// Set the from page\'s height and start it transitioning out\n
+\t\t\t// Note: setting an explicit height helps eliminate tiling in the transitions\n
+\t\t\tthis.$from\n
+\t\t\t\t.height( screenHeight + $.mobile.window.scrollTop() )\n
+\t\t\t\t.addClass( this.name + " out" + reverseClass );\n
+\t\t},\n
+\n
+\n
+\t\ttoggleViewportClass: function() {\n
+\t\t\t$.mobile.pageContainer.toggleClass( "ui-mobile-viewport-transitioning viewport-" + this.name );\n
+\t\t},\n
+\n
+\t\ttransition: function() {\n
+\t\t\t// NOTE many of these could be calculated/recorded in the constructor, it\'s my\n
+\t\t\t//      opinion that binding them as late as possible has value with regards to\n
+\t\t\t//      better transitions with fewer bugs. Ie, it\'s not guaranteed that the\n
+\t\t\t//      object will be created and transition will be run immediately after as\n
+\t\t\t//      it is today. So we wait until transition is invoked to gather the following\n
+\t\t\tvar reverseClass = this.reverse ? " reverse" : "",\n
+\t\t\t\tscreenHeight = $.mobile.getScreenHeight(),\n
+\t\t\t\tmaxTransitionOverride = $.mobile.maxTransitionWidth !== false && $.mobile.window.width() > $.mobile.maxTransitionWidth,\n
+\t\t\t\tnone = !$.support.cssTransitions || maxTransitionOverride || !this.name || this.name === "none" || Math.max( $.mobile.window.scrollTop(), this.toScroll ) > $.mobile.getMaxScrollForTransition();\n
+\n
+\t\t\tthis.toScroll = $.mobile.urlHistory.getActive().lastScroll || $.mobile.defaultHomeScroll;\n
+\t\t\tthis.toggleViewportClass();\n
+\n
+\t\t\tif ( this.$from && !none ) {\n
+\t\t\t\tthis.startOut( screenHeight, reverseClass, none );\n
+\t\t\t} else {\n
+\t\t\t\tthis.doneOut( screenHeight, reverseClass, none, true );\n
+\t\t\t}\n
+\n
+\t\t\treturn this.deferred.promise();\n
+\t\t}\n
+\t});\n
+})( jQuery, this );\n
+\n
+\n
+(function( $ ) {\n
+\n
+\t$.mobile.SerialTransition = function() {\n
+\t\tthis.init.apply(this, arguments);\n
+\t};\n
+\n
+\t$.extend($.mobile.SerialTransition.prototype, $.mobile.Transition.prototype, {\n
+\t\tsequential: true,\n
+\n
+\t\tbeforeDoneOut: function() {\n
+\t\t\tif ( this.$from ) {\n
+\t\t\t\tthis.cleanFrom();\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\tbeforeStartOut: function( screenHeight, reverseClass, none ) {\n
+\t\t\tthis.$from.animationComplete($.proxy(function() {\n
+\t\t\t\tthis.doneOut( screenHeight, reverseClass, none );\n
+\t\t\t}, this ));\n
+\t\t}\n
+\t});\n
+\n
+})( jQuery );\n
+\n
+\n
+(function( $ ) {\n
+\n
+\t$.mobile.ConcurrentTransition = function() {\n
+\t\tthis.init.apply(this, arguments);\n
+\t};\n
+\n
+\t$.extend($.mobile.ConcurrentTransition.prototype, $.mobile.Transition.prototype, {\n
+\t\tsequential: false,\n
+\n
+\t\tbeforeDoneIn: function() {\n
+\t\t\tif ( this.$from ) {\n
+\t\t\t\tthis.cleanFrom();\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\tbeforeStartOut: function( screenHeight, reverseClass, none ) {\n
+\t\t\tthis.doneOut( screenHeight, reverseClass, none );\n
+\t\t}\n
+\t});\n
+\n
+})( jQuery );\n
+\n
+\n
+(function( $ ) {\n
+\n
+\t// generate the handlers from the above\n
+\tvar defaultGetMaxScrollForTransition = function() {\n
+\t\treturn $.mobile.getScreenHeight() * 3;\n
+\t};\n
+\n
+\t//transition handler dictionary for 3rd party transitions\n
+\t$.mobile.transitionHandlers = {\n
+\t\t"sequential": $.mobile.SerialTransition,\n
+\t\t"simultaneous": $.mobile.ConcurrentTransition\n
+\t};\n
+\n
+\t// Make our transition handler the public default.\n
+\t$.mobile.defaultTransitionHandler = $.mobile.transitionHandlers.sequential;\n
+\n
+\t$.mobile.transitionFallbacks = {};\n
+\n
+\t// If transition is defined, check if css 3D transforms are supported, and if not, if a fallback is specified\n
+\t$.mobile._maybeDegradeTransition = function( transition ) {\n
+\t\tif ( transition && !$.support.cssTransform3d && $.mobile.transitionFallbacks[ transition ] ) {\n
+\t\t\ttransition = $.mobile.transitionFallbacks[ transition ];\n
+\t\t}\n
+\n
+\t\treturn transition;\n
+\t};\n
+\n
+\t// Set the getMaxScrollForTransition to default if no implementation was set by user\n
+\t$.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defaultGetMaxScrollForTransition;\n
+\n
+})( jQuery );\n
+\n
+/*\n
+* fallback transition for flip in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n
+*/\n
+\n
+(function( $, window, undefined ) {\n
+\n
+$.mobile.transitionFallbacks.flip = "fade";\n
+\n
+})( jQuery, this );\n
+/*\n
+* fallback transition for flow in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n
+*/\n
+\n
+(function( $, window, undefined ) {\n
+\n
+$.mobile.transitionFallbacks.flow = "fade";\n
+\n
+})( jQuery, this );\n
+/*\n
+* fallback transition for pop in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n
+*/\n
+\n
+(function( $, window, undefined ) {\n
+\n
+$.mobile.transitionFallbacks.pop = "fade";\n
+\n
+})( jQuery, this );\n
+/*\n
+* fallback transition for slide in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n
+*/\n
+\n
+(function( $, window, undefined ) {\n
+\n
+// Use the simultaneous transitions handler for slide transitions\n
+$.mobile.transitionHandlers.slide = $.mobile.transitionHandlers.simultaneous;\n
+\n
+// Set the slide transitions\'s fallback to "fade"\n
+$.mobile.transitionFallbacks.slide = "fade";\n
+\n
+})( jQuery, this );\n
+/*\n
+* fallback transition for slidedown in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n
+*/\n
+\n
+(function( $, window, undefined ) {\n
+\n
+$.mobile.transitionFallbacks.slidedown = "fade";\n
+\n
+})( jQuery, this );\n
+/*\n
+* fallback transition for slidefade in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n
+*/\n
+\n
+(function( $, window, undefined ) {\n
+\n
+// Set the slide transitions\'s fallback to "fade"\n
+$.mobile.transitionFallbacks.slidefade = "fade";\n
+\n
+})( jQuery, this );\n
+/*\n
+* fallback transition for slideup in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n
+*/\n
+\n
+(function( $, window, undefined ) {\n
+\n
+$.mobile.transitionFallbacks.slideup = "fade";\n
+\n
+})( jQuery, this );\n
+/*\n
+* fallback transition for turn in non-3D supporting browsers (which tend to handle complex transitions poorly in general\n
+*/\n
+\n
+(function( $, window, undefined ) {\n
+\n
+$.mobile.transitionFallbacks.turn = "fade";\n
+\n
+})( jQuery, this );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.mobile.degradeInputs = {\n
+\tcolor: false,\n
+\tdate: false,\n
+\tdatetime: false,\n
+\t"datetime-local": false,\n
+\temail: false,\n
+\tmonth: false,\n
+\tnumber: false,\n
+\trange: "number",\n
+\tsearch: "text",\n
+\ttel: false,\n
+\ttime: false,\n
+\turl: false,\n
+\tweek: false\n
+};\n
+// Backcompat remove in 1.5\n
+$.mobile.page.prototype.options.degradeInputs = $.mobile.degradeInputs;\n
+\n
+// Auto self-init widgets\n
+$.mobile.degradeInputsWithin = function( target ) {\n
+\n
+\ttarget = $( target );\n
+\n
+\t// Degrade inputs to avoid poorly implemented native functionality\n
+\ttarget.find( "input" ).not( $.mobile.page.prototype.keepNativeSelector() ).each(function() {\n
+\t\tvar element = $( this ),\n
+\t\t\ttype = this.getAttribute( "type" ),\n
+\t\t\toptType = $.mobile.degradeInputs[ type ] || "text",\n
+\t\t\thtml, hasType, findstr, repstr;\n
+\n
+\t\tif ( $.mobile.degradeInputs[ type ] ) {\n
+\t\t\thtml = $( "<div>" ).html( element.clone() ).html();\n
+\t\t\t// In IE browsers, the type sometimes doesn\'t exist in the cloned markup, so we replace the closing tag instead\n
+\t\t\thasType = html.indexOf( " type=" ) > -1;\n
+\t\t\tfindstr = hasType ? /\\s+type=["\']?\\w+[\'"]?/ : /\\/?>/;\n
+\t\t\trepstr = " type=\\"" + optType + "\\" data-" + $.mobile.ns + "type=\\"" + type + "\\"" + ( hasType ? "" : ">" );\n
+\n
+\t\t\telement.replaceWith( html.replace( findstr, repstr ) );\n
+\t\t}\n
+\t});\n
+\n
+};\n
+\n
+})( jQuery );\n
+\n
+(function( $, window, undefined ) {\n
+\n
+$.widget( "mobile.page", $.mobile.page, {\n
+\toptions: {\n
+\n
+\t\t// Accepts left, right and none\n
+\t\tcloseBtn: "left",\n
+\t\tcloseBtnText: "Close",\n
+\t\toverlayTheme: "a",\n
+\t\tcorners: true,\n
+\t\tdialog: false\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tthis._super();\n
+\t\tif( this.options.dialog ){\n
+\n
+\t\t\t$.extend( this, {\n
+\t\t\t\t_isCloseable: false,\n
+\t\t\t\t_inner: this.element.children(),\n
+\t\t\t\t_headerCloseButton: null\n
+\t\t\t});\n
+\n
+\t\t\tif( !this.options.enhanced ) {\n
+\t\t\t\tthis._setCloseBtn( this.options.closeBtn );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t_enhance: function() {\n
+\t\tthis._super();\n
+\n
+\t\t// Class the markup for dialog styling and wrap interior\n
+\t\tif( this.options.dialog ){\n
+\t\t\tthis.element.addClass( "ui-dialog" )\n
+\t\t\t\t.wrapInner( $( "<div/>", {\n
+\n
+\t\t\t\t\t// ARIA role\n
+\t\t\t\t\t"role" : "dialog",\n
+\t\t\t\t\t"class" : "ui-dialog-contain ui-overlay-shadow" +\n
+\t\t\t\t\t\t( this.options.corners ? " ui-corner-all" : "" )\n
+\t\t\t\t}));\n
+\t\t}\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tvar closeButtonLocation, closeButtonText,\n
+\t\t\tcurrentOpts = this.options;\n
+\n
+\t\tif ( options.corners !== undefined ) {\n
+\t\t\tthis._inner.toggleClass( "ui-corner-all", !!options.corners );\n
+\t\t}\n
+\n
+\t\tif ( options.overlayTheme !== undefined ) {\n
+\t\t\tif ( $.mobile.activePage[ 0 ] === this.element[ 0 ] ) {\n
+\t\t\t\tcurrentOpts.overlayTheme = options.overlayTheme;\n
+\t\t\t\tthis._handlePageBeforeShow();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( options.closeBtnText !== undefined ) {\n
+\t\t\tcloseButtonLocation = currentOpts.closeBtn;\n
+\t\t\tcloseButtonText = options.closeBtnText;\n
+\t\t}\n
+\n
+\t\tif ( options.closeBtn !== undefined ) {\n
+\t\t\tcloseButtonLocation = options.closeBtn;\n
+\t\t}\n
+\n
+\t\tif ( closeButtonLocation ) {\n
+\t\t\tthis._setCloseBtn( closeButtonLocation, closeButtonText );\n
+\t\t}\n
+\n
+\t\tthis._super( options );\n
+\t},\n
+\n
+\t_handlePageBeforeShow: function () {\n
+\t\tif ( this.options.overlayTheme ) {\n
+\t\t\tthis.removeContainerBackground();\n
+\t\t\tthis.setContainerBackground( this.options.overlayTheme );\n
+\t\t} else {\n
+\t\t\tthis._super();\n
+\t\t}\n
+\t},\n
+\n
+\t_setCloseBtn: function( location, text ) {\n
+\t\tvar dst,\n
+\t\t\tbtn = this._headerCloseButton;\n
+\n
+\t\t// Sanitize value\n
+\t\tlocation = "left" === location ? "left" : "right" === location ? "right" : "none";\n
+\n
+\t\tif ( "none" === location ) {\n
+\t\t\tif ( btn ) {\n
+\t\t\t\tbtn.remove();\n
+\t\t\t\tbtn = null;\n
+\t\t\t}\n
+\t\t} else if ( btn ) {\n
+\t\t\tbtn.removeClass( "ui-btn-left ui-btn-right" ).addClass( "ui-btn-" + location );\n
+\t\t\tif ( text ) {\n
+\t\t\t\tbtn.text( text );\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tdst = this._inner.find( ":jqmData(role=\'header\')" ).first();\n
+\t\t\tbtn = $( "<a></a>", {\n
+\t\t\t\t\t"role": "button",\n
+\t\t\t\t\t"href": "#",\n
+\t\t\t\t\t"class": "ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-" + location\n
+\t\t\t\t})\n
+\t\t\t\t.text( text || this.options.closeBtnText || "" )\n
+\t\t\t\t.prependTo( dst );\n
+\t\t\tthis._on( btn, { click: "close" } );\n
+\t\t}\n
+\n
+\t\tthis._headerCloseButton = btn;\n
+\t},\n
+\n
+\t// Close method goes back in history\n
+\tclose: function() {\n
+\t\tvar idx, dst, hist = $.mobile.navigate.history;\n
+\n
+\t\t\tif ( $.mobile.hashListeningEnabled && hist.activeIndex > 0 ) {\n
+\t\t\t\t$.mobile.back();\n
+\t\t\t} else {\n
+\t\t\t\tidx = Math.max( 0, hist.activeIndex - 1 );\n
+\t\t\t\tdst = hist.stack[ idx ].pageUrl || hist.stack[ idx ].url;\n
+\t\t\t\thist.previousIndex = hist.activeIndex;\n
+\t\t\t\thist.activeIndex = idx;\n
+\t\t\t\tif ( !$.mobile.path.isPath( dst ) ) {\n
+\t\t\t\t\tdst = $.mobile.path.makeUrlAbsolute( "#" + dst );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t$.mobile.changePage( dst, { direction: "back", changeHash: false, fromHashChange: true } );\n
+\t\t\t}\n
+\t}\n
+});\n
+\n
+})( jQuery, this );\n
+\n
+(function( $, window, undefined ) {\n
+\n
+$.widget( "mobile.dialog", {\n
+\toptions: {\n
+\n
+\t\t// Accepts left, right and none\n
+\t\tcloseBtn: "left",\n
+\t\tcloseBtnText: "Close",\n
+\t\toverlayTheme: "a",\n
+\t\tcorners: true\n
+\t},\n
+\n
+\t// Override the theme set by the page plugin on pageshow\n
+\t_handlePageBeforeShow: function() {\n
+\t\tthis._isCloseable = true;\n
+\t\tif ( this.options.overlayTheme ) {\n
+\t\t\tthis.element\n
+\t\t\t\t.page( "removeContainerBackground" )\n
+\t\t\t\t.page( "setContainerBackground", this.options.overlayTheme );\n
+\t\t}\n
+\t},\n
+\n
+\t_handlePageBeforeHide: function() {\n
+\t\tthis._isCloseable = false;\n
+\t},\n
+\n
+\t// click and submit events:\n
+\t// - clicks and submits should use the closing transition that the dialog\n
+\t//   opened with unless a data-transition is specified on the link/form\n
+\t// - if the click was on the close button, or the link has a data-rel="back"\n
+\t//   it\'ll go back in history naturally\n
+\t_handleVClickSubmit: function( event ) {\n
+\t\tvar attrs,\n
+\t\t\t$target = $( event.target ).closest( event.type === "vclick" ? "a" : "form" );\n
+\n
+\t\tif ( $target.length && !$target.jqmData( "transition" ) ) {\n
+\t\t\tattrs = {};\n
+\t\t\tattrs[ "data-" + $.mobile.ns + "transition" ] =\n
+\t\t\t\t( $.mobile.urlHistory.getActive() || {} )[ "transition" ] ||\n
+\t\t\t\t$.mobile.defaultDialogTransition;\n
+\t\t\tattrs[ "data-" + $.mobile.ns + "direction" ] = "reverse";\n
+\t\t\t$target.attr( attrs );\n
+\t\t}\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tvar elem = this.element,\n
+\t\t\topts = this.options;\n
+\n
+\t\t// Class the markup for dialog styling and wrap interior\n
+\t\telem.addClass( "ui-dialog" )\n
+\t\t\t.wrapInner( $( "<div/>", {\n
+\n
+\t\t\t\t// ARIA role\n
+\t\t\t\t"role" : "dialog",\n
+\t\t\t\t"class" : "ui-dialog-contain ui-overlay-shadow" +\n
+\t\t\t\t\t( !!opts.corners ? " ui-corner-all" : "" )\n
+\t\t\t}));\n
+\n
+\t\t$.extend( this, {\n
+\t\t\t_isCloseable: false,\n
+\t\t\t_inner: elem.children(),\n
+\t\t\t_headerCloseButton: null\n
+\t\t});\n
+\n
+\t\tthis._on( elem, {\n
+\t\t\tvclick: "_handleVClickSubmit",\n
+\t\t\tsubmit: "_handleVClickSubmit",\n
+\t\t\tpagebeforeshow: "_handlePageBeforeShow",\n
+\t\t\tpagebeforehide: "_handlePageBeforeHide"\n
+\t\t});\n
+\n
+\t\tthis._setCloseBtn( opts.closeBtn );\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tvar closeButtonLocation, closeButtonText,\n
+\t\t\tcurrentOpts = this.options;\n
+\n
+\t\tif ( options.corners !== undefined ) {\n
+\t\t\tthis._inner.toggleClass( "ui-corner-all", !!options.corners );\n
+\t\t}\n
+\n
+\t\tif ( options.overlayTheme !== undefined ) {\n
+\t\t\tif ( $.mobile.activePage[ 0 ] === this.element[ 0 ] ) {\n
+\t\t\t\tcurrentOpts.overlayTheme = options.overlayTheme;\n
+\t\t\t\tthis._handlePageBeforeShow();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( options.closeBtnText !== undefined ) {\n
+\t\t\tcloseButtonLocation = currentOpts.closeBtn;\n
+\t\t\tcloseButtonText = options.closeBtnText;\n
+\t\t}\n
+\n
+\t\tif ( options.closeBtn !== undefined ) {\n
+\t\t\tcloseButtonLocation = options.closeBtn;\n
+\t\t}\n
+\n
+\t\tif ( closeButtonLocation ) {\n
+\t\t\tthis._setCloseBtn( closeButtonLocation, closeButtonText );\n
+\t\t}\n
+\n
+\t\tthis._super( options );\n
+\t},\n
+\n
+\t_setCloseBtn: function( location, text ) {\n
+\t\tvar dst,\n
+\t\t\tbtn = this._headerCloseButton;\n
+\n
+\t\t// Sanitize value\n
+\t\tlocation = "left" === location ? "left" : "right" === location ? "right" : "none";\n
+\n
+\t\tif ( "none" === location ) {\n
+\t\t\tif ( btn ) {\n
+\t\t\t\tbtn.remove();\n
+\t\t\t\tbtn = null;\n
+\t\t\t}\n
+\t\t} else if ( btn ) {\n
+\t\t\tbtn.removeClass( "ui-btn-left ui-btn-right" ).addClass( "ui-btn-" + location );\n
+\t\t\tif ( text ) {\n
+\t\t\t\tbtn.text( text );\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tdst = this._inner.find( ":jqmData(role=\'header\')" ).first();\n
+\t\t\tbtn = $( "<a></a>", {\n
+\t\t\t\t\t"role": "button",\n
+\t\t\t\t\t"href": "#",\n
+\t\t\t\t\t"class": "ui-btn ui-corner-all ui-icon-delete ui-btn-icon-notext ui-btn-" + location\n
+\t\t\t\t})\n
+\t\t\t\t.text( text || this.options.closeBtnText || "" )\n
+\t\t\t\t.prependTo( dst );\n
+\t\t\tthis._on( btn, { click: "close" } );\n
+\t\t}\n
+\n
+\t\tthis._headerCloseButton = btn;\n
+\t},\n
+\n
+\t// Close method goes back in history\n
+\tclose: function() {\n
+\t\tvar idx, dst, hist = $.mobile.navigate.history;\n
+\n
+\t\tif ( this._isCloseable ) {\n
+\t\t\tthis._isCloseable = false;\n
+\t\t\t// If the hash listening is enabled and there is at least one preceding history\n
+\t\t\t// entry it\'s ok to go back. Initial pages with the dialog hash state are an example\n
+\t\t\t// where the stack check is necessary\n
+\t\t\tif ( $.mobile.hashListeningEnabled && hist.activeIndex > 0 ) {\n
+\t\t\t\t$.mobile.back();\n
+\t\t\t} else {\n
+\t\t\t\tidx = Math.max( 0, hist.activeIndex - 1 );\n
+\t\t\t\tdst = hist.stack[ idx ].pageUrl || hist.stack[ idx ].url;\n
+\t\t\t\thist.previousIndex = hist.activeIndex;\n
+\t\t\t\thist.activeIndex = idx;\n
+\t\t\t\tif ( !$.mobile.path.isPath( dst ) ) {\n
+\t\t\t\t\tdst = $.mobile.path.makeUrlAbsolute( "#" + dst );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t$.mobile.changePage( dst, { direction: "back", changeHash: false, fromHashChange: true } );\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+});\n
+\n
+})( jQuery, this );\n
+(function( $, undefined ) {\n
+\n
+var rInitialLetter = /([A-Z])/g;\n
+\n
+$.widget( "mobile.collapsible", {\n
+\toptions: {\n
+\t\tenhanced: false,\n
+\t\texpandCueText: null,\n
+\t\tcollapseCueText: null,\n
+\t\tcollapsed: true,\n
+\t\theading: "h1,h2,h3,h4,h5,h6,legend",\n
+\t\tcollapsedIcon: null,\n
+\t\texpandedIcon: null,\n
+\t\ticonpos: null,\n
+\t\ttheme: null,\n
+\t\tcontentTheme: null,\n
+\t\tinset: null,\n
+\t\tcorners: null,\n
+\t\tmini: null\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tvar elem = this.element,\n
+\t\t\tui = {\n
+\t\t\t\taccordion: elem\n
+\t\t\t\t\t.closest( ":jqmData(role=\'collapsible-set\')" +\n
+\t\t\t\t\t\t( $.mobile.collapsibleset ? ", :mobile-collapsibleset" : "" ) )\n
+\t\t\t\t\t.addClass( "ui-collapsible-set" )\n
+\t\t\t};\n
+\n
+\t\t$.extend( this, {\n
+\t\t\t_ui: ui\n
+\t\t});\n
+\n
+\t\tif ( this.options.enhanced ) {\n
+\t\t\tui.heading = $( ".ui-collapsible-heading", this.element[ 0 ] );\n
+\t\t\tui.content = ui.heading.next();\n
+\t\t\tui.anchor = $( "a", ui.heading[ 0 ] ).first();\n
+\t\t\tui.status = ui.anchor.children( ".ui-collapsible-heading-status" );\n
+\t\t} else {\n
+\t\t\tthis._enhance( elem, ui );\n
+\t\t}\n
+\n
+\t\tthis._on( ui.heading, {\n
+\t\t\t"tap": function() {\n
+\t\t\t\tui.heading.find( "a" ).first().addClass( $.mobile.activeBtnClass );\n
+\t\t\t},\n
+\n
+\t\t\t"click": function( event ) {\n
+\t\t\t\tthis._handleExpandCollapse( !ui.heading.hasClass( "ui-collapsible-heading-collapsed" ) );\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t\tevent.stopPropagation();\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t// Adjust the keys inside options for inherited values\n
+\t_getOptions: function( options ) {\n
+\t\tvar key,\n
+\t\t\taccordion = this._ui.accordion,\n
+\t\t\taccordionWidget = this._ui.accordionWidget;\n
+\n
+\t\t// Copy options\n
+\t\toptions = $.extend( {}, options );\n
+\n
+\t\tif ( accordion.length && !accordionWidget ) {\n
+\t\t\tthis._ui.accordionWidget =\n
+\t\t\taccordionWidget = accordion.data( "mobile-collapsibleset" );\n
+\t\t}\n
+\n
+\t\tfor ( key in options ) {\n
+\n
+\t\t\t// Retrieve the option value first from the options object passed in and, if\n
+\t\t\t// null, from the parent accordion or, if that\'s null too, or if there\'s no\n
+\t\t\t// parent accordion, then from the defaults.\n
+\t\t\toptions[ key ] =\n
+\t\t\t\t( options[ key ] != null ) ? options[ key ] :\n
+\t\t\t\t( accordionWidget ) ? accordionWidget.options[ key ] :\n
+\t\t\t\taccordion.length ? $.mobile.getAttribute( accordion[ 0 ],\n
+\t\t\t\t\tkey.replace( rInitialLetter, "-$1" ).toLowerCase() ):\n
+\t\t\t\tnull;\n
+\n
+\t\t\tif ( null == options[ key ] ) {\n
+\t\t\t\toptions[ key ] = $.mobile.collapsible.defaults[ key ];\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn options;\n
+\t},\n
+\n
+\t_themeClassFromOption: function( prefix, value ) {\n
+\t\treturn ( value ? ( value === "none" ? "" : prefix + value ) : "" );\n
+\t},\n
+\n
+\t_enhance: function( elem, ui ) {\n
+\t\tvar iconclass,\n
+\t\t\topts = this._getOptions( this.options ),\n
+\t\t\tcontentThemeClass = this._themeClassFromOption( "ui-body-", opts.contentTheme );\n
+\n
+\t\telem.addClass( "ui-collapsible " +\n
+\t\t\t( opts.inset ? "ui-collapsible-inset " : "" ) +\n
+\t\t\t( opts.inset && opts.corners ? "ui-corner-all " : "" ) +\n
+\t\t\t( contentThemeClass ? "ui-collapsible-themed-content " : "" ) );\n
+\t\tui.originalHeading = elem.children( this.options.heading ).first(),\n
+\t\tui.content = elem\n
+\t\t\t.wrapInner( "<div " +\n
+\t\t\t\t"class=\'ui-collapsible-content " +\n
+\t\t\t\tcontentThemeClass + "\'></div>" )\n
+\t\t\t.children( ".ui-collapsible-content" ),\n
+\t\tui.heading = ui.originalHeading;\n
+\n
+\t\t// Replace collapsibleHeading if it\'s a legend\n
+\t\tif ( ui.heading.is( "legend" ) ) {\n
+\t\t\tui.heading = $( "<div role=\'heading\'>"+ ui.heading.html() +"</div>" );\n
+\t\t\tui.placeholder = $( "<div><!-- placeholder for legend --></div>" ).insertBefore( ui.originalHeading );\n
+\t\t\tui.originalHeading.remove();\n
+\t\t}\n
+\n
+\t\ticonclass = ( opts.collapsed ? ( opts.collapsedIcon ? "ui-icon-" + opts.collapsedIcon : "" ):\n
+\t\t\t( opts.expandedIcon ? "ui-icon-" + opts.expandedIcon : "" ) );\n
+\n
+\t\tui.status = $( "<span class=\'ui-collapsible-heading-status\'></span>" );\n
+\t\tui.anchor = ui.heading\n
+\t\t\t.detach()\n
+\t\t\t//modify markup & attributes\n
+\t\t\t.addClass( "ui-collapsible-heading" )\n
+\t\t\t.append( ui.status )\n
+\t\t\t.wrapInner( "<a href=\'#\' class=\'ui-collapsible-heading-toggle\'></a>" )\n
+\t\t\t.find( "a" )\n
+\t\t\t\t.first()\n
+\t\t\t\t.addClass( "ui-btn " +\n
+\t\t\t\t\t( iconclass ? iconclass + " " : "" ) +\n
+\t\t\t\t\t( iconclass ? ( "ui-btn-icon-" +\n
+\t\t\t\t\t\t( opts.iconpos === "right" ? "right" : "left" ) ) +\n
+\t\t\t\t\t\t" " : "" ) +\n
+\t\t\t\t\tthis._themeClassFromOption( "ui-btn-", opts.theme ) + " " +\n
+\t\t\t\t\t( opts.mini ? "ui-mini " : "" ) );\n
+\n
+\t\t//drop heading in before content\n
+\t\tui.heading.insertBefore( ui.content );\n
+\n
+\t\tthis._handleExpandCollapse( this.options.collapsed );\n
+\n
+\t\treturn ui;\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tvar key, options = {};\n
+\n
+\t\tfor ( key in $.mobile.collapsible.defaults ) {\n
+\t\t\toptions[ key ] = this.options[ key ];\n
+\t\t}\n
+\n
+\t\tthis._setOptions( options );\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tvar isCollapsed, newTheme, oldTheme,\n
+\t\t\telem = this.element,\n
+\t\t\tcurrentOpts = this.options,\n
+\t\t\tui = this._ui,\n
+\t\t\tanchor = ui.anchor,\n
+\t\t\tstatus = ui.status,\n
+\t\t\topts = this._getOptions( options );\n
+\n
+\t\t// First and foremost we need to make sure the collapsible is in the proper\n
+\t\t// state, in case somebody decided to change the collapsed option at the\n
+\t\t// same time as another option\n
+\t\tif ( options.collapsed !== undefined ) {\n
+\t\t\tthis._handleExpandCollapse( options.collapsed );\n
+\t\t}\n
+\n
+\t\tisCollapsed = elem.hasClass( "ui-collapsible-colapsed" );\n
+\n
+\t\t// Only options referring to the current state need to be applied right away\n
+\t\t// It is enough to store options covering the alternate in this.options.\n
+\t\tif ( isCollapsed ) {\n
+\t\t\tif ( opts.expandCueText !== undefined ) {\n
+\t\t\t\tstatus.text( opts.expandCueText );\n
+\t\t\t}\n
+\t\t\tif ( opts.collapsedIcon !== undefined ) {\n
+\t\t\t\tif ( currentOpts.collapsedIcon ) {\n
+\t\t\t\t\tanchor.removeClass( "ui-icon-" + currentOpts.collapsedIcon );\n
+\t\t\t\t}\n
+\t\t\t\tif ( opts.collapsedIcon ) {\n
+\t\t\t\t\tanchor.addClass( "ui-icon-" + opts.collapsedIcon );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tif ( opts.collapseCueText !== undefined ) {\n
+\t\t\t\tstatus.text( opts.collapseCueText );\n
+\t\t\t}\n
+\t\t\tif ( opts.expandedIcon !== undefined ) {\n
+\t\t\t\tif ( currentOpts.expandedIcon ) {\n
+\t\t\t\t\tanchor.removeClass( "ui-icon-" + currentOpts.expandedWIcon );\n
+\t\t\t\t}\n
+\t\t\t\tif ( opts.expandedIcon ) {\n
+\t\t\t\t\tanchor.addClass( "ui-icon-" + opts.expandedIcon );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( opts.iconpos !== undefined ) {\n
+\t\t\tanchor.removeClass( "ui-btn-icon-" + ( currentOpts.iconPos === "right" ? "right" : "left" ) );\n
+\t\t\tanchor.addClass( "ui-btn-icon-" + ( opts.iconPos === "right" ? "right" : "left" ) );\n
+\t\t}\n
+\n
+\t\tif ( opts.theme !== undefined ) {\n
+\t\t\toldTheme = this._themeClassFromOption( "ui-btn-", currentOpts.theme );\n
+\t\t\tnewTheme = this._themeClassFromOption( "ui-btn-", opts.theme );\n
+\t\t\tanchor.removeClass( oldTheme ).addClass( newTheme );\n
+\t\t}\n
+\n
+\t\tif ( opts.contentTheme !== undefined ) {\n
+\t\t\toldTheme = this._themeClassFromOption( "ui-body-", currentOpts.theme );\n
+\t\t\tnewTheme = this._themeClassFromOption( "ui-body-", opts.theme );\n
+\t\t\tui.content.removeClass( oldTheme ).addClass( newTheme );\n
+\t\t}\n
+\n
+\t\t// It is important to apply "inset" before corners, because the new value of\n
+\t\t// "inset" can affect whether we display corners or not. Note that setting\n
+\t\t// the "inset" option to false does not cause a change in the value of\n
+\t\t// this.options.corners - it merely causes a change in the interpretation of\n
+\t\t// the value of the "corners" option.\n
+\t\tif ( opts.inset !== undefined ) {\n
+\t\t\telem.toggleClass( "ui-collapsible-inset", opts.inset );\n
+\t\t\tcurrentOpts.inset = opts.inset;\n
+\t\t\tif ( !opts.inset ) {\n
+\t\t\t\topts.corners = false;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( opts.corners !== undefined ) {\n
+\t\t\telem.toggleClass( "ui-corner-all", currentOpts.inset && opts.corners );\n
+\t\t}\n
+\n
+\t\tif ( opts.mini !== undefined ) {\n
+\t\t\tanchor.toggleClass( "ui-mini", opts.mini );\n
+\t\t}\n
+\n
+\t\tthis._super( options );\n
+\t},\n
+\n
+\t_handleExpandCollapse: function( isCollapse ) {\n
+\t\tvar opts = this._getOptions( this.options ),\n
+\t\t\tui = this._ui;\n
+\n
+\t\tui.status.text( isCollapse ? opts.expandCueText : opts.collapseCueText );\n
+\t\tui.heading\n
+\t\t\t.toggleClass( "ui-collapsible-heading-collapsed", isCollapse )\n
+\t\t\t.find( "a" ).first()\n
+\t\t\t.toggleClass( "ui-icon-" + opts.expandedIcon, !isCollapse )\n
+\n
+\t\t\t// logic or cause same icon for expanded/collapsed state would remove the ui-icon-class\n
+\t\t\t.toggleClass( "ui-icon-" + opts.collapsedIcon, ( isCollapse || opts.expandedIcon === opts.collapsedIcon ) )\n
+\t\t\t.removeClass( $.mobile.activeBtnClass );\n
+\n
+\t\tthis.element.toggleClass( "ui-collapsible-collapsed", isCollapse );\n
+\t\tui.content\n
+\t\t\t.toggleClass( "ui-collapsible-content-collapsed", isCollapse )\n
+\t\t\t.attr( "aria-hidden", isCollapse )\n
+\t\t\t.trigger( "updatelayout" );\n
+\t\tthis.options.collapsed = isCollapse;\n
+\t\tthis._trigger( isCollapse ? "collapse" : "expand" );\n
+\t},\n
+\n
+\texpand: function() {\n
+\t\tthis._handleExpandCollapse( false );\n
+\t},\n
+\n
+\tcollapse: function() {\n
+\t\tthis._handleExpandCollapse( true );\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tvar ui = this._ui,\n
+\t\t\topts = this.options;\n
+\n
+\t\tif ( opts.enhanced ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( ui.placeholder ) {\n
+\t\t\tui.originalHeading.insertBefore( ui.placeholder );\n
+\t\t\tui.placeholder.remove();\n
+\t\t\tui.heading.remove();\n
+\t\t} else {\n
+\t\t\tui.status.remove();\n
+\t\t\tui.heading\n
+\t\t\t\t.removeClass( "ui-collapsible-heading ui-collapsible-heading-collapsed" )\n
+\t\t\t\t.children()\n
+\t\t\t\t\t.contents()\n
+\t\t\t\t\t\t.unwrap();\n
+\t\t}\n
+\n
+\t\tui.anchor.contents().unwrap();\n
+\t\tui.content.contents().unwrap();\n
+\t\tthis.element\n
+\t\t\t.removeClass( "ui-collapsible ui-collapsible-collapsed " +\n
+\t\t\t\t"ui-collapsible-themed-content ui-collapsible-inset ui-corner-all" );\n
+\t}\n
+});\n
+\n
+// Defaults to be used by all instances of collapsible if per-instance values\n
+// are unset or if nothing is specified by way of inheritance from an accordion.\n
+// Note that this hash does not contain options "collapsed" or "heading",\n
+// because those are not inheritable.\n
+$.mobile.collapsible.defaults = {\n
+\texpandCueText: " click to expand contents",\n
+\tcollapseCueText: " click to collapse contents",\n
+\tcollapsedIcon: "plus",\n
+\tcontentTheme: "inherit",\n
+\texpandedIcon: "minus",\n
+\ticonpos: "left",\n
+\tinset: true,\n
+\tcorners: true,\n
+\tmini: false\n
+};\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.mobile.behaviors.addFirstLastClasses = {\n
+\t_getVisibles: function( $els, create ) {\n
+\t\tvar visibles;\n
+\n
+\t\tif ( create ) {\n
+\t\t\tvisibles = $els.not( ".ui-screen-hidden" );\n
+\t\t} else {\n
+\t\t\tvisibles = $els.filter( ":visible" );\n
+\t\t\tif ( visibles.length === 0 ) {\n
+\t\t\t\tvisibles = $els.not( ".ui-screen-hidden" );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn visibles;\n
+\t},\n
+\n
+\t_addFirstLastClasses: function( $els, $visibles, create ) {\n
+\t\t$els.removeClass( "ui-first-child ui-last-child" );\n
+\t\t$visibles.eq( 0 ).addClass( "ui-first-child" ).end().last().addClass( "ui-last-child" );\n
+\t\tif ( !create ) {\n
+\t\t\tthis.element.trigger( "updatelayout" );\n
+\t\t}\n
+\t},\n
+\n
+\t_removeFirstLastClasses: function( $els ) {\n
+\t\t$els.removeClass( "ui-first-child ui-last-child" );\n
+\t}\n
+};\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+var childCollapsiblesSelector = ":mobile-collapsible, " + $.mobile.collapsible.initSelector;\n
+\n
+$.widget( "mobile.collapsibleset", $.extend( {\n
+\tinitSelector: ":jqmData(role=\'collapsible-set\')",\n
+\n
+\toptions: $.extend( {\n
+\t\tenhanced: false,\n
+\t}, $.mobile.collapsible.defaults ),\n
+\n
+\t_handleCollapsibleExpand: function( event ) {\n
+\t\tvar closestCollapsible = $( event.target ).closest( ".ui-collapsible" );\n
+\n
+\t\tif ( closestCollapsible.parent().is( ":mobile-collapsibleset, :jqmData(role=\'collapsible-set\')" ) ) {\n
+\t\t\tclosestCollapsible\n
+\t\t\t\t.siblings( ".ui-collapsible:not(.ui-collapsible-collapsed)" )\n
+\t\t\t\t.collapsible( "collapse" );\n
+\t\t}\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tvar elem = this.element,\n
+\t\t\topts = this.options;\n
+\n
+\t\t$.extend( this, {\n
+\t\t\t_classes: ""\n
+\t\t});\n
+\n
+\t\tif ( !opts.enhanced ) {\n
+\t\t\telem.addClass( "ui-collapsible-set " +\n
+\t\t\t\tthis._themeClassFromOption( "ui-group-theme-", opts.theme ) + " " +\n
+\t\t\t\t( opts.corners && opts.inset ? "ui-corner-all " : "" ) );\n
+\t\t\tthis.element.find( $.mobile.collapsible.initSelector ).collapsible();\n
+\t\t}\n
+\n
+\t\tthis._on( elem, { collapsibleexpand: "_handleCollapsibleExpand" } );\n
+\t},\n
+\n
+\t_themeClassFromOption: function( prefix, value ) {\n
+\t\treturn ( value ? ( value === "none" ? "" : prefix + value ) : "" );\n
+\t},\n
+\n
+\t_init: function() {\n
+\t\tthis._refresh( true );\n
+\n
+\t\t// Because the corners are handled by the collapsible itself and the default state is collapsed\n
+\t\t// That was causing https://github.com/jquery/jquery-mobile/issues/4116\n
+\t\tthis.element\n
+\t\t\t.children( childCollapsiblesSelector )\n
+\t\t\t.filter( ":jqmData(collapsed=\'false\')" )\n
+\t\t\t.collapsible( "expand" );\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tvar ret,\n
+\t\t\telem = this.element,\n
+\t\t\tthemeClass = this._themeClassFromOption( "ui-group-theme-", options.theme );\n
+\n
+\t\tif ( themeClass ) {\n
+\t\t\telem\n
+\t\t\t\t.removeClass( this._themeClassFromOption( "ui-group-theme-", this.options.theme ) )\n
+\t\t\t\t.addClass( themeClass );\n
+\t\t}\n
+\n
+\t\tif ( options.corners !== undefined ) {\n
+\t\t\telem.toggleClass( "ui-corner-all", options.corners );\n
+\t\t}\n
+\n
+\t\tret = this._super( options );\n
+\t\tthis.element.children( ":mobile-collapsible" ).collapsible( "refresh" );\n
+\t\treturn ret;\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tvar el = this.element;\n
+\n
+\t\tthis._removeFirstLastClasses( el.children( childCollapsiblesSelector ) );\n
+\t\tel\n
+\t\t\t.removeClass( "ui-collapsible-set ui-corner-all " +\n
+\t\t\t\tthis._themeClassFromOption( "ui-group-theme", this.options.theme ) )\n
+\t\t\t.children( ":mobile-collapsible" )\n
+\t\t\t.collapsible( "destroy" );\n
+\t},\n
+\n
+\t_refresh: function( create ) {\n
+\t\tvar collapsiblesInSet = this.element.children( childCollapsiblesSelector );\n
+\n
+\t\t$.mobile.collapsible.prototype.enhance( collapsiblesInSet.not( ".ui-collapsible" ) );\n
+\n
+\t\tthis._addFirstLastClasses( collapsiblesInSet, this._getVisibles( collapsiblesInSet, create ), create );\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tthis._refresh( false );\n
+\t}\n
+}, $.mobile.behaviors.addFirstLastClasses ) );\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+// Deprecated in 1.4\n
+$.fn.fieldcontain = function(/* options */) {\n
+\treturn this.addClass( "ui-field-contain" );\n
+};\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.fn.grid = function( options ) {\n
+\treturn this.each(function() {\n
+\n
+\t\tvar $this = $( this ),\n
+\t\t\to = $.extend({\n
+\t\t\t\tgrid: null\n
+\t\t\t}, options ),\n
+\t\t\t$kids = $this.children(),\n
+\t\t\tgridCols = { solo:1, a:2, b:3, c:4, d:5 },\n
+\t\t\tgrid = o.grid,\n
+\t\t\titerator,\n
+\t\t\tletter;\n
+\n
+\t\t\tif ( !grid ) {\n
+\t\t\t\tif ( $kids.length <= 5 ) {\n
+\t\t\t\t\tfor ( letter in gridCols ) {\n
+\t\t\t\t\t\tif ( gridCols[ letter ] === $kids.length ) {\n
+\t\t\t\t\t\t\tgrid = letter;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t} else {\n
+\t\t\t\t\tgrid = "a";\n
+\t\t\t\t\t$this.addClass( "ui-grid-duo" );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\titerator = gridCols[grid];\n
+\n
+\t\t$this.addClass( "ui-grid-" + grid );\n
+\n
+\t\t$kids.filter( ":nth-child(" + iterator + "n+1)" ).addClass( "ui-block-a" );\n
+\n
+\t\tif ( iterator > 1 ) {\n
+\t\t\t$kids.filter( ":nth-child(" + iterator + "n+2)" ).addClass( "ui-block-b" );\n
+\t\t}\n
+\t\tif ( iterator > 2 ) {\n
+\t\t\t$kids.filter( ":nth-child(" + iterator + "n+3)" ).addClass( "ui-block-c" );\n
+\t\t}\n
+\t\tif ( iterator > 3 ) {\n
+\t\t\t$kids.filter( ":nth-child(" + iterator + "n+4)" ).addClass( "ui-block-d" );\n
+\t\t}\n
+\t\tif ( iterator > 4 ) {\n
+\t\t\t$kids.filter( ":nth-child(" + iterator + "n+5)" ).addClass( "ui-block-e" );\n
+\t\t}\n
+\t});\n
+};\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.navbar", {\n
+\toptions: {\n
+\t\ticonpos: "top",\n
+\t\tgrid: null\n
+\t},\n
+\n
+\t_create: function() {\n
+\n
+\t\tvar $navbar = this.element,\n
+\t\t\t$navbtns = $navbar.find( "a" ),\n
+\t\t\ticonpos = $navbtns.filter( ":jqmData(icon)" ).length ? this.options.iconpos : undefined;\n
+\n
+\t\t$navbar.addClass( "ui-navbar" )\n
+\t\t\t.attr( "role", "navigation" )\n
+\t\t\t.find( "ul" )\n
+\t\t\t.jqmEnhanceable()\n
+\t\t\t.grid({ grid: this.options.grid });\n
+\n
+\t\t$navbtns\n
+\t\t\t.each( function() {\n
+\t\t\t\tvar icon = $.mobile.getAttribute( this, "icon" ),\n
+\t\t\t\t\ttheme = $.mobile.getAttribute( this, "theme" ),\n
+\t\t\t\t\tclasses = "ui-btn";\n
+\n
+\t\t\t\tif ( theme ) {\n
+\t\t\t\t\tclasses += " ui-btn-" + theme;\n
+\t\t\t\t}\n
+\t\t\t\tif ( icon ) {\n
+\t\t\t\t\tclasses += " ui-icon-" + icon + " ui-btn-icon-" + iconpos;\n
+\t\t\t\t}\n
+\t\t\t\t$( this ).addClass( classes );\n
+\t\t\t});\n
+\n
+\t\t$navbar.delegate( "a", "vclick", function( /* event */ ) {\n
+\t\t\tvar activeBtn;\n
+\n
+\t\t\tif ( !$( this ).is( ".ui-disabled, .ui-btn-active" ) ) {\n
+\t\t\t\t$navbtns.removeClass( $.mobile.activeBtnClass );\n
+\t\t\t\t$( this ).addClass( $.mobile.activeBtnClass );\n
+\n
+\t\t\t\t// The code below is a workaround to fix #1181\n
+\t\t\t\tactiveBtn = $( this );\n
+\n
+\t\t\t\t$( document ).one( "pagehide", function() {\n
+\t\t\t\t\tactiveBtn.removeClass( $.mobile.activeBtnClass );\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\t// Buttons in the navbar with ui-state-persist class should regain their active state before page show\n
+\t\t$navbar.closest( ".ui-page" ).bind( "pagebeforeshow", function() {\n
+\t\t\t$navbtns.filter( ".ui-state-persist" ).addClass( $.mobile.activeBtnClass );\n
+\t\t});\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+var getAttr = $.mobile.getAttribute;\n
+\n
+$.widget( "mobile.listview", $.extend( {\n
+\n
+\toptions: {\n
+\t\ttheme: null,\n
+\t\tcountTheme: null, /* Deprecated in 1.4 */\n
+\t\tdividerTheme: null,\n
+\t\ticon: "carat-r",\n
+\t\tsplitIcon: "carat-r",\n
+\t\tsplitTheme: null,\n
+\t\tcorners: true,\n
+\t\tshadow: true,\n
+\t\tinset: false\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tvar t = this,\n
+\t\t\tlistviewClasses = "";\n
+\n
+\t\tlistviewClasses += t.options.inset ? " ui-listview-inset" : "";\n
+\n
+\t\tif ( !!t.options.inset ) {\n
+\t\t\tlistviewClasses += t.options.corners ? " ui-corner-all" : "";\n
+\t\t\tlistviewClasses += t.options.shadow ? " ui-shadow" : "";\n
+\t\t}\n
+\n
+\t\t// create listview markup\n
+\t\tt.element.addClass( " ui-listview" + listviewClasses );\n
+\n
+\t\tt.refresh( true );\n
+\t},\n
+\n
+\t// TODO: Remove in 1.5\n
+\t_findFirstElementByTagName: function( ele, nextProp, lcName, ucName ) {\n
+\t\tvar dict = {};\n
+\t\tdict[ lcName ] = dict[ ucName ] = true;\n
+\t\twhile ( ele ) {\n
+\t\t\tif ( dict[ ele.nodeName ] ) {\n
+\t\t\t\treturn ele;\n
+\t\t\t}\n
+\t\t\tele = ele[ nextProp ];\n
+\t\t}\n
+\t\treturn null;\n
+\t},\n
+\t// TODO: Remove in 1.5\n
+\t_addThumbClasses: function( containers ) {\n
+\t\tvar i, img, len = containers.length;\n
+\t\tfor ( i = 0; i < len; i++ ) {\n
+\t\t\timg = $( this._findFirstElementByTagName( containers[ i ].firstChild, "nextSibling", "img", "IMG" ) );\n
+\t\t\tif ( img.length ) {\n
+\t\t\t\t$( this._findFirstElementByTagName( img[ 0 ].parentNode, "parentNode", "li", "LI" ) ).addClass( img.hasClass( "ui-li-icon" ) ? "ui-li-has-icon" : "ui-li-has-thumb" );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t_getChildrenByTagName: function( ele, lcName, ucName ) {\n
+\t\tvar results = [],\n
+\t\t\tdict = {};\n
+\t\tdict[ lcName ] = dict[ ucName ] = true;\n
+\t\tele = ele.firstChild;\n
+\t\twhile ( ele ) {\n
+\t\t\tif ( dict[ ele.nodeName ] ) {\n
+\t\t\t\tresults.push( ele );\n
+\t\t\t}\n
+\t\t\tele = ele.nextSibling;\n
+\t\t}\n
+\t\treturn $( results );\n
+\t},\n
+\n
+\trefresh: function( create ) {\n
+\t\tvar buttonClass, pos, numli, item, itemClass, itemTheme, itemIcon, icon, a,\n
+\t\t\tisDivider, startCount, newStartCount, value, last, splittheme, splitThemeClass, spliticon,\n
+\t\t\taltButtonClass, dividerTheme,\n
+\t\t\to = this.options,\n
+\t\t\t$list = this.element,\n
+\t\t\tli = this._getChildrenByTagName( $list[ 0 ], "li", "LI" ),\n
+\t\t\tol = !!$.nodeName( $list[ 0 ], "ol" ),\n
+\t\t\tstart = $list.attr( "start" ),\n
+\t\t\titemClassDict = {},\n
+\t\t\tcountBubbles = $list.find( ".ui-li-count" ),\n
+\t\t\tcountTheme = getAttr( $list[ 0 ], "counttheme" ) || this.options.countTheme,\n
+\t\t\tcountThemeClass = countTheme ? "ui-body-" + countTheme : "ui-body-inherit";\n
+\n
+\t\tif ( o.theme ) {\n
+\t\t\t$list.addClass( "ui-group-theme-" + o.theme );\n
+\t\t}\n
+\n
+\t\t// Check if a start attribute has been set while taking a value of 0 into account\n
+\t\tif ( ol && ( start || start === 0 ) ) {\n
+\t\t\tstartCount = parseInt( start, 10 ) - 1;\n
+\t\t\t$list.css( "counter-reset", "listnumbering " + startCount );\n
+\t\t}\n
+\n
+\t\tfor ( pos = 0, numli = li.length; pos < numli; pos++ ) {\n
+\t\t\titem = li.eq( pos );\n
+\t\t\titemClass = "";\n
+\n
+\t\t\tif ( create || item[ 0 ].className.search( /\\bui-li-static\\b|\\bui-li-divider\\b/ ) < 0 ) {\n
+\t\t\t\ta = this._getChildrenByTagName( item[ 0 ], "a", "A" );\n
+\t\t\t\tisDivider = ( getAttr( item[ 0 ], "role" ) === "list-divider" );\n
+\t\t\t\tvalue = item.attr( "value" );\n
+\t\t\t\titemTheme = getAttr( item[ 0 ], "theme" );\n
+\n
+\t\t\t\tif ( a.length && a[ 0 ].className.search( /\\bui-btn\\b/ ) < 0 && !isDivider ) {\n
+\t\t\t\t\titemIcon = getAttr( item[ 0 ], "icon" );\n
+\t\t\t\t\ticon = ( itemIcon === false ) ? false : ( itemIcon || o.icon );\n
+\n
+\t\t\t\t\t// TODO: Remove in 1.5 together with links.js (links.js / .ui-link deprecated in 1.4)\n
+\t\t\t\t\ta.removeClass( "ui-link" );\n
+\n
+\t\t\t\t\tbuttonClass = "ui-btn";\n
+\n
+\t\t\t\t\tif ( itemTheme ) {\n
+\t\t\t\t\t\tbuttonClass += " ui-btn-" + itemTheme;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tif ( a.length > 1 ) {\n
+\t\t\t\t\t\titemClass = "ui-li-has-alt";\n
+\n
+\t\t\t\t\t\tlast = a.last();\n
+\t\t\t\t\t\tsplittheme = getAttr( last[ 0 ], "theme" ) || o.splitTheme || getAttr( item[ 0 ], "theme", true );\n
+\t\t\t\t\t\tsplitThemeClass = splittheme ? " ui-btn-" + splittheme : "";\n
+\t\t\t\t\t\tspliticon = getAttr( last[ 0 ], "icon" ) || getAttr( item[ 0 ], "icon" ) || o.splitIcon;\n
+\t\t\t\t\t\taltButtonClass = "ui-btn ui-btn-icon-notext ui-icon-" + spliticon + splitThemeClass;\n
+\n
+\t\t\t\t\t\tlast\n
+\t\t\t\t\t\t\t.attr( "title", $.trim( last.getEncodedText() ) )\n
+\t\t\t\t\t\t\t.addClass( altButtonClass )\n
+\t\t\t\t\t\t\t.empty();\n
+\t\t\t\t\t} else if ( icon ) {\n
+\t\t\t\t\t\tbuttonClass += " ui-btn-icon-right ui-icon-" + icon;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\ta.first().addClass( buttonClass );\n
+\t\t\t\t} else if ( isDivider ) {\n
+\t\t\t\t\tdividerTheme = ( getAttr( item[ 0 ], "theme" ) || o.dividerTheme || o.theme );\n
+\n
+\t\t\t\t\titemClass = "ui-li-divider ui-bar-" + ( dividerTheme ? dividerTheme : "inherit" );\n
+\n
+\t\t\t\t\titem.attr( "role", "heading" );\n
+\t\t\t\t} else if ( a.length <= 0 ) {\n
+\t\t\t\t\titemClass = "ui-li-static ui-body-" + ( itemTheme ? itemTheme : "inherit" );\n
+\t\t\t\t}\n
+\t\t\t\tif ( ol && value ) {\n
+\t\t\t\t\tnewStartCount = parseInt( value , 10 ) - 1;\n
+\n
+\t\t\t\t\titem.css( "counter-reset", "listnumbering " + newStartCount );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// Instead of setting item class directly on the list item\n
+\t\t\t// at this point in time, push the item into a dictionary\n
+\t\t\t// that tells us what class to set on it so we can do this after this\n
+\t\t\t// processing loop is finished.\n
+\n
+\t\t\tif ( !itemClassDict[ itemClass ] ) {\n
+\t\t\t\titemClassDict[ itemClass ] = [];\n
+\t\t\t}\n
+\n
+\t\t\titemClassDict[ itemClass ].push( item[ 0 ] );\n
+\t\t}\n
+\n
+\t\t// Set the appropriate listview item classes on each list item.\n
+\t\t// The main reason we didn\'t do this\n
+\t\t// in the for-loop above is because we can eliminate per-item function overhead\n
+\t\t// by calling addClass() and children() once or twice afterwards. This\n
+\t\t// can give us a significant boost on platforms like WP7.5.\n
+\n
+\t\tfor ( itemClass in itemClassDict ) {\n
+\t\t\t$( itemClassDict[ itemClass ] ).addClass( itemClass 
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAU=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="5" aka="AAAAAAAAAAU=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+);\n
+\t\t}\n
+\n
+\t\tcountBubbles.each( function() {\n
+\t\t\t$( this ).closest( "li" ).addClass( "ui-li-has-count" );\n
+\t\t});\n
+\t\tif ( countThemeClass ) {\n
+\t\t\tcountBubbles.addClass( countThemeClass );\n
+\t\t}\n
+\n
+\t\t// Deprecated in 1.4. From 1.5 you have to add class ui-li-has-thumb or ui-li-has-icon to the LI.\n
+\t\tthis._addThumbClasses( li );\n
+\t\tthis._addThumbClasses( li.find( ".ui-btn" ) );\n
+\n
+\t\tthis._addFirstLastClasses( li, this._getVisibles( li, create ), create );\n
+\t\t// autodividers binds to this to redraw dividers after the listview refresh\n
+\t\tthis._trigger( "afterrefresh" );\n
+\t}\n
+}, $.mobile.behaviors.addFirstLastClasses ) );\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+// TODO rename filterCallback/deprecate and default to the item itself as the first argument\n
+var defaultFilterCallback = function( index, searchValue ) {\n
+\treturn ( ( "" + ( $.mobile.getAttribute( this, "filtertext" ) || $( this ).text() ) )\n
+\t\t.toLowerCase().indexOf( searchValue ) === -1 );\n
+};\n
+\n
+$.widget( "mobile.filterable", {\n
+\n
+\tinitSelector: ":jqmData(filter=\'true\')",\n
+\n
+\toptions: {\n
+\t\tfilterReveal: false,\n
+\t\tfilterCallback: defaultFilterCallback,\n
+\t\tenhanced: false,\n
+\t\tinput: null,\n
+\t\tchildren: "> li, > option, optgroup options, tbody tr, .ui-controlgroup-controls .ui-btn"\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tvar opts = this.options;\n
+\n
+\t\t$.extend( this, {\n
+\t\t\t_search: null,\n
+\t\t\t_timer: 0\n
+\t\t});\n
+\n
+\t\tthis._setInput( opts.input );\n
+\t\tif ( !opts.enhanced ) {\n
+\t\t\tthis._filterItems( ( ( this._search && this._search.val() ) || "" ).toLowerCase() );\n
+\t\t}\n
+\t},\n
+\n
+\t_onKeyUp: function() {\n
+\t\tvar val, lastval,\n
+\t\t\tsearch = this._search;\n
+\n
+\t\tif ( search ) {\n
+\t\t\tval = search.val().toLowerCase(),\n
+\t\t\tlastval = $.mobile.getAttribute( search[ 0 ], "lastval" ) + "";\n
+\n
+\t\t\tif ( lastval && lastval === val ) {\n
+\t\t\t\t// Execute the handler only once per value change\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\n
+\t\t\tif ( this._timer ) {\n
+\t\t\t\twindow.clearTimeout( this._timer );\n
+\t\t\t\tthis._timer = 0;\n
+\t\t\t}\n
+\n
+\t\t\tthis._timer = this._delay( function() {\n
+\t\t\t\tthis._trigger( "beforefilter", "beforefilter", { input: search } );\n
+\n
+\t\t\t\t// Change val as lastval for next execution\n
+\t\t\t\tsearch[ 0 ].setAttribute( "data-" + $.mobile.ns + "lastval", val );\n
+\n
+\t\t\t\tthis._filterItems( val );\n
+\t\t\t\tthis._timer = 0;\n
+\t\t\t}, 250 );\n
+\t\t}\n
+\t},\n
+\n
+\t_getFilterableItems: function() {\n
+\t\tvar elem = this.element,\n
+\t\t\tchildren = this.options.children,\n
+\t\t\titems = !children ? { length: 0 }:\n
+\t\t\t\t$.isFunction( children ) ? children():\n
+\t\t\t\tchildren.nodeName ? $( children ):\n
+\t\t\t\tchildren.jquery ? children:\n
+\t\t\t\tthis.element.find( children );\n
+\n
+\t\tif ( items.length === 0 ) {\n
+\t\t\titems = elem.children();\n
+\t\t}\n
+\n
+\t\treturn items;\n
+\t},\n
+\n
+\t_filterItems: function( val ) {\n
+\t\tvar idx, callback, length, dst,\n
+\t\t\tshow = [],\n
+\t\t\thide = [],\n
+\t\t\topts = this.options,\n
+\t\t\tfilterItems = this._getFilterableItems();\n
+\n
+\t\tif ( val != null ) {\n
+\t\t\tcallback = opts.filterCallback || defaultFilterCallback;\n
+\t\t\tlength = filterItems.length;\n
+\n
+\t\t\t// Partition the items into those to be hidden and those to be shown\n
+\t\t\tfor ( idx = 0 ; idx < length ; idx++ ) {\n
+\t\t\t\tdst = ( callback.call( filterItems[ idx ], idx, val ) ) ? hide : show;\n
+\t\t\t\tdst.push( filterItems[ idx ] );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// If nothing is hidden, then the decision whether to hide or show the items\n
+\t\t// is based on the "filterReveal" option.\n
+\t\tif ( hide.length === 0 ) {\n
+\t\t\tfilterItems[ opts.filterReveal ? "addClass" : "removeClass" ]( "ui-screen-hidden" );\n
+\t\t} else {\n
+\t\t\t$( hide ).addClass( "ui-screen-hidden" );\n
+\t\t\t$( show ).removeClass( "ui-screen-hidden" );\n
+\t\t}\n
+\n
+\t\tthis._refreshChildWidget();\n
+\t},\n
+\n
+\t// The Default implementation of _refreshChildWidget attempts to call\n
+\t// refresh on collapsibleset, controlgroup, selectmenu, or listview\n
+\t_refreshChildWidget: function() {\n
+\t\tvar widget, idx,\n
+\t\t\trecognizedWidgets = [ "collapsibleset", "selectmenu", "controlgroup", "listview" ];\n
+\n
+\t\tfor ( idx = recognizedWidgets.length - 1 ; idx > -1 ; idx-- ) {\n
+\t\t\twidget = recognizedWidgets[ idx ];\n
+\t\t\tif ( $.mobile[ widget ] ) {\n
+\t\t\t\twidget = this.element.data( "mobile-" + widget );\n
+\t\t\t\tif ( widget && $.isFunction( widget.refresh ) ) {\n
+\t\t\t\t\twidget.refresh();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t// TODO: When the input is not internal, do not even store it in this._search\n
+\t_setInput: function ( selector ) {\n
+\t\tvar search = this._search;\n
+\n
+\t\t// Stop a pending filter operation\n
+\t\tif ( this._timer ) {\n
+\t\t\twindow.clearTimeout( this._timer );\n
+\t\t\tthis._timer = 0;\n
+\t\t}\n
+\n
+\t\tif ( search ) {\n
+\t\t\tthis._off( search, "keyup change input" );\n
+\t\t\tsearch = null;\n
+\t\t}\n
+\n
+\t\tif ( selector ) {\n
+\t\t\tsearch = selector.jquery ? selector:\n
+\t\t\t\tselector.nodeName ? $( selector ):\n
+\t\t\t\tthis.document.find( selector );\n
+\n
+\t\t\tthis._on( search, {\n
+\t\t\t\tkeyup: "_onKeyUp",\n
+\t\t\t\tchange: "_onKeyUp",\n
+\t\t\t\tinput: "_onKeyUp"\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tthis._search = search;\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tvar refilter = !( ( options.filterReveal === undefined ) &&\n
+\t\t\t\t( options.filterCallback === undefined ) &&\n
+\t\t\t\t( options.children === undefined ) );\n
+\n
+\t\tthis._super( options );\n
+\n
+\t\tif ( options.input !== undefined ) {\n
+\t\t\tthis._setInput( options.input );\n
+\t\t\trefilter = true;\n
+\t\t}\n
+\n
+\t\tif ( refilter ) {\n
+\t\t\tthis.refresh();\n
+\t\t}\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tvar opts = this.options,\n
+\t\t\titems = this._getFilterableItems();\n
+\n
+\t\tif ( opts.enhanced ) {\n
+\t\t\titems.toggleClass( "ui-screen-hidden", opts.filterReveal );\n
+\t\t} else {\n
+\t\t\titems.removeClass( "ui-screen-hidden" );\n
+\t\t}\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tif ( this._timer ) {\n
+\t\t\twindow.clearTimeout( this._timer );\n
+\t\t\tthis._timer = 0;\n
+\t\t}\n
+\t\tthis._filterItems( ( ( this._search && this._search.val() ) || "" ).toLowerCase() );\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+// Create a function that will replace the _setOptions function of a widget,\n
+// and will pass the options on to the input of the filterable.\n
+var replaceSetOptions = function( self, orig ) {\n
+\t\treturn function( options ) {\n
+\t\t\torig.call( this, options );\n
+\t\t\tself._syncTextInputOptions( options );\n
+\t\t};\n
+\t},\n
+\trDividerListItem = /(^|\\s)ui-li-divider(\\s|$)/,\n
+\torigDefaultFilterCallback = $.mobile.filterable.prototype.options.filterCallback;\n
+\n
+// Override the default filter callback with one that does not hide list dividers\n
+$.mobile.filterable.prototype.options.filterCallback = function( index, searchValue ) {\n
+\treturn !this.className.match( rDividerListItem ) &&\n
+\t\torigDefaultFilterCallback.call( this, index, searchValue );\n
+};\n
+\n
+$.widget( "mobile.filterable", $.mobile.filterable, {\n
+\toptions: {\n
+\t\tfilterPlaceholder: "Filter items...",\n
+\t\tfilterTheme: null\n
+\t},\n
+\n
+\n
+\t_create: function() {\n
+\t\tvar idx, widgetName,\n
+\t\t\telem = this.element,\n
+\t\t\trecognizedWidgets = [ "collapsibleset", "selectmenu", "controlgroup", "listview" ],\n
+\t\t\tcreateHandlers = {};\n
+\n
+\t\tthis._super();\n
+\n
+\t\t$.extend( this, {\n
+\t\t\t_widget: null\n
+\t\t});\n
+\n
+\t\tfor ( idx = recognizedWidgets.length - 1 ; idx > -1 ; idx-- ) {\n
+\t\t\twidgetName = recognizedWidgets[ idx ];\n
+\t\t\tif ( $.mobile[ widgetName ] ) {\n
+\t\t\t\tif ( this._setWidget( elem.data( "mobile-" + widgetName ) ) ) {\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t} else {\n
+\t\t\t\t\tcreateHandlers[ widgetName + "create" ] = "_handleCreate";\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( !this._widget ) {\n
+\t\t\tthis._on( elem, createHandlers );\n
+\t\t}\n
+\t},\n
+\n
+\t_handleCreate: function( evt ) {\n
+\t\tthis._setWidget( this.element.data( "mobile-" + evt.type.substring( 0, evt.type.length - 6 ) ) );\n
+\t},\n
+\n
+\t_setWidget: function( widget ) {\n
+\t\tif ( !this._widget && widget ) {\n
+\t\t\tthis._widget = widget;\n
+\t\t\tthis._widget._setOptions = replaceSetOptions( this, this._widget._setOptions );\n
+\t\t}\n
+\n
+\t\tif ( !!this._widget ) {\n
+\t\t\tthis._syncTextInputOptions( this._widget.options );\n
+\t\t}\n
+\n
+\t\treturn !!this._widget;\n
+\t},\n
+\n
+\t_isSearchInternal: function() {\n
+\t\treturn ( this._search && this._search.jqmData( "ui-filterable-" + this.uuid + "-internal" ) );\n
+\t},\n
+\n
+\t_setInput: function( selector ) {\n
+\t\tvar opts = this.options,\n
+\t\t\tupdatePlaceholder = true,\n
+\t\t\ttextinputOpts = {};\n
+\n
+\t\tif ( !selector ) {\n
+\t\t\tif ( this._isSearchInternal() ) {\n
+\n
+\t\t\t\t// Ignore the call to set a new input if the selector goes to falsy and\n
+\t\t\t\t// the current textinput is already of the internally generated variety.\n
+\t\t\t\treturn;\n
+\t\t\t} else {\n
+\n
+\t\t\t\t// Generating a new textinput widget. No need to set the placeholder\n
+\t\t\t\t// further down the function.\n
+\t\t\t\tupdatePlaceholder = false;\n
+\t\t\t\tselector = $( "<input " +\n
+\t\t\t\t\t"data-" + $.mobile.ns + "type=\'search\' " +\n
+\t\t\t\t\t"placeholder=\'" + opts.filterPlaceholder + "\'></input>" )\n
+\t\t\t\t\t.jqmData( "ui-filterable-" + this.uuid + "-internal", true );\n
+\t\t\t\t$( "<form class=\'ui-filterable\'></form>" )\n
+\t\t\t\t\t.append( selector )\n
+\t\t\t\t\t.submit( function( evt ) {\n
+\t\t\t\t\t\tevt.preventDefault();\n
+\t\t\t\t\t\tselector.blur();\n
+\t\t\t\t\t})\n
+\t\t\t\t\t.insertBefore( this.element );\n
+\t\t\t\tif ( $.mobile.textinput ) {\n
+\t\t\t\t\tif ( this.options.filterTheme != null ) {\n
+\t\t\t\t\t\ttextinputOpts[ "theme" ] = opts.filterTheme;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tselector.textinput( textinputOpts );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis._super( selector );\n
+\n
+\t\tif ( this._search && updatePlaceholder ) {\n
+\t\t\tthis._search.attr( "placeholder", this.options.filterPlaceholder );\n
+\t\t}\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tvar ret = this._super( options );\n
+\n
+\t\t// Need to set the filterPlaceholder after having established the search input\n
+\t\tif ( options.filterPlaceholder !== undefined ) {\n
+\t\t\tif ( this._search ) {\n
+\t\t\t\tthis._search.attr( "placeholder", options.filterPlaceholder );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( options.filterTheme !== undefined && this._search && $.mobile.textinput ) {\n
+\t\t\tthis._search.textinput( "option", "theme", options.filterTheme );\n
+\t\t}\n
+\n
+\t\treturn ret;\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tif ( this._isSearchInternal() ) {\n
+\t\t\tthis._search.remove();\n
+\t\t}\n
+\t\tthis._super();\n
+\t},\n
+\n
+\t_syncTextInputOptions: function( options ) {\n
+\t\tvar idx,\n
+\t\t\ttextinputOptions = {};\n
+\n
+\t\t// We only sync options if the filterable\'s textinput is of the internally\n
+\t\t// generated variety, rather than one specified by the user.\n
+\t\tif ( this._isSearchInternal() && $.mobile.textinput ) {\n
+\n
+\t\t\t// Apply only the options understood by textinput\n
+\t\t\tfor ( idx in $.mobile.textinput.prototype.options ) {\n
+\t\t\t\tif ( options[ idx ] !== undefined ) {\n
+\t\t\t\t\tif ( idx === "theme" && this.options.filterTheme != null ) {\n
+\t\t\t\t\t\ttextinputOptions[ idx ] = this.options.filterTheme;\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\ttextinputOptions[ idx ] = options[ idx ];\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tthis._search.textinput( "option", textinputOptions );\n
+\t\t}\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+function defaultAutodividersSelector( elt ) {\n
+\t// look for the text in the given element\n
+\tvar text = $.trim( elt.text() ) || null;\n
+\n
+\tif ( !text ) {\n
+\t\treturn null;\n
+\t}\n
+\n
+\t// create the text for the divider (first uppercased letter)\n
+\ttext = text.slice( 0, 1 ).toUpperCase();\n
+\n
+\treturn text;\n
+}\n
+\n
+$.widget( "mobile.listview", $.mobile.listview, {\n
+\toptions: {\n
+\t\tautodividers: false,\n
+\t\tautodividersSelector: defaultAutodividersSelector\n
+\t},\n
+\n
+\t_afterListviewRefresh: function() {\n
+\t\tvar el = this.element;\n
+\t\tthis._off( el, "listviewafterrefresh" );\n
+\t\tthis._replaceDividers();\n
+\t\tthis.refresh();\n
+\t\tthis._on( el, { listviewafterrefresh: "_afterListviewRefresh" } );\n
+\t},\n
+\n
+\t_replaceDividers: function() {\n
+\t\tvar i, lis, li, dividerText,\n
+\t\t\tlastDividerText = null,\n
+\t\t\tlist = this.element,\n
+\t\t\tdivider;\n
+\n
+\t\tlist.find( "li:jqmData(role=\'list-divider\')" ).remove();\n
+\n
+\t\tlis = list.find( "li" );\n
+\n
+\t\tfor ( i = 0; i < lis.length ; i++ ) {\n
+\t\t\tli = lis[ i ];\n
+\t\t\tdividerText = this.options.autodividersSelector( $( li ) );\n
+\n
+\t\t\tif ( dividerText && lastDividerText !== dividerText ) {\n
+\t\t\t\tdivider = document.createElement( "li" );\n
+\t\t\t\tdivider.appendChild( document.createTextNode( dividerText ) );\n
+\t\t\t\tdivider.setAttribute( "data-" + $.mobile.ns + "role", "list-divider" );\n
+\t\t\t\tli.parentNode.insertBefore( divider, li );\n
+\t\t\t}\n
+\n
+\t\t\tlastDividerText = dividerText;\n
+\t\t}\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tthis._super();\n
+\n
+\t\tif ( !this.options.autodividers ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis._afterListviewRefresh();\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+var rdivider = /(^|\\s)ui-li-divider($|\\s)/,\n
+\trhidden = /(^|\\s)ui-screen-hidden($|\\s)/;\n
+\n
+$.widget( "mobile.listview", $.mobile.listview, {\n
+\toptions: {\n
+\t\thidedividers: true\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tvar items, idx, item, hideDivider = true;\n
+\n
+\t\tthis._superApply( arguments );\n
+\n
+\t\tif ( this.options.hidedividers ) {\n
+\t\t\titems = this._getChildrenByTagName( this.element[ 0 ], "li", "LI" );\n
+\t\t\tfor ( idx = items.length - 1 ; idx > -1 ; idx-- ) {\n
+\t\t\t\titem = items[ idx ];\n
+\t\t\t\tif ( item.className.match( rdivider ) ) {\n
+\t\t\t\t\tif ( hideDivider ) {\n
+\t\t\t\t\t\titem.className = item.className + " ui-screen-hidden";\n
+\t\t\t\t\t}\n
+\t\t\t\t\thideDivider = true;\n
+\t\t\t\t} else {\n
+\t\t\t\t\tif ( !item.className.match( rhidden ) ) {\n
+\t\t\t\t\t\thideDivider = false;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.mobile.nojs = function( target ) {\n
+\t$( ":jqmData(role=\'nojs\')", target ).addClass( "ui-nojs" );\n
+};\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.mobile.behaviors.formReset = {\n
+\t_handleFormReset: function() {\n
+\t\tthis._on( this.element.closest( "form" ), {\n
+\t\t\treset: function() {\n
+\t\t\t\tthis._delay( "_reset" );\n
+\t\t\t}\n
+\t\t});\n
+\t}\n
+};\n
+\n
+})( jQuery );\n
+\n
+/*\n
+* "checkboxradio" plugin\n
+*/\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.checkboxradio", $.extend( {\n
+\n
+\tinitSelector: "input:not( :jqmData(role=\'flipswitch\' ) )[type=\'checkbox\'],input[type=\'radio\']:not( :jqmData(role=\'flipswitch\' ))",\n
+\n
+\toptions: {\n
+\t\ttheme: "inherit",\n
+\t\tmini: false,\n
+\t\twrapperClass: null,\n
+\t\tenhanced: false,\n
+\t\ticonpos: "left"\n
+\n
+\t},\n
+\t_create: function() {\n
+\t\tvar input = this.element,\n
+\t\t\to = this.options,\n
+\t\t\tinheritAttr = function( input, dataAttr ) {\n
+\t\t\t\treturn input.jqmData( dataAttr ) ||\n
+\t\t\t\t\tinput.closest( "form, fieldset" ).jqmData( dataAttr );\n
+\t\t\t},\n
+\t\t\t// NOTE: Windows Phone could not find the label through a selector\n
+\t\t\t// filter works though.\n
+\t\t\tparentLabel = input.closest( "label" ),\n
+\t\t\tlabel = parentLabel.length ? parentLabel :\n
+\t\t\t\tinput\n
+\t\t\t\t\t.closest( "form, fieldset, :jqmData(role=\'page\'), :jqmData(role=\'dialog\')" )\n
+\t\t\t\t\t.find( "label" )\n
+\t\t\t\t\t.filter( "[for=\'" + $.mobile.path.hashToSelector( input[0].id ) + "\']" )\n
+\t\t\t\t\t.first(),\n
+\t\t\tinputtype = input[0].type,\n
+\t\t\tcheckedState = inputtype + "-on",\n
+\t\t\tuncheckedState = inputtype + "-off",\n
+\t\t\tcheckedClass = "ui-" + checkedState,\n
+\t\t\tuncheckedClass = "ui-" + uncheckedState;\n
+\n
+\t\tif ( inputtype !== "checkbox" && inputtype !== "radio" ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( this.element[0].disabled ){\n
+\t\t\tthis.options.disabled = true;\n
+\t\t}\n
+\n
+\t\to.iconpos = inheritAttr( input, "iconpos" ) || label.attr( "data-" + $.mobile.ns + "iconpos" ) || o.iconpos,\n
+\n
+\t\t// Establish options\n
+\t\to.mini = inheritAttr( input, "mini" ) || o.mini;\n
+\n
+\t\t// Expose for other methods\n
+\t\t$.extend( this, {\n
+\t\t\tinput: input,\n
+\t\t\tlabel: label,\n
+\t\t\tparentLabel: parentLabel,\n
+\t\t\tinputtype: inputtype,\n
+\t\t\tcheckedClass: checkedClass,\n
+\t\t\tuncheckedClass: uncheckedClass,\n
+\t\t\tcheckedicon: checkedState,\n
+\t\t\tuncheckedicon: uncheckedState\n
+\t\t});\n
+\n
+\t\tif ( !this.options.enhanced ) {\n
+\t\t\tthis._enhance();\n
+\t\t}\n
+\n
+\t\tthis._on( label, {\n
+\t\t\tvmouseover: "_handleLabelVMouseOver",\n
+\t\t\tvclick: "_handleLabelVClick"\n
+\t\t});\n
+\n
+\t\tthis._on( input, {\n
+\t\t\tvmousedown: "_cacheVals",\n
+\t\t\tvclick: "_handleInputVClick",\n
+\t\t\tfocus: "_handleInputFocus",\n
+\t\t\tblur: "_handleInputBlur"\n
+\t\t});\n
+\n
+\t\tthis._handleFormReset();\n
+\t\tthis.refresh();\n
+\t},\n
+\n
+\t_enhance: function() {\n
+\t\tthis.label.addClass( "ui-btn ui-corner-all");\n
+\n
+\t\tif( this.parentLabel.length > 0 ){\n
+\t\t\tthis.input.add( this.label ).wrapAll( this._wrapper() );\n
+\t\t} else {\n
+\t\t\t//this.element.replaceWith( this.input.add( this.label ).wrapAll( this._wrapper() ) );\n
+\t\t\tthis.element.wrap( this._wrapper() );\n
+\t\t\tthis.element.parent().prepend( this.label );\n
+\t\t}\n
+\t\t\n
+\t\t// Wrap the input + label in a div\n
+\t\t\n
+\t\tthis._setOptions({\n
+\t\t\t"theme": this.options.theme,\n
+\t\t\t"iconpos": this.options.iconpos,\n
+\t\t\t"mini": this.options.mini\n
+\t\t});\n
+\n
+\t},\n
+\n
+\t_wrapper: function() {\n
+\t\treturn $( "<div class=\'"  + ( this.options.wrapperClass ? this.options.wrapperClass : "" ) + " ui-" + this.inputtype + ( this.options.disabled ? " ui-disabled" : "" ) + "\' >" );\n
+\t},\n
+\n
+\t_handleInputFocus: function() {\n
+\t\tthis.label.addClass( $.mobile.focusClass );\n
+\t},\n
+\n
+\t_handleInputBlur: function() {\n
+\t\tthis.label.removeClass( $.mobile.focusClass );\n
+\t},\n
+\n
+\t_handleInputVClick: function() {\n
+\t\tvar $this = this.element;\n
+\n
+\t\t// Adds checked attribute to checked input when keyboard is used\n
+\t\tif ( $this.is( ":checked" ) ) {\n
+\n
+\t\t\t$this.prop( "checked", true);\n
+\t\t\tthis._getInputSet().not( $this ).prop( "checked", false );\n
+\t\t} else {\n
+\t\t\t$this.prop( "checked", false );\n
+\t\t}\n
+\n
+\t\tthis._updateAll();\n
+\t},\n
+\n
+\t_handleLabelVMouseOver: function( event ) {\n
+\t\tif ( this.label.parent().hasClass( "ui-state-disabled" ) ) {\n
+\t\t\tevent.stopPropagation();\n
+\t\t}\n
+\t},\n
+\n
+\tenable: function() {\n
+\t\tthis._setOptions({\n
+\t\t\t"disabled": false\n
+\t\t});\n
+\t},\n
+\n
+\tdisable: function() {\n
+\t\tthis._setOptions({\n
+\t\t\t"disabled": true\n
+\t\t});\n
+\t},\n
+\n
+\t_handleLabelVClick: function( event ) {\n
+\t\tvar input = this.element;\n
+\n
+\t\tif ( input.is( ":disabled" ) ) {\n
+\t\t\tevent.preventDefault();\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis._cacheVals();\n
+\n
+\t\tinput.prop( "checked", this.inputtype === "radio" && true || !input.prop( "checked" ) );\n
+\n
+\t\t// trigger click handler\'s bound directly to the input as a substitute for\n
+\t\t// how label clicks behave normally in the browsers\n
+\t\t// TODO: it would be nice to let the browser\'s handle the clicks and pass them\n
+\t\t//       through to the associate input. we can swallow that click at the parent\n
+\t\t//       wrapper element level\n
+\t\tinput.triggerHandler( "click" );\n
+\n
+\t\t// Input set for common radio buttons will contain all the radio\n
+\t\t// buttons, but will not for checkboxes. clearing the checked status\n
+\t\t// of other radios ensures the active button state is applied properly\n
+\t\tthis._getInputSet().not( input ).prop( "checked", false );\n
+\n
+\t\tthis._updateAll();\n
+\t\treturn false;\n
+\t},\n
+\n
+\t_cacheVals: function() {\n
+\t\tthis._getInputSet().each( function() {\n
+\t\t\t$( this ).attr("data-" + $.mobile.ns + "cacheVal", this.checked );\n
+\t\t});\n
+\t},\n
+\n
+\t//returns either a set of radios with the same name attribute, or a single checkbox\n
+\t_getInputSet: function() {\n
+\t\tif ( this.inputtype === "checkbox" ) {\n
+\t\t\treturn this.element;\n
+\t\t}\n
+\n
+\t\treturn this.element.closest( "form, :jqmData(role=\'page\'), :jqmData(role=\'dialog\')" )\n
+\t\t\t.find( "input[name=\'" + this.element[ 0 ].name + "\'][type=\'" + this.inputtype + "\']" );\n
+\t},\n
+\n
+\t_updateAll: function() {\n
+\t\tvar self = this;\n
+\n
+\t\tthis._getInputSet().each( function() {\n
+\t\t\tvar $this = $( this );\n
+\n
+\t\t\tif ( this.checked || self.inputtype === "checkbox" ) {\n
+\t\t\t\t$this.trigger( "change" );\n
+\t\t\t}\n
+\t\t})\n
+\t\t.checkboxradio( "refresh" );\n
+\t},\n
+\n
+\t_reset: function() {\n
+\t\tthis.refresh();\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tvar input = this.element[ 0 ],\n
+\t\t\tactive = " " + $.mobile.activeBtnClass,\n
+\t\t\thasIcon = ( this.element.parents( ".ui-controlgroup-horizontal" ).length === 0 ),\n
+\t\t\tcheckedClass = this.checkedClass + ( hasIcon ? "" : active ),\n
+\t\t\tlabel = this.label;\n
+\n
+\t\tlabel\n
+\t\t\t.toggleClass( "ui-icon-" + this.checkedicon, input.checked )\n
+\t\t\t.toggleClass( "ui-icon-" + this.uncheckedicon, !input.checked );\n
+\t\tif ( input.checked ) {\n
+\t\t\tlabel.removeClass( this.uncheckedClass + active ).addClass( checkedClass );\n
+\t\t} else {\n
+\t\t\tlabel.removeClass( checkedClass ).addClass( this.uncheckedClass );\n
+\t\t}\n
+\t},\n
+\n
+\twidget: function() {\n
+\t\treturn this.label.parent();\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tif ( options.disabled !== undefined ) {\n
+\t\t\tthis.input.prop( "disabled", !!options.disabled );\n
+\t\t\tthis.widget().toggleClass( "ui-disabled", !!options.disabled );\n
+\t\t}\n
+\t\tif ( options.mini !== undefined ) {\n
+\t\t\tthis.label.parent().toggleClass( "ui-mini", !!options.mini );\n
+\t\t}\n
+\t\tif ( options.theme !== undefined ) {\n
+\t\t\tthis.label.removeClass( "ui-btn-" + this.options.theme ).addClass( "ui-btn-" + options.theme );\n
+\t\t}\n
+\t\tif ( options.wrapperClass !== undefined ) {\n
+\t\t\tthis.widget().removeClass( this.options.wrapperClass ).addClass( options.wrapperClass );\n
+\t\t}\n
+\t\tif ( options.iconpos !== undefined && ( this.element.parents( "[data-" + $.mobile.ns + "type=\'horizontal\']" ).length === 0 ) ) {\n
+\t\t\tthis.label.removeClass( "ui-btn-icon-" + this.options.iconpos ).addClass( "ui-btn-icon-" + options.iconpos );\n
+\t\t} else if ( this.element.parents( "[data-" + $.mobile.ns + "type=\'horizontal\']" ).length !== 0 ){\n
+\t\t\tthis.label.removeClass( "ui-btn-icon-" + this.options.iconpos );\n
+\t\t}\n
+\t\tthis._super( options );\n
+\t}\n
+\n
+}, $.mobile.behaviors.formReset ) );\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.button", {\n
+\n
+\tinitSelector: "input[type=\'button\'], input[type=\'submit\'], input[type=\'reset\']",\n
+\n
+\toptions: {\n
+\t\ttheme: null,\n
+\t\ticon: null,\n
+\t\ticonpos: "left",\n
+\t\ticonshadow: false, /* TODO: Deprecated in 1.4, remove in 1.5. */\n
+\t\tcorners: true,\n
+\t\tshadow: true,\n
+\t\tinline: null,\n
+\t\tmini: null,\n
+\t\twrapperClass: null,\n
+\t\tenhanced: false\n
+\t},\n
+\n
+\t_create: function() {\n
+\n
+\t\tif ( this.element.is( ":disabled" ) ) {\n
+\t\t\tthis.options.disabled = true;\n
+\t\t}\n
+\n
+\t\tif ( !this.options.enhanced ) {\n
+\t\t\tthis._enhance();\n
+\t\t}\n
+\n
+\t\t$.extend( this, {\n
+\t\t\twrapper: this.element.parent()\n
+\t\t});\n
+\n
+\t\tthis._on( {\n
+\t\t\tfocus: function() {\n
+\t\t\t\tthis.widget().addClass( $.mobile.focusClass );\n
+\t\t\t},\n
+\n
+\t\t\tblur: function() {\n
+\t\t\t\tthis.widget().removeClass( $.mobile.focusClass );\n
+\t\t\t}\n
+\t\t});\n
+\t\t\n
+\t\tthis.refresh( true );\n
+\t},\n
+\n
+\t_enhance: function() {\n
+\t\tthis.element.wrap( this._button() );\n
+\t},\n
+\n
+\t_button: function() {\n
+\t\treturn $("<div class=\'ui-btn ui-input-btn" +\n
+\t\t\t( this.options.wrapperClass ? " " + this.options.wrapperClass : "" ) +\n
+\t\t\t( this.options.theme ? " ui-btn-" + this.options.theme : "" ) +\n
+\t\t\t( this.options.corners ? " ui-corner-all" : "" ) +\n
+\t\t\t( this.options.shadow ? " ui-shadow" : "" ) +\n
+\t\t\t( this.options.inline ? " ui-btn-inline" : "" ) +\n
+\t\t\t( this.options.mini ? " ui-mini" : "" ) +\n
+\t\t\t( this.options.disabled ? " ui-disabled" : "" ) +\n
+\t\t\t( ( this.options.iconpos && this.options.icon ) ? " ui-btn-icon-" + this.options.iconpos : ( this.options.icon ? " ui-btn-icon-left" : "" ) ) +\n
+\t\t\t( this.options.icon ? " ui-icon-" + this.options.icon : "" ) +\n
+\t\t\t"\' >" + this.element.val() + "</div>");\n
+\t},\n
+\n
+\twidget: function() {\n
+\t\treturn this.wrapper;\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\t\tthis.element.insertBefore( this.button );\n
+\t\t\tthis.button.remove();\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tif ( options.theme !== undefined ) {\n
+\t\t\tthis.widget().removeClass( this.options.theme ).addClass( "ui-btn-" + options.theme );\n
+\t\t}\n
+\t\tif ( options.corners !== undefined ) {\n
+\t\t\tthis.widget().toggleClass( "ui-corner-all", options.corners );\n
+\t\t}\n
+\t\tif ( options.shadow !== undefined ) {\n
+\t\t\tthis.widget().toggleClass( "ui-shadow", options.shadow );\n
+\t\t}\n
+\t\tif ( options.inline !== undefined ) {\n
+\t\t\tthis.widget().toggleClass( "ui-btn-inline", options.inline );\n
+\t\t}\n
+\t\tif ( options.mini !== undefined ) {\n
+\t\t\tthis.widget().toggleClass( "ui-mini", options.mini );\n
+\t\t}\n
+\t\tif ( options.iconpos !== undefined ) {\n
+\t\t\tthis.widget().removeClass( "ui-btn-icon-" + options.iconpos );\n
+\t\t}\n
+\t\tif ( options.icon !== undefined ) {\n
+\t\t\tif ( !this.options.iconpos && !options.iconpos ) {\n
+\t\t\t\tthis.widget.toggleClass( "ui-btn-icon-left", options.icon );\n
+\t\t\t}\n
+\t\t\tthis.widget().removeClass( "ui-icon-" + this.options.icon ).toggleClass( "ui-icon-" + options.icon, options.icon );\n
+\t\t}\n
+\t},\n
+\n
+\trefresh: function( create ) {\n
+\t\tif ( this.options.icon && this.options.iconpos === "notext" && this.element.attr( "title" ) ) {\n
+\t\t\tthis.element.attr( "title", this.element.val() );\n
+\t\t}\n
+\t\tif ( !create ) {\n
+\t\t\tvar originalElement = this.element.detach();\n
+\t\t\t$( this.wrapper ).text( this.element.val() ).append( originalElement );\n
+\t\t}\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+(function( $ ) {\n
+\tvar\tmeta = $( "meta[name=viewport]" ),\n
+\t\tinitialContent = meta.attr( "content" ),\n
+\t\tdisabledZoom = initialContent + ",maximum-scale=1, user-scalable=no",\n
+\t\tenabledZoom = initialContent + ",maximum-scale=10, user-scalable=yes",\n
+\t\tdisabledInitially = /(user-scalable[\\s]*=[\\s]*no)|(maximum-scale[\\s]*=[\\s]*1)[$,\\s]/.test( initialContent );\n
+\n
+\t$.mobile.zoom = $.extend( {}, {\n
+\t\tenabled: !disabledInitially,\n
+\t\tlocked: false,\n
+\t\tdisable: function( lock ) {\n
+\t\t\tif ( !disabledInitially && !$.mobile.zoom.locked ) {\n
+\t\t\t\tmeta.attr( "content", disabledZoom );\n
+\t\t\t\t$.mobile.zoom.enabled = false;\n
+\t\t\t\t$.mobile.zoom.locked = lock || false;\n
+\t\t\t}\n
+\t\t},\n
+\t\tenable: function( unlock ) {\n
+\t\t\tif ( !disabledInitially && ( !$.mobile.zoom.locked || unlock === true ) ) {\n
+\t\t\t\tmeta.attr( "content", enabledZoom );\n
+\t\t\t\t$.mobile.zoom.enabled = true;\n
+\t\t\t\t$.mobile.zoom.locked = false;\n
+\t\t\t}\n
+\t\t},\n
+\t\trestore: function() {\n
+\t\t\tif ( !disabledInitially ) {\n
+\t\t\t\tmeta.attr( "content", initialContent );\n
+\t\t\t\t$.mobile.zoom.enabled = true;\n
+\t\t\t}\n
+\t\t}\n
+\t});\n
+\n
+}( jQuery ));\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.textinput", {\n
+\tinitSelector: "input[type=\'text\'], input[type=\'search\'], :jqmData(type=\'search\'), input[type=\'number\'], :jqmData(type=\'number\'), input[type=\'password\'], input[type=\'email\'], input[type=\'url\'], input[type=\'tel\'], textarea, input[type=\'time\'], input[type=\'date\'], input[type=\'month\'], input[type=\'week\'], input[type=\'datetime\'], input[type=\'datetime-local\'], input[type=\'color\'], input:not([type]), input[type=\'file\']",\n
+\n
+\toptions: {\n
+\t\ttheme: null,\n
+\t\tcorners: true,\n
+\t\tmini: false,\n
+\t\t// This option defaults to true on iOS devices.\n
+\t\tpreventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( "AppleWebKit" ) > -1,\n
+\t\twrapperClass: "",\n
+\t\tenhanced: false\n
+\t},\n
+\n
+\t_create: function() {\n
+\n
+\t\tvar o = this.options,\n
+\t\t\tisSearch = this.element.is( "[type=\'search\'], :jqmData(type=\'search\')" ),\n
+\t\t\tisTextarea = this.element[ 0 ].tagName === "TEXTAREA",\n
+\t\t\tinputNeedsWrap = ((this.element.is( "input" ) || this.element.is( "[data-" + ( $.mobile.ns || "" ) + "type=\'search\']" ) ) && !this.element.is( "[data-" + ( $.mobile.ns || "" ) + "type=\'range\']" ));\n
+\t\t\t\n
+\t\t$.extend( this, {\n
+\t\t\tthemeclass: "ui-body-" + ( ( o.theme === null ) ? "inherit" : o.theme ),\n
+\t\t\tisSearch: isSearch,\n
+\t\t\tisTextarea: isTextarea,\n
+\t\t\tinputNeedsWrap: inputNeedsWrap\n
+\t\t});\n
+\n
+\t\tthis._autoCorrect();\n
+\n
+\t\tif ( this.element[ 0 ].disabled ) {\n
+\t\t\tthis.options.disabled = true;\n
+\t\t}\n
+\n
+\t\tif ( !o.enhanced ) {\n
+\t\t\tthis._enhance();\n
+\t\t}\n
+\n
+\t\tthis._on( {\n
+\t\t\t"focus": "_handleFocus",\n
+\t\t\t"blur": "_handleBlur"\n
+\t\t});\n
+\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tthis.setOptions({\n
+\t\t\t"disabled" : this.element.is( ":disabled" )\n
+\t\t});\n
+\t},\n
+\n
+\t_enhance: function() {\n
+\n
+\t\tif ( this.isTextarea ) {\n
+\t\t\tthis.element.addClass( "ui-input-text" );\n
+\t\t}\n
+\n
+\t\tif ( this.element.is( "textarea, [data-" + ( $.mobile.ns || "" ) + "type=\'range\']" ) ) {\n
+\t\t\tthis.element.addClass( "ui-shadow-inset" );\n
+\t\t\tthis._setOptions( this.options );\n
+\t\t}\n
+\n
+\t\t//"search" and "text" input widgets\n
+\t\tif ( this.inputNeedsWrap ) {\n
+\t\t\tthis.element.wrap( this._wrap() );\n
+\t\t}\n
+\n
+\t},\n
+\n
+\twidget: function() {\n
+\t\treturn ( this.inputNeedsWrap ) ? this.element.parent() : this.element;\n
+\t},\n
+\n
+\t_wrap: function() {\n
+\t\tvar opts = this.options;\n
+\n
+\t\treturn $( "<div class=\'" +\n
+\t\t\t( this.isSearch ? "ui-input-search " : "ui-input-text " ) +\n
+\t\t\t"ui-body-" + ( ( opts.theme === null ) ? "inherit" : opts.theme ) + " " +\n
+\t\t\t( opts.corners ? "ui-corner-all " : "" ) +\n
+\t\t\t( opts.mini ? "ui-mini " : "" ) +\n
+\t\t\t( opts.disabled ? "ui-state-disabled " : "" ) +\n
+\t\t\t( opts.wrapperClass !== "" ? opts.wrapperClass + " " : "" ) +\n
+\t\t\t"ui-shadow-inset\'></div>" );\n
+\t},\n
+\n
+\t_autoCorrect: function() {\n
+\t\t// XXX: Temporary workaround for issue 785 (Apple bug 8910589).\n
+\t\t//      Turn off autocorrect and autocomplete on non-iOS 5 devices\n
+\t\t//      since the popup they use can\'t be dismissed by the user. Note\n
+\t\t//      that we test for the presence of the feature by looking for\n
+\t\t//      the autocorrect property on the input element. We currently\n
+\t\t//      have no test for iOS 5 or newer so we\'re temporarily using\n
+\t\t//      the touchOverflow support flag for jQM 1.0. Yes, I feel dirty. - jblas\n
+\t\tif ( typeof this.element[0].autocorrect !== "undefined" && !$.support.touchOverflow ) {\n
+\t\t\t// Set the attribute instead of the property just in case there\n
+\t\t\t// is code that attempts to make modifications via HTML.\n
+\t\t\tthis.element[0].setAttribute( "autocorrect", "off" );\n
+\t\t\tthis.element[0].setAttribute( "autocomplete", "off" );\n
+\t\t}\n
+\t},\n
+\n
+\t_handleBlur: function() {\n
+\t\tthis.element.removeClass( $.mobile.focusClass );\n
+\t\tif ( this.options.preventFocusZoom ) {\n
+\t\t\t$.mobile.zoom.enable( true );\n
+\t\t}\n
+\t},\n
+\n
+\t_handleFocus: function() {\n
+\t\t// In many situations, iOS will zoom into the input upon tap, this prevents that from happening\n
+\t\tif ( this.options.preventFocusZoom ) {\n
+\t\t\t$.mobile.zoom.disable( true );\n
+\t\t}\n
+\t\tthis.element.addClass( $.mobile.focusClass );\n
+\t},\n
+\n
+\t_setOptions: function ( options ) {\n
+\t\tvar themeclass,\n
+\t\t\touter = this.widget();\n
+\n
+\t\tthis._super( options );\n
+\n
+\t\tif ( options.theme !== undefined ) {\n
+\t\t\tthemeclass = "ui-body-" + ( ( options.theme === null ) ? "inherit" : options.theme );\n
+\t\t\touter.removeClass( this.themeclass ).addClass( themeclass );\n
+\t\t\tthis.themeclass = themeclass;\n
+\t\t}\n
+\n
+\t\tif ( options.corners !== undefined ) {\n
+\t\t\touter.toggleClass( "ui-corner-all", options.corners );\n
+\t\t}\n
+\n
+\t\tif ( options.mini !== undefined ) {\n
+\t\t\touter.toggleClass( "ui-mini", options.mini );\n
+\t\t}\n
+\n
+\t\tif ( options.disabled !== undefined ) {\n
+\t\t\tthis.element.prop( "disabled", !!options.disabled );\n
+\t\t\touter.toggleClass( "ui-disabled", !!options.disabled );\n
+\t\t}\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tif ( this.options.enhanced ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tif ( this.inputNeedsWrap ) {\n
+\t\t\tthis.element.unwrap();\n
+\t\t}\n
+\t\tthis.element.removeClass( "ui-input-text " + this.themeclass + " ui-corner-all ui-mini ui-disabled" );\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.slider", $.extend( {\n
+\tinitSelector: "input[type=\'range\'], :jqmData(type=\'range\'), :jqmData(role=\'slider\')",\n
+\n
+\twidgetEventPrefix: "slide",\n
+\n
+\toptions: {\n
+\t\ttheme: null,\n
+\t\ttrackTheme: null,\n
+\t\tcorners: true,\n
+\t\tmini: false,\n
+\t\thighlight: false\n
+\t},\n
+\n
+\t_create: function() {\n
+\n
+\t\t// TODO: Each of these should have comments explain what they\'re for\n
+\t\tvar self = this,\n
+\t\t\tcontrol = this.element,\n
+\t\t\ttrackTheme = this.options.trackTheme || $.mobile.getAttribute( control[ 0 ], "theme" ),\n
+\t\t\ttrackThemeClass = trackTheme ? " ui-bar-" + trackTheme : " ui-bar-inherit",\n
+\t\t\tcornerClass = ( this.options.corners || control.jqmData( "corners" ) ) ? " ui-corner-all" : "",\n
+\t\t\tminiClass = ( this.options.mini || control.jqmData( "mini" ) ) ? " ui-mini" : "",\n
+\t\t\tcType = control[ 0 ].nodeName.toLowerCase(),\n
+\t\t\tisToggleSwitch = ( cType === "select" ),\n
+\t\t\tisRangeslider = control.parent().is( ":jqmData(role=\'rangeslider\')" ),\n
+\t\t\tselectClass = ( isToggleSwitch ) ? "ui-slider-switch" : "",\n
+\t\t\tcontrolID = control.attr( "id" ),\n
+\t\t\t$label = $( "[for=\'" + controlID + "\']" ),\n
+\t\t\tlabelID = $label.attr( "id" ) || controlID + "-label",\n
+\t\t\tmin = !isToggleSwitch ? parseFloat( control.attr( "min" ) ) : 0,\n
+\t\t\tmax =  !isToggleSwitch ? parseFloat( control.attr( "max" ) ) : control.find( "option" ).length-1,\n
+\t\t\tstep = window.parseFloat( control.attr( "step" ) || 1 ),\n
+\t\t\tdomHandle = document.createElement( "a" ),\n
+\t\t\thandle = $( domHandle ),\n
+\t\t\tdomSlider = document.createElement( "div" ),\n
+\t\t\tslider = $( domSlider ),\n
+\t\t\tvaluebg = this.options.highlight && !isToggleSwitch ? (function() {\n
+\t\t\t\tvar bg = document.createElement( "div" );\n
+\t\t\t\tbg.className = "ui-slider-bg " + $.mobile.activeBtnClass;\n
+\t\t\t\treturn $( bg ).prependTo( slider );\n
+\t\t\t})() : false,\n
+\t\t\toptions,\n
+\t\t\twrapper,\n
+\t\t\tj, length,\n
+\t\t\ti, optionsCount, origTabIndex,\n
+\t\t\tside, activeClass, sliderImg;\n
+\n
+\t\t$label.attr( "id", labelID );\n
+\t\tthis.isToggleSwitch = isToggleSwitch;\n
+\n
+\t\tdomHandle.setAttribute( "href", "#" );\n
+\t\tdomSlider.setAttribute( "role", "application" );\n
+\t\tdomSlider.className = [ this.isToggleSwitch ? "ui-slider ui-slider-track ui-shadow-inset " : "ui-slider-track ui-shadow-inset ", selectClass, trackThemeClass, cornerClass, miniClass ].join( "" );\n
+\t\tdomHandle.className = "ui-slider-handle";\n
+\t\tdomSlider.appendChild( domHandle );\n
+\n
+\t\thandle.attr({\n
+\t\t\t"role": "slider",\n
+\t\t\t"aria-valuemin": min,\n
+\t\t\t"aria-valuemax": max,\n
+\t\t\t"aria-valuenow": this._value(),\n
+\t\t\t"aria-valuetext": this._value(),\n
+\t\t\t"title": this._value(),\n
+\t\t\t"aria-labelledby": labelID\n
+\t\t});\n
+\n
+\t\t$.extend( this, {\n
+\t\t\tslider: slider,\n
+\t\t\thandle: handle,\n
+\t\t\tcontrol: control,\n
+\t\t\ttype: cType,\n
+\t\t\tstep: step,\n
+\t\t\tmax: max,\n
+\t\t\tmin: min,\n
+\t\t\tvaluebg: valuebg,\n
+\t\t\tisRangeslider: isRangeslider,\n
+\t\t\tdragging: false,\n
+\t\t\tbeforeStart: null,\n
+\t\t\tuserModified: false,\n
+\t\t\tmouseMoved: false\n
+\t\t});\n
+\n
+\t\tif ( isToggleSwitch ) {\n
+\t\t\t// TODO: restore original tabindex (if any) in a destroy method\n
+\t\t\torigTabIndex = control.attr( "tabindex" );\n
+\t\t\tif ( origTabIndex ) {\n
+\t\t\t\thandle.attr( "tabindex", origTabIndex );\n
+\t\t\t}\n
+\t\t\tcontrol.attr( "tabindex", "-1" ).focus(function() {\n
+\t\t\t\t$( this ).blur();\n
+\t\t\t\thandle.focus();\n
+\t\t\t});\n
+\n
+\t\t\twrapper = document.createElement( "div" );\n
+\t\t\twrapper.className = "ui-slider-inneroffset";\n
+\n
+\t\t\tfor ( j = 0, length = domSlider.childNodes.length; j < length; j++ ) {\n
+\t\t\t\twrapper.appendChild( domSlider.childNodes[j] );\n
+\t\t\t}\n
+\n
+\t\t\tdomSlider.appendChild( wrapper );\n
+\n
+\t\t\t// slider.wrapInner( "<div class=\'ui-slider-inneroffset\'></div>" );\n
+\n
+\t\t\t// make the handle move with a smooth transition\n
+\t\t\thandle.addClass( "ui-slider-handle-snapping" );\n
+\n
+\t\t\toptions = control.find( "option" );\n
+\n
+\t\t\tfor ( i = 0, optionsCount = options.length; i < optionsCount; i++ ) {\n
+\t\t\t\tside = !i ? "b" : "a";\n
+\t\t\t\tactiveClass = !i ? "" : " " + $.mobile.activeBtnClass;\n
+\t\t\t\tsliderImg = document.createElement( "span" );\n
+\n
+\t\t\t\tsliderImg.className = [ "ui-slider-label ui-slider-label-", side, activeClass ].join( "" );\n
+\t\t\t\tsliderImg.setAttribute( "role", "img" );\n
+\t\t\t\tsliderImg.appendChild( document.createTextNode( options[i].innerHTML ) );\n
+\t\t\t\t$( sliderImg ).prependTo( slider );\n
+\t\t\t}\n
+\n
+\t\t\tself._labels = $( ".ui-slider-label", slider );\n
+\n
+\t\t}\n
+\n
+\t\t// monitor the input for updated values\n
+\t\tcontrol.addClass( isToggleSwitch ? "ui-slider-switch" : "ui-slider-input" );\n
+\n
+\t\tthis._on( control, {\n
+\t\t\t"change": "_controlChange",\n
+\t\t\t"keyup": "_controlKeyup",\n
+\t\t\t"blur": "_controlBlur",\n
+\t\t\t"vmouseup": "_controlVMouseUp"\n
+\t\t});\n
+\n
+\t\tslider.bind( "vmousedown", $.proxy( this._sliderVMouseDown, this ) )\n
+\t\t\t.bind( "vclick", false );\n
+\n
+\t\t// We have to instantiate a new function object for the unbind to work properly\n
+\t\t// since the method itself is defined in the prototype (causing it to unbind everything)\n
+\t\tthis._on( document, { "vmousemove": "_preventDocumentDrag" });\n
+\t\tthis._on( slider.add( document ), { "vmouseup": "_sliderVMouseUp" });\n
+\n
+\t\tslider.insertAfter( control );\n
+\n
+\t\t// wrap in a div for styling purposes\n
+\t\tif ( !isToggleSwitch && !isRangeslider ) {\n
+\t\t\twrapper = this.options.mini ? "<div class=\'ui-slider ui-mini\'>" : "<div class=\'ui-slider\'>";\n
+\n
+\t\t\tcontrol.add( slider ).wrapAll( wrapper );\n
+\t\t}\n
+\n
+\t\t// bind the handle event callbacks and set the context to the widget instance\n
+\t\tthis._on( this.handle, {\n
+\t\t\t"vmousedown": "_handleVMouseDown",\n
+\t\t\t"keydown": "_handleKeydown",\n
+\t\t\t"keyup": "_handleKeyup"\n
+\t\t});\n
+\n
+\t\tthis.handle.bind( "vclick", false );\n
+\n
+\t\tthis._handleFormReset();\n
+\n
+\t\tthis.refresh( undefined, undefined, true );\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tif ( options.theme !== undefined ) {\n
+\t\t\tthis._setTheme( options.theme );\n
+\t\t}\n
+\n
+\t\tif ( options.trackTheme !== undefined ) {\n
+\t\t\tthis._setTrackTheme( options.trackTheme );\n
+\t\t}\n
+\n
+\t\tif ( options.corners !== undefined ) {\n
+\t\t\tthis._setCorners( options.corners );\n
+\t\t}\n
+\n
+\t\tif ( options.mini !== undefined ) {\n
+\t\t\tthis._setMini( options.mini );\n
+\t\t}\n
+\n
+\t\tif ( options.highlight !== undefined ) {\n
+\t\t\tthis._setHighlight( options.highlight );\n
+\t\t}\n
+\n
+\t\tif ( options.disabled !== undefined ) {\n
+\t\t\tthis._setDisabled( options.disabled );\n
+\t\t}\n
+\t\tthis._super( options );\n
+\t},\n
+\n
+\t_controlChange: function( event ) {\n
+\t\t// if the user dragged the handle, the "change" event was triggered from inside refresh(); don\'t call refresh() again\n
+\t\tif ( this._trigger( "controlchange", event ) === false ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\tif ( !this.mouseMoved ) {\n
+\t\t\tthis.refresh( this._value(), true );\n
+\t\t}\n
+\t},\n
+\n
+\t_controlKeyup: function(/* event */) { // necessary?\n
+\t\tthis.refresh( this._value(), true, true );\n
+\t},\n
+\n
+\t_controlBlur: function(/* event */) {\n
+\t\tthis.refresh( this._value(), true );\n
+\t},\n
+\n
+\t// it appears the clicking the up and down buttons in chrome on\n
+\t// range/number inputs doesn\'t trigger a change until the field is\n
+\t// blurred. Here we check thif the value has changed and refresh\n
+\t_controlVMouseUp: function(/* event */) {\n
+\t\tthis._checkedRefresh();\n
+\t},\n
+\n
+\t// NOTE force focus on handle\n
+\t_handleVMouseDown: function(/* event */) {\n
+\t\tthis.handle.focus();\n
+\t},\n
+\n
+\t_handleKeydown: function( event ) {\n
+\t\tvar index = this._value();\n
+\t\tif ( this.options.disabled ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// In all cases prevent the default and mark the handle as active\n
+\t\tswitch ( event.keyCode ) {\n
+\t\t\tcase $.mobile.keyCode.HOME:\n
+\t\t\tcase $.mobile.keyCode.END:\n
+\t\t\tcase $.mobile.keyCode.PAGE_UP:\n
+\t\t\tcase $.mobile.keyCode.PAGE_DOWN:\n
+\t\t\tcase $.mobile.keyCode.UP:\n
+\t\t\tcase $.mobile.keyCode.RIGHT:\n
+\t\t\tcase $.mobile.keyCode.DOWN:\n
+\t\t\tcase $.mobile.keyCode.LEFT:\n
+\t\t\t\tevent.preventDefault();\n
+\n
+\t\t\t\tif ( !this._keySliding ) {\n
+\t\t\t\t\tthis._keySliding = true;\n
+\t\t\t\t\tthis.handle.addClass( "ui-state-active" ); /* TODO: We don\'t use this class for styling. Do we need to add it? */\n
+\t\t\t\t}\n
+\n
+\t\t\t\tbreak;\n
+\t\t}\n
+\n
+\t\t// move the slider according to the keypress\n
+\t\tswitch ( event.keyCode ) {\n
+\t\t\tcase $.mobile.keyCode.HOME:\n
+\t\t\t\tthis.refresh( this.min );\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.mobile.keyCode.END:\n
+\t\t\t\tthis.refresh( this.max );\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.mobile.keyCode.PAGE_UP:\n
+\t\t\tcase $.mobile.keyCode.UP:\n
+\t\t\tcase $.mobile.keyCode.RIGHT:\n
+\t\t\t\tthis.refresh( index + this.step );\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.mobile.keyCode.PAGE_DOWN:\n
+\t\t\tcase $.mobile.keyCode.DOWN:\n
+\t\t\tcase $.mobile.keyCode.LEFT:\n
+\t\t\t\tthis.refresh( index - this.step );\n
+\t\t\t\tbreak;\n
+\t\t}\n
+\t}, // remove active mark\n
+\n
+\t_handleKeyup: function(/* event */) {\n
+\t\tif ( this._keySliding ) {\n
+\t\t\tthis._keySliding = false;\n
+\t\t\tthis.handle.removeClass( "ui-state-active" ); /* See comment above. */\n
+\t\t}\n
+\t},\n
+\n
+\t_sliderVMouseDown: function( event ) {\n
+\t\t// NOTE: we don\'t do this in refresh because we still want to\n
+\t\t//       support programmatic alteration of disabled inputs\n
+\t\tif ( this.options.disabled || !( event.which === 1 || event.which === 0 || event.which === undefined ) ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\tif ( this._trigger( "beforestart", event ) === false ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\t\tthis.dragging = true;\n
+\t\tthis.userModified = false;\n
+\t\tthis.mouseMoved = false;\n
+\n
+\t\tif ( this.isToggleSwitch ) {\n
+\t\t\tthis.beforeStart = this.element[0].selectedIndex;\n
+\t\t}\n
+\n
+\t\tthis.refresh( event );\n
+\t\tthis._trigger( "start" );\n
+\t\treturn false;\n
+\t},\n
+\n
+\t_sliderVMouseUp: function() {\n
+\t\tif ( this.dragging ) {\n
+\t\t\tthis.dragging = false;\n
+\n
+\t\t\tif ( this.isToggleSwitch ) {\n
+\t\t\t\t// make the handle move with a smooth transition\n
+\t\t\t\tthis.handle.addClass( "ui-slider-handle-snapping" );\n
+\n
+\t\t\t\tif ( this.mouseMoved ) {\n
+\t\t\t\t\t// this is a drag, change the value only if user dragged enough\n
+\t\t\t\t\tif ( this.userModified ) {\n
+\t\t\t\t\t\tthis.refresh( this.beforeStart === 0 ? 1 : 0 );\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tthis.refresh( this.beforeStart );\n
+\t\t\t\t\t}\n
+\t\t\t\t} else {\n
+\t\t\t\t\t// this is just a click, change the value\n
+\t\t\t\t\tthis.refresh( this.beforeStart === 0 ? 1 : 0 );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tthis.mouseMoved = false;\n
+\t\t\tthis._trigger( "stop" );\n
+\t\t\treturn false;\n
+\t\t}\n
+\t},\n
+\n
+\t_preventDocumentDrag: function( event ) {\n
+\t\t\t// NOTE: we don\'t do this in refresh because we still want to\n
+\t\t\t//       support programmatic alteration of disabled inputs\n
+\t\t\tif ( this._trigger( "drag", event ) === false) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t\tif ( this.dragging && !this.options.disabled ) {\n
+\n
+\t\t\t\t// this.mouseMoved must be updated before refresh() because it will be used in the control "change" event\n
+\t\t\t\tthis.mouseMoved = true;\n
+\n
+\t\t\t\tif ( this.isToggleSwitch ) {\n
+\t\t\t\t\t// make the handle move in sync with the mouse\n
+\t\t\t\t\tthis.handle.removeClass( "ui-slider-handle-snapping" );\n
+\t\t\t\t}\n
+\n
+\t\t\t\tthis.refresh( event );\n
+\n
+\t\t\t\t// only after refresh() you can calculate this.userModified\n
+\t\t\t\tthis.userModified = this.beforeStart !== this.element[0].selectedIndex;\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t_checkedRefresh: function() {\n
+\t\tif ( this.value !== this._value() ) {\n
+\t\t\tthis.refresh( this._value() );\n
+\t\t}\n
+\t},\n
+\n
+\t_value: function() {\n
+\t\treturn  this.isToggleSwitch ? this.element[0].selectedIndex : parseFloat( this.element.val() ) ;\n
+\t},\n
+\n
+\n
+\t_reset: function() {\n
+\t\tthis.refresh( undefined, false, true );\n
+\t},\n
+\n
+\trefresh: function( val, isfromControl, preventInputUpdate ) {\n
+\t\t// NOTE: we don\'t return here because we want to support programmatic\n
+\t\t//       alteration of the input value, which should still update the slider\n
+\n
+\t\tvar self = this,\n
+\t\t\tparentTheme = $.mobile.getAttribute( this.element[ 0 ], "theme" ),\n
+\t\t\ttheme = this.options.theme || parentTheme,\n
+\t\t\tthemeClass =  theme ? " ui-btn-" + theme : "",\n
+\t\t\ttrackTheme = this.options.trackTheme || parentTheme,\n
+\t\t\ttrackThemeClass = trackTheme ? " ui-bar-" + trackTheme : " ui-bar-inherit",\n
+\t\t\tcornerClass = this.options.corners ? " ui-corner-all" : "",\n
+\t\t\tminiClass = this.options.mini ? " ui-mini" : "",\n
+\t\t\tleft, width, data, tol,\n
+\t\t\tpxStep, percent,\n
+\t\t\tcontrol, isInput, optionElements, min, max, step,\n
+\t\t\tnewval, valModStep, alignValue, percentPerStep,\n
+\t\t\thandlePercent, aPercent, bPercent,\n
+\t\t\tvalueChanged;\n
+\n
+\t\tself.slider[0].className = [ this.isToggleSwitch ? "ui-slider ui-slider-switch ui-slider-track ui-shadow-inset" : "ui-slider-track ui-shadow-inset", trackThemeClass, cornerClass, miniClass ].join( "" );\n
+\t\tif ( this.options.disabled || this.element.prop( "disabled" ) ) {\n
+\t\t\tthis.disable();\n
+\t\t}\n
+\n
+\t\t// set the stored value for comparison later\n
+\t\tthis.value = this._value();\n
+\t\tif ( this.options.highlight && !this.isToggleSwitch && this.slider.find( ".ui-slider-bg" ).length === 0 ) {\n
+\t\t\tthis.valuebg = (function() {\n
+\t\t\t\tvar bg = document.createElement( "div" );\n
+\t\t\t\tbg.className = "ui-slider-bg " + $.mobile.activeBtnClass;\n
+\t\t\t\treturn $( bg ).prependTo( self.slider );\n
+\t\t\t})();\n
+\t\t}\n
+\t\tthis.handle.addClass( "ui-btn" + themeClass + " ui-shadow" );\n
+\n
+\t\tcontrol = this.element;\n
+\t\tisInput = !this.isToggleSwitch;\n
+\t\toptionElements = isInput ? [] : control.find( "option" );\n
+\t\tmin =  isInput ? parseFloat( control.attr( "min" ) ) : 0;\n
+\t\tmax = isInput ? parseFloat( control.attr( "max" ) ) : optionElements.length - 1;\n
+\t\tstep = ( isInput && parseFloat( control.attr( "step" ) ) > 0 ) ? parseFloat( control.attr( "step" ) ) : 1;\n
+\n
+\t\tif ( typeof val === "object" ) {\n
+\t\t\tdata = val;\n
+\t\t\t// a slight tolerance helped get to the ends of the slider\n
+\t\t\ttol = 8;\n
+\n
+\t\t\tleft = this.slider.offset().left;\n
+\t\t\twidth = this.slider.width();\n
+\t\t\tpxStep = width/((max-min)/step);\n
+\t\t\tif ( !this.dragging ||\n
+\t\t\t\t\tdata.pageX < left - tol ||\n
+\t\t\t\t\tdata.pageX > left + width + tol ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\tif ( pxStep > 1 ) {\n
+\t\t\t\tpercent = ( ( data.pageX - left ) / width ) * 100;\n
+\t\t\t} else {\n
+\t\t\t\tpercent = Math.round( ( ( data.pageX - left ) / width ) * 100 );\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tif ( val == null ) {\n
+\t\t\t\tval = isInput ? parseFloat( control.val() || 0 ) : control[0].selectedIndex;\n
+\t\t\t}\n
+\t\t\tpercent = ( parseFloat( val ) - min ) / ( max - min ) * 100;\n
+\t\t}\n
+\n
+\t\tif ( isNaN( percent ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tnewval = ( percent / 100 ) * ( max - min ) + min;\n
+\n
+\t\t//from jQuery UI slider, the following source will round to the nearest step\n
+\t\tvalModStep = ( newval - min ) % step;\n
+\t\talignValue = newval - valModStep;\n
+\n
+\t\tif ( Math.abs( valModStep ) * 2 >= step ) {\n
+\t\t\talignValue += ( valModStep > 0 ) ? step : ( -step );\n
+\t\t}\n
+\n
+\t\tpercentPerStep = 100/((max-min)/step);\n
+\t\t// Since JavaScript has problems with large floats, round\n
+\t\t// the final value to 5 digits after the decimal point (see jQueryUI: #4124)\n
+\t\tnewval = parseFloat( alignValue.toFixed(5) );\n
+\n
+\t\tif ( typeof pxStep === "undefined" ) {\n
+\t\t\tpxStep = width / ( (max-min) / step );\n
+\t\t}\n
+\t\tif ( pxStep > 1 && isInput ) {\n
+\t\t\tpercent = ( newval - min ) * percentPerStep * ( 1 / step );\n
+\t\t}\n
+\t\tif ( percent < 0 ) {\n
+\t\t\tpercent = 0;\n
+\t\t}\n
+\n
+\t\tif ( percent > 100 ) {\n
+\t\t\tpercent = 100;\n
+\t\t}\n
+\n
+\t\tif ( newval < min ) {\n
+\t\t\tnewval = min;\n
+\t\t}\n
+\n
+\t\tif ( newval > max ) {\n
+\t\t\tnewval = max;\n
+\t\t}\n
+\n
+\t\tthis.handle.css( "left", percent + "%" );\n
+\n
+\t\tthis.handle[0].setAttribute( "aria-valuenow", isInput ? newval : optionElements.eq( newval ).attr( "value" ) );\n
+\n
+\t\tthis.handle[0].setAttribute( "aria-valuetext", isInput ? newval : optionElements.eq( newval ).getEncodedText() );\n
+\n
+\t\tthis.handle[0].setAttribute( "title", isInput ? newval : optionElements.eq( newval ).getEncodedText() );\n
+\n
+\t\tif ( this.valuebg ) {\n
+\t\t\tthis.valuebg.css( "width", percent + "%" );\n
+\t\t}\n
+\n
+\t\t// drag the label widths\n
+\t\tif ( this._labels ) {\n
+\t\t\thandlePercent = this.handle.width() / this.slider.width() * 100;\n
+\t\t\taPercent = percent && handlePercent + ( 100 - handlePercent ) * percent / 100;\n
+\t\t\tbPercent = percent === 100 ? 0 : Math.min( handlePercent + 100 - aPercent, 100 );\n
+\n
+\t\t\tthis._labels.each(function() {\n
+\t\t\t\tvar ab = $( this ).hasClass( "ui-slider-label-a" );\n
+\t\t\t\t$( this ).width( ( ab ? aPercent : bPercent  ) + "%" );\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tif ( !preventInputUpdate ) {\n
+\t\t\tvalueChanged = false;\n
+\n
+\t\t\t// update control"s value\n
+\t\t\tif ( isInput ) {\n
+\t\t\t\tvalueChanged = control.val() !== newval;\n
+\t\t\t\tcontrol.val( newval );\n
+\t\t\t} else {\n
+\t\t\t\tvalueChanged = control[ 0 ].selectedIndex !== newval;\n
+\t\t\t\tcontrol[ 0 ].selectedIndex = newval;\n
+\t\t\t}\n
+\t\t\tif ( this._trigger( "beforechange", val ) === false) {\n
+\t\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t\tif ( !isfromControl && valueChanged ) {\n
+\t\t\t\tcontrol.trigger( "change" );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t_setHighlight: function( value ) {\n
+\t\tvalue = !!value;\n
+\t\tif ( value ) {\n
+\t\t\tthis.options.highlight = !!value;\n
+\t\t\tthis.refresh();\n
+\t\t} else if ( this.valuebg ) {\n
+\t\t\tthis.valuebg.remove();\n
+\t\t\tthis.valuebg = false;\n
+\t\t}\n
+\t},\n
+\n
+\t_setTheme: function( value ) {\n
+\t\tthis.handle\n
+\t\t\t.removeClass( "ui-btn-" + this.options.theme )\n
+\t\t\t.addClass( "ui-btn-" + value );\n
+\n
+\t\tvar currentTheme = this.options.theme ? this.options.theme : "inherit",\n
+\t\t\tnewTheme = value ? value : "inherit";\n
+\n
+\t\tthis.control\n
+\t\t\t.removeClass( "ui-body-" + currentTheme )\n
+\t\t\t.addClass( "ui-body-" + newTheme );\n
+\t},\n
+\n
+\t_setTrackTheme: function( value ) {\n
+\t\tvar currentTrackTheme = this.options.trackTheme ? this.options.trackTheme : "inherit",\n
+\t\t\tnewTrackTheme = value ? value : "inherit";\n
+\n
+\t\tthis.slider\n
+\t\t\t.removeClass( "ui-body-" + currentTrackTheme )\n
+\t\t\t.addClass( "ui-body-" + newTrackTheme );\n
+\t},\n
+\n
+\t_setMini: function( value ) {\n
+\t\tvalue = !!value;\n
+\t\tif ( !this.isToggleSwitch && !this.isRangeslider ) {\n
+\t\t\tthis.slider.parent().toggleClass( "ui-mini", value );\n
+\t\t\tthis.element.toggleClass( "ui-mini", value );\n
+\t\t}\n
+\t\tthis.slider.toggleClass( "ui-mini", value );\n
+\t},\n
+\n
+\t_setCorners: function( value ) {\n
+\t\tthis.slider.toggleClass( "ui-corner-all", value );\n
+\n
+\t\tif ( !this.isToggleSwitch ) {\n
+\t\t\tthis.control.toggleClass( "ui-corner-all", value );\n
+\t\t}\n
+\t},\n
+\n
+\t_setDisabled: function( value ) {\n
+\t\tvalue = !!value;\n
+\t\tthis.element.prop( "disabled", value );\n
+\t\tthis.slider.toggleClass( "ui-disabled", value ).attr( "aria-disabled", value );\n
+\t}\n
+\n
+}, $.mobile.behaviors.formReset ) );\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.flipswitch", $.extend({\n
+\n
+\toptions: {\n
+\t\tonText: "On",\n
+\t\toffText: "Off",\n
+\t\ttheme: null,\n
+\t\tenhanced: false,\n
+\t\twrapperClass: null,\n
+\t\tmini: false\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\t\tif ( !this.options.enhanced ) {\n
+\t\t\t\tthis._enhance();\n
+\t\t\t} else {\n
+\t\t\t\t$.extend( this, {\n
+\t\t\t\t\tflipswitch: this.element.parent(),\n
+\t\t\t\t\ton: this.element.find( ".ui-flipswitch-on" ).eq( 0 ),\n
+\t\t\t\t\toff: this.element.find( ".ui-flipswitch-off" ).eq(0),\n
+\t\t\t\t\ttype: this.element.get( 0 ).tagName\n
+\t\t\t\t});\n
+\t\t\t}\n
+\n
+\t\t\tif( this.element.is( ":disabled" ) ){\n
+\t\t\t\tthis._setOptions({\n
+\t\t\t\t\t"disabled": true\n
+\t\t\t\t});\n
+\t\t\t}\n
+\n
+\t\t\tthis._on( this.flipswitch, {\n
+\t\t\t\t"click": "_toggle",\n
+\t\t\t\t"swipeleft": "_left",\n
+\t\t\t\t"swiperight": "_right"\n
+\t\t\t});\n
+\n
+\t\t\tthis._on( this.on, {\n
+\t\t\t\t"keydown": "_keydown"\n
+\t\t\t});\n
+\t},\n
+\n
+\twidget: function() {\n
+\t\treturn this.flipswitch;\n
+\t},\n
+\n
+\t_left: function() {\n
+\t\tthis.flipswitch.removeClass( "ui-flipswitch-active" );\n
+\t\tif ( this.type === "SELECT" ) {\n
+\t\t\tthis.element.get( 0 ).selectedIndex = 0;\n
+\t\t} else {\n
+\t\t\tthis.element.prop( "checked", true );\n
+\t\t}\n
+\t\tthis._trigger( "change" );\n
+\t},\n
+\n
+\t_right: function() {\n
+\t\tthis.flipswitch.addClass( "ui-flipswitch-active" );\n
+\t\tif ( this.type === "SELECT" ) {\n
+\t\t\tthis.element.get( 0 ).selectedIndex = 1;\n
+\t\t} else {\n
+\t\t\tthis.element.prop( "checked", false );\n
+\t\t}\n
+\t\tthis._trigger( "change" );\n
+\t},\n
+\n
+\t_enhance: function() {\n
+\t\tvar flipswitch = $( "<div>" ),\n
+\t\t\ttheme = this.options.theme ? this.options.theme : "inherit",\n
+\t\t\ton = $( "<span tabindex=\'1\'></span>" ),\n
+\t\t\toff = $( "<span></span>" ),\n
+\t\t\ttype = this.element.get( 0 ).tagName,\n
+\t\t\tonText = ( type === "INPUT" ) ? this.options.onText : this.element.find( "option" ).eq( 1 ).text(),\n
+\t\t\toffText = ( type === "INPUT" ) ? this.options.offText : this.element.find( "option" ).eq( 0 ).text();\n
+\n
+\t\t\ton.addClass( "ui-flipswitch-on ui-btn ui-shadow ui-btn-inherit" ).text( onText );\n
+\t\t\toff.addClass( "ui-flipswitch-off" ).text( offText );\n
+\t\t\t\n
+\t\t\tflipswitch.addClass( "ui-flipswitch ui-shadow-inset ui-corner-all ui-bar-" + theme + " " + ( this.options.wrapperClass ? this.options.wrapperClass : "" ) + " " + ( ( this.element.is( ":checked" ) || this.element.find("option").eq(1).is(":selected") ) ? "ui-flipswitch-active" : "" ) + ( this.element.is(":disabled") ? " ui-state-disabled": "") + ( this.options.mini ? " ui-mini": "" ) ).append( on, off );\n
+\t\t\t\n
+\t\t\tthis.element.addClass( "ui-flipswitch-input" );\n
+\t\t\tthis.element.after( flipswitch ).appendTo( flipswitch );\n
+\n
+\t\t$.extend( this, {\n
+\t\t\tflipswitch: flipswitch,\n
+\t\t\ton: on,\n
+\t\t\toff: off,\n
+\t\t\ttype: type\n
+\t\t});\n
+\t},\n
+\n
+\t_change: function() {\n
+\t\tvar direction;\n
+\t\t\n
+\t\tif ( this.type === "SELECT" ) {\n
+\t\t\tdirection = ( this.element.get( 0 ).selectedIndex > 0 )? "_right": "_left";\n
+\t\t} else {\n
+\t\t\tdirection = this.element.is( ":checked" )? "_right": "_left";\n
+\t\t}\n
+\t\tthis[ direction ]();\n
+\t},\n
+\n
+\t_toggle: function() {\n
+\t\tvar direction = this.flipswitch.hasClass( "ui-flipswitch-active" ) ? "_left" : "_right";\n
+\t\t\n
+\t\tthis[direction]();\n
+\t},\n
+\n
+\t_keydown: function( e ) {\n
+\t\tif ( e.which === $.mobile.keyCode.LEFT ) {\n
+\t\t\tthis._left();\n
+\t\t} else if ( e.which === $.mobile.keyCode.RIGHT ) {\n
+\t\t\tthis._right();\n
+\t\t} else if ( e.which === $.mobile.keyCode.SPACE ) {\n
+\t\t\tthis._toggle();\n
+\t\t\te.preventDefault();\n
+\t\t}\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tif ( options.theme !== undefined ) {\n
+\t\t\tvar currentTheme = options.theme ? options.theme : "inherit",\n
+\t\t\t\tnewTheme = options.theme ? options.theme : "inherit";\n
+\n
+\t\t\tthis.widget()\n
+\t\t\t\t.removeClass( "ui-bar-" + currentTheme )\n
+\t\t\t\t.addClass( "ui-bar-" + newTheme );\n
+\t\t}\n
+\t\tif ( options.onText !== undefined ) {\n
+\t\t\tthis.on.text( options.onText );\n
+\t\t}\n
+\t\tif ( options.offText !== undefined ) {\n
+\t\t\tthis.off.text( options.offText );\n
+\t\t}\n
+\t\tif ( options.disabled !== undefined ) {\n
+\t\t\tthis.widget().toggleClass( "ui-state-disabled", options.disabled );\n
+\t\t}\n
+\t\tif( options.mini !== undefined ) {\n
+\t\t\tthis.widget().toggleClass( "ui-mini", options.mini );\n
+\t\t}\n
+\t\t\n
+\t\tthis._super( options );\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tif ( this.options.enhanced ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\tthis.on.remove();\n
+\t\tthis.off.remove();\n
+\t\tthis.element.unwrap();\n
+\t\tthis.flipswitch.remove();\n
+\t\tthis.removeClass( "ui-flipswitch-input" );\n
+\t}\n
+\n
+}, $.mobile.behaviors.formReset ) );\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\t$.widget( "mobile.rangeslider", $.extend( {\n
+\n
+\t\toptions: {\n
+\t\t\ttheme: null,\n
+\t\t\ttrackTheme: null,\n
+\t\t\tcorners: true,\n
+\t\t\tmini: false,\n
+\t\t\thighlight: true\n
+\t\t},\n
+\n
+\t\t_create: function() {\n
+\t\t\tvar $el = this.element,\n
+\t\t\telClass = this.options.mini ? "ui-rangeslider ui-mini" : "ui-rangeslider",\n
+\t\t\t_inputFirst = $el.find( "input" ).first(),\n
+\t\t\t_inputLast = $el.find( "input" ).last(),\n
+\t\t\t_label = $el.find( "label" ).first(),\n
+\t\t\t_sliderFirst = $.data( _inputFirst.get(0), "mobile-slider" ).slider,\n
+\t\t\t_sliderLast = $.data( _inputLast.get(0), "mobile-slider" ).slider,\n
+\t\t\tfirstHandle = $.data( _inputFirst.get(0), "mobile-slider" ).handle,\n
+\t\t\t_sliders = $( "<div class=\'ui-rangeslider-sliders\' />" ).appendTo( $el );\n
+\n
+\t\t\t_inputFirst.addClass( "ui-rangeslider-first" );\n
+\t\t\t_inputLast.addClass( "ui-rangeslider-last" );\n
+\t\t\t$el.addClass( elClass );\n
+\n
+\t\t\t_sliderFirst.appendTo( _sliders );\n
+\t\t\t_sliderLast.appendTo( _sliders );\n
+\t\t\t_label.insertBefore( $el );\n
+\t\t\tfirstHandle.prependTo( _sliderLast );\n
+\n
+\t\t\t$.extend( this, {\n
+\t\t\t\t_inputFirst: _inputFirst,\n
+\t\t\t\t_inputLast: _inputLast,\n
+\t\t\t\t_sliderFirst: _sliderFirst,\n
+\t\t\t\t_sliderLast: _sliderLast,\n
+\t\t\t\t_label: _label,\n
+\t\t\t\t_targetVal: null,\n
+\t\t\t\t_sliderTarget: false,\n
+\t\t\t\t_sliders: _sliders,\n
+\t\t\t\t_proxy: false\n
+\t\t\t});\n
+\n
+\t\t\tthis.refresh();\n
+\t\t\tthis._on( this.element.find( "input.ui-slider-input" ), {\n
+\t\t\t\t"slidebeforestart": "_slidebeforestart",\n
+\t\t\t\t"slidestop": "_slidestop",\n
+\t\t\t\t"slidedrag": "_slidedrag",\n
+\t\t\t\t"slidebeforechange": "_change",\n
+\t\t\t\t"blur": "_change",\n
+\t\t\t\t"keyup": "_change"\n
+\t\t\t});\n
+\t\t\tthis._on({\n
+\t\t\t\t"mousedown":"_change"\n
+\t\t\t});\n
+\t\t\tthis._on( this.element.closest( "form" ), {\n
+\t\t\t\t"reset":"_handleReset"\n
+\t\t\t});\n
+\t\t\tthis._on( firstHandle, {\n
+\t\t\t\t"vmousedown": "_dragFirstHandle"\n
+\t\t\t});\n
+\t\t},\n
+\t\t_handleReset: function() {\n
+\t\t\tvar self = this;\n
+\t\t\t//we must wait for the stack to unwind before updateing other wise sliders will not have updated yet\n
+\t\t\tsetTimeout( function() {\n
+\t\t\t\tself._updateHighlight();\n
+\t\t\t},0);\n
+\t\t},\n
+\n
+\t\t_dragFirstHandle: function( event ) {\n
+\t\t\t//if the first handle is dragged send the event to the first slider\n
+\t\t\t$.data( this._inputFirst.get(0), "mobile-slider" ).dragging = true;\n
+\t\t\t$.data( this._inputFirst.get(0), "mobile-slider" ).refresh( event );\n
+\t\t\treturn false;\n
+\t\t},\n
+\n
+\t\t_slidedrag: function( event ) {\n
+\t\t\tvar first = $( event.target ).is( this._inputFirst ),\n
+\t\t\t\totherSlider = ( first ) ? this._inputLast : this._inputFirst;\n
+\n
+\t\t\tthis._sliderTarget = false;\n
+\t\t\t//if the drag was initiated on an extreme and the other handle is focused send the events to\n
+\t\t\t//the closest handle\n
+\t\t\tif ( ( this._proxy === "first" && first ) || ( this._proxy === "last" && !first ) ) {\n
+\t\t\t\t$.data( otherSlider.get(0), "mobile-slider" ).dragging = true;\n
+\t\t\t\t$.data( otherSlider.get(0), "mobile-slider" ).refresh( event );\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_slidestop: function( event ) {\n
+\t\t\tvar first = $( event.target ).is( this._inputFirst );\n
+\n
+\t\t\tthis._proxy = false;\n
+\t\t\t//this stops dragging of the handle and brings the active track to the front\n
+\t\t\t//this makes clicks on the track go the the last handle used\n
+\t\t\tthis.element.find( "input" ).trigger( "vmouseup" );\n
+\t\t\tthis._sliderFirst.css( "z-index", first ? 1 : "" );\n
+\t\t},\n
+\n
+\t\t_slidebeforestart: function( event ) {\n
+\t\t\tthis._sliderTarget = false;\n
+\t\t\t//if the track is the target remember this and the original value\n
+\t\t\tif ( $( event.originalEvent.target ).hasClass( "ui-slider-track" ) ) {\n
+\t\t\t\tthis._sliderTarget = true;\n
+\t\t\t\tthis._targetVal = $( event.target ).val();\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_setOptions: function( options ) {\n
+\t\t\tif ( options.theme !== undefined ) {\n
+\t\t\t\tthis._setTheme( options.theme );\n
+\t\t\t}\n
+\n
+\t\t\tif ( options.trackTheme !== undefined ) {\n
+\t\t\t\tthis._setTrackTheme( options.trackTheme );\n
+\t\t\t}\n
+\n
+\t\t\tif ( options.mini !== undefined ) {\n
+\t\t\t\tthis._setMini( options.mini );\n
+\t\t\t}\n
+\n
+\t\t\tif ( options.highlight !== undefined ) {\n
+\t\t\t\tthis._setHighlight( options.highlight );\n
+\t\t\t}\n
+\t\t\tthis._super( options );\n
+\t\t\tthis.refresh();\n
+\t\t},\n
+\n
+\t\trefresh: function() {\n
+\t\t\tvar $el = this.element,\n
+\t\t\t\to = this.options;\n
+\n
+\t\t\t$el.find( "input" ).slider({\n
+\t\t\t\ttheme: o.theme,\n
+\t\t\t\ttrackTheme: o.trackTheme,\n
+\t\t\t\tdisabled: o.disabled,\n
+\t\t\t\tcorners: o.corners,\n
+\t\t\t\tmini: o.mini,\n
+\t\t\t\thighlight: o.highlight\n
+\t\t\t}).slider( "refresh" );\n
+\t\t\tthis._updateHighlight();\n
+\t\t},\n
+\n
+\t\t_change: function( event ) {\n
+\t\t\tif ( event.type === "keyup" ) {\n
+\t\t\t\tthis._updateHighlight();\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\n
+\t\t\tvar self = this,\n
+\t\t\t\tmin = parseFloat( this._inputFirst.val(), 10 ),\n
+\t\t\t\tmax = parseFloat( this._inputLast.val(), 10 ),\n
+\t\t\t\tfirst = $( event.target ).hasClass( "ui-rangeslider-first" ),\n
+\t\t\t\tthisSlider = first ? this._inputFirst : this._inputLast,\n
+\t\t\t\totherSlider = first ? this._inputLast : this._inputFirst;\n
+\n
+\n
+\t\t\tif ( ( this._inputFirst.val() > this._inputLast.val() && event.type === "mousedown" && !$(event.target).hasClass("ui-slider-handle")) ){\n
+\t\t\t\tthisSlider.blur();\n
+\t\t\t} else if ( event.type === "mousedown" ){\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\tif ( min > max && !this._sliderTarget ) {\n
+\t\t\t\t//this prevents min from being greater then max\n
+\t\t\t\tthisSlider.val( first ? max: min ).slider( "refresh" );\n
+\t\t\t\tthis._trigger( "normalize" );\n
+\t\t\t} else if ( min > max ) {\n
+\t\t\t\t//this makes it so clicks on the target on either extreme go to the closest handle\n
+\t\t\t\tthisSlider.val( this._targetVal ).slider( "refresh" );\n
+\n
+\t\t\t\t//You must wait for the stack to unwind so first slider is updated before updating second\n
+\t\t\t\tsetTimeout( function() {\n
+\t\t\t\t\totherSlider.val( first ? min: max ).slider( "refresh" );\n
+\t\t\t\t\t$.data( otherSlider.get(0), "mobile-slider" ).handle.focus();\n
+\t\t\t\t\tself._sliderFirst.css( "z-index", first ? "" : 1 );\n
+\t\t\t\t\tself._trigger( "normalize" );\n
+\t\t\t\t}, 0 );\n
+\t\t\t\tthis._proxy = ( first ) ? "first" : "last";\n
+\t\t\t}\n
+\t\t\t//fixes issue where when both _sliders are at min they cannot be adjusted\n
+\t\t\tif ( min === max ) {\n
+\t\t\t\t$.data( thisSlider.get(0), "mobile-slider" ).handle.css( "z-index", 1 );\n
+\t\t\t\t$.data( otherSlider.get(0), "mobile-slider" ).handle.css( "z-index", 0 );\n
+\t\t\t} else {\n
+\t\t\t\t$.data( otherSlider.get(0), "mobile-slider" ).handle.css( "z-index", "" );\n
+\t\t\t\t$.data( thisSlider.get(0), "mobile-slider" ).handle.css( "z-index", "" );\n
+\t\t\t}\n
+\n
+\t\t\tthis._updateHighlight();\n
+\n
+\t\t\tif ( min >= max ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_updateHighlight: function() {\n
+\t\t\tvar min = parseInt( $.data( this._inputFirst.get(0), "mobile-slider" ).handle.get(0).style.left, 10 ),\n
+\t\t\t\tmax = parseInt( $.data( this._inputLast.get(0), "mobile-slider" ).handle.get(0).style.left, 10 ),\n
+\t\t\t\twidth = (max - min);\n
+\n
+\t\t\tthis.element.find( ".ui-slider-bg" ).css({\n
+\t\t\t\t"margin-left": min + "%",\n
+\t\t\t\t"width": width + "%"\n
+\t\t\t});\n
+\t\t},\n
+\n
+\t\t_setTheme: function( value ) {\n
+\t\t\tthis._inputFirst.slider( "option", "theme", value );\n
+\t\t\tthis._inputLast.slider( "option", "theme", value );\n
+\t\t},\n
+\n
+\t\t_setTrackTheme: function( value ) {\n
+\t\t\tthis._inputFirst.slider( "option", "trackTheme", value );\n
+\t\t\tthis._inputLast.slider( "option", "trackTheme", value );\n
+\t\t},\n
+\n
+\t\t_setMini: function( value ) {\n
+\t\t\tthis._inputFirst.slider( "option", "mini", value );\n
+\t\t\tthis._inputLast.slider( "option", "mini", value );\n
+\t\t\tthis.element.toggleClass( "ui-mini", !!value );\n
+\t\t},\n
+\n
+\t\t_setHighlight: function( value ) {\n
+\t\t\tthis._inputFirst.slider( "option", "highlight", value );\n
+\t\t\tthis._inputLast.slider( "option", "highlight", value );\n
+\t\t},\n
+\n
+\t\t_destroy: function() {\n
+\t\t\tthis._label.prependTo( this.element );\n
+\t\t\tthis.element.removeClass( "ui-rangeslider ui-mini" );\n
+\t\t\tthis._inputFirst.after( this._sliderFirst );\n
+\t\t\tthis._inputLast.after( this._sliderLast );\n
+\t\t\tthis._sliders.remove();\n
+\t\t\tthis.element.find( "input" ).removeClass( "ui-rangeslider-first ui-rangeslider-last" ).slider( "destroy" );\n
+\t\t}\n
+\n
+\t}, $.mobile.behaviors.formReset ) );\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+\t$.widget( "mobile.textinput", $.mobile.textinput, {\n
+\t\toptions: {\n
+\t\t\tclearBtn: false,\n
+\t\t\tclearBtnText: "Clear text"\n
+\t\t},\n
+\n
+\t\t_create: function() {\n
+\t\t\tthis._super();\n
+\n
+\t\t\tif ( !!this.options.clearBtn || this.isSearch ){\n
+\t\t\t\tthis._addClearBtn();\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\tclearButton: function() {\n
+\n
+\t\t\treturn $( "<a href=\'#\' class=\'ui-input-clear ui-btn ui-icon-delete ui-btn-icon-notext ui-corner-all" +\n
+    "\' title=\'" + this.options.clearBtnText + "\'>" + this.options.clearBtnText + "</a>" );\n
+\n
+\t\t},\n
+\n
+\t\t_clearBtnClick: function( event ) {\n
+\t\t\tthis.element.val( "" )\n
+\t\t\t\t\t.focus()\n
+\t\t\t\t\t.trigger( "change" );\n
+\n
+\t\t\tthis._clearBtn.addClass( "ui-input-clear-hidden" );\n
+\t\t\tevent.preventDefault();\n
+\t\t},\n
+\n
+\t\t_addClearBtn: function() {\n
+\n
+\t\t\tif ( !this.options.enhanced ) {\n
+\t\t\t\tthis._enhanceClear();\n
+\t\t\t}\n
+\n
+\t\t\t$.extend( this, {\n
+\t\t\t\t_clearBtn: this.widget().find("a.ui-input-clear")\n
+\t\t\t});\n
+\n
+\t\t\tthis._bindClearEvents();\n
+\n
+\t\t\tthis._toggleClear();\n
+\n
+\t\t},\n
+\n
+\t\t_enhanceClear: function() {\n
+\n
+\t\t\tthis.clearButton().appendTo( this.widget() );\n
+\t\t\tthis.widget().addClass( "ui-input-has-clear" );\n
+\n
+\t\t},\n
+\n
+\t\t_bindClearEvents: function() {\n
+\n
+\t\t\tthis._on( this._clearBtn, {\n
+\t\t\t\t"click": "_clearBtnClick"\n
+\t\t\t});\n
+\n
+\t\t\tthis._on({\n
+\t\t\t\t"keyup": "_toggleClear",\n
+\t\t\t\t"change": "_toggleClear",\n
+\t\t\t\t"input": "_toggleClear",\n
+\t\t\t\t"focus": "_toggleClear",\n
+\t\t\t\t"blur": "_toggleClear",\n
+\t\t\t\t"cut": "_toggleClear",\n
+\t\t\t\t"paste": "_toggleClear"\n
+\n
+\t\t\t});\n
+\n
+\t\t},\n
+\n
+\t\t_unbindClear: function() {\n
+\t\t\tthis._off( this._clearBtn, "click");\n
+\t\t\tthis._off( this.element, "keyup change input focus blur cut paste" );\n
+\t\t},\n
+\n
+\t\t_setOptions:function( options ) {\n
+\t\t\tthis._super( options );\n
+\n
+\t\t\tif ( options.clearbtn !== undefined && !this.element.is( "textarea, :jqmData(type=\'range\')" ) ) {\n
+\t\t\t\tif ( options.clearBtn ){\n
+\t\t\t\t\tthis._addClearBtn();\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthis._destroyClear();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif ( options.clearBtnText !== undefined && this._clearBtn !== undefined ) {\n
+\t\t\t\tthis._clearBtn.text( options.clearBtnText );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_toggleClear: function() {\n
+\t\t\tthis._delay( "_toggleClearClass", 0 );\n
+\t\t},\n
+\n
+\t\t_toggleClearClass: function() {\n
+\t\t\tthis._clearBtn.toggleClass( "ui-input-clear-hidden", !this.element.val() );\n
+\t\t},\n
+\n
+\t\t_destroyClear: function() {\n
+\t\t\tthis.element.removeClass( "ui-input-has-clear" );\n
+\t\t\tthis._unbindClear()._clearBtn.remove();\n
+\t\t},\n
+\n
+\t\t_destroy: function() {\n
+\t\t\tthis._super();\n
+\t\t\tthis._destroyClear();\n
+\t\t}\n
+\n
+\t});\n
+\n
+\n
+})( jQuery );\n
+(function( $, undefined ) {\n
+\n
+\t$.widget( "mobile.textinput", $.mobile.textinput, {\n
+\t\toptions: {\n
+\t\t\tautogrow:true,\n
+\t\t\tkeyupTimeoutBuffer: 100\n
+\t\t},\n
+\n
+\t\t_create: function() {\n
+\t\t\tthis._super();\n
+\n
+\t\t\tif ( this.options.autogrow && this.isTextarea ) {\n
+\t\t\t\tthis._autogrow();\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_autogrow: function() {\n
+\t\t\tthis._on({\n
+\t\t\t\t"keyup": "_timeout",\n
+\t\t\t\t"change": "_timeout",\n
+\t\t\t\t"input": "_timeout",\n
+\t\t\t\t"paste": "_timeout",\n
+\t\t\t});\n
+\n
+\t\t\t// Issue 509: the browser is not providing scrollHeight properly until the styles load\n
+\t\t\tif ( $.trim( this.element.val() ) ) {\n
+\t\t\t\t// bind to the window load to make sure the height is calculated based on BOTH\n
+\t\t\t\t// the DOM and CSS\n
+\t\t\t\t// binding to pagechange here ensures that for pages loaded via\n
+\t\t\t\t// ajax the height is recalculated without user input\n
+\t\t\t\tthis._on( true, $.mobile.window, {\n
+\t\t\t\t\t"load": "_timeout",\n
+\t\t\t\t\t"pagechange": "_timeout"\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_unbindAutogrow: function() {\n
+\t\t\tthis._off( this.element, "keyup change input paste" );\n
+\t\t\tthis._off( $.mobile.window, "load pagechange" );\n
+\t\t},\n
+\n
+\t\tkeyupTimeout:null,\n
+\n
+\t\t_timeout: function() {\n
+\t\t\tclearTimeout( this.keyupTimeout );\n
+\t\t\tthis.keyupTimeout = this._delay( "_updateHeight", this.options.keyupTimeoutBuffer );\n
+\t\t},\n
+\n
+\t\t_updateHeight:function() {\n
+\n
+\t\t\tthis.element.css( "height", "0px" );\n
+\n
+\t\t\tvar paddingTop, paddingBottom, paddingHeight,\n
+\t\t\t\tscrollHeight = this.element[ 0 ].scrollHeight,\n
+\t\t\t\tclientHeight = this.element[ 0 ].clientHeight,\n
+\t\t\t\tborderTop = parseFloat( this.element.css( "border-top-width" ) ),\n
+\t\t\t\tborderBottom = parseFloat( this.element.css( "border-bottom-width" ) ),\n
+\t\t\t\tborderHeight = borderTop + borderBottom,\n
+\t\t\t\theight = scrollHeight + borderHeight + 15;\n
+\n
+\t\t\t// Issue 6179: Padding is not included in scrollHeight and\n
+\t\t\t// clientHeight by Firefox if no scrollbar is visible. Because\n
+\t\t\t// textareas use the border-box box-sizing model, padding should be\n
+\t\t\t// included in the new (assigned) height. Because the height is set\n
+\t\t\t// to 0, clientHeight == 0 in Firefox. Therefore, we can use this to\n
+\t\t\t// check if padding must be added.\n
+\t\t\tif ( clientHeight === 0 ) {\n
+\t\t\t\tpaddingTop = parseFloat( this.element.css( "padding-top" ) );\n
+\t\t\t\tpaddingBottom = parseFloat( this.element.css( "padding-bottom" ) );\n
+\t\t\t\tpaddingHeight = paddingTop + paddingBottom;\n
+\n
+\t\t\t\theight += paddingHeight;\n
+\t\t\t}\n
+\n
+\t\t\tthis.element.css( "height", height + "px" );\n
+\t\t},\n
+\n
+\t\t_setOptions: function( options ){\n
+\n
+\t\t\tthis._super( options );\n
+\n
+\t\t\tif ( options.autogrow !== undefined && this.isTextarea ){\n
+\t\t\t\tif ( options.autogrow ){\n
+\t\t\t\t\tthis._autogrow();\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthis._unbindAutogrow();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t});\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.selectmenu", $.extend( {\n
+\tinitSelector: "select:not( :jqmData(role=\'slider\')):not( :jqmData(role=\'flipswitch\') )",\n
+\n
+\toptions: {\n
+\t\ttheme: null,\n
+\t\tdisabled: false,\n
+\t\ticon: "carat-d",\n
+\t\ticonpos: "right",\n
+\t\tinline: false,\n
+\t\tcorners: true,\n
+\t\tshadow: true,\n
+\t\ticonshadow: false, /* TODO: Deprecated in 1.4, remove in 1.5. */\n
+\t\toverlayTheme: null,\n
+\t\tdividerTheme: null,\n
+\t\thidePlaceholderMenuItems: true,\n
+\t\tcloseText: "Close",\n
+\t\tnativeMenu: true,\n
+\t\t// This option defaults to true on iOS devices.\n
+\t\tpreventFocusZoom: /iPhone|iPad|iPod/.test( navigator.platform ) && navigator.userAgent.indexOf( "AppleWebKit" ) > -1,\n
+\t\tmini: false\n
+\t},\n
+\n
+\t_button: function() {\n
+\t\treturn $( "<div/>" );\n
+\t},\n
+\n
+\t_setDisabled: function( value ) {\n
+\t\tthis.element.attr( "disabled", value );\n
+\t\tthis.button.attr( "aria-disabled", value );\n
+\t\treturn this._setOption( "disabled", value );\n
+\t},\n
+\n
+\t_focusButton : function() {\n
+\t\tvar self = this;\n
+\n
+\t\tsetTimeout( function() {\n
+\t\t\tself.button.focus();\n
+\t\t}, 40);\n
+\t},\n
+\n
+\t_selectOptions: function() {\n
+\t\treturn this.select.find( "option" );\n
+\t},\n
+\n
+\t// setup items that are generally necessary for select menu extension\n
+\t_preExtension: function() {\n
+\t\tvar inline = this.options.inline || this.element.jqmData( "inline" ),\n
+\t\t\tmini = this.options.mini || this.element.jqmData( "mini" ),\n
+\t\t\tclasses = "";\n
+\t\t// TODO: Post 1.1--once we have time to test thoroughly--any classes manually applied to the original element should be carried over to the enhanced element, with an `-enhanced` suffix. See https://github.com/jquery/jquery-mobile/issues/3577\n
+\t\t/* if ( $el[0].className.length ) {\n
+\t\t\tclasses = $el[0].className;\n
+\t\t} */\n
+\t\tif ( !!~this.element[0].className.indexOf( "ui-btn-left" ) ) {\n
+\t\t\tclasses = " ui-btn-left";\n
+\t\t}\n
+\n
+\t\tif (  !!~this.element[0].className.indexOf( "ui-btn-right" ) ) {\n
+\t\t\tclasses = " ui-btn-right";\n
+\t\t}\n
+\n
+\t\tif ( inline ) {\n
+\t\t\tclasses += " ui-btn-inline";\n
+\t\t}\n
+\t\tif ( mini ) {\n
+\t\t\tclasses += " ui-mini";\n
+\t\t}\n
+\n
+\t\tthis.select = this.element.removeClass( "ui-btn-left ui-btn-right" ).wrap( "<div class=\'ui-select" + classes + "\'>" );\n
+\t\tthis.selectId  = this.select.attr( "id" ) || ( "select-" + this.uuid );\n
+\t\tthis.buttonId = this.selectId + "-button";\n
+\t\tthis.label = $( "label[for=\'"+ this.selectId +"\']" );\n
+\t\tthis.isMultiple = this.select[ 0 ].multiple;\n
+\t},\n
+\n
+\t_destroy: function() {
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAY=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="6" aka="AAAAAAAAAAY=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+\n
+\t\tvar wrapper = this.element.parents( ".ui-select" );\n
+\t\tif ( wrapper.length > 0 ) {\n
+\t\t\tif ( wrapper.is( ".ui-btn-left, .ui-btn-right" ) ) {\n
+\t\t\t\tthis.element.addClass( wrapper.hasClass( "ui-btn-left" ) ? "ui-btn-left" : "ui-btn-right" );\n
+\t\t\t}\n
+\t\t\tthis.element.insertAfter( wrapper );\n
+\t\t\twrapper.remove();\n
+\t\t}\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tthis._preExtension();\n
+\n
+\t\tthis.button = this._button();\n
+\n
+\t\tvar self = this,\n
+\n
+\t\t\toptions = this.options,\n
+\n
+\t\t\ticonpos = options.icon ? ( options.iconpos || this.select.jqmData( "iconpos" ) ) : false,\n
+\n
+\t\t\tbutton = this.button\n
+\t\t\t\t.insertBefore( this.select )\n
+\t\t\t\t.attr( "id", this.buttonId )\n
+\t\t\t\t.addClass( "ui-btn" +\n
+\t\t\t\t\t( options.icon ? ( " ui-icon-" + options.icon + " ui-btn-icon-" + iconpos +\n
+\t\t\t\t\t( options.iconshadow ? " ui-shadow-icon" : "" ) ) :\t"" ) + /* TODO: Remove in 1.5. */\n
+\t\t\t\t\t( options.theme ? " ui-btn-" + options.theme : "" ) +\n
+\t\t\t\t\t( options.corners ? " ui-corner-all" : "" ) +\n
+\t\t\t\t\t( options.shadow ? " ui-shadow" : "" ) );\n
+\n
+\t\tthis.setButtonText();\n
+\n
+\t\t// Opera does not properly support opacity on select elements\n
+\t\t// In Mini, it hides the element, but not its text\n
+\t\t// On the desktop,it seems to do the opposite\n
+\t\t// for these reasons, using the nativeMenu option results in a full native select in Opera\n
+\t\tif ( options.nativeMenu && window.opera && window.opera.version ) {\n
+\t\t\tbutton.addClass( "ui-select-nativeonly" );\n
+\t\t}\n
+\n
+\t\t// Add counter for multi selects\n
+\t\tif ( this.isMultiple ) {\n
+\t\t\tthis.buttonCount = $( "<span>" )\n
+\t\t\t\t.addClass( "ui-li-count ui-body-inherit" )\n
+\t\t\t\t.hide()\n
+\t\t\t\t.appendTo( button.addClass( "ui-li-has-count" ) );\n
+\t\t}\n
+\n
+\t\t// Disable if specified\n
+\t\tif ( options.disabled || this.element.attr( "disabled" )) {\n
+\t\t\tthis.disable();\n
+\t\t}\n
+\n
+\t\t// Events on native select\n
+\t\tthis.select.change(function() {\n
+\t\t\tself.refresh();\n
+\n
+\t\t\tif ( !!options.nativeMenu ) {\n
+\t\t\t\tthis.blur();\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tthis._handleFormReset();\n
+\n
+\t\tthis.build();\n
+\t},\n
+\n
+\tbuild: function() {\n
+\t\tvar self = this;\n
+\n
+\t\tthis.select\n
+\t\t\t.appendTo( self.button )\n
+\t\t\t.bind( "vmousedown", function() {\n
+\t\t\t\t// Add active class to button\n
+\t\t\t\tself.button.addClass( $.mobile.activeBtnClass );\n
+\t\t\t})\n
+\t\t\t.bind( "focus", function() {\n
+\t\t\t\tself.button.addClass( $.mobile.focusClass );\n
+\t\t\t})\n
+\t\t\t.bind( "blur", function() {\n
+\t\t\t\tself.button.removeClass( $.mobile.focusClass );\n
+\t\t\t})\n
+\t\t\t.bind( "focus vmouseover", function() {\n
+\t\t\t\tself.button.trigger( "vmouseover" );\n
+\t\t\t})\n
+\t\t\t.bind( "vmousemove", function() {\n
+\t\t\t\t// Remove active class on scroll/touchmove\n
+\t\t\t\tself.button.removeClass( $.mobile.activeBtnClass );\n
+\t\t\t})\n
+\t\t\t.bind( "change blur vmouseout", function() {\n
+\t\t\t\tself.button.trigger( "vmouseout" )\n
+\t\t\t\t\t.removeClass( $.mobile.activeBtnClass );\n
+\t\t\t});\n
+\n
+\t\t// In many situations, iOS will zoom into the select upon tap, this prevents that from happening\n
+\t\tself.button.bind( "vmousedown", function() {\n
+\t\t\tif ( self.options.preventFocusZoom ) {\n
+\t\t\t\t\t$.mobile.zoom.disable( true );\n
+\t\t\t}\n
+\t\t});\n
+\t\tself.label.bind( "click focus", function() {\n
+\t\t\tif ( self.options.preventFocusZoom ) {\n
+\t\t\t\t\t$.mobile.zoom.disable( true );\n
+\t\t\t}\n
+\t\t});\n
+\t\tself.select.bind( "focus", function() {\n
+\t\t\tif ( self.options.preventFocusZoom ) {\n
+\t\t\t\t\t$.mobile.zoom.disable( true );\n
+\t\t\t}\n
+\t\t});\n
+\t\tself.button.bind( "mouseup", function() {\n
+\t\t\tif ( self.options.preventFocusZoom ) {\n
+\t\t\t\tsetTimeout(function() {\n
+\t\t\t\t\t$.mobile.zoom.enable( true );\n
+\t\t\t\t}, 0 );\n
+\t\t\t}\n
+\t\t});\n
+\t\tself.select.bind( "blur", function() {\n
+\t\t\tif ( self.options.preventFocusZoom ) {\n
+\t\t\t\t$.mobile.zoom.enable( true );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t},\n
+\n
+\tselected: function() {\n
+\t\treturn this._selectOptions().filter( ":selected" );\n
+\t},\n
+\n
+\tselectedIndices: function() {\n
+\t\tvar self = this;\n
+\n
+\t\treturn this.selected().map(function() {\n
+\t\t\treturn self._selectOptions().index( this );\n
+\t\t}).get();\n
+\t},\n
+\n
+\tsetButtonText: function() {\n
+\t\tvar self = this,\n
+\t\t\tselected = this.selected(),\n
+\t\t\ttext = this.placeholder,\n
+\t\t\tspan = $( document.createElement( "span" ) );\n
+\n
+\t\tthis.button.children( "span" ).not( ".ui-li-count" ).remove().end().end().prepend( (function() {\n
+\t\t\tif ( selected.length ) {\n
+\t\t\t\ttext = selected.map(function() {\n
+\t\t\t\t\treturn $( this ).text();\n
+\t\t\t\t}).get().join( ", " );\n
+\t\t\t} else {\n
+\t\t\t\ttext = self.placeholder;\n
+\t\t\t}\n
+\n
+\t\t\tif ( text ) {\n
+\t\t\t\tspan.text( text );\n
+\t\t\t} else {\n
+\t\t\t\tspan.html( "&nbsp;" );\n
+\t\t\t}\n
+\n
+\t\t\t// TODO possibly aggregate multiple select option classes\n
+\t\t\treturn span\n
+\t\t\t\t.addClass( self.select.attr( "class" ) )\n
+\t\t\t\t.addClass( selected.attr( "class" ) )\n
+\t\t\t\t.removeClass( "ui-screen-hidden" );\n
+\t\t})());\n
+\t},\n
+\n
+\tsetButtonCount: function() {\n
+\t\tvar selected = this.selected();\n
+\n
+\t\t// multiple count inside button\n
+\t\tif ( this.isMultiple ) {\n
+\t\t\tthis.buttonCount[ selected.length > 1 ? "show" : "hide" ]().text( selected.length );\n
+\t\t}\n
+\t},\n
+\n
+\t_reset: function() {\n
+\t\tthis.refresh();\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tthis.setButtonText();\n
+\t\tthis.setButtonCount();\n
+\t},\n
+\n
+\t// open and close preserved in native selects\n
+\t// to simplify users code when looping over selects\n
+\topen: $.noop,\n
+\tclose: $.noop,\n
+\n
+\tdisable: function() {\n
+\t\tthis._setDisabled( true );\n
+\t\tthis.button.addClass( "ui-state-disabled" );\n
+\t},\n
+\n
+\tenable: function() {\n
+\t\tthis._setDisabled( false );\n
+\t\tthis.button.removeClass( "ui-state-disabled" );\n
+\t}\n
+}, $.mobile.behaviors.formReset ) );\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.mobile.links = function( target ) {\n
+\n
+\t//links within content areas, tests included with page\n
+\t$( target )\n
+\t\t.find( "a" )\n
+\t\t.jqmEnhanceable()\n
+\t\t.filter( ":jqmData(rel=\'popup\')[href][href!=\'\']" )\n
+\t\t.each( function() {\n
+\t\t\t// Accessibility info for popups\n
+\t\t\tvar e = this,\n
+\t\t\t\thref = $( this ).attr( "href" ),\n
+\t\t\t\tsel = $.mobile.path.hashToSelector( href ),\n
+\t\t\t\tidref = href.substring( 1 );\n
+\n
+\t\t\te.setAttribute( "aria-haspopup", true );\n
+\t\t\te.setAttribute( "aria-owns", idref );\n
+\t\t\te.setAttribute( "aria-expanded", false );\n
+\t\t\t$( document )\n
+\t\t\t\t.on( "popupafteropen", sel, function() {\n
+\t\t\t\t\te.setAttribute( "aria-expanded", true );\n
+\t\t\t\t})\n
+\t\t\t\t.on( "popupafterclose", sel, function() {\n
+\t\t\t\t\te.setAttribute( "aria-expanded", false );\n
+\t\t\t\t});\n
+\t\t})\n
+\t\t.end()\n
+\t\t.not( ".ui-btn, :jqmData(role=\'none\'), :jqmData(role=\'nojs\')" )\n
+\t\t.addClass( "ui-link" );\n
+\n
+};\n
+\n
+})( jQuery );\n
+\n
+\n
+(function( $, undefined ) {\n
+\n
+function fitSegmentInsideSegment( windowSize, segmentSize, offset, desired ) {\n
+\tvar returnValue = desired;\n
+\n
+\tif ( windowSize < segmentSize ) {\n
+\t\t// Center segment if it\'s bigger than the window\n
+\t\treturnValue = offset + ( windowSize - segmentSize ) / 2;\n
+\t} else {\n
+\t\t// Otherwise center it at the desired coordinate while keeping it completely inside the window\n
+\t\treturnValue = Math.min( Math.max( offset, desired - segmentSize / 2 ), offset + windowSize - segmentSize );\n
+\t}\n
+\n
+\treturn returnValue;\n
+}\n
+\n
+function getWindowCoordinates() {\n
+\tvar theWindow = $.mobile.window;\n
+\n
+\treturn {\n
+\t\tx: theWindow.scrollLeft(),\n
+\t\ty: theWindow.scrollTop(),\n
+\t\tcx: ( window.innerWidth || theWindow.width() ),\n
+\t\tcy: ( window.innerHeight || theWindow.height() )\n
+\t};\n
+}\n
+\n
+$.widget( "mobile.popup", {\n
+\toptions: {\n
+\t\twrapperClass: null,\n
+\t\ttheme: null,\n
+\t\toverlayTheme: null,\n
+\t\tshadow: true,\n
+\t\tcorners: true,\n
+\t\ttransition: "none",\n
+\t\tpositionTo: "origin",\n
+\t\ttolerance: null,\n
+\t\tcloseLinkSelector: "a:jqmData(rel=\'back\')",\n
+\t\tcloseLinkEvents: "click.popup",\n
+\t\tnavigateEvents: "navigate.popup",\n
+\t\tcloseEvents: "navigate.popup pagebeforechange.popup",\n
+\t\tdismissible: true,\n
+\t\tenhanced: false,\n
+\n
+\t\t// NOTE Windows Phone 7 has a scroll position caching issue that\n
+\t\t//      requires us to disable popup history management by default\n
+\t\t//      https://github.com/jquery/jquery-mobile/issues/4784\n
+\t\t//\n
+\t\t// NOTE this option is modified in _create!\n
+\t\thistory: !$.mobile.browser.oldIE\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tvar theElement = this.element,\n
+\t\t\tmyId = theElement.attr( "id" ),\n
+\t\t\tcurrentOptions = this.options;\n
+\n
+\t\t// We need to adjust the history option to be false if there\'s no AJAX nav.\n
+\t\t// We can\'t do it in the option declarations because those are run before\n
+\t\t// it is determined whether there shall be AJAX nav.\n
+\t\tcurrentOptions.history = currentOptions.history && $.mobile.ajaxEnabled && $.mobile.hashListeningEnabled;\n
+\n
+\t\t// Define instance variables\n
+\t\t$.extend( this, {\n
+\t\t\t_scrollTop: 0,\n
+\t\t\t_page: theElement.closest( ".ui-page" ),\n
+\t\t\t_ui: null,\n
+\t\t\t_fallbackTransition: "",\n
+\t\t\t_currentTransition: false,\n
+\t\t\t_prerequisites: null,\n
+\t\t\t_isOpen: false,\n
+\t\t\t_tolerance: null,\n
+\t\t\t_resizeData: null,\n
+\t\t\t_ignoreResizeTo: 0,\n
+\t\t\t_orientationchangeInProgress: false\n
+\t\t});\n
+\n
+\t\tif ( this._page.length === 0 ) {\n
+\t\t\tthis._page = $( "body" );\n
+\t\t}\n
+\n
+\t\tif ( currentOptions.enhanced ) {\n
+\t\t\tthis._ui = {\n
+\t\t\t\tcontainer: theElement.parent(),\n
+\t\t\t\tscreen: theElement.parent().prev(),\n
+\t\t\t\tplaceholder: $( this.document[ 0 ].getElementById( myId + "-placeholder" ) )\n
+\t\t\t};\n
+\t\t} else {\n
+\t\t\tthis._ui = this._enhance( theElement, myId );\n
+\t\t\tthis\n
+\t\t\t\t._applyTransition( currentOptions.transition )\n
+\t\t\t\t._setTolerance( currentOptions.tolerance );\n
+\t\t}\n
+\t\tthis._ui.focusElement = this._ui.container;\n
+\n
+\t\t// Event handlers\n
+\t\tthis._on( this._ui.screen, { "vclick": "_eatEventAndClose" } );\n
+\t\tthis._on( $.mobile.window, {\n
+\t\t\torientationchange: $.proxy( this, "_handleWindowOrientationchange" ),\n
+\t\t\tresize: $.proxy( this, "_handleWindowResize" ),\n
+\t\t\tkeyup: $.proxy( this, "_handleWindowKeyUp" )\n
+\t\t});\n
+\t\tthis._on( $.mobile.document, { "focusin": "_handleDocumentFocusIn" } );\n
+\t},\n
+\n
+\t_enhance: function( theElement, myId ) {\n
+\t\tvar currentOptions = this.options,\n
+\t\t\twrapperClass = currentOptions.wrapperClass,\n
+\t\t\tui = {\n
+\t\t\t\tscreen: $( "<div class=\'ui-screen-hidden ui-popup-screen " +\n
+\t\t\t\tthis._themeClassFromOption( "ui-overlay-", currentOptions.overlayTheme ) + "\'></div>" ),\n
+\t\t\t\tplaceholder: $( "<div style=\'display: none;\'><!-- placeholder --></div>" ),\n
+\t\t\t\tcontainer: $( "<div class=\'ui-popup-container ui-popup-hidden ui-popup-truncate" +\n
+\t\t\t\t\t( wrapperClass ? ( " " + wrapperClass ) : "" ) + "\'></div>" )\n
+\t\t\t},\n
+\t\t\tfragment = this.document[ 0 ].createDocumentFragment();\n
+\n
+\t\tfragment.appendChild( ui.screen[ 0 ] );\n
+\t\tfragment.appendChild( ui.container[ 0 ] );\n
+\n
+\t\tif ( myId ) {\n
+\t\t\tui.screen.attr( "id", myId + "-screen" );\n
+\t\t\tui.container.attr( "id", myId + "-popup" );\n
+\t\t\tui.placeholder\n
+\t\t\t\t.attr( "id", myId + "-placeholder" )\n
+\t\t\t\t.html( "<!-- placeholder for " + myId + " -->" );\n
+\t\t}\n
+\n
+\t\t// Apply the proto\n
+\t\tthis._page[ 0 ].appendChild( fragment );\n
+\t\t// Leave a placeholder where the element used to be\n
+\t\tui.placeholder.insertAfter( theElement );\n
+\t\ttheElement\n
+\t\t\t.detach()\n
+\t\t\t.addClass( "ui-popup " +\n
+\t\t\t\tthis._themeClassFromOption( "ui-body-", currentOptions.theme ) + " " +\n
+\t\t\t\t( currentOptions.shadow ? "ui-overlay-shadow " : "" ) +\n
+\t\t\t\t( currentOptions.corners ? "ui-corner-all " : "" ) )\n
+\t\t\t.appendTo( ui.container );\n
+\n
+\t\treturn ui;\n
+\t},\n
+\n
+\t_eatEventAndClose: function( theEvent ) {\n
+\t\ttheEvent.preventDefault();\n
+\t\ttheEvent.stopImmediatePropagation();\n
+\t\tif ( this.options.dismissible ) {\n
+\t\t\tthis.close();\n
+\t\t}\n
+\t\treturn false;\n
+\t},\n
+\n
+\t// Make sure the screen size is increased beyond the page height if the popup\'s causes the document to increase in height\n
+\t_resizeScreen: function() {\n
+\t\tvar popupHeight = this._ui.container.outerHeight( true );\n
+\n
+\t\tthis._ui.screen.removeAttr( "style" );\n
+\t\tif ( popupHeight > this._ui.screen.height() ) {\n
+\t\t\tthis._ui.screen.height( popupHeight );\n
+\t\t}\n
+\t},\n
+\n
+\t_handleWindowKeyUp: function( theEvent ) {\n
+\t\tif ( this._isOpen && theEvent.keyCode === $.mobile.keyCode.ESCAPE ) {\n
+\t\t\treturn this._eatEventAndClose( theEvent );\n
+\t\t}\n
+\t},\n
+\n
+\t_expectResizeEvent: function() {\n
+\t\tvar windowCoordinates = getWindowCoordinates();\n
+\n
+\t\tif ( this._resizeData ) {\n
+\t\t\tif ( windowCoordinates.x === this._resizeData.windowCoordinates.x &&\n
+\t\t\t\twindowCoordinates.y === this._resizeData.windowCoordinates.y &&\n
+\t\t\t\twindowCoordinates.cx === this._resizeData.windowCoordinates.cx &&\n
+\t\t\t\twindowCoordinates.cy === this._resizeData.windowCoordinates.cy ) {\n
+\t\t\t\t// timeout not refreshed\n
+\t\t\t\treturn false;\n
+\t\t\t} else {\n
+\t\t\t\t// clear existing timeout - it will be refreshed below\n
+\t\t\t\tclearTimeout( this._resizeData.timeoutId );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis._resizeData = {\n
+\t\t\ttimeoutId: this._delay( "_resizeTimeout", 200 ),\n
+\t\t\twindowCoordinates: windowCoordinates\n
+\t\t};\n
+\n
+\t\treturn true;\n
+\t},\n
+\n
+\t_resizeTimeout: function() {\n
+\t\tif ( this._isOpen ) {\n
+\t\t\tif ( !this._expectResizeEvent() ) {\n
+\t\t\t\tif ( this._ui.container.hasClass( "ui-popup-hidden" ) ) {\n
+\t\t\t\t\t// effectively rapid-open the popup while leaving the screen intact\n
+\t\t\t\t\tthis._ui.container.removeClass( "ui-popup-hidden ui-popup-truncate" );\n
+\t\t\t\t\tthis.reposition( { positionTo: "window" } );\n
+\t\t\t\t\tthis._ignoreResizeEvents();\n
+\t\t\t\t}\n
+\n
+\t\t\t\tthis._resizeScreen();\n
+\t\t\t\tthis._resizeData = null;\n
+\t\t\t\tthis._orientationchangeInProgress = false;\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\tthis._resizeData = null;\n
+\t\t\tthis._orientationchangeInProgress = false;\n
+\t\t}\n
+\t},\n
+\n
+\t_stopIgnoringResizeEvents: function() {\n
+\t\tthis._ignoreResizeTo = 0;\n
+\t},\n
+\n
+\t_ignoreResizeEvents: function() {\n
+\t\tif ( this._ignoreResizeTo ) {\n
+\t\t\tclearTimeout( this._ignoreResizeTo );\n
+\t\t}\n
+\t\tthis._ignoreResizeTo = this._delay( "_stopIgnoringResizeEvents", 1000 );\n
+\t},\n
+\n
+\t_handleWindowResize: function(/* theEvent */) {\n
+\t\tif ( this._isOpen && this._ignoreResizeTo === 0 ) {\n
+\t\t\tif ( ( this._expectResizeEvent() || this._orientationchangeInProgress ) &&\n
+\t\t\t\t!this._ui.container.hasClass( "ui-popup-hidden" ) ) {\n
+\t\t\t\t// effectively rapid-close the popup while leaving the screen intact\n
+\t\t\t\tthis._ui.container\n
+\t\t\t\t\t.addClass( "ui-popup-hidden ui-popup-truncate" )\n
+\t\t\t\t\t.removeAttr( "style" );\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t_handleWindowOrientationchange: function(/* theEvent */) {\n
+\t\tif ( !this._orientationchangeInProgress && this._isOpen && this._ignoreResizeTo === 0 ) {\n
+\t\t\tthis._expectResizeEvent();\n
+\t\t\tthis._orientationchangeInProgress = true;\n
+\t\t}\n
+\t},\n
+\n
+\t// When the popup is open, attempting to focus on an element that is not a\n
+\t// child of the popup will redirect focus to the popup\n
+\t_handleDocumentFocusIn: function( theEvent ) {\n
+\t\tvar target,\n
+\t\t\ttargetElement = theEvent.target,\n
+\t\t\tui = this._ui;\n
+\n
+\t\tif ( !this._isOpen ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( targetElement !== ui.container[ 0 ] ) {\n
+\t\t\ttarget = $( targetElement );\n
+\t\t\tif ( 0 === target.parents().filter( ui.container[ 0 ] ).length ) {\n
+\t\t\t\t$( this.document[ 0 ].activeElement ).one( "focus", function(/* theEvent */) {\n
+\t\t\t\t\ttarget.blur();\n
+\t\t\t\t});\n
+\t\t\t\tui.focusElement.focus();\n
+\t\t\t\ttheEvent.preventDefault();\n
+\t\t\t\ttheEvent.stopImmediatePropagation();\n
+\t\t\t\treturn false;\n
+\t\t\t} else if ( ui.focusElement[ 0 ] === ui.container[ 0 ] ) {\n
+\t\t\t\tui.focusElement = target;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis._ignoreResizeEvents();\n
+\t},\n
+\n
+\t_themeClassFromOption: function( prefix, value ) {\n
+\t\treturn ( value ? ( value === "none" ? "" : ( prefix + value ) ) : ( prefix + "inherit" ) );\n
+\t},\n
+\n
+\t_applyTransition: function( value ) {\n
+\t\tif ( value ) {\n
+\t\t\tthis._ui.container.removeClass( this._fallbackTransition );\n
+\t\t\tif ( value !== "none" ) {\n
+\t\t\t\tthis._fallbackTransition = $.mobile._maybeDegradeTransition( value );\n
+\t\t\t\tif ( this._fallbackTransition === "none" ) {\n
+\t\t\t\t\tthis._fallbackTransition = "";\n
+\t\t\t\t}\n
+\t\t\t\tthis._ui.container.addClass( this._fallbackTransition );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\t_setOptions: function( newOptions ) {\n
+\t\tvar currentOptions = this.options,\n
+\t\t\ttheElement = this.element,\n
+\t\t\tscreen = this._ui.screen;\n
+\n
+\t\tif ( newOptions.wrapperClass !== undefined ) {\n
+\t\t\tthis._ui.container\n
+\t\t\t\t.removeClass( currentOptions.wrapperClass )\n
+\t\t\t\t.addClass( newOptions.wrapperClass );\n
+\t\t}\n
+\n
+\t\tif ( newOptions.theme !== undefined ) {\n
+\t\t\ttheElement\n
+\t\t\t\t.removeClass( this._themeClassFromOption( "ui-body-", currentOptions.theme ) )\n
+\t\t\t\t.addClass( this._themeClassFromOption( "ui-body-", newOptions.theme ) );\n
+\t\t}\n
+\n
+\t\tif ( newOptions.overlayTheme !== undefined ) {\n
+\t\t\tscreen\n
+\t\t\t\t.removeClass( this._themeClassFromOption( "ui-overlay-", currentOptions.overlayTheme ) )\n
+\t\t\t\t.addClass( this._themeClassFromOption( "ui-overlay-", newOptions.overlayTheme ) );\n
+\n
+\t\t\tif ( this._isOpen ) {\n
+\t\t\t\tscreen.addClass( "in" );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( newOptions.shadow !== undefined ) {\n
+\t\t\ttheElement.toggleClass( "ui-overlay-shadow", newOptions.shadow );\n
+\t\t}\n
+\n
+\t\tif ( newOptions.corners !== undefined ) {\n
+\t\t\ttheElement.toggleClass( "ui-corner-all", newOptions.corners );\n
+\t\t}\n
+\n
+\t\tif ( newOptions.transition !== undefined ) {\n
+\t\t\tif ( !this._currentTransition ) {\n
+\t\t\t\tthis._applyTransition( newOptions.transition );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( newOptions.tolerance !== undefined ) {\n
+\t\t\tthis._setTolerance( newOptions.tolerance );\n
+\t\t}\n
+\n
+\t\tif ( newOptions.disabled !== undefined ) {\n
+\t\t\tif ( newOptions.disabled ) {\n
+\t\t\t\tthis.close();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn this._super( newOptions );\n
+\t},\n
+\n
+\t_setTolerance: function( value ) {\n
+\t\tvar tol = { t: 30, r: 15, b: 30, l: 15 },\n
+\t\t\tar;\n
+\n
+\t\tif ( value !== undefined ) {\n
+\t\t\tar = String( value ).split( "," );\n
+\n
+\t\t\t$.each( ar, function( idx, val ) { ar[ idx ] = parseInt( val, 10 ); } );\n
+\n
+\t\t\tswitch( ar.length ) {\n
+\t\t\t\t// All values are to be the same\n
+\t\t\t\tcase 1:\n
+\t\t\t\t\tif ( !isNaN( ar[ 0 ] ) ) {\n
+\t\t\t\t\t\ttol.t = tol.r = tol.b = tol.l = ar[ 0 ];\n
+\t\t\t\t\t}\n
+\t\t\t\t\tbreak;\n
+\n
+\t\t\t\t// The first value denotes top/bottom tolerance, and the second value denotes left/right tolerance\n
+\t\t\t\tcase 2:\n
+\t\t\t\t\tif ( !isNaN( ar[ 0 ] ) ) {\n
+\t\t\t\t\t\ttol.t = tol.b = ar[ 0 ];\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif ( !isNaN( ar[ 1 ] ) ) {\n
+\t\t\t\t\t\ttol.l = tol.r = ar[ 1 ];\n
+\t\t\t\t\t}\n
+\t\t\t\t\tbreak;\n
+\n
+\t\t\t\t// The array contains values in the order top, right, bottom, left\n
+\t\t\t\tcase 4:\n
+\t\t\t\t\tif ( !isNaN( ar[ 0 ] ) ) {\n
+\t\t\t\t\t\ttol.t = ar[ 0 ];\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif ( !isNaN( ar[ 1 ] ) ) {\n
+\t\t\t\t\t\ttol.r = ar[ 1 ];\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif ( !isNaN( ar[ 2 ] ) ) {\n
+\t\t\t\t\t\ttol.b = ar[ 2 ];\n
+\t\t\t\t\t}\n
+\t\t\t\t\tif ( !isNaN( ar[ 3 ] ) ) {\n
+\t\t\t\t\t\ttol.l = ar[ 3 ];\n
+\t\t\t\t\t}\n
+\t\t\t\t\tbreak;\n
+\n
+\t\t\t\tdefault:\n
+\t\t\t\t\tbreak;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis._tolerance = tol;\n
+\t\treturn this;\n
+\t},\n
+\n
+\t_clampPopupWidth: function( infoOnly ) {\n
+\t\tvar menuSize,\n
+\t\t\twindowCoordinates = getWindowCoordinates(),\n
+\t\t\t// rectangle within which the popup must fit\n
+\t\t\trectangle = {\n
+\t\t\t\tx: this._tolerance.l,\n
+\t\t\t\ty: windowCoordinates.y + this._tolerance.t,\n
+\t\t\t\tcx: windowCoordinates.cx - this._tolerance.l - this._tolerance.r,\n
+\t\t\t\tcy: windowCoordinates.cy - this._tolerance.t - this._tolerance.b\n
+\t\t\t};\n
+\n
+\t\tif ( !infoOnly ) {\n
+\t\t\t// Clamp the width of the menu before grabbing its size\n
+\t\t\tthis._ui.container.css( "max-width", rectangle.cx );\n
+\t\t}\n
+\n
+\t\tmenuSize = {\n
+\t\t\tcx: this._ui.container.outerWidth( true ),\n
+\t\t\tcy: this._ui.container.outerHeight( true )\n
+\t\t};\n
+\n
+\t\treturn { rc: rectangle, menuSize: menuSize };\n
+\t},\n
+\n
+\t_calculateFinalLocation: function( desired, clampInfo ) {\n
+\t\tvar returnValue,\n
+\t\t\trectangle = clampInfo.rc,\n
+\t\t\tmenuSize = clampInfo.menuSize;\n
+\n
+\n
+\t\t// Center the menu over the desired coordinates, while not going outside\n
+\t\t// the window tolerances. This will center wrt. the window if the popup is\n
+\t\t// too large.\n
+\t\treturnValue = {\n
+\t\t\tleft: fitSegmentInsideSegment( rectangle.cx, menuSize.cx, rectangle.x, desired.x ),\n
+\t\t\ttop: fitSegmentInsideSegment( rectangle.cy, menuSize.cy, rectangle.y, desired.y )\n
+\t\t};\n
+\n
+\t\t// Make sure the top of the menu is visible\n
+\t\treturnValue.top = Math.max( 0, returnValue.top );\n
+\n
+\t\t// If the height of the menu is smaller than the height of the document\n
+\t\t// align the bottom with the bottom of the document\n
+\n
+\t\treturnValue.top -= Math.min( returnValue.top,\n
+\t\t\tMath.max( 0, returnValue.top + menuSize.cy - $.mobile.document.height() ) );\n
+\n
+\t\treturn returnValue;\n
+\t},\n
+\n
+\t// Try and center the overlay over the given coordinates\n
+\t_placementCoords: function( desired ) {\n
+\t\treturn this._calculateFinalLocation( desired, this._clampPopupWidth() );\n
+\t},\n
+\n
+\t_createPrerequisites: function( screenPrerequisite, containerPrerequisite, whenDone ) {\n
+\t\tvar prerequisites,\n
+\t\t\tself = this;\n
+\n
+\t\t// It is important to maintain both the local variable prerequisites and\n
+\t\t// self._prerequisites. The local variable remains in the closure of the\n
+\t\t// functions which call the callbacks passed in. The comparison between the\n
+\t\t// local variable and self._prerequisites is necessary, because once a\n
+\t\t// function has been passed to .animationComplete() it will be called next\n
+\t\t// time an animation completes, even if that\'s not the animation whose end\n
+\t\t// the function was supposed to catch (for example, if an abort happens\n
+\t\t// during the opening animation, the .animationComplete handler is not\n
+\t\t// called for that animation anymore, but the handler remains attached, so\n
+\t\t// it is called the next time the popup is opened - making it stale.\n
+\t\t// Comparing the local variable prerequisites to the widget-level variable\n
+\t\t// self._prerequisites ensures that callbacks triggered by a stale\n
+\t\t// .animationComplete will be ignored.\n
+\n
+\t\tprerequisites = {\n
+\t\t\tscreen: $.Deferred(),\n
+\t\t\tcontainer: $.Deferred()\n
+\t\t};\n
+\n
+\t\tprerequisites.screen.then( function() {\n
+\t\t\tif ( prerequisites === self._prerequisites ) {\n
+\t\t\t\tscreenPrerequisite();\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tprerequisites.container.then( function() {\n
+\t\t\tif ( prerequisites === self._prerequisites ) {\n
+\t\t\t\tcontainerPrerequisite();\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\t$.when( prerequisites.screen, prerequisites.container ).done( function() {\n
+\t\t\tif ( prerequisites === self._prerequisites ) {\n
+\t\t\t\tself._prerequisites = null;\n
+\t\t\t\twhenDone();\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tself._prerequisites = prerequisites;\n
+\t},\n
+\n
+\t_animate: function( args ) {\n
+\t\t// NOTE before removing the default animation of the screen\n
+\t\t//      this had an animate callback that would resolve the deferred\n
+\t\t//      now the deferred is resolved immediately\n
+\t\t// TODO remove the dependency on the screen deferred\n
+\t\tthis._ui.screen\n
+\t\t\t.removeClass( args.classToRemove )\n
+\t\t\t.addClass( args.screenClassToAdd );\n
+\n
+\t\targs.prerequisites.screen.resolve();\n
+\n
+\t\tif ( args.transition && args.transition !== "none" ) {\n
+\t\t\tif ( args.applyTransition ) {\n
+\t\t\t\tthis._applyTransition( args.transition );\n
+\t\t\t}\n
+\t\t\tif ( this._fallbackTransition ) {\n
+\t\t\t\tthis._ui.container\n
+\t\t\t\t\t.animationComplete( $.proxy( args.prerequisites.container, "resolve" ) )\n
+\t\t\t\t\t.addClass( args.containerClassToAdd )\n
+\t\t\t\t\t.removeClass( args.classToRemove );\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t}\n
+\t\tthis._ui.container.removeClass( args.classToRemove );\n
+\t\targs.prerequisites.container.resolve();\n
+\t},\n
+\n
+\t// The desired coordinates passed in will be returned untouched if no reference element can be identified via\n
+\t// desiredPosition.positionTo. Nevertheless, this function ensures that its return value always contains valid\n
+\t// x and y coordinates by specifying the center middle of the window if the coordinates are absent.\n
+\t// options: { x: coordinate, y: coordinate, positionTo: string: "origin", "window", or jQuery selector\n
+\t_desiredCoords: function( openOptions ) {\n
+\t\tvar offset,\n
+\t\t\tdst = null,\n
+\t\t\twindowCoordinates = getWindowCoordinates(),\n
+\t\t\tx = openOptions.x,\n
+\t\t\ty = openOptions.y,\n
+\t\t\tpTo = openOptions.positionTo;\n
+\n
+\t\t// Establish which element will serve as the reference\n
+\t\tif ( pTo && pTo !== "origin" ) {\n
+\t\t\tif ( pTo === "window" ) {\n
+\t\t\t\tx = windowCoordinates.cx / 2 + windowCoordinates.x;\n
+\t\t\t\ty = windowCoordinates.cy / 2 + windowCoordinates.y;\n
+\t\t\t} else {\n
+\t\t\t\ttry {\n
+\t\t\t\t\tdst = $( pTo );\n
+\t\t\t\t} catch( err ) {\n
+\t\t\t\t\tdst = null;\n
+\t\t\t\t}\n
+\t\t\t\tif ( dst ) {\n
+\t\t\t\t\tdst.filter( ":visible" );\n
+\t\t\t\t\tif ( dst.length === 0 ) {\n
+\t\t\t\t\t\tdst = null;\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// If an element was found, center over it\n
+\t\tif ( dst ) {\n
+\t\t\toffset = dst.offset();\n
+\t\t\tx = offset.left + dst.outerWidth() / 2;\n
+\t\t\ty = offset.top + dst.outerHeight() / 2;\n
+\t\t}\n
+\n
+\t\t// Make sure x and y are valid numbers - center over the window\n
+\t\tif ( $.type( x ) !== "number" || isNaN( x ) ) {\n
+\t\t\tx = windowCoordinates.cx / 2 + windowCoordinates.x;\n
+\t\t}\n
+\t\tif ( $.type( y ) !== "number" || isNaN( y ) ) {\n
+\t\t\ty = windowCoordinates.cy / 2 + windowCoordinates.y;\n
+\t\t}\n
+\n
+\t\treturn { x: x, y: y };\n
+\t},\n
+\n
+\t_reposition: function( openOptions ) {\n
+\t\t// We only care about position-related parameters for repositioning\n
+\t\topenOptions = {\n
+\t\t\tx: openOptions.x,\n
+\t\t\ty: openOptions.y,\n
+\t\t\tpositionTo: openOptions.positionTo\n
+\t\t};\n
+\t\tthis._trigger( "beforeposition", undefined, openOptions );\n
+\t\tthis._ui.container.offset( this._placementCoords( this._desiredCoords( openOptions ) ) );\n
+\t},\n
+\n
+\treposition: function( openOptions ) {\n
+\t\tif ( this._isOpen ) {\n
+\t\t\tthis._reposition( openOptions );\n
+\t\t}\n
+\t},\n
+\n
+\t_openPrerequisitesComplete: function() {\n
+\t\tthis._ui.container.addClass( "ui-popup-active" );\n
+\t\tthis._isOpen = true;\n
+\t\tthis._resizeScreen();\n
+\t\tthis._ui.container.attr( "tabindex", "0" ).focus();\n
+\t\tthis._ignoreResizeEvents();\n
+\t\tthis._trigger( "afteropen" );\n
+\t},\n
+\n
+\t_open: function( options ) {\n
+\t\tvar openOptions = $.extend( {}, this.options, options ),\n
+\t\t\t// TODO move blacklist to private method\n
+\t\t\tandroidBlacklist = ( function() {\n
+\t\t\t\tvar ua = navigator.userAgent,\n
+\t\t\t\t\t// Rendering engine is Webkit, and capture major version\n
+\t\t\t\t\twkmatch = ua.match( /AppleWebKit\\/([0-9\\.]+)/ ),\n
+\t\t\t\t\twkversion = !!wkmatch && wkmatch[ 1 ],\n
+\t\t\t\t\tandroidmatch = ua.match( /Android (\\d+(?:\\.\\d+))/ ),\n
+\t\t\t\t\tandversion = !!androidmatch && androidmatch[ 1 ],\n
+\t\t\t\t\tchromematch = ua.indexOf( "Chrome" ) > -1;\n
+\n
+\t\t\t\t// Platform is Android, WebKit version is greater than 534.13 ( Android 3.2.1 ) and not Chrome.\n
+\t\t\t\tif ( androidmatch !== null && andversion === "4.0" && wkversion && wkversion > 534.13 && !chromematch ) {\n
+\t\t\t\t\treturn true;\n
+\t\t\t\t}\n
+\t\t\t\treturn false;\n
+\t\t\t}());\n
+\n
+\t\t// Count down to triggering "popupafteropen" - we have two prerequisites:\n
+\t\t// 1. The popup window animation completes (container())\n
+\t\t// 2. The screen opacity animation completes (screen())\n
+\t\tthis._createPrerequisites(\n
+\t\t\t$.noop,\n
+\t\t\t$.noop,\n
+\t\t\t$.proxy( this, "_openPrerequisitesComplete" ) );\n
+\n
+\t\tthis._currentTransition = openOptions.transition;\n
+\t\tthis._applyTransition( openOptions.transition );\n
+\n
+\t\tthis._ui.screen.removeClass( "ui-screen-hidden" );\n
+\t\tthis._ui.container.removeClass( "ui-popup-truncate" );\n
+\n
+\t\t// Give applications a chance to modify the contents of the container before it appears\n
+\t\tthis._reposition( openOptions );\n
+\n
+\t\tthis._ui.container.removeClass( "ui-popup-hidden" );\n
+\n
+\t\tif ( this.options.overlayTheme && androidBlacklist ) {\n
+\t\t\t/* TODO: The native browser on Android 4.0.X ("Ice Cream Sandwich") suffers from an issue where the popup overlay appears to be z-indexed above the popup itself when certain other styles exist on the same page -- namely, any element set to `position: fixed` and certain types of input. These issues are reminiscent of previously uncovered bugs in older versions of Android\'s native browser: https://github.com/scottjehl/Device-Bugs/issues/3\n
+\t\t\tThis fix closes the following bugs ( I use "closes" with reluctance, and stress that this issue should be revisited as soon as possible ):\n
+\t\t\thttps://github.com/jquery/jquery-mobile/issues/4816\n
+\t\t\thttps://github.com/jquery/jquery-mobile/issues/4844\n
+\t\t\thttps://github.com/jquery/jquery-mobile/issues/4874\n
+\t\t\t*/\n
+\n
+\t\t\t// TODO sort out why this._page isn\'t working\n
+\t\t\tthis.element.closest( ".ui-page" ).addClass( "ui-popup-open" );\n
+\t\t}\n
+\t\tthis._animate({\n
+\t\t\tadditionalCondition: true,\n
+\t\t\ttransition: openOptions.transition,\n
+\t\t\tclassToRemove: "",\n
+\t\t\tscreenClassToAdd: "in",\n
+\t\t\tcontainerClassToAdd: "in",\n
+\t\t\tapplyTransition: false,\n
+\t\t\tprerequisites: this._prerequisites\n
+\t\t});\n
+\t},\n
+\n
+\t_closePrerequisiteScreen: function() {\n
+\t\tthis._ui.screen\n
+\t\t\t.removeClass( "out" )\n
+\t\t\t.addClass( "ui-screen-hidden" );\n
+\t},\n
+\n
+\t_closePrerequisiteContainer: function() {\n
+\t\tthis._ui.container\n
+\t\t\t.removeClass( "reverse out" )\n
+\t\t\t.addClass( "ui-popup-hidden ui-popup-truncate" )\n
+\t\t\t.removeAttr( "style" );\n
+\t},\n
+\n
+\t_closePrerequisitesDone: function() {\n
+\t\tvar container = this._ui.container;\n
+\n
+\t\tcontainer.removeAttr( "tabindex" );\n
+\n
+\t\t// remove the global mutex for popups\n
+\t\t$.mobile.popup.active = undefined;\n
+\n
+\t\t// Blur elements inside the container, including the container\n
+\t\t$( ":focus", container[ 0 ] ).add( container[ 0 ] ).blur();\n
+\n
+\t\t// alert users that the popup is closed\n
+\t\tthis._trigger( "afterclose" );\n
+\t},\n
+\n
+\t_close: function( immediate ) {\n
+\t\tthis._ui.container.removeClass( "ui-popup-active" );\n
+\t\tthis._page.removeClass( "ui-popup-open" );\n
+\n
+\t\tthis._isOpen = false;\n
+\n
+\t\t// Count down to triggering "popupafterclose" - we have two prerequisites:\n
+\t\t// 1. The popup window reverse animation completes (container())\n
+\t\t// 2. The screen opacity animation completes (screen())\n
+\t\tthis._createPrerequisites(\n
+\t\t\t$.proxy( this, "_closePrerequisiteScreen" ),\n
+\t\t\t$.proxy( this, "_closePrerequisiteContainer" ),\n
+\t\t\t$.proxy( this, "_closePrerequisitesDone" ) );\n
+\n
+\t\tthis._animate( {\n
+\t\t\tadditionalCondition: this._ui.screen.hasClass( "in" ),\n
+\t\t\ttransition: ( immediate ? "none" : ( this._currentTransition ) ),\n
+\t\t\tclassToRemove: "in",\n
+\t\t\tscreenClassToAdd: "out",\n
+\t\t\tcontainerClassToAdd: "reverse out",\n
+\t\t\tapplyTransition: true,\n
+\t\t\tprerequisites: this._prerequisites\n
+\t\t});\n
+\t},\n
+\n
+\t_unenhance: function() {\n
+\t\tif ( this.options.enhanced ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Put the element back to where the placeholder was and remove the "ui-popup" class\n
+\t\tthis._setOptions( { theme: $.mobile.popup.prototype.options.theme } );\n
+\t\tthis.element\n
+\t\t\t// Cannot directly insertAfter() - we need to detach() first, because\n
+\t\t\t// insertAfter() will do nothing if the payload div was not attached\n
+\t\t\t// to the DOM at the time the widget was created, and so the payload\n
+\t\t\t// will remain inside the container even after we call insertAfter().\n
+\t\t\t// If that happens and we remove the container a few lines below, we\n
+\t\t\t// will cause an infinite recursion - #5244\n
+\t\t\t.detach()\n
+\t\t\t.insertAfter( this._ui.placeholder )\n
+\t\t\t.removeClass( "ui-popup ui-overlay-shadow ui-corner-all ui-body-inherit" );\n
+\t\tthis._ui.screen.remove();\n
+\t\tthis._ui.container.remove();\n
+\t\tthis._ui.placeholder.remove();\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tif ( $.mobile.popup.active === this ) {\n
+\t\t\tthis.element.one( "popupafterclose", $.proxy( this, "_unenhance" ) );\n
+\t\t\tthis.close();\n
+\t\t} else {\n
+\t\t\tthis._unenhance();\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\t_closePopup: function( theEvent, data ) {\n
+\t\tvar parsedDst, toUrl,\n
+\t\t\tcurrentOptions = this.options,\n
+\t\t\timmediate = false;\n
+\n
+\t\tif ( ( theEvent && theEvent.isDefaultPrevented() ) || $.mobile.popup.active !== this ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// restore location on screen\n
+\t\twindow.scrollTo( 0, this._scrollTop );\n
+\n
+\t\tif ( theEvent && theEvent.type === "pagebeforechange" && data ) {\n
+\t\t\t// Determine whether we need to rapid-close the popup, or whether we can\n
+\t\t\t// take the time to run the closing transition\n
+\t\t\tif ( typeof data.toPage === "string" ) {\n
+\t\t\t\tparsedDst = data.toPage;\n
+\t\t\t} else {\n
+\t\t\t\tparsedDst = data.toPage.jqmData( "url" );\n
+\t\t\t}\n
+\t\t\tparsedDst = $.mobile.path.parseUrl( parsedDst );\n
+\t\t\ttoUrl = parsedDst.pathname + parsedDst.search + parsedDst.hash;\n
+\n
+\t\t\tif ( this._myUrl !== $.mobile.path.makeUrlAbsolute( toUrl ) ) {\n
+\t\t\t\t// Going to a different page - close immediately\n
+\t\t\t\timmediate = true;\n
+\t\t\t} else {\n
+\t\t\t\ttheEvent.preventDefault();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// remove nav bindings\n
+\t\t$.mobile.window.off( currentOptions.closeEvents );\n
+\t\t// unbind click handlers added when history is disabled\n
+\t\tthis.element.undelegate( currentOptions.closeLinkSelector, currentOptions.closeLinkEvents );\n
+\n
+\t\tthis._close( immediate );\n
+\t},\n
+\n
+\t// any navigation event after a popup is opened should close the popup\n
+\t// NOTE the pagebeforechange is bound to catch navigation events that don\'t\n
+\t//      alter the url (eg, dialogs from popups)\n
+\t_bindContainerClose: function() {\n
+\t\t$.mobile.window\n
+\t\t\t.on( this.options.closeEvents, $.proxy( this, "_closePopup" ) );\n
+\t},\n
+\n
+\twidget: function() {\n
+\t\treturn this._ui.container;\n
+\t},\n
+\n
+\t// TODO no clear deliniation of what should be here and\n
+\t// what should be in _open. Seems to be "visual" vs "history" for now\n
+\topen: function( options ) {\n
+\t\tvar url, hashkey, activePage, currentIsDialog, hasHash, urlHistory,\n
+\t\t\tself = this,\n
+\t\t\tcurrentOptions = this.options;\n
+\n
+\t\t// make sure open is idempotent\n
+\t\tif ( $.mobile.popup.active || currentOptions.disabled ) {\n
+\t\t\treturn this;\n
+\t\t}\n
+\n
+\t\t// set the global popup mutex\n
+\t\t$.mobile.popup.active = this;\n
+\t\tthis._scrollTop = $.mobile.window.scrollTop();\n
+\n
+\t\t// if history alteration is disabled close on navigate events\n
+\t\t// and leave the url as is\n
+\t\tif ( !( currentOptions.history ) ) {\n
+\t\t\tself._open( options );\n
+\t\t\tself._bindContainerClose();\n
+\n
+\t\t\t// When histoy is disabled we have to grab the data-rel\n
+\t\t\t// back link clicks so we can close the popup instead of\n
+\t\t\t// relying on history to do it for us\n
+\t\t\tself.element\n
+\t\t\t\t.delegate( currentOptions.closeLinkSelector, currentOptions.closeLinkEvents, function( theEvent ) {\n
+\t\t\t\t\tself.close();\n
+\t\t\t\t\ttheEvent.preventDefault();\n
+\t\t\t\t});\n
+\n
+\t\t\treturn this;\n
+\t\t}\n
+\n
+\t\t// cache some values for min/readability\n
+\t\turlHistory = $.mobile.urlHistory;\n
+\t\thashkey = $.mobile.dialogHashKey;\n
+\t\tactivePage = $.mobile.activePage;\n
+\t\tcurrentIsDialog = ( activePage ? activePage.hasClass( "ui-dialog" ) : false );\n
+\t\tthis._myUrl = url = urlHistory.getActive().url;\n
+\t\thasHash = ( url.indexOf( hashkey ) > -1 ) && !currentIsDialog && ( urlHistory.activeIndex > 0 );\n
+\n
+\t\tif ( hasHash ) {\n
+\t\t\tself._open( options );\n
+\t\t\tself._bindContainerClose();\n
+\t\t\treturn this;\n
+\t\t}\n
+\n
+\t\t// if the current url has no dialog hash key proceed as normal\n
+\t\t// otherwise, if the page is a dialog simply tack on the hash key\n
+\t\tif ( url.indexOf( hashkey ) === -1 && !currentIsDialog ){\n
+\t\t\turl = url + (url.indexOf( "#" ) > -1 ? hashkey : "#" + hashkey);\n
+\t\t} else {\n
+\t\t\turl = $.mobile.path.parseLocation().hash + hashkey;\n
+\t\t}\n
+\n
+\t\t// Tack on an extra hashkey if this is the first page and we\'ve just reconstructed the initial hash\n
+\t\tif ( urlHistory.activeIndex === 0 && url === urlHistory.initialDst ) {\n
+\t\t\turl += hashkey;\n
+\t\t}\n
+\n
+\t\t// swallow the the initial navigation event, and bind for the next\n
+\t\t$.mobile.window.one( "beforenavigate", function( theEvent ) {\n
+\t\t\ttheEvent.preventDefault();\n
+\t\t\tself._open( options );\n
+\t\t\tself._bindContainerClose();\n
+\t\t});\n
+\n
+\t\tthis.urlAltered = true;\n
+\t\t$.mobile.navigate( url, { role: "dialog" } );\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\tclose: function() {\n
+\t\t// make sure close is idempotent\n
+\t\tif ( $.mobile.popup.active !== this ) {\n
+\t\t\treturn this;\n
+\t\t}\n
+\n
+\t\tthis._scrollTop = $.mobile.window.scrollTop();\n
+\n
+\t\tif ( this.options.history && this.urlAltered ) {\n
+\t\t\t$.mobile.back();\n
+\t\t\tthis.urlAltered = false;\n
+\t\t} else {\n
+\t\t\t// simulate the nav bindings having fired\n
+\t\t\tthis._closePopup();\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t}\n
+});\n
+\n
+\n
+// TODO this can be moved inside the widget\n
+$.mobile.popup.handleLink = function( $link ) {\n
+\tvar closestPage = $link.closest( ":jqmData(role=\'page\')" ),\n
+\t\tpath = $.mobile.path,\n
+\t\tscope = ( ( closestPage.length === 0 ) ? $( "body" ) : closestPage ),\n
+\t\t// NOTE make sure to get only the hash, ie7 (wp7) returns the absolute href\n
+\t\t//      in this case ruining the element selection\n
+\t\tpopup = $( path.hashToSelector( path.parseUrl( $link.attr( "href" ) ).hash ), scope[ 0 ] ),\n
+\t\toffset;\n
+\n
+\tif ( popup.data( "mobile-popup" ) ) {\n
+\t\toffset = $link.offset();\n
+\t\tpopup.popup( "open", {\n
+\t\t\tx: offset.left + $link.outerWidth() / 2,\n
+\t\t\ty: offset.top + $link.outerHeight() / 2,\n
+\t\t\ttransition: $link.jqmData( "transition" ),\n
+\t\t\tpositionTo: $link.jqmData( "position-to" )\n
+\t\t});\n
+\t}\n
+\n
+\t//remove after delay\n
+\tsetTimeout( function() {\n
+\t\t$link.removeClass( $.mobile.activeBtnClass );\n
+\t}, 300 );\n
+};\n
+\n
+// TODO move inside _create\n
+$.mobile.document.on( "pagebeforechange", function( theEvent, data ) {\n
+\tif ( data.options.role === "popup" ) {\n
+\t\t$.mobile.popup.handleLink( data.options.link );\n
+\t\ttheEvent.preventDefault();\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+/*\n
+* custom "selectmenu" plugin\n
+*/\n
+\n
+(function( $, undefined ) {\n
+\n
+var unfocusableItemSelector = ".ui-disabled,.ui-li-divider,.ui-screen-hidden,:jqmData(role=\'placeholder\')",\n
+\tgoToAdjacentItem = function( item, target, direction ) {\n
+\t\tvar adjacent = item[ direction + "All" ]()\n
+\t\t\t.not( unfocusableItemSelector )\n
+\t\t\t.first();\n
+\n
+\t\t// if there\'s a previous option, focus it\n
+\t\tif ( adjacent.length ) {\n
+\t\t\ttarget\n
+\t\t\t\t.blur()\n
+\t\t\t\t.attr( "tabindex", "-1" );\n
+\n
+\t\t\tadjacent.find( "a" ).first().focus();\n
+\t\t}\n
+\t};\n
+\n
+$.widget( "mobile.selectmenu", $.mobile.selectmenu, {\n
+\t_create: function() {\n
+\t\tvar o = this.options;\n
+\n
+\t\t// Custom selects cannot exist inside popups, so revert the "nativeMenu"\n
+\t\t// option to true if a parent is a popup\n
+\t\to.nativeMenu = o.nativeMenu || ( this.element.parents( ":jqmData(role=\'popup\'),:mobile-popup" ).length > 0 );\n
+\n
+\t\treturn this._super();\n
+\t},\n
+\n
+\t_handleSelectFocus: function() {\n
+\t\tthis.element.blur();\n
+\t\tthis.button.focus();\n
+\t},\n
+\n
+\t_handleButtonVclickKeydown: function( event ) {\n
+\t\tif ( this.options.disabled || this.isOpen ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif (event.type === "vclick" ||\n
+\t\t\t\tevent.keyCode && (event.keyCode === $.mobile.keyCode.ENTER || event.keyCode === $.mobile.keyCode.SPACE)) {\n
+\n
+\t\t\tthis._decideFormat();\n
+\t\t\tif ( this.menuType === "overlay" ) {\n
+\t\t\t\tthis.button.attr( "href", "#" + this.popupId ).attr( "data-" + ( $.mobile.ns || "" ) + "rel", "popup" );\n
+\t\t\t} else {\n
+\t\t\t\tthis.button.attr( "href", "#" + this.dialogId ).attr( "data-" + ( $.mobile.ns || "" ) + "rel", "dialog" );\n
+\t\t\t}\n
+\t\t\tthis.isOpen = true;\n
+\t\t\t// Do not prevent default, so the navigation may have a chance to actually open the chosen format\n
+\t\t}\n
+\t},\n
+\n
+\t_handleListFocus: function( e ) {\n
+\t\tvar params = ( e.type === "focusin" ) ?\n
+\t\t\t{ tabindex: "0", event: "vmouseover" }:\n
+\t\t\t{ tabindex: "-1", event: "vmouseout" };\n
+\n
+\t\t$( e.target )\n
+\t\t\t.attr( "tabindex", params.tabindex )\n
+\t\t\t.trigger( params.event );\n
+\t},\n
+\n
+\t_handleListKeydown: function( event ) {\n
+\t\tvar target = $( event.target ),\n
+\t\t\tli = target.closest( "li" );\n
+\n
+\t\t// switch logic based on which key was pressed\n
+\t\tswitch ( event.keyCode ) {\n
+\t\t\t// up or left arrow keys\n
+\t\tcase 38:\n
+\t\t\tgoToAdjacentItem( li, target, "prev" );\n
+\t\t\treturn false;\n
+\t\t\t// down or right arrow keys\n
+\t\tcase 40:\n
+\t\t\tgoToAdjacentItem( li, target, "next" );\n
+\t\t\treturn false;\n
+\t\t\t// If enter or space is pressed, trigger click\n
+\t\tcase 13:\n
+\t\tcase 32:\n
+\t\t\ttarget.trigger( "click" );\n
+\t\t\treturn false;\n
+\t\t}\n
+\t},\n
+\n
+\t_handleMenuPageHide: function() {\n
+\t\t// TODO centralize page removal binding / handling in the page plugin.\n
+\t\t// Suggestion from @jblas to do refcounting\n
+\t\t//\n
+\t\t// TODO extremely confusing dependency on the open method where the pagehide.remove\n
+\t\t// bindings are stripped to prevent the parent page from disappearing. The way\n
+\t\t// we\'re keeping pages in the DOM right now sucks\n
+\t\t//\n
+\t\t// rebind the page remove that was unbound in the open function\n
+\t\t// to allow for the parent page removal from actions other than the use\n
+\t\t// of a dialog sized custom select\n
+\t\t//\n
+\t\t// doing this here provides for the back button on the custom select dialog\n
+\t\tthis.thisPage.page( "bindRemove" );\n
+\t},\n
+\n
+\t_handleHeaderCloseClick: function() {\n
+\t\tif ( this.menuType === "overlay" ) {\n
+\t\t\tthis.close();\n
+\t\t\treturn false;\n
+\t\t}\n
+\t},\n
+\n
+\tbuild: function() {\n
+\t\tvar selectId, popupId, dialogId, label, thisPage, isMultiple, menuId, themeAttr, overlayThemeAttr,\n
+\t\t\tdividerThemeAttr, menuPage, listbox, list, header, headerTitle, menuPageContent, menuPageClose, headerClose, self,\n
+\t\t\to = this.options;\n
+\n
+\t\tif ( o.nativeMenu ) {\n
+\t\t\treturn this._super();\n
+\t\t}\n
+\n
+\t\tself = this;\n
+\t\tselectId = this.selectId;\n
+\t\tpopupId = selectId + "-listbox";\n
+\t\tdialogId = selectId + "-dialog";\n
+\t\tlabel = this.label;\n
+\t\tthisPage = this.element.closest( ".ui-page" );\n
+\t\tisMultiple = this.element[ 0 ].multiple;\n
+\t\tmenuId = selectId + "-menu";\n
+\t\tthemeAttr = o.theme ? ( " data-" + $.mobile.ns + "theme=\'" + o.theme + "\'" ) : "";\n
+\t\toverlayThemeAttr = o.overlayTheme ? ( " data-" + $.mobile.ns + "theme=\'" + o.overlayTheme + "\'" ) : "";\n
+\t\tdividerThemeAttr = ( o.dividerTheme && isMultiple ) ? ( " data-" + $.mobile.ns + "divider-theme=\'" + o.dividerTheme + "\'" ) : "";\n
+\t\tmenuPage = $( "<div data-" + $.mobile.ns + "role=\'dialog\' class=\'ui-selectmenu\' id=\'" + dialogId + "\'" + themeAttr + overlayThemeAttr + ">" +\n
+\t\t\t"<div data-" + $.mobile.ns + "role=\'header\'>" +\n
+\t\t\t"<div class=\'ui-title\'>" + label.getEncodedText() + "</div>"+\n
+\t\t\t"</div>"+\n
+\t\t\t"<div data-" + $.mobile.ns + "role=\'content\'></div>"+\n
+\t\t\t"</div>" );\n
+\t\tlistbox = $( "<div id=\'" + popupId + "\' class=\'ui-selectmenu\'>" ).insertAfter( this.select ).popup({ theme: o.overlayTheme });\n
+\t\tlist = $( "<ul class=\'ui-selectmenu-list\' id=\'" + menuId + "\' role=\'listbox\' aria-labelledby=\'" + this.buttonId + "\'" + themeAttr + dividerThemeAttr + ">" ).appendTo( listbox );\n
+\t\theader = $( "<div class=\'ui-header ui-bar-" + ( o.theme ? o.theme : "inherit" ) + "\'>" ).prependTo( listbox );\n
+\t\theaderTitle = $( "<h1 class=\'ui-title\'>" ).appendTo( header );\n
+\n
+\t\tif ( this.isMultiple ) {\n
+\t\t\theaderClose = $( "<a>", {\n
+\t\t\t\t"role": "button",\n
+\t\t\t\t"text": o.closeText,\n
+\t\t\t\t"href": "#",\n
+\t\t\t\t"class": "ui-btn ui-corner-all ui-btn-left ui-btn-icon-notext ui-icon-delete"\n
+\t\t\t}).appendTo( header );\n
+\t\t}\n
+\n
+\t\t$.extend( this, {\n
+\t\t\tselectId: selectId,\n
+\t\t\tmenuId: menuId,\n
+\t\t\tpopupId: popupId,\n
+\t\t\tdialogId: dialogId,\n
+\t\t\tthisPage: thisPage,\n
+\t\t\tmenuPage: menuPage,\n
+\t\t\tlabel: label,\n
+\t\t\tisMultiple: isMultiple,\n
+\t\t\ttheme: o.theme,\n
+\t\t\tlistbox: listbox,\n
+\t\t\tlist: list,\n
+\t\t\theader: header,\n
+\t\t\theaderTitle: headerTitle,\n
+\t\t\theaderClose: headerClose,\n
+\t\t\tmenuPageContent: menuPageContent,\n
+\t\t\tmenuPageClose: menuPageClose,\n
+\t\t\tplaceholder: ""\n
+\t\t});\n
+\n
+\t\t// Create list from select, update state\n
+\t\tthis.refresh();\n
+\n
+\t\tif ( this._origTabIndex === undefined ) {\n
+\t\t\t// Map undefined to false, because this._origTabIndex === undefined\n
+\t\t\t// indicates that we have not yet checked whether the select has\n
+\t\t\t// originally had a tabindex attribute, whereas false indicates that\n
+\t\t\t// we have checked the select for such an attribute, and have found\n
+\t\t\t// none present.\n
+\t\t\tthis._origTabIndex = ( this.select[ 0 ].getAttribute( "tabindex" ) === null ) ? false : this.select.attr( "tabindex" );\n
+\t\t}\n
+\t\tthis.select.attr( "tabindex", "-1" );\n
+\t\tthis._on( this.select, { focus : "_handleSelectFocus" } );\n
+\n
+\t\t// Button events\n
+\t\tthis._on( this.button, {\n
+\t\t\tvclick : "_handleButtonVclickKeydown",\n
+\t\t\tkeydown : "_handleButtonVclickKeydown"\n
+\t\t});\n
+\n
+\t\t// Events for list items\n
+\t\tthis.list.attr( "role", "listbox" );\n
+\t\tthis._on( this.list, {\n
+\t\t\tfocusin : "_handleListFocus",\n
+\t\t\tfocusout : "_handleListFocus",\n
+\t\t\tkeydown: "_handleListKeydown"\n
+\t\t});\n
+\t\tthis.list\n
+\t\t\t.delegate( "li:not(.ui-disabled, .ui-li-divider)", "click", function( event ) {\n
+\n
+\t\t\t\t// index of option tag to be selected\n
+\t\t\t\tvar oldIndex = self.select[ 0 ].selectedIndex,\n
+\t\t\t\t\tnewIndex = $.mobile.getAttribute( this, "option-index" ),\n
+\t\t\t\t\toption = self._selectOptions().eq( newIndex )[ 0 ];\n
+\n
+\t\t\t\t// toggle selected status on the tag for multi selects\n
+\t\t\t\toption.selected = self.isMultiple ? !option.selected : true;\n
+\n
+\t\t\t\t// toggle checkbox class for multiple selects\n
+\t\t\t\tif ( self.isMultiple ) {\n
+\t\t\t\t\t$( this ).find( "a" )\n
+\t\t\t\t\t\t.toggleClass( "ui-icon-checkbox-on", option.selected )\n
+\t\t\t\t\t\t.toggleClass( "ui-icon-checkbox-off", !option.selected );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// trigger change if value changed\n
+\t\t\t\tif ( self.isMultiple || oldIndex !== newIndex ) {\n
+\t\t\t\t\tself.select.trigger( "change" );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// hide custom select for single selects only - otherwise focus clicked item\n
+\t\t\t\t// We need to grab the clicked item the hard way, because the list may have been rebuilt\n
+\t\t\t\tif ( self.isMultiple ) {\n
+\t\t\t\t\tself.list.find( "li:not(.ui-li-divider)" ).eq( newIndex )\n
+\t\t\t\t\t\t.find( "a" ).first().focus();\n
+\t\t\t\t}\n
+\t\t\t\telse {\n
+\t\t\t\t\tself.close();\n
+\t\t\t\t}\n
+\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t});\n
+\n
+\t\t// button refocus ensures proper height calculation\n
+\t\t// by removing the inline style and ensuring page inclusion\n
+\t\tthis._on( this.menuPage, { pagehide: "_handleMenuPageHide" } );\n
+\n
+\t\t// Events on the popup\n
+\t\tthis._on( this.listbox, { popupafterclose: "close" } );\n
+\n
+\t\t// Close button on small overlays\n
+\t\tif ( this.isMultiple ) {\n
+\t\t\tthis._on( this.headerClose, { click: "_handleHeaderCloseClick" } );\n
+\t\t}\n
+\n
+\t\treturn this;\n
+\t},\n
+\n
+\t_isRebuildRequired: function() {\n
+\t\tvar list = this.list.find( "li" ),\n
+\t\t\toptions = this._selectOptions().not( ".ui-screen-hidden" );\n
+\n
+\t\t// TODO exceedingly naive method to determine difference\n
+\t\t// ignores value changes etc in favor of a forcedRebuild\n
+\t\t// from the user in the refresh method\n
+\t\treturn options.text() !== list.text();\n
+\t},\n
+\n
+\tselected: function() {\n
+\t\treturn this._selectOptions().filter( ":selected:not( :jqmData(placeholder=\'true\') )" );\n
+\t},\n
+\n
+\trefresh: function( force ) {\n
+\t\tvar self, indices;\n
+\n
+\t\tif ( this.options.nativeMenu ) {\n
+\t\t\treturn this._super( force );\n
+\t\t}\n
+\n
+\t\tself = this;\n
+\t\tif ( force || this._isRebuildRequired() ) {\n
+\t\t\tself._buildList();\n
+\t\t}\n
+\n
+\t\tindices = this.selectedIndices();\n
+\n
+\t\tself.setButtonText();\n
+\t\tself.setButtonCount();\n
+\n
+\t\tself.list.find( "li:not(.ui-li-divider)" )\n
+\t\t\t.find( "a" ).removeClass( $.mobile.activeBtnClass ).end()\n
+\t\t\t.attr( "aria-selected", false )\n
+\t\t\t.each(function( i ) {\n
+\n
+\t\t\t\tif ( $.inArray( i, indices ) > -1 ) {\n
+\t\t\t\t\tvar item = $( this );\n
+\n
+\t\t\t\t\t// Aria selected attr\n
+\t\t\t\t\titem.attr( "aria-selected", true );\n
+\n
+\t\t\t\t\t// Multiple selects: add the "on" checkbox state to the icon\n
+\t\t\t\t\tif ( self.isMultiple ) {\n
+\t\t\t\t\t\titem.find( "a" ).removeClass( "ui-icon-checkbox-off" ).addClass( "ui-icon-checkbox-on" );\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tif ( item.hasClass( "ui-screen-hidden" ) ) {\n
+\t\t\t\t\t\t\titem.next().find( "a" ).addClass( $.mobile.activeBtnClass );\n
+\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\titem.find( "a" ).addClass( $.mobile.activeBtnClass );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t},\n
+\n
+\tclose: function() {\n
+\t\tif ( this.options.disabled || !this.isOpen ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tvar self = this;\n
+\n
+\t\tif ( self.menuType === "page" ) {\n
+\t\t\tself.menuPage.dialog( "close" );\n
+\t\t\tself.list.appendTo( self.listbox );\n
+\t\t} else {\n
+\t\t\tself.listbox.popup( "close" );\n
+\t\t}\n
+\n
+\t\tself._focusButton();\n
+\t\t// allow the dialog to be closed again\n
+\t\tself.isOpen = false;\n
+\t},\n
+\n
+\topen: function() {\n
+\t\tthis.button.click();\n
+\t},\n
+\n
+\t_focusMenuItem: function() {\n
+\t\tvar selector = this.list.find( "a." + $.mobile.activeBtnClass );\n
+\t\tif ( selector.length === 0 ) {\n
+\t\t\tselector = this.list.find( "li:not(" + unfocusableItemSelector + ") a.ui-btn" );\n
+\t\t}\n
+\t\tselector.first().focus();\n
+\t},\n
+\n
+\t_decideFormat: function() {\n
+\t\tvar self = this,\n
+\t\t\t$window = $.mobile.window,\n
+\t\t\tselfListParent = self.list.parent(),\n
+\t\t\tmenuHeight = selfListParent.outerHeight(),\n
+\t\t\tscrollTop = $window.scrollTop(),\n
+\t\t\tbtnOffset = self.button.offset().top,\n
+\t\t\tscreenHeight = $window.height();\n
+\n
+\t\tif ( menuHeight > screenHeight - 80 || !$.support.scrollTop ) {\n
+\n
+\t\t\tself.menuPage.appendTo( $.mobile.pageContainer ).page();\n
+\t\t\tself.menuPageContent = self.menuPage.find( ".ui-content" );\n
+\t\t\tself.menuPageClose = self.menuPage.find( ".ui-header a" );\n
+\n
+\t\t\t// prevent the parent page from being removed from the DOM,\n
+\t\t\t// otherwise the results of selecting a list item in the dialog\n
+\t\t\t// fall into a black hole\n
+\t\t\tself.thisPage.unbind( "pagehide.remove" );\n
+\n
+\t\t\t//for WebOS/Opera Mini (set lastscroll using button offset)\n
+\t\t\tif ( scrollTop === 0 && btnOffset > screenHeight ) {\n
+\t\t\t\tself.thisPage.one( "pagehide", function() {\n
+\t\t\t\t\t$( this ).jqmData( "lastScroll", btnOffset );\n
+\t\t\t\t});\n
+\t\t\t}\n
+\n
+\t\t\tself.menuPage.one( {\n
+\t\t\t\tpageshow: $.proxy( this, "_focusMenuItem" ),\n
+\t\t\t\tpagehide: $.proxy( this, "close" )\n
+\t\t\t});\n
+\n
+\t\t\tself.menuType = "page";\n
+\t\t\tself.menuPageContent.append( self.list );\n
+\t\t\tself.menuPage.find( "div .ui-title" ).text( self.label.text() );\n
+\t\t} else {\n
+\t\t\tself.menuType = "overlay";\n
+\n
+\t\t\tself.listbox.one( { popupafteropen: $.proxy( this, "_focusMenuItem" ) } );\n
+\t\t}\n
+\t},\n
+\n
+\t_buildList: function() {\n
+\t\tvar self = this,\n
+\t\t\to = this.options,\n
+\t\t\tplaceholder = this.placeholder,\n
+\t\t\tneedPlaceholder = true,\n
+\t\t\tdataIcon = this.isMultiple ? "checkbox-off" : "false",\n
+\t\t\t$options, numOptions, select,\n
+\t\t\tdataPrefix = "data-" + $.mobile.ns,\n
+\t\t\tdataIndexAttr = dataPrefix + "option-index",\n
+\t\t\tdataIconAttr = dataPrefix + "icon",\n
+\t\t\tdataRoleAttr = dataPrefix + "role",\n
+\t\t\tdataPlaceholderAttr = dataPrefix + "placeholder",\n
+\t\t\tfragment = document.createDocumentFragment(),\n
+\t\t\tisPlaceholderItem = false,\n
+\t\t\toptGroup,\n
+\t\t\ti,\n
+\t\t\toption, $option, parent, text, anchor, classes,\n
+\t\t\toptLabel, divider, item;\n
+\n
+\t\tself.list.empty().filter( ".ui-listview" ).listview( "destroy" );\n
+\t\t$options = this._selectOptions();\n
+\t\tnumOptions = $options.length;\n
+\t\tselect = this.select[ 0 ];\n
+\n
+\t\tfor ( i = 0; i < numOptions;i++, isPlaceholderItem = false) {\n
+\t\t\toption = $options[i];\n
+\t\t\t$option = $( option );\n
+\n
+\t\t\t// Do not create options based on ui-screen-hidden select options\n
+\t\t\tif ( $option.hasClass( "ui-screen-hidden" ) ) {\n
+\t\t\t\tcontinue;\n
+\t\t\t}\n
+\n
+\t\t\tparent = option.parentNode;\n
+\t\t\ttext = $option.text();\n
+\t\t\tanchor  = document.createElement( "a" );\n
+\t\t\tclasses = [];\n
+\n
+\t\t\tanchor.setAttribute( "href", "#" );\n
+\t\t\tanchor.appendChild( document.createTextNode( text ) );\n
+\n
+\t\t\t// Are we inside an optgroup?\n
+\t\t\tif ( parent !== select && parent.nodeName.toLowerCase() === "optgroup" ) {\n
+\t\t\t\toptLabel = parent.getAttribute( "label" );\n
+\t\t\t\tif ( optLabel !== optGroup ) {\n
+\t\t\t\t\tdivider = document.createElement( "li" );\n
+\t\t\t\t\tdivider.setAttribute( dataRoleAttr, "list-divider" );\n
+\t\t\t\t\tdivider.setAttribute( "role", "option" );\n
+\t\t\t\t\tdivider.setAttribute( "tabindex", "-1" );\n
+\t\t\t\t\tdivider.appendChild( document.createTextNode( optLabel ) );\n
+\t\t\t\t\tfragment.appendChild( divider );\n
+\t\t\t\t\toptGroup = optLabel;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif ( needPlaceholder && ( !option.getAttribute( "value" ) || text.length === 0 || $option.jqmData( "placeholder" ) ) ) {\n
+\t\t\t\tneedPlaceholder = false;\n
+\t\t\t\tisPlaceholderItem = true;\n
+\n
+\t\t\t\t// If we have identified a placeholder, record the fact that it was\n
+\t\t\t\t// us who have added the placeholder to the option and mark it\n
+\t\t\t\t// retroactively in the select as well\n
+\t\t\t\tif ( null === option.getAttribute( dataPlaceholderAttr ) ) {\n
+\t\t\t\t\tthis._removePlaceholderAttr = true;\n
+\t\t\t\t}\n
+\t\t\t\toption.setAttribute( dataPlaceholderAttr, true );\n
+\t\t\t\tif ( o.hidePlaceholderMenuItems ) {\n
+\t\t\t\t\tclasses.push( "ui-screen-hidden" );\n
+\t\t\t\t}\n
+\t\t\t\tif ( placeholder !== text ) {\n
+\t\t\t\t\tplaceholder = self.placeholder = text;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\titem = document.createElement( "li" );\n
+\t\t\tif ( option.disabled ) {\n
+\t\t\t\tclasses.push( "ui-disabled" );\n
+\t\t\t\titem.setAttribute( "aria-disabled", true );\n
+\t\t\t}\n
+\t\t\titem.setAttribute( dataIndexAttr, i );\n
+\t\t\titem.setAttribute( dataIconAttr, dataIcon );\n
+\t\t\tif ( isPlaceholderItem ) {\n
+\t\t\t\titem.setAttribute( dataPlaceholderAttr, true );\n
+\t\t\t}\n
+\t\t\titem.className = classes.join( " " );\n
+\t\t\titem.setAttribute( "role", "option" );\n
+\t\t\tanchor.setAttribute( "tabindex", "-1" );\n
+\t\t\titem.appendChild( anchor );\n
+\t\t\tfragment.appendChild( item );\n
+\t\t}\n
+\n
+\t\tself.list[0].appendChild( fragment );\n
+\n
+\t\t// Hide header if it\'s not a multiselect and there\'s no placeholder\n
+\t\tif ( !this.isMultiple && !placeholder.length ) {\n
+\t\t\tthis.header.addClass( "ui-screen-hidden" );\n
+\t\t} else {\n
+\t\t\tthis.headerTitle.text( this.placeholder );\n
+\t\t}\n
+\n
+\t\t// Now populated, create listview\n
+\t\tself.list.listview();\n
+\t},\n
+\n
+\t_button: function() {\n
+\t\treturn this.options.nativeMenu ?\n
+\t\t\tthis._super() :\n
+\t\t\t$( "<a>", {\n
+\t\t\t\t"href": "#",\n
+\t\t\t\t"role": "button",\n
+\t\t\t\t// TODO value is undefined at creation\n
+\t\t\t\t"id": this.buttonId,\n
+\t\t\t\t"aria-haspopup": "true",\n
+\n
+\t\t\t\t// TODO value is undefined at creation\n
+\t\t\t\t"aria-owns": this.menuId\n
+\t\t\t});\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\n
+\t\tif ( !this.options.nativeMenu ) {\n
+\t\t\tthis.close();\n
+\n
+\t\t\t// Restore the tabindex attribute to its original value\n
+\t\t\tif ( this._origTabIndex !== undefined ) {\n
+\t\t\t\tif ( this._origTabIndex !== false ) {\n
+\t\t\t\t\tthis.select.attr( "tabindex", this._origTabIndex );\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthis.select.removeAttr( "tabindex" );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// Remove the placeholder attribute if we were the ones to add it\n
+\t\t\tif ( this._removePlaceholderAttr ) {\n
+\t\t\t\tthis._selectOptions().removeAttr( "data-" + $.mobile.ns + "placeholder" );\n
+\t\t\t}\n
+\n
+\t\t\t// Remove the popup\n
+\t\t\tthis.listbox.remove();\n
+\n
+\t\t\t// Remove the dialog\n
+\t\t\tthis.menuPage.remove();\n
+\t\t}\n
+\n
+\t\t// Chain up\n
+\t\tthis._super();\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+\n
+(function( $, undefined ) {\n
+\n
+\n
+// General policy: Do not access data-* attributes except during enhancement.\n
+// In all other cases we determine the state of the button exclusively from its\n
+// className. That\'s why optionsToClasses expects a full complement of options,\n
+// and the jQuery plugin completes the set of options from the default values.\n
+\n
+// Map classes to buttonMarkup boolean options - used in classNameToOptions()\n
+var reverseBoolOptionMap = {\n
+\t\t"ui-shadow" : "shadow",\n
+\t\t"ui-corner-all" : "corners",\n
+\t\t"ui-btn-inline" : "inline",\n
+\t\t"ui-shadow-icon" : "iconshadow", /* TODO: Remove in 1.5 */\n
+\t\t"ui-mini" : "mini"\n
+\t},\n
+\tgetAttrFixed = function() {\n
+\t\tvar ret = $.mobile.getAttribute.apply( this, arguments );\n
+\n
+\t\treturn ( ret == null ? undefined : ret );\n
+\t},\n
+\tcapitalLettersRE = /[A-Z]/g;\n
+\n
+// optionsToClasses:\n
+// @options: A complete set of options to convert to class names.\n
+// @existingClasses: extra classes to add to the result\n
+//\n
+// Converts @options to buttonMarkup classes and returns the result as an array\n
+// that can be converted to an element\'s className with .join( " " ). All\n
+// possible options must be set inside @options. Use $.fn.buttonMarkup.defaults\n
+// to get a complete set and use $.extend to override your choice of options\n
+// from that set.\n
+function optionsToClasses( options, existingClasses ) {\n
+\tvar classes = existingClasses ? existingClasses : [];\n
+\n
+\t// Add classes to the array - first ui-btn\n
+\tclasses.push( "ui-btn" );\n
+\n
+\t// If there is a theme\n
+\tif ( options.theme ) {\n
+\t\tclasses.push( "ui-btn-" + options.theme );\n
+\t}\n
+\n
+\t// If there\'s an icon, add the icon-related classes\n
+\tif ( options.icon ) {\n
+\t\tclasses = classes.concat([\n
+\t\t\t"ui-icon-" + options.icon,\n
+\t\t\t"ui-btn-icon-" + options.iconpos\n
+\t\t]);\n
+\t\tif ( options.iconshadow ) {\n
+\t\t\tclasses.push( "ui-shadow-icon" ); /* TODO: Remove in 1.5 */\n
+\t\t}\n
+\t}\n
+\n
+\t// Add the appropriate class for each boolean option\n
+\tif ( options.inline ) {\n
+\t\tclasses.push( "ui-btn-inline" );\n
+\t}\n
+\tif ( options.shadow ) {\n
+\t\tclasses.push( "ui-shadow" );\n
+\t}\n
+\tif ( options.corners ) {\n
+\t\tclasses.push( "ui-corner-all" );\n
+\t}\n
+\tif ( options.mini ) {\n
+\t\tclasses.push( "ui-mini" );\n
+\t}\n
+\n
+\t// Create a string from the array and return it\n
+\treturn classes;\n
+}\n
+\n
+// classNameToOptions:\n
+// @classes: A string containing a .className-style space-separated class list\n
+//\n
+// Loops over @classes and calculates an options object based on the\n
+// buttonMarkup-related classes it finds. It records unrecognized classes in an\n
+// array.\n
+//\n
+// Returns: An object containing the following items:\n
+//\n
+// "options": buttonMarkup options found to be present because of the\n
+// presence/absence of corresponding classes\n
+//\n
+// "unknownClasses": a string containing all the non-buttonMarkup-related\n
+// classes found in @classes\n
+//\n
+// "alreadyEnhanced": A boolean indicating whether the ui-btn class was among\n
+// those found to be present\n
+function classNameToOptions( classes ) {\n
+\tvar idx, map, unknownClass,\n
+\t\talreadyEnhanced = false,\n
+\t\tnoIcon = true,\n
+\t\to = {\n
+\t\t\ticon: "",\n
+\t\t\tinline: false,\n
+\t\t\tshadow: false,\n
+\t\t\tcorners: false,\n
+\t\t\ticonshadow: false,\n
+\t\t\tmini: false\n
+\t\t},\n
+\t\tunknownClasses = [];\n
+\n
+\tclasses = classes.split( " " );\n
+\n
+\t// Loop over the classes\n
+\tfor ( idx = 0 ; idx < classes.length ; idx++ ) {\n
+\n
+\t\t// Assume it\'s an unrecognized class\n
+\t\tunknownClass = true;\n
+\n
+\t\t// Recognize boolean options from the presence of classes\n
+\t\tmap = reverseBoolOptionMap[ classes[ idx ] ];\n
+\t\tif ( map !== undefined ) {\n
+\t\t\tunknownClass = false;\n
+\t\t\to[ map ] = true;\n
+\n
+\t\t// Recognize the presence of an icon and establish the icon position\n
+\t\t} else if ( classes[ idx ].indexOf( "ui-btn-icon-" ) === 0 ) {\n
+\t\t\tunknownClass = false;\n
+\t\t\tnoIcon = false;\n
+\t\t\to.iconpos = classes[ idx ].substring( 12 );\n
+\n
+\t\t// Establish which icon is present\n
+\t\t} else if ( classes[ idx ].indexOf( "ui-icon-" ) === 0 ) {\n
+\t\t\tunknownClass = false;\n
+\t\t\to.icon = classes[ idx ].substring( 8 );\n
+\n
+\t\t// Establish the theme - this recognizes one-letter theme swatch names\n
+\t\t} else if ( classes[ idx ].indexOf( "ui-btn-" ) === 0 && classes[ idx ].length === 8 ) {\n
+\t\t\tunknownClass = false;\n
+\t\t\to.theme = classes[ idx ].substring( 7 );\n
+\n
+\t\t// Recognize that this element has already been buttonMarkup-enhanced\n
+\t\t} else if ( classes[ idx ] === "ui-btn" ) {\n
+\t\t\tunknownClass = false;\n
+\t\t\talreadyEnhanced = true;\n
+\t\t}\n
+\n
+\t\t// If this class has not been recognized, add it to the list\n
+\t\tif ( unknownClass ) {\n
+\t\t\tunknownClasses.push( classes[ idx ] );\n
+\t\t}\n
+\t}\n
+\n
+\t// If a "ui-btn-icon-*" icon position class is absent there cannot be an icon\n
+\tif ( noIcon ) {\n
+\t\to.icon = "";\n
+\t}\n
+\n
+\treturn {\n
+\t\toptions: o,\n
+\t\tunknownClasses: unknownClasses,\n
+\t\talreadyEnhanced: alreadyEnhanced\n
+\t};\n
+}\n
+\n
+function camelCase2Hyphenated( c ) {\n
+\treturn "-" + c.toLowerCase();\n
+}\n
+\n
+// $.fn.buttonMarkup:\n
+// DOM: gets/sets .className\n
+//\n
+// @options: options to apply to the elements in the jQuery object\n
+// @overwriteClasses: boolean indicating whether to honour existing classes\n
+//\n
+// Calculates the classes to apply to the elements in the jQuery object based on\n
+// the options passed in. If @overwriteClasses is true, it sets the className\n
+// property of each element in the jQuery object to the buttonMarkup classes\n
+// it calculates based on the options passed in.\n
+//\n
+// If you wish to preserve any classes that are already present on the elements\n
+// inside the jQuery object, including buttonMarkup-related classes that were\n
+// added by a previous call to $.fn.buttonMarkup() or during page enhancement\n
+// then you should omit @overwriteClasses or set it to false.\n
+$.fn.buttonMarkup = function( options, overwriteClasses ) {\n
+\tvar idx, data, el, retrievedOptions, optionKey,\n
+\t\tdefaults = $.fn.buttonMarkup.defaults;\n
+\n
+\tfor ( idx = 0 ; idx < this.length ; idx++ ) {\n
+\t\tel = this[ idx ];\n
+\t\tdata = overwriteClasses ?\n
+\n
+\t\t\t// Assume this element is not enhanced and ignore its classes\n
+\t\t\t{ alreadyEnhanced: false, unknownClasses: [] } :\n
+\n
+\t\t\t// Otherwise analyze existing classes to establish existing options and\n
+\t\t\t// classes\n
+\t\t\tclassNameToOptions( el.className );\n
+\n
+\t\tretrievedOptions = $.extend( {},\n
+\n
+\t\t\t// If the element already has the class ui-btn, then we assume that\n
+\t\t\t// it has passed through buttonMarkup before - otherwise, the options\n
+\t\t\t// returned by classNameToOptions do not correctly reflect the state of\n
+\t\t\t// the element\n
+\t\t\t( data.alreadyEnhanced ? data.options : {} ),\n
+\n
+\t\t\t// Finally, apply the options passed in\n
+\t\t\toptions );\n
+\n
+\t\t// If this is the first call on this element, retrieve remaining options\n
+\t\t// from the data-attributes\n
+\t\tif ( !data.alreadyEnhanced ) {\n
+\t\t\tfor ( optionKey in defaults ) {\n
+\t\t\t\tif ( retrievedOptions[ optionKey ] === undefined ) {\n
+\t\t\t\t\tretrievedOptions[ optionKey ] = getAttrFixed( el,\n
+\t\t\t\t\t\toptionKey.replace( capitalLettersRE, camelCase2Hyphenated )\n
+\t\t\t\t\t);\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tel.className = optionsToClasses(\n
+\n
+\t\t\t// Merge all the options and apply them as classes\n
+\t\t\t$.extend( {},\n
+\n
+\t\t\t\t// The defaults form the basis\n
+\t\t\t\tdefaults,\n
+\n
+\t\t\t\t// Add the computed options\n
+\t\t\t\tretrievedOptions\n
+\t\t\t),\n
+\n
+\t\t\t// ... and re-apply any unrecognized classes that were found\n
+\t\t\tdata.unknownClasses ).join( " " );\n
+\t\tel.setAttribute( "role", "button" );\n
+\t}\n
+\n
+\treturn this;\n
+};\n
+\n
+// buttonMarkup defaults. This must be a complete set, i.e., a value must be\n
+// given here for all recognized options\n
+$.fn.buttonMarkup.defaults = {\n
+\ticon: "",\n
+\ticonpos: "left",\n
+\ttheme: null,\n
+\tinline: false,\n
+\tshadow: true,\n
+\tcorners: true,\n
+\ticonshadow: false, /* TODO: Remove in 1.5. Option deprecated in 1.4. */\n
+\tmini: false\n
+};\n
+\n
+$.extend( $.fn.buttonMarkup, {\n
+\tinitSelector: "a:jqmData(role=\'button\'), .ui-bar > a, .ui-bar > :jqmData(role=\'controlgroup\') > a, button"\n
+});\n
+\n
+})( jQuery );\n
+\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.controlgroup", $.extend( {\n
+\toptions: {\n
+\t\tenhanced: false,\n
+\t\ttheme: null,\n
+\t\tshadow: false,\n
+\t\tcorners: true,\n
+\t\texcludeInvisible: true,\n
+\t\ttype: "vertical",\n
+\t\tmini: false\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tvar elem = this.element,\n
+\t\t\topts = this.options;\n
+\n
+\t\t// Run buttonmarkup\n
+\t\tif( $.mobile.enhanceWithButtonMarkup ){\n
+\t\t\tthis.element.find( $.mobile.enhanceWithButtonMarkup.initSelector ).each( $.mobile.enhanceWithButtonMarkup );\n
+\t\t}\n
+\t\t// Enhance child widgets\n
+\t\t$.each( this._childWidgets, $.proxy( function( number, widgetName ) {\n
+\t\t\tif( $.mobile[ widgetName ] ) {\n
+\t\t\t\tthis.element.find( $.mobile[ widgetName ].initSelector )[ widgetName ]();\n
+\t\t\t}\n
+\t\t}, this ));\n
+\n
+\t\t$.extend( this, {\n
+\t\t\t_ui: null,\n
+\t\t\t_initialRefresh: true\n
+\t\t});\n
+\n
+\t\tif ( opts.enhanced ) {\n
+\t\t\tthis._ui = {\n
+\t\t\t\tgroupLegend: elem.children( ".ui-controlgroup-label" ).children(),\n
+\t\t\t\tchildWrapper: elem.children( ".ui-controlgroup-controls" )\n
+\t\t\t};\n
+\t\t} else {\n
+\t\t\tthis._ui = this._enhance();\n
+\t\t}\n
+\t\t\n
+\t},\n
+\n
+\t_childWidgets: [ "checkboxradio", "selectmenu", "button" ],\n
+\n
+\t_themeClassFromOption: function( value ) {\n
+\t\treturn ( value ? ( value === "none" ? "" : "ui-group-theme-" + value ) : "" );\n
+\t},\n
+\n
+\t_enhance: function() {\n
+\t\tvar elem = this.element,\n
+\t\t\topts = this.options,\n
+\t\t\tui = {\n
+\t\t\t\tgroupLegend: elem.children( "legend" ),\n
+\t\t\t\tchildWrapper: elem\n
+\t\t\t\t\t.addClass( "ui-controlgroup " +\n
+\t\t\t\t\t\t"ui-controlgroup-" +\n
+\t\t\t\t\t\t\t( opts.type === "horizontal" ? "horizontal" : "vertical" ) + " " +\n
+\t\t\t\t\t\tthis._themeClassFromOption( opts.theme ) + " " +\n
+\t\t\t\t\t\t( opts.corners ? "ui-corner-all " : "" ) +\n
+\t\t\t\t\t\t( opts.mini ? "ui-mini " : "" ) )\n
+\t\t\t\t\t.wrapInner( "<div " +\n
+\t\t\t\t\t\t"class=\'ui-controlgroup-controls " +\n
+\t\t\t\t\t\t\t( opts.shadow === true ? "ui-shadow" : "" ) + "\'></div>" )\n
+\t\t\t\t\t.children()\n
+\t\t\t};\n
+\n
+\t\tif ( ui.groupLegend.length > 0 ) {\n
+\t\t\t$( "<div role=\'heading\' class=\'ui-controlgroup-label\'></div>" )\n
+\t\t\t\t.append( ui.groupLegend )\n
+\t\t\t\t.prependTo( elem );\n
+\t\t}\n
+\n
+\t\treturn ui;\n
+\t},\n
+\n
+\t_init: function() {\n
+\t\tthis.refresh();\n
+\t},\n
+\n
+\t_setOptions: function( options ) {\n
+\t\tvar callRefresh,\n
+\t\t\telem = this.element;\n
+\n
+\t\t// Must have one of horizontal or vertical\n
+\t\tif ( options.type !== undefined ) {\n
+\t\t\telem\n
+\t\t\t\t.removeClass( "ui-controlgroup-horizontal ui-controlgroup-vertical" )\n
+\t\t\t\t.addClass( "ui-controlgroup-" + ( options.type === "horizontal" ? "horizontal" : "vertical" ) );\n
+\t\t\tcallRefresh = true;\n
+\t\t}\n
+\n
+\t\tif ( options.theme !== undefined ) {\n
+\t\t\telem\n
+\t\t\t\t.removeClass( this._themeClassFromOption( this.options.theme ) )\n
+\t\t\t\t.addClass( this._themeClassFromOption( options.theme ) );\n
+\t\t}\n
+\n
+\t\tif ( options.corners !== undefined ) {\n
+\t\t\telem.toggleClass( "ui-corner-all", options.corners );\n
+\t\t}\n
+\n
+\t\tif ( options.mini !== undefined ) {\n
+\t\t\telem.toggleClass( "ui-mini", options.mini );\n
+\t\t}\n
+\n
+\t\tif ( options.shadow !== undefined ) {\n
+\t\t\tthis._ui.childWrapper.toggleClass( "ui-shadow", options.shadow );\n
+\t\t}\n
+\n
+\t\tif ( options.excludeInvisible !== undefined ) {\n
+\t\t\tthis.options.excludeInvisible = options.excludeInvisible;\n
+\t\t\tcallRefresh = true;\n
+\t\t}\n
+\n
+\t\tif ( callRefresh ) {\n
+\t\t\tthis.refresh();\n
+\t\t}\n
+\n
+\t\treturn this._super( options );\n
+\t},\n
+\n
+\tcontainer: function() {\n
+\t\treturn this._ui.childWrapper;\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tvar $el = this.container(),\n
+\t\t\tels = $el.find( ".ui-btn" ).not( ".ui-slider-handle" ),\n
+\t\t\tcreate = this._initialRefresh;\n
+\t\tif ( $.mobile.checkboxradio ) {\n
+\t\t\t$el.find( ":mobile-checkboxradio" ).checkboxradio( "refresh" );\n
+\t\t}\n
+\t\tthis._addFirstLastClasses( els,\n
+\t\t\tthis.options.excludeInvisible ? this._getVisibles( els, create ) : els,\n
+\t\t\tcreate );\n
+\t\tthis._initialRefresh = false;\n
+\t},\n
+\n
+\t// Caveat: If the legend is not the first child of the controlgroup at enhance\n
+\t// time, it will be after _destroy().\n
+\t_destroy: function() {\n
+\t\tvar ui, buttons,\n
+\t\t\topts = this.options;\n
+\n
+\t\tif ( opts.enhanced ) {\n
+\t\t\treturn this;\n
+\t\t}\n
+\n
+\t\tui = this._ui;\n
+\t\tbuttons = this.element\n
+\t\t\t.removeClass( "ui-controlgroup " +\n
+\t\t\t\t"ui-controlgroup-horizontal ui-controlgroup-vertical ui-corner-all ui-mini " +\n
+\t\t\t\tthis._themeClassFromOption( opts.theme ) )\n
+\t\t\t.find( ".ui-btn" )\n
+\t\t\t.not( ".ui-slider-handle" );\n
+\n
+\t\tthis._removeFirstLastClasses( buttons );\n
+\n
+\t\tui.groupLegend.unwrap();\n
+\t\tui.childWrapper.children().unwrap();\n
+\t}\n
+}, $.mobile.behaviors.addFirstLastClasses ) );\n
+\n
+})(jQuery);\n
+\n
+(function( $, undefined ) {\n
+\n
+\n
+\t$.widget( "mobile.toolbar", {\n
+\t\tinitSelector: ":jqmData(role=\'footer\'), :jqmData(role=\'header\')",\n
+\n
+\t\toptions: {\n
+\t\t\ttheme: null,\n
+\t\t\taddBackBtn: false,\n
+\t\t\tbackBtnTheme: null,\n
+\t\t\tbackBtnText: "Back"\n
+\t\t},\n
+\n
+\t\t_create: function() {\n
+\t\t\tvar leftbtn, rightbtn, backBtn,\n
+\t\t\t\trole =  this.element.is( ":jqmData(role=\'header\')" ) ? "header" : "footer",\n
+\t\t\t\tpage = this.element.closest( ".ui-page" );\n
+\t\t\tif ( page.length === 0 ){\n
+\t\t\t\tpage = false;\n
+\t\t\t\tthis._on( $.mobile.document, {\n
+\t\t\t\t\t"pageshow": "refresh"\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t\t$.extend( this, {\n
+\t\t\t\trole: role,\n
+\t\t\t\tpage: page,\n
+\t\t\t\tleftbtn: leftbtn,\n
+\t\t\t\trightbtn: rightbtn,\n
+\t\t\t\tbackBtn: backBtn\n
+\t\t\t});\n
+\t\t\tthis.element.attr( "role", role === "header" ? "banner" : "contentinfo" ).addClass( "ui-" + role );\n
+\t\t\tthis.refresh();\n
+\t\t\tthis._setOptions( this.options );\n
+\t\t},\n
+\t\t_setOptions: function( o ) {\n
+\t\t\tif ( o.addBackBtn !== undefined ) {\n
+\t\t\t\tif ( this.options.addBackBtn &&\n
+\t\t\t\t\tthis.role === "header" &&\n
+\t\t\t\t\t$( ".ui-page" ).length > 1 &&\n
+\t\t\t\t\tthis.page[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) !== $.mobile.path.stripHash( location.hash ) &&\n
+\t\t\t\t\t!this.leftbtn ) {\n
+\t\t\t\t\t\tthis._addBackButton();\n
+\t\t\t\t} else {\n
+\t\t\t\t\tthis.element.find( ".ui-toolbar-back-btn" ).remove();\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tif ( o.backBtnTheme !== undefined ) {\n
+\t\t\t\tthis.element\n
+\t\t\t\t\t.find( ".ui-toolbar-back-btn" )\n
+\t\t\t\t\t.addClass( "ui-btn ui-btn-" + o.backBtnTheme );\n
+\t\t\t}\n
+\t\t\tif ( o.backBtnText !== undefined ) {\n
+\t\t\t\tthis.element.find( ".ui-toolbar-back-btn .ui-btn-text" ).text( o.backBtnText );\n
+\t\t\t}\n
+\t\t\tif ( o.theme !== undefined ) {\n
+\t\t\t\tvar currentTheme = this.options.theme ? this.options.theme : "inherit",\n
+\t\t\t\t\tnewTheme = o.theme ? o.theme : "inherit";\n
+\n
+\t\t\t\tthis.element.removeClass( "ui-bar-" + currentTheme ).addClass( "ui-bar-" + newTheme );\n
+\t\t\t}\n
+\n
+\t\t\tthis._super( o );\n
+\t\t},\n
+\t\trefresh: function() {\n
+\t\t\tif ( this.role === "header" ) {\n
+\t\t\t\tthis._addHeaderButtonClasses();\n
+\t\t\t}\n
+\t\t\tif ( !this.page ) {\n
+\t\t\t\t$( "[data-"+ $.mobile.ns +"role=\'page\']" ).css({"position":"relative"});\n
+\t\t\t\tif ( this.role === "footer" ) {\n
+\t\t\t\t\tthis.element.appendTo( "body" );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tthis._addHeadingClasses();\n
+\t\t\tthis._btnMarkup();\n
+\t\t},\n
+\t\t// Deprecated in 1.4. As from 1.5 data-role="button" has to be present in the markup.\n
+\t\t_btnMarkup: function() {\n
+\t\t\tthis.element.children( "a" ).attr( "data-" + $.mobile.ns + "role", "button" );\n
+\t\t\tthis.element.trigger( "create" );\n
+\t\t},\n
+\t\t_addHeaderButtonClasses: function() {\n
+\t\t\tvar $headeranchors = this.element.children( "a, button" );\n
+\t\t\tthis.leftbtn = $headeranchors.hasClass( "ui-btn-left" );\n
+\t\t\tthis.rightbtn = $headeranchors.hasClass( "ui-btn-right" );\n
+\n
+\t\t\tthis.leftbtn = this.leftbtn || $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;\n
+\n
+\t\t\tthis.rightbtn = this.rig
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAc=</string> </persistent>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="7" aka="AAAAAAAAAAc=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+htbtn || $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;\n
+\n
+\t\t},\n
+\t\t_addBackButton: function() {\n
+\t\t\tthis.backBtn = $( "<a role=\'button\' href=\'javascript:void(0);\' class=\'ui-btn-left ui-toolbar-back-btn\' data-" + $.mobile.ns + "rel=\'back\' data-" + $.mobile.ns + "icon=\'carat-l\'>" + this.options.backBtnText + "</a>" )\n
+\t\t\t\t\t// If theme is provided, override default inheritance\n
+\t\t\t\t\t.attr( "data-" + $.mobile.ns + "theme", this.options.backBtnTheme || this.options.theme )\n
+\t\t\t\t\t.prependTo( this.element );\n
+\t\t},\n
+\t\t_addHeadingClasses: function() {\n
+\t\t\tthis.element.children( "h1, h2, h3, h4, h5, h6" )\n
+\t\t\t\t.addClass( "ui-title" )\n
+\t\t\t\t// Regardless of h element number in src, it becomes h1 for the enhanced page\n
+\t\t\t\t.attr({\n
+\t\t\t\t\t"role": "heading",\n
+\t\t\t\t\t"aria-level": "1"\n
+\t\t\t\t});\n
+\t\t}\n
+\t});\n
+\t\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+\n
+\t$.widget( "mobile.toolbar", $.mobile.toolbar, {\n
+\t\toptions: {\n
+\t\t\tposition:null,\n
+\t\t\tvisibleOnPageShow: true,\n
+\t\t\tdisablePageZoom: true,\n
+\t\t\ttransition: "slide", //can be none, fade, slide (slide maps to slideup or slidedown)\n
+\t\t\tfullscreen: false,\n
+\t\t\ttapToggle: true,\n
+\t\t\ttapToggleBlacklist: "a, button, input, select, textarea, .ui-header-fixed, .ui-footer-fixed, .ui-popup, .ui-panel, .ui-panel-dismiss-open",\n
+\t\t\thideDuringFocus: "input, textarea, select",\n
+\t\t\tupdatePagePadding: true,\n
+\t\t\ttrackPersistentToolbars: true,\n
+\n
+\t\t\t// Browser detection! Weeee, here we go...\n
+\t\t\t// Unfortunately, position:fixed is costly, not to mention probably impossible, to feature-detect accurately.\n
+\t\t\t// Some tests exist, but they currently return false results in critical devices and browsers, which could lead to a broken experience.\n
+\t\t\t// Testing fixed positioning is also pretty obtrusive to page load, requiring injected elements and scrolling the window\n
+\t\t\t// The following function serves to rule out some popular browsers with known fixed-positioning issues\n
+\t\t\t// This is a plugin option like any other, so feel free to improve or overwrite it\n
+\t\t\tsupportBlacklist: function() {\n
+\t\t\t\treturn !$.support.fixedPosition;\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_create: function() {\n
+\t\t\tthis._super();\n
+\t\t\tif ( this.options.position === "fixed" && !this.options.supportBlacklist() ){\n
+\t\t\t\tthis.element.addClass( "ui-"+ this.role +"-fixed" );\n
+\t\t\t\tthis.updatePagePadding();\n
+\t\t\t\tthis._addTransitionClass();\n
+\t\t\t\tthis._bindPageEvents();\n
+\t\t\t\tthis._bindToggleHandlers();\n
+\t\t\t\tthis._setOptions( this.options );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_setOptions: function( o ){\n
+\t\t\tif ( this.options.position === "fixed" && !this.options.supportBlacklist() ){\n
+\t\t\t\tvar $page = ( !!this.page )? this.page: ( $(".ui-page-active").length > 0 )? $(".ui-page-active"): $(".ui-page").eq(0);\n
+\n
+\t\t\t\tif ( o.fullscreen !== undefined){\n
+\t\t\t\t\tif ( o.fullscreen ) {\n
+\t\t\t\t\t\tthis.element.addClass( "ui-"+ this.role +"-fullscreen" );\n
+\t\t\t\t\t\t$page.addClass( "ui-page-" + this.role + "-fullscreen" );\n
+\t\t\t\t\t}\n
+\t\t\t\t\t// If not fullscreen, add class to page to set top or bottom padding\n
+\t\t\t\t\telse {\n
+\t\t\t\t\t\tthis.element.removeClass( "ui-"+ this.role +"-fullscreen" );\n
+\t\t\t\t\t\t$page.removeClass( "ui-page-" + this.role + "-fullscreen" ).addClass( "ui-page-" + this.role+ "-fixed" );\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tthis._super(o);\n
+\t\t},\n
+\n
+\t\t_addTransitionClass: function() {\n
+\t\t\tvar tclass = this.options.transition;\n
+\n
+\t\t\tif ( tclass && tclass !== "none" ) {\n
+\t\t\t\t// use appropriate slide for header or footer\n
+\t\t\t\tif ( tclass === "slide" ) {\n
+\t\t\t\t\ttclass = this.element.hasClass( "ui-header" ) ? "slidedown" : "slideup";\n
+\t\t\t\t}\n
+\n
+\t\t\t\tthis.element.addClass( tclass );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_bindPageEvents: function() {\n
+\t\t\tvar page = ( !!this.page )? this.element.closest( ".ui-page" ): $.mobile.document;\n
+\t\t\t//page event bindings\n
+\t\t\t// Fixed toolbars require page zoom to be disabled, otherwise usability issues crop up\n
+\t\t\t// This method is meant to disable zoom while a fixed-positioned toolbar page is visible\n
+\t\t\tthis._on( page , {\n
+\t\t\t\t"pagebeforeshow": "_handlePageBeforeShow",\n
+\t\t\t\t"webkitAnimationStart":"_handleAnimationStart",\n
+\t\t\t\t"animationstart":"_handleAnimationStart",\n
+\t\t\t\t"updatelayout": "_handleAnimationStart",\n
+\t\t\t\t"pageshow": "_handlePageShow",\n
+\t\t\t\t"pagebeforehide": "_handlePageBeforeHide"\n
+\t\t\t});\n
+\t\t},\n
+\n
+\t\t_handlePageBeforeShow: function( ) {\n
+\t\t\tvar o = this.options;\n
+\t\t\tif ( o.disablePageZoom ) {\n
+\t\t\t\t$.mobile.zoom.disable( true );\n
+\t\t\t}\n
+\t\t\tif ( !o.visibleOnPageShow ) {\n
+\t\t\t\tthis.hide( true );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_handleAnimationStart: function() {\n
+\t\t\tif ( this.options.updatePagePadding ) {\n
+\t\t\t\tthis.updatePagePadding( ( !!this.page )? this.page: ".ui-page-active" );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_handlePageShow: function() {\n
+\t\t\tthis.updatePagePadding( ( !!this.page )? this.page: ".ui-page-active" );\n
+\t\t\tif ( this.options.updatePagePadding ) {\n
+\t\t\t\tthis._on( $.mobile.window, { "throttledresize": "updatePagePadding" } );\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_handlePageBeforeHide: function( e, ui ) {\n
+\t\t\tvar o = this.options,\n
+\t\t\t\tthisFooter, thisHeader, nextFooter, nextHeader;\n
+\n
+\n
+\t\t\tif ( o.disablePageZoom ) {\n
+\t\t\t\t$.mobile.zoom.enable( true );\n
+\t\t\t}\n
+\t\t\tif ( o.updatePagePadding ) {\n
+\t\t\t\tthis._off( $.mobile.window, "throttledresize" );\n
+\t\t\t}\n
+\n
+\t\t\tif ( o.trackPersistentToolbars ) {\n
+\t\t\t\tthisFooter = $( ".ui-footer-fixed:jqmData(id)", this.page );\n
+\t\t\t\tthisHeader = $( ".ui-header-fixed:jqmData(id)", this.page );\n
+\t\t\t\tnextFooter = thisFooter.length && ui.nextPage && $( ".ui-footer-fixed:jqmData(id=\'" + thisFooter.jqmData( "id" ) + "\')", ui.nextPage ) || $();\n
+\t\t\t\tnextHeader = thisHeader.length && ui.nextPage && $( ".ui-header-fixed:jqmData(id=\'" + thisHeader.jqmData( "id" ) + "\')", ui.nextPage ) || $();\n
+\n
+\t\t\t\tif ( nextFooter.length || nextHeader.length ) {\n
+\n
+\t\t\t\t\tnextFooter.add( nextHeader ).appendTo( $.mobile.pageContainer );\n
+\n
+\t\t\t\t\tui.nextPage.one( "pageshow", function() {\n
+\t\t\t\t\t\tnextHeader.prependTo( this );\n
+\t\t\t\t\t\tnextFooter.appendTo( this );\n
+\t\t\t\t\t});\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t_visible: true,\n
+\n
+\t\t// This will set the content element\'s top or bottom padding equal to the toolbar\'s height\n
+\t\tupdatePagePadding: function( tbPage ) {\n
+\t\t\tvar $el = this.element,\n
+\t\t\t\theader = ( this.role ==="header" ),\n
+\t\t\t\tpos = parseFloat( $el.css( header ? "top" : "bottom" ) );\n
+\n
+\t\t\t// This behavior only applies to "fixed", not "fullscreen"\n
+\t\t\tif ( this.options.fullscreen ) { return; }\n
+\t\t\t// tbPage argument can be a Page object or an event, if coming from throttled resize.\n
+\t\t\ttbPage = ( tbPage && tbPage.type === undefined && tbPage ) || this.page || $el.closest( ".ui-page" );\n
+\t\t\ttbPage = ( !!this.page )? this.page: ".ui-page-active";\n
+\t\t\t$( tbPage ).css( "padding-" + ( header ? "top" : "bottom" ), $el.outerHeight() + pos );\n
+\t\t},\n
+\n
+\t\t_useTransition: function( notransition ) {\n
+\t\t\tvar $win = $.mobile.window,\n
+\t\t\t\t$el = this.element,\n
+\t\t\t\tscroll = $win.scrollTop(),\n
+\t\t\t\telHeight = $el.height(),\n
+\t\t\t\tpHeight = ( !!this.page )? $el.closest( ".ui-page" ).height():$(".ui-page-active").height(),\n
+\t\t\t\tviewportHeight = $.mobile.getScreenHeight();\n
+\n
+\t\t\treturn !notransition &&\n
+\t\t\t\t( this.options.transition && this.options.transition !== "none" &&\n
+\t\t\t\t(\n
+\t\t\t\t\t( this.role === "header" && !this.options.fullscreen && scroll > elHeight ) ||\n
+\t\t\t\t\t( this.role === "footer" && !this.options.fullscreen && scroll + viewportHeight < pHeight - elHeight )\n
+\t\t\t\t) || this.options.fullscreen\n
+\t\t\t\t);\n
+\t\t},\n
+\n
+\t\tshow: function( notransition ) {\n
+\t\t\tvar hideClass = "ui-fixed-hidden",\n
+\t\t\t\t$el = this.element;\n
+\n
+\t\t\tif ( this._useTransition( notransition ) ) {\n
+\t\t\t\t$el\n
+\t\t\t\t\t.removeClass( "out " + hideClass )\n
+\t\t\t\t\t.addClass( "in" )\n
+\t\t\t\t\t.animationComplete(function () {\n
+\t\t\t\t\t\t$el.removeClass( "in" );\n
+\t\t\t\t\t});\n
+\t\t\t}\n
+\t\t\telse {\n
+\t\t\t\t$el.removeClass( hideClass );\n
+\t\t\t}\n
+\t\t\tthis._visible = true;\n
+\t\t},\n
+\n
+\t\thide: function( notransition ) {\n
+\t\t\tvar hideClass = "ui-fixed-hidden",\n
+\t\t\t\t$el = this.element,\n
+\t\t\t\t// if it\'s a slide transition, our new transitions need the reverse class as well to slide outward\n
+\t\t\t\toutclass = "out" + ( this.options.transition === "slide" ? " reverse" : "" );\n
+\n
+\t\t\tif ( this._useTransition( notransition ) ) {\n
+\t\t\t\t$el\n
+\t\t\t\t\t.addClass( outclass )\n
+\t\t\t\t\t.removeClass( "in" )\n
+\t\t\t\t\t.animationComplete(function() {\n
+\t\t\t\t\t\t$el.addClass( hideClass ).removeClass( outclass );\n
+\t\t\t\t\t});\n
+\t\t\t}\n
+\t\t\telse {\n
+\t\t\t\t$el.addClass( hideClass ).removeClass( outclass );\n
+\t\t\t}\n
+\t\t\tthis._visible = false;\n
+\t\t},\n
+\n
+\t\ttoggle: function() {\n
+\t\t\tthis[ this._visible ? "hide" : "show" ]();\n
+\t\t},\n
+\n
+\t\t_bindToggleHandlers: function() {\n
+\t\t\tvar self = this,\n
+\t\t\t\to = self.options,\n
+\t\t\t\tdelayShow, delayHide,\n
+\t\t\t\tisVisible = true,\n
+\t\t\t\tpage = ( !!this.page )? this.page: $(".ui-page");\n
+\n
+\t\t\t// tap toggle\n
+\t\t\tpage\n
+\t\t\t\t.bind( "vclick", function( e ) {\n
+\t\t\t\t\tif ( o.tapToggle && !$( e.target ).closest( o.tapToggleBlacklist ).length ) {\n
+\t\t\t\t\t\tself.toggle();\n
+\t\t\t\t\t}\n
+\t\t\t\t})\n
+\t\t\t\t.bind( "focusin focusout", function( e ) {\n
+\t\t\t\t\t//this hides the toolbars on a keyboard pop to give more screen room and prevent ios bug which\n
+\t\t\t\t\t//positions fixed toolbars in the middle of the screen on pop if the input is near the top or\n
+\t\t\t\t\t//bottom of the screen addresses issues #4410 Footer navbar moves up when clicking on a textbox in an Android environment\n
+\t\t\t\t\t//and issue #4113 Header and footer change their position after keyboard popup - iOS\n
+\t\t\t\t\t//and issue #4410 Footer navbar moves up when clicking on a textbox in an Android environment\n
+\t\t\t\t\tif ( screen.width < 1025 && $( e.target ).is( o.hideDuringFocus ) && !$( e.target ).closest( ".ui-header-fixed, .ui-footer-fixed" ).length ) {\n
+\t\t\t\t\t\t//Fix for issue #4724 Moving through form in Mobile Safari with "Next" and "Previous" system\n
+\t\t\t\t\t\t//controls causes fixed position, tap-toggle false Header to reveal itself\n
+\t\t\t\t\t\t// isVisible instead of self._visible because the focusin and focusout events fire twice at the same time\n
+\t\t\t\t\t\t// Also use a delay for hiding the toolbars because on Android native browser focusin is direclty followed\n
+\t\t\t\t\t\t// by a focusout when a native selects opens and the other way around when it closes.\n
+\t\t\t\t\t\tif ( e.type === "focusout" && !isVisible ) {\n
+\t\t\t\t\t\t\tisVisible = true;\n
+\t\t\t\t\t\t\t//wait for the stack to unwind and see if we have jumped to another input\n
+\t\t\t\t\t\t\tclearTimeout( delayHide );\n
+\t\t\t\t\t\t\tdelayShow = setTimeout( function() {\n
+\t\t\t\t\t\t\t\tself.show();\n
+\t\t\t\t\t\t\t}, 0 );\n
+\t\t\t\t\t\t} else if ( e.type === "focusin" && !!isVisible ) {\n
+\t\t\t\t\t\t\t//if we have jumped to another input clear the time out to cancel the show.\n
+\t\t\t\t\t\t\tclearTimeout( delayShow );\n
+\t\t\t\t\t\t\tisVisible = false;\n
+\t\t\t\t\t\t\tdelayHide = setTimeout( function() {\n
+\t\t\t\t\t\t\t\tself.hide();\n
+\t\t\t\t\t\t\t}, 0 );\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t},\n
+\n
+\t\t_destroy: function() {\n
+\t\t\tvar $el = this.element,\n
+\t\t\t\theader = $el.hasClass( "ui-header" );\n
+\n
+\t\t\t$el.closest( ".ui-page" ).css( "padding-" + ( header ? "top" : "bottom" ), "" );\n
+\t\t\t$el.removeClass( "ui-header-fixed ui-footer-fixed ui-header-fullscreen ui-footer-fullscreen in out fade slidedown slideup ui-fixed-hidden" );\n
+\t\t\t$el.closest( ".ui-page" ).removeClass( "ui-page-header-fixed ui-page-footer-fixed ui-page-header-fullscreen ui-page-footer-fullscreen" );\n
+\t\t}\n
+\n
+\t});\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\t$.widget( "mobile.toolbar", $.mobile.toolbar, {\n
+\n
+\t\t_create: function() {\n
+\t\t\tthis._super();\n
+\t\t\tthis._workarounds();\n
+\t\t},\n
+\n
+\t\t//check the browser and version and run needed workarounds\n
+\t\t_workarounds: function() {\n
+\t\t\tvar ua = navigator.userAgent,\n
+\t\t\tplatform = navigator.platform,\n
+\t\t\t// Rendering engine is Webkit, and capture major version\n
+\t\t\twkmatch = ua.match( /AppleWebKit\\/([0-9]+)/ ),\n
+\t\t\twkversion = !!wkmatch && wkmatch[ 1 ],\n
+\t\t\tos = null,\n
+\t\t\tself = this;\n
+\t\t\t//set the os we are working in if it dosent match one with workarounds return\n
+\t\t\tif ( platform.indexOf( "iPhone" ) > -1 || platform.indexOf( "iPad" ) > -1  || platform.indexOf( "iPod" ) > -1 ) {\n
+\t\t\t\tos = "ios";\n
+\t\t\t} else if ( ua.indexOf( "Android" ) > -1 ) {\n
+\t\t\t\tos = "android";\n
+\t\t\t} else {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\t//check os version if it dosent match one with workarounds return\n
+\t\t\tif ( os === "ios" ) {\n
+\t\t\t\t//iOS  workarounds\n
+\t\t\t\tself._bindScrollWorkaround();\n
+\t\t\t} else if ( os === "android" && wkversion && wkversion < 534 ) {\n
+\t\t\t\t//Android 2.3 run all Android 2.3 workaround\n
+\t\t\t\tself._bindScrollWorkaround();\n
+\t\t\t\tself._bindListThumbWorkaround();\n
+\t\t\t} else {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t},\n
+\n
+\t\t//Utility class for checking header and footer positions relative to viewport\n
+\t\t_viewportOffset: function() {\n
+\t\t\tvar $el = this.element,\n
+\t\t\t\theader = $el.hasClass( "ui-header" ),\n
+\t\t\t\toffset = Math.abs( $el.offset().top - $.mobile.window.scrollTop() );\n
+\t\t\tif ( !header ) {\n
+\t\t\t\toffset = Math.round( offset - $.mobile.window.height() + $el.outerHeight() ) - 60;\n
+\t\t\t}\n
+\t\t\treturn offset;\n
+\t\t},\n
+\n
+\t\t//bind events for _triggerRedraw() function\n
+\t\t_bindScrollWorkaround: function() {\n
+\t\t\tvar self = this;\n
+\t\t\t//bind to scrollstop and check if the toolbars are correctly positioned\n
+\t\t\tthis._on( $.mobile.window, { scrollstop: function() {\n
+\t\t\t\tvar viewportOffset = self._viewportOffset();\n
+\t\t\t\t//check if the header is visible and if its in the right place\n
+\t\t\t\tif ( viewportOffset > 2 && self._visible ) {\n
+\t\t\t\t\tself._triggerRedraw();\n
+\t\t\t\t}\n
+\t\t\t}});\n
+\t\t},\n
+\n
+\t\t//this addresses issue #4250 Persistent footer instability in v1.1 with long select lists in Android 2.3.3\n
+\t\t//and issue #3748 Android 2.x: Page transitions broken when fixed toolbars used\n
+\t\t//the absolutely positioned thumbnail in a list view causes problems with fixed position buttons above in a nav bar\n
+\t\t//setting the li\'s to -webkit-transform:translate3d(0,0,0); solves this problem to avoide potential issues in other\n
+\t\t//platforms we scope this with the class ui-android-2x-fix\n
+\t\t_bindListThumbWorkaround: function() {\n
+\t\t\tthis.element.closest( ".ui-page" ).addClass( "ui-android-2x-fixed" );\n
+\t\t},\n
+\t\t//this addresses issues #4337 Fixed header problem after scrolling content on iOS and Android\n
+\t\t//and device bugs project issue #1 Form elements can lose click hit area in position: fixed containers.\n
+\t\t//this also addresses not on fixed toolbars page in docs\n
+\t\t//adding 1px of padding to the bottom then removing it causes a "redraw"\n
+\t\t//which positions the toolbars correctly (they will always be visually correct)\n
+\t\t_triggerRedraw: function() {\n
+\t\t\tvar paddingBottom = parseFloat( $( ".ui-page-active" ).css( "padding-bottom" ) );\n
+\t\t\t//trigger page redraw to fix incorrectly positioned fixed elements\n
+\t\t\t$( ".ui-page-active" ).css( "padding-bottom", ( paddingBottom + 1 ) + "px" );\n
+\t\t\t//if the padding is reset with out a timeout the reposition will not occure.\n
+\t\t\t//this is independant of JQM the browser seems to need the time to react.\n
+\t\t\tsetTimeout( function() {\n
+\t\t\t\t$( ".ui-page-active" ).css( "padding-bottom", paddingBottom + "px" );\n
+\t\t\t}, 0 );\n
+\t\t},\n
+\n
+\t\tdestroy: function() {\n
+\t\t\tthis._super();\n
+\t\t\t//Remove the class we added to the page previously in android 2.x\n
+\t\t\tthis.element.closest( ".ui-page-active" ).removeClass( "ui-android-2x-fix" );\n
+\t\t}\n
+\t});\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.panel", {\n
+\toptions: {\n
+\t\tclasses: {\n
+\t\t\tpanel: "ui-panel",\n
+\t\t\tpanelOpen: "ui-panel-open",\n
+\t\t\tpanelClosed: "ui-panel-closed",\n
+\t\t\tpanelFixed: "ui-panel-fixed",\n
+\t\t\tpanelInner: "ui-panel-inner",\n
+\t\t\tmodal: "ui-panel-dismiss",\n
+\t\t\tmodalOpen: "ui-panel-dismiss-open",\n
+\t\t\tpageContainer: "ui-panel-page-container",\n
+\t\t\tpageWrapper: "ui-panel-wrapper",\n
+\t\t\tpageFixedToolbar: "ui-panel-fixed-toolbar",\n
+\t\t\tpageContentPrefix: "ui-panel-page-content", /* Used for wrapper and fixed toolbars position, display and open classes. */\n
+\t\t\tanimate: "ui-panel-animate"\n
+\t\t},\n
+\t\tanimate: true,\n
+\t\ttheme: "a",\n
+\t\tposition: "left",\n
+\t\tdismissible: true,\n
+\t\tdisplay: "reveal", //accepts reveal, push, overlay\n
+\t\tswipeClose: true,\n
+\t\tpositionFixed: false\n
+\t},\n
+\n
+\t_panelID: null,\n
+\t_closeLink: null,\n
+\t_parentPage: null,\n
+\t_page: null,\n
+\t_modal: null,\n
+\t_panelInner: null,\n
+\t_wrapper: null,\n
+\t_fixedToolbars: null,\n
+\n
+\t_create: function() {\n
+\t\tvar el = this.element,\n
+\t\t\tparentPage = el.closest( ":jqmData(role=\'page\')" );\n
+\n
+\t\t// expose some private props to other methods\n
+\t\t$.extend( this, {\n
+\t\t\t_panelID: el.attr( "id" ),\n
+\t\t\t_closeLink: el.find( ":jqmData(rel=\'close\')" ),\n
+\t\t\t_parentPage: ( parentPage.length > 0 ) ? parentPage : false,\n
+\t\t\t_page: this._getPage,\n
+\t\t\t_panelInner: this._getPanelInner(),\n
+\t\t\t_wrapper: this._getWrapper,\n
+\t\t\t_fixedToolbars: this._getFixedToolbars\n
+\t\t});\n
+\t\t\n
+\t\tthis._addPanelClasses();\n
+\n
+\t\t// if animating, add the class to do so\n
+\t\tif ( $.support.cssTransform3d && !!this.options.animate ) {\n
+\t\t\tthis.element.addClass( this.options.classes.animate );\n
+\t\t}\n
+\n
+\t\tthis._bindUpdateLayout();\n
+\t\tthis._bindCloseEvents();\n
+\t\tthis._bindLinkListeners();\n
+\t\tthis._bindPageEvents();\n
+\n
+\t\tif ( !!this.options.dismissible ) {\n
+\t\t\tthis._createModal();\n
+\t\t}\n
+\n
+\t\tthis._bindSwipeEvents();\n
+\t},\n
+\t\n
+\t_getPanelInner: function() {\n
+\t\tvar panelInner = this.element.find( "." + this.options.classes.panelInner );\n
+\t\t\n
+\t\tif ( panelInner.length === 0 ) {\n
+\t\t\tpanelInner = this.element.children().wrapAll( "<div class=\'" + this.options.classes.panelInner + "\' />" ).parent();\n
+\t\t}\n
+\t\t\n
+\t\treturn panelInner;\n
+\t},\n
+\t\n
+\t_createModal: function() {\n
+\t\tvar self = this,\n
+\t\t\ttarget = self._parentPage ? self._parentPage.parent() : self.element.parent();\n
+\n
+\t\tself._modal = $( "<div class=\'" + self.options.classes.modal + "\' data-panelid=\'" + self._panelID + "\'></div>" )\n
+\t\t\t.on( "mousedown", function() {\n
+\t\t\t\tself.close();\n
+\t\t\t})\n
+\t\t\t.appendTo( target );\n
+\t},\n
+\t\n
+\t_getPage: function() {\n
+\t\tvar page = this._parentPage ? this._parentPage : $( "." + $.mobile.activePageClass );\n
+\t\t\n
+\t\treturn page;\n
+\t},\n
+\t\n
+\t_getWrapper: function() {\n
+\t\tvar wrapper = this._page().find( "." + this.options.classes.pageWrapper ),\n
+\t\t\tanimateClass = ( $.support.cssTransform3d && !!this.options.animate ) ? " " + this.options.classes.animate : "";\n
+\n
+\t\tif ( wrapper.length === 0 ) {\n
+\t\t\twrapper = this._page().children( ".ui-header:not(:jqmData(position=\'fixed\')), .ui-content:not(:jqmData(role=\'popup\')), .ui-footer:not(:jqmData(position=\'fixed\'))" )\n
+\t\t\t\t.wrapAll( "<div class=\'" + this.options.classes.pageWrapper + animateClass + "\' /></div>" )\n
+\t\t\t\t.parent();\n
+\t\t}\n
+\n
+\t\treturn wrapper;\n
+\t},\n
+\t\n
+\t_getFixedToolbars: function() {\n
+\t\tvar extFixedToolbars = $( "body" ).children( ".ui-header:jqmData(position=\'fixed\'), .ui-footer:jqmData(position=\'fixed\')" ),\n
+\t\t\tintFixedToolbars = this._page().find( ".ui-header:jqmData(position=\'fixed\'), .ui-footer:jqmData(position=\'fixed\')" ),\n
+\t\t\tfixedToolbars = extFixedToolbars.add( intFixedToolbars ).addClass( this.options.classes.pageFixedToolbar );\n
+\n
+\t\treturn fixedToolbars;\n
+\t},\n
+\n
+\t_getPosDisplayClasses: function( prefix ) {\n
+\t\treturn prefix + "-position-" + this.options.position + " " + prefix + "-display-" + this.options.display;\n
+\t},\n
+\n
+\t_getPanelClasses: function() {\n
+\t\tvar panelClasses = this.options.classes.panel +\n
+\t\t\t" " + this._getPosDisplayClasses( this.options.classes.panel ) +\n
+\t\t\t" " + this.options.classes.panelClosed;\n
+\n
+\t\tif ( this.options.theme ) {\n
+\t\t\tpanelClasses += " ui-body-" + this.options.theme;\n
+\t\t}\n
+\t\tif ( !!this.options.positionFixed ) {\n
+\t\t\tpanelClasses += " " + this.options.classes.panelFixed;\n
+\t\t}\n
+\t\treturn panelClasses;\n
+\t},\n
+\n
+\t_addPanelClasses: function() {\n
+\t\tthis.element.addClass( this._getPanelClasses() );\n
+\t},\n
+\n
+\t_bindCloseEvents: function() {\n
+\t\tvar self = this;\n
+\n
+\t\tself._closeLink.on( "click.panel" , function( e ) {\n
+\t\t\te.preventDefault();\n
+\t\t\tself.close();\n
+\t\t\treturn false;\n
+\t\t});\n
+\t\tself.element.on( "click.panel" , "a:jqmData(ajax=\'false\')", function(/* e */) {\n
+\t\t\tself.close();\n
+\t\t});\n
+\t},\n
+\n
+\t_positionPanel: function() {\n
+\t\tvar self = this,\n
+\t\t\tpanelInnerHeight = self._panelInner.outerHeight(),\n
+\t\t\texpand = panelInnerHeight > $.mobile.getScreenHeight();\n
+\n
+\t\tif ( expand || !self.options.positionFixed ) {\n
+\t\t\tif ( expand ) {\n
+\t\t\t\tself._unfixPanel();\n
+\t\t\t\t$.mobile.resetActivePageHeight( panelInnerHeight );\n
+\t\t\t}\n
+\t\t\twindow.scrollTo( 0, $.mobile.defaultHomeScroll );\n
+\t\t} else {\n
+\t\t\tself._fixPanel();\n
+\t\t}\n
+\t},\n
+\n
+\t_bindFixListener: function() {\n
+\t\tthis._on( $( window ), { "throttledresize": "_positionPanel" });\n
+\t},\n
+\n
+\t_unbindFixListener: function() {\n
+\t\tthis._off( $( window ), "throttledresize" );\n
+\t},\n
+\n
+\t_unfixPanel: function() {\n
+\t\tif ( !!this.options.positionFixed && $.support.fixedPosition ) {\n
+\t\t\tthis.element.removeClass( this.options.classes.panelFixed );\n
+\t\t}\n
+\t},\n
+\n
+\t_fixPanel: function() {\n
+\t\tif ( !!this.options.positionFixed && $.support.fixedPosition ) {\n
+\t\t\tthis.element.addClass( this.options.classes.panelFixed );\n
+\t\t}\n
+\t},\n
+\n
+\t_bindUpdateLayout: function() {\n
+\t\tvar self = this;\n
+\n
+\t\tself.element.on( "updatelayout", function(/* e */) {\n
+\t\t\tif ( self._open ) {\n
+\t\t\t\tself._positionPanel();\n
+\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_bindLinkListeners: function() {\n
+\t\tthis._on( "a", {\n
+\t\t\t"click": "_handleClick"\n
+\t\t});\n
+\t\t\n
+\t},\n
+\n
+\t_handleClick: function( e ){\n
+\t\tif (  e.currentTarget.href.split( "#" )[ 1 ] === this._panelID && this._panelID !== undefined ) {\n
+\t\t\te.preventDefault();\n
+\t\t\tvar link = $( e.target );\n
+\t\t\tif ( link.hasClass( "ui-btn" ) ) {\n
+\t\t\t\tlink.addClass( $.mobile.activeBtnClass );\n
+\t\t\t\tthis.element.one( "panelopen panelclose", function() {\n
+\t\t\t\t\tlink.removeClass( $.mobile.activeBtnClass );\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t\tthis.toggle();\n
+\t\t\treturn false;\n
+\t\t}\n
+\t},\n
+\n
+\t_bindSwipeEvents: function() {\n
+\t\tvar self = this,\n
+\t\t\tarea = self._modal ? self.element.add( self._modal ) : self.element;\n
+\n
+\t\t// on swipe, close the panel\n
+\t\tif ( !!self.options.swipeClose ) {\n
+\t\t\tif ( self.options.position === "left" ) {\n
+\t\t\t\tarea.on( "swipeleft.panel", function(/* e */) {\n
+\t\t\t\t\tself.close();\n
+\t\t\t\t});\n
+\t\t\t} else {\n
+\t\t\t\tarea.on( "swiperight.panel", function(/* e */) {\n
+\t\t\t\t\tself.close();\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\n
+\t_bindPageEvents: function() {\n
+\t\tvar self = this;\n
+\n
+\t\t$.mobile.document\n
+\t\t\t// Close the panel if another panel on the page opens\n
+\t\t\t.on( "panelbeforeopen", function( e ) {\n
+\t\t\t\tif ( self._open && e.target !== self.element[ 0 ] ) {\n
+\t\t\t\t\tself.close();\n
+\t\t\t\t}\n
+\t\t\t})\n
+\t\t\t// On escape, close? might need to have a target check too...\n
+\t\t\t.on( "keyup.panel", function( e ) {\n
+\t\t\t\tif ( e.keyCode === 27 && self._open ) {\n
+\t\t\t\t\tself.close();\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t\t\n
+\t\t// Clean up open panels after page hide\n
+\t\tif ( self._parentPage ) {\n
+\t\t\t$.mobile.document.on( "pagehide", ":jqmData(role=\'page\')", function() {\n
+\t\t\t\tif ( self._open ) {\n
+\t\t\t\t\tself.close( true );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t} else {\n
+\t\t\t$.mobile.document.on( "pagebeforehide", function() {\n
+\t\t\t\tif ( self._open ) {\n
+\t\t\t\t\tself.close( true );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\t\t}\n
+\t},\n
+\n
+\t// state storage of open or closed\n
+\t_open: false,\n
+\t_pageContentOpenClasses: null,\n
+\t_modalOpenClasses: null,\n
+\n
+\topen: function( immediate ) {\n
+\t\tif ( !this._open ) {\n
+\t\t\tvar self = this,\n
+\t\t\t\to = self.options,\n
+\t\t\t\t\n
+\t\t\t\t_openPanel = function() {\n
+\t\t\t\t\t$.mobile.document.off( "panelclose" );\n
+\t\t\t\t\tself._page().jqmData( "panel", "open" );\n
+\t\t\t\t\t\n
+\t\t\t\t\tif ( $.support.cssTransform3d && !!o.animate && o.display !== "overlay" ) {\n
+\t\t\t\t\t\tself._wrapper().addClass( o.classes.animate );\n
+\t\t\t\t\t\tself._fixedToolbars().addClass( o.classes.animate );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tif ( !immediate && $.support.cssTransform3d && !!o.animate ) {\n
+\t\t\t\t\t\t$.mobile.document.on( self._transitionEndEvents, complete );\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tsetTimeout( complete, 0 );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tif ( o.theme && o.display !== "overlay" ) {\n
+\t\t\t\t\t\tself._page().parent()\n
+\t\t\t\t\t\t\t.addClass( o.classes.pageContainer + "-themed " + o.classes.pageContainer + "-" + o.theme );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tself.element\n
+\t\t\t\t\t\t.removeClass( o.classes.panelClosed )\n
+\t\t\t\t\t\t.addClass( o.classes.panelOpen );\n
+\n
+\t\t\t\t\tself._positionPanel();\n
+\n
+\t\t\t\t\tself._pageContentOpenClasses = self._getPosDisplayClasses( o.classes.pageContentPrefix );\n
+\t\t\t\t\t\n
+\t\t\t\t\tif ( o.display !== "overlay" ) {\n
+\t\t\t\t\t\tself._page().parent().addClass( o.classes.pageContainer );\n
+\t\t\t\t\t\tself._wrapper().addClass( self._pageContentOpenClasses );\n
+\t\t\t\t\t\tself._fixedToolbars().addClass( self._pageContentOpenClasses );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tself._modalOpenClasses = self._getPosDisplayClasses( o.classes.modal ) + " " + o.classes.modalOpen;\n
+\t\t\t\t\tif ( self._modal ) {\n
+\t\t\t\t\t\tself._modal.addClass( self._modalOpenClasses );\n
+\t\t\t\t\t}\n
+\t\t\t\t},\n
+\t\t\t\tcomplete = function() {\n
+\t\t\t\t\t$.mobile.document.off( self._transitionEndEvents, complete );\n
+\t\t\t\t\t\n
+\t\t\t\t\tif ( o.display !== "overlay" ) {\n
+\t\t\t\t\t\tself._wrapper().addClass( o.classes.pageContentPrefix + "-open" );\n
+\t\t\t\t\t\tself._fixedToolbars().addClass( o.classes.pageContentPrefix + "-open" );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tself._bindFixListener();\n
+\n
+\t\t\t\t\tself._trigger( "open" );\n
+\t\t\t\t};\n
+\n
+\t\t\tself._trigger( "beforeopen" );\n
+\t\t\t\n
+\t\t\tif ( self._page().jqmData( "panel" ) === "open" ) {\n
+\t\t\t\t$.mobile.document.on( "panelclose", function() {\n
+\t\t\t\t\t_openPanel();\n
+\t\t\t\t});\n
+\t\t\t} else {\n
+\t\t\t\t_openPanel();\n
+\t\t\t}\n
+\n
+\t\t\tself._open = true;\n
+\t\t}\n
+\t},\n
+\n
+\tclose: function( immediate ) {\n
+\t\tif ( this._open ) {\n
+\t\t\tvar self = this,\n
+\t\t\t\to = this.options,\n
+\t\t\t\t\n
+\t\t\t\t_closePanel = function() {\n
+\t\t\t\t\tif ( !immediate && $.support.cssTransform3d && !!o.animate ) {\n
+\t\t\t\t\t\t$.mobile.document.on( self._transitionEndEvents, complete );\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\tsetTimeout( complete, 0 );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tself.element.removeClass( o.classes.panelOpen );\n
+\t\t\t\t\t\n
+\t\t\t\t\tif ( o.display !== "overlay" ) {\n
+\t\t\t\t\t\tself._wrapper().removeClass( self._pageContentOpenClasses );\n
+\t\t\t\t\t\tself._fixedToolbars().removeClass( self._pageContentOpenClasses );\n
+\t\t\t\t\t}\n
+\t\t\t\t\t\n
+\t\t\t\t\tif ( self._modal ) {\n
+\t\t\t\t\t\tself._modal.removeClass( self._modalOpenClasses );\n
+\t\t\t\t\t}\n
+\t\t\t\t},\n
+\t\t\t\tcomplete = function() {\n
+\t\t\t\t\t$.mobile.document.off( self._transitionEndEvents, complete );\n
+\t\t\t\t\t\n
+\t\t\t\t\tif ( o.theme && o.display !== "overlay" ) {\n
+\t\t\t\t\t\tself._page().parent().removeClass( o.classes.pageContainer + "-themed " + o.classes.pageContainer + "-" + o.theme );\n
+\t\t\t\t\t}\n
+\t\t\t\t\t\t\n
+\t\t\t\t\tself.element.addClass( o.classes.panelClosed );\n
+\n
+\t\t\t\t\tif ( o.display !== "overlay" ) {\n
+\t\t\t\t\t\tself._page().parent().removeClass( o.classes.pageContainer );\n
+\t\t\t\t\t\tself._wrapper().removeClass( o.classes.pageContentPrefix + "-open" );\n
+\t\t\t\t\t\tself._fixedToolbars().removeClass( o.classes.pageContentPrefix + "-open" );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tif ( $.support.cssTransform3d && !!o.animate && o.display !== "overlay" ) {\n
+\t\t\t\t\t\tself._wrapper().removeClass( o.classes.animate );\n
+\t\t\t\t\t\tself._fixedToolbars().removeClass( o.classes.animate );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tself._fixPanel();\n
+\t\t\t\t\tself._unbindFixListener();\n
+\t\t\t\t\t$.mobile.resetActivePageHeight();\n
+\n
+\t\t\t\t\tself._page().jqmRemoveData( "panel" );\n
+\t\t\t\t\t\n
+\t\t\t\t\tself._trigger( "close" );\n
+\t\t\t\t};\n
+\n
+\t\t\tself._trigger( "beforeclose" );\n
+\n
+\t\t\t_closePanel();\n
+\n
+\t\t\tself._open = false;\n
+\t\t}\n
+\t},\n
+\n
+\ttoggle: function() {\n
+\t\tthis[ this._open ? "close" : "open" ]();\n
+\t},\n
+\n
+\t_transitionEndEvents: "webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd",\n
+\n
+\t_destroy: function() {\n
+\t\tvar o = this.options,\n
+\t\t\tmultiplePanels = ( $( "body > :mobile-panel" ).length + $.mobile.activePage.find( ":mobile-panel" ).length ) > 1;\n
+\n
+\t\tif ( o.display !== "overlay" ) {\n
+\t\t\t// Destroy the wrapper even if there are still other panels, because we don\'t know if they use a wrapper\n
+\t\t\tthis._wrapper().children().unwrap();\n
+\n
+\t\t\tif ( this._open ) {\n
+\t\t\t\t\n
+\t\t\t\tthis._fixedToolbars().removeClass( o.classes.pageContentPrefix + "-open" );\n
+\t\t\t\t\n
+\t\t\t\tif ( $.support.cssTransform3d && !!o.animate ) {\n
+\t\t\t\t\tthis._fixedToolbars().removeClass( o.classes.animate );\n
+\t\t\t\t}\n
+\t\t\t\t\n
+\t\t\t\tthis._page().parent().removeClass( o.classes.pageContainer );\n
+\t\t\t\t\n
+\t\t\t\tif ( o.theme ) {\n
+\t\t\t\t\tthis._page().parent().removeClass( o.classes.pageContainer + "-themed " + o.classes.pageContainer + "-" + o.theme );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( !multiplePanels ) {\n
+\n
+\t\t\t$.mobile.document.off( "panelopen panelclose" );\n
+\t\t\t\n
+\t\t\tif ( this._open ) {\n
+\t\t\t\t$.mobile.document.off( this._transitionEndEvents );\n
+\t\t\t\t$.mobile.resetActivePageHeight();\n
+\t\t\t}\n
+\t\t}\n
+\t\t\n
+\t\tif ( this._open ) {\n
+\t\t\tthis._page().jqmRemoveData( "panel" );\n
+\t\t}\n
+\t\t\n
+\t\tthis._panelInner.children().unwrap();\n
+\n
+\t\tthis.element\n
+\t\t\t.removeClass( [ this._getPanelClasses(), o.classes.panelOpen, o.classes.animate ].join( " " ) )\n
+\t\t\t.off( "swipeleft.panel swiperight.panel" )\n
+\t\t\t.off( "panelbeforeopen" )\n
+\t\t\t.off( "panelhide" )\n
+\t\t\t.off( "keyup.panel" )\n
+\t\t\t.off( "updatelayout" )\n
+\t\t\t.off( this._transitionEndEvents );\n
+\n
+\t\tthis._closeLink.off( "click.panel" );\n
+\n
+\t\tif ( this._modal ) {\n
+\t\t\tthis._modal.remove();\n
+\t\t}\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.table", {\n
+\toptions: {\n
+\t\tclasses: {\n
+\t\t\ttable: "ui-table"\n
+\t\t},\n
+\t\tenhanced: false\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tif ( !this.options.enhanced ) {\n
+\t\t\tthis.element.addClass( this.options.classes.table );\n
+\t\t}\n
+\n
+\t\t// extend here, assign on refresh > _setHeaders\n
+\t\t$.extend( this, {\n
+\n
+\t\t\t// Expose headers and allHeaders properties on the widget\n
+\t\t\t// headers references the THs within the first TR in the table\n
+\t\t\theaders: undefined,\n
+\n
+\t\t\t// allHeaders references headers, plus all THs in the thead, which may\n
+\t\t\t// include several rows, or not\n
+\t\t\tallHeaders: undefined\n
+\t\t});\n
+\n
+\t\tthis._refresh( true );\n
+\t},\n
+\n
+\t_setHeaders: function() {\n
+\t\tvar trs = this.element.find( "thead tr" );\n
+\n
+\t\tthis.headers = this.element.find( "tr:eq(0)" ).children();\n
+\t\tthis.allHeaders = this.headers.add( trs.children() );\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tthis._refresh();\n
+\t},\n
+\n
+\trebuild: $.noop,\n
+\n
+\t_refresh: function( /* create */ ) {\n
+\t\tvar table = this.element,\n
+\t\t\ttrs = table.find( "thead tr" );\n
+\n
+\t\t// updating headers on refresh (fixes #5880)\n
+\t\tthis._setHeaders();\n
+\n
+\t\t// Iterate over the trs\n
+\t\ttrs.each( function() {\n
+\t\t\tvar columnCount = 0;\n
+\n
+\t\t\t// Iterate over the children of the tr\n
+\t\t\t$( this ).children().each( function() {\n
+\t\t\t\tvar span = parseInt( this.getAttribute( "colspan" ), 10 ),\n
+\t\t\t\t\tselector = ":nth-child(" + ( columnCount + 1 ) + ")",\n
+\t\t\t\t\tj;\n
+\n
+\t\t\t\tthis.setAttribute( "data-" + $.mobile.ns + "colstart", columnCount + 1 );\n
+\n
+\t\t\t\tif ( span ) {\n
+\t\t\t\t\tfor( j = 0; j < span - 1; j++ ) {\n
+\t\t\t\t\t\tcolumnCount++;\n
+\t\t\t\t\t\tselector += ", :nth-child(" + ( columnCount + 1 ) + ")";\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// Store "cells" data on header as a reference to all cells in the \n
+\t\t\t\t// same column as this TH\n
+\t\t\t\t$( this ).jqmData( "cells", table.find( "tr" ).not( trs.eq( 0 ) ).not( this ).children( selector ) );\n
+\n
+\t\t\t\tcolumnCount++;\n
+\t\t\t});\n
+\t\t});\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.table", $.mobile.table, {\n
+\toptions: {\n
+\t\tmode: "columntoggle",\n
+\t\tcolumnBtnTheme: null,\n
+\t\tcolumnPopupTheme: null,\n
+\t\tcolumnBtnText: "Columns...",\n
+\t\tclasses: $.extend( $.mobile.table.prototype.options.classes, {\n
+\t\t\tpopup: "ui-table-columntoggle-popup",\n
+\t\t\tcolumnBtn: "ui-table-columntoggle-btn",\n
+\t\t\tpriorityPrefix: "ui-table-priority-",\n
+\t\t\tcolumnToggleTable: "ui-table-columntoggle"\n
+\t\t})\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tthis._super();\n
+\n
+\t\tif( this.options.mode !== "columntoggle" ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t$.extend( this, {\n
+\t\t\t_menu: null\n
+\t\t});\n
+\n
+\t\tif( this.options.enhanced ) {\n
+\t\t\tthis._menu = this.document.find( this._id() + "-popup" ).children().first();\n
+\t\t} else {\n
+\t\t\tthis._menu = this._enhanceColToggle();\n
+\t\t\tthis.element.addClass( this.options.classes.columnToggleTable );\n
+\t\t}\n
+\n
+\t\tthis._setupEvents();\n
+\n
+\t\tthis._setToggleState();\n
+\t},\n
+\n
+\t_id: function() {\n
+\t\treturn ( this.element.attr( "id" ) || ( this.widgetName + this.uuid ) );\n
+\t},\n
+\n
+\t_setupEvents: function() {\n
+\t\t//NOTE: inputs are bound in bindToggles,\n
+\t\t// so it can be called on refresh, too\n
+\n
+\t\t// update column toggles on resize\n
+\t\tthis._on( $.mobile.window, {\n
+\t\t\tthrottledresize: "_setToggleState"\n
+\t\t});\n
+\t},\n
+\n
+\t_bindToggles: function( menu ) {\n
+\t\tvar inputs = menu.find( "input" );\n
+\n
+\t\tthis._on( inputs, {\n
+\t\t\tchange: "_menuInputChange"\n
+\t\t});\n
+\t},\n
+\n
+\t_addToggles: function( menu, keep ) {\n
+\t\tvar opts = this.options;\n
+\n
+\t\t// allow update of menu on refresh (fixes #5880)\n
+\t\tif ( !keep ) {\n
+\t\t\tmenu.empty();\n
+\t\t}\n
+\n
+\t\t// create the hide/show toggles\n
+\t\tthis.headers.not( "td" ).each( function() {\n
+\t\t\tvar header = $( this ),\n
+\t\t\t\tpriority = $.mobile.getAttribute( this, "priority" ),\n
+\t\t\t\tcells = header.add( header.jqmData( "cells" ) );\n
+\n
+\t\t\tif( priority ) {\n
+\t\t\t\tcells.addClass( opts.classes.priorityPrefix + priority );\n
+\n
+\t\t\t\tif ( !keep ) {\n
+\t\t\t\t\t$("<label><input type=\'checkbox\' checked />" +\n
+\t\t\t\t\t\t( header.children( "abbr" ).first().attr( "title" ) ||\n
+\t\t\t\t\t\t\theader.text() ) +\n
+\t\t\t\t\t\t"</label>" )\n
+\t\t\t\t\t\t.appendTo( menu )\n
+\t\t\t\t\t\t.children( 0 )\n
+\t\t\t\t\t\t.jqmData( "cells", cells )\n
+\t\t\t\t\t\t.checkboxradio( {\n
+\t\t\t\t\t\t\ttheme: opts.columnPopupTheme\n
+\t\t\t\t\t\t});\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\t// set bindings here\n
+\t\tif ( !keep ) {\n
+\t\t\tthis._bindToggles( menu );\n
+\t\t}\n
+\t},\n
+\n
+\t_menuInputChange: function( evt ) {\n
+\t\tvar input = $( evt.target ),\n
+\t\t\tchecked = input[ 0 ].checked;\n
+\n
+\t\tinput.jqmData( "cells" )\n
+\t\t\t.toggleClass( "ui-table-cell-hidden", !checked )\n
+\t\t\t.toggleClass( "ui-table-cell-visible", checked );\n
+\n
+\t\tif ( input[ 0 ].getAttribute( "locked" ) ) {\n
+\t\t\tinput.removeAttr( "locked" );\n
+\n
+\t\t\tthis._unlockCells( input.jqmData( "cells" ) );\n
+\t\t} else {\n
+\t\t\tinput.attr( "locked", true );\n
+\t\t}\n
+\t},\n
+\n
+\t_unlockCells: function( cells ) {\n
+\t\t// allow hide/show via CSS only = remove all toggle-locks\n
+\t\tcells.removeClass( "ui-table-cell-hidden ui-table-cell-visible");\n
+\t},\n
+\n
+\t_enhanceColToggle: function() {\n
+\t\tvar id , menuButton, popup, menu,\n
+\t\t\ttable = this.element,\n
+\t\t\topts = this.options,\n
+\t\t\tns = $.mobile.ns,\n
+\t\t\tfragment = $.mobile.document[ 0 ].createDocumentFragment();\n
+\n
+\t\tid = this._id() + "-popup";\n
+\t\tmenuButton = $( "<a role=\'button\' href=\'#" + id + "\' " +\n
+\t\t\t"class=\'" + opts.classes.columnBtn + " ui-btn ui-btn-" + ( opts.columnBtnTheme || "a" ) + " ui-corner-all ui-shadow ui-mini\' " +\n
+\t\t\t"data-" + ns + "rel=\'popup\' " +\n
+\t\t\t"data-" + ns + "mini=\'true\'>" + opts.columnBtnText + "</a>" );\n
+\t\tpopup = $( "<div data-" + ns + "role=\'popup\' data-" + ns + "role=\'fieldcontain\' class=\'" + opts.classes.popup + "\' id=\'" + id + "\'></div>" );\n
+\t\tmenu = $( "<fieldset data-" + ns + "role=\'controlgroup\'></fieldset>" );\n
+\n
+\t\t// set extension here, send "false" to trigger build/rebuild\n
+\t\tthis._addToggles( menu, false );\n
+\n
+\t\tmenu.appendTo( popup );\n
+\n
+\t\tfragment.appendChild( popup[ 0 ] );\n
+\t\tfragment.appendChild( menuButton[ 0 ] );\n
+\t\ttable.before( fragment );\n
+\n
+\t\tpopup.popup().enhanceWithin();\n
+\n
+\t\treturn menu;\n
+\t},\n
+\n
+\trebuild: function() {\n
+\t\tthis._super();\n
+\n
+\t\tif ( this.options.mode === "columntoggle" ) {\n
+\t\t\t// NOTE: rebuild passes "false", while refresh passes "undefined"\n
+\t\t\t// both refresh the table, but inside addToggles, !false will be true,\n
+\t\t\t// so a rebuild call can be indentified\n
+\t\t\tthis._refresh( false );\n
+\t\t}\n
+\t},\n
+\n
+\t_refresh: function( create ) {\n
+\t\tthis._super( create );\n
+\n
+\t\tif ( !create && this.options.mode === "columntoggle" ) {\n
+\t\t\t// columns not being replaced must be cleared from input toggle-locks\n
+\t\t\tthis._unlockCells( this.allHeaders );\n
+\n
+\t\t\t// update columntoggles and cells\n
+\t\t\tthis._addToggles( this._menu, create );\n
+\n
+\t\t\t// check/uncheck\n
+\t\t\tthis._setToggleState();\n
+\t\t}\n
+\t},\n
+\n
+\t_setToggleState: function() {\n
+\t\tthis._menu.find( "input" ).each( function() {\n
+\t\t\tvar checkbox = $( this );\n
+\n
+\t\t\tthis.checked = checkbox.jqmData( "cells" ).eq( 0 ).css( "display" ) === "table-cell";\n
+\t\t\tcheckbox.checkboxradio( "refresh" );\n
+\t\t});\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tthis._super();\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+(function( $, undefined ) {\n
+\n
+$.widget( "mobile.table", $.mobile.table, {\n
+\toptions: {\n
+\t\tmode: "reflow",\n
+\t\tclasses: $.extend( $.mobile.table.prototype.options.classes, {\n
+\t\t\treflowTable: "ui-table-reflow",\n
+\t\t\tcellLabels: "ui-table-cell-label"\n
+\t\t})\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tthis._super();\n
+\n
+\t\t// If it\'s not reflow mode, return here.\n
+\t\tif( this.options.mode !== "reflow" ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif( !this.options.enhanced ) {\n
+\t\t\tthis.element.addClass( this.options.classes.reflowTable );\n
+\n
+\t\t\tthis._updateReflow();\n
+\t\t}\n
+\t},\n
+\n
+\trebuild: function() {\n
+\t\tthis._super();\n
+\n
+\t\tif ( this.options.mode === "reflow" ) {\n
+\t\t\tthis._refresh( false );\n
+\t\t}\n
+\t},\n
+\n
+\t_refresh: function( create ) {\n
+\t\tthis._super( create );\n
+\t\tif ( !create && this.options.mode === "reflow" ) {\n
+\t\t\tthis._updateReflow( );\n
+\t\t}\n
+\t},\n
+\n
+\t_updateReflow: function() {\n
+\t\tvar table = this,\n
+\t\t\topts = this.options;\n
+\n
+\t\t// get headers in reverse order so that top-level headers are appended last\n
+\t\t$( table.allHeaders.get().reverse() ).each( function() {\n
+\t\t\tvar cells = $( this ).jqmData( "cells" ),\n
+\t\t\t\tcolstart = $.mobile.getAttribute( this, "colstart" ),\n
+\t\t\t\thierarchyClass = cells.not( this ).filter( "thead th" ).length && " ui-table-cell-label-top",\n
+\t\t\t\ttext = $( this ).text(),\n
+\t\t\t\titeration, filter;\n
+\n
+\t\t\t\tif ( text !== ""  ) {\n
+\n
+\t\t\t\t\tif( hierarchyClass ) {\n
+\t\t\t\t\t\titeration = parseInt( this.getAttribute( "colspan" ), 10 );\n
+\t\t\t\t\t\tfilter = "";\n
+\n
+\t\t\t\t\t\tif ( iteration ){\n
+\t\t\t\t\t\t\tfilter = "td:nth-child("+ iteration +"n + " + ( colstart ) +")";\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\ttable._addLabels( cells.filter( filter ), opts.classes.cellLabels + hierarchyClass, text );\n
+\t\t\t\t\t} else {\n
+\t\t\t\t\t\ttable._addLabels( cells, opts.classes.cellLabels, text );\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t}\n
+\t\t});\n
+\t},\n
+\n
+\t_addLabels: function( cells, label, text ) {\n
+\t\t// .not fixes #6006\n
+\t\tcells.not( ":has(b." + label + ")" ).prepend( "<b class=\'" + label + "\'>" + text + "</b>"  );\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+\n
+/*!\n
+ * jQuery UI Tabs @VERSION\n
+ * http://jqueryui.com\n
+ *\n
+ * Copyright 2013 jQuery Foundation and other contributors\n
+ * Released under the MIT license.\n
+ * http://jquery.org/license\n
+ *\n
+ * http://api.jqueryui.com/tabs/\n
+ *\n
+ * Depends:\n
+ *\tjquery.ui.core.js\n
+ *\tjquery.ui.widget.js\n
+ */\n
+(function( $, undefined ) {\n
+\n
+var tabId = 0,\n
+\trhash = /#.*$/;\n
+\n
+function getNextTabId() {\n
+\treturn ++tabId;\n
+}\n
+\n
+function isLocal( anchor ) {\n
+\treturn anchor.hash.length > 1 &&\n
+\t\tdecodeURIComponent( anchor.href.replace( rhash, "" ) ) ===\n
+\t\t\tdecodeURIComponent( location.href.replace( rhash, "" ) );\n
+}\n
+\n
+$.widget( "ui.tabs", {\n
+\tversion: "@VERSION",\n
+\tdelay: 300,\n
+\toptions: {\n
+\t\tactive: null,\n
+\t\tcollapsible: false,\n
+\t\tevent: "click",\n
+\t\theightStyle: "content",\n
+\t\thide: null,\n
+\t\tshow: null,\n
+\n
+\t\t// callbacks\n
+\t\tactivate: null,\n
+\t\tbeforeActivate: null,\n
+\t\tbeforeLoad: null,\n
+\t\tload: null\n
+\t},\n
+\n
+\t_create: function() {\n
+\t\tvar that = this,\n
+\t\t\toptions = this.options;\n
+\n
+\t\tthis.running = false;\n
+\n
+\t\tthis.element\n
+\t\t\t.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )\n
+\t\t\t.toggleClass( "ui-tabs-collapsible", options.collapsible )\n
+\t\t\t// Prevent users from focusing disabled tabs via click\n
+\t\t\t.delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {\n
+\t\t\t\tif ( $( this ).is( ".ui-state-disabled" ) ) {\n
+\t\t\t\t\tevent.preventDefault();\n
+\t\t\t\t}\n
+\t\t\t})\n
+\t\t\t// support: IE <9\n
+\t\t\t// Preventing the default action in mousedown doesn\'t prevent IE\n
+\t\t\t// from focusing the element, so if the anchor gets focused, blur.\n
+\t\t\t// We don\'t have to worry about focusing the previously focused\n
+\t\t\t// element since clicking on a non-focusable element should focus\n
+\t\t\t// the body anyway.\n
+\t\t\t.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {\n
+\t\t\t\tif ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {\n
+\t\t\t\t\tthis.blur();\n
+\t\t\t\t}\n
+\t\t\t});\n
+\n
+\t\tthis._processTabs();\n
+\t\toptions.active = this._initialActive();\n
+\n
+\t\t// Take disabling tabs via class attribute from HTML\n
+\t\t// into account and update option properly.\n
+\t\tif ( $.isArray( options.disabled ) ) {\n
+\t\t\toptions.disabled = $.unique( options.disabled.concat(\n
+\t\t\t\t$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {\n
+\t\t\t\t\treturn that.tabs.index( li );\n
+\t\t\t\t})\n
+\t\t\t) ).sort();\n
+\t\t}\n
+\n
+\t\t// check for length avoids error when initializing empty list\n
+\t\tif ( this.options.active !== false && this.anchors.length ) {\n
+\t\t\tthis.active = this._findActive( options.active );\n
+\t\t} else {\n
+\t\t\tthis.active = $();\n
+\t\t}\n
+\n
+\t\tthis._refresh();\n
+\n
+\t\tif ( this.active.length ) {\n
+\t\t\tthis.load( options.active );\n
+\t\t}\n
+\t},\n
+\n
+\t_initialActive: function() {\n
+\t\tvar active = this.options.active,\n
+\t\t\tcollapsible = this.options.collapsible,\n
+\t\t\tlocationHash = location.hash.substring( 1 );\n
+\n
+\t\tif ( active === null ) {\n
+\t\t\t// check the fragment identifier in the URL\n
+\t\t\tif ( locationHash ) {\n
+\t\t\t\tthis.tabs.each(function( i, tab ) {\n
+\t\t\t\t\tif ( $( tab ).attr( "aria-controls" ) === locationHash ) {\n
+\t\t\t\t\t\tactive = i;\n
+\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t}\n
+\t\t\t\t});\n
+\t\t\t}\n
+\n
+\t\t\t// check for a tab marked active via a class\n
+\t\t\tif ( active === null ) {\n
+\t\t\t\tactive = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );\n
+\t\t\t}\n
+\n
+\t\t\t// no active tab, set to false\n
+\t\t\tif ( active === null || active === -1 ) {\n
+\t\t\t\tactive = this.tabs.length ? 0 : false;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// handle numbers: negative, out of range\n
+\t\tif ( active !== false ) {\n
+\t\t\tactive = this.tabs.index( this.tabs.eq( active ) );\n
+\t\t\tif ( active === -1 ) {\n
+\t\t\t\tactive = collapsible ? false : 0;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// don\'t allow collapsible: false and active: false\n
+\t\tif ( !collapsible && active === false && this.anchors.length ) {\n
+\t\t\tactive = 0;\n
+\t\t}\n
+\n
+\t\treturn active;\n
+\t},\n
+\n
+\t_getCreateEventData: function() {\n
+\t\treturn {\n
+\t\t\ttab: this.active,\n
+\t\t\tpanel: !this.active.length ? $() : this._getPanelForTab( this.active )\n
+\t\t};\n
+\t},\n
+\n
+\t_tabKeydown: function( event ) {\n
+\t\tvar focusedTab = $( this.document[0].activeElement ).closest( "li" ),\n
+\t\t\tselectedIndex = this.tabs.index( focusedTab ),\n
+\t\t\tgoingForward = true;\n
+\n
+\t\tif ( this._handlePageNav( event ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tswitch ( event.keyCode ) {\n
+\t\t\tcase $.ui.keyCode.RIGHT:\n
+\t\t\tcase $.ui.keyCode.DOWN:\n
+\t\t\t\tselectedIndex++;\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.ui.keyCode.UP:\n
+\t\t\tcase $.ui.keyCode.LEFT:\n
+\t\t\t\tgoingForward = false;\n
+\t\t\t\tselectedIndex--;\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.ui.keyCode.END:\n
+\t\t\t\tselectedIndex = this.anchors.length - 1;\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.ui.keyCode.HOME:\n
+\t\t\t\tselectedIndex = 0;\n
+\t\t\t\tbreak;\n
+\t\t\tcase $.ui.keyCode.SPACE:\n
+\t\t\t\t// Activate only, no collapsing\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t\tclearTimeout( this.activating );\n
+\t\t\t\tthis._activate( selectedIndex );\n
+\t\t\t\treturn;\n
+\t\t\tcase $.ui.keyCode.ENTER:\n
+\t\t\t\t// Toggle (cancel delayed activation, allow collapsing)\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t\tclearTimeout( this.activating );\n
+\t\t\t\t// Determine if we should collapse or activate\n
+\t\t\t\tthis._activate( selectedIndex === this.options.active ? false : selectedIndex );\n
+\t\t\t\treturn;\n
+\t\t\tdefault:\n
+\t\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Focus the appropriate tab, based on which key was pressed\n
+\t\tevent.preventDefault();\n
+\t\tclearTimeout( this.activating );\n
+\t\tselectedIndex = this._focusNextTab( selectedIndex, goingForward );\n
+\n
+\t\t// Navigating with control key will prevent automatic activation\n
+\t\tif ( !event.ctrlKey ) {\n
+\t\t\t// Update aria-selected immediately so that AT think the tab is already selected.\n
+\t\t\t// Otherwise AT may confuse the user by stating that they need to activate the tab,\n
+\t\t\t// but the tab will already be activated by the time the announcement finishes.\n
+\t\t\tfocusedTab.attr( "aria-selected", "false" );\n
+\t\t\tthis.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );\n
+\n
+\t\t\tthis.activating = this._delay(function() {\n
+\t\t\t\tthis.option( "active", selectedIndex );\n
+\t\t\t}, this.delay );\n
+\t\t}\n
+\t},\n
+\n
+\t_panelKeydown: function( event ) {\n
+\t\tif ( this._handlePageNav( event ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// Ctrl+up moves focus to the current tab\n
+\t\tif ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {\n
+\t\t\tevent.preventDefault();\n
+\t\t\tthis.active.focus();\n
+\t\t}\n
+\t},\n
+\n
+\t// Alt+page up/down moves focus to the previous/next tab (and activates)\n
+\t_handlePageNav: function( event ) {\n
+\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {\n
+\t\t\tthis._activate( this._focusNextTab( this.options.active - 1, false ) );\n
+\t\t\treturn true;\n
+\t\t}\n
+\t\tif ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {\n
+\t\t\tthis._activate( this._focusNextTab( this.options.active + 1, true ) );\n
+\t\t\treturn true;\n
+\t\t}\n
+\t},\n
+\n
+\t_findNextTab: function( index, goingForward ) {\n
+\t\tvar lastTabIndex = this.tabs.length - 1;\n
+\n
+\t\tfunction constrain() {\n
+\t\t\tif ( index > lastTabIndex ) {\n
+\t\t\t\tindex = 0;\n
+\t\t\t}\n
+\t\t\tif ( index < 0 ) {\n
+\t\t\t\tindex = lastTabIndex;\n
+\t\t\t}\n
+\t\t\treturn index;\n
+\t\t}\n
+\n
+\t\twhile ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {\n
+\t\t\tindex = goingForward ? index + 1 : index - 1;\n
+\t\t}\n
+\n
+\t\treturn index;\n
+\t},\n
+\n
+\t_focusNextTab: function( index, goingForward ) {\n
+\t\tindex = this._findNextTab( index, goingForward );\n
+\t\tthis.tabs.eq( index ).focus();\n
+\t\treturn index;\n
+\t},\n
+\n
+\t_setOption: function( key, value ) {\n
+\t\tif ( key === "active" ) {\n
+\t\t\t// _activate() will handle invalid values and update this.options\n
+\t\t\tthis._activate( value );\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( key === "disabled" ) {\n
+\t\t\t// don\'t use the widget factory\'s disabled handling\n
+\t\t\tthis._setupDisabled( value );\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis._super( key, value);\n
+\n
+\t\tif ( key === "collapsible" ) {\n
+\t\t\tthis.element.toggleClass( "ui-tabs-collapsible", value );\n
+\t\t\t// Setting collapsible: false while collapsed; open first panel\n
+\t\t\tif ( !value && this.options.active === false ) {\n
+\t\t\t\tthis._activate( 0 );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tif ( key === "event" ) {\n
+\t\t\tthis._setupEvents( value );\n
+\t\t}\n
+\n
+\t\tif ( key === "heightStyle" ) {\n
+\t\t\tthis._setupHeightStyle( value );\n
+\t\t}\n
+\t},\n
+\n
+\t_tabId: function( tab ) {\n
+\t\treturn tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();\n
+\t},\n
+\n
+\t_sanitizeSelector: function( hash ) {\n
+\t\treturn hash ? hash.replace( /[!"$%&\'()*+,.\\/:;<=>?@\\[\\]\\^`{|}~]/g, "\\\\$&" ) : "";\n
+\t},\n
+\n
+\trefresh: function() {\n
+\t\tvar options = this.options,\n
+\t\t\tlis = this.tablist.children( ":has(a[href])" );\n
+\n
+\t\t// get disabled tabs from class attribute from HTML\n
+\t\t// this will get converted to a boolean if needed in _refresh()\n
+\t\toptions.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {\n
+\t\t\treturn lis.index( tab );\n
+\t\t});\n
+\n
+\t\tthis._processTabs();\n
+\n
+\t\t// was collapsed or no tabs\n
+\t\tif ( options.active === false || !this.anchors.length ) {\n
+\t\t\toptions.active = false;\n
+\t\t\tthis.active = $();\n
+\t\t// was active, but active tab is gone\n
+\t\t} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {\n
+\t\t\t// all remaining tabs are disabled\n
+\t\t\tif ( this.tabs.length === options.disabled.length ) {\n
+\t\t\t\toptions.active = false;\n
+\t\t\t\tthis.active = $();\n
+\t\t\t// activate previous tab\n
+\t\t\t} else {\n
+\t\t\t\tthis._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );\n
+\t\t\t}\n
+\t\t// was active, active tab still exists\n
+\t\t} else {\n
+\t\t\t// make sure active index is correct\n
+\t\t\toptions.active = this.tabs.index( this.active );\n
+\t\t}\n
+\n
+\t\tthis._refresh();\n
+\t},\n
+\n
+\t_refresh: function() {\n
+\t\tthis._setupDisabled( this.options.disabled );\n
+\t\tthis._setupEvents( this.options.event );\n
+\t\tthis._setupHeightStyle( this.options.heightStyle );\n
+\n
+\t\tthis.tabs.not( this.active ).attr({\n
+\t\t\t"aria-selected": "false",\n
+\t\t\ttabIndex: -1\n
+\t\t});\n
+\t\tthis.panels.not( this._getPanelForTab( this.active ) )\n
+\t\t\t.hide()\n
+\t\t\t.attr({\n
+\t\t\t\t"aria-expanded": "false",\n
+\t\t\t\t"aria-hidden": "true"\n
+\t\t\t});\n
+\n
+\t\t// Make sure one tab is in the tab order\n
+\t\tif ( !this.active.length ) {\n
+\t\t\tthis.tabs.eq( 0 ).attr( "tabIndex", 0 );\n
+\t\t} else {\n
+\t\t\tthis.active\n
+\t\t\t\t.addClass( "ui-tabs-active ui-state-active" )\n
+\t\t\t\t.attr({\n
+\t\t\t\t\t"aria-selected": "true",\n
+\t\t\t\t\ttabIndex: 0\n
+\t\t\t\t});\n
+\t\t\tthis._getPanelForTab( this.active )\n
+\t\t\t\t.show()\n
+\t\t\t\t.attr({\n
+\t\t\t\t\t"aria-expanded": "true",\n
+\t\t\t\t\t"aria-hidden": "false"\n
+\t\t\t\t});\n
+\t\t}\n
+\t},\n
+\n
+\t_processTabs: function() {\n
+\t\tvar that = this;\n
+\n
+\t\tthis.tablist = this._getList()\n
+\t\t\t.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )\n
+\t\t\t.attr( "role", "tablist" );\n
+\n
+\t\tthis.tabs = this.tablist.find( "> li:has(a[href])" )\n
+\t\t\t.addClass( "ui-state-default ui-corner-top" )\n
+\t\t\t.attr({\n
+\t\t\t\trole: "tab",\n
+\t\t\t\ttabIndex: -1\n
+\t\t\t});\n
+\n
+\t\tthis.anchors = this.tabs.map(function() {\n
+\t\t\t\treturn $( "a", this )[ 0 ];\n
+\t\t\t})\n
+\t\t\t.addClass( "ui-tabs-anchor" )\n
+\t\t\t.attr({\n
+\t\t\t\trole: "presentation",\n
+\t\t\t\ttabIndex: -1\n
+\t\t\t});\n
+\n
+\t\tthis.panels = $();\n
+\n
+\t\tthis.anchors.each(function( i, anchor ) {\n
+\t\t\tvar selector, panel, panelId,\n
+\t\t\t\tanchorId = $( anchor ).uniqueId().attr( "id" ),\n
+\t\t\t\ttab = $( anchor ).closest( "li" ),\n
+\t\t\t\toriginalAriaControls = tab.attr( "aria-controls" );\n
+\n
+\t\t\t// inline tab\n
+\t\t\tif ( isLocal( anchor ) ) {\n
+\t\t\t\tselector = anchor.hash;\n
+\t\t\t\tpanel = that.element.find( that._sanitizeSelector( selector ) );\n
+\t\t\t// remote tab\n
+\t\t\t} else {\n
+\t\t\t\tpanelId = that._tabId( tab );\n
+\t\t\t\tselector = "#" + panelId;\n
+\t\t\t\tpanel = that.element.find( selector );\n
+\t\t\t\tif ( !panel.length ) {\n
+\t\t\t\t\tpanel = that._createPanel( panelId );\n
+\t\t\t\t\tpanel.insertAfter( that.panels[ i - 1 ] || that.tablist );\n
+\t\t\t\t}\n
+\t\t\t\tpanel.attr( "aria-live", "polite" );\n
+\t\t\t}\n
+\n
+\t\t\tif ( panel.length) {\n
+\t\t\t\tthat.panels = that.panels.add( panel );\n
+\t\t\t}\n
+\t\t\tif ( originalAriaControls ) {\n
+\t\t\t\ttab.data( "ui-tabs-aria-controls", originalAriaControls );\n
+\t\t\t}\n
+\t\t\ttab.attr({\n
+\t\t\t\t"aria-controls": selector.substring( 1 ),\n
+\t\t\t\t"aria-labelledby": anchorId\n
+\t\t\t});\n
+\t\t\tpanel.attr( "aria-labelledby", anchorId );\n
+\t\t});\n
+\n
+\t\tthis.panels\n
+\t\t\t.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )\n
+\t\t\t.attr( "role", "tabpanel" );\n
+\t},\n
+\n
+\t// allow overriding how to find the list for rare usage scenarios (#7715)\n
+\t_getList: function() {\n
+\t\treturn this.element.find( "ol,ul" ).eq( 0 );\n
+\t},\n
+\n
+\t_createPanel: function( id ) {\n
+\t\treturn $( "<div>" )\n
+\t\t\t.attr( "id", id )\n
+\t\t\t.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )\n
+\t\t\t.data( "ui-tabs-destroy", true );\n
+\t},\n
+\n
+\t_setupDisabled: function( disabled ) {\n
+\t\tif ( $.isArray( disabled ) ) {\n
+\t\t\tif ( !disabled.length ) {\n
+\t\t\t\tdisabled = false;\n
+\t\t\t} else if ( disabled.length === this.anchors.length ) {\n
+\t\t\t\tdisabled = true;\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// disable tabs\n
+\t\tfor ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {\n
+\t\t\tif ( disabled === true || $.inArray( i, disabled ) !== -1 ) {\n
+\t\t\t\t$( li )\n
+\t\t\t\t\t.addClass( "ui-state-disabled" )\n
+\t\t\t\t\t.attr( "aria-disabled", "true" );\n
+\t\t\t} else {\n
+\t\t\t\t$( li )\n
+\t\t\t\t\t.removeClass( "ui-state-disabled" )\n
+\t\t\t\t\t.removeAttr( "aria-disabled" );\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tthis.options.disabled = disabled;\n
+\t},\n
+\n
+\t_setupEvents: function( event ) {\n
+\t\tvar events = {\n
+\t\t\tclick: function( event ) {\n
+\t\t\t\tevent.preventDefault();\n
+\t\t\t}\n
+\t\t};\n
+\t\tif ( event ) {\n
+\t\t\t$.each( event.split(" "), function( index, eventName ) {\n
+\t\t\t\tevents[ eventName ] = "_eventHandler";\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tthis._off( this.anchors.add( this.tabs ).add( this.panels ) );\n
+\t\tthis._on( this.anchors, events );\n
+\t\tthis._on( this.tabs, { keydown: "_tabKeydown" } );\n
+\t\tthis._on( this.panels, { keydown: "_panelKeydown" } );\n
+\n
+\t\tthis._focusable( this.tabs );\n
+\t\tthis._hoverable( this.tabs );\n
+\t},\n
+\n
+\t_setupHeightStyle: function( heightStyle ) {\n
+\t\tvar maxHeight,\n
+\t\t\tparent = this.element.parent();\n
+\n
+\t\tif ( heightStyle === "fill" ) {\n
+\t\t\tmaxHeight = parent.height();\n
+\t\t\tmaxHeight -= this.element.outerHeight() - this.element.height();\n
+\n
+\t\t\tthis.element.siblings( ":visible" ).each(function() {\n
+\t\t\t\tvar elem = $( this ),\n
+\t\t\t\t\tposition = elem.css( "position" );\n
+\n
+\t\t\t\tif ( position === "absolute" || position === "fixed" ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\tmaxHeight -= elem.outerHeight( true );\n
+\t\t\t});\n
+\n
+\t\t\tthis.element.children().not( this.panels ).each(function() {\n
+\t\t\t\tmaxHeight -= $( this ).outerHeight( true );\n
+\t\t\t});\n
+\n
+\t\t\tthis.panels.each(function() {\n
+\t\t\t\t$( this ).height( Math.max( 0, maxHeight -\n
+\t\t\t\t\t$( this ).innerHeight() + $( this ).height() ) );\n
+\t\t\t})\n
+\t\t\t.css( "overflow", "auto" );\n
+\t\t} else if ( heightStyle === "auto" ) {\n
+\t\t\tmaxHeight = 0;\n
+\t\t\tthis.panels.each(function() {\n
+\t\t\t\tmaxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );\n
+\t\t\t}).height( maxHeight );\n
+\t\t}\n
+\t},\n
+\n
+\t_eventHandler: function( event ) {\n
+\t\tvar options = this.options,\n
+\t\t\tactive = this.active,\n
+\t\t\tanchor = $( event.currentTarget ),\n
+\t\t\ttab = anchor.closest( "li" ),\n
+\t\t\tclickedIsActive = tab[ 0 ] === active[ 0 ],\n
+\t\t\tcollapsing = clickedIsActive && options.collapsible,\n
+\t\t\ttoShow = collapsing ? $() : this._getPanelForTab( tab ),\n
+\t\t\ttoHide = !active.length ? $() : this._getPanelForTab( active ),\n
+\t\t\teventData = {\n
+\t\t\t\toldTab: active,\n
+\t\t\t\toldPanel: toHide,\n
+\t\t\t\tnewTab: collapsing ? $() : tab,\n
+\t\t\t\tnewPanel: toShow\n
+\t\t\t};\n
+\n
+\t\tevent.preventDefault();\n
+\n
+\t\tif ( tab.hasClass( "ui-state-disabled" ) ||\n
+\t\t\t\t// tab is already loading\n
+\t\t\t\ttab.hasClass( "ui-tabs-loading" ) ||\n
+\t\t\t\t// can\'t switch durning an animation\n
+\t\t\t\tthis.running ||\n
+\t\t\t\t// click on active header, but not collapsible\n
+\t\t\t\t( clickedIsActive && !options.collapsible ) ||\n
+\t\t\t\t// allow canceling activation\n
+\t\t\t\t( this._trigger( "beforeActivate", event, eventData ) === false ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\toptions.active = collapsing ? false : this.tabs.index( tab );\n
+\n
+\t\tthis.active = clickedIsActive ? $() : tab;\n
+\t\tif ( this.xhr ) {\n
+\t\t\tthis.xhr.abort();\n
+\t\t}\n
+\n
+\t\tif ( !toHide.length && !toShow.length ) {\n
+\t\t\t$.error( "jQuery UI Tabs: Mismatching fragment identifier." );\n
+\t\t}\n
+\n
+\t\tif ( toShow.length ) {\n
+\t\t\tthis.load( this.tabs.index( tab ), event );\n
+\t\t}\n
+\t\tthis._toggle( event, eventData );\n
+\t},\n
+\n
+\t// handles show/hide for selecting tabs\n
+\t_toggle: function( event, eventData ) {\n
+\t\tvar that = this,\n
+\t\t\ttoShow = eventData.newPanel,\n
+\t\t\ttoHide = eventData.oldPanel;\n
+\n
+\t\tthis.running = true;\n
+\n
+\t\tfunction complete() {\n
+\t\t\tthat.running = false;\n
+\t\t\tthat._trigger( "activate", event, eventData );\n
+\t\t}\n
+\n
+\t\tfunction show() {\n
+\t\t\teventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );\n
+\n
+\t\t\tif ( toShow.length && that.options.show ) {\n
+\t\t\t\tthat._show( toShow, that.options.show, complete );\n
+\t\t\t} else {\n
+\t\t\t\ttoShow.show();\n
+\t\t\t\tcomplete();\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\t// start out by hiding, then showing, then completing\n
+\t\tif ( toHide.length && this.options.hide ) {\n
+\t\t\tthis._hide( toHide, this.options.hide, function() {\n
+\t\t\t\teventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );\n
+\t\t\t\tshow();\n
+\t\t\t});\n
+\t\t} else {\n
+\t\t\teventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );\n
+\t\t\ttoHide.hide();\n
+\t\t\tshow();\n
+\t\t}\n
+\n
+\t\ttoHide.attr({\n
+\t\t\t"aria-expanded": "false",\n
+\t\t\t"aria-hidden": "true"\n
+\t\t});\n
+\t\teventData.oldTab.attr( "aria-selected", "false" );\n
+\t\t// If we\'re switching tabs, remove the old tab from the tab order.\n
+\t\t// If we\'re opening from collapsed state, remove the previous tab from the tab order.\n
+\t\t// If we\'re collapsing, then keep the collapsing tab in the tab order.\n
+\t\tif ( toShow.length && toHide.length ) {\n
+\t\t\teventData.oldTab.attr( "tabIndex", -1 );\n
+\t\t} else if ( toShow.length ) {\n
+\t\t\tthis.tabs.filter(function() {\n
+\t\t\t\treturn $( this ).attr( "tabIndex" ) === 0;\n
+\t\t\t})\n
+\t\t\t.attr( "tabIndex", -1 );\n
+\t\t}\n
+\n
+\t\ttoShow.attr({\n
+\t\t\t"aria-expanded": "true",\n
+\t\t\t"aria-hidden": "false"\n
+\t\t});\n
+\t\teventData.newTab.attr({\n
+\t\t\t"aria-selected": "true",\n
+\t\t\ttabIndex: 0\n
+\t\t});\n
+\t},\n
+\n
+\t_activate: function( index ) {\n
+\t\tvar anchor,\n
+\t\t\tactive = this._findActive( index );\n
+\n
+\t\t// trying to activate the already active panel\n
+\t\tif ( active[ 0 ] === this.active[ 0 ] ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\t// trying to collapse, simulate a click on the current active header\n
+\t\tif ( !active.length ) {\n
+\t\t\tactive = this.active;\n
+\t\t}\n
+\n
+\t\tanchor = active.find( ".ui-tabs-anchor" )[ 0 ];\n
+\t\tthis._eventHandler({\n
+\t\t\ttarget: anchor,\n
+\t\t\tcurrentTarget: anchor,\n
+\t\t\tpreventDefault: $.noop\n
+\t\t});\n
+\t},\n
+\n
+\t_findActive: function( index ) {\n
+\t\treturn index === false ? $() : this.tabs.eq( index );\n
+\t},\n
+\n
+\t_getIndex: function( index ) {\n
+\t\t// meta-function to give users option to provide a href string instead of a numerical index.\n
+\t\tif ( typeof index === "string" ) {\n
+\t\t\tindex = this.anchors.index( this.anchors.filter( "[href$=\'" + index + "\']" ) );\n
+\t\t}\n
+\n
+\t\treturn index;\n
+\t},\n
+\n
+\t_destroy: function() {\n
+\t\tif ( this.xhr ) {\n
+\t\t\tthis.xhr.abort();\n
+\t\t}\n
+\n
+\t\tthis.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );\n
+\n
+\t\tthis.tablist\n
+\t\t\t.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )\n
+\t\t\t.removeAttr( "role" );\n
+\n
+\t\tthis.anchors\n
+\t\t\t.removeClass( "ui-tabs-anchor" )\n
+\t\t\t.removeAttr( "role" )\n
+\t\t\t.removeAttr( "tabIndex" )\n
+\t\t\t.removeUniqueId();\n
+\n
+\t\tthis.tabs.add( this.panels ).each(function() {\n
+\t\t\tif ( $.data( this, "ui-tabs-destroy" ) ) {\n
+\t\t\t\t$( this ).remove();\n
+\t\t\t} else {\n
+\t\t\t\t$( this )\n
+\t\t\t\t\t.removeClass( "ui-state-default ui-state-active ui-state-disabled " +\n
+\t\t\t\t\t\t"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )\n
+\t\t\t\t\t.removeAttr( "tabIndex" )\n
+\t\t\t\t\t.removeAttr( "aria-live" )\n
+\t\t\t\t\t.removeAttr( "aria-busy" )\n
+\t\t\t\t\t.removeAttr( "aria-selected" )\n
+\t\t\t\t\t.removeAttr( "aria-labelledby" )\n
+\t\t\t\t\t.removeAttr( "aria-hidden" )\n
+\t\t\t\t\t.removeAttr( "aria-expanded" )\n
+\t\t\t\t\t.removeAttr( "role" );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tthis.tabs.each(function() {\n
+\t\t\tvar li = $( this ),\n
+\t\t\t\tprev = li.data( "ui-tabs-aria-controls" );\n
+\t\t\tif ( prev ) {\n
+\t\t\t\tli\n
+\t\t\t\t\t.attr( "aria-controls", prev )\n
+\t\t\t\t\t.removeData( "ui-tabs-aria-controls" );\n
+\t\t\t} else {\n
+\t\t\t\tli.removeAttr( "aria-controls" );\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tthis.panels.show();\n
+\n
+\t\tif ( this.options.heightStyle !== "content" ) {\n
+\t\t\tthis.panels.css( "height", "" );\n
+\t\t}\n
+\t},\n
+\n
+\tenable: function( index ) {\n
+\t\tvar disabled = this.options.disabled;\n
+\t\tif ( disabled === false ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( index === undefined ) {\n
+\t\t\tdisabled = false;\n
+\t\t} else {\n
+\t\t\tindex = this._getIndex( index );\n
+\t\t\tif ( $.isArray( disabled ) ) {\n
+\t\t\t\tdisabled = $.map( disabled, function( num ) {\n
+\t\t\t\t\treturn num !== index ? num : null;\n
+\t\t\t\t});\n
+\t\t\t} else {\n
+\t\t\t\tdisabled = $.map( this.tabs, function( li, num ) {\n
+\t\t\t\t\treturn num !== index ? num : null;\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t}\n
+\t\tthis._setupDisabled( disabled );\n
+\t},\n
+\n
+\tdisable: function( index ) {\n
+\t\tvar disabled = this.options.disabled;\n
+\t\tif ( disabled === true ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tif ( index === undefined ) {\n
+\t\t\tdisabled = true;\n
+\t\t} else {\n
+\t\t\tindex = this._getIndex( index );\n
+\t\t\tif ( $.inArray( index, disabled ) !== -1 ) {\n
+\t\t\t\treturn;\n
+\t\t\t}\n
+\t\t\tif ( $.isArray( disabled ) ) {\n
+\t\t\t\tdisabled = $.merge( [ index ], disabled ).sort();\n
+\t\t\t} else {\n
+\t\t\t\tdisabled = [ index ];\n
+\t\t\t}\n
+\t\t}\n
+\t\tthis._setupDisabled( disabled );\n
+\t},\n
+\n
+\tload: function( index, event ) {\n
+\t\tindex = this._getIndex( index );\n
+\t\tvar that = this,\n
+\t\t\ttab = this.tabs.eq( index ),\n
+\t\t\tanchor = tab.find( ".ui-tabs-anchor" ),\n
+\t\t\tpanel = this._getPanelForTab( tab ),\n
+\t\t\teventData = {\n
+\t\t\t\ttab: tab,\n
+\t\t\t\tpanel: panel\n
+\t\t\t};\n
+\n
+\t\t// not remote\n
+\t\tif ( isLocal( anchor[ 0 ] ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tthis.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );\n
+\n
+\t\t// support: jQuery <1.8\n
+\t\t// jQuery <1.8 returns false if the request is canceled in beforeSend,\n
+\t\t// but as of 1.8, $.ajax() always returns a jqXHR object.\n
+\t\tif ( this.xhr && this.xhr.statusText !== "canceled" ) {\n
+\t\t\ttab.addClass( "ui-tabs-loading" );\n
+\t\t\tpanel.attr( "aria-busy", "true" );\n
+\n
+\t\t\tthis.xhr\n
+\t\t\t\t.success(function( response ) {\n
+\t\t\t\t\t// support: jQuery <1.8\n
+\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n
+\t\t\t\t\tsetTimeout(function() {\n
+\t\t\t\t\t\tpanel.html( response );\n
+\t\t\t\t\t\tthat._trigger( "load", event, eventData );\n
+\t\t\t\t\t}, 1 );\n
+\t\t\t\t})\n
+\t\t\t\t.complete(function( jqXHR, status ) {\n
+\t\t\t\t\t// support: jQuery <1.8\n
+\t\t\t\t\t// http://bugs.jquery.com/ticket/11778\n
+\t\t\t\t\tsetTimeout(function() {\n
+\t\t\t\t\t\tif ( status === "abort" ) {\n
+\t\t\t\t\t\t\tthat.panels.stop( false, true );\n
+\t\t\t\t\t\t}\n
+\n
+\t\t\t\t\t\ttab.removeClass( "ui-tabs-loading" );\n
+\t\t\t\t\t\tpanel.removeAttr( "aria-busy" );\n
+\n
+\t\t\t\t\t\tif ( jqXHR === that.xhr ) {\n
+\t\t\t\t\t\t\tdelete that.xhr;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}, 1 );\n
+\t\t\t\t});\n
+\t\t}\n
+\t},\n
+\n
+\t_ajaxSettings: function( anchor, event, eventData ) {\n
+\t\tvar that = this;\n
+\t\treturn {\n
+\t\t\turl: anchor.attr( "href" ),\n
+\t\t\tbeforeSend: function( jqXHR, settings ) {\n
+\t\t\t\treturn that._trigger( "beforeLoad", event,\n
+\t\t\t\t\t$.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );\n
+\t\t\t}\n
+\t\t};\n
+\t},\n
+\n
+\t_getPanelForTab: function( tab ) {\n
+\t\tvar id = $( tab ).attr( "aria-controls" );\n
+\t\treturn this.element.find( this._sanitizeSelector( "#" + id ) );\n
+\t}\n
+});\n
+\n
+})( jQuery );\n
+(function( $, undefined ) {\n
+\n
+})( jQuery );\n
+\n
+(function( $, window ) {\n
+\n
+\t$.mobile.iosorientationfixEnabled = true;\n
+\n
+\t// This fix addresses an iOS bug, so return early if the UA claims it\'s something else.\n
+\tvar ua = navigator.userAgent,\n
+\t\tzoom,\n
+\t\tevt, x, y, z, aig;\n
+\tif ( !( /iPhone|iPad|iPod/.test( navigator.platform ) && /OS [1-5]_[0-9_]* like Mac OS X/i.test( ua ) && ua.indexOf( "AppleWebKit" ) > -1 ) ){\n
+\t\t$.mobile.iosorientationfixEnabled = false;\n
+\t\treturn;\n
+\t}\n
+\n
+\tzoom = $.mobile.zoom;\n
+\n
+\tfunction checkTilt( e ) {\n
+\t\tevt = e.originalEvent;\n
+\t\taig = evt.accelerationIncludingGravity;\n
+\n
+\t\tx = Math.abs( aig.x );\n
+\t\ty = Math.abs( aig.y );\n
+\t\tz = Math.abs( aig.z );\n
+\n
+\t\t// If portrait orientation and in one of the danger zones\n
+\t\tif ( !window.orientation && ( x > 7 || ( ( z > 6 && y < 8 || z < 8 && y > 6 ) && x > 5 ) ) ) {\n
+\t\t\t\tif ( zoom.enabled ) {\n
+\t\t\t\t\tzoom.disable();\n
+\t\t\t\t}\n
+\t\t}\telse if ( !zoom.enabled ) {\n
+\t\t\t\tzoom.enable();\n
+\t\t}\n
+\t}\n
+\n
+\t$.mobile.document.on( "mobileinit", function() {\n
+\t\tif ( $.mobile.iosorientationfixEnabled ){\n
+\t\t\t$.mobile.window\n
+\t\t\t\t.bind( "orientationchange.iosorientationfix", zoom.enable )\n
+\t\t\t\t.bind( "devicemotion.iosorientationfix", checkTilt );\n
+\t\t}\n
+\t});\n
+\n
+}( jQuery, this ));\n
+\n
+(function( $, window, undefined ) {\n
+\tvar\t$html = $( "html" ),\n
+\t\t$window = $.mobile.window;\n
+\n
+\t//remove initial build class (only present on first pageshow)\n
+\tfunction hideRenderingClass() {\n
+\t\t$html.removeClass( "ui-mobile-rendering" );\n
+\t}\n
+\n
+\t// trigger mobileinit event - useful hook for configuring $.mobile settings before they\'re used\n
+\t$( window.document ).trigger( "mobileinit" );\n
+\n
+\t// support conditions\n
+\t// if device support condition(s) aren\'t met, leave things as they are -> a basic, usable experience,\n
+\t// otherwise, proceed with the enhancements\n
+\tif ( !$.mobile.gradeA() ) {\n
+\t\treturn;\n
+\t}\n
+\n
+\t// override ajaxEnabled on platforms that have known conflicts with hash history updates\n
+\t// or generally work better browsing in regular http for full page refreshes (BB5, Opera Mini)\n
+\tif ( $.mobile.ajaxBlacklist ) {\n
+\t\t$.mobile.ajaxEnabled = false;\n
+\t}\n
+\n
+\t// Add mobile, initial load "rendering" classes to docEl\n
+\t$html.addClass( "ui-mobile ui-mobile-rendering" );\n
+\n
+\t// This is a fallback. If anything goes wrong (JS errors, etc), or events don\'t fire,\n
+\t// this ensures the rendering class is removed after 5 seconds, so content is visible and accessible\n
+\tsetTimeout( hideRenderingClass, 5000 );\n
+\n
+\t$.extend( $.mobile, {\n
+\t\t// find and enhance the pages in the dom and transition to the first page.\n
+\t\tinitializePage: function() {\n
+\t\t\t// find present pages\n
+\t\t\tvar path = $.mobile.path,\n
+\t\t\t\t$pages = $( ":jqmData(role=\'page\'), :jqmData(role=\'dialog\')" ),\n
+\t\t\t\thash = path.stripHash( path.stripQueryParams(path.parseLocation().hash) ),\n
+\t\t\t\thashPage = document.getElementById( hash );\n
+\n
+\t\t\t// if no pages are found, create one with body\'s inner html\n
+\t\t\tif ( !$pages.length ) {\n
+\t\t\t\t$pages = $( "body" ).wrapInner( "<div data-" + $.mobile.ns + "role=\'page\'></div>" ).children( 0 );\n
+\t\t\t}\n
+\n
+\t\t\t// add dialogs, set data-url attrs\n
+\t\t\t$pages.each(function() {\n
+\t\t\t\tvar $this = $( this );\n
+\n
+\t\t\t\t// unless the data url is already set set it to the pathname\n
+\t\t\t\tif ( !$this[ 0 ].getAttribute( "data-" + $.mobile.ns + "url" ) ) {\n
+\t\t\t\t\t$this.attr( "data-" + $.mobile.ns + "url", $this.attr( "id" ) || location.pathname + location.search );\n
+\t\t\t\t}\n
+\t\t\t});\n
+\n
+\t\t\t// define first page in dom case one backs out to the directory root (not always the first page visited, but defined as fallback)\n
+\t\t\t$.mobile.firstPage = $pages.first();\n
+\n
+\t\t\t// define page container\n
+\t\t\t$.mobile.pageContainer = $.mobile.firstPage\n
+\t\t\t\t.parent()\n
+\t\t\t\t.addClass( "ui-mobile-viewport" )\n
+\t\t\t\t.content();\n
+\n
+\t\t\t// initialize navigation events now, after mobileinit has occurred and the page container\n
+\t\t\t// has been created but before the rest of the library is alerted to that fact\n
+\t\t\t$.mobile.navreadyDeferred.resolve();\n
+\n
+\t\t\t// alert listeners that the pagecontainer has been determined for binding\n
+\t\t\t// to events triggered on it\n
+\t\t\t$window.trigger( "pagecontainercreate" );\n
+\n
+\t\t\t// cue page loading message\n
+\t\t\t$.mobile.showPageLoadingMsg();\n
+\n
+\t\t\t//remove initial build class (only present on first pageshow)\n
+\t\t\thideRenderingClass();\n
+\n
+\t\t\t// if hashchange listening is disabled, there\'s no hash deeplink,\n
+\t\t\t// the hash is not valid (contains more than one # or does not start with #)\n
+\t\t\t// or there is no page with that hash, change to the first page in the DOM\n
+\t\t\t// Remember, however, that the hash can also be a path!\n
+\t\t\tif ( ! ( $.mobile.hashListeningEnabled &&\n
+\t\t\t\t$.mobile.path.isHashValid( location.hash ) &&\n
+\t\t\t\t( $( hashPage ).is( ":jqmData(role=\'page\')" ) ||\n
+\t\t\t\t\t$.mobile.path.isPath( hash ) ||\n
+\t\t\t\t\thash === $.mobile.dialogHashKey ) ) ) {\n
+\n
+\t\t\t\t// Store the initial destination\n
+\t\t\t\tif ( $.mobile.path.isHashValid( location.hash ) ) {\n
+\t\t\t\t\t$.mobile.urlHistory.initialDst = hash.replace( "#", "" );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t// make sure to set initial popstate state if it exists\n
+\t\t\t\t// so that navigation back to the initial page works properly\n
+\t\t\t\tif ( $.event.special.navigate.isPushStateEnabled() ) {\n
+\t\t\t\t\t$.mobile.navigate.navigator.squash( path.parseLocation().href );\n
+\t\t\t\t}\n
+\n
+\t\t\t\t$.mobile.changePage( $.mobile.firstPage, {\n
+\t\t\t\t\ttransition: "none",\n
+\t\t\t\t\treverse: true,\n
+\t\t\t\t\tchangeHash: false,\n
+\t\t\t\t\tfromHashChange: true\n
+\t\t\t\t});\n
+\t\t\t} else {\n
+\t\t\t\t// trigger hashchange or navigate to squash and record the correct\n
+\t\t\t\t// history entry for an initial hash path\n
+\t\t\t\tif ( !$.event.special.navigate.isPushStateEnabled() ) {\n
+\t\t\t\t\t$window.trigger( "hashchange", [true] );\n
+\t\t\t\t} else {\n
+\t\t\t\t\t// TODO figure out how to simplify this interaction with the initial history entry\n
+\t\t\t\t\t// at the bottom js/navigate/navigate.js\n
+\t\t\t\t\t$.mobile.navigate.history.stack = [];\n
+\t\t\t\t\t$.mobile.navigate( $.mobile.path.isPath( location.hash ) ? location.hash : location.href );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t});\n
+\n
+\t$(function() {\n
+\t\t//Run inlineSVG support test\n
+\t\t$.support.inlineSVG();\n
+\t\t\n
+\t\t// check which scrollTop value should be used by scrolling to 1 immediately at domready\n
+\t\t// then check what the scroll top is. Android will report 0... others 1\n
+\t\t// note that this initial scroll won\'t hide the address bar. It\'s just for the check.\n
+\t\t\n
+\t\t// hide iOS browser chrome on load if hideUrlBar is true this is to try and do it as soon as possible\n
+\t\tif ( $.mobile.hideUrlBar ) {\n
+\t\t\twindow.scrollTo( 0, 1 );\n
+\t\t}\n
+\n
+\t\t// if defaultHomeScroll hasn\'t been set yet, see if scrollTop is 1\n
+\t\t// it should be 1 in most browsers, but android treats 1 as 0 (for hiding addr bar)\n
+\t\t// so if it\'s 1, use 0 from now on\n
+\t\t$.mobile.defaultHomeScroll = ( !$.support.scrollTop || $.mobile.window.scrollTop() === 1 ) ? 0 : 1;\n
+\n
+\t\t//dom-ready inits\n
+\t\tif ( $.mobile.autoInitializePage ) {\n
+\t\t\t$.mobile.initializePage();\n
+\t\t}\n
+\n
+\t\t// window load event\n
+\t\t// hide iOS browser chrome on load if hideUrlBar is true this is as fall back incase we were too early before\n
+\t\tif ( $.mobile.hideUrlBar ) {\n
+\t\t\t$window.load( $.mobile.silentScroll );\n
+\t\t}\n
+\n
+\t\tif ( !$.support.cssPointerEvents ) {\n
+\t\t\t// IE and Opera don\'t support CSS pointer-events: none that we use to disable link-based buttons\n
+\t\t\t// by adding the \'ui-disabled\' class to them. Using a JavaScript workaround for those browser.\n
+\t\t\t// https://github.com/jquery/jquery-mobile/issues/3558\n
+\n
+\t\t\t$.mobile.document.delegate( ".ui-disabled", "vclick",\n
+\t\t\t\tfunction( e ) {\n
+\t\t\t\t\te.preventDefault();\n
+\t\t\t\t\te.stopImmediatePropagation();\n
+\t\t\t\t}\n
+\t\t\t);\n
+\t\t}\n
+\t});\n
+}( jQuery, this ));\n
+\n
+\n
+}));\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>next</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/moment.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/moment.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2a05ec873d68f35e5d05e767a3726e066176b397
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/moment.js.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681770.68</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>moment.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>122254</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+//! moment.js\n
+//! version : 2.5.1\n
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors\n
+//! license : MIT\n
+//! momentjs.com\n
+(function(a){function b(){return{empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1}}function c(a,b){return function(c){return k(a.call(this,c),b)}}function d(a,b){return function(c){return this.lang().ordinal(a.call(this,c),b)}}function e(){}function f(a){w(a),h(this,a)}function g(a){var b=q(a),c=b.year||0,d=b.month||0,e=b.week||0,f=b.day||0,g=b.hour||0,h=b.minute||0,i=b.second||0,j=b.millisecond||0;this._milliseconds=+j+1e3*i+6e4*h+36e5*g,this._days=+f+7*e,this._months=+d+12*c,this._data={},this._bubble()}function h(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c]);return b.hasOwnProperty("toString")&&(a.toString=b.toString),b.hasOwnProperty("valueOf")&&(a.valueOf=b.valueOf),a}function i(a){var b,c={};for(b in a)a.hasOwnProperty(b)&&qb.hasOwnProperty(b)&&(c[b]=a[b]);return c}function j(a){return 0>a?Math.ceil(a):Math.floor(a)}function k(a,b,c){for(var d=""+Math.abs(a),e=a>=0;d.length<b;)d="0"+d;return(e?c?"+":"":"-")+d}function l(a,b,c,d){var e,f,g=b._milliseconds,h=b._days,i=b._months;g&&a._d.setTime(+a._d+g*c),(h||i)&&(e=a.minute(),f=a.hour()),h&&a.date(a.date()+h*c),i&&a.month(a.month()+i*c),g&&!d&&db.updateOffset(a),(h||i)&&(a.minute(e),a.hour(f))}function m(a){return"[object Array]"===Object.prototype.toString.call(a)}function n(a){return"[object Date]"===Object.prototype.toString.call(a)||a instanceof Date}function o(a,b,c){var d,e=Math.min(a.length,b.length),f=Math.abs(a.length-b.length),g=0;for(d=0;e>d;d++)(c&&a[d]!==b[d]||!c&&s(a[d])!==s(b[d]))&&g++;return g+f}function p(a){if(a){var b=a.toLowerCase().replace(/(.)s$/,"$1");a=Tb[a]||Ub[b]||b}return a}function q(a){var b,c,d={};for(c in a)a.hasOwnProperty(c)&&(b=p(c),b&&(d[b]=a[c]));return d}function r(b){var c,d;if(0===b.indexOf("week"))c=7,d="day";else{if(0!==b.indexOf("month"))return;c=12,d="month"}db[b]=function(e,f){var g,h,i=db.fn._lang[b],j=[];if("number"==typeof e&&(f=e,e=a),h=function(a){var b=db().utc().set(d,a);return i.call(db.fn._lang,b,e||"")},null!=f)return h(f);for(g=0;c>g;g++)j.push(h(g));return j}}function s(a){var b=+a,c=0;return 0!==b&&isFinite(b)&&(c=b>=0?Math.floor(b):Math.ceil(b)),c}function t(a,b){return new Date(Date.UTC(a,b+1,0)).getUTCDate()}function u(a){return v(a)?366:365}function v(a){return a%4===0&&a%100!==0||a%400===0}function w(a){var b;a._a&&-2===a._pf.overflow&&(b=a._a[jb]<0||a._a[jb]>11?jb:a._a[kb]<1||a._a[kb]>t(a._a[ib],a._a[jb])?kb:a._a[lb]<0||a._a[lb]>23?lb:a._a[mb]<0||a._a[mb]>59?mb:a._a[nb]<0||a._a[nb]>59?nb:a._a[ob]<0||a._a[ob]>999?ob:-1,a._pf._overflowDayOfYear&&(ib>b||b>kb)&&(b=kb),a._pf.overflow=b)}function x(a){return null==a._isValid&&(a._isValid=!isNaN(a._d.getTime())&&a._pf.overflow<0&&!a._pf.empty&&!a._pf.invalidMonth&&!a._pf.nullInput&&!a._pf.invalidFormat&&!a._pf.userInvalidated,a._strict&&(a._isValid=a._isValid&&0===a._pf.charsLeftOver&&0===a._pf.unusedTokens.length)),a._isValid}function y(a){return a?a.toLowerCase().replace("_","-"):a}function z(a,b){return b._isUTC?db(a).zone(b._offset||0):db(a).local()}function A(a,b){return b.abbr=a,pb[a]||(pb[a]=new e),pb[a].set(b),pb[a]}function B(a){delete pb[a]}function C(a){var b,c,d,e,f=0,g=function(a){if(!pb[a]&&rb)try{require("./lang/"+a)}catch(b){}return pb[a]};if(!a)return db.fn._lang;if(!m(a)){if(c=g(a))return c;a=[a]}for(;f<a.length;){for(e=y(a[f]).split("-"),b=e.length,d=y(a[f+1]),d=d?d.split("-"):null;b>0;){if(c=g(e.slice(0,b).join("-")))return c;if(d&&d.length>=b&&o(e,d,!0)>=b-1)break;b--}f++}return db.fn._lang}function D(a){return a.match(/\\[[\\s\\S]/)?a.replace(/^\\[|\\]$/g,""):a.replace(/\\\\/g,"")}function E(a){var b,c,d=a.match(vb);for(b=0,c=d.length;c>b;b++)d[b]=Yb[d[b]]?Yb[d[b]]:D(d[b]);return function(e){var f="";for(b=0;c>b;b++)f+=d[b]instanceof Function?d[b].call(e,a):d[b];return f}}function F(a,b){return a.isValid()?(b=G(b,a.lang()),Vb[b]||(Vb[b]=E(b)),Vb[b](a)):a.lang().invalidDate()}function G(a,b){function c(a){return b.longDateFormat(a)||a}var d=5;for(wb.lastIndex=0;d>=0&&wb.test(a);)a=a.replace(wb,c),wb.lastIndex=0,d-=1;return a}function H(a,b){var c,d=b._strict;switch(a){case"DDDD":return Ib;case"YYYY":case"GGGG":case"gggg":return d?Jb:zb;case"Y":case"G":case"g":return Lb;case"YYYYYY":case"YYYYY":case"GGGGG":case"ggggg":return d?Kb:Ab;case"S":if(d)return Gb;case"SS":if(d)return Hb;case"SSS":if(d)return Ib;case"DDD":return yb;case"MMM":case"MMMM":case"dd":case"ddd":case"dddd":return Cb;case"a":case"A":return C(b._l)._meridiemParse;case"X":return Fb;case"Z":case"ZZ":return Db;case"T":return Eb;case"SSSS":return Bb;case"MM":case"DD":case"YY":case"GG":case"gg":case"HH":case"hh":case"mm":case"ss":case"ww":case"WW":return d?Hb:xb;case"M":case"D":case"d":case"H":case"h":case"m":case"s":case"w":case"W":case"e":case"E":return xb;default:return c=new RegExp(P(O(a.replace("\\\\","")),"i"))}}function I(a){a=a||"";var b=a.match(Db)||[],c=b[b.length-1]||[],d=(c+"").match(Qb)||["-",0,0],e=+(60*d[1])+s(d[2]);return"+"===d[0]?-e:e}function J(a,b,c){var d,e=c._a;switch(a){case"M":case"MM":null!=b&&(e[jb]=s(b)-1);break;case"MMM":case"MMMM":d=C(c._l).monthsParse(b),null!=d?e[jb]=d:c._pf.invalidMonth=b;break;case"D":case"DD":null!=b&&(e[kb]=s(b));break;case"DDD":case"DDDD":null!=b&&(c._dayOfYear=s(b));break;case"YY":e[ib]=s(b)+(s(b)>68?1900:2e3);break;case"YYYY":case"YYYYY":case"YYYYYY":e[ib]=s(b);break;case"a":case"A":c._isPm=C(c._l).isPM(b);break;case"H":case"HH":case"h":case"hh":e[lb]=s(b);break;case"m":case"mm":e[mb]=s(b);break;case"s":case"ss":e[nb]=s(b);break;case"S":case"SS":case"SSS":case"SSSS":e[ob]=s(1e3*("0."+b));break;case"X":c._d=new Date(1e3*parseFloat(b));break;case"Z":case"ZZ":c._useUTC=!0,c._tzm=I(b);break;case"w":case"ww":case"W":case"WW":case"d":case"dd":case"ddd":case"dddd":case"e":case"E":a=a.substr(0,1);case"gg":case"gggg":case"GG":case"GGGG":case"GGGGG":a=a.substr(0,2),b&&(c._w=c._w||{},c._w[a]=b)}}function K(a){var b,c,d,e,f,g,h,i,j,k,l=[];if(!a._d){for(d=M(a),a._w&&null==a._a[kb]&&null==a._a[jb]&&(f=function(b){var c=parseInt(b,10);return b?b.length<3?c>68?1900+c:2e3+c:c:null==a._a[ib]?db().weekYear():a._a[ib]},g=a._w,null!=g.GG||null!=g.W||null!=g.E?h=Z(f(g.GG),g.W||1,g.E,4,1):(i=C(a._l),j=null!=g.d?V(g.d,i):null!=g.e?parseInt(g.e,10)+i._week.dow:0,k=parseInt(g.w,10)||1,null!=g.d&&j<i._week.dow&&k++,h=Z(f(g.gg),k,j,i._week.doy,i._week.dow)),a._a[ib]=h.year,a._dayOfYear=h.dayOfYear),a._dayOfYear&&(e=null==a._a[ib]?d[ib]:a._a[ib],a._dayOfYear>u(e)&&(a._pf._overflowDayOfYear=!0),c=U(e,0,a._dayOfYear),a._a[jb]=c.getUTCMonth(),a._a[kb]=c.getUTCDate()),b=0;3>b&&null==a._a[b];++b)a._a[b]=l[b]=d[b];for(;7>b;b++)a._a[b]=l[b]=null==a._a[b]?2===b?1:0:a._a[b];l[lb]+=s((a._tzm||0)/60),l[mb]+=s((a._tzm||0)%60),a._d=(a._useUTC?U:T).apply(null,l)}}function L(a){var b;a._d||(b=q(a._i),a._a=[b.year,b.month,b.day,b.hour,b.minute,b.second,b.millisecond],K(a))}function M(a){var b=new Date;return a._useUTC?[b.getUTCFullYear(),b.getUTCMonth(),b.getUTCDate()]:[b.getFullYear(),b.getMonth(),b.getDate()]}function N(a){a._a=[],a._pf.empty=!0;var b,c,d,e,f,g=C(a._l),h=""+a._i,i=h.length,j=0;for(d=G(a._f,g).match(vb)||[],b=0;b<d.length;b++)e=d[b],c=(h.match(H(e,a))||[])[0],c&&(f=h.substr(0,h.indexOf(c)),f.length>0&&a._pf.unusedInput.push(f),h=h.slice(h.indexOf(c)+c.length),j+=c.length),Yb[e]?(c?a._pf.empty=!1:a._pf.unusedTokens.push(e),J(e,c,a)):a._strict&&!c&&a._pf.unusedTokens.push(e);a._pf.charsLeftOver=i-j,h.length>0&&a._pf.unusedInput.push(h),a._isPm&&a._a[lb]<12&&(a._a[lb]+=12),a._isPm===!1&&12===a._a[lb]&&(a._a[lb]=0),K(a),w(a)}function O(a){return a.replace(/\\\\(\\[)|\\\\(\\])|\\[([^\\]\\[]*)\\]|\\\\(.)/g,function(a,b,c,d,e){return b||c||d||e})}function P(a){return a.replace(/[-\\/\\\\^$*+?.()|[\\]{}]/g,"\\\\$&")}function Q(a){var c,d,e,f,g;if(0===a._f.length)return a._pf.invalidFormat=!0,a._d=new Date(0/0),void 0;for(f=0;f<a._f.length;f++)g=0,c=h({},a),c._pf=b(),c._f=a._f[f],N(c),x(c)&&(g+=c._pf.charsLeftOver,g+=10*c._pf.unusedTokens.length,c._pf.score=g,(null==e||e>g)&&(e=g,d=c));h(a,d||c)}function R(a){var b,c,d=a._i,e=Mb.exec(d);if(e){for(a._pf.iso=!0,b=0,c=Ob.length;c>b;b++)if(Ob[b][1].exec(d)){a._f=Ob[b][0]+(e[6]||" ");break}for(b=0,c=Pb.length;c>b;b++)if(Pb[b][1].exec(d)){a._f+=Pb[b][0];break}d.match(Db)&&(a._f+="Z"),N(a)}else a._d=new Date(d)}function S(b){var c=b._i,d=sb.exec(c);c===a?b._d=new Date:d?b._d=new Date(+d[1]):"string"==typeof c?R(b):m(c)?(b._a=c.slice(0),K(b)):n(c)?b._d=new Date(+c):"object"==typeof c?L(b):b._d=new Date(c)}function T(a,b,c,d,e,f,g){var h=new Date(a,b,c,d,e,f,g);return 1970>a&&h.setFullYear(a),h}function U(a){var b=new Date(Date.UTC.apply(null,arguments));return 1970>a&&b.setUTCFullYear(a),b}function V(a,b){if("string"==typeof a)if(isNaN(a)){if(a=b.weekdaysParse(a),"number"!=typeof a)return null}else a=parseInt(a,10);return a}function W(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function X(a,b,c){var d=hb(Math.abs(a)/1e3),e=hb(d/60),f=hb(e/60),g=hb(f/24),h=hb(g/365),i=45>d&&["s",d]||1===e&&["m"]||45>e&&["mm",e]||1===f&&["h"]||22>f&&["hh",f]||1===g&&["d"]||25>=g&&["dd",g]||45>=g&&["M"]||345>g&&["MM",hb(g/30)]||1===h&&["y"]||["yy",h];return i[2]=b,i[3]=a>0,i[4]=c,W.apply({},i)}function Y(a,b,c){var d,e=c-b,f=c-a.day();return f>e&&(f-=7),e-7>f&&(f+=7),d=db(a).add("d",f),{week:Math.ceil(d.dayOfYear()/7),year:d.year()}}function Z(a,b,c,d,e){var f,g,h=U(a,0,1).getUTCDay();return c=null!=c?c:e,f=e-h+(h>d?7:0)-(e>h?7:0),g=7*(b-1)+(c-e)+f+1,{year:g>0?a:a-1,dayOfYear:g>0?g:u(a-1)+g}}function $(a){var b=a._i,c=a._f;return null===b?db.invalid({nullInput:!0}):("string"==typeof b&&(a._i=b=C().preparse(b)),db.isMoment(b)?(a=i(b),a._d=new Date(+b._d)):c?m(c)?Q(a):N(a):S(a),new f(a))}function _(a,b){db.fn[a]=db.fn[a+"s"]=function(a){var c=this._isUTC?"UTC":"";return null!=a?(this._d["set"+c+b](a),db.updateOffset(this),this):this._d["get"+c+b]()}}function ab(a){db.duration.fn[a]=function(){return this._data[a]}}function bb(a,b){db.duration.fn["as"+a]=function(){return+this/b}}function cb(a){var b=!1,c=db;"undefined"==typeof ender&&(a?(gb.moment=function(){return!b&&console&&console.warn&&(b=!0,console.warn("Accessing Moment through the global scope is deprecated, and will be removed in an upcoming release.")),c.apply(null,arguments)},h(gb.moment,c)):gb.moment=db)}for(var db,eb,fb="2.5.1",gb=this,hb=Math.round,ib=0,jb=1,kb=2,lb=3,mb=4,nb=5,ob=6,pb={},qb={_isAMomentObject:null,_i:null,_f:null,_l:null,_strict:null,_isUTC:null,_offset:null,_pf:null,_lang:null},rb="undefined"!=typeof module&&module.exports&&"undefined"!=typeof require,sb=/^\\/?Date\\((\\-?\\d+)/i,tb=/(\\-)?(?:(\\d*)\\.)?(\\d+)\\:(\\d+)(?:\\:(\\d+)\\.?(\\d{3})?)?/,ub=/^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,vb=/(\\[[^\\[]*\\])|(\\\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,wb=/(\\[[^\\[]*\\])|(\\\\)?(LT|LL?L?L?|l{1,4})/g,xb=/\\d\\d?/,yb=/\\d{1,3}/,zb=/\\d{1,4}/,Ab=/[+\\-]?\\d{1,6}/,Bb=/\\d+/,Cb=/[0-9]*[\'a-z\\u00A0-\\u05FF\\u0700-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF]+|[\\u0600-\\u06FF\\/]+(\\s*?[\\u0600-\\u06FF]+){1,2}/i,Db=/Z|[\\+\\-]\\d\\d:?\\d\\d/gi,Eb=/T/i,Fb=/[\\+\\-]?\\d+(\\.\\d{1,3})?/,Gb=/\\d/,Hb=/\\d\\d/,Ib=/\\d{3}/,Jb=/\\d{4}/,Kb=/[+-]?\\d{6}/,Lb=/[+-]?\\d+/,Mb=/^\\s*(?:[+-]\\d{6}|\\d{4})-(?:(\\d\\d-\\d\\d)|(W\\d\\d$)|(W\\d\\d-\\d)|(\\d\\d\\d))((T| )(\\d\\d(:\\d\\d(:\\d\\d(\\.\\d+)?)?)?)?([\\+\\-]\\d\\d(?::?\\d\\d)?|\\s*Z)?)?$/,Nb="YYYY-MM-DDTHH:mm:ssZ",Ob=[["YYYYYY-MM-DD",/[+-]\\d{6}-\\d{2}-\\d{2}/],["YYYY-MM-DD",/\\d{4}-\\d{2}-\\d{2}/],["GGGG-[W]WW-E",/\\d{4}-W\\d{2}-\\d/],["GGGG-[W]WW",/\\d{4}-W\\d{2}/],["YYYY-DDD",/\\d{4}-\\d{3}/]],Pb=[["HH:mm:ss.SSSS",/(T| )\\d\\d:\\d\\d:\\d\\d\\.\\d{1,3}/],["HH:mm:ss",/(T| )\\d\\d:\\d\\d:\\d\\d/],["HH:mm",/(T| )\\d\\d:\\d\\d/],["HH",/(T| )\\d\\d/]],Qb=/([\\+\\-]|\\d\\d)/gi,Rb="Date|Hours|Minutes|Seconds|Milliseconds".split("|"),Sb={Milliseconds:1,Seconds:1e3,Minutes:6e4,Hours:36e5,Days:864e5,Months:2592e6,Years:31536e6},Tb={ms:"millisecond",s:"second",m:"minute",h:"hour",d:"day",D:"date",w:"week",W:"isoWeek",M:"month",y:"year",DDD:"dayOfYear",e:"weekday",E:"isoWeekday",gg:"weekYear",GG:"isoWeekYear"},Ub={dayofyear:"dayOfYear",isoweekday:"isoWeekday",isoweek:"isoWeek",weekyear:"weekYear",isoweekyear:"isoWeekYear"},Vb={},Wb="DDD w W M D d".split(" "),Xb="M D H h m s w W".split(" "),Yb={M:function(){return this.month()+1},MMM:function(a){return this.lang().monthsShort(this,a)},MMMM:function(a){return this.lang().months(this,a)},D:function(){return this.date()},DDD:function(){return this.dayOfYear()},d:function(){return this.day()},dd:function(a){return this.lang().weekdaysMin(this,a)},ddd:function(a){return this.lang().weekdaysShort(this,a)},dddd:function(a){return this.lang().weekdays(this,a)},w:function(){return this.week()},W:function(){return this.isoWeek()},YY:function(){return k(this.year()%100,2)},YYYY:function(){return k(this.year(),4)},YYYYY:function(){return k(this.year(),5)},YYYYYY:function(){var a=this.year(),b=a>=0?"+":"-";return b+k(Math.abs(a),6)},gg:function(){return k(this.weekYear()%100,2)},gggg:function(){return k(this.weekYear(),4)},ggggg:function(){return k(this.weekYear(),5)},GG:function(){return k(this.isoWeekYear()%100,2)},GGGG:function(){return k(this.isoWeekYear(),4)},GGGGG:function(){return k(this.isoWeekYear(),5)},e:function(){return this.weekday()},E:function(){return this.isoWeekday()},a:function(){return this.lang().meridiem(this.hours(),this.minutes(),!0)},A:function(){return this.lang().meridiem(this.hours(),this.minutes(),!1)},H:function(){return this.hours()},h:function(){return this.hours()%12||12},m:function(){return this.minutes()},s:function(){return this.seconds()},S:function(){return s(this.milliseconds()/100)},SS:function(){return k(s(this.milliseconds()/10),2)},SSS:function(){return k(this.milliseconds(),3)},SSSS:function(){return k(this.milliseconds(),3)},Z:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+k(s(a/60),2)+":"+k(s(a)%60,2)},ZZ:function(){var a=-this.zone(),b="+";return 0>a&&(a=-a,b="-"),b+k(s(a/60),2)+k(s(a)%60,2)},z:function(){return this.zoneAbbr()},zz:function(){return this.zoneName()},X:function(){return this.unix()},Q:function(){return this.quarter()}},Zb=["months","monthsShort","weekdays","weekdaysShort","weekdaysMin"];Wb.length;)eb=Wb.pop(),Yb[eb+"o"]=d(Yb[eb],eb);for(;Xb.length;)eb=Xb.pop(),Yb[eb+eb]=c(Yb[eb],2);for(Yb.DDDD=c(Yb.DDD,3),h(e.prototype,{set:function(a){var b,c;for(c in a)b=a[c],"function"==typeof b?this[c]=b:this["_"+c]=b},_months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),months:function(a){return this._months[a.month()]},_monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),monthsShort:function(a){return this._monthsShort[a.month()]},monthsParse:function(a){var b,c,d;for(this._monthsParse||(this._monthsParse=[]),b=0;12>b;b++)if(this._monthsParse[b]||(c=db.utc([2e3,b]),d="^"+this.months(c,"")+"|^"+this.monthsShort(c,""),this._monthsParse[b]=new RegExp(d.replace(".",""),"i")),this._monthsParse[b].test(a))return b},_weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdays:function(a){return this._weekdays[a.day()]},_weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysShort:function(a){return this._weekdaysShort[a.day()]},_weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),weekdaysMin:function(a){return this._weekdaysMin[a.day()]},weekdaysParse:function(a){var b,c,d;for(this._weekdaysParse||(this._weekdaysParse=[]),b=0;7>b;b++)if(this._weekdaysParse[b]||(c=db([2e3,1]).day(b),d="^"+this.weekdays(c,"")+"|^"+this.weekdaysShort(c,"")+"|^"+this.weekdaysMin(c,""),this._weekdaysParse[b]=new RegExp(d.replace(".",""),"i")),this._weekdaysParse[b].test(a))return b},_longDateFormat:{LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D YYYY",LLL:"MMMM D YYYY LT",LLLL:"dddd, MMMM D YYYY LT"},longDateFormat:function(a){var b=this._longDateFormat[a];return!b&&this._longDateFormat[a.toUpperCase()]&&(b=this._longDateFormat[a.toUpperCase()].replace(/MMMM|MM|DD|dddd/g,function(a){return a.slice(1)}),this._longDateFormat[a]=b),b},isPM:function(a){return"p"===(a+"").toLowerCase().charAt(0)},_meridiemParse:/[ap]\\.?m?\\.?/i,meridiem:function(a,b,c){return a>11?c?"pm":"PM":c?"am":"AM"},_calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendar[a];return"function"==typeof c?c.apply(b):c},_relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},relativeTime:function(a,b,c,d){var e=this._relativeTime[c];return"function"==typeof e?e(a,b,c,d):e.replace(/%d/i,a)},pastFuture:function(a,b){var c=this._relativeTime[a>0?"future":"past"];return"function"==typeof c?c(b):c.replace(/%s/i,b)},ordinal:function(a){return this._ordinal.replace("%d",a)},_ordinal:"%d",preparse:function(a){return a},postformat:function(a){return a},week:function(a){return Y(a,this._week.dow,this._week.doy).week},_week:{dow:0,doy:6},_invalidDate:"Invalid date",invalidDate:function(){return this._invalidDate}}),db=function(c,d,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._i=c,g._f=d,g._l=e,g._strict=f,g._isUTC=!1,g._pf=b(),$(g)},db.utc=function(c,d,e,f){var g;return"boolean"==typeof e&&(f=e,e=a),g={},g._isAMomentObject=!0,g._useUTC=!0,g._isUTC=!0,g._l=e,g._i=c,g._f=d,g._strict=f,g._pf=b(),$(g).utc()},db.unix=function(a){return db(1e3*a)},db.duration=function(a,b){var c,d,e,f=a,h=null;return db.isDuration(a)?f={ms:a._milliseconds,d:a._days,M:a._months}:"number"==typeof a?(f={},b?f[b]=a:f.milliseconds=a):(h=tb.exec(a))?(c="-"===h[1]?-1:1,f={y:0,d:s(h[kb])*c,h:s(h[lb])*c,m:s(h[mb])*c,s:s(h[nb])*c,ms:s(h[ob])*c}):(h=ub.exec(a))&&(c="-"===h[1]?-1:1,e=function(a){var b=a&&parseFloat(a.replace(",","."));return(isNaN(b)?0:b)*c},f={y:e(h[2]),M:e(h[3]),d:e(h[4]),h:e(h[5]),m:e(h[6]),s:e(h[7]),w:e(h[8])}),d=new g(f),db.isDuration(a)&&a.hasOwnProperty("_lang")&&(d._lang=a._lang),d},db.version=fb,db.defaultFormat=Nb,db.updateOffset=function(){},db.lang=function(a,b){var c;return a?(b?A(y(a),b):null===b?(B(a),a="en"):pb[a]||C(a),c=db.duration.fn._lang=db.fn._lang=C(a),c._abbr):db.fn._lang._abbr},db.langData=function(a){return a&&a._lang&&a._lang._abbr&&(a=a._lang._abbr),C(a)},db.isMoment=function(a){return a instanceof f||null!=a&&a.hasOwnProperty("_isAMomentObject")},db.isDuration=function(a){return a instanceof g},eb=Zb.length-1;eb>=0;--eb)r(Zb[eb]);for(db.normalizeUnits=function(a){return p(a)},db.invalid=function(a){var b=db.utc(0/0);return null!=a?h(b._pf,a):b._pf.userInvalidated=!0,b},db.parseZone=function(a){return db(a).parseZone()},h(db.fn=f.prototype,{clone:function(){return db(this)},valueOf:function(){return+this._d+6e4*(this._offset||0)},unix:function(){return Math.floor(+this/1e3)},toString:function(){return this.clone().lang("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},toDate:function(){return this._offset?new Date(+this):this._d},toISOString:function(){var a=db(this).utc();return 0<a.year()&&a.year()<=9999?F(a,"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]"):F(a,"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]")},toArray:function(){var a=this;return[a.year(),a.month(),a.date(),a.hours(),a.minutes(),a.seconds(),a.milliseconds()]},isValid:function(){return x(this)},isDSTShifted:function(){return this._a?this.isValid()&&o(this._a,(this._isUTC?db.utc(this._a):db(this._a)).toArray())>0:!1},parsingFlags:function(){return h({},this._pf)},invalidAt:function(){return this._pf.overflow},utc:function(){return this.zone(0)},local:function(){return this.zone(0),this._isUTC=!1,this},format:function(a){var b=F(this,a||db.defaultFormat);return this.lang().postformat(b)},add:function(a,b){var c;return c="string"==typeof a?db.duration(+b,a):db.duration(a,b),l(this,c,1),this},subtract:function(a,b){var c;return c="string"==typeof a?db.duration(+b,a):db.duration(a,b),l(this,c,-1),this},diff:function(a,b,c){var d,e,f=z(a,this),g=6e4*(this.zone()-f.zone());return b=p(b),"year"===b||"month"===b?(d=432e5*(this.daysInMonth()+f.daysInMonth()),e=12*(this.year()-f.year())+(this.month()-f.month()),e+=(this-db(this).startOf("month")-(f-db(f).startOf("month")))/d,e-=6e4*(this.zone()-db(this).startOf("month").zone()-(f.zone()-db(f).startOf("month").zone()))/d,"year"===b&&(e/=12)):(d=this-f,e="second"===b?d/1e3:"minute"===b?d/6e4:"hour"===b?d/36e5:"day"===b?(d-g)/864e5:"week"===b?(d-g)/6048e5:d),c?e:j(e)},from:function(a,b){return db.duration(this.diff(a)).lang(this.lang()._abbr).humanize(!b)},fromNow:function(a){return this.from(db(),a)},calendar:function(){var a=z(db(),this).startOf("day"),b=this.diff(a,"days",!0),c=-6>b?"sameElse":-1>b?"lastWeek":0>b?"lastDay":1>b?"sameDay":2>b?"nextDay":7>b?"nextWeek":"sameElse";return this.format(this.lang().calendar(c,this))},isLeapYear:function(){return v(this.year())},isDST:function(){return this.zone()<this.clone().month(0).zone()||this.zone()<this.clone().month(5).zone()},day:function(a){var b=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=a?(a=V(a,this.lang()),this.add({d:a-b})):b},month:function(a){var b,c=this._isUTC?"UTC":"";return null!=a?"string"==typeof a&&(a=this.lang().monthsParse(a),"number"!=typeof a)?this:(b=this.date(),this.date(1),this._d["set"+c+"Month"](a),this.date(Math.min(b,this.daysInMonth())),db.updateOffset(this),this):this._d["get"+c+"Month"]()},startOf:function(a){switch(a=p(a)){case"year":this.month(0);case"month":this.date(1);case"week":case"isoWeek":case"day":this.hours(0);case"hour":this.minutes(0);case"minute":this.seconds(0);case"second":this.milliseconds(0)}return"week"===a?this.weekday(0):"isoWeek"===a&&this.isoWeekday(1),this},endOf:function(a){return a=p(a),this.startOf(a).add("isoWeek"===a?"week":a,1).subtract("ms",1)},isAfter:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)>+db(a).startOf(b)},isBefore:function(a,b){return b="undefined"!=typeof b?b:"millisecond",+this.clone().startOf(b)<+db(a).startOf(b)},isSame:function(a,b){return b=b||"ms",+this.clone().startOf(b)===+z(a,this).startOf(b)},min:function(a){return a=db.apply(null,arguments),this>a?this:a},max:function(a){return a=db.apply(null,arguments),a>this?this:a},zone:function(a){var b=this._offset||0;return null==a?this._isUTC?b:this._d.getTimezoneOffset():("string"==typeof a&&(a=I(a)),Math.abs(a)<16&&(a=60*a),this._offset=a,this._isUTC=!0,b!==a&&l(this,db.duration(b-a,"m"),1,!0),this)},zoneAbbr:function(){return this._isUTC?"UTC":""},zoneName:function(){return this._isUTC?"Coordinated Universal Time":""},parseZone:function(){return this._tzm?this.zone(this._tzm):"string"==typeof this._i&&this.zone(this._i),this},hasAlignedHourOffset:function(a){return a=a?db(a).zone():0,(this.zone()-a)%60===0},daysInMonth:function(){return t(this.year(),this.month())},dayOfYear:function(a){var b=hb((db(this).startOf("day")-db(this).startOf("year"))/864e5)+1;return null==a?b:this.add("d",a-b)},quarter:function(){return Math.ceil((this.month()+1)/3)},weekYear:function(a){var b=Y(this,this.lang()._week.dow,this.lang()._week.doy).year;return null==a?b:this.add("y",a-b)},isoWeekYear:function(a){var b=Y(this,1,4).year;return null==a?b:this.add("y",a-b)},week:function(a){var b=this.lang().week(this);return null==a?b:this.add("d",7*(a-b))},isoWeek:function(a){var b=Y(this,1,4).week;return null==a?b:this.add("d",7*(a-b))},weekday:function(a){var b=(this.day()+7-this.lang()._week.dow)%7;return null==a?b:this.add("d",a-b)},isoWeekday:function(a){return null==a?this.day()||7:this.day(this.day()%7?a:a-7)},get:function(a){return a=p(a),this[a]()},set:function(a,b){return a=p(a),"function"==typeof this[a]&&this[a](b),this},lang:function(b){return b===a?this._lang:(this._lang=C(b),this)}}),eb=0;eb<Rb.length;eb++)_(Rb[eb].toLowerCase().replace(/s$/,""),Rb[eb]);_("year","FullYear"),db.fn.days=db.fn.day,db.fn.months=db.fn.month,db.fn.weeks=db.fn.week,db.fn.isoWeeks=db.fn.isoWeek,db.fn.toJSON=db.fn.toISOString,h(db.duration.fn=g.prototype,{_bubble:function(){var a,b,c,d,e=this._milliseconds,f=this._days,g=this._months,h=this._data;h.milliseconds=e%1e3,a=j(e/1e3),h.seconds=a%60,b=j(a/60),h.minutes=b%60,c=j(b/60),h.hours=c%24,f+=j(c/24),h.days=f%30,g+=j(f/30),h.months=g%12,d=j(g/12),h.years=d},weeks:function(){return j(this.days()/7)},valueOf:function(){return this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*s(this._months/12)},humanize:function(a){var b=+this,c=X(b,!a,this.lang());return a&&(c=this.lang().pastFuture(b,c)),this.lang().postformat(c)},add:function(a,b){var c=db.duration(a,b);return this._milliseconds+=c._milliseconds,this._days+=c._days,this._months+=c._months,this._bubble(),this},subtract:function(a,b){var c=db.duration(a,b);return this._milliseconds-=c._milliseconds,this._days-=c._days,this._months-=c._months,this._bubble(),this},get:function(a){return a=p(a),this[a.toLowerCase()+"s"]()},as:function(a){return a=p(a),this["as"+a.charAt(0).toUpperCase()+a.slice(1)+"s"]()},lang:db.fn.lang,toIsoString:function(){var a=Math.abs(this.years()),b=Math.abs(this.months()),c=Math.abs(this.days()),d=Math.abs(this.hours()),e=Math.abs(this.minutes()),f=Math.abs(this.seconds()+this.milliseconds()/1e3);return this.asSeconds()?(this.asSeconds()<0?"-":"")+"P"+(a?a+"Y":"")+(b?b+"M":"")+(c?c+"D":"")+(d||e||f?"T":"")+(d?d+"H":"")+(e?e+"M":"")+(f?f+"S":""):"P0D"}});for(eb in Sb)Sb.hasOwnProperty(eb)&&(bb(eb,Sb[eb]),ab(eb.toLowerCase()));bb("Weeks",6048e5),db.duration.fn.asMonths=function(){return(+this-31536e6*this.years())/2592e6+12*this.years()},db.lang("en",{ordinal:function(a){var b=a%10,c=1===s(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}}),function(a){a(db)}(function(a){return a.lang("ar-ma",{months:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),monthsShort:"يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر".split("_"),weekdays:"الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:6,doy:12}})}),function(a){a(db)}(function(a){return a.lang("ar",{months:"يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"),monthsShort:"يناير/ كانون الثاني_فبراير/ شباط_مارس/ آذار_أبريل/ نيسان_مايو/ أيار_يونيو/ حزيران_يوليو/ تموز_أغسطس/ آب_سبتمبر/ أيلول_أكتوبر/ تشرين الأول_نوفمبر/ تشرين الثاني_ديسمبر/ كانون الأول".split("_"),weekdays:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysShort:"الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت".split("_"),weekdaysMin:"ح_ن_ث_ر_خ_ج_س".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[اليوم على الساعة] LT",nextDay:"[غدا على الساعة] LT",nextWeek:"dddd [على الساعة] LT",lastDay:"[أمس على الساعة] LT",lastWeek:"dddd [على الساعة] LT",sameElse:"L"},relativeTime:{future:"في %s",past:"منذ %s",s:"ثوان",m:"دقيقة",mm:"%d دقائق",h:"ساعة",hh:"%d ساعات",d:"يوم",dd:"%d أيام",M:"شهر",MM:"%d أشهر",y:"سنة",yy:"%d سنوات"},week:{dow:6,doy:12}})}),function(a){a(db)}(function(a){return a.lang("bg",{months:"януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември".split("_"),monthsShort:"янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек".split("_"),weekdays:"неделя_понеделник_вторник_сряда_четвъртък_петък_събота".split("_"),weekdaysShort:"нед_пон_вто_сря_чет_пет_съб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"H:mm",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Днес в] LT",nextDay:"[Утре в] LT",nextWeek:"dddd [в] LT",lastDay:"[Вчера в] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[В изминалата] dddd [в] LT";case 1:case 2:case 4:case 5:return"[В изминалия] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"след %s",past:"преди %s",s:"няколко секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дни",M:"месец",MM:"%d месеца",y:"година",yy:"%d години"},ordinal:function(a){var b=a%10,c=a%100;return 0===a?a+"-ев":0===c?a+"-ен":c>10&&20>c?a+"-ти":1===b?a+"-ви":2===b?a+"-ри":7===b||8===b?a+"-ми":a+"-ти"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(b){function c(a,b,c){var d={mm:"munutenn",MM:"miz",dd:"devezh"};return a+" "+f(d[c],a)}function d(a){switch(e(a)){case 1:case 3:case 4:case 5:case 9:return a+" bloaz";default:return a+" vloaz"}}function e(a){return a>9?e(a%10):a}function f(a,b){return 2===b?g(a):a}function g(b){var c={m:"v",b:"v",d:"z"};return c[b.charAt(0)]===a?b:c[b.charAt(0)]+b.substring(1)}return b.lang("br",{months:"Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu".split("_"),monthsShort:"Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker".split("_"),weekdays:"Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn".split("_"),weekdaysShort:"Sul_Lun_Meu_Mer_Yao_Gwe_Sad".split("_"),weekdaysMin:"Su_Lu_Me_Mer_Ya_Gw_Sa".split("_"),longDateFormat:{LT:"h[e]mm A",L:"DD/MM/YYYY",LL:"D [a viz] MMMM YYYY",LLL:"D [a viz] MMMM YYYY LT",LLLL:"dddd, D [a viz] MMMM YYYY LT"},calendar:{sameDay:"[Hiziv da] LT",nextDay:"[Warc\'hoazh da] LT",nextWeek:"dddd [da] LT",lastDay:"[Dec\'h da] LT",lastWeek:"dddd [paset da] LT",sameElse:"L"},relativeTime:{future:"a-benn %s",past:"%s \'zo",s:"un nebeud segondennoù",m:"ur vunutenn",mm:c,h:"un eur",hh:"%d eur",d:"un devezh",dd:c,M:"ur miz",MM:c,y:"ur bloaz",yy:d},ordinal:function(a){var b=1===a?"añ":"vet";return a+b},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}return a.lang("bs",{months:"januar_februar_mart_april_maj_juni_juli_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),longDateFormat:{LT:"H:mm",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:b,mm:b,h:b,hh:b,d:"dan",dd:b,M:"mjesec",MM:b,y:"godinu",yy:b},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("ca",{months:"gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre".split("_"),monthsShort:"gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.".split("_"),weekdays:"diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte".split("_"),weekdaysShort:"dg._dl._dt._dc._dj._dv._ds.".split("_"),weekdaysMin:"Dg_Dl_Dt_Dc_Dj_Dv_Ds".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[avui a "+(1!==this.hours()?"les":"la")+"] LT"\n
+},nextDay:function(){return"[demà a "+(1!==this.hours()?"les":"la")+"] LT"},nextWeek:function(){return"dddd [a "+(1!==this.hours()?"les":"la")+"] LT"},lastDay:function(){return"[ahir a "+(1!==this.hours()?"les":"la")+"] LT"},lastWeek:function(){return"[el] dddd [passat a "+(1!==this.hours()?"les":"la")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"fa %s",s:"uns segons",m:"un minut",mm:"%d minuts",h:"una hora",hh:"%d hores",d:"un dia",dd:"%d dies",M:"un mes",MM:"%d mesos",y:"un any",yy:"%d anys"},ordinal:"%dº",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a){return a>1&&5>a&&1!==~~(a/10)}function c(a,c,d,e){var f=a+" ";switch(d){case"s":return c||e?"pár vteřin":"pár vteřinami";case"m":return c?"minuta":e?"minutu":"minutou";case"mm":return c||e?f+(b(a)?"minuty":"minut"):f+"minutami";break;case"h":return c?"hodina":e?"hodinu":"hodinou";case"hh":return c||e?f+(b(a)?"hodiny":"hodin"):f+"hodinami";break;case"d":return c||e?"den":"dnem";case"dd":return c||e?f+(b(a)?"dny":"dní"):f+"dny";break;case"M":return c||e?"měsíc":"měsícem";case"MM":return c||e?f+(b(a)?"měsíce":"měsíců"):f+"měsíci";break;case"y":return c||e?"rok":"rokem";case"yy":return c||e?f+(b(a)?"roky":"let"):f+"lety"}}var d="leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec".split("_"),e="led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro".split("_");return a.lang("cs",{months:d,monthsShort:e,monthsParse:function(a,b){var c,d=[];for(c=0;12>c;c++)d[c]=new RegExp("^"+a[c]+"$|^"+b[c]+"$","i");return d}(d,e),weekdays:"neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota".split("_"),weekdaysShort:"ne_po_út_st_čt_pá_so".split("_"),weekdaysMin:"ne_po_út_st_čt_pá_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd D. MMMM YYYY LT"},calendar:{sameDay:"[dnes v] LT",nextDay:"[zítra v] LT",nextWeek:function(){switch(this.day()){case 0:return"[v neděli v] LT";case 1:case 2:return"[v] dddd [v] LT";case 3:return"[ve středu v] LT";case 4:return"[ve čtvrtek v] LT";case 5:return"[v pátek v] LT";case 6:return"[v sobotu v] LT"}},lastDay:"[včera v] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulou neděli v] LT";case 1:case 2:return"[minulé] dddd [v] LT";case 3:return"[minulou středu v] LT";case 4:case 5:return"[minulý] dddd [v] LT";case 6:return"[minulou sobotu v] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"před %s",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("cv",{months:"кăрлач_нарăс_пуш_ака_май_çĕртме_утă_çурла_авăн_юпа_чӳк_раштав".split("_"),monthsShort:"кăр_нар_пуш_ака_май_çĕр_утă_çур_ав_юпа_чӳк_раш".split("_"),weekdays:"вырсарникун_тунтикун_ытларикун_юнкун_кĕçнерникун_эрнекун_шăматкун".split("_"),weekdaysShort:"выр_тун_ытл_юн_кĕç_эрн_шăм".split("_"),weekdaysMin:"вр_тн_ыт_юн_кç_эр_шм".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ]",LLL:"YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT",LLLL:"dddd, YYYY [çулхи] MMMM [уйăхĕн] D[-мĕшĕ], LT"},calendar:{sameDay:"[Паян] LT [сехетре]",nextDay:"[Ыран] LT [сехетре]",lastDay:"[Ĕнер] LT [сехетре]",nextWeek:"[Çитес] dddd LT [сехетре]",lastWeek:"[Иртнĕ] dddd LT [сехетре]",sameElse:"L"},relativeTime:{future:function(a){var b=/сехет$/i.exec(a)?"рен":/çул$/i.exec(a)?"тан":"ран";return a+b},past:"%s каялла",s:"пĕр-ик çеккунт",m:"пĕр минут",mm:"%d минут",h:"пĕр сехет",hh:"%d сехет",d:"пĕр кун",dd:"%d кун",M:"пĕр уйăх",MM:"%d уйăх",y:"пĕр çул",yy:"%d çул"},ordinal:"%d-мĕш",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("cy",{months:"Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr".split("_"),monthsShort:"Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag".split("_"),weekdays:"Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn".split("_"),weekdaysShort:"Sul_Llun_Maw_Mer_Iau_Gwe_Sad".split("_"),weekdaysMin:"Su_Ll_Ma_Me_Ia_Gw_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Heddiw am] LT",nextDay:"[Yfory am] LT",nextWeek:"dddd [am] LT",lastDay:"[Ddoe am] LT",lastWeek:"dddd [diwethaf am] LT",sameElse:"L"},relativeTime:{future:"mewn %s",past:"%s yn àl",s:"ychydig eiliadau",m:"munud",mm:"%d munud",h:"awr",hh:"%d awr",d:"diwrnod",dd:"%d diwrnod",M:"mis",MM:"%d mis",y:"blwyddyn",yy:"%d flynedd"},ordinal:function(a){var b=a,c="",d=["","af","il","ydd","ydd","ed","ed","ed","fed","fed","fed","eg","fed","eg","eg","fed","eg","eg","fed","eg","fed"];return b>20?c=40===b||50===b||60===b||80===b||100===b?"fed":"ain":b>0&&(c=d[b]),a+c},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("da",{months:"januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"søn_man_tir_ons_tor_fre_lør".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D. MMMM, YYYY LT"},calendar:{sameDay:"[I dag kl.] LT",nextDay:"[I morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[I går kl.] LT",lastWeek:"[sidste] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"%s siden",s:"få sekunder",m:"et minut",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dage",M:"en måned",MM:"%d måneder",y:"et år",yy:"%d år"},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c){var d={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?d[c][0]:d[c][1]}return a.lang("de",{months:"Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag".split("_"),weekdaysShort:"So._Mo._Di._Mi._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mo_Di_Mi_Do_Fr_Sa".split("_"),longDateFormat:{LT:"H:mm [Uhr]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Heute um] LT",sameElse:"L",nextDay:"[Morgen um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gestern um] LT",lastWeek:"[letzten] dddd [um] LT"},relativeTime:{future:"in %s",past:"vor %s",s:"ein paar Sekunden",m:b,mm:"%d Minuten",h:b,hh:"%d Stunden",d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("el",{monthsNominativeEl:"Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος".split("_"),monthsGenitiveEl:"Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου".split("_"),months:function(a,b){return/D/.test(b.substring(0,b.indexOf("MMMM")))?this._monthsGenitiveEl[a.month()]:this._monthsNominativeEl[a.month()]},monthsShort:"Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ".split("_"),weekdays:"Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο".split("_"),weekdaysShort:"Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ".split("_"),weekdaysMin:"Κυ_Δε_Τρ_Τε_Πε_Πα_Σα".split("_"),meridiem:function(a,b,c){return a>11?c?"μμ":"ΜΜ":c?"πμ":"ΠΜ"},longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendarEl:{sameDay:"[Σήμερα {}] LT",nextDay:"[Αύριο {}] LT",nextWeek:"dddd [{}] LT",lastDay:"[Χθες {}] LT",lastWeek:"[την προηγούμενη] dddd [{}] LT",sameElse:"L"},calendar:function(a,b){var c=this._calendarEl[a],d=b&&b.hours();return c.replace("{}",d%12===1?"στη":"στις")},relativeTime:{future:"σε %s",past:"%s πριν",s:"δευτερόλεπτα",m:"ένα λεπτό",mm:"%d λεπτά",h:"μία ώρα",hh:"%d ώρες",d:"μία μέρα",dd:"%d μέρες",M:"ένας μήνας",MM:"%d μήνες",y:"ένας χρόνος",yy:"%d χρόνια"},ordinal:function(a){return a+"η"},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("en-au",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("en-ca",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"h:mm A",L:"YYYY-MM-DD",LL:"D MMMM, YYYY",LLL:"D MMMM, YYYY LT",LLLL:"dddd, D MMMM, YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c}})}),function(a){a(db)}(function(a){return a.lang("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("eo",{months:"januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec".split("_"),weekdays:"Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato".split("_"),weekdaysShort:"Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Ĵa_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D[-an de] MMMM, YYYY",LLL:"D[-an de] MMMM, YYYY LT",LLLL:"dddd, [la] D[-an de] MMMM, YYYY LT"},meridiem:function(a,b,c){return a>11?c?"p.t.m.":"P.T.M.":c?"a.t.m.":"A.T.M."},calendar:{sameDay:"[Hodiaŭ je] LT",nextDay:"[Morgaŭ je] LT",nextWeek:"dddd [je] LT",lastDay:"[Hieraŭ je] LT",lastWeek:"[pasinta] dddd [je] LT",sameElse:"L"},relativeTime:{future:"je %s",past:"antaŭ %s",s:"sekundoj",m:"minuto",mm:"%d minutoj",h:"horo",hh:"%d horoj",d:"tago",dd:"%d tagoj",M:"monato",MM:"%d monatoj",y:"jaro",yy:"%d jaroj"},ordinal:"%da",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("es",{months:"enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre".split("_"),monthsShort:"ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.".split("_"),weekdays:"domingo_lunes_martes_miércoles_jueves_viernes_sábado".split("_"),weekdaysShort:"dom._lun._mar._mié._jue._vie._sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mi_Ju_Vi_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:function(){return"[hoy a la"+(1!==this.hours()?"s":"")+"] LT"},nextDay:function(){return"[mañana a la"+(1!==this.hours()?"s":"")+"] LT"},nextWeek:function(){return"dddd [a la"+(1!==this.hours()?"s":"")+"] LT"},lastDay:function(){return"[ayer a la"+(1!==this.hours()?"s":"")+"] LT"},lastWeek:function(){return"[el] dddd [pasado a la"+(1!==this.hours()?"s":"")+"] LT"},sameElse:"L"},relativeTime:{future:"en %s",past:"hace %s",s:"unos segundos",m:"un minuto",mm:"%d minutos",h:"una hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un año",yy:"%d años"},ordinal:"%dº",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c,d){var e={s:["mõne sekundi","mõni sekund","paar sekundit"],m:["ühe minuti","üks minut"],mm:[a+" minuti",a+" minutit"],h:["ühe tunni","tund aega","üks tund"],hh:[a+" tunni",a+" tundi"],d:["ühe päeva","üks päev"],M:["kuu aja","kuu aega","üks kuu"],MM:[a+" kuu",a+" kuud"],y:["ühe aasta","aasta","üks aasta"],yy:[a+" aasta",a+" aastat"]};return b?e[c][2]?e[c][2]:e[c][1]:d?e[c][0]:e[c][1]}return a.lang("et",{months:"jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember".split("_"),monthsShort:"jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets".split("_"),weekdays:"pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev".split("_"),weekdaysShort:"P_E_T_K_N_R_L".split("_"),weekdaysMin:"P_E_T_K_N_R_L".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Täna,] LT",nextDay:"[Homme,] LT",nextWeek:"[Järgmine] dddd LT",lastDay:"[Eile,] LT",lastWeek:"[Eelmine] dddd LT",sameElse:"L"},relativeTime:{future:"%s pärast",past:"%s tagasi",s:b,m:b,mm:b,h:b,hh:b,d:b,dd:"%d päeva",M:b,MM:b,y:b,yy:b},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("eu",{months:"urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua".split("_"),monthsShort:"urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.".split("_"),weekdays:"igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata".split("_"),weekdaysShort:"ig._al._ar._az._og._ol._lr.".split("_"),weekdaysMin:"ig_al_ar_az_og_ol_lr".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"YYYY[ko] MMMM[ren] D[a]",LLL:"YYYY[ko] MMMM[ren] D[a] LT",LLLL:"dddd, YYYY[ko] MMMM[ren] D[a] LT",l:"YYYY-M-D",ll:"YYYY[ko] MMM D[a]",lll:"YYYY[ko] MMM D[a] LT",llll:"ddd, YYYY[ko] MMM D[a] LT"},calendar:{sameDay:"[gaur] LT[etan]",nextDay:"[bihar] LT[etan]",nextWeek:"dddd LT[etan]",lastDay:"[atzo] LT[etan]",lastWeek:"[aurreko] dddd LT[etan]",sameElse:"L"},relativeTime:{future:"%s barru",past:"duela %s",s:"segundo batzuk",m:"minutu bat",mm:"%d minutu",h:"ordu bat",hh:"%d ordu",d:"egun bat",dd:"%d egun",M:"hilabete bat",MM:"%d hilabete",y:"urte bat",yy:"%d urte"},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){var b={1:"۱",2:"۲",3:"۳",4:"۴",5:"۵",6:"۶",7:"۷",8:"۸",9:"۹",0:"۰"},c={"۱":"1","۲":"2","۳":"3","۴":"4","۵":"5","۶":"6","۷":"7","۸":"8","۹":"9","۰":"0"};return a.lang("fa",{months:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),monthsShort:"ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر".split("_"),weekdays:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysShort:"یک‌شنبه_دوشنبه_سه‌شنبه_چهارشنبه_پنج‌شنبه_جمعه_شنبه".split("_"),weekdaysMin:"ی_د_س_چ_پ_ج_ش".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},meridiem:function(a){return 12>a?"قبل از ظهر":"بعد از ظهر"},calendar:{sameDay:"[امروز ساعت] LT",nextDay:"[فردا ساعت] LT",nextWeek:"dddd [ساعت] LT",lastDay:"[دیروز ساعت] LT",lastWeek:"dddd [پیش] [ساعت] LT",sameElse:"L"},relativeTime:{future:"در %s",past:"%s پیش",s:"چندین ثانیه",m:"یک دقیقه",mm:"%d دقیقه",h:"یک ساعت",hh:"%d ساعت",d:"یک روز",dd:"%d روز",M:"یک ماه",MM:"%d ماه",y:"یک سال",yy:"%d سال"},preparse:function(a){return a.replace(/[۰-۹]/g,function(a){return c[a]}).replace(/،/g,",")},postformat:function(a){return a.replace(/\\d/g,function(a){return b[a]}).replace(/,/g,"،")},ordinal:"%dم",week:{dow:6,doy:12}})}),function(a){a(db)}(function(a){function b(a,b,d,e){var f="";switch(d){case"s":return e?"muutaman sekunnin":"muutama sekunti";case"m":return e?"minuutin":"minuutti";case"mm":f=e?"minuutin":"minuuttia";break;case"h":return e?"tunnin":"tunti";case"hh":f=e?"tunnin":"tuntia";break;case"d":return e?"päivän":"päivä";case"dd":f=e?"päivän":"päivää";break;case"M":return e?"kuukauden":"kuukausi";case"MM":f=e?"kuukauden":"kuukautta";break;case"y":return e?"vuoden":"vuosi";case"yy":f=e?"vuoden":"vuotta"}return f=c(a,e)+" "+f}function c(a,b){return 10>a?b?e[a]:d[a]:a}var d="nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän".split(" "),e=["nolla","yhden","kahden","kolmen","neljän","viiden","kuuden",d[7],d[8],d[9]];return a.lang("fi",{months:"tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu".split("_"),monthsShort:"tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu".split("_"),weekdays:"sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai".split("_"),weekdaysShort:"su_ma_ti_ke_to_pe_la".split("_"),weekdaysMin:"su_ma_ti_ke_to_pe_la".split("_"),longDateFormat:{LT:"HH.mm",L:"DD.MM.YYYY",LL:"Do MMMM[ta] YYYY",LLL:"Do MMMM[ta] YYYY, [klo] LT",LLLL:"dddd, Do MMMM[ta] YYYY, [klo] LT",l:"D.M.YYYY",ll:"Do MMM YYYY",lll:"Do MMM YYYY, [klo] LT",llll:"ddd, Do MMM YYYY, [klo] LT"},calendar:{sameDay:"[tänään] [klo] LT",nextDay:"[huomenna] [klo] LT",nextWeek:"dddd [klo] LT",lastDay:"[eilen] [klo] LT",lastWeek:"[viime] dddd[na] [klo] LT",sameElse:"L"},relativeTime:{future:"%s päästä",past:"%s sitten",s:b,m:b,mm:b,h:b,hh:b,d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("fo",{months:"januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur".split("_"),weekdaysShort:"sun_mán_týs_mik_hós_frí_ley".split("_"),weekdaysMin:"su_má_tý_mi_hó_fr_le".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D. MMMM, YYYY LT"},calendar:{sameDay:"[Í dag kl.] LT",nextDay:"[Í morgin kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[Í gjár kl.] LT",lastWeek:"[síðstu] dddd [kl] LT",sameElse:"L"},relativeTime:{future:"um %s",past:"%s síðani",s:"fá sekund",m:"ein minutt",mm:"%d minuttir",h:"ein tími",hh:"%d tímar",d:"ein dagur",dd:"%d dagar",M:"ein mánaði",MM:"%d mánaðir",y:"eitt ár",yy:"%d ár"},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("fr-ca",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd\'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinal:function(a){return a+(1===a?"er":"")}})}),function(a){a(db)}(function(a){return a.lang("fr",{months:"janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre".split("_"),monthsShort:"janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.".split("_"),weekdays:"dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi".split("_"),weekdaysShort:"dim._lun._mar._mer._jeu._ven._sam.".split("_"),weekdaysMin:"Di_Lu_Ma_Me_Je_Ve_Sa".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Aujourd\'hui à] LT",nextDay:"[Demain à] LT",nextWeek:"dddd [à] LT",lastDay:"[Hier à] LT",lastWeek:"dddd [dernier à] LT",sameElse:"L"},relativeTime:{future:"dans %s",past:"il y a %s",s:"quelques secondes",m:"une minute",mm:"%d minutes",h:"une heure",hh:"%d heures",d:"un jour",dd:"%d jours",M:"un mois",MM:"%d mois",y:"un an",yy:"%d ans"},ordinal:function(a){return a+(1===a?"er":"")},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("gl",{months:"Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro".split("_"),monthsShort:"Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.".split("_"),weekdays:"Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado".split("_"),weekdaysShort:"Dom._Lun._Mar._Mér._Xov._Ven._Sáb.".split("_"),weekdaysMin:"Do_Lu_Ma_Mé_Xo_Ve_Sá".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:function(){return"[hoxe "+(1!==this.hours()?"ás":"á")+"] LT"},nextDay:function(){return"[mañá "+(1!==this.hours()?"ás":"á")+"] LT"},nextWeek:function(){return"dddd ["+(1!==this.hours()?"ás":"a")+"] LT"},lastDay:function(){return"[onte "+(1!==this.hours()?"á":"a")+"] LT"},lastWeek:function(){return"[o] dddd [pasado "+(1!==this.hours()?"ás":"a")+"] LT"},sameElse:"L"},relativeTime:{future:function(a){return"uns segundos"===a?"nuns segundos":"en "+a},past:"hai %s",s:"uns segundos",m:"un minuto",mm:"%d minutos",h:"unha hora",hh:"%d horas",d:"un día",dd:"%d días",M:"un mes",MM:"%d meses",y:"un ano",yy:"%d anos"},ordinal:"%dº",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("he",{months:"ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר".split("_"),monthsShort:"ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳".split("_"),weekdays:"ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת".split("_"),weekdaysShort:"א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳".split("_"),weekdaysMin:"א_ב_ג_ד_ה_ו_ש".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [ב]MMMM YYYY",LLL:"D [ב]MMMM YYYY LT",LLLL:"dddd, D [ב]MMMM YYYY LT",l:"D/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY LT",llll:"ddd, D MMM YYYY LT"},calendar:{sameDay:"[היום ב־]LT",nextDay:"[מחר ב־]LT",nextWeek:"dddd [בשעה] LT",lastDay:"[אתמול ב־]LT",lastWeek:"[ביום] dddd [האחרון בשעה] LT",sameElse:"L"},relativeTime:{future:"בעוד %s",past:"לפני %s",s:"מספר שניות",m:"דקה",mm:"%d דקות",h:"שעה",hh:function(a){return 2===a?"שעתיים":a+" שעות"},d:"יום",dd:function(a){return 2===a?"יומיים":a+" ימים"},M:"חודש",MM:function(a){return 2===a?"חודשיים":a+" חודשים"},y:"שנה",yy:function(a){return 2===a?"שנתיים":a+" שנים"}}})}),function(a){a(db)}(function(a){var b={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},c={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};return a.lang("hi",{months:"जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर".split("_"),monthsShort:"जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.".split("_"),weekdays:"रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},calendar:{sameDay:"[आज] LT",nextDay:"[कल] LT",nextWeek:"dddd, LT",lastDay:"[कल] LT",lastWeek:"[पिछले] dddd, LT",sameElse:"L"},relativeTime:{future:"%s में",past:"%s पहले",s:"कुछ ही क्षण",m:"एक मिनट",mm:"%d मिनट",h:"एक घंटा",hh:"%d घंटे",d:"एक दिन",dd:"%d दिन",M:"एक महीने",MM:"%d महीने",y:"एक वर्ष",yy:"%d वर्ष"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return c[a]})},postformat:function(a){return a.replace(/\\d/g,function(a){return b[a]})},meridiem:function(a){return 4>a?"रात":10>a?"सुबह":17>a?"दोपहर":20>a?"शाम":"रात"},week:{dow:0,doy:6}})}),function(a){a(db)}(function(a){function b(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}return a.lang("hr",{months:"sječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac".split("_"),monthsShort:"sje._vel._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.".split("_"),weekdays:"nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sri._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),longDateFormat:{LT:"H:mm",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedjelju] [u] LT";case 3:return"[u] [srijedu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[jučer u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"prije %s",s:"par sekundi",m:b,mm:b,h:b,hh:b,d:"dan",dd:b,M:"mjesec",MM:b,y:"godinu",yy:b},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a,b,c,d){var e=a;switch(c){case"s":return d||b?"néhány másodperc":"néhány másodperce";case"m":return"egy"+(d||b?" perc":" perce");case"mm":return e+(d||b?" perc":" perce");case"h":return"egy"+(d||b?" óra":" órája");case"hh":return e+(d||b?" óra":" órája");case"d":return"egy"+(d||b?" nap":" napja");case"dd":return e+(d||b?" nap":" napja");case"M":return"egy"+(d||b?" hónap":" hónapja");case"MM":return e+(d||b?" hónap":" hónapja");case"y":return"egy"+(d||b?" év":" éve");case"yy":return e+(d||b?" év":" éve")}return""}function c(a){return(a?"":"[múlt] ")+"["+d[this.day()]+"] LT[-kor]"}var d="vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton".split(" ");return a.lang("hu",{months:"január_február_március_április_május_június_július_augusztus_szeptember_október_november_december".split("_"),monthsShort:"jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec".split("_"),weekdays:"vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat".split("_"),weekdaysShort:"vas_hét_kedd_sze_csüt_pén_szo".split("_"),weekdaysMin:"v_h_k_sze_cs_p_szo".split("_"),longDateFormat:{LT:"H:mm",L:"YYYY.MM.DD.",LL:"YYYY. MMMM D.",LLL:"YYYY. MMMM D., LT",LLLL:"YYYY. MMMM D., dddd LT"},calendar:{sameDay:"[ma] LT[-kor]",nextDay:"[holnap] LT[-kor]",nextWeek:function(){return c.call(this,!0)},lastDay:"[tegnap] LT[-kor]",lastWeek:function(){return c.call(this,!1)},sameElse:"L"},relativeTime:{future:"%s múlva",past:"%s",s:b,m:b,mm:b,h:b,hh:b,d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a,b){var c={nominative:"հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր".split("_"),accusative:"հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի".split("_")},d=/D[oD]?(\\[[^\\[\\]]*\\]|\\s+)+MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function c(a){var b="հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ".split("_");return b[a.month()]}function d(a){var b="կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ".split("_");return b[a.day()]}return a.lang("hy-am",{months:b,monthsShort:c,weekdays:d,weekdaysShort:"կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),weekdaysMin:"կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY թ.",LLL:"D MMMM YYYY թ., LT",LLLL:"dddd, D MMMM YYYY թ., LT"},calendar:{sameDay:"[այսօր] LT",nextDay:"[վաղը] LT",lastDay:"[երեկ] LT",nextWeek:function(){return"dddd [օրը ժամը] LT"},lastWeek:function(){return"[անցած] dddd [օրը ժամը] LT"},sameElse:"L"},relativeTime:{future:"%s հետո",past:"%s առաջ",s:"մի քանի վայրկյան",m:"րոպե",mm:"%d րոպե",h:"ժամ",hh:"%d ժամ",d:"օր",dd:"%d օր",M:"ամիս",MM:"%d ամիս",y:"տարի",yy:"%d տարի"},meridiem:function(a){return 4>a?"գիշերվա":12>a?"առավոտվա":17>a?"ցերեկվա":"երեկոյան"},ordinal:function(a,b){switch(b){case"DDD":case"w":case"W":case"DDDo":return 1===a?a+"-ին":a+"-րդ";default:return a}},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("id",{months:"Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember".split("_"),monthsShort:"Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des".split("_"),weekdays:"Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu".split("_"),weekdaysShort:"Min_Sen_Sel_Rab_Kam_Jum_Sab".split("_"),weekdaysMin:"Mg_Sn_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] LT",LLLL:"dddd, D MMMM YYYY [pukul] LT"},meridiem:function(a){return 11>a?"pagi":15>a?"siang":19>a?"sore":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Besok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kemarin pukul] LT",lastWeek:"dddd [lalu pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lalu",s:"beberapa detik",m:"semenit",mm:"%d menit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a){return a%100===11?!0:a%10===1?!1:!0}function c(a,c,d,e){var f=a+" ";switch(d){case"s":return c||e?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return c?"mínúta":"mínútu";case"mm":return b(a)?f+(c||e?"mínútur":"mínútum"):c?f+"mínúta":f+"mínútu";case"hh":return b(a)?f+(c||e?"klukkustundir":"klukkustundum"):f+"klukkustund";case"d":return c?"dagur":e?"dag":"degi";case"dd":return b(a)?c?f+"dagar":f+(e?"daga":"dögum"):c?f+"dagur":f+(e?"dag":"degi");case"M":return c?"mánuður":e?"mánuð":"mánuði";case"MM":return b(a)?c?f+"mánuðir":f+(e?"mánuði":"mánuðum"):c?f+"mánuður":f+(e?"mánuð":"mánuði");case"y":return c||e?"ár":"ári";case"yy":return b(a)?f+(c||e?"ár":"árum"):f+(c||e?"ár":"ári")}}return a.lang("is",{months:"janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember".split("_"),monthsShort:"jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des".split("_"),weekdays:"sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur".split("_"),weekdaysShort:"sun_mán_þri_mið_fim_fös_lau".split("_"),weekdaysMin:"Su_Má_Þr_Mi_Fi_Fö_La".split("_"),longDateFormat:{LT:"H:mm",L:"DD/MM/YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] LT",LLLL:"dddd, D. MMMM YYYY [kl.] LT"},calendar:{sameDay:"[í dag kl.] LT",nextDay:"[á morgun kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[í gær kl.] LT",lastWeek:"[síðasta] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"eftir %s",past:"fyrir %s síðan",s:c,m:c,mm:c,h:"klukkustund",hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinal:"%d.",week:{dow:1,doy:4}})\n
+}),function(a){a(db)}(function(a){return a.lang("it",{months:"Gennaio_Febbraio_Marzo_Aprile_Maggio_Giugno_Luglio_Agosto_Settembre_Ottobre_Novembre_Dicembre".split("_"),monthsShort:"Gen_Feb_Mar_Apr_Mag_Giu_Lug_Ago_Set_Ott_Nov_Dic".split("_"),weekdays:"Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato".split("_"),weekdaysShort:"Dom_Lun_Mar_Mer_Gio_Ven_Sab".split("_"),weekdaysMin:"D_L_Ma_Me_G_V_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Oggi alle] LT",nextDay:"[Domani alle] LT",nextWeek:"dddd [alle] LT",lastDay:"[Ieri alle] LT",lastWeek:"[lo scorso] dddd [alle] LT",sameElse:"L"},relativeTime:{future:function(a){return(/^[0-9].+$/.test(a)?"tra":"in")+" "+a},past:"%s fa",s:"alcuni secondi",m:"un minuto",mm:"%d minuti",h:"un\'ora",hh:"%d ore",d:"un giorno",dd:"%d giorni",M:"un mese",MM:"%d mesi",y:"un anno",yy:"%d anni"},ordinal:"%dº",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("ja",{months:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日".split("_"),weekdaysShort:"日_月_火_水_木_金_土".split("_"),weekdaysMin:"日_月_火_水_木_金_土".split("_"),longDateFormat:{LT:"Ah時m分",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日LT",LLLL:"YYYY年M月D日LT dddd"},meridiem:function(a){return 12>a?"午前":"午後"},calendar:{sameDay:"[今日] LT",nextDay:"[明日] LT",nextWeek:"[来週]dddd LT",lastDay:"[昨日] LT",lastWeek:"[前週]dddd LT",sameElse:"L"},relativeTime:{future:"%s後",past:"%s前",s:"数秒",m:"1分",mm:"%d分",h:"1時間",hh:"%d時間",d:"1日",dd:"%d日",M:"1ヶ月",MM:"%dヶ月",y:"1年",yy:"%d年"}})}),function(a){a(db)}(function(a){function b(a,b){var c={nominative:"იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი".split("_"),accusative:"იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს".split("_")},d=/D[oD] *MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function c(a,b){var c={nominative:"კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი".split("_"),accusative:"კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს".split("_")},d=/(წინა|შემდეგ)/.test(b)?"accusative":"nominative";return c[d][a.day()]}return a.lang("ka",{months:b,monthsShort:"იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ".split("_"),weekdays:c,weekdaysShort:"კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ".split("_"),weekdaysMin:"კვ_ორ_სა_ოთ_ხუ_პა_შა".split("_"),longDateFormat:{LT:"h:mm A",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[დღეს] LT[-ზე]",nextDay:"[ხვალ] LT[-ზე]",lastDay:"[გუშინ] LT[-ზე]",nextWeek:"[შემდეგ] dddd LT[-ზე]",lastWeek:"[წინა] dddd LT-ზე",sameElse:"L"},relativeTime:{future:function(a){return/(წამი|წუთი|საათი|წელი)/.test(a)?a.replace(/ი$/,"ში"):a+"ში"},past:function(a){return/(წამი|წუთი|საათი|დღე|თვე)/.test(a)?a.replace(/(ი|ე)$/,"ის წინ"):/წელი/.test(a)?a.replace(/წელი$/,"წლის წინ"):void 0},s:"რამდენიმე წამი",m:"წუთი",mm:"%d წუთი",h:"საათი",hh:"%d საათი",d:"დღე",dd:"%d დღე",M:"თვე",MM:"%d თვე",y:"წელი",yy:"%d წელი"},ordinal:function(a){return 0===a?a:1===a?a+"-ლი":20>a||100>=a&&a%20===0||a%100===0?"მე-"+a:a+"-ე"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("ko",{months:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),monthsShort:"1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월".split("_"),weekdays:"일요일_월요일_화요일_수요일_목요일_금요일_토요일".split("_"),weekdaysShort:"일_월_화_수_목_금_토".split("_"),weekdaysMin:"일_월_화_수_목_금_토".split("_"),longDateFormat:{LT:"A h시 mm분",L:"YYYY.MM.DD",LL:"YYYY년 MMMM D일",LLL:"YYYY년 MMMM D일 LT",LLLL:"YYYY년 MMMM D일 dddd LT"},meridiem:function(a){return 12>a?"오전":"오후"},calendar:{sameDay:"오늘 LT",nextDay:"내일 LT",nextWeek:"dddd LT",lastDay:"어제 LT",lastWeek:"지난주 dddd LT",sameElse:"L"},relativeTime:{future:"%s 후",past:"%s 전",s:"몇초",ss:"%d초",m:"일분",mm:"%d분",h:"한시간",hh:"%d시간",d:"하루",dd:"%d일",M:"한달",MM:"%d달",y:"일년",yy:"%d년"},ordinal:"%d일",meridiemParse:/(오전|오후)/,isPM:function(a){return"오후"===a}})}),function(a){a(db)}(function(a){function b(a,b,c){var d={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],dd:[a+" Deeg",a+" Deeg"],M:["ee Mount","engem Mount"],MM:[a+" Méint",a+" Méint"],y:["ee Joer","engem Joer"],yy:[a+" Joer",a+" Joer"]};return b?d[c][0]:d[c][1]}function c(a){var b=a.substr(0,a.indexOf(" "));return g(b)?"a "+a:"an "+a}function d(a){var b=a.substr(0,a.indexOf(" "));return g(b)?"viru "+a:"virun "+a}function e(){var a=this.format("d");return f(a)?"[Leschte] dddd [um] LT":"[Leschten] dddd [um] LT"}function f(a){switch(a=parseInt(a,10)){case 0:case 1:case 3:case 5:case 6:return!0;default:return!1}}function g(a){if(a=parseInt(a,10),isNaN(a))return!1;if(0>a)return!0;if(10>a)return a>=4&&7>=a?!0:!1;if(100>a){var b=a%10,c=a/10;return 0===b?g(c):g(b)}if(1e4>a){for(;a>=10;)a/=10;return g(a)}return a/=1e3,g(a)}return a.lang("lb",{months:"Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.".split("_"),weekdays:"Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg".split("_"),weekdaysShort:"So._Mé._Dë._Më._Do._Fr._Sa.".split("_"),weekdaysMin:"So_Mé_Dë_Më_Do_Fr_Sa".split("_"),longDateFormat:{LT:"H:mm [Auer]",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[Haut um] LT",sameElse:"L",nextDay:"[Muer um] LT",nextWeek:"dddd [um] LT",lastDay:"[Gëschter um] LT",lastWeek:e},relativeTime:{future:c,past:d,s:"e puer Sekonnen",m:b,mm:"%d Minutten",h:b,hh:"%d Stonnen",d:b,dd:b,M:b,MM:b,y:b,yy:b},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c,d){return b?"kelios sekundės":d?"kelių sekundžių":"kelias sekundes"}function c(a,b,c,d){return b?e(c)[0]:d?e(c)[1]:e(c)[2]}function d(a){return a%10===0||a>10&&20>a}function e(a){return h[a].split("_")}function f(a,b,f,g){var h=a+" ";return 1===a?h+c(a,b,f[0],g):b?h+(d(a)?e(f)[1]:e(f)[0]):g?h+e(f)[1]:h+(d(a)?e(f)[1]:e(f)[2])}function g(a,b){var c=-1===b.indexOf("dddd LT"),d=i[a.weekday()];return c?d:d.substring(0,d.length-2)+"į"}var h={m:"minutė_minutės_minutę",mm:"minutės_minučių_minutes",h:"valanda_valandos_valandą",hh:"valandos_valandų_valandas",d:"diena_dienos_dieną",dd:"dienos_dienų_dienas",M:"mėnuo_mėnesio_mėnesį",MM:"mėnesiai_mėnesių_mėnesius",y:"metai_metų_metus",yy:"metai_metų_metus"},i="pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis_sekmadienis".split("_");return a.lang("lt",{months:"sausio_vasario_kovo_balandžio_gegužės_biržėlio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio".split("_"),monthsShort:"sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd".split("_"),weekdays:g,weekdaysShort:"Sek_Pir_Ant_Tre_Ket_Pen_Šeš".split("_"),weekdaysMin:"S_P_A_T_K_Pn_Š".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"YYYY [m.] MMMM D [d.]",LLL:"YYYY [m.] MMMM D [d.], LT [val.]",LLLL:"YYYY [m.] MMMM D [d.], dddd, LT [val.]",l:"YYYY-MM-DD",ll:"YYYY [m.] MMMM D [d.]",lll:"YYYY [m.] MMMM D [d.], LT [val.]",llll:"YYYY [m.] MMMM D [d.], ddd, LT [val.]"},calendar:{sameDay:"[Šiandien] LT",nextDay:"[Rytoj] LT",nextWeek:"dddd LT",lastDay:"[Vakar] LT",lastWeek:"[Praėjusį] dddd LT",sameElse:"L"},relativeTime:{future:"po %s",past:"prieš %s",s:b,m:c,mm:f,h:c,hh:f,d:c,dd:f,M:c,MM:f,y:c,yy:f},ordinal:function(a){return a+"-oji"},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c){var d=a.split("_");return c?b%10===1&&11!==b?d[2]:d[3]:b%10===1&&11!==b?d[0]:d[1]}function c(a,c,e){return a+" "+b(d[e],a,c)}var d={mm:"minūti_minūtes_minūte_minūtes",hh:"stundu_stundas_stunda_stundas",dd:"dienu_dienas_diena_dienas",MM:"mēnesi_mēnešus_mēnesis_mēneši",yy:"gadu_gadus_gads_gadi"};return a.lang("lv",{months:"janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris".split("_"),monthsShort:"jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec".split("_"),weekdays:"svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena".split("_"),weekdaysShort:"Sv_P_O_T_C_Pk_S".split("_"),weekdaysMin:"Sv_P_O_T_C_Pk_S".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"YYYY. [gada] D. MMMM",LLL:"YYYY. [gada] D. MMMM, LT",LLLL:"YYYY. [gada] D. MMMM, dddd, LT"},calendar:{sameDay:"[Šodien pulksten] LT",nextDay:"[Rīt pulksten] LT",nextWeek:"dddd [pulksten] LT",lastDay:"[Vakar pulksten] LT",lastWeek:"[Pagājušā] dddd [pulksten] LT",sameElse:"L"},relativeTime:{future:"%s vēlāk",past:"%s agrāk",s:"dažas sekundes",m:"minūti",mm:c,h:"stundu",hh:c,d:"dienu",dd:c,M:"mēnesi",MM:c,y:"gadu",yy:c},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("mk",{months:"јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември".split("_"),monthsShort:"јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек".split("_"),weekdays:"недела_понеделник_вторник_среда_четврток_петок_сабота".split("_"),weekdaysShort:"нед_пон_вто_сре_чет_пет_саб".split("_"),weekdaysMin:"нe_пo_вт_ср_че_пе_сa".split("_"),longDateFormat:{LT:"H:mm",L:"D.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Денес во] LT",nextDay:"[Утре во] LT",nextWeek:"dddd [во] LT",lastDay:"[Вчера во] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[Во изминатата] dddd [во] LT";case 1:case 2:case 4:case 5:return"[Во изминатиот] dddd [во] LT"}},sameElse:"L"},relativeTime:{future:"после %s",past:"пред %s",s:"неколку секунди",m:"минута",mm:"%d минути",h:"час",hh:"%d часа",d:"ден",dd:"%d дена",M:"месец",MM:"%d месеци",y:"година",yy:"%d години"},ordinal:function(a){var b=a%10,c=a%100;return 0===a?a+"-ев":0===c?a+"-ен":c>10&&20>c?a+"-ти":1===b?a+"-ви":2===b?a+"-ри":7===b||8===b?a+"-ми":a+"-ти"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("ml",{months:"ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ".split("_"),monthsShort:"ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.".split("_"),weekdays:"ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച".split("_"),weekdaysShort:"ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി".split("_"),weekdaysMin:"ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ".split("_"),longDateFormat:{LT:"A h:mm -നു",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},calendar:{sameDay:"[ഇന്ന്] LT",nextDay:"[നാളെ] LT",nextWeek:"dddd, LT",lastDay:"[ഇന്നലെ] LT",lastWeek:"[കഴിഞ്ഞ] dddd, LT",sameElse:"L"},relativeTime:{future:"%s കഴിഞ്ഞ്",past:"%s മുൻപ്",s:"അൽപ നിമിഷങ്ങൾ",m:"ഒരു മിനിറ്റ്",mm:"%d മിനിറ്റ്",h:"ഒരു മണിക്കൂർ",hh:"%d മണിക്കൂർ",d:"ഒരു ദിവസം",dd:"%d ദിവസം",M:"ഒരു മാസം",MM:"%d മാസം",y:"ഒരു വർഷം",yy:"%d വർഷം"},meridiem:function(a){return 4>a?"രാത്രി":12>a?"രാവിലെ":17>a?"ഉച്ച കഴിഞ്ഞ്":20>a?"വൈകുന്നേരം":"രാത്രി"}})}),function(a){a(db)}(function(a){var b={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},c={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};return a.lang("mr",{months:"जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर".split("_"),monthsShort:"जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.".split("_"),weekdays:"रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार".split("_"),weekdaysShort:"रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि".split("_"),weekdaysMin:"र_सो_मं_बु_गु_शु_श".split("_"),longDateFormat:{LT:"A h:mm वाजता",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},calendar:{sameDay:"[आज] LT",nextDay:"[उद्या] LT",nextWeek:"dddd, LT",lastDay:"[काल] LT",lastWeek:"[मागील] dddd, LT",sameElse:"L"},relativeTime:{future:"%s नंतर",past:"%s पूर्वी",s:"सेकंद",m:"एक मिनिट",mm:"%d मिनिटे",h:"एक तास",hh:"%d तास",d:"एक दिवस",dd:"%d दिवस",M:"एक महिना",MM:"%d महिने",y:"एक वर्ष",yy:"%d वर्षे"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return c[a]})},postformat:function(a){return a.replace(/\\d/g,function(a){return b[a]})},meridiem:function(a){return 4>a?"रात्री":10>a?"सकाळी":17>a?"दुपारी":20>a?"सायंकाळी":"रात्री"},week:{dow:0,doy:6}})}),function(a){a(db)}(function(a){return a.lang("ms-my",{months:"Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember".split("_"),monthsShort:"Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis".split("_"),weekdays:"Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu".split("_"),weekdaysShort:"Ahd_Isn_Sel_Rab_Kha_Jum_Sab".split("_"),weekdaysMin:"Ah_Is_Sl_Rb_Km_Jm_Sb".split("_"),longDateFormat:{LT:"HH.mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY [pukul] LT",LLLL:"dddd, D MMMM YYYY [pukul] LT"},meridiem:function(a){return 11>a?"pagi":15>a?"tengahari":19>a?"petang":"malam"},calendar:{sameDay:"[Hari ini pukul] LT",nextDay:"[Esok pukul] LT",nextWeek:"dddd [pukul] LT",lastDay:"[Kelmarin pukul] LT",lastWeek:"dddd [lepas pukul] LT",sameElse:"L"},relativeTime:{future:"dalam %s",past:"%s yang lepas",s:"beberapa saat",m:"seminit",mm:"%d minit",h:"sejam",hh:"%d jam",d:"sehari",dd:"%d hari",M:"sebulan",MM:"%d bulan",y:"setahun",yy:"%d tahun"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("nb",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.".split("_"),weekdays:"søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag".split("_"),weekdaysShort:"sø._ma._ti._on._to._fr._lø.".split("_"),weekdaysMin:"sø_ma_ti_on_to_fr_lø".split("_"),longDateFormat:{LT:"H.mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY [kl.] LT",LLLL:"dddd D. MMMM YYYY [kl.] LT"},calendar:{sameDay:"[i dag kl.] LT",nextDay:"[i morgen kl.] LT",nextWeek:"dddd [kl.] LT",lastDay:"[i går kl.] LT",lastWeek:"[forrige] dddd [kl.] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekunder",m:"ett minutt",mm:"%d minutter",h:"en time",hh:"%d timer",d:"en dag",dd:"%d dager",M:"en måned",MM:"%d måneder",y:"ett år",yy:"%d år"},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){var b={1:"१",2:"२",3:"३",4:"४",5:"५",6:"६",7:"७",8:"८",9:"९",0:"०"},c={"१":"1","२":"2","३":"3","४":"4","५":"5","६":"6","७":"7","८":"8","९":"9","०":"0"};return a.lang("ne",{months:"जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर".split("_"),monthsShort:"जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.".split("_"),weekdays:"आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार".split("_"),weekdaysShort:"आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.".split("_"),weekdaysMin:"आइ._सो._मङ्_बु._बि._शु._श.".split("_"),longDateFormat:{LT:"Aको h:mm बजे",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},preparse:function(a){return a.replace(/[१२३४५६७८९०]/g,function(a){return c[a]})},postformat:function(a){return a.replace(/\\d/g,function(a){return b[a]})},meridiem:function(a){return 3>a?"राती":10>a?"बिहान":15>a?"दिउँसो":18>a?"बेलुका":20>a?"साँझ":"राती"},calendar:{sameDay:"[आज] LT",nextDay:"[भोली] LT",nextWeek:"[आउँदो] dddd[,] LT",lastDay:"[हिजो] LT",lastWeek:"[गएको] dddd[,] LT",sameElse:"L"},relativeTime:{future:"%sमा",past:"%s अगाडी",s:"केही समय",m:"एक मिनेट",mm:"%d मिनेट",h:"एक घण्टा",hh:"%d घण्टा",d:"एक दिन",dd:"%d दिन",M:"एक महिना",MM:"%d महिना",y:"एक बर्ष",yy:"%d बर्ष"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){var b="jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.".split("_"),c="jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec".split("_");return a.lang("nl",{months:"januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december".split("_"),monthsShort:function(a,d){return/-MMM-/.test(d)?c[a.month()]:b[a.month()]},weekdays:"zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag".split("_"),weekdaysShort:"zo._ma._di._wo._do._vr._za.".split("_"),weekdaysMin:"Zo_Ma_Di_Wo_Do_Vr_Za".split("_"),longDateFormat:{LT:"HH:mm",L:"DD-MM-YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[vandaag om] LT",nextDay:"[morgen om] LT",nextWeek:"dddd [om] LT",lastDay:"[gisteren om] LT",lastWeek:"[afgelopen] dddd [om] LT",sameElse:"L"},relativeTime:{future:"over %s",past:"%s geleden",s:"een paar seconden",m:"één minuut",mm:"%d minuten",h:"één uur",hh:"%d uur",d:"één dag",dd:"%d dagen",M:"één maand",MM:"%d maanden",y:"één jaar",yy:"%d jaar"},ordinal:function(a){return a+(1===a||8===a||a>=20?"ste":"de")},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("nn",{months:"januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember".split("_"),monthsShort:"jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des".split("_"),weekdays:"sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag".split("_"),weekdaysShort:"sun_mån_tys_ons_tor_fre_lau".split("_"),weekdaysMin:"su_må_ty_on_to_fr_lø".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[I dag klokka] LT",nextDay:"[I morgon klokka] LT",nextWeek:"dddd [klokka] LT",lastDay:"[I går klokka] LT",lastWeek:"[Føregående] dddd [klokka] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"for %s siden",s:"noen sekund",m:"ett minutt",mm:"%d minutt",h:"en time",hh:"%d timar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a){return 5>a%10&&a%10>1&&~~(a/10)%10!==1}function c(a,c,d){var e=a+" ";switch(d){case"m":return c?"minuta":"minutę";case"mm":return e+(b(a)?"minuty":"minut");case"h":return c?"godzina":"godzinę";case"hh":return e+(b(a)?"godziny":"godzin");case"MM":return e+(b(a)?"miesiące":"miesięcy");case"yy":return e+(b(a)?"lata":"lat")}}var d="styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień".split("_"),e="stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia".split("_");return a.lang("pl",{months:function(a,b){return/D MMMM/.test(b)?e[a.month()]:d[a.month()]},monthsShort:"sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru".split("_"),weekdays:"niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota".split("_"),weekdaysShort:"nie_pon_wt_śr_czw_pt_sb".split("_"),weekdaysMin:"N_Pn_Wt_Śr_Cz_Pt_So".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Dziś o] LT",nextDay:"[Jutro o] LT",nextWeek:"[W] dddd [o] LT",lastDay:"[Wczoraj o] LT",lastWeek:function(){switch(this.day()){case 0:return"[W zeszłą niedzielę o] LT";case 3:return"[W zeszłą środę o] LT";case 6:return"[W zeszłą sobotę o] LT";default:return"[W zeszły] dddd [o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"%s temu",s:"kilka sekund",m:c,mm:c,h:c,hh:c,d:"1 dzień",dd:"%d dni",M:"miesiąc",MM:c,y:"rok",yy:c},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("pt-br",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:"%dº"})}),function(a){a(db)}(function(a){return a.lang("pt",{months:"Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro".split("_"),monthsShort:"Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez".split("_"),weekdays:"Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado".split("_"),weekdaysShort:"Dom_Seg_Ter_Qua_Qui_Sex_Sáb".split("_"),weekdaysMin:"Dom_2ª_3ª_4ª_5ª_6ª_Sáb".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D [de] MMMM [de] YYYY",LLL:"D [de] MMMM [de] YYYY LT",LLLL:"dddd, D [de] MMMM [de] YYYY LT"},calendar:{sameDay:"[Hoje às] LT",nextDay:"[Amanhã às] LT",nextWeek:"dddd [às] LT",lastDay:"[Ontem às] LT",lastWeek:function(){return 0===this.day()||6===this.day()?"[Último] dddd [às] LT":"[Última] dddd [às] LT"},sameElse:"L"},relativeTime:{future:"em %s",past:"%s atrás",s:"segundos",m:"um minuto",mm:"%d minutos",h:"uma hora",hh:"%d horas",d:"um dia",dd:"%d dias",M:"um mês",MM:"%d meses",y:"um ano",yy:"%d anos"},ordinal:"%dº",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c){var d={mm:"minute",hh:"ore",dd:"zile",MM:"luni",yy:"ani"},e=" ";return(a%100>=20||a>=100&&a%100===0)&&(e=" de "),a+e+d[c]}return a.lang("ro",{months:"ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie".split("_"),monthsShort:"ian_feb_mar_apr_mai_iun_iul_aug_sep_oct_noi_dec".split("_"),weekdays:"duminică_luni_marți_miercuri_joi_vineri_sâmbătă".split("_"),weekdaysShort:"Dum_Lun_Mar_Mie_Joi_Vin_Sâm".split("_"),weekdaysMin:"Du_Lu_Ma_Mi_Jo_Vi_Sâ".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY H:mm",LLLL:"dddd, D MMMM YYYY H:mm"},calendar:{sameDay:"[azi la] LT",nextDay:"[mâine la] LT",nextWeek:"dddd [la] LT",lastDay:"[ieri la] LT",lastWeek:"[fosta] dddd [la] LT",sameElse:"L"},relativeTime:{future:"peste %s",past:"%s în urmă",s:"câteva secunde",m:"un minut",mm:b,h:"o oră",hh:b,d:"o zi",dd:b,M:"o lună",MM:b,y:"un an",yy:b},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mesec":2===a||3===a||4===a?"meseca":"meseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}return a.lang("rs",{months:"januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),weekdays:"nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota".split("_"),weekdaysShort:"ned._pon._uto._sre._čet._pet._sub.".split("_"),weekdaysMin:"ne_po_ut_sr_če_pe_su".split("_"),longDateFormat:{LT:"H:mm",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danas u] LT",nextDay:"[sutra u] LT",nextWeek:function(){switch(this.day()){case 0:return"[u] [nedelju] [u] LT";case 3:return"[u] [sredu] [u] LT";case 6:return"[u] [subotu] [u] LT";case 1:case 2:case 4:case 5:return"[u] dddd [u] LT"}},lastDay:"[juče u] LT",lastWeek:function(){switch(this.day()){case 0:case 3:return"[prošlu] dddd [u] LT";case 6:return"[prošle] [subote] [u] LT";case 1:case 2:case 4:case 5:return"[prošli] dddd [u] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pre %s",s:"par sekundi",m:b,mm:b,h:b,hh:b,d:"dan",dd:b,M:"mesec",MM:b,y:"godinu",yy:b},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function c(a,c,d){var e={mm:"минута_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};return"m"===d?c?"минута":"минуту":a+" "+b(e[d],+a)}function d(a,b){var c={nominative:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),accusative:"января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря".split("_")},d=/D[oD]?(\\[[^\\[\\]]*\\]|\\s+)+MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function e(a,b){var c={nominative:"янв_фев_мар_апр_май_июнь_июль_авг_сен_окт_ноя_дек".split("_"),accusative:"янв_фев_мар_апр_мая_июня_июля_авг_сен_окт_ноя_дек".split("_")},d=/D[oD]?(\\[[^\\[\\]]*\\]|\\s+)+MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function f(a,b){var c={nominative:"воскресенье_понедельник_вторник_среда_четверг_пятница_суббота".split("_"),accusative:"воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу".split("_")},d=/\\[ ?[Вв] ?(?:прошлую|следующую)? ?\\] ?dddd/.test(b)?"accusative":"nominative";return c[d][a.day()]}return a.lang("ru",{months:d,monthsShort:e,weekdays:f,weekdaysShort:"вс_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"вс_пн_вт_ср_чт_пт_сб".split("_"),monthsParse:[/^янв/i,/^фев/i,/^мар/i,/^апр/i,/^ма[й|я]/i,/^июн/i,/^июл/i,/^авг/i,/^сен/i,/^окт/i,/^ноя/i,/^дек/i],longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY г.",LLL:"D MMMM YYYY г., LT",LLLL:"dddd, D MMMM YYYY г., LT"},calendar:{sameDay:"[Сегодня в] LT",nextDay:"[Завтра в] LT",lastDay:"[Вчера в] LT",nextWeek:function(){return 2===this.day()?"[Во] dddd [в] LT":"[В] dddd [в] LT"},lastWeek:function(){switch(this.day()){case 0:return"[В прошлое] dddd [в] LT";case 1:case 2:case 4:return"[В прошлый] dddd [в] LT";case 3:case 5:case 6:return"[В прошлую] dddd [в] LT"}},sameElse:"L"},relativeTime:{future:"через %s",past:"%s назад",s:"несколько секунд",m:c,mm:c,h:"час",hh:c,d:"день",dd:c,M:"месяц",MM:c,y:"год",yy:c},meridiem:function(a){return 4>a?"ночи":12>a?"утра":17>a?"дня":"вечера"},ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":return a+"-й";case"D":return a+"-го";case"w":case"W":return a+"-я";default:return a}},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){function b(a){return a>1&&5>a}function c(a,c,d,e){var f=a+" ";switch(d){case"s":return c||e?"pár sekúnd":"pár sekundami";case"m":return c?"minúta":e?"minútu":"minútou";case"mm":return c||e?f+(b(a)?"minúty":"minút"):f+"minútami";break;case"h":return c?"hodina":e?"hodinu":"hodinou";case"hh":return c||e?f+(b(a)?"hodiny":"hodín"):f+"hodinami";break;case"d":return c||e?"deň":"dňom";case"dd":return c||e?f+(b(a)?"dni":"dní"):f+"dňami";break;case"M":return c||e?"mesiac":"mesiacom";case"MM":return c||e?f+(b(a)?"mesiace":"mesiacov"):f+"mesiacmi";break;case"y":return c||e?"rok":"rokom";case"yy":return c||e?f+(b(a)?"roky":"rokov"):f+"rokmi"}}var d="január_február_marec_apríl_máj_jún_júl_august_september_október_november_december".split("_"),e="jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec".split("_");return a.lang("sk",{months:d,monthsShort:e,monthsParse:function(a,b){var c,d=[];for(c=0;12>c;c++)d[c]=new RegExp("^"+a[c]+"$|^"+b[c]+"$","i");return d}(d,e),weekdays:"nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota".split("_"),weekdaysShort:"ne_po_ut_st_št_pi_so".split("_"),weekdaysMin:"ne_po_ut_st_št_pi_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD.MM.YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd D. MMMM YYYY LT"},calendar:{sameDay:"[dnes o] LT",nextDay:"[zajtra o] LT",nextWeek:function(){switch(this.day()){case 0:return"[v nedeľu o] LT";case 1:case 2:return"[v] dddd [o] LT";case 3:return"[v stredu o] LT";case 4:return"[vo štvrtok o] LT";case 5:return"[v piatok o] LT";case 6:return"[v sobotu o] LT"}},lastDay:"[včera o] LT",lastWeek:function(){switch(this.day()){case 0:return"[minulú nedeľu o] LT";case 1:case 2:return"[minulý] dddd [o] LT";case 3:return"[minulú stredu o] LT";case 4:case 5:return"[minulý] dddd [o] LT";case 6:return"[minulú sobotu o] LT"}},sameElse:"L"},relativeTime:{future:"za %s",past:"pred %s",s:c,m:c,mm:c,h:c,hh:c,d:c,dd:c,M:c,MM:c,y:c,yy:c},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){function b(a,b,c){var d=a+" ";switch(c){case"m":return b?"ena minuta":"eno minuto";case"mm":return d+=1===a?"minuta":2===a?"minuti":3===a||4===a?"minute":"minut";case"h":return b?"ena ura":"eno uro";case"hh":return d+=1===a?"ura":2===a?"uri":3===a||4===a?"ure":"ur";case"dd":return d+=1===a?"dan":"dni";case"MM":return d+=1===a?"mesec":2===a?"meseca":3===a||4===a?"mesece":"mesecev";case"yy":return d+=1===a?"leto":2===a?"leti":3===a||4===a?"leta":"let"}}return a.lang("sl",{months:"januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december".split("_"),monthsShort:"jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.".split("_"),weekdays:"nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota".split("_"),weekdaysShort:"ned._pon._tor._sre._čet._pet._sob.".split("_"),weekdaysMin:"ne_po_to_sr_če_pe_so".split("_"),longDateFormat:{LT:"H:mm",L:"DD. MM. YYYY",LL:"D. MMMM YYYY",LLL:"D. MMMM YYYY LT",LLLL:"dddd, D. MMMM YYYY LT"},calendar:{sameDay:"[danes ob] LT",nextDay:"[jutri ob] LT",nextWeek:function(){switch(this.day()){case 0:return"[v] [nedeljo] [ob] LT";case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[včeraj ob] LT",lastWeek:function(){switch(this.day()){case 0:case 3:case 6:return"[prejšnja] dddd [ob] LT";case 1:case 2:case 4:case 5:return"[prejšnji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"čez %s",past:"%s nazaj",s:"nekaj sekund",m:b,mm:b,h:b,hh:b,d:"en dan",dd:b,M:"en mesec",MM:b,y:"eno leto",yy:b},ordinal:"%d.",week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("sq",{months:"Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor".split("_"),monthsShort:"Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj".split("_"),weekdays:"E Diel_E Hënë_E Marte_E Mërkure_E Enjte_E Premte_E Shtunë".split("_"),weekdaysShort:"Die_Hën_Mar_Mër_Enj_Pre_Sht".split("_"),weekdaysMin:"D_H_Ma_Më_E_P_Sh".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Sot në] LT",nextDay:"[Neser në] LT",nextWeek:"dddd [në] LT",lastDay:"[Dje në] LT",lastWeek:"dddd [e kaluar në] LT",sameElse:"L"},relativeTime:{future:"në %s",past:"%s me parë",s:"disa sekonda",m:"një minut",mm:"%d minuta",h:"një orë",hh:"%d orë",d:"një ditë",dd:"%d ditë",M:"një muaj",MM:"%d muaj",y:"një vit",yy:"%d vite"},ordinal:"%d.",week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("sv",{months:"januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec".split("_"),weekdays:"söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag".split("_"),weekdaysShort:"sön_mån_tis_ons_tor_fre_lör".split("_"),weekdaysMin:"sö_må_ti_on_to_fr_lö".split("_"),longDateFormat:{LT:"HH:mm",L:"YYYY-MM-DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[Idag] LT",nextDay:"[Imorgon] LT",lastDay:"[Igår] LT",nextWeek:"dddd LT",lastWeek:"[Förra] dddd[en] LT",sameElse:"L"},relativeTime:{future:"om %s",past:"för %s sedan",s:"några sekunder",m:"en minut",mm:"%d minuter",h:"en timme",hh:"%d timmar",d:"en dag",dd:"%d dagar",M:"en månad",MM:"%d månader",y:"ett år",yy:"%d år"},ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"e":1===b?"a":2===b?"a":3===b?"e":"e";return a+c},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("ta",{months:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),monthsShort:"ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்".split("_"),weekdays:"ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை".split("_"),weekdaysShort:"ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி".split("_"),weekdaysMin:"ஞா_தி_செ_பு_வி_வெ_ச".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY, LT",LLLL:"dddd, D MMMM YYYY, LT"},calendar:{sameDay:"[இன்று] LT",nextDay:"[நாளை] LT",nextWeek:"dddd, LT",lastDay:"[நேற்று] LT",lastWeek:"[கடந்த வாரம்] dddd, LT",sameElse:"L"},relativeTime:{future:"%s இல்",past:"%s முன்",s:"ஒரு சில விநாடிகள்",m:"ஒரு நிமிடம்",mm:"%d நிமிடங்கள்",h:"ஒரு மணி நேரம்",hh:"%d மணி நேரம்",d:"ஒரு நாள்",dd:"%d நாட்கள்",M:"ஒரு மாதம்",MM:"%d மாதங்கள்",y:"ஒரு வருடம்",yy:"%d ஆண்டுகள்"},ordinal:function(a){return a+"வது"\n
+},meridiem:function(a){return a>=6&&10>=a?" காலை":a>=10&&14>=a?" நண்பகல்":a>=14&&18>=a?" எற்பாடு":a>=18&&20>=a?" மாலை":a>=20&&24>=a?" இரவு":a>=0&&6>=a?" வைகறை":void 0},week:{dow:0,doy:6}})}),function(a){a(db)}(function(a){return a.lang("th",{months:"มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม".split("_"),monthsShort:"มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา".split("_"),weekdays:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์".split("_"),weekdaysShort:"อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์".split("_"),weekdaysMin:"อา._จ._อ._พ._พฤ._ศ._ส.".split("_"),longDateFormat:{LT:"H นาฬิกา m นาที",L:"YYYY/MM/DD",LL:"D MMMM YYYY",LLL:"D MMMM YYYY เวลา LT",LLLL:"วันddddที่ D MMMM YYYY เวลา LT"},meridiem:function(a){return 12>a?"ก่อนเที่ยง":"หลังเที่ยง"},calendar:{sameDay:"[วันนี้ เวลา] LT",nextDay:"[พรุ่งนี้ เวลา] LT",nextWeek:"dddd[หน้า เวลา] LT",lastDay:"[เมื่อวานนี้ เวลา] LT",lastWeek:"[วัน]dddd[ที่แล้ว เวลา] LT",sameElse:"L"},relativeTime:{future:"อีก %s",past:"%sที่แล้ว",s:"ไม่กี่วินาที",m:"1 นาที",mm:"%d นาที",h:"1 ชั่วโมง",hh:"%d ชั่วโมง",d:"1 วัน",dd:"%d วัน",M:"1 เดือน",MM:"%d เดือน",y:"1 ปี",yy:"%d ปี"}})}),function(a){a(db)}(function(a){return a.lang("tl-ph",{months:"Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre".split("_"),monthsShort:"Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis".split("_"),weekdays:"Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado".split("_"),weekdaysShort:"Lin_Lun_Mar_Miy_Huw_Biy_Sab".split("_"),weekdaysMin:"Li_Lu_Ma_Mi_Hu_Bi_Sab".split("_"),longDateFormat:{LT:"HH:mm",L:"MM/D/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY LT",LLLL:"dddd, MMMM DD, YYYY LT"},calendar:{sameDay:"[Ngayon sa] LT",nextDay:"[Bukas sa] LT",nextWeek:"dddd [sa] LT",lastDay:"[Kahapon sa] LT",lastWeek:"dddd [huling linggo] LT",sameElse:"L"},relativeTime:{future:"sa loob ng %s",past:"%s ang nakalipas",s:"ilang segundo",m:"isang minuto",mm:"%d minuto",h:"isang oras",hh:"%d oras",d:"isang araw",dd:"%d araw",M:"isang buwan",MM:"%d buwan",y:"isang taon",yy:"%d taon"},ordinal:function(a){return a},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){var b={1:"\'inci",5:"\'inci",8:"\'inci",70:"\'inci",80:"\'inci",2:"\'nci",7:"\'nci",20:"\'nci",50:"\'nci",3:"\'üncü",4:"\'üncü",100:"\'üncü",6:"\'ncı",9:"\'uncu",10:"\'uncu",30:"\'uncu",60:"\'ıncı",90:"\'ıncı"};return a.lang("tr",{months:"Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık".split("_"),monthsShort:"Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara".split("_"),weekdays:"Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi".split("_"),weekdaysShort:"Paz_Pts_Sal_Çar_Per_Cum_Cts".split("_"),weekdaysMin:"Pz_Pt_Sa_Ça_Pe_Cu_Ct".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[bugün saat] LT",nextDay:"[yarın saat] LT",nextWeek:"[haftaya] dddd [saat] LT",lastDay:"[dün] LT",lastWeek:"[geçen hafta] dddd [saat] LT",sameElse:"L"},relativeTime:{future:"%s sonra",past:"%s önce",s:"birkaç saniye",m:"bir dakika",mm:"%d dakika",h:"bir saat",hh:"%d saat",d:"bir gün",dd:"%d gün",M:"bir ay",MM:"%d ay",y:"bir yıl",yy:"%d yıl"},ordinal:function(a){if(0===a)return a+"\'ıncı";var c=a%10,d=a%100-c,e=a>=100?100:null;return a+(b[c]||b[d]||b[e])},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("tzm-la",{months:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),monthsShort:"innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir".split("_"),weekdays:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysShort:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),weekdaysMin:"asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[asdkh g] LT",nextDay:"[aska g] LT",nextWeek:"dddd [g] LT",lastDay:"[assant g] LT",lastWeek:"dddd [g] LT",sameElse:"L"},relativeTime:{future:"dadkh s yan %s",past:"yan %s",s:"imik",m:"minuḍ",mm:"%d minuḍ",h:"saɛa",hh:"%d tassaɛin",d:"ass",dd:"%d ossan",M:"ayowr",MM:"%d iyyirn",y:"asgas",yy:"%d isgasn"},week:{dow:6,doy:12}})}),function(a){a(db)}(function(a){return a.lang("tzm",{months:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),monthsShort:"ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ".split("_"),weekdays:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysShort:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),weekdaysMin:"ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd D MMMM YYYY LT"},calendar:{sameDay:"[ⴰⵙⴷⵅ ⴴ] LT",nextDay:"[ⴰⵙⴽⴰ ⴴ] LT",nextWeek:"dddd [ⴴ] LT",lastDay:"[ⴰⵚⴰⵏⵜ ⴴ] LT",lastWeek:"dddd [ⴴ] LT",sameElse:"L"},relativeTime:{future:"ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s",past:"ⵢⴰⵏ %s",s:"ⵉⵎⵉⴽ",m:"ⵎⵉⵏⵓⴺ",mm:"%d ⵎⵉⵏⵓⴺ",h:"ⵙⴰⵄⴰ",hh:"%d ⵜⴰⵙⵙⴰⵄⵉⵏ",d:"ⴰⵙⵙ",dd:"%d oⵙⵙⴰⵏ",M:"ⴰⵢoⵓⵔ",MM:"%d ⵉⵢⵢⵉⵔⵏ",y:"ⴰⵙⴳⴰⵙ",yy:"%d ⵉⵙⴳⴰⵙⵏ"},week:{dow:6,doy:12}})}),function(a){a(db)}(function(a){function b(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function c(a,c,d){var e={mm:"хвилина_хвилини_хвилин",hh:"година_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"};return"m"===d?c?"хвилина":"хвилину":"h"===d?c?"година":"годину":a+" "+b(e[d],+a)}function d(a,b){var c={nominative:"січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень".split("_"),accusative:"січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня".split("_")},d=/D[oD]? *MMMM?/.test(b)?"accusative":"nominative";return c[d][a.month()]}function e(a,b){var c={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".split("_"),accusative:"неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу".split("_"),genitive:"неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи".split("_")},d=/(\\[[ВвУу]\\]) ?dddd/.test(b)?"accusative":/\\[?(?:минулої|наступної)? ?\\] ?dddd/.test(b)?"genitive":"nominative";return c[d][a.day()]}function f(a){return function(){return a+"о"+(11===this.hours()?"б":"")+"] LT"}}return a.lang("uk",{months:d,monthsShort:"січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд".split("_"),weekdays:e,weekdaysShort:"нд_пн_вт_ср_чт_пт_сб".split("_"),weekdaysMin:"нд_пн_вт_ср_чт_пт_сб".split("_"),longDateFormat:{LT:"HH:mm",L:"DD.MM.YYYY",LL:"D MMMM YYYY р.",LLL:"D MMMM YYYY р., LT",LLLL:"dddd, D MMMM YYYY р., LT"},calendar:{sameDay:f("[Сьогодні "),nextDay:f("[Завтра "),lastDay:f("[Вчора "),nextWeek:f("[У] dddd ["),lastWeek:function(){switch(this.day()){case 0:case 3:case 5:case 6:return f("[Минулої] dddd [").call(this);case 1:case 2:case 4:return f("[Минулого] dddd [").call(this)}},sameElse:"L"},relativeTime:{future:"за %s",past:"%s тому",s:"декілька секунд",m:c,mm:c,h:"годину",hh:c,d:"день",dd:c,M:"місяць",MM:c,y:"рік",yy:c},meridiem:function(a){return 4>a?"ночі":12>a?"ранку":17>a?"дня":"вечора"},ordinal:function(a,b){switch(b){case"M":case"d":case"DDD":case"w":case"W":return a+"-й";case"D":return a+"-го";default:return a}},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("uz",{months:"январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь".split("_"),monthsShort:"янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек".split("_"),weekdays:"Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба".split("_"),weekdaysShort:"Якш_Душ_Сеш_Чор_Пай_Жум_Шан".split("_"),weekdaysMin:"Як_Ду_Се_Чо_Па_Жу_Ша".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"D MMMM YYYY, dddd LT"},calendar:{sameDay:"[Бугун соат] LT [да]",nextDay:"[Эртага] LT [да]",nextWeek:"dddd [куни соат] LT [да]",lastDay:"[Кеча соат] LT [да]",lastWeek:"[Утган] dddd [куни соат] LT [да]",sameElse:"L"},relativeTime:{future:"Якин %s ичида",past:"Бир неча %s олдин",s:"фурсат",m:"бир дакика",mm:"%d дакика",h:"бир соат",hh:"%d соат",d:"бир кун",dd:"%d кун",M:"бир ой",MM:"%d ой",y:"бир йил",yy:"%d йил"},week:{dow:1,doy:7}})}),function(a){a(db)}(function(a){return a.lang("vn",{months:"tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12".split("_"),monthsShort:"Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12".split("_"),weekdays:"chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy".split("_"),weekdaysShort:"CN_T2_T3_T4_T5_T6_T7".split("_"),weekdaysMin:"CN_T2_T3_T4_T5_T6_T7".split("_"),longDateFormat:{LT:"HH:mm",L:"DD/MM/YYYY",LL:"D MMMM [năm] YYYY",LLL:"D MMMM [năm] YYYY LT",LLLL:"dddd, D MMMM [năm] YYYY LT",l:"DD/M/YYYY",ll:"D MMM YYYY",lll:"D MMM YYYY LT",llll:"ddd, D MMM YYYY LT"},calendar:{sameDay:"[Hôm nay lúc] LT",nextDay:"[Ngày mai lúc] LT",nextWeek:"dddd [tuần tới lúc] LT",lastDay:"[Hôm qua lúc] LT",lastWeek:"dddd [tuần rồi lúc] LT",sameElse:"L"},relativeTime:{future:"%s tới",past:"%s trước",s:"vài giây",m:"một phút",mm:"%d phút",h:"một giờ",hh:"%d giờ",d:"một ngày",dd:"%d ngày",M:"một tháng",MM:"%d tháng",y:"một năm",yy:"%d năm"},ordinal:function(a){return a},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("zh-cn",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah点mm",L:"YYYY-MM-DD",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT",l:"YYYY-MM-DD",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日LT",llll:"YYYY年MMMD日ddddLT"},meridiem:function(a,b){var c=100*a+b;return 600>c?"凌晨":900>c?"早上":1130>c?"上午":1230>c?"中午":1800>c?"下午":"晚上"},calendar:{sameDay:function(){return 0===this.minutes()?"[今天]Ah[点整]":"[今天]LT"},nextDay:function(){return 0===this.minutes()?"[明天]Ah[点整]":"[明天]LT"},lastDay:function(){return 0===this.minutes()?"[昨天]Ah[点整]":"[昨天]LT"},nextWeek:function(){var b,c;return b=a().startOf("week"),c=this.unix()-b.unix()>=604800?"[下]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},lastWeek:function(){var b,c;return b=a().startOf("week"),c=this.unix()<b.unix()?"[上]":"[本]",0===this.minutes()?c+"dddAh点整":c+"dddAh点mm"},sameElse:"LL"},ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";case"M":return a+"月";case"w":case"W":return a+"周";default:return a}},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1分钟",mm:"%d分钟",h:"1小时",hh:"%d小时",d:"1天",dd:"%d天",M:"1个月",MM:"%d个月",y:"1年",yy:"%d年"},week:{dow:1,doy:4}})}),function(a){a(db)}(function(a){return a.lang("zh-tw",{months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"週日_週一_週二_週三_週四_週五_週六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),longDateFormat:{LT:"Ah點mm",L:"YYYY年MMMD日",LL:"YYYY年MMMD日",LLL:"YYYY年MMMD日LT",LLLL:"YYYY年MMMD日ddddLT",l:"YYYY年MMMD日",ll:"YYYY年MMMD日",lll:"YYYY年MMMD日LT",llll:"YYYY年MMMD日ddddLT"},meridiem:function(a,b){var c=100*a+b;return 900>c?"早上":1130>c?"上午":1230>c?"中午":1800>c?"下午":"晚上"},calendar:{sameDay:"[今天]LT",nextDay:"[明天]LT",nextWeek:"[下]ddddLT",lastDay:"[昨天]LT",lastWeek:"[上]ddddLT",sameElse:"L"},ordinal:function(a,b){switch(b){case"d":case"D":case"DDD":return a+"日";case"M":return a+"月";case"w":case"W":return a+"週";default:return a}},relativeTime:{future:"%s內",past:"%s前",s:"幾秒",m:"一分鐘",mm:"%d分鐘",h:"一小時",hh:"%d小時",d:"一天",dd:"%d天",M:"一個月",MM:"%d個月",y:"一年",yy:"%d年"}})}),db.lang("en"),rb?(module.exports=db,cb(!0)):"function"==typeof define&&define.amd?define("moment",function(b,c,d){return d.config&&d.config()&&d.config().noGlobal!==!0&&cb(d.config().noGlobal===a),db}):cb()}).call(this);
+
+]]></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/pubsub.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/pubsub.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..d341b370841d56e2aeecbd2554fa38ae7627c5e2
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/pubsub.js.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681771.66</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>pubsub.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global jQuery */\n
+/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011\n
+ * http://benalman.com/\n
+ * Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */\n
+(function($) {\n
+    "use strict";\n
+    var o = $({});\n
+    $.subscribe = function() {\n
+        o.on.apply(o, arguments);\n
+    };\n
+    $.unsubscribe = function() {\n
+        o.off.apply(o, arguments);\n
+    };\n
+    $.publish = function() {\n
+        o.trigger.apply(o, arguments);\n
+    };\n
+})(jQuery);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>434</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/qunit.css.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/qunit.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..7c432c8872ee9c403245f93fe2c2bf08bc86ce85
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/qunit.css.xml
@@ -0,0 +1,281 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681769.16</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>qunit.css</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/css</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*!\n
+ * QUnit 1.14.0\n
+ * http://qunitjs.com/\n
+ *\n
+ * Copyright 2013 jQuery Foundation and other contributors\n
+ * Released under the MIT license\n
+ * http://jquery.org/license\n
+ *\n
+ * Date: 2014-01-31T16:40Z\n
+ */\n
+\n
+/** Font Family and Sizes */\n
+\n
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {\n
+\tfont-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;\n
+}\n
+\n
+#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }\n
+#qunit-tests { font-size: smaller; }\n
+\n
+\n
+/** Resets */\n
+\n
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {\n
+\tmargin: 0;\n
+\tpadding: 0;\n
+}\n
+\n
+\n
+/** Header */\n
+\n
+#qunit-header {\n
+\tpadding: 0.5em 0 0.5em 1em;\n
+\n
+\tcolor: #8699A4;\n
+\tbackground-color: #0D3349;\n
+\n
+\tfont-size: 1.5em;\n
+\tline-height: 1em;\n
+\tfont-weight: 400;\n
+\n
+\tborder-radius: 5px 5px 0 0;\n
+}\n
+\n
+#qunit-header a {\n
+\ttext-decoration: none;\n
+\tcolor: #C2CCD1;\n
+}\n
+\n
+#qunit-header a:hover,\n
+#qunit-header a:focus {\n
+\tcolor: #FFF;\n
+}\n
+\n
+#qunit-testrunner-toolbar label {\n
+\tdisplay: inline-block;\n
+\tpadding: 0 0.5em 0 0.1em;\n
+}\n
+\n
+#qunit-banner {\n
+\theight: 5px;\n
+}\n
+\n
+#qunit-testrunner-toolbar {\n
+\tpadding: 0.5em 0 0.5em 2em;\n
+\tcolor: #5E740B;\n
+\tbackground-color: #EEE;\n
+\toverflow: hidden;\n
+}\n
+\n
+#qunit-userAgent {\n
+\tpadding: 0.5em 0 0.5em 2.5em;\n
+\tbackground-color: #2B81AF;\n
+\tcolor: #FFF;\n
+\ttext-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;\n
+}\n
+\n
+#qunit-modulefilter-container {\n
+\tfloat: right;\n
+}\n
+\n
+/** Tests: Pass/Fail */\n
+\n
+#qunit-tests {\n
+\tlist-style-position: inside;\n
+}\n
+\n
+#qunit-tests li {\n
+\tpadding: 0.4em 0.5em 0.4em 2.5em;\n
+\tborder-bottom: 1px solid #FFF;\n
+\tlist-style-position: inside;\n
+}\n
+\n
+#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running  {\n
+\tdisplay: none;\n
+}\n
+\n
+#qunit-tests li strong {\n
+\tcursor: pointer;\n
+}\n
+\n
+#qunit-tests li a {\n
+\tpadding: 0.5em;\n
+\tcolor: #C2CCD1;\n
+\ttext-decoration: none;\n
+}\n
+#qunit-tests li a:hover,\n
+#qunit-tests li a:focus {\n
+\tcolor: #000;\n
+}\n
+\n
+#qunit-tests li .runtime {\n
+\tfloat: right;\n
+\tfont-size: smaller;\n
+}\n
+\n
+.qunit-assert-list {\n
+\tmargin-top: 0.5em;\n
+\tpadding: 0.5em;\n
+\n
+\tbackground-color: #FFF;\n
+\n
+\tborder-radius: 5px;\n
+}\n
+\n
+.qunit-collapsed {\n
+\tdisplay: none;\n
+}\n
+\n
+#qunit-tests table {\n
+\tborder-collapse: collapse;\n
+\tmargin-top: 0.2em;\n
+}\n
+\n
+#qunit-tests th {\n
+\ttext-align: right;\n
+\tvertical-align: top;\n
+\tpadding: 0 0.5em 0 0;\n
+}\n
+\n
+#qunit-tests td {\n
+\tvertical-align: top;\n
+}\n
+\n
+#qunit-tests pre {\n
+\tmargin: 0;\n
+\twhite-space: pre-wrap;\n
+\tword-wrap: break-word;\n
+}\n
+\n
+#qunit-tests del {\n
+\tbackground-color: #E0F2BE;\n
+\tcolor: #374E0C;\n
+\ttext-decoration: none;\n
+}\n
+\n
+#qunit-tests ins {\n
+\tbackground-color: #FFCACA;\n
+\tcolor: #500;\n
+\ttext-decoration: none;\n
+}\n
+\n
+/*** Test Counts */\n
+\n
+#qunit-tests b.counts                       { color: #000; }\n
+#qunit-tests b.passed                       { color: #5E740B; }\n
+#qunit-tests b.failed                       { color: #710909; }\n
+\n
+#qunit-tests li li {\n
+\tpadding: 5px;\n
+\tbackground-color: #FFF;\n
+\tborder-bottom: none;\n
+\tlist-style-position: inside;\n
+}\n
+\n
+/*** Passing Styles */\n
+\n
+#qunit-tests li li.pass {\n
+\tcolor: #3C510C;\n
+\tbackground-color: #FFF;\n
+\tborder-left: 10px solid #C6E746;\n
+}\n
+\n
+#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }\n
+#qunit-tests .pass .test-name               { color: #366097; }\n
+\n
+#qunit-tests .pass .test-actual,\n
+#qunit-tests .pass .test-expected           { color: #999; }\n
+\n
+#qunit-banner.qunit-pass                    { background-color: #C6E746; }\n
+\n
+/*** Failing Styles */\n
+\n
+#qunit-tests li li.fail {\n
+\tcolor: #710909;\n
+\tbackground-color: #FFF;\n
+\tborder-left: 10px solid #EE5757;\n
+\twhite-space: pre;\n
+}\n
+\n
+#qunit-tests > li:last-child {\n
+\tborder-radius: 0 0 5px 5px;\n
+}\n
+\n
+#qunit-tests .fail                          { color: #000; background-color: #EE5757; }\n
+#qunit-tests .fail .test-name,\n
+#qunit-tests .fail .module-name             { color: #000; }\n
+\n
+#qunit-tests .fail .test-actual             { color: #EE5757; }\n
+#qunit-tests .fail .test-expected           { color: #008000; }\n
+\n
+#qunit-banner.qunit-fail                    { background-color: #EE5757; }\n
+\n
+\n
+/** Result */\n
+\n
+#qunit-testresult {\n
+\tpadding: 0.5em 0.5em 0.5em 2.5em;\n
+\n
+\tcolor: #2B81AF;\n
+\tbackground-color: #D2E0E6;\n
+\n
+\tborder-bottom: 1px solid #FFF;\n
+}\n
+#qunit-testresult .module-name {\n
+\tfont-weight: 700;\n
+}\n
+\n
+/** Fixture */\n
+\n
+#qunit-fixture {\n
+\tposition: absolute;\n
+\ttop: -10000px;\n
+\tleft: -10000px;\n
+\twidth: 1000px;\n
+\theight: 1000px;\n
+}\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>4362</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/qunit.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/qunit.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4a074aa7ec2c72526f73cae6f4130398ee5c077b
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/qunit.js.xml
@@ -0,0 +1,2332 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681769.3</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>qunit.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*!\n
+ * QUnit 1.14.0\n
+ * http://qunitjs.com/\n
+ *\n
+ * Copyright 2013 jQuery Foundation and other contributors\n
+ * Released under the MIT license\n
+ * http://jquery.org/license\n
+ *\n
+ * Date: 2014-01-31T16:40Z\n
+ */\n
+\n
+(function( window ) {\n
+\n
+var QUnit,\n
+\tassert,\n
+\tconfig,\n
+\tonErrorFnPrev,\n
+\ttestId = 0,\n
+\tfileName = (sourceFromStacktrace( 0 ) || "" ).replace(/(:\\d+)+\\)?/, "").replace(/.+\\//, ""),\n
+\ttoString = Object.prototype.toString,\n
+\thasOwn = Object.prototype.hasOwnProperty,\n
+\t// Keep a local reference to Date (GH-283)\n
+\tDate = window.Date,\n
+\tsetTimeout = window.setTimeout,\n
+\tclearTimeout = window.clearTimeout,\n
+\tdefined = {\n
+\t\tdocument: typeof window.document !== "undefined",\n
+\t\tsetTimeout: typeof window.setTimeout !== "undefined",\n
+\t\tsessionStorage: (function() {\n
+\t\t\tvar x = "qunit-test-string";\n
+\t\t\ttry {\n
+\t\t\t\tsessionStorage.setItem( x, x );\n
+\t\t\t\tsessionStorage.removeItem( x );\n
+\t\t\t\treturn true;\n
+\t\t\t} catch( e ) {\n
+\t\t\t\treturn false;\n
+\t\t\t}\n
+\t\t}())\n
+\t},\n
+\t/**\n
+\t * Provides a normalized error string, correcting an issue\n
+\t * with IE 7 (and prior) where Error.prototype.toString is\n
+\t * not properly implemented\n
+\t *\n
+\t * Based on http://es5.github.com/#x15.11.4.4\n
+\t *\n
+\t * @param {String|Error} error\n
+\t * @return {String} error message\n
+\t */\n
+\terrorString = function( error ) {\n
+\t\tvar name, message,\n
+\t\t\terrorString = error.toString();\n
+\t\tif ( errorString.substring( 0, 7 ) === "[object" ) {\n
+\t\t\tname = error.name ? error.name.toString() : "Error";\n
+\t\t\tmessage = error.message ? error.message.toString() : "";\n
+\t\t\tif ( name && message ) {\n
+\t\t\t\treturn name + ": " + message;\n
+\t\t\t} else if ( name ) {\n
+\t\t\t\treturn name;\n
+\t\t\t} else if ( message ) {\n
+\t\t\t\treturn message;\n
+\t\t\t} else {\n
+\t\t\t\treturn "Error";\n
+\t\t\t}\n
+\t\t} else {\n
+\t\t\treturn errorString;\n
+\t\t}\n
+\t},\n
+\t/**\n
+\t * Makes a clone of an object using only Array or Object as base,\n
+\t * and copies over the own enumerable properties.\n
+\t *\n
+\t * @param {Object} obj\n
+\t * @return {Object} New object with only the own properties (recursively).\n
+\t */\n
+\tobjectValues = function( obj ) {\n
+\t\t// Grunt 0.3.x uses an older version of jshint that still has jshint/jshint#392.\n
+\t\t/*jshint newcap: false */\n
+\t\tvar key, val,\n
+\t\t\tvals = QUnit.is( "array", obj ) ? [] : {};\n
+\t\tfor ( key in obj ) {\n
+\t\t\tif ( hasOwn.call( obj, key ) ) {\n
+\t\t\t\tval = obj[key];\n
+\t\t\t\tvals[key] = val === Object(val) ? objectValues(val) : val;\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn vals;\n
+\t};\n
+\n
+\n
+// Root QUnit object.\n
+// `QUnit` initialized at top of scope\n
+QUnit = {\n
+\n
+\t// call on start of module test to prepend name to all tests\n
+\tmodule: function( name, testEnvironment ) {\n
+\t\tconfig.currentModule = name;\n
+\t\tconfig.currentModuleTestEnvironment = testEnvironment;\n
+\t\tconfig.modules[name] = true;\n
+\t},\n
+\n
+\tasyncTest: function( testName, expected, callback ) {\n
+\t\tif ( arguments.length === 2 ) {\n
+\t\t\tcallback = expected;\n
+\t\t\texpected = null;\n
+\t\t}\n
+\n
+\t\tQUnit.test( testName, expected, callback, true );\n
+\t},\n
+\n
+\ttest: function( testName, expected, callback, async ) {\n
+\t\tvar test,\n
+\t\t\tnameHtml = "<span class=\'test-name\'>" + escapeText( testName ) + "</span>";\n
+\n
+\t\tif ( arguments.length === 2 ) {\n
+\t\t\tcallback = expected;\n
+\t\t\texpected = null;\n
+\t\t}\n
+\n
+\t\tif ( config.currentModule ) {\n
+\t\t\tnameHtml = "<span class=\'module-name\'>" + escapeText( config.currentModule ) + "</span>: " + nameHtml;\n
+\t\t}\n
+\n
+\t\ttest = new Test({\n
+\t\t\tnameHtml: nameHtml,\n
+\t\t\ttestName: testName,\n
+\t\t\texpected: expected,\n
+\t\t\tasync: async,\n
+\t\t\tcallback: callback,\n
+\t\t\tmodule: config.currentModule,\n
+\t\t\tmoduleTestEnvironment: config.currentModuleTestEnvironment,\n
+\t\t\tstack: sourceFromStacktrace( 2 )\n
+\t\t});\n
+\n
+\t\tif ( !validTest( test ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\ttest.queue();\n
+\t},\n
+\n
+\t// Specify the number of expected assertions to guarantee that failed test (no assertions are run at all) don\'t slip through.\n
+\texpect: function( asserts ) {\n
+\t\tif (arguments.length === 1) {\n
+\t\t\tconfig.current.expected = asserts;\n
+\t\t} else {\n
+\t\t\treturn config.current.expected;\n
+\t\t}\n
+\t},\n
+\n
+\tstart: function( count ) {\n
+\t\t// QUnit hasn\'t been initialized yet.\n
+\t\t// Note: RequireJS (et al) may delay onLoad\n
+\t\tif ( config.semaphore === undefined ) {\n
+\t\t\tQUnit.begin(function() {\n
+\t\t\t\t// This is triggered at the top of QUnit.load, push start() to the event loop, to allow QUnit.load to finish first\n
+\t\t\t\tsetTimeout(function() {\n
+\t\t\t\t\tQUnit.start( count );\n
+\t\t\t\t});\n
+\t\t\t});\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\tconfig.semaphore -= count || 1;\n
+\t\t// don\'t start until equal number of stop-calls\n
+\t\tif ( config.semaphore > 0 ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\t// ignore if start is called more often then stop\n
+\t\tif ( config.semaphore < 0 ) {\n
+\t\t\tconfig.semaphore = 0;\n
+\t\t\tQUnit.pushFailure( "Called start() while already started (QUnit.config.semaphore was 0 already)", null, sourceFromStacktrace(2) );\n
+\t\t\treturn;\n
+\t\t}\n
+\t\t// A slight delay, to avoid any current callbacks\n
+\t\tif ( defined.setTimeout ) {\n
+\t\t\tsetTimeout(function() {\n
+\t\t\t\tif ( config.semaphore > 0 ) {\n
+\t\t\t\t\treturn;\n
+\t\t\t\t}\n
+\t\t\t\tif ( config.timeout ) {\n
+\t\t\t\t\tclearTimeout( config.timeout );\n
+\t\t\t\t}\n
+\n
+\t\t\t\tconfig.blocking = false;\n
+\t\t\t\tprocess( true );\n
+\t\t\t}, 13);\n
+\t\t} else {\n
+\t\t\tconfig.blocking = false;\n
+\t\t\tprocess( true );\n
+\t\t}\n
+\t},\n
+\n
+\tstop: function( count ) {\n
+\t\tconfig.semaphore += count || 1;\n
+\t\tconfig.blocking = true;\n
+\n
+\t\tif ( config.testTimeout && defined.setTimeout ) {\n
+\t\t\tclearTimeout( config.timeout );\n
+\t\t\tconfig.timeout = setTimeout(function() {\n
+\t\t\t\tQUnit.ok( false, "Test timed out" );\n
+\t\t\t\tconfig.semaphore = 1;\n
+\t\t\t\tQUnit.start();\n
+\t\t\t}, config.testTimeout );\n
+\t\t}\n
+\t}\n
+};\n
+\n
+// We use the prototype to distinguish between properties that should\n
+// be exposed as globals (and in exports) and those that shouldn\'t\n
+(function() {\n
+\tfunction F() {}\n
+\tF.prototype = QUnit;\n
+\tQUnit = new F();\n
+\t// Make F QUnit\'s constructor so that we can add to the prototype later\n
+\tQUnit.constructor = F;\n
+}());\n
+\n
+/**\n
+ * Config object: Maintain internal state\n
+ * Later exposed as QUnit.config\n
+ * `config` initialized at top of scope\n
+ */\n
+config = {\n
+\t// The queue of tests to run\n
+\tqueue: [],\n
+\n
+\t// block until document ready\n
+\tblocking: true,\n
+\n
+\t// when enabled, show only failing tests\n
+\t// gets persisted through sessionStorage and can be changed in UI via checkbox\n
+\thidepassed: false,\n
+\n
+\t// by default, run previously failed tests first\n
+\t// very useful in combination with "Hide passed tests" checked\n
+\treorder: true,\n
+\n
+\t// by default, modify document.title when suite is done\n
+\taltertitle: true,\n
+\n
+\t// by default, scroll to top of the page when suite is done\n
+\tscrolltop: true,\n
+\n
+\t// when enabled, all tests must call expect()\n
+\trequireExpects: false,\n
+\n
+\t// add checkboxes that are persisted in the query-string\n
+\t// when enabled, the id is set to `true` as a `QUnit.config` property\n
+\turlConfig: [\n
+\t\t{\n
+\t\t\tid: "noglobals",\n
+\t\t\tlabel: "Check for Globals",\n
+\t\t\ttooltip: "Enabling this will test if any test introduces new properties on the `window` object. Stored as query-strings."\n
+\t\t},\n
+\t\t{\n
+\t\t\tid: "notrycatch",\n
+\t\t\tlabel: "No try-catch",\n
+\t\t\ttooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging exceptions in IE reasonable. Stored as query-strings."\n
+\t\t}\n
+\t],\n
+\n
+\t// Set of all modules.\n
+\tmodules: {},\n
+\n
+\t// logging callback queues\n
+\tbegin: [],\n
+\tdone: [],\n
+\tlog: [],\n
+\ttestStart: [],\n
+\ttestDone: [],\n
+\tmoduleStart: [],\n
+\tmoduleDone: []\n
+};\n
+\n
+// Initialize more QUnit.config and QUnit.urlParams\n
+(function() {\n
+\tvar i, current,\n
+\t\tlocation = window.location || { search: "", protocol: "file:" },\n
+\t\tparams = location.search.slice( 1 ).split( "&" ),\n
+\t\tlength = params.length,\n
+\t\turlParams = {};\n
+\n
+\tif ( params[ 0 ] ) {\n
+\t\tfor ( i = 0; i < length; i++ ) {\n
+\t\t\tcurrent = params[ i ].split( "=" );\n
+\t\t\tcurrent[ 0 ] = decodeURIComponent( current[ 0 ] );\n
+\n
+\t\t\t// allow just a key to turn on a flag, e.g., test.html?noglobals\n
+\t\t\tcurrent[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true;\n
+\t\t\tif ( urlParams[ current[ 0 ] ] ) {\n
+\t\t\t\turlParams[ current[ 0 ] ] = [].concat( urlParams[ current[ 0 ] ], current[ 1 ] );\n
+\t\t\t} else {\n
+\t\t\t\turlParams[ current[ 0 ] ] = current[ 1 ];\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\tQUnit.urlParams = urlParams;\n
+\n
+\t// String search anywhere in moduleName+testName\n
+\tconfig.filter = urlParams.filter;\n
+\n
+\t// Exact match of the module name\n
+\tconfig.module = urlParams.module;\n
+\n
+\tconfig.testNumber = [];\n
+\tif ( urlParams.testNumber ) {\n
+\n
+\t\t// Ensure that urlParams.testNumber is an array\n
+\t\turlParams.testNumber = [].concat( urlParams.testNumber );\n
+\t\tfor ( i = 0; i < urlParams.testNumber.length; i++ ) {\n
+\t\t\tcurrent = urlParams.testNumber[ i ];\n
+\t\t\tconfig.testNumber.push( parseInt( current, 10 ) );\n
+\t\t}\n
+\t}\n
+\n
+\t// Figure out if we\'re running the tests from a server or not\n
+\tQUnit.isLocal = location.protocol === "file:";\n
+}());\n
+\n
+extend( QUnit, {\n
+\n
+\tconfig: config,\n
+\n
+\t// Initialize the configuration options\n
+\tinit: function() {\n
+\t\textend( config, {\n
+\t\t\tstats: { all: 0, bad: 0 },\n
+\t\t\tmoduleStats: { all: 0, bad: 0 },\n
+\t\t\tstarted: +new Date(),\n
+\t\t\tupdateRate: 1000,\n
+\t\t\tblocking: false,\n
+\t\t\tautostart: true,\n
+\t\t\tautorun: false,\n
+\t\t\tfilter: "",\n
+\t\t\tqueue: [],\n
+\t\t\tsemaphore: 1\n
+\t\t});\n
+\n
+\t\tvar tests, banner, result,\n
+\t\t\tqunit = id( "qunit" );\n
+\n
+\t\tif ( qunit ) {\n
+\t\t\tqunit.innerHTML =\n
+\t\t\t\t"<h1 id=\'qunit-header\'>" + escapeText( document.title ) + "</h1>" +\n
+\t\t\t\t"<h2 id=\'qunit-banner\'></h2>" +\n
+\t\t\t\t"<div id=\'qunit-testrunner-toolbar\'></div>" +\n
+\t\t\t\t"<h2 id=\'qunit-userAgent\'></h2>" +\n
+\t\t\t\t"<ol id=\'qunit-tests\'></ol>";\n
+\t\t}\n
+\n
+\t\ttests = id( "qunit-tests" );\n
+\t\tbanner = id( "qunit-banner" );\n
+\t\tresult = id( "qunit-testresult" );\n
+\n
+\t\tif ( tests ) {\n
+\t\t\ttests.innerHTML = "";\n
+\t\t}\n
+\n
+\t\tif ( banner ) {\n
+\t\t\tbanner.className = "";\n
+\t\t}\n
+\n
+\t\tif ( result ) {\n
+\t\t\tresult.parentNode.removeChild( result );\n
+\t\t}\n
+\n
+\t\tif ( tests ) {\n
+\t\t\tresult = document.createElement( "p" );\n
+\t\t\tresult.id = "qunit-testresult";\n
+\t\t\tresult.className = "result";\n
+\t\t\ttests.parentNode.insertBefore( result, tests );\n
+\t\t\tresult.innerHTML = "Running...<br/>&nbsp;";\n
+\t\t}\n
+\t},\n
+\n
+\t// Resets the test setup. Useful for tests that modify the DOM.\n
+\t/*\n
+\tDEPRECATED: Use multiple tests instead of resetting inside a test.\n
+\tUse testStart or testDone for custom cleanup.\n
+\tThis method will throw an error in 2.0, and will be removed in 2.1\n
+\t*/\n
+\treset: function() {\n
+\t\tvar fixture = id( "qunit-fixture" );\n
+\t\tif ( fixture ) {\n
+\t\t\tfixture.innerHTML = config.fixture;\n
+\t\t}\n
+\t},\n
+\n
+\t// Safe object type checking\n
+\tis: function( type, obj ) {\n
+\t\treturn QUnit.objectType( obj ) === type;\n
+\t},\n
+\n
+\tobjectType: function( obj ) {\n
+\t\tif ( typeof obj === "undefined" ) {\n
+\t\t\treturn "undefined";\n
+\t\t}\n
+\n
+\t\t// Consider: typeof null === object\n
+\t\tif ( obj === null ) {\n
+\t\t\treturn "null";\n
+\t\t}\n
+\n
+\t\tvar match = toString.call( obj ).match(/^\\[object\\s(.*)\\]$/),\n
+\t\t\ttype = match && match[1] || "";\n
+\n
+\t\tswitch ( type ) {\n
+\t\t\tcase "Number":\n
+\t\t\t\tif ( isNaN(obj) ) {\n
+\t\t\t\t\treturn "nan";\n
+\t\t\t\t}\n
+\t\t\t\treturn "number";\n
+\t\t\tcase "String":\n
+\t\t\tcase "Boolean":\n
+\t\t\tcase "Array":\n
+\t\t\tcase "Date":\n
+\t\t\tcase "RegExp":\n
+\t\t\tcase "Function":\n
+\t\t\t\treturn type.toLowerCase();\n
+\t\t}\n
+\t\tif ( typeof obj === "object" ) {\n
+\t\t\treturn "object";\n
+\t\t}\n
+\t\treturn undefined;\n
+\t},\n
+\n
+\tpush: function( result, actual, expected, message ) {\n
+\t\tif ( !config.current ) {\n
+\t\t\tthrow new Error( "assertion outside test context, was " + sourceFromStacktrace() );\n
+\t\t}\n
+\n
+\t\tvar output, source,\n
+\t\t\tdetails = {\n
+\t\t\t\tmodule: config.current.module,\n
+\t\t\t\tname: config.current.testName,\n
+\t\t\t\tresult: result,\n
+\t\t\t\tmessage: message,\n
+\t\t\t\tactual: actual,\n
+\t\t\t\texpected: expected\n
+\t\t\t};\n
+\n
+\t\tmessage = escapeText( message ) || ( result ? "okay" : "failed" );\n
+\t\tmessage = "<span class=\'test-message\'>" + message + "</span>";\n
+\t\toutput = message;\n
+\n
+\t\tif ( !result ) {\n
+\t\t\texpected = escapeText( QUnit.jsDump.parse(expected) );\n
+\t\t\tactual = escapeText( QUnit.jsDump.parse(actual) );\n
+\t\t\toutput += "<table><tr class=\'test-expected\'><th>Expected: </th><td><pre>" + expected + "</pre></td></tr>";\n
+\n
+\t\t\tif ( actual !== expected ) {\n
+\t\t\t\toutput += "<tr class=\'test-actual\'><th>Result: </th><td><pre>" + actual + "</pre></td></tr>";\n
+\t\t\t\toutput += "<tr class=\'test-diff\'><th>Diff: </th><td><pre>" + QUnit.diff( expected, actual ) + "</pre></td></tr>";\n
+\t\t\t}\n
+\n
+\t\t\tsource = sourceFromStacktrace();\n
+\n
+\t\t\tif ( source ) {\n
+\t\t\t\tdetails.source = source;\n
+\t\t\t\toutput += "<tr class=\'test-source\'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";\n
+\t\t\t}\n
+\n
+\t\t\toutput += "</table>";\n
+\t\t}\n
+\n
+\t\trunLoggingCallbacks( "log", QUnit, details );\n
+\n
+\t\tconfig.current.assertions.push({\n
+\t\t\tresult: !!result,\n
+\t\t\tmessage: output\n
+\t\t});\n
+\t},\n
+\n
+\tpushFailure: function( message, source, actual ) {\n
+\t\tif ( !config.current ) {\n
+\t\t\tthrow new Error( "pushFailure() assertion outside test context, was " + sourceFromStacktrace(2) );\n
+\t\t}\n
+\n
+\t\tvar output,\n
+\t\t\tdetails = {\n
+\t\t\t\tmodule: config.current.module,\n
+\t\t\t\tname: config.current.testName,\n
+\t\t\t\tresult: false,\n
+\t\t\t\tmessage: message\n
+\t\t\t};\n
+\n
+\t\tmessage = escapeText( message ) || "error";\n
+\t\tmessage = "<span class=\'test-message\'>" + message + "</span>";\n
+\t\toutput = message;\n
+\n
+\t\toutput += "<table>";\n
+\n
+\t\tif ( actual ) {\n
+\t\t\toutput += "<tr class=\'test-actual\'><th>Result: </th><td><pre>" + escapeText( actual ) + "</pre></td></tr>";\n
+\t\t}\n
+\n
+\t\tif ( source ) {\n
+\t\t\tdetails.source = source;\n
+\t\t\toutput += "<tr class=\'test-source\'><th>Source: </th><td><pre>" + escapeText( source ) + "</pre></td></tr>";\n
+\t\t}\n
+\n
+\t\toutput += "</table>";\n
+\n
+\t\trunLoggingCallbacks( "log", QUnit, details );\n
+\n
+\t\tconfig.current.assertions.push({\n
+\t\t\tresult: false,\n
+\t\t\tmessage: output\n
+\t\t});\n
+\t},\n
+\n
+\turl: function( params ) {\n
+\t\tparams = extend( extend( {}, QUnit.urlParams ), params );\n
+\t\tvar key,\n
+\t\t\tquerystring = "?";\n
+\n
+\t\tfor ( key in params ) {\n
+\t\t\tif ( hasOwn.call( params, key ) ) {\n
+\t\t\t\tquerystring += encodeURIComponent( key ) + "=" +\n
+\t\t\t\t\tencodeURIComponent( params[ key ] ) + "&";\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn window.location.protocol + "//" + window.location.host +\n
+\t\t\twindow.location.pathname + querystring.slice( 0, -1 );\n
+\t},\n
+\n
+\textend: extend,\n
+\tid: id,\n
+\taddEvent: addEvent,\n
+\taddClass: addClass,\n
+\thasClass: hasClass,\n
+\tremoveClass: removeClass\n
+\t// load, equiv, jsDump, diff: Attached later\n
+});\n
+\n
+/**\n
+ * @deprecated: Created for backwards compatibility with test runner that set the hook function\n
+ * into QUnit.{hook}, instead of invoking it and passing the hook function.\n
+ * QUnit.constructor is set to the empty F() above so that we can add to it\'s prototype here.\n
+ * Doing this allows us to tell if the following methods have been overwritten on the actual\n
+ * QUnit object.\n
+ */\n
+extend( QUnit.constructor.prototype, {\n
+\n
+\t// Logging callbacks; all receive a single argument with the listed properties\n
+\t// run test/logs.html for any related changes\n
+\tbegin: registerLoggingCallback( "begin" ),\n
+\n
+\t// done: { failed, passed, total, runtime }\n
+\tdone: registerLoggingCallback( "done" ),\n
+\n
+\t// log: { result, actual, expected, message }\n
+\tlog: registerLoggingCallback( "log" ),\n
+\n
+\t// testStart: { name }\n
+\ttestStart: registerLoggingCallback( "testStart" ),\n
+\n
+\t// testDone: { name, failed, passed, total, runtime }\n
+\ttestDone: registerLoggingCallback( "testDone" ),\n
+\n
+\t// moduleStart: { name }\n
+\tmoduleStart: registerLoggingCallback( "moduleStart" ),\n
+\n
+\t// moduleDone: { name, failed, passed, total }\n
+\tmoduleDone: registerLoggingCallback( "moduleDone" )\n
+});\n
+\n
+if ( !defined.document || document.readyState === "complete" ) {\n
+\tconfig.autorun = true;\n
+}\n
+\n
+QUnit.load = function() {\n
+\trunLoggingCallbacks( "begin", QUnit, {} );\n
+\n
+\t// Initialize the config, saving the execution queue\n
+\tvar banner, filter, i, j, label, len, main, ol, toolbar, val, selection,\n
+\t\turlConfigContainer, moduleFilter, userAgent,\n
+\t\tnumModules = 0,\n
+\t\tmoduleNames = [],\n
+\t\tmoduleFilterHtml = "",\n
+\t\turlConfigHtml = "",\n
+\t\toldconfig = extend( {}, config );\n
+\n
+\tQUnit.init();\n
+\textend(config, oldconfig);\n
+\n
+\tconfig.blocking = false;\n
+\n
+\tlen = config.urlConfig.length;\n
+\n
+\tfor ( i = 0; i < len; i++ ) {\n
+\t\tval = config.urlConfig[i];\n
+\t\tif ( typeof val === "string" ) {\n
+\t\t\tval = {\n
+\t\t\t\tid: val,\n
+\t\t\t\tlabel: val\n
+\t\t\t};\n
+\t\t}\n
+\t\tconfig[ val.id ] = QUnit.urlParams[ val.id ];\n
+\t\tif ( !val.value || typeof val.value === "string" ) {\n
+\t\t\turlConfigHtml += "<input id=\'qunit-urlconfig-" + escapeText( val.id ) +\n
+\t\t\t\t"\' name=\'" + escapeText( val.id ) +\n
+\t\t\t\t"\' type=\'checkbox\'" +\n
+\t\t\t\t( val.value ? " value=\'" + escapeText( val.value ) + "\'" : "" ) +\n
+\t\t\t\t( config[ val.id ] ? " checked=\'checked\'" : "" ) +\n
+\t\t\t\t" title=\'" + escapeText( val.tooltip ) +\n
+\t\t\t\t"\'><label for=\'qunit-urlconfig-" + escapeText( val.id ) +\n
+\t\t\t\t"\' title=\'" + escapeText( val.tooltip ) + "\'>" + val.label + "</label>";\n
+\t\t} else {\n
+\t\t\turlConfigHtml += "<label for=\'qunit-urlconfig-" + escapeText( val.id ) +\n
+\t\t\t\t"\' title=\'" + escapeText( val.tooltip ) +\n
+\t\t\t\t"\'>" + val.label +\n
+\t\t\t\t": </label><select id=\'qunit-urlconfig-" + escapeText( val.id ) +\n
+\t\t\t\t"\' name=\'" + escapeText( val.id ) +\n
+\t\t\t\t"\' title=\'" + escapeText( val.tooltip ) +\n
+\t\t\t\t"\'><option></option>";\n
+\t\t\tselection = false;\n
+\t\t\tif ( QUnit.is( "array", val.value ) ) {\n
+\t\t\t\tfor ( j = 0; j < val.value.length; j++ ) {\n
+\t\t\t\t\turlConfigHtml += "<option value=\'" + escapeText( val.value[j] ) + "\'" +\n
+\t\t\t\t\t\t( config[ val.id ] === val.value[j] ?\n
+\t\t\t\t\t\t\t(selection = true) && " selected=\'selected\'" :\n
+\t\t\t\t\t\t\t"" ) +\n
+\t\t\t\t\t\t">" + escapeText( val.value[j] ) + "</option>";\n
+\t\t\t\t}\n
+\t\t\t} else {\n
+\t\t\t\tfor ( j in val.value ) {\n
+\t\t\t\t\tif ( hasOwn.call( val.value, j ) ) {\n
+\t\t\t\t\t\turlConfigHtml += "<option value=\'" + escapeText( j ) + "\'" +\n
+\t\t\t\t\t\t\t( config[ val.id ] === j ?\n
+\t\t\t\t\t\t\t\t(selection = true) && " selected=\'selected\'" :\n
+\t\t\t\t\t\t\t\t"" ) +\n
+\t\t\t\t\t\t\t">" + escapeText( val.value[j] ) + "</option>";\n
+\t\t\t\t\t}\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t\tif ( config[ val.id ] && !selection ) {\n
+\t\t\t\turlConfigHtml += "<option value=\'" + escapeText( config[ val.id ] ) +\n
+\t\t\t\t\t"\' selected=\'selected\' disabled=\'disabled\'>" +\n
+\t\t\t\t\tescapeText( config[ val.id ] ) +\n
+\t\t\t\t\t"</option>";\n
+\t\t\t}\n
+\t\t\turlConfigHtml += "</select>";\n
+\t\t}\n
+\t}\n
+\tfor ( i in config.modules ) {\n
+\t\tif ( config.modules.hasOwnProperty( i ) ) {\n
+\t\t\tmoduleNames.push(i);\n
+\t\t}\n
+\t}\n
+\tnumModules = moduleNames.length;\n
+\tmoduleNames.sort( function( a, b ) {\n
+\t\treturn a.localeCompare( b );\n
+\t});\n
+\tmoduleFilterHtml += "<label for=\'qunit-modulefilter\'>Module: </label><select id=\'qunit-modulefilter\' name=\'modulefilter\'><option value=\'\' " +\n
+\t\t( config.module === undefined  ? "selected=\'selected\'" : "" ) +\n
+\t\t">< All Modules ></option>";\n
+\n
+\n
+\tfor ( i = 0; i < numModules; i++) {\n
+\t\t\tmoduleFilterHtml += "<option value=\'" + escapeText( encodeURIComponent(moduleNames[i]) ) + "\' " +\n
+\t\t\t\t( config.module === moduleNames[i] ? "selected=\'selected\'" : "" ) +\n
+\t\t\t\t">" + escapeText(moduleNames[i]) + "</option>";\n
+\t}\n
+\tmoduleFilterHtml += "</select>";\n
+\n
+\t// `userAgent` initialized at top of scope\n
+\tuserAgent = id( "qunit-userAgent" );\n
+\tif ( userAgent ) {\n
+\t\tuserAgent.innerHTML = navigator.userAgent;\n
+\t}\n
+\n
+\t// `banner` initialized at top of scope\n
+\tbanner = id( "qunit-header" );\n
+\tif ( banner ) {\n
+\t\tbanner.innerHTML = "<a href=\'" + QUnit.url({ filter: undefined, module: undefined, testNumber: undefined }) + "\'>" + banner.innerHTML + "</a> ";\n
+\t}\n
+\n
+\t// `toolbar` initialized at top of scope\n
+\ttoolbar = id( "qunit-testrunner-toolbar" );\n
+\tif ( toolbar ) {\n
+\t\t// `filter` initialized at top of scope\n
+\t\tfilter = document.createElement( "input" );\n
+\t\tfilter.type = "checkbox";\n
+\t\tfilter.id = "qunit-filter-pass";\n
+\n
+\t\taddEvent( filter, "click", function() {\n
+\t\t\tvar tmp,\n
+\t\t\t\tol = id( "qunit-tests" );\n
+\n
+\t\t\tif ( filter.checked ) {\n
+\t\t\t\tol.className = ol.className + " hidepass";\n
+\t\t\t} else {\n
+\t\t\t\ttmp = " " + ol.className.replace( /[\\n\\t\\r]/g, " " ) + " ";\n
+\t\t\t\tol.className = tmp.replace( / hidepass /, " " );\n
+\t\t\t}\n
+\t\t\tif ( defined.sessionStorage ) {\n
+\t\t\t\tif (filter.checked) {\n
+\t\t\t\t\tsessionStorage.setItem( "qunit-filter-passed-tests", "true" );\n
+\t\t\t\t} else {\n
+\t\t\t\t\tsessionStorage.removeItem( "qunit-filter-passed-tests" );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t});\n
+\n
+\t\tif ( config.hidepassed || defined.sessionStorage && sessionStorage.getItem( "qunit-filter-passed-tests" ) ) {\n
+\t\t\tfilter.checked = true;\n
+\t\t\t// `ol` initialized at top of scope\n
+\t\t\tol = id( "qunit-tests" );\n
+\t\t\tol.className = ol.className + " hidepass";\n
+\t\t}\n
+\t\ttoolbar.appendChild( filter );\n
+\n
+\t\t// `label` initialized at top of scope\n
+\t\tlabel = document.createElement( "label" );\n
+\t\tlabel.setAttribute( "for", "qunit-filter-pass" );\n
+\t\tlabel.setAttribute( "title", "Only show tests and assertions that fail. Stored in sessionStorage." );\n
+\t\tlabel.innerHTML = "Hide passed tests";\n
+\t\ttoolbar.appendChild( label );\n
+\n
+\t\turlConfigContainer = document.createElement("span");\n
+\t\turlConfigContainer.innerHTML = urlConfigHtml;\n
+\t\t// For oldIE support:\n
+\t\t// * Add handlers to the individual elements instead of the container\n
+\t\t// * Use "click" instead of "change" for checkboxes\n
+\t\t// * Fallback from event.target to event.srcElement\n
+\t\taddEvents( urlConfigContainer.getElementsByTagName("input"), "click", function( event ) {\n
+\t\t\tvar params = {},\n
+\t\t\t\ttarget = event.target || event.srcElement;\n
+\t\t\tparams[ target.name ] = target.checked ?\n
+\t\t\t\ttarget.defaultValue || true :\n
+\t\t\t\tundefined;\n
+\t\t\twindow.location = QUnit.url( params );\n
+\t\t});\n
+\t\taddEvents( urlConfigContainer.getElementsByTagName("select"), "change", function( event ) {\n
+\t\t\tvar params = {},\n
+\t\t\t\ttarget = event.target || event.srcElement;\n
+\t\t\tparams[ target.name ] = target.options[ target.selectedIndex ].value || undefined;\n
+\t\t\twindow.location = QUnit.url( params );\n
+\t\t});\n
+\t\ttoolbar.appendChild( urlConfigContainer );\n
+\n
+\t\tif (numModules > 1) {\n
+\t\t\tmoduleFilter = document.createElement( "span" );\n
+\t\t\tmoduleFilter.setAttribute( "id", "qunit-modulefilter-container" );\n
+\t\t\tmoduleFilter.innerHTML = moduleFilterHtml;\n
+\t\t\taddEvent( moduleFilter.lastChild, "change", function() {\n
+\t\t\t\tvar selectBox = moduleFilter.getElementsByTagName("select")[0],\n
+\t\t\t\t\tselectedModule = decodeURIComponent(selectBox.options[selectBox.selectedIndex].value);\n
+\n
+\t\t\t\twindow.location = QUnit.url({\n
+\t\t\t\t\tmodule: ( selectedModule === "" ) ? undefined : selectedModule,\n
+\t\t\t\t\t// Remove any existing filters\n
+\t\t\t\t\tfilter: undefined,\n
+\t\t\t\t\ttestNumber: undefined\n
+\t\t\t\t});\n
+\t\t\t});\n
+\t\t\ttoolbar.appendChild(moduleFilter);\n
+\t\t}\n
+\t}\n
+\n
+\t// `main` initialized at top of scope\n
+\tmain = id( "qunit-fixture" );\n
+\tif ( main ) {\n
+\t\tconfig.fixture = main.innerHTML;\n
+\t}\n
+\n
+\tif ( config.autostart ) {\n
+\t\tQUnit.start();\n
+\t}\n
+};\n
+\n
+if ( defined.document ) {\n
+\taddEvent( window, "load", QUnit.load );\n
+}\n
+\n
+// `onErrorFnPrev` initialized at top of scope\n
+// Preserve other handlers\n
+onErrorFnPrev = window.onerror;\n
+\n
+// Cover uncaught exceptions\n
+// Returning true will suppress the default browser handler,\n
+// returning false will let it run.\n
+window.onerror = function ( error, filePath, linerNr ) {\n
+\tvar ret = false;\n
+\tif ( onErrorFnPrev ) {\n
+\t\tret = onErrorFnPrev( error, filePath, linerNr );\n
+\t}\n
+\n
+\t// Treat return value as window.onerror itself does,\n
+\t// Only do our handling if not suppressed.\n
+\tif ( ret !== true ) {\n
+\t\tif ( QUnit.config.current ) {\n
+\t\t\tif ( QUnit.config.current.ignoreGlobalErrors ) {\n
+\t\t\t\treturn true;\n
+\t\t\t}\n
+\t\t\tQUnit.pushFailure( error, filePath + ":" + linerNr );\n
+\t\t} else {\n
+\t\t\tQUnit.test( "global failure", extend( function() {\n
+\t\t\t\tQUnit.pushFailure( error, filePath + ":" + linerNr );\n
+\t\t\t}, { validTest: validTest } ) );\n
+\t\t}\n
+\t\treturn false;\n
+\t}\n
+\n
+\treturn ret;\n
+};\n
+\n
+function done() {\n
+\tconfig.autorun = true;\n
+\n
+\t// Log the last module results\n
+\tif ( config.previousModule ) {\n
+\t\trunLoggingCallbacks( "moduleDone", QUnit, {\n
+\t\t\tname: config.previousModule,\n
+\t\t\tfailed: config.moduleStats.bad,\n
+\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n
+\t\t\ttotal: config.moduleStats.all\n
+\t\t});\n
+\t}\n
+\tdelete config.previousModule;\n
+\n
+\tvar i, key,\n
+\t\tbanner = id( "qunit-banner" ),\n
+\t\ttests = id( "qunit-tests" ),\n
+\t\truntime = +new Date() - config.started,\n
+\t\tpassed = config.stats.all - config.stats.bad,\n
+\t\thtml = [\n
+\t\t\t"Tests completed in ",\n
+\t\t\truntime,\n
+\t\t\t" milliseconds.<br/>",\n
+\t\t\t"<span class=\'passed\'>",\n
+\t\t\tpassed,\n
+\t\t\t"</span> assertions of <span class=\'total\'>",\n
+\t\t\tconfig.stats.all,\n
+\t\t\t"</span> passed, <span class=\'failed\'>",\n
+\t\t\tconfig.stats.bad,\n
+\t\t\t"</span> failed."\n
+\t\t].join( "" );\n
+\n
+\tif ( banner ) {\n
+\t\tbanner.className = ( config.stats.bad ? "qunit-fail" : "qunit-pass" );\n
+\t}\n
+\n
+\tif ( tests ) {\n
+\t\tid( "qunit-testresult" ).innerHTML = html;\n
+\t}\n
+\n
+\tif ( config.altertitle && defined.document && document.title ) {\n
+\t\t// show ✖ for good, ✔ for bad suite result in title\n
+\t\t// use escape sequences in case file gets loaded with non-utf-8-charset\n
+\t\tdocument.title = [\n
+\t\t\t( config.stats.bad ? "\\u2716" : "\\u2714" ),\n
+\t\t\tdocument.title.replace( /^[\\u2714\\u2716] /i, "" )\n
+\t\t].join( " " );\n
+\t}\n
+\n
+\t// clear own sessionStorage items if all tests passed\n
+\tif ( config.reorder && defined.sessionStorage && config.stats.bad === 0 ) {\n
+\t\t// `key` & `i` initialized at top of scope\n
+\t\tfor ( i = 0; i < sessionStorage.length; i++ ) {\n
+\t\t\tkey = sessionStorage.key( i++ );\n
+\t\t\tif ( key.indexOf( "qunit-test-" ) === 0 ) {\n
+\t\t\t\tsessionStorage.removeItem( key );\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\t// scroll back to top to show results\n
+\tif ( config.scrolltop && window.scrollTo ) {\n
+\t\twindow.scrollTo(0, 0);\n
+\t}\n
+\n
+\trunLoggingCallbacks( "done", QUnit, {\n
+\t\tfailed: config.stats.bad,\n
+\t\tpassed: passed,\n
+\t\ttotal: config.stats.all,\n
+\t\truntime: runtime\n
+\t});\n
+}\n
+\n
+/** @return Boolean: true if this test should be ran */\n
+function validTest( test ) {\n
+\tvar include,\n
+\t\tfilter = config.filter && config.filter.toLowerCase(),\n
+\t\tmodule = config.module && config.module.toLowerCase(),\n
+\t\tfullName = ( test.module + ": " + test.testName ).toLowerCase();\n
+\n
+\t// Internally-generated tests are always valid\n
+\tif ( test.callback && test.callback.validTest === validTest ) {\n
+\t\tdelete test.callback.validTest;\n
+\t\treturn true;\n
+\t}\n
+\n
+\tif ( config.testNumber.length > 0 ) {\n
+\t\tif ( inArray( test.testNumber, config.testNumber ) < 0 ) {\n
+\t\t\treturn false;\n
+\t\t}\n
+\t}\n
+\n
+\tif ( module && ( !test.module || test.module.toLowerCase() !== module ) ) {\n
+\t\treturn false;\n
+\t}\n
+\n
+\tif ( !filter ) {\n
+\t\treturn true;\n
+\t}\n
+\n
+\tinclude = filter.charAt( 0 ) !== "!";\n
+\tif ( !include ) {\n
+\t\tfilter = filter.slice( 1 );\n
+\t}\n
+\n
+\t// If the filter matches, we need to honour include\n
+\tif ( fullName.indexOf( filter ) !== -1 ) {\n
+\t\treturn include;\n
+\t}\n
+\n
+\t// Otherwise, do the opposite\n
+\treturn !include;\n
+}\n
+\n
+// so far supports only Firefox, Chrome and Opera (buggy), Safari (for real exceptions)\n
+// Later Safari and IE10 are supposed to support error.stack as well\n
+// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack\n
+function extractStacktrace( e, offset ) {\n
+\toffset = offset === undefined ? 3 : offset;\n
+\n
+\tvar stack, include, i;\n
+\n
+\tif ( e.stacktrace ) {\n
+\t\t// Opera\n
+\t\treturn e.stacktrace.split( "\\n" )[ offset + 3 ];\n
+\t} else if ( e.stack ) {\n
+\t\t// Firefox, Chrome\n
+\t\tstack = e.stack.split( "\\n" );\n
+\t\tif (/^error$/i.test( stack[0] ) ) {\n
+\t\t\tstack.shift();\n
+\t\t}\n
+\t\tif ( fileName ) {\n
+\t\t\tinclude = [];\n
+\t\t\tfor ( i = offset; i < stack.length; i++ ) {\n
+\t\t\t\tif ( stack[ i ].indexOf( fileName ) !== -1 ) {\n
+\t\t\t\t\tbreak;\n
+\t\t\t\t}\n
+\t\t\t\tinclude.push( stack[ i ] );\n
+\t\t\t}\n
+\t\t\tif ( include.length ) {\n
+\t\t\t\treturn include.join( "\\n" );\n
+\t\t\t}\n
+\t\t}\n
+\t\treturn stack[ offset ];\n
+\t} else if ( e.sourceURL ) {\n
+\t\t// Safari, PhantomJS\n
+\t\t// hopefully one day Safari provides actual stacktraces\n
+\t\t// exclude useless self-reference for generated Error objects\n
+\t\tif ( /qunit.js$/.test( e.sourceURL ) ) {\n
+\t\t\treturn;\n
+\t\t}\n
+\t\t// for actual exceptions, this is useful\n
+\t\treturn e.sourceURL + ":" + e.line;\n
+\t}\n
+}\n
+function sourceFromStacktrace( offset ) {\n
+\ttry {\n
+\t\tthrow new Error();\n
+\t} catch ( e ) {\n
+\t\treturn extractStacktrace( e, offset );\n
+\t}\n
+}\n
+\n
+/**\n
+ * Escape text for attribute or text content.\n
+ */\n
+function escapeText( s ) {\n
+\tif ( !s ) {\n
+\t\treturn "";\n
+\t}\n
+\ts = s + "";\n
+\t// Both single quotes and double quotes (for attributes)\n
+\treturn s.replace( /[\'"<>&]/g, function( s ) {\n
+\t\tswitch( s ) {\n
+\t\t\tcase "\'":\n
+\t\t\t\treturn "&#039;";\n
+\t\t\tcase "\\"":\n
+\t\t\t\treturn "&quot;";\n
+\t\t\tcase "<":\n
+\t\t\t\treturn "&lt;";\n
+\t\t\tcase ">":\n
+\t\t\t\treturn "&gt;";\n
+\t\t\tcase "&":\n
+\t\t\t\treturn "&amp;";\n
+\t\t}\n
+\t});\n
+}\n
+\n
+function synchronize( callback, last ) {\n
+\tconfig.queue.push( callback );\n
+\n
+\tif ( config.autorun && !config.blocking ) {\n
+\t\tprocess( last );\n
+\t}\n
+}\n
+\n
+function process( last ) {\n
+\tfunction next() {\n
+\t\tprocess( last );\n
+\t}\n
+\tvar start = new Date().getTime();\n
+\tconfig.depth = config.depth ? config.depth + 1 : 1;\n
+\n
+\twhile ( config.queue.length && !config.blocking ) {\n
+\t\tif ( !defined.setTimeout || config.updateRate <= 0 || ( ( new Date().getTime() - start ) < config.updateRate ) ) {\n
+\t\t\tconfig.queue.shift()();\n
+\t\t} else {\n
+\t\t\tsetTimeout( next, 13 );\n
+\t\t\tbreak;\n
+\t\t}\n
+\t}\n
+\tconfig.depth--;\n
+\tif ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {\n
+\t\tdone();\n
+\t}\n
+}\n
+\n
+function saveGlobal() {\n
+\tconfig.pollution = [];\n
+\n
+\tif ( config.noglobals ) {\n
+\t\tfor ( var key in window ) {\n
+\t\t\tif ( hasOwn.call( window, key ) ) {\n
+\t\t\t\t// in Opera sometimes DOM element ids show up here, ignore them\n
+\t\t\t\tif ( /^qunit-test-output/.test( key ) ) {\n
+\t\t\t\t\tcontinue;\n
+\t\t\t\t}\n
+\t\t\t\tconfig.pollution.push( key );\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+}\n
+\n
+function checkPollution() {\n
+\tvar newGlobals,\n
+\t\tdeletedGlobals,\n
+\t\told = config.pollution;\n
+\n
+\tsaveGlobal();\n
+\n
+\tnewGlobals = diff( config.pollution, old );\n
+\tif ( newGlobals.length > 0 ) {\n
+\t\tQUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join(", ") );\n
+\t}\n
+\n
+\tdeletedGlobals = diff( old, config.pollution );\n
+\tif ( deletedGlobals.length > 0 ) {\n
+\t\tQUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join(", ") );\n
+\t}\n
+}\n
+\n
+// returns a new Array with the elements that are in a but not in b\n
+function diff( a, b ) {\n
+\tvar i, j,\n
+\t\tresult = a.slice();\n
+\n
+\tfor ( i = 0; i < result.length; i++ ) {\n
+\t\tfor ( j = 0; j < b.length; j++ ) {\n
+\t\t\tif ( result[i] === b[j] ) {\n
+\t\t\t\tresult.splice( i, 1 );\n
+\t\t\t\ti--;\n
+\t\t\t\tbreak;\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\treturn result;\n
+}\n
+\n
+function extend( a, b ) {\n
+\tfor ( var prop in b ) {\n
+\t\tif ( hasOwn.call( b, prop ) ) {\n
+\t\t\t// Avoid "Member not found" error in IE8 caused by messing with window.constructor\n
+\t\t\tif ( !( prop === "constructor" && a === window ) ) {\n
+\t\t\t\tif ( b[ prop ] === undefined ) {\n
+\t\t\t\t\tdelete a[ prop ];\n
+\t\t\t\t} else {\n
+\t\t\t\t\ta[ prop ] = b[ prop ];\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\treturn a;\n
+}\n
+\n
+/**\n
+ * @param {HTMLElement} elem\n
+ * @param {string} type\n
+ * @param {Function} fn\n
+ */\n
+function addEvent( elem, type, fn ) {\n
+\tif ( elem.addEventListener ) {\n
+\n
+\t\t// Standards-based browsers\n
+\t\telem.addEventListener( type, fn, false );\n
+\t} else if ( elem.attachEvent ) {\n
+\n
+\t\t// support: IE <9\n
+\t\telem.attachEvent( "on" + type, fn );\n
+\t} else {\n
+\n
+\t\t// Caller must ensure support for event listeners is present\n
+\t\tthrow new Error( "addEvent() was called in a context without event listener support" );\n
+\t}\n
+}\n
+\n
+/**\n
+ * @param {Array|NodeList} elems\n
+ * @param {string} type\n
+ * @param {Function} fn\n
+ */\n
+function addEvents( elems, type, fn ) {\n
+\tvar i = elems.length;\n
+\twhile ( i-- ) {\n
+\t\taddEvent( elems[i], type, fn );\n
+\t}\n
+}\n
+\n
+function hasClass( elem, name ) {\n
+\treturn (" " + elem.className + " ").indexOf(" " + name + " ") > -1;\n
+}\n
+\n
+function addClass( elem, name ) {\n
+\tif ( !hasClass( elem, name ) ) {\n
+\t\telem.className += (elem.className ? " " : "") + name;\n
+\t}\n
+}\n
+\n
+function removeClass( elem, name ) {\n
+\tvar set = " " + elem.className + " ";\n
+\t// Class name may appear multiple times\n
+\twhile ( set.indexOf(" " + name + " ") > -1 ) {\n
+\t\tset = set.replace(" " + name + " " , " ");\n
+\t}\n
+\t// If possible, trim it for prettiness, but not necessarily\n
+\telem.className = typeof set.trim === "function" ? set.trim() : set.replace(/^\\s+|\\s+$/g, "");\n
+}\n
+\n
+function id( name ) {\n
+\treturn defined.document && document.getElementById && document.getElementById( name );\n
+}\n
+\n
+function registerLoggingCallback( key ) {\n
+\treturn function( callback ) {\n
+\t\tconfig[key].push( callback );\n
+\t};\n
+}\n
+\n
+// Supports deprecated method of completely overwriting logging callbacks\n
+function runLoggingCallbacks( key, scope, args ) {\n
+\tvar i, callbacks;\n
+\tif ( QUnit.hasOwnProperty( key ) ) {\n
+\t\tQUnit[ key ].call(scope, args );\n
+\t} else {\n
+\t\tcallbacks = config[ key ];\n
+\t\tfor ( i = 0; i < callbacks.length; i++ ) {\n
+\t\t\tcallbacks[ i ].call( scope, args );\n
+\t\t}\n
+\t}\n
+}\n
+\n
+// from jquery.js\n
+function inArray( elem, array ) {\n
+\tif ( array.indexOf ) {\n
+\t\treturn array.indexOf( elem );\n
+\t}\n
+\n
+\tfor ( var i = 0, length = array.length; i < length; i++ ) {\n
+\t\tif ( array[ i ] === elem ) {\n
+\t\t\treturn i;\n
+\t\t}\n
+\t}\n
+\n
+\treturn -1;\n
+}\n
+\n
+function Test( settings ) {\n
+\textend( this, settings );\n
+\tthis.assertions = [];\n
+\tthis.testNumber = ++Test.count;\n
+}\n
+\n
+Test.count = 0;\n
+\n
+Test.prototype = {\n
+\tinit: function() {\n
+\t\tvar a, b, li,\n
+\t\t\ttests = id( "qunit-tests" );\n
+\n
+\t\tif ( tests ) {\n
+\t\t\tb = document.createElement( "strong" );\n
+\t\t\tb.innerHTML = this.nameHtml;\n
+\n
+\t\t\t// `a` initialized at top of scope\n
+\t\t\ta = document.createElement( "a" );\n
+\t\t\ta.innerHTML = "Rerun";\n
+\t\t\ta.href = QUnit.url({ testNumber: this.testNumber });\n
+\n
+\t\t\tli = document.createElement( "li" );\n
+\t\t\tli.appendChild( b );\n
+\t\t\tli.appendChild( a );\n
+\t\t\tli.className = "running";\n
+\t\t\tli.id = this.id = "qunit-test-output" + testId++;\n
+\n
+\t\t\ttests.appendChild( li );\n
+\t\t}\n
+\t},\n
+\tsetup: function() {\n
+\t\tif (\n
+\t\t\t// Emit moduleStart when we\'re switching from one module to another\n
+\t\t\tthis.module !== config.previousModule ||\n
+\t\t\t\t// They could be equal (both undefined) but if the previousModule property doesn\'t\n
+\t\t\t\t// yet exist it means this is the first test in a suite that isn\'t wrapped in a\n
+\t\t\t\t// module, in which case we\'ll just emit a moduleStart event for \'undefined\'.\n
+\t\t\t\t// Without this, reporters can get testStart before moduleStart  which is a problem.\n
+\t\t\t\t!hasOwn.call( config, "previousModule" )\n
+\t\t) {\n
+\t\t\tif ( hasOwn.call( config, "previousModule" ) ) {\n
+\t\t\t\trunLoggingCallbacks( "moduleDone", QUnit, {\n
+\t\t\t\t\tname: config.previousModule,\n
+\t\t\t\t\tfailed: config.moduleStats.bad,\n
+\t\t\t\t\tpassed: config.moduleStats.all - config.moduleStats.bad,\n
+\t\t\t\t\ttotal: config.moduleStats.all\n
+\t\t\t\t});\n
+\t\t\t}\n
+\t\t\tconfig.previousModule = this.module;\n
+\t\t\tconfig.moduleStats = { all: 0, bad: 0 };\n
+\t\t\trunLoggingCallbacks( "moduleStart", QUnit, {\n
+\t\t\t\tname: this.module\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\tconfig.current = this;\n
+\n
+\t\tthis.testEnvironment = extend({\n
+\t\t\tsetup: function() {},\n
+\t\t\tteardown: function() {}\n
+\t\t}, this.moduleTestEnvironment );\n
+\n
+\t\tthis.started = +new Date();\n
+\t\trunLoggingCallbacks( "testStart", QUnit, {\n
+\t\t\tname: this.testName,\n
+\t\t\tmodule: this.module\n
+\t\t});\n
+\n
+\t\t/*jshint camelcase:false */\n
+\n
+\n
+\t\t/**\n
+\t\t * Expose the current test environment.\n
+\t\t *\n
+\t\t * @deprecated since 1.12.0: Use QUnit.config.current.testEnvironment instead.\n
+\t\t */\n
+\t\tQUnit.current_testEnvironment = this.testEnvironment;\n
+\n
+\t\t/*jshint camelcase:true */\n
+\n
+\t\tif ( !config.pollution ) {\n
+\t\t\tsaveGlobal();\n
+\t\t}\n
+\t\tif ( config.notrycatch ) {\n
+\t\t\tthis.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );\n
+\t\t\treturn;\n
+\t\t}\n
+\t\ttry {\n
+\t\t\tthis.testEnvironment.setup.call( this.testEnvironment, QUnit.assert );\n
+\t\t} catch( e ) {\n
+\t\t\tQUnit.pushFailure( "Setup failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );\n
+\t\t}\n
+\t},\n
+\trun: function() {\n
+\t\tconfig.current = this;\n
+\n
+\t\tvar running = id( "qunit-testresult" );\n
+\n
+\t\tif ( running ) {\n
+\t\t\trunning.innerHTML = "Running: <br/>" + this.nameHtml;\n
+\t\t}\n
+\n
+\t\tif ( this.async ) {\n
+\t\t\tQUnit.stop();\n
+\t\t}\n
+\n
+\t\tthis.callbackStarted = +new Date();\n
+\n
+\t\tif ( config.notrycatch ) {\n
+\t\t\tthis.callback.call( this.testEnvironment, QUnit.assert );\n
+\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n
+\t\t\treturn;\n
+\t\t}\n
+\n
+\t\ttry {\n
+\t\t\tthis.callback.call( this.testEnvironment, QUnit.assert );\n
+\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n
+\t\t} catch( e ) {\n
+\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n
+\n
+\t\t\tQUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );\n
+\t\t\t// else next test will carry the responsibility\n
+\t\t\tsaveGlobal();\n
+\n
+\t\t\t// Restart the tests if they\'re blocking\n
+\t\t\tif ( config.blocking ) {\n
+\t\t\t\tQUnit.start();\n
+\t\t\t}\n
+\t\t}\n
+\t},\n
+\tteardown: function() {\n
+\t\tconfig.current = this;\n
+\t\tif ( config.notrycatch ) {\n
+\t\t\tif ( typeof this.callbackRuntime === "undefined" ) {\n
+\t\t\t\tthis.callbackRuntime = +new Date() - this.callbackStarted;\n
+\t\t\t}\n
+\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );\n
+\t\t\treturn;\n
+\t\t} else {\n
+\t\t\ttry {\n
+\t\t\t\tthis.testEnvironment.teardown.call( this.testEnvironment, QUnit.assert );\n
+\t\t\t} catch( e ) {\n
+\t\t\t\tQUnit.pushFailure( "Teardown failed on " + this.testName + ": " + ( e.message || e ), extractStacktrace( e, 1 ) );\n
+\t\t\t}\n
+\t\t}\n
+\t\tcheckPollution();\n
+\t},\n
+\tfinish: function() {\n
+\t\tconfig.current = this;\n
+\t\tif ( config.requireExpects && this.expected === null ) {\n
+\t\t\tQUnit.pushFailure( "Expected number of assertions to be defined, but expect() was not called.", this.stack );\n
+\t\t} else if ( this.expected !== null && this.expected !== this.assertions.length ) {\n
+\t\t\tQUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack );\n
+\t\t} else if ( this.expected === null && !this.assertions.length ) {\n
+\t\t\tQUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions.", this.stack );\n
+\t\t}\n
+\n
+\t\tvar i, assertion, a, b, time, li, ol,\n
+\t\t\ttest = this,\n
+\t\t\tgood = 0,\n
+\t\t\tbad = 0,\n
+\t\t\ttests = id( "qunit-tests" );\n
+\n
+\t\tthis.runtime = +new Date() - this.started;\n
+\t\tconfig.stats.all += this.assertions.length;\n
+\t\tconfig.moduleStats.all += this.assertions.length;\n
+\n
+\t\tif ( tests ) {\n
+\t\t\tol = document.createElement( "ol" );\n
+\t\t\tol.className = "qunit-assert-list";\n
+\n
+\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n
+\t\t\t\tassertion = this.assertions[i];\n
+\n
+\t\t\t\tli = document.createElement( "li" );\n
+\t\t\t\tli.className = assertion.result ? "pass" : "fail";\n
+\t\t\t\tli.innerHTML = assertion.message || ( assertion.result ? "okay" : "failed" );\n
+\t\t\t\tol.appendChild( li );\n
+\n
+\t\t\t\tif ( assertion.result ) {\n
+\t\t\t\t\tgood++;\n
+\t\t\t\t} else {\n
+\t\t\t\t\tbad++;\n
+\t\t\t\t\tconfig.stats.bad++;\n
+\t\t\t\t\tconfig.moduleStats.bad++;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\t// store result when possible\n
+\t\t\tif ( QUnit.config.reorder && defined.sessionStorage ) {\n
+\t\t\t\tif ( bad ) {\n
+\t\t\t\t\tsessionStorage.setItem( "qunit-test-" + this.module + "-" + this.testName, bad );\n
+\t\t\t\t} else {\n
+\t\t\t\t\tsessionStorage.removeItem( "qunit-test-" + this.module + "-" + this.testName );\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tif ( bad === 0 ) {\n
+\t\t\t\taddClass( ol, "qunit-collapsed" );\n
+\t\t\t}\n
+\n
+\t\t\t// `b` initialized at top of scope\n
+\t\t\tb = document.createElement( "strong" );\n
+\t\t\tb.innerHTML = this.nameHtml + " <b class=\'counts\'>(<b class=\'failed\'>" + bad + "</b>, <b class=\'passed\'>" + good + "</b>, " + this.assertions.length + ")</b>";\n
+\n
+\t\t\taddEvent(b, "click", function() {\n
+\t\t\t\tvar next = b.parentNode.lastChild,\n
+\t\t\t\t\tcollapsed = hasClass( next, "qunit-collapsed" );\n
+\t\t\t\t( collapsed ? removeClass : addClass )( next, "qunit-collapsed" );\n
+\t\t\t});\n
+\n
+\t\t\taddEvent(b, "dblclick", function( e ) {\n
+\t\t\t\tvar target = e && e.target ? e.target : window.event.srcElement;\n
+\t\t\t\tif ( target.nodeName.toLowerCase() === "span" || target.nodeName.toLowerCase() === "b" ) {\n
+\t\t\t\t\ttarget = target.parentNode;\n
+\t\t\t\t}\n
+\t\t\t\tif ( window.location && target.nodeName.toLowerCase() === "strong" ) {\n
+\t\t\t\t\twindow.location = QUnit.url({ testNumber: test.testNumber });\n
+\t\t\t\t}\n
+\t\t\t});\n
+\n
+\t\t\t// `time` initialized at top of scope\n
+\t\t\ttime = document.createElement( "span" );\n
+\t\t\ttime.className = "runtime";\n
+\t\t\ttime.innerHTML = this.runtime + " ms";\n
+\n
+\t\t\t// `li` initialized at top of scope\n
+\t\t\tli = id( this.id );\n
+\t\t\tli.className = bad ? "fail" : "pass";\n
+\t\t\tli.removeChild( li.firstChild );\n
+\t\t\ta = li.firstChild;\n
+\t\t\tli.appendChild( b );\n
+\t\t\tli.appendChild( a );\n
+\t\t\tli.appendChild( time );\n
+\t\t\tli.appendChild( ol );\n
+\n
+\t\t} else {\n
+\t\t\tfor ( i = 0; i < this.assertions.length; i++ ) {\n
+\t\t\t\tif ( !this.assertions[i].result ) {\n
+\t\t\t\t\tbad++;\n
+\t\t\t\t\tconfig.stats.bad++;\n
+\t\t\t\t\tconfig.moduleStats.bad++;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\trunLoggingCallbacks( "testDone", QUnit, {\n
+\t\t\tname: this.testName,\n
+\t\t\tmodule: this.module,\n
+\t\t\tfailed: bad,\n
+\t\t\tpassed: this.assertions.length - bad,\n
+\t\t\ttotal: this.assertions.length,\n
+\t\t\truntime: this.runtime,\n
+\t\t\t// DEPRECATED: this property will be removed in 2.0.0, use runtime instead\n
+\t\t\tduration: this.runtime\n
+\t\t});\n
+\n
+\t\tQUnit.reset();\n
+\n
+\t\tconfig.current = undefined;\n
+\t},\n
+\n
+\tqueue: function() {\n
+\t\tvar bad,\n
+\t\t\ttest = this;\n
+\n
+\t\tsynchronize(function() {\n
+\t\t\ttest.init();\n
+\t\t});\n
+\t\tfunction run() {\n
+\t\t\t// each of these can by async\n
+\t\t\tsynchronize(function() {\n
+\t\t\t\ttest.setup();\n
+\t\t\t});\n
+\t\t\tsynchronize(function() {\n
+\t\t\t\ttest.run();\n
+\t\t\t});\n
+\t\t\tsynchronize(function() {\n
+\t\t\t\ttest.teardown();\n
+\t\t\t});\n
+\t\t\tsynchronize(function() {\n
+\t\t\t\ttest.finish();\n
+\t\t\t});\n
+\t\t}\n
+\n
+\t\t// `bad` initialized at top of scope\n
+\t\t// defer when previous test run passed, if storage is available\n
+\t\tbad = QUnit.config.reorder && defined.sessionStorage &&\n
+\t\t\t\t\t\t+sessionStorage.getItem( "qunit-test-" + this.module + "-" + this.testName );\n
+\n
+\t\tif ( bad ) {\n
+\t\t\trun();\n
+\t\t} else {\n
+\t\t\tsynchronize( run, true );\n
+\t\t}\n
+\t}\n
+};\n
+\n
+// `assert` initialized at top of scope\n
+// Assert helpers\n
+// All of these must either call QUnit.push() or manually do:\n
+// - runLoggingCallbacks( "log", .. );\n
+// - config.current.assertions.push({ .. });\n
+assert = QUnit.assert = {\n
+\t/**\n
+\t * Asserts rough true-ish result.\n
+\t * @name ok\n
+\t * @function\n
+\t * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" );\n
+\t */\n
+\tok: function( result, msg ) {\n
+\t\tif ( !config.current ) {\n
+\t\t\tthrow new Error( "ok() assertion outside test context, was " + sourceFromStacktrace(2) );\n
+\t\t}\n
+\t\tresult = !!result;\n
+\t\tmsg = msg || ( result ? "okay" : "failed" );\n
+\n
+\t\tvar source,\n
+\t\t\tdetails = {\n
+\t\t\t\tmodule: config.current.module,\n
+\t\t\t\tname: config.current.testName,\n
+\t\t\t\tresult: result,\n
+\t\t\t\tmessage: msg\n
+\t\t\t};\n
+\n
+\t\tmsg = "<span class=\'test-message\'>" + escapeText( msg ) + "</span>";\n
+\n
+\t\tif ( !result ) {\n
+\t\t\tsource = sourceFromStacktrace( 2 );\n
+\t\t\tif ( source ) {\n
+\t\t\t\tdetails.source = source;\n
+\t\t\t\tmsg += "<table><tr class=\'test-source\'><th>Source: </th><td><pre>" +\n
+\t\t\t\t\tescapeText( source ) +\n
+\t\t\t\t\t"</pre></td></tr></table>";\n
+\t\t\t}\n
+\t\t}\n
+\t\trunLoggingCallbacks( "log", QUnit, details );\n
+\t\tconfig.current.assertions.push({\n
+\t\t\tresult: result,\n
+\t\t\tmessage: msg\n
+\t\t});\n
+\t},\n
+\n
+\t/**\n
+\t * Assert that the first two arguments are equal, with an optional message.\n
+\t * Prints out both actual and expected values.\n
+\t * @name equal\n
+\t * @function\n
+\t * @example equal( format( "Received {0} bytes.", 2), "Received 2 bytes.", "format() replaces {0} with next argument" );\n
+\t */\n
+\tequal: function( actual, expected, message ) {\n
+\t\t/*jshint eqeqeq:false */\n
+\t\tQUnit.push( expected == actual, actual, expected, message );\n
+\t},\n
+\n
+\t/**\n
+\t * @name notEqual\n
+\t * @function\n
+\t */\n
+\tnotEqual: function( actual, expected, message ) {\n
+\t\t/*jshint eqeqeq:false */\n
+\t\tQUnit.push( expected != actual, actual, expected, message );\n
+\t},\n
+\n
+\t/**\n
+\t * @name propEqual\n
+\t * @function\n
+\t */\n
+\tpropEqual: function( actual, expected, message ) {\n
+\t\tactual = objectValues(actual);\n
+\t\texpected = objectValues(expected);\n
+\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n
+\t},\n
+\n
+\t/**\n
+\t * @name notPropEqual\n
+\t * @function\n
+\t */\n
+\tnotPropEqual: function( actual, expected, message ) {\n
+\t\tactual = objectValues(actual);\n
+\t\texpected = objectValues(expected);\n
+\t\tQUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );\n
+\t},\n
+\n
+\t/**\n
+\t * @name deepEqual\n
+\t * @function\n
+\t */\n
+\tdeepEqual: function( actual, expected, message ) {\n
+\t\tQUnit.push( QUnit.equiv(actual, expected), actual, expected, message );\n
+\t},\n
+\n
+\t/**\n
+\t * @name notDeepEqual\n
+\t * @function\n
+\t */\n
+\tnotDeepEqual: function( actual, expected, message ) {\n
+\t\tQUnit.push( !QUnit.equiv(actual, expected), actual, expected, message );\n
+\t},\n
+\n
+\t/**\n
+\t * @name strictEqual\n
+\t * @function\n
+\t */\n
+\tstrictEqual: function( actual, expected, message ) {\n
+\t\tQUnit.push( expected === actual, actual, expected, message );\n
+\t},\n
+\n
+\t/**\n
+\t * @name notStrictEqual\n
+\t * @function\n
+\t */\n
+\tnotStrictEqual: function( actual, expected, message ) {\n
+\t\tQUnit.push( expected !== actual, actual, expected, message );\n
+\t},\n
+\n
+\t"throws": function( block, expected, message ) {\n
+\t\tvar actual,\n
+\t\t\texpectedOutput = expected,\n
+\t\t\tok = false;\n
+\n
+\t\t// \'expected\' is optional\n
+\t\tif ( !message && typeof expected === "string" ) {\n
+\t\t\tmessage = expected;\n
+\t\t\texpected = null;\n
+\t\t}\n
+\n
+\t\tconfig.current.ignoreGlobalErrors = true;\n
+\t\ttry {\n
+\t\t\tblock.call( config.current.testEnvironment );\n
+\t\t} catch (e) {\n
+\t\t\tactual = e;\n
+\t\t}\n
+\t\tconfig.current.ignoreGlobalErrors = false;\n
+\n
+\t\tif ( actual ) {\n
+\n
+\t\t\t// we don\'t want to validate thrown error\n
+\t\t\tif ( !expected ) {\n
+\t\t\t\tok = true;\n
+\t\t\t\texpectedOutput = null;\n
+\n
+\t\t\t// expected is an Error object\n
+\t\t\t} else if ( expected instanceof Error ) {\n
+\t\t\t\tok = actual instanceof Error &&\n
+\t\t\t\t\t actual.name === expected.name &&\n
+\t\t\t\t\t actual.message === expected.message;\n
+\n
+\t\t\t// expected is a regexp\n
+\t\t\t} else if ( QUnit.objectType( expected ) === "regexp" ) {\n
+\t\t\t\tok = expected.test( errorString( actual ) );\n
+\n
+\t\t\t// expected is a string\n
+\t\t\t} else if ( QUnit.objectType( expected ) === "string" ) {\n
+\t\t\t\tok = expected === errorString( actual );\n
+\n
+\t\t\t// expected is a constructor\n
+\t\t\t} else if ( actual instanceof expected ) {\n
+\t\t\t\tok = true;\n
+\n
+\t\t\t// expected is a validation function which returns true is validation passed\n
+\t\t\t} else if ( expected.call( {}, actual ) === true ) {\n
+\t\t\t\texpectedOutput = null;\n
+\t\t\t\tok = true;\n
+\t\t\t}\n
+\n
+\t\t\tQUnit.push( ok, actual, expectedOutput, message );\n
+\t\t} else {\n
+\t\t\tQUnit.pushFailure( message, null, "No exception was thrown." );\n
+\t\t}\n
+\t}\n
+};\n
+\n
+/**\n
+ * @deprecated since 1.8.0\n
+ * Kept assertion helpers in root for backwards compatibility.\n
+ */\n
+extend( QUnit.constructor.prototype, assert );\n
+\n
+/**\n
+ * @deprecated since 1.9.0\n
+ * Kept to avoid TypeErrors for undefined methods.\n
+ */\n
+QUnit.constructor.prototype.raises = function() {\n
+\tQUnit.push( false, false, false, "QUnit.raises has been deprecated since 2012 (fad3c1ea), use QUnit.throws instead" );\n
+};\n
+\n
+/**\n
+ * @deprecated since 1.0.0, replaced with error pushes since 1.3.0\n
+ * Kept to avoid TypeErrors for undefined methods.\n
+ */\n
+QUnit.constructor.prototype.equals = function() {\n
+\tQUnit.push( false, false, false, "QUnit.equals has been deprecated since 2009 (e88049a0), use QUnit.equal instead" );\n
+};\n
+QUnit.constructor.prototype.same = function() {\n
+\tQUnit.push( false, false, false, "QUnit.same has been deprecated since 2009 (e88049a0), use QUnit.deepEqual instead" );\n
+};\n
+\n
+// Test for equality any JavaScript type.\n
+// Author: Philippe Rathé <prathe@gmail.com>\n
+QUnit.equiv = (function() {\n
+\n
+\t// Call the o related callback with the given arguments.\n
+\tfunction bindCallbacks( o, callbacks, args ) {\n
+\t\tvar prop = QUnit.objectType( o );\n
+\t\tif ( prop ) {\n
+\t\t\tif ( QUnit.objectType( callbacks[ prop ] ) === "function" ) {\n
+\t\t\t\treturn callbacks[ prop ].apply( callbacks, args );\n
+\t\t\t} else {\n
+\t\t\t\treturn callbacks[ prop ]; // or undefined\n
+\t\t\t}\n
+\t\t}\n
+\t}\n
+\n
+\t// the real equiv function\n
+\tvar innerEquiv,\n
+\t\t// stack to decide between skip/abort functions\n
+\t\tcallers = [],\n
+\t\t// stack to avoiding loops from circular referencing\n
+\t\tparents = [],\n
+\t\tparentsB = [],\n
+\n
+\t\tgetProto = Object.getPrototypeOf || function ( obj ) {\n
+\t\t\t/*jshint camelcase:false */\n
+\t\t\treturn obj.__proto__;\n
+\t\t},\n
+\t\tcallbacks = (function () {\n
+\n
+\t\t\t// for string, boolean, number and null\n
+\t\t\tfunction useStrictEquality( b, a ) {\n
+\t\t\t\t/*jshint eqeqeq:false */\n
+\t\t\t\tif ( b instanceof a.constructor || a instanceof b.constructor ) {\n
+\t\t\t\t\t// to catch short annotation VS \'new\' annotation of a\n
+\t\t\t\t\t// declaration\n
+\t\t\t\t\t// e.g. var i = 1;\n
+\t\t\t\t\t// var j = new Number(1);\n
+\t\t\t\t\treturn a == b;\n
+\t\t\t\t} else {\n
+\t\t\t\t\treturn a === b;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\treturn {\n
+\t\t\t\t"string": useStrictEquality,\n
+\t\t\t\t"boolean": useStrictEquality,\n
+\t\t\t\t"number": useStrictEquality,\n
+\t\t\t\t"null": useStrictEquality,\n
+\t\t\t\t"undefined": useStrictEquality,\n
+\n
+\t\t\t\t"nan": function( b ) {\n
+\t\t\t\t\treturn isNaN( b );\n
+\t\t\t\t},\n
+\n
+\t\t\t\t"date": function( b, a ) {\n
+\t\t\t\t\treturn QUnit.objectType( b ) === "date" && a.valueOf() === b.valueOf();\n
+\t\t\t\t},\n
+\n
+\t\t\t\t"regexp": function( b, a ) {\n
+\t\t\t\t\treturn QUnit.objectType( b ) === "regexp" &&\n
+\t\t\t\t\t\t// the regex itself\n
+\t\t\t\t\t\ta.source === b.source &&\n
+\t\t\t\t\t\t// and its modifiers\n
+\t\t\t\t\t\ta.global === b.global &&\n
+\t\t\t\t\t\t// (gmi) ...\n
+\t\t\t\t\t\ta.ignoreCase === b.ignoreCase &&\n
+\t\t\t\t\t\ta.multiline === b.multiline &&\n
+\t\t\t\t\t\ta.sticky === b.sticky;\n
+\t\t\t\t},\n
+\n
+\t\t\t\t// - skip when the property is a method of an instance (OOP)\n
+\t\t\t\t// - abort otherwise,\n
+\t\t\t\t// initial === would have catch identical references anyway\n
+\t\t\t\t"function": function() {\n
+\t\t\t\t\tvar caller = callers[callers.length - 1];\n
+\t\t\t\t\treturn caller !== Object && typeof caller !== "undefined";\n
+\t\t\t\t},\n
+\n
+\t\t\t\t"array": function( b, a ) {\n
+\t\t\t\t\tvar i, j, len, loop, aCircular, bCircular;\n
+\n
+\t\t\t\t\t// b could be an object literal here\n
+\t\t\t\t\tif ( QUnit.objectType( b ) !== "array" ) {\n
+\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tlen = a.length;\n
+\t\t\t\t\tif ( len !== b.length ) {\n
+\t\t\t\t\t\t// safe and faster\n
+\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// track reference to avoid circular references\n
+\t\t\t\t\tparents.push( a );\n
+\t\t\t\t\tparentsB.push( b );\n
+\t\t\t\t\tfor ( i = 0; i < len; i++ ) {\n
+\t\t\t\t\t\tloop = false;\n
+\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n
+\t\t\t\t\t\t\taCircular = parents[j] === a[i];\n
+\t\t\t\t\t\t\tbCircular = parentsB[j] === b[i];\n
+\t\t\t\t\t\t\tif ( aCircular || bCircular ) {\n
+\t\t\t\t\t\t\t\tif ( a[i] === b[i] || aCircular && bCircular ) {\n
+\t\t\t\t\t\t\t\t\tloop = true;\n
+\t\t\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t\t\tparents.pop();\n
+\t\t\t\t\t\t\t\t\tparentsB.pop();\n
+\t\t\t\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\tif ( !loop && !innerEquiv(a[i], b[i]) ) {\n
+\t\t\t\t\t\t\tparents.pop();\n
+\t\t\t\t\t\t\tparentsB.pop();\n
+\t\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\tparents.pop();\n
+\t\t\t\t\tparentsB.pop();\n
+\t\t\t\t\treturn true;\n
+\t\t\t\t},\n
+\n
+\t\t\t\t"object": function( b, a ) {\n
+\t\t\t\t\t/*jshint forin:false */\n
+\t\t\t\t\tvar i, j, loop, aCircular, bCircular,\n
+\t\t\t\t\t\t// Default to true\n
+\t\t\t\t\t\teq = true,\n
+\t\t\t\t\t\taProperties = [],\n
+\t\t\t\t\t\tbProperties = [];\n
+\n
+\t\t\t\t\t// comparing constructors is more strict than using\n
+\t\t\t\t\t// instanceof\n
+\t\t\t\t\tif ( a.constructor !== b.constructor ) {\n
+\t\t\t\t\t\t// Allow objects with no prototype to be equivalent to\n
+\t\t\t\t\t\t// objects with Object as their constructor.\n
+\t\t\t\t\t\tif ( !(( getProto(a) === null && getProto(b) === Object.prototype ) ||\n
+\t\t\t\t\t\t\t( getProto(b) === null && getProto(a) === Object.prototype ) ) ) {\n
+\t\t\t\t\t\t\t\treturn false;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// stack constructor before traversing properties\n
+\t\t\t\t\tcallers.push( a.constructor );\n
+\n
+\t\t\t\t\t// track reference to avoid circular references\n
+\t\t\t\t\tparents.push( a );\n
+\t\t\t\t\tparentsB.push( b );\n
+\n
+\t\t\t\t\t// be strict: don\'t ensure hasOwnProperty and go deep\n
+\t\t\t\t\tfor ( i in a ) {\n
+\t\t\t\t\t\tloop = false;\n
+\t\t\t\t\t\tfor ( j = 0; j < parents.length; j++ ) {\n
+\t\t\t\t\t\t\taCircular = parents[j] === a[i];\n
+\t\t\t\t\t\t\tbCircular = parentsB[j] === b[i];\n
+\t\t\t\t\t\t\tif ( aCircular || bCircular ) {\n
+\t\t\t\t\t\t\t\tif ( a[i] === b[i] || aCircular && bCircular ) {\n
+\t\t\t\t\t\t\t\t\tloop = true;\n
+\t\t\t\t\t\t\t\t} else {\n
+\t\t\t\t\t\t\t\t\teq = false;\n
+\t\t\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t\taProperties.push(i);\n
+\t\t\t\t\t\tif ( !loop && !innerEquiv(a[i], b[i]) ) {\n
+\t\t\t\t\t\t\teq = false;\n
+\t\t\t\t\t\t\tbreak;\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\tparents.pop();\n
+\t\t\t\t\tparentsB.pop();\n
+\t\t\t\t\tcallers.pop(); // unstack, we are done\n
+\n
+\t\t\t\t\tfor ( i in b ) {\n
+\t\t\t\t\t\tbProperties.push( i ); // collect b\'s properties\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\t// Ensures identical properties name\n
+\t\t\t\t\treturn eq && innerEquiv( aProperties.sort(), bProperties.sort() );\n
+\t\t\t\t}\n
+\t\t\t};\n
+\t\t}());\n
+\n
+\tinnerEquiv = function() { // can take multiple arguments\n
+\t\tvar args = [].slice.apply( arguments );\n
+\t\tif ( args.length < 2 ) {\n
+\t\t\treturn true; // end transition\n
+\t\t}\n
+\n
+\t\treturn (function( a, b ) {\n
+\t\t\tif ( a === b ) {\n
+\t\t\t\treturn true; // catch the most you can\n
+\t\t\t} else if ( a === null || b === null || typeof a === "undefined" ||\n
+\t\t\t\t\ttypeof b === "undefined" ||\n
+\t\t\t\t\tQUnit.objectType(a) !== QUnit.objectType(b) ) {\n
+\t\t\t\treturn false; // don\'t lose time with error prone cases\n
+\t\t\t} else {\n
+\t\t\t\treturn bindCallbacks(a, callbacks, [ b, a ]);\n
+\t\t\t}\n
+\n
+\t\t\t// apply transition with (1..n) arguments\n
+\t\t}( args[0], args[1] ) && innerEquiv.apply( this, args.splice(1, args.length - 1 )) );\n
+\t};\n
+\n
+\treturn innerEquiv;\n
+}());\n
+\n
+/**\n
+ * jsDump Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com |\n
+ * http://flesler.blogspot.com Licensed under BSD\n
+ * (http://www.opensource.org/licenses/bsd-license.php) Date: 5/15/2008\n
+ *\n
+ * @projectDescription Advanced and extensible data dumping for Javascript.\n
+ * @version 1.0.0\n
+ * @author Ariel Flesler\n
+ * @link {http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html}\n
+ */\n
+QUnit.jsDump = (function() {\n
+\tfunction quote( str ) {\n
+\t\treturn "\\"" + str.toString().replace( /"/g, "\\\\\\"" ) + "\\"";\n
+\t}\n
+\tfunction literal( o ) {\n
+\t\treturn o + "";\n
+\t}\n
+\tfunction join( pre, arr, post ) {\n
+\t\tvar s = jsDump.separator(),\n
+\t\t\tbase = jsDump.indent(),\n
+\t\t\tinner = jsDump.indent(1);\n
+\t\tif ( arr.join ) {\n
+\t\t\tarr = arr.join( "," + s + inner );\n
+\t\t}\n
+\t\tif ( !arr ) {\n
+\t\t\treturn pre + post;\n
+\t\t}\n
+\t\treturn [ pre, inner + arr, base + post ].join(s);\n
+\t}\n
+\tfunction array( arr, stack ) {\n
+\t\tvar i = arr.length, ret = new Array(i);\n
+\t\tthis.up();\n
+\t\twhile ( i-- ) {\n
+\t\t\tret[i] = this.parse( arr[i] , undefined , stack);\n
+\t\t}\n
+\t\tthis.down();\n
+\t\treturn join( "[", ret, "]" );\n
+\t}\n
+\n
+\tvar reName = /^function (\\w+)/,\n
+\t\tjsDump = {\n
+\t\t\t// type is used mostly internally, you can fix a (custom)type in advance\n
+\t\t\tparse: function( obj, type, stack ) {\n
+\t\t\t\tstack = stack || [ ];\n
+\t\t\t\tvar inStack, res,\n
+\t\t\t\t\tparser = this.parsers[ type || this.typeOf(obj) ];\n
+\n
+\t\t\t\ttype = typeof parser;\n
+\t\t\t\tinStack = inArray( obj, stack );\n
+\n
+\t\t\t\tif ( inStack !== -1 ) {\n
+\t\t\t\t\treturn "recursion(" + (inStack - stack.length) + ")";\n
+\t\t\t\t}\n
+\t\t\t\tif ( type === "function" )  {\n
+\t\t\t\t\tstack.push( obj );\n
+\t\t\t\t\tres = parser.call( this, obj, stack );\n
+\t\t\t\t\tstack.pop();\n
+\t\t\t\t\treturn res;\n
+\t\t\t\t}\n
+\t\t\t\treturn ( type === "string" ) ? parser : this.parsers.error;\n
+\t\t\t},\n
+\t\t\ttypeOf: function( obj ) {\n
+\t\t\t\tvar type;\n
+\t\t\t\tif ( obj === null ) {\n
+\t\t\t\t\ttype = "null";\n
+\t\t\t\t} else if ( typeof obj === "undefined" ) {\n
+\t\t\t\t\ttype = "undefined";\n
+\t\t\t\t} else if ( QUnit.is( "regexp", obj) ) {\n
+\t\t\t\t\ttype = "regexp";\n
+\t\t\t\t} else if ( QUnit.is( "date", obj) ) {\n
+\t\t\t\t\ttype = "date";\n
+\t\t\t\t} else if ( QUnit.is( "function", obj) ) {\n
+\t\t\t\t\ttype = "function";\n
+\t\t\t\t} else if ( typeof obj.setInterval !== undefined && typeof obj.document !== "undefined" && typeof obj.nodeType === "undefined" ) {\n
+\t\t\t\t\ttype = "window";\n
+\t\t\t\t} else if ( obj.nodeType === 9 ) {\n
+\t\t\t\t\ttype = "document";\n
+\t\t\t\t} else if ( obj.nodeType ) {\n
+\t\t\t\t\ttype = "node";\n
+\t\t\t\t} else if (\n
+\t\t\t\t\t// native arrays\n
+\t\t\t\t\ttoString.call( obj ) === "[object Array]" ||\n
+\t\t\t\t\t// NodeList objects\n
+\t\t\t\t\t( typeof obj.length === "number" && typeof obj.item !== "undefined" && ( obj.length ? obj.item(0) === obj[0] : ( obj.item( 0 ) === null && typeof obj[0] === "undefined" ) ) )\n
+\t\t\t\t) {\n
+\t\t\t\t\ttype = "array";\n
+\t\t\t\t} else if ( obj.constructor === Error.prototype.constructor ) {\n
+\t\t\t\t\ttype = "error";\n
+\t\t\t\t} else {\n
+\t\t\t\t\ttype = typeof obj;\n
+\t\t\t\t}\n
+\t\t\t\treturn type;\n
+\t\t\t},\n
+\t\t\tseparator: function() {\n
+\t\t\t\treturn this.multiline ?\tthis.HTML ? "<br />" : "\\n" : this.HTML ? "&nbsp;" : " ";\n
+\t\t\t},\n
+\t\t\t// extra can be a number, shortcut for increasing-calling-decreasing\n
+\t\t\tindent: function( extra ) {\n
+\t\t\t\tif ( !this.multiline ) {\n
+\t\t\t\t\treturn "";\n
+\t\t\t\t}\n
+\t\t\t\tvar chr = this.indentChar;\n
+\t\t\t\tif ( this.HTML ) {\n
+\t\t\t\t\tchr = chr.replace( /\\t/g, "   " ).replace( / /g, "&nbsp;" );\n
+\t\t\t\t}\n
+\t\t\t\treturn new Array( this.depth + ( extra || 0 ) ).join(chr);\n
+\t\t\t},\n
+\t\t\tup: function( a ) {\n
+\t\t\t\tthis.depth += a || 1;\n
+\t\t\t},\n
+\t\t\tdown: function( a ) {\n
+\t\t\t\tthis.depth -= a || 1;\n
+\t\t\t},\n
+\t\t\tsetParser: function( name, parser ) {\n
+\t\t\t\tthis.parsers[name] = parser;\n
+\t\t\t},\n
+\t\t\t// The next 3 are exposed so you can use them\n
+\t\t\tquote: quote,\n
+\t\t\tliteral: literal,\n
+\t\t\tjoin: join,\n
+\t\t\t//\n
+\t\t\tdepth: 1,\n
+\t\t\t// This is the list of parsers, to modify them, use jsDump.setParser\n
+\t\t\tparsers: {\n
+\t\t\t\twindow: "[Window]",\n
+\t\t\t\tdocument: "[Document]",\n
+\t\t\t\terror: function(error) {\n
+\t\t\t\t\treturn "Error(\\"" + error.message + "\\")";\n
+\t\t\t\t},\n
+\t\t\t\tunknown: "[Unknown]",\n
+\t\t\t\t"null": "null",\n
+\t\t\t\t"undefined": "undefined",\n
+\t\t\t\t"function": function( fn ) {\n
+\t\t\t\t\tvar ret = "function",\n
+\t\t\t\t\t\t// functions never have name in IE\n
+\t\t\t\t\t\tname = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];\n
+\n
+\t\t\t\t\tif ( name ) {\n
+\t\t\t\t\t\tret += " " + name;\n
+\t\t\t\t\t}\n
+\t\t\t\t\tret += "( ";\n
+\n
+\t\t\t\t\tret = [ ret, QUnit.jsDump.parse( fn, "functionArgs" ), "){" ].join( "" );\n
+\t\t\t\t\treturn join( ret, QUnit.jsDump.parse(fn,"functionCode" ), "}" );\n
+\t\t\t\t},\n
+\t\t\t\tarray: array,\n
+\t\t\t\tnodelist: array,\n
+\t\t\t\t"arguments": array,\n
+\t\t\t\tobject: function( map, stack ) {\n
+\t\t\t\t\t/*jshint forin:false */\n
+\t\t\t\t\tvar ret = [ ], keys, key, val, i;\n
+\t\t\t\t\tQUnit.jsDump.up();\n
+\t\t\t\t\tkeys = [];\n
+\t\t\t\t\tfor ( key in map ) {\n
+\t\t\t\t\t\tkeys.push( key );\n
+\t\t\t\t\t}\n
+\t\t\t\t\tkeys.sort();\n
+\t\t\t\t\tfor ( i = 0; i < keys.length; i++ ) {\n
+\t\t\t\t\t\tkey = keys[ i ];\n
+\t\t\t\t\t\tval = map[ key ];\n
+\t\t\t\t\t\tret.push( QUnit.jsDump.parse( key, "key" ) + ": " + QUnit.jsDump.parse( val, undefined, stack ) );\n
+\t\t\t\t\t}\n
+\t\t\t\t\tQUnit.jsDump.down();\n
+\t\t\t\t\treturn join( "{", ret, "}" );\n
+\t\t\t\t},\n
+\t\t\t\tnode: function( node ) {\n
+\t\t\t\t\tvar len, i, val,\n
+\t\t\t\t\t\topen = QUnit.jsDump.HTML ? "&lt;" : "<",\n
+\t\t\t\t\t\tclose = QUnit.jsDump.HTML ? "&gt;" : ">",\n
+\t\t\t\t\t\ttag = node.nodeName.toLowerCase(),\n
+\t\t\t\t\t\tret = open + tag,\n
+\t\t\t\t\t\tattrs = node.attributes;\n
+\n
+\t\t\t\t\tif ( attrs ) {\n
+\t\t\t\t\t\tfor ( i = 0, len = attrs.length; i < len; i++ ) {\n
+\t\t\t\t\t\t\tval = attrs[i].nodeValue;\n
+\t\t\t\t\t\t\t// IE6 includes all attributes in .attributes, even ones not explicitly set.\n
+\t\t\t\t\t\t\t// Those have values like undefined, null, 0, false, "" or "inherit".\n
+\t\t\t\t\t\t\tif ( val && val !== "inherit" ) {\n
+\t\t\t\t\t\t\t\tret += " " + attrs[i].nodeName + "=" + QUnit.jsDump.parse( val, "attribute" );\n
+\t\t\t\t\t\t\t}\n
+\t\t\t\t\t\t}\n
+\t\t\t\t\t}\n
+\t\t\t\t\tret += close;\n
+\n
+\t\t\t\t\t// Show content of TextNode or CDATASection\n
+\t\t\t\t\tif ( node.nodeType === 3 || node.nodeType === 4 ) {\n
+\t\t\t\t\t\tret += node.nodeValue;\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\treturn ret + open + "/" + tag + close;\n
+\t\t\t\t},\n
+\t\t\t\t// function calls it internally, it\'s the arguments part of the function\n
+\t\t\t\tfunctionArgs: function( fn ) {\n
+\t\t\t\t\tvar args,\n
+\t\t\t\t\t\tl = fn.length;\n
+\n
+\t\t\t\t\tif ( !l ) {\n
+\t\t\t\t\t\treturn "";\n
+\t\t\t\t\t}\n
+\n
+\t\t\t\t\targs = new Array(l);\n
+\t\t\t\t\twhile ( l-- ) {\n
+\t\t\t\t\t\t// 97 is \'a\'\n
+\t\t\t\t\t\targs[l] = String.fromCharCode(97+l);\n
+\t\t\t\t\t}\n
+\t\t\t\t\treturn " " + args.join( ", " ) + " ";\n
+\t\t\t\t},\n
+\t\t\t\t// object calls it internally, the key part of an item in a map\n
+\t\t\t\tkey: quote,\n
+\t\t\t\t// function calls it internally, it\'s the content of the function\n
+\t\t\t\tfunctionCode: "[code]",\n
+\t\t\t\t// node calls it internally, it\'s an html attribute value\n
+\t\t\t\tattribute: quote,\n
+\t\t\t\tstring: quote,\n
+\t\t\t\tdate: quote,\n
+\t\t\t\tregexp: literal,\n
+\t\t\t\tnumber: literal,\n
+\t\t\t\t"boolean": literal\n
+\t\t\t},\n
+\t\t\t// if true, entities are escaped ( <, >, \\t, space and \\n )\n
+\t\t\tHTML: false,\n
+\t\t\t// indentation unit\n
+\t\t\tindentChar: "  ",\n
+\t\t\t// if true, items in a collection, are separated by a \\n, else just a space.\n
+\t\t\tmultiline: true\n
+\t\t};\n
+\n
+\treturn jsDump;\n
+}());\n
+\n
+/*\n
+ * Javascript Diff Algorithm\n
+ *  By John Resig (http://ejohn.org/)\n
+ *  Modified by Chu Alan "sprite"\n
+ *\n
+ * Released under the MIT license.\n
+ *\n
+ * More Info:\n
+ *  http://ejohn.org/projects/javascript-diff-algorithm/\n
+ *\n
+ * Usage: QUnit.diff(expected, actual)\n
+ *\n
+ * QUnit.diff( "the quick brown fox jumped over", "the quick fox jumps over" ) == "the  quick <del>brown </del> fox <del>jumped </del><ins>jumps </ins> over"\n
+ */\n
+QUnit.diff = (function() {\n
+\t/*jshint eqeqeq:false, eqnull:true */\n
+\tfunction diff( o, n ) {\n
+\t\tvar i,\n
+\t\t\tns = {},\n
+\t\t\tos = {};\n
+\n
+\t\tfor ( i = 0; i < n.length; i++ ) {\n
+\t\t\tif ( !hasOwn.call( ns, n[i] ) ) {\n
+\t\t\t\tns[ n[i] ] = {\n
+\t\t\t\t\trows: [],\n
+\t\t\t\t\to: null\n
+\t\t\t\t};\n
+\t\t\t}\n
+\t\t\tns[ n[i] ].rows.push( i );\n
+\t\t}\n
+\n
+\t\tfor ( i = 0; i < o.length; i++ ) {\n
+\t\t\tif ( !hasOwn.call( os, o[i] ) ) {\n
+\t\t\t\tos[ o[i] ] = {\n
+\t\t\t\t\trows: [],\n
+\t\t\t\t\tn: null\n
+\t\t\t\t};\n
+\t\t\t}\n
+\t\t\tos[ o[i] ].rows.push( i );\n
+\t\t}\n
+\n
+\t\tfor ( i in ns ) {\n
+\t\t\tif ( hasOwn.call( ns, i ) ) {\n
+\t\t\t\tif ( ns[i].rows.length === 1 && hasOwn.call( os, i ) && os[i].rows.length === 1 ) {\n
+\t\t\t\t\tn[ ns[i].rows[0] ] = {\n
+\t\t\t\t\t\ttext: n[ ns[i].rows[0] ],\n
+\t\t\t\t\t\trow: os[i].rows[0]\n
+\t\t\t\t\t};\n
+\t\t\t\t\to[ os[i].rows[0] ] = {\n
+\t\t\t\t\t\ttext: o[ os[i].rows[0] ],\n
+\t\t\t\t\t\trow: ns[i].rows[0]\n
+\t\t\t\t\t};\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tfor ( i = 0; i < n.length - 1; i++ ) {\n
+\t\t\tif ( n[i].text != null && n[ i + 1 ].text == null && n[i].row + 1 < o.length && o[ n[i].row + 1 ].text == null &&\n
+\t\t\t\t\t\tn[ i + 1 ] == o[ n[i].row + 1 ] ) {\n
+\n
+\t\t\t\tn[ i + 1 ] = {\n
+\t\t\t\t\ttext: n[ i + 1 ],\n
+\t\t\t\t\trow: n[i].row + 1\n
+\t\t\t\t};\n
+\t\t\t\to[ n[i].row + 1 ] = {\n
+\t\t\t\t\ttext: o[ n[i].row + 1 ],\n
+\t\t\t\t\trow: i + 1\n
+\t\t\t\t};\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\tfor ( i = n.length - 1; i > 0; i-- ) {\n
+\t\t\tif ( n[i].text != null && n[ i - 1 ].text == null && n[i].row > 0 && o[ n[i].row - 1 ].text == null &&\n
+\t\t\t\t\t\tn[ i - 1 ] == o[ n[i].row - 1 ]) {\n
+\n
+\t\t\t\tn[ i - 1 ] = {\n
+\t\t\t\t\ttext: n[ i - 1 ],\n
+\t\t\t\t\trow: n[i].row - 1\n
+\t\t\t\t};\n
+\t\t\t\to[ n[i].row - 1 ] = {\n
+\t\t\t\t\ttext: o[ n[i].row - 1 ],\n
+\t\t\t\t\trow: i - 1\n
+\t\t\t\t};\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn {\n
+\t\t\to: o,\n
+\t\t\tn: n\n
+\t\t};\n
+\t}\n
+\n
+\treturn function( o, n ) {\n
+\t\to = o.replace( /\\s+$/, "" );\n
+\t\tn = n.replace( /\\s+$/, "" );\n
+\n
+\t\tvar i, pre,\n
+\t\t\tstr = "",\n
+\t\t\tout = diff( o === "" ? [] : o.split(/\\s+/), n === "" ? [] : n.split(/\\s+/) ),\n
+\t\t\toSpace = o.match(/\\s+/g),\n
+\t\t\tnSpace = n.match(/\\s+/g);\n
+\n
+\t\tif ( oSpace == null ) {\n
+\t\t\toSpace = [ " " ];\n
+\t\t}\n
+\t\telse {\n
+\t\t\toSpace.push( " " );\n
+\t\t}\n
+\n
+\t\tif ( nSpace == null ) {\n
+\t\t\tnSpace = [ " " ];\n
+\t\t}\n
+\t\telse {\n
+\t\t\tnSpace.push( " " );\n
+\t\t}\n
+\n
+\t\tif ( out.n.length === 0 ) {\n
+\t\t\tfor ( i = 0; i < out.o.length; i++ ) {\n
+\t\t\t\tstr += "<del>" + out.o[i] + oSpace[i] + "</del>";\n
+\t\t\t}\n
+\t\t}\n
+\t\telse {\n
+\t\t\tif ( out.n[0].text == null ) {\n
+\t\t\t\tfor ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {\n
+\t\t\t\t\tstr += "<del>" + out.o[n] + oSpace[n] + "</del>";\n
+\t\t\t\t}\n
+\t\t\t}\n
+\n
+\t\t\tfor ( i = 0; i < out.n.length; i++ ) {\n
+\t\t\t\tif (out.n[i].text == null) {\n
+\t\t\t\t\tstr += "<ins>" + out.n[i] + nSpace[i] + "</ins>";\n
+\t\t\t\t}\n
+\t\t\t\telse {\n
+\t\t\t\t\t// `pre` initialized at top of scope\n
+\t\t\t\t\tpre = "";\n
+\n
+\t\t\t\t\tfor ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {\n
+\t\t\t\t\t\tpre += "<del>" + out.o[n] + oSpace[n] + "</del>";\n
+\t\t\t\t\t}\n
+\t\t\t\t\tstr += " " + out.n[i].text + nSpace[i] + pre;\n
+\t\t\t\t}\n
+\t\t\t}\n
+\t\t}\n
+\n
+\t\treturn str;\n
+\t};\n
+}());\n
+\n
+// For browser, export only select globals\n
+if ( typeof window !== "undefined" ) {\n
+\textend( window, QUnit.constructor.prototype );\n
+\twindow.QUnit = QUnit;\n
+}\n
+\n
+// For CommonJS environments, export everything\n
+if ( typeof module !== "undefined" && module.exports ) {\n
+\tmodule.exports = QUnit;\n
+}\n
+\n
+\n
+// Get a reference to the global object, like window in browsers\n
+}( (function() {\n
+\treturn this;\n
+})() ));\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>61033</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/renderjs.min.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/renderjs.min.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ec10ba35ebbd770ed5319123515942a09cfeed5b
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/renderjs.min.js.xml
@@ -0,0 +1,2222 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681768.93</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>renderjs.min.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value>
+              <persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
+            </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>80955</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+  <record id="2" aka="AAAAAAAAAAI=">
+    <pickle>
+      <global name="Pdata" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*\n
+ * js_channel is a very lightweight abstraction on top of\n
+ * postMessage which defines message formats and semantics\n
+ * to support interactions more rich than just message passing\n
+ * js_channel supports:\n
+ *  + query/response - traditional rpc\n
+ *  + query/update/response - incremental async return of results\n
+ *    to a query\n
+ *  + notifications - fire and forget\n
+ *  + error handling\n
+ *\n
+ * js_channel is based heavily on json-rpc, but is focused at the\n
+ * problem of inter-iframe RPC.\n
+ *\n
+ * Message types:\n
+ *  There are 5 types of messages that can flow over this channel,\n
+ *  and you may determine what type of message an object is by\n
+ *  examining its parameters:\n
+ *  1. Requests\n
+ *    + integer id\n
+ *    + string method\n
+ *    + (optional) any params\n
+ *  2. Callback Invocations (or just "Callbacks")\n
+ *    + integer id\n
+ *    + string callback\n
+ *    + (optional) params\n
+ *  3. Error Responses (or just "Errors)\n
+ *    + integer id\n
+ *    + string error\n
+ *    + (optional) string message\n
+ *  4. Responses\n
+ *    + integer id\n
+ *    + (optional) any result\n
+ *  5. Notifications\n
+ *    + string method\n
+ *    + (optional) any params\n
+ */\n
+\n
+;var Channel = (function() {\n
+    "use strict";\n
+\n
+    // current transaction id, start out at a random *odd* number between 1 and a million\n
+    // There is one current transaction counter id per page, and it\'s shared between\n
+    // channel instances.  That means of all messages posted from a single javascript\n
+    // evaluation context, we\'ll never have two with the same id.\n
+    var s_curTranId = Math.floor(Math.random()*1000001);\n
+\n
+    // no two bound channels in the same javascript evaluation context may have the same origin, scope, and window.\n
+    // futher if two bound channels have the same window and scope, they may not have *overlapping* origins\n
+    // (either one or both support \'*\').  This restriction allows a single onMessage handler to efficiently\n
+    // route messages based on origin and scope.  The s_boundChans maps origins to scopes, to message\n
+    // handlers.  Request and Notification messages are routed using this table.\n
+    // Finally, channels are inserted into this table when built, and removed when destroyed.\n
+    var s_boundChans = { };\n
+\n
+    // add a channel to s_boundChans, throwing if a dup exists\n
+    function s_addBoundChan(win, origin, scope, handler) {\n
+        function hasWin(arr) {\n
+            for (var i = 0; i < arr.length; i++) if (arr[i].win === win) return true;\n
+            return false;\n
+        }\n
+\n
+        // does she exist?\n
+        var exists = false;\n
+\n
+\n
+        if (origin === \'*\') {\n
+            // we must check all other origins, sadly.\n
+            for (var k in s_boundChans) {\n
+                if (!s_boundChans.hasOwnProperty(k)) continue;\n
+                if (k === \'*\') continue;\n
+                if (typeof s_boundChans[k][scope] === \'object\') {\n
+                    exists = hasWin(s_boundChans[k][scope]);\n
+                    if (exists) break;\n
+                }\n
+            }\n
+        } else {\n
+            // we must check only \'*\'\n
+            if ((s_boundChans[\'*\'] && s_boundChans[\'*\'][scope])) {\n
+                exists = hasWin(s_boundChans[\'*\'][scope]);\n
+            }\n
+            if (!exists && s_boundChans[origin] && s_boundChans[origin][scope])\n
+            {\n
+                exists = hasWin(s_boundChans[origin][scope]);\n
+            }\n
+        }\n
+        if (exists) throw "A channel is already bound to the same window which overlaps with origin \'"+ origin +"\' and has scope \'"+scope+"\'";\n
+\n
+        if (typeof s_boundChans[origin] != \'object\') s_boundChans[origin] = { };\n
+        if (typeof s_boundChans[origin][scope] != \'object\') s_boundChans[origin][scope] = [ ];\n
+        s_boundChans[origin][scope].push({win: win, handler: handler});\n
+    }\n
+\n
+    function s_removeBoundChan(win, origin, scope) {\n
+        var arr = s_boundChans[origin][scope];\n
+        for (var i = 0; i < arr.length; i++) {\n
+            if (arr[i].win === win) {\n
+                arr.splice(i,1);\n
+            }\n
+        }\n
+        if (s_boundChans[origin][scope].length === 0) {\n
+            delete s_boundChans[origin][scope];\n
+        }\n
+    }\n
+\n
+    function s_isArray(obj) {\n
+        if (Array.isArray) return Array.isArray(obj);\n
+        else {\n
+            return (obj.constructor.toString().indexOf("Array") != -1);\n
+        }\n
+    }\n
+\n
+    // No two outstanding outbound messages may have the same id, period.  Given that, a single table\n
+    // mapping "transaction ids" to message handlers, allows efficient routing of Callback, Error, and\n
+    // Response messages.  Entries are added to this table when requests are sent, and removed when\n
+    // responses are received.\n
+    var s_transIds = { };\n
+\n
+    // class singleton onMessage handler\n
+    // this function is registered once and all incoming messages route through here.  This\n
+    // arrangement allows certain efficiencies, message data is only parsed once and dispatch\n
+    // is more efficient, especially for large numbers of simultaneous channels.\n
+    var s_onMessage = function(e) {\n
+        try {\n
+          var m = JSON.parse(e.data);\n
+          if (typeof m !== \'object\' || m === null) throw "malformed";\n
+        } catch(e) {\n
+          // just ignore any posted messages that do not consist of valid JSON\n
+          return;\n
+        }\n
+\n
+        var w = e.source;\n
+        var o = e.origin;\n
+        var s, i, meth;\n
+\n
+        if (typeof m.method === \'string\') {\n
+            var ar = m.method.split(\'::\');\n
+            if (ar.length == 2) {\n
+                s = ar[0];\n
+                meth = ar[1];\n
+            } else {\n
+                meth = m.method;\n
+            }\n
+        }\n
+\n
+        if (typeof m.id !== \'undefined\') i = m.id;\n
+\n
+        // w is message source window\n
+        // o is message origin\n
+        // m is parsed message\n
+        // s is message scope\n
+        // i is message id (or undefined)\n
+        // meth is unscoped method name\n
+        // ^^ based on these factors we can route the message\n
+\n
+        // if it has a method it\'s either a notification or a request,\n
+        // route using s_boundChans\n
+        if (typeof meth === \'string\') {\n
+            var delivered = false;\n
+            if (s_boundChans[o] && s_boundChans[o][s]) {\n
+                for (var j = 0; j < s_boundChans[o][s].length; j++) {\n
+                    if (s_boundChans[o][s][j].win === w) {\n
+                        s_boundChans[o][s][j].handler(o, meth, m);\n
+                        delivered = true;\n
+                        break;\n
+                    }\n
+                }\n
+            }\n
+\n
+            if (!delivered && s_boundChans[\'*\'] && s_boundChans[\'*\'][s]) {\n
+                for (var j = 0; j < s_boundChans[\'*\'][s].length; j++) {\n
+                    if (s_boundChans[\'*\'][s][j].win === w) {\n
+                        s_boundChans[\'*\'][s][j].handler(o, meth, m);\n
+                        break;\n
+                    }\n
+                }\n
+            }\n
+        }\n
+        // otherwise it must have an id (or be poorly formed\n
+        else if (typeof i != \'undefined\') {\n
+            if (s_transIds[i]) s_transIds[i](o, meth, m);\n
+        }\n
+    };\n
+\n
+    // Setup postMessage event listeners\n
+    if (window.addEventListener) window.addEventListener(\'message\', s_onMessage, false);\n
+    else if(window.attachEvent) window.attachEvent(\'onmessage\', s_onMessage);\n
+\n
+    /* a messaging channel is constructed from a window and an origin.\n
+     * the channel will assert that all messages received over the\n
+     * channel match the origin\n
+     *\n
+     * Arguments to Channel.build(cfg):\n
+     *\n
+     *   cfg.window - the remote window with which we\'ll communicate\n
+     *   cfg.origin - the expected origin of the remote window, may be \'*\'\n
+     *                which matches any origin\n
+     *   cfg.scope  - the \'scope\' of messages.  a scope string that is\n
+     *                prepended to message names.  local and remote endpoints\n
+     *                of a single channel must agree upon scope. Scope may\n
+     *                not contain double colons (\'::\').\n
+     *   cfg.debugOutput - A boolean value.  If true and window.console.log is\n
+     *                a function, then debug strings will be emitted to that\n
+     *                function.\n
+     *   cfg.debugOutput - A boolean value.  If true and window.console.log is\n
+     *                a function, then debug strings will be emitted to that\n
+     *                function.\n
+     *   cfg.postMessageObserver - A function that will be passed two arguments,\n
+     *                an origin and a message.  It will be passed these immediately\n
+     *                before messages are posted.\n
+     *   cfg.gotMessageObserver - A function that will be passed two arguments,\n
+     *                an origin and a message.  It will be passed these arguments\n
+     *                immediately after they pass scope and origin checks, but before\n
+     *                they are processed.\n
+     *   cfg.onReady - A function that will be invoked when a channel becomes "ready",\n
+     *                this occurs once both sides of the channel have been\n
+     *                instantiated and an application level handshake is exchanged.\n
+     *                the onReady function will be passed a single argument which is\n
+     *                the channel object that was returned from build().\n
+     */\n
+    return {\n
+        build: function(cfg) {\n
+            var debug = function(m) {\n
+                if (cfg.debugOutput && window.console && window.console.log) {\n
+                    // try to stringify, if it doesn\'t work we\'ll let javascript\'s built in toString do its magic\n
+                    try { if (typeof m !== \'string\') m = JSON.stringify(m); } catch(e) { }\n
+                    console.log("["+chanId+"] " + m);\n
+                }\n
+            };\n
+\n
+            /* browser capabilities check */\n
+            if (!window.postMessage) throw("jschannel cannot run this browser, no postMessage");\n
+            if (!window.JSON || !window.JSON.stringify || ! window.JSON.parse) {\n
+                throw("jschannel cannot run this browser, no JSON parsing/serialization");\n
+            }\n
+\n
+            /* basic argument validation */\n
+            if (typeof cfg != \'object\') throw("Channel build invoked without a proper object argument");\n
+\n
+            if (!cfg.window || !cfg.window.postMessage) throw("Channel.build() called without a valid window argument");\n
+\n
+            /* we\'d have to do a little more work to be able to run multiple channels that intercommunicate the same\n
+             * window...  Not sure if we care to support that */\n
+            if (window === cfg.window) throw("target window is same as present window -- not allowed");\n
+\n
+            // let\'s require that the client specify an origin.  if we just assume \'*\' we\'ll be\n
+            // propagating unsafe practices.  that would be lame.\n
+            var validOrigin = false;\n
+            if (typeof cfg.origin === \'string\') {\n
+                var oMatch;\n
+                if (cfg.origin === "*") validOrigin = true;\n
+                // allow valid domains under http and https.  Also, trim paths off otherwise valid origins.\n
+                else if (null !== (oMatch = cfg.origin.match(/^https?:\\/\\/(?:[-a-zA-Z0-9_\\.])+(?::\\d+)?/))) {\n
+                    cfg.origin = oMatch[0].toLowerCase();\n
+                    validOrigin = true;\n
+                }\n
+            }\n
+\n
+            if (!validOrigin) throw ("Channel.build() called with an invalid origin");\n
+\n
+            if (typeof cfg.scope !== \'undefined\') {\n
+                if (typeof cfg.scope !== \'string\') throw \'scope, when specified, must be a string\';\n
+                if (cfg.scope.split(\'::\').length > 1) throw "scope may not contain double colons: \'::\'";\n
+            }\n
+\n
+            /* private variables */\n
+            // generate a random and psuedo unique id for this channel\n
+            var chanId = (function () {\n
+                var text = "";\n
+                var alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";\n
+                for(var i=0; i < 5; i++) text += alpha.charAt(Math.floor(Math.random() * alpha.length));\n
+                return text;\n
+            })();\n
+\n
+            // registrations: mapping method names to call objects\n
+            var regTbl = { };\n
+            // current oustanding sent requests\n
+            var outTbl = { };\n
+            // current oustanding received requests\n
+            var inTbl = { };\n
+            // are we ready yet?  when false we will block outbound messages.\n
+            var ready = false;\n
+            var pendingQueue = [ ];\n
+\n
+            var createTransaction = function(id,origin,callbacks) {\n
+                var shouldDelayReturn = false;\n
+                var completed = false;\n
+\n
+                return {\n
+                    origin: origin,\n
+                    invoke: function(cbName, v) {\n
+                        // verify in table\n
+                        if (!inTbl[id]) throw "attempting to invoke a callback of a nonexistent transaction: " + id;\n
+                        // verify that the callback name is valid\n
+                        var valid = false;\n
+                        for (var i = 0; i < callbacks.length; i++) if (cbName === callbacks[i]) { valid = true; break; }\n
+                        if (!valid) throw "request supports no such callback \'" + cbName + "\'";\n
+\n
+                        // send callback invocation\n
+                        postMessage({ id: id, callback: cbName, params: v});\n
+                    },\n
+                    error: function(error, message) {\n
+                        completed = true;\n
+                        // verify in table\n
+                        if (!inTbl[id]) throw "error called for nonexistent message: " + id;\n
+\n
+                        // remove transaction from table\n
+                        delete inTbl[id];\n
+\n
+                        // send error\n
+                        postMessage({ id: id, error: error, message: message });\n
+                    },\n
+                    complete: function(v) {\n
+                        completed = true;\n
+                        // verify in table\n
+                        if (!inTbl[id]) throw "complete called for nonexistent message: " + id;\n
+                        // remove transaction from table\n
+                        delete inTbl[id];\n
+                        // send complete\n
+                        postMessage({ id: id, result: v });\n
+                    },\n
+                    delayReturn: function(delay) {\n
+                        if (typeof delay === \'boolean\') {\n
+                            shouldDelayReturn = (delay === true);\n
+                        }\n
+                        return shouldDelayReturn;\n
+                    },\n
+                    completed: function() {\n
+                        return completed;\n
+                    }\n
+                };\n
+            };\n
+\n
+            var setTransactionTimeout = function(transId, timeout, method) {\n
+              return window.setTimeout(function() {\n
+                if (outTbl[transId]) {\n
+                  // XXX: what if client code raises an exception here?\n
+                  var msg = "timeout (" + timeout + "ms) exceeded on method \'" + method + "\'";\n
+                  (1,outTbl[transId].error)("timeout_error", msg);\n
+                  delete outTbl[transId];\n
+                  delete s_transIds[transId];\n
+                }\n
+              }, timeout);\n
+            };\n
+\n
+            var onMessage = function(origin, method, m) {\n
+                // if an observer was specified at allocation time, invoke it\n
+                if (typeof cfg.gotMessageObserver === \'function\') {\n
+                    // pass observer a clone of the object so that our\n
+                    // manipulations are not visible (i.e. method unscoping).\n
+                    // This is not particularly efficient, but then we expect\n
+                    // that message observers are primarily for debugging anyway.\n
+                    try {\n
+                        cfg.gotMessageObserver(origin, m);\n
+                    } catch (e) {\n
+                        debug("gotMessageObserver() raised an exception: " + e.toString());\n
+                    }\n
+                }\n
+\n
+                // now, what type of message is this?\n
+                if (m.id && method) {\n
+                    // a request!  do we have a registered handler for this request?\n
+                    if (regTbl[method]) {\n
+                        var trans = createTransaction(m.id, origin, m.callbacks ? m.callbacks : [ ]);\n
+                        inTbl[m.id] = { };\n
+                        try {\n
+                            // callback handling.  we\'ll magically create functions inside the parameter list for each\n
+                            // callback\n
+                            if (m.callbacks && s_isArray(m.callbacks) && m.callbacks.length > 0) {\n
+                                for (var i = 0; i < m.callbacks.length; i++) {\n
+                                    var path = m.callbacks[i];\n
+                                    var obj = m.params;\n
+                                    var pathItems = path.split(\'/\');\n
+                                    for (var j = 0; j < pathItems.length - 1; j++) {\n
+                                        var cp = pathItems[j];\n
+                                        if (typeof obj[cp] !== \'object\') obj[cp] = { };\n
+                                        obj = obj[cp];\n
+                                    }\n
+                                    obj[pathItems[pathItems.length - 1]] = (function() {\n
+                                        var cbName = path;\n
+                                        return function(params) {\n
+                                            return trans.invoke(cbName, params);\n
+                                        };\n
+                                    })();\n
+                                }\n
+                            }\n
+                            var resp = regTbl[method](trans, m.params);\n
+                            if (!trans.delayReturn() && !trans.completed()) trans.complete(resp);\n
+                        } catch(e) {\n
+                            // automagic handling of exceptions:\n
+                            var error = "runtime_error";\n
+                            var message = null;\n
+                            // * if it\'s a string then it gets an error code of \'runtime_error\' and string is the message\n
+                            if (typeof e === \'string\') {\n
+                                message = e;\n
+                            } else if (typeof e === \'object\') {\n
+                                // either an array or an object\n
+                                // * if it\'s an array of length two, then  array[0] is the code, array[1] is the error message\n
+                                if (e && s_isArray(e) && e.length == 2) {\n
+                                    error = e[0];\n
+                                    message = e[1];\n
+                                }\n
+                                // * if it\'s an object then we\'ll look form error and message parameters\n
+                                else if (typeof e.error === \'string\') {\n
+                                    error = e.error;\n
+                                    if (!e.message) message = "";\n
+                                    else if (typeof e.message === \'string\') message = e.message;\n
+                                    else e = e.message; // let the stringify/toString message give us a reasonable verbose error string\n
+                                }\n
+                            }\n
+\n
+                            // message is *still* null, let\'s try harder\n
+                            if (message === null) {\n
+                                try {\n
+                                    message = JSON.stringify(e);\n
+                                    /* On MSIE8, this can result in \'out of memory\', which\n
+                                     * leaves message undefined. */\n
+                                    if (typeof(message) == \'undefined\')\n
+                                      message = e.toString();\n
+                                } catch (e2) {\n
+                                    message = e.toString();\n
+                                }\n
+                            }\n
+\n
+                            trans.error(error,message);\n
+                        }\n
+                    }\n
+                } else if (m.id && m.callback) {\n
+                    if (!outTbl[m.id] ||!outTbl[m.id].callbacks || !outTbl[m.id].callbacks[m.callback])\n
+                    {\n
+                        debug("ignoring invalid callback, id:"+m.id+ " (" + m.callback +")");\n
+                    } else {\n
+                        // XXX: what if client code raises an exception here?\n
+                        outTbl[m.id].callbacks[m.callback](m.params);\n
+                    }\n
+                } else if (m.id) {\n
+                    if (!outTbl[m.id]) {\n
+                        debug("ignoring invalid response: " + m.id);\n
+                    } else {\n
+                        // XXX: what if client code raises an exception here?\n
+                        if (m.error) {\n
+                            (1,outTbl[m.id].error)(m.error, m.message);\n
+                        } else {\n
+                            if (m.result !== undefined) (1,outTbl[m.id].success)(m.result);\n
+                            else (1,outTbl[m.id].success)();\n
+                        }\n
+                        delete outTbl[m.id];\n
+                        delete s_transIds[m.id];\n
+                    }\n
+                } else if (method) {\n
+                    // tis a notification.\n
+                    if (regTbl[method]) {\n
+                        // yep, there\'s a handler for that.\n
+                        // transaction has only origin for notifications.\n
+                        regTbl[method]({ origin: origin }, m.params);\n
+                        // if the client throws, we\'ll just let it bubble out\n
+                        // what can we do?  Also, here we\'ll ignore return values\n
+                    }\n
+                }\n
+            };\n
+\n
+            // now register our bound channel for msg routing\n
+            s_addBoundChan(cfg.window, cfg.origin, ((typeof cfg.scope === \'string\') ? cfg.scope : \'\'), onMessage);\n
+\n
+            // scope method names based on cfg.scope specified when the Channel was instantiated\n
+            var scopeMethod = function(m) {\n
+                if (typeof cfg.scope === \'string\' && cfg.scope.length) m = [cfg.scope, m].join("::");\n
+                return m;\n
+            };\n
+\n
+            // a small wrapper around postmessage whose primary function is to handle the\n
+            // case that clients start sending messages before the other end is "ready"\n
+            var postMessage = function(msg, force) {\n
+                if (!msg) throw "postMessage called with null message";\n
+\n
+                // delay posting if we\'re not ready yet.\n
+                var verb = (ready ? "post  " : "queue ");\n
+                debug(verb + " message: " + JSON.stringify(msg));\n
+                if (!force && !ready) {\n
+                    pendingQueue.push(msg);\n
+                } else {\n
+                    if (typeof cfg.postMessageObserver === \'function\') {\n
+                        try {\n
+                            cfg.postMessageObserver(cfg.origin, msg);\n
+                        } catch (e) {\n
+                            debug("postMessageObserver() raised an exception: " + e.toString());\n
+                        }\n
+                    }\n
+\n
+                    cfg.window.postMessage(JSON.stringify(msg), cfg.origin);\n
+                }\n
+            };\n
+\n
+            var onReady = function(trans, type) {\n
+                debug(\'ready msg received\');\n
+                if (ready) throw "received ready message while in ready state.  help!";\n
+\n
+                if (type === \'ping\') {\n
+                    chanId += \'-R\';\n
+                } else {\n
+                    chanId += \'-L\';\n
+                }\n
+\n
+                obj.unbind(\'__ready\'); // now this handler isn\'t needed any more.\n
+                ready = true;\n
+                debug(\'ready msg accepted.\');\n
+\n
+                if (type === \'ping\') {\n
+                    obj.notify({ method: \'__ready\', params: \'pong\' });\n
+                }\n
+\n
+                // flush queue\n
+                while (pendingQueue.length) {\n
+                    postMessage(pendingQueue.pop());\n
+                }\n
+\n
+                // invoke onReady observer if provided\n
+                if (typeof cfg.onReady === \'function\') cfg.onReady(obj);\n
+            };\n
+\n
+            var obj = {\n
+                // tries to unbind a bound message handler.  returns false if not possible\n
+                unbind: function (method) {\n
+                    if (regTbl[method]) {\n
+                        if (!(delete regTbl[method])) throw ("can\'t delete method: " + method);\n
+                        return true;\n
+                    }\n
+                    return false;\n
+                },\n
+                bind: function (method, cb) {\n
+                    if (!method || typeof method !== \'string\') throw "\'method\' argument to bind must be string";\n
+                    if (!cb || typeof cb !== \'function\') throw "callback missing from bind params";\n
+\n
+                    if (regTbl[method]) throw "method \'"+method+"\' is already bound!";\n
+                    regTbl[method] = cb;\n
+                    return this;\n
+                },\n
+                call: function(m) {\n
+                    if (!m) throw \'missing arguments to call function\';\n
+                    if (!m.method || typeof m.method !== \'string\') throw "\'method\' argument to call must be string";\n
+                    if (!m.success || typeof m.success !== \'function\') throw "\'success\' callback missing from call";\n
+\n
+                    // now it\'s time to support the \'callback\' feature of jschannel.  We\'ll traverse the argument\n
+                    // object and pick out all of the functions that were passed as arguments.\n
+                    var callbacks = { };\n
+                    var callbackNames = [ ];\n
+\n
+                    var pruneFunctions = function (path, obj) {\n
+                        if (typeof obj === \'object\') {\n
+                            for (var k in obj) {\n
+                                if (!obj.hasOwnProperty(k)) continue;\n
+                                var np = path + (path.length ? \'/\' : \'\') + k;\n
+                                if (typeof obj[k] === \'function\') {\n
+                                    callbacks[np] = obj[k];\n
+                                    callbackNames.push(np);\n
+                                    delete obj[k];\n
+                                } else if (typeof obj[k] === \'object\') {\n
+                                    pruneFunctions(np, obj[k]);\n
+                                }\n
+                            }\n
+                        }\n
+                    };\n
+                    pruneFunctions("", m.params);\n
+\n
+                    // build a \'request\' message and send it\n
+                    var msg = { id: s_curTranId, method: scopeMethod(m.method), params: m.params };\n
+                    if (callbackNames.length) msg.callbacks = callbackNames;\n
+\n
+                    if (m.timeout)\n
+                      // XXX: This function returns a timeout ID, but we don\'t do anything with it.\n
+                      // We might want to keep track of it so we can cancel it using clearTimeout()\n
+                      // when the transaction completes.\n
+                      setTransactionTimeout(s_curTranId, m.timeout, scopeMethod(m.method));\n
+\n
+                    // insert into the transaction table\n
+                    outTbl[s_curTranId] = { callbacks: callbacks, error: m.error, success: m.success };\n
+                    s_transIds[s_curTranId] = onMessage;\n
+\n
+                    // increment current id\n
+                    s_curTranId++;\n
+\n
+                    postMessage(msg);\n
+                },\n
+                notify: function(m) {\n
+                    if (!m) throw \'missing arguments to notify function\';\n
+                    if (!m.method || typeof m.method !== \'string\') throw "\'method\' argument to notify must be string";\n
+\n
+                    // no need to go into any transaction table\n
+                    postMessage({ method: scopeMethod(m.method), params: m.params });\n
+                },\n
+                destroy: function () {\n
+                    s_removeBoundChan(cfg.window, cfg.origin, ((typeof cfg.scope === \'string\') ? cfg.scope : \'\'));\n
+                    if (window.removeEventListener) window.removeEventListener(\'message\', onMessage, false);\n
+                    else if(window.detachEvent) window.detachEvent(\'onmessage\', onMessage);\n
+                    ready = false;\n
+                    regTbl = { };\n
+                    inTbl = { };\n
+                    outTbl = { };\n
+                    cfg.origin = null;\n
+                    pendingQueue = [ ];\n
+                    debug("channel destroyed");\n
+                    chanId = "";\n
+                }\n
+            };\n
+\n
+            obj.bind(\'__ready\', onReady);\n
+            setTimeout(function() {\n
+                postMessage({ method: scopeMethod(\'__ready\'), params: "ping" }, true);\n
+            }, 0);\n
+\n
+            return obj;\n
+        }\n
+    };\n
+})();\n
+;/*\n
+ * DOMParser HTML extension\n
+ * 2012-09-04\n
+ *\n
+ * By Eli Grey, http://eligrey.com\n
+ * Public domain.\n
+ * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.\n
+ */\n
+/*! @source https://gist.github.com/1129031 */\n
+(function (DOMParser) {\n
+  "use strict";\n
+  var DOMParser_proto = DOMParser.prototype,\n
+    real_parseFromString = DOMParser_proto.parseFromString;\n
+\n
+  // Firefox/Opera/IE throw errors on unsupported types\n
+  try {\n
+    // WebKit returns null on unsupported types\n
+    if ((new DOMParser()).parseFromString("", "text/html")) {\n
+      // text/html parsing is natively supported\n
+      return;\n
+    }\n
+  } catch (ignore) {}\n
+\n
+  DOMParser_proto.parseFromString = function (markup, type) {\n
+    var result, doc, doc_elt, first_elt;\n
+    if (/^\\s*text\\/html\\s*(?:;|$)/i.test(type)) {\n
+      doc = document.implementation.createHTMLDocument("");\n
+      doc_elt = doc.documentElement;\n
+\n
+      doc_elt.innerHTML = markup;\n
+      first_elt = doc_elt.firstElementChild;\n
+\n
+      if (doc_elt.childElementCount === 1\n
+          && first_elt.localName.toLowerCase() === "html") {\n
+        doc.replaceChild(first_elt, doc_elt);\n
+      }\n
+\n
+      result = doc;\n
+    } else {\n
+      result = real_parseFromString.apply(this, arguments);\n
+    }\n
+    return result;\n
+  };\n
+}(DOMParser));\n
+\n
+;// IE does not support have Document.prototype.contains.\n
+if (typeof document.contains !== \'function\') {\n
+  Document.prototype.contains = function(node) {\n
+    if (node === this || node.parentNode === this)\n
+      return true;\n
+    return this.documentElement.contains(node);\n
+ }\n
+}\n
+;/*! RenderJs */\n
+/*global console*/\n
+/*jslint nomen: true*/\n
+function loopEventListener(target, type, useCapture, callback) {\n
+  "use strict";\n
+  //////////////////////////\n
+  // Infinite event listener (promise is never resolved)\n
+  // eventListener is removed when promise is cancelled/rejected\n
+  //////////////////////////\n
+  var handle_event_callback,\n
+    callback_promise;\n
+\n
+  function cancelResolver() {\n
+    if ((callback_promise !== undefined) &&\n
+        (typeof callback_promise.cancel === "function")) {\n
+      callback_promise.cancel();\n
+    }\n
+  }\n
+\n
+  function canceller() {\n
+    if (handle_event_callback !== undefined) {\n
+      target.removeEventListener(type, handle_event_callback, useCapture);\n
+    }\n
+    cancelResolver();\n
+  }\n
+  function itsANonResolvableTrap(resolve, reject) {\n
+\n
+    handle_event_callback = function (evt) {\n
+      evt.stopPropagation();\n
+      evt.preventDefault();\n
+      cancelResolver();\n
+      callback_promise = new RSVP.Queue()\n
+        .push(function () {\n
+          return callback(evt);\n
+        })\n
+        .push(undefined, function (error) {\n
+          if (!(error instanceof RSVP.CancellationError)) {\n
+            canceller();\n
+            reject(error);\n
+          }\n
+        });\n
+    };\n
+\n
+    target.addEventListener(type, handle_event_callback, useCapture);\n
+  }\n
+  return new RSVP.Promise(itsANonResolvableTrap, canceller);\n
+}\n
+\n
+/*\n
+ * renderJs - Generic Gadget library renderer.\n
+ * http://www.renderjs.org/documentation\n
+ */\n
+(function (document, window, RSVP, DOMParser, Channel, MutationObserver,\n
+           Node) {\n
+  "use strict";\n
+\n
+  var gadget_model_dict = {},\n
+    javascript_registration_dict = {},\n
+    stylesheet_registration_dict = {},\n
+    gadget_loading_klass,\n
+    loading_klass_promise,\n
+    renderJS,\n
+    Monitor;\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // Helper functions\n
+  /////////////////////////////////////////////////////////////////\n
+  function listenHashChange(gadget) {\n
+\n
+    function extractHashAndDispatch(evt) {\n
+      var hash = (evt.newURL || window.location.toString()).split(\'#\')[1],\n
+        subhashes,\n
+        subhash,\n
+        keyvalue,\n
+        index,\n
+        options = {};\n
+      if (hash === undefined) {\n
+        hash = "";\n
+      } else {\n
+        hash = hash.split(\'?\')[0];\n
+      }\n
+\n
+      function optionalize(key, value, dict) {\n
+        var key_list = key.split("."),\n
+          kk,\n
+          i;\n
+        for (i = 0; i < key_list.length; i += 1) {\n
+          kk = key_list[i];\n
+          if (i === key_list.length - 1) {\n
+            dict[kk] = value;\n
+          } else {\n
+            if (!dict.hasOwnProperty(kk)) {\n
+              dict[kk] = {};\n
+            }\n
+            dict = dict[kk];\n
+          }\n
+        }\n
+      }\n
+\n
+      subhashes = hash.split(\'&\');\n
+      for (index in subhashes) {\n
+        if (subhashes.hasOwnProperty(index)) {\n
+          subhash = subhashes[index];\n
+          if (subhash !== \'\') {\n
+            keyvalue = subhash.split(\'=\');\n
+            if (keyvalue.length === 2) {\n
+\n
+              optionalize(decodeURIComponent(keyvalue[0]),\n
+                decodeURIComponent(keyvalue[1]),\n
+                options);\n
+\n
+            }\n
+          }\n
+        }\n
+      }\n
+\n
+      if (gadget.render !== undefined) {\n
+        return gadget.render(options);\n
+      }\n
+    }\n
+\n
+    var result = loopEventListener(window, \'hashchange\', false,\n
+                                   extractHashAndDispatch),\n
+      event = document.createEvent("Event");\n
+\n
+    event.initEvent(\'hashchange\', true, true);\n
+    event.newURL = window.location.toString();\n
+    window.dispatchEvent(event);\n
+    return result;\n
+  }\n
+\n
+\n
+  function removeHash(url) {\n
+    var index = url.indexOf(\'#\');\n
+    if (index > 0) {\n
+      url = url.substring(0, index);\n
+    }\n
+    return url;\n
+  }\n
+\n
+  function letsCrash(e) {\n
+    if (e.constructor === XMLHttpRequest) {\n
+      e = {\n
+        readyState: e.readyState,\n
+        status: e.status,\n
+        statusText: e.statusText,\n
+        response_headers: e.getAllResponseHeaders()\n
+      };\n
+    }\n
+    if (e.constructor === Array ||\n
+        e.constructor === String ||\n
+        e.constructor === Object) {\n
+      try {\n
+        e = JSON.stringify(e);\n
+      } catch (ignore) {\n
+      }\n
+    }\n
+    document.getElementsByTagName(\'body\')[0].textContent = e;\n
+    // XXX Do not crash the application if it fails\n
+    // Where to write the error?\n
+    /*global console*/\n
+    console.error(e.stack);\n
+    console.error(e);\n
+  }\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // Service Monitor promise\n
+  /////////////////////////////////////////////////////////////////\n
+  function ResolvedMonitorError(message) {\n
+    this.name = "resolved";\n
+    if ((message !== undefined) && (typeof message !== "string")) {\n
+      throw new TypeError(\'You must pass a string.\');\n
+    }\n
+    this.message = message || "Default Message";\n
+  }\n
+  ResolvedMonitorError.prototype = new Error();\n
+  ResolvedMonitorError.prototype.constructor = ResolvedMonitorError;\n
+\n
+  Monitor = function () {\n
+    var monitor = this,\n
+      promise_list = [],\n
+      promise,\n
+      reject,\n
+      notify,\n
+      resolved;\n
+\n
+    if (!(this instanceof Monitor)) {\n
+      return new Monitor();\n
+    }\n
+\n
+    function canceller() {\n
+      var len = promise_list.length,\n
+        i;\n
+      for (i = 0; i < len; i += 1) {\n
+        promise_list[i].cancel();\n
+      }\n
+      // Clean it to speed up other canceller run\n
+      promise_list = [];\n
+    }\n
+\n
+    promise = new RSVP.Promise(function (done, fail, progress) {\n
+      reject = function (rejectedReason) {\n
+        if (resolved) {\n
+          return;\n
+        }\n
+        monitor.isRejected = true;\n
+        monitor.rejectedReason = rejectedReason;\n
+        resolved = true;\n
+        canceller();\n
+        return fail(rejectedReason);\n
+      };\n
+      notify = progress;\n
+    }, canceller);\n
+\n
+    monitor.cancel = function () {\n
+      if (resolved) {\n
+        return;\n
+      }\n
+      resolved = true;\n
+      promise.cancel();\n
+      promise.fail(function (rejectedReason) {\n
+        monitor.isRejected = true;\n
+        monitor.rejectedReason = rejectedReason;\n
+      });\n
+    };\n
+    monitor.then = function () {\n
+      return promise.then.apply(promise, arguments);\n
+    };\n
+    monitor.fail = function () {\n
+      return promise.fail.apply(promise, arguments);\n
+    };\n
+\n
+    monitor.monitor = function (promise_to_monitor) {\n
+      if (resolved) {\n
+        throw new ResolvedMonitorError();\n
+      }\n
+      var queue = new RSVP.Queue()\n
+        .push(function () {\n
+          return promise_to_monitor;\n
+        })\n
+        .push(function (fulfillmentValue) {\n
+          // Promise to monitor is fullfilled, remove it from the list\n
+          var len = promise_list.length,\n
+            sub_promise_to_monitor,\n
+            new_promise_list = [],\n
+            i;\n
+          for (i = 0; i < len; i += 1) {\n
+            sub_promise_to_monitor = promise_list[i];\n
+            if (!(sub_promise_to_monitor.isFulfilled ||\n
+                sub_promise_to_monitor.isRejected)) {\n
+              new_promise_list.push(sub_promise_to_monitor);\n
+            }\n
+          }\n
+          promise_list = new_promise_list;\n
+        }, function (rejectedReason) {\n
+          if (rejectedReason instanceof RSVP.CancellationError) {\n
+            if (!(promise_to_monitor.isFulfilled &&\n
+                  promise_to_monitor.isRejected)) {\n
+              // The queue could be cancelled before the first push is run\n
+              promise_to_monitor.cancel();\n
+            }\n
+          }\n
+          reject(rejectedReason);\n
+          throw rejectedReason;\n
+        }, function (notificationValue) {\n
+          notify(notificationValue);\n
+          return notificationValue;\n
+        });\n
+\n
+      promise_list.push(queue);\n
+\n
+      return this;\n
+    };\n
+  };\n
+\n
+  Monitor.prototype = Object.create(RSVP.Promise.prototype);\n
+  Monitor.prototype.constructor = Monitor;\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // RenderJSGadget\n
+  /////////////////////////////////////////////////////////////////\n
+  function RenderJSGadget() {\n
+    if (!(this instanceof RenderJSGadget)) {\n
+      return new RenderJSGadget();\n
+    }\n
+  }\n
+  RenderJSGadget.prototype.__title = "";\n
+  RenderJSGadget.prototype.__interface_list = [];\n
+  RenderJSGadget.prototype.__path = "";\n
+  RenderJSGadget.prototype.__html = "";\n
+  RenderJSGadget.prototype.__required_css_list = [];\n
+  RenderJSGadget.prototype.__required_js_list = [];\n
+\n
+  function createMonitor(g) {\n
+    if (g.__monitor !== undefined) {\n
+      g.__monitor.cancel();\n
+    }\n
+    g.__monitor = new Monitor();\n
+    g.__monitor.fail(function (error) {\n
+      if (!(error instanceof RSVP.CancellationError)) {\n
+        return g.aq_reportServiceError(error);\n
+      }\n
+    }).fail(function (error) {\n
+      // Crash the application if the acquisition generates an error.\n
+      return letsCrash(error);\n
+    });\n
+  }\n
+\n
+  function clearGadgetInternalParameters(g) {\n
+    g.__sub_gadget_dict = {};\n
+    createMonitor(g);\n
+  }\n
+\n
+  function loadSubGadgetDOMDeclaration(g) {\n
+    var element_list = g.__element.querySelectorAll(\'[data-gadget-scope]\'),\n
+      element,\n
+      promise_list = [],\n
+      scope,\n
+      url,\n
+      sandbox,\n
+      i;\n
+\n
+    for (i = 0; i < element_list.length; i += 1) {\n
+      element = element_list[i];\n
+      scope = element.getAttribute("data-gadget-scope");\n
+      url = element.getAttribute("data-gadget-url");\n
+      sandbox = element.getAttribute("data-gadget-sandbox");\n
+      if ((scope !== null) && (url !== null)) {\n
+        promise_list.push(g.declareGadget(url, {\n
+          element: element,\n
+          scope: scope || undefined,\n
+          sandbox: sandbox || undefined\n
+        }));\n
+      }\n
+    }\n
+\n
+    return RSVP.all(promise_list);\n
+  }\n
+\n
+  RenderJSGadget.__ready_list = [clearGadgetInternalParameters,\n
+                                 loadSubGadgetDOMDeclaration];\n
+  RenderJSGadget.ready = function (callback) {\n
+    this.__ready_list.push(callback);\n
+    return this;\n
+  };\n
+\n
+  RenderJSGadget.__service_list = [];\n
+  RenderJSGadget.declareService = function (callback) {\n
+    this.__service_list.push(callback);\n
+    return this;\n
+  };\n
+\n
+  function startService(gadget) {\n
+    gadget.__monitor.monitor(new RSVP.Queue()\n
+      .push(function () {\n
+        var i,\n
+          service_list = gadget.constructor.__service_list;\n
+        for (i = 0; i < service_list.length; i += 1) {\n
+          gadget.__monitor.monitor(service_list[i].apply(gadget));\n
+        }\n
+      })\n
+      );\n
+  }\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // RenderJSGadget.declareMethod\n
+  /////////////////////////////////////////////////////////////////\n
+  RenderJSGadget.declareMethod = function (name, callback) {\n
+    this.prototype[name] = function () {\n
+      var context = this,\n
+        argument_list = arguments;\n
+\n
+      return new RSVP.Queue()\n
+        .push(function () {\n
+          return callback.apply(context, argument_list);\n
+        });\n
+    };\n
+    // Allow chain\n
+    return this;\n
+  };\n
+\n
+  RenderJSGadget\n
+    .declareMethod(\'getInterfaceList\', function () {\n
+      // Returns the list of gadget prototype\n
+      return this.__interface_list;\n
+    })\n
+    .declareMethod(\'getRequiredCSSList\', function () {\n
+      // Returns a list of CSS required by the gadget\n
+      return this.__required_css_list;\n
+    })\n
+    .declareMethod(\'getRequiredJSList\', function () {\n
+      // Returns a list of JS required by the gadget\n
+      return this.__required_js_list;\n
+    })\n
+    .declareMethod(\'getPath\', function () {\n
+      // Returns the path of the code of a gadget\n
+      return this.__path;\n
+    })\n
+    .declareMethod(\'getTitle\', function () {\n
+      // Returns the title of a gadget\n
+      return this.__title;\n
+    })\n
+    .declareMethod(\'getElement\', function () {\n
+      // Returns the DOM Element of a gadget\n
+      if (this.__element === undefined) {\n
+        throw new Error("No element defined");\n
+      }\n
+      return this.__element;\n
+    });\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // RenderJSGadget.declareAcquiredMethod\n
+  /////////////////////////////////////////////////////////////////\n
+  function acquire(child_gadget, method_name, argument_list) {\n
+    var gadget = this,\n
+      key,\n
+      gadget_scope;\n
+\n
+    for (key in gadget.__sub_gadget_dict) {\n
+      if (gadget.__sub_gadget_dict.hasOwnProperty(key)) {\n
+        if (gadget.__sub_gadget_dict[key] === child_gadget) {\n
+          gadget_scope = key;\n
+        }\n
+      }\n
+    }\n
+    return new RSVP.Queue()\n
+      .push(function () {\n
+        // Do not specify default __acquired_method_dict on prototype\n
+        // to prevent modifying this default value (with\n
+        // allowPublicAcquiredMethod for example)\n
+        var aq_dict = gadget.__acquired_method_dict || {};\n
+        if (aq_dict.hasOwnProperty(method_name)) {\n
+          return aq_dict[method_name].apply(gadget,\n
+                                            [argument_list, gadget_scope]);\n
+        }\n
+        throw new renderJS.AcquisitionError("aq_dynamic is not defined");\n
+      })\n
+      .push(undefined, function (error) {\n
+        if (error instanceof renderJS.AcquisitionError) {\n
+          return gadget.__aq_parent(method_name, argument_list);\n
+        }\n
+        throw error;\n
+      });\n
+  }\n
+\n
+  RenderJSGadget.declareAcquiredMethod =\n
+    function (name, method_name_to_acquire) {\n
+      this.prototype[name] = function () {\n
+        var argument_list = Array.prototype.slice.call(arguments, 0),\n
+          gadget = this;\n
+        return new RSVP.Queue()\n
+          .push(function () {\n
+            return gadget.__aq_parent(method_name_to_acquire, argument_list);\n
+          });\n
+      };\n
+\n
+      // Allow chain\n
+      return this;\n
+    };\n
+  RenderJSGadget.declareAcquiredMethod("aq_reportServiceError",\n
+                                       "reportServiceError");\n
+  RenderJSGadget.declareAcquiredMethod("aq_pleasePublishMyState",\n
+                                       "pleasePublishMyState");\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // RenderJSGadget.allowPublicAcquisition\n
+  /////////////////////////////////////////////////////////////////\n
+  RenderJSGadget.allowPublicAcquisition =\n
+    function (method_name, callback) {\n
+      this.prototype.__acquired_method_dict[method_name] = callback;\n
+\n
+      // Allow chain\n
+      return this;\n
+    };\n
+\n
+  // Set aq_parent on gadget_instance which call acquire on parent_gadget\n
+  function setAqParent(gadget_instance, parent_gadget) {\n
+    gadget_instance.__aq_parent = function (method_name, argument_list) {\n
+      return acquire.apply(parent_gadget, [gadget_instance, method_name,\n
+                                           argument_list]);\n
+    };\n
+  }\n
+\n
+  function pleasePublishMyState(param_list, child_gadget_scope) {\n
+    var new_param = {},\n
+      key;\n
+    for (key in this.state_parameter_dict) {\n
+      if (this.state_parameter_dict.hasOwnProperty(key)) {\n
+        new_param[key] = this.state_parameter_dict[key];\n
+      }\n
+    }\n
+    if (child_gadget_scope === undefined) {\n
+      throw new Error("gadget scope is mandatory");\n
+    }\n
+    new_param[child_gadget_scope] = param_list[0];\n
+    param_list = [new_param];\n
+    return this.aq_pleasePublishMyState.apply(this, param_list);\n
+  }\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // RenderJSEmbeddedGadget\n
+  /////////////////////////////////////////////////////////////////\n
+  // Class inheritance\n
+  function RenderJSEmbeddedGadget() {\n
+    if (!(this instanceof RenderJSEmbeddedGadget)) {\n
+      return new RenderJSEmbeddedGadget();\n
+    }\n
+    RenderJSGadget.call(this);\n
+  }\n
+  RenderJSEmbeddedGadget.__ready_list = RenderJSGadget.__ready_list.slice();\n
+  RenderJSEmbeddedGadget.__service_list =\n
+    RenderJSGadget.__service_list.slice();\n
+  RenderJSEmbeddedGadget.ready =\n
+    RenderJSGadget.ready;\n
+  RenderJSEmbeddedGadget.declareService =\n
+    RenderJSGadget.declareService;\n
+  RenderJSEmbeddedGadget.prototype = new RenderJSGadget();\n
+  RenderJSEmbeddedGadget.prototype.constructor = RenderJSEmbeddedGadget;\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // privateDeclarePublicGadget\n
+  /////////////////////////////////////////////////////////////////\n
+  function privateDeclarePublicGadget(url, options, parent_gadget) {\n
+    var gadget_instance;\n
+    if (options.element === undefined) {\n
+      options.element = document.createElement("div");\n
+    }\n
+\n
+    function loadDependency(method, url) {\n
+      return function () {\n
+        return method(url);\n
+      };\n
+    }\n
+\n
+    return new RSVP.Queue()\n
+      .push(function () {\n
+        return renderJS.declareGadgetKlass(url);\n
+      })\n
+      // Get the gadget class and instanciate it\n
+      .push(function (Klass) {\n
+        var i,\n
+          template_node_list = Klass.__template_element.body.childNodes;\n
+        gadget_loading_klass = Klass;\n
+        gadget_instance = new Klass();\n
+        gadget_instance.__element = options.element;\n
+        for (i = 0; i < template_node_list.length; i += 1) {\n
+          gadget_instance.__element.appendChild(\n
+            template_node_list[i].cloneNode(true)\n
+          );\n
+        }\n
+        setAqParent(gadget_instance, parent_gadget);\n
+        // Load dependencies if needed\n
+        return RSVP.all([\n
+          gadget_instance.getRequiredJSList(),\n
+          gadget_instance.getRequiredCSSList()\n
+        ]);\n
+      })\n
+      // Load all JS/CSS\n
+      .push(function (all_list) {\n
+        var q = new RSVP.Queue(),\n
+          i;\n
+        // Load JS\n
+        for (i = 0; i < all_list[0].length; i += 1) {\n
+          q.push(loadDependency(renderJS.declareJS, all_list[0][i]));\n
+        }\n
+        // Load CSS\n
+        for (i = 0; i < all_list[1].length; i += 1) {\n
+          q.push(loadDependency(renderJS.declareCSS, all_list[1][i]));\n
+        }\n
+        return q;\n
+      })\n
+      .push(function () {\n
+        return gadget_instance;\n
+      });\n
+  }\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // RenderJSIframeGadget\n
+  /////////////////////////////////////////////////////////////////\n
+  function RenderJSIframeGadget() {\n
+    if (!(this instanceof RenderJSIframeGadget)) {\n
+      return new RenderJSIframeGadget();\n
+    }\n
+    RenderJSGadget.call(this);\n
+  }\n
+  RenderJSIframeGadget.__ready_list = RenderJSGadget.__ready_list.slice();\n
+  RenderJSIframeGadget.ready =\n
+    RenderJSGadget.ready;\n
+  RenderJSIframeGadget.__service_list = RenderJSGadget.__service_list.slice();\n
+  RenderJSIframeGadget.declareService =\n
+    RenderJSGadget.declareService;\n
+  RenderJSIframeGadget.prototype = new RenderJSGadget();\n
+  RenderJSIframeGadget.prototype.constructor = RenderJSIframeGadget;\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // privateDeclareIframeGadget\n
+  /////////////////////////////////////////////////////////////////\n
+  function privateDeclareIframeGadget(url, options, parent_gadget) {\n
+    var gadget_instance,\n
+      iframe,\n
+      iframe_loading_deferred = RSVP.defer();\n
+    if (options.element === undefined) {\n
+      throw new Error("DOM element is required to create Iframe Gadget " +\n
+                      url);\n
+    }\n
+\n
+    // Check if the element is attached to the DOM\n
+    if (!document.contains(options.element)) {\n
+      throw new Error("The parent element is not attached to the DOM for " +\n
+                      url);\n
+    }\n
+\n
+    gadget_instance = new RenderJSIframeGadget();\n
+    setAqParent(gadget_instance, parent_gadget);\n
+    iframe = document.createElement("iframe");\n
+//    gadget_instance.element.setAttribute("seamless", "seamless");\n
+    iframe.setAttribute("src", url);\n
+    gadget_instance.__path = url;\n
+    gadget_instance.__element = options.element;\n
+    // Attach it to the DOM\n
+    options.element.appendChild(iframe);\n
+\n
+    // XXX Manage unbind when deleting the gadget\n
+\n
+    // Create the communication channel with the iframe\n
+    gadget_instance.__chan = Channel.build({\n
+      window: iframe.contentWindow,\n
+      origin: "*",\n
+      scope: "renderJS"\n
+    });\n
+\n
+    // Create new method from the declareMethod call inside the iframe\n
+    gadget_instance.__chan.bind("declareMethod",\n
+                                function (trans, method_name) {\n
+        gadget_instance[method_name] = function () {\n
+          var argument_list = arguments;\n
+          return new RSVP.Promise(function (resolve, reject) {\n
+            gadget_instance.__chan.call({\n
+              method: "methodCall",\n
+              params: [\n
+                method_name,\n
+                Array.prototype.slice.call(argument_list, 0)],\n
+              success: function (s) {\n
+                resolve(s);\n
+              },\n
+              error: function (e) {\n
+                reject(e);\n
+              }\n
+            });\n
+          });\n
+        };\n
+        return "OK";\n
+      });\n
+\n
+    // Wait for the iframe to be loaded before continuing\n
+    gadget_instance.__chan.bind("ready", function (trans) {\n
+      iframe_loading_deferred.resolve(gadget_instance);\n
+      return "OK";\n
+    });\n
+    gadget_instance.__chan.bind("failed", function (trans, params) {\n
+      iframe_loading_deferred.reject(params);\n
+      return "OK";\n
+    });\n
+    gadget_instance.__chan.bind("acquire", function (trans, params) {\n
+      gadget_instance.__aq_parent.apply(gadget_instance, params)\n
+        .then(function (g) {\n
+          trans.complete(g);\n
+        }).fail(function (e) {\n
+          trans.error(e.toString());\n
+        });\n
+      trans.delayReturn(true);\n
+    });\n
+\n
+    return RSVP.any([\n
+      iframe_loading_deferred.promise,\n
+      // Timeout to prevent non renderJS embeddable gadget\n
+      // XXX Maybe using iframe.onload/onerror would be safer?\n
+      RSVP.timeout(5000)\n
+    ]);\n
+  }\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // RenderJSGadget.declareGadget\n
+  /////////////////////////////////////////////////////////////////\n
+  RenderJSGadget\n
+    .declareMethod(\'declareGadget\', function (url, options) {\n
+      var queue,\n
+        parent_gadget = this,\n
+        local_loading_klass_promise,\n
+        previous_loading_klass_promise = loading_klass_promise;\n
+\n
+      if (options === undefined) {\n
+        options = {};\n
+      }\n
+      if (options.sandbox === undefined) {\n
+        options.sandbox = "public";\n
+      }\n
+\n
+      // transform url to absolute url if it is relative\n
+      url = renderJS.getAbsoluteURL(url, this.__path);\n
+      // Change the global variable to update the loading queue\n
+      loading_klass_promise = new RSVP.Queue()\n
+        // Wait for previous gadget loading to finish first\n
+        .push(function () {\n
+          return previous_loading_klass_promise;\n
+        })\n
+        .push(undefined, function () {\n
+          // Forget previous declareGadget error\n
+          return;\n
+        })\n
+        .push(function () {\n
+          var method;\n
+          if (options.sandbox === "public") {\n
+            method = privateDeclarePublicGadget;\n
+          } else if (options.sandbox === "iframe") {\n
+            method = privateDeclareIframeGadget;\n
+          } else {\n
+            throw new Error("Unsupported sandbox options \'" +\n
+                            options.sandbox + "\'");\n
+          }\n
+          return method(url, options, parent_gadget);\n
+        })\n
+        // Set the HTML context\n
+        .push(function (gadget_instance) {\n
+          // Drop the current loading klass info used by selector\n
+          gadget_loading_klass = undefined;\n
+          return gadget_instance;\n
+        })\n
+        .push(undefined, function (e) {\n
+          // Drop the current loading klass info used by selector\n
+          // even in case of error\n
+          gadget_loading_klass = undefined;\n
+          throw e;\n
+        });\n
+      local_loading_klass_promise = loading_klass_promise;\n
+\n
+      queue = new RSVP.Queue()\n
+        .push(function () {\n
+          return local_loading_klass_promise;\n
+        })\n
+        // Set the HTML context\n
+        .push(function (gadget_instance) {\n
+          var i;\n
+          // Trigger calling of all ready callback\n
+          function ready_wrapper() {\n
+            return gadget_instance;\n
+          }\n
+          for (i = 0; i < gadget_instance.constructor.__ready_list.length;\n
+               i += 1) {\n
+            // Put a timeout?\n
+            queue.push(gadget_instance.constructor.__ready_list[i]);\n
+            // Always return the gadget instance after ready function\n
+            queue.push(ready_wrapper);\n
+          }\n
+\n
+          // Store local reference to the gadget instance\n
+          if (options.scope !== undefined) {\n
+            parent_gadget.__sub_gadget_dict[options.scope] = gadget_instance;\n
+            gadget_instance.__element.setAttribute("data-gadget-scope",\n
+                                                   options.scope);\n
+          }\n
+\n
+          // Put some attribute to ease page layout comprehension\n
+          gadget_instance.__element.setAttribute("data-gadget-url", url);\n
+          gadget_instance.__element.setAttribute("data-gadget-sandbox",\n
+                                                 options.sandbox);\n
+          gadget_instance.__element._gadget = gadget_instance;\n
+\n
+          if (document.contains(gadget_instance.__element)) {\n
+            // Put a timeout\n
+            queue.push(startService);\n
+          }\n
+          // Always return the gadget instance after ready function\n
+          queue.push(ready_wrapper);\n
+\n
+          return gadget_instance;\n
+        });\n
+      return queue;\n
+    })\n
+    .declareMethod(\'getDeclaredGadget\', function (gadget_scope) {\n
+      if (!this.__sub_gadget_dict.hasOwnProperty(gadget_scope)) {\n
+        throw new Error("Gadget scope \'" + gadget_scope + "\' is not known.");\n
+      }\n
+      return this.__sub_gadget_dict[gadget_scope];\n
+    })\n
+    .declareMethod(\'dropGadget\', function (gadget_scope) {\n
+      if (!this.__sub_gadget_dict.hasOwnProperty(gadget_scope)) {\n
+        throw new Error("Gadget scope \'" + gadget_scope + "\' is not known.");\n
+      }\n
+      // http://perfectionkills.com/understanding-delete/\n
+      delete this.__sub_gadget_dict[gadget_scope];\n
+    });\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // renderJS selector\n
+  /////////////////////////////////////////////////////////////////\n
+  renderJS = function (selector) {\n
+    var result;\n
+    if (selector === window) {\n
+      // window is the \'this\' value when loading a javascript file\n
+      // In this case, use the current loading gadget constructor\n
+      result = gadget_loading_klass;\n
+    }\n
+    if (result === undefined) {\n
+      throw new Error("Unknown selector \'" + selector + "\'");\n
+    }\n
+    return result;\n
+  };\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // renderJS.AcquisitionError\n
+  /////////////////////////////////////////////////////////////////\n
+  renderJS.AcquisitionError = function (message) {\n
+    this.name = "AcquisitionError";\n
+    if ((message !== undefined) && (typeof message !== "string")) {\n
+      throw new TypeError(\'You must pass a string.\');\n
+    }\n
+    this.message = message || "Acquisition failed";\n
+  };\n
+  renderJS.AcquisitionError.prototype = new Error();\n
+  renderJS.AcquisitionError.prototype.constructor =\n
+    renderJS.AcquisitionError;\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // renderJS.getAbsoluteURL\n
+  /////////////////////////////////////////////////////////////////\n
+  renderJS.getAbsoluteURL = function (url, base_url) {\n
+    var doc, base, link,\n
+      html = "<!doctype><html><head></head></html>",\n
+      isAbsoluteOrDataURL = new RegExp(\'^(?:[a-z]+:)?//|data:\', \'i\');\n
+\n
+    if (url && base_url && !isAbsoluteOrDataURL.test(url)) {\n
+      doc = (new DOMParser()).parseFromString(html, \'text/html\');\n
+      base = doc.createElement(\'base\');\n
+      link = doc.createElement(\'link\');\n
+      doc.head.appendChild(base);\n
+      doc.head.appendChild(link);\n
+      base.href = base_url;\n
+      link.href = url;\n
+      return link.href;\n
+    }\n
+    return url;\n
+  };\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // renderJS.declareJS\n
+  /////////////////////////////////////////////////////////////////\n
+  renderJS.declareJS = function (url) {\n
+    // Prevent infinite recursion if loading render.js\n
+    // more than once\n
+    var result;\n
+    if (javascript_registration_dict.hasOwnProperty(url)) {\n
+      result = RSVP.resolve();\n
+    } else {\n
+      result = new RSVP.Promise(function (resolve, reject) {\n
+        var newScript;\n
+        newScript = document.createElement(\'script\');\n
+        newScript.type = \'text/javascript\';\n
+        newScript.src = url;\n
+        newScript.onload = function () {\n
+          javascript_registration_dict[url] = null;\n
+          resolve();\n
+        };\n
+        newScript.onerror = function (e) {\n
+          reject(e);\n
+        };\n
+        document.head.appendChild(newScript);\n
+      });\n
+    }\n
+    return result;\n
+  };\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // renderJS.declareCSS\n
+  /////////////////////////////////////////////////////////////////\n
+  renderJS.declareCSS = function (url) {\n
+    // https://github.com/furf/jquery-getCSS/blob/master/jquery.getCSS.js\n
+    // No way to cleanly check if a css has been loaded\n
+    // So, always resolve the promise...\n
+    // http://requirejs.org/docs/faq-advanced.html#css\n
+    var result;\n
+    if (stylesheet_registration_dict.hasOwnProperty(url)) {\n
+      result = RSVP.resolve();\n
+    } else {\n
+      result = new RSVP.Promise(function (resolve, reject) {\n
+        var link;\n
+        link = document.createElement(\'link\');\n
+        link.rel = \'stylesheet\';\n
+        link.type = \'text/css\';\n
+        link.href = url;\n
+        link.onload = function () {\n
+          stylesheet_registration_dict[url] = null;\n
+          resolve();\n
+        };\n
+        link.onerror = function (e) {\n
+          reject(e);\n
+        };\n
+        document.head.appendChild(link);\n
+      });\n
+    }\n
+    return result;\n
+  };\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // renderJS.declareGadgetKlass\n
+  /////////////////////////////////////////////////////////////////\n
+  renderJS.declareGadgetKlass = function (url) {\n
+    var result,\n
+      xhr;\n
+\n
+    function parse() {\n
+      var tmp_constructor,\n
+        key,\n
+        parsed_html;\n
+      if (!gadget_model_dict.hasOwnProperty(url)) {\n
+        // Class inheritance\n
+        tmp_constructor = function () {\n
+          RenderJSGadget.call(this);\n
+        };\n
+        tmp_constructor.__ready_list = RenderJSGadget.__ready_list.slice();\n
+        tmp_constructor.__service_list = RenderJSGadget.__service_list.slice();\n
+        tmp_constructor.declareMethod =\n
+          RenderJSGadget.declareMethod;\n
+        tmp_constructor.declareAcquiredMethod =\n
+          RenderJSGadget.declareAcquiredMethod;\n
+        tmp_constructor.allowPublicAcquisition =\n
+          RenderJSGadget.allowPublicAcquisition;\n
+        tmp_constructor.ready =\n
+          RenderJSGadget.ready;\n
+        tmp_constructor.declareService =\n
+          RenderJSGadget.declareService;\n
+        tmp_constructor.prototype = new RenderJSGadget();\n
+        tmp_constructor.prototype.constructor = tmp_constructor;\n
+        tmp_constructor.prototype.__path = url;\n
+        tmp_constructor.prototype.__acquired_method_dict = {};\n
+        tmp_constructor.allowPublicAcquisition("pleasePublishMyState",\n
+                                               pleasePublishMyState);\n
+        // https://developer.mozilla.org/en-US/docs/HTML_in_XMLHttpRequest\n
+        // https://developer.mozilla.org/en-US/docs/Web/API/DOMParser\n
+        // https://developer.mozilla.org/en-US/docs/Code_snippets/HTML_to_DOM\n
+        tmp_constructor.__template_element =\n
+          (new DOMParser()).parseFromString(xhr.responseText, "text/html");\n
+        parsed_html = renderJS.parseGadgetHTMLDocument(\n
+          tmp_constructor.__template_element,\n
+          url\n
+        );\n
+        for (key in parsed_html) {\n
+          if (parsed_html.hasOwnProperty(key)) {\n
+            tmp_constructor.prototype[\'__\' + key] = parsed_html[key];\n
+          }\n
+        }\n
+\n
+        gadget_model_dict[url] = tmp_constructor;\n
+      }\n
+\n
+      return gadget_model_dict[url];\n
+    }\n
+\n
+    function resolver(resolve, reject) {\n
+      function handler() {\n
+        var tmp_result;\n
+        try {\n
+          if (xhr.readyState === 0) {\n
+            // UNSENT\n
+            reject(xhr);\n
+          } else if (xhr.readyState === 4) {\n
+            // DONE\n
+            if ((xhr.status < 200) || (xhr.status >= 300) ||\n
+                (!/^text\\/html[;]?/.test(\n
+                  xhr.getResponseHeader("Content-Type") || ""\n
+                ))) {\n
+              reject(xhr);\n
+            } else {\n
+              tmp_result = parse();\n
+              resolve(tmp_result);\n
+            }\n
+          }\n
+        } catch (e) {\n
+          reject(e);\n
+        }\n
+      }\n
+\n
+      xhr = new XMLHttpRequest();\n
+      xhr.open("GET", url);\n
+      xhr.onreadystatechange = handler;\n
+      xhr.setRequestHeader(\'Accept\', \'text/html\');\n
+      xhr.withCredentials = true;\n
+      xhr.send();\n
+    }\n
+\n
+    function canceller() {\n
+      if ((xhr !== undefined) && (xhr.readyState !== xhr.DONE)) {\n
+        xhr.abort();\n
+      }\n
+    }\n
+\n
+    if (gadget_model_dict.hasOwnProperty(url)) {\n
+      // Return klass object if it already exists\n
+      result = RSVP.resolve(gadget_model_dict[url]);\n
+    } else {\n
+      // Fetch the HTML page and parse it\n
+      result = new RSVP.Promise(resolver, canceller);\n
+    }\n
+    return result;\n
+  };\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // renderJS.clearGadgetKlassList\n
+  /////////////////////////////////////////////////////////////////\n
+  // For test purpose only\n
+  renderJS.clearGadgetKlassList = function () {\n
+    gadget_model_dict = {};\n
+    javascript_registration_dict = {};\n
+    stylesheet_registration_dict = {};\n
+  };\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // renderJS.parseGadgetHTMLDocument\n
+  /////////////////////////////////////////////////////////////////\n
+  renderJS.parseGadgetHTMLDocument = function (document_element, url) {\n
+    var settings = {\n
+        title: "",\n
+        interface_list: [],\n
+        required_css_list: [],\n
+        required_js_list: []\n
+      },\n
+      i,\n
+      element,\n
+      isAbsoluteURL = new RegExp(\'^(?:[a-z]+:)?//\', \'i\');\n
+\n
+    if (!url || !isAbsoluteURL.test(url)) {\n
+      throw new Error("The url should be absolute: " + url);\n
+    }\n
+\n
+    if (document_element.nodeType === 9) {\n
+      settings.title = document_element.title;\n
+\n
+      if (document_element.head !== null) {\n
+        for (i = 0; i < document_element.head.children.length; i += 1) {\n
+          element = document_element.head.children[i];\n
+          if (element.href !== null) {\n
+            // XXX Manage relative URL during extraction of URLs\n
+            // element.href returns absolute URL in firefox but "" in chrome;\n
+            if (element.rel === "stylesheet") {\n
+              settings.required_css_list.push(\n
+                renderJS.getAbsoluteURL(element.getAttribute("href"), url)\n
+              );\n
+            } else if (element.nodeName === "SCRIPT" &&\n
+                       (element.type === "text/javascript" ||\n
+                        !element.type)) {\n
+              settings.required_js_list.push(\n
+                renderJS.getAbsoluteURL(element.getAttribute("src"), url)\n
+              );\n
+            } else if (element.rel ===\n
+                       "http://www.renderjs.org/rel/interface") {\n
+              settings.interface_list.push(\n
+                renderJS.getAbsoluteURL(element.getAttribute("href"), url)\n
+              );\n
+            }\n
+          }\n
+        }\n
+      }\n
+    } else {\n
+      throw new Error("The first parameter should be an HTMLDocument");\n
+    }\n
+    return settings;\n
+  };\n
+\n
+  /////////////////////////////////////////////////////////////////\n
+  // global\n
+  /////////////////////////////////////////////////////////////////\n
+  window.rJS = window.renderJS = renderJS;\n
+  window.__RenderJSGadget = RenderJSGadget;\n
+  window.__RenderJSEmbeddedGadget = RenderJSEmbeddedGadget;\n
+  window.__RenderJSIframeGadget = RenderJSIframeGadget;\n
+\n
+  ///////////////////////////////////////////////////\n
+  // Bootstrap process. Register the self gadget.\n
+  ///////////////////////////////////////////////////\n
+\n
+  function mergeSubDict(dict) {\n
+    var subkey,\n
+      subkey2,\n
+      subresult2,\n
+      value,\n
+      result = {};\n
+    for (subkey in dict) {\n
+      if (dict.hasOwnProperty(subkey)) {\n
+        value = dict[subkey];\n
+        if (value instanceof Object) {\n
+          subresult2 = mergeSubDict(value);\n
+          for (subkey2 in subresult2) {\n
+            if (subresult2.hasOwnProperty(subkey2)) {\n
+              // XXX key should not have an . inside\n
+              if (result.hasOwnProperty(subkey + "." + subkey2)) {\n
+                throw new Error("Key " + subkey + "." +\n
+                                subkey2 + " already present");\n
+              }\n
+              result[subkey + "." + subkey2] = subresult2[subkey2];\n
+            }\n
+          }\n
+        } else {\n
+          if (result.hasOwnProperty(subkey)) {\n
+            throw new Error("Key " + subkey + " already present");\n
+          }\n
+          result[subkey] = value;\n
+        }\n
+      }\n
+    }\n
+    return result;\n
+\n
+  }\n
+\n
+  function bootstrap() {\n
+    var url = removeHash(window.location.href),\n
+      tmp_constructor,\n
+      root_gadget,\n
+      loading_gadget_promise = new RSVP.Queue(),\n
+      declare_method_count = 0,\n
+      embedded_channel,\n
+      notifyReady,\n
+      notifyDeclareMethod,\n
+      gadget_ready = false,\n
+      iframe_top_gadget,\n
+      last_acquisition_gadget;\n
+\n
+    // Create the gadget class for the current url\n
+    if (gadget_model_dict.hasOwnProperty(url)) {\n
+      throw new Error("bootstrap should not be called twice");\n
+    }\n
+    loading_klass_promise = new RSVP.Promise(function (resolve, reject) {\n
+\n
+      last_acquisition_gadget = new RenderJSGadget();\n
+      last_acquisition_gadget.__acquired_method_dict = {\n
+        getTopURL: function () {\n
+          return url;\n
+        },\n
+        reportServiceError: function (param_list) {\n
+          letsCrash(param_list[0]);\n
+        },\n
+        pleaseRedirectMyHash: function (param_list) {\n
+          window.location.replace(param_list[0]);\n
+        },\n
+        pleasePublishMyState: function (param_list) {\n
+          var key,\n
+            first = true,\n
+            hash = "#";\n
+          param_list[0] = mergeSubDict(param_list[0]);\n
+          for (key in param_list[0]) {\n
+            if (param_list[0].hasOwnProperty(key)) {\n
+              if (!first) {\n
+                hash += "&";\n
+              }\n
+              hash += encodeURIComponent(key) + "=" +\n
+                encodeURIComponent(param_list[0][key]);\n
+              first = false;\n
+            }\n
+          }\n
+          return hash;\n
+        }\n
+      };\n
+      // Stop acquisition on the last acquisition gadget\n
+      // Do not put this on the klass, as their could be multiple instances\n
+      last_acquisition_gadget.__aq_parent = function (method_name) {\n
+        throw new renderJS.AcquisitionError(\n
+          "No gadget provides " + method_name\n
+        );\n
+      };\n
+\n
+      //we need to determine tmp_constructor\'s value before exit bootstrap\n
+      //because of function : renderJS\n
+      //but since the channel checking is async,\n
+      //we can\'t use code structure like:\n
+      // if channel communication is ok\n
+      //    tmp_constructor = RenderJSGadget\n
+      // else\n
+      //    tmp_constructor = RenderJSEmbeddedGadget\n
+      if (window.self === window.top) {\n
+        // XXX Copy/Paste from declareGadgetKlass\n
+        tmp_constructor = function () {\n
+          RenderJSGadget.call(this);\n
+        };\n
+        tmp_constructor.declareMethod = RenderJSGadget.declareMethod;\n
+        tmp_constructor.declareAcquiredMethod =\n
+          RenderJSGadget.declareAcquiredMethod;\n
+        tmp_constructor.allowPublicAcquisition =\n
+          RenderJSGadget.allowPublicAcquisition;\n
+        tmp_constructor.__ready_list = RenderJSGadget.__ready_list.slice();\n
+        tmp_constructor.ready = RenderJSGadget.ready;\n
+        tmp_constructor.__service_list = RenderJSGadget.__service_list.slice();\n
+        tmp_constructor.declareService =\n
+          RenderJSGadget.declareService;\n
+        tmp_constructor.prototype = new RenderJSGadget();\n
+        tmp_constructor.prototype.constructor = tmp_constructor;\n
+        tmp_constructor.prototype.__path = url;\n
+        gadget_model_dict[url] = tmp_constructor;\n
+\n
+        // Create the root gadget instance and put it in the loading stack\n
+        root_gadget = new gadget_model_dict[url]();\n
+\n
+        tmp_constructor.declareService(function () {\n
+          return listenHashChange(this);\n
+        });\n
+\n
+        setAqParent(root_gadget, last_acquisition_gadget);\n
+\n
+      } else {\n
+        // Create the communication channel\n
+        embedded_channel = Channel.build({\n
+          window: window.parent,\n
+          origin: "*",\n
+          scope: "renderJS"\n
+        });\n
+        // Create the root gadget instance and put it in the loading stack\n
+        tmp_constructor = RenderJSEmbeddedGadget;\n
+        tmp_constructor.__ready_list = RenderJSGadget.__ready_list.slice();\n
+        tmp_constructor.__service_list = RenderJSGadget.__service_list.slice();\n
+        tmp_constructor.prototype.__path = url;\n
+        root_gadget = new RenderJSEmbeddedGadget();\n
+\n
+\n
+        // Notify parent about gadget instanciation\n
+        notifyReady = function () {\n
+          if ((declare_method_count === 0) && (gadget_ready === true)) {\n
+            embedded_channel.notify({method: "ready"});\n
+          }\n
+        };\n
+\n
+        // Inform parent gadget about declareMethod calls here.\n
+        notifyDeclareMethod = function (name) {\n
+          declare_method_count += 1;\n
+          embedded_channel.call({\n
+            method: "declareMethod",\n
+            params: name,\n
+            success: function () {\n
+              declare_method_count -= 1;\n
+              notifyReady();\n
+            },\n
+            error: function () {\n
+              declare_method_count -= 1;\n
+            }\n
+          });\n
+        };\n
+\n
+        notifyDeclareMethod("getInterfaceList");\n
+        notifyDeclareMethod("getRequiredCSSList");\n
+        notifyDeclareMethod("getRequiredJSList");\n
+        notifyDeclareMethod("getPath");\n
+        notifyDeclareMethod("getTitle");\n
+\n
+        // Surcharge declareMethod to inform parent window\n
+        tmp_constructor.declareMethod = function (name, callback) {\n
+          var result = RenderJSGadget.declareMethod.apply(\n
+              this,\n
+              [name, callback]\n
+            );\n
+          notifyDeclareMethod(name);\n
+          return result;\n
+        };\n
+\n
+        tmp_constructor.declareService =\n
+          RenderJSGadget.declareService;\n
+        tmp_constructor.declareAcquiredMethod =\n
+          RenderJSGadget.declareAcquiredMethod;\n
+        tmp_constructor.allowPublicAcquisition =\n
+          RenderJSGadget.allowPublicAcquisition;\n
+\n
+        //Default: Define __aq_parent to inform parent window\n
+        tmp_constructor.prototype.__aq_parent = function (method_name,\n
+          argument_list, time_out) {\n
+          return new RSVP.Promise(function (resolve, reject) {\n
+            embedded_channel.call({\n
+              method: "acquire",\n
+              params: [\n
+                method_name,\n
+                argument_list\n
+              ],\n
+              success: function (s) {\n
+                resolve(s);\n
+              },\n
+              error: function (e) {\n
+                reject(e);\n
+              },\n
+              timeout: time_out\n
+            });\n
+          });\n
+        };\n
+      }\n
+\n
+      tmp_constructor.prototype.__acquired_method_dict = {};\n
+      tmp_constructor.allowPublicAcquisition("pleasePublishMyState",\n
+                                             pleasePublishMyState);\n
+      gadget_loading_klass = tmp_constructor;\n
+\n
+      function init() {\n
+        // XXX HTML properties can only be set when the DOM is fully loaded\n
+        var settings = renderJS.parseGadgetHTMLDocument(document, url),\n
+          j,\n
+          key;\n
+        for (key in settings) {\n
+          if (settings.hasOwnProperty(key)) {\n
+            tmp_constructor.prototype[\'__\' + key] = settings[key];\n
+          }\n
+        }\n
+        tmp_constructor.__template_element = document.createElement("div");\n
+        root_gadget.__element = document.body;\n
+        for (j = 0; j < root_gadget.__element.childNodes.length; j += 1) {\n
+          tmp_constructor.__template_element.appendChild(\n
+            root_gadget.__element.childNodes[j].cloneNode(true)\n
+          );\n
+        }\n
+        RSVP.all([root_gadget.getRequiredJSList(),\n
+                  root_gadget.getRequiredCSSList()])\n
+          .then(function (all_list) {\n
+            var i,\n
+              js_list = all_list[0],\n
+              css_list = all_list[1];\n
+            for (i = 0; i < js_list.length; i += 1) {\n
+              javascript_registration_dict[js_list[i]] = null;\n
+            }\n
+            for (i = 0; i < css_list.length; i += 1) {\n
+              stylesheet_registration_dict[css_list[i]] = null;\n
+            }\n
+            gadget_loading_klass = undefined;\n
+          }).then(function () {\n
+\n
+            // select the target node\n
+            var target = document.querySelector(\'body\'),\n
+              // create an observer instance\n
+              observer = new MutationObserver(function (mutations) {\n
+                var i, k, len, len2, node, added_list;\n
+                mutations.forEach(function (mutation) {\n
+                  if (mutation.type === \'childList\') {\n
+\n
+                    len = mutation.removedNodes.length;\n
+                    for (i = 0; i < len; i += 1) {\n
+                      node = mutation.removedNodes[i];\n
+                      if (node.nodeType === Node.ELEMENT_NODE) {\n
+                        if (node.hasAttribute("data-gadget-url") &&\n
+                            (node._gadget !== undefined)) {\n
+                          createMonitor(node._gadget);\n
+                        }\n
+                        added_list =\n
+                          node.querySelectorAll("[data-gadget-url]");\n
+                        len2 = added_list.length;\n
+                        for (k = 0; k < len2; k += 1) {\n
+                          node = added_list[k];\n
+                          if (node._gadget !== undefined) {\n
+                            createMonitor(node._gadget);\n
+                          }\n
+                        }\n
+                      }\n
+                    }\n
+\n
+                    len = mutation.addedNodes.length;\n
+                    for (i = 0; i < len; i += 1) {\n
+                      node = mutation.addedNodes[i];\n
+                      if (node.nodeType === Node.ELEMENT_NODE) {\n
+                        if (node.hasAttribute("data-gadget-url") &&\n
+                            (node._gadget !== undefined)) {\n
+                          if (document.contains(node)) {\n
+                            startService(node._gadget);\n
+                          }\n
+                        }\n
+                        added_list =\n
+                          node.querySelectorAll("[data-gadget-url]");\n
+                        len2 = added_list.length;\n
+                        for (k = 0; k < len2; k += 1) {\n
+                          node = added_list[k];\n
+                          if (document.contains(node)) {\n
+                            if (node._gadget !== undefined) {\n
+                              startService(node._gadget);\n
+                            }\n
+                          }\n
+                        }\n
+                      }\n
+                    }\n
+\n
+                  }\n
+                });\n
+              }),\n
+              // configuration of the observer:\n
+              config = {\n
+                childList: true,\n
+                subtree: true,\n
+                attributes: false,\n
+                characterData: false\n
+              };\n
+\n
+            // pass in the target node, as well as the observer options\n
+            observer.observe(target, config);\n
+\n
+            return root_gadget;\n
+          }).then(resolve, function (e) {\n
+            reject(e);\n
+            console.error(e);\n
+            throw e;\n
+          });\n
+      }\n
+      document.addEventListener(\'DOMContentLoaded\', init, false);\n
+    });\n
+\n
+    loading_gadget_promise\n
+      .push(function () {\n
+        return loading_klass_promise;\n
+      })\n
+      .push(function (root_gadget) {\n
+        var i;\n
+\n
+        function ready_wrapper() {\n
+          return root_gadget;\n
+        }\n
+\n
+        if (window.top !== window.self) {\n
+          //checking channel should be done before sub gadget\'s declaration\n
+          //__ready_list:\n
+          //0: clearGadgetInternalParameters\n
+          //1: loadSubGadgetDOMDeclaration\n
+          //.....\n
+          tmp_constructor.__ready_list.splice(1, 0, function () {\n
+            return root_gadget.__aq_parent(\'getTopURL\', [], 100)\n
+              .then(function (topURL) {\n
+                var base = document.createElement(\'base\');\n
+                base.href = topURL;\n
+                base.target = "_top";\n
+                document.head.appendChild(base);\n
+                //the channel is ok\n
+                //so bind calls to renderJS method on the instance\n
+                embedded_channel.bind("methodCall", function (trans, v) {\n
+                  root_gadget[v[0]].apply(root_gadget, v[1])\n
+                    .then(function (g) {\n
+                      trans.complete(g);\n
+                    }).fail(function (e) {\n
+                      trans.error(e.toString());\n
+                    });\n
+                  trans.delayReturn(true);\n
+                });\n
+              })\n
+              .fail(function (error) {\n
+                if (error === "timeout_error") {\n
+                  //the channel fail\n
+                  //we consider current gadget is parent gadget\n
+                  //redifine last acquisition gadget\n
+                  iframe_top_gadget = true;\n
+                  tmp_constructor.declareService(function () {\n
+                    return listenHashChange(this);\n
+                  });\n
+                  setAqParent(root_gadget, last_acquisition_gadget);\n
+                } else {\n
+                  throw error;\n
+                }\n
+              });\n
+          });\n
+        }\n
+\n
+        tmp_constructor.ready(function (g) {\n
+          return startService(g);\n
+        });\n
+\n
+        loading_gadget_promise.push(ready_wrapper);\n
+        for (i = 0; i < tmp_constructor.__ready_list.length; i += 1) {\n
+          // Put a timeout?\n
+          loading_gadget_promise\n
+            .push(tmp_constructor.__ready_list[i])\n
+            // Always return the gadget instance after ready function\n
+            .push(ready_wrapper);\n
+        }\n
+      });\n
+    if (window.self === window.top) {\n
+      loading_gadget_promise\n
+        .fail(function (e) {\n
+          letsCrash(e);\n
+          throw e;\n
+        });\n
+    } else {\n
+      // Inform parent window that gadget is correctly loaded\n
+      loading_gadget_promise\n
+        .then(function () {\n
+          gadget_ready = true;\n
+          notifyReady();\n
+        })\n
+        .fail(function (e) {\n
+          //top gadget in iframe\n
+          if (iframe_top_gadget) {\n
+            letsCrash(e);\n
+          } else {\n
+            embedded_channel.notify({method: "failed", params: e.toString()});\n
+          }\n
+          throw e;\n
+        });\n
+    }\n
+\n
+  }\n
+  bootstrap();\n
+\n
+}(document, window, RSVP, DOMParser, Channel, MutationObserver, Node));\n
+
+
+]]></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/rsvp.min.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/rsvp.min.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..85fa6ebe76917aed906e13f258031d27ef0af97f
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/rsvp.min.js.xml
@@ -0,0 +1,1167 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681769.39</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>rsvp.min.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+(function(globals) {\n
+var define, requireModule;\n
+\n
+(function() {\n
+  var registry = {}, seen = {};\n
+\n
+  define = function(name, deps, callback) {\n
+    registry[name] = { deps: deps, callback: callback };\n
+  };\n
+\n
+  requireModule = function(name) {\n
+    if (seen[name]) { return seen[name]; }\n
+    seen[name] = {};\n
+\n
+    var mod = registry[name];\n
+    if (!mod) {\n
+      throw new Error("Module \'" + name + "\' not found.");\n
+    }\n
+\n
+    var deps = mod.deps,\n
+        callback = mod.callback,\n
+        reified = [],\n
+        exports;\n
+\n
+    for (var i=0, l=deps.length; i<l; i++) {\n
+      if (deps[i] === \'exports\') {\n
+        reified.push(exports = {});\n
+      } else {\n
+        reified.push(requireModule(deps[i]));\n
+      }\n
+    }\n
+\n
+    var value = callback.apply(this, reified);\n
+    return seen[name] = exports || value;\n
+  };\n
+})();\n
+\n
+define("rsvp/all",\n
+  ["rsvp/promise","exports"],\n
+  function(__dependency1__, __exports__) {\n
+    "use strict";\n
+    var Promise = __dependency1__.Promise;\n
+    /* global toString */\n
+\n
+\n
+    function promiseAtLeast(expected_count, promises) {\n
+      if (Object.prototype.toString.call(promises) !== "[object Array]") {\n
+        throw new TypeError(\'You must pass an array to all.\');\n
+      }\n
+\n
+      function canceller() {\n
+        var promise;\n
+        for (var i = 0; i < promises.length; i++) {\n
+          promise = promises[i];\n
+\n
+          if (promise && typeof promise.then === \'function\' &&\n
+              typeof promise.cancel === \'function\') {\n
+            promise.cancel();\n
+          }\n
+        }\n
+      }\n
+\n
+      return new Promise(function(resolve, reject, notify) {\n
+        var results = [], remaining = promises.length,\n
+        promise, remaining_count = promises.length - expected_count;\n
+\n
+        if (remaining === 0) {\n
+          if (expected_count === 1) {\n
+            resolve();\n
+          } else {\n
+            resolve([]);\n
+          }\n
+        }\n
+\n
+        function resolver(index) {\n
+          return function(value) {\n
+            resolveAll(index, value);\n
+          };\n
+        }\n
+\n
+        function resolveAll(index, value) {\n
+          results[index] = value;\n
+          if (--remaining === remaining_count) {\n
+            if (remaining_count === 0) {\n
+              resolve(results);\n
+            } else {\n
+              resolve(value);\n
+              canceller();\n
+            }\n
+          }\n
+        }\n
+\n
+        function notifier(index) {\n
+          return function(value) {\n
+            notify({"index": index, "value": value});\n
+          };\n
+        }\n
+\n
+        function cancelAll(rejectionValue) {\n
+          reject(rejectionValue);\n
+          canceller();\n
+        }\n
+\n
+        for (var i = 0; i < promises.length; i++) {\n
+          promise = promises[i];\n
+\n
+          if (promise && typeof promise.then === \'function\') {\n
+            promise.then(resolver(i), cancelAll, notifier(i));\n
+          } else {\n
+            resolveAll(i, promise);\n
+          }\n
+        }\n
+      }, canceller\n
+      );\n
+    }\n
+\n
+    function all(promises) {\n
+      return promiseAtLeast(promises.length, promises);\n
+    }\n
+\n
+    function any(promises) {\n
+      return promiseAtLeast(1, promises);\n
+    }\n
+\n
+\n
+    __exports__.all = all;\n
+    __exports__.any = any;\n
+  });\n
+define("rsvp/async",\n
+  ["exports"],\n
+  function(__exports__) {\n
+    "use strict";\n
+    var browserGlobal = (typeof window !== \'undefined\') ? window : {};\n
+    var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver;\n
+    var async;\n
+    var local = (typeof global !== \'undefined\') ? global : this;\n
+\n
+    // old node\n
+    function useNextTick() {\n
+      return function(callback, arg) {\n
+        process.nextTick(function() {\n
+          callback(arg);\n
+        });\n
+      };\n
+    }\n
+\n
+    // node >= 0.10.x\n
+    function useSetImmediate() {\n
+      return function(callback, arg) {\n
+        /* global  setImmediate */\n
+        setImmediate(function(){\n
+          callback(arg);\n
+        });\n
+      };\n
+    }\n
+\n
+    function useMutationObserver() {\n
+      var queue = [];\n
+\n
+      var observer = new BrowserMutationObserver(function() {\n
+        var toProcess = queue.slice();\n
+        queue = [];\n
+\n
+        toProcess.forEach(function(tuple) {\n
+          var callback = tuple[0], arg= tuple[1];\n
+          callback(arg);\n
+        });\n
+      });\n
+\n
+      var element = document.createElement(\'div\');\n
+      observer.observe(element, { attributes: true });\n
+\n
+      // Chrome Memory Leak: https://bugs.webkit.org/show_bug.cgi?id=93661\n
+      window.addEventListener(\'unload\', function(){\n
+        observer.disconnect();\n
+        observer = null;\n
+      }, false);\n
+\n
+      return function(callback, arg) {\n
+        queue.push([callback, arg]);\n
+        element.setAttribute(\'drainQueue\', \'drainQueue\');\n
+      };\n
+    }\n
+\n
+    function useSetTimeout() {\n
+      return function(callback, arg) {\n
+        local.setTimeout(function() {\n
+          callback(arg);\n
+        }, 1);\n
+      };\n
+    }\n
+\n
+    if (typeof setImmediate === \'function\') {\n
+      async = useSetImmediate();\n
+    } else if (typeof process !== \'undefined\' && {}.toString.call(process) === \'[object process]\') {\n
+      async = useNextTick();\n
+    } else if (BrowserMutationObserver) {\n
+      async = useMutationObserver();\n
+    } else {\n
+      async = useSetTimeout();\n
+    }\n
+\n
+\n
+    __exports__.async = async;\n
+  });\n
+define("rsvp/cancellation_error",\n
+  ["exports"],\n
+  function(__exports__) {\n
+    "use strict";\n
+    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error\n
+    function CancellationError(message) {\n
+      this.name = "cancel";\n
+      if ((message !== undefined) && (typeof message !== "string")) {\n
+        throw new TypeError(\'You must pass a string.\');\n
+      }\n
+      this.message = message || "Default Message";\n
+    }\n
+    CancellationError.prototype = new Error();\n
+    CancellationError.prototype.constructor = CancellationError;\n
+\n
+\n
+    __exports__.CancellationError = CancellationError;\n
+  });\n
+define("rsvp/config",\n
+  ["rsvp/async","exports"],\n
+  function(__dependency1__, __exports__) {\n
+    "use strict";\n
+    var async = __dependency1__.async;\n
+\n
+    var config = {};\n
+    config.async = async;\n
+\n
+\n
+    __exports__.config = config;\n
+  });\n
+define("rsvp/defer",\n
+  ["rsvp/promise","exports"],\n
+  function(__dependency1__, __exports__) {\n
+    "use strict";\n
+    var Promise = __dependency1__.Promise;\n
+\n
+    function defer() {\n
+      var deferred = {\n
+        // pre-allocate shape\n
+        resolve: undefined,\n
+        reject:  undefined,\n
+        promise: undefined\n
+      };\n
+\n
+      deferred.promise = new Promise(function(resolve, reject) {\n
+        deferred.resolve = resolve;\n
+        deferred.reject = reject;\n
+      });\n
+\n
+      return deferred;\n
+    }\n
+\n
+\n
+    __exports__.defer = defer;\n
+  });\n
+define("rsvp/events",\n
+  ["exports"],\n
+  function(__exports__) {\n
+    "use strict";\n
+    var Event = function(type, options) {\n
+      this.type = type;\n
+\n
+      for (var option in options) {\n
+        if (!options.hasOwnProperty(option)) { continue; }\n
+\n
+        this[option] = options[option];\n
+      }\n
+    };\n
+\n
+    var indexOf = function(callbacks, callback) {\n
+      for (var i=0, l=callbacks.length; i<l; i++) {\n
+        if (callbacks[i][0] === callback) { return i; }\n
+      }\n
+\n
+      return -1;\n
+    };\n
+\n
+    var callbacksFor = function(object) {\n
+      var callbacks = object._promiseCallbacks;\n
+\n
+      if (!callbacks) {\n
+        callbacks = object._promiseCallbacks = {};\n
+      }\n
+\n
+      return callbacks;\n
+    };\n
+\n
+    var EventTarget = {\n
+      mixin: function(object) {\n
+        object.on = this.on;\n
+        object.off = this.off;\n
+        object.trigger = this.trigger;\n
+        return object;\n
+      },\n
+\n
+      on: function(eventNames, callback, binding) {\n
+        var allCallbacks = callbacksFor(this), callbacks, eventName;\n
+        eventNames = eventNames.split(/\\s+/);\n
+        binding = binding || this;\n
+\n
+        while (eventName = eventNames.shift()) {\n
+          callbacks = allCallbacks[eventName];\n
+\n
+          if (!callbacks) {\n
+            callbacks = allCallbacks[eventName] = [];\n
+          }\n
+\n
+          if (indexOf(callbacks, callback) === -1) {\n
+            callbacks.push([callback, binding]);\n
+          }\n
+        }\n
+      },\n
+\n
+      off: function(eventNames, callback) {\n
+        var allCallbacks = callbacksFor(this), callbacks, eventName, index;\n
+        eventNames = eventNames.split(/\\s+/);\n
+\n
+        while (eventName = eventNames.shift()) {\n
+          if (!callback) {\n
+            allCallbacks[eventName] = [];\n
+            continue;\n
+          }\n
+\n
+          callbacks = allCallbacks[eventName];\n
+\n
+          index = indexOf(callbacks, callback);\n
+\n
+          if (index !== -1) { callbacks.splice(index, 1); }\n
+        }\n
+      },\n
+\n
+      trigger: function(eventName, options) {\n
+        var allCallbacks = callbacksFor(this),\n
+            callbacks, callbackTuple, callback, binding, event;\n
+\n
+        if (callbacks = allCallbacks[eventName]) {\n
+          // Don\'t cache the callbacks.length since it may grow\n
+          for (var i=0; i<callbacks.length; i++) {\n
+            callbackTuple = callbacks[i];\n
+            callback = callbackTuple[0];\n
+            binding = callbackTuple[1];\n
+\n
+            if (typeof options !== \'object\') {\n
+              options = { detail: options };\n
+            }\n
+\n
+            event = new Event(eventName, options);\n
+            callback.call(binding, event);\n
+          }\n
+        }\n
+      }\n
+    };\n
+\n
+\n
+    __exports__.EventTarget = EventTarget;\n
+  });\n
+define("rsvp/hash",\n
+  ["rsvp/defer","exports"],\n
+  function(__dependency1__, __exports__) {\n
+    "use strict";\n
+    var defer = __dependency1__.defer;\n
+\n
+    function size(object) {\n
+      var s = 0;\n
+\n
+      for (var prop in object) {\n
+        s++;\n
+      }\n
+\n
+      return s;\n
+    }\n
+\n
+    function hash(promises) {\n
+      var results = {}, deferred = defer(), remaining = size(promises);\n
+\n
+      if (remaining === 0) {\n
+        deferred.resolve({});\n
+      }\n
+\n
+      var resolver = function(prop) {\n
+        return function(value) {\n
+          resolveAll(prop, value);\n
+        };\n
+      };\n
+\n
+      var resolveAll = function(prop, value) {\n
+        results[prop] = value;\n
+        if (--remaining === 0) {\n
+          deferred.resolve(results);\n
+        }\n
+      };\n
+\n
+      var rejectAll = function(error) {\n
+        deferred.reject(error);\n
+      };\n
+\n
+      for (var prop in promises) {\n
+        if (promises[prop] && typeof promises[prop].then === \'function\') {\n
+          promises[prop].then(resolver(prop), rejectAll);\n
+        } else {\n
+          resolveAll(prop, promises[prop]);\n
+        }\n
+      }\n
+\n
+      return deferred.promise;\n
+    }\n
+\n
+\n
+    __exports__.hash = hash;\n
+  });\n
+define("rsvp/node",\n
+  ["rsvp/promise","rsvp/all","exports"],\n
+  function(__dependency1__, __dependency2__, __exports__) {\n
+    "use strict";\n
+    var Promise = __dependency1__.Promise;\n
+    var all = __dependency2__.all;\n
+\n
+    function makeNodeCallbackFor(resolve, reject) {\n
+      return function (error, value) {\n
+        if (error) {\n
+          reject(error);\n
+        } else if (arguments.length > 2) {\n
+          resolve(Array.prototype.slice.call(arguments, 1));\n
+        } else {\n
+          resolve(value);\n
+        }\n
+      };\n
+    }\n
+\n
+    function denodeify(nodeFunc) {\n
+      return function()  {\n
+        var nodeArgs = Array.prototype.slice.call(arguments), resolve, reject;\n
+        var thisArg = this;\n
+\n
+        var promise = new Promise(function(nodeResolve, nodeReject) {\n
+          resolve = nodeResolve;\n
+          reject = nodeReject;\n
+        });\n
+\n
+        all(nodeArgs).then(function(nodeArgs) {\n
+          nodeArgs.push(makeNodeCallbackFor(resolve, reject));\n
+\n
+          try {\n
+            nodeFunc.apply(thisArg, nodeArgs);\n
+          } catch(e) {\n
+            reject(e);\n
+          }\n
+        });\n
+\n
+        return promise;\n
+      };\n
+    }\n
+\n
+\n
+    __exports__.denodeify = denodeify;\n
+  });\n
+define("rsvp/promise",\n
+  ["rsvp/config","rsvp/events","rsvp/cancellation_error","exports"],\n
+  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {\n
+    "use strict";\n
+    var config = __dependency1__.config;\n
+    var EventTarget = __dependency2__.EventTarget;\n
+    var CancellationError = __dependency3__.CancellationError;\n
+\n
+    function objectOrFunction(x) {\n
+      return isFunction(x) || (typeof x === "object" && x !== null);\n
+    }\n
+\n
+    function isFunction(x){\n
+      return typeof x === "function";\n
+    }\n
+\n
+    var Promise = function(resolver, canceller) {\n
+      var promise = this,\n
+      resolved = false;\n
+\n
+      if (typeof resolver !== \'function\') {\n
+        throw new TypeError(\'You must pass a resolver function as the sole argument to the promise constructor\');\n
+      }\n
+\n
+      if ((canceller !== undefined) && (typeof canceller !== \'function\')) {\n
+        throw new TypeError(\'You can only pass a canceller function\' +\n
+          \' as the second argument to the promise constructor\');\n
+      }\n
+\n
+      if (!(promise instanceof Promise)) {\n
+        return new Promise(resolver, canceller);\n
+      }\n
+\n
+      var resolvePromise = function(value) {\n
+        if (resolved) { return; }\n
+        resolved = true;\n
+        resolve(promise, value);\n
+      };\n
+\n
+      var rejectPromise = function(value) {\n
+        if (resolved) { return; }\n
+        resolved = true;\n
+        reject(promise, value);\n
+      };\n
+\n
+      var notifyPromise = function(value) {\n
+        if (resolved) { return; }\n
+        notify(promise, value);\n
+      };\n
+\n
+      this.on(\'promise:failed\', function(event) {\n
+        this.trigger(\'error\', { detail: event.detail });\n
+      }, this);\n
+\n
+      this.on(\'error\', onerror);\n
+\n
+      this.cancel = function () {\n
+        // For now, simply reject the promise and does not propagate the cancel\n
+        // to parent or children\n
+        if (resolved) { return; }\n
+        if (canceller !== undefined) {\n
+          try {\n
+            canceller();\n
+          } catch (e) {\n
+            rejectPromise(e);\n
+            return;\n
+          }\n
+        }\n
+        // Trigger cancel?\n
+        rejectPromise(new CancellationError());\n
+      };\n
+\n
+      try {\n
+        resolver(resolvePromise, rejectPromise, notifyPromise);\n
+      } catch(e) {\n
+        rejectPromise(e);\n
+      }\n
+    };\n
+\n
+    function onerror(event) {\n
+      if (config.onerror) {\n
+        config.onerror(event.detail);\n
+      }\n
+    }\n
+\n
+    var invokeCallback = function(type, promise, callback, event) {\n
+      var hasCallback = isFunction(callback),\n
+          value, error, succeeded, failed;\n
+\n
+      if (promise.isFulfilled) { return; }\n
+      if (promise.isRejected) { return; }\n
+\n
+      if (hasCallback) {\n
+        try {\n
+          value = callback(event.detail);\n
+          succeeded = true;\n
+        } catch(e) {\n
+          failed = true;\n
+          error = e;\n
+        }\n
+      } else {\n
+        value = event.detail;\n
+        succeeded = true;\n
+      }\n
+\n
+      if (handleThenable(promise, value)) {\n
+        return;\n
+      } else if (hasCallback && succeeded) {\n
+        resolve(promise, value);\n
+      } else if (failed) {\n
+        reject(promise, error);\n
+      } else if (type === \'resolve\') {\n
+        resolve(promise, value);\n
+      } else if (type === \'reject\') {\n
+        reject(promise, value);\n
+      }\n
+    };\n
+\n
+\n
+    var invokeNotifyCallback = function(promise, callback, event) {\n
+      var value;\n
+      if (typeof callback === \'function\') {\n
+        try {\n
+          value = callback(event.detail);\n
+        } catch (e) {\n
+          // stop propagating\n
+          return;\n
+        }\n
+        notify(promise, value);\n
+      } else {\n
+        notify(promise, event.detail);\n
+      }\n
+    };\n
+\n
+    Promise.prototype = {\n
+      constructor: Promise,\n
+\n
+      isRejected: undefined,\n
+      isFulfilled: undefined,\n
+      rejectedReason: undefined,\n
+      fulfillmentValue: undefined,\n
+\n
+      then: function(done, fail, progress) {\n
+        this.off(\'error\', onerror);\n
+\n
+        var thenPromise = new this.constructor(function() {},\n
+            function () {\n
+              thenPromise.trigger(\'promise:cancelled\', {});\n
+            });\n
+\n
+        if (this.isFulfilled) {\n
+          config.async(function(promise) {\n
+            invokeCallback(\'resolve\', thenPromise, done, { detail: promise.fulfillmentValue });\n
+          }, this);\n
+        }\n
+\n
+        if (this.isRejected) {\n
+          config.async(function(promise) {\n
+            invokeCallback(\'reject\', thenPromise, fail, { detail: promise.rejectedReason });\n
+          }, this);\n
+        }\n
+\n
+        this.on(\'promise:resolved\', function(event) {\n
+          invokeCallback(\'resolve\', thenPromise, done, event);\n
+        });\n
+\n
+        this.on(\'promise:failed\', function(event) {\n
+          invokeCallback(\'reject\', thenPromise, fail, event);\n
+        });\n
+\n
+        this.on(\'promise:notified\', function (event) {\n
+          invokeNotifyCallback(thenPromise, progress, event);\n
+        });\n
+\n
+        return thenPromise;\n
+      },\n
+\n
+      fail: function(fail) {\n
+        return this.then(null, fail);\n
+      },\n
+\n
+      always: function(fail) {\n
+        return this.then(fail, fail);\n
+      }\n
+    };\n
+\n
+    EventTarget.mixin(Promise.prototype);\n
+\n
+    function resolve(promise, value) {\n
+      if (promise === value) {\n
+        fulfill(promise, value);\n
+      } else if (!handleThenable(promise, value)) {\n
+        fulfill(promise, value);\n
+      }\n
+    }\n
+\n
+    function handleThenable(promise, value) {\n
+      var then = null,\n
+      resolved;\n
+\n
+      try {\n
+        if (promise === value) {\n
+          throw new TypeError("A promises callback cannot return that same promise.");\n
+        }\n
+\n
+        if (objectOrFunction(value)) {\n
+          then = value.then;\n
+\n
+          if (isFunction(then)) {\n
+            if (isFunction(value.on)) {\n
+              value.on(\'promise:notified\', function (event) {\n
+                notify(promise, event.detail);\n
+              });\n
+            }\n
+            promise.on(\'promise:cancelled\', function(event) {\n
+              if (isFunction(value.cancel)) {\n
+                value.cancel();\n
+              }\n
+            });\n
+            then.call(value, function(val) {\n
+              if (resolved) { return true; }\n
+              resolved = true;\n
+\n
+              if (value !== val) {\n
+                resolve(promise, val);\n
+              } else {\n
+                fulfill(promise, val);\n
+              }\n
+            }, function(val) {\n
+              if (resolved) { return true; }\n
+              resolved = true;\n
+\n
+              reject(promise, val);\n
+            });\n
+\n
+            return true;\n
+          }\n
+        }\n
+      } catch (error) {\n
+        reject(promise, error);\n
+        return true;\n
+      }\n
+\n
+      return false;\n
+    }\n
+\n
+    function fulfill(promise, value) {\n
+      config.async(function() {\n
+        if (promise.isFulfilled) { return; }\n
+        if (promise.isRejected) { return; }\n
+        promise.trigger(\'promise:resolved\', { detail: value });\n
+        promise.isFulfilled = true;\n
+        promise.fulfillmentValue = value;\n
+      });\n
+    }\n
+\n
+    function reject(promise, value) {\n
+      config.async(function() {\n
+        if (promise.isFulfilled) { return; }\n
+        if (promise.isRejected) { return; }\n
+        promise.trigger(\'promise:failed\', { detail: value });\n
+        promise.isRejected = true;\n
+        promise.rejectedReason = value;\n
+      });\n
+    }\n
+\n
+    function notify(promise, value) {\n
+      config.async(function() {\n
+        promise.trigger(\'promise:notified\', { detail: value });\n
+      });\n
+    }\n
+\n
+\n
+    __exports__.Promise = Promise;\n
+  });\n
+define("rsvp/queue",\n
+  ["rsvp/promise","rsvp/timeout","exports"],\n
+  function(__dependency1__, __dependency2__, __exports__) {\n
+    "use strict";\n
+    var Promise = __dependency1__.Promise;\n
+    var delay = __dependency2__.delay;\n
+\n
+    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error\n
+    function ResolvedQueueError(message) {\n
+      this.name = "resolved";\n
+      if ((message !== undefined) && (typeof message !== "string")) {\n
+        throw new TypeError(\'You must pass a string.\');\n
+      }\n
+      this.message = message || "Default Message";\n
+    }\n
+    ResolvedQueueError.prototype = new Error();\n
+    ResolvedQueueError.prototype.constructor = ResolvedQueueError;\n
+\n
+    var Queue = function() {\n
+      var queue = this,\n
+        promise_list = [],\n
+        promise,\n
+        fulfill,\n
+        reject,\n
+        notify,\n
+        resolved;\n
+\n
+      if (!(this instanceof Queue)) {\n
+        return new Queue();\n
+      }\n
+\n
+      function canceller() {\n
+        for (var i = 0; i < 2; i++) {\n
+          promise_list[i].cancel();\n
+        }\n
+      }\n
+\n
+      promise = new Promise(function(done, fail, progress) {\n
+        fulfill = function (fulfillmentValue) {\n
+          if (resolved) {return;}\n
+          queue.isFulfilled = true;\n
+          queue.fulfillmentValue = fulfillmentValue;\n
+          resolved = true;\n
+          return done(fulfillmentValue);\n
+        };\n
+        reject = function (rejectedReason) {\n
+          if (resolved) {return;}\n
+          queue.isRejected = true;\n
+          queue.rejectedReason = rejectedReason ;\n
+          resolved = true;\n
+          return fail(rejectedReason);\n
+        };\n
+        notify = progress;\n
+      }, canceller);\n
+\n
+      promise_list.push(delay());\n
+      promise_list.push(promise_list[0].then(function () {\n
+        promise_list.splice(0, 2);\n
+        if (promise_list.length === 0) {\n
+          fulfill();\n
+        }\n
+      }));\n
+\n
+      queue.cancel = function () {\n
+        if (resolved) {return;}\n
+        resolved = true;\n
+        promise.cancel();\n
+        promise.fail(function (rejectedReason) {\n
+          queue.isRejected = true;\n
+          queue.rejectedReason = rejectedReason;\n
+        });\n
+      };\n
+      queue.then = function () {\n
+        return promise.then.apply(promise, arguments);\n
+      };\n
+\n
+      queue.push = function(done, fail, progress) {\n
+        var last_promise = promise_list[promise_list.length - 1],\n
+          next_promise;\n
+\n
+        if (resolved) {\n
+          throw new ResolvedQueueError();\n
+        }\n
+\n
+        next_promise = last_promise.then(done, fail, progress);\n
+        promise_list.push(next_promise);\n
+\n
+        // Handle pop\n
+        last_promise = next_promise.then(function (fulfillmentValue) {\n
+          promise_list.splice(0, 2);\n
+          if (promise_list.length === 0) {\n
+            fulfill(fulfillmentValue);\n
+          } else {\n
+            return fulfillmentValue;\n
+          }\n
+        }, function (rejectedReason) {\n
+          promise_list.splice(0, 2);\n
+          if (promise_list.length === 0) {\n
+            reject(rejectedReason);\n
+          } else {\n
+            throw rejectedReason;\n
+          }\n
+        }, function (notificationValue) {\n
+          if (promise_list[promise_list.length - 1] === last_promise) {\n
+            notify(notificationValue);\n
+          }\n
+          return notificationValue;\n
+        });\n
+        promise_list.push(last_promise);\n
+\n
+        return this;\n
+      };\n
+    };\n
+\n
+    Queue.prototype = Object.create(Promise.prototype);\n
+    Queue.prototype.constructor = Queue;\n
+\n
+\n
+    __exports__.Queue = Queue;\n
+    __exports__.ResolvedQueueError = ResolvedQueueError;\n
+  });\n
+define("rsvp/reject",\n
+  ["rsvp/promise","exports"],\n
+  function(__dependency1__, __exports__) {\n
+    "use strict";\n
+    var Promise = __dependency1__.Promise;\n
+\n
+    function reject(reason) {\n
+      return new Promise(function (resolve, reject) {\n
+        reject(reason);\n
+      });\n
+    }\n
+\n
+\n
+    __exports__.reject = reject;\n
+  });\n
+define("rsvp/resolve",\n
+  ["rsvp/promise","exports"],\n
+  function(__dependency1__, __exports__) {\n
+    "use strict";\n
+    var Promise = __dependency1__.Promise;\n
+\n
+    function resolve(thenable) {\n
+      return new Promise(function(resolve, reject) {\n
+        if (typeof thenable === "object" && thenable !== null) {\n
+          var then = thenable.then;\n
+          if ((then !== undefined) && (typeof then === "function")) {\n
+            return then.apply(thenable, [resolve, reject]);\n
+          }\n
+        }\n
+        return resolve(thenable);\n
+      }, function () {\n
+        if ((thenable !== undefined) && (thenable.cancel !== undefined)) {\n
+          thenable.cancel();\n
+        }\n
+      });\n
+    }\n
+\n
+\n
+    __exports__.resolve = resolve;\n
+  });\n
+define("rsvp/rethrow",\n
+  ["exports"],\n
+  function(__exports__) {\n
+    "use strict";\n
+    var local = (typeof global === "undefined") ? this : global;\n
+\n
+    function rethrow(reason) {\n
+      local.setTimeout(function() {\n
+        throw reason;\n
+      });\n
+      throw reason;\n
+    }\n
+\n
+\n
+    __exports__.rethrow = rethrow;\n
+  });\n
+define("rsvp/timeout",\n
+  ["rsvp/promise","exports"],\n
+  function(__dependency1__, __exports__) {\n
+    "use strict";\n
+    var Promise = __dependency1__.Promise;\n
+\n
+    function promiseSetTimeout(millisecond, should_reject, message) {\n
+      var timeout_id;\n
+\n
+      function resolver(resolve, reject) {\n
+        timeout_id = setTimeout(function () {\n
+          if (should_reject) {\n
+            reject(message);\n
+          } else {\n
+            resolve(message);\n
+          }\n
+        }, millisecond);\n
+      }\n
+      function canceller() {\n
+        clearTimeout(timeout_id);\n
+      }\n
+      return new Promise(resolver, canceller);\n
+    }\n
+\n
+    function delay(millisecond, message) {\n
+      return promiseSetTimeout(millisecond, false, message);\n
+    }\n
+\n
+    function timeout(millisecond) {\n
+      return promiseSetTimeout(millisecond, true,\n
+                               "Timed out after " + millisecond + " ms");\n
+    }\n
+\n
+    Promise.prototype.delay = function(millisecond) {\n
+      return this.then(function (fulfillmentValue) {\n
+        return delay(millisecond, fulfillmentValue);\n
+      });\n
+    };\n
+\n
+\n
+    __exports__.delay = delay;\n
+    __exports__.timeout = timeout;\n
+  });\n
+define("rsvp/watcher",\n
+  ["rsvp/promise","rsvp/queue","rsvp/cancellation_error","exports"],\n
+  function(__dependency1__, __dependency2__, __dependency3__, __exports__) {\n
+    "use strict";\n
+    var Promise = __dependency1__.Promise;\n
+    var Queue = __dependency2__.Queue;\n
+    var CancellationError = __dependency3__.CancellationError;\n
+\n
+    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error\n
+    function ResolvedMonitorError(message) {\n
+      this.name = "resolved";\n
+      if ((message !== undefined) && (typeof message !== "string")) {\n
+        throw new TypeError(\'You must pass a string.\');\n
+      }\n
+      this.message = message || "Default Message";\n
+    }\n
+    ResolvedMonitorError.prototype = new Error();\n
+    ResolvedMonitorError.prototype.constructor = ResolvedMonitorError;\n
+\n
+    function isFunction(x){\n
+      return typeof x === "function";\n
+    }\n
+\n
+    var Monitor = function() {\n
+      var monitor = this,\n
+        promise_list = [],\n
+        promise,\n
+        reject,\n
+        notify,\n
+        resolved;\n
+\n
+      if (!(this instanceof Monitor)) {\n
+        return new Monitor();\n
+      }\n
+\n
+      function canceller() {\n
+        var len = promise_list.length,\n
+          i;\n
+        for (i = 0; i < len; i += 1) {\n
+          promise_list[i].cancel();\n
+        }\n
+        // Clean it to speed up other canceller run\n
+        promise_list = [];\n
+      }\n
+\n
+      promise = new Promise(function(done, fail, progress) {\n
+        reject = function (rejectedReason) {\n
+          if (resolved) {return;}\n
+          monitor.isRejected = true;\n
+          monitor.rejectedReason = rejectedReason ;\n
+          resolved = true;\n
+          canceller();\n
+          return fail(rejectedReason);\n
+        };\n
+        notify = progress;\n
+      }, canceller);\n
+\n
+      monitor.cancel = function () {\n
+        if (resolved) {return;}\n
+        resolved = true;\n
+        promise.cancel();\n
+        promise.fail(function (rejectedReason) {\n
+          monitor.isRejected = true;\n
+          monitor.rejectedReason = rejectedReason;\n
+        });\n
+      };\n
+      monitor.then = function () {\n
+        return promise.then.apply(promise, arguments);\n
+      };\n
+\n
+      monitor.monitor = function(promise_to_monitor) {\n
+        if (resolved) {\n
+          throw new ResolvedMonitorError();\n
+        }\n
+        var queue = new Queue()\n
+          .push(function () {\n
+            return promise_to_monitor;\n
+          })\n
+          .push(function (fulfillmentValue) {\n
+            // Promise to monitor is fullfilled, remove it from the list\n
+            var len = promise_list.length,\n
+              promise_to_monitor,\n
+              new_promise_list = [],\n
+              i;\n
+            for (i = 0; i < len; i += 1) {\n
+              promise_to_monitor = promise_list[i];\n
+              if (!(promise_to_monitor.isFulfilled ||\n
+                  promise_to_monitor.isRejected)) {\n
+                new_promise_list.push(promise_to_monitor);\n
+              }\n
+            }\n
+            promise_list = new_promise_list;\n
+          }, function (rejectedReason) {\n
+            if (rejectedReason instanceof CancellationError) {\n
+              if (!(promise_to_monitor.isFulfilled && promise_to_monitor.isRejected)) {\n
+                // The queue could be cancelled before the first push is run\n
+                promise_to_monitor.cancel();\n
+              }\n
+            }\n
+            reject(rejectedReason);\n
+            throw rejectedReason;\n
+          }, function (notificationValue) {\n
+            notify(notificationValue);\n
+            return notificationValue;\n
+          });\n
+\n
+        promise_list.push(queue);\n
+\n
+        return this;\n
+      };\n
+    };\n
+\n
+    Monitor.prototype = Object.create(Promise.prototype);\n
+    Monitor.prototype.constructor = Monitor;\n
+\n
+\n
+    __exports__.Monitor = Monitor;\n
+    __exports__.ResolvedMonitorError = ResolvedMonitorError;\n
+  });\n
+define("rsvp",\n
+  ["rsvp/events","rsvp/cancellation_error","rsvp/promise","rsvp/node","rsvp/all","rsvp/queue","rsvp/watcher","rsvp/timeout","rsvp/hash","rsvp/rethrow","rsvp/defer","rsvp/config","rsvp/resolve","rsvp/reject","exports"],\n
+  function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __dependency10__, __dependency11__, __dependency12__, __dependency13__, __dependency14__, __exports__) {\n
+    "use strict";\n
+    var EventTarget = __dependency1__.EventTarget;\n
+    var CancellationError = __dependency2__.CancellationError;\n
+    var Promise = __dependency3__.Promise;\n
+    var denodeify = __dependency4__.denodeify;\n
+    var all = __dependency5__.all;\n
+    var any = __dependency5__.any;\n
+    var Queue = __dependency6__.Queue;\n
+    var ResolvedQueueError = __dependency6__.ResolvedQueueError;\n
+    var Monitor = __dependency7__.Monitor;\n
+    var ResolvedMonitorError = __dependency7__.ResolvedMonitorError;\n
+    var delay = __dependency8__.delay;\n
+    var timeout = __dependency8__.timeout;\n
+    var hash = __dependency9__.hash;\n
+    var rethrow = __dependency10__.rethrow;\n
+    var defer = __dependency11__.defer;\n
+    var config = __dependency12__.config;\n
+    var resolve = __dependency13__.resolve;\n
+    var reject = __dependency14__.reject;\n
+\n
+    function configure(name, value) {\n
+      config[name] = value;\n
+    }\n
+\n
+\n
+    __exports__.CancellationError = CancellationError;\n
+    __exports__.Promise = Promise;\n
+    __exports__.EventTarget = EventTarget;\n
+    __exports__.all = all;\n
+    __exports__.any = any;\n
+    __exports__.Queue = Queue;\n
+    __exports__.ResolvedQueueError = ResolvedQueueError;\n
+    __exports__.Monitor = Monitor;\n
+    __exports__.ResolvedMonitorError = ResolvedMonitorError;\n
+    __exports__.delay = delay;\n
+    __exports__.timeout = timeout;\n
+    __exports__.hash = hash;\n
+    __exports__.rethrow = rethrow;\n
+    __exports__.defer = defer;\n
+    __exports__.denodeify = denodeify;\n
+    __exports__.configure = configure;\n
+    __exports__.resolve = resolve;\n
+    __exports__.reject = reject;\n
+  });\n
+window.RSVP = requireModule("rsvp");\n
+})(window);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>30923</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/uritemplate.min.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/uritemplate.min.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..bb03c4b51b9658232bf23f68a153d30c87a5707d
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/lib/uritemplate.min.js.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681770.79</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>uritemplate.min.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+!function(e){"use strict";function t(e){var n;if(null===e||void 0===e)return!1;if(r.isArray(e))return e.length>0;if("string"==typeof e||"number"==typeof e||"boolean"==typeof e)return!0;for(n in e)if(e.hasOwnProperty(n)&&t(e[n]))return!0;return!1}var n=function(){function e(e){this.options=e}return e.prototype.toString=function(){return JSON&&JSON.stringify?JSON.stringify(this.options):this.options},e}(),r=function(){function e(e){return"[object Array]"===Object.prototype.toString.apply(e)}function t(e){return"[object String]"===Object.prototype.toString.apply(e)}function n(e){return"[object Number]"===Object.prototype.toString.apply(e)}function r(e){return"[object Boolean]"===Object.prototype.toString.apply(e)}function i(e,t){var n,r="",i=!0;for(n=0;n<e.length;n+=1)i?i=!1:r+=t,r+=e[n];return r}function o(e,t){for(var n=[],r=0;r<e.length;r+=1)n.push(t(e[r]));return n}function s(e,t){for(var n=[],r=0;r<e.length;r+=1)t(e[r])&&n.push(e[r]);return n}function a(e){if("object"!=typeof e||null===e)return e;Object.freeze(e);var t,n;for(n in e)e.hasOwnProperty(n)&&(t=e[n],"object"==typeof t&&u(t));return e}function u(e){return"function"==typeof Object.freeze?a(e):e}return{isArray:e,isString:t,isNumber:n,isBoolean:r,join:i,map:o,filter:s,deepFreeze:u}}(),i=function(){function e(e){return e>="a"&&"z">=e||e>="A"&&"Z">=e}function t(e){return e>="0"&&"9">=e}function n(e){return t(e)||e>="a"&&"f">=e||e>="A"&&"F">=e}return{isAlpha:e,isDigit:t,isHexDigit:n}}(),o=function(){function e(e){var t,n,r="",i=s.encode(e);for(n=0;n<i.length;n+=1)t=i.charCodeAt(n),r+="%"+(16>t?"0":"")+t.toString(16).toUpperCase();return r}function t(e,t){return"%"===e.charAt(t)&&i.isHexDigit(e.charAt(t+1))&&i.isHexDigit(e.charAt(t+2))}function n(e,t){return parseInt(e.substr(t,2),16)}function r(e){if(!t(e,0))return!1;var r=n(e,1),i=s.numBytes(r);if(0===i)return!1;for(var o=1;i>o;o+=1)if(!t(e,3*o)||!s.isValidFollowingCharCode(n(e,3*o+1)))return!1;return!0}function o(e,r){var i=e.charAt(r);if(!t(e,r))return i;var o=n(e,r+1),a=s.numBytes(o);if(0===a)return i;for(var u=1;a>u;u+=1)if(!t(e,r+3*u)||!s.isValidFollowingCharCode(n(e,r+3*u+1)))return i;return e.substr(r,3*a)}var s={encode:function(e){return unescape(encodeURIComponent(e))},numBytes:function(e){return 127>=e?1:e>=194&&223>=e?2:e>=224&&239>=e?3:e>=240&&244>=e?4:0},isValidFollowingCharCode:function(e){return e>=128&&191>=e}};return{encodeCharacter:e,isPctEncoded:r,pctCharAt:o}}(),s=function(){function e(e){return i.isAlpha(e)||i.isDigit(e)||"_"===e||o.isPctEncoded(e)}function t(e){return i.isAlpha(e)||i.isDigit(e)||"-"===e||"."===e||"_"===e||"~"===e}function n(e){return":"===e||"/"===e||"?"===e||"#"===e||"["===e||"]"===e||"@"===e||"!"===e||"$"===e||"&"===e||"("===e||")"===e||"*"===e||"+"===e||","===e||";"===e||"="===e||"\'"===e}return{isVarchar:e,isUnreserved:t,isReserved:n}}(),a=function(){function e(e,t){var n,r="",i="";for(("number"==typeof e||"boolean"==typeof e)&&(e=e.toString()),n=0;n<e.length;n+=i.length)i=e.charAt(n),r+=s.isUnreserved(i)||t&&s.isReserved(i)?i:o.encodeCharacter(i);return r}function t(t){return e(t,!0)}function n(e,t){var n=o.pctCharAt(e,t);return n.length>1?n:s.isReserved(n)||s.isUnreserved(n)?n:o.encodeCharacter(n)}function r(e){var t,n="",r="";for(t=0;t<e.length;t+=r.length)r=o.pctCharAt(e,t),n+=r.length>1?r:s.isReserved(r)||s.isUnreserved(r)?r:o.encodeCharacter(r);return n}return{encode:e,encodePassReserved:t,encodeLiteral:r,encodeLiteralCharacter:n}}(),u=function(){function e(e){t[e]={symbol:e,separator:"?"===e?"&":""===e||"+"===e||"#"===e?",":e,named:";"===e||"&"===e||"?"===e,ifEmpty:"&"===e||"?"===e?"=":"",first:"+"===e?"":e,encode:"+"===e||"#"===e?a.encodePassReserved:a.encode,toString:function(){return this.symbol}}}var t={};return e(""),e("+"),e("#"),e("."),e("/"),e(";"),e("?"),e("&"),{valueOf:function(e){return t[e]?t[e]:"=,!@|".indexOf(e)>=0?null:t[""]}}}(),p=function(){function e(e){this.literal=a.encodeLiteral(e)}return e.prototype.expand=function(){return this.literal},e.prototype.toString=e.prototype.expand,e}(),f=function(){function e(e){function t(){var t=e.substring(h,p);if(0===t.length)throw new n({expressionText:e,message:"a varname must be specified",position:p});c={varname:t,exploded:!1,maxLength:null},h=null}function r(){if(d===p)throw new n({expressionText:e,message:"after a \':\' you have to specify the length",position:p});c.maxLength=parseInt(e.substring(d,p),10),d=null}var a,p,f=[],c=null,h=null,d=null,g="";for(a=function(t){var r=u.valueOf(t);if(null===r)throw new n({expressionText:e,message:"illegal use of reserved operator",position:p,operator:t});return r}(e.charAt(0)),p=a.symbol.length,h=p;p<e.length;p+=g.length){if(g=o.pctCharAt(e,p),null!==h){if("."===g){if(h===p)throw new n({expressionText:e,message:"a varname MUST NOT start with a dot",position:p});continue}if(s.isVarchar(g))continue;t()}if(null!==d){if(p===d&&"0"===g)throw new n({expressionText:e,message:"A :prefix must not start with digit 0",position:p});if(i.isDigit(g)){if(p-d>=4)throw new n({expressionText:e,message:"A :prefix must have max 4 digits",position:p});continue}r()}if(":"!==g)if("*"!==g){if(","!==g)throw new n({expressionText:e,message:"illegal character",character:g,position:p});f.push(c),c=null,h=p+1}else{if(null===c)throw new n({expressionText:e,message:"exploded without varspec",position:p});if(c.exploded)throw new n({expressionText:e,message:"exploded twice",position:p});if(c.maxLength)throw new n({expressionText:e,message:"an explode (*) MUST NOT follow to a prefix",position:p});c.exploded=!0}else{if(null!==c.maxLength)throw new n({expressionText:e,message:"only one :maxLength is allowed per varspec",position:p});if(c.exploded)throw new n({expressionText:e,message:"an exploeded varspec MUST NOT be varspeced",position:p});d=p+1}}return null!==h&&t(),null!==d&&r(),f.push(c),new l(e,a,f)}function t(e){return e.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g,"\\\\$&")}function r(r){var i,o,s,a=[],u=null,f="",l=!0,h=0;for(i=0;i<r.length;i+=1)if(o=r.charAt(i),null===h){if(null===u)throw new Error("reached unreachable code");if("{"===o)throw new n({templateText:r,message:"brace already opened",position:i});if("}"===o){if(u+1===i)throw new n({templateText:r,message:"empty braces",position:u});try{s=e(r.substring(u+1,i))}catch(d){if(d.prototype===n.prototype)throw new n({templateText:r,message:d.options.message,position:u+d.options.position,details:d.options});throw d}a.push(s),0===s.operator.symbol.length?f+="([^/]+)":l=!1,u=null,h=i+1}}else{if("}"===o)throw new n({templateText:r,message:"unopened brace closed",position:i});"{"===o&&(i>h&&(s=new p(r.substring(h,i)),a.push(s),f+=t(s.literal)),h=null,u=i)}if(null!==u)throw new n({templateText:r,message:"unclosed brace",position:u});return h<r.length&&(s=new p(r.substring(h)),a.push(s),f+=t(s.literal)),l===!1&&(f=void 0),new c(r,a,f)}return r}(),l=function(){function e(e){return JSON&&JSON.stringify?JSON.stringify(e):e}function n(e){if(!t(e))return!0;if(r.isString(e))return""===e;if(r.isNumber(e)||r.isBoolean(e))return!1;if(r.isArray(e))return 0===e.length;for(var n in e)if(e.hasOwnProperty(n))return!1;return!0}function i(e){var t,n=[];for(t in e)e.hasOwnProperty(t)&&n.push({name:t,value:e[t]});return n}function o(e,t,n){this.templateText=e,this.operator=t,this.varspecs=n}function s(e,t,n){var r="";if(n=n.toString(),t.named){if(r+=a.encodeLiteral(e.varname),""===n)return r+=t.ifEmpty;r+="="}return null!==e.maxLength&&(n=n.substr(0,e.maxLength)),r+=t.encode(n)}function u(e){return t(e.value)}function p(e,o,s){var p=[],f="";if(o.named){if(f+=a.encodeLiteral(e.varname),n(s))return f+=o.ifEmpty;f+="="}return r.isArray(s)?(p=s,p=r.filter(p,t),p=r.map(p,o.encode),f+=r.join(p,",")):(p=i(s),p=r.filter(p,u),p=r.map(p,function(e){return o.encode(e.name)+","+o.encode(e.value)}),f+=r.join(p,",")),f}function f(e,o,s){var p=r.isArray(s),f=[];return p?(f=s,f=r.filter(f,t),f=r.map(f,function(t){var r=a.encodeLiteral(e.varname);return r+=n(t)?o.ifEmpty:"="+o.encode(t)})):(f=i(s),f=r.filter(f,u),f=r.map(f,function(e){var t=a.encodeLiteral(e.name);return t+=n(e.value)?o.ifEmpty:"="+o.encode(e.value)})),r.join(f,o.separator)}function l(e,n){var o=[],s="";return r.isArray(n)?(o=n,o=r.filter(o,t),o=r.map(o,e.encode),s+=r.join(o,e.separator)):(o=i(n),o=r.filter(o,function(e){return t(e.value)}),o=r.map(o,function(t){return e.encode(t.name)+"="+e.encode(t.value)}),s+=r.join(o,e.separator)),s}return o.prototype.toString=function(){return this.templateText},o.prototype.expand=function(i){var o,a,u,c,h=[],d=!1,g=this.operator;for(o=0;o<this.varspecs.length;o+=1)if(a=this.varspecs[o],u=i[a.varname],null!==u&&void 0!==u)if(a.exploded&&(d=!0),c=r.isArray(u),"string"==typeof u||"number"==typeof u||"boolean"==typeof u)h.push(s(a,g,u));else{if(a.maxLength&&t(u))throw new Error("Prefix modifiers are not applicable to variables that have composite values. You tried to expand "+this+" with "+e(u));a.exploded?t(u)&&(g.named?h.push(f(a,g,u)):h.push(l(g,u))):(g.named||!n(u))&&h.push(p(a,g,u))}return 0===h.length?"":g.first+r.join(h,g.separator)},o}(),c=function(){function e(e,t,n){this.templateText=e,this.expressions=t,void 0!==n&&(this.regexp=new RegExp("^"+n+"$")),r.deepFreeze(this)}return e.prototype.toString=function(){return this.templateText},e.prototype.expand=function(e){var t,n="";for(t=0;t<this.expressions.length;t+=1)n+=this.expressions[t].expand(e);return n},e.prototype.extract=function(e){var t,n,r,i,o=1,s=!0,a={};if(void 0!==this.regexp&&this.regexp.test(e)){for(i=this.regexp.exec(e),t=0;t<this.expressions.length;t+=1)n=this.expressions[t],void 0===n.literal&&(void 0!==n.operator&&0===n.operator.symbol.length&&1===n.varspecs.length?(r=n.varspecs[0],r.exploded===!1&&null===r.maxLength?-1===i[o].indexOf(",")?(a[r.varname]=decodeURIComponent(i[o]),o+=1):s=!1:s=!1):s=!1);if(s)return a}return!1},e.parse=f,e.UriTemplateError=n,e}();e(c)}(function(e){"use strict";"undefined"!=typeof module?module.exports=e:"function"==typeof define?define([],function(){return e}):"undefined"!=typeof window?window.UriTemplate=e:global.UriTemplate=e});
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>10059</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/list_field.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/list_field.xml
new file mode 100644
index 0000000000000000000000000000000000000000..97a1afdabd7eaf1e4d931cd014ee7fd602564b67
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/list_field.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>list_field</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/list_field/index.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/list_field/index.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..160ee6ca08d84f5126d795c7d223914cacdc27a3
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/list_field/index.html.xml
@@ -0,0 +1,71 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681771.98</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />\n
+    <meta name="viewport" content="width=device-width, user-scalable=no" />\n
+    <title>Listfield</title>\n
+\n
+    <!-- renderjs -->\n
+    <script src="../lib/rsvp.min.js" type="text/javascript"></script>\n
+    <script src="../lib/renderjs.min.js" type="text/javascript"></script>\n
+    <script src="../lib/handlebars.min.js" type="text/javascript"></script>\n
+    <!-- custom script -->\n
+    <script src="listfield.js" type="text/javascript"></script>\n
+\n
+    <script id="option-template" type="text/x-handlebars-template">\n
+      <option value="{{value}}">{{text}}</option>\n
+    </script>\n
+\n
+    <script id="selected-option-template" type="text/x-handlebars-template">\n
+      <option selected="selected" value="{{value}}">{{text}}</option>\n
+    </script>\n
+\n
+  </head>\n
+  <body>\n
+    <select />\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>893</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/list_field/listfield.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/list_field/listfield.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..625df7ec7fb896c0cf4fd2016ec99394b4976ce4
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/list_field/listfield.js.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681772.11</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>listfield.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+/*global window, rJS, Handlebars */\n
+/*jslint nomen: true */\n
+(function(window, rJS, Handlebars) {\n
+    "use strict";\n
+    /////////////////////////////////////////////////////////////////\n
+    // Handlebars\n
+    /////////////////////////////////////////////////////////////////\n
+    // Precompile the templates while loading the first gadget instance\n
+    var gadget_klass = rJS(window), option_source = gadget_klass.__template_element.getElementById("option-template").innerHTML, option_template = Handlebars.compile(option_source), selected_option_source = gadget_klass.__template_element.getElementById("selected-option-template").innerHTML, selected_option_template = Handlebars.compile(selected_option_source);\n
+    gadget_klass.ready(function(g) {\n
+        return g.getElement().push(function(element) {\n
+            g.element = element;\n
+        });\n
+    }).declareMethod("render", function(options) {\n
+        var select = this.element.getElementsByTagName("select")[0], i, template, tmp = "";\n
+        select.setAttribute("name", options.key);\n
+        for (i = 0; i < options.property_definition.enum.length; i += 1) {\n
+            if (options.property_definition.enum[i] === options.value) {\n
+                template = selected_option_template;\n
+            } else {\n
+                template = option_template;\n
+            }\n
+            // XXX value and text are always same in json schema\n
+            tmp += template({\n
+                value: options.property_definition.enum[i],\n
+                text: options.property_definition.enum[i]\n
+            });\n
+        }\n
+        select.innerHTML += tmp;\n
+    }).declareMethod("getContent", function() {\n
+        var select = this.element.getElementsByTagName("select")[0], result = {};\n
+        result[select.getAttribute("name")] = select.options[select.selectedIndex].value;\n
+        return result;\n
+    });\n
+})(window, rJS, Handlebars);
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1870</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/number_field.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/number_field.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5a082740b801c4fc1dfe4ac488d9f961e8a27e0f
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/number_field.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>number_field</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/number_field/index.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/number_field/index.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2fa1574982d447df9d9d11ce18afbc2459e90077
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/number_field/index.html.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681772.4</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />\n
+    <meta name="viewport" content="width=device-width, user-scalable=no" />\n
+    <title>Number field</title>\n
+\n
+    <!-- renderjs -->\n
+    <script src="../lib/rsvp.min.js"></script>\n
+    <script src="../lib/renderjs.min.js"></script>\n
+    <!-- custom script -->\n
+    <script src="numberfield.js" type="text/javascript"></script>\n
+\n
+  </head>\n
+  <body>\n
+    <input type=\'number\' step="any" data-mini="true" />\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>522</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/number_field/numberfield.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/number_field/numberfield.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..5f947ef85efc3df8a651c3eba7505e6e13f94ca7
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/number_field/numberfield.js.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681772.54</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>numberfield.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global window, rJS */\n
+(function(window, rJS) {\n
+    "use strict";\n
+    rJS(window).ready(function(gadget) {\n
+        return gadget.getElement().push(function(element) {\n
+            gadget.element = element;\n
+        });\n
+    }).declareMethod("render", function(options) {\n
+        var input = this.element.querySelector("input");\n
+        input.setAttribute("value", options.value);\n
+        input.setAttribute("name", options.key);\n
+        input.setAttribute("title", options.title || options.key);\n
+    }).declareMethod("getContent", function() {\n
+        var input = this.element.querySelector("input"), result = {};\n
+        if (input.value !== "") {\n
+            result[input.getAttribute("name")] = parseFloat(input.value);\n
+        } else {\n
+            result[input.getAttribute("name")] = null;\n
+        }\n
+        return result;\n
+    });\n
+})(window, rJS);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>849</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/string_field.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/string_field.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6c4cf0f0e494db2d97f74517c0cd889afbd55ede
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/string_field.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>string_field</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/string_field/index.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/string_field/index.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..cb0ed261c700073b5ad78197a5728132c4e43fad
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/string_field/index.html.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681773.03</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!DOCTYPE html>\n
+<html>\n
+  <head>\n
+    <meta http-equiv="Content-type" content="text/html; charset=utf-8" />\n
+    <meta name="viewport" content="width=device-width, user-scalable=no" />\n
+    <title>Stringfield</title>\n
+\n
+    <!-- renderjs -->\n
+    <script src="../lib/rsvp.min.js"></script>\n
+    <script src="../lib/renderjs.min.js"></script>\n
+    <!-- custom script -->\n
+    <script src="stringfield.js" type="text/javascript"></script>\n
+\n
+  </head>\n
+  <body>\n
+    <input type=\'text\' data-mini="true" />\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>508</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/string_field/stringfield.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/string_field/stringfield.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fd2bb995e7d9d43c6a5c8d1921576f2ec0f4bc4e
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/string_field/stringfield.js.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681773.32</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>stringfield.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global window, rJS */\n
+(function(window, rJS) {\n
+    "use strict";\n
+    rJS(window).ready(function(gadget) {\n
+        return gadget.getElement().push(function(element) {\n
+            gadget.element = element;\n
+        });\n
+    }).declareMethod("render", function(options) {\n
+        var input = this.element.querySelector("input");\n
+        input.setAttribute("value", options.value || "");\n
+        input.setAttribute("name", options.key);\n
+        input.setAttribute("title", options.title || options.key);\n
+    }).declareMethod("getContent", function() {\n
+        var input = this.element.querySelector("input"), result = {};\n
+        result[input.getAttribute("name")] = input.value;\n
+        return result;\n
+    });\n
+})(window, rJS);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>723</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ae5377a311ab09077255feae1687dfe2da9ff6df
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Folder" module="OFS.Folder"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>toolbox</string> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox/index.html.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox/index.html.xml
new file mode 100644
index 0000000000000000000000000000000000000000..fdc2dece6fa6e0ce13b54da3e7ea69bef8437234
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox/index.html.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681773.72</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>index.html</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/html</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string encoding="cdata"><![CDATA[
+
+<!doctype html>\n
+<html>\n
+  <head>\n
+    <meta charset="utf-8">\n
+    <link rel="stylesheet" href="../lib/jquery-ui.css">\n
+    <link rel="stylesheet" href="toolbox.css">\n
+\n
+    <script src="../lib/rsvp.min.js"></script>\n
+    <script src="../lib/renderjs.min.js"></script>\n
+    <script src="../dream/mixin_gadget.js"></script>\n
+    <script src="../dream/mixin_promise.js"></script>\n
+\n
+    <script src="toolbox.js"></script>\n
+  </head>\n
+  <body>\n
+    <div class="tools"></div>\n
+  </body>\n
+</html>\n
+
+
+]]></string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>475</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox/toolbox.css.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox/toolbox.css.xml
new file mode 100644
index 0000000000000000000000000000000000000000..246d15247fec9746d651f8a61fa97f98eef279ac
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox/toolbox.css.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681773.91</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>toolbox.css</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>text/css</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>.tools{border:1px solid #999;margin:20px 0;border-radius:10px;padding-bottom:20px}.tools-container{margin-bottom:4px}.tools .ui-button{margin:4px 0}.tool{border:1px solid #d3d3d3;box-shadow:1px 1px 2px #aaa;min-width:7em;height:3em;z-index:10001;color:gray;font-family:serif;font-style:italic;font-size:.9em;margin:.8em;display:inline-block;border-radius:5px;text-align:center;padding-top:1.3em;cursor:move}.Dream-Source,.Dream-BatchSource{border:1px solid #bbc;background-color:#ffe;background-image:linear-gradient(to bottom,#ffe 0,#dde 100%)}.Dream-Machine,.Dream-MachineJobShop,.Dream-BatchScrapMachine,.Dream-MachineManagedJob,.Dream-MouldAssembly{border:1px solid #cbc;background-color:#fef;background-image:linear-gradient(to bottom,#fef 0,#ede 100%)}.Dream-Queue,.Dream-QueueJobShop,.Dream-LineClearance,.Dream-QueueManagedJob,.Dream-ConditionalBuffer,.Dream-OrderDecomposition,.Dream-MouldAssemblyBuffer{border:1px solid #bcc;background-color:#eff;background-image:linear-gradient(to bottom,#eff 0,#dee 100%)}.Dream-Exit,.Dream-ExitJobShop{border:1px solid #ccb;background-color:#eef;background-image:linear-gradient(to bottom,#eef 0,#dde 100%)}.Dream-EventGenerator{border:1px solid #cba;background-color:#fdc;background-image:linear-gradient(to bottom,#fdc 0,#ecb 100%)}.Dream-BatchDecomposition,.Dream-BatchDecompositionStartTime,.Dream-BatchReassembly{border:1px solid #bcb;background-color:#dfd;background-image:linear-gradient(to bottom,#dfd 0,#cec 100%)}.Dream-Repairman{border:1px solid #cbb;background-color:#fdd;background-image:linear-gradient(to bottom,#fdd 0,#dcc 100%)}</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>1592</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox/toolbox.js.xml b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox/toolbox.js.xml
new file mode 100644
index 0000000000000000000000000000000000000000..60cce82786c302bebbf55a0c3001dbb437d7eff3
--- /dev/null
+++ b/bt5/erp5_graph_editor/SkinTemplateItem/portal_skins/erp5_graph_editor/toolbox/toolbox.js.xml
@@ -0,0 +1,95 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="File" module="OFS.Image"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_EtagSupport__etag</string> </key>
+            <value> <string>ts17681774.03</string> </value>
+        </item>
+        <item>
+            <key> <string>__name__</string> </key>
+            <value> <string>toolbox.js</string> </value>
+        </item>
+        <item>
+            <key> <string>content_type</string> </key>
+            <value> <string>application/javascript</string> </value>
+        </item>
+        <item>
+            <key> <string>data</string> </key>
+            <value> <string>/*global window, document, RSVP, rJS, initGadgetMixin*/\n
+(function(window, document, RSVP, rJS, initGadgetMixin) {\n
+    "use strict";\n
+    /*jslint nomen: true*/\n
+    var gadget_klass = rJS(window);\n
+    function waitForDragstart(tool) {\n
+        var callback;\n
+        function canceller() {\n
+            if (callback !== undefined) {\n
+                tool.removeEventListener("dragstart", callback, false);\n
+            }\n
+        }\n
+        /*jslint unparam: true*/\n
+        function itsANonResolvableTrap(resolve, reject) {\n
+            callback = function(evt) {\n
+                try {\n
+                    evt.dataTransfer.setData("application/json", tool.dataset.class_name);\n
+                } catch (e) {\n
+                    reject(e);\n
+                }\n
+            };\n
+            tool.addEventListener("dragstart", callback, false);\n
+        }\n
+        return new RSVP.Promise(itsANonResolvableTrap, canceller);\n
+    }\n
+    initGadgetMixin(gadget_klass);\n
+    gadget_klass.declareMethod("render", function(json_data) {\n
+        var data = JSON.parse(json_data), tools_container = document.createElement("div");\n
+        /* display all nodes in the palette.\n
+       */\n
+        tools_container.className = "tools-container";\n
+        Object.keys(data.class_definition).forEach(function(key) {\n
+            var _class = data.class_definition[key], tool;\n
+            // XXX "expand" the json schema "allOF" etc\n
+            if (_class._class === "node") {\n
+                tool = document.createElement("div");\n
+                // XXX maybe allow to configure the class name ?\n
+                tool.className = "tool " + key;\n
+                tool.textContent = _class.name || key;\n
+                tool.draggable = true;\n
+                tool.dataset.class_name = JSON.stringify(key);\n
+                Object.keys(_class.css || {}).forEach(function(k) {\n
+                    tool.style[k] = _class.css[k];\n
+                });\n
+                tools_container.appendChild(tool);\n
+            }\n
+        });\n
+        this.props.element.querySelector(".tools").appendChild(tools_container);\n
+    }).declareMethod("startService", function() {\n
+        var promiseArray = [];\n
+        [].forEach.call(this.props.element.querySelectorAll(".tool"), function(tool) {\n
+            promiseArray.push(waitForDragstart(tool));\n
+        });\n
+        return RSVP.all(promiseArray);\n
+    });\n
+})(window, document, RSVP, rJS, initGadgetMixin);</string> </value>
+        </item>
+        <item>
+            <key> <string>precondition</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>size</string> </key>
+            <value> <int>2386</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow.xml b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow.xml
new file mode 100644
index 0000000000000000000000000000000000000000..4cb04adf399bce95a809373906e9400bc6c06bb4
--- /dev/null
+++ b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="InteractionWorkflowDefinition" module="Products.ERP5.InteractionWorkflow"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>groups</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>business_process_graph_editor_interaction_workflow</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/interactions.xml b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/interactions.xml
new file mode 100644
index 0000000000000000000000000000000000000000..e18bf8cbf778a6808aa24ec39bba4b527d7b1bef
--- /dev/null
+++ b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/interactions.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Interaction" module="Products.ERP5.Interaction"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_mapping</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>interactions</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/interactions/edit.xml b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/interactions/edit.xml
new file mode 100644
index 0000000000000000000000000000000000000000..2191e2d2d49fa0f68087023c15288f1447ca44e3
--- /dev/null
+++ b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/interactions/edit.xml
@@ -0,0 +1,100 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="InteractionDefinition" module="Products.ERP5.Interaction"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>actbox_category</string> </key>
+            <value> <string>workflow</string> </value>
+        </item>
+        <item>
+            <key> <string>actbox_name</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>actbox_url</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>activate_script_name</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>after_script_name</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>before_commit_script_name</string> </key>
+            <value>
+              <list>
+                <string>afterEdit</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>description</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>guard</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>edit</string> </value>
+        </item>
+        <item>
+            <key> <string>method_id</string> </key>
+            <value>
+              <list>
+                <string>edit</string>
+              </list>
+            </value>
+        </item>
+        <item>
+            <key> <string>once_per_transaction</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>portal_type_filter</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>portal_type_group_filter</string> </key>
+            <value>
+              <none/>
+            </value>
+        </item>
+        <item>
+            <key> <string>script_name</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>temporary_document_disallowed</string> </key>
+            <value> <int>0</int> </value>
+        </item>
+        <item>
+            <key> <string>title</string> </key>
+            <value> <string></string> </value>
+        </item>
+        <item>
+            <key> <string>trigger_type</string> </key>
+            <value> <int>2</int> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/scripts.xml b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/scripts.xml
new file mode 100644
index 0000000000000000000000000000000000000000..072c8f6540c07806bee17a34c920ec09b2de1bd5
--- /dev/null
+++ b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/scripts.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Scripts" module="Products.DCWorkflow.Scripts"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_mapping</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>_objects</string> </key>
+            <value>
+              <tuple/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>scripts</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/scripts/afterEdit.xml b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/scripts/afterEdit.xml
new file mode 100644
index 0000000000000000000000000000000000000000..9a4ee142d300ed238986291cb0bdfe3ef4b3c9d9
--- /dev/null
+++ b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/scripts/afterEdit.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>Script_magic</string> </key>
+            <value> <int>3</int> </value>
+        </item>
+        <item>
+            <key> <string>_bind_names</string> </key>
+            <value>
+              <object>
+                <klass>
+                  <global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
+                </klass>
+                <tuple/>
+                <state>
+                  <dictionary>
+                    <item>
+                        <key> <string>_asgns</string> </key>
+                        <value>
+                          <dictionary>
+                            <item>
+                                <key> <string>name_container</string> </key>
+                                <value> <string>container</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_context</string> </key>
+                                <value> <string>context</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_m_self</string> </key>
+                                <value> <string>script</string> </value>
+                            </item>
+                            <item>
+                                <key> <string>name_subpath</string> </key>
+                                <value> <string>traverse_subpath</string> </value>
+                            </item>
+                          </dictionary>
+                        </value>
+                    </item>
+                  </dictionary>
+                </state>
+              </object>
+            </value>
+        </item>
+        <item>
+            <key> <string>_body</string> </key>
+            <value> <string>import json\n
+graph = sci[\'object\'].getProperty(\'jsplumb_graph\')\n
+\n
+#if graph:\n
+#  graph = json.loads(graph)\n
+context.log(graph)\n
+</string> </value>
+        </item>
+        <item>
+            <key> <string>_params</string> </key>
+            <value> <string>sci</string> </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>afterEdit</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/variables.xml b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/variables.xml
new file mode 100644
index 0000000000000000000000000000000000000000..6ae03699d19840ac42b097dfc0a5f34edd416170
--- /dev/null
+++ b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/variables.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Variables" module="Products.DCWorkflow.Variables"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_mapping</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>variables</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/worklists.xml b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/worklists.xml
new file mode 100644
index 0000000000000000000000000000000000000000..c3432aa051eac2d67ec0692a384adb38d1b6bac8
--- /dev/null
+++ b/bt5/erp5_graph_editor/WorkflowTemplateItem/portal_workflow/business_process_graph_editor_interaction_workflow/worklists.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0"?>
+<ZopeData>
+  <record id="1" aka="AAAAAAAAAAE=">
+    <pickle>
+      <global name="Worklists" module="Products.DCWorkflow.Worklists"/>
+    </pickle>
+    <pickle>
+      <dictionary>
+        <item>
+            <key> <string>_mapping</string> </key>
+            <value>
+              <dictionary/>
+            </value>
+        </item>
+        <item>
+            <key> <string>id</string> </key>
+            <value> <string>worklists</string> </value>
+        </item>
+      </dictionary>
+    </pickle>
+  </record>
+</ZopeData>
diff --git a/bt5/erp5_graph_editor/bt/template_format_version b/bt5/erp5_graph_editor/bt/template_format_version
new file mode 100644
index 0000000000000000000000000000000000000000..56a6051ca2b02b04ef92d5150c9ef600403cb1de
--- /dev/null
+++ b/bt5/erp5_graph_editor/bt/template_format_version
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/bt5/erp5_graph_editor/bt/template_portal_type_workflow_chain_list b/bt5/erp5_graph_editor/bt/template_portal_type_workflow_chain_list
new file mode 100644
index 0000000000000000000000000000000000000000..f4c4524dfbc1adbb004b7e0f5831df71379be9d8
--- /dev/null
+++ b/bt5/erp5_graph_editor/bt/template_portal_type_workflow_chain_list
@@ -0,0 +1 @@
+Business Process | business_process_graph_editor_interaction_workflow
\ No newline at end of file
diff --git a/bt5/erp5_graph_editor/bt/template_skin_id_list b/bt5/erp5_graph_editor/bt/template_skin_id_list
new file mode 100644
index 0000000000000000000000000000000000000000..27ad73f282a6db6d294f7fa07847ba16e951c01a
--- /dev/null
+++ b/bt5/erp5_graph_editor/bt/template_skin_id_list
@@ -0,0 +1 @@
+erp5_graph_editor
\ No newline at end of file
diff --git a/bt5/erp5_graph_editor/bt/template_workflow_id_list b/bt5/erp5_graph_editor/bt/template_workflow_id_list
new file mode 100644
index 0000000000000000000000000000000000000000..e249f9108bb04335913a0e7ce281589174100464
--- /dev/null
+++ b/bt5/erp5_graph_editor/bt/template_workflow_id_list
@@ -0,0 +1 @@
+business_process_graph_editor_interaction_workflow
\ No newline at end of file
diff --git a/bt5/erp5_graph_editor/bt/title b/bt5/erp5_graph_editor/bt/title
new file mode 100644
index 0000000000000000000000000000000000000000..27ad73f282a6db6d294f7fa07847ba16e951c01a
--- /dev/null
+++ b/bt5/erp5_graph_editor/bt/title
@@ -0,0 +1 @@
+erp5_graph_editor
\ No newline at end of file