diff options
Diffstat (limited to 'dgbuilder')
378 files changed, 50219 insertions, 0 deletions
diff --git a/dgbuilder/.gitignore b/dgbuilder/.gitignore new file mode 100644 index 00000000..1b8a6ba9 --- /dev/null +++ b/dgbuilder/.gitignore @@ -0,0 +1,12 @@ +org.eclipse.core.resources.prefs +.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+*.class
+target/
+MANIFEST.MF
+.DS_STORE
+.metadata
diff --git a/dgbuilder/CONTRIBUTING.md b/dgbuilder/CONTRIBUTING.md new file mode 100644 index 00000000..52fe8911 --- /dev/null +++ b/dgbuilder/CONTRIBUTING.md @@ -0,0 +1,82 @@ +# Contributing to Node-RED + +We welcome contributions, but request you follow these guidelines. + +## Raising issues + +Please raise any bug reports on the project's +[issue tracker](https://github.com/node-red/node-red/issues?state=open). Be sure to +search the list to see if your issue has already been raised. + +A good bug report is one that make it easy for us to understand what you were +trying to do and what went wrong. + +Provide as much context as possible so we can try to recreate the issue. +If possible, include the relevant part of your flow. To do this, select the +relevant nodes, press Ctrl-E and copy the flow data from the Export dialog. + +At a minimum, please include: + + - Version of Node-RED - either release number if you downloaded a zip, or the first few lines of `git log` if you are cloning the repository directly. + - Version of node.js - what does `node -v` say? + + +## New features + +For feature requests, please raise them on the [mailing list](https://groups.google.com/forum/#!forum/node-red). + +## Pull-Requests + +### Changes to existing code +if you want to raise a pull-request with a new feature, or a refactoring +of existing code, it may well get rejected if you haven't discussed it on +the [mailing list](https://groups.google.com/forum/#!forum/node-red) first. + +### New nodes + +The plugin nature of Node-RED means anyone can create a new node to extend +its capabilities. + +We want to avoid duplication as that can lead to confusion. Many of our existing +nodes offer a starting point of functionality. If they are missing features, +we would rather extend them than add separate 'advanced' versions. But the key +to that approach is getting the UX right to not lose the simplicity. + +To contribute a new node, please raise a pull-request against the +`node-red-nodes` repository. + +Eventually, the nodes will be npm-installable, but we're not there yet. We'll +also have some sort of registry of nodes to help with discoverability. + +### Coding standards + +Please ensure you follow the coding standards used through-out the existing +code base. Some basic rules include: + + - all files must have the Apache license in the header. + - indent with 4-spaces, no tabs. No arguments. + - opening brace on same line as `if`/`for`/`function`/etc, closing brace on its + own line. + +### Contributor License Aggreement + +In order for us to accept pull-requests, the contributor must first complete +a Contributor License Agreement (CLA). This clarifies the intellectual +property license granted with any contribution. It is for your protection as a +Contributor as well as the protection of IBM and its customers; it does not +change your rights to use your own Contributions for any other purpose. + +You can download the CLAs here: + + - [individual](http://nodered.org/cla/node-red-cla-individual.pdf) + - [corporate](http://nodered.org/cla/node-red-cla-corporate.pdf) + +If you are an IBMer, please contact us directly as the contribution process is +slightly different. + + + + + + + diff --git a/dgbuilder/Gruntfile.js b/dgbuilder/Gruntfile.js new file mode 100644 index 00000000..62a553f7 --- /dev/null +++ b/dgbuilder/Gruntfile.js @@ -0,0 +1,91 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + simplemocha: { + options: { + globals: ['expect'], + timeout: 3000, + ignoreLeaks: false, + ui: 'bdd', + reporter: 'spec' + }, + all: { src: ['test/**/*_spec.js'] }, + core: { src: ["test/_spec.js","test/red/**/*_spec.js"]}, + nodes: { src: ["test/nodes/**/*_spec.js"]} + }, + jshint: { + options: { + // http://www.jshint.com/docs/options/ + "asi": true, // allow missing semicolons + "curly": true, // require braces + "eqnull": true, // ignore ==null + "forin": true, // require property filtering in "for in" loops + "immed": true, // require immediate functions to be wrapped in ( ) + "nonbsp": true, // warn on unexpected whitespace breaking chars + //"strict": true, // commented out for now as it causes 100s of warnings, but want to get there eventually + "loopfunc": true, // allow functions to be defined in loops + "sub": true // don't warn that foo['bar'] should be written as foo.bar + }, + all: [ + 'Gruntfile.js', + 'red.js', + 'red/**/*.js', + 'nodes/**/*.js', + 'public/red/**/*.js' + ], + + core: { + files: { + src: [ + 'Gruntfile.js', + 'red.js', + 'red/**/*.js' + ] + } + }, + nodes: { + files: { + src: [ 'nodes/**/*.js' ] + } + }, + editor: { + files: { + src: [ 'public/red/**/*.js' ] + } + }, + tests: { + files: { + src: ['test/**/*.js'] + }, + options: { + "expr": true + } + } + + } + }); + + grunt.loadNpmTasks('grunt-simple-mocha'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + + grunt.registerTask('default', ['jshint:core','jshint:tests','jshint:editor','simplemocha:core','simplemocha:nodes']); + +}; diff --git a/dgbuilder/INSTALL.md b/dgbuilder/INSTALL.md new file mode 100644 index 00000000..90922e6f --- /dev/null +++ b/dgbuilder/INSTALL.md @@ -0,0 +1,57 @@ +Node-RED Install +================ + +## Install node.js + +You can get the latest version from <http://nodejs.org/download/>. + +Or, you may want to use a version from your operating system's package manager: + <https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager> + +## Get Node-RED + +Clone the repository from GitHub: + + $ git clone git@github.com:node-red/node-red.git + +## Install the pre-requisite modules + +From the top-level directory of Node-RED, run: + + $ npm install + +This will install the core pre-requisite modules. + +## Run Node-RED + +From the top-level directory, run: + + $ node red.js + +You can then access Node-RED at <http://localhost:1880>. + +Online documentation is available at <http://nodered.org/docs>. + +## Installing individual node dependencies + +When Node-RED starts, it attempts to load the nodes from the `nodes/` directory. +Each will have its own set of dependencies that will need to be installed before +the node is available in the palette. + +To help identify the dependencies, Node-RED logs any modules it fails to find +for a particular node. You don't have to install these unless you want or need +that node to appear. + +Alternatively, a node's `.js` file can be examined to identify the modules it +explicitly requires. For example, the Twitter node is defined in +`nodes/social/27-twitter.js` and contains: + + var RED = require("../../red/red"); + var ntwitter = require('ntwitter'); + var OAuth= require('oauth').OAuth; + +Of these, `ntwitter` and `oauth` are neither built-in modules nor ones provided +by Node-RED itself. They can subsequently be installed by running: + + $ npm install ntwitter oauth + diff --git a/dgbuilder/LICENSE b/dgbuilder/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/dgbuilder/LICENSE @@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/dgbuilder/build_pom_for_yang_compile b/dgbuilder/build_pom_for_yang_compile new file mode 100755 index 00000000..c9aa38ac --- /dev/null +++ b/dgbuilder/build_pom_for_yang_compile @@ -0,0 +1,86 @@ +echo "Version of dgbuilder pom is : $4" +echo "Building pom.xml_base for compiling yang" + +model_pom_content=$(cat <<EOF +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.onap.ccsdk.distribution</groupId> + <artifactId>distribution-root</artifactId> + <version>${1}</version> + </parent> + <artifactId>yangApp-model</artifactId> + <packaging>bundle</packaging> + <version>1.0.0-SNAPSHOT</version> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>*</Import-Package> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>yang-maven-plugin</artifactId> + <version>\${odl.yangtools.yang.maven.plugin.version}</version> + <dependencies> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>maven-sal-api-gen-plugin</artifactId> + <version>\${odl.sal.api.gen.plugin.version}</version> + <type>jar</type> + </dependency> + </dependencies> + <executions> + <execution> + <goals> + <goal>generate-sources</goal> + </goals> + <configuration> + <yangFilesRootDir>\${yang.file.directory}</yangFilesRootDir> + <codeGenerators> + <generator> + <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass> + <outputBaseDir>\${salGeneratorPath}</outputBaseDir> + </generator> + </codeGenerators> + <inspectDependencies>true</inspectDependencies> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>yang-binding</artifactId> + <version>\${odl.mdsal.yang.binding.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>yang-common</artifactId> + <version>\${odl.yangtools.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.model</groupId> + <artifactId>ietf-inet-types</artifactId> + <version>\${odl.ietf-inet-types.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.model</groupId> + <artifactId>ietf-yang-types</artifactId> + <version>\${odl.ietf-yang-types.version}</version> + </dependency> + </dependencies> +</project> +EOF +) +echo "$model_pom_content" >tools/pom.xml_base diff --git a/dgbuilder/core_nodes/analysis/72-sentiment.html b/dgbuilder/core_nodes/analysis/72-sentiment.html new file mode 100644 index 00000000..c33b873b --- /dev/null +++ b/dgbuilder/core_nodes/analysis/72-sentiment.html @@ -0,0 +1,49 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="sentiment"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="sentiment"> + <p>Analyses the <b>msg.payload</b> and adds a <b>msg.sentiment</b> object that contains the resulting AFINN-111 sentiment score as <b>msg.sentiment.score</b>.</p> + <p>A score greater than zero is positive and less than zero is negative.</p> + <p>The score typically ranges from -5 to +5, but can go higher and lower.</p> + <p>An object of word score overrides can be supplied as <b>msg.overrides</b>.</p> + <p>See <a href="https://github.com/thisandagain/sentiment/blob/master/README.md" target="_new">the Sentiment docs here</a>.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('sentiment',{ + category: 'analysis-function', + color:"#E6E0F8", + defaults: { + name: {value:""}, + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name||"sentiment"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/analysis/72-sentiment.js b/dgbuilder/core_nodes/analysis/72-sentiment.js new file mode 100644 index 00000000..747e079c --- /dev/null +++ b/dgbuilder/core_nodes/analysis/72-sentiment.js @@ -0,0 +1,33 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var sentiment = require('sentiment'); + + function SentimentNode(n) { + RED.nodes.createNode(this,n); + var node = this; + + this.on("input", function(msg) { + sentiment(msg.payload, msg.overrides || null, function (err, result) { + msg.sentiment = result; + node.send(msg); + }); + }); + } + RED.nodes.registerType("sentiment",SentimentNode); +} diff --git a/dgbuilder/core_nodes/core/20-inject.html b/dgbuilder/core_nodes/core/20-inject.html new file mode 100644 index 00000000..38aa6efe --- /dev/null +++ b/dgbuilder/core_nodes/core/20-inject.html @@ -0,0 +1,437 @@ +<!--
+ Copyright 2013 IBM Corp.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="inject">
+ <div class="form-row node-input-payload">
+ <label for="node-input-payloadType"><i class="fa fa-envelope"></i> Payload</label>
+ <select id="node-input-payloadType" style="width:125px !important">
+ <option value="date">timestamp</option>
+ <option value="none">blank</option>
+ <option value="string">string</option>
+ </select>
+ </div>
+
+ <div class="form-row" id="node-input-row-payload">
+ <label for="node-input-payload"></label>
+ <input type="text" id="node-input-payload" placeholder="payload">
+ </div>
+
+ <div class="form-row">
+ <label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
+ <input type="text" id="node-input-topic" placeholder="topic">
+ </div>
+
+ <div class="form-row">
+ <label for=""><i class="fa fa-repeat"></i> Repeat</label>
+ <select id="inject-time-type-select" style="width: 288px"><option value="none">none</option><option value="interval">interval</option><option value="interval-time">interval between times</option><option value="time">at a specific time</option></select>
+ <input type="hidden" id="node-input-repeat" placeholder="payload">
+ <input type="hidden" id="node-input-crontab" placeholder="payload">
+ </div>
+
+ <div class="form-row inject-time-row hidden" id="inject-time-row-interval">
+ every <input id="inject-time-interval-count" class="inject-time-count" value="1"></input>
+ <select style="width: 100px" id="inject-time-interval-units"><option value="s">seconds</option><option value="m">minutes</option><option value="h">hours</option></select><br/>
+ <!-- on <select disabled id="inject-time-interval-days" class="inject-time-days"></select> -->
+ </div>
+
+ <div class="form-row inject-time-row hidden" id="inject-time-row-interval-time">
+ at every <select style="width: 90px" id="inject-time-interval-time-units" class="inject-time-int-count" value="1">
+ <option value="1">1</option>
+ <option value="2">2</option>
+ <option value="3">3</option>
+ <option value="4">4</option>
+ <option value="5">5</option>
+ <option value="6">6</option>
+ <option value="10">10</option>
+ <option value="12">12</option>
+ <option value="15">15</option>
+ <option value="20">20</option>
+ <option value="30">30</option>
+ <option value="0">60</option>
+ </select> minutes<br/>
+ between <select id="inject-time-interval-time-start" class="inject-time-times"></select>
+ and <select id="inject-time-interval-time-end" class="inject-time-times"></select><br/>
+ on <select id="inject-time-interval-time-days" class="inject-time-days"></select>
+ </div>
+
+ <div class="form-row inject-time-row hidden" id="inject-time-row-time">
+ at <input id="inject-time-time" value="12:00"></input><br/>
+ on <select id="inject-time-time-days" class="inject-time-days"></select>
+ </div>
+
+ <div class="form-row" id="node-once">
+ <label> </label>
+ <input type="checkbox" id="node-input-once" style="display: inline-block; width: auto; vertical-align: top;">
+ <label for="node-input-once" style="width: 70%;">Fire once at start ?</label>
+ </div>
+
+ <div class="form-row">
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+ <input type="text" id="node-input-name" placeholder="name">
+ </div>
+
+ <div class="form-tips"><b>Note:</b> "interval between times" and "at a specific time" will use cron.<br/>See info box for details.</div>
+</script>
+<style>
+ .inject-time-row {
+ padding-left: 110px;
+ }
+ .inject-time-row select {
+ margin: 3px 0;
+ }
+ .inject-time-days {
+ width: 262px;
+ }
+ .inject-time-times {
+ width: 90px;
+ }
+ .inject-time-row > .ui-spinner {
+ height: 28px;
+ margin: 3px 0;
+ border-color: rgb(204, 204, 204);
+ }
+ #inject-time-time {
+ margin-top: 3px;
+ width: 75px;
+ }
+ .inject-time-count {
+ width: 40px !important;
+ }
+</style>
+<script type="text/x-red" data-help-name="inject">
+ <p>Pressing the button on the left side of the node allows a message on a topic to be injected into the flow. This is mainly for test purposes.</p>
+ <p>If no payload is specified the payload is set to the current time in millisecs since 1970. This allows subsequent functions to perform time based actions.</p>
+ <p>The repeat function does what it says on the tin and continuously sends the payload every x seconds.</p>
+ <p>The Fire once at start option actually waits 50mS before firing to give other nodes a chance to instantiate properly.</p>
+ <p><b>Note: </b>"Interval between times" and "at a specific time" will use cron. This means that 20 minutes will be at the next hour, 20 minutes past and 40 minutes past - not in 20 minutes time.
+ If you want every 20 minutes from now - use the basic "interval" option.</p>
+</script>
+
+<script type="text/javascript">
+ RED.nodes.registerType('inject',{
+ category: 'input',
+ color:"#a6bbcf",
+ defaults: {
+ name: {value:""},
+ topic: {value:""},
+ payload: {value:""},
+ payloadType: {value:"date"},
+ repeat: {value:""},
+ crontab: {value:""},
+ once: {value:false}
+ },
+ inputs:0,
+ outputs:1,
+ icon: "inject.png",
+ label: function() {
+ if (this.payloadType === "string") {
+ return this.name||this.topic||this.payload||"inject";
+ }
+ else { return this.name||this.topic||"inject"; }
+ },
+ labelStyle: function() {
+ return this.name?"node_label_italic":"";
+ },
+ oneditprepare: function() {
+ $("#inject-time-type-select").change(function() {
+ $("#node-input-crontab").val('');
+ var id = $("#inject-time-type-select option:selected").val();
+ $(".inject-time-row").hide();
+ $("#inject-time-row-"+id).show();
+ if ((id == "none") || (id == "interval")) {
+ $("#node-once").show();
+ }
+ else {
+ $("#node-once").hide();
+ $("#node-input-once").prop('checked', false);
+ }
+ });
+
+ var days = [
+ {v:"*",t:"every day"},
+ {v:"1-5",t:"Mondays to Fridays"},
+ {v:"0,6",t:"Saturdays and Sundays"},
+ {v:"1",t:"Mondays"},
+ {v:"2",t:"Tuesdays"},
+ {v:"3",t:"Wednesdays"},
+ {v:"4",t:"Thursdays"},
+ {v:"5",t:"Fridays"},
+ {v:"6",t:"Saturdays"},
+ {v:"0",t:"Sundays"}
+ ];
+
+ $(".inject-time-days").each(function() {
+ for (var d in days) {
+ $(this).append($("<option></option>").val(days[d].v).text(days[d].t));
+ }
+ });
+
+ $(".inject-time-times").each(function() {
+ for (var i=0;i<24;i++) {
+ var l = (i<10?"0":"")+i+":00";
+ $(this).append($("<option></option>").val(i).text(l));
+ }
+ });
+
+ $(".inject-time-count").spinner({
+ //max:60,
+ min:1
+ });
+
+ $("#inject-time-interval-units").change(function() {
+ var units = $("#inject-time-interval-units option:selected").val();
+ //$("#inject-time-interval-days").prop("disabled",(units == "s")?"disabled":false);
+ //$(".inject-time-count").spinner("option","max",(units == "h")?24:60);
+ });
+
+ $.widget( "ui.injecttimespinner", $.ui.spinner, {
+ options: {
+ // seconds
+ step: 60 * 1000,
+ // hours
+ page: 60
+ },
+ _parse: function( value ) {
+ if ( typeof value === "string" ) {
+ // already a timestamp
+ if ( Number( value ) == value ) {
+ return Number( value );
+ }
+ var p = value.split(":");
+ var offset = new Date().getTimezoneOffset();
+ return (((Number(p[0])+1)*60)+Number(p[1])+offset)*60*1000;
+ }
+ return value;
+ },
+ _format: function( value ) {
+ var d = new Date(value);
+ var h = d.getHours();
+ var m = d.getMinutes();
+ return ((h < 10)?"0":"")+h+":"+((m < 10)?"0":"")+m;
+ }
+ });
+
+ $("#inject-time-time").injecttimespinner();
+
+ var repeattype = "none";
+ if (this.repeat != "" && this.repeat != 0) {
+ repeattype = "interval";
+ var r = "s";
+ var c = this.repeat;
+ if (this.repeat % 60 === 0) { r = "m"; c = c/60; }
+ if (this.repeat % 1440 === 0) { r = "h"; c = c/24; }
+ $("#inject-time-interval-count").val(c);
+ $("#inject-time-interval-units").val(r);
+ //$("#inject-time-interval-units option").filter(function() {return $(this).val() == "s";}).attr('selected',true);
+ $("#inject-time-interval-days").prop("disabled","disabled");
+ } else if (this.crontab) {
+ var cronparts = this.crontab.split(" ");
+ var days = cronparts[4];
+ if (!isNaN(cronparts[0]) && !isNaN(cronparts[1])) {
+ repeattype = "time";
+ // Fixed time
+ var time = cronparts[1]+":"+cronparts[0];
+ $("#inject-time-time").val(time);
+ $("#inject-time-type-select option").filter(function() {return $(this).val() == "s";}).attr('selected',true);
+ $("#inject-time-time-days option").filter(function() {return $(this).val() == days;}).attr('selected',true);
+ }
+ //else if (cronparts[0] == "0") {
+ // // interval - hours
+ // var hours = cronparts[1].slice(2);
+ // repeattype = "interval";
+ // $("#inject-time-interval-days").prop("disabled",false);
+ // $("#inject-time-interval-days option").filter(function() {return $(this).val() == days;}).attr('selected',true);
+ // $("#inject-time-interval-count").val(hours)
+ // $("#inject-time-interval-units option").filter(function() {return $(this).val() == "h";}).attr('selected',true);
+ //} else if (cronparts[1] == "*") {
+ // // interval - minutes
+ // var minutes = cronparts[0].slice(2);
+ // repeattype = "interval";
+ // $("#inject-time-interval-days").prop("disabled",false);
+ // $("#inject-time-interval-days option").filter(function() {return $(this).val() == days;}).attr('selected',true);
+ // $("#inject-time-interval-count").val(minutes)
+ // $("#inject-time-interval-units option").filter(function() {return $(this).val() == "m";}).attr('selected',true);
+ //}
+ else {
+ repeattype = "interval-time";
+ // interval - time period
+ var minutes = cronparts[0].slice(2);
+ if (minutes === "") { minutes = "0"; }
+ $("#inject-time-interval-time-units").val(minutes);
+ $("#inject-time-interval-time-days option").filter(function() {return $(this).val() == days;}).attr('selected',true);
+ var time = cronparts[1];
+ var timeparts = time.split(",");
+ var start;
+ var end;
+ if (timeparts.length == 1) {
+ // 0 or 0-10
+ var hours = timeparts[0].split("-");
+ if (hours.length == 1) {
+ if (hours[0] === "") {
+ start = "0";
+ end = "0";
+ }
+ else {
+ start = hours[0];
+ end = Number(hours[0])+1;
+ }
+ } else {
+ start = hours[0];
+ end = (Number(hours[1])+1)%24;
+ }
+ } else {
+ // 23,0 or 17-23,0-10 or 23,0-2 or 17-23,0
+ var startparts = timeparts[0].split("-");
+ start = startparts[0];
+
+ var endparts = timeparts[1].split("-");
+ if (endparts.length == 1) {
+ end = Number(endparts[0])+1;
+ } else {
+ end = Number(endparts[1])+1;
+ }
+ }
+ $("#inject-time-interval-time-start option").filter(function() {return $(this).val() == start;}).attr('selected',true);
+ $("#inject-time-interval-time-end option").filter(function() {return $(this).val() == end;}).attr('selected',true);
+
+ }
+ } else {
+ $("#inject-time-type-select option").filter(function() {return $(this).val() == "none";}).attr('selected',true);
+ }
+
+ $(".inject-time-row").hide();
+ $("#inject-time-type-select option").filter(function() {return $(this).val() == repeattype;}).attr('selected',true);
+ $("#inject-time-row-"+repeattype).show();
+
+ if (this.payloadType == null) {
+ if (this.payload == "") {
+ this.payloadType = "date";
+ } else {
+ this.payloadType = "string";
+ }
+ }
+
+ $("#node-input-payloadType").change(function() {
+ var id = $("#node-input-payloadType option:selected").val();
+ if (id == "string") {
+ $("#node-input-row-payload").show();
+ } else {
+ $("#node-input-row-payload").hide();
+ }
+ });
+ $("#node-input-payloadType").val(this.payloadType);
+ $("#node-input-payloadType").change();
+ $("#inject-time-type-select").change();
+
+ },
+ oneditsave: function() {
+ var repeat = "";
+ var crontab = "";
+ var type = $("#inject-time-type-select option:selected").val();
+ if (type == "none") {
+ // nothing
+ } else if (type == "interval") {
+ var count = $("#inject-time-interval-count").val();
+ var units = $("#inject-time-interval-units option:selected").val();
+ var days = $("#inject-time-interval-days option:selected").val();
+ if (units == "s") {
+ repeat = count;
+ } else {
+ if (units == "m") {
+ //crontab = "*/"+count+" * * * "+days;
+ repeat = count * 60;
+ } else if (units == "h") {
+ //crontab = "0 */"+count+" * * "+days;
+ repeat = count * 60 * 24;
+ }
+ }
+ } else if (type == "interval-time") {
+ var count = $("#inject-time-interval-time-units").val();
+ var startTime = Number($("#inject-time-interval-time-start option:selected").val());
+ var endTime = Number($("#inject-time-interval-time-end option:selected").val());
+ var days = $("#inject-time-interval-time-days option:selected").val();
+ var timerange = "*";
+ if (startTime == endTime) {
+ //TODO: invalid
+ repeat = "";
+ crontab = "";
+ } else if (endTime == 0) {
+ timerange = startTime+"-23";
+ } else if (startTime+1 < endTime) {
+ timerange = startTime+"-"+(endTime-1);
+ } else if (startTime+1 == endTime) {
+ timerange = startTime;
+ } else {
+ var startpart = "";
+ var endpart = "";
+ if (startTime == 23) {
+ startpart = "23";
+ } else {
+ startpart = startTime+"-23";
+ }
+ if (endTime == 1) {
+ endpart = "0";
+ } else {
+ endpart = "0-"+(endTime-1);
+ }
+ timerange = startpart+","+endpart;
+ }
+ repeat = "";
+ if (count === "0") {
+ crontab = count+" "+timerange+" * * "+days;
+ }
+ else {
+ crontab = "*/"+count+" "+timerange+" * * "+days;
+ }
+ } else if (type == "time") {
+ var time = $("#inject-time-time").val();
+ var days = $("#inject-time-time-days option:selected").val();
+ var parts = time.split(":");
+ repeat = "";
+ crontab = parts[1]+" "+parts[0]+" * * "+days;
+ }
+
+ $("#node-input-repeat").val(repeat);
+ $("#node-input-crontab").val(crontab);
+
+ },
+ button: {
+ onclick: function() {
+ var label = (this.name||this.payload).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
+ if (this.payloadType === "date") { label = "timestamp"; }
+ if (this.payloadType === "none") { label = "blank"; }
+ d3.xhr("inject/"+this.id).post(function(err,resp) {
+ if (err) {
+ if (err.status == 404) {
+ RED.notify("<strong>Error</strong>: inject node not deployed","error");
+ } else if (err.status == 500) {
+ RED.notify("<strong>Error</strong>: inject failed, see log for details.","error");
+ } else if (err.status == 0) {
+ RED.notify("<strong>Error</strong>: no response from server","error");
+ } else {
+ RED.notify("<strong>Error</strong>: unexpected error: ("+err.status+")"+err.response,"error");
+ }
+ } else if (resp.status == 200) {
+ RED.notify("Successfully injected: "+label,"success");
+ } else {
+ RED.notify("<strong>Error</strong>: unexpected response: ("+resp.status+") "+resp.response,"error");
+ }
+ });
+ }
+ }
+ });
+
+</script>
diff --git a/dgbuilder/core_nodes/core/20-inject.js b/dgbuilder/core_nodes/core/20-inject.js new file mode 100644 index 00000000..dff0fb65 --- /dev/null +++ b/dgbuilder/core_nodes/core/20-inject.js @@ -0,0 +1,97 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + var cron = require("cron"); + + function InjectNode(n) { + RED.nodes.createNode(this,n); + this.topic = n.topic; + this.payload = n.payload; + this.payloadType = n.payloadType; + this.repeat = n.repeat; + this.crontab = n.crontab; + this.once = n.once; + var node = this; + this.interval_id = null; + this.cronjob = null; + + if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) { + this.repeat = this.repeat * 1000; + this.log("repeat = "+this.repeat); + this.interval_id = setInterval( function() { + node.emit("input",{}); + }, this.repeat ); + } else if (this.crontab) { + if (cron) { + this.log("crontab = "+this.crontab); + this.cronjob = new cron.CronJob(this.crontab, + function() { + node.emit("input",{}); + }, + null,true); + } else { + this.error("'cron' module not found"); + } + } + + if (this.once) { + setTimeout( function(){ node.emit("input",{}); }, 100); + } + + this.on("input",function(msg) { + var msg = {topic:this.topic}; + if ( (this.payloadType == null && this.payload == "") || this.payloadType == "date") { + msg.payload = Date.now(); + } else if (this.payloadType == null || this.payloadType == "string") { + msg.payload = this.payload; + } else { + msg.payload = ""; + } + this.send(msg); + msg = null; + }); + } + + RED.nodes.registerType("inject",InjectNode); + + InjectNode.prototype.close = function() { + if (this.interval_id != null) { + clearInterval(this.interval_id); + this.log("inject: repeat stopped"); + } else if (this.cronjob != null) { + this.cronjob.stop(); + this.log("inject: cronjob stopped"); + delete this.cronjob; + } + } + + RED.httpAdmin.post("/inject/:id", function(req,res) { + var node = RED.nodes.getNode(req.params.id); + if (node != null) { + try { + node.receive(); + res.send(200); + } catch(err) { + res.send(500); + node.error("Inject failed:"+err); + console.log(err.stack); + } + } else { + res.send(404); + } + }); +} diff --git a/dgbuilder/core_nodes/core/58-debug.html b/dgbuilder/core_nodes/core/58-debug.html new file mode 100644 index 00000000..04aa5078 --- /dev/null +++ b/dgbuilder/core_nodes/core/58-debug.html @@ -0,0 +1,248 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="debug"> + <div class="form-row"> + <label for="node-input-complete"><i class="fa fa-list"></i> Output</label> + <select type="text" id="node-input-complete" style="display: inline-block; width: 250px; vertical-align: top;"> + <option value="false">payload only</option> + <option value="true">complete msg object</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-console"><i class="fa fa-random"></i> to</label> + <select type="text" id="node-input-console" style="display: inline-block; width: 250px; vertical-align: top;"> + <option value="false">debug tab</option> + <option value="true">debug tab and console</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="debug"> + <p>The Debug node can be connected to the output of any node. It will display the timestamp, <b>msg.topic</b> and <b>msg.payload</b> fields of any messages it receives in the debug tab of the sidebar. + <br/>The sidebar can be accessed under the options drop-down in the top right corner.</p> + <p>The button to the right of the node will toggle it's output on and off so you can de-clutter the debug window.</p> + <p>If the payload is an object it will be stringified first for display and indicate that by saying "(Object) ".</p> + <p>If the payload is a buffer it will be stringified first for display and indicate that by saying "(Buffer) ".</p> + <p>Selecting any particular message will highlight (in red) the debug node that reported it. This is useful if you wire up multiple debug nodes.</p> + <p>Optionally can show the complete msg object - but the screen can get messy.</p> + <p>In addition any calls to node.warn or node.error will appear here.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('debug',{ + category: 'output', + defaults: { + name: {value:""}, + active: {value:true}, + console: {value:"false"}, + complete: {value:"false"} + }, + label: function() { + return this.name||"debug"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + color:"#87a980", + inputs:1, + outputs:0, + icon: "debug.png", + align: "right", + button: { + toggle: "active", + onclick: function() { + var label = this.name||"debug"; + d3.xhr("debug/"+this.id+"/"+(this.active?"enable":"disable")).post(function(err,resp) { + if (err) { + if (err.status == 404) { + RED.notify("<strong>Error</strong>: debug node not deployed","error"); + } else if (err.status == 0) { + RED.notify("<strong>Error</strong>: no response from server","error"); + } else { + RED.notify("<strong>Error</strong>: unexpected error: ("+err.status+")"+err.response,"error"); + } + } else if (resp.status == 200) { + RED.notify("Successfully activated: "+label,"success"); + } else if (resp.status == 201) { + RED.notify("Successfully deactivated: "+label,"success"); + } else { + RED.notify("<strong>Error</strong>: unexpected response: ("+resp.status+") "+resp.response,"error"); + } + }); + } + }, + onpaletteadd: function() { + var content = document.createElement("div"); + content.id = "tab-debug"; + + var toolbar = document.createElement("div"); + toolbar.id = "debug-toolbar"; + content.appendChild(toolbar); + + toolbar.innerHTML = '<div class="btn-group pull-right"><a id="debug-tab-clear" title="clear log" class="btn btn-mini" href="#"><i class="fa fa-trash"></i></a></div> '; + + var messages = document.createElement("div"); + messages.id = "debug-content"; + content.appendChild(messages); + + RED.sidebar.addTab("debug",content); + + function getTimestamp() { + var d = new Date(); + return d.toLocaleString(); + } + + var sbc = document.getElementById("debug-content"); + + var messageCount = 0; + var that = this; + RED._debug = function(msg) { + that.handleDebugMessage("",{ + name:"debug", + msg:msg + }); + } + + this.handleDebugMessage = function(t,o) { + var msg = document.createElement("div"); + msg.onmouseover = function() { + msg.style.borderRightColor = "#999"; + var n = RED.nodes.node(o.id); + if (n) { + n.highlighted = true; + n.dirty = true; + } + RED.view.redraw(); + }; + msg.onmouseout = function() { + msg.style.borderRightColor = ""; + var n = RED.nodes.node(o.id); + if (n) { + n.highlighted = false; + n.dirty = true; + } + RED.view.redraw(); + }; + msg.onclick = function() { + var node = RED.nodes.node(o.id); + if (node) { + RED.view.showWorkspace(node.z); + } + + }; + var name = (o.name?o.name:o.id).toString().replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); + var topic = (o.topic||"").toString().replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); + var payload = (o.msg||"").toString().replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); + msg.className = 'debug-message'+(o.level?(' debug-message-level-'+o.level):''); + msg.innerHTML = '<span class="debug-message-date">'+getTimestamp()+'</span>'+ + '<span class="debug-message-name">['+name+']</span>'+ + (o.topic?'<span class="debug-message-topic">'+topic+'</span>':'')+ + '<span class="debug-message-payload">'+payload+'</span>'; + var atBottom = (sbc.scrollHeight-messages.offsetHeight-sbc.scrollTop) < 5; + messageCount++; + $(messages).append(msg); + + if (messageCount > 200) { + $("#debug-content .debug-message:first").remove(); + messageCount--; + } + if (atBottom) { + $(sbc).scrollTop(sbc.scrollHeight); + } + }; + RED.comms.subscribe("debug",this.handleDebugMessage); + + $("#debug-tab-clear").click(function() { + $(".debug-message").remove(); + messageCount = 0; + RED.nodes.eachNode(function(node) { + node.highlighted = false; + node.dirty = true; + }); + RED.view.redraw(); + }); + }, + onpaletteremove: function() { + RED.comms.unsubscribe("debug",this.handleDebugMessage); + RED.sidebar.removeTab("debug"); + delete RED._debug; + } + }); +</script> + +<style> + #debug-content { + position: absolute; + top: 30px; + bottom: 0px; + left:0px; + right: 0px; + overflow-y: scroll; + } + #debug-toolbar { + padding: 3px 10px; + height: 24px; + background: #f3f3f3; + } + .debug-message { + cursor: pointer; + border-bottom: 1px solid #eee; + border-left: 8px solid #eee; + border-right: 8px solid #eee; + padding: 2px; + } + .debug-message-date { + background: #fff; + font-size: 9px; + color: #aaa; + padding: 1px 5px 1px 1px; + } + .debug-message-topic { + display: block; + background: #fff; + padding: 1px 5px; + font-size: 9px; + color: #a66; + } + .debug-message-name { + background: #fff; + padding: 1px 5px; + font-size: 9px; + color: #aac; + } + .debug-message-payload { + display: block; + padding: 2px; + background: #fff; + } + .debug-message-level-log { + border-left-color: #eee; + border-right-color: #eee; + } + .debug-message-level-warn { + border-left-color: #ffdf9d; + border-right-color: #ffdf9d; + } + .debug-message-level-error { + border-left-color: #f99; + border-right-color: #f99; + } +</style> diff --git a/dgbuilder/core_nodes/core/58-debug.js b/dgbuilder/core_nodes/core/58-debug.js new file mode 100644 index 00000000..7436bf2c --- /dev/null +++ b/dgbuilder/core_nodes/core/58-debug.js @@ -0,0 +1,114 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + var util = require("util"); + var events = require("events"); + var debuglength = RED.settings.debugMaxLength||1000; + var useColors = false; + // util.inspect.styles.boolean = "red"; + + function DebugNode(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.complete = n.complete; + this.console = n.console; + this.active = (n.active == null)||n.active; + var node = this; + + this.on("input",function(msg) { + if (this.complete == "true") { // debug complete msg object + if (this.console == "true") { + node.log("\n"+util.inspect(msg, {colors:useColors, depth:10})); + } + if (this.active) { + sendDebug({id:this.id,name:this.name,topic:msg.topic,msg:msg,_path:msg._path}); + } + } else { // debug just the msg.payload + if (this.console == "true") { + if (typeof msg.payload === "string") { + node.log((msg.payload.indexOf("\n") != -1 ? "\n" : "") + msg.payload); + } + else if (typeof msg.payload === "object") { node.log("\n"+util.inspect(msg.payload, {colors:useColors, depth:10})); } + else { node.log(util.inspect(msg.payload, {colors:useColors})); } + } + if (this.active) { + sendDebug({id:this.id,name:this.name,topic:msg.topic,msg:msg.payload,_path:msg._path}); + } + } + }); + } + + RED.nodes.registerType("debug",DebugNode); + + function sendDebug(msg) { + if (msg.msg instanceof Error) { + msg.msg = msg.msg.toString(); + } else if (msg.msg instanceof Buffer) { + msg.msg = "(Buffer) "+msg.msg.toString('hex'); + } else if (typeof msg.msg === 'object') { + var seen = []; + var ty = "(Object) "; + if (util.isArray(msg.msg)) { ty = "(Array) "; } + msg.msg = ty + JSON.stringify(msg.msg, function(key, value) { + if (typeof value === 'object' && value !== null) { + if (seen.indexOf(value) !== -1) { return "[circular]"; } + seen.push(value); + } + return value; + }," "); + seen = null; + } else if (typeof msg.msg === "boolean") { + msg.msg = "(boolean) "+msg.msg.toString(); + } else if (msg.msg === 0) { + msg.msg = "0"; + } else if (msg.msg == null) { + msg.msg = "(undefined)"; + } + + if (msg.msg.length > debuglength) { + msg.msg = msg.msg.substr(0,debuglength) +" ...."; + } + + RED.comms.publish("debug",msg); + } + + DebugNode.logHandler = new events.EventEmitter(); + DebugNode.logHandler.on("log",function(msg) { + if (msg.level == "warn" || msg.level == "error") { + sendDebug(msg); + } + }); + RED.log.addHandler(DebugNode.logHandler); + + RED.httpAdmin.post("/debug/:id/:state", function(req,res) { + var node = RED.nodes.getNode(req.params.id); + var state = req.params.state; + if (node != null) { + if (state === "enable") { + node.active = true; + res.send(200); + } else if (state === "disable") { + node.active = false; + res.send(201); + } else { + res.send(404); + } + } else { + res.send(404); + } + }); +} diff --git a/dgbuilder/core_nodes/core/75-exec.html b/dgbuilder/core_nodes/core/75-exec.html new file mode 100644 index 00000000..567a34c1 --- /dev/null +++ b/dgbuilder/core_nodes/core/75-exec.html @@ -0,0 +1,68 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="exec"> + <div class="form-row"> + <label for="node-input-command"><i class="fa fa-file"></i> Command</label> + <input type="text" id="node-input-command" placeholder="command"> + </div> + <div class="form-row"> + <label for="node-input-append"><i class="fa fa-list"></i> Append</label> + <input type="text" id="node-input-append" placeholder="extra input"> + </div> + <div class="form-row"> + <label> </label> + <input type="checkbox" id="node-input-useSpawn" placeholder="spawn" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-useSpawn" style="width: 70%;">Use spawn() instead of exec() ?</label> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">Tip: <i>spawn</i> expects only one command word - and appended args to be comma separated.</div> +</script> + +<script type="text/x-red" data-help-name="exec"> + <p>Calls out to a system command.<br/></p> + <p>Provides 3 outputs... stdout, stderr, and return code.</p> + <p>By default uses exec() which calls the command, blocks while waiting for completion, and then returns the complete result in one go, along with any errors.</p> + <p>Optionally can use spawn() instead, which returns output from stdout and stderr as the command runs (ie one line at a time). On completion it then returns a return code (on the 3rd output).</p> + <p>Spawn only expect one command word, with all extra parameters to be comma separated and passed as the append.</p> + <p>The optional append gets added to the command after the <b>msg.payload</b> - so you can do things like pipe the result to another command.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('exec',{ + category: 'advanced-function', + color:"darksalmon", + defaults: { + command: {value:"",required:true}, + append: {value:""}, + useSpawn: {value:""}, + name: {value:""} + }, + inputs:1, + outputs:3, + icon: "arrow-in.png", + align: "right", + label: function() { + return this.name||this.command; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/core/75-exec.js b/dgbuilder/core_nodes/core/75-exec.js new file mode 100644 index 00000000..a07b1401 --- /dev/null +++ b/dgbuilder/core_nodes/core/75-exec.js @@ -0,0 +1,84 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var spawn = require('child_process').spawn; + var exec = require('child_process').exec; + + function ExecNode(n) { + RED.nodes.createNode(this,n); + this.cmd = n.command.trim(); + this.append = n.append.trim() || ""; + this.useSpawn = n.useSpawn; + + var node = this; + this.on("input", function(msg) { + node.status({fill:"blue",shape:"dot"}); + if (this.useSpawn === true) { + // make the extra args into an array + // then prepend with the msg.payload + if (typeof(msg.payload !== "string")) { msg.payload = msg.payload.toString(); } + var arg = []; + if (node.append.length > 0) { arg = node.append.split(","); } + if (msg.payload.trim() !== "") { arg.unshift(msg.payload); } + node.log(node.cmd+" ["+arg+"]"); + if (node.cmd.indexOf(" ") == -1) { + var ex = spawn(node.cmd,arg); + ex.stdout.on('data', function (data) { + //console.log('[exec] stdout: ' + data); + msg.payload = data.toString(); + node.send([msg,null,null]); + }); + ex.stderr.on('data', function (data) { + //console.log('[exec] stderr: ' + data); + msg.payload = data.toString(); + node.send([null,msg,null]); + }); + ex.on('close', function (code) { + //console.log('[exec] result: ' + code); + msg.payload = code; + node.status({}); + node.send([null,null,msg]); + }); + ex.on('error', function (code) { + node.warn(code); + }); + } + else { node.error("Spawn command must be just the command - no spaces or extra parameters"); } + } + else { + var cl = node.cmd+" "+msg.payload+" "+node.append; + node.log(cl); + var child = exec(cl, function (error, stdout, stderr) { + msg.payload = stdout; + var msg2 = {payload:stderr}; + var msg3 = null; + //console.log('[exec] stdout: ' + stdout); + //console.log('[exec] stderr: ' + stderr); + if (error !== null) { + msg3 = {payload:error}; + //console.log('[exec] error: ' + error); + } + node.status({}); + node.send([msg,msg2,msg3]); + }); + } + }); + } + + RED.nodes.registerType("exec",ExecNode); +} diff --git a/dgbuilder/core_nodes/core/80-function.html b/dgbuilder/core_nodes/core/80-function.html new file mode 100644 index 00000000..442c391d --- /dev/null +++ b/dgbuilder/core_nodes/core/80-function.html @@ -0,0 +1,110 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="function"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-func"><i class="fa fa-wrench"></i> Function</label> + <input type="hidden" id="node-input-func" autofocus="autofocus"> + <div style="height: 250px;" class="node-text-editor" id="node-input-func-editor" ></div> + </div> + <div class="form-row"> + <label for="node-input-outputs"><i class="fa fa-random"></i> Outputs</label> + <input id="node-input-outputs" style="width: 60px; height: 1.7em;" value="1"> + </div> + <div class="form-tips">See the Info tab for help writing functions.</div> +</script> + +<script type="text/x-red" data-help-name="function"> + <p>A function block where you can write code to do more interesting things.</p> + <p>The message is passed in as a JavaScript object called <code>msg</code>.</p> + <p>By convention it will have a <code>msg.payload</code> property containing + the body of the message.</p> + <p>The function should return the messages it wants to pass on to the next nodes + in the flow. It can return:</p> + <ul> + <li>a single message object - passed to nodes connected to the first output</li> + <li>an array of message objects - passed to nodes connected to the corresponding outputs</li> + </ul> + <p>If any element of the array is itself an array of messages, multiple + messages are sent to the corresponding output.</p> + <p>If null is returned, either by itself or as an element of the array, no + message is passed on.</p> + <p>See the <a target="_new" href="http://nodered.org/docs/writing-functions.html">online documentation</a> for more help.</p> + +</script> + +<script type="text/javascript"> + RED.nodes.registerType('function',{ + color:"#fdd0a2", + category: 'function', + defaults: { + name: {value:""}, + func: {value:"\nreturn msg;"}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "function.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + function functionDialogResize(ev,ui) { + $("#node-input-func-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-func-editor'), + lang:"js", + contents: $("#node-input-func").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + + }); + }, + oneditsave: function() { + $("#node-input-func").val(this.editor.getText()) + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/core_nodes/core/80-function.js b/dgbuilder/core_nodes/core/80-function.js new file mode 100644 index 00000000..e1413a7a --- /dev/null +++ b/dgbuilder/core_nodes/core/80-function.js @@ -0,0 +1,79 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function FunctionNode(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.func = n.func; + var functionText = "var results = null; results = (function(msg){"+this.func+"\n})(msg);"; + this.topic = n.topic; + var sandbox = { + console:console, + util:util, + Buffer:Buffer, + context: { + global:RED.settings.functionGlobalContext || {} + } + }; + var context = vm.createContext(sandbox); + try { + this.script = vm.createScript(functionText); + this.on("input", function(msg) { + try { + var start = process.hrtime(); + context.msg = msg; + this.script.runInContext(context); + var results = context.results; + if (results == null) { + results = []; + } else if (results.length == null) { + results = [results]; + } + if (msg._topic) { + for (var m in results) { + if (results[m]) { + if (util.isArray(results[m])) { + for (var n=0; n < results[m].length; n++) { + results[m][n]._topic = msg._topic; + } + } else { + results[m]._topic = msg._topic; + } + } + } + } + this.send(results); + var duration = process.hrtime(start); + if (process.env.NODE_RED_FUNCTION_TIME) { + this.status({fill:"yellow",shape:"dot",text:""+Math.floor((duration[0]* 1e9 + duration[1])/10000)/100}); + } + } catch(err) { + this.error(err.toString()); + } + }); + } catch(err) { + this.error(err); + } + } + + RED.nodes.registerType("function",FunctionNode); + RED.library.register("functions"); +} diff --git a/dgbuilder/core_nodes/core/80-template.html b/dgbuilder/core_nodes/core/80-template.html new file mode 100644 index 00000000..dc014d37 --- /dev/null +++ b/dgbuilder/core_nodes/core/80-template.html @@ -0,0 +1,102 @@ +<!-- + Copyright 2013,2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="template"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-template"><i class="fa fa-file-code-o"></i> Template</label> + <input type="hidden" id="node-input-template" autofocus="autofocus"> + <div style="height: 250px;" class="node-text-editor" id="node-input-template-editor" ></div> + </div> + <div class="form-row"> + <label for="node-input-field"><i class="fa fa-edit"></i> Property</label> + msg.<input type="text" id="node-input-field" placeholder="payload" style="width: 64%;"> + </div> +</script> + +<script type="text/x-red" data-help-name="template"> + <p>Creates a new message based on the provided template.</p> + <p>This uses the <i><a href="http://mustache.github.io/mustache.5.html" target="_new">mustache</a></i> format.</p> + <p>For example, when a template of: + <pre>Hello {{name}}. Today is {{date}}</pre> + <p>receives a message containing: + <pre>{ + name: "Fred", + date: "Monday" + payload: ... +}</pre> + <p>The resulting payload will be: + <pre>Hello Fred. Today is Monday</pre> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('template',{ + color:"rgb(243, 181, 103)", + category: 'function', + defaults: { + name: {value:""}, + field: {value:"payload"}, + template: {value:"This is the payload: {{payload}}!"}, + }, + inputs:1, + outputs:1, + icon: "template.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + + function templateDialogResize(ev,ui) { + $("#node-input-template-editor").css("height",(ui.size.height-200)+"px"); + }; + + $( "#dialog" ).on("dialogresize", templateDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-template'); + if (size) { + templateDialogResize(null,{size:size}); + } + }); + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",templateDialogResize); + }); + + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-template-editor'), + lang:"html", + contents: $("#node-input-template").val() + }); + RED.library.create({ + url:"templates", // where to get the data from + type:"template", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','field'] + }); + $("#node-input-name").focus(); + }); + }, + oneditsave: function() { + $("#node-input-template").val(this.editor.getText()) + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/core_nodes/core/80-template.js b/dgbuilder/core_nodes/core/80-template.js new file mode 100644 index 00000000..7c84142d --- /dev/null +++ b/dgbuilder/core_nodes/core/80-template.js @@ -0,0 +1,61 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var mustache = require("mustache"); + + function TemplateNode(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.field = n.field || "payload"; + this.template = n.template; + var node = this; + + var b = node.field.split("."); + var i = 0; + var m = null; + var rec = function(obj) { + i += 1; + if ((i < b.length) && (typeof obj[b[i-1]] === "object")) { + rec(obj[b[i-1]]); // not there yet - carry on digging + } + else { + if (i === b.length) { // we've finished so assign the value + obj[b[i-1]] = mustache.render(node.template,m); + node.send(m); + } + else { + obj[b[i-1]] = {}; // needs to be a new object so create it + rec(obj[b[i-1]]); // and carry on digging + } + } + } + + node.on("input", function(msg) { + try { + m = msg; + i = 0; + rec(msg); + } catch(err) { + node.error(err.message); + } + }); + } + + RED.nodes.registerType("template",TemplateNode); + RED.library.register("templates"); +} diff --git a/dgbuilder/core_nodes/core/89-delay.html b/dgbuilder/core_nodes/core/89-delay.html new file mode 100644 index 00000000..dcb0a5b9 --- /dev/null +++ b/dgbuilder/core_nodes/core/89-delay.html @@ -0,0 +1,167 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- First, the content of the edit dialog is defined. --> +<script type="text/x-red" data-template-name="delay"> + + <div class="form-row"> + <label for="node-input-pauseType"><i class="fa fa-tasks"></i> Action</label> + <select id="node-input-pauseType" style="width:270px !important"> + <option value="delay">Delay message</option> + <option value="rate">Limit rate to</option> + <option value="random">Random delay</option> + </select> + </div> + <div id="delay-details" class="form-row"> + <label for="node-input-timeout"><i class="fa fa-clock-o"></i> For</label> + <input type="text" id="node-input-timeout" placeholder="Time" style="direction:rtl; width:50px !important"> + <select id="node-input-timeoutUnits" style="width:200px !important"> + <option value="milliseconds">Milliseconds</option> + <option value="seconds">Seconds</option> + <option value="minutes">Minutes</option> + <option value="hours">Hours</option> + <option value="days">Days</option> + </select> + </div> + + <div id="rate-details" class="form-row"> + <label for="node-input-rate"><i class="fa fa-clock-o"></i> To</label> + <input type="text" id="node-input-rate" placeholder="1" style="direction:rtl; width:30px !important"> + <label for="node-input-reateUnits">msg(s) per</label> + <select id="node-input-rateUnits" style="width:140px !important"> + <option value="second">Second</option> + <option value="minute">Minute</option> + <option value="hour">Hour</option> + <option value="day">Day</option> + </select> + <br/> + <input style="margin: 20px 0 20px 100px; width: 30px;" type="checkbox" id="node-input-drop"><label style="width: 250px;" for="node-input-drop">drop intermediate messages</label> + </div> + + <div id="random-details" class="form-row"> + <label for="node-input-randomFirst"><i class="fa fa-clock-o"></i> Between</label> + <input type="text" id="node-input-randomFirst" placeholder="" style="directon:rtl; width:30px !important"> + <label for="node-input-randomLast" style="width:20px"> & </label> + <input type="text" id="node-input-randomLast" placeholder="" style="directon:rtl; width:30px !important"> + <select id="node-input-randomUnits" style="width:140px !important"> + <option value="milliseconds">Milliseconds</option> + <option value="seconds">Seconds</option> + <option value="minutes">Minutes</option> + <option value="hours">Hours</option> + <option value="days">Days</option> + </select> + </div> + + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + +</script> + +<!-- Next, some simple help text is provided for the node. --> +<script type="text/x-red" data-help-name="delay"> + <p>Introduces a delay into a flow or rate limts messges</p> + <p>Default delay is 5 seconds and rate limit of 1 msg/second, but both can be configured</p> +</script> + +<!-- Finally, the node type is registered along with all of its properties --> +<script type="text/javascript"> + RED.nodes.registerType('delay',{ + category: 'function', // the palette category + color:"#E6E0F8", + defaults: { // defines the editable properties of the node + name: {value:""}, // along with default values. + pauseType: {value:"delay", required:true}, + timeout: {value:"5", required:true, validate:RED.validators.number()}, + timeoutUnits: {value:"seconds"}, + rate: {value:"1", required:true, validate:RED.validators.number()}, + rateUnits: {value: "second"}, + randomFirst: {value:"1", required:true, validate:RED.validators.number()}, + randomLast: {value:"5", required:true, validate:RED.validators.number()}, + randomUnits: {value: "seconds"}, + drop: {value:false} + }, + inputs:1, // set the number of inputs - only 0 or 1 + outputs:1, // set the number of outputs - 0 to n + icon: "timer.png", // set the icon (held in public/icons) + label: function() { // sets the default label contents + if (this.pauseType == "delay") { + var units = this.timeoutUnits ? this.timeoutUnits.charAt(0) : "s"; + if (this.timeoutUnits == "milliseconds") { units = "ms"; } + return this.name||"delay "+this.timeout+" " + units; + } else if (this.pauseType == "rate") { + var units = this.rateUnits ? this.rateUnits.charAt(0) : "s"; + return this.name||"limit "+this.rate+" msg/"+ units; + } else if (this.pauseType == "random") { + return this.name || "random"; + } + return "foo"; + }, + labelStyle: function() { // sets the class to apply to the label + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + $( "#node-input-timeout" ).spinner({min:1,max:60}); + $( "#node-input-rate" ).spinner({min:1}); + + $( "#node-input-randomFirst" ).spinner({min:0}); + $( "#node-input-randomLast" ).spinner({min:1}); + + if (this.pauseType == "delay") { + $("#delay-details").show(); + $("#rate-details").hide(); + $("#random-details").hide(); + } else if (this.pauseType == "rate") { + $("#delay-details").hide(); + $("#rate-details").show(); + $("#random-details").hide(); + } else if (this.pauseType == "random") { + $("#delay-details").hide(); + $("#rate-details").hide(); + $("#random-details").show(); + } + + if (!this.timeoutUnits) { + $("#node-input-timeoutUnits option").filter(function() { + return $(this).val() == 'seconds'; + }).attr('selected', true); + } + + if (!this.randomUnits) { + $("#node-input-randomUnits option").filter(function() { + return $(this).val() == 'seconds'; + }).attr('selected', true); + } + + $("#node-input-pauseType").on("change",function() { + if (this.value == "delay") { + $("#delay-details").show(); + $("#rate-details").hide(); + $("#random-details").hide(); + } else if (this.value == "rate") { + $("#delay-details").hide(); + $("#rate-details").show(); + $("#random-details").hide(); + } else if (this.value == "random") { + $("#delay-details").hide(); + $("#rate-details").hide(); + $("#random-details").show(); + } + }); + } + }); +</script> diff --git a/dgbuilder/core_nodes/core/89-delay.js b/dgbuilder/core_nodes/core/89-delay.js new file mode 100644 index 00000000..3c4e1c01 --- /dev/null +++ b/dgbuilder/core_nodes/core/89-delay.js @@ -0,0 +1,171 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +//Simple node to introduce a pause into a flow +module.exports = function(RED) { + "use strict"; + + var MILLIS_TO_NANOS = 1000000; + var SECONDS_TO_NANOS = 1000000000; + + function random(n) { + var wait = n.randomFirst + (n.diff * Math.random()); + if (n.buffer.length > 0) { + n.send(n.buffer.pop()); + n.randomID = setTimeout(function() {random(n);},wait); + } else { + n.randomID = -1; + } + } + + function DelayNode(n) { + RED.nodes.createNode(this,n); + + this.pauseType = n.pauseType; + this.timeoutUnits = n.timeoutUnits; + this.randomUnits = n.randomUnits; + this.rateUnits = n.rateUnits; + + if (n.timeoutUnits === "milliseconds") { + this.timeout = n.timeout; + } else if (n.timeoutUnits === "seconds") { + this.timeout = n.timeout * 1000; + } else if (n.timeoutUnits === "minutes") { + this.timeout = n.timeout * (60 * 1000); + } else if (n.timeoutUnits === "hours") { + this.timeout = n.timeout * (60 * 60 * 1000); + } else if (n.timeoutUnits === "days") { + this.timeout = n.timeout * (24 * 60 * 60 * 1000); + } + + if (n.rateUnits === "second") { + this.rate = 1000/n.rate; + } else if (n.rateUnits === "minute") { + this.rate = (60 * 1000)/n.rate; + } else if (n.rateUnits === "hour") { + this.rate = (60 * 60 * 1000)/n.rate; + } else if (n.rateUnits === "day") { + this.rate = (24 * 60 * 60 * 1000)/n.rate; + } + + if (n.randomUnits === "milliseconds") { + this.randomFirst = n.randomFirst; + this.randomLast = n.randomLast; + } else if (n.randomUnits === "seconds") { + this.randomFirst = n.randomFirst * 1000; + this.randomLast = n.randomLast * 1000; + } else if (n.randomUnits === "minutes") { + this.randomFirst = n.randomFirst * (60 * 1000); + this.randomLast = n.randomLast * (60 * 1000); + } else if (n.randomUnits === "hours") { + this.randomFirst = n.randomFirst * (60 * 60 * 1000); + this.randomLast = n.randomLast * (60 * 60 * 1000); + } else if (n.randomUnits === "days") { + this.randomFirst = n.randomFirst * (24 * 60 * 60 * 1000); + this.randomLast = n.randomLast * (24 * 60 * 60 * 1000); + } + + this.diff = this.randomLast - this.randomFirst; + this.name = n.name; + this.idList = []; + this.buffer = []; + this.intervalID = -1; + this.randomID = -1; + this.lastSent; + this.drop = n.drop; + var node = this; + + if (this.pauseType === "delay") { + this.on("input", function(msg) { + var id; + id = setTimeout(function(){ + node.idList.splice(node.idList.indexOf(id),1); + node.send(msg); + }, node.timeout); + this.idList.push(id); + }); + + this.on("close", function() { + for (var i=0; i<this.idList.length; i++ ) { + clearTimeout(this.idList[i]); + } + this.idList = []; + }); + + } else if (this.pauseType === "rate") { + this.on("input", function(msg) { + if (!node.drop) { + if ( node.intervalID !== -1) { + node.buffer.push(msg); + if (node.buffer.length > 0) { + node.status({text:node.buffer.length}); + } + if (node.buffer.length > 1000) { + node.warn(this.name + " buffer exceeded 1000 messages"); + } + } else { + node.send(msg); + node.intervalID = setInterval(function() { + if (node.buffer.length === 0) { + clearInterval(node.intervalID); + node.intervalID = -1; + node.status({text:""}); + } + + if (node.buffer.length > 0) { + node.send(node.buffer.shift()); + node.status({text:node.buffer.length}); + } + },node.rate); + } + } else { + var timeSinceLast; + if (node.lastSent) { + timeSinceLast = process.hrtime(node.lastSent); + } + if (!node.lastSent) { // ensuring that we always send the first message + node.lastSent = process.hrtime(); + node.send(msg); + } else if ( ( (timeSinceLast[0] * SECONDS_TO_NANOS) + timeSinceLast[1] ) > (node.rate * MILLIS_TO_NANOS) ) { + node.lastSent = process.hrtime(); + node.send(msg); + } + } + }); + + this.on("close", function() { + clearInterval(this.intervalID); + this.buffer = []; + }); + + } else if (this.pauseType === "random") { + this.on("input",function(msg){ + node.buffer.push(msg); + if (node.randomID === -1) { + var wait = node.randomFirst + (node.diff * Math.random()); + node.randomID = setTimeout(function() {random(node);},wait); + } + }); + + this.on("close", function (){ + if (this.randomID !== -1) { + clearTimeout(this.randomID); + } + }); + } + } + RED.nodes.registerType("delay",DelayNode); +} diff --git a/dgbuilder/core_nodes/core/89-trigger.html b/dgbuilder/core_nodes/core/89-trigger.html new file mode 100644 index 00000000..f3ec530d --- /dev/null +++ b/dgbuilder/core_nodes/core/89-trigger.html @@ -0,0 +1,130 @@ +<!-- + Copyright 2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="trigger"> + <div class="form-row"> + <label for="node-input-op1type"><i class="fa fa-arrow-up"></i> Output</label> + <select id="node-input-op1type" style="width:73% !important"> + <option value="val">the value below</option> + <option value="pay">the existing payload</option> + <option value="nul">nothing (no output)</option> + </select> + </div> + <div class="form-row" id="node-op1"> + <label for="node-input-op1"> </label> + <input type="text" id="node-input-op1"> + </div> + <div class="form-row"> + <label for="node-input-duration"><i class="fa fa-clock-o"></i> then wait</label> + <input type="text" id="node-input-duration" placeholder="250" style="direction:rtl; width:70px !important"> + <select id="node-input-units" style="width:140px !important"> + <option value="ms">Milliseconds</option> + <option value="s">Seconds</option> + <option value="min">Minutes</option> + <option value="hr">Hours</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-op2type"><i class="fa fa-arrow-down"></i> output</label> + <select id="node-input-op2type" style="width:73% !important"> + <option value="val">the value below</option> + <option value="pay">the existing payload</option> + <option value="nul">nothing (no output)</option> + </select> + </div> + <div class="form-row" id="node-op2"> + <label for="node-input-op2"> </label> + <input type="text" id="node-input-op2"> + </div> + <div class="form-row"> + <label for="node-input-extend"><i class="fa fa-repeat"></i> and</label> + <select id="node-input-extend" style="width:73% !important"> + <option value="false">don't extend the timer if retriggered</option> + <option value="true">extend the timer if retriggered</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <!-- <div class="form-tips">Tip: Outputs can be values, null, {{templated}} or msg.payload<br/> --> + <div class="form-tips">Setting the timeout to 0 sets an infinite timeout = single shot.</div> + <script> + { + $("#node-input-op1type").change(function() { + if ($("#node-input-op1type").val() == "val") { $("#node-op1").show(); } + else { $("#node-op1").hide(); } + }); + $("#node-input-op2type").change(function() { + if ($("#node-input-op2type").val() == "val") { $("#node-op2").show(); } + else { $("#node-op2").hide(); } + }); + } + </script> +</script> + +<script type="text/x-red" data-help-name="trigger"> + <p>Creates two messages on the output separated by a timeout whenever ANY <b>msg</b> arrives on the input.</p> + <p>For example, this can be used to toggle a Raspberry PI GPIO pin on and off.</p> + <p>The two output states can be specified as can the duration of the timer. + Either output can be set to a value, or templated from the inbound + <b>msg</b> using mustache syntax. <pre>The payload is {{payload}}</pre></p> + <p>If the payload is an object then setting the output to <i>existing payload</i> will pass the complete payload object through.</p> + <p>Optionally the timer can be extended by being retriggered... or not.</p> + <p>By setting the first output to <i>nothing</i>, and selecting extend timer - a watchdog timer can be created. + No output will happen as long as repeated inputs occur within the timeout period.</p> + <p>Setting the timer to 0 creates an "infinite" timeout - the first output will happen but the second + never will, and neither can the first be retriggered - so a true one shot.</p> + <p>If a <b>msg.reset</b> property is present any timeout currently in progress + will be cleared and the second output will not happen.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('trigger',{ + category: 'function', + color:"#E6E0F8", + defaults: { + op1: {value:"1"}, + op2: {value:"0"}, + op1type: {value:""}, + op2type: {value:""}, + duration: {value:"250",required:true,validate:RED.validators.number()}, + extend: {value:"false"}, + units: {value: "ms"}, + name: {value:""} + }, + inputs:1, + outputs:1, + icon: "trigger.png", + label: function() { + if (this.duration > 0) { + return this.name||"trigger "+this.duration+this.units; + } + else { + return this.name||"trigger once ∞"; + } + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + $( "#node-input-duration" ).spinner({ + min:1, + increment:25 + }); + } + }); +</script> diff --git a/dgbuilder/core_nodes/core/89-trigger.js b/dgbuilder/core_nodes/core/89-trigger.js new file mode 100644 index 00000000..d86a2130 --- /dev/null +++ b/dgbuilder/core_nodes/core/89-trigger.js @@ -0,0 +1,91 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var mustache = require("mustache"); + function TriggerNode(n) { + RED.nodes.createNode(this,n); + this.op1 = n.op1 || "1"; + this.op2 = n.op2 || "0"; + this.op1type = n.op1type || "val"; + this.op2type = n.op2type || "val"; + this.extend = n.extend || false; + this.units = n.units || "ms"; + this.duration = n.duration || 250; + if (this.duration <= 0) { this.duration = 0; } + else { + if (this.units == "s") { this.duration = this.duration * 1000; } + if (this.units == "min") { this.duration = this.duration * 1000 * 60; } + if (this.units == "hr") { this.duration = this.duration * 1000 *60 * 60; } + } + this.op1Templated = this.op1.indexOf("{{") != -1; + this.op2Templated = this.op2.indexOf("{{") != -1; + if (!isNaN(this.op1)) { this.op1 = Number(this.op1); } + if (!isNaN(this.op2)) { this.op2 = Number(this.op2); } + if (this.op1 == "true") { this.op1 = true; } + if (this.op2 == "true") { this.op1 = true; } + if (this.op1 == "false") { this.op2 = false; } + if (this.op2 == "false") { this.op2 = false; } + if (this.op1 == "null") { this.op1 = null; } + if (this.op2 == "null") { this.op1 = null; } + try { this.op1 = JSON.parse(this.op1); } + catch(e) { this.op1 = this.op1; } + try { this.op2 = JSON.parse(this.op2); } + catch(e) { this.op2 = this.op2; } + + var node = this; + var tout = null; + var m2; + this.on("input", function(msg) { + if (msg.hasOwnProperty("reset")) { + clearTimeout(tout); + tout = null; + } + else { + if (!tout) { + if (node.op2type === "pay") { m2 = msg.payload; } + else if (node.op2Templated) { m2 = mustache.render(node.op2,msg); } + else { m2 = node.op2; } + if (node.op1type === "pay") { } + else if (node.op1Templated) { msg.payload = mustache.render(node.op1,msg); } + else { msg.payload = node.op1; } + if (node.op1type !== "nul") { node.send(msg); } + if (node.duration === 0) { tout = "infinite"; } + else { + tout = setTimeout(function() { + msg.payload = m2; + if (node.op2type !== "nul") { node.send(msg); } + tout = null; + },node.duration); + } + } + else if ((node.extend == "true") && (node.duration > 0)) { + clearTimeout(tout); + tout = setTimeout(function() { + msg.payload = m2; + if (node.op2type !== "nul") { node.send(msg); } + tout = null; + },node.duration); + } + } + }); + this.on("close", function() { + if (tout) { clearTimeout(tout); } + }); + } + RED.nodes.registerType("trigger",TriggerNode); +} diff --git a/dgbuilder/core_nodes/core/90-comment.html b/dgbuilder/core_nodes/core/90-comment.html new file mode 100644 index 00000000..3638fdaa --- /dev/null +++ b/dgbuilder/core_nodes/core/90-comment.html @@ -0,0 +1,86 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="comment"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-comment"></i> Comment</label> + <input type="text" id="node-input-name" placeholder="Comment"> + </div> + <div class="form-row"> + <label for="node-input-info" style="width: 100% !important;"><i class="fa fa-comments"></i> More</label> + <input type="hidden" id="node-input-info" autofocus="autofocus"> + <div style="height: 250px;" class="node-text-editor" id="node-input-info-editor" ></div> + </div> + <div class="form-tips">Tip: this isn't meant for "War and Peace" - but useful notes can be kept here.</div> +</script> + +<script type="text/x-red" data-help-name="comment"> + <p>Simple comment block.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('comment',{ + category: 'function', + color:"#ffffff", + defaults: { + name: {value:""}, + info: {value:""} + }, + inputs:0, + outputs:0, + icon: "comment.png", + label: function() { + return this.name||""; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + function functionDialogResize(ev,ui) { + $("#node-input-info-editor").css("height",(ui.size.height-235)+"px"); + }; + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-info-editor'), + lang:"text", + showLinesRuler:false, + showFoldingRuler:false, + contents: $("#node-input-info").val() + }); + $("#node-input-name").focus(); + }); + }, + oneditsave: function() { + $("#node-input-info").val(this.editor.getText()); + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/core_nodes/core/90-comment.js b/dgbuilder/core_nodes/core/90-comment.js new file mode 100644 index 00000000..ef5f0800 --- /dev/null +++ b/dgbuilder/core_nodes/core/90-comment.js @@ -0,0 +1,23 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + function CommentNode(n) { + RED.nodes.createNode(this,n); + } + RED.nodes.registerType("comment",CommentNode); +} diff --git a/dgbuilder/core_nodes/core/98-unknown.html b/dgbuilder/core_nodes/core/98-unknown.html new file mode 100644 index 00000000..19a4ad59 --- /dev/null +++ b/dgbuilder/core_nodes/core/98-unknown.html @@ -0,0 +1,49 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="unknown"> + <div class="form-tips"><p>This node is a type unknown to your installation of Node-RED.</p> + <p><i>If you deploy with the node in this state, it will lose all of its configuration.</i></p> + <p>See the Info side bar for more help</p></div> +</script> + +<script type="text/x-red" data-help-name="unknown"> + <p>This node is a type unknown to your installation of Node-RED.</p> + <p><i>If you deploy with the node in this state, it will lose all of its configuration.</i></p> + <p>It is possible this node type is already installed, but is missing a dependency. Check the Node-RED start-up log for + any error messages associated with the missing node type. Use <b>npm install <module></b> to install any missing modules + and restart Node-RED and reimport the nodes.</p> + <p>Otherwise, you should contact the author of the flow to obtain a copy of the missing node type.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('unknown',{ + category: 'unknown', + color:"#fff0f0", + defaults: { + name: {value:""} + }, + inputs:1, + outputs:1, + icon: "", + label: function() { + return "("+this.name+")"||"unknown"; + }, + labelStyle: function() { + return "node_label_unknown"; + } + }); +</script> diff --git a/dgbuilder/core_nodes/core/98-unknown.js b/dgbuilder/core_nodes/core/98-unknown.js new file mode 100644 index 00000000..ed4716b8 --- /dev/null +++ b/dgbuilder/core_nodes/core/98-unknown.js @@ -0,0 +1,23 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + function UnknownNode(n) { + RED.nodes.createNode(this,n); + } + RED.nodes.registerType("unknown",UnknownNode); +} diff --git a/dgbuilder/core_nodes/deprecated/61-imap.html b/dgbuilder/core_nodes/deprecated/61-imap.html new file mode 100644 index 00000000..9702cd64 --- /dev/null +++ b/dgbuilder/core_nodes/deprecated/61-imap.html @@ -0,0 +1,56 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="imap"> + <div class="form-row node-input-repeat"> + <label for="node-input-repeat"><i class="fa fa-repeat"></i>Repeat (S)</label> + <input type="text" id="node-input-repeat" placeholder="300"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="imap"> + <p>Repeatedly gets a <b>single email</b> from an IMAP server and forwards on as a msg if not already seen.</p> + <p>The subject is loaded into <b>msg.topic</b> and <b>msg.payload</b> is the plain text body. + If there is text/html then that is returned in <b>msg.html</b>. <b>msg.from</b> and <b>msg.date</b> are also set if you need them.</p> + <p>Uses the imap module - you also need to pre-configure your email settings in a file emailkeys.js as per below.</p> + <p><pre>module.exports = { service: "Gmail", user: "blahblah@gmail.com", pass: "password", server: "imap.gmail.com", port: "993" }</pre></p> + <p>This <b>must</b> be located in the directory <b>above</b> node-red.</p> + <p><b>Note:</b> this node <i>only</i> gets the most recent single email from the inbox, so set the repeat (polling) time appropriately.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('imap',{ + category: 'deprecated', + color:"#c7e9c0", + defaults: { + repeat: {value:"300",required:true}, + name: {value:""} + }, + inputs:0, + outputs:1, + icon: "envelope.png", + label: function() { + return this.name||"IMAP"; + }, + labelStyle: function() { + return (this.name||!this.topic)?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/deprecated/61-imap.js b/dgbuilder/core_nodes/deprecated/61-imap.js new file mode 100644 index 00000000..aa2b4beb --- /dev/null +++ b/dgbuilder/core_nodes/deprecated/61-imap.js @@ -0,0 +1,139 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var RED = require(process.env.NODE_RED_HOME+"/red/red"); +var Imap = require('imap'); +var util = require('util'); + +try { + var emailkey = RED.settings.email || require(process.env.NODE_RED_HOME+"/../emailkeys.js"); +} catch (err) { + //util.log("[61-imap.js] Info : No Email credentials found."); +} + +if (emailkey) { + var imap = new Imap({ + user: emailkey.user, + password: emailkey.pass, + host: emailkey.server||"imap.gmail.com", + port: emailkey.port||"993", + tls: true, + tlsOptions: { rejectUnauthorized: false } + }); + + function openInbox(cb) { + imap.openBox('INBOX', true, cb); + } +} + +function ImapNode(n) { + RED.nodes.createNode(this,n); + this.warn("This node has been deprecated and will be deleted in a future release. Please update your flow to use the 'e-mail in' node."); + this.name = n.name; + this.repeat = n.repeat * 1000 || 300000; + var node = this; + this.interval_id = null; + var oldmail = {}; + + if (!isNaN(this.repeat) && this.repeat > 0) { + node.log("repeat = "+this.repeat); + this.interval_id = setInterval( function() { + node.emit("input",{}); + }, this.repeat ); + } + + this.on("input", function(msg) { + if (imap) { + imap.once('ready', function() { + var pay = {}; + openInbox(function(err, box) { + if (box.messages.total > 0) { + var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM SUBJECT DATE)','TEXT'] }); + f.on('message', function(msg, seqno) { + node.log('message: #'+ seqno); + var prefix = '(#' + seqno + ') '; + msg.on('body', function(stream, info) { + var buffer = ''; + stream.on('data', function(chunk) { + buffer += chunk.toString('utf8'); + }); + stream.on('end', function() { + if (info.which !== 'TEXT') { + pay.from = Imap.parseHeader(buffer).from[0]; + pay.topic = Imap.parseHeader(buffer).subject[0]; + pay.date = Imap.parseHeader(buffer).date[0]; + } else { + var parts = buffer.split("Content-Type"); + for (var p in parts) { + if (parts[p].indexOf("text/plain") >= 0) { + pay.payload = parts[p].split("\n").slice(1,-2).join("\n").trim(); + } + if (parts[p].indexOf("text/html") >= 0) { + pay.html = parts[p].split("\n").slice(1,-2).join("\n").trim(); + } + } + //pay.body = buffer; + } + }); + }); + msg.on('end', function() { + //node.log('Finished: '+prefix); + }); + }); + f.on('error', function(err) { + node.warn('fetch error: ' + err); + }); + f.on('end', function() { + if (JSON.stringify(pay) !== oldmail) { + node.send(pay); + oldmail = JSON.stringify(pay); + node.log('sent new message: '+pay.topic); + } + else { node.log('duplicate not sent: '+pay.topic); } + imap.end(); + }); + } + else { + // node.log("you have achieved inbox zero"); + imap.end(); + } + }); + }); + imap.connect(); + } + else { node.warn("No Email credentials found. See info panel."); } + }); + + if (imap) { + imap.on('error', function(err) { + util.log(err); + }); + } + + this.on("error", function(err) { + node.log("error: ",err); + }); + + this.on("close", function() { + if (this.interval_id != null) { + clearInterval(this.interval_id); + } + if (imap) { imap.destroy(); } + }); + + node.emit("input",{}); +} +RED.nodes.registerType("imap",ImapNode); diff --git a/dgbuilder/core_nodes/deprecated/73-parsexml.html b/dgbuilder/core_nodes/deprecated/73-parsexml.html new file mode 100644 index 00000000..b6fc16fe --- /dev/null +++ b/dgbuilder/core_nodes/deprecated/73-parsexml.html @@ -0,0 +1,53 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="xml2js"> + <!-- <div class="form-row"> + <label>Use Console</label> + <input type="checkbox" id="node-input-useEyes" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-useEyes" style="width: 70%;">Debug output in console ?</label> + </div> --> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <!-- <div class="form-tips">Uses xml2js to process xml into javascript object.</div> --> +</script> + +<script type="text/x-red" data-help-name="xml2js"> + <p>A function that parses the <b>msg.payload</b> using the xml2js library. Places the result in the payload.</p> + <p>See <a href="https://github.com/Leonidas-from-XIV/node-xml2js/blob/master/README.md" target="_new">the xml2js docs <i>here</i></a> for more information.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('xml2js',{ + category: 'deprecated', + color:"#E6E0F8", + defaults: { + //useEyes: {value:false}, + name: {value:""} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name||"xml2json"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/deprecated/73-parsexml.js b/dgbuilder/core_nodes/deprecated/73-parsexml.js new file mode 100644 index 00000000..92850cb6 --- /dev/null +++ b/dgbuilder/core_nodes/deprecated/73-parsexml.js @@ -0,0 +1,47 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var parseString = require('xml2js').parseString; + var useColors = true; + //util.inspect.styles.boolean = "red"; + + function Xml2jsNode(n) { + RED.nodes.createNode(this,n); + this.warn("This node has been deprecated and will be deleted in a future release. Please update your flow to use the 'xml' node."); + this.useEyes = n.useEyes||false; + var node = this; + this.on("input", function(msg) { + try { + parseString(msg.payload, {strict:true,async:true}, function (err, result) { + //parseString(msg.payload, {strict:false,async:true}, function (err, result) { + if (err) { node.error(err); } + else { + msg.payload = result; + node.send(msg); + if (node.useEyes == true) { + node.log("\n"+util.inspect(msg, {colors:useColors, depth:10})); + } + } + }); + } + catch(e) { util.log("[73-parsexml.js] "+e); } + }); + } + RED.nodes.registerType("xml2js",Xml2jsNode); +} diff --git a/dgbuilder/core_nodes/deprecated/74-js2xml.html b/dgbuilder/core_nodes/deprecated/74-js2xml.html new file mode 100644 index 00000000..f614579b --- /dev/null +++ b/dgbuilder/core_nodes/deprecated/74-js2xml.html @@ -0,0 +1,51 @@ +<!--
+ Copyright 2013 IBM Corp.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="json2xml">
+ <div class="form-row">
+ <label for="node-input-name"><i class="fa fa-list"></i> XML Root</label>
+ <input type="text" id="node-input-root" placeholder="object"></input>
+ </div>
+ <div class="form-row">
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+ <input type="text" id="node-input-name" placeholder="Name"></input>
+ </div>
+</script>
+
+<script type="text/x-red" data-help-name="json2xml">
+ <p>A function that parses the <b>msg.payload</b> using the js2xmlparser library. Places the result back in <b>msg.payload</b>.</p>
+ <p>See the <a href="https://github.com/michaelkourlas/node-js2xmlparser" target="_new">js2xmlparser docs</a> for more information.</p>
+</script>
+
+<script type="text/javascript">
+ RED.nodes.registerType('json2xml',{
+ category: 'deprecated',
+ color:"#E6E0F8",
+ defaults: {
+ name: {value:""},
+ root: {value:"object"},
+ },
+ inputs:1,
+ outputs:1,
+ icon: "arrow-in.png",
+ label: function() {
+ return this.name||"json2xml";
+ },
+ labelStyle: function() {
+ return this.name?"node_label_italic":"";
+ }
+ });
+</script>
diff --git a/dgbuilder/core_nodes/deprecated/74-js2xml.js b/dgbuilder/core_nodes/deprecated/74-js2xml.js new file mode 100644 index 00000000..164bafad --- /dev/null +++ b/dgbuilder/core_nodes/deprecated/74-js2xml.js @@ -0,0 +1,39 @@ +/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+ "use strict";
+ var js2xmlparser = require("js2xmlparser");
+
+ function Js2XmlNode(n) {
+ RED.nodes.createNode(this,n);
+ this.warn("This node has been deprecated and will be deleted in a future release. Please update your flow to use the 'xml' node.");
+ this.root = n.root;
+ var node = this;
+
+ this.on("input", function(msg) {
+ try {
+ var root = node.root || typeof msg.payload;
+ if (typeof msg.payload !== "object") { msg.payload = '"'+msg.payload+'"'; }
+ console.log(root, typeof msg.payload,msg.payload);
+ msg.payload = js2xmlparser(root, msg.payload);
+ node.send(msg);
+ }
+ catch(e) { console.log(e); }
+ });
+ }
+ RED.nodes.registerType("json2xml",Js2XmlNode);
+}
diff --git a/dgbuilder/core_nodes/deprecated/90-httpget.html b/dgbuilder/core_nodes/deprecated/90-httpget.html new file mode 100644 index 00000000..b1f2e080 --- /dev/null +++ b/dgbuilder/core_nodes/deprecated/90-httpget.html @@ -0,0 +1,61 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="httpget"> + <div class="form-tips"><b>Deprecated</b>: please use the <i>http request</i> node.</div> + <br> + <div class="form-row"> + <label for="node-input-baseurl"><i class="fa fa-tasks"></i> Base URL</label> + <input type="text" id="node-input-baseurl" placeholder="http(s)://url"> + </div> + <div class="form-row"> + <label for="node-input-append"><i class="fa fa-tasks"></i> Append</label> + <input type="text" id="node-input-append" placeholder=""> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">The <b>Base URL</b> gets prepended to whatever payload is passed in. Leave blank if you pass in a full url.<br/>The append gets added to the end after any payload.<br/>The output Topic is the same as the input Topic.</div> +</script> + +<script type="text/x-red" data-help-name="httpget"> + <p>Performs an HTTP or HTTPS GET and returns the fetched page.</p> + <p>The return code is placed in <b>msg.rc</b>, and the full text of the result is in <b>msg.payload</b>.</p> + <p>The <b>msg.payload</b> is added to the base url, and then the optional append is added after.</p> + <p>This is mostly suitable for small pages as large results will need a lot of parsing....</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('httpget',{ + category: 'deprecated', + color:"rgb(231, 231, 174)", + defaults: { + name: {value:""}, + baseurl: {value:""}, + append: {value:""} + }, + inputs:1, + outputs:1, + icon: "white-globe.png", + label: function() { + return this.name||this.baseurl; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/deprecated/90-httpget.js b/dgbuilder/core_nodes/deprecated/90-httpget.js new file mode 100644 index 00000000..63e16b93 --- /dev/null +++ b/dgbuilder/core_nodes/deprecated/90-httpget.js @@ -0,0 +1,53 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var RED = require(process.env.NODE_RED_HOME+"/red/red"); + +function HttpGet(n) { + RED.nodes.createNode(this,n); + this.warn("This node has been deprecated and will be deleted in a future release. Please update your flow to use the 'http request' node."); + this.baseurl = n.baseurl || ""; + this.append = n.append || ""; + var node = this; + if (this.baseurl.substring(0,5) === "https") { var http = require("https"); } + else { var http = require("http"); } + this.on("input", function(msg) { + msg._payload = msg.payload; + //util.log("[httpget] "+this.baseurl+msg.payload+this.append); + http.get(this.baseurl+msg.payload+this.append, function(res) { + node.log("Http response: " + res.statusCode); + msg.rc = res.statusCode; + msg.payload = ""; + if ((msg.rc != 200) && (msg.rc != 404)) { + node.send(msg); + } + res.setEncoding('utf8'); + res.on('data', function(chunk) { + msg.payload += chunk; + }); + res.on('end', function() { + node.send(msg); + }); + }).on('error', function(e) { + //node.error(e); + msg.rc = 503; + msg.payload = e; + node.send(msg); + }); + }); +} + +RED.nodes.registerType("httpget",HttpGet); diff --git a/dgbuilder/core_nodes/hardware/35-arduino.html b/dgbuilder/core_nodes/hardware/35-arduino.html new file mode 100644 index 00000000..17f02892 --- /dev/null +++ b/dgbuilder/core_nodes/hardware/35-arduino.html @@ -0,0 +1,171 @@ +<!-- + Copyright 2013,2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<script type="text/x-red" data-template-name="arduino in"> + <div class="form-row"> + <label for="node-input-arduino"><i class="fa fa-tasks"></i> Arduino</label> + <input type="text" id="node-input-arduino"> + </div> + <div class="form-row"> + <label for="node-input-pin"><i class="fa fa-circle"></i> Pin</label> + <input type="text" id="node-input-pin" placeholder="2"> + </div> + <div class="form-row"> + <label for="node-input-state"><i class="fa fa-wrench"></i> Type</label> + <select type="text" id="node-input-state" style="width: 150px;"> + <option value="INPUT">Digital pin</option> + <option value="ANALOG">Analogue pin</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips"><b>Note:</b> You cannot use the same pin for both output and input.</div> +</script> + +<script type="text/x-red" data-help-name="arduino in"> + <p>Arduino input node. Connects to local Arduino and monitors the selected pin for changes. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p> + <p>The Arduino must be loaded with the Standard Firmata sketch available in the Arduino examples.</p> + <p>You can select either Digital or Analogue input. Outputs the value read as <b>msg.payload</b> and the pin number as <b>msg.topic</b>.</p> + <p>It only outputs on a change of value - fine for digital inputs, but you can get a lot of data from analogue pins which you must then handle.</p> + <p>You can set the sample rate in ms from 20 to 65535.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('arduino in',{ + category: 'Arduino', + color:"#3fadb5", + defaults: { + name: {value:""}, + pin: {value:"",required:true}, + state: {value:"INPUT",required:true}, + arduino: {type:"arduino-board"} + }, + inputs:0, + outputs:1, + icon: "arduino.png", + label: function() { + var a = ""; + if (this.state == "ANALOG") a = "A"; + return this.name||"Pin: "+a+this.pin; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> + +<script type="text/x-red" data-template-name="arduino out"> + <div class="form-row"> + <label for="node-input-arduino"><i class="fa fa-tasks"></i> Arduino</label> + <input type="text" id="node-input-arduino"> + </div> + <div class="form-row"> + <label for="node-input-pin"><i class="fa fa-circle"></i> Pin</label> + <input type="text" id="node-input-pin" placeholder="13"> + </div> + <div class="form-row"> + <label for="node-input-state"><i class="fa fa-wrench"></i> Type</label> + <select type="text" id="node-input-state" style="width: 200px;"> + <option value="OUTPUT">Digital (0/1)</option> + <option value="PWM">Analogue (0-255)</option> + <option value="SERVO">Servo (0-180)</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips"><b>Note:</b> You cannot use the same pin for both output and input.</div> +</script> + +<script type="text/x-red" data-help-name="arduino out"> + <p>Arduino output node. Connects to local Arduino and writes to the selected digital pin. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p> + <p>The Arduino must be loaded with the Standard Firmata sketch available in the Arduino examples.</p> + <p>You can select Digital, Analogue (PWM) or Servo type outputs. Expects a numeric value in <b>msg.payload</b>. The pin number is set in the properties panel.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('arduino out',{ + category: 'Arduino', + color:"#3fadb5", + defaults: { + name: {value:""}, + pin: {value:"",required:true}, + state: {value:"",required:true}, + arduino: {type:"arduino-board"} + }, + inputs:1, + outputs:0, + icon: "arduino.png", + align: "right", + label: function() { + return this.name||"Pin: "+this.pin; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> + + +<script type="text/x-red" data-template-name="arduino-board"> + <div class="form-row"> + <label for="node-config-input-device"><i class="fa fa-random"></i> Port</label> + <input type="text" id="node-config-input-device" style="width:60%;" placeholder="e.g. /dev/ttyUSB0 COM1"/> + <a id="node-config-lookup-serial" class="btn"><i id="node-config-lookup-serial-icon" class="fa fa-search"></i></a> + </div> + <div class="form-tips"><b>Tip:</b> Use search to try to auto-detect serial port.</div> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('arduino-board',{ + category: 'config', + defaults: { + device: {value:"",required:true} + }, + label: function() { + return this.device||"arduino"; + }, + oneditprepare: function() { + try { + $("#node-config-input-device").autocomplete( "destroy" ); + } catch(err) { } + $("#node-config-lookup-serial").click(function() { + $("#node-config-lookup-serial-icon").removeClass('fa-search'); + $("#node-config-lookup-serial-icon").addClass('spinner'); + $("#node-config-lookup-serial").addClass('disabled'); + + $.getJSON('arduinoports',function(data) { + $("#node-config-lookup-serial-icon").addClass('fa-search'); + $("#node-config-lookup-serial-icon").removeClass('spinner'); + $("#node-config-lookup-serial").removeClass('disabled'); + var ports = []; + $.each(data, function(i, port){ + ports.push(port); + }); + $("#node-config-input-device").autocomplete({ + source:ports, + minLength:0, + close: function( event, ui ) { + $("#node-config-input-device").autocomplete( "destroy" ); + } + }).autocomplete("search",""); + }); + }); + } + }); +</script> diff --git a/dgbuilder/core_nodes/hardware/35-arduino.js b/dgbuilder/core_nodes/hardware/35-arduino.js new file mode 100644 index 00000000..795e9907 --- /dev/null +++ b/dgbuilder/core_nodes/hardware/35-arduino.js @@ -0,0 +1,160 @@ +/** + * Copyright 2013,2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var ArduinoFirmata = require('arduino-firmata'); + var fs = require('fs'); + var plat = require('os').platform(); + var portlist = ArduinoFirmata.list(function (err, ports) { + portlist = ports; + }); + + // The Board Definition - this opens (and closes) the connection + function ArduinoNode(n) { + RED.nodes.createNode(this,n); + this.device = n.device || null; + this.repeat = n.repeat||25; + //node.log("opening connection "+this.device); + var node = this; + node.board = new ArduinoFirmata(); + if (portlist.indexOf(node.device) === -1) { + node.warn("Device "+node.device+" not found"); + } + else { + node.board.connect(node.device); + } + + node.board.on('boardReady', function(){ + node.log("version "+node.board.boardVersion); + }); + + node.on('close', function() { + if (node.board) { + try { + node.board.close(function() { + node.log("port closed"); + }); + } catch(e) { } + } + }); + } + RED.nodes.registerType("arduino-board",ArduinoNode); + + + // The Input Node + function DuinoNodeIn(n) { + RED.nodes.createNode(this,n); + this.buttonState = -1; + this.pin = n.pin; + this.state = n.state; + this.arduino = n.arduino; + this.serverConfig = RED.nodes.getNode(this.arduino); + if (typeof this.serverConfig === "object") { + this.board = this.serverConfig.board; + //this.repeat = this.serverConfig.repeat; + var node = this; + node.status({fill:"red",shape:"ring",text:"connecting"}); + + node.board.on('connect', function() { + node.status({fill:"green",shape:"dot",text:"connected"}); + //console.log("i",node.state,node.pin); + if (node.state == "ANALOG") { + node.board.on('analogChange', function(e) { + if (e.pin == node.pin) { + var msg = {payload:e.value, topic:"A"+e.pin}; + node.send(msg); + } + }); + + } + else { + node.board.pinMode(node.pin, ArduinoFirmata.INPUT); + node.board.on('digitalChange', function(e) { + if (e.pin == node.pin) { + var msg = {payload:e.value, topic:e.pin}; + node.send(msg); + } + }); + } + }); + } + else { + util.log("[Firmata-arduino] port not configured"); + } + } + RED.nodes.registerType("arduino in",DuinoNodeIn); + + + // The Output Node + function DuinoNodeOut(n) { + RED.nodes.createNode(this,n); + this.buttonState = -1; + this.pin = n.pin; + this.state = n.state; + this.arduino = n.arduino; + this.serverConfig = RED.nodes.getNode(this.arduino); + if (typeof this.serverConfig === "object") { + this.board = this.serverConfig.board; + var node = this; + node.status({fill:"red",shape:"ring",text:"connecting"}); + + node.board.on('connect', function() { + node.status({fill:"green",shape:"dot",text:"connected"}); + //console.log("o",node.state,node.pin); + node.board.pinMode(node.pin, node.state); + node.on("input", function(msg) { + if (node.state == "OUTPUT") { + if ((msg.payload == true)||(msg.payload == 1)||(msg.payload.toString().toLowerCase() == "on")) { + node.board.digitalWrite(node.pin, true); + } + if ((msg.payload == false)||(msg.payload == 0)||(msg.payload.toString().toLowerCase() == "off")) { + node.board.digitalWrite(node.pin, false); + } + } + if (node.state == "PWM") { + msg.payload = msg.payload * 1; + if ((msg.payload >= 0) && (msg.payload <= 255)) { + //console.log(msg.payload, node.pin); + node.board.servoWrite(node.pin, msg.payload); + } + } + if (node.state == "SERVO") { + msg.payload = msg.payload * 1; + if ((msg.payload >= 0) && (msg.payload <= 180)) { + //console.log(msg.payload, node.pin); + node.board.servoWrite(node.pin, msg.payload); + } + } + }); + }); + } + else { + util.log("[Firmata-arduino] port not configured"); + } + } + RED.nodes.registerType("arduino out",DuinoNodeOut); + + RED.httpAdmin.get("/arduinoports",function(req,res) { + ArduinoFirmata.list(function (err, ports) { + //console.log(JSON.stringify(ports)); + res.writeHead(200, {'Content-Type': 'text/plain'}); + res.write(JSON.stringify(ports)); + res.end(); + }); + }); +} diff --git a/dgbuilder/core_nodes/hardware/36-rpi-gpio.html b/dgbuilder/core_nodes/hardware/36-rpi-gpio.html new file mode 100644 index 00000000..9e705c2c --- /dev/null +++ b/dgbuilder/core_nodes/hardware/36-rpi-gpio.html @@ -0,0 +1,182 @@ +<!-- + Copyright 2013,2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="rpi-gpio in"> + <div class="form-row"> + <label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label> + <select type="text" id="node-input-pin" style="width: 200px;"> + <option value="-" disabled>select pin </option> + <option value="3">3 - SDA1 </option> + <option value="5">5 - SCL1 </option> + <option value="7">7 - GPIO7</option> + <option value="8">8 - TxD </option> + <option value="10">10 - RxD </option> + <option value="11">11 - GPIO0</option> + <option value="12">12 - GPIO1</option> + <option value="13">13 - GPIO2</option> + <option value="15">15 - GPIO3</option> + <option value="16">16 - GPIO4</option> + <option value="18">18 - GPIO5</option> + <option value="19">19 - MOSI </option> + <option value="21">21 - MISO </option> + <option value="22">22 - GPIO6</option> + <option value="23">23 - SCLK </option> + <option value="24">24 - CE0 </option> + <option value="26">26 - CE1 </option> + </select> + <span id="pitype"></span> + </div> + <div class="form-row"> + <label for="node-input-intype"><i class="fa fa-long-arrow-up"></i> Resistor?</label> + <select type="text" id="node-input-intype" style="width: 150px;"> + <option value="tri">none</option> + <option value="up">pullup</option> + <option value="down">pulldown</option> + <!--<option value="tri">tristate</option>--> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">Tip: Only Digital I/O is supported - input must be 0 or 1.</div> +</script> + +<script type="text/x-red" data-help-name="rpi-gpio in"> + <p>Raspberry Pi input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin. Requires the gpio command to work.</p> + <p>You may also enable the input pullup resitor or the pulldown resistor.</p> + <p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></p> + <p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p> + <p><b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu, and will be rewritten shortly to try to use interrupts.</p> + +</script> + +<script type="text/javascript"> + RED.nodes.registerType('rpi-gpio in',{ + category: 'advanced-input', + color:"#c6dbef", + defaults: { + name: { value:"" }, + intype: { value: "in" }, + pin: { value:"",required:true,validate:RED.validators.number() }, + }, + inputs:0, + outputs:1, + icon: "rpi.png", + label: function() { + return this.name||"Pin: "+this.pin ; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + $.getJSON('rpi-gpio/'+this.id,function(data) { + $('#pitype').text(data.type); + if (data.type === "Model B+") { + $('#node-input-pin').append($("<option></option>").attr("value",27).text("27 - SDA0")); + $('#node-input-pin').append($("<option></option>").attr("value",28).text("28 - SCL0")); + $('#node-input-pin').append($("<option></option>").attr("value",29).text("29 - GPIO21")); + $('#node-input-pin').append($("<option></option>").attr("value",31).text("31 - GPIO22")); + $('#node-input-pin').append($("<option></option>").attr("value",32).text("32 - GPIO26")); + $('#node-input-pin').append($("<option></option>").attr("value",33).text("33 - GPIO23")); + $('#node-input-pin').append($("<option></option>").attr("value",35).text("35 - GPIO24")); + $('#node-input-pin').append($("<option></option>").attr("value",36).text("36 - GPIO27")); + $('#node-input-pin').append($("<option></option>").attr("value",37).text("37 - GPIO25")); + $('#node-input-pin').append($("<option></option>").attr("value",38).text("38 - GPIO28")); + $('#node-input-pin').append($("<option></option>").attr("value",40).text("40 - GPIO29")); + } + }); + } + }); +</script> + + +<script type="text/x-red" data-template-name="rpi-gpio out"> + <div class="form-row"> + <label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label> + <select type="text" id="node-input-pin" style="width: 200px;"> + <option value="-">select pin </option> + <option value="3">3 - SDA1 </option> + <option value="5">5 - SCL1 </option> + <option value="7">7 - GPIO7</option> + <option value="8">8 - TxD </option> + <option value="10">10 - RxD </option> + <option value="11">11 - GPIO0</option> + <option value="12">12 - GPIO1</option> + <option value="13">13 - GPIO2</option> + <option value="15">15 - GPIO3</option> + <option value="16">16 - GPIO4</option> + <option value="18">18 - GPIO5</option> + <option value="19">19 - MOSI </option> + <option value="21">21 - MISO </option> + <option value="22">22 - GPIO6</option> + <option value="23">23 - SCLK </option> + <option value="24">24 - CE0 </option> + <option value="26">26 - CE1 </option> + </select> + <span id="pitype"></span> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">Tip: Only Digital I/O is supported - input must be 0 or 1.</div> +</script> + +<script type="text/x-red" data-help-name="rpi-gpio out"> + <p>Raspberry Pi output node. Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false). Requires the gpio command to work.</p> + <p>Will set the selected physical pin high or low depending on the value passed in.</p> + <p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('rpi-gpio out',{ + category: 'advanced-output', + color:"#c6dbef", + defaults: { + name: { value:"" }, + pin: { value:"",required:true,validate:RED.validators.number() }, + }, + inputs:1, + outputs:0, + icon: "rpi.png", + align: "right", + label: function() { + return this.name||"Pin: "+this.pin; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + $.getJSON('rpi-gpio/'+this.id,function(data) { + $('#pitype').text(data.type); + if (data.type === "Model B+") { + $('#node-input-pin').append($("<option></option>").attr("value",27).text("27 - SDA0")); + $('#node-input-pin').append($("<option></option>").attr("value",28).text("28 - SCL0")); + $('#node-input-pin').append($("<option></option>").attr("value",29).text("29 - GPIO21")); + $('#node-input-pin').append($("<option></option>").attr("value",31).text("31 - GPIO22")); + $('#node-input-pin').append($("<option></option>").attr("value",32).text("32 - GPIO26")); + $('#node-input-pin').append($("<option></option>").attr("value",33).text("33 - GPIO23")); + $('#node-input-pin').append($("<option></option>").attr("value",35).text("35 - GPIO24")); + $('#node-input-pin').append($("<option></option>").attr("value",36).text("36 - GPIO27")); + $('#node-input-pin').append($("<option></option>").attr("value",37).text("37 - GPIO25")); + $('#node-input-pin').append($("<option></option>").attr("value",38).text("38 - GPIO28")); + $('#node-input-pin').append($("<option></option>").attr("value",40).text("40 - GPIO29")); + } + }); + } + }); +</script> diff --git a/dgbuilder/core_nodes/hardware/36-rpi-gpio.js b/dgbuilder/core_nodes/hardware/36-rpi-gpio.js new file mode 100644 index 00000000..93cbc4e0 --- /dev/null +++ b/dgbuilder/core_nodes/hardware/36-rpi-gpio.js @@ -0,0 +1,185 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var exec = require('child_process').exec; + var fs = require('fs'); + + var gpioCommand = '/usr/local/bin/gpio'; + + if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi + throw "Info : Ignoring Raspberry Pi specific node."; + } + + if (!fs.existsSync(gpioCommand)) { // gpio command not installed + throw "Info : Can't find Raspberry Pi wiringPi gpio command."; + } + + // Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant) + var pintable = { + // Physical : WiringPi + "11":"0", + "12":"1", + "13":"2", + "15":"3", + "16":"4", + "18":"5", + "22":"6", + "7":"7", + "3":"8", + "5":"9", + "24":"10", + "26":"11", + "19":"12", + "21":"13", + "23":"14", + "8":"15", + "10":"16", + "27":"30", + "28":"31", + "29":"21", + "31":"22", + "32":"26", + "33":"23", + "35":"24", + "36":"27", + "37":"25", + "38":"28", + "40":"29" + } + var tablepin = { + // WiringPi : Physical + "0":"11", + "1":"12", + "2":"13", + "3":"15", + "4":"16", + "5":"18", + "6":"22", + "7":"7", + "8":"3", + "9":"5", + "10":"24", + "11":"26", + "12":"19", + "13":"21", + "14":"23", + "15":"8", + "16":"10", + "30":"27", + "31":"28", + "21":"29", + "22":"31", + "26":"32", + "23":"33", + "24":"35", + "27":"36", + "25":"37", + "28":"38", + "29":"40" + } + + function GPIOInNode(n) { + RED.nodes.createNode(this,n); + this.buttonState = -1; + this.pin = pintable[n.pin]; + this.intype = n.intype; + var node = this; + + if (node.pin !== undefined) { + exec(gpioCommand+" mode "+node.pin+" "+node.intype, function(err,stdout,stderr) { + if (err) { node.error(err); } + else { + node._interval = setInterval( function() { + exec(gpioCommand+" read "+node.pin, function(err,stdout,stderr) { + if (err) { node.error(err); } + else { + if (node.buttonState !== Number(stdout)) { + var previousState = node.buttonState; + node.buttonState = Number(stdout); + if (previousState !== -1) { + var msg = {topic:"pi/"+tablepin[node.pin], payload:node.buttonState}; + node.send(msg); + } + } + } + }); + }, 250); + } + }); + } + else { + node.error("Invalid GPIO pin: "+node.pin); + } + + node.on("close", function() { + clearInterval(node._interval); + }); + } + + function GPIOOutNode(n) { + RED.nodes.createNode(this,n); + this.pin = pintable[n.pin]; + var node = this; + + if (node.pin !== undefined) { + process.nextTick(function() { + exec(gpioCommand+" mode "+node.pin+" out", function(err,stdout,stderr) { + if (err) { node.error(err); } + else { + node.on("input", function(msg) { + if (msg.payload === "true") { msg.payload = true; } + if (msg.payload === "false") { msg.payload = false; } + var out = Number(msg.payload); + if ((out === 0)|(out === 1)) { + exec(gpioCommand+" write "+node.pin+" "+out, function(err,stdout,stderr) { + if (err) { node.error(err); } + }); + } + else { node.warn("Invalid input - not 0 or 1"); } + }); + } + }); + }); + } + else { + node.error("Invalid GPIO pin: "+node.pin); + } + + node.on("close", function() { + exec(gpioCommand+" mode "+node.pin+" in"); + }); + } + + var pitype = { type:"" }; + exec(gpioCommand+" -v | grep Type", function(err,stdout,stderr) { + if (err) { + util.log('[36-rpi-gpio.js] Error: "'+gpioCommand+' -v" command failed for some reason.'); + } + else { + pitype = { type:(stdout.split(","))[0].split(": ")[1], rev:(stdout.split(","))[1].split(": ")[1] }; + } + }); + + RED.nodes.registerType("rpi-gpio in",GPIOInNode); + RED.nodes.registerType("rpi-gpio out",GPIOOutNode); + + RED.httpAdmin.get('/rpi-gpio/:id',function(req,res) { + res.send( JSON.stringify(pitype) ); + }); +} diff --git a/dgbuilder/core_nodes/io/10-mqtt.html b/dgbuilder/core_nodes/io/10-mqtt.html new file mode 100644 index 00000000..2ff5eb29 --- /dev/null +++ b/dgbuilder/core_nodes/io/10-mqtt.html @@ -0,0 +1,157 @@ +<!-- + Copyright 2013,2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="mqtt in"> + <div class="form-row"> + <label for="node-input-broker"><i class="fa fa-globe"></i> Broker</label> + <input type="text" id="node-input-broker"> + </div> + <div class="form-row"> + <label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label> + <input type="text" id="node-input-topic" placeholder="Topic"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="mqtt in"> + <p>MQTT input node. Connects to a broker and subscribes to the specified topic. The topic may contain MQTT wildcards.</p> + <p>Outputs an object called <b>msg</b> containing <b>msg.topic, msg.payload, msg.qos</b> and <b>msg.retain</b>.</p> + <p><b>msg.payload</b> is a String.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('mqtt in',{ + category: 'input', + defaults: { + name: {value:""}, + topic: {value:"",required:true}, + broker: {type:"mqtt-broker", required:true} + }, + color:"#d8bfd8", + inputs:0, + outputs:1, + icon: "bridge.png", + label: function() { + return this.name||this.topic||"mqtt"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> + +<script type="text/x-red" data-template-name="mqtt out"> + <div class="form-row"> + <label for="node-input-broker"><i class="fa fa-globe"></i> Broker</label> + <input type="text" id="node-input-broker"> + </div> + <div class="form-row"> + <label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label> + <input type="text" id="node-input-topic" placeholder="Topic"> + </div> + <div class="form-row"> + <label for="node-input-qos"><i class="fa fa-empire"></i> QoS</label> + <select id="node-input-qos" style="width:125px !important"> + <option value=""></option> + <option value="0">0</option> + <option value="1">1</option> + <option value="2">2</option> + </select> + <i class="fa fa-history"></i> Retain <select id="node-input-retain" style="width:125px !important"> + <option value=""></option> + <option value="false">false</option> + <option value="true">true</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">Tip: Leave topic, qos or retain blank if you want to set them via msg properties.</div> +</script> + +<script type="text/x-red" data-help-name="mqtt out"> + <p>Connects to a MQTT broker and publishes <b>msg.payload</b> either to the <b>msg.topic</b> or to the topic specified in the edit window. The value in the edit window has precedence.</p> + <p>Likewise QoS and/or retain values in the edit panel will overwrite any <b>msg.qos</b> and <b>msg.retain</b> properties. If nothing is set they default to <i>0</i> and <i>false</i> respectively.</p> + <p>If <b>msg.payload</b> contains an object it will be stringified before being sent.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('mqtt out',{ + category: 'output', + defaults: { + name: {value:""}, + topic: {value:""}, + qos: {value:""}, + retain: {value:""}, + broker: {type:"mqtt-broker", required:true} + }, + color:"#d8bfd8", + inputs:1, + outputs:0, + icon: "bridge.png", + align: "right", + label: function() { + return this.name||this.topic||"mqtt"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> + +<script type="text/x-red" data-template-name="mqtt-broker"> + <div class="form-row node-input-broker"> + <label for="node-config-input-broker"><i class="fa fa-globe"></i> Broker</label> + <input class="input-append-left" type="text" id="node-config-input-broker" placeholder="localhost" style="width: 40%;" > + <label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> Port</label> + <input type="text" id="node-config-input-port" placeholder="Port" style="width:45px"> + </div> + <div class="form-row"> + <label for="node-config-input-clientid"><i class="fa fa-tag"></i> Client ID</label> + <input type="text" id="node-config-input-clientid" placeholder="Leave blank for auto generated"> + </div> + <div class="form-row"> + <label for="node-config-input-user"><i class="fa fa-user"></i> Username</label> + <input type="text" id="node-config-input-user"> + </div> + <div class="form-row"> + <label for="node-config-input-password"><i class="fa fa-lock"></i> Password</label> + <input type="password" id="node-config-input-password"> + </div> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('mqtt-broker',{ + category: 'config', + defaults: { + broker: {value:"",required:true}, + port: {value:1883,required:true,validate:RED.validators.number()}, + clientid: { value:"" } + }, + credentials: { + user: {type:"text"}, + password: {type: "password"} + }, + label: function() { + if (this.broker == "") { this.broker = "localhost"; } + return (this.clientid?this.clientid+"@":"")+this.broker+":"+this.port; + } + }); +</script> diff --git a/dgbuilder/core_nodes/io/10-mqtt.js b/dgbuilder/core_nodes/io/10-mqtt.js new file mode 100644 index 00000000..c8bc4901 --- /dev/null +++ b/dgbuilder/core_nodes/io/10-mqtt.js @@ -0,0 +1,119 @@ +/** + * Copyright 2013,2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var connectionPool = require("./lib/mqttConnectionPool"); + + function MQTTBrokerNode(n) { + RED.nodes.createNode(this,n); + this.broker = n.broker; + this.port = n.port; + this.clientid = n.clientid; + if (this.credentials) { + this.username = this.credentials.user; + this.password = this.credentials.password; + } + } + RED.nodes.registerType("mqtt-broker",MQTTBrokerNode,{ + credentials: { + user: {type:"text"}, + password: {type: "password"} + } + }); + + function MQTTInNode(n) { + RED.nodes.createNode(this,n); + this.topic = n.topic; + this.broker = n.broker; + this.brokerConfig = RED.nodes.getNode(this.broker); + if (this.brokerConfig) { + this.status({fill:"red",shape:"ring",text:"disconnected"}); + this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password); + var node = this; + this.client.subscribe(this.topic,2,function(topic,payload,qos,retain) { + var msg = {topic:topic,payload:payload,qos:qos,retain:retain}; + if ((node.brokerConfig.broker == "localhost")||(node.brokerConfig.broker == "127.0.0.1")) { + msg._topic = topic; + } + node.send(msg); + }); + this.client.on("connectionlost",function() { + node.status({fill:"red",shape:"ring",text:"disconnected"}); + }); + this.client.on("connect",function() { + node.status({fill:"green",shape:"dot",text:"connected"}); + }); + this.client.connect(); + } else { + this.error("missing broker configuration"); + } + this.on('close', function() { + if (this.client) { + this.client.disconnect(); + } + }); + } + RED.nodes.registerType("mqtt in",MQTTInNode); + + function MQTTOutNode(n) { + RED.nodes.createNode(this,n); + this.topic = n.topic; + this.qos = n.qos || null; + this.retain = n.retain; + this.broker = n.broker; + this.brokerConfig = RED.nodes.getNode(this.broker); + + if (this.brokerConfig) { + this.status({fill:"red",shape:"ring",text:"disconnected"},true); + this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password); + var node = this; + this.on("input",function(msg) { + if (msg.qos) { + msg.qos = parseInt(msg.qos); + if ((msg.qos !== 0) && (msg.qos !== 1) && (msg.qos !== 2)) { + msg.qos = null; + } + } + msg.qos = Number(node.qos || msg.qos || 0); + msg.retain = node.retain || msg.retain || false; + msg.retain = ((msg.retain === true) || (msg.retain === "true")) || false; + if (node.topic) { + msg.topic = node.topic; + } + if ((msg.hasOwnProperty("topic")) && (typeof msg.topic === "string") && (msg.topic !== "")) { // topic must exist + this.client.publish(msg); // send the message + } + else { node.warn("Invalid topic specified"); } + }); + this.client.on("connectionlost",function() { + node.status({fill:"red",shape:"ring",text:"disconnected"}); + }); + this.client.on("connect",function() { + node.status({fill:"green",shape:"dot",text:"connected"}); + }); + this.client.connect(); + } else { + this.error("missing broker configuration"); + } + this.on('close', function() { + if (this.client) { + this.client.disconnect(); + } + }); + } + RED.nodes.registerType("mqtt out",MQTTOutNode); +} diff --git a/dgbuilder/core_nodes/io/21-httpin.html b/dgbuilder/core_nodes/io/21-httpin.html new file mode 100644 index 00000000..059b8596 --- /dev/null +++ b/dgbuilder/core_nodes/io/21-httpin.html @@ -0,0 +1,254 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="http in"> + <div class="form-row"> + <label for="node-input-method"><i class="fa fa-tasks"></i> Method</label> + <select type="text" id="node-input-method" style="width:72%;"> + <option value="get">GET</option> + <option value="post">POST</option> + <option value="put">PUT</option> + <option value="delete">DELETE</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-url"><i class="fa fa-globe"></i> url</label> + <input type="text" id="node-input-url" placeholder="/url"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div id="node-input-tip" class="form-tips">The url will be relative to <code><span id="node-input-path"></span></code>.</div> +</script> + +<script type="text/x-red" data-help-name="http in"> + <p>Provides an input node for http requests, allowing the creation of simple web services.</p> + <p>The resulting message has the following properties: + <ul> + <li>msg.req : <a href="http://expressjs.com/api.html#req">http request</a></li> + <li>msg.res : <a href="http://expressjs.com/api.html#res">http response</a></li> + </ul> + </p> + <p>For POST/PUT requests, the body is available under <code>msg.req.body</code>. This + uses the <a href="http://expressjs.com/api.html#bodyParser">Express bodyParser middleware</a> to parse the content to a JSON object. + </p> + <p> + By default, this expects the body of the request to be url encoded: + <pre>foo=bar&this=that</pre> + </p> + <p> + To send JSON encoded data to the node, the content-type header of the request must be set to + <code>application/json</code>. + </p> + <p> + <b>Note: </b>This node does not send any response to the http request. This should be done with + a subsequent HTTP Response node, or Function node. + In the case of a Function node, the <a href="http://expressjs.com/api.html#res">Express response documentation</a> + describes how this should be done. For example: + <pre>msg.res.send(200, 'Thanks for the request ');<br/>return msg;</pre> + </p> + +</script> + +<script type="text/x-red" data-template-name="http response"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">The messages sent to this node <b>must</b> originate from an <i>http input</i> node</div> +</script> + +<script type="text/x-red" data-help-name="http response"> + <p>Sends responses back to http requests received from an HTTP Input node.</p> + <p>The response can be customised using the following message properties:</p> + <ul> + <li><code>payload</code> is sent as the body of the response</li> + <li><code>statusCode</code>, if set, is used as the response status code (default: 200)</li> + <li><code>headers</code>, if set, should be an object containing field/value + pairs to be added as response headers.</li> + </ul> +</script> + +<script type="text/x-red" data-template-name="http request"> + <div class="form-row"> + <label for="node-input-method"><i class="fa fa-tasks"></i> Method</label> + <select type="text" id="node-input-method" style="width:72%;"> + <option value="GET">GET</option> + <option value="POST">POST</option> + <option value="PUT">PUT</option> + <option value="DELETE">DELETE</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-url"><i class="fa fa-globe"></i> URL</label> + <input type="text" id="node-input-url" placeholder="http://"> + </div> + <div class="form-row"> + <label> </label> + <input type="checkbox" id="node-input-useAuth" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-useAuth" style="width: 70%;">Use basic authentication?</label> + </div> + <div class="form-row node-input-useAuth-row"> + <label for="node-input-user"><i class="fa fa-user"></i> Username</label> + <input type="text" id="node-input-user"> + </div> + <div class="form-row node-input-useAuth-row"> + <label for="node-input-password"><i class="fa fa-lock"></i> Password</label> + <input type="password" id="node-input-password"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="http request"> + <p>Provides a node for making http requests.</p> + <p>The URL and HTTP method can be configured in the node, but also + overridden by the incoming message: + <ul> + <li><code>url</code>, if set, is used as the url of the request. Must start with http: or https:</li> + <li><code>method</code>, if set, is used as the HTTP method of the request. + Must be one of <code>GET</code>, <code>PUT</code>, <code>POST</code> or <code>DELETE</code> (default: GET)</li> + <li><code>headers</code>, if set, should be an object containing field/value + pairs to be added as request headers</li> + <li><code>payload</code> is sent as the body of the request</li> + </ul> + <p>When configured within the node, the URL property can contain <a href="http://mustache.github.io/mustache.5.html" target="_new">mustache-style</a> tags. These allow the + url to be constructed using values of the incoming message. For example, if the url is set to + <code>example.com/{{topic}}</code>, it will have the value of <code>msg.topic</code> automatically inserted.</p> + <p> + The output message contains the following properties: + <ul> + <li><code>payload</code> is the body of the response</li> + <li><code>statusCode</code> is the status code of the response, or the error code if the request could not be completed</li> + <li><code>headers</code> is an object containing the response headers</li> + </ul> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('http in',{ + category: 'input', + color:"rgb(231, 231, 174)", + defaults: { + name: {value:""}, + url: {value:"",required:true}, + method: {value:"get",required:true} + }, + inputs:0, + outputs:1, + icon: "white-globe.png", + label: function() { + if (this.name) { + return this.name; + } else if (this.url) { + var root = RED.settings.httpNodeRoot; + if (root.slice(-1) != "/") { + root = root+"/"; + } + if (this.url.charAt(0) == "/") { + root += this.url.slice(1); + } else { + root += this.url; + } + return "["+this.method+"] "+root; + } else { + return "http"; + } + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + var root = RED.settings.httpNodeRoot; + if (root.slice(-1) == "/") { + root = root.slice(0,-1); + } + if (root == "") { + $("#node-input-tip").hide(); + } else { + $("#node-input-path").html(root); + $("#node-input-tip").show(); + } + //document.getElementById("node-config-wsdocpath").innerHTML= + } + + }); + + RED.nodes.registerType('http response',{ + category: 'output', + color:"rgb(231, 231, 174)", + defaults: { + name: {value:""} + }, + inputs:1, + outputs:0, + align: "right", + icon: "white-globe.png", + label: function() { + return this.name||"http"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); + + RED.nodes.registerType('http request',{ + category: 'function', + color:"rgb(231, 231, 174)", + defaults: { + name: {value:""}, + method:{value:"GET"}, + url:{value:""}, + //user -> credentials + //pass -> credentials + }, + credentials: { + user: {type:"text"}, + password: {type: "password"} + }, + inputs:1, + outputs:1, + align: "right", + icon: "white-globe.png", + label: function() { + return this.name||"http request"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + if (this.credentials.user || this.credentials.has_password) { + $('#node-input-useAuth').prop('checked', true); + $(".node-input-useAuth-row").show(); + } else { + $('#node-input-useAuth').prop('checked', false); + $(".node-input-useAuth-row").hide(); + } + + $("#node-input-useAuth").change(function() { + if ($(this).is(":checked")) { + $(".node-input-useAuth-row").show(); + } else { + $(".node-input-useAuth-row").hide(); + $('#node-input-user').val(''); + $('#node-input-password').val(''); + } + }); + }, + }); +</script> diff --git a/dgbuilder/core_nodes/io/21-httpin.js b/dgbuilder/core_nodes/io/21-httpin.js new file mode 100644 index 00000000..877ccc09 --- /dev/null +++ b/dgbuilder/core_nodes/io/21-httpin.js @@ -0,0 +1,241 @@ +/** + * Copyright 2013,2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var http = require("follow-redirects").http; + var https = require("follow-redirects").https; + var urllib = require("url"); + var express = require("express"); + var getBody = require('raw-body'); + var mustache = require("mustache"); + var querystring = require("querystring"); + + var cors = require('cors'); + var jsonParser = express.json(); + var urlencParser = express.urlencoded(); + + function rawBodyParser(req, res, next) { + if (req._body) { return next(); } + req.body = ""; + req._body = true; + getBody(req, { + limit: '1mb', + length: req.headers['content-length'], + encoding: 'utf8' + }, function (err, buf) { + if (err) { return next(err); } + req.body = buf; + next(); + }); + } + + + function HTTPIn(n) { + RED.nodes.createNode(this,n); + if (RED.settings.httpNodeRoot !== false) { + + this.url = n.url; + this.method = n.method; + + var node = this; + + this.errorHandler = function(err,req,res,next) { + node.warn(err); + res.send(500); + }; + + this.callback = function(req,res) { + if (node.method == "post") { + node.send({req:req,res:res,payload:req.body}); + } else if (node.method == "get") { + node.send({req:req,res:res,payload:req.query}); + } else { + node.send({req:req,res:res}); + } + } + + var corsHandler = function(req,res,next) { next(); } + + if (RED.settings.httpNodeCors) { + corsHandler = cors(RED.settings.httpNodeCors); + RED.httpNode.options(this.url,corsHandler); + } + + if (this.method == "get") { + RED.httpNode.get(this.url,corsHandler,this.callback,this.errorHandler); + } else if (this.method == "post") { + RED.httpNode.post(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); + } else if (this.method == "put") { + RED.httpNode.put(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler); + } else if (this.method == "delete") { + RED.httpNode.delete(this.url,corsHandler,this.callback,this.errorHandler); + } + + this.on("close",function() { + var routes = RED.httpNode.routes[this.method]; + for (var i = 0; i<routes.length; i++) { + if (routes[i].path == this.url) { + routes.splice(i,1); + //break; + } + } + if (RED.settings.httpNodeCors) { + var route = RED.httpNode.route['options']; + for (var j = 0; j<route.length; j++) { + if (route[j].path == this.url) { + route.splice(j,1); + //break; + } + } + } + }); + } else { + this.warn("Cannot create http-in node when httpNodeRoot set to false"); + } + } + RED.nodes.registerType("http in",HTTPIn); + + + function HTTPOut(n) { + RED.nodes.createNode(this,n); + var node = this; + this.on("input",function(msg) { + if (msg.res) { + if (msg.headers) { + msg.res.set(msg.headers); + } + var statusCode = msg.statusCode || 200; + if (typeof msg.payload == "object" && !Buffer.isBuffer(msg.payload)) { + msg.res.jsonp(statusCode,msg.payload); + } else { + if (msg.res.get('content-length') == null) { + var len; + if (msg.payload == null) { + len = 0; + } else if (typeof msg.payload == "number") { + len = Buffer.byteLength(""+msg.payload); + } else { + len = Buffer.byteLength(msg.payload); + } + msg.res.set('content-length', len); + } + msg.res.send(statusCode,msg.payload); + } + } else { + node.warn("No response object"); + } + }); + } + RED.nodes.registerType("http response",HTTPOut); + + function HTTPRequest(n) { + RED.nodes.createNode(this,n); + var nodeUrl = n.url; + var isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1; + var nodeMethod = n.method || "GET"; + var node = this; + this.on("input",function(msg) { + node.status({fill:"blue",shape:"dot",text:"requesting"}); + var url; + if (msg.url) { + url = msg.url; + } else if (isTemplatedUrl) { + url = mustache.render(nodeUrl,msg); + } else { + url = nodeUrl; + } + // url must start http:// or https:// so assume http:// if not set + if (!((url.indexOf("http://")===0) || (url.indexOf("https://")===0))) { + url = "http://"+url; + } + + var method = (msg.method||nodeMethod).toUpperCase(); + //node.log(method+" : "+url); + var opts = urllib.parse(url); + opts.method = method; + opts.headers = {}; + if (msg.headers) { + for (var v in msg.headers) { + if (msg.headers.hasOwnProperty(v)) { + var name = v.toLowerCase(); + if (name !== "content-type" && name !== "content-length") { + // only normalise the known headers used later in this + // function. Otherwise leave them alone. + name = v; + } + opts.headers[name] = msg.headers[v]; + } + } + } + if (this.credentials && this.credentials.user) { + opts.auth = this.credentials.user+":"+(this.credentials.password||""); + } + var payload = null; + + if (msg.payload && (method == "POST" || method == "PUT") ) { + if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) { + payload = msg.payload; + } else if (typeof msg.payload == "number") { + payload = msg.payload+""; + } else { + if (opts.headers['content-type'] == 'application/x-www-form-urlencoded') { + payload = querystring.stringify(msg.payload); + } else { + payload = JSON.stringify(msg.payload); + if (opts.headers['content-type'] == null) { + opts.headers['content-type'] = "application/json"; + } + } + } + if (opts.headers['content-length'] == null) { + opts.headers['content-length'] = Buffer.byteLength(payload); + } + } + + var req = ((/^https/.test(url))?https:http).request(opts,function(res) { + res.setEncoding('utf8'); + msg.statusCode = res.statusCode; + msg.headers = res.headers; + msg.payload = ""; + res.on('data',function(chunk) { + msg.payload += chunk; + }); + res.on('end',function() { + node.send(msg); + node.status({}); + }); + }); + req.on('error',function(err) { + msg.payload = err.toString() + " : " + url; + msg.statusCode = err.code; + node.send(msg); + node.status({fill:"red",shape:"ring",text:err.code}); + }); + if (payload) { + req.write(payload); + } + req.end(); + }); + } + + RED.nodes.registerType("http request",HTTPRequest,{ + credentials: { + user: {type:"text"}, + password: {type: "password"} + } + }); +} diff --git a/dgbuilder/core_nodes/io/22-websocket.html b/dgbuilder/core_nodes/io/22-websocket.html new file mode 100644 index 00000000..ff6ed742 --- /dev/null +++ b/dgbuilder/core_nodes/io/22-websocket.html @@ -0,0 +1,163 @@ +<!--
+ Copyright 2013 IBM Corp.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!-- WebSocket Input Node -->
+<script type="text/x-red" data-template-name="websocket in">
+ <div class="form-row">
+ <label for="node-input-server"><i class="fa fa-bookmark"></i> Path</label>
+ <input type="text" id="node-input-server">
+ </div>
+ <div class="form-row">
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+ <input type="text" id="node-input-name" placeholder="Name">
+ </div>
+</script>
+
+<script type="text/x-red" data-help-name="websocket in">
+ <p>WebSocket input node.</p>
+ <p>By default, the data received from the WebSocket will be in <b>msg.payload</b>.
+ The listener can be configured to expect a properly formed JSON string, in which
+ case it will parse the JSON and send on the resulting object as the entire message.</p>
+</script>
+
+<script type="text/javascript">
+ RED.nodes.registerType('websocket in',{
+ category: 'input',
+ defaults: {
+ name: {value:""},
+ server: {type:"websocket-listener"}
+ },
+ color:"rgb(215, 215, 160)",
+ inputs:0,
+ outputs:1,
+ icon: "white-globe.png",
+ label: function() {
+ var wsNode = RED.nodes.node(this.server);
+ return this.name||(wsNode?"[ws] "+wsNode.label():"websocket");
+ },
+ labelStyle: function() {
+ return this.name?"node_label_italic":"";
+ }
+ });
+</script>
+
+<!-- WebSocket out Node -->
+<script type="text/x-red" data-template-name="websocket out">
+ <div class="form-row">
+ <label for="node-input-server"><i class="fa fa-bookmark"></i> Path</label>
+ <input type="text" id="node-input-server">
+ </div>
+ <div class="form-row">
+ <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+ <input type="text" id="node-input-name" placeholder="Name">
+ </div>
+</script>
+
+<script type="text/x-red" data-help-name="websocket out">
+ <p>WebSocket out node.</p>
+ <p>By default, <b>msg.payload</b> will be sent over the WebSocket. The listener
+ can be configured to encode the entire message object as a JSON string and send that
+ over the WebSocket.</p>
+
+ <p>If the message arriving at this node started at a WebSocket In node, the message
+ will be sent back to the client that triggered the flow. Otherwise, the message
+ will be broadcast to all connected clients.</p>
+ <p>If you want to broadcast a message that started at a WebSocket In node, you
+ should delete the <b>msg._session</b> property within the flow</p>.
+</script>
+
+<script type="text/javascript">
+ RED.nodes.registerType('websocket out',{
+ category: 'output',
+ defaults: {
+ name: {value:""},
+ server: {type:"websocket-listener", required:true}
+ },
+ color:"rgb(215, 215, 160)",
+ inputs:1,
+ outputs:0,
+ icon: "white-globe.png",
+ align: "right",
+ label: function() {
+ var wsNode = RED.nodes.node(this.server);
+ return this.name||(wsNode?"[ws] "+wsNode.label():"websocket");
+ },
+ labelStyle: function() {
+ return this.name?"node_label_italic":"";
+ }
+ });
+</script>
+
+<!-- WebSocket Server configuration node -->
+<script type="text/x-red" data-template-name="websocket-listener">
+ <div class="form-row">
+ <label for="node-config-input-path"><i class="fa fa-bookmark"></i> Path</label>
+ <input type="text" id="node-config-input-path" placeholder="/ws/example">
+ </div>
+ <div class="form-row">
+ <label for="node-config-input-wholemsg"> </label>
+ <select type="text" id="node-config-input-wholemsg" style="width: 70%;">
+ <option value="false">Send/Receive payload</option>
+ <option value="true">Send/Receive entire message</option>
+ </select>
+ </div>
+ <div class="form-tips">
+ Be default, <code>payload</code> will contain the data to be sent over, or received from a websocket.
+ The listener can be configured to send or receive the entire message object as a JSON formatted string.
+ <p id="node-config-ws-tip">This path will be relative to <code><span id="node-config-ws-path"></span></code>.</p>
+ </div>
+</script>
+
+<script type="text/x-red" data-help-name="websocket-listener">
+ <p>This configuration node creates a WebSocket Server using the specified path</p>
+</script>
+
+<script type="text/javascript">
+ RED.nodes.registerType('websocket-listener',{
+ category: 'config',
+ defaults: {
+ path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/) },
+ wholemsg: {value:"false"}
+ },
+ inputs:0,
+ outputs:0,
+ label: function() {
+ var root = RED.settings.httpNodeRoot;
+ if (root.slice(-1) != "/") {
+ root = root+"/";
+ }
+ if (this.path.charAt(0) == "/") {
+ root += this.path.slice(1);
+ } else {
+ root += this.path;
+ }
+ return root;
+ },
+ oneditprepare: function() {
+ var root = RED.settings.httpNodeRoot;
+ if (root.slice(-1) == "/") {
+ root = root.slice(0,-1);
+ }
+ if (root == "") {
+ $("#node-config-ws-tip").hide();
+ } else {
+ $("#node-config-ws-path").html(root);
+ $("#node-config-ws-tip").show();
+ }
+ //document.getElementById("node-config-wsdocpath").innerHTML=
+ }
+ });
+</script>
diff --git a/dgbuilder/core_nodes/io/22-websocket.js b/dgbuilder/core_nodes/io/22-websocket.js new file mode 100644 index 00000000..72eda502 --- /dev/null +++ b/dgbuilder/core_nodes/io/22-websocket.js @@ -0,0 +1,185 @@ +/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+ "use strict";
+ var ws = require("ws"),
+ inspect = require("sys").inspect;
+
+ // A node red node that sets up a local websocket server
+ function WebSocketListenerNode(n) {
+ // Create a RED node
+ RED.nodes.createNode(this,n);
+
+ var node = this;
+
+ // Store local copies of the node configuration (as defined in the .html)
+ node.path = n.path;
+ node.wholemsg = (n.wholemsg === "true");
+
+ node._inputNodes = []; // collection of nodes that want to receive events
+
+ var path = RED.settings.httpNodeRoot || "/";
+ path = path + (path.slice(-1) == "/" ? "":"/") + (node.path.charAt(0) == "/" ? node.path.substring(1) : node.path);
+
+ // Workaround https://github.com/einaros/ws/pull/253
+ // Listen for 'newListener' events from RED.server
+ node._serverListeners = {};
+
+ var storeListener = function(/*String*/event,/*function*/listener){
+ if(event == "error" || event == "upgrade" || event == "listening"){
+ node._serverListeners[event] = listener;
+ }
+ }
+
+ node._clients = {};
+
+ RED.server.addListener('newListener',storeListener);
+
+ // Create a WebSocket Server
+ node.server = new ws.Server({server:RED.server,path:path});
+
+ // Workaround https://github.com/einaros/ws/pull/253
+ // Stop listening for new listener events
+ RED.server.removeListener('newListener',storeListener);
+
+ node.server.on('connection', function(socket){
+ var id = (1+Math.random()*4294967295).toString(16);
+ node._clients[id] = socket;
+ socket.on('close',function() {
+ delete node._clients[id];
+ });
+ socket.on('message',function(data,flags){
+ node.handleEvent(id,socket,'message',data,flags);
+ });
+ socket.on('error', function(err) {
+ node.warn("An error occured on the ws connection: "+inspect(err));
+ });
+ });
+
+ node.on("close", function() {
+ // Workaround https://github.com/einaros/ws/pull/253
+ // Remove listeners from RED.server
+ var listener = null;
+ for(var event in node._serverListeners) {
+ if (node._serverListeners.hasOwnProperty(event)) {
+ listener = node._serverListeners[event];
+ if(typeof listener === "function"){
+ RED.server.removeListener(event,listener);
+ }
+ }
+ }
+ node._serverListeners = {};
+ node.server.close();
+ node._inputNodes = [];
+ });
+ }
+ RED.nodes.registerType("websocket-listener",WebSocketListenerNode);
+
+ WebSocketListenerNode.prototype.registerInputNode = function(/*Node*/handler){
+ this._inputNodes.push(handler);
+ }
+
+ WebSocketListenerNode.prototype.handleEvent = function(id,/*socket*/socket,/*String*/event,/*Object*/data,/*Object*/flags){
+ var msg;
+ if (this.wholemsg) {
+ try {
+ msg = JSON.parse(data);
+ }
+ catch(err) {
+ msg = { payload:data };
+ }
+ } else {
+ msg = {
+ payload:data
+ };
+ }
+ msg._session = {type:"websocket",id:id};
+
+ for (var i = 0; i < this._inputNodes.length; i++) {
+ this._inputNodes[i].send(msg);
+ }
+ }
+
+ WebSocketListenerNode.prototype.broadcast = function(data){
+ try {
+ for (var i = 0; i < this.server.clients.length; i++) {
+ this.server.clients[i].send(data);
+ }
+ }
+ catch(e) { // swallow any errors
+ this.warn("ws:"+i+" : "+e);
+ }
+ }
+
+ WebSocketListenerNode.prototype.send = function(id,data) {
+ var session = this._clients[id];
+ if (session) {
+ try {
+ session.send(data);
+ }
+ catch(e) { // swallow any errors
+ }
+ }
+ }
+
+ function WebSocketInNode(n) {
+ RED.nodes.createNode(this,n);
+ this.server = n.server;
+ var node = this;
+ this.serverConfig = RED.nodes.getNode(this.server);
+ if (this.serverConfig) {
+ this.serverConfig.registerInputNode(this);
+ } else {
+ this.error("Missing server configuration");
+ }
+ }
+ RED.nodes.registerType("websocket in",WebSocketInNode);
+
+ function WebSocketOutNode(n) {
+ RED.nodes.createNode(this,n);
+ var node = this;
+ this.server = n.server;
+ this.serverConfig = RED.nodes.getNode(this.server);
+ if (!this.serverConfig) {
+ this.error("Missing server configuration");
+ }
+ this.on("input", function(msg) {
+ var payload;
+ if (this.serverConfig.wholemsg) {
+ delete msg._session;
+ payload = JSON.stringify(msg);
+ } else {
+ if (!Buffer.isBuffer(msg.payload)) { // if it's not a buffer make sure it's a string.
+ payload = RED.util.ensureString(msg.payload);
+ }
+ else {
+ payload = msg.payload;
+ }
+ }
+ if (msg._session && msg._session.type == "websocket") {
+ node.serverConfig.send(msg._session.id,payload);
+ } else {
+ node.serverConfig.broadcast(payload,function(error){
+ if (!!error) {
+ node.warn("An error occurred while sending:" + inspect(error));
+ }
+ });
+ }
+ });
+ }
+ RED.nodes.registerType("websocket out",WebSocketOutNode);
+}
diff --git a/dgbuilder/core_nodes/io/23-watch.html b/dgbuilder/core_nodes/io/23-watch.html new file mode 100644 index 00000000..8bf22be5 --- /dev/null +++ b/dgbuilder/core_nodes/io/23-watch.html @@ -0,0 +1,57 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="watch"> + <div class="form-row node-input-filename"> + <label for="node-input-files"><i class="fa fa-file"></i> File(s)</label> + <input type="text" id="node-input-files" placeholder="File(s) or Directory"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div id="node-input-tip" class="form-tips">On Windows you must use double slashes \\ in any directory names.</div> +</script> + +<script type="text/x-red" data-help-name="watch"> + <p>Watches a directory or file for any changes.</p> + <p>You can enter a list of comma separated directories or files if you like. You will need to put " around any that have spaces in.</p> + <p>On Windows you must use double slashes \\ in any directory names.</p> + <p>The full filename of the file that actually changed is put into <b>msg.payload</b>, while a stringified version of the watched criteria is returned in <b>msg.topic</b>.</p> + <p><b>msg.file</b> contains just the short filename of the file that changed.</p> + <p>Of course in Linux, <i>everything</i> could be a file and thus watched...</p> + <p><b>Note: </b>The directory or file must exist in order to be watched. If the file or directory gets deleted it may no longer be monitored even if it gets re-created.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('watch',{ + category: 'advanced-input', + defaults: { + name: {value:""}, + files: {value:"",required:true} + }, + color:"BurlyWood", + inputs:0, + outputs:1, + icon: "watch.png", + label: function() { + return this.name||this.files; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/io/23-watch.js b/dgbuilder/core_nodes/io/23-watch.js new file mode 100644 index 00000000..8a17f5ac --- /dev/null +++ b/dgbuilder/core_nodes/io/23-watch.js @@ -0,0 +1,51 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var Notify = require("fs.notify"); + var fs = require("fs"); + var sep = require("path").sep; + + function WatchNode(n) { + RED.nodes.createNode(this,n); + + this.files = n.files.split(","); + for (var f =0; f < this.files.length; f++) { + this.files[f] = this.files[f].trim(); + } + this.p = (this.files.length == 1) ? this.files[0] : JSON.stringify(this.files); + var node = this; + + var notifications = new Notify(node.files); + notifications.on('change', function (file, event, path) { + try { + if (fs.statSync(path).isDirectory()) { path = path + sep + file; } + } catch(e) { } + var msg = { payload: path, topic: node.p, file: file }; + node.send(msg); + }); + + notifications.on('error', function (error, path) { + node.warn(error); + }); + + this.close = function() { + notifications.close(); + } + } + RED.nodes.registerType("watch",WatchNode); +} diff --git a/dgbuilder/core_nodes/io/25-serial.html b/dgbuilder/core_nodes/io/25-serial.html new file mode 100644 index 00000000..225e4dc3 --- /dev/null +++ b/dgbuilder/core_nodes/io/25-serial.html @@ -0,0 +1,265 @@ +<!-- + Copyright 2013,2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="serial in"> + <div class="form-row node-input-serial"> + <label for="node-input-serial"><i class="fa fa-random"></i> Serial Port</label> + <input type="text" id="node-input-serial"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="serial in"> + <p>Reads data from a local serial port.</p> + <p>Can either <ul><li>wait for a "split" character (default \n). Also accepts hex notation (0x0a).</li> + <li>Wait for a timeout in milliseconds for the first character received</li> + <li>Wait to fill a fixed sized buffer</li></ul></p> + <p>It then outputs <b>msg.payload</b> as either a UTF8 ascii string or a binary Buffer object.</p> + <p>If no split character is specified, or a timeout or buffer size of 0, then a stream of single characters is sent - again either as ascii chars or size 1 binary buffers.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('serial in',{ + category: 'input', + defaults: { + name: {name:""}, + serial: {type:"serial-port",required:true} + }, + color:"BurlyWood", + inputs:0, + outputs:1, + icon: "serial.png", + label: function() { + var serialNode = RED.nodes.node(this.serial); + return this.name||(serialNode?serialNode.label().split(":")[0]:"serial"); + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> + +<script type="text/x-red" data-template-name="serial out"> + <div class="form-row node-input-serial"> + <label for="node-input-serial"><i class="fa fa-random"></i> Serial Port</label> + <input type="text" id="node-input-serial"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="serial out"> + <p>Provides a connection to an outbound serial port.</p> + <p>Only the <b>msg.payload</b> is sent.</p> + <p>Optionally the new line character used to split the input can be appended to every message sent out to the serial port.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('serial out',{ + category: 'output', + defaults: { + name: {name:""}, + serial: {type:"serial-port",required:true} + }, + color:"BurlyWood", + inputs:1, + outputs:0, + icon: "serial.png", + align: "right", + label: function() { + var serialNode = RED.nodes.node(this.serial); + return this.name||(serialNode?serialNode.label().split(":")[0]:"serial"); + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> + + +<script type="text/x-red" data-template-name="serial-port"> + <div class="form-row"> + <label for="node-config-input-serialport"><i class="fa fa-random"></i> Serial Port</label> + <input type="text" id="node-config-input-serialport" style="width:60%;" placeholder="/dev/ttyUSB0"/> + <a id="node-config-lookup-serial" class="btn"><i id="node-config-lookup-serial-icon" class="fa fa-search"></i></a> + </div> + <div class="form-row"> + <table><tr> + <td width = "102px"><i class="fa fa-wrench"></i> Settings</td> + <td width = "100px">Baud Rate</td> + <td width = "80px">Data Bits</td> + <td width = "80px">Parity</td> + <td width = "80px">Stop Bits</td> + </tr><tr><td> </td> + <td> + <select type="text" id="node-config-input-serialbaud" style="width: 100px;"> + <option value="115200">115200</option> + <option value="57600">57600</option> + <option value="38400">38400</option> + <option value="19200">19200</option> + <option value="9600">9600</option> + <option value="4800">4800</option> + <option value="2400">2400</option> + <option value="1800">1800</option> + <option value="1200">1200</option> + <option value="600">600</option> + <option value="300">300</option> + <option value="200">200</option> + <option value="150">150</option> + <option value="134">134</option> + <option value="110">110</option> + <option value="75">75</option> + <option value="50">50</option> + </select> + </td><td> + <select type="text" id="node-config-input-databits" style="width: 80px;"> + <option value="8">8</option> + <option value="7">7</option> + <option value="6">6</option> + <option value="5">5</option> + </select> + </td><td> + <select type="text" id="node-config-input-parity" style="width: 80px;"> + <option value="none">None</option> + <option value="even">Even</option> + <option value="mark">Mark</option> + <option value="odd">Odd</option> + <option value="space">Space</option> + </select> + </td><td> + <select type="text" id="node-config-input-stopbits" style="width: 80px;"> + <option value="2">2</option> + <option value="1">1</option> + </select> + </td> + </tr></table><br/> + + <div class="form-row"> + <label for="node-config-input-out"><i class="fa fa-cut"></i> Split input</label> + <select type="text" id="node-config-input-out" style="width:52%;"> + <option value="char">when character received is</option> + <option value="time">after a fixed timeout of</option> + <option value="count">a fixed number of characters</option> + </select> + <input type="text" id="node-config-input-newline" style="width:50px;"> + <span id="node-units"></span> + </div> + + <div class="form-row"> + <label for="node-config-input-bin"><i class="fa fa-sign-in"></i> and deliver</label> + <select type="text" id="node-config-input-bin" style="width: 77%;"> + <option value="false">ascii strings</option> + <option value="bin">binary buffers</option> + </select> + </div> + <br/> + <div class="form-row" id="node-config-addchar"> + <label for="node-config-input-addchar"><i class="fa fa-sign-out"></i> On output</label> + <select type="text" id="node-config-input-addchar" style="width: 77%;"> + <option value="false">don't add 'split' character to output messages</option> + <option value="true">add 'split' character to output messages</option> + </select> + </div> + <div class="form-tips" id="tip-split">Tip: the "Split on" character is used to split the input into separate messages. It can also be added to every message sent out to the serial port.</div> + <div class="form-tips" id="tip-bin" hidden>Tip: In timeout mode timeout starts from arrival of first character.</div> + <script> + var previous = null; + $("#node-config-input-out").on('focus', function () { previous = this.value; }).change(function() { + if (previous == null) { previous = $("#node-config-input-out").val(); } + if ($("#node-config-input-out").val() == "char") { + if (previous != "char") { $("#node-config-input-newline").val("\\n"); } + $("#node-units").text(""); + $("#node-config-addchar").show(); + $("#tip-split").show(); + $("#tip-bin").hide(); + } + else if ($("#node-config-input-out").val() == "time") { + if (previous != "time") { $("#node-config-input-newline").val("0"); } + $("#node-units").text("ms"); + $("#node-config-addchar").hide(); + $("#node-config-input-addchar").val("false"); + $("#tip-split").hide(); + $("#tip-bin").show(); + } + else { + if (previous != "count") { $("#node-config-input-newline").val("12"); } + $("#node-units").text("chars"); + $("#node-config-addchar").hide(); + $("#node-config-input-addchar").val("false"); + $("#tip-split").hide(); + $("#tip-bin").hide(); + } + }); + + </script> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('serial-port',{ + category: 'config', + defaults: { + //name: {value:""}, + serialport: {value:"",required:true}, + serialbaud: {value:57600,required:true}, + databits: {value:8,required:true}, + parity: {value:"none",required:true}, + stopbits: {value:1,required:true}, + newline: {value:"\\n"}, + bin: {value:""}, + out: {value:""}, + addchar: {value:false} + }, + label: function() { + this.serialbaud = this.serialbaud || 57600; + this.databits = this.databits || 8; + this.parity = this.parity || 'none'; + this.stopbits = this.stopbits || 1; + return this.serialport+":"+this.serialbaud+"-"+this.databits+this.parity.charAt(0).toUpperCase()+this.stopbits; + }, + oneditprepare: function() { + try { + $("#node-config-input-serialport").autocomplete( "destroy" ); + } catch(err) { + } + $("#node-config-lookup-serial").click(function() { + //$("#node-config-lookup-serial-icon").removeClass('fa fa-search'); + //$("#node-config-lookup-serial-icon").addClass('fa fa-spinner'); + $("#node-config-lookup-serial").addClass('disabled'); + $.getJSON('serialports',function(data) { + //$("#node-config-lookup-serial-icon").addClass('fa fa-search'); + //$("#node-config-lookup-serial-icon").removeClass('fa fa-spinner'); + $("#node-config-lookup-serial").removeClass('disabled'); + var ports = []; + $.each(data, function(i, port){ + ports.push(port.comName); + }); + $("#node-config-input-serialport").autocomplete({ + source:ports, + minLength:0, + close: function( event, ui ) { + $("#node-config-input-serialport").autocomplete( "destroy" ); + } + }).autocomplete("search",""); + }); + }); + } + }); +</script> diff --git a/dgbuilder/core_nodes/io/25-serial.js b/dgbuilder/core_nodes/io/25-serial.js new file mode 100644 index 00000000..96e4aca6 --- /dev/null +++ b/dgbuilder/core_nodes/io/25-serial.js @@ -0,0 +1,310 @@ +/** +* Copyright 2013,2014 IBM Corp. +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +**/ + +module.exports = function(RED) { + "use strict"; + var settings = RED.settings; + var events = require("events"); + var util = require("util"); + var serialp = require("serialport"); + var bufMaxSize = 32768; // Max serial buffer size, for inputs... + + // TODO: 'serialPool' should be encapsulated in SerialPortNode + + function SerialPortNode(n) { + RED.nodes.createNode(this,n); + this.serialport = n.serialport; + this.newline = n.newline; + this.addchar = n.addchar || "false"; + this.serialbaud = parseInt(n.serialbaud) || 57600; + this.databits = parseInt(n.databits) || 8; + this.parity = n.parity || "none"; + this.stopbits = parseInt(n.stopbits) || 1; + this.bin = n.bin || "false"; + this.out = n.out || "char"; + } + RED.nodes.registerType("serial-port",SerialPortNode); + + function SerialOutNode(n) { + RED.nodes.createNode(this,n); + this.serial = n.serial; + this.serialConfig = RED.nodes.getNode(this.serial); + + if (this.serialConfig) { + var node = this; + node.port = serialPool.get(this.serialConfig.serialport, + this.serialConfig.serialbaud, + this.serialConfig.databits, + this.serialConfig.parity, + this.serialConfig.stopbits, + this.serialConfig.newline); + node.addCh = ""; + if (node.serialConfig.addchar == "true") { + node.addCh = this.serialConfig.newline.replace("\\n","\n").replace("\\r","\r").replace("\\t","\t").replace("\\e","\e").replace("\\f","\f").replace("\\0","\0"); + } + node.on("input",function(msg) { + var payload = msg.payload; + if (!Buffer.isBuffer(payload)) { + if (typeof payload === "object") { + payload = JSON.stringify(payload); + } else { + payload = payload.toString(); + } + payload += node.addCh; + } else if (node.addCh !== "") { + payload = Buffer.concat([payload,new Buffer(node.addCh)]); + } + node.port.write(payload,function(err,res) { + if (err) { + node.error(err); + } + }); + }); + node.port.on('ready', function() { + node.status({fill:"green",shape:"dot",text:"connected"}); + }); + node.port.on('closed', function() { + node.status({fill:"red",shape:"ring",text:"not connected"}); + }); + } else { + this.error("missing serial config"); + } + + this.on("close", function(done) { + if (this.serialConfig) { + serialPool.close(this.serialConfig.serialport,done); + } else { + done(); + } + }); + } + RED.nodes.registerType("serial out",SerialOutNode); + + + function SerialInNode(n) { + RED.nodes.createNode(this,n); + this.serial = n.serial; + this.serialConfig = RED.nodes.getNode(this.serial); + + if (this.serialConfig) { + var node = this; + node.tout = null; + var buf; + if (node.serialConfig.out != "count") { buf = new Buffer(bufMaxSize); } + else { buf = new Buffer(Number(node.serialConfig.newline)); } + var i = 0; + node.status({fill:"grey",shape:"dot",text:"unknown"}); + node.port = serialPool.get(this.serialConfig.serialport, + this.serialConfig.serialbaud, + this.serialConfig.databits, + this.serialConfig.parity, + this.serialConfig.stopbits, + this.serialConfig.newline + ); + + var splitc; + if (node.serialConfig.newline.substr(0,2) == "0x") { + splitc = new Buffer([parseInt(node.serialConfig.newline)]); + } else { + splitc = new Buffer(node.serialConfig.newline.replace("\\n","\n").replace("\\r","\r").replace("\\t","\t").replace("\\e","\e").replace("\\f","\f").replace("\\0","\0")); + } + + this.port.on('data', function(msg) { + // single char buffer + if ((node.serialConfig.newline === 0)||(node.serialConfig.newline === "")) { + if (node.serialConfig.bin !== "bin") { node.send({"payload": String.fromCharCode(msg)}); } + else { node.send({"payload": new Buffer([msg])}); } + } + else { + // do the timer thing + if (node.serialConfig.out === "time") { + if (node.tout) { + i += 1; + buf[i] = msg; + } + else { + node.tout = setTimeout(function () { + node.tout = null; + var m = new Buffer(i+1); + buf.copy(m,0,0,i+1); + if (node.serialConfig.bin !== "bin") { m = m.toString(); } + node.send({"payload": m}); + m = null; + }, node.serialConfig.newline); + i = 0; + buf[0] = msg; + } + } + // count bytes into a buffer... + else if (node.serialConfig.out === "count") { + buf[i] = msg; + i += 1; + if ( i >= parseInt(node.serialConfig.newline)) { + var m = new Buffer(i); + buf.copy(m,0,0,i); + if (node.serialConfig.bin !== "bin") { m = m.toString(); } + node.send({"payload":m}); + m = null; + i = 0; + } + } + // look to match char... + else if (node.serialConfig.out === "char") { + buf[i] = msg; + i += 1; + if ((msg === splitc[0]) || (i === bufMaxSize)) { + var m = new Buffer(i); + buf.copy(m,0,0,i); + if (node.serialConfig.bin !== "bin") { m = m.toString(); } + node.send({"payload":m}); + m = null; + i = 0; + } + } + else { console.log("Should never get here"); } + } + }); + this.port.on('ready', function() { + node.status({fill:"green",shape:"dot",text:"connected"}); + }); + this.port.on('closed', function() { + node.status({fill:"red",shape:"ring",text:"not connected"}); + }); + } else { + this.error("missing serial config"); + } + + this.on("close", function(done) { + if (this.serialConfig) { + serialPool.close(this.serialConfig.serialport,done); + } else { + done(); + } + }); + } + RED.nodes.registerType("serial in",SerialInNode); + + + var serialPool = function() { + var connections = {}; + return { + get:function(port,baud,databits,parity,stopbits,newline,callback) { + var id = port; + if (!connections[id]) { + connections[id] = function() { + var obj = { + _emitter: new events.EventEmitter(), + serial: null, + _closing: false, + tout: null, + on: function(a,b) { this._emitter.on(a,b); }, + close: function(cb) { this.serial.close(cb); }, + write: function(m,cb) { this.serial.write(m,cb); }, + } + //newline = newline.replace("\\n","\n").replace("\\r","\r"); + var setupSerial = function() { + //if (newline == "") { + obj.serial = new serialp.SerialPort(port,{ + baudrate: baud, + databits: databits, + parity: parity, + stopbits: stopbits, + parser: serialp.parsers.raw + },true, function(err, results) { if (err) { obj.serial.emit('error',err); } }); + //} + //else { + // obj.serial = new serialp.SerialPort(port,{ + // baudrate: baud, + // databits: databits, + // parity: parity, + // stopbits: stopbits, + // parser: serialp.parsers.readline(newline) + // },true, function(err, results) { if (err) obj.serial.emit('error',err); }); + //} + obj.serial.on('error', function(err) { + util.log("[serial] serial port "+port+" error "+err); + obj._emitter.emit('closed'); + obj.tout = setTimeout(function() { + setupSerial(); + }, settings.serialReconnectTime); + }); + obj.serial.on('close', function() { + if (!obj._closing) { + util.log("[serial] serial port "+port+" closed unexpectedly"); + obj._emitter.emit('closed'); + obj.tout = setTimeout(function() { + setupSerial(); + }, settings.serialReconnectTime); + } + }); + obj.serial.on('open',function() { + util.log("[serial] serial port "+port+" opened at "+baud+" baud "+databits+""+parity.charAt(0).toUpperCase()+stopbits); + if (obj.tout) { clearTimeout(obj.tout); } + //obj.serial.flush(); + obj._emitter.emit('ready'); + }); + obj.serial.on('data',function(d) { + //console.log(Buffer.isBuffer(d),d.length,d); + //if (typeof d !== "string") { + // //d = d.toString(); + for (var z=0; z<d.length; z++) { + obj._emitter.emit('data',d[z]); + } + //} + //else { + // obj._emitter.emit('data',d); + //} + }); + obj.serial.on("disconnect",function() { + util.log("[serial] serial port "+port+" gone away"); + }); + } + setupSerial(); + return obj; + }(); + } + return connections[id]; + }, + close: function(port,done) { + if (connections[port]) { + if (connections[port].tout != null) { + clearTimeout(connections[port].tout); + } + connections[port]._closing = true; + try { + connections[port].close(function() { + util.log("[serial] serial port closed"); + done(); + }); + } + catch(err) { } + delete connections[port]; + } else { + done(); + } + } + } + }(); + + RED.httpAdmin.get("/serialports",function(req,res) { + serialp.list(function (err, ports) { + //console.log(JSON.stringify(ports)); + res.writeHead(200, {'Content-Type': 'text/plain'}); + res.write(JSON.stringify(ports)); + res.end(); + }); + }); +} diff --git a/dgbuilder/core_nodes/io/31-tcpin.html b/dgbuilder/core_nodes/io/31-tcpin.html new file mode 100644 index 00000000..c8cec599 --- /dev/null +++ b/dgbuilder/core_nodes/io/31-tcpin.html @@ -0,0 +1,299 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="tcp in"> + <div class="form-row"> + <label for="node-input-server"><i class="fa fa-dot-circle-o"></i> Type</label> + <select id="node-input-server" style="width:120px; margin-right:5px;"> + <option value="server">Listen on</option> + <option value="client">Connect to</option> + </select> + port <input type="text" id="node-input-port" style="width: 50px"> + </div> + <div class="form-row hidden" id="node-input-host-row" style="padding-left: 110px;"> + at host <input type="text" id="node-input-host" placeholder="localhost" style="width: 60%;"> + </div> + + <div class="form-row"> + <label><i class="fa fa-sign-out"></i> Output</label> + a + <select id="node-input-datamode" style="width:110px;"> + <option value="stream">stream of</option> + <option value="single">single</option> + </select> + <select id="node-input-datatype" style="width:140px;"> + <option value="buffer">Buffer</option> + <option value="utf8">String</option> + <option value="base64">Base64 String</option> + </select> + payload<span id="node-input-datamode-plural">s</span> + </div> + + <div id="node-row-newline" class="form-row hidden" style="padding-left: 110px;"> + delimited by <input type="text" id="node-input-newline" style="width: 110px;"> + </div> + + <div class="form-row"> + <label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label> + <input type="text" id="node-input-topic" placeholder="Topic"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="tcp in"> + <p>Provides a choice of tcp inputs. Can either connect to a remote tcp port, + or accept incoming connections.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('tcp in',{ + category: 'input', + color:"Silver", + defaults: { + server: {value:"server",required:true}, + host: {value:"",validate:function(v) { return (this.server == "server")||v.length > 0;} }, + port: {value:"",required:true,validate:RED.validators.number()}, + datamode:{value:"stream"}, + datatype:{value:"buffer"}, + newline:{value:""}, + topic: {value:""}, + name: {value:""}, + base64: {/*deprecated*/ value:false,required:true} + }, + inputs:0, + outputs:1, + icon: "bridge-dash.png", + label: function() { + return this.name || "tcp:"+(this.host?this.host+":":"")+this.port; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + var updateOptions = function() { + var sockettype = $("#node-input-server option:selected").val(); + if (sockettype == "client") { + $("#node-input-host-row").show(); + } else { + $("#node-input-host-row").hide(); + } + var datamode = $("#node-input-datamode option:selected").val(); + var datatype = $("#node-input-datatype option:selected").val(); + if (datamode == "stream") { + $("#node-input-datamode-plural").show(); + if (datatype == "utf8") { + $("#node-row-newline").show(); + } else { + $("#node-row-newline").hide(); + } + } else { + $("#node-input-datamode-plural").hide(); + $("#node-row-newline").hide(); + } + }; + updateOptions(); + $("#node-input-server").change(updateOptions); + $("#node-input-datatype").change(updateOptions); + $("#node-input-datamode").change(updateOptions); + } + }); +</script> + + +<script type="text/x-red" data-template-name="tcp out"> + <div class="form-row"> + <label for="node-input-beserver"><i class="fa fa-dot-circle-o"></i> Type</label> + <select id="node-input-beserver" style="width:150px; margin-right:5px;"> + <option value="server">Listen on</option> + <option value="client">Connect to</option> + <option value="reply">Reply to TCP</option> + </select> + <span id="node-input-port-row">port <input type="text" id="node-input-port" style="width: 50px"></span> + </div> + + <div class="form-row hidden" id="node-input-host-row" style="padding-left: 110px;"> + at host <input type="text" id="node-input-host" placeholder="localhost" style="width: 60%;"> + </div> + + <div class="form-row hidden" id="node-input-end-row"> + <label> </label> + <input type="checkbox" id="node-input-end" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-end" style="width: 70%;">Close connection after each message is sent ?</label> + </div> + + <div class="form-row"> + <label> </label> + <input type="checkbox" id="node-input-base64" placeholder="base64" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-base64" style="width: 70%;">Decode Base64 message ?</label> + </div> + + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + + <div class="form-tips hidden" id="fin-tip"> + <b>Note:</b> Closing the connection after each message is generally not a good thing - but is useful to indicate an end-of-file for example. + </div> + <div class="form-tips hidden" id="fin-tip2"> + <b>Note:</b> Closing the connection after each message is generally not a good thing - but is useful to indicate an end-of-file for example. The receiving client will need to reconnect. + </div> +</script> + +<script type="text/x-red" data-help-name="tcp out"> + <p>Provides a choice of tcp outputs. Can either connect to a remote tcp port, + accept incoming connections, or reply to messages received from a TCP In node.</p> + <p>Only <b>msg.payload</b> is sent.</p> + <p>If <b>msg.payload</b> is a string containing a Base64 encoding of binary + data, the Base64 decoding option will cause it to be converted back to binary + before being sent.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('tcp out',{ + category: 'output', + color:"Silver", + defaults: { + host: {value:"",validate:function(v) { return (this.beserver != "client")||v.length > 0;} }, + port: {value:"",validate:function(v) { return (this.beserver == "reply")||RED.validators.number()(v) } }, + beserver: {value:"client",required:true}, + base64: {value:false,required:true}, + end: {value:false,required:true}, + name: {value:""} + }, + inputs:1, + outputs:0, + icon: "bridge-dash.png", + align: "right", + label: function() { + return this.name || "tcp:"+(this.host?this.host+":":"")+this.port; + }, + labelStyle: function() { + return (this.name)?"node_label_italic":""; + }, + oneditprepare: function() { + var updateOptions = function() { + var sockettype = $("#node-input-beserver option:selected").val(); + if (sockettype == "reply") { + $("#node-input-port-row").hide(); + $("#node-input-host-row").hide(); + $("#node-input-end-row").hide(); + } else { + $("#node-input-port-row").show(); + $("#node-input-end-row").show(); + } + + if (sockettype == "client") { + $("#node-input-host-row").show(); + $("#fin-tip").show(); + } else { + $("#node-input-host-row").hide(); + $("#fin-tip").hide(); + } + + if (sockettype == "server") { + $("#fin-tip2").show(); + } + else { + $("#fin-tip2").hide(); + } + + }; + updateOptions(); + $("#node-input-beserver").change(updateOptions); + } + }); +</script> + + +<script type="text/x-red" data-template-name="tcp request"> + <div class="form-row"> + <label for="node-input-server"><i class="fa fa-globe"></i> Server</label> + <input type="text" id="node-input-server" placeholder="ip.address" style="width:50%"> + port <input type="text" id="node-input-port" style="width:50px"> + </div> + <div class="form-row"> + <label for="node-input-out"><i class="fa fa-sign-out"></i> Return</label> + <select type="text" id="node-input-out" style="width:52%;"> + <option value="time">after a fixed timeout of</option> + <option value="char">when character received is</option> + <option value="count">a fixed number of characters</option> + <option value="sit">never. Keep connection open</option> + </select> + <input type="text" id="node-input-splitc" style="width:50px;"> + <span id="node-units"></span> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips"><b>Tip:</b> outputs a binary <b>Buffer</b>, so you may want to .toString() it.</div> + <script> + var previous = null; + $("#node-input-out").on('focus', function () { previous = this.value; }).change(function() { + if (previous == null) { previous = $("#node-input-out").val(); } + if ($("#node-input-out").val() == "char") { + if (previous != "char") $("#node-input-splitc").val("\\n"); + $("#node-units").text(""); + } + else if ($("#node-input-out").val() == "time") { + if (previous != "time") $("#node-input-splitc").val("0"); + $("#node-units").text("ms"); + } + else if ($("#node-input-out").val() == "count") { + if (previous != "count") $("#node-input-splitc").val("12"); + $("#node-units").text("chars"); + } + else { + if (previous != "sit") $("#node-input-splitc").val("0"); + $("#node-units").text(""); + } + }); +</script> + +<script type="text/x-red" data-help-name="tcp request"> + <p>A simple TCP request node - sends the <b>msg.payload</b> to a server tcp port and expects a response.</p> + <p>Connects, sends the "request", reads the "response". It can either count a number of + returned characters into a fixed buffer, match a specified character before returning, + wait a fixed timeout from first reply and then return, or just sit and wait for data.</p> + <p>The response will be output in <b>msg.payload</b> as a buffer, so you may want to .toString() it.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('tcp request',{ + category: 'function', + color:"Silver", + defaults: { + server: {value:"",required:true}, + port: {value:"",required:true,validate:RED.validators.number()}, + out: {value:"time",required:true}, + splitc: {value:"0",required:true}, + name: {value:""} + }, + inputs:1, + outputs:1, + icon: "bridge-dash.png", + label: function() { + return this.name || "tcp:"+(this.server?this.server+":":"")+this.port; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/io/31-tcpin.js b/dgbuilder/core_nodes/io/31-tcpin.js new file mode 100644 index 00000000..2e4e5e7b --- /dev/null +++ b/dgbuilder/core_nodes/io/31-tcpin.js @@ -0,0 +1,472 @@ +/** + * Copyright 2013,2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var reconnectTime = RED.settings.socketReconnectTime||10000; + var socketTimeout = RED.settings.socketTimeout||null; + var net = require('net'); + + var connectionPool = {}; + + function TcpIn(n) { + RED.nodes.createNode(this,n); + this.host = n.host; + this.port = n.port * 1; + this.topic = n.topic; + this.stream = (!n.datamode||n.datamode=='stream'); /* stream,single*/ + this.datatype = n.datatype||'buffer'; /* buffer,utf8,base64 */ + this.newline = (n.newline||"").replace("\\n","\n").replace("\\r","\r"); + this.base64 = n.base64; + this.server = (typeof n.server == 'boolean')?n.server:(n.server == "server"); + this.closing = false; + var node = this; + var count = 0; + + if (!node.server) { + var buffer = null; + var client; + var reconnectTimeout; + var end = false; + var setupTcpClient = function() { + node.log("connecting to "+node.host+":"+node.port); + node.status({fill:"grey",shape:"dot",text:"connecting"}); + var id = (1+Math.random()*4294967295).toString(16); + client = net.connect(node.port, node.host, function() { + buffer = (node.datatype == 'buffer')? new Buffer(0):""; + node.log("connected to "+node.host+":"+node.port); + node.status({fill:"green",shape:"dot",text:"connected"}); + }); + connectionPool[id] = client; + + client.on('data', function (data) { + if (node.datatype != 'buffer') { + data = data.toString(node.datatype); + } + if (node.stream) { + if ((node.datatype) === "utf8" && node.newline != "") { + buffer = buffer+data; + var parts = buffer.split(node.newline); + for (var i = 0;i<parts.length-1;i+=1) { + var msg = {topic:node.topic, payload:parts[i]}; + msg._session = {type:"tcp",id:id}; + node.send(msg); + } + buffer = parts[parts.length-1]; + } else { + var msg = {topic:node.topic, payload:data}; + msg._session = {type:"tcp",id:id}; + node.send(msg); + } + } else { + if ((typeof data) === "string") { + buffer = buffer+data; + } else { + buffer = Buffer.concat([buffer,data],buffer.length+data.length); + } + } + }); + client.on('end', function() { + if (!node.stream || (node.datatype == "utf8" && node.newline != "" && buffer.length > 0)) { + var msg = {topic:node.topic,payload:buffer}; + msg._session = {type:"tcp",id:id}; + if (buffer.length !== 0) { + end = true; // only ask for fast re-connect if we actually got something + node.send(msg); + } + buffer = null; + } + }); + client.on('close', function() { + delete connectionPool[id]; + node.status({fill:"red",shape:"ring",text:"disconnected"}); + if (!node.closing) { + if (end) { // if we were asked to close then try to reconnect once very quick. + end = false; + reconnectTimeout = setTimeout(setupTcpClient, 20); + } + else { + node.log("connection lost to "+node.host+":"+node.port); + reconnectTimeout = setTimeout(setupTcpClient, reconnectTime); + } + } + }); + client.on('error', function(err) { + node.log(err); + }); + } + setupTcpClient(); + + this.on('close', function() { + this.closing = true; + client.end(); + clearTimeout(reconnectTimeout); + }); + } else { + var server = net.createServer(function (socket) { + if (socketTimeout !== null) { socket.setTimeout(socketTimeout); } + var id = (1+Math.random()*4294967295).toString(16); + connectionPool[id] = socket; + node.status({text:++count+" connections"}); + + var buffer = (node.datatype == 'buffer')? new Buffer(0):""; + socket.on('data', function (data) { + if (node.datatype != 'buffer') { + data = data.toString(node.datatype); + } + if (node.stream) { + if ((typeof data) === "string" && node.newline != "") { + buffer = buffer+data; + var parts = buffer.split(node.newline); + for (var i = 0;i<parts.length-1;i+=1) { + var msg = {topic:node.topic, payload:parts[i],ip:socket.remoteAddress,port:socket.remotePort}; + msg._session = {type:"tcp",id:id}; + node.send(msg); + } + buffer = parts[parts.length-1]; + } else { + var msg = {topic:node.topic, payload:data}; + msg._session = {type:"tcp",id:id}; + node.send(msg); + } + } else { + if ((typeof data) === "string") { + buffer = buffer+data; + } else { + buffer = Buffer.concat([buffer,data],buffer.length+data.length); + } + } + }); + socket.on('end', function() { + if (!node.stream || (node.datatype === "utf8" && node.newline !== "")) { + if (buffer.length > 0) { + var msg = {topic:node.topic,payload:buffer}; + msg._session = {type:"tcp",id:id}; + node.send(msg); + } + buffer = null; + } + }); + socket.on('timeout', function() { + node.log('timeout closed socket port '+node.port); + socket.end(); + }); + socket.on('close', function() { + delete connectionPool[id]; + node.status({text:--count+" connections"}); + }); + socket.on('error',function(err) { + node.log(err); + }); + }); + server.on('error', function(err) { + if (err) { + node.error('unable to listen on port '+node.port+' : '+err); + } + }); + server.listen(node.port, function(err) { + if (err) { + node.error('unable to listen on port '+node.port+' : '+err); + } else { + node.log('listening on port '+node.port); + + node.on('close', function() { + node.closing = true; + server.close(); + node.log('stopped listening on port '+node.port); + }); + } + }); + } + + } + RED.nodes.registerType("tcp in",TcpIn); + + function TcpOut(n) { + RED.nodes.createNode(this,n); + this.host = n.host; + this.port = n.port * 1; + this.base64 = n.base64; + this.doend = n.end || false; + this.beserver = n.beserver; + this.name = n.name; + this.closing = false; + var node = this; + + if (!node.beserver||node.beserver=="client") { + var reconnectTimeout; + var client = null; + var connected = false; + var end = false; + + var setupTcpClient = function() { + node.log("connecting to "+node.host+":"+node.port); + node.status({fill:"grey",shape:"dot",text:"connecting"}); + client = net.connect(node.port, node.host, function() { + connected = true; + node.log("connected to "+node.host+":"+node.port); + node.status({fill:"green",shape:"dot",text:"connected"}); + }); + client.on('error', function (err) { + node.log('error : '+err); + }); + client.on('end', function (err) { + }); + client.on('close', function() { + node.status({fill:"red",shape:"ring",text:"disconnected"}); + connected = false; + client.destroy(); + if (!node.closing) { + if (end) { + end = false; + reconnectTimeout = setTimeout(setupTcpClient,20); + } + else { + node.log("connection lost to "+node.host+":"+node.port); + reconnectTimeout = setTimeout(setupTcpClient,reconnectTime); + } + } + }); + } + setupTcpClient(); + + node.on("input", function(msg) { + if (connected && msg.payload != null) { + if (Buffer.isBuffer(msg.payload)) { + client.write(msg.payload); + } else if (typeof msg.payload === "string" && node.base64) { + client.write(new Buffer(msg.payload,'base64')); + } else { + client.write(new Buffer(""+msg.payload)); + } + if (node.doend === true) { + end = true; + client.end(); + } + } + }); + + node.on("close", function() { + this.closing = true; + client.end(); + clearTimeout(reconnectTimeout); + }); + + } else if (node.beserver == "reply") { + node.on("input",function(msg) { + if (msg._session && msg._session.type == "tcp") { + var client = connectionPool[msg._session.id]; + if (client) { + if (Buffer.isBuffer(msg.payload)) { + client.write(msg.payload); + } else if (typeof msg.payload === "string" && node.base64) { + client.write(new Buffer(msg.payload,'base64')); + } else { + client.write(new Buffer(""+msg.payload)); + } + } + } + }); + } else { + var connectedSockets = []; + node.status({text:"0 connections"}); + var server = net.createServer(function (socket) { + if (socketTimeout !== null) { socket.setTimeout(socketTimeout); } + var remoteDetails = socket.remoteAddress+":"+socket.remotePort; + node.log("connection from "+remoteDetails); + connectedSockets.push(socket); + node.status({text:connectedSockets.length+" connections"}); + socket.on('timeout', function() { + node.log('timeout closed socket port '+node.port); + socket.end(); + }); + socket.on('close',function() { + node.log("connection closed from "+remoteDetails); + connectedSockets.splice(connectedSockets.indexOf(socket),1); + node.status({text:connectedSockets.length+" connections"}); + }); + socket.on('error',function() { + node.log("socket error from "+remoteDetails); + connectedSockets.splice(connectedSockets.indexOf(socket),1); + node.status({text:connectedSockets.length+" connections"}); + }); + }); + + node.on("input", function(msg) { + if (msg.payload != null) { + var buffer; + if (Buffer.isBuffer(msg.payload)) { + buffer = msg.payload; + } else if (typeof msg.payload === "string" && node.base64) { + buffer = new Buffer(msg.payload,'base64'); + } else { + buffer = new Buffer(""+msg.payload); + } + for (var i = 0; i<connectedSockets.length;i+=1) { + if (node.doend === true) { connectedSockets[i].end(buffer); } + else { connectedSockets[i].write(buffer); } + } + } + }); + + server.on('error', function(err) { + if (err) { + node.error('unable to listen on port '+node.port+' : '+err); + } + }); + + server.listen(node.port, function(err) { + if (err) { + node.error('unable to listen on port '+node.port+' : '+err); + } else { + node.log('listening on port '+node.port); + node.on('close', function() { + server.close(); + node.log('stopped listening on port '+node.port); + }); + } + }); + } + } + RED.nodes.registerType("tcp out",TcpOut); + + function TcpGet(n) { + RED.nodes.createNode(this,n); + this.server = n.server; + this.port = Number(n.port); + this.out = n.out; + this.splitc = n.splitc; + + if (this.out != "char") { this.splitc = Number(this.splitc); } + else { this.splitc.replace("\\n","\n").replace("\\r","\r").replace("\\t","\t").replace("\\e","\e").replace("\\f","\f").replace("\\0","\0"); } + + var buf; + if (this.out == "count") { buf = new Buffer(this.splitc); } + else { buf = new Buffer(32768); } // set it to 32k... hopefully big enough for most.... but only hopefully + + this.connected = false; + var node = this; + var client; + + this.on("input", function(msg) { + var i = 0; + if ((!Buffer.isBuffer(msg.payload)) && (typeof msg.payload !== "string")) { + msg.payload = msg.payload.toString(); + } + if (!node.connected) { + client = net.Socket(); + client.setTimeout(socketTimeout); + node.status({}); + client.connect(node.port, node.server, function() { + //node.log('client connected'); + node.status({fill:"green",shape:"dot",text:"connected"}); + node.connected = true; + client.write(msg.payload); + }); + + client.on('data', function(data) { + //node.log("data:"+ data.length+":"+ data); + if (node.splitc === 0) { + node.send({"payload": data}); + } + else if (node.out === "sit") { // if we are staying connected just send the buffer + node.send({"payload": data}); + } + else { + for (var j = 0; j < data.length; j++ ) { + if (node.out === "time") { + // do the timer thing + if (node.tout) { + i += 1; + buf[i] = data[j]; + } + else { + node.tout = setTimeout(function () { + node.tout = null; + var m = new Buffer(i+1); + buf.copy(m,0,0,i+1); + node.send({"payload": m}); + client.end(); + m = null; + }, node.splitc); + i = 0; + buf[0] = data[j]; + } + } + // count bytes into a buffer... + else if (node.out == "count") { + buf[i] = data[j]; + i += 1; + if ( i >= node.serialConfig.count) { + node.send({"payload": buf}); + client.end(); + i = 0; + } + } + // look for a char + else { + buf[i] = data[j]; + i += 1; + if (data[j] == node.splitc) { + var m = new Buffer(i); + buf.copy(m,0,0,i); + node.send({"payload": m}); + client.end(); + m = null; + i = 0; + } + } + } + } + }); + + client.on('end', function() { + //node.log('client disconnected'); + node.connected = false; + node.status({}); + client = null; + }); + + client.on('error', function() { + node.log('connect failed'); + node.status({fill:"red",shape:"ring",text:"error"}); + if (client) { client.end(); } + }); + + client.on('timeout',function() { + node.log('connect timeout'); + if (client) { + client.end(); + setTimeout(function() { + client.connect(node.port, node.server, function() { + //node.log('client connected'); + node.connected = true; + client.write(msg.payload); + }); + },reconnectTime); + } + }); + } + else { client.write(msg.payload); } + }); + + this.on("close", function() { + if (client) { buf = null; client.end(); } + }); + + } + RED.nodes.registerType("tcp request",TcpGet); +} diff --git a/dgbuilder/core_nodes/io/32-udp.html b/dgbuilder/core_nodes/io/32-udp.html new file mode 100644 index 00000000..1c2eed57 --- /dev/null +++ b/dgbuilder/core_nodes/io/32-udp.html @@ -0,0 +1,212 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- The Input Node --> +<script type="text/x-red" data-template-name="udp in"> + <div class="form-row"> + <label for="node-input-port"><i class="fa fa-sign-in"></i> Listen</label> + on port <input type="text" id="node-input-port" placeholder="Port" style="width: 45px"> + for <select id="node-input-multicast" style='width:40%'> + <option value="false">udp messages</option> + <option value="true">multicast messages</option> + </select> + </div> + <div class="form-row node-input-group"> + <label for="node-input-group"><i class="fa fa-list"></i> Group</label> + <input type="text" id="node-input-group" placeholder="225.0.18.83"> + </div> + <div class="form-row node-input-iface"> + <label for="node-input-iface"><i class="fa fa-random"></i> Interface</label> + <input type="text" id="node-input-iface" placeholder="(optional) ip address of eth0"> + </div> + <div class="form-row"> + <label for="node-input-datatype"><i class="fa fa-sign-out"></i> Output</label> + <select id="node-input-datatype" style="width: 70%;"> + <option value="buffer">a Buffer</option> + <option value="utf8">a String</option> + <option value="base64">a Base64 encoded string</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">Tip: Make sure your firewall will allow the data in.</div> + <script> + $("#node-input-multicast").change(function() { + var id = $("#node-input-multicast option:selected").val(); + if (id == "false") { + $(".node-input-group").hide(); + $(".node-input-iface").hide(); + } + else { + $(".node-input-group").show(); + $(".node-input-iface").show(); + } + }); + </script> +</script> + +<script type="text/x-red" data-help-name="udp in"> + <p>A udp input node, that produces a <b>msg.payload</b> containing a <i>BUFFER</i>, string, or base64 encoded string. Supports multicast.</p> + <p>It also provides <b>msg.ip</b> and <b>msg.port</b> to the ip address and port from which the message was received.</p> + <p>On some systems you may need to be root to use ports below 1024 and/or broadcast.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('udp in',{ + category: 'input', + color:"Silver", + defaults: { + name: {value:""}, + iface: {value:""}, + port: {value:"",required:true,validate:RED.validators.number()}, + datatype: {value:"buffer",required:true}, + multicast: {value:"false"}, + group: {value:"",validate:function(v) { return (this.multicast !== "true")||v.length > 0;} } + }, + inputs:0, + outputs:1, + icon: "bridge-dash.png", + label: function() { + if (this.multicast=="false") { + return this.name||"udp "+this.port; + } + else return this.name||"udp "+(this.group+":"+this.port); + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> + + +<!-- The Output Node --> +<script type="text/x-red" data-template-name="udp out"> + <div class="form-row"> + <label for="node-input-port"><i class="fa fa-envelope"></i> Send a</label> + <select id="node-input-multicast" style='width:40%'> + <option value="false">udp message</option> + <option value="broad">broadcast message</option> + <option value="multi">multicast message</option> + </select> + to port <input type="text" id="node-input-port" placeholder="port" style="width: 70px"> + </div> + <div class="form-row node-input-addr"> + <label for="node-input-addr" id="node-input-addr-label"><i class="fa fa-list"></i> Address</label> + <input type="text" id="node-input-addr" placeholder="destination ip" style="width: 70%;"> + </div> + <div class="form-row node-input-iface"> + <label for="node-input-iface"><i class="fa fa-random"></i> Interface</label> + <input type="text" id="node-input-iface" placeholder="(optional) ip address of eth0"> + </div> + <div class="form-row"> + <label for="node-input-outport-type"> </label> + <select id="node-input-outport-type"> + <option id="node-input-outport-type-random" value="random">use random local port</option> + <option value="fixed">bind to local port</option> + </select> + <input type="text" id="node-input-outport" style="width: 70px;" placeholder="port"> + </div> + <div class="form-row"> + <label> </label> + <input type="checkbox" id="node-input-base64" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-base64" style="width: 70%;">Decode Base64 encoded payload ?</label> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">Tip: leave address and port blank if you want to set using <b>msg.ip</b> and <b>msg.port</b>.</div> + <script> + $("#node-input-multicast").change(function() { + var id = $("#node-input-multicast option:selected").val(); + if (id !== "multi") { + $(".node-input-iface").hide(); + $("#node-input-addr-label").html('<i class="fa fa-list"></i> Address'); + $("#node-input-addr")[0].placeholder = 'destination ip'; + } + else { + $(".node-input-iface").show(); + $("#node-input-addr-label").html('<i class="fa fa-list"></i> Group'); + $("#node-input-addr")[0].placeholder = '225.0.18.83'; + } + if (id === "broad") { + $("#node-input-addr")[0].placeholder = '255.255.255.255'; + } + }); + </script> +</script> + +<script type="text/x-red" data-help-name="udp out"> + <p>This node sends <b>msg.payload</b> to the designated udp host and port. Supports multicast.</p> + <p>You may also use <b>msg.ip</b> and <b>msg.port</b> to set the destination values.<br/><b>Note</b>: the statically configured values have precedence.</p> + <p>If you select broadcast either set the address to the local broadcast ip address, or maybe try 255.255.255.255, which is the global broadcast address.</p> + <p>On some systems you may need to be root to use ports below 1024 and/or broadcast.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('udp out',{ + category: 'output', + color:"Silver", + defaults: { + name: {value:""}, + addr: {value:""}, + iface: {value:""}, + port: {value:""}, + outport: {value:""}, + base64: {value:false,required:true}, + multicast: {value:"false"} + }, + inputs:1, + outputs:0, + icon: "bridge-dash.png", + align: "right", + label: function() { + return this.name||"udp "+(this.addr+":"+this.port); + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + var type = this.outport==""?"random":"fixed"; + $("#node-input-outport-type option").filter(function() { + return $(this).val() == type; + }).attr('selected',true); + + $("#node-input-outport-type").change(function() { + var type = $(this).children("option:selected").val(); + if (type == "random") { + $("#node-input-outport").val("").hide(); + } else { + $("#node-input-outport").show(); + } + }); + + $("#node-input-outport-type").change(); + + $("#node-input-multicast").change(function() { + var type = $(this).children("option:selected").val(); + if (type == "false") { + $("#node-input-outport-type-random").html("bind to random local port"); + } else { + $("#node-input-outport-type-random").html("bind to target port"); + } + }); + $("#node-input-multicast").change(); + } + }); +</script> diff --git a/dgbuilder/core_nodes/io/32-udp.js b/dgbuilder/core_nodes/io/32-udp.js new file mode 100644 index 00000000..a7968e3a --- /dev/null +++ b/dgbuilder/core_nodes/io/32-udp.js @@ -0,0 +1,171 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var dgram = require('dgram'); + + // The Input Node + function UDPin(n) { + RED.nodes.createNode(this,n); + this.group = n.group; + this.port = n.port; + this.datatype = n.datatype; + this.iface = n.iface || null; + this.multicast = n.multicast; + var node = this; + + var server = dgram.createSocket('udp4'); + + server.on("error", function (err) { + if ((err.code == "EACCES") && (node.port < 1024)) { + node.error("UDP access error, you may need root access for ports below 1024"); + } else { + node.error("UDP error : "+err.code); + } + server.close(); + }); + + server.on('message', function (message, remote) { + var msg; + if (node.datatype =="base64") { + msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port }; + } else if (node.datatype =="utf8") { + msg = { payload:message.toString('utf8'), fromip:remote.address+':'+remote.port }; + } else { + msg = { payload:message, fromip:remote.address+':'+remote.port, ip:remote.address, port:remote.port }; + } + node.send(msg); + }); + + server.on('listening', function () { + var address = server.address(); + node.log('udp listener at ' + address.address + ":" + address.port); + if (node.multicast == "true") { + server.setBroadcast(true); + try { + server.setMulticastTTL(128); + server.addMembership(node.group,node.iface); + node.log("udp multicast group "+node.group); + } catch (e) { + if (e.errno == "EINVAL") { + node.error("Bad Multicast Address"); + } else if (e.errno == "ENODEV") { + node.error("Must be ip address of the required interface"); + } else { + node.error("Error :"+e.errno); + } + } + } + }); + + node.on("close", function() { + try { + server.close(); + node.log('udp listener stopped'); + } catch (err) { + node.error(err); + } + }); + + server.bind(node.port,node.iface); + } + RED.nodes.registerType("udp in",UDPin); + + + // The Output Node + function UDPout(n) { + RED.nodes.createNode(this,n); + //this.group = n.group; + this.port = n.port; + this.outport = n.outport||""; + this.base64 = n.base64; + this.addr = n.addr; + this.iface = n.iface || null; + this.multicast = n.multicast; + var node = this; + + var sock = dgram.createSocket('udp4'); // only use ipv4 for now + + if (node.multicast != "false") { + if (node.outport == "") { node.outport = node.port; } + sock.bind(node.outport, function() { // have to bind before you can enable broadcast... + sock.setBroadcast(true); // turn on broadcast + if (node.multicast == "multi") { + try { + sock.setMulticastTTL(128); + sock.addMembership(node.addr,node.iface); // Add to the multicast group + node.log('udp multicast ready : '+node.outport+' -> '+node.addr+":"+node.port); + } catch (e) { + if (e.errno == "EINVAL") { + node.error("Bad Multicast Address"); + } else if (e.errno == "ENODEV") { + node.error("Must be ip address of the required interface"); + } else { + node.error("Error :"+e.errno); + } + } + } else { + node.log('udp broadcast ready : '+node.outport+' -> '+node.addr+":"+node.port); + } + }); + } else if (node.outport != "") { + sock.bind(node.outport); + node.log('udp ready : '+node.outport+' -> '+node.addr+":"+node.port); + } else { + node.log('udp ready : '+node.addr+":"+node.port); + } + + node.on("input", function(msg) { + if (msg.payload != null) { + var add = node.addr || msg.ip || ""; + var por = node.port || msg.port || 0; + if (add == "") { + node.warn("udp: ip address not set"); + } else if (por == 0) { + node.warn("udp: port not set"); + } else if (isNaN(por) || (por < 1) || (por > 65535)) { + node.warn("udp: port number not valid"); + } else { + var message; + if (node.base64) { + message = new Buffer(msg.payload, 'base64'); + } else if (msg.payload instanceof Buffer) { + message = msg.payload; + } else { + message = new Buffer(""+msg.payload); + } + sock.send(message, 0, message.length, por, add, function(err, bytes) { + if (err) { + node.error("udp : "+err); + } + message = null; + }); + } + } + }); + + node.on("close", function() { + try { + sock.close(); + node.log('udp output stopped'); + } catch (err) { + node.error(err); + } + }); + } + RED.nodes.registerType("udp out",UDPout); +} diff --git a/dgbuilder/core_nodes/io/lib/mqtt.js b/dgbuilder/core_nodes/io/lib/mqtt.js new file mode 100644 index 00000000..141a8889 --- /dev/null +++ b/dgbuilder/core_nodes/io/lib/mqtt.js @@ -0,0 +1,254 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var util = require("util"); +var mqtt = require("mqtt"); +var events = require("events"); +//var inspect = require("sys").inspect; + +//var Client = module.exports.Client = function( + +var port = 1883; +var host = "localhost"; + +function MQTTClient(port,host) { + this.port = port||1883; + this.host = host||"localhost"; + this.messageId = 1; + this.pendingSubscriptions = {}; + this.inboundMessages = {}; + this.lastOutbound = (new Date()).getTime(); + this.lastInbound = (new Date()).getTime(); + this.connected = false; + + this._nextMessageId = function() { + this.messageId += 1; + if (this.messageId > 0xFFFF) { + this.messageId = 1; + } + return this.messageId; + } + events.EventEmitter.call(this); +} +util.inherits(MQTTClient, events.EventEmitter); + +MQTTClient.prototype.connect = function(options) { + if (!this.connected) { + var self = this; + options = options||{}; + self.options = options; + self.options.keepalive = options.keepalive||15; + self.options.clean = self.options.clean||true; + self.options.protocolId = 'MQIsdp'; + self.options.protocolVersion = 3; + + self.client = mqtt.createConnection(this.port,this.host,function(err,client) { + if (err) { + self.connected = false; + clearInterval(self.watchdog); + self.connectionError = true; + //util.log('[mqtt] ['+self.uid+'] connection error 1 : '+inspect(err)); + self.emit('connectionlost',err); + return; + } + client.on('close',function(e) { + //util.log('[mqtt] ['+self.uid+'] on close'); + clearInterval(self.watchdog); + if (!self.connectionError) { + if (self.connected) { + self.connected = false; + self.emit('connectionlost',e); + } else { + self.emit('disconnect'); + } + } + }); + client.on('error',function(e) { + //util.log('[mqtt] ['+self.uid+'] on error : '+inspect(e)); + clearInterval(self.watchdog); + if (self.connected) { + self.connected = false; + self.emit('connectionlost',e); + } + }); + client.on('connack',function(packet) { + if (packet.returnCode == 0) { + self.watchdog = setInterval(function(self) { + var now = (new Date()).getTime(); + + //util.log('[mqtt] ['+self.uid+'] watchdog '+inspect({connected:self.connected,connectionError:self.connectionError,pingOutstanding:self.pingOutstanding,now:now,lastOutbound:self.lastOutbound,lastInbound:self.lastInbound})); + + if (now - self.lastOutbound > self.options.keepalive*500 || now - self.lastInbound > self.options.keepalive*500) { + if (self.pingOutstanding) { + //util.log('[mqtt] ['+self.uid+'] watchdog pingOustanding - disconnect'); + try { + self.client.disconnect(); + } catch (err) { + } + } else { + //util.log('[mqtt] ['+self.uid+'] watchdog pinging'); + self.lastOutbound = (new Date()).getTime(); + self.lastInbound = (new Date()).getTime(); + self.pingOutstanding = true; + self.client.pingreq(); + } + } + + },self.options.keepalive*500,self); + self.pingOutstanding = false; + self.lastInbound = (new Date()).getTime() + self.lastOutbound = (new Date()).getTime() + self.connected = true; + self.connectionError = false; + self.emit('connect'); + } else { + self.connected = false; + self.emit('connectionlost'); + } + }); + client.on('suback',function(packet) { + self.lastInbound = (new Date()).getTime() + var topic = self.pendingSubscriptions[packet.messageId]; + self.emit('subscribe',topic,packet.granted[0]); + delete self.pendingSubscriptions[packet.messageId]; + }); + client.on('unsuback',function(packet) { + self.lastInbound = (new Date()).getTime() + var topic = self.pendingSubscriptions[packet.messageId]; + self.emit('unsubscribe',topic,packet.granted[0]); + delete self.pendingSubscriptions[packet.messageId]; + }); + client.on('publish',function(packet) { + self.lastInbound = (new Date()).getTime() + if (packet.qos < 2) { + var p = packet; + self.emit('message',p.topic,p.payload,p.qos,p.retain); + } else { + self.inboundMessages[packet.messageId] = packet; + this.lastOutbound = (new Date()).getTime() + self.client.pubrec(packet); + } + if (packet.qos == 1) { + this.lastOutbound = (new Date()).getTime() + self.client.puback(packet); + } + }); + + client.on('pubrel',function(packet) { + self.lastInbound = (new Date()).getTime() + var p = self.inboundMessages[packet.messageId]; + if (p) { + self.emit('message',p.topic,p.payload,p.qos,p.retain); + delete self.inboundMessages[packet.messageId]; + } + self.lastOutbound = (new Date()).getTime() + self.client.pubcomp(packet); + }); + + client.on('puback',function(packet) { + self.lastInbound = (new Date()).getTime() + // outbound qos-1 complete + }); + + client.on('pubrec',function(packet) { + self.lastInbound = (new Date()).getTime() + self.lastOutbound = (new Date()).getTime() + self.client.pubrel(packet); + }); + client.on('pubcomp',function(packet) { + self.lastInbound = (new Date()).getTime() + // outbound qos-2 complete + }); + client.on('pingresp',function(packet) { + //util.log('[mqtt] ['+self.uid+'] received pingresp'); + self.lastInbound = (new Date()).getTime() + self.pingOutstanding = false; + }); + + this.lastOutbound = (new Date()).getTime() + this.connectionError = false; + client.connect(self.options); + }); + } +} + +MQTTClient.prototype.subscribe = function(topic,qos) { + var self = this; + if (self.connected) { + var options = { + subscriptions:[{topic:topic,qos:qos}], + messageId: self._nextMessageId() + }; + this.pendingSubscriptions[options.messageId] = topic; + this.lastOutbound = (new Date()).getTime() + self.client.subscribe(options); + } +} +MQTTClient.prototype.unsubscribe = function(topic) { + var self = this; + if (self.connected) { + var options = { + topic:topic, + messageId: self._nextMessageId() + }; + this.pendingSubscriptions[options.messageId] = topic; + this.lastOutbound = (new Date()).getTime() + self.client.unsubscribe(options); + } +} + +MQTTClient.prototype.publish = function(topic,payload,qos,retain) { + var self = this; + if (self.connected) { + + if (!Buffer.isBuffer(payload)) { + if (typeof payload === "object") { + payload = JSON.stringify(payload); + } else if (typeof payload !== "string") { + payload = ""+payload; + } + } + var options = { + topic: topic, + payload: payload, + qos: qos||0, + retain:retain||false + }; + if (options.qos != 0) { + options.messageId = self._nextMessageId(); + } + this.lastOutbound = (new Date()).getTime() + self.client.publish(options); + } +} + +MQTTClient.prototype.disconnect = function() { + var self = this; + if (this.connected) { + this.connected = false; + try { + this.client.disconnect(); + } catch(err) { + } + } +} +MQTTClient.prototype.isConnected = function() { + return this.connected; +} +module.exports.createClient = function(port,host) { + var mqtt_client = new MQTTClient(port,host); + return mqtt_client; +} + diff --git a/dgbuilder/core_nodes/io/lib/mqttConnectionPool.js b/dgbuilder/core_nodes/io/lib/mqttConnectionPool.js new file mode 100644 index 00000000..d15f0fc7 --- /dev/null +++ b/dgbuilder/core_nodes/io/lib/mqttConnectionPool.js @@ -0,0 +1,128 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var util = require("util"); +var mqtt = require("./mqtt"); +var settings = require(process.env.NODE_RED_HOME+"/red/red").settings; + +var connections = {}; + +function matchTopic(ts,t) { + if (ts == "#") { + return true; + } + var re = new RegExp("^"+ts.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$"); + return re.test(t); +} + +module.exports = { + get: function(broker,port,clientid,username,password,will) { + var id = "["+(username||"")+":"+(password||"")+"]["+(clientid||"")+"]@"+broker+":"+port; + if (!connections[id]) { + connections[id] = function() { + var uid = (1+Math.random()*4294967295).toString(16); + var client = mqtt.createClient(port,broker); + client.uid = uid; + client.setMaxListeners(0); + var options = {keepalive:15}; + options.clientId = clientid || 'mqtt_' + (1+Math.random()*4294967295).toString(16); + options.username = username; + options.password = password; + options.will = will; + var queue = []; + var subscriptions = []; + var connecting = false; + var obj = { + _instances: 0, + publish: function(msg) { + if (client.isConnected()) { + client.publish(msg.topic,msg.payload,msg.qos,msg.retain); + } else { + if (!connecting) { + connecting = true; + client.connect(options); + } + queue.push(msg); + } + }, + subscribe: function(topic,qos,callback) { + subscriptions.push({topic:topic,qos:qos,callback:callback}); + client.on('message',function(mtopic,mpayload,mqos,mretain) { + if (matchTopic(topic,mtopic)) { + callback(mtopic,mpayload,mqos,mretain); + } + }); + if (client.isConnected()) { + client.subscribe(topic,qos); + } + }, + on: function(a,b){ + client.on(a,b); + }, + once: function(a,b){ + client.once(a,b); + }, + connect: function() { + if (client && !client.isConnected() && !connecting) { + connecting = true; + client.connect(options); + } + }, + disconnect: function() { + this._instances -= 1; + if (this._instances == 0) { + client.disconnect(); + client = null; + delete connections[id]; + } + } + }; + client.on('connect',function() { + if (client) { + util.log('[mqtt] ['+uid+'] connected to broker tcp://'+broker+':'+port); + connecting = false; + for (var s in subscriptions) { + var topic = subscriptions[s].topic; + var qos = subscriptions[s].qos; + var callback = subscriptions[s].callback; + client.subscribe(topic,qos); + } + //console.log("connected - publishing",queue.length,"messages"); + while(queue.length) { + var msg = queue.shift(); + //console.log(msg); + client.publish(msg.topic,msg.payload,msg.qos,msg.retain); + } + } + }); + client.on('connectionlost', function(err) { + util.log('[mqtt] ['+uid+'] connection lost to broker tcp://'+broker+':'+port); + connecting = false; + setTimeout(function() { + obj.connect(); + }, settings.mqttReconnectTime||5000); + }); + client.on('disconnect', function() { + connecting = false; + util.log('[mqtt] ['+uid+'] disconnected from broker tcp://'+broker+':'+port); + }); + + return obj + }(); + } + connections[id]._instances += 1; + return connections[id]; + } +}; diff --git a/dgbuilder/core_nodes/logic/10-switch.html b/dgbuilder/core_nodes/logic/10-switch.html new file mode 100644 index 00000000..4e02f446 --- /dev/null +++ b/dgbuilder/core_nodes/logic/10-switch.html @@ -0,0 +1,198 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="switch"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row" style="padding-top:10px;"> + If msg.<input type="text" id="node-input-property" style="width: 200px;"/> + </div> + <div class="form-row"> + <div id="node-input-rule-container-div" style="border-radius: 5px; height: 310px; padding: 5px; border: 1px solid #ccc; overflow-y:scroll;"> + <ol id="node-input-rule-container" style=" list-style-type:none; margin: 0;"> + </ol> + </div> + <a href="#" class="btn btn-mini" id="node-input-add-rule" style="margin-top: 4px;"><i class="fa fa-plus"></i> Add</a> + </div> + <div> + <select id="node-input-checkall" style="width:100%; margin-right:5px;"> + <option value="true">checking all rules</option> + <option value="false">stopping after first match</option> + </select> + </div> +</script> + +<script type="text/x-red" data-help-name="switch"> + <p>A simple function node to route messages based on its properties.</p> + <p>When a message arrives, the selected property is evaluated against each + of the defined rules. The message is then sent to the output of <i>all</i> + rules that pass.</p> + <p>Note: the <i>otherwise</i> rule applies as a "not any of" the rules preceding it.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('switch', { + color: "#E2D96E", + category: 'function', + defaults: { + name: {value:""}, + property: {value:"payload", required:true}, + rules: {value:[{t:"eq", v:""}]}, + checkall: {value:"true", required:true}, + outputs: {value:1} + }, + inputs: 1, + outputs: 1, + icon: "switch.png", + label: function() { + return this.name||"switch"; + }, + oneditprepare: function() { + + var operators = [ + {v:"eq",t:"=="}, + {v:"neq",t:"!="}, + {v:"lt",t:"<"}, + {v:"lte",t:"<="}, + {v:"gt",t:">"}, + {v:"gte",t:">="}, + {v:"btwn",t:"is between"}, + {v:"cont",t:"contains"}, + {v:"regex",t:"matches regex"}, + {v:"true",t:"is true"}, + {v:"false",t:"is false"}, + {v:"null",t:"is null"}, + {v:"nnull",t:"is not null"}, + {v:"else",t:"otherwise"} + ]; + + function generateRule(i,rule) { + var container = $('<li/>',{style:"margin:0; padding:8px 0px; border-bottom: 1px solid #ccc;"}); + var row = $('<div/>').appendTo(container); + var row2 = $('<div/>',{style:"padding-top: 5px; text-align: right;"}).appendTo(container); + + var selectField = $('<select/>',{style:"width:120px; margin-left: 5px; text-align: center;"}).appendTo(row); + for (var d in operators) { + selectField.append($("<option></option>").val(operators[d].v).text(operators[d].t)); + } + + var valueField = $('<input/>',{class:"node-input-rule-value",type:"text",style:"margin-left: 5px; width: 145px;"}).appendTo(row); + var btwnField = $('<span/>').appendTo(row); + var btwnValueField = $('<input/>',{class:"node-input-rule-btwn-value",type:"text",style:"margin-left: 5px; width: 50px;"}).appendTo(btwnField); + btwnField.append(" and "); + var btwnValue2Field = $('<input/>',{class:"node-input-rule-btwn-value2",type:"text",style:"width: 50px;margin-left:2px;"}).appendTo(btwnField); + + var finalspan = $('<span/>',{style:"float: right; margin-top: 3px;margin-right: 10px;"}).appendTo(row); + finalspan.append(' send to <span class="node-input-rule-index">'+i+'</span> '); + + selectField.change(function() { + var type = selectField.children("option:selected").val(); + if (type.length < 4) { + selectField.css({"width":"60px"}); + } else if (type === "regex") { + selectField.css({"width":"147px"}); + } else { + selectField.css({"width":"120px"}); + } + if (type === "btwn") { + valueField.hide(); + btwnField.show(); + } else { + btwnField.hide(); + if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "else") { + valueField.hide(); + } else { + valueField.show(); + } + } + }); + + var deleteButton = $('<a/>',{href:"#",class:"btn btn-mini", style:"margin-left: 5px;"}).appendTo(finalspan); + $('<i/>',{class:"fa fa-remove"}).appendTo(deleteButton); + + deleteButton.click(function() { + container.css({"background":"#fee"}); + container.fadeOut(300, function() { + $(this).remove(); + $("#node-input-rule-container").children().each(function(i) { + $(this).find(".node-input-rule-index").html(i+1); + }); + + }); + }); + + $("#node-input-rule-container").append(container); + + selectField.find("option").filter(function() {return $(this).val() == rule.t;}).attr('selected',true); + if (rule.t == "btwn") { + btwnValueField.val(rule.v); + btwnValue2Field.val(rule.v2); + } else if (typeof rule.v != "undefined") { + valueField.val(rule.v); + } + selectField.change(); + } + + $("#node-input-add-rule").click(function() { + generateRule($("#node-input-rule-container").children().length+1,{t:"",v:"",v2:""}); + $("#node-input-rule-container-div").scrollTop($("#node-input-rule-container-div").get(0).scrollHeight); + }); + + for (var i=0;i<this.rules.length;i++) { + var rule = this.rules[i]; + generateRule(i+1,rule); + } + + function switchDialogResize(ev,ui) { + $("#node-input-rule-container-div").css("height",(ui.size.height-260)+"px"); + }; + + $( "#dialog" ).on("dialogresize", switchDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-switch'); + if (size) { + switchDialogResize(null,{size:size}); + } + }); + $( "#dialog" ).one("dialogclose", function(ev,ui) { + $( "#dialog" ).off("dialogresize",switchDialogResize); + }); + }, + oneditsave: function() { + var rules = $("#node-input-rule-container").children(); + var ruleset; + var node = this; + node.rules= []; + rules.each(function(i) { + var rule = $(this); + var type = rule.find("select option:selected").val(); + var r = {t:type}; + if (!(type === "true" || type === "false" || type === "null" || type === "nnull" || type === "else")) { + if (type === "btwn") { + r.v = rule.find(".node-input-rule-btwn-value").val(); + r.v2 = rule.find(".node-input-rule-btwn-value2").val(); + } else { + r.v = rule.find(".node-input-rule-value").val(); + } + } + node.rules.push(r); + }); + node.outputs = node.rules.length; + } + }); +</script> diff --git a/dgbuilder/core_nodes/logic/10-switch.js b/dgbuilder/core_nodes/logic/10-switch.js new file mode 100644 index 00000000..8bcb8571 --- /dev/null +++ b/dgbuilder/core_nodes/logic/10-switch.js @@ -0,0 +1,78 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var operators = { + 'eq': function(a, b) { return a == b; }, + 'neq': function(a, b) { return a != b; }, + 'lt': function(a, b) { return a < b; }, + 'lte': function(a, b) { return a <= b; }, + 'gt': function(a, b) { return a > b; }, + 'gte': function(a, b) { return a >= b; }, + 'btwn': function(a, b, c) { return a >= b && a <= c; }, + 'cont': function(a, b) { return (a + "").indexOf(b) != -1; }, + 'regex': function(a, b) { return (a + "").match(new RegExp(b)); }, + 'true': function(a) { return a === true; }, + 'false': function(a) { return a === false; }, + 'null': function(a) { return typeof a == "undefined"; }, + 'nnull': function(a) { return typeof a != "undefined"; }, + 'else': function(a) { return a === true; } + }; + + function SwitchNode(n) { + RED.nodes.createNode(this, n); + this.rules = n.rules; + this.property = n.property; + this.checkall = n.checkall || "true"; + var propertyParts = n.property.split("."); + var node = this; + + for (var i=0; i<this.rules.length; i+=1) { + var rule = this.rules[i]; + if (!isNaN(Number(rule.v))) { + rule.v = Number(rule.v); + rule.v2 = Number(rule.v2); + } + } + + this.on('input', function (msg) { + var onward = []; + try { + var prop = propertyParts.reduce(function (obj, i) { + return obj[i] + }, msg); + var elseflag = true; + for (var i=0; i<node.rules.length; i+=1) { + var rule = node.rules[i]; + var test = prop; + if (rule.t == "else") { test = elseflag; elseflag = true; } + if (operators[rule.t](test,rule.v, rule.v2)) { + onward.push(msg); + elseflag = false; + if (node.checkall == "false") { break; } + } else { + onward.push(null); + } + } + this.send(onward); + } catch(err) { + node.warn(err); + } + }); + } + RED.nodes.registerType("switch", SwitchNode); +} diff --git a/dgbuilder/core_nodes/logic/15-change.html b/dgbuilder/core_nodes/logic/15-change.html new file mode 100644 index 00000000..702dd807 --- /dev/null +++ b/dgbuilder/core_nodes/logic/15-change.html @@ -0,0 +1,139 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="change"> + <div> + <select id="node-input-action" style="width:95%; margin-right:5px;"> + <option value="replace">Set the value of the message property</option> + <option value="change">Search/replace the value of the message property</option> + <option value="delete">Delete the message property</option> + </select> + </div> + <div class="form-row" style="padding-top:10px;" id="node-prop1-row"> + <label for="node-input-property">called</label> msg.<input type="text" id="node-input-property" style="width: 63%;"/> + </div> + <div class="form-row" id="node-from-row"> + <label for="node-input-from" id="node-input-f"></label> + <input type="text" id="node-input-from" placeholder="this"/> + </div> + <div class="form-row" id="node-to-row"> + <label for="node-input-to" id="node-input-t"></label> + <input type="text" id="node-input-to" placeholder="that"/> + </div> + <div class="form-row" id="node-reg-row"> + <label> </label> + <input type="checkbox" id="node-input-reg" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-reg" style="width: 70%;">Use regular expressions ?</label> + </div> + <div class="form-tips" id="node-tip"></div> + <br/> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="change"> + <p>A simple function node to change, replace, add or delete properties of a message.</p> + <p>When a message arrives, the selected property is modified by the defined rules. + The message is then sent to the output.</p> + <p><b>Note:</b> Replace only operates on <b>strings</b>. Anything else will be passed straight through.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('change', { + color: "#E2D96E", + category: 'function', + defaults: { + action: {value:"replace",required:true}, + property: {value:"payload",required:true}, + from: {value:"",validate: function(v) { + if (this.action == "change" && this.reg) { + try { + var re = new RegExp(this.from, "g"); + return true; + } catch(err) { + return false; + } + } + return true; + }}, + to: {value:""}, + reg: {value:false}, + name: {value:""} + }, + inputs: 1, + outputs: 1, + icon: "swap.png", + label: function() { + if (this.name) { + return this.name; + } + if (this.action == "replace") { + return "set msg."+this.property; + } else { + return this.action+" msg."+this.property + } + }, + labelStyle: function() { + return this.name ? "node_label_italic" : ""; + }, + oneditprepare: function() { + if (this.reg === null) { $("#node-input-reg").prop('checked', true); } + $("#node-input-action").change( function() { + var a = $("#node-input-action").val(); + if (a === "replace") { + $("#node-input-todo").html("called"); + //$("#node-input-f").html("name"); + $("#node-input-t").html("to"); + $("#node-from-row").hide(); + $("#node-to-row").show(); + $("#node-reg-row").hide(); + $("#node-tip").show(); + $("#node-tip").html("Tip: expects a new property name and either a fixed value OR the full name of another message property eg: msg.sentiment.score"); + } + if (a === "delete") { + $("#node-input-todo").html("called"); + //$("#node-input-f").html("called"); + //$("#node-input-t").html("to"); + $("#node-from-row").hide(); + $("#node-to-row").hide(); + $("#node-reg-row").hide(); + $("#node-tip").hide(); + } + if (a === "change") { + $("#node-input-todo").html("called"); + $("#node-input-f").html("Search for"); + $("#node-input-t").html("replace with"); + $("#node-from-row").show(); + $("#node-to-row").show(); + $("#node-reg-row").show(); + $("#node-tip").show(); + $("#node-tip").html("Tip: only works on string properties. If regular expressions are used, the <i>replace with</i> field can contain capture results, eg $1."); + } + //if (a === "replace") { + // $("#node-input-todo").html("called"); + // //$("#node-input-f").html("with"); + // $("#node-input-t").html("with"); + // $("#node-from-row").hide(); + // $("#node-to-row").show(); + // $("#node-tip").html("Tip: accepts either a fixed value OR the full name of another msg.property eg: msg.sentiment.score"); + //} + }); + $("#node-input-action").change(); + } + }); +</script> diff --git a/dgbuilder/core_nodes/logic/15-change.js b/dgbuilder/core_nodes/logic/15-change.js new file mode 100644 index 00000000..b7ef62e1 --- /dev/null +++ b/dgbuilder/core_nodes/logic/15-change.js @@ -0,0 +1,74 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + function ChangeNode(n) { + RED.nodes.createNode(this, n); + this.action = n.action; + this.property = n.property || ""; + this.from = n.from || " "; + this.to = n.to || " "; + this.reg = (n.reg === null || n.reg); + var node = this; + if (node.reg === false) { + this.from = this.from.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); + } + var makeNew = function( stem, path, value ) { + var lastPart = (arguments.length === 3) ? path.pop() : false; + for (var i = 0; i < path.length; i++) { + stem = stem[path[i]] = stem[path[i]] || {}; + } + if (lastPart) { stem = stem[lastPart] = value; } + return stem; + }; + + this.on('input', function (msg) { + if (node.action == "change") { + try { + node.re = new RegExp(this.from, "g"); + } catch (e) { + node.error(e.message); + } + if (typeof msg[node.property] === "string") { + msg[node.property] = (msg[node.property]).replace(node.re, node.to); + } + } + //else if (node.action == "replace") { + //if (node.to.indexOf("msg.") == 0) { + //msg[node.property] = eval(node.to); + //} + //else { + //msg[node.property] = node.to; + //} + //} + else if (node.action == "replace") { + if (node.to.indexOf("msg.") === 0) { + makeNew( msg, node.property.split("."), eval(node.to) ); + } + else { + makeNew( msg, node.property.split("."), node.to ); + } + //makeNew( msg, node.property.split("."), node.to ); + } + else if (node.action == "delete") { + delete(msg[node.property]); + } + node.send(msg); + }); + } + RED.nodes.registerType("change", ChangeNode); +} diff --git a/dgbuilder/core_nodes/logic/16-range.html b/dgbuilder/core_nodes/logic/16-range.html new file mode 100644 index 00000000..5f87128f --- /dev/null +++ b/dgbuilder/core_nodes/logic/16-range.html @@ -0,0 +1,81 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="range"> + <div class="form-row"> + <label for="node-input-action"><i class="fa fa-dot-circle-o"></i> Action</label> + <select id="node-input-action" style="width:70%; margin-right:5px;"> + <option value="scale">Scale msg.payload</option> + <option value="clamp">Scale and limit to the target range</option> + <option value="roll">Scale and wrap within the target range</option> + </select> + </div> + <br/> + <div class="form-row"><i class="fa fa-sign-in"></i> Map the input range:</div> + <div class="form-row"><label></label> + from: <input type="text" id="node-input-minin" placeholder="e.g. 0" style="width:100px;"/> + to: <input type="text" id="node-input-maxin" placeholder="e.g. 99" style="width:100px;"/> + </div> + <div class="form-row"><i class="fa fa-sign-out"></i> to the result range:</div> + <div class="form-row"><label></label> + from: <input type="text" id="node-input-minout" placeholder="e.g. 0" style="width:100px;"/> + to: <input type="text" id="node-input-maxout" placeholder="e.g. 255" style="width:100px;"/> + </div> + <br/> + <div class="form-row"><label></label> + <input type="checkbox" id="node-input-round" style="display: inline-block; width: auto; vertical-align: top;"> + <label style="width: auto;" for="node-input-round">Round result to the nearest integer?</label></input> + </div> + <br/> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips" id="node-tip">Tip: This node ONLY works with numbers.</div> +</script> + +<script type="text/x-red" data-help-name="range"> + <p>A simple function node to remap numeric input values to another scale.</p> + <p>Currently only does a linear scaling.</p> + <p><b>Note:</b> This only operates on <b>numbers</b>. Anything else will try to be made into a number and rejected if that fails.</p> + <p><i>Scale and limit to target range</i> means that the result will never be outside the range specified within the result range.</p> + <p><i>Scale and wrap within the target range</i> means that the result will essentially be a "modulo-style" wrap-around within the result range.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('range', { + color: "#E2D96E", + category: 'function', + defaults: { + minin: {value:"",required:true,validate:RED.validators.number()}, + maxin: {value:"",required:true,validate:RED.validators.number()}, + minout: {value:"",required:true,validate:RED.validators.number()}, + maxout: {value:"",required:true,validate:RED.validators.number()}, + action: {value:"scale"}, + round: {value:false}, + name: {value:""} + }, + inputs: 1, + outputs: 1, + icon: "range.png", + label: function() { + return this.name || "range"; + }, + labelStyle: function() { + return this.name ? "node_label_italic" : ""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/logic/16-range.js b/dgbuilder/core_nodes/logic/16-range.js new file mode 100644 index 00000000..ec39342a --- /dev/null +++ b/dgbuilder/core_nodes/logic/16-range.js @@ -0,0 +1,48 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + function RangeNode(n) { + RED.nodes.createNode(this, n); + this.action = n.action; + this.round = n.round || false; + this.minin = Number(n.minin); + this.maxin = Number(n.maxin); + this.minout = Number(n.minout); + this.maxout = Number(n.maxout); + var node = this; + + this.on('input', function (msg) { + var n = Number(msg.payload); + if (!isNaN(n)) { + if (node.action == "clamp") { + if (n < node.minin) { n = node.minin; } + if (n > node.maxin) { n = node.maxin; } + } + if (node.action == "roll") { + if (n >= node.maxin) { n = (n - node.minin) % (node.maxin - node.minin) + node.minin; } + if (n < node.minin) { n = (n - node.minin) % (node.maxin - node.minin) + node.maxin; } + } + msg.payload = ((n - node.minin) / (node.maxin - node.minin) * (node.maxout - node.minout)) + node.minout; + if (node.round) { msg.payload = Math.round(msg.payload); } + node.send(msg); + } + else { node.log("Not a number: "+msg.payload); } + }); + } + RED.nodes.registerType("range", RangeNode); +} diff --git a/dgbuilder/core_nodes/parsers/70-CSV.html b/dgbuilder/core_nodes/parsers/70-CSV.html new file mode 100644 index 00000000..5632246f --- /dev/null +++ b/dgbuilder/core_nodes/parsers/70-CSV.html @@ -0,0 +1,123 @@ + +<!-- + Copyright 2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="csv"> + <div class="form-row"> + <label for="node-input-temp"><i class="fa fa-list"></i> Columns</label> + <input type="text" id="node-input-temp" placeholder="comma-separated column names"> + </div> + <div class="form-row"> + <label for="node-input-select-sep"><i class="fa fa-text-width"></i> Separator</label> + <select style="width: 150px" id="node-input-select-sep"> + <option value=",">comma</option> + <option value="\t">tab</option> + <option value=" ">space</option> + <option value=";">semicolon</option> + <option value=":">colon</option> + <option value="">other...</option> + </select> + <input style="width: 40px;" type="text" id="node-input-sep" pattern="."> + </div> + + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <hr align="middle"/> + <div class="form-row"> + <label style="width: 100%;"><i class="fa fa-gears"></i> CSV-to-Object options</label> + <label style="margin-left: 10px; margin-right: -10px;"><i class="fa fa-sign-in"></i> Input</label> + <input style="width: 30px" type="checkbox" id="node-input-hdrin"><label style="width: auto;" for="node-input-hdrin">first row contains column names</span> + </div> + <div class="form-row"> + <label style="margin-left: 10px; margin-right: -10px;"><i class="fa fa-sign-out"></i> Output</label> + <select type="text" id="node-input-multi" style="width: 250px;"> + <option value="one">a message per row</option> + <option value="mult">a single message [array]</option> + </select> + </div> + <hr align="middle"/> + <div class="form-row"> + <label style="width: 100%;"><i class="fa fa-gears"></i> Object-to-CSV options</label> + <label style="margin-left: 10px; margin-right: -10px;"><i class="fa fa-sign-in"></i> Output</label> + <input style="width: 30px" type="checkbox" id="node-input-hdrout"><label style="width: auto;" for="node-input-hdrout">include column name row</span> + </div> + <div class="form-row"> + <label style="margin-left: 10px; margin-right: -10px;"><i class="fa fa-align-left"></i> Newline</label> + <select style="width: 150px" id="node-input-ret"> + <option value='\n'>Linux (\n)</option> + <option value='\r'>Mac (\r)</option> + <option value='\r\n'>Windows (\r\n)</option> + </select> + </div> +</script> + +<script type="text/x-red" data-help-name="csv"> + <p>A function that parses the <b>msg.payload</b> to convert csv to/from a javascript object. + Places the result in the payload.</p> + <p>If the input is a string it tries to parse it as CSV and creates a javascript object.</p> + <p>If the input is a javascript object it tries to build a CSV string.</p> + <p>The columns template should contain an ordered list of column headers. For csv input these become the property names. + For csv output these specify the properties to extract from the object and the order for the csv.</p> + <p><b>Note:</b> the columns should always be specified comma separated - even if another separator is chosen for the data.</p> + </script> + +<script type="text/javascript"> + RED.nodes.registerType('csv',{ + category: 'function', + color:"#DEBD5C", + defaults: { + name: {value:""}, + sep: {value:',',required:true,validate:RED.validators.regex(/^.{1,2}$/)}, + //quo: {value:'"',required:true}, + hdrin: {value:""}, + hdrout: {value:""}, + multi: {value:"one",required:true}, + ret: {value:'\\n'}, + temp: {value:""} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name||"csv"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + if (this.sep == "," || this.sep == "\\t" || this.sep == ";" || this.sep == ":" || this.sep == " ") { + $("#node-input-select-sep").val(this.sep); + $("#node-input-sep").hide(); + } else { + $("#node-input-select-sep").val(""); + $("#node-input-sep").val(this.sep); + $("#node-input-sep").show(); + } + $("#node-input-select-sep").change(function() { + var v = $("#node-input-select-sep option:selected").val(); + $("#node-input-sep").val(v); + if (v == "") { + $("#node-input-sep").val(""); + $("#node-input-sep").show().focus(); + } else { + $("#node-input-sep").hide(); + } + }); + } + }); +</script> diff --git a/dgbuilder/core_nodes/parsers/70-CSV.js b/dgbuilder/core_nodes/parsers/70-CSV.js new file mode 100644 index 00000000..56aa7c72 --- /dev/null +++ b/dgbuilder/core_nodes/parsers/70-CSV.js @@ -0,0 +1,157 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + function CSVNode(n) { + RED.nodes.createNode(this,n); + this.template = n.temp.split(","); + this.sep = (n.sep || ',').replace("\\t","\t").replace("\\n","\n").replace("\\r","\r"); + this.quo = '"'; + this.ret = (n.ret || "\n").replace("\\n","\n").replace("\\r","\r"); + this.winflag = (this.ret === "\r\n"); + this.lineend = "\n"; + this.multi = n.multi || "one"; + this.hdrin = n.hdrin || false; + this.hdrout = n.hdrout || false; + this.goodtmpl = true; + var node = this; + + // pass in an array of column names to be trimed, de-quoted and retrimed + var clean = function(col) { + for (var t = 0; t < col.length; t++) { + col[t] = col[t].trim(); // remove leading and trailing whitespace + if (col[t].charAt(0) === '"' && col[t].charAt(col[t].length -1) === '"') { + // remove leading and trailing quotes (if they exist) - and remove whitepace again. + col[t] = col[t].substr(1,col[t].length -2).trim(); + } + } + if ((col.length === 1) && (col[0] === "")) { node.goodtmpl = false; } + else { node.goodtmpl = true; } + return col; + } + node.template = clean(node.template); + + this.on("input", function(msg) { + if (msg.hasOwnProperty("payload")) { + if (typeof msg.payload == "object") { // convert object to CSV string + try { + var ou = ""; + if (node.hdrout) { + ou += node.template.join(node.sep) + node.ret; + } + if (!Array.isArray(msg.payload)) { msg.payload = [ msg.payload ]; } + for (var s = 0; s < msg.payload.length; s++) { + for (var t=0; t < node.template.length; t++) { + + // aaargh - resorting to eval here - but fairly contained front and back. + var p = RED.util.ensureString(eval("msg.payload[s]."+node.template[t])); + + if (p === "undefined") { p = ""; } + if (p.indexOf(node.sep) != -1) { // add quotes if any "commas" + ou += node.quo + p + node.quo + node.sep; + } + else if (p.indexOf(node.quo) != -1) { // add double quotes if any quotes + p = p.replace(/"/g, '""'); + ou += node.quo + p + node.quo + node.sep; + } + else { ou += p + node.sep; } // otherwise just add + } + ou = ou.slice(0,-1) + node.ret; // remove final "comma" and add "newline" + } + node.send({payload:ou}); + } + catch(e) { node.log(e); } + } + else if (typeof msg.payload == "string") { // convert CSV string to object + try { + var f = true; // flag to indicate if inside or outside a pair of quotes true = outside. + var j = 0; // pointer into array of template items + var k = [""]; // array of data for each of the template items + var o = {}; // output object to build up + var a = []; // output array is needed for multiline option + var first = true; // is this the first line + var tmp = ""; + + // For now we are just going to assume that any \r or \n means an end of line... + // got to be a weird csv that has singleton \r \n in it for another reason... + + // Now process the whole file/line + for (var i = 0; i < msg.payload.length; i++) { + if ((node.hdrin === true) && first) { // if the template is in the first line + if ((msg.payload[i] === "\n")||(msg.payload[i] === "\r")) { // look for first line break + node.template = clean(tmp.split(node.sep)); + first = false; + } + else { tmp += msg.payload[i]; } + } + else { + if (msg.payload[i] === node.quo) { // if it's a quote toggle inside or outside + f = !f; + if (msg.payload[i-1] === node.quo) { k[j] += '\"'; } // if it's a quotequote then it's actually a quote + } + else if ((msg.payload[i] === node.sep) && f) { // if we are outside of quote (ie valid separator + if (!node.goodtmpl) { node.template[j] = "col"+(j+1); } + if ( node.template[j] && (node.template[j] !== "") && (k[j] !== "" ) ) { + if (!isNaN(Number(k[j]))) { k[j] = Number(k[j]); } + o[node.template[j]] = k[j]; + } + j += 1; + k[j] = ""; + } + else if (f && ((msg.payload[i] === "\n") || (msg.payload[i] === "\r"))) { // handle multiple lines + //console.log(j,k,o,k[j]); + if ( node.template[j] && (node.template[j] !== "") && (k[j] !== "") ) { + if (!isNaN(Number(k[j]))) { k[j] = Number(k[j]); } + else { k[j].replace(/\r$/,''); } + o[node.template[j]] = k[j]; + } + if (JSON.stringify(o) !== "{}") { // don't send empty objects + if (node.multi === "one") { node.send({payload:o}); } // either send + else { a.push(o); } // or add to the array + } + j = 0; + k = [""]; + o = {}; + } + else { // just add to the part of the message + k[j] += msg.payload[i]; + } + } + } + // Finished so finalize and send anything left + //console.log(j,k,o,k[j]); + if (!node.goodtmpl) { node.template[j] = "col"+(j+1); } + if ( node.template[j] && (node.template[j] !== "") && (k[j] !== "") ) { + if (!isNaN(Number(k[j]))) { k[j] = Number(k[j]); } + else { k[j].replace(/\r$/,''); } + o[node.template[j]] = k[j]; + } + msg.payload = o; + if (JSON.stringify(o) !== "{}") { // don't send empty objects + if (node.multi === "one") { node.send({payload:o}); } // either send + else { a.push(o); } // or add to the aray + } + if (node.multi !== "one") { node.send({payload:a}); } // finally send the array + } + catch(e) { node.log(e); } + } + else { node.log("This node only handles csv strings or js objects."); } + } + }); + } + RED.nodes.registerType("csv",CSVNode); +} diff --git a/dgbuilder/core_nodes/parsers/70-HTML.html b/dgbuilder/core_nodes/parsers/70-HTML.html new file mode 100644 index 00000000..2b73b49c --- /dev/null +++ b/dgbuilder/core_nodes/parsers/70-HTML.html @@ -0,0 +1,73 @@ +<!-- + Copyright 2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="html"> + <div class="form-row"> + <label for="node-input-tag"><i class="fa fa-filter"></i> Select</label> + <input type="text" id="node-input-tag" placeholder="h1"> + </div> + <div class="form-row"> + <label for="node-input-ret"><i class="fa fa-sign-out"></i> Output</label> + <select id="node-input-ret" style="width:73% !important"> + <option value="html">the html content of the elements</option> + <option value="text">only the text content of the elements</option> + <!-- <option value="attr">an object of any attributes</option> --> + <!-- <option value="val">return the value from a form element</option> --> + </select> + </div> + <div class="form-row"> + <label for="node-input-as"> </label> + <select id="node-input-as" style="width:73% !important"> + <option value="single">as a single message containing an array</option> + <option value="multi">as multiple messages, one for each element</option> + </select> + </div> + <br/> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">Tip: The <b>Select</b> value is a <a href="http://api.jquery.com/category/selectors/" target="_new"><i><u>jQuery</u></i></a> style selector.</div> +</script> + +<script type="text/x-red" data-help-name="html"> + <p>Extracts elements from an html document held in <b>msg.payload</b> using a selector.</p> + <p>The selector uses the <a href="http://api.jquery.com/category/selectors/" target="_new">jQuery syntax</a>.</p> + <p>The result is either a single message with a payload containing an array of the matched elements, or multiple + messages that each contain a matched element.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('html',{ + category: 'function', + color:"#DEBD5C", + defaults: { + tag: {value:""}, + ret: {value:"html"}, + as: {value:"single"}, + name: {value:""} + }, + inputs:1, + outputs:1, + icon: "jq.png", + label: function() { + return this.name||this.tag||"html"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/parsers/70-HTML.js b/dgbuilder/core_nodes/parsers/70-HTML.js new file mode 100644 index 00000000..7a9450f3 --- /dev/null +++ b/dgbuilder/core_nodes/parsers/70-HTML.js @@ -0,0 +1,60 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var cheerio = require('cheerio'); + + function CheerioNode(n) { + RED.nodes.createNode(this,n); + this.tag = n.tag || "h1"; + this.ret = n.ret || "html"; + this.as = n.as || "single"; + var node = this; + this.on("input", function(msg) { + try { + var $ = cheerio.load(msg.payload); + var pay = []; + $(node.tag).each(function() { + if (node.as === "multi") { + var pay2 = null; + if (node.ret === "html") { pay2 = $(this).html(); } + if (node.ret === "text") { pay2 = $(this).text(); } + //if (node.ret === "attr") { pay2 = $(this)[0]["attribs"]; } + //if (node.ret === "val") { pay2 = $(this).val(); } + if (pay2) { + msg.payload = pay2; + node.send(msg); + } + } + if (node.as === "single") { + if (node.ret === "html") { pay.push( $(this).html() ); } + if (node.ret === "text") { pay.push( $(this).text() ); } + //if (node.ret === "attr") { pay.push( $(this)[0]["attribs"] ); } + //if (node.ret === "val") { pay.push( $(this).val() ); } + } + }); + if ((node.as === "single") && (pay.length !== 0)) { + msg.payload = pay; + node.send(msg); + } + } catch (error) { + node.log('Error: '+error.message); + } + }); + } + RED.nodes.registerType("html",CheerioNode); +} diff --git a/dgbuilder/core_nodes/parsers/70-JSON.html b/dgbuilder/core_nodes/parsers/70-JSON.html new file mode 100644 index 00000000..864974ab --- /dev/null +++ b/dgbuilder/core_nodes/parsers/70-JSON.html @@ -0,0 +1,47 @@ +<!-- + Copyright 2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="json"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="json"> + <p>A function that parses the <b>msg.payload</b> to convert a JSON string to/from a javascript object. Places the result back into the payload.</p> + <p>If the input is a JSON string it tries to parse it to a javascript object.</p> + <p>If the input is a javascript object it creates a JSON string.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('json',{ + category: 'function', + color:"#DEBD5C", + defaults: { + name: {value:""} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name||"json"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/parsers/70-JSON.js b/dgbuilder/core_nodes/parsers/70-JSON.js new file mode 100644 index 00000000..e216bd4f --- /dev/null +++ b/dgbuilder/core_nodes/parsers/70-JSON.js @@ -0,0 +1,46 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + + function JSONNode(n) { + RED.nodes.createNode(this,n); + var node = this; + this.on("input", function(msg) { + if (msg.hasOwnProperty("payload")) { + if (typeof msg.payload === "string") { + try { + msg.payload = JSON.parse(msg.payload); + node.send(msg); + } + catch(e) { node.log(e+ "\n"+msg.payload); } + } + else if (typeof msg.payload === "object") { + if (!Buffer.isBuffer(msg.payload) ) { + if (!util.isArray(msg.payload)) { + msg.payload = JSON.stringify(msg.payload); + node.send(msg); + } + } + } + else { node.log("dropped: "+msg.payload); } + } + }); + } + RED.nodes.registerType("json",JSONNode); +} diff --git a/dgbuilder/core_nodes/parsers/70-XML.html b/dgbuilder/core_nodes/parsers/70-XML.html new file mode 100644 index 00000000..8b0a2843 --- /dev/null +++ b/dgbuilder/core_nodes/parsers/70-XML.html @@ -0,0 +1,48 @@ +<!-- + Copyright 2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="xml"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="xml"> + <p>A function that parses the <b>msg.payload</b> to convert xml to/from a javascript object. Places the result in the payload.</p> + <p>If the input is a string it tries to parse it as XML and creates a javascript object.</p> + <p>If the input is a javascript object it tries to build an XML string.</p> + <p>See <a href="https://github.com/Leonidas-from-XIV/node-xml2js/blob/master/README.md" target="_new">the xml2js docs <i>here</i></a> for more information.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('xml',{ + category: 'function', + color:"#DEBD5C", + defaults: { + name: {value:""} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name||"xml"; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/parsers/70-XML.js b/dgbuilder/core_nodes/parsers/70-XML.js new file mode 100644 index 00000000..931de7f5 --- /dev/null +++ b/dgbuilder/core_nodes/parsers/70-XML.js @@ -0,0 +1,46 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var xml2js = require('xml2js'); + var parseString = xml2js.parseString; + var builder = new xml2js.Builder({renderOpts:{pretty:false}}); + + function XMLNode(n) { + RED.nodes.createNode(this,n); + var node = this; + this.on("input", function(msg) { + if (msg.hasOwnProperty("payload")) { + if (typeof msg.payload == "object") { + msg.payload = builder.buildObject(msg.payload); + node.send(msg); + } + else if (typeof msg.payload == "string") { + parseString(msg.payload, {strict:true,async:true}, function (err, result) { + if (err) { node.error(err); } + else { + msg.payload = result; + node.send(msg); + } + }); + } + else { node.log("This node only handles xml strings or js objects."); } + } + }); + } + RED.nodes.registerType("xml",XMLNode); +} diff --git a/dgbuilder/core_nodes/social/27-twitter.html b/dgbuilder/core_nodes/social/27-twitter.html new file mode 100644 index 00000000..99d45213 --- /dev/null +++ b/dgbuilder/core_nodes/social/27-twitter.html @@ -0,0 +1,223 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="twitter-credentials"> + <div class="form-row" id="node-config-twitter-row"></div> + <input type="hidden" id="node-config-input-screen_name"> +</script> + +<script type="text/javascript"> +(function() { + var twitterConfigNodeId = null; + var twitterConfigNodeIntervalId = null; + + function showTwitterAuthStart() { + var pathname = document.location.pathname; + if (pathname.slice(-1) != "/") { + pathname += "/"; + } + var callback = encodeURIComponent(location.protocol+"//"+location.hostname+":"+location.port+pathname+"twitter-credentials/"+twitterConfigNodeId+"/auth/callback"); + $("#node-config-dialog-ok").button("disable"); + $("#node-config-twitter-row").html('<div style="text-align: center; margin-top: 20px; "><a class="btn" id="node-config-twitter-start" href="twitter-credentials/'+twitterConfigNodeId+'/auth?callback='+callback+'" target="_blank">Click here to authenticate with Twitter.</a></div>'); + $("#node-config-twitter-start").click(function() { + twitterConfigNodeIntervalId = window.setTimeout(pollTwitterCredentials,2000); + }); + } + function updateTwitterScreenName(sn) { + $("#node-config-input-screen_name").val(sn); + $("#node-config-twitter-row").html('<label><i class="fa fa-user"></i> Twitter ID</label><span class="input-xlarge uneditable-input">'+sn+'</span>'); + } + function pollTwitterCredentials(e) { + $.getJSON('credentials/twitter-credentials/'+twitterConfigNodeId,function(data) { + if (data.screen_name) { + updateTwitterScreenName(data.screen_name); + twitterConfigNodeIntervalId = null; + $("#node-config-dialog-ok").button("enable"); + } else { + twitterConfigNodeIntervalId = window.setTimeout(pollTwitterCredentials,2000); + } + }) + } + RED.nodes.registerType('twitter-credentials',{ + category: 'config', + defaults: { + screen_name: {value:""} + }, + credentials: { + screen_name: {type:"text"}, + access_token: {type: "password"}, + access_token_secret: {type:"password"} + }, + + label: function() { + return this.screen_name; + }, + exportable: false, + oneditprepare: function() { + twitterConfigNodeId = this.id; + if (!this.screen_name || this.screen_name == "") { + showTwitterAuthStart(); + } else { + if (this.credentials.screen_name) { + updateTwitterScreenName(this.credentials.screen_name); + } else { + showTwitterAuthStart(); + } + } + }, + oneditsave: function() { + if (twitterConfigNodeIntervalId) { + window.clearTimeout(twitterConfigNodeIntervalId); + } + }, + oneditcancel: function(adding) { + if (twitterConfigNodeIntervalId) { + window.clearTimeout(twitterConfigNodeIntervalId); + } + } + }); +})(); +</script> + +<script type="text/x-red" data-template-name="twitter in"> + <div class="form-row"> + <label for="node-input-twitter"><i class="fa fa-user"></i> Log in as</label> + <input type="text" id="node-input-twitter"> + </div> + <div class="form-row"> + <label for="node-input-user"><i class="fa fa-search"></i> Search</label> + <select type="text" id="node-input-user" style="display: inline-block; vertical-align: middle; width:60%;"> + <option value="false">all public tweets</option> + <option value="true">the tweets of who you follow</option> + <option value="user">the tweets of specific users</option> + <option value="dm">your direct messages</option> + </select> + </div> + <div class="form-row" id="node-input-tags-row"> + <label for="node-input-tags"><i class="fa fa-tags"></i> <span id="node-input-tags-label">for</span></label> + <input type="text" id="node-input-tags" placeholder="comma-separated words, @ids, #tags"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">Tip: Use commas without spaces between multiple search terms. Comma = OR, Space = AND. + <br/>The Twitter API WILL NOT deliver 100% of all tweets. + <br/>Tweets of who you follow will include their retweets and favourites.</div> +</script> + +<script type="text/x-red" data-help-name="twitter in"> + <p>Twitter input node. Can be used to search either: + <ul><li>the public or a user's stream for tweets containing the configured search term</li> + <li>all tweets by specific users</li> + <li>direct messages received by the authenticated user</li> + </ul></p> + <p>Use space for <i>and</i> and comma , for <i>or</i> when searching for multiple terms.</p> + <p>Sets the <b>msg.topic</b> to <i>tweets/</i> and then appends the senders screen name.</p> + <p>Sets <b>msg.location</b> to the tweeters location if known.</p> + <p>Sets <b>msg.tweet</b> to the full tweet object as documented by <a href="https://dev.twitter.com/docs/platform-objects/tweets">Twitter</a>. + <p><b>Note:</b> when set to a specific user's tweets, or your direct messages, the node is subject to + Twitter's API rate limiting. If you deploy the flows multiple times within a 15 minute window, you may + exceed the limit and will see errors from the node. These errors will clear when the current 15 minute window + passes.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('twitter in',{ + category: 'social-input', + color:"#C0DEED", + defaults: { + twitter: {type:"twitter-credentials",required:true}, + tags: {value:"",validate:function(v) { return this.user == "dm" || v.length > 0;}}, + user: {value:"false",required:true}, + name: {value:""}, + topic: {value:"tweets"} + }, + inputs:0, + outputs:1, + icon: "twitter.png", + label: function() { + if (this.name) { + return this.name; + } + if (this.user == "dm") { + var user = RED.nodes.node(this.twitter); + return (user?user.label()+" ":"")+"DMs"; + } else if (this.user == "user") { + return this.tags+" tweets"; + } + return this.tags; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + $("#node-input-user").change(function() { + var type = $("#node-input-user option:selected").val(); + if (type == "user") { + $("#node-input-tags-row").show(); + $("#node-input-tags-label").html("User"); + $("#node-input-tags").attr("placeholder","comma-separated @twitter handles"); + } else if (type == "dm") { + $("#node-input-tags-row").hide(); + } else { + $("#node-input-tags-row").show(); + $("#node-input-tags-label").html("for"); + $("#node-input-tags").attr("placeholder","comma-separated words, @ids, #hashtags"); + } + + }); + $("#node-input-user").change(); + + } + }); +</script> + + +<script type="text/x-red" data-template-name="twitter out"> + <div class="form-row"> + <label for="node-input-twitter"><i class="fa fa-user"></i> Twitter</label> + <input type="text" id="node-input-twitter"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="twitter out"> + <p>Twitter out node. Tweets the <b>msg.payload</b>.</p> + <p>If <b>msg.media</b> exists and is a Buffer object, this node will treat it + as an image and attach it to the tweet.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('twitter out',{ + category: 'social-output', + color:"#C0DEED", + defaults: { + twitter: {type:"twitter-credentials",required:true}, + name: {value:"Tweet"} + }, + inputs:1, + outputs:0, + icon: "twitter.png", + align: "right", + label: function() { + return this.name; + } + }); +</script> diff --git a/dgbuilder/core_nodes/social/27-twitter.js b/dgbuilder/core_nodes/social/27-twitter.js new file mode 100644 index 00000000..5cacd9eb --- /dev/null +++ b/dgbuilder/core_nodes/social/27-twitter.js @@ -0,0 +1,347 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var ntwitter = require('twitter-ng'); + var OAuth= require('oauth').OAuth; + var request = require('request'); + + function TwitterNode(n) { + RED.nodes.createNode(this,n); + this.screen_name = n.screen_name; + } + RED.nodes.registerType("twitter-credentials",TwitterNode,{ + credentials: { + screen_name: {type:"text"}, + access_token: {type: "password"}, + access_token_secret: {type:"password"} + } + }); + + function TwitterInNode(n) { + RED.nodes.createNode(this,n); + this.active = true; + this.user = n.user; + //this.tags = n.tags.replace(/ /g,''); + this.tags = n.tags; + this.twitter = n.twitter; + this.topic = n.topic||"tweets"; + this.twitterConfig = RED.nodes.getNode(this.twitter); + var credentials = RED.nodes.getCredentials(this.twitter); + + if (credentials && credentials.screen_name == this.twitterConfig.screen_name) { + var twit = new ntwitter({ + consumer_key: "OKjYEd1ef2bfFolV25G5nQ", + consumer_secret: "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g", + access_token_key: credentials.access_token, + access_token_secret: credentials.access_token_secret + }); + + + //setInterval(function() { + // twit.get("/application/rate_limit_status.json",null,function(err,cb) { + // console.log("direct_messages:",cb["resources"]["direct_messages"]); + // }); + // + //},10000); + + var node = this; + if (this.user === "user") { + node.poll_ids = []; + node.since_ids = {}; + var users = node.tags.split(","); + for (var i=0;i<users.length;i++) { + var user = users[i].replace(" ",""); + twit.getUserTimeline({ + screen_name:user, + trim_user:0, + count:1 + },function() { + var u = user+""; + return function(err,cb) { + if (err) { + node.error(err); + return; + } + if (cb[0]) { + node.since_ids[u] = cb[0].id_str; + } else { + node.since_ids[u] = '0'; + } + node.poll_ids.push(setInterval(function() { + twit.getUserTimeline({ + screen_name:u, + trim_user:0, + since_id:node.since_ids[u] + },function(err,cb) { + if (cb) { + for (var t=cb.length-1;t>=0;t-=1) { + var tweet = cb[t]; + var where = tweet.user.location||""; + var la = tweet.lang || tweet.user.lang; + //console.log(tweet.user.location,"=>",tweet.user.screen_name,"=>",pay); + var msg = { topic:node.topic+"/"+tweet.user.screen_name, payload:tweet.text, location:where, lang:la, tweet:tweet }; + node.send(msg); + if (t == 0) { + node.since_ids[u] = tweet.id_str; + } + } + } + if (err) { + node.error(err); + } + }); + },60000)); + } + }()); + } + } else if (this.user === "dm") { + node.poll_ids = []; + twit.getDirectMessages({ + screen_name:node.twitterConfig.screen_name, + trim_user:0, + count:1 + },function(err,cb) { + if (err) { + node.error(err); + return; + } + if (cb[0]) { + node.since_id = cb[0].id_str; + } else { + node.since_id = '0'; + } + node.poll_ids.push(setInterval(function() { + twit.getDirectMessages({ + screen_name:node.twitterConfig.screen_name, + trim_user:0, + since_id:node.since_id + },function(err,cb) { + if (cb) { + for (var t=cb.length-1;t>=0;t-=1) { + var tweet = cb[t]; + var msg = { topic:node.topic+"/"+tweet.sender.screen_name, payload:tweet.text, tweet:tweet }; + node.send(msg); + if (t == 0) { + node.since_id = tweet.id_str; + } + } + } + if (err) { + node.error(err); + } + }); + },120000)); + }); + + } else if (this.tags !== "") { + try { + var thing = 'statuses/filter'; + if (this.user === "true") { thing = 'user'; } + var st = { track: [node.tags] }; + var bits = node.tags.split(","); + if ((bits.length > 0) && (bits.length % 4 == 0)) { + if ((Number(bits[0]) < Number(bits[2])) && (Number(bits[1]) < Number(bits[3]))) { + st = { locations: node.tags }; + } + else { + node.log("possible bad geo area format. Should be lower-left lon, lat, upper-right lon, lat"); + } + } + + var setupStream = function() { + if (node.active) { + twit.stream(thing, st, function(stream) { + //console.log(st); + //twit.stream('user', { track: [node.tags] }, function(stream) { + //twit.stream('site', { track: [node.tags] }, function(stream) { + //twit.stream('statuses/filter', { track: [node.tags] }, function(stream) { + node.stream = stream; + stream.on('data', function(tweet) { + //console.log(tweet.user); + if (tweet.user !== undefined) { + var where = tweet.user.location||""; + var la = tweet.lang || tweet.user.lang; + //console.log(tweet.user.location,"=>",tweet.user.screen_name,"=>",pay); + var msg = { topic:node.topic+"/"+tweet.user.screen_name, payload:tweet.text, location:where, lang:la, tweet:tweet }; + node.send(msg); + } + }); + stream.on('limit', function(tweet) { + node.log("tweet rate limit hit"); + }); + stream.on('error', function(tweet,rc) { + if (rc == 420) { + node.warn("Twitter rate limit hit"); + } else { + node.warn("Stream error:"+tweet.toString()+" ("+rc+")"); + } + setTimeout(setupStream,10000); + }); + stream.on('destroy', function (response) { + if (this.active) { + node.warn("twitter ended unexpectedly"); + setTimeout(setupStream,10000); + } + }); + }); + } + } + setupStream(); + } + catch (err) { + node.error(err); + } + } else { + this.error("Invalid tag property"); + } + } else { + this.error("missing twitter credentials"); + } + + this.on('close', function() { + if (this.stream) { + this.active = false; + this.stream.destroy(); + } + if (this.poll_ids) { + for (var i=0;i<this.poll_ids.length;i++) { + clearInterval(this.poll_ids[i]); + } + } + }); + } + RED.nodes.registerType("twitter in",TwitterInNode); + + + function TwitterOutNode(n) { + RED.nodes.createNode(this,n); + this.topic = n.topic; + this.twitter = n.twitter; + this.twitterConfig = RED.nodes.getNode(this.twitter); + var credentials = RED.nodes.getCredentials(this.twitter); + var node = this; + + if (credentials && credentials.screen_name == this.twitterConfig.screen_name) { + var twit = new ntwitter({ + consumer_key: "OKjYEd1ef2bfFolV25G5nQ", + consumer_secret: "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g", + access_token_key: credentials.access_token, + access_token_secret: credentials.access_token_secret + }); + node.on("input", function(msg) { + node.status({fill:"blue",shape:"dot",text:"tweeting"}); + + if (msg.payload.length > 140) { + msg.payload = msg.payload.slice(0,139); + node.warn("Tweet greater than 140 : truncated"); + } + + if (msg.media && Buffer.isBuffer(msg.media)) { + var apiUrl = "https://api.twitter.com/1.1/statuses/update_with_media.json"; + var signedUrl = oa.signUrl(apiUrl, + credentials.access_token, + credentials.access_token_secret, + "POST"); + + var r = request.post(signedUrl,function(err,httpResponse,body) { + if (err) { + node.error(err.toString()); + node.status({fill:"red",shape:"ring",text:"failed"}); + } else { + var response = JSON.parse(body); + if (body.errors) { + var errorList = body.errors.map(function(er) { return er.code+": "+er.message }).join(", "); + node.error("tweet failed: "+errorList); + node.status({fill:"red",shape:"ring",text:"failed"}); + } else { + node.status({}); + } + } + }); + var form = r.form(); + form.append("status",msg.payload); + form.append("media[]",msg.media,{filename:"image"}); + + } else { + twit.updateStatus(msg.payload, function (err, data) { + if (err) { + node.status({fill:"red",shape:"ring",text:"failed"}); + node.error(err); + } + node.status({}); + }); + } + }); + } + } + RED.nodes.registerType("twitter out",TwitterOutNode); + + var oa = new OAuth( + "https://api.twitter.com/oauth/request_token", + "https://api.twitter.com/oauth/access_token", + "OKjYEd1ef2bfFolV25G5nQ", + "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g", + "1.0", + null, + "HMAC-SHA1" + ); + + RED.httpAdmin.get('/twitter-credentials/:id/auth', function(req, res){ + var credentials = {}; + oa.getOAuthRequestToken({ + oauth_callback: req.query.callback + },function(error, oauth_token, oauth_token_secret, results){ + if (error) { + var resp = '<h2>Oh no!</h2>'+ + '<p>Something went wrong with the authentication process. The following error was returned:<p>'+ + '<p><b>'+error.statusCode+'</b>: '+error.data+'</p>'+ + '<p>One known cause of this type of failure is if the clock is wrong on system running Node-RED.'; + res.send(resp) + } else { + credentials.oauth_token = oauth_token; + credentials.oauth_token_secret = oauth_token_secret; + res.redirect('https://twitter.com/oauth/authorize?oauth_token='+oauth_token) + RED.nodes.addCredentials(req.params.id,credentials); + } + }); + }); + + RED.httpAdmin.get('/twitter-credentials/:id/auth/callback', function(req, res, next){ + var credentials = RED.nodes.getCredentials(req.params.id); + credentials.oauth_verifier = req.query.oauth_verifier; + + oa.getOAuthAccessToken( + credentials.oauth_token, + credentials.token_secret, + credentials.oauth_verifier, + function(error, oauth_access_token, oauth_access_token_secret, results){ + if (error){ + console.log(error); + res.send("yeah something broke."); + } else { + credentials = {}; + credentials.access_token = oauth_access_token; + credentials.access_token_secret = oauth_access_token_secret; + credentials.screen_name = "@"+results.screen_name; + RED.nodes.addCredentials(req.params.id,credentials); + res.send("<html><head></head><body>Authorised - you can close this window and return to Node-RED</body></html>"); + } + } + ); + }); +} diff --git a/dgbuilder/core_nodes/social/32-feedparse.html b/dgbuilder/core_nodes/social/32-feedparse.html new file mode 100644 index 00000000..a7954277 --- /dev/null +++ b/dgbuilder/core_nodes/social/32-feedparse.html @@ -0,0 +1,57 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="feedparse"> + <div class="form-row"> + <label for="node-input-url"><i class="fa fa-globe"></i> Feed url</label> + <input type="text" id="node-input-url"> + </div> + <div class="form-row"> + <label for="node-input-interval"><i class="fa fa-repeat"></i> Repeat <span style="font-size: 0.9em;">(M)</span></label> + <input type="text" id="node-input-interval" placeholder="minutes"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <!-- <div class="form-tips"></div> --> +</script> + +<script type="text/x-red" data-help-name="feedparse"> + <p>Monitors an RSS/atom feed for new entries.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('feedparse',{ + category: 'advanced-input', + color:"#C0DEED", + defaults: { + name: {value:""}, + url: {value:"", required:true}, + interval: { value:15, required: true,validate:RED.validators.number()} + }, + inputs:0, + outputs:1, + icon: "feed.png", + label: function() { + return this.name||this.url; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); + +</script> diff --git a/dgbuilder/core_nodes/social/32-feedparse.js b/dgbuilder/core_nodes/social/32-feedparse.js new file mode 100644 index 00000000..97630e7d --- /dev/null +++ b/dgbuilder/core_nodes/social/32-feedparse.js @@ -0,0 +1,71 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var FeedParser = require("feedparser"); + var request = require("request"); + + function FeedParseNode(n) { + RED.nodes.createNode(this,n); + this.url = n.url; + this.interval = (parseInt(n.interval)||15)*60000; + var node = this; + this.interval_id = null; + this.seen = {}; + if (this.url !== "") { + var getFeed = function() { + request(node.url,function(err) { + if (err) node.error(err); + }) + .pipe(new FeedParser({feedurl:node.url})) + .on('error', function(error) { + node.error(error); + }) + .on('meta', function (meta) {}) + .on('readable', function () { + var stream = this, article; + while (article = stream.read()) { + if (!(article.guid in node.seen) || ( node.seen[article.guid] != 0 && node.seen[article.guid] != article.date.getTime())) { + node.seen[article.guid] = article.date?article.date.getTime():0; + var msg = { + topic:article.origlink||article.link, + payload: article.description, + article: article + }; + node.send(msg); + } + } + }) + .on('end', function () { + }); + }; + this.interval_id = setInterval(getFeed,node.interval); + getFeed(); + + } else { + this.error("Invalid url"); + } + } + + RED.nodes.registerType("feedparse",FeedParseNode); + + FeedParseNode.prototype.close = function() { + if (this.interval_id != null) { + clearInterval(this.interval_id); + } + } +} diff --git a/dgbuilder/core_nodes/social/61-email.html b/dgbuilder/core_nodes/social/61-email.html new file mode 100644 index 00000000..37397083 --- /dev/null +++ b/dgbuilder/core_nodes/social/61-email.html @@ -0,0 +1,189 @@ +<!-- + Copyright 2013,2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="e-mail"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-envelope"></i> To</label> + <input type="text" id="node-input-name" placeholder="email@address.com"> + </div> + <!-- <div class="form-row"> + <label for="node-input-pin"><i class="fa fa-asterisk"></i> Service</label> + <select type="text" id="node-input-pin" style="width: 150px;"> + <option value="-" disabled> </option> + <option value="DynectEmail">DynectEmail</option> + <option value="Gmail">Gmail</option> + <option value="hot.ee">hot.ee</option> + <option value="Hotmail">Hotmail</option> + <option value="iCloud">iCloud</option> + <option value="mail.ee">mail.ee</option> + <option value="Mail.Ru">Mail.Ru</option> + <option value="Mailgun">Mailgun</option> + <option value="Mailjet">Mailjet</option> + <option value="Mandrill">Mandrill</option> + <option value="Postmark">Postmark</option> + <option value="QQ">QQ</option> + <option value="QQex">QQex</option> + <option value="SendGrid">SendGrid</option> + <option value="SendCloud">SendCloud</option> + <option value="SES">SES</option> + <option value="Yahoo">Yahoo</option> + <option value="yandex">yandex</option> + <option value="Zoho">Zoho</option> + </select> + </div> --> + <div class="form-row"> + <label for="node-input-server"><i class="fa fa-globe"></i> Server</label> + <input type="text" id="node-input-server" placeholder="smtp.gmail.com"> + </div> + <div class="form-row"> + <label for="node-input-port"><i class="fa fa-random"></i> Port</label> + <input type="text" id="node-input-port" placeholder="465"> + </div> + <div class="form-row"> + <label for="node-input-userid"><i class="fa fa-user"></i> Userid</label> + <input type="text" id="node-input-userid"> + </div> + <div class="form-row"> + <label for="node-input-password"><i class="fa fa-lock"></i> Password</label> + <input type="password" id="node-input-password"> + </div> + <br/> + <div class="form-row"> + <label for="node-input-dname"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-dname" placeholder="Name"> + </div> + <div class="form-tips" id="node-tip"><b>Note:</b> Copied credentials from global emailkeys.js file.</div> +</script> + +<script type="text/x-red" data-help-name="e-mail"> + <p>Sends the <b>msg.payload</b> as an email, with a subject of <b>msg.topic</b>.</p> + <!-- <p>It sends the message to the configured recipient <i>only</i>.</p> --> + <p>You may dynamically overide the default recipient by setting a <b>msg.to</b> property.</p> + <!-- <p><b>msg.topic</b> is used to set the subject of the email, and <b>msg.payload</b> is the body text.</p> --> +</script> + +<script type="text/javascript"> +(function() { + RED.nodes.registerType('e-mail',{ + category: 'social-output', + color:"#c7e9c0", + defaults: { + server: {value:"smtp.gmail.com",required:true}, + port: {value:"465",required:true}, + name: {value:"",required:true}, + dname: {value:""} + }, + credentials: { + userid: {type:"text"}, + password: {type: "password"}, + global: { type:"boolean"} + }, + + inputs:1, + outputs:0, + icon: "envelope.png", + align: "right", + label: function() { + return this.dname||this.name||"email"; + }, + labelStyle: function() { + return (this.dname||!this.topic)?"node_label_italic":""; + }, + oneditprepare: function() { + if (this.credentials.global) { + $('#node-tip').show(); + } else { + $('#node-tip').hide(); + }; + } + }); +})(); +</script> + + +<script type="text/x-red" data-template-name="e-mail in"> + <div class="form-row node-input-repeat"> + <label for="node-input-repeat"><i class="fa fa-repeat"></i> Check Repeat (S)</label> + <input type="text" id="node-input-repeat" placeholder="300"> + </div> + <div class="form-row"> + <label for="node-input-server"><i class="fa fa-globe"></i> Server</label> + <input type="text" id="node-input-server" placeholder="imap.gmail.com"> + </div> + <div class="form-row"> + <label for="node-input-port"><i class="fa fa-random"></i> Port</label> + <input type="text" id="node-input-port" placeholder="993"> + </div> + <div class="form-row"> + <label for="node-input-userid"><i class="fa fa-user"></i> Userid</label> + <input type="text" id="node-input-userid"> + </div> + <div class="form-row"> + <label for="node-config-input-password"><i class="fa fa-lock"></i> Password</label> + <input type="password" id="node-input-password"> + </div> + <br/> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips" id="node-tip"><b>Note:</b> Copied credentials from global emailkeys.js file.</div> + <div id="node-input-tip" class="form-tips">Tip: <b>ONLY</b> retrieves the single most recent email.</div> +</script> + +<script type="text/x-red" data-help-name="e-mail in"> + <p>Repeatedly gets a <b>single email</b> from an IMAP server and forwards on as a msg if not already seen.</p> + <p>The subject is loaded into <b>msg.topic</b> and <b>msg.payload</b> is the plain text body. + If there is text/html then that is returned in <b>msg.html</b>. <b>msg.from</b> and <b>msg.date</b> are also set if you need them.</p> + <p>Uses the imap module.</p> + <p><b>Note:</b> this node <i>only</i> gets the most recent single email from the inbox, so set the repeat (polling) time appropriately.</p> +</script> + +<script type="text/javascript"> +(function() { + RED.nodes.registerType('e-mail in',{ + category: 'social-input', + color:"#c7e9c0", + defaults: { + repeat: {value:"300",required:true}, + server: {value:"imap.gmail.com",required:true}, + port: {value:"993",required:true}, + name: {value:""} + }, + credentials: { + userid: {type:"text"}, + password: {type: "password"}, + global: { type:"boolean"} + }, + inputs:0, + outputs:1, + icon: "envelope.png", + label: function() { + return this.name||"email"; + }, + labelStyle: function() { + return (this.name||!this.topic)?"node_label_italic":""; + }, + oneditprepare: function() { + if (this.credentials.global) { + $('#node-tip').show(); + } else { + $('#node-tip').hide(); + }; + } + }); +})(); +</script> diff --git a/dgbuilder/core_nodes/social/61-email.js b/dgbuilder/core_nodes/social/61-email.js new file mode 100644 index 00000000..7d0f8cb9 --- /dev/null +++ b/dgbuilder/core_nodes/social/61-email.js @@ -0,0 +1,246 @@ +/** + * Copyright 2013,2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var nodemailer = require("nodemailer"); + var Imap = require('imap'); + + //console.log(nodemailer.Transport.transports.SMTP.wellKnownHosts); + + try { + var globalkeys = RED.settings.email || require(process.env.NODE_RED_HOME+"/../emailkeys.js"); + } catch(err) { + } + + function EmailNode(n) { + RED.nodes.createNode(this,n); + this.topic = n.topic; + this.name = n.name; + this.outserver = n.server; + this.outport = n.port; + var flag = false; + if (this.credentials && this.credentials.hasOwnProperty("userid")) { + this.userid = this.credentials.userid; + } else { + if (globalkeys) { + this.userid = globalkeys.user; + flag = true; + } else { + this.error("No e-mail userid set"); + } + } + if (this.credentials && this.credentials.hasOwnProperty("password")) { + this.password = this.credentials.password; + } else { + if (globalkeys) { + this.password = globalkeys.pass; + flag = true; + } else { + this.error("No e-mail password set"); + } + } + if (flag) { + RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true}); + } + var node = this; + + var smtpTransport = nodemailer.createTransport({ + host: node.outserver, + port: node.outport, + secure: true, + auth: { + user: node.userid, + pass: node.password + } + }); + + this.on("input", function(msg) { + if (smtpTransport) { + node.status({fill:"blue",shape:"dot",text:"sending"}); + var payload = RED.util.ensureString(msg.payload); + smtpTransport.sendMail({ + from: node.userid, // sender address + to: msg.to || node.name, // comma separated list of addressees + subject: msg.topic, // subject line + text: payload // plaintext body + }, function(error, info) { + if (error) { + node.error(error); + node.status({fill:"red",shape:"ring",text:"send failed"}); + } else { + node.log("Message sent: " + info.response); + node.status({}); + } + }); + } + else { node.warn("No Email credentials found. See info panel."); } + }); + } + RED.nodes.registerType("e-mail",EmailNode,{ + credentials: { + userid: {type:"text"}, + password: {type: "password"}, + global: { type:"boolean"} + } + }); + + function EmailInNode(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.repeat = n.repeat * 1000 || 300000; + this.inserver = n.server || globalkeys.server || "imap.gmail.com"; + this.inport = n.port || globalkeys.port || "993"; + var flag = false; + + if (this.credentials && this.credentials.hasOwnProperty("userid")) { + this.userid = this.credentials.userid; + } else { + if (globalkeys) { + this.userid = globalkeys.user; + flag = true; + } else { + this.error("No e-mail userid set"); + } + } + if (this.credentials && this.credentials.hasOwnProperty("password")) { + this.password = this.credentials.password; + } else { + if (globalkeys) { + this.password = globalkeys.pass; + flag = true; + } else { + this.error("No e-mail password set"); + } + } + if (flag) { + RED.nodes.addCredentials(n.id,{userid:this.userid, password:this.password, global:true}); + } + + var node = this; + this.interval_id = null; + var oldmail = {}; + + var imap = new Imap({ + user: node.userid, + password: node.password, + host: node.inserver, + port: node.inport, + tls: true, + tlsOptions: { rejectUnauthorized: false }, + connTimeout: node.repeat, + authTimeout: node.repeat + }); + + if (!isNaN(this.repeat) && this.repeat > 0) { + node.log("repeat = "+this.repeat); + this.interval_id = setInterval( function() { + node.emit("input",{}); + }, this.repeat ); + } + + this.on("input", function(msg) { + imap.once('ready', function() { + node.status({fill:"blue",shape:"dot",text:"fetching"}); + var pay = {}; + imap.openBox('INBOX', true, function(err, box) { + if (box.messages.total > 0) { + var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM SUBJECT DATE)','TEXT'] }); + f.on('message', function(msg, seqno) { + node.log('message: #'+ seqno); + var prefix = '(#' + seqno + ') '; + msg.on('body', function(stream, info) { + var buffer = ''; + stream.on('data', function(chunk) { + buffer += chunk.toString('utf8'); + }); + stream.on('end', function() { + if (info.which !== 'TEXT') { + pay.from = Imap.parseHeader(buffer).from[0]; + pay.topic = Imap.parseHeader(buffer).subject[0]; + pay.date = Imap.parseHeader(buffer).date[0]; + } else { + var parts = buffer.split("Content-Type"); + for (var p = 0; p < parts.length; p++) { + if (parts[p].indexOf("text/plain") >= 0) { + pay.payload = parts[p].split("\n").slice(1,-2).join("\n").trim(); + } + if (parts[p].indexOf("text/html") >= 0) { + pay.html = parts[p].split("\n").slice(1,-2).join("\n").trim(); + } + } + //pay.body = buffer; + } + }); + }); + msg.on('end', function() { + //node.log('Finished: '+prefix); + }); + }); + f.on('error', function(err) { + node.warn('fetch error: ' + err); + node.status({fill:"red",shape:"ring",text:"fetch error"}); + }); + f.on('end', function() { + if (JSON.stringify(pay) !== oldmail) { + node.send(pay); + oldmail = JSON.stringify(pay); + node.log('received new email: '+pay.topic); + } + else { node.log('duplicate not sent: '+pay.topic); } + //node.status({fill:"green",shape:"dot",text:"ok"}); + node.status({}); + imap.end(); + }); + } + else { + node.log("you have achieved inbox zero"); + //node.status({fill:"green",shape:"dot",text:"ok"}); + node.status({}); + imap.end(); + } + }); + }); + node.status({fill:"grey",shape:"dot",text:"connecting"}); + imap.connect(); + }); + + imap.on('error', function(err) { + node.log(err); + node.status({fill:"red",shape:"ring",text:"connect error"}); + }); + + this.on("error", function(err) { + node.log("error: ",err); + }); + + this.on("close", function() { + if (this.interval_id != null) { + clearInterval(this.interval_id); + } + if (imap) { imap.destroy(); } + }); + + node.emit("input",{}); + } + RED.nodes.registerType("e-mail in",EmailInNode,{ + credentials: { + userid: {type:"text"}, + password: {type: "password"}, + global: { type:"boolean"} + } + }); +} diff --git a/dgbuilder/core_nodes/social/91-irc.html b/dgbuilder/core_nodes/social/91-irc.html new file mode 100644 index 00000000..11112374 --- /dev/null +++ b/dgbuilder/core_nodes/social/91-irc.html @@ -0,0 +1,206 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="irc in"> + <div class="form-row"> + <label for="node-input-ircserver"><i class="fa fa-globe"></i> IRC Server</label> + <input type="text" id="node-input-ircserver"> + </div> + <div class="form-row"> + <label for="node-input-channel"><i class="fa fa-random"></i> Channel</label> + <input type="text" id="node-input-channel" placeholder="#nodered"> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">The channel to join must start with a # (as per normal irc rules...)<br/> + You may join multiple channels by comma separating a list - #chan1,#chan2,etc.</div> +</script> + +<script type="text/x-red" data-help-name="irc in"> + <p>Connects to a channel on an IRC server.</p> + <p>You may join multiple channels by comma separating a list - #chan1,#chan2,#etc.</p> + <p>Any messages on that channel will appear on the <code>msg.payload</code> at the output, + while <code>msg.topic</code> will contain who it is from. + <code>msg.to</code> contains either the name of the channel or PRIV in the case of a pm.</p> + <p>The second output provides a <code>msg.payload</code> that has any status messages such as joins, parts, kicks etc.</p> + <p>The type of the status message is set as <code>msg.payload.type</code>.</p> + <p>The possible status types are: <br /> + <table border="1" cellpadding="1" cellspacing="1"> + <thead> + <tr> + <th scope="col">Type</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td>message</td> + <td>message is sent into the channel</td> + </tr> + <tr> + <td>pm</td> + <td>private message to the bot</td> + </tr> + <tr> + <td>join</td> + <td>a user joined the channel (also triggered when the bot joins a channel)</td> + </tr> + <tr> + <td>invite</td> + <td>the bot is being invited to a channel</td> + </tr> + <tr> + <td>part</td> + <td>a user leaves a channel</td> + </tr> + <tr> + <td>quit</td> + <td>a user quits a channel</td> + </tr> + <tr> + <td>kick</td> + <td>a user is kicked from a channel</td> + </tr> + <tr> + <td>names</td> + <td>retrieves the list of users when the bot joins a channel</td> + </tr> + </tbody> +</table> +</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('irc in',{ + category: 'social-input', + defaults: { + name: {value:""}, + ircserver: {type:"irc-server", required:true}, + channel: {value:"",required:true,validate:RED.validators.regex(/^#/)} + }, + color:"Silver", + inputs:0, + outputs:2, + icon: "hash.png", + label: function() { + var ircNode = RED.nodes.node(this.ircserver); + return this.name || (ircNode ? ircNode.label() : "irc"); + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + if ((this.ircserver !== undefined) && (this.ircserver !== "")) { + this.channel = this.channel || RED.nodes.node(this.ircserver).channel; + $("#node-input-channel").val(this.channel); + } + else { this.channel = this.channel; } + $("#node-input-channel").val(this.channel); + } + }); +</script> + + +<script type="text/x-red" data-template-name="irc out"> + <div class="form-row"> + <label for="node-input-ircserver"><i class="fa fa-globe"></i> IRC Server</label> + <input type="text" id="node-input-ircserver"> + </div> + <div class="form-row"> + <label for="node-input-channel"><i class="fa fa-random"></i> Channel</label> + <input type="text" id="node-input-channel" placeholder="#nodered"> + </div> + <div class="form-row"> + <label for="node-input-sendObject"><i class="fa fa-arrows"></i> Action</label> + <select type="text" id="node-input-sendObject" style="display: inline-block; vertical-align: middle; width:70%;"> + <option value="pay">Send payload to channel(s)</option> + <option value="true">Use msg.topic to set nickname or channel(s)</option> + <option value="false">Send complete msg object to channel(s)</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips">The channel to join must start with a # (as per normal irc rules...)<br/> + Sending the complete object will stringify the whole msg object before sending.</div> +</script> + +<script type="text/x-red" data-help-name="irc out"> + <p>Sends messages to a channel on an IRC server</p> + <p>You can send just the <code>msg.payload</code>, or the complete <code>msg</code> object to the selected channel, + or you can select to use <code>msg.topic</code> to send the <code>msg.payload</code> to a specific user (private message) or channel.</p> + <p>If multiple output channels are listed (eg. #chan1,#chan2), then the message will be sent to all of them.</p> + <p><b>Note:</b> you can only send to channels you have previously joined so they MUST be specified in the node - even if you then decide to use a subset in msg.topic</p> + <p>You may send RAW commands using <code>msg.raw</code> - This must contain an array of parameters - eg. <pre>["privmsg","#nodered","Hello world"]</pre></p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('irc out',{ + category: 'social-output', + defaults: { + name: {value:""}, + sendObject: {value:"pay", required:true}, + ircserver: {type:"irc-server", required:true}, + channel: {value:"",required:true,validate:RED.validators.regex(/^#/)} + }, + color:"Silver", + inputs:1, + outputs:0, + icon: "hash.png", + align: "right", + label: function() { + return this.name || (this.ircserver ? RED.nodes.node(this.ircserver).label() : "irc"); + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + if ((this.ircserver !== undefined) && (this.ircserver !== "")) { + this.channel = this.channel || RED.nodes.node(this.ircserver).channel; + $("#node-input-channel").val(this.channel); + } + else { this.channel = this.channel; } + } + }); +</script> + + +<script type="text/x-red" data-template-name="irc-server"> + <div class="form-row"> + <label for="node-config-input-server"><i class="fa fa-globe"></i> IRC Server</label> + <input type="text" id="node-config-input-server" placeholder="irc.freenode.net"> + </div> + <div class="form-row"> + <label for="node-config-input-nickname"><i class="fa fa-user"></i> Nickname</label> + <input type="text" id="node-config-input-nickname" placeholder="joe123"> + </div> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('irc-server',{ + category: 'config', + defaults: { + server: {value:"",required:true}, + nickname: {value:"",required:true} + }, + label: function() { + return this.server; + } + }); +</script> diff --git a/dgbuilder/core_nodes/social/91-irc.js b/dgbuilder/core_nodes/social/91-irc.js new file mode 100644 index 00000000..c520e44f --- /dev/null +++ b/dgbuilder/core_nodes/social/91-irc.js @@ -0,0 +1,237 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var irc = require("irc"); + + // The Server Definition - this opens (and closes) the connection + function IRCServerNode(n) { + RED.nodes.createNode(this,n); + this.server = n.server; + this.channel = n.channel; + this.nickname = n.nickname; + this.lastseen = 0; + this.ircclient = null; + this.on("close", function() { + if (this.ircclient != null) { + this.ircclient.removeAllListeners(); + this.ircclient.disconnect(); + } + }); + } + RED.nodes.registerType("irc-server",IRCServerNode); + + + // The Input Node + function IrcInNode(n) { + RED.nodes.createNode(this,n); + this.ircserver = n.ircserver; + this.serverConfig = RED.nodes.getNode(this.ircserver); + this.channel = n.channel || this.serverConfig.channel; + var node = this; + if (node.serverConfig.ircclient === null) { + node.log("Connecting to "+node.serverConfig.server); + node.status({fill:"grey",shape:"dot",text:"connecting"}); + node.serverConfig.ircclient = new irc.Client(node.serverConfig.server, node.serverConfig.nickname,{autoConnect:false,retryDelay:20000}); + node.serverConfig.ircclient.setMaxListeners(0); + node.serverConfig.ircclient.addListener('error', function(message) { + node.log(JSON.stringify(message)); + }); + node.serverConfig.ircclient.addListener('netError', function(message) { + node.log(JSON.stringify("NET "+message)); + node.serverConfig.lastseen = Date.now(); + }); + node.serverConfig.ircclient.addListener('connect', function() { + node.serverConfig.lastseen = Date.now(); + }); + node.serverConfig.ircclient.addListener('ping', function(server) { + node.serverConfig.lastseen = Date.now(); + //node.log("PING "+JSON.stringify(server)); + }); + node.recon = setInterval( function() { + //console.log("CHK ",(Date.now()-node.serverConfig.lastseen)/1000); + if ((Date.now()-node.serverConfig.lastseen) > 300000) { // if more than 5 mins since last seen + node.ircclient.send.apply(node.ircclient,["TIME"]); // request time to check link + } + if ((Date.now()-node.serverConfig.lastseen) > 400000) { // If more than 6.5 mins + node.serverConfig.ircclient.disconnect(); + node.serverConfig.ircclient.connect(); + node.log("reconnect"); // then retry + } + node.ircclient.send.apply(node.ircclient,["TIME"]); // request time to check link + }, 60000); // check every 1 min + } + else { node.status({text:""}); } + node.ircclient = node.serverConfig.ircclient; + + node.ircclient.addListener('registered', function(message) { + //node.log(node.ircclient.nick+" ONLINE"); + node.status({fill:"yellow",shape:"dot",text:"connected"}); + node.ircclient.join( node.channel, function(data) { + // node.log(data+" JOINED "+node.channel); + node.status({fill:"green",shape:"dot",text:"joined"}); + }); + }); + node.ircclient.addListener('message', function (from, to, message) { + //node.log(from + ' => ' + to + ' : ' + message); + if (~node.channel.toLowerCase().indexOf(to.toLowerCase())) { + var msg = { "topic":from, "from":from, "to":to, "payload":message }; + node.send([msg,null]); + } + //else { console.log(node.channel,to); } + }); + node.ircclient.addListener('pm', function(from, message) { + //node.log("PM => "+from + ': ' + message); + var msg = { "topic":from, "from":from, "to":"PRIV", "payload":message }; + node.send([msg,null]); + }); + node.ircclient.addListener('join', function(channel, who) { + var msg = { "payload": { "type":"join", "who":who, "channel":channel } }; + node.send([null,msg]); + //node.log(who+' has joined '+channel); + }); + node.ircclient.addListener('invite', function(channel, from, message) { + var msg = { "payload": { "type":"invite", "who":from, "channel":channel, "message":message } }; + node.send([null,msg]); + //node.log(from+' sent invite to '+channel+': '+message); + }); + node.ircclient.addListener('part', function(channel, who, reason) { + var msg = { "payload": { "type":"part", "who":who, "channel":channel, "reason":reason } }; + node.send([null,msg]); + //node.log(who+' has left '+channel+': '+reason); + }); + node.ircclient.addListener('quit', function(nick, reason, channels, message) { + var msg = { "payload": { "type":"quit", "who":nick, "channel":channels, "reason":reason } }; + node.send([null,msg]); + //node.log(nick+' has quit '+channels+': '+reason); + }); + node.ircclient.addListener('kick', function(channel, who, by, reason) { + var msg = { "payload": { "type":"kick", "who":who, "channel":channel, "by":by, "reason":reason } }; + node.send([null,msg]); + //node.log(who+' was kicked from '+channel+' by '+by+': '+reason); + }); + node.ircclient.addListener('names', function (channel, nicks) { + var msg = { "payload": { "type": "names", "channel": channel, "names": nicks} }; + node.send([null, msg]); + }); + node.ircclient.addListener('raw', function (message) { // any message means we are alive + node.serverConfig.lastseen = Date.now(); + }); + node.on("close", function() { + node.ircclient.removeAllListeners(); + if (node.recon) { clearInterval(node.recon); } + }); + } + RED.nodes.registerType("irc in",IrcInNode); + + + // The Output Node + function IrcOutNode(n) { + RED.nodes.createNode(this,n); + this.sendFlag = n.sendObject; + this.ircserver = n.ircserver; + this.serverConfig = RED.nodes.getNode(this.ircserver); + this.channel = n.channel || this.serverConfig.channel; + var node = this; + if (node.serverConfig.ircclient === null) { + node.log("connecting to "+node.serverConfig.server); + node.status({fill:"grey",shape:"dot",text:"connecting"}); + node.serverConfig.ircclient = new irc.Client(node.serverConfig.server, node.serverConfig.nickname,{autoConnect:false,retryDelay:20000}); + node.serverConfig.ircclient.setMaxListeners(0); + node.serverConfig.ircclient.addListener('error', function(message) { + node.log(JSON.stringify(message)); + }); + node.serverConfig.ircclient.addListener('netError', function(message) { + node.log(JSON.stringify("NET "+message)); + node.serverConfig.lastseen = Date.now(); + }); + node.serverConfig.ircclient.addListener('connect', function() { + node.serverConfig.lastseen = Date.now(); + }); + node.serverConfig.ircclient.addListener('ping', function(server) { + node.serverConfig.lastseen = Date.now(); + //node.log("PING "+JSON.stringify(server)); + }); + node.serverConfig.ircclient.addListener('raw', function (message) { // any message received means we are alive + if (message.commandType === "reply") { node.serverConfig.lastseen = Date.now(); } + }); + node.recon = setInterval( function() { + //console.log("CHK ",(Date.now()-node.serverConfig.lastseen)/1000); + if ((Date.now()-node.serverConfig.lastseen) > 300000) { // if more than 5 mins since last seen + node.ircclient.send.apply(node.ircclient,["TIME"]); // request time to check link + } + if ((Date.now()-node.serverConfig.lastseen) > 400000) { // If more than 6.5 mins + node.serverConfig.ircclient.disconnect(); + node.serverConfig.ircclient.connect(); + node.log("reconnect"); // then retry + } + node.ircclient.send.apply(node.ircclient,["TIME"]); // request time to check link + }, 60000); // check every 1 min + node.serverConfig.ircclient.connect(); + } + else { node.status({text:""}); } + node.ircclient = node.serverConfig.ircclient; + + node.ircclient.addListener('registered', function(message) { + node.log(node.ircclient.nick+" ONLINE"); + node.status({fill:"yellow",shape:"dot",text:"connected"}); + node.ircclient.join( node.channel, function(data) { + //node.log(data+" JOINED "+node.channel); + node.status({fill:"green",shape:"dot",text:"joined"}); + }); + }); + + node.on("input", function(msg) { + if (Object.prototype.toString.call( msg.raw ) === '[object Array]') { + node.log("RAW command:"+msg.raw); + node.ircclient.send.apply(node.ircclient,msg.raw); + //var m = msg.raw; + //for (var i = 0; i < 10; i++) { + //if (typeof m[i] !== "string") { m[i] = ""; } + //m[i] = m[i].replace(/"/g, ""); + //} + //node.log("RAW command:"+m); + //node.ircclient.send(m[0],m[1],m[2],m[3],m[4],m[5],m[6],m[7],m[8],m[9]); + } + else { + if (msg._topic) { delete msg._topic; } + var ch = node.channel.split(","); // split on , so we can send to multiple + if (node.sendFlag == "true") { // override channels with msg.topic + if ((msg.hasOwnProperty('topic'))&&(typeof msg.topic === "string")) { + ch = msg.topic.split(","); // split on , so we can send to multiple + } + else { node.warn("msg.topic not set"); } + } + for (var c = 0; c < ch.length; c++) { + if (node.sendFlag == "false") { // send whole message object to each channel + node.ircclient.say(ch[c], JSON.stringify(msg)); + } + else { // send just the payload to each channel + if (typeof msg.payload === "object") { msg.payload = JSON.stringify(msg.payload); } + node.ircclient.say(ch[c], msg.payload); + } + } + } + }); + + node.on("close", function() { + node.ircclient.removeAllListeners(); + if (node.recon) { clearInterval(node.recon); } + }); + } + RED.nodes.registerType("irc out",IrcOutNode); +} diff --git a/dgbuilder/core_nodes/storage/28-tail.html b/dgbuilder/core_nodes/storage/28-tail.html new file mode 100644 index 00000000..c094d064 --- /dev/null +++ b/dgbuilder/core_nodes/storage/28-tail.html @@ -0,0 +1,58 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="tail"> + <div class="form-row node-input-filename"> + <label for="node-input-filename"><i class="fa fa-file"></i> Filename</label> + <input type="text" id="node-input-filename" placeholder="Filename"> + </div> + <div class="form-row"> + <label> </label> + <input type="checkbox" id="node-input-split" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-split" style="width: 70%;">Split lines if we see \n ?</label> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <!-- <div class="form-tips">WON'T work on Windows.</div> --> +</script> + +<script type="text/x-red" data-help-name="tail"> + <p>Tails (watches for things to be added) to the configured file. (Linux/Mac ONLY)</p> + <p>This won't work on Windows filesystems, as it relies on the tail -F command.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('tail',{ + category: 'storage-input', + defaults: { + name: {value:""}, + split: {value:false}, + filename: {value:"",required:true} + }, + color:"BurlyWood", + inputs:0, + outputs:1, + icon: "file.png", + label: function() { + return this.name||this.filename; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/core_nodes/storage/28-tail.js b/dgbuilder/core_nodes/storage/28-tail.js new file mode 100644 index 00000000..89c7a639 --- /dev/null +++ b/dgbuilder/core_nodes/storage/28-tail.js @@ -0,0 +1,69 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var spawn = require('child_process').spawn; + var plat = require('os').platform(); + + if (plat.match(/^win/)) { + throw "Info : Currently not supported on Windows."; + } + + function TailNode(n) { + RED.nodes.createNode(this,n); + + this.filename = n.filename; + this.split = n.split; + var node = this; + + var err = ""; + // TODO: rewrite to use node-tail + var tail = spawn("tail", ["-F", "-n", "0", this.filename]); + tail.stdout.on("data", function (data) { + if (node.split) { + // TODO: allow customisation of the line break - as we do elsewhere + var strings = data.toString().split("\n"); + for (var s in strings) { + //TODO: should we really filter blanks? Is that expected? + if (strings[s] !== "") { + node.send({ + topic: node.filename, + payload: strings[s] + }); + } + } + } + else { + var msg = { + topic:node.filename, + payload: data.toString() + }; + node.send(msg); + } + }); + + tail.stderr.on("data", function(data) { + node.warn(data.toString()); + }); + + this.on("close", function() { + if (tail) { tail.kill(); } + }); + } + + RED.nodes.registerType("tail",TailNode); +} diff --git a/dgbuilder/core_nodes/storage/50-file.html b/dgbuilder/core_nodes/storage/50-file.html new file mode 100644 index 00000000..5113a17d --- /dev/null +++ b/dgbuilder/core_nodes/storage/50-file.html @@ -0,0 +1,110 @@ +<!-- + Copyright 2013, 2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="file"> + <div class="form-row node-input-filename"> + <label for="node-input-filename"><i class="fa fa-file"></i> Filename</label> + <input type="text" id="node-input-filename" placeholder="Filename"> + </div> + <div class="form-row"> + <label> </label> + <input type="checkbox" id="node-input-appendNewline" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-appendNewline" style="width: 70%;">Append newline ?</label> + </div> + <div class="form-row"> + <label> </label> + <input type="checkbox" id="node-input-overwriteFile" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-overwriteFile" style="width: 70%;">Overwrite complete file ?</label> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="file"> + <p>Writes <b>msg.payload</b> to the file specified, e.g. to create a log.</p> + <p>The filename can be overridden by the <b>msg.filename</b> property of the incoming message.</p> + <p>A newline is added to every message. But this can be turned off if required, for example, to allow binary files to be written.</p> + <p>The default behaviour is to append to the file. This can be changed to overwrite the file each time, for example if you want to output a "static" web page or report.</p> + <p>If a <b>msg.delete</b> property exists then the file will be deleted instead.</p> +</script> + +<script type="text/x-red" data-template-name="file in"> + <div class="form-row"> + <label for="node-input-filename"><i class="fa fa-file"></i> Filename</label> + <input type="text" id="node-input-filename" placeholder="Filename"> + </div> + <div class="form-row"> + <label for="node-input-format"><i class="fa fa-sign-out"></i> Output as</label> + <select id="node-input-format"> + <option value="utf8">a utf8 string</option> + <option value="">a Buffer</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/x-red" data-help-name="file in"> + <p>Reads the specified file and sends the content as <b>msg.payload</b>, and the filename as <b>msg.filename</b>.</p> + <p>The filename can be overridden by the <b>msg.filename</b> property of the incoming message.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('file',{ + category: 'storage-output', + defaults: { + name: {value:""}, + filename: {value:""}, + appendNewline: {value:true}, + overwriteFile: {value:false} + }, + color:"BurlyWood", + inputs:1, + outputs:0, + icon: "file.png", + align: "right", + label: function() { + return this.name||this.filename; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); + + RED.nodes.registerType('file in',{ + category: 'storage-input', + defaults: { + name: {value:""}, + filename: {value:""}, + format: {value:"utf8"}, + }, + color:"BurlyWood", + inputs:1, + outputs:1, + icon: "file.png", + label: function() { + return this.name||this.filename; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + } + }); + +</script> diff --git a/dgbuilder/core_nodes/storage/50-file.js b/dgbuilder/core_nodes/storage/50-file.js new file mode 100644 index 00000000..d6cc4410 --- /dev/null +++ b/dgbuilder/core_nodes/storage/50-file.js @@ -0,0 +1,93 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var fs = require("fs"); + + function FileNode(n) { + RED.nodes.createNode(this,n); + this.filename = n.filename || ""; + this.appendNewline = n.appendNewline; + this.overwriteFile = n.overwriteFile; + var node = this; + this.on("input",function(msg) { + var filename = msg.filename || this.filename; + if (filename === "") { + node.warn('No filename specified'); + } else if (msg.hasOwnProperty('delete')) { + fs.unlink(filename, function (err) { + if (err) { node.warn('Failed to delete file : '+err); } + //console.log('Deleted file",filename); + }); + } else if (typeof msg.payload != "undefined") { + var data = msg.payload; + if (typeof data === "object") { + if (!Buffer.isBuffer(data)) { + data = JSON.stringify(data); + } + } + if (typeof data === "boolean") { data = data.toString(); } + if ((this.appendNewline)&&(!Buffer.isBuffer(data))) { data += "\n"; } + if (this.overwriteFile) { + // using "binary" not {encoding:"binary"} to be 0.8 compatible for a while + fs.writeFile(filename, data, "binary", function (err) { + if (err) { node.warn('Failed to write to file : '+err); } + //console.log('Message written to file',filename); + }); + } + else { + // using "binary" not {encoding:"binary"} to be 0.8 compatible for a while + fs.appendFile(filename, data, "binary", function (err) { + if (err) { node.warn('Failed to append to file : '+err); } + //console.log('Message appended to file',filename); + }); + } + } + }); + } + RED.nodes.registerType("file",FileNode); + + function FileInNode(n) { + RED.nodes.createNode(this,n); + + this.filename = n.filename || ""; + this.format = n.format; + var node = this; + var options = {}; + if (this.format) { + options['encoding'] = this.format; + } + this.on("input",function(msg) { + var filename = msg.filename || this.filename; + if (filename === "") { + node.warn('No filename specified'); + } else { + fs.readFile(filename,options,function(err,data) { + if (err) { + node.warn(err); + msg.error = err; + } else { + msg.filename = filename; + msg.payload = data; + } + node.send(msg); + }); + } + }); + } + RED.nodes.registerType("file in",FileInNode); +} diff --git a/dgbuilder/core_nodes/storage/65-redisout.html b/dgbuilder/core_nodes/storage/65-redisout.html new file mode 100644 index 00000000..9000dfd6 --- /dev/null +++ b/dgbuilder/core_nodes/storage/65-redisout.html @@ -0,0 +1,105 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="redis out"> + <div class="form-row node-input-hostname"> + <label for="node-input-hostname"><i class="fa fa-bookmark"></i> Host</label> + <input class="input-append-left" type="text" id="node-input-hostname" placeholder="127.0.0.1" style="width: 40%;" ><button id="node-input-hostname-lookup" class="btn input-append-right"><span class="caret"></span></button> + <label for="node-input-port" style="margin-left: 10px; width: 35px; "> Port</label> + <input type="text" id="node-input-port" placeholder="6379" style="width:45px"> + </div> + <div class="form-row"> + <label for="node-input-key"><i class="fa fa-key"></i> Key</label> + <input type="text" id="node-input-key" placeholder="Redis Key"> + </div> + <div class="form-row"> + <label for="node-input-type"><i class="fa fa-th"></i> Type</label> + <select type="text" id="node-input-structtype" style="width: 150px;"> + <option value="string">String</option> + <option value="hash">Hash</option> + <option value="set">Set</option> + <option value="list">List</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips"> + If key is blank, the topic will be used as the key.<br> + If type is hash, payload should be field=value. + </div> +</script> + +<script type="text/x-red" data-help-name="redis out"> + <p>A Redis output node. Options include Hash, Set, List and String.</p> + <p>To run this you need a local Redis server running. For details see <a href="http://redis.io/" target="_new">the Redis site</a>.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('redis out',{ + category: 'storage-output', + color:"#ffaaaa", + defaults: { + hostname: { value:"127.0.0.1",required:true}, + port: { value: 6379,required:true}, + name: {value:""}, + key: {value:""}, + structtype: {value:"",required:true} + }, + inputs:1, + outputs:0, + icon: "redis.png", + align: "right", + label: function() { + return this.name||this.key+" ("+this.structtype+")"; + }, + oneditprepare: function() { + var availableServers = []; + var matchedServers = {}; + RED.nodes.eachNode(function(node) { + if (node.type == "redis out" && node.hostname && node.port && !matchedServers[node.hostname+":"+node.port]) { + var label = node.hostname+":"+node.port; + matchedServers[label] = true; + availableServers.push({ + label:label, + value:node.hostname, + port:node.port + }); + } + }); + $( "#node-input-hostname" ).autocomplete({ + minLength: 0, + source: availableServers, + select: function( event, ui ) { + $("#node-input-port").val(ui.item.port); + } + }); + var tt = this; + tt._acOpen = false; + $( "#node-input-hostname" ).on( "autocompleteclose", function( event, ui ) { tt._acOpen = false;} ); + $( "#node-input-hostname-lookup" ).click(function(e) { + if (tt._acOpen) { + $( "#node-input-hostname" ).autocomplete( "close"); + } else { + $( "#node-input-hostname" ).autocomplete( "search", "" ); + } + tt._acOpen = !tt._acOpen; + e.preventDefault(); + }); + } + }); +</script> diff --git a/dgbuilder/core_nodes/storage/65-redisout.js b/dgbuilder/core_nodes/storage/65-redisout.js new file mode 100644 index 00000000..907e2a55 --- /dev/null +++ b/dgbuilder/core_nodes/storage/65-redisout.js @@ -0,0 +1,107 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var redis = require("redis"); + + var hashFieldRE = /^([^=]+)=(.*)$/; + + var redisConnectionPool = function() { + var connections = {}; + var obj = { + get: function(host,port) { + var id = host+":"+port; + if (!connections[id]) { + connections[id] = redis.createClient(port,host); + connections[id].on("error",function(err) { + util.log("[redis] "+err); + }); + connections[id].on("connect",function() { + util.log("[redis] connected to "+host+":"+port); + }); + connections[id]._id = id; + connections[id]._nodeCount = 0; + } + connections[id]._nodeCount += 1; + return connections[id]; + }, + close: function(connection) { + connection._nodeCount -= 1; + if (connection._nodeCount === 0) { + if (connection) { + clearTimeout(connection.retry_timer); + connection.end(); + } + delete connections[connection._id]; + } + } + }; + return obj; + }(); + + + function RedisOutNode(n) { + RED.nodes.createNode(this,n); + this.port = n.port||"6379"; + this.hostname = n.hostname||"127.0.0.1"; + this.key = n.key; + this.structtype = n.structtype; + + this.client = redisConnectionPool.get(this.hostname,this.port); + + if (this.client.connected) { + this.status({fill:"green",shape:"dot",text:"connected"}); + } else { + this.status({fill:"red",shape:"ring",text:"disconnected"},true); + } + + var node = this; + this.client.on("end", function() { + node.status({fill:"red",shape:"ring",text:"disconnected"}); + }); + this.client.on("connect", function() { + node.status({fill:"green",shape:"dot",text:"connected"}); + }); + + this.on("input", function(msg) { + var k = this.key || msg.topic; + if (k) { + if (this.structtype == "string") { + this.client.set(k,RED.util.ensureString(msg.payload)); + } else if (this.structtype == "hash") { + var r = hashFieldRE.exec(msg.payload); + if (r) { + this.client.hset(k,r[1],r[2]); + } else { + this.warn("Invalid payload for redis hash"); + } + } else if (this.structtype == "set") { + this.client.sadd(k,msg.payload); + } else if (this.structtype == "list") { + this.client.rpush(k,msg.payload); + } + } else { + this.warn("No key or topic set"); + } + }); + this.on("close", function() { + redisConnectionPool.close(node.client); + }); + } + RED.nodes.registerType("redis out",RedisOutNode); +} diff --git a/dgbuilder/core_nodes/storage/66-mongodb.html b/dgbuilder/core_nodes/storage/66-mongodb.html new file mode 100644 index 00000000..81c56389 --- /dev/null +++ b/dgbuilder/core_nodes/storage/66-mongodb.html @@ -0,0 +1,231 @@ +<!-- + Copyright 2013,2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="mongodb"> + <div class="form-row"> + <label for="node-config-input-hostname"><i class="fa fa-bookmark"></i> Host</label> + <input class="input-append-left" type="text" id="node-config-input-hostname" placeholder="localhost" style="width: 40%;" > + <label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> Port</label> + <input type="text" id="node-config-input-port" placeholder="27017" style="width:45px"> + </div> + <div class="form-row"> + <label for="node-config-input-db"><i class="fa fa-database"></i> Database</label> + <input type="text" id="node-config-input-db" placeholder="test"> + </div> + <div class="form-row"> + <label for="node-config-input-user"><i class="fa fa-user"></i> Username</label> + <input type="text" id="node-config-input-user"> + </div> + <div class="form-row"> + <label for="node-config-input-password"><i class="fa fa-lock"></i> Password</label> + <input type="password" id="node-config-input-password"> + </div> + <div class="form-row"> + <label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-config-input-name" placeholder="Name"> + </div> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('mongodb', { + category: 'config', + color: "rgb(218, 196, 180)", + defaults: { + hostname: {value: "127.0.0.1", required: true}, + port: {value: 27017, required: true}, + db: {value: "", required: true}, + name: {value: ""} + }, + credentials: { + user: {type: "text"}, + password: {type: "password"} + }, + label: function() { + return this.name || this.hostname + ":" + this.port + "/" + this.db; + } + }); +</script> + + +<script type="text/x-red" data-template-name="mongodb out"> + <div class="form-row"> + <label for="node-input-mongodb"><i class="fa fa-bookmark"></i> Server</label> + <input type="text" id="node-input-mongodb"> + </div> + <div class="form-row"> + <label for="node-input-collection"><i class="fa fa-briefcase"></i> Collection</label> + <input type="text" id="node-input-collection" placeholder="collection"> + </div> + <div class="form-row"> + <label for="node-input-operation"><i class="fa fa-wrench"></i> Operation</label> + <select type="text" id="node-input-operation" style="display: inline-block; vertical-align: top;"> + <option value="store">save</option> + <option value="insert">insert</option> + <option value="update">update</option> + <option value="delete">remove</option> + </select> + </div> + <div class="form-row node-input-payonly"> + <label> </label> + <input type="checkbox" id="node-input-payonly" placeholder="Only" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-payonly" style="width: 70%;">Only store msg.payload object</label> + </div> + <div class="form-row node-input-upsert"> + <label> </label> + <input type="checkbox" id="node-input-upsert" placeholder="Only" style="display: inline-block; width: auto; vertical-align: top;"> + <label for="node-input-upsert" style="width: 70%;">Create a new document if no match found</label> + </div> + <div class="form-row node-input-multi"> + <label> </label> + <input type="checkbox" id="node-input-multi" placeholder="Only" style="display: inline-block; width: auto; vertical-align: top;;"> + <label for="node-input-multi" style="width: 70%;">Update all matching documents</label> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips" id="node-warning" style="display: none"><b> Tip:</b> If no collection is set, ensure <b>msg.collection</b> will contain the collection name + </div> +</script> + +<script type="text/x-red" data-help-name="mongodb out"> + <p>A simple MongoDB output node. Can save, insert, update and remove objects from a chosen collection.</p> + <p>Save will update an existing object or insert a new object if one does not already exist.</p> + <p>Insert will insert a new object.</p> + <p>Save and insert either store <b>msg</b> or <b>msg.payload</b>.</p> + <p>Update will modify an existing object or objects. The query to select objects to update uses <b>msg.query</b> and the update to the element uses <b>msg.payload</b>.</p> + <p>Update can add a object if it does not exist or update multiple objects.</p> + <p>Remove will remove objects that match the query passed in on <b>msg.payload</b>. A blank query will delete <i>all of the objects</i> in the collection.</p> + <p>You can either set the collection method in the node config or on <b>msg.collection</b>. Setting it in the node will override <b>msg.collection</b>.</p> + <p>By default MongoDB creates an <i>_id</i> property as the primary key - so repeated injections of the same <b>msg</b> will result in many database entries.</p> + <p>If this is NOT the desired behaviour - ie. you want repeated entries to overwrite, then you must set the <b>msg._id</b> property to be a constant by the use of a previous function node.</p> + <p>This could be a unique constant or you could create one based on some other msg property.</p> + <p>Currently we do not limit or cap the collection size at all... this may well change.</p> +</script> + +<script type="text/javascript"> + + function oneditprepare() { + $("#node-input-operation").change(function () { + var id = $("#node-input-operation option:selected").val(); + + if (id === "update") { + $(".node-input-payonly").hide(); + $(".node-input-upsert, .node-input-multi").show(); + } else if (id === "delete") { + $(".node-input-payonly, .node-input-upsert, .node-input-multi").hide(); + } else { + $(".node-input-payonly").show(); + $(".node-input-upsert, .node-input-multi").hide(); + } + }); + + $("#node-input-collection").change(function () { + if($("#node-input-collection").val() === "") { + $("#node-warning").show(); + } else { + $("#node-warning").hide(); + } + }); + } + + RED.nodes.registerType('mongodb out', { + category: 'storage-output', + color: "rgb(218, 196, 180)", + defaults: { + mongodb: {type: "mongodb", required: true}, + name: {value: ""}, + collection: {value: ""}, + payonly: {value: false}, + upsert: {value: false}, + multi: {value: false}, + operation: {value: "store"} + }, + inputs: 1, + outputs: 0, + icon: "mongodb.png", + align: "right", + label: function() { + var mongoNode = RED.nodes.node(this.mongodb); + return this.name || (mongoNode ? mongoNode.label() + " " + this.collection: "mongodb"); + }, + labelStyle: function() { + return this.name ? "node_label_italic" : ""; + }, + oneditprepare: oneditprepare + }); +</script> + + +<script type="text/x-red" data-template-name="mongodb in"> + <div class="form-row"> + <label for="node-input-mongodb"><i class="fa fa-bookmark"></i> Server</label> + <input type="text" id="node-input-mongodb"> + </div> + <div class="form-row"> + <label for="node-input-collection"><i class="fa fa-briefcase"></i> Collection</label> + <input type="text" id="node-input-collection" placeholder="collection"> + </div> + <div class="form-row"> + <label for="node-input-operation"><i class="fa fa-wrench"></i> Operation</label> + <select type="text" id="node-input-operation" style="display: inline-block; vertical-align: top;"> + <option value="find">find</option> + <option value="count">count</option> + <option value="aggregate">aggregate</option> + </select> + </div> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-tips" id="node-warning" style="display: none"><b> Tip:</b> If no collection is set, ensure <b>msg.collection</b> will contain the collection name + </div> +</script> + +<script type="text/x-red" data-help-name="mongodb in"> + <p>Calls a MongoDB collection method based on the selected operator.</p> + <p>Find queries a collection using the <b>msg.payload</b> as the query statement as per the .find() function. Optionally, you may also (via a function) set a <b>msg.projection</b> object to constrain the returned fields, a <b>msg.sort</b> object and a <b>msg.limit</b> object.</p> + <p>Count returns a count of the number of documents in a collection or matching a query using the <b>msg.payload</b> as the query statement.</p> + <p>Aggregate provides access to the aggregation pipeline using the <b>msg.payload</b> as the pipeline array.</p> + <p>You can override the collection the method is performed on by setting <b>msg.collection</b> to the desired collection name.</p> + <p>See the <a href="http://docs.mongodb.org/manual/reference/method/db.collection.find/" target="new"><i>MongoDB collection methods docs</i></a> for examples.</p> + <p>The result is returned in <b>msg.payload</b>.</p> +</script> + +<script type="text/javascript"> + + RED.nodes.registerType('mongodb in', { + category: 'storage-input', + color: "rgb(218, 196, 180)", + defaults: { + mongodb: {type: "mongodb", required: true}, + name: {value: ""}, + collection: {value: ""}, + operation: {value: "find"} + }, + inputs: 1, + outputs: 1, + icon: "mongodb.png", + label: function() { + var mongoNode = RED.nodes.node(this.mongodb); + return this.name || (mongoNode ? mongoNode.label() + " " + this.collection: "mongodb"); + }, + labelStyle: function() { + return this.name ? "node_label_italic" : ""; + }, + oneditprepare: oneditprepare + }); +</script> diff --git a/dgbuilder/core_nodes/storage/66-mongodb.js b/dgbuilder/core_nodes/storage/66-mongodb.js new file mode 100644 index 00000000..3a71407c --- /dev/null +++ b/dgbuilder/core_nodes/storage/66-mongodb.js @@ -0,0 +1,233 @@ +/** + * Copyright 2013,2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var mongo = require('mongodb'); + var MongoClient = mongo.MongoClient; + + function MongoNode(n) { + RED.nodes.createNode(this,n); + this.hostname = n.hostname; + this.port = n.port; + this.db = n.db; + this.name = n.name; + + var url = "mongodb://"; + if (this.credentials && this.credentials.user && this.credentials.password) { + url += this.credentials.user+":"+this.credentials.password+"@"; + } + url += this.hostname+":"+this.port+"/"+this.db; + + this.url = url; + } + + RED.nodes.registerType("mongodb",MongoNode,{ + credentials: { + user: {type:"text"}, + password: {type: "password"} + } + }); + + function ensureValidSelectorObject(selector) { + if (selector != null && (typeof selector != 'object' || Buffer.isBuffer(selector))) { + return {}; + } + return selector; + } + + + function MongoOutNode(n) { + RED.nodes.createNode(this,n); + this.collection = n.collection; + this.mongodb = n.mongodb; + this.payonly = n.payonly || false; + this.upsert = n.upsert || false; + this.multi = n.multi || false; + this.operation = n.operation; + this.mongoConfig = RED.nodes.getNode(this.mongodb); + + if (this.mongoConfig) { + var node = this; + MongoClient.connect(this.mongoConfig.url, function(err, db) { + if (err) { + node.error(err); + } else { + node.clientDb = db; + var coll; + if (node.collection) { + coll = db.collection(node.collection); + } + node.on("input",function(msg) { + if (!coll) { + if (msg.collection) { + coll = db.collection(msg.collection); + } else { + node.error("No collection defined"); + return; + } + } + delete msg._topic; + delete msg.collection; + if (node.operation === "store") { + if (node.payonly) { + if (typeof msg.payload !== "object") { + msg.payload = {"payload": msg.payload}; + } + coll.save(msg.payload,function(err, item) { + if (err) { + node.error(err); + } + }); + } else { + coll.save(msg,function(err, item) { + if (err) { + node.error(err); + } + }); + } + } else if (node.operation === "insert") { + if (node.payonly) { + if (typeof msg.payload !== "object") { + msg.payload = {"payload": msg.payload}; + } + coll.insert(msg.payload, function(err, item) { + if (err) { + node.error(err); + } + }); + } else { + coll.insert(msg, function(err,item) { + if (err) { + node.error(err); + } + }); + } + } else if (node.operation === "update") { + if (typeof msg.payload !== "object") { + msg.payload = {"payload": msg.payload}; + } + var query = msg.query || {}; + var payload = msg.payload || {}; + var options = { + upsert: node.upsert, + multi: node.multi + }; + + coll.update(query, payload, options, function(err, item) { + if (err) { + node.error(err + " " + payload); + } + }); + } else if (node.operation === "delete") { + coll.remove(msg.payload, function(err, items) { + if (err) { + node.error(err); + } + }); + } + }); + } + }); + } else { + this.error("missing mongodb configuration"); + } + + this.on("close", function() { + if (this.clientDb) { + this.clientDb.close(); + } + }); + } + RED.nodes.registerType("mongodb out",MongoOutNode); + + function MongoInNode(n) { + RED.nodes.createNode(this,n); + this.collection = n.collection; + this.mongodb = n.mongodb; + this.operation = n.operation || "find"; + this.mongoConfig = RED.nodes.getNode(this.mongodb); + + if (this.mongoConfig) { + var node = this; + MongoClient.connect(this.mongoConfig.url, function(err,db) { + if (err) { + node.error(err); + } else { + node.clientDb = db; + var coll; + if (node.collection) { + coll = db.collection(node.collection); + } + node.on("input", function(msg) { + if (!coll) { + if (msg.collection) { + coll = db.collection(msg.collection); + } else { + node.error("No collection defined"); + return; + } + } + if (node.operation === "find") { + msg.projection = msg.projection || {}; + var selector = ensureValidSelectorObject(msg.payload); + coll.find(selector,msg.projection).sort(msg.sort).limit(msg.limit).toArray(function(err, items) { + if (err) { + node.error(err); + } else { + msg.payload = items; + delete msg.projection; + delete msg.sort; + delete msg.limit; + node.send(msg); + } + }); + } else if (node.operation === "count") { + var selector = ensureValidSelectorObject(msg.payload); + coll.count(selector, function(err, count) { + if (err) { + node.error(err); + } else { + msg.payload = count; + node.send(msg); + } + }); + } else if (node.operation === "aggregate") { + msg.payload = (msg.payload instanceof Array) ? msg.payload : []; + coll.aggregate(msg.payload, function(err, result) { + if (err) { + node.error(err); + } else { + msg.payload = result; + node.send(msg); + } + }); + } + }); + } + }); + } else { + this.error("missing mongodb configuration"); + } + + this.on("close", function() { + if (this.clientDb) { + this.clientDb.close(); + } + }); + } + RED.nodes.registerType("mongodb in",MongoInNode); +} diff --git a/dgbuilder/createReleaseDir.sh b/dgbuilder/createReleaseDir.sh new file mode 100755 index 00000000..00d185f7 --- /dev/null +++ b/dgbuilder/createReleaseDir.sh @@ -0,0 +1,129 @@ +#!/bin/bash +export PATH=$PATH:. +appDir=$(pwd) +if [ "$#" != 3 -a "$#" != 4 ] +then + echo "Usage $0 releaseDir loginId emailAddress [gitLocalRepository]" + echo "Note: Specify the gitLocalRepository path if you would want to be able to import flows from your local git repository" + exit +fi +if [ ! -e "releases" ] +then + mkdir releases +fi +releaseDir="$1" +name="Release $releaseDir" +loginId="$2" +emailid="$3" +dbHost="dbhost" +dbPort="3306" +dbName="sdnctl" +dbUser="sdnctl" +dbPassword="gamma" +gitLocalRepository="$4" + +lastPort=$(find "releases/" -name "customSettings.js" |xargs grep uiPort|cut -d: -f2|sed -e s/,//|sort|tail -1) +echo $lastPort|grep uiPort >/dev/null 2>&1 +if [ "$?" == "0" ] +then +lastPort=$(find "releases/" -name "customSettings.js" |xargs grep uiPort|cut -d: -f3|sed -e s/,//|sort|tail -1) +fi +#echo $lastPort +if [ "${lastPort}" == "" ] +then + lastPort="3099" +fi +let nextPort=$(expr $lastPort+1) +#echo $nextPort +if [ ! -e "releases/$releaseDir" ] +then +mkdir releases/$releaseDir +cd releases/$releaseDir +mkdir flows +mkdir flows/shared +mkdir flows/shared/backups +mkdir html +mkdir xml +mkdir lib +mkdir lib/flows +mkdir logs +mkdir conf +mkdir codecloud +customSettingsFile="customSettings.js" +if [ ! -e "./$customSettingsFile" ] +then + echo "module.exports = {" >$customSettingsFile + echo " 'name' : '$name'," >>$customSettingsFile + echo " 'emailAddress' :'$emailid'," >>$customSettingsFile + echo " 'uiPort' :$nextPort," >>$customSettingsFile + echo " 'mqttReconnectTime': 15000," >>$customSettingsFile + echo " 'serialReconnectTime' : 15000," >>$customSettingsFile + echo " 'debugMaxLength': 1000," >>$customSettingsFile + echo " 'htmlPath': 'releases/$releaseDir/html/'," >>$customSettingsFile + echo " 'xmlPath': 'releases/$releaseDir/xml/'," >>$customSettingsFile + echo " 'flowFile' : 'releases/$releaseDir/flows/flows.json'," >>$customSettingsFile + echo " 'sharedDir': 'releases/$releaseDir/flows/shared'," >>$customSettingsFile + echo " 'userDir' : 'releases/$releaseDir'," >>$customSettingsFile + echo " 'httpAuth': {user:'$loginId',pass:'cc03e747a6afbbcbf8be7668acfebee5'}," >>$customSettingsFile + echo " 'dbHost': '$dbHost'," >>$customSettingsFile + echo " 'dbPort': '$dbPort'," >>$customSettingsFile + echo " 'dbName': '$dbName'," >>$customSettingsFile + echo " 'dbUser': '$dbUser'," >>$customSettingsFile + echo " 'dbPassword': '$dbPassword'," >>$customSettingsFile + echo " 'gitLocalRepository': '$gitLocalRepository'" >>$customSettingsFile + echo " }" >>$customSettingsFile +fi + #echo "Created custom settings file $customSettingsFile" + echo "Done ....." +else + echo "ERROR:customSettings file $customSettingsFile already exists for $releaseDir" + exit +fi +#echo "Content of custom settings file" +#echo "============================================================================" +# cat $customSettingsFile +#echo "============================================================================" +svclogicPropFile="./conf/svclogic.properties" +if [ ! -d "${appDir}/yangFiles" ] +then + mkdir -p "${appDir}/yangFiles" +fi +if [ ! -d "${appDir}/generatedJS" ] +then + mkdir -p "${appDir}/generatedJS" +fi + +if [ ! -e "./$svclogicPropFile" ] +then + echo "org.onap.ccsdk.sli.dbtype=jdbc" >$svclogicPropFile + echo "org.onap.ccsdk.sli.jdbc.url=jdbc:mysql://dbhost:3306/sdnctl" >>$svclogicPropFile + echo "org.onap.ccsdk.sli.jdbc.database=sdnctl" >>$svclogicPropFile + echo "org.onap.ccsdk.sli.jdbc.user=sdnctl" >>$svclogicPropFile + echo "org.onap.ccsdk.sli.jdbc.password=gamma" >>$svclogicPropFile +fi +if [ ! -e "${appDir}/flowShareUsers.js" ] +then + echo "module.exports = {\"flowShareUsers\":" >${appDir}/flowShareUsers.js + echo " [" >>${appDir}/flowShareUsers.js + echo " ]" >>${appDir}/flowShareUsers.js + echo "}" >>${appDir}/flowShareUsers.js +fi +grep "$releaseDir" ${appDir}/flowShareUsers.js >/dev/null 2>&1 +if [ "$?" != "0" ] +then + num_of_lines=$(cat ${appDir}/flowShareUsers.js|wc -l) + if [ $num_of_lines -gt 4 ] + then + content=$(head -n -2 ${appDir}/flowShareUsers.js) + echo "${content}," > ${appDir}/flowShareUsers.js + else + content=$(head -n -2 ${appDir}/flowShareUsers.js) + echo "$content" > ${appDir}/flowShareUsers.js + fi + echo " {" >> ${appDir}/flowShareUsers.js + echo " \"name\" : \"$name\"," >> ${appDir}/flowShareUsers.js + echo " \"rootDir\" : \"$releaseDir\"" >> ${appDir}/flowShareUsers.js + echo " }" >> ${appDir}/flowShareUsers.js + echo " ]" >> ${appDir}/flowShareUsers.js + echo "}" >> ${appDir}/flowShareUsers.js +fi diff --git a/dgbuilder/flowShareUsers.js b/dgbuilder/flowShareUsers.js new file mode 100644 index 00000000..d132116d --- /dev/null +++ b/dgbuilder/flowShareUsers.js @@ -0,0 +1,16 @@ +module.exports = {"flowShareUsers": + [ + { + "name" : "Release sdnc1.0", + "rootDir" : "sdnc1.0" + }, + { + "name" : "Release sdnc2.0", + "rootDir" : "sdnc2.0" + }, + { + "name" : "Release sdnc3.0", + "rootDir" : "sdnc3.0" + } + ] +} diff --git a/dgbuilder/generatedJS/.gitignore b/dgbuilder/generatedJS/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/dgbuilder/generatedJS/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/dgbuilder/git_scripts/gitcheckout b/dgbuilder/git_scripts/gitcheckout new file mode 100755 index 00000000..ca01dd79 --- /dev/null +++ b/dgbuilder/git_scripts/gitcheckout @@ -0,0 +1,17 @@ +if [ "$#" != "2" ] +then + echo "Usage $0 gitLocalRepositoryDir branch" + exit +fi +branch=$2 +localGitRepository=$1 +cd $localGitRepository +if [ -e "$localGitRepository" ] +then + git checkout $branch + echo + echo -n "Now on Branch:" + git rev-parse --abbrev-ref HEAD +else + echo Git Local repository not set +fi diff --git a/dgbuilder/git_scripts/gitckout b/dgbuilder/git_scripts/gitckout new file mode 100755 index 00000000..3db9db82 --- /dev/null +++ b/dgbuilder/git_scripts/gitckout @@ -0,0 +1,15 @@ +if [ "$#" != "2" ] +then + echo "Usage $0 commitId full_path_to_the_source_file" + exit +fi +fileName=$(basename $2) +dirName=$(dirname $2) +commitId=$1 +cd $dirName +if [ -e "$2" ] +then + rm $2 2>/dev/null +fi +git checkout $commitId $fileName +cat $fileName diff --git a/dgbuilder/git_scripts/gitcurbranch b/dgbuilder/git_scripts/gitcurbranch new file mode 100755 index 00000000..5a82e483 --- /dev/null +++ b/dgbuilder/git_scripts/gitcurbranch @@ -0,0 +1,13 @@ +if [ "$#" != "1" ] +then + echo "Usage $0 gitLocalRepositoryDir" + exit +fi +localGitRepository=$1 +cd $localGitRepository +if [ -e "$localGitRepository" ] +then + git rev-parse --abbrev-ref HEAD +else + echo Git Local repository not set +fi diff --git a/dgbuilder/git_scripts/gitlog b/dgbuilder/git_scripts/gitlog new file mode 100755 index 00000000..fd8cd379 --- /dev/null +++ b/dgbuilder/git_scripts/gitlog @@ -0,0 +1,18 @@ +if [ "$#" != "1" ] +then + echo "Usage $0 full_path_to_the_source_file" + exit +fi +fileName=$(basename $1) +dirName=$(dirname $1) +cd $dirName +glog=$(git log --pretty=format:'%H %cD %an %s' -n 25 ${fileName}|awk ' ORS=" "{print \ +"\n{\n" \ +"\"commit\": \"" $1 "\",\n" \ +"\"date\": \""$2 " "$3" "$4" "$5 " "$6 "\",\n" \ +"\"author\": \"" $8 ", "$9 "\",\n" \ +"\"comment\": \""} { s = ""; for (i = 10; i <= NF; i++) s = s $i " "; print s } { print "\"\n},"}') +echo "[" +update_glog=$(echo $glog|sed -e 's/,$//g') +echo $update_glog +echo "]" diff --git a/dgbuilder/git_scripts/gitpull b/dgbuilder/git_scripts/gitpull new file mode 100755 index 00000000..8d475adf --- /dev/null +++ b/dgbuilder/git_scripts/gitpull @@ -0,0 +1,7 @@ +if [ "$#" != "1" ] +then + echo "Usage $0 full_path_to_local_repository" + exit +fi +cd $1 +git pull diff --git a/dgbuilder/git_scripts/gitstatus b/dgbuilder/git_scripts/gitstatus new file mode 100755 index 00000000..9b24ea79 --- /dev/null +++ b/dgbuilder/git_scripts/gitstatus @@ -0,0 +1,7 @@ +if [ "$#" != "1" ] +then + echo "Usage $0 full_path_to_local_repository" + exit +fi +cd $1 +git status diff --git a/dgbuilder/nodes/99-sample.html.demo b/dgbuilder/nodes/99-sample.html.demo new file mode 100644 index 00000000..4dcc8ba5 --- /dev/null +++ b/dgbuilder/nodes/99-sample.html.demo @@ -0,0 +1,79 @@ +<!-- + Copyright 2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<!-- Sample html file that corresponds to the 99-sample.js file --> +<!-- This creates and configures the onscreen elements of the node --> + +<!-- If you use this as a template, update the copyright with your own name. --> + +<!-- First, the content of the edit dialog is defined. --> + +<script type="text/x-red" data-template-name="sample"> + <!-- data-template-name identifies the node type this is for --> + + <!-- Each of the following divs creates a field in the edit dialog. --> + <!-- Generally, there should be an input for each property of the node. --> + <!-- The for and id attributes identify the corresponding property --> + <!-- (with the 'node-input-' prefix). --> + <!-- The available icon classes are defined Twitter Bootstrap glyphicons --> + <div class="form-row"> + <label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label> + <input type="text" id="node-input-topic" placeholder="Topic"> + </div> + + <br/> + <!-- By convention, most nodes have a 'name' property. The following div --> + <!-- provides the necessary field. Should always be the last option --> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> +</script> + + +<!-- Next, some simple help text is provided for the node. --> +<script type="text/x-red" data-help-name="sample"> + <!-- data-help-name identifies the node type this help is for --> + <!-- This content appears in the Info sidebar when a node is selected --> + <!-- The first <p> is used as the pop-up tool tip when hovering over a --> + <!-- node in the palette. --> + <p>Simple sample input node. Just sends a single message when it starts up. + This is not very useful.</p> + <p>Outputs an object called <b>msg</b> containing <b>msg.topic</b> and + <b>msg.payload</b>. msg.payload is a String.</p> +</script> + +<!-- Finally, the node type is registered along with all of its properties --> +<!-- The example below shows a small subset of the properties that can be set--> +<script type="text/javascript"> + RED.nodes.registerType('sample',{ + category: 'input', // the palette category + defaults: { // defines the editable properties of the node + name: {value:""}, // along with default values. + topic: {value:"", required:true} + }, + inputs:1, // set the number of inputs - only 0 or 1 + outputs:1, // set the number of outputs - 0 to n + // set the icon (held in icons dir below where you save the node) + icon: "myicon.png", // saved in icons/myicon.png + label: function() { // sets the default label contents + return this.name||this.topic||"sample"; + }, + labelStyle: function() { // sets the class to apply to the label + return this.name?"node_label_italic":""; + } + }); +</script> diff --git a/dgbuilder/nodes/99-sample.js.demo b/dgbuilder/nodes/99-sample.js.demo new file mode 100644 index 00000000..f9269451 --- /dev/null +++ b/dgbuilder/nodes/99-sample.js.demo @@ -0,0 +1,64 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +// If you use this as a template, update the copyright with your own name. + +// Sample Node-RED node file + + +module.exports = function(RED) { + "use strict"; + // require any external libraries we may need.... + //var foo = require("foo-library"); + + // The main node definition - most things happen in here + function SampleNode(n) { + // Create a RED node + RED.nodes.createNode(this,n); + + // Store local copies of the node configuration (as defined in the .html) + this.topic = n.topic; + + // Do whatever you need to do in here - declare callbacks etc + // Note: this sample doesn't do anything much - it will only send + // this message once at startup... + // Look at other real nodes for some better ideas of what to do.... + var msg = {}; + msg.topic = this.topic; + msg.payload = "Hello world !" + + // send out the message to the rest of the workspace. + this.send(msg); + + // respond to inputs.... + this.on('input', function (msg) { + node.warn("I saw a payload: "+msg.payload); + // in this example just send it straight on... should process it here really + this.send(msg); + }); + + this.on("close", function() { + // Called when the node is shutdown - eg on redeploy. + // Allows ports to be closed, connections dropped etc. + // eg: this.client.disconnect(); + }); + } + + // Register the node by name. This must be called before overriding any of the + // Node functions. + RED.nodes.registerType("sample",SampleNode); + +} diff --git a/dgbuilder/nodes/dge/dgelogic/block.html b/dgbuilder/nodes/dge/dgelogic/block.html new file mode 100644 index 00000000..fadf8a8c --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/block.html @@ -0,0 +1,223 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<script type="text/x-red" data-template-name="block"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <div> + <table border='0' width='100%' style='cellspacing:5px;'> + <tr> + <td> + <input type="checkbox" id="node-input-atomic-chkBox" onclick=updateXml()> + <input type="hidden" id="node-input-atomic" value=""> + </td> + <td> + <span style="font-size:.8em;">Atomic</span> + </td> + </tr> + </table> + </div> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="block"> + <p>A block node.</p> + <p>Name can be anything.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + + <div class="section"> +<h3><a name="Flow_Control"></a>Flow Control</h3> +<div class="section"> +<h4><a name="Block_node"></a>Block node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>block</b> node is used to executes a set of nodes. </p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>atomic</b></td> +<td align="left">if <i>true</i>, then if a node returns failure, subsequent nodes will not be executed and nodes already executed will be backed out.</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>None</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<p>None</p></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><block> + <record plugin="org.onap.ccsdk.sli.core.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sample_r1.log" /> + <parameter name="field1" value="__TIMESTAMP__"/> + <parameter name="field2" value="RESERVED"/> + <parameter name="field3" value="$asePort.uni_circuit_id"/> + </record> + <return status="success"> + <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" /> + </return> +</block></pre></div></div></div> + +</script> + + +<script type="text/javascript"> + var blockXmlEditor ; + RED.nodes.registerType('block',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"block"}, + xml: {value:"<block>\n"}, + atomic: {value:"false"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + var atomic = $( "#node-input-atomic").val(); + if(atomic == "true"){ + $('#node-input-atomic-chkBox').prop('checked', true); + }else{ + $('#node-input-atomic-chkBox').prop('checked', false); + } + + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + blockXmlEditor=that.editor; + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + //console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + //console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + delete blockXmlEditor; + } + }); +function updateXml(){ + if($("#node-input-atomic-chkBox").is(':checked')){ + $("#node-input-name").val("block : atomic"); + $("#node-input-atomic").val("true"); + //alert($("#node-input-xml-editor div.textview div.textviewContent").text()); + var xmlStr = blockXmlEditor.getText(); + var re = new RegExp("<block[^<]+"); + xmlStr=xmlStr.replace(re,"<block atomic='true'>"); + //$("#node-input-xml-editor div.textview div.textviewContent").text(xmlStr); + blockXmlEditor.setText(xmlStr); + //console.log("block xmlStr:" + xmlStr); + }else{ + $("#node-input-name").val("block"); + $("#node-input-atomic").val("false"); + var xmlStr = blockXmlEditor.getText(); + var re = new RegExp("<block[^<]+"); + xmlStr=xmlStr.replace(re,"<block>"); + blockXmlEditor.setText(xmlStr); + //$("#node-input-xml-editor div.textview div.textviewContent").text(xmlStr); + //console.log("block xmlStr:" + xmlStr); + } +} +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/block.js b/dgbuilder/nodes/dge/dgelogic/block.js new file mode 100644 index 00000000..4414d86d --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/block.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function block(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("block",block); + // RED.library.register("block"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/breakNode.html b/dgbuilder/nodes/dge/dgelogic/breakNode.html new file mode 100644 index 00000000..e3edef9d --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/breakNode.html @@ -0,0 +1,161 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="break"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="break"> + <p>A break node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Break_node"></a>Break node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>break</b> node works like a break in any programming language. So you can break out of a for loop.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<p>Not applicable. The <b>break</b> node does not have attributes.</p></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>Not applicable. The <b>break</b> node does not have attributes.</p> </div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<p>Not applicable. The <b>break</b> node has no outcomes.</p></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><break> +</pre></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('break',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"break"}, + xml: {value:"<break>\n"}, + comments:{value:""} + }, + inputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/breakNode.js b/dgbuilder/nodes/dge/dgelogic/breakNode.js new file mode 100644 index 00000000..9b0b1b00 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/breakNode.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function breakNode(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("break",breakNode); + // RED.library.register("block"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/call.html b/dgbuilder/nodes/dge/dgelogic/call.html new file mode 100644 index 00000000..0e49e26c --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/call.html @@ -0,0 +1,183 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="call"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="call"> + <p>A call node.</p> + <p>Name can be anything.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Call_node"></a>Call node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>call</b> node is used to call another graph</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>module</b></td> +<td align="left">Module of directed graph to call. If unset, defaults to that of calling graph</td></tr> +<tr class="b"> +<td align="center"><b>rpc</b></td> +<td align="left">rpc of directed graph to call.</td></tr> +<tr class="a"> +<td align="center"><b>version</b></td> +<td align="left">version of graph to call, If unset, uses active version.</td></tr> +<tr class="b"> +<td align="center"><b>mode</b></td> +<td align="left">mode (sync/async) of graph to call. If unset, defaults to that of calling graph.</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>Not applicable</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"><caption> .</caption> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Sub graph returned success</td></tr> +<tr class="b"> +<td align="center"><b>not-found</b></td> +<td align="left">Graph not found</td></tr> +<tr class="a"> +<td align="center"><b>failure</b></td> +<td align="left">Subgraph returned success</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><call rpc="svc-topology-reserve" mode="sync" /></pre></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('call',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"call"}, + xml: {value:"<call module='' rpc='' mode='sync' >\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + //console.log("show Values clicked."); + showValuesBox(that.editor,rpcValues); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/call.js b/dgbuilder/nodes/dge/dgelogic/call.js new file mode 100644 index 00000000..3570e3db --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/call.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function call(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("call",call); + // RED.library.register("call"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/configure.html b/dgbuilder/nodes/dge/dgelogic/configure.html new file mode 100644 index 00000000..7503b1f1 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/configure.html @@ -0,0 +1,227 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="configure"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="configure"> + <p>A configure node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + + + <div class="section"> +<h3><a name="Device_Management"></a>Device Management</h3> +<div class="section"> +<h4><a name="Configure_node"></a>Configure node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>configure</b> node is used to configure a device.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of resource adaptor to be used</td></tr> +<tr class="b"> +<td align="center"><b>activate</b></td> +<td align="left">Activate device/interface, for devices that support a separate activation step.</td></tr> +<tr class="a"> +<td align="center"><b>key</b></td> +<td align="left">SQL-like string specifying criteria for item to configure</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>Specific to device adaptor.</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Device successfully configured</td></tr> +<tr class="b"> +<td align="center"><b>not-found</b></td> +<td align="left">Element to be configured does not exist.</td></tr> +<tr class="a"> +<td align="center"><b>not-ready</b></td> +<td align="left">Element is not in a state where it can be configured/activated</td></tr> +<tr class="b"> +<td align="center"><b>already-active</b></td> +<td align="left">Attempt to activate element that is already active</td></tr> +<tr class="a"> +<td align="center"><b>failure</b></td> +<td align="left">Configure failed for some other reason</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><configure adaptor="org.onap.ccsdk.sli.adaptor.emt.EmtAdaptor" + key="$uni-circuit-id" activate="true"> + <parameter name="circuit.id" value="$uni-circuit-id" /> + <parameter name="subscriber.name" value="$subscriber-name" /> + <parameter name="emt.clli" value="$edge-device-clli" /> + <parameter name="port.tagging" value="$port-tagging" /> + <parameter name="port.mediaSpeed" value="$media-speed" /> + <parameter name="location.state" value="$uni-location-state" /> + <parameter name="location.city" value="$uni-location-city" /> + <parameter name="cosCategory" value="$cos-category" /> + <parameter name="gosProfile" value="$gos-profile" /> + <parameter name="lldp" value="$asePort.resource-lldp" /> + <parameter name="mtu" value="$asePort.resource-mtu" /> + <outcome value="success"> + <block> + <record plugin="org.onap.ccsdk.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sampler1.log" /> + <parameter name="field1" value="__TIMESTAMP__"/> + <parameter name="field2" value="ACTIVE"/> + <parameter name="field3" value="$uni-circuit-id"/> + </record> + <return status="success"> + <parameter name="edge-device-clli" value="$asePort.resource-emt-clli" /> + </return> + </block> + </outcome> + <outcome value="already-active"> + <return status="failure"> + <parameter name="error-code" value="1590" /> + <parameter name="error-message" value="Port already active" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="Activation failure" /> + </return> + </outcome> +</configure></pre></div></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('configure',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"configure"}, + xml: {value:"<configure adaptor='' key='' activate='' >\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/configure.js b/dgbuilder/nodes/dge/dgelogic/configure.js new file mode 100644 index 00000000..7345750d --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/configure.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function configure(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("configure",configure); + // RED.library.register("configure"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/delete.html b/dgbuilder/nodes/dge/dgelogic/delete.html new file mode 100644 index 00000000..b4c7f52f --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/delete.html @@ -0,0 +1,187 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="delete"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="delete"> + <p>A delete node.</p> + <p>Name can be anything.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Delete_node"></a>Delete node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>delete</b> node is used to delete a resource from the local resource inventory.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of resource adaptor to be used</td></tr> +<tr class="b"> +<td align="center"><b>resource</b></td> +<td align="left">Type of resource to delete</td></tr> +<tr class="a"> +<td align="center"><b>key</b></td> +<td align="left">SQL-like string specifying key to delete</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>None</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Resource specified deleted successfully.</td></tr> +<tr class="b"> +<td align="center"><i>failure</i>></td> +<td align="left">Resource specified was not deleted</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><delete plugin="org.onap.ccsdk.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="uni_circuit_id == $uni-circuit-id"> + <outcome value="true"> + <return status="success"/> + </outcome> + <outcome value="false"> + <return status="failure"/> + </outcome> +</delete></pre></div></div></div> + + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('delete',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"delete"}, + xml: {value:"<delete plugin='' resource='' key=''>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/delete.js b/dgbuilder/nodes/dge/dgelogic/delete.js new file mode 100644 index 00000000..37731061 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/delete.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function deleteNode(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("delete",deleteNode); + // RED.library.register("delete"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/execute.html b/dgbuilder/nodes/dge/dgelogic/execute.html new file mode 100644 index 00000000..3d5fc6d7 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/execute.html @@ -0,0 +1,197 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="execute"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="execute"> + <p>A execute node.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + <div class="section"> +<h3><a name="Java_Plugin_Support"></a>Java Plugin Support</h3> +<div class="section"> +<h4><a name="Execute_node"></a>Execute node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>An <b>execute</b> node is used to execute Java code supplied as a plugin</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of plugin to be used</td></tr> +<tr class="b"> +<td align="center"><b>method</b></td> +<td align="left">Name of method in the plugin class to execute. Method must return void, and take 2 arguments: a Map (for parameters) and a SvcLogicContext (to allow plugin read/write access to context memory)</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>Specific to plugin / method</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Device successfully configured</td></tr> +<tr class="b"> +<td align="center"><b>not-found</b></td> +<td align="left">Plugin class could not be loaded</td></tr> +<tr class="a"> +<td align="center"><b>unsupported-method</b></td> +<td align="left">Named method taking (Map, SvcLogicContext) could not be found</td></tr> +<tr class="b"> +<td align="center"><b>failure</b></td> +<td align="left">Configure failed for some other reason</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><execute plugin="org.onap.ccsdk.sli.plugin.HelloWorld" + method="log"> + <parameter name="message" value="Hello, world!" /> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="not-found"> + <return status="failure"> + <parameter name="error-code" value="1590" /> + <parameter name="error-message" value="Could not locate plugin" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="Internal error" /> + </return> + </outcome> +</execute></pre></div></div></div></div> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('execute',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"execute"}, + xml: {value:"<execute plugin='' method='' >\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/execute.js b/dgbuilder/nodes/dge/dgelogic/execute.js new file mode 100644 index 00000000..66265f98 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/execute.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function execute(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("execute",execute); + // RED.library.register("configure"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/exists.html b/dgbuilder/nodes/dge/dgelogic/exists.html new file mode 100644 index 00000000..001e8ca1 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/exists.html @@ -0,0 +1,187 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="exists"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="exists"> + <p>A exists node.</p> + <p>Name can be anything.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Exists_node"></a>Exists node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>An <b>exists</b> node is used to determine whether a particular instance of a resource exists. For example, this might be used to test whether a particular switch CLLI is provisioned.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of resource adaptor to be used</td></tr> +<tr class="b"> +<td align="center"><b>resource</b></td> +<td align="left">Type of resource to check</td></tr> +<tr class="a"> +<td align="center"><b>key</b></td> +<td align="left">SQL-like string specifying key to check for</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>None</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>true</b></td> +<td align="left">Resource specified exists.</td></tr> +<tr class="b"> +<td align="center"><b>false</b></td> +<td align="left">Resource specified is unknown</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><exists plugin="org.onap.ccsdk.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="uni_circuit_id == $uni-circuit-id"> + <outcome value="true"> + <return status="success"/> + </outcome> + <outcome value="false"> + <return status="failure"/> + </outcome> +</exists></pre></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('exists',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"exists"}, + xml: {value:"<exists plugin='' resource='' key=''>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/exists.js b/dgbuilder/nodes/dge/dgelogic/exists.js new file mode 100644 index 00000000..d4482afc --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/exists.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function exists(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("exists",exists); + // RED.library.register("exists"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/forNode.html b/dgbuilder/nodes/dge/dgelogic/forNode.html new file mode 100644 index 00000000..c7327db4 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/forNode.html @@ -0,0 +1,172 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="for"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="for"> + <p>A for node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>for</b> node provides a fixed iteration looping mechanism, similar to the Java for loop</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>index</b></td> +<td align="left">index variable</td></tr> +<tr class="b"> +<td align="center"><b>start</b></td> +<td align="left">initial value</td></tr> +<tr class="a"> +<td align="center"><b>end</b></td> +<td align="left">maximum value</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>Not applicable.</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<p>Not applicable. The <b>status</b> node has no outcomes.</p></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><for index="i" start="0" end="$network.num-segments"> + <set> + <parameter name="$vlanlist" value="$network.segment[i].provider-segmentation-id"/> + </set> +</for></pre></div></div></div> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('for',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"for"}, + xml: {value:"<for index='' start='' end='' >\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/forNode.js b/dgbuilder/nodes/dge/dgelogic/forNode.js new file mode 100644 index 00000000..567da858 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/forNode.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function forNode(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("for",forNode); + // RED.library.register("for"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/get-resource.html b/dgbuilder/nodes/dge/dgelogic/get-resource.html new file mode 100644 index 00000000..b3b65581 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/get-resource.html @@ -0,0 +1,192 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="get-resource"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="get-resource"> + <p>A get-resource node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Get-resource_node"></a>Get-resource node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>get-resource</b> node is used to retrieve information about a particular resource and make it available to other nodes in the service logic tree. For example, this might be used to retrieve information about a particular uni-port.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of resource adaptor to be used</td></tr> +<tr class="b"> +<td align="center"><b>resource</b></td> +<td align="left">Type of resource to retrieve</td></tr> +<tr class="a"> +<td align="center"><b>key</b></td> +<td align="left">SQL-like string specifying criteria for retrieval</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>None</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Resource successfully released</td></tr> +<tr class="b"> +<td align="center"><b>not-found</b></td> +<td align="left">Resource referenced does not exist</td></tr> +<tr class="a"> +<td align="center"><b>failure</b></td> +<td align="left">Resource release failed for some other reason</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><get-resource plugin="org.onap.ccsdk.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="uni_circuit_id == $uni-circuit-id"> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="not-found"> + <return status="failure"/> + </outcome> + <outcome value="failure"> + <return status="failure"/> + </outcome> +</get-resource></pre></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('get-resource',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"get-resource"}, + xml: {value:"<get-resource plugin='' resource='' key='' >\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/get-resource.js b/dgbuilder/nodes/dge/dgelogic/get-resource.js new file mode 100644 index 00000000..597e0219 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/get-resource.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function getResource(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("get-resource",getResource); + // RED.library.register("get-resource"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/is-available.html b/dgbuilder/nodes/dge/dgelogic/is-available.html new file mode 100644 index 00000000..8bc45ef5 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/is-available.html @@ -0,0 +1,186 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="is-available"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="is-available"> + <p>A is-available node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Is-available_node"></a>Is-available node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>An <b>is-available</b> node is used to determine whether a particular type of resource is available. For example, this might be used to test whether any ports are available for assignment on a particular switch.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of resource adaptor to be used</td></tr> +<tr class="b"> +<td align="center"><b>resource</b></td> +<td align="left">Type of resource to check</td></tr> +<tr class="a"> +<td align="center"><b>key</b></td> +<td align="left">SQL-like string specifying key to check for</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>None</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>true</b></td> +<td align="left">Resource requested is available</td></tr> +<tr class="b"> +<td align="center"><b>false</b></td> +<td align="left">Resource requested is not available</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><is-available plugin="org.onap.ccsdk.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value"> + <outcome value="true"> + <return status="success"/> + </outcome> + <outcome value="false"> + <return status="failure"/> + </outcome> +</is-available></pre></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('is-available',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"is-available"}, + xml: {value:"<is-available plugin='' resource='' key=''>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/is-available.js b/dgbuilder/nodes/dge/dgelogic/is-available.js new file mode 100644 index 00000000..93f23f48 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/is-available.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function isAvailable(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("is-available",isAvailable); + // RED.library.register("is-available"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/notify.html b/dgbuilder/nodes/dge/dgelogic/notify.html new file mode 100644 index 00000000..e5bc24bc --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/notify.html @@ -0,0 +1,195 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="notify"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="notify"> + <p>A notify node.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +<!-- +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>An <b>notify</b> node is used to execute Java code supplied as a plugin</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of plugin to be used</td></tr> +<tr class="b"> +<td align="center"><b>method</b></td> +<td align="left">Name of method in the plugin class to execute. Method must return void, and take 2 arguments: a Map (for parameters) and a SvcLogicContext (to allow plugin read/write access to context memory)</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>Specific to plugin / method</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Device successfully configured</td></tr> +<tr class="b"> +<td align="center"><b>not-found</b></td> +<td align="left">Plugin class could not be loaded</td></tr> +<tr class="a"> +<td align="center"><b>unsupported-method</b></td> +<td align="left">Named method taking (Map, SvcLogicContext) could not be found</td></tr> +<tr class="b"> +<td align="center"><b>failure</b></td> +<td align="left">Configure failed for some other reason</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><notify plugin="org.onap.ccsdk.sli.resource.samplesvc.SampleServiceResource" + resource="network-connection" action="DELETE" > + <parameter name="message" value="Hello, world!" /> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="not-found"> + <return status="failure"> + <parameter name="error-code" value="1590" /> + <parameter name="error-message" value="Could not locate plugin" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="Internal error" /> + </return> + </outcome> +</notify></pre></div></div></div></div> +--> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('notify',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"notify"}, + xml: {value:"<notify plugin='' resource='' action='' >\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + //console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + //console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/notify.js b/dgbuilder/nodes/dge/dgelogic/notify.js new file mode 100644 index 00000000..8b58e9e4 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/notify.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function notify(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("notify",notify); + // RED.library.register("configure"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/record.html b/dgbuilder/nodes/dge/dgelogic/record.html new file mode 100644 index 00000000..3eb7a2e6 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/record.html @@ -0,0 +1,185 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="record"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="record"> + <p>A record node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h3><a name="Recording"></a>Recording</h3> +<div class="section"> +<h4><a name="Record_node"></a>Record node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>record</b> node is used to record an event. For example, this might be used to log provisioning events.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class to handle recording.</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>Parameters will depend on the plugin being used. For the FileRecorder class, the parameters are as follows</p> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>file</b></td> +<td align="left">The file to which the record should be written</td></tr> +<tr class="b"> +<td align="center"><b>field1</b></td> +<td align="left">First field to write. There will be <b>field</b> parameters for each field to write, from <b>field1</b> through <b>fieldN</b>. A special value __TIMESTAMP__ may be assigned to a field to insert the current timestamp</td></tr></table></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Record successfully written</td></tr> +<tr class="b"> +<td align="center"><b>failure</b></td> +<td align="left">Record could not be successfully written</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><record plugin="org.onap.ccsdk.sli.core.sli.recording.FileRecorder"> + <parameter name="file" value="/tmp/sample_r1.log" /> + <parameter name="field1" value="__TIMESTAMP__"/> + <parameter name="field2" value="ACTIVE"/> + <parameter name="field3" value="$uni-circuit-id"/> +</record></pre></div></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('record',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"record"}, + xml: {value:"<record>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/record.js b/dgbuilder/nodes/dge/dgelogic/record.js new file mode 100644 index 00000000..f29bf8f5 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/record.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function record(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("record",record); + // RED.library.register("record"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/release.html b/dgbuilder/nodes/dge/dgelogic/release.html new file mode 100644 index 00000000..044616a9 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/release.html @@ -0,0 +1,192 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="release"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="release"> + <p>A release node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Release_node"></a>Release node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>release</b> node is used to mark a resource as no longer in use, and thus available for assignment.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of resource adaptor to be used</td></tr> +<tr class="b"> +<td align="center"><b>resource</b></td> +<td align="left">Type of resource to release</td></tr> +<tr class="a"> +<td align="center"><b>key</b></td> +<td align="left">SQL-like string specifying key to check of resource to release</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>None</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Resource successfully released</td></tr> +<tr class="b"> +<td align="center"><b>not-found</b></td> +<td align="left">Resource referenced does not exist</td></tr> +<tr class="a"> +<td align="center"><b>failure</b></td> +<td align="left">Resource release failed for some other reason</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><release plugin="org.onap.ccsdk.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="uni_circuit_id == $uni-circuit-id"> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="not-found"> + <return status="failure"/> + </outcome> + <outcome value="failure"> + <return status="failure"/> + </outcome> +</release></pre></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('release',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"release"}, + xml: {value:"<release plugin='' resource='' key='' >\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/release.js b/dgbuilder/nodes/dge/dgelogic/release.js new file mode 100644 index 00000000..ff03fff6 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/release.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function release(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("release",release); + // RED.library.register("release"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/reserve.html b/dgbuilder/nodes/dge/dgelogic/reserve.html new file mode 100644 index 00000000..bcd3fcb9 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/reserve.html @@ -0,0 +1,189 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="reserve"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="reserve"> + <p>A reserve node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Reserve_node"></a>Reserve node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>reserve</b> node is used to reserve a particular type of resource.. For example, this might be used to reserve a port on a particular switch.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of resource adaptor to be used</td></tr> +<tr class="b"> +<td align="center"><b>resource</b></td> +<td align="left">Type of resource to reserve</td></tr> +<tr class="a"> +<td align="center"><b>key</b></td> +<td align="left">SQL-like string specifying criteria for reservation</td></tr> +<tr class="b"> +<td align="center"><b>select</b></td> +<td align="left">String to specify, if <b>key</b> matches multiple entries, which entry should take precedence</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>None</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Resource requested was successfully reserved</td></tr> +<tr class="b"> +<td align="center"><b>failure</b></td> +<td align="left">Resource requested was not successfully reserved</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><reserve plugin="org.onap.ccsdk.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value" + select="min(speed)"> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="failure"> + <return status="failure"/> + </outcome> +</reserve></pre></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('reserve',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"reserve"}, + xml: {value:"<reserve plugin='' resource='' key='' select=''>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/reserve.js b/dgbuilder/nodes/dge/dgelogic/reserve.js new file mode 100644 index 00000000..6aab1bd7 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/reserve.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function reserve(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("reserve",reserve); + // RED.library.register("reserve"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/save.html b/dgbuilder/nodes/dge/dgelogic/save.html new file mode 100644 index 00000000..6e022154 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/save.html @@ -0,0 +1,189 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="save"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="save"> + <p>A save node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Save_node"></a>Save node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>save</b> node is used to save information about a particular resource to persistent storage. For example, this might be used to save information about a particular uni-port.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of resource adaptor to be used</td></tr> +<tr class="b"> +<td align="center"><b>resource</b></td> +<td align="left">Type of resource to save</td></tr> +<tr class="a"> +<td align="center"><b>key</b></td> +<td align="left">SQL-like string specifying criteria for retrieval</td></tr> +<tr class="b"> +<td align="center"><b>force</b></td> +<td align="left">If "true", save resource even if this resource is already stored in persistent storage</td></tr> +<tr class="a"> +<td align="center"><b>pfx</b></td> +<td align="left">Prefix to be prepended to variable names, when attributes are set in SvcLogicContext</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>Values to save (columns) are specified as parameters, with each name corresponding to a column name and each value corresponding to the value to set.</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Resource successfully saved</td></tr> +<tr class="b"> +<td align="center"><b>failure</b></td> +<td align="left">Resource save failed</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><save plugin="`$resource-plugin`" resource="resourceName" + key="keyName=value" + pfx="requests.resourceName"> + <parameter name="parameter1" + value="`$parameterOneValue`" /> + <parameter name="parameter2" value="`$parameterparameterTwoValue`" /> +</save></pre></div></div></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('save',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"save"}, + xml: {value:"<save plugin='' resource='' key='' force='' pfx=''>\n<parameter name='' value='' />\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/save.js b/dgbuilder/nodes/dge/dgelogic/save.js new file mode 100644 index 00000000..5771ae98 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/save.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function save(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("save",save); + // RED.library.register("save"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/set.html b/dgbuilder/nodes/dge/dgelogic/set.html new file mode 100644 index 00000000..bcbcae30 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/set.html @@ -0,0 +1,162 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="set"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="set"> + <p>A set node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Set_node"></a>Set node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>set</b> node is used to set one or more values in the execution context</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<p>Not applicable. The <b>set</b> node does not have attributes.</p></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>Values to be set are passed as parameters</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<p>Not applicable. The <b>set</b> node has no outcomes.</p></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><set> + <parameter name="vlan" value="$network.provider-segmentation-id" /> +</set></pre></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('set',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"set"}, + xml: {value:"<set>\n<parameter name='' value='' />\n"}, + comments:{value:""} + }, + inputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/set.js b/dgbuilder/nodes/dge/dgelogic/set.js new file mode 100644 index 00000000..9b939507 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/set.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function set(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("set",set); + // RED.library.register("set"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/switchNode.html b/dgbuilder/nodes/dge/dgelogic/switchNode.html new file mode 100644 index 00000000..35c9fe67 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/switchNode.html @@ -0,0 +1,232 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="switchNode"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="switchNode"> + <p>A switch node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Switch_node"></a>Switch node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>switch</b> node is used to make a decision based on its <b>test</b> attribute.</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>test</b></td> +<td align="left">Condition to test</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>None</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<p>Depends on the <b>test</b> condition</p></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><switch test="$uni-cir-units"> + <outcome value="Mbps"> + <reserve plugin="org.onap.ccsdk.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value" + pfx="asePort"> + + <outcome value="success"> + <return status="success"> + <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1010" /> + <parameter name="error-message" value="No ports found that match criteria" /> + </return> + </outcome> + </reserve> + </outcome> + <outcome value="Gbps"> + <reserve plugin="org.onap.ccsdk.sli.resource.samplesvc.SampleServiceResource" + resource="ase-port" + key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value*1000" + pfx="asePort"> + + <outcome value="success"> + <return status="success"> + <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1010" /> + <parameter name="error-message" value="No ports found that match criteria" /> + </return> + </outcome> + </reserve> + </outcome> +</switch></pre></div></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('switchNode',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"switch"}, + xml: {value:"<switch test=''>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + //To increase the width of dialogbox + //$(".ui-dialog.ui-widget.ui-widget-content.ui-corner-all.ui-front.ui-dialog-buttons.ui-draggable.ui-resizable").css("width","1400px"); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); + +function encodeTestStr(xmlStr){ + var updatedXmlStr=xmlStr; + if(updatedXmlStr != null){ + var testCondition = getAttributeValue(xmlStr,"test"); + if(testCondition != null && testCondition != ''){ + if(testCondition.indexOf("<") == -1){ + testCondition=testCondition.replace(/</g,"<"); + } + updatedXmlStr="<switch test=\"" + testCondition + "\" >"; + } + } + return updatedXmlStr; +} + +function decodeTestStr(xmlStr){ + var updatedXmlStr=xmlStr; + if(updatedXmlStr != null){ + var testCondition = getAttributeValue(xmlStr,"test"); + if(testCondition != null && testCondition != ''){ + testCondition=testCondition.replace(/</g,"<"); + updatedXmlStr="<switch test=\"" + testCondition + "\" >"; + } + } + return updatedXmlStr; +} +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/switchNode.js b/dgbuilder/nodes/dge/dgelogic/switchNode.js new file mode 100644 index 00000000..6a7a545d --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/switchNode.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function switchNode(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("switchNode",switchNode); + // RED.library.register("switch"); +} diff --git a/dgbuilder/nodes/dge/dgelogic/update.html b/dgbuilder/nodes/dge/dgelogic/update.html new file mode 100644 index 00000000..a7d28283 --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/update.html @@ -0,0 +1,195 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="update"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="update"> + <p>A update node.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +<!-- +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>An <b>update</b> node is used to execute Java code supplied as a plugin</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>plugin</b></td> +<td align="left">Fully qualified Java class of plugin to be used</td></tr> +<tr class="b"> +<td align="center"><b>method</b></td> +<td align="left">Name of method in the plugin class to execute. Method must return void, and take 2 arguments: a Map (for parameters) and a SvcLogicContext (to allow plugin read/write access to context memory)</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>Specific to plugin / method</p></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>success</b></td> +<td align="left">Device successfully configured</td></tr> +<tr class="b"> +<td align="center"><b>not-found</b></td> +<td align="left">Plugin class could not be loaded</td></tr> +<tr class="a"> +<td align="center"><b>unsupported-method</b></td> +<td align="left">Named method taking (Map, SvcLogicContext) could not be found</td></tr> +<tr class="b"> +<td align="center"><b>failure</b></td> +<td align="left">Configure failed for some other reason</td></tr></table></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><update plugin="org.onap.ccsdk.sli.resource.samplesvc.SampleServiceResource" + resource="network-connection" action="DELETE" > + <parameter name="message" value="Hello, world!" /> + <outcome value="success"> + <return status="success"/> + </outcome> + <outcome value="not-found"> + <return status="failure"> + <parameter name="error-code" value="1590" /> + <parameter name="error-message" value="Could not locate plugin" /> + </return> + </outcome> + <outcome value="Other"> + <return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="Internal error" /> + </return> + </outcome> +</update></pre></div></div></div></div> +--> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('update',{ + color:"#fdd0a2", + category: 'DGElogic', + defaults: { + name: {value:"update"}, + xml: {value:"<update resource='' force='' plugin='' key='' pfx='' local-only=''>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + //console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + //console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgelogic/update.js b/dgbuilder/nodes/dge/dgelogic/update.js new file mode 100644 index 00000000..f614af8b --- /dev/null +++ b/dgbuilder/nodes/dge/dgelogic/update.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function update(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("update",update); + // RED.library.register("configure"); +} diff --git a/dgbuilder/nodes/dge/dgemain/GenericXML.html b/dgbuilder/nodes/dge/dgemain/GenericXML.html new file mode 100644 index 00000000..4c9c01a6 --- /dev/null +++ b/dgbuilder/nodes/dge/dgemain/GenericXML.html @@ -0,0 +1,140 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="GenericXML"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 250px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show SLI Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="GenericXML"> + <p>A generic DGEmain node.</p> + <p>Name can be anything.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('GenericXML',{ + color:"#fdd0a2", + category: 'DGEmain', + defaults: { + name: {value:"dge-node"}, + xml: {value:""}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + //console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgemain/GenericXML.js b/dgbuilder/nodes/dge/dgemain/GenericXML.js new file mode 100644 index 00000000..e5fc0624 --- /dev/null +++ b/dgbuilder/nodes/dge/dgemain/GenericXML.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function GenericXML(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("GenericXML",GenericXML); + // RED.library.register("GenericXML"); +} diff --git a/dgbuilder/nodes/dge/dgemain/comment.html b/dgbuilder/nodes/dge/dgemain/comment.html new file mode 100644 index 00000000..c34d14c9 --- /dev/null +++ b/dgbuilder/nodes/dge/dgemain/comment.html @@ -0,0 +1,97 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="comment"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-comment"></i> Comment</label> + <input type="text" id="node-input-name" placeholder="Comment"> + </div> + <div class="form-row"> + <label for="node-input-info" style="width: 100% !important;"><i class="fa fa-comments"></i> More</label> + <input type="hidden" id="node-input-info" autofocus="autofocus"> + <div style="height: 250px;" class="node-text-editor" id="node-input-info-editor" ></div> + <input type="hidden" id="node-input-comments"> + </div> + <div class="form-tips">Tip: this isn't meant for "War and Peace" - but useful notes can be kept here.</div> +</script> + +<script type="text/x-red" data-help-name="comment"> + <p>Simple comment block.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('comment',{ + category: 'DGEmain', + color:"#ffffff", + defaults: { + name: {value:""}, + info: {value:""}, + comments:{value:""} + }, + inputs:0, + outputs:0, + icon: "comment.png", + label: function() { + return this.name||""; + }, + labelStyle: function() { + return this.name?"node_label_italic":""; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-info-editor").css("height",(ui.size.height-235)+"px"); + }; + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-info-editor'), + lang:"text", + showLinesRuler:false, + showFoldingRuler:false, + contents: $("#node-input-info").val() + }); + $("#node-input-name").focus(); + }); + }, + oneditsave: function() { + $("#node-input-info").val(this.editor.getText()); + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgemain/comment.js b/dgbuilder/nodes/dge/dgemain/comment.js new file mode 100644 index 00000000..ef5f0800 --- /dev/null +++ b/dgbuilder/nodes/dge/dgemain/comment.js @@ -0,0 +1,23 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + function CommentNode(n) { + RED.nodes.createNode(this,n); + } + RED.nodes.registerType("comment",CommentNode); +} diff --git a/dgbuilder/nodes/dge/dgemain/dgstart.html b/dgbuilder/nodes/dge/dgemain/dgstart.html new file mode 100644 index 00000000..9caa841a --- /dev/null +++ b/dgbuilder/nodes/dge/dgemain/dgstart.html @@ -0,0 +1,1322 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<div id="svclogicPageDiv" ></div> +<!-- dgbuilder javascript files START --> +<script src="util/js/validateNodeXml.js"/> +<script src="util/js/sliValues.js"/> +<script src="util/js/dgeToXml.js"/> +<script src="util/js/vkbeautify.0.99.00.beta.js"/> +<!-- dgbuilder javascript files END --> + +<script type="text/x-red" data-template-name="dgstart"> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> +<style> +.no-close .ui-dialog-titlebar-close {display: none } +.alertDialogButton { + border-top: 1px solid #96d1f8; + background: #65a9d7; + background: -webkit-gradient(linear, left top, left bottom, from(#3e779d), to(#65a9d7)); + background: -webkit-linear-gradient(top, #3e779d, #65a9d7); + background: -moz-linear-gradient(top, #3e779d, #65a9d7); + background: -ms-linear-gradient(top, #3e779d, #65a9d7); + background: -o-linear-gradient(top, #3e779d, #65a9d7); + padding: 5px 10px; + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: rgba(0,0,0,1) 0 1px 0; + -moz-box-shadow: rgba(0,0,0,1) 0 1px 0; + box-shadow: rgba(0,0,0,1) 0 1px 0; + text-shadow: rgba(0,0,0,.4) 0 1px 0; + color: white; + font-size: 14px; + font-family: Georgia, serif; + text-decoration: none; + vertical-align: middle; + } +.alertDialogButton:hover { + border-top-color: #28597a; + background: #28597a; + color: #ccc; + } + +.alertDialogButton:active { + border-top-color: #1b435e; + background: #1b435e; + } +.disabled-button { + border-top: 1px solid #96d1f8; + background: lightgrey; + background: -webkit-gradient(linear, left top, left bottom, from(grey), to(lightgrey)); + background: -webkit-linear-gradient(top, grey, grey); + background: -moz-linear-gradient(top, grey, grey); + background: -ms-linear-gradient(top, grey, grey); + background: -o-linear-gradient(top, grey, grey); + padding: 5px 10px; + -webkit-border-radius: 8px; + -moz-border-radius: 8px; + border-radius: 8px; + -webkit-box-shadow: rgba(0,0,0,1) 0 1px 0; + -moz-box-shadow: rgba(0,0,0,1) 0 1px 0; + box-shadow: rgba(0,0,0,1) 0 1px 0; + text-shadow: rgba(0,0,0,.4) 0 1px 0; + color: lightgrey; + font-size: 14px; + font-family: Georgia, serif; + text-decoration: none; + vertical-align: middle; + } +</style> +<script type="text/javascript"> + +function activateDG(module,rpc,version,mode,displayOnlyCurrent){ + var paramsObj = {'module': module , 'rpc' : rpc , 'version' : version , 'mode' : mode,'displayOnlyCurrent' : false}; + if(displayOnlyCurrent){ + paramsObj = {'module': module , 'rpc' : rpc , 'version' : version , 'mode' : mode,'displayOnlyCurrent' : true}; + } + var dgInfo = "<div><table width='100%' border='1'><tr style='background-color:#65a9d7;color:white;' ><th>Module</th><th>RPC</th><th>Version</th></tr><tr style='background-color:white'><td>" + module +"</td><td>" + rpc + "</td><td>" +version + "</td></tr></table></div><br>"; + var alertMsg = dgInfo + "<p>Are you sure you want to Activate this DG ?</p>"; +$( "#alertdialog" ).dialog({ + dialogClass: "no-close", + autoOpen :false, + modal:true, + draggable : true, + /*dialogClass: "alert",*/ + title: "Confirm Activate", + width: 600, + buttons: [ + { + text: "Activate", + class:"alertDialogButton", + click: function() { + $.get("/activateDG" , paramsObj) + .done(function( data ) { + //RED.notify("<strong>Activated Successfully</strong>"); + var htmlStr = ""; + var title =""; + if(displayOnlyCurrent){ + htmlStr=getHtmlStr(data,true); + title="Service Logic Administration Module=" + module + " and RPC=" + rpc; + }else{ + htmlStr=getHtmlStr(data); + title= "Service Logic Administration - " + data.dbHost; + } + $("#svclogicPageDiv").dialog({ + modal:true, + title: title, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .fail(function( err ) { + RED.notify("<strong>Could not Activate</strong>"); + var htmlStr = "<p>" + "could not activate" + module + " " + rpc + " " + version +"</p> <a onclick='javascript:showSLA()'></a>"; + if(displayOnlyCurrent == true){ + htmlStr = "<p>" + "could not activate" + module + " " + rpc + " " + version +"</p> <a onclick='javascript:showCurrentDGs(\"" + module + "\",\"" + rpc + "\")'>Back to DG List</a>"; + } + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Service Logic Administration - " + err.dbHost, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .always(function() { + // $('.ui-dialog:has(#alertdialog)').empty().remove(); + $("#alertdialog" ).dialog('close'); + + }); + } + }, + { + text: "Cancel", + class:"alertDialogButton", + click: function() { + //$('.ui-dialog:has(#alertdialog)').empty().remove(); + $( this ).dialog( "close" ); + } + } + ] +}).html(alertMsg).dialog('open'); +//var dialogClass = $("#alertdialog").dialog( "option", "dialogClass" ); +//$( "#alertdialog" ).dialog( "option", "dialogClass", "alert" ); +//$("#alertdialog").dialog("widget").find(".ui-dialog-buttonpane").css("background-color", "#ECECFF"); +/* +$('#alertdialog').css("background-color", "#ECECEC"); +$("#alertdialog").dialog("widget").find(".ui-dialog-buttonpane").css("background-color", "#ECECEC"); + +// button pane style +$("#alertdialog").dialog("widget").find(".ui-dialog-buttonpane").css({"padding":".1em .1em .1em 0","margin":"0 0 0 0"} ) + +// button style +$("#alertdialog").dialog("widget").find("button").css({"padding":"0 .2em 0 .2em","margin":"0 .5em 0 0"} ) +$("#alertdialog").dialog("widget").find("button").addClass("alertDialogButton"); +*/ +//console.dir($("#alertdialog")); +} + + +function deActivateDG(module,rpc,version,mode,displayOnlyCurrent){ + var paramsObj = {'module': module , 'rpc' : rpc , 'version' : version , 'mode' : mode,'displayOnlyCurrent' : false}; + if(displayOnlyCurrent){ + paramsObj = {'module': module , 'rpc' : rpc , 'version' : version , 'mode' : mode,'displayOnlyCurrent' : true}; + } + var dgInfo = "<div ><table width='100%' border='1'><tr style='background-color:#65a9d7;color:white;'><th>Module</th><th>RPC</th><th>Version</th></tr><tr style='background-color:white'><td>" + module +"</td><td>" + rpc + "</td><td>" +version + "</td></tr></table></div><br>"; + var alertMsg = dgInfo + "<p>Are you sure you want to De-Activate this DG ?</p>"; +$( "#alertdialog" ).dialog({ + dialogClass: "no-close", + autoOpen : false, + modal:true, + draggable : true, + title: "Confirm De-Activate", + width: 600, + buttons: [ + { + text: "De-Activate", + class:"alertDialogButton", + click: function() { + $.get("/deActivateDG" , paramsObj) + .done(function( data ) { + //RED.notify("<strong>deActivated Successfully</strong>"); + var htmlStr = ""; + var title =""; + if(displayOnlyCurrent){ + htmlStr=getHtmlStr(data,true); + title="Service Logic Administration Module=" + module + " and RPC=" + rpc; + }else{ + htmlStr=getHtmlStr(data); + title= "Service Logic Administration - " + data.dbHost; + } + $("#svclogicPageDiv").dialog({ + modal:true, + title: title, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .fail(function( err ) { + RED.notify("<strong>Could not De-Activate</strong>"); + var htmlStr = "<p>" + "could not deactivate" + module + " " + rpc + " " + version +"</p> <a onclick='javascript:showSLA()'></a>"; + if(displayOnlyCurrent == true){ + htmlStr = "<p>" + "could not deactivate" + module + " " + rpc + " " + version +"</p> <a onclick='javascript:showCurrentDGs(\"" + module + "\",\"" + rpc + "\")'>Back to DG List</a>"; + } + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Service Logic Administration - " + err.dbHost, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .always(function() { + //$('.ui-dialog:has(#alertdialog)').empty().remove(); + $( "#alertdialog" ).dialog( "close" ); + //$("#alertdialog" ).dialog('destroy').remove(); + }); + } + }, + { + text: "Cancel", + class:"alertDialogButton", + click: function() { + //$('.ui-dialog:has(#alertdialog)').empty().remove(); + //$(this).dialog('destroy').remove() + //$( this ).dialog( "close" ); + /*if ($("#alertdialog").hasClass('ui-dialog-content')) { + $("#alertdialog" ).dialog('close'); + }else{ + $( this ).dialog( "close" ); + } + */ + $( this ).dialog( "close" ); + } + } + ] +}).html(alertMsg).dialog("open"); +} + +function deleteDG(module,rpc,version,mode,displayOnlyCurrent){ + var paramsObj = {'module': module , 'rpc' : rpc , 'version' : version , 'mode' : mode,'displayOnlyCurrent' : false}; + if(displayOnlyCurrent){ + paramsObj = {'module': module , 'rpc' : rpc , 'version' : version , 'mode' : mode,'displayOnlyCurrent' : true}; + } + var dgInfo = "<div ><table width='100%' border='1'><tr style='background-color:#65a9d7;color:white;'><th>Module</th><th>RPC</th><th>Version</th></tr><tr style='background-color:white'><td>" + module +"</td><td>" + rpc + "</td><td>" +version + "</td></tr></table></div><br>"; + var alertMsg = dgInfo + "<p>Are you sure you want to Delete this DG ?</p>"; +$( "#alertdialog" ).dialog({ + dialogClass: "no-close", + autoOpen: false, + modal:true, + draggable : true, + title: "Confirm Delete", + width: 600, + buttons: [ + { + text: "Delete", + class:"alertDialogButton", + click: function() { + $.get("/deleteDG" , paramsObj) + .done(function( data ) { + RED.notify("<strong>Deleted " + module + " " + rpc + " " + version + " Successfully</strong>"); + var htmlStr = ""; + var title =""; + if(displayOnlyCurrent){ + htmlStr=getHtmlStr(data,true); + title="Service Logic Administration Module=" + module + " and RPC=" + rpc; + }else{ + htmlStr=getHtmlStr(data); + title= "Service Logic Administration - " + data.dbHost; + } + $("#svclogicPageDiv").dialog({ + modal:true, + title: title, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .fail(function( err ) { + //RED.notify("<strong>Could not Delete" + module + " " + rpc + " " + version + "</strong>"); + var htmlStr = "<p>" + "could not delete" + module + " " + rpc + " " + version +"</p> <a onclick='javascript:showSLA()'></a>"; + if(displayOnlyCurrent == true){ + htmlStr = "<p>" + "could not delete" + module + " " + rpc + " " + version +"</p> <a onclick='javascript:showCurrentDGs(\"" + module + "\",\"" + rpc + "\")'>Back to DG List</a>"; + } + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Service Logic Administration - " + err.dbHost, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .always(function() { + $( "#alertdialog" ).dialog( "close" ); + //$('.ui-dialog:has(#alertdialog)').empty().remove(); + //$("#alertdialog" ).dialog('destroy').remove(); + }); + } + }, + { + text: "Cancel", + class:"alertDialogButton", + click: function() { + /* + if ($("#alertdialog").hasClass('ui-dialog-content')) { + $("#alertdialog" ).dialog('close'); + }else{ + $( this ).dialog( "close" ); + } + */ + //$( "#alertdialog" ).dialog( "close" ); + //$('.ui-dialog:has(#alertdialog)').empty().remove(); + //$( this ).dialog( "close" ); + $( this ).dialog( "close" ); + } + } + ] +}).html(alertMsg).dialog("open"); +} +/* +function downloadDGXml(_module,rpc,version,mode){ + var paramsObj = {'_module': _module , 'rpc' : rpc , 'version' : version , 'mode' : mode}; + var form = $('<form id="dwnldDbXmlFormId" method="POST" action="/downloadDGXml"></form>'); + form.append('<input type="hidden" name="_module" value="' + _module + '"/>'); + form.append('<input type="hidden" name="rpc" value="' + rpc + '"/>'); + form.append('<input type="hidden" name="version" value="' + version + '"/>'); + form.append('<input type="hidden" name="mode" value="' + mode + '"/>'); + form.appendTo('body'); + $("#dwnldDbXmlFormId").submit(); +} +*/ + +function displayXml(module,rpc,version,mode,displayOnlyCurrent){ + var paramsObj = {'_module': module , 'rpc' : rpc , 'version' : version , 'mode' : mode,'displayOnlyCurrent' : false}; + var title="Service Logic Administration"; + if(displayOnlyCurrent){ + paramsObj = {'_module': module , 'rpc' : rpc , 'version' : version , 'mode' : mode,'displayOnlyCurrent' : true}; + title="Service Logic Administration Module=" + module + " and RPC=" + rpc; + }else{ + title="Service Logic Administration"; + } + //var headingStr = "<a style='color: #337ab7;' onclick='javascript:showSLA()'><<Back to DG List</a><br><div style='background-color:#337ab7;clear:both;'><table style='width:100%;' border='0'>" + + var headingStr = "<a style='color: #337ab7;cursor:pointer;' onclick='javascript:showSLA()'><<Back to DG List</a><br><div style='clear:both;'><table style='width:25%' border='0'>" ; + if(displayOnlyCurrent == true){ + headingStr = "<a style='color: #337ab7;cursor:pointer;' onclick='javascript:showCurrentDGs(\"" + module + "\",\"" + rpc + "\")'><<Back to DG List</a><br><div style='clear:both;'><table style='width:25%' border='0'>" ; + } + headingStr += "<tr><td><b>Module</b></td><td>" + module + "</td></tr>" + + "<tr><td><b>RPC</b></td><td>" + rpc + "</td></tr>" + + "<tr><td><b>Version</b></td><td>" + version + "</td></tr>" + + "<tr><td><b>Mode</b></td><td>" + mode + "</td></tr>" + + "</table></div>"; + + //var urlStr = "/displayXml?_module=" + module + "&rpc=" + rpc + "&version=" + version + "&mode=" + mode; + $.get("/displayXml",paramsObj) + .done(function( data ) { + //var htmlStr= headingStr + '<div style="clear:both;"></div><div style="background-color:lightgrey;border-style: solid;border-color:#337ab7;clear:both;">' + data.xmldata + "</div>"; + var htmlStr= headingStr + '<hr style="clear:both;height:5px;background-color:#337ab7;"><div>' + data.xmldata + "</div>"; + $("#svclogicPageDiv").dialog({ + modal:true, + title: title, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .fail(function( err ) { + //RED.notify("<strong>Could not display XML</strong>"); + var htmlStr = "<p>" + "Could not display xml for" + module + " " + rpc + " " + version + "</p><a style='color: #337ab7;cursor:pointer;' onclick='javascript:showSLA()'>Back to DG List</a><br>"; + if(displayOnlyCurrent == true){ + htmlStr = "<p>" + "could not display XML" + module + " " + rpc + " " + version +"</p> <a onclick='javascript:showCurrentDGs(\"" + module + "\",\"" + rpc + "\")'>Back to DG List</a>"; + } + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Service Logic Administration", + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .always(function() { + }); +} + +function displayDG(module,rpc,version,mode,displayOnlyCurrent){ + var paramsObj = {'_module': module , 'rpc' : rpc , 'version' : version , 'mode' : mode,'displayOnlyCurrent' : false}; + var title="Service Logic Administration"; + if(displayOnlyCurrent){ + paramsObj = {'_module': module , 'rpc' : rpc , 'version' : version , 'mode' : mode,'displayOnlyCurrent' : true}; + } + //var headingStr = "<a style='color: #337ab7;cursor:pointer' onclick='javascript:showSLA()'><<Back to DG List</a><br><div><table id='msgTable' style='width:25%;background-color:lightgrey' border='0'>" + + var headingStr = "<a style='color: #337ab7;cursor:pointer;' onclick='javascript:showSLA()'><<Back to DG List</a><br><div><table id='msgTable' style='width:25%;' border='0'>" ; + if(displayOnlyCurrent == true){ + headingStr = "<a style='color: #337ab7;cursor:pointer;' onclick='javascript:showCurrentDGs(\"" + module + "\",\"" + rpc + "\")'><<Back to DG List</a><br><div style='clear:both;'><table style='width:25%' border='0'>" ; + title="Service Logic Administration Module=" + module + " and RPC=" + rpc; + } + headingStr +="<tr><td><b>Module</b></td><td>" + module + "</td></tr>" + + "<tr><td><b>RPC</b></td><td>" + rpc + "</td></tr>" + + "<tr><td><b>Version</b></td><td>" + version + "</td></tr>" + + "<tr><td><b>Mode</b></td><td>" + mode + "</td></tr>" + + "</table></div>"; + + //var urlStr = "/displayAsGv?_module=" + module + "&rpc=" + rpc + "&version=" + version + "&mode=" + mode; + $.get("/displayAsGv",paramsObj) + .done(function( data ) { + var htmlStr= headingStr + '<div style="background-color:white;">' + data.svg_html + "</div>"; + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Service Logic Administration", + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .fail(function( err ) { + //RED.notify("<strong>Could not display XML</strong>"); + var htmlStr = "<p>" + "Could not display DG for" + module + " " + rpc + " " + version + "</p><a style='color: #337ab7;cursor:pointer;' onclick='javascript:showSLA()'>Back to DG List</a><br>"; + if(displayOnlyCurrent == true){ + htmlStr = "<p>" + "could not display DG for" + module + " " + rpc + " " + version +"</p> <a onclick='javascript:showCurrentDGs(\"" + module + "\",\"" + rpc + "\")'>Back to DG List</a>"; + } + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Service Logic Administration", + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .always(function() { + }); +} + +function getHtmlStr(data,displayOnlyCurrent,module,rpc){ + var styleStr = "<style> " + + "table#t01 { width:100%; } \n" + + "table#t01 th,table#t01 td { border: 1px solid black; border-collapse: collapse; } \n" + + /*"table, th, td { border: 1px solid #65a9d7; border-collapse: collapse; } \n" +*/ + "table#t01 th,table#t01 td { padding: 5px; text-align: left; } \n" + + "table#t01 tr:nth-child(even) { background-color: #eee; }\n" + + "table#t01 tr:nth-child(odd) { background-color:#fff; }\n" + + "table#t01 th { background-color: #65a9d7; color: white; }\n" + + "table#t01 a { color: #337ab7; }\n" + + "table#t01 a:link { color: #65a9d7; }\n" + + "table#t01 a:visited { color: #636; }\n" + + "table#t01 a:hover { color: #3366CC; cursor: pointer }\n" + + "table#t01 a:active { color: #65a9d7 }\n" + + "</style>"; + if(data != null && data.rows != undefined && data.error == undefined){ + var alertDialog = '<div id="alertdialog"></div>'; + htmlStr= alertDialog + "<div style='width:1050;height:650'>" + styleStr; + htmlStr += "<table id='t01' >"; + htmlStr += "<tr>"; + htmlStr += "<th>Module</th>" ; + htmlStr += "<th>RPC</th>" ; + htmlStr += "<th>Version</th>" ; + htmlStr += "<th>Mode</th>" ; + htmlStr += "<th>Active</th>" ; + htmlStr += "<th>Activate/Deactivate</th>"; + htmlStr += "<th>Display DG</th>"; + htmlStr += "<th>XML</th>"; + htmlStr += "<th>Delete</th>"; + htmlStr += "</tr>"; + var rows = data.rows; + if(rows != null && rows.length == 0){ + htmlStr += "<tr>"; + htmlStr += "<td><b>No rows found</b></td>"; + htmlStr += "</tr></table></div>"; + return htmlStr; + } + for(var i=0;i<rows.length;i++){ + var row = rows[i]; + var _module = row.module; + var rpc = row.rpc; + var version = row.version; + var mode = row.mode; + var active = row.active; + htmlStr += "<tr>"; + htmlStr += "<td>" + _module + "</td>"; + htmlStr += "<td>" + rpc + "</td>"; + htmlStr += "<td>" + version + "</td>"; + htmlStr += "<td>" + mode + "</td>"; + htmlStr += "<td>" + active + "</td>"; + + var methodParams = "'" + _module + "','" + rpc + "','" + version + "','" + mode + "'"; + if(displayOnlyCurrent){ + methodParams+= ",true"; + } + if(active == 'Y'){ + htmlStr += "<td><a onclick=\"javascript:deActivateDG(" + methodParams + ")\">DeActivate</a></td>"; + }else{ + htmlStr += "<td><a onclick=\"javascript:activateDG(" + methodParams + ")\">Activate</a></td>"; + } + htmlStr += "<td><a onclick=\"javascript:displayDG(" + methodParams + ")\">Display</a></td>"; + + htmlStr += "<td><a onclick=\"javascript:displayXml(" + methodParams + ")\">XML</a></td>"; + + htmlStr += "<td><a onclick=\"javascript:deleteDG(" + methodParams + ")\">Delete</a></td>"; + htmlStr += "</tr>"; + } + htmlStr += "</table>"; + htmlStr += "</div>"; + } + return htmlStr; +} + +function showSLA(){ + var htmlStr = ""; + try{ + $.get("/listSLA") + .done(function( data ) { + var htmlStr=getHtmlStr(data); + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Service Logic Administration - " + data.dbHost, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .fail(function(err) { + htmlStr= "<div>Error occured displaying the DG list</div>"; + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Service Logic Administration - " + data.dbHost, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .always(function() { + }); + }catch(err){ + } +} + +function showCurrentDGs(module,rpc){ + var htmlStr = ""; + try{ + var params="?module=" + module + "&rpc=" + rpc; + var url="/listCurrentDGs" + params; + //console.log("url:" + url); + $.get(url) + .done(function( data ) { + var htmlStr=getHtmlStr(data,true); + $("#svclogicPageDiv").dialog({ + modal:true, + title:"Service Logic Administration Module=" + module + " and RPC=" + rpc, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .fail(function(err) { + htmlStr= "<div>Error occured displaying the DG list</div>"; + $("#svclogicPageDiv").dialog({ + modal:true, + title:"Service Logic Administration Module=" + module + " and RPC=" + rpc, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }) + .always(function() { + }); + }catch(err){ + } +} + + +function displaySLA(callback){ + var htmlStr = ""; + try{ + $.get("/listSLA") + .done(function( data ) { + var htmlStr=getHtmlStr(data); + callback(htmlStr,data.dbHost); + }) + .fail(function(err) { + htmlStr= "<div>Error occured displaying the DG list</div>"; + callback(htmlStr,err.dbHost); + }) + .always(function() { + }); + }catch(err){ + callback(htmlStr,""); + } +} + +function displayCurrentDGs(module,rpc,callback){ + var htmlStr = ""; + try{ + var params="?module=" + module + "&rpc=" + rpc; + var url="/listCurrentDGs" + params; + //console.log("url:" + url); + $.get(url ) + .done(function( data ) { + var htmlStr=getHtmlStr(data,true); + callback(htmlStr,data.dbHost); + }) + .fail(function(err) { + htmlStr= "<div>Error occured displaying the Current DG list</div>"; + callback(htmlStr,err.dbHost); + }) + .always(function() { + }); + }catch(err){ + callback(htmlStr,""); + } +} + + +window.onbeforeunload = function (event) { + var dis = $('#btn-deploy').attr('class') + if ( dis.indexOf('disabled') == -1 ) { + var message = 'Important: You have changes that were not \'deployed\'.'; + if (typeof event == 'undefined') { + event = window.event; + } + if (event) { + event.returnValue = message; + } + return message; + } +}; +</script> +<script type="text/x-red" data-help-name="dgstart"> + <p>This node starts a flow. This node is required on every flow.</p> + <p>This node has a button to its left, when clicked generates the XML for the flow</p> + <img src="images/dgstart.png"></img> +</script> +<style> +.textview{ + font-size:20px; +} +</style> + +<div id="screenInfoId"></div> +<script type="text/javascript"> +function getAttributeValue(xmlStr,attribute){ + var attrVal=null; + try{ + var myRe = new RegExp(attribute + "[\s+]?=[\s+]?['\"]([^'\"]+)['\"]","m"); + var myArray = myRe.exec(xmlStr); + if(myArray != null && myArray[1] != null){ + attrVal=myArray[1]; + } + }catch(err){ + console.log(err); + } + return attrVal; + +} + + +function showDgStartGenerateXmlStatus(){ + var htmlStr="<div id='dgstart-generate-xml-div' style='width:375;height:225'><p>Generating XML. Please wait... </p><img src='images/page-loading.gif'></div>" + $("#dgstart-generate-xml-dialog").dialog({ + modal:true, + title: "DGBuilder XML Generation Status", + width: 400, + height: 250, + minWidth : 400, + minHeight :200, + }).html(htmlStr); +} + + RED.nodes.registerType('dgstart',{ + color:"#fdd0a2", + category: 'DGEmain', + defaults: { + name: {value:"DGSTART"}, + outputs: {value:1} + }, + inputs:0, + outputs:1, + icon: "inject.png", + label: function() { + return this.name; + }, + onpaletteadd: function() { + //console.log("DGSTART Added to the palette."); + }, + button: { + onclick: function() { + //$('#processingStatusId').text('working...'); + //$('#processingStatusId').html("<span><p> Processing Please Wait...</span><img src='images/page-loading.gif'>"); + $('#processingStatusId').html("<span style='font-size:0.2em;color:green'> Processing...</span>"); + var timerObj = window.setTimeout(function() { + //document.getElementById("processingStatusId").innerHTML ="<img src='images/page-loading.gif'>"; + + /* + var target = $(event.target); + //target.text("Validating XML"); + target.css({ "background-image": "url('images/page-loading.gif')" }); + target.css({ "background-repeat": "no-repeat" }); + target.css({ "background-size": "25px 25px" }); + */ + + //deploy button + //$("#btn-deploy") + var loopDetectionEnabled = true; + console.log("loopDetectionEnabled:" +loopDetectionEnabled); + if(loopDetectionEnabled){ + var msecs1= Date.now(); + var isLoopDetected = detectLoop(); + var msecs2= Date.now(); + console.log("Time taken for loop detection:" + (msecs2 - msecs1)); + if(isLoopDetected){ + //RED.notify("<strong>Error</strong>: Loop Detected","error"); + //target.css({ "background-image": "none" }); + return false; + } + } + var nodeSetWithUpdatedDgNumbers = updateDgNumbers(); + validateEachNodeXml(); + //var nodeToXmlStr = getNodeToXml(); + var unformatted_xml_str = getNodeToXml(); + //console.log("Size of unformatted_xml_str" + unformatted_xml_str.length); + //console.log("output:" + nodeToXmlStr); + var formatted_xml = vkbeautify.xml(unformatted_xml_str); + /* + var minified_xml = vkbeautify.xmlmin(unformatted_xml_str,true); + var lengthOfMinifiedXml = minified_xml.length; + if(lengthOfMinifiedXml >0){ + var val = lengthOfMinifiedXml/(1024*1024) + var minSizeStr = val.toFixed(4) + " MB"; + console.log("minified XML size:" + minSizeStr); + } + */ + var lengthOfXml = formatted_xml.length; + var sizeStr = ""; + if(lengthOfXml >0){ + var val = lengthOfXml/(1024*1024) + sizeStr = val.toFixed(4) + " MB"; + console.log("length:" + val); + } + var xmlLines = formatted_xml.split("\n"); + console.log("Number of lines " + xmlLines.length); + var numberOfLines = xmlLines.length; + //var display_formatted_xml = formatted_xml.replace("<","<"); + var currentNodeSet = getCurrentFlowNodeSet(); + //get max x and y coordinates + var x=0; + var y=0; + var maxX=0; + var maxY=0; + var moduleName = ""; + var dgVersion = ""; + var methodName = ""; + var formattedMethodName = ""; + var origModuleName = ""; + var origMethodName = ""; + for(var i=0;currentNodeSet != null && i<currentNodeSet.length;i++){ + if(currentNodeSet[i].type == "service-logic"){ + //moduleName = currentNodeSet[i].name; + moduleName = currentNodeSet[i].module; + dgVersion = currentNodeSet[i].version; + origModuleName = getAttributeValue(currentNodeSet[i].xml,"module"); + } + if(currentNodeSet[i].type == "method"){ + //methodName = currentNodeSet[i].name; + origMethodName = getAttributeValue(currentNodeSet[i].xml,"rpc");; + methodName = origMethodName; + if(methodName == ""){ + methodName = "rpc_not_set"; + } + } + x = currentNodeSet[i].x; + y = currentNodeSet[i].y; + if(x>maxX){ + maxX=x; + } + if(y>maxY){ + maxY=y; + } + } + //add 5 more pixels to that + maxX= Math.ceil(maxX) + 5; + maxY= Math.ceil(maxY) + 5; + //console.log("maxX:" + maxX); + //console.log("maxY:" + maxY); + var unformatted_json_str=JSON.stringify(currentNodeSet); + var formatted_json = vkbeautify.json(unformatted_json_str); + //var displayHtmlStr="<div><textarea readonly='1' style='width:1100px;height:700px;border:none'>" + formatted_xml + "</textarea></div>"; + var displayHtmlStr="<div style='font-size:20px;'><xmp>" + formatted_xml + "</xmp></div>"; + var xmlInfoStr = "<div id='xml-info-div'><p>" + "XML size:" + sizeStr + " <br>Number of Lines:" + numberOfLines + "</p></div>"; + var htmlCode =""; + $( "#xmldialog" ).dialog({ + title: "XML Generated", + width: 1200, + height: 750, + minWidth : 800, + minHeight :450, + dialogClass : "no-close", + closeOnEscape : false, + autoOpen : false, + resize: function( event, ui ) { + /* + $( this ).dialog( "option", "title", + ui.size.height + " x " + ui.size.width ); + */ + }, + modal: true, + /*show: { + effect: "slide", + duration: 1000 + }, + */ + /*hide: { + effect: "slide", + duration: 500 + }, + */ + buttons: { + /* + "+" : function () { + var size= $("#xmldialog").find('.textview').css("font-size"); + console.log("size:" + size); + size=size.replace("px",""); + var fsize=Number(size) +1; + if(fsize<19){ + fsize+=4; + } + if(fsize >= 26){ + return; + } + $("#xmldialog").find('.textview').css("font-size",fsize); + }, + "-" : function () { + var size= $("#xmldialog").find('.textview').css("font-size"); + console.log("size:" + size); + size=size.replace(/px/,""); + var fsize=Number(size) -1; + if(fsize <= 14){ + return; + } + $("#xmldialog").find('.textview').css("font-size",fsize); + }, + */ + "Validate XML" : function (event) { + if(!event) event = window.event; + var target = $(event.target); + target.text("Validating XML"); + target.css({ "background-image": "url('images/page-loading.gif')" }); + target.css({ "background-repeat": "no-repeat" }); + target.css({ "background-size": "25px 25px" }); + + var resp= validateFinalXML(unformatted_xml_str); + console.log("errorList:" + errList); + if(!resp){ + showErrors(); + } + target.text("Validate XML"); + target.css({ "background-image": "none" }); + }, + "Email Flow" : function (event) { + if(!event) event = window.event; + var target = $(event.target); + target.text("Processing"); + target.css({ "background-image": "url('images/page-loading.gif')" }); + target.css({ "background-repeat": "no-repeat" }); + target.css({ "background-size": "25px 25px" }); + d3.xhr("style.css").get(function(err,resp){ + console.log("resp:" + resp); + //console.dir(resp); + var styleSheetText = resp.responseText; + /*var htmlCode = "<style>" + styleSheetText + "</style></head>" + + '<body><div id="chart" class="ui-droppable">' + + */ + //var svgTagInfo = '<div style="overflow:auto;border:1px solid #D76D2D;height:600px;"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1024 768" preserveAspectRatio="xMidYMid meet">'; + //var svgTagInfo = '<div style="overflow-x:auto;overflow-y:auto;border:1px solid #D76D2D;width:1200px;height:750px;"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="3500px" height="3200px" viewBox="0 0 5500 5000" >'; + var svgTagInfo = '<div style="overflow-x:auto;overflow-y:auto;border:1px solid #D76D2D;width:1200px;height:750px;"> <svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="3500px" height="3200px" viewBox="0 0 8000 7500" >'; + var svgHtmlCode = $("svg").html(); + //svgHtmlCode = svgHtmlCode.replace('<rect width="5000" height="5000"','<rect width="' + maxX + '" height="' + maxY +'"'); + var find = 'href="icons/arrow-in.png"'; + var re = new RegExp(find, 'g'); + svgHtmlCode = svgHtmlCode.replace(re, 'href=""'); + find = 'href="icons/inject.png"'; + re = new RegExp(find, 'g'); + svgHtmlCode = svgHtmlCode.replace(re, 'href=""'); + htmlCode = "\n<style>\n" + styleSheetText + "</style></head>\n<body>" + svgTagInfo + svgHtmlCode + "\n</svg></div>"; + //console.log($("svg").html()); + //console.log(htmlCode); + //html,xml,json form id + /* + //using form to submit + var form = $('<form id="hxjFormId" method="POST" action="/sendEmail"></form>'); + form.append('<input id="flowHtmlId" type="hidden" name="flowHtml" value=""/>'); + form.append('<input id="flowXmlId" type="hidden" name="flowXml" value=""/>'); + form.append('<input id="flowJsonId" type="hidden" name="flowJson" value=""/>'); + $("#screenInfoId").append(form); + //console.log($("#screenInfoId").html()); + document.getElementById("flowHtmlId").value=htmlCode; + document.getElementById("flowXmlId").value=formatted_xml; + document.getElementById("flowJsonId").value=formatted_json; + //console.log($("#screenInfoId").html()); + $("#hxjFormId").submit(); + console.log("Submitted."); + */ + var reqData = { + "flowHtml" : htmlCode, + "flowXml" : formatted_xml, + "flowJson" : formatted_json + }; + + $.post( "/sendEmail",reqData ) + .done(function( data ) { + //console.log( "Data Loaded: " + data ); + if(data != null && data.envelope != undefined && data.envelope != null){ + var toAddress = data.envelope.to; + RED.notify("Email sent successfully to " + toAddress); + }else{ + RED.notify("Email sent successfully."); + } + }) + .fail(function(err) { + console.log( "error" + err ); + RED.notify("Email send Failed."); + }) + .always(function() { + console.log( "finished" ); + target.text("Email Flow"); + target.css({ "background-image": "none" }); + }); + + /* + d3.xhr("/sendEmail").post(reqData,function(err,resp){ + console.log("Error:" + JSON.stringify(err)); + console.log("resp:" + JSON.stringify(resp)); + console.dir(resp); + }); + */ + }); + }, + /* + Deploy : function () { + $("#btn-deploy").click(); + }, + */ + "Upload XML" : function (event) { + if(!event) event = window.event; + //Save the flows.json + //RED.view.dirty(true); + //$('#btn-deploy').click(); + console.log("Deployed.."); + var target = $(event.target); + target.text("Processing"); + target.css({ "background-image": "url('images/page-loading.gif')" }); + target.css({ "background-repeat": "no-repeat" }); + target.css({ "background-size": "25px 25px" }); + var date = new Date(); + + var fileName = date.getTime() + ".xml"; + var reqData = { + "flowXml" : unformatted_xml_str, + "module" : origModuleName, + "rpc" : origMethodName + }; + $.post("/uploadxml", reqData ) + .done(function( data ) { + console.log("calling uploadxml. sending to server"); + //var successHtmlStr = "<object width='600' height='450' type='text/html' data='" + data.url + "' />"; + + if( data != undefined && data != null && (data.stdout.indexOf('Saving SvcLogicGraph to database') != -1 || data.stderr.indexOf('Saving SvcLogicGraph to database') != -1)){ + //RED.notify("<strong>Uploaded Successfully</strong>"); + //console.dir(data); + var _moduleName = data.module; + var _rpc = data.rpc; + var msg = ""; + var actualMsg = ""; + var msg_lines = ""; + msg_lines += data.stderr; + msg_lines += data.stdout; + + msgHtmlStr="<div><p><b>Uploaded the XML.<br>Additional Details<br><textarea style='width:90%;height:100%' readonly='1' rows='10' cols='90' >" + msg_lines + "</textarea></div>"; + $("#upload-xml-status-dialog").dialog({ + modal:true, + title: "Upload XML ", + width: 900, + height: 750, + minWidth : 600, + minHeight :450, + buttons: [ + { + text: "ViewDGList", + class:"alertDialogButton", + click: function() { + $(this).dialog("close"); + displayCurrentDGs(_moduleName,_rpc,function(htmlStr,dbHost){ + $("#svclogicPageDiv").dialog({ + modal:true, + title:"Service Logic Administration Module=" + _moduleName + " and RPC=" + _rpc, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }); + } + }, + { + text: "Close", + class:"alertDialogButton", + click: function() { + $(this).dialog("close"); + } + } + ] + }).html(msgHtmlStr); + }else{ + console.log("Could not upload."); + var emsg =JSON.parse( data.responseText); + var msg = ""; + var actualMsg = ""; + var msg_lines = ""; + if( emsg.stderr != "COMPILE_ERROR"){ + msg = JSON.stringify(emsg.stderr); + actualMsg = msg; + msg = msg.replace('\\t',""); + msg1 = msg.split('\\n'); + for(var k=0;k<=msg1.length && k<=10;k++){ + /* + if(k == 0){ + //msg_lines += "<span style='color:blue'>" + msg1[k] + "</span><br>"; + //msg_lines += msg1[k] +"\n"; + }else{ + if(msg1[k].indexOf("Caused by:") != -1){ + //msg_lines += "<span style='color:red'> " + msg1[k] + "</span><br>"; + msg_lines += msg1[k] ; + break; + } + } + */ + if(msg1[k] != null && msg1[k].indexOf("Caused by:") != -1){ + msg_lines += msg1[k] ; + if((k+1)<=msg1.length){ + msg_lines += "\n" + msg1[k+1] ; + } + if((k+2)<=msg1.length){ + msg_lines += "\n" + msg1[k+2] ; + } + break; + } + } + } + htmlStr="<div><p><b>Could not upload the XML. Status:" + data.status + " Message:" + data.statusText + "</b><br></p><br>Additional Details<br><textarea style='width:90%;height:100%' readonly='1' rows='10' cols='90' >" + msg_lines + "</textarea></div>"; + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Upload XML ", + width: 900, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + } + }) + .fail(function(err) { + //console.log( "error" + JSON.stringify(err) ); + //console.log( JSON.stringify(err.responseText)); + var emsg =JSON.parse( err.responseText); + //console.log( emsg.stderr); + var msg = ""; + var actualMsg = ""; + var msg_lines = ""; + if( emsg != null && emsg.stderr != 'COMPILE_ERROR'){ + msg = JSON.stringify(emsg.stderr); + actualMsg = msg; + //msg = msg.replace("Caused by:","<span style='color:red'>Caused by:</span>"); + msg = msg.replace(/\\t/g,""); + msg1 = msg.split('\\n'); + for(var k=0;k<=msg1.length && k<=msg1.length;k++){ + /* + if(k == 0){ + //msg_lines += "<span style='color:blue'>" + msg1[k] + "</span><br>"; + //msg_lines += msg1[k] + "\n" ; + }else{ + if(msg1[k].indexOf("Caused by:") != -1){ + //msg_lines += "<span style='color:red'> " + msg1[k] + "</span><br>"; + msg_lines += msg1[k] ; + break; + } + } + */ + if(msg1[k] != null && msg1[k].indexOf("Caused by:") != -1){ + msg_lines += msg1[k] ; + if((k+1)<=msg1.length){ + msg_lines += "\n" + msg1[k+1] ; + } + if((k+2)<=msg1.length){ + msg_lines += "\n" + msg1[k+2] ; + } + break; + } + } + }else{ + msg = JSON.stringify(emsg.stdout); + actualMsg = msg; + msg = msg.replace('\\t',""); + msg1 = msg.split('\\n'); + msg_lines=msg1; + } + var htmlStr="<div><p><b>Could not upload the XML. Status:" + err.status + " Message:" + err.statusText + "</b><br></p><br><b>Additional Details</b><br><textarea style='width:90%;height:100%' readonly='1' rows='15' cols='90'>" + msg_lines + "</textarea></div>"; + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Upload XML ", + width: 900, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + //RED.notify("<strong>ERROR:</strong>:" + err,"error"); + }) + .always(function() { + console.log( "finished" ); + target.text("Upload XML"); + target.css({ "background-image": "none" }); + }); + /* + d3.xhr("/uploadxml?fileName=" + fileName).post(function(err,resp) { + if ( resp != null && resp.status == 200) { + RED.notify("<strong>Uploaded Successfully</strong>"); + }else{ + RED.notify("<strong>ERROR:</strong>:" + err,"error"); + console.log(err); + //console.dir(resp); + } + }); + */ + }, + "View DG List": function () { + + displayCurrentDGs(origModuleName,origMethodName,function(htmlStr,dbHost){ + //console.log("htmlStr:" + htmlStr); + $("#svclogicPageDiv").dialog({ + modal:true, + title: "Service Logic Administration for Module=" + origModuleName + " and RPC=" + origMethodName, + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); + }); + }, + "Download XML": function () { + $(document).ready(function(){ + errList=[]; + if(moduleName != undefined && moduleName != null && moduleName != ""){ + moduleName=moduleName.replace(/\s/g, "_"); + }else{ + errList.push("Module name is required in the service-logic node."); + } + + if(dgVersion == undefined || dgVersion == null || dgVersion == ""){ + errList.push("Module version is required in the service-logic node."); + } + + if(methodName != undefined && methodName != null && methodName != ""){ + methodName=methodName.replace(/\s/g, "_"); + //formattedMethodName=methodName + "_" + dgVersion; + formattedMethodName=methodName ; + }else{ + errList.push("rpc name is required in the method node."); + } + console.log("Download Xml moduleName:" + moduleName); + console.log("Download Xml methodName:" + formattedMethodName); + + if(errList != null && errList.length > 0 ){ + showErrors(); + return; + } + + $("#dwnldXmlFormId").empty().remove(); + //using form to submit + var form = $('<form id="dwnldXmlFormId" method="POST" action="/downloadXml"></form>'); + form.append('<input id="flowXmlId" type="hidden" name="flowXml"/>'); + form.append('<input type="hidden" name="moduleName" value="' + moduleName + '"/>'); + form.append('<input type="hidden" name="methodName" value="' + formattedMethodName + '"/>'); + form.appendTo('body'); + //$("#flowXmlId").val(formatted_xml); + $("#flowXmlId").val(unformatted_xml_str); + $("#dwnldXmlFormId").submit(); + //console.log("Form submitted."); + }); + }, + "Download JSON": function () { + $(document).ready(function(){ + errList=[]; + if(moduleName != undefined && moduleName != null && moduleName != ""){ + moduleName=moduleName.replace(/\s/g, "_"); + }else{ + errList.push("Module name is required in the service-logic node."); + } + + if(dgVersion == undefined || dgVersion == null || dgVersion == ""){ + errList.push("Module version is required in the service-logic node."); + } + + if(methodName != undefined && methodName != null && methodName != ""){ + methodName=methodName.replace(/\s/g, "_"); + //formattedMethodName=methodName + "_" + dgVersion; + formattedMethodName=methodName ; + }else{ + errList.push("rpc name is required in the method node."); + } + console.log("Download Xml moduleName:" + moduleName); + console.log("Download Xml methodName:" + formattedMethodName); + + if(errList != null && errList.length > 0 ){ + showErrors(); + return; + } + //console.log("formatted_json:" + formatted_json); + $("#dwnldJsonFormId").empty().remove(); + //using form to submit + var form = $('<form id="dwnldJsonFormId" method="POST" action="/downloadJson"></form>'); + form.append('<input id="flowJsonId" type="hidden" name="flowJson" value=""/>'); + form.append('<input type="hidden" name="moduleName" value="' + moduleName + '"/>'); + form.append('<input type="hidden" name="methodName" value="' + formattedMethodName + '"/>'); + form.appendTo('body'); + //$("#flowJsonId").val(formatted_json); + $("#flowJsonId").val(unformatted_json_str); + $("#dwnldJsonFormId").submit(); + //console.log("Form submitted."); + }); + }, + Close: function () { + /* + console.log("clearing the variables."); + htmlCode =""; + formatted_json =""; + formatted_xml =""; + xmlLines =[]; + unformatted_xml_str=""; + unformatted_json_str=""; + */ + $('.ui-dialog:has(#xmldialog)').empty().remove(); + RED.view.redraw(); + + //console.log($("#xmldialog").attr('id')); + //$('.ui-dialog:has(# + $("#xmldialog").attr('id') + ')').empty().remove(); + //$("#xmldialog").hide(); + //$("#xmldialog").dialog("destroy").remove(); + } + }, + open:function (){ + $(function(){ + $("#xmldialog").dialog("widget").find(".ui-dialog-buttonpane").append(xmlInfoStr); + console.log("opened."); + }); + } + }).html(displayHtmlStr).dialog("open"); + + //}).html(displayHtmlStr).dialog("widget").find(".ui-dialog-buttonpane").append(xmlInfoStr); + + //display size and number of lines in XML + //$("#xmldialog").dialog("widget").find(".ui-dialog-buttonpane").append(xmlInfoStr); + + //$("#processingStatusId").html(""); + //This logic is commented as formatting and displaying orion is taking time + //START + /* + var msecs1= Date.now(); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('xmldialog'), + lang:"html", + readonly:true, + //showLinesRuler: false, + contents: formatted_xml + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + }); + var msecs2= Date.now(); + //console.log("Time taken for displaying XML:" + (msecs2 - msecs1)); + */ + //END + //var success = customValidation(currentNodeSet); + var success = customValidation(nodeSetWithUpdatedDgNumbers); + if(!success){ + showFlowDesignErrorBox(); + } + $('#processingStatusId').html(""); + }, 0); + } + } + + }); +</script> diff --git a/dgbuilder/nodes/dge/dgemain/dgstart.js b/dgbuilder/nodes/dge/dgemain/dgstart.js new file mode 100644 index 00000000..f2b4815e --- /dev/null +++ b/dgbuilder/nodes/dge/dgemain/dgstart.js @@ -0,0 +1,594 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + //var dgxml=require("/home/users/schinthakayala/nodered/sheshi/dgxml/dgxml2"); + var _=require('lodash'); + var fs=require('fs'); + var path = require('path'); + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + RED.settings.userDir; + var dbHost = RED.settings.dbHost; + var request = require('request'); + var sharedDir = appDir + "/" + RED.settings.sharedDir; + var xmlDir = appDir + "/" + RED.settings.xmlPath; + + //console.log("appDir:" + appDir); + //var dgeraw=fs.readFileSync(appDir + "/dge.json").toString(); + //var dgejson=JSON.parse(dgeraw); + //var uploadUrl=dgejson.slaHost + dgejson.uploadUrl; + //var slaUrl=dgejson.slaHost + dgejson.slaUrl; + //var uploadUrl=RED.settings.slaHost + RED.settings.uploadUrl; + //var slaUrl=RED.settings.slaHost + RED.settings.slaUrl; + var uploadUrl=""; + var slaUrl=""; + //console.log("Upload url: " + uploadUrl); + + function dgstart(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.topic = n.topic; + } + + function writeHtmlToFile(fileName,str){ + var localfile = appDir + "/" + RED.settings.htmlPath + fileName; + try{ + fs.writeFileSync(localfile,str); + }catch(e){ + console.log("Error:" + e); + } + } + + function writeXmlToFile(fileName,str){ + var localfile = appDir + "/" + RED.settings.xmlPath + fileName; + try{ + fs.writeFileSync(localfile,str); + }catch(e){ + console.log("Error:" + e); + } + } + + function sendXml(fileName,res) { + var needle, localfile, data; + needle = require('needle') + localfile = appDir + "/" + RED.settings.xmlPath + fileName; + console.log("localfile:" + localfile); + data={ + uploadedfile: { file: localfile, content_type: 'text/xml' } + } + needle.post(uploadUrl, data, { multipart: true }, function(err, resp, body) { + //console.log(body) + if(resp != undefined && resp != null){ + console.log("resp Code for sendXml:" + resp.statusCode); + } + fs.unlink(localfile, function (error) { + if (error) { + console.log("Error deleting file "+localfile); + }else{ + //console.log("deleted file:" + localfile); + } + }); + + if(err){ + console.log("Error posting to slaUrl:" + slaUrl); + console.log("Error:" +err); + res.json({"error":err}); + }else{ + //console.dir(resp); + //console.log("slaUrl:" + slaUrl); + res.json({"url":slaUrl}); + } + + }); + } + + function oldsendXml(fileName) { + console.log("In sendXML for file: " + fileName); + var fileStream, formdata, localfile; + localfile = appDir + "/" + RED.settings.xmlPath + fileName; + + formdata = { + MAX_FILE_SIZE: "100000", + uploadedfile: { + options: { + contentType: 'audio/mpeg' + } + } + + }; + + console.log("Attempting to upload file: " + localfile); + console.log("Sending to: " + uploadUrl); + formdata.uploadedfile.value = fs.createReadStream(localfile); + fileStream = formdata.uploadedfile.value; + +//console.log("Formdata:"); +//console.dir(formdata); + + request.post({ + url: uploadUrl, + proxy: false, + formData: formdata + }, function(err, resp, body) { + fileStream.close(); + console.log("err: " + err); + return console.log("body: " + body); + }); + + }; + + RED.nodes.registerType("dgstart",dgstart); +/* + RED.httpAdmin.post("/uploadxml", function(req,res) { + console.dir(req); + console.log("USER:" + req.user); + console.log("Got request to upload xml to SDN-C."); + console.log("Requested filename to upload: " + req.params.fileName); + console.log("Requested xml to upload: " + req.params.xmlStr); + writeToFile( req.params.fileName,req.params.xmlStr); + + sendXml(req.params.fileName,res); + // res.send("Attempt complete."); + // res.redirect(slaUrl); + }); +*/ + + RED.httpAdmin.post("/OldUploadxml", function(req,res) { + //console.dir(req); + //console.log("USER:" + req.user); + var qs = require('querystring'); + var body = ''; + req.on('data', function (data) { + body += data; + // Too much POST data, kill the connection! + /*if (body.length > 1e6) + request.connection.destroy(); + */ + }); + req.on('end', function () { + //console.log("BODY:" + body); + var d = new Date().getTime(); + var user = req.user; + var fileName= user + "_" + d +".xml"; + var post = qs.parse(body); + //console.log(JSON.stringify(post)); + // use post['blah'], etc. + var localfile = appDir + "/" + RED.settings.xmlPath + fileName; + //console.log("localfile:" + localfile); + var xmlStr = post['flowXml']; + writeXmlToFile(fileName,xmlStr); + sendXml(fileName,res); + + }); + + }); + + RED.httpAdmin.post("/uploadxml", function(req,res) { + //console.dir(req); + //console.log("USER:" + req.user); + var qs = require('querystring'); + var body = ''; + req.on('data', function (data) { + body += data; + // Too much POST data, kill the connection! + /*if (body.length > 1e6) + request.connection.destroy(); + */ + }); + req.on('end', function () { + //console.log("BODY:" + body); + var d = new Date().getTime(); + var user = req.user; + var fileName= user + "_" + d +".xml"; + var post = qs.parse(body); + //console.log(JSON.stringify(post)); + // use post['blah'], etc. + var localfile = appDir + "/" + RED.settings.xmlPath + fileName; + //console.log("localfile:" + localfile); + var xmlStr = post['flowXml']; + var moduleName = post['module']; + var rpc = post['rpc']; + writeXmlToFile(fileName,xmlStr); + uploadDG(localfile,moduleName,rpc,res); + }); + + }); + + +function uploadDG(filePath,moduleName,rpc,res){ + console.log("called uploadDG..."); + var exec = require('child_process').exec; + var commandToExec = appDir + "/svclogic/svclogic.sh load " + filePath + " " + userDir + "/conf/svclogic.properties"; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,function (error,stdout,stderr){ + //console.log(error); + console.log("stdout:" + stdout); + console.log("stderr:" + stderr); + if(error){ + console.log("Error occured:" + error); + if(stderr){ + //console.log("stderr:" + stderr); + res.send(500,{'error':error,'stderr':stderr}); + }else{ + res.send(500,{'error':error}); + } + //console.log("stdout :" + stdout); + }else{ + if(stdout ){ + //console.log("output:" + stdout); + if(stdout.indexOf('Compiler error') != -1){ + //console.log("compileError occured."); + + var resp = { + 'stdout':stdout, + 'stderr':"COMPILE_ERROR", + 'url':dbHost, + 'module':moduleName, + 'rpc':rpc + } + res.send(500,resp); + }else{ + res.send(200,{'stdout':stdout,'stderr':stderr,"url":dbHost,"module" : moduleName,"rpc" : rpc}); + } + } + if(stderr && !stdout){ + //console.log("stderr:" + stderr); + if(stderr.indexOf("Saving SvcLogicGraph to database") != -1){ + res.send(200,{'error':error,'stdout' :'','stderr':stderr,"url":dbHost,"module" : moduleName,"rpc" : rpc}); + }else{ + res.send(500,{'error':error,'stdout' :'','stderr':stderr}); + } + } + } + }); +} + + RED.httpAdmin.get("/displayXml", function(req,res) { + var _module = req.query._module; + var rpc = req.query.rpc; + var version = req.query.version; + var mode = req.query.mode; + var d = new Date().getTime(); + displayXml(_module,rpc,version,mode,res); + }); + +function displayXml(_module,rpc,version,mode,res){ + var exec = require('child_process').exec; + var msg = { + '_module' : _module, + 'rpc' : rpc, + 'version' : version, + 'mode' : mode + } + var commandToExec = appDir + "/svclogic/svclogic.sh get-source " + _module + " " + + rpc + " " + mode + " " + version + " " + userDir + "/conf/svclogic.properties"; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,{'maxBuffer':16*1024*1024},function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + //console.log("stderr:" + stderr); + res.send(500,{'error':error,'stderr':stderr,'msg':msg}); + }else{ + res.send(500,{'error':error,'msg':msg}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + res.send({'xmldata' : "<xmp>" + stdout + "</xmp>"}); + } + } + }); +} + + + RED.httpAdmin.post("/downloadDGXml", function(req,res) { + //console.dir(req); + var qs = require('querystring'); + var body = ''; + req.on('data', function (data) { + body += data; + }); + + req.on('end', function () { + var post = qs.parse(body); + var _module = post._module; + var rpc = post.rpc; + var version = post.version; + var mode = post.mode; + var d = new Date().getTime(); + downloadDGXml(_module,rpc,version,mode,res); + }); + }); + +function downloadDGXml(_module,rpc,version,mode,res){ + var exec = require('child_process').exec; + var msg = { + '_module' : _module, + 'rpc' : rpc, + 'version' : version, + 'mode' : mode + } + var commandToExec = appDir + "/svclogic/svclogic.sh get-source " + _module + " " + + rpc + " " + mode + " " + version + " " + userDir + "/conf/svclogic.properties"; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + //console.log("stderr:" + stderr); + res.send(500,{'error':error,'stderr':stderr,'msg':msg}); + }else{ + res.send(500,{'error':error,'msg':msg}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + //console.log("output:" + stdout); + //var newOutput = "<pre>" + stdout.replace(/\n/g,'<br>') + "</pre>"; + //res.json({'stdout': stdout ,'stderr':stderr,"msg":msg}); + //res.set('Content-Type', 'text/xml'); + //res.set('Content-Type', 'application/octet-stream'); + //res.end("<code>" + stdout + "</code>" ); + //var newOutput ="<html><body>" + stdout + "</body></html>"; + //res.send(new Buffer( "<code>" + newOutput + "</code>" ) ); + //res.send(newOutput); + + /* + var xslStr = '<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">' + + '<xsl:output omit-xml-declaration="yes" indent="yes"/>' + + '<xsl:template match="node()|@*">' + + '<xsl:copy>' + + '<xsl:apply-templates select="node()|@*"/>' + + '</xsl:copy>' + + '</xsl:template>' + + '</xsl:stylesheet>'; + */ + + var formatted_date = getCurrentDate(); + var fileName= "db_" + _module + "_" +rpc+ "_" + version + "_" + formatted_date + ".html"; + var file = xmlDir + "/" + fileName; + var xmlStr = '<xmp>' + stdout + "</xmp>"; + //var xmlStr = "<![CDATA[" + stdout + "]]"; + //var xmlStr = stdout.replace(/</g,"<"); + //xmlStr = xmlStr.replace(/>/g,">"); + //xmlStr = xmlStr.replace(/\n>/g,"<br>"); + //xmlStr = xmlStr.replace(/\t>/g," "); + + writeToFile(file,"<html><body>" +xmlStr+ "</body></html>"); + //console.log("xmlStr:" + xmlStr); + res.setHeader('Content-disposition', 'attachment; filename=' + file); + //res.setHeader('Content-type', 'text/html'); + res.setHeader('Content-type', 'text/xml'); + res.download(file); + } + } + }); +} + + + RED.httpAdmin.get("/displayAsGv", function(req,res) { + var _module = req.query._module; + var rpc = req.query.rpc; + var version = req.query.version; + var mode = req.query.mode; + var d = new Date().getTime(); + displayAsGv(_module,rpc,version,mode,res); + }); + +function displayAsGv(_module,rpc,version,mode,res){ + var exec = require('child_process').exec; + var msg = { + '_module' : _module, + 'rpc' : rpc, + 'version' : version, + 'mode' : mode + } + var commandToExec = appDir + "/svclogic/svclogic.sh print " + + _module + " " + rpc + " " + mode + " " + version + " " + //+ userDir + "/conf/svclogic.properties | dot -Tpng "; + //the label="""" is giving an error so replacing it with "null" + + userDir + "/conf/svclogic.properties |sed -e 's%label=\"\"\"\"%label=\"null\"%g'| dot -Tsvg "; + console.log("commandToExec:" + commandToExec); + //+ userDir + "/conf/svclogic.properties | dot -Tsvg "; + //var child = exec(commandToExec ,function (error,stdout,stderr){ + //var child = exec(commandToExec ,{maxBuffer:16*1024*1024},function (error,stdout,stderr){ + //var child = exec(commandToExec ,{encoding:'base64',maxBuffer:20*1024*1024},function (error,stdout,stderr){ + var child = exec(commandToExec ,{maxBuffer:20*1024*1024},function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + console.log("stderr:" + stderr); + res.send(500,{'error':error,'stderr':stderr,"msg":msg}); + }else{ + res.send(500,{'error':error,"msg":msg}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + //To convert base64 to ascii + //console.log(new Buffer(stderr, 'base64').toString('ascii')); + } + if(stdout){ + //console.log(stdout.length); + //console.log("output:" + stdout); + //var svg_html = stdout ; + //var image = "<img src='data:image/png;base64," + stdout + "'>"; + //var image = "<iframe width='1200' height='750' src='data:image/png;base64," + stdout + "'></frame>"; + //var image = "<iframe width='1200' height='750' src='data:image/svg+xml;base64," + stdout + "'></frame>"; + //var image = "<iframe width='1200' height='750' src='data:image/gif;base64," + stdout + "'></frame>"; + var image = "<iframe width='1200' height='750' src='data:image/svg+xml;UTF-8," + stdout + "'></frame>"; + //console.log(image); + res.send({'svg_html':image}); + } + } + }); +} + + RED.httpAdmin.post("/shareFlow", function(req,res) { + //console.dir(req); + //console.log("USER:" + req.user); + var qs = require('querystring'); + var body = ''; + req.on('data', function (data) { + body += data; + // Too much POST data, kill the connection! + /*if (body.length > 1e6) + request.connection.destroy(); + */ + }); + req.on('end', function () { + var post = qs.parse(body); + + var nodeSet = JSON.parse(post['flowData']); + var activeWorkspace=post['activeWorkspace']; + var methodName = ""; + var moduleName = ""; + for(var i=0;nodeSet != null && i<nodeSet.length;i++){ + var node = nodeSet[i]; + if(node.type == 'module' ){ + moduleName= node.name; + moduleName=moduleName.replace(/ /g,"-"); + } + if(node.type == 'method' ){ + methodName= node.name; + methodName=methodName.replace(/ /g,"-"); + } + } + //console.log("BODY:" + body); + var d = new Date().getTime(); + var user = req.user; + var fileName= moduleName + "_" +methodName+".json"; + var localfile = sharedDir + "/" + fileName; + //console.log("localfile:" + localfile); + + writeToFile(localfile,JSON.stringify(nodeSet)); + res.send({"fileName": fileName}); + }); + + }); + + + RED.httpAdmin.post("/sendEmail", function(req,res) { + //console.dir(req); + console.log("USER:" + req.user); + var fromAddr = RED.settings.emailAddress; + var toAddr = RED.settings.emailAddress; + var qs = require('querystring'); + var body = ''; + req.on('data', function (data) { + body += data; + // Too much POST data, kill the connection! + /*if (body.length > 1e6) + request.connection.destroy(); + */ + }); + req.on('end', function () { + //console.log("BODY:" + body); + var d = new Date().getTime(); + var user = req.user; + var fileName= user + "_" + d +".html"; + var post = qs.parse(body); + //console.log(JSON.stringify(post)); + // use post['blah'], etc. + var localfile = appDir + "/" + RED.settings.htmlPath + fileName; + //console.log("localfile:" + localfile); + var nodemailer = require("nodemailer"); + nodemailer.sendmail = true; + var transporter = nodemailer.createTransport(); + var ua = req.headers['user-agent']; + var host = req.headers.host; + var fullHtml="<!doctype html><html><head>" + post['flowHtml']; + //fullHtml+="<div style='fill:both'></div>"; + fullHtml+="<div style='margin-left:10px;'><p>XML</p><br><textarea rows='50' cols='150'>" + post['flowXml'] + "</textarea>"; + fullHtml+="<p>JSON</p><br><textarea rows='50' cols='150'>" + post['flowJson'] + "</textarea></div>"; + fullHtml+="</body></html>"; + writeHtmlToFile(fileName,fullHtml); + + transporter.sendMail({ + from: fromAddr, + to: toAddr, + html: "<p>DG Node Flow. click on the attachment to view</p>", + subject: 'Node flow from Host:<' + host + '>', + attachments : [{'filename': fileName, + 'contentType': "text/html", + /*'filePath': localfile*/ + 'content': fs.createReadStream(localfile) + }] + + }, function(err, response) { + var fullPathtoFileName = appDir + "/" + RED.settings.htmlPath + fileName; + fs.unlink(fullPathtoFileName, function (error) { + if (error) { + console.log("Error deleting file "+fullPathtoFileName); + }else{ + //console.log("deleted file:" + fullPathtoFileName); + } + }); + + if(err){ + console.log("Error:" + err); + res.json(err); + }else{ + res.json(response); + } + console.log(response); + }); + + }); + + + }); +/* + RED.httpAdmin.post("/doxml/:id", function(req,res) { + var node = RED.nodes.getNode(req.params.id); + if (node != null) { + try { + // node.receive(); + //console.log("doxml was called for node: "); + //console.dir(node); + //console.log("calling getJson"); + var nrjson=dgxml.getJson(); + console.log("calling nodered2xml"); + var results=[]; + results=dgxml.nodered2xml(nrjson,node.id); + var nrxml=results[0]; + fileName=results[1]; + console.log("Got this filename: " + fileName); + // res.send(200); + console.log("appDir: " + appDir); + fs.writeFileSync(appDir + "/public/xml/"+fileName,nrxml); + // res.send("XML generated! See help on right for link."); + res.send(fileName); + } catch(err) { + res.send(500); + node.error("doxml failed:"+err); + console.log(err.stack); + } + } else { + res.send(404); + } + }); +*/ +} diff --git a/dgbuilder/nodes/dge/dgemain/method.html b/dgbuilder/nodes/dge/dgemain/method.html new file mode 100644 index 00000000..134896e7 --- /dev/null +++ b/dgbuilder/nodes/dge/dgemain/method.html @@ -0,0 +1,141 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="method"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show RPCs</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> +<script type="text/x-red" data-help-name="method"> + <p>A method node.</p> + <p>Name can be anything.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +</script> + +<script type="text/javascript"> + RED.nodes.registerType('method',{ + color:"#fdd0a2", + category: 'DGEmain', + defaults: { + name: {value:"method"}, + xml: {value:"<method rpc='' mode='sync'>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + //console.log("show Values clicked."); + showRpcsValuesBox(that.editor,rpcValues); + }); + + }); + + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgemain/method.js b/dgbuilder/nodes/dge/dgemain/method.js new file mode 100644 index 00000000..6a29bd83 --- /dev/null +++ b/dgbuilder/nodes/dge/dgemain/method.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function method(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("method",method); + // RED.library.register("method"); +} diff --git a/dgbuilder/nodes/dge/dgemain/serviceLogic.html b/dgbuilder/nodes/dge/dgemain/serviceLogic.html new file mode 100644 index 00000000..ca8ac8c4 --- /dev/null +++ b/dgbuilder/nodes/dge/dgemain/serviceLogic.html @@ -0,0 +1,125 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="service-logic"> + <div class="form-row"> + <!--<label for="node-input-name"><i class="fa"></i> Name</label>--> + <input type="hidden" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <input type="hidden" id="node-input-xml"> + <label for="node-input-module"><i class="fa"></i>Module</label> + <input type="text" id="node-input-module" autofocus="autofocus"> + <label for="node-input-version"><i class="fa"></i>Version</label> + <input type="text" id="node-input-version"> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + </div> + <!--<div class="form-tips">See the Info tab for help using this node.</div>--> +</script> + +<script type="text/x-red" data-help-name="service-logic"> + <p>A service-logic node.</p> + <p>Double click the node to configure the module name and the version</p> + +</script> + +<script type="text/javascript"> + RED.nodes.registerType('service-logic',{ + color:"#fdd0a2", + category: 'DGEmain', + defaults: { + name: {value:"service-logic"}, + module: {value:""}, + version: {value:""}, + comments:{value:""}, + xml: {value:"<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='' version=''>\n"}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + //$("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + + $("#node-input-module").focus(); + + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + var module = $("#node-input-module").val(); + if(module == null){ + module=''; + } + var version = $("#node-input-version").val(); + if(version == null){ + version=''; + } + console.log("module:" + module); + console.log("version:" + version); + //xmlStr= xmlStr.replace("$MODULE",module); + //xmlStr= xmlStr.replace("$VERSION",version); + var xmlVal = "<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='" + module + "' version='" + version + "'>" + $("#node-input-xml").val(xmlVal); + if(module == "" || version == ""){ + this.status = {fill:"red",shape:"dot",text:"Not configured"}; + }else{ + this.status = {fill:"green",shape:"dot",text:"configured"}; + $("#node-input-name").val(module + " " + version); + } + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgemain/serviceLogic.js b/dgbuilder/nodes/dge/dgemain/serviceLogic.js new file mode 100644 index 00000000..a5e77e4e --- /dev/null +++ b/dgbuilder/nodes/dge/dgemain/serviceLogic.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function serviceLogic(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("service-logic",serviceLogic); + // RED.library.register("service-logic"); +} diff --git a/dgbuilder/nodes/dge/dgeoutcome/already-active.html b/dgbuilder/nodes/dge/dgeoutcome/already-active.html new file mode 100644 index 00000000..914bda10 --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/already-active.html @@ -0,0 +1,144 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="already-active"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="already-active"> + <p>A already-active outcome.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('already-active',{ + color: "#ffccff", + category: 'DGEoutcome', + defaults: { + name: {value:"already-active"}, + xml: {value:"<outcome value='already-active'>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgeoutcome/already-active.js b/dgbuilder/nodes/dge/dgeoutcome/already-active.js new file mode 100644 index 00000000..f6ab4faf --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/already-active.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function alreadyActive(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("already-active",alreadyActive); + // RED.library.register("already-active"); +} diff --git a/dgbuilder/nodes/dge/dgeoutcome/failure.html b/dgbuilder/nodes/dge/dgeoutcome/failure.html new file mode 100644 index 00000000..cabfab4b --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/failure.html @@ -0,0 +1,142 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="failure"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="failure"> + <p>A failure outcome.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('failure',{ + color:"#ffccff", + category: 'DGEoutcome', + defaults: { + name: {value:"failure"}, + xml: {value:"<outcome value='failure'>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgeoutcome/failure.js b/dgbuilder/nodes/dge/dgeoutcome/failure.js new file mode 100644 index 00000000..5abd1b74 --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/failure.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function failure(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("failure",failure); + // RED.library.register("failure"); +} diff --git a/dgbuilder/nodes/dge/dgeoutcome/not-found.html b/dgbuilder/nodes/dge/dgeoutcome/not-found.html new file mode 100644 index 00000000..0b6bb8f9 --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/not-found.html @@ -0,0 +1,142 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="not-found"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="not-found"> + <p>A not-found outcome.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('not-found',{ + color: "#ffccff", + category: 'DGEoutcome', + defaults: { + name: {value:"not-found"}, + xml: {value:"<outcome value='not-found'>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgeoutcome/not-found.js b/dgbuilder/nodes/dge/dgeoutcome/not-found.js new file mode 100644 index 00000000..80e10af4 --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/not-found.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function notFound(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("not-found",notFound); + // RED.library.register("not-found"); +} diff --git a/dgbuilder/nodes/dge/dgeoutcome/other.html b/dgbuilder/nodes/dge/dgeoutcome/other.html new file mode 100644 index 00000000..7ceb2e79 --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/other.html @@ -0,0 +1,143 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="other"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="other"> + <p>A other outcome.</p> + <p>Name can be anything.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('other',{ + color: "#ffccff", + category: 'DGEoutcome', + defaults: { + name: {value:"other"}, + xml: {value:"<outcome value='Other'>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgeoutcome/other.js b/dgbuilder/nodes/dge/dgeoutcome/other.js new file mode 100644 index 00000000..97bad48d --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/other.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function other(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("other",other); + // RED.library.register("other"); +} diff --git a/dgbuilder/nodes/dge/dgeoutcome/outcome.html b/dgbuilder/nodes/dge/dgeoutcome/outcome.html new file mode 100644 index 00000000..122f7d3d --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/outcome.html @@ -0,0 +1,143 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="outcome"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="outcome"> + <p>A generic outcome node.</p> + <p>Use this node if you do not have a outcome value node in the node panel.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('outcome',{ + color:"#ffccff", + category: 'DGEoutcome', + defaults: { + name: {value:"outcome"}, + xml: {value:"<outcome value=''>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgeoutcome/outcome.js b/dgbuilder/nodes/dge/dgeoutcome/outcome.js new file mode 100644 index 00000000..33513e4b --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/outcome.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function outcome(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("outcome",outcome); + // RED.library.register("outcome"); +} diff --git a/dgbuilder/nodes/dge/dgeoutcome/outcomeFalse.html b/dgbuilder/nodes/dge/dgeoutcome/outcomeFalse.html new file mode 100644 index 00000000..d1044208 --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/outcomeFalse.html @@ -0,0 +1,143 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="outcomeFalse"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="outcomeFalse"> + <p>A false outcome.</p> + <p>Name can be anything.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('outcomeFalse',{ + color:"#ffccff", + category: 'DGEoutcome', + defaults: { + name: {value:"false"}, + xml: {value:"<outcome value='false'>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgeoutcome/outcomeFalse.js b/dgbuilder/nodes/dge/dgeoutcome/outcomeFalse.js new file mode 100644 index 00000000..f4a9a774 --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/outcomeFalse.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function outcomeFalse(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("outcomeFalse",outcomeFalse); + // RED.library.register("success"); +} diff --git a/dgbuilder/nodes/dge/dgeoutcome/outcomeTrue.html b/dgbuilder/nodes/dge/dgeoutcome/outcomeTrue.html new file mode 100644 index 00000000..a080bbf6 --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/outcomeTrue.html @@ -0,0 +1,142 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="outcomeTrue"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="outcomeTrue"> + <p>A true outcome.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('outcomeTrue',{ + color:"#ffccff", + category: 'DGEoutcome', + defaults: { + name: {value:"true"}, + xml: {value:"<outcome value='true'>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgeoutcome/outcomeTrue.js b/dgbuilder/nodes/dge/dgeoutcome/outcomeTrue.js new file mode 100644 index 00000000..f27310e0 --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/outcomeTrue.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function outcomeTrue(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("outcomeTrue",outcomeTrue); + // RED.library.register("success"); +} diff --git a/dgbuilder/nodes/dge/dgeoutcome/success.html b/dgbuilder/nodes/dge/dgeoutcome/success.html new file mode 100644 index 00000000..347d7d6a --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/success.html @@ -0,0 +1,141 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="success"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="success"> + <p>A success outcome.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('success',{ + color:"#ffccff", + category: 'DGEoutcome', + defaults: { + name: {value:"success"}, + xml: {value:"<outcome value='success'>\n"}, + comments:{value:""}, + outputs: {value:1} + }, + inputs:1, + outputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + $( "#node-input-outputs" ).spinner({ + min:1 + }); + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgeoutcome/success.js b/dgbuilder/nodes/dge/dgeoutcome/success.js new file mode 100644 index 00000000..4dbafbf7 --- /dev/null +++ b/dgbuilder/nodes/dge/dgeoutcome/success.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function success(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("success",success); + // RED.library.register("success"); +} diff --git a/dgbuilder/nodes/dge/dgereturn/returnFailure.html b/dgbuilder/nodes/dge/dgereturn/returnFailure.html new file mode 100644 index 00000000..60ab2299 --- /dev/null +++ b/dgbuilder/nodes/dge/dgereturn/returnFailure.html @@ -0,0 +1,170 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="returnFailure"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="returnFailure"> + <p>A returnFailure node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Return_node"></a>Return node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>return</b> node is used to return a status to the invoking MD-SAL application</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>status</b></td> +<td align="left">Status value to return (<i>failure</i>)</td></tr></table></div> +<div class="section"> +<h5><a name="Parameters"></a>Parameters</h5> +<p>The following optional parameters may be passed to convey more detailed status information.</p> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>error-code</b></td> +<td align="left">A brief, usually numeric, code indicating the error condition</td></tr> +<tr class="b"> +<td align="center"><b>error-message</b></td> +<td align="left">A more detailed error message</td></tr></table></div> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<p>Not applicable. The <b>status</b> node has no outcomes.</p></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><return status="failure"> + <parameter name="error-code" value="1542" /> + <parameter name="error-message" value="Activation failure" /> +</return></pre></div></div></div> + +</script> + + +<script type="text/javascript"> + RED.nodes.registerType('returnFailure',{ + color:"#ED0819", + category: 'DGEreturn', + defaults: { + name: {value:"return failure"}, + xml: {value:"<return status='failure'>\n<parameter name='error-code' value='' />\n<parameter name='error-message' value='' />\n"}, + comments:{value:""} + }, + inputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgereturn/returnFailure.js b/dgbuilder/nodes/dge/dgereturn/returnFailure.js new file mode 100644 index 00000000..da9fc742 --- /dev/null +++ b/dgbuilder/nodes/dge/dgereturn/returnFailure.js @@ -0,0 +1,31 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function returnFailure(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + RED.nodes.registerType("returnFailure",returnFailure); + // RED.library.register("returnFailure"); +} diff --git a/dgbuilder/nodes/dge/dgereturn/returnSuccess.html b/dgbuilder/nodes/dge/dgereturn/returnSuccess.html new file mode 100644 index 00000000..e2d50f3a --- /dev/null +++ b/dgbuilder/nodes/dge/dgereturn/returnSuccess.html @@ -0,0 +1,174 @@ +<!-- + Copyright 2013 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> + +<script type="text/x-red" data-template-name="returnSuccess"> + <div class="form-row"> + <label for="node-input-name"><i class="fa fa-tag"></i> Name</label> + <input type="text" id="node-input-name" placeholder="Name"> + </div> + <div class="form-row"> + <label for="node-input-xml"><i class="fa fa-wrench"></i> Node XML</label> + <input type="hidden" id="node-input-xml" autofocus="autofocus"> + <div style="height: 450px;" class="node-text-editor" id="node-input-xml-editor" onkeyup="resetStatus()" ></div> + </div> + <div class="form-row"> + <a href="#" class="btn btn-mini" id="node-input-validate" style="margin-top: 4px;"><b>Validate XML</b></a> + <a href="#" class="btn btn-mini" id="node-input-show-sli-values" style="margin-top: 4px;"><b>Show Values</b></a> + <input type="hidden" id="node-input-comments"> + <a href="#" class="btn btn-mini" id="node-input-btnComments" style="margin-top: 4px;"><b>Add Comments</b></a> + <div id="node-validate-result" class="form-tips" style="float:right;font-size:10px"></div> + </div> + <div class="form-tips">See the Info tab for help using this node.</div> +</script> + +<script type="text/x-red" data-help-name="returnSuccess"> + <p>A returnSuccess node.</p> + <p>First line of XML must contain opening tag.</p> + <p>Do not include closing tag - it will be automatically generated.</p> + +<div class="section"> +<h4><a name="Return_node"></a>Return node</h4> +<div class="section"> +<h5><a name="Description"></a>Description</h5> +<p>A <b>return</b> node is used to return a status to the invoking MD-SAL application</p></div> +<div class="section"> +<h5><a name="Attributes"></a>Attributes</h5> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>status</b></td> +<td align="left">Status value to return (<i>success</i>)</td></tr></table></div> +<div class="section"> +<!-- +<h5><a name="Parameters"></a>Parameters</h5> +<p>The following optional parameters may be passed to convey more detailed status information.</p> +<table border="1" class="table table-striped"> +<tr class="a"> +<td align="center"><b>error-code</b></td> +<td align="left">A brief, usually numeric, code indicating the error condition</td></tr> +<tr class="b"> +<td align="center"><b>error-message</b></td> +<td align="left">A more detailed error message</td></tr></table></div> +--> +<div class="section"> +<h5><a name="Outcomes"></a>Outcomes</h5> +<p>Not applicable. The <b>status</b> node has no outcomes.</p></div> +<div class="section"> +<h5><a name="Example"></a>Example</h5> +<div class="source"> +<pre><return status="success"> + <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" /> +</return></pre></div></div></div> + +</script> + + +<script type="text/javascript"> + + RED.nodes.registerType('returnSuccess',{ + color:"#9AE767", + category: 'DGEreturn', + defaults: { + name: {value:"return success"}, + xml: {value:"<return status='success'>\n<parameter name='' value='' />\n",required:true}, + comments:{value:""} + }, + inputs:1, + icon: "arrow-in.png", + label: function() { + return this.name; + }, + oneditprepare: function() { + + + var comments = $( "#node-input-comments").val(); + if(comments != null){ + comments = comments.trim(); + if(comments != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + } + } + + function functionDialogResize(ev,ui) { + $("#node-input-xml-editor").css("height",(ui.size.height-275)+"px"); + }; + + $( "#dialog" ).dialog( "option", "width", 1200 ); + $( "#dialog" ).dialog( "option", "height", 750 ); + $( "#dialog" ).on("dialogresize", functionDialogResize); + $( "#dialog" ).one("dialogopen", function(ev) { + var size = $( "#dialog" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); + + /* close dialog when ESC is pressed and released */ + $( "#dialog" ).keyup(function(event){ + if(event.which == 27 ) { + $("#node-dialog-cancel").click(); + } + }); + + + $( "#dialog" ).one("dialogclose", function(ev,ui) { + var height = $( "#dialog" ).dialog('option','height'); + $( "#dialog" ).off("dialogresize",functionDialogResize); + }); + + var that = this; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('node-input-xml-editor'), + lang:"html", + contents: $("#node-input-xml").val() + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + $("#node-input-name").focus(); + $("#node-input-validate").click(function(){ + console.log("validate clicked."); + //console.dir(that.editor); + //console.log("getText:" + that.editor.getText()); + var val = that.editor.getText(); + validateXML(val); + }); + $("#node-input-show-sli-values").click(function(){ + console.log("SLIValues clicked."); + showValuesBox(that.editor,sliValuesObj); + }); + }); + //for click of add comments button + $("#node-input-btnComments").click(function(e){ + showCommentsBox(); + }); + + }, + oneditsave: function() { + $("#node-input-xml").val(this.editor.getText()); + var resp=validateXML(this.editor.getText()); + if(resp){ + this.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + this.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + delete this.editor; + } + }); +</script> diff --git a/dgbuilder/nodes/dge/dgereturn/returnSuccess.js b/dgbuilder/nodes/dge/dgereturn/returnSuccess.js new file mode 100644 index 00000000..d6c41c9a --- /dev/null +++ b/dgbuilder/nodes/dge/dgereturn/returnSuccess.js @@ -0,0 +1,32 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +module.exports = function(RED) { + "use strict"; + var util = require("util"); + var vm = require("vm"); + + function returnSuccess(n) { + RED.nodes.createNode(this,n); + this.name = n.name; + this.xml = n.xml; + this.topic = n.topic; + } + + + RED.nodes.registerType("returnSuccess",returnSuccess); + // RED.library.register("ret-success"); +} diff --git a/dgbuilder/package.json b/dgbuilder/package.json new file mode 100644 index 00000000..64114b3a --- /dev/null +++ b/dgbuilder/package.json @@ -0,0 +1,104 @@ +{ + "name": "node-red", + "version": "0.9.1", + "description": "A visual tool for wiring the Internet of Things", + "homepage": "http://nodered.org", + "license": "Apache", + "repository": { + "type": "git", + "url": "https://github.com/node-red/node-red.git" + }, + "main": "red/red.js", + "scripts": { + "start": "node red.js", + "test": "grunt" + }, + "contributors": [ + { + "name": "Nick O'Leary" + }, + { + "name": "Dave Conway-Jones" + } + ], + "keywords": [ + "editor", + "messaging", + "iot", + "m2m", + "pi", + "arduino", + "beaglebone", + "ibm", + "flow" + ], + "dependencies": { + "express": "3.17.2", + "when": "3.4.6", + "nopt": "3.0.1", + "mqtt": "0.3.x", + "ws": "0.4.32", + "fs-extra": "0.11.1", + "clone": "0.1.18", + "mustache": "0.8.2", + "cron": "1.0.4", + "raw-body": "1.3.0", + "twitter-ng": "0.6.2", + "oauth": "0.9.12", + "xml2js": "0.4.4", + "sentiment": "0.2.3", + "irc": "0.3.7", + "follow-redirects": "0.0.3", + "cors": "2.4.2", + "mkdirp": "0.5.0", + "cheerio": "0.17.0", + "uglify-js": "2.4.15", + "nodemailer": "1.3.0", + "imap": "0.8.13", + "request": "2.42.0", + "colors": "0.6.2", + "glob" : "5.0.15", + "lodash" : "3.7.0", + "multer" : "1.1.0", + "mysql" : "2.7.0", + "needle" : "0.9.2", + "pretty-data" : "0.40.0" + }, + "devDependencies": { + "grunt": "0.4.5", + "grunt-cli": "0.1.13", + "grunt-simple-mocha": "0.4.0", + "grunt-contrib-jshint": "0.10.0", + "mocha": "1.21.4", + "should": "4.0.4", + "sinon": "1.10.3", + "supertest": "^0.13.0" + }, + "engines": { + "node": ">=0.8" + }, + "bugs": { + "url": "https://github.com/node-red/node-red/issues" + }, + "_id": "node-red@0.9.1", + "dist": { + "shasum": "1c5f7ae2ef3dbcd090ca7db2e9c080968adc2f73", + "tarball": "http://registry.npmjs.org/node-red/-/node-red-0.9.1.tgz" + }, + "_from": "node-red@0.9.1", + "_npmVersion": "1.4.6", + "_npmUser": { + "name": "knolleary", + "email": "nick.oleary@gmail.com" + }, + "maintainers": [ + { + "name": "knolleary", + "email": "nick.oleary@gmail.com" + } + ], + "directories": {}, + "_shasum": "1c5f7ae2ef3dbcd090ca7db2e9c080968adc2f73", + "_resolved": "https://registry.npmjs.org/node-red/-/node-red-0.9.1.tgz", + "readme": "ERROR: No README data found!" +} diff --git a/dgbuilder/pom.xml b/dgbuilder/pom.xml new file mode 100644 index 00000000..e1cde5a0 --- /dev/null +++ b/dgbuilder/pom.xml @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + + <parent> + <groupId>org.onap.ccsdk.distribution</groupId> + <artifactId>distribution-root</artifactId> + <version>0.1.0-SNAPSHOT</version> + </parent> + + <modelVersion>4.0.0</modelVersion> + <packaging>pom</packaging> + <groupId>org.onap.ccsdk.distribution</groupId> + <artifactId>distribution-dgbuilder</artifactId> + + <version>0.1.0-SNAPSHOT</version> + + <name>Distribution - dgbuilder</name> + <description>Directed Graph Builder</description> + + <properties> + <application.name>dgbuilder</application.name> + <skip.SWM>true</skip.SWM> + <adm.base>/opt/app/dgbuilder</adm.base> + <maven.build.timestamp.format>yyMMdd-HHmmss</maven.build.timestamp.format> + <build.number>${maven.build.timestamp}</build.number> + <SWM_VERSION>${project.version}-${build.number}</SWM_VERSION> + </properties> + + <dependencies> + <dependency> + <groupId>org.onap.ccsdk.sli.core</groupId> + <artifactId>sli-common</artifactId> + <version>${sdnctl.sli.version}</version> + </dependency> + <dependency> + <groupId>mysql</groupId> + <artifactId>mysql-connector-java</artifactId> + <version>5.1.31</version> + <type>jar</type> + </dependency> + <dependency> + <groupId>org.antlr</groupId> + <artifactId>antlr4</artifactId> + <version>${antlr.version}</version> + <type>jar</type> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + <version>${slf4j.version}</version> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + <version>1.7.5</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + <version>${commons.lang3.version}</version> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <version>2.6</version> + <executions> + <execution> + <id>create-zip</id> + <goals> + <goal>single</goal> + </goals> + <phase>package</phase> + <configuration> + <finalName>${application.name}.${project.version}</finalName> + <attach>true</attach> + <descriptors> + <descriptor>src/assembly/assemble_zip.xml</descriptor> + </descriptors> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-dependency-plugin</artifactId> + <executions> + <execution> + <id>copy-dependencies</id> + <goals> + <goal>copy-dependencies</goal> + </goals> + <phase>prepare-package</phase> + <configuration> + <transitive>false</transitive> + <outputDirectory>${project.build.directory}/svclogic/lib</outputDirectory> + <overWriteReleases>false</overWriteReleases> + <overWriteSnapshots>true</overWriteSnapshots> + <overWriteIfNewer>true</overWriteIfNewer> + <useRepositoryLayout>false</useRepositoryLayout> + <addParentPoms>false</addParentPoms> + <copyPom>false</copyPom> + <scope>provided</scope> + </configuration> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <phase>generate-sources</phase> + <configuration> + <tasks> + <exec executable="${project.basedir}/build_pom_for_yang_compile"> + <arg value="${project.parent.version}"/> + </exec> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + <organization> + <name>ONAP</name> + </organization> +</project> + diff --git a/dgbuilder/public/bootstrap/css/bootstrap.min.css b/dgbuilder/public/bootstrap/css/bootstrap.min.css new file mode 100644 index 00000000..df96c864 --- /dev/null +++ b/dgbuilder/public/bootstrap/css/bootstrap.min.css @@ -0,0 +1,9 @@ +/*! + * Bootstrap v2.3.2 + * + * Copyright 2013 Twitter, Inc + * Licensed under the Apache License v2.0 + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Designed and built with all the love in the world by @mdo and @fat. + */.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;line-height:0;content:""}.clearfix:after{clear:both}.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}audio,canvas,video{display:inline-block;*display:inline;*zoom:1}audio:not([controls]){display:none}html{font-size:100%;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%}a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}a:hover,a:active{outline:0}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{width:auto\9;height:auto;max-width:100%;vertical-align:middle;border:0;-ms-interpolation-mode:bicubic}#map_canvas img,.google-maps img{max-width:none}button,input,select,textarea{margin:0;font-size:100%;vertical-align:middle}button,input{*overflow:visible;line-height:normal}button::-moz-focus-inner,input::-moz-focus-inner{padding:0;border:0}button,html input[type="button"],input[type="reset"],input[type="submit"]{cursor:pointer;-webkit-appearance:button}label,select,button,input[type="button"],input[type="reset"],input[type="submit"],input[type="radio"],input[type="checkbox"]{cursor:pointer}input[type="search"]{-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;-webkit-appearance:textfield}input[type="search"]::-webkit-search-decoration,input[type="search"]::-webkit-search-cancel-button{-webkit-appearance:none}textarea{overflow:auto;vertical-align:top}@media print{*{color:#000!important;text-shadow:none!important;background:transparent!important;box-shadow:none!important}a,a:visited{text-decoration:underline}a[href]:after{content:" (" attr(href) ")"}abbr[title]:after{content:" (" attr(title) ")"}.ir a:after,a[href^="javascript:"]:after,a[href^="#"]:after{content:""}pre,blockquote{border:1px solid #999;page-break-inside:avoid}thead{display:table-header-group}tr,img{page-break-inside:avoid}img{max-width:100%!important}@page{margin:.5cm}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}}body{margin:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:20px;color:#333;background-color:#fff}a{color:#08c;text-decoration:none}a:hover,a:focus{color:#005580;text-decoration:underline}.img-rounded{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.img-polaroid{padding:4px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1)}.img-circle{-webkit-border-radius:500px;-moz-border-radius:500px;border-radius:500px}.row{margin-left:-20px;*zoom:1}.row:before,.row:after{display:table;line-height:0;content:""}.row:after{clear:both}[class*="span"]{float:left;min-height:1px;margin-left:20px}.container,.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.span12{width:940px}.span11{width:860px}.span10{width:780px}.span9{width:700px}.span8{width:620px}.span7{width:540px}.span6{width:460px}.span5{width:380px}.span4{width:300px}.span3{width:220px}.span2{width:140px}.span1{width:60px}.offset12{margin-left:980px}.offset11{margin-left:900px}.offset10{margin-left:820px}.offset9{margin-left:740px}.offset8{margin-left:660px}.offset7{margin-left:580px}.offset6{margin-left:500px}.offset5{margin-left:420px}.offset4{margin-left:340px}.offset3{margin-left:260px}.offset2{margin-left:180px}.offset1{margin-left:100px}.row-fluid{width:100%;*zoom:1}.row-fluid:before,.row-fluid:after{display:table;line-height:0;content:""}.row-fluid:after{clear:both}.row-fluid [class*="span"]{display:block;float:left;width:100%;min-height:30px;margin-left:2.127659574468085%;*margin-left:2.074468085106383%;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.row-fluid [class*="span"]:first-child{margin-left:0}.row-fluid .controls-row [class*="span"]+[class*="span"]{margin-left:2.127659574468085%}.row-fluid .span12{width:100%;*width:99.94680851063829%}.row-fluid .span11{width:91.48936170212765%;*width:91.43617021276594%}.row-fluid .span10{width:82.97872340425532%;*width:82.92553191489361%}.row-fluid .span9{width:74.46808510638297%;*width:74.41489361702126%}.row-fluid .span8{width:65.95744680851064%;*width:65.90425531914893%}.row-fluid .span7{width:57.44680851063829%;*width:57.39361702127659%}.row-fluid .span6{width:48.93617021276595%;*width:48.88297872340425%}.row-fluid .span5{width:40.42553191489362%;*width:40.37234042553192%}.row-fluid .span4{width:31.914893617021278%;*width:31.861702127659576%}.row-fluid .span3{width:23.404255319148934%;*width:23.351063829787233%}.row-fluid .span2{width:14.893617021276595%;*width:14.840425531914894%}.row-fluid .span1{width:6.382978723404255%;*width:6.329787234042553%}.row-fluid .offset12{margin-left:104.25531914893617%;*margin-left:104.14893617021275%}.row-fluid .offset12:first-child{margin-left:102.12765957446808%;*margin-left:102.02127659574467%}.row-fluid .offset11{margin-left:95.74468085106382%;*margin-left:95.6382978723404%}.row-fluid .offset11:first-child{margin-left:93.61702127659574%;*margin-left:93.51063829787232%}.row-fluid .offset10{margin-left:87.23404255319149%;*margin-left:87.12765957446807%}.row-fluid .offset10:first-child{margin-left:85.1063829787234%;*margin-left:84.99999999999999%}.row-fluid .offset9{margin-left:78.72340425531914%;*margin-left:78.61702127659572%}.row-fluid .offset9:first-child{margin-left:76.59574468085106%;*margin-left:76.48936170212764%}.row-fluid .offset8{margin-left:70.2127659574468%;*margin-left:70.10638297872339%}.row-fluid .offset8:first-child{margin-left:68.08510638297872%;*margin-left:67.9787234042553%}.row-fluid .offset7{margin-left:61.70212765957446%;*margin-left:61.59574468085106%}.row-fluid .offset7:first-child{margin-left:59.574468085106375%;*margin-left:59.46808510638297%}.row-fluid .offset6{margin-left:53.191489361702125%;*margin-left:53.085106382978715%}.row-fluid .offset6:first-child{margin-left:51.063829787234035%;*margin-left:50.95744680851063%}.row-fluid .offset5{margin-left:44.68085106382979%;*margin-left:44.57446808510638%}.row-fluid .offset5:first-child{margin-left:42.5531914893617%;*margin-left:42.4468085106383%}.row-fluid .offset4{margin-left:36.170212765957444%;*margin-left:36.06382978723405%}.row-fluid .offset4:first-child{margin-left:34.04255319148936%;*margin-left:33.93617021276596%}.row-fluid .offset3{margin-left:27.659574468085104%;*margin-left:27.5531914893617%}.row-fluid .offset3:first-child{margin-left:25.53191489361702%;*margin-left:25.425531914893618%}.row-fluid .offset2{margin-left:19.148936170212764%;*margin-left:19.04255319148936%}.row-fluid .offset2:first-child{margin-left:17.02127659574468%;*margin-left:16.914893617021278%}.row-fluid .offset1{margin-left:10.638297872340425%;*margin-left:10.53191489361702%}.row-fluid .offset1:first-child{margin-left:8.51063829787234%;*margin-left:8.404255319148938%}[class*="span"].hide,.row-fluid [class*="span"].hide{display:none}[class*="span"].pull-right,.row-fluid [class*="span"].pull-right{float:right}.container{margin-right:auto;margin-left:auto;*zoom:1}.container:before,.container:after{display:table;line-height:0;content:""}.container:after{clear:both}.container-fluid{padding-right:20px;padding-left:20px;*zoom:1}.container-fluid:before,.container-fluid:after{display:table;line-height:0;content:""}.container-fluid:after{clear:both}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:21px;font-weight:200;line-height:30px}small{font-size:85%}strong{font-weight:bold}em{font-style:italic}cite{font-style:normal}.muted{color:#999}a.muted:hover,a.muted:focus{color:#808080}.text-warning{color:#c09853}a.text-warning:hover,a.text-warning:focus{color:#a47e3c}.text-error{color:#b94a48}a.text-error:hover,a.text-error:focus{color:#953b39}.text-info{color:#3a87ad}a.text-info:hover,a.text-info:focus{color:#2d6987}.text-success{color:#468847}a.text-success:hover,a.text-success:focus{color:#356635}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}h1,h2,h3,h4,h5,h6{margin:10px 0;font-family:inherit;font-weight:bold;line-height:20px;color:inherit;text-rendering:optimizelegibility}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-weight:normal;line-height:1;color:#999}h1,h2,h3{line-height:40px}h1{font-size:38.5px}h2{font-size:31.5px}h3{font-size:24.5px}h4{font-size:17.5px}h5{font-size:14px}h6{font-size:11.9px}h1 small{font-size:24.5px}h2 small{font-size:17.5px}h3 small{font-size:14px}h4 small{font-size:14px}.page-header{padding-bottom:9px;margin:20px 0 30px;border-bottom:1px solid #eee}ul,ol{padding:0;margin:0 0 10px 25px}ul ul,ul ol,ol ol,ol ul{margin-bottom:0}li{line-height:20px}ul.unstyled,ol.unstyled{margin-left:0;list-style:none}ul.inline,ol.inline{margin-left:0;list-style:none}ul.inline>li,ol.inline>li{display:inline-block;*display:inline;padding-right:5px;padding-left:5px;*zoom:1}dl{margin-bottom:20px}dt,dd{line-height:20px}dt{font-weight:bold}dd{margin-left:10px}.dl-horizontal{*zoom:1}.dl-horizontal:before,.dl-horizontal:after{display:table;line-height:0;content:""}.dl-horizontal:after{clear:both}.dl-horizontal dt{float:left;width:160px;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}hr{margin:20px 0;border:0;border-top:1px solid #eee;border-bottom:1px solid #fff}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}abbr.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:0 0 0 15px;margin:0 0 20px;border-left:5px solid #eee}blockquote p{margin-bottom:0;font-size:17.5px;font-weight:300;line-height:1.25}blockquote small{display:block;line-height:20px;color:#999}blockquote small:before{content:'\2014 \00A0'}blockquote.pull-right{float:right;padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0}blockquote.pull-right p,blockquote.pull-right small{text-align:right}blockquote.pull-right small:before{content:''}blockquote.pull-right small:after{content:'\00A0 \2014'}q:before,q:after,blockquote:before,blockquote:after{content:""}address{display:block;margin-bottom:20px;font-style:normal;line-height:20px}code,pre{padding:0 3px 2px;font-family:Monaco,Menlo,Consolas,"Courier New",monospace;font-size:12px;color:#333;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}code{padding:2px 4px;color:#d14;white-space:nowrap;background-color:#f7f7f9;border:1px solid #e1e1e8}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:20px;word-break:break-all;word-wrap:break-word;white-space:pre;white-space:pre-wrap;background-color:#f5f5f5;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}pre.prettyprint{margin-bottom:20px}pre code{padding:0;color:inherit;white-space:pre;white-space:pre-wrap;background-color:transparent;border:0}.pre-scrollable{max-height:340px;overflow-y:scroll}form{margin:0 0 20px}fieldset{padding:0;margin:0;border:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:40px;color:#333;border:0;border-bottom:1px solid #e5e5e5}legend small{font-size:15px;color:#999}label,input,button,select,textarea{font-size:14px;font-weight:normal;line-height:20px}input,button,select,textarea{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif}label{display:block;margin-bottom:5px}select,textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{display:inline-block;height:20px;padding:4px 6px;margin-bottom:10px;font-size:14px;line-height:20px;color:#555;vertical-align:middle;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}input,textarea,.uneditable-input{width:206px}textarea{height:auto}textarea,input[type="text"],input[type="password"],input[type="datetime"],input[type="datetime-local"],input[type="date"],input[type="month"],input[type="time"],input[type="week"],input[type="number"],input[type="email"],input[type="url"],input[type="search"],input[type="tel"],input[type="color"],.uneditable-input{background-color:#fff;border:1px solid #ccc;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border linear .2s,box-shadow linear .2s;-moz-transition:border linear .2s,box-shadow linear .2s;-o-transition:border linear .2s,box-shadow linear .2s;transition:border linear .2s,box-shadow linear .2s}textarea:focus,input[type="text"]:focus,input[type="password"]:focus,input[type="datetime"]:focus,input[type="datetime-local"]:focus,input[type="date"]:focus,input[type="month"]:focus,input[type="time"]:focus,input[type="week"]:focus,input[type="number"]:focus,input[type="email"]:focus,input[type="url"]:focus,input[type="search"]:focus,input[type="tel"]:focus,input[type="color"]:focus,.uneditable-input:focus{border-color:rgba(82,168,236,0.8);outline:0;outline:thin dotted \9;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(82,168,236,0.6)}input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;*margin-top:0;line-height:normal}input[type="file"],input[type="image"],input[type="submit"],input[type="reset"],input[type="button"],input[type="radio"],input[type="checkbox"]{width:auto}select,input[type="file"]{height:30px;*margin-top:4px;line-height:30px}select{width:220px;background-color:#fff;border:1px solid #ccc}select[multiple],select[size]{height:auto}select:focus,input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.uneditable-input,.uneditable-textarea{color:#999;cursor:not-allowed;background-color:#fcfcfc;border-color:#ccc;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.025);box-shadow:inset 0 1px 2px rgba(0,0,0,0.025)}.uneditable-input{overflow:hidden;white-space:nowrap}.uneditable-textarea{width:auto;height:auto}input:-moz-placeholder,textarea:-moz-placeholder{color:#999}input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#999}input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#999}.radio,.checkbox{min-height:20px;padding-left:20px}.radio input[type="radio"],.checkbox input[type="checkbox"]{float:left;margin-left:-20px}.controls>.radio:first-child,.controls>.checkbox:first-child{padding-top:5px}.radio.inline,.checkbox.inline{display:inline-block;padding-top:5px;margin-bottom:0;vertical-align:middle}.radio.inline+.radio.inline,.checkbox.inline+.checkbox.inline{margin-left:10px}.input-mini{width:60px}.input-small{width:90px}.input-medium{width:150px}.input-large{width:210px}.input-xlarge{width:270px}.input-xxlarge{width:530px}input[class*="span"],select[class*="span"],textarea[class*="span"],.uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"]{float:none;margin-left:0}.input-append input[class*="span"],.input-append .uneditable-input[class*="span"],.input-prepend input[class*="span"],.input-prepend .uneditable-input[class*="span"],.row-fluid input[class*="span"],.row-fluid select[class*="span"],.row-fluid textarea[class*="span"],.row-fluid .uneditable-input[class*="span"],.row-fluid .input-prepend [class*="span"],.row-fluid .input-append [class*="span"]{display:inline-block}input,textarea,.uneditable-input{margin-left:0}.controls-row [class*="span"]+[class*="span"]{margin-left:20px}input.span12,textarea.span12,.uneditable-input.span12{width:926px}input.span11,textarea.span11,.uneditable-input.span11{width:846px}input.span10,textarea.span10,.uneditable-input.span10{width:766px}input.span9,textarea.span9,.uneditable-input.span9{width:686px}input.span8,textarea.span8,.uneditable-input.span8{width:606px}input.span7,textarea.span7,.uneditable-input.span7{width:526px}input.span6,textarea.span6,.uneditable-input.span6{width:446px}input.span5,textarea.span5,.uneditable-input.span5{width:366px}input.span4,textarea.span4,.uneditable-input.span4{width:286px}input.span3,textarea.span3,.uneditable-input.span3{width:206px}input.span2,textarea.span2,.uneditable-input.span2{width:126px}input.span1,textarea.span1,.uneditable-input.span1{width:46px}.controls-row{*zoom:1}.controls-row:before,.controls-row:after{display:table;line-height:0;content:""}.controls-row:after{clear:both}.controls-row [class*="span"],.row-fluid .controls-row [class*="span"]{float:left}.controls-row .checkbox[class*="span"],.controls-row .radio[class*="span"]{padding-top:5px}input[disabled],select[disabled],textarea[disabled],input[readonly],select[readonly],textarea[readonly]{cursor:not-allowed;background-color:#eee}input[type="radio"][disabled],input[type="checkbox"][disabled],input[type="radio"][readonly],input[type="checkbox"][readonly]{background-color:transparent}.control-group.warning .control-label,.control-group.warning .help-block,.control-group.warning .help-inline{color:#c09853}.control-group.warning .checkbox,.control-group.warning .radio,.control-group.warning input,.control-group.warning select,.control-group.warning textarea{color:#c09853}.control-group.warning input,.control-group.warning select,.control-group.warning textarea{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.warning input:focus,.control-group.warning select:focus,.control-group.warning textarea:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #dbc59e}.control-group.warning .input-prepend .add-on,.control-group.warning .input-append .add-on{color:#c09853;background-color:#fcf8e3;border-color:#c09853}.control-group.error .control-label,.control-group.error .help-block,.control-group.error .help-inline{color:#b94a48}.control-group.error .checkbox,.control-group.error .radio,.control-group.error input,.control-group.error select,.control-group.error textarea{color:#b94a48}.control-group.error input,.control-group.error select,.control-group.error textarea{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.error input:focus,.control-group.error select:focus,.control-group.error textarea:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #d59392}.control-group.error .input-prepend .add-on,.control-group.error .input-append .add-on{color:#b94a48;background-color:#f2dede;border-color:#b94a48}.control-group.success .control-label,.control-group.success .help-block,.control-group.success .help-inline{color:#468847}.control-group.success .checkbox,.control-group.success .radio,.control-group.success input,.control-group.success select,.control-group.success textarea{color:#468847}.control-group.success input,.control-group.success select,.control-group.success textarea{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.success input:focus,.control-group.success select:focus,.control-group.success textarea:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7aba7b}.control-group.success .input-prepend .add-on,.control-group.success .input-append .add-on{color:#468847;background-color:#dff0d8;border-color:#468847}.control-group.info .control-label,.control-group.info .help-block,.control-group.info .help-inline{color:#3a87ad}.control-group.info .checkbox,.control-group.info .radio,.control-group.info input,.control-group.info select,.control-group.info textarea{color:#3a87ad}.control-group.info input,.control-group.info select,.control-group.info textarea{border-color:#3a87ad;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.control-group.info input:focus,.control-group.info select:focus,.control-group.info textarea:focus{border-color:#2d6987;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #7ab5d3}.control-group.info .input-prepend .add-on,.control-group.info .input-append .add-on{color:#3a87ad;background-color:#d9edf7;border-color:#3a87ad}input:focus:invalid,textarea:focus:invalid,select:focus:invalid{color:#b94a48;border-color:#ee5f5b}input:focus:invalid:focus,textarea:focus:invalid:focus,select:focus:invalid:focus{border-color:#e9322d;-webkit-box-shadow:0 0 6px #f8b9b7;-moz-box-shadow:0 0 6px #f8b9b7;box-shadow:0 0 6px #f8b9b7}.form-actions{padding:19px 20px 20px;margin-top:20px;margin-bottom:20px;background-color:#f5f5f5;border-top:1px solid #e5e5e5;*zoom:1}.form-actions:before,.form-actions:after{display:table;line-height:0;content:""}.form-actions:after{clear:both}.help-block,.help-inline{color:#595959}.help-block{display:block;margin-bottom:10px}.help-inline{display:inline-block;*display:inline;padding-left:5px;vertical-align:middle;*zoom:1}.input-append,.input-prepend{display:inline-block;margin-bottom:10px;font-size:0;white-space:nowrap;vertical-align:middle}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input,.input-append .dropdown-menu,.input-prepend .dropdown-menu,.input-append .popover,.input-prepend .popover{font-size:14px}.input-append input,.input-prepend input,.input-append select,.input-prepend select,.input-append .uneditable-input,.input-prepend .uneditable-input{position:relative;margin-bottom:0;*margin-left:0;vertical-align:top;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append input:focus,.input-prepend input:focus,.input-append select:focus,.input-prepend select:focus,.input-append .uneditable-input:focus,.input-prepend .uneditable-input:focus{z-index:2}.input-append .add-on,.input-prepend .add-on{display:inline-block;width:auto;height:20px;min-width:16px;padding:4px 5px;font-size:14px;font-weight:normal;line-height:20px;text-align:center;text-shadow:0 1px 0 #fff;background-color:#eee;border:1px solid #ccc}.input-append .add-on,.input-prepend .add-on,.input-append .btn,.input-prepend .btn,.input-append .btn-group>.dropdown-toggle,.input-prepend .btn-group>.dropdown-toggle{vertical-align:top;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-append .active,.input-prepend .active{background-color:#a9dba9;border-color:#46a546}.input-prepend .add-on,.input-prepend .btn{margin-right:-1px}.input-prepend .add-on:first-child,.input-prepend .btn:first-child{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input,.input-append select,.input-append .uneditable-input{-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-append input+.btn-group .btn:last-child,.input-append select+.btn-group .btn:last-child,.input-append .uneditable-input+.btn-group .btn:last-child{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-append .add-on,.input-append .btn,.input-append .btn-group{margin-left:-1px}.input-append .add-on:last-child,.input-append .btn:last-child,.input-append .btn-group:last-child>.dropdown-toggle{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append input,.input-prepend.input-append select,.input-prepend.input-append .uneditable-input{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.input-prepend.input-append input+.btn-group .btn,.input-prepend.input-append select+.btn-group .btn,.input-prepend.input-append .uneditable-input+.btn-group .btn{-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .add-on:first-child,.input-prepend.input-append .btn:first-child{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.input-prepend.input-append .add-on:last-child,.input-prepend.input-append .btn:last-child{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.input-prepend.input-append .btn-group:first-child{margin-left:0}input.search-query{padding-right:14px;padding-right:4px \9;padding-left:14px;padding-left:4px \9;margin-bottom:0;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.form-search .input-append .search-query,.form-search .input-prepend .search-query{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.form-search .input-append .search-query{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search .input-append .btn{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .search-query{-webkit-border-radius:0 14px 14px 0;-moz-border-radius:0 14px 14px 0;border-radius:0 14px 14px 0}.form-search .input-prepend .btn{-webkit-border-radius:14px 0 0 14px;-moz-border-radius:14px 0 0 14px;border-radius:14px 0 0 14px}.form-search input,.form-inline input,.form-horizontal input,.form-search textarea,.form-inline textarea,.form-horizontal textarea,.form-search select,.form-inline select,.form-horizontal select,.form-search .help-inline,.form-inline .help-inline,.form-horizontal .help-inline,.form-search .uneditable-input,.form-inline .uneditable-input,.form-horizontal .uneditable-input,.form-search .input-prepend,.form-inline .input-prepend,.form-horizontal .input-prepend,.form-search .input-append,.form-inline .input-append,.form-horizontal .input-append{display:inline-block;*display:inline;margin-bottom:0;vertical-align:middle;*zoom:1}.form-search .hide,.form-inline .hide,.form-horizontal .hide{display:none}.form-search label,.form-inline label,.form-search .btn-group,.form-inline .btn-group{display:inline-block}.form-search .input-append,.form-inline .input-append,.form-search .input-prepend,.form-inline .input-prepend{margin-bottom:0}.form-search .radio,.form-search .checkbox,.form-inline .radio,.form-inline .checkbox{padding-left:0;margin-bottom:0;vertical-align:middle}.form-search .radio input[type="radio"],.form-search .checkbox input[type="checkbox"],.form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:left;margin-right:3px;margin-left:0}.control-group{margin-bottom:10px}legend+.control-group{margin-top:20px;-webkit-margin-top-collapse:separate}.form-horizontal .control-group{margin-bottom:20px;*zoom:1}.form-horizontal .control-group:before,.form-horizontal .control-group:after{display:table;line-height:0;content:""}.form-horizontal .control-group:after{clear:both}.form-horizontal .control-label{float:left;width:160px;padding-top:5px;text-align:right}.form-horizontal .controls{*display:inline-block;*padding-left:20px;margin-left:180px;*margin-left:0}.form-horizontal .controls:first-child{*padding-left:180px}.form-horizontal .help-block{margin-bottom:0}.form-horizontal input+.help-block,.form-horizontal select+.help-block,.form-horizontal textarea+.help-block,.form-horizontal .uneditable-input+.help-block,.form-horizontal .input-prepend+.help-block,.form-horizontal .input-append+.help-block{margin-top:10px}.form-horizontal .form-actions{padding-left:180px}table{max-width:100%;background-color:transparent;border-collapse:collapse;border-spacing:0}.table{width:100%;margin-bottom:20px}.table th,.table td{padding:8px;line-height:20px;text-align:left;vertical-align:top;border-top:1px solid #ddd}.table th{font-weight:bold}.table thead th{vertical-align:bottom}.table caption+thead tr:first-child th,.table caption+thead tr:first-child td,.table colgroup+thead tr:first-child th,.table colgroup+thead tr:first-child td,.table thead:first-child tr:first-child th,.table thead:first-child tr:first-child td{border-top:0}.table tbody+tbody{border-top:2px solid #ddd}.table .table{background-color:#fff}.table-condensed th,.table-condensed td{padding:4px 5px}.table-bordered{border:1px solid #ddd;border-collapse:separate;*border-collapse:collapse;border-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.table-bordered th,.table-bordered td{border-left:1px solid #ddd}.table-bordered caption+thead tr:first-child th,.table-bordered caption+tbody tr:first-child th,.table-bordered caption+tbody tr:first-child td,.table-bordered colgroup+thead tr:first-child th,.table-bordered colgroup+tbody tr:first-child th,.table-bordered colgroup+tbody tr:first-child td,.table-bordered thead:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child th,.table-bordered tbody:first-child tr:first-child td{border-top:0}.table-bordered thead:first-child tr:first-child>th:first-child,.table-bordered tbody:first-child tr:first-child>td:first-child,.table-bordered tbody:first-child tr:first-child>th:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered thead:first-child tr:first-child>th:last-child,.table-bordered tbody:first-child tr:first-child>td:last-child,.table-bordered tbody:first-child tr:first-child>th:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-bordered thead:last-child tr:last-child>th:first-child,.table-bordered tbody:last-child tr:last-child>td:first-child,.table-bordered tbody:last-child tr:last-child>th:first-child,.table-bordered tfoot:last-child tr:last-child>td:first-child,.table-bordered tfoot:last-child tr:last-child>th:first-child{-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomleft:4px}.table-bordered thead:last-child tr:last-child>th:last-child,.table-bordered tbody:last-child tr:last-child>td:last-child,.table-bordered tbody:last-child tr:last-child>th:last-child,.table-bordered tfoot:last-child tr:last-child>td:last-child,.table-bordered tfoot:last-child tr:last-child>th:last-child{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-bottomright:4px}.table-bordered tfoot+tbody:last-child tr:last-child td:first-child{-webkit-border-bottom-left-radius:0;border-bottom-left-radius:0;-moz-border-radius-bottomleft:0}.table-bordered tfoot+tbody:last-child tr:last-child td:last-child{-webkit-border-bottom-right-radius:0;border-bottom-right-radius:0;-moz-border-radius-bottomright:0}.table-bordered caption+thead tr:first-child th:first-child,.table-bordered caption+tbody tr:first-child td:first-child,.table-bordered colgroup+thead tr:first-child th:first-child,.table-bordered colgroup+tbody tr:first-child td:first-child{-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topleft:4px}.table-bordered caption+thead tr:first-child th:last-child,.table-bordered caption+tbody tr:first-child td:last-child,.table-bordered colgroup+thead tr:first-child th:last-child,.table-bordered colgroup+tbody tr:first-child td:last-child{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-moz-border-radius-topright:4px}.table-striped tbody>tr:nth-child(odd)>td,.table-striped tbody>tr:nth-child(odd)>th{background-color:#f9f9f9}.table-hover tbody tr:hover>td,.table-hover tbody tr:hover>th{background-color:#f5f5f5}table td[class*="span"],table th[class*="span"],.row-fluid table td[class*="span"],.row-fluid table th[class*="span"]{display:table-cell;float:none;margin-left:0}.table td.span1,.table th.span1{float:none;width:44px;margin-left:0}.table td.span2,.table th.span2{float:none;width:124px;margin-left:0}.table td.span3,.table th.span3{float:none;width:204px;margin-left:0}.table td.span4,.table th.span4{float:none;width:284px;margin-left:0}.table td.span5,.table th.span5{float:none;width:364px;margin-left:0}.table td.span6,.table th.span6{float:none;width:444px;margin-left:0}.table td.span7,.table th.span7{float:none;width:524px;margin-left:0}.table td.span8,.table th.span8{float:none;width:604px;margin-left:0}.table td.span9,.table th.span9{float:none;width:684px;margin-left:0}.table td.span10,.table th.span10{float:none;width:764px;margin-left:0}.table td.span11,.table th.span11{float:none;width:844px;margin-left:0}.table td.span12,.table th.span12{float:none;width:924px;margin-left:0}.table tbody tr.success>td{background-color:#dff0d8}.table tbody tr.error>td{background-color:#f2dede}.table tbody tr.warning>td{background-color:#fcf8e3}.table tbody tr.info>td{background-color:#d9edf7}.table-hover tbody tr.success:hover>td{background-color:#d0e9c6}.table-hover tbody tr.error:hover>td{background-color:#ebcccc}.table-hover tbody tr.warning:hover>td{background-color:#faf2cc}.table-hover tbody tr.info:hover>td{background-color:#c4e3f3}[class^="icon-"],[class*=" icon-"]{display:inline-block;width:14px;height:14px;margin-top:1px;*margin-right:.3em;line-height:14px;vertical-align:text-top;background-image:url("../img/glyphicons-halflings.png");background-position:14px 14px;background-repeat:no-repeat}.icon-white,.nav-pills>.active>a>[class^="icon-"],.nav-pills>.active>a>[class*=" icon-"],.nav-list>.active>a>[class^="icon-"],.nav-list>.active>a>[class*=" icon-"],.navbar-inverse .nav>.active>a>[class^="icon-"],.navbar-inverse .nav>.active>a>[class*=" icon-"],.dropdown-menu>li>a:hover>[class^="icon-"],.dropdown-menu>li>a:focus>[class^="icon-"],.dropdown-menu>li>a:hover>[class*=" icon-"],.dropdown-menu>li>a:focus>[class*=" icon-"],.dropdown-menu>.active>a>[class^="icon-"],.dropdown-menu>.active>a>[class*=" icon-"],.dropdown-submenu:hover>a>[class^="icon-"],.dropdown-submenu:focus>a>[class^="icon-"],.dropdown-submenu:hover>a>[class*=" icon-"],.dropdown-submenu:focus>a>[class*=" icon-"]{background-image:url("../img/glyphicons-halflings-white.png")}.icon-glass{background-position:0 0}.icon-music{background-position:-24px 0}.icon-search{background-position:-48px 0}.icon-envelope{background-position:-72px 0}.icon-heart{background-position:-96px 0}.icon-star{background-position:-120px 0}.icon-star-empty{background-position:-144px 0}.icon-user{background-position:-168px 0}.icon-film{background-position:-192px 0}.icon-th-large{background-position:-216px 0}.icon-th{background-position:-240px 0}.icon-th-list{background-position:-264px 0}.icon-ok{background-position:-288px 0}.icon-remove{background-position:-312px 0}.icon-zoom-in{background-position:-336px 0}.icon-zoom-out{background-position:-360px 0}.icon-off{background-position:-384px 0}.icon-signal{background-position:-408px 0}.icon-cog{background-position:-432px 0}.icon-trash{background-position:-456px 0}.icon-home{background-position:0 -24px}.icon-file{background-position:-24px -24px}.icon-time{background-position:-48px -24px}.icon-road{background-position:-72px -24px}.icon-download-alt{background-position:-96px -24px}.icon-download{background-position:-120px -24px}.icon-upload{background-position:-144px -24px}.icon-inbox{background-position:-168px -24px}.icon-play-circle{background-position:-192px -24px}.icon-repeat{background-position:-216px -24px}.icon-refresh{background-position:-240px -24px}.icon-list-alt{background-position:-264px -24px}.icon-lock{background-position:-287px -24px}.icon-flag{background-position:-312px -24px}.icon-headphones{background-position:-336px -24px}.icon-volume-off{background-position:-360px -24px}.icon-volume-down{background-position:-384px -24px}.icon-volume-up{background-position:-408px -24px}.icon-qrcode{background-position:-432px -24px}.icon-barcode{background-position:-456px -24px}.icon-tag{background-position:0 -48px}.icon-tags{background-position:-25px -48px}.icon-book{background-position:-48px -48px}.icon-bookmark{background-position:-72px -48px}.icon-print{background-position:-96px -48px}.icon-camera{background-position:-120px -48px}.icon-font{background-position:-144px -48px}.icon-bold{background-position:-167px -48px}.icon-italic{background-position:-192px -48px}.icon-text-height{background-position:-216px -48px}.icon-text-width{background-position:-240px -48px}.icon-align-left{background-position:-264px -48px}.icon-align-center{background-position:-288px -48px}.icon-align-right{background-position:-312px -48px}.icon-align-justify{background-position:-336px -48px}.icon-list{background-position:-360px -48px}.icon-indent-left{background-position:-384px -48px}.icon-indent-right{background-position:-408px -48px}.icon-facetime-video{background-position:-432px -48px}.icon-picture{background-position:-456px -48px}.icon-pencil{background-position:0 -72px}.icon-map-marker{background-position:-24px -72px}.icon-adjust{background-position:-48px -72px}.icon-tint{background-position:-72px -72px}.icon-edit{background-position:-96px -72px}.icon-share{background-position:-120px -72px}.icon-check{background-position:-144px -72px}.icon-move{background-position:-168px -72px}.icon-step-backward{background-position:-192px -72px}.icon-fast-backward{background-position:-216px -72px}.icon-backward{background-position:-240px -72px}.icon-play{background-position:-264px -72px}.icon-pause{background-position:-288px -72px}.icon-stop{background-position:-312px -72px}.icon-forward{background-position:-336px -72px}.icon-fast-forward{background-position:-360px -72px}.icon-step-forward{background-position:-384px -72px}.icon-eject{background-position:-408px -72px}.icon-chevron-left{background-position:-432px -72px}.icon-chevron-right{background-position:-456px -72px}.icon-plus-sign{background-position:0 -96px}.icon-minus-sign{background-position:-24px -96px}.icon-remove-sign{background-position:-48px -96px}.icon-ok-sign{background-position:-72px -96px}.icon-question-sign{background-position:-96px -96px}.icon-info-sign{background-position:-120px -96px}.icon-screenshot{background-position:-144px -96px}.icon-remove-circle{background-position:-168px -96px}.icon-ok-circle{background-position:-192px -96px}.icon-ban-circle{background-position:-216px -96px}.icon-arrow-left{background-position:-240px -96px}.icon-arrow-right{background-position:-264px -96px}.icon-arrow-up{background-position:-289px -96px}.icon-arrow-down{background-position:-312px -96px}.icon-share-alt{background-position:-336px -96px}.icon-resize-full{background-position:-360px -96px}.icon-resize-small{background-position:-384px -96px}.icon-plus{background-position:-408px -96px}.icon-minus{background-position:-433px -96px}.icon-asterisk{background-position:-456px -96px}.icon-exclamation-sign{background-position:0 -120px}.icon-gift{background-position:-24px -120px}.icon-leaf{background-position:-48px -120px}.icon-fire{background-position:-72px -120px}.icon-eye-open{background-position:-96px -120px}.icon-eye-close{background-position:-120px -120px}.icon-warning-sign{background-position:-144px -120px}.icon-plane{background-position:-168px -120px}.icon-calendar{background-position:-192px -120px}.icon-random{width:16px;background-position:-216px -120px}.icon-comment{background-position:-240px -120px}.icon-magnet{background-position:-264px -120px}.icon-chevron-up{background-position:-288px -120px}.icon-chevron-down{background-position:-313px -119px}.icon-retweet{background-position:-336px -120px}.icon-shopping-cart{background-position:-360px -120px}.icon-folder-close{width:16px;background-position:-384px -120px}.icon-folder-open{width:16px;background-position:-408px -120px}.icon-resize-vertical{background-position:-432px -119px}.icon-resize-horizontal{background-position:-456px -118px}.icon-hdd{background-position:0 -144px}.icon-bullhorn{background-position:-24px -144px}.icon-bell{background-position:-48px -144px}.icon-certificate{background-position:-72px -144px}.icon-thumbs-up{background-position:-96px -144px}.icon-thumbs-down{background-position:-120px -144px}.icon-hand-right{background-position:-144px -144px}.icon-hand-left{background-position:-168px -144px}.icon-hand-up{background-position:-192px -144px}.icon-hand-down{background-position:-216px -144px}.icon-circle-arrow-right{background-position:-240px -144px}.icon-circle-arrow-left{background-position:-264px -144px}.icon-circle-arrow-up{background-position:-288px -144px}.icon-circle-arrow-down{background-position:-312px -144px}.icon-globe{background-position:-336px -144px}.icon-wrench{background-position:-360px -144px}.icon-tasks{background-position:-384px -144px}.icon-filter{background-position:-408px -144px}.icon-briefcase{background-position:-432px -144px}.icon-fullscreen{background-position:-456px -144px}.dropup,.dropdown{position:relative}.dropdown-toggle{*margin-bottom:-3px}.dropdown-toggle:active,.open .dropdown-toggle{outline:0}.caret{display:inline-block;width:0;height:0;vertical-align:top;border-top:4px solid #000;border-right:4px solid transparent;border-left:4px solid transparent;content:""}.dropdown .caret{margin-top:8px;margin-left:2px}.dropdown-menu{position:absolute;top:100%;left:0;z-index:1000;display:none;float:left;min-width:160px;padding:5px 0;margin:2px 0 0;list-style:none;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);*border-right-width:2px;*border-bottom-width:2px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:normal;line-height:20px;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus,.dropdown-submenu:hover>a,.dropdown-submenu:focus>a{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;background-color:#0081c2;background-image:-moz-linear-gradient(top,#08c,#0077b3);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#0077b3));background-image:-webkit-linear-gradient(top,#08c,#0077b3);background-image:-o-linear-gradient(top,#08c,#0077b3);background-image:linear-gradient(to bottom,#08c,#0077b3);background-repeat:repeat-x;outline:0;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0077b3',GradientType=0)}.dropdown-menu>.disabled>a,.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{color:#999}.dropdown-menu>.disabled>a:hover,.dropdown-menu>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.open{*z-index:1000}.open>.dropdown-menu{display:block}.dropdown-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:990}.pull-right>.dropdown-menu{right:0;left:auto}.dropup .caret,.navbar-fixed-bottom .dropdown .caret{border-top:0;border-bottom:4px solid #000;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}.dropdown-submenu{position:relative}.dropdown-submenu>.dropdown-menu{top:0;left:100%;margin-top:-6px;margin-left:-1px;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px}.dropdown-submenu:hover>.dropdown-menu{display:block}.dropup .dropdown-submenu>.dropdown-menu{top:auto;bottom:0;margin-top:0;margin-bottom:-2px;-webkit-border-radius:5px 5px 5px 0;-moz-border-radius:5px 5px 5px 0;border-radius:5px 5px 5px 0}.dropdown-submenu>a:after{display:block;float:right;width:0;height:0;margin-top:5px;margin-right:-10px;border-color:transparent;border-left-color:#ccc;border-style:solid;border-width:5px 0 5px 5px;content:" "}.dropdown-submenu:hover>a:after{border-left-color:#fff}.dropdown-submenu.pull-left{float:none}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.dropdown .dropdown-menu .nav-header{padding-right:20px;padding-left:20px}.typeahead{z-index:1051;margin-top:2px;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 1px rgba(0,0,0,0.05);box-shadow:inset 0 1px 1px rgba(0,0,0,0.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,0.15)}.well-large{padding:24px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.well-small{padding:9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.fade{opacity:0;-webkit-transition:opacity .15s linear;-moz-transition:opacity .15s linear;-o-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;-moz-transition:height .35s ease;-o-transition:height .35s ease;transition:height .35s ease}.collapse.in{height:auto}.close{float:right;font-size:20px;font-weight:bold;line-height:20px;color:#000;text-shadow:0 1px 0 #fff;opacity:.2;filter:alpha(opacity=20)}.close:hover,.close:focus{color:#000;text-decoration:none;cursor:pointer;opacity:.4;filter:alpha(opacity=40)}button.close{padding:0;cursor:pointer;background:transparent;border:0;-webkit-appearance:none}.btn{display:inline-block;*display:inline;padding:4px 12px;margin-bottom:0;*margin-left:.3em;font-size:14px;line-height:20px;color:#333;text-align:center;text-shadow:0 1px 1px rgba(255,255,255,0.75);vertical-align:middle;cursor:pointer;background-color:#f5f5f5;*background-color:#e6e6e6;background-image:-moz-linear-gradient(top,#fff,#e6e6e6);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#e6e6e6));background-image:-webkit-linear-gradient(top,#fff,#e6e6e6);background-image:-o-linear-gradient(top,#fff,#e6e6e6);background-image:linear-gradient(to bottom,#fff,#e6e6e6);background-repeat:repeat-x;border:1px solid #ccc;*border:0;border-color:#e6e6e6 #e6e6e6 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);border-bottom-color:#b3b3b3;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#ffe6e6e6',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);*zoom:1;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn:hover,.btn:focus,.btn:active,.btn.active,.btn.disabled,.btn[disabled]{color:#333;background-color:#e6e6e6;*background-color:#d9d9d9}.btn:active,.btn.active{background-color:#ccc \9}.btn:first-child{*margin-left:0}.btn:hover,.btn:focus{color:#333;text-decoration:none;background-position:0 -15px;-webkit-transition:background-position .1s linear;-moz-transition:background-position .1s linear;-o-transition:background-position .1s linear;transition:background-position .1s linear}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn.active,.btn:active{background-image:none;outline:0;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn.disabled,.btn[disabled]{cursor:default;background-image:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-large{padding:11px 19px;font-size:17.5px;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.btn-large [class^="icon-"],.btn-large [class*=" icon-"]{margin-top:4px}.btn-small{padding:2px 10px;font-size:11.9px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-small [class^="icon-"],.btn-small [class*=" icon-"]{margin-top:0}.btn-mini [class^="icon-"],.btn-mini [class*=" icon-"]{margin-top:-1px}.btn-mini{padding:0 6px;font-size:10.5px;-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.btn-block{display:block;width:100%;padding-right:0;padding-left:0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.btn-block+.btn-block{margin-top:5px}input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%}.btn-primary.active,.btn-warning.active,.btn-danger.active,.btn-success.active,.btn-info.active,.btn-inverse.active{color:rgba(255,255,255,0.75)}.btn-primary{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#006dcc;*background-color:#04c;background-image:-moz-linear-gradient(top,#08c,#04c);background-image:-webkit-gradient(linear,0 0,0 100%,from(#08c),to(#04c));background-image:-webkit-linear-gradient(top,#08c,#04c);background-image:-o-linear-gradient(top,#08c,#04c);background-image:linear-gradient(to bottom,#08c,#04c);background-repeat:repeat-x;border-color:#04c #04c #002a80;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff0088cc',endColorstr='#ff0044cc',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.btn-primary.disabled,.btn-primary[disabled]{color:#fff;background-color:#04c;*background-color:#003bb3}.btn-primary:active,.btn-primary.active{background-color:#039 \9}.btn-warning{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#faa732;*background-color:#f89406;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;border-color:#f89406 #f89406 #ad6704;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.btn-warning.disabled,.btn-warning[disabled]{color:#fff;background-color:#f89406;*background-color:#df8505}.btn-warning:active,.btn-warning.active{background-color:#c67605 \9}.btn-danger{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#da4f49;*background-color:#bd362f;background-image:-moz-linear-gradient(top,#ee5f5b,#bd362f);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#bd362f));background-image:-webkit-linear-gradient(top,#ee5f5b,#bd362f);background-image:-o-linear-gradient(top,#ee5f5b,#bd362f);background-image:linear-gradient(to bottom,#ee5f5b,#bd362f);background-repeat:repeat-x;border-color:#bd362f #bd362f #802420;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffbd362f',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.btn-danger.disabled,.btn-danger[disabled]{color:#fff;background-color:#bd362f;*background-color:#a9302a}.btn-danger:active,.btn-danger.active{background-color:#942a25 \9}.btn-success{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#5bb75b;*background-color:#51a351;background-image:-moz-linear-gradient(top,#62c462,#51a351);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#51a351));background-image:-webkit-linear-gradient(top,#62c462,#51a351);background-image:-o-linear-gradient(top,#62c462,#51a351);background-image:linear-gradient(to bottom,#62c462,#51a351);background-repeat:repeat-x;border-color:#51a351 #51a351 #387038;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff51a351',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.btn-success.disabled,.btn-success[disabled]{color:#fff;background-color:#51a351;*background-color:#499249}.btn-success:active,.btn-success.active{background-color:#408140 \9}.btn-info{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#49afcd;*background-color:#2f96b4;background-image:-moz-linear-gradient(top,#5bc0de,#2f96b4);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#2f96b4));background-image:-webkit-linear-gradient(top,#5bc0de,#2f96b4);background-image:-o-linear-gradient(top,#5bc0de,#2f96b4);background-image:linear-gradient(to bottom,#5bc0de,#2f96b4);background-repeat:repeat-x;border-color:#2f96b4 #2f96b4 #1f6377;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff2f96b4',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.btn-info.disabled,.btn-info[disabled]{color:#fff;background-color:#2f96b4;*background-color:#2a85a0}.btn-info:active,.btn-info.active{background-color:#24748c \9}.btn-inverse{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#363636;*background-color:#222;background-image:-moz-linear-gradient(top,#444,#222);background-image:-webkit-gradient(linear,0 0,0 100%,from(#444),to(#222));background-image:-webkit-linear-gradient(top,#444,#222);background-image:-o-linear-gradient(top,#444,#222);background-image:linear-gradient(to bottom,#444,#222);background-repeat:repeat-x;border-color:#222 #222 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff444444',endColorstr='#ff222222',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.btn-inverse:hover,.btn-inverse:focus,.btn-inverse:active,.btn-inverse.active,.btn-inverse.disabled,.btn-inverse[disabled]{color:#fff;background-color:#222;*background-color:#151515}.btn-inverse:active,.btn-inverse.active{background-color:#080808 \9}button.btn,input[type="submit"].btn{*padding-top:3px;*padding-bottom:3px}button.btn::-moz-focus-inner,input[type="submit"].btn::-moz-focus-inner{padding:0;border:0}button.btn.btn-large,input[type="submit"].btn.btn-large{*padding-top:7px;*padding-bottom:7px}button.btn.btn-small,input[type="submit"].btn.btn-small{*padding-top:3px;*padding-bottom:3px}button.btn.btn-mini,input[type="submit"].btn.btn-mini{*padding-top:1px;*padding-bottom:1px}.btn-link,.btn-link:active,.btn-link[disabled]{background-color:transparent;background-image:none;-webkit-box-shadow:none;-moz-box-shadow:none;box-shadow:none}.btn-link{color:#08c;cursor:pointer;border-color:transparent;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-link:hover,.btn-link:focus{color:#005580;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,.btn-link[disabled]:focus{color:#333;text-decoration:none}.btn-group{position:relative;display:inline-block;*display:inline;*margin-left:.3em;font-size:0;white-space:nowrap;vertical-align:middle;*zoom:1}.btn-group:first-child{*margin-left:0}.btn-group+.btn-group{margin-left:5px}.btn-toolbar{margin-top:10px;margin-bottom:10px;font-size:0}.btn-toolbar>.btn+.btn,.btn-toolbar>.btn-group+.btn,.btn-toolbar>.btn+.btn-group{margin-left:5px}.btn-group>.btn{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group>.btn+.btn{margin-left:-1px}.btn-group>.btn,.btn-group>.dropdown-menu,.btn-group>.popover{font-size:14px}.btn-group>.btn-mini{font-size:10.5px}.btn-group>.btn-small{font-size:11.9px}.btn-group>.btn-large{font-size:17.5px}.btn-group>.btn:first-child{margin-left:0;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.btn-group>.btn:last-child,.btn-group>.dropdown-toggle{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.btn-group>.btn.large:first-child{margin-left:0;-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.btn-group>.btn.large:last-child,.btn-group>.large.dropdown-toggle{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.btn-group>.btn:hover,.btn-group>.btn:focus,.btn-group>.btn:active,.btn-group>.btn.active{z-index:2}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group>.btn+.dropdown-toggle{*padding-top:5px;padding-right:8px;*padding-bottom:5px;padding-left:8px;-webkit-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 1px 0 0 rgba(255,255,255,0.125),inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05)}.btn-group>.btn-mini+.dropdown-toggle{*padding-top:2px;padding-right:5px;*padding-bottom:2px;padding-left:5px}.btn-group>.btn-small+.dropdown-toggle{*padding-top:5px;*padding-bottom:4px}.btn-group>.btn-large+.dropdown-toggle{*padding-top:7px;padding-right:12px;*padding-bottom:7px;padding-left:12px}.btn-group.open .dropdown-toggle{background-image:none;-webkit-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05);box-shadow:inset 0 2px 4px rgba(0,0,0,0.15),0 1px 2px rgba(0,0,0,0.05)}.btn-group.open .btn.dropdown-toggle{background-color:#e6e6e6}.btn-group.open .btn-primary.dropdown-toggle{background-color:#04c}.btn-group.open .btn-warning.dropdown-toggle{background-color:#f89406}.btn-group.open .btn-danger.dropdown-toggle{background-color:#bd362f}.btn-group.open .btn-success.dropdown-toggle{background-color:#51a351}.btn-group.open .btn-info.dropdown-toggle{background-color:#2f96b4}.btn-group.open .btn-inverse.dropdown-toggle{background-color:#222}.btn .caret{margin-top:8px;margin-left:0}.btn-large .caret{margin-top:6px}.btn-large .caret{border-top-width:5px;border-right-width:5px;border-left-width:5px}.btn-mini .caret,.btn-small .caret{margin-top:8px}.dropup .btn-large .caret{border-bottom-width:5px}.btn-primary .caret,.btn-warning .caret,.btn-danger .caret,.btn-info .caret,.btn-success .caret,.btn-inverse .caret{border-top-color:#fff;border-bottom-color:#fff}.btn-group-vertical{display:inline-block;*display:inline;*zoom:1}.btn-group-vertical>.btn{display:block;float:none;max-width:100%;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.btn-group-vertical>.btn+.btn{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:first-child{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.btn-group-vertical>.btn:last-child{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.btn-group-vertical>.btn-large:first-child{-webkit-border-radius:6px 6px 0 0;-moz-border-radius:6px 6px 0 0;border-radius:6px 6px 0 0}.btn-group-vertical>.btn-large:last-child{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.alert{padding:8px 35px 8px 14px;margin-bottom:20px;text-shadow:0 1px 0 rgba(255,255,255,0.5);background-color:#fcf8e3;border:1px solid #fbeed5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.alert,.alert h4{color:#c09853}.alert h4{margin:0}.alert .close{position:relative;top:-2px;right:-21px;line-height:20px}.alert-success{color:#468847;background-color:#dff0d8;border-color:#d6e9c6}.alert-success h4{color:#468847}.alert-danger,.alert-error{color:#b94a48;background-color:#f2dede;border-color:#eed3d7}.alert-danger h4,.alert-error h4{color:#b94a48}.alert-info{color:#3a87ad;background-color:#d9edf7;border-color:#bce8f1}.alert-info h4{color:#3a87ad}.alert-block{padding-top:14px;padding-bottom:14px}.alert-block>p,.alert-block>ul{margin-bottom:0}.alert-block p+p{margin-top:5px}.nav{margin-bottom:20px;margin-left:0;list-style:none}.nav>li>a{display:block}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li>a>img{max-width:none}.nav>.pull-right{float:right}.nav-header{display:block;padding:3px 15px;font-size:11px;font-weight:bold;line-height:20px;color:#999;text-shadow:0 1px 0 rgba(255,255,255,0.5);text-transform:uppercase}.nav li+.nav-header{margin-top:9px}.nav-list{padding-right:15px;padding-left:15px;margin-bottom:0}.nav-list>li>a,.nav-list .nav-header{margin-right:-15px;margin-left:-15px;text-shadow:0 1px 0 rgba(255,255,255,0.5)}.nav-list>li>a{padding:3px 15px}.nav-list>.active>a,.nav-list>.active>a:hover,.nav-list>.active>a:focus{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.2);background-color:#08c}.nav-list [class^="icon-"],.nav-list [class*=" icon-"]{margin-right:2px}.nav-list .divider{*width:100%;height:1px;margin:9px 1px;*margin:-5px 0 5px;overflow:hidden;background-color:#e5e5e5;border-bottom:1px solid #fff}.nav-tabs,.nav-pills{*zoom:1}.nav-tabs:before,.nav-pills:before,.nav-tabs:after,.nav-pills:after{display:table;line-height:0;content:""}.nav-tabs:after,.nav-pills:after{clear:both}.nav-tabs>li,.nav-pills>li{float:left}.nav-tabs>li>a,.nav-pills>li>a{padding-right:12px;padding-left:12px;margin-right:2px;line-height:14px}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{margin-bottom:-1px}.nav-tabs>li>a{padding-top:8px;padding-bottom:8px;line-height:20px;border:1px solid transparent;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover,.nav-tabs>li>a:focus{border-color:#eee #eee #ddd}.nav-tabs>.active>a,.nav-tabs>.active>a:hover,.nav-tabs>.active>a:focus{color:#555;cursor:default;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent}.nav-pills>li>a{padding-top:8px;padding-bottom:8px;margin-top:2px;margin-bottom:2px;-webkit-border-radius:5px;-moz-border-radius:5px;border-radius:5px}.nav-pills>.active>a,.nav-pills>.active>a:hover,.nav-pills>.active>a:focus{color:#fff;background-color:#08c}.nav-stacked>li{float:none}.nav-stacked>li>a{margin-right:0}.nav-tabs.nav-stacked{border-bottom:0}.nav-tabs.nav-stacked>li>a{border:1px solid #ddd;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.nav-tabs.nav-stacked>li:first-child>a{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-topleft:4px}.nav-tabs.nav-stacked>li:last-child>a{-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-moz-border-radius-bottomright:4px;-moz-border-radius-bottomleft:4px}.nav-tabs.nav-stacked>li>a:hover,.nav-tabs.nav-stacked>li>a:focus{z-index:2;border-color:#ddd}.nav-pills.nav-stacked>li>a{margin-bottom:3px}.nav-pills.nav-stacked>li:last-child>a{margin-bottom:1px}.nav-tabs .dropdown-menu{-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px}.nav-pills .dropdown-menu{-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.nav .dropdown-toggle .caret{margin-top:6px;border-top-color:#08c;border-bottom-color:#08c}.nav .dropdown-toggle:hover .caret,.nav .dropdown-toggle:focus .caret{border-top-color:#005580;border-bottom-color:#005580}.nav-tabs .dropdown-toggle .caret{margin-top:8px}.nav .active .dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.nav-tabs .active .dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.nav>.dropdown.active>a:hover,.nav>.dropdown.active>a:focus{cursor:pointer}.nav-tabs .open .dropdown-toggle,.nav-pills .open .dropdown-toggle,.nav>li.dropdown.open.active>a:hover,.nav>li.dropdown.open.active>a:focus{color:#fff;background-color:#999;border-color:#999}.nav li.dropdown.open .caret,.nav li.dropdown.open.active .caret,.nav li.dropdown.open a:hover .caret,.nav li.dropdown.open a:focus .caret{border-top-color:#fff;border-bottom-color:#fff;opacity:1;filter:alpha(opacity=100)}.tabs-stacked .open>a:hover,.tabs-stacked .open>a:focus{border-color:#999}.tabbable{*zoom:1}.tabbable:before,.tabbable:after{display:table;line-height:0;content:""}.tabbable:after{clear:both}.tab-content{overflow:auto}.tabs-below>.nav-tabs,.tabs-right>.nav-tabs,.tabs-left>.nav-tabs{border-bottom:0}.tab-content>.tab-pane,.pill-content>.pill-pane{display:none}.tab-content>.active,.pill-content>.active{display:block}.tabs-below>.nav-tabs{border-top:1px solid #ddd}.tabs-below>.nav-tabs>li{margin-top:-1px;margin-bottom:0}.tabs-below>.nav-tabs>li>a{-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.tabs-below>.nav-tabs>li>a:hover,.tabs-below>.nav-tabs>li>a:focus{border-top-color:#ddd;border-bottom-color:transparent}.tabs-below>.nav-tabs>.active>a,.tabs-below>.nav-tabs>.active>a:hover,.tabs-below>.nav-tabs>.active>a:focus{border-color:transparent #ddd #ddd #ddd}.tabs-left>.nav-tabs>li,.tabs-right>.nav-tabs>li{float:none}.tabs-left>.nav-tabs>li>a,.tabs-right>.nav-tabs>li>a{min-width:74px;margin-right:0;margin-bottom:3px}.tabs-left>.nav-tabs{float:left;margin-right:19px;border-right:1px solid #ddd}.tabs-left>.nav-tabs>li>a{margin-right:-1px;-webkit-border-radius:4px 0 0 4px;-moz-border-radius:4px 0 0 4px;border-radius:4px 0 0 4px}.tabs-left>.nav-tabs>li>a:hover,.tabs-left>.nav-tabs>li>a:focus{border-color:#eee #ddd #eee #eee}.tabs-left>.nav-tabs .active>a,.tabs-left>.nav-tabs .active>a:hover,.tabs-left>.nav-tabs .active>a:focus{border-color:#ddd transparent #ddd #ddd;*border-right-color:#fff}.tabs-right>.nav-tabs{float:right;margin-left:19px;border-left:1px solid #ddd}.tabs-right>.nav-tabs>li>a{margin-left:-1px;-webkit-border-radius:0 4px 4px 0;-moz-border-radius:0 4px 4px 0;border-radius:0 4px 4px 0}.tabs-right>.nav-tabs>li>a:hover,.tabs-right>.nav-tabs>li>a:focus{border-color:#eee #eee #eee #ddd}.tabs-right>.nav-tabs .active>a,.tabs-right>.nav-tabs .active>a:hover,.tabs-right>.nav-tabs .active>a:focus{border-color:#ddd #ddd #ddd transparent;*border-left-color:#fff}.nav>.disabled>a{color:#999}.nav>.disabled>a:hover,.nav>.disabled>a:focus{text-decoration:none;cursor:default;background-color:transparent}.navbar{*position:relative;*z-index:2;margin-bottom:20px;overflow:visible}.navbar-inner{min-height:40px;padding-right:20px;padding-left:20px;background-color:#fafafa;background-image:-moz-linear-gradient(top,#fff,#f2f2f2);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fff),to(#f2f2f2));background-image:-webkit-linear-gradient(top,#fff,#f2f2f2);background-image:-o-linear-gradient(top,#fff,#f2f2f2);background-image:linear-gradient(to bottom,#fff,#f2f2f2);background-repeat:repeat-x;border:1px solid #d4d4d4;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff',endColorstr='#fff2f2f2',GradientType=0);*zoom:1;-webkit-box-shadow:0 1px 4px rgba(0,0,0,0.065);-moz-box-shadow:0 1px 4px rgba(0,0,0,0.065);box-shadow:0 1px 4px rgba(0,0,0,0.065)}.navbar-inner:before,.navbar-inner:after{display:table;line-height:0;content:""}.navbar-inner:after{clear:both}.navbar .container{width:auto}.nav-collapse.collapse{height:auto;overflow:visible}.navbar .brand{display:block;float:left;padding:10px 20px 10px;margin-left:-20px;font-size:20px;font-weight:200;color:#777;text-shadow:0 1px 0 #fff}.navbar .brand:hover,.navbar .brand:focus{text-decoration:none}.navbar-text{margin-bottom:0;line-height:40px;color:#777}.navbar-link{color:#777}.navbar-link:hover,.navbar-link:focus{color:#333}.navbar .divider-vertical{height:40px;margin:0 9px;border-right:1px solid #fff;border-left:1px solid #f2f2f2}.navbar .btn,.navbar .btn-group{margin-top:5px}.navbar .btn-group .btn,.navbar .input-prepend .btn,.navbar .input-append .btn,.navbar .input-prepend .btn-group,.navbar .input-append .btn-group{margin-top:0}.navbar-form{margin-bottom:0;*zoom:1}.navbar-form:before,.navbar-form:after{display:table;line-height:0;content:""}.navbar-form:after{clear:both}.navbar-form input,.navbar-form select,.navbar-form .radio,.navbar-form .checkbox{margin-top:5px}.navbar-form input,.navbar-form select,.navbar-form .btn{display:inline-block;margin-bottom:0}.navbar-form input[type="image"],.navbar-form input[type="checkbox"],.navbar-form input[type="radio"]{margin-top:3px}.navbar-form .input-append,.navbar-form .input-prepend{margin-top:5px;white-space:nowrap}.navbar-form .input-append input,.navbar-form .input-prepend input{margin-top:0}.navbar-search{position:relative;float:left;margin-top:5px;margin-bottom:0}.navbar-search .search-query{padding:4px 14px;margin-bottom:0;font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:13px;font-weight:normal;line-height:1;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.navbar-static-top{position:static;margin-bottom:0}.navbar-static-top .navbar-inner{-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030;margin-bottom:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{border-width:0 0 1px}.navbar-fixed-bottom .navbar-inner{border-width:1px 0 0}.navbar-fixed-top .navbar-inner,.navbar-fixed-bottom .navbar-inner{padding-right:0;padding-left:0;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}.navbar-static-top .container,.navbar-fixed-top .container,.navbar-fixed-bottom .container{width:940px}.navbar-fixed-top{top:0}.navbar-fixed-top .navbar-inner,.navbar-static-top .navbar-inner{-webkit-box-shadow:0 1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 1px 10px rgba(0,0,0,0.1);box-shadow:0 1px 10px rgba(0,0,0,0.1)}.navbar-fixed-bottom{bottom:0}.navbar-fixed-bottom .navbar-inner{-webkit-box-shadow:0 -1px 10px rgba(0,0,0,0.1);-moz-box-shadow:0 -1px 10px rgba(0,0,0,0.1);box-shadow:0 -1px 10px rgba(0,0,0,0.1)}.navbar .nav{position:relative;left:0;display:block;float:left;margin:0 10px 0 0}.navbar .nav.pull-right{float:right;margin-right:0}.navbar .nav>li{float:left}.navbar .nav>li>a{float:none;padding:10px 15px 10px;color:#777;text-decoration:none;text-shadow:0 1px 0 #fff}.navbar .nav .dropdown-toggle .caret{margin-top:8px}.navbar .nav>li>a:focus,.navbar .nav>li>a:hover{color:#333;text-decoration:none;background-color:transparent}.navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus{color:#555;text-decoration:none;background-color:#e5e5e5;-webkit-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);-moz-box-shadow:inset 0 3px 8px rgba(0,0,0,0.125);box-shadow:inset 0 3px 8px rgba(0,0,0,0.125)}.navbar .btn-navbar{display:none;float:right;padding:7px 10px;margin-right:5px;margin-left:5px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#ededed;*background-color:#e5e5e5;background-image:-moz-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f2f2f2),to(#e5e5e5));background-image:-webkit-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:-o-linear-gradient(top,#f2f2f2,#e5e5e5);background-image:linear-gradient(to bottom,#f2f2f2,#e5e5e5);background-repeat:repeat-x;border-color:#e5e5e5 #e5e5e5 #bfbfbf;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2f2f2',endColorstr='#ffe5e5e5',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);-moz-box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075);box-shadow:inset 0 1px 0 rgba(255,255,255,0.1),0 1px 0 rgba(255,255,255,0.075)}.navbar .btn-navbar:hover,.navbar .btn-navbar:focus,.navbar .btn-navbar:active,.navbar .btn-navbar.active,.navbar .btn-navbar.disabled,.navbar .btn-navbar[disabled]{color:#fff;background-color:#e5e5e5;*background-color:#d9d9d9}.navbar .btn-navbar:active,.navbar .btn-navbar.active{background-color:#ccc \9}.navbar .btn-navbar .icon-bar{display:block;width:18px;height:2px;background-color:#f5f5f5;-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,0.25);-moz-box-shadow:0 1px 0 rgba(0,0,0,0.25);box-shadow:0 1px 0 rgba(0,0,0,0.25)}.btn-navbar .icon-bar+.icon-bar{margin-top:3px}.navbar .nav>li>.dropdown-menu:before{position:absolute;top:-7px;left:9px;display:inline-block;border-right:7px solid transparent;border-bottom:7px solid #ccc;border-left:7px solid transparent;border-bottom-color:rgba(0,0,0,0.2);content:''}.navbar .nav>li>.dropdown-menu:after{position:absolute;top:-6px;left:10px;display:inline-block;border-right:6px solid transparent;border-bottom:6px solid #fff;border-left:6px solid transparent;content:''}.navbar-fixed-bottom .nav>li>.dropdown-menu:before{top:auto;bottom:-7px;border-top:7px solid #ccc;border-bottom:0;border-top-color:rgba(0,0,0,0.2)}.navbar-fixed-bottom .nav>li>.dropdown-menu:after{top:auto;bottom:-6px;border-top:6px solid #fff;border-bottom:0}.navbar .nav li.dropdown>a:hover .caret,.navbar .nav li.dropdown>a:focus .caret{border-top-color:#333;border-bottom-color:#333}.navbar .nav li.dropdown.open>.dropdown-toggle,.navbar .nav li.dropdown.active>.dropdown-toggle,.navbar .nav li.dropdown.open.active>.dropdown-toggle{color:#555;background-color:#e5e5e5}.navbar .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#777;border-bottom-color:#777}.navbar .nav li.dropdown.open>.dropdown-toggle .caret,.navbar .nav li.dropdown.active>.dropdown-toggle .caret,.navbar .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#555;border-bottom-color:#555}.navbar .pull-right>li>.dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right{right:0;left:auto}.navbar .pull-right>li>.dropdown-menu:before,.navbar .nav>li>.dropdown-menu.pull-right:before{right:12px;left:auto}.navbar .pull-right>li>.dropdown-menu:after,.navbar .nav>li>.dropdown-menu.pull-right:after{right:13px;left:auto}.navbar .pull-right>li>.dropdown-menu .dropdown-menu,.navbar .nav>li>.dropdown-menu.pull-right .dropdown-menu{right:100%;left:auto;margin-right:-1px;margin-left:0;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px}.navbar-inverse .navbar-inner{background-color:#1b1b1b;background-image:-moz-linear-gradient(top,#222,#111);background-image:-webkit-gradient(linear,0 0,0 100%,from(#222),to(#111));background-image:-webkit-linear-gradient(top,#222,#111);background-image:-o-linear-gradient(top,#222,#111);background-image:linear-gradient(to bottom,#222,#111);background-repeat:repeat-x;border-color:#252525;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222',endColorstr='#ff111111',GradientType=0)}.navbar-inverse .brand,.navbar-inverse .nav>li>a{color:#999;text-shadow:0 -1px 0 rgba(0,0,0,0.25)}.navbar-inverse .brand:hover,.navbar-inverse .nav>li>a:hover,.navbar-inverse .brand:focus,.navbar-inverse .nav>li>a:focus{color:#fff}.navbar-inverse .brand{color:#999}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .nav>li>a:focus,.navbar-inverse .nav>li>a:hover{color:#fff;background-color:transparent}.navbar-inverse .nav .active>a,.navbar-inverse .nav .active>a:hover,.navbar-inverse .nav .active>a:focus{color:#fff;background-color:#111}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover,.navbar-inverse .navbar-link:focus{color:#fff}.navbar-inverse .divider-vertical{border-right-color:#222;border-left-color:#111}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle{color:#fff;background-color:#111}.navbar-inverse .nav li.dropdown>a:hover .caret,.navbar-inverse .nav li.dropdown>a:focus .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .nav li.dropdown>.dropdown-toggle .caret{border-top-color:#999;border-bottom-color:#999}.navbar-inverse .nav li.dropdown.open>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.active>.dropdown-toggle .caret,.navbar-inverse .nav li.dropdown.open.active>.dropdown-toggle .caret{border-top-color:#fff;border-bottom-color:#fff}.navbar-inverse .navbar-search .search-query{color:#fff;background-color:#515151;border-color:#111;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1),0 1px 0 rgba(255,255,255,0.15);-webkit-transition:none;-moz-transition:none;-o-transition:none;transition:none}.navbar-inverse .navbar-search .search-query:-moz-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:-ms-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query::-webkit-input-placeholder{color:#ccc}.navbar-inverse .navbar-search .search-query:focus,.navbar-inverse .navbar-search .search-query.focused{padding:5px 15px;color:#333;text-shadow:0 1px 0 #fff;background-color:#fff;border:0;outline:0;-webkit-box-shadow:0 0 3px rgba(0,0,0,0.15);-moz-box-shadow:0 0 3px rgba(0,0,0,0.15);box-shadow:0 0 3px rgba(0,0,0,0.15)}.navbar-inverse .btn-navbar{color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e0e0e;*background-color:#040404;background-image:-moz-linear-gradient(top,#151515,#040404);background-image:-webkit-gradient(linear,0 0,0 100%,from(#151515),to(#040404));background-image:-webkit-linear-gradient(top,#151515,#040404);background-image:-o-linear-gradient(top,#151515,#040404);background-image:linear-gradient(to bottom,#151515,#040404);background-repeat:repeat-x;border-color:#040404 #040404 #000;border-color:rgba(0,0,0,0.1) rgba(0,0,0,0.1) rgba(0,0,0,0.25);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff151515',endColorstr='#ff040404',GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .btn-navbar:hover,.navbar-inverse .btn-navbar:focus,.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active,.navbar-inverse .btn-navbar.disabled,.navbar-inverse .btn-navbar[disabled]{color:#fff;background-color:#040404;*background-color:#000}.navbar-inverse .btn-navbar:active,.navbar-inverse .btn-navbar.active{background-color:#000 \9}.breadcrumb{padding:8px 15px;margin:0 0 20px;list-style:none;background-color:#f5f5f5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.breadcrumb>li{display:inline-block;*display:inline;text-shadow:0 1px 0 #fff;*zoom:1}.breadcrumb>li>.divider{padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{margin:20px 0}.pagination ul{display:inline-block;*display:inline;margin-bottom:0;margin-left:0;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;*zoom:1;-webkit-box-shadow:0 1px 2px rgba(0,0,0,0.05);-moz-box-shadow:0 1px 2px rgba(0,0,0,0.05);box-shadow:0 1px 2px rgba(0,0,0,0.05)}.pagination ul>li{display:inline}.pagination ul>li>a,.pagination ul>li>span{float:left;padding:4px 12px;line-height:20px;text-decoration:none;background-color:#fff;border:1px solid #ddd;border-left-width:0}.pagination ul>li>a:hover,.pagination ul>li>a:focus,.pagination ul>.active>a,.pagination ul>.active>span{background-color:#f5f5f5}.pagination ul>.active>a,.pagination ul>.active>span{color:#999;cursor:default}.pagination ul>.disabled>span,.pagination ul>.disabled>a,.pagination ul>.disabled>a:hover,.pagination ul>.disabled>a:focus{color:#999;cursor:default;background-color:transparent}.pagination ul>li:first-child>a,.pagination ul>li:first-child>span{border-left-width:1px;-webkit-border-bottom-left-radius:4px;border-bottom-left-radius:4px;-webkit-border-top-left-radius:4px;border-top-left-radius:4px;-moz-border-radius-bottomleft:4px;-moz-border-radius-topleft:4px}.pagination ul>li:last-child>a,.pagination ul>li:last-child>span{-webkit-border-top-right-radius:4px;border-top-right-radius:4px;-webkit-border-bottom-right-radius:4px;border-bottom-right-radius:4px;-moz-border-radius-topright:4px;-moz-border-radius-bottomright:4px}.pagination-centered{text-align:center}.pagination-right{text-align:right}.pagination-large ul>li>a,.pagination-large ul>li>span{padding:11px 19px;font-size:17.5px}.pagination-large ul>li:first-child>a,.pagination-large ul>li:first-child>span{-webkit-border-bottom-left-radius:6px;border-bottom-left-radius:6px;-webkit-border-top-left-radius:6px;border-top-left-radius:6px;-moz-border-radius-bottomleft:6px;-moz-border-radius-topleft:6px}.pagination-large ul>li:last-child>a,.pagination-large ul>li:last-child>span{-webkit-border-top-right-radius:6px;border-top-right-radius:6px;-webkit-border-bottom-right-radius:6px;border-bottom-right-radius:6px;-moz-border-radius-topright:6px;-moz-border-radius-bottomright:6px}.pagination-mini ul>li:first-child>a,.pagination-small ul>li:first-child>a,.pagination-mini ul>li:first-child>span,.pagination-small ul>li:first-child>span{-webkit-border-bottom-left-radius:3px;border-bottom-left-radius:3px;-webkit-border-top-left-radius:3px;border-top-left-radius:3px;-moz-border-radius-bottomleft:3px;-moz-border-radius-topleft:3px}.pagination-mini ul>li:last-child>a,.pagination-small ul>li:last-child>a,.pagination-mini ul>li:last-child>span,.pagination-small ul>li:last-child>span{-webkit-border-top-right-radius:3px;border-top-right-radius:3px;-webkit-border-bottom-right-radius:3px;border-bottom-right-radius:3px;-moz-border-radius-topright:3px;-moz-border-radius-bottomright:3px}.pagination-small ul>li>a,.pagination-small ul>li>span{padding:2px 10px;font-size:11.9px}.pagination-mini ul>li>a,.pagination-mini ul>li>span{padding:0 6px;font-size:10.5px}.pager{margin:20px 0;text-align:center;list-style:none;*zoom:1}.pager:before,.pager:after{display:table;line-height:0;content:""}.pager:after{clear:both}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;-webkit-border-radius:15px;-moz-border-radius:15px;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#f5f5f5}.pager .next>a,.pager .next>span{float:right}.pager .previous>a,.pager .previous>span{float:left}.pager .disabled>a,.pager .disabled>a:hover,.pager .disabled>a:focus,.pager .disabled>span{color:#999;cursor:default;background-color:#fff}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0}.modal-backdrop,.modal-backdrop.fade.in{opacity:.8;filter:alpha(opacity=80)}.modal{position:fixed;top:10%;left:50%;z-index:1050;width:560px;margin-left:-280px;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,0.3);*border:1px solid #999;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;outline:0;-webkit-box-shadow:0 3px 7px rgba(0,0,0,0.3);-moz-box-shadow:0 3px 7px rgba(0,0,0,0.3);box-shadow:0 3px 7px rgba(0,0,0,0.3);-webkit-background-clip:padding-box;-moz-background-clip:padding-box;background-clip:padding-box}.modal.fade{top:-25%;-webkit-transition:opacity .3s linear,top .3s ease-out;-moz-transition:opacity .3s linear,top .3s ease-out;-o-transition:opacity .3s linear,top .3s ease-out;transition:opacity .3s linear,top .3s ease-out}.modal.fade.in{top:10%}.modal-header{padding:9px 15px;border-bottom:1px solid #eee}.modal-header .close{margin-top:2px}.modal-header h3{margin:0;line-height:30px}.modal-body{position:relative;max-height:400px;padding:15px;overflow-y:auto}.modal-form{margin-bottom:0}.modal-footer{padding:14px 15px 15px;margin-bottom:0;text-align:right;background-color:#f5f5f5;border-top:1px solid #ddd;-webkit-border-radius:0 0 6px 6px;-moz-border-radius:0 0 6px 6px;border-radius:0 0 6px 6px;*zoom:1;-webkit-box-shadow:inset 0 1px 0 #fff;-moz-box-shadow:inset 0 1px 0 #fff;box-shadow:inset 0 1px 0 #fff}.modal-footer:before,.modal-footer:after{display:table;line-height:0;content:""}.modal-footer:after{clear:both}.modal-footer .btn+.btn{margin-bottom:0;margin-left:5px}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}.tooltip{position:absolute;z-index:1030;display:block;font-size:11px;line-height:1.4;opacity:0;filter:alpha(opacity=0);visibility:visible}.tooltip.in{opacity:.8;filter:alpha(opacity=80)}.tooltip.top{padding:5px 0;margin-top:-3px}.tooltip.right{padding:0 5px;margin-left:3px}.tooltip.bottom{padding:5px 0;margin-top:3px}.tooltip.left{padding:0 5px;margin-left:-3px}.tooltip-inner{max-width:200px;padding:8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.tooltip-arrow{position:absolute;width:0;height:0;border-color:transparent;border-style:solid}.tooltip.top .tooltip-arrow{bottom:0;left:50%;margin-left:-5px;border-top-color:#000;border-width:5px 5px 0}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-right-color:#000;border-width:5px 5px 5px 0}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-left-color:#000;border-width:5px 0 5px 5px}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-bottom-color:#000;border-width:0 5px 5px}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;max-width:276px;padding:1px;text-align:left;white-space:normal;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.2);-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,0.2);-moz-box-shadow:0 5px 10px rgba(0,0,0,0.2);box-shadow:0 5px 10px rgba(0,0,0,0.2);-webkit-background-clip:padding-box;-moz-background-clip:padding;background-clip:padding-box}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{padding:8px 14px;margin:0;font-size:14px;font-weight:normal;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0}.popover-title:empty{display:none}.popover-content{padding:9px 14px}.popover .arrow,.popover .arrow:after{position:absolute;display:block;width:0;height:0;border-color:transparent;border-style:solid}.popover .arrow{border-width:11px}.popover .arrow:after{border-width:10px;content:""}.popover.top .arrow{bottom:-11px;left:50%;margin-left:-11px;border-top-color:#999;border-top-color:rgba(0,0,0,0.25);border-bottom-width:0}.popover.top .arrow:after{bottom:1px;margin-left:-10px;border-top-color:#fff;border-bottom-width:0}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-right-color:#999;border-right-color:rgba(0,0,0,0.25);border-left-width:0}.popover.right .arrow:after{bottom:-10px;left:1px;border-right-color:#fff;border-left-width:0}.popover.bottom .arrow{top:-11px;left:50%;margin-left:-11px;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,0.25);border-top-width:0}.popover.bottom .arrow:after{top:1px;margin-left:-10px;border-bottom-color:#fff;border-top-width:0}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-left-color:#999;border-left-color:rgba(0,0,0,0.25);border-right-width:0}.popover.left .arrow:after{right:1px;bottom:-10px;border-left-color:#fff;border-right-width:0}.thumbnails{margin-left:-20px;list-style:none;*zoom:1}.thumbnails:before,.thumbnails:after{display:table;line-height:0;content:""}.thumbnails:after{clear:both}.row-fluid .thumbnails{margin-left:0}.thumbnails>li{float:left;margin-bottom:20px;margin-left:20px}.thumbnail{display:block;padding:4px;line-height:20px;border:1px solid #ddd;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.055);-moz-box-shadow:0 1px 3px rgba(0,0,0,0.055);box-shadow:0 1px 3px rgba(0,0,0,0.055);-webkit-transition:all .2s ease-in-out;-moz-transition:all .2s ease-in-out;-o-transition:all .2s ease-in-out;transition:all .2s ease-in-out}a.thumbnail:hover,a.thumbnail:focus{border-color:#08c;-webkit-box-shadow:0 1px 4px rgba(0,105,214,0.25);-moz-box-shadow:0 1px 4px rgba(0,105,214,0.25);box-shadow:0 1px 4px rgba(0,105,214,0.25)}.thumbnail>img{display:block;max-width:100%;margin-right:auto;margin-left:auto}.thumbnail .caption{padding:9px;color:#555}.media,.media-body{overflow:hidden;*overflow:visible;zoom:1}.media,.media .media{margin-top:15px}.media:first-child{margin-top:0}.media-object{display:block}.media-heading{margin:0 0 5px}.media>.pull-left{margin-right:10px}.media>.pull-right{margin-left:10px}.media-list{margin-left:0;list-style:none}.label,.badge{display:inline-block;padding:2px 4px;font-size:11.844px;font-weight:bold;line-height:14px;color:#fff;text-shadow:0 -1px 0 rgba(0,0,0,0.25);white-space:nowrap;vertical-align:baseline;background-color:#999}.label{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.badge{padding-right:9px;padding-left:9px;-webkit-border-radius:9px;-moz-border-radius:9px;border-radius:9px}.label:empty,.badge:empty{display:none}a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}.label-important,.badge-important{background-color:#b94a48}.label-important[href],.badge-important[href]{background-color:#953b39}.label-warning,.badge-warning{background-color:#f89406}.label-warning[href],.badge-warning[href]{background-color:#c67605}.label-success,.badge-success{background-color:#468847}.label-success[href],.badge-success[href]{background-color:#356635}.label-info,.badge-info{background-color:#3a87ad}.label-info[href],.badge-info[href]{background-color:#2d6987}.label-inverse,.badge-inverse{background-color:#333}.label-inverse[href],.badge-inverse[href]{background-color:#1a1a1a}.btn .label,.btn .badge{position:relative;top:-1px}.btn-mini .label,.btn-mini .badge{top:0}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-moz-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-ms-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@-o-keyframes progress-bar-stripes{from{background-position:0 0}to{background-position:40px 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f7f7f7;background-image:-moz-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#f5f5f5),to(#f9f9f9));background-image:-webkit-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:-o-linear-gradient(top,#f5f5f5,#f9f9f9);background-image:linear-gradient(to bottom,#f5f5f5,#f9f9f9);background-repeat:repeat-x;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5',endColorstr='#fff9f9f9',GradientType=0);-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);-moz-box-shadow:inset 0 1px 2px rgba(0,0,0,0.1);box-shadow:inset 0 1px 2px rgba(0,0,0,0.1)}.progress .bar{float:left;width:0;height:100%;font-size:12px;color:#fff;text-align:center;text-shadow:0 -1px 0 rgba(0,0,0,0.25);background-color:#0e90d2;background-image:-moz-linear-gradient(top,#149bdf,#0480be);background-image:-webkit-gradient(linear,0 0,0 100%,from(#149bdf),to(#0480be));background-image:-webkit-linear-gradient(top,#149bdf,#0480be);background-image:-o-linear-gradient(top,#149bdf,#0480be);background-image:linear-gradient(to bottom,#149bdf,#0480be);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff149bdf',endColorstr='#ff0480be',GradientType=0);-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,0.15);-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-transition:width .6s ease;-moz-transition:width .6s ease;-o-transition:width .6s ease;transition:width .6s ease}.progress .bar+.bar{-webkit-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);-moz-box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15);box-shadow:inset 1px 0 0 rgba(0,0,0,0.15),inset 0 -1px 0 rgba(0,0,0,0.15)}.progress-striped .bar{background-color:#149bdf;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);-webkit-background-size:40px 40px;-moz-background-size:40px 40px;-o-background-size:40px 40px;background-size:40px 40px}.progress.active .bar{-webkit-animation:progress-bar-stripes 2s linear infinite;-moz-animation:progress-bar-stripes 2s linear infinite;-ms-animation:progress-bar-stripes 2s linear infinite;-o-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-danger .bar,.progress .bar-danger{background-color:#dd514c;background-image:-moz-linear-gradient(top,#ee5f5b,#c43c35);background-image:-webkit-gradient(linear,0 0,0 100%,from(#ee5f5b),to(#c43c35));background-image:-webkit-linear-gradient(top,#ee5f5b,#c43c35);background-image:-o-linear-gradient(top,#ee5f5b,#c43c35);background-image:linear-gradient(to bottom,#ee5f5b,#c43c35);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffee5f5b',endColorstr='#ffc43c35',GradientType=0)}.progress-danger.progress-striped .bar,.progress-striped .bar-danger{background-color:#ee5f5b;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-success .bar,.progress .bar-success{background-color:#5eb95e;background-image:-moz-linear-gradient(top,#62c462,#57a957);background-image:-webkit-gradient(linear,0 0,0 100%,from(#62c462),to(#57a957));background-image:-webkit-linear-gradient(top,#62c462,#57a957);background-image:-o-linear-gradient(top,#62c462,#57a957);background-image:linear-gradient(to bottom,#62c462,#57a957);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff62c462',endColorstr='#ff57a957',GradientType=0)}.progress-success.progress-striped .bar,.progress-striped .bar-success{background-color:#62c462;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-info .bar,.progress .bar-info{background-color:#4bb1cf;background-image:-moz-linear-gradient(top,#5bc0de,#339bb9);background-image:-webkit-gradient(linear,0 0,0 100%,from(#5bc0de),to(#339bb9));background-image:-webkit-linear-gradient(top,#5bc0de,#339bb9);background-image:-o-linear-gradient(top,#5bc0de,#339bb9);background-image:linear-gradient(to bottom,#5bc0de,#339bb9);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de',endColorstr='#ff339bb9',GradientType=0)}.progress-info.progress-striped .bar,.progress-striped .bar-info{background-color:#5bc0de;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.progress-warning .bar,.progress .bar-warning{background-color:#faa732;background-image:-moz-linear-gradient(top,#fbb450,#f89406);background-image:-webkit-gradient(linear,0 0,0 100%,from(#fbb450),to(#f89406));background-image:-webkit-linear-gradient(top,#fbb450,#f89406);background-image:-o-linear-gradient(top,#fbb450,#f89406);background-image:linear-gradient(to bottom,#fbb450,#f89406);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffbb450',endColorstr='#fff89406',GradientType=0)}.progress-warning.progress-striped .bar,.progress-striped .bar-warning{background-color:#fbb450;background-image:-webkit-gradient(linear,0 100%,100% 0,color-stop(0.25,rgba(255,255,255,0.15)),color-stop(0.25,transparent),color-stop(0.5,transparent),color-stop(0.5,rgba(255,255,255,0.15)),color-stop(0.75,rgba(255,255,255,0.15)),color-stop(0.75,transparent),to(transparent));background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-moz-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:-o-linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,0.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,0.15) 50%,rgba(255,255,255,0.15) 75%,transparent 75%,transparent)}.accordion{margin-bottom:20px}.accordion-group{margin-bottom:2px;border:1px solid #e5e5e5;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.accordion-heading{border-bottom:0}.accordion-heading .accordion-toggle{display:block;padding:8px 15px}.accordion-toggle{cursor:pointer}.accordion-inner{padding:9px 15px;border-top:1px solid #e5e5e5}.carousel{position:relative;margin-bottom:20px;line-height:1}.carousel-inner{position:relative;width:100%;overflow:hidden}.carousel-inner>.item{position:relative;display:none;-webkit-transition:.6s ease-in-out left;-moz-transition:.6s ease-in-out left;-o-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;line-height:1}.carousel-inner>.active,.carousel-inner>.next,.carousel-inner>.prev{display:block}.carousel-inner>.active{left:0}.carousel-inner>.next,.carousel-inner>.prev{position:absolute;top:0;width:100%}.carousel-inner>.next{left:100%}.carousel-inner>.prev{left:-100%}.carousel-inner>.next.left,.carousel-inner>.prev.right{left:0}.carousel-inner>.active.left{left:-100%}.carousel-inner>.active.right{left:100%}.carousel-control{position:absolute;top:40%;left:15px;width:40px;height:40px;margin-top:-20px;font-size:60px;font-weight:100;line-height:30px;color:#fff;text-align:center;background:#222;border:3px solid #fff;-webkit-border-radius:23px;-moz-border-radius:23px;border-radius:23px;opacity:.5;filter:alpha(opacity=50)}.carousel-control.right{right:15px;left:auto}.carousel-control:hover,.carousel-control:focus{color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-indicators{position:absolute;top:15px;right:15px;z-index:5;margin:0;list-style:none}.carousel-indicators li{display:block;float:left;width:10px;height:10px;margin-left:5px;text-indent:-999px;background-color:#ccc;background-color:rgba(255,255,255,0.25);border-radius:5px}.carousel-indicators .active{background-color:#fff}.carousel-caption{position:absolute;right:0;bottom:0;left:0;padding:15px;background:#333;background:rgba(0,0,0,0.75)}.carousel-caption h4,.carousel-caption p{line-height:20px;color:#fff}.carousel-caption h4{margin:0 0 5px}.carousel-caption p{margin-bottom:0}.hero-unit{padding:60px;margin-bottom:30px;font-size:18px;font-weight:200;line-height:30px;color:inherit;background-color:#eee;-webkit-border-radius:6px;-moz-border-radius:6px;border-radius:6px}.hero-unit h1{margin-bottom:0;font-size:60px;line-height:1;letter-spacing:-1px;color:inherit}.hero-unit li{line-height:30px}.pull-right{float:right}.pull-left{float:left}.hide{display:none}.show{display:block}.invisible{visibility:hidden}.affix{position:fixed} diff --git a/dgbuilder/public/bootstrap/img/glyphicons-halflings-white.png b/dgbuilder/public/bootstrap/img/glyphicons-halflings-white.png Binary files differnew file mode 100644 index 00000000..3bf6484a --- /dev/null +++ b/dgbuilder/public/bootstrap/img/glyphicons-halflings-white.png diff --git a/dgbuilder/public/bootstrap/img/glyphicons-halflings.png b/dgbuilder/public/bootstrap/img/glyphicons-halflings.png Binary files differnew file mode 100644 index 00000000..a9969993 --- /dev/null +++ b/dgbuilder/public/bootstrap/img/glyphicons-halflings.png diff --git a/dgbuilder/public/bootstrap/js/bootstrap.min.js b/dgbuilder/public/bootstrap/js/bootstrap.min.js new file mode 100644 index 00000000..848258d3 --- /dev/null +++ b/dgbuilder/public/bootstrap/js/bootstrap.min.js @@ -0,0 +1,6 @@ +/*! +* Bootstrap.js by @fat & @mdo +* Copyright 2013 Twitter, Inc. +* http://www.apache.org/licenses/LICENSE-2.0.txt +*/ +!function(e){"use strict";e(function(){e.support.transition=function(){var e=function(){var e=document.createElement("bootstrap"),t={WebkitTransition:"webkitTransitionEnd",MozTransition:"transitionend",OTransition:"oTransitionEnd otransitionend",transition:"transitionend"},n;for(n in t)if(e.style[n]!==undefined)return t[n]}();return e&&{end:e}}()})}(window.jQuery),!function(e){"use strict";var t='[data-dismiss="alert"]',n=function(n){e(n).on("click",t,this.close)};n.prototype.close=function(t){function s(){i.trigger("closed").remove()}var n=e(this),r=n.attr("data-target"),i;r||(r=n.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,"")),i=e(r),t&&t.preventDefault(),i.length||(i=n.hasClass("alert")?n:n.parent()),i.trigger(t=e.Event("close"));if(t.isDefaultPrevented())return;i.removeClass("in"),e.support.transition&&i.hasClass("fade")?i.on(e.support.transition.end,s):s()};var r=e.fn.alert;e.fn.alert=function(t){return this.each(function(){var r=e(this),i=r.data("alert");i||r.data("alert",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.alert.Constructor=n,e.fn.alert.noConflict=function(){return e.fn.alert=r,this},e(document).on("click.alert.data-api",t,n.prototype.close)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.button.defaults,n)};t.prototype.setState=function(e){var t="disabled",n=this.$element,r=n.data(),i=n.is("input")?"val":"html";e+="Text",r.resetText||n.data("resetText",n[i]()),n[i](r[e]||this.options[e]),setTimeout(function(){e=="loadingText"?n.addClass(t).attr(t,t):n.removeClass(t).removeAttr(t)},0)},t.prototype.toggle=function(){var e=this.$element.closest('[data-toggle="buttons-radio"]');e&&e.find(".active").removeClass("active"),this.$element.toggleClass("active")};var n=e.fn.button;e.fn.button=function(n){return this.each(function(){var r=e(this),i=r.data("button"),s=typeof n=="object"&&n;i||r.data("button",i=new t(this,s)),n=="toggle"?i.toggle():n&&i.setState(n)})},e.fn.button.defaults={loadingText:"loading..."},e.fn.button.Constructor=t,e.fn.button.noConflict=function(){return e.fn.button=n,this},e(document).on("click.button.data-api","[data-toggle^=button]",function(t){var n=e(t.target);n.hasClass("btn")||(n=n.closest(".btn")),n.button("toggle")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.$indicators=this.$element.find(".carousel-indicators"),this.options=n,this.options.pause=="hover"&&this.$element.on("mouseenter",e.proxy(this.pause,this)).on("mouseleave",e.proxy(this.cycle,this))};t.prototype={cycle:function(t){return t||(this.paused=!1),this.interval&&clearInterval(this.interval),this.options.interval&&!this.paused&&(this.interval=setInterval(e.proxy(this.next,this),this.options.interval)),this},getActiveIndex:function(){return this.$active=this.$element.find(".item.active"),this.$items=this.$active.parent().children(),this.$items.index(this.$active)},to:function(t){var n=this.getActiveIndex(),r=this;if(t>this.$items.length-1||t<0)return;return this.sliding?this.$element.one("slid",function(){r.to(t)}):n==t?this.pause().cycle():this.slide(t>n?"next":"prev",e(this.$items[t]))},pause:function(t){return t||(this.paused=!0),this.$element.find(".next, .prev").length&&e.support.transition.end&&(this.$element.trigger(e.support.transition.end),this.cycle(!0)),clearInterval(this.interval),this.interval=null,this},next:function(){if(this.sliding)return;return this.slide("next")},prev:function(){if(this.sliding)return;return this.slide("prev")},slide:function(t,n){var r=this.$element.find(".item.active"),i=n||r[t](),s=this.interval,o=t=="next"?"left":"right",u=t=="next"?"first":"last",a=this,f;this.sliding=!0,s&&this.pause(),i=i.length?i:this.$element.find(".item")[u](),f=e.Event("slide",{relatedTarget:i[0],direction:o});if(i.hasClass("active"))return;this.$indicators.length&&(this.$indicators.find(".active").removeClass("active"),this.$element.one("slid",function(){var t=e(a.$indicators.children()[a.getActiveIndex()]);t&&t.addClass("active")}));if(e.support.transition&&this.$element.hasClass("slide")){this.$element.trigger(f);if(f.isDefaultPrevented())return;i.addClass(t),i[0].offsetWidth,r.addClass(o),i.addClass(o),this.$element.one(e.support.transition.end,function(){i.removeClass([t,o].join(" ")).addClass("active"),r.removeClass(["active",o].join(" ")),a.sliding=!1,setTimeout(function(){a.$element.trigger("slid")},0)})}else{this.$element.trigger(f);if(f.isDefaultPrevented())return;r.removeClass("active"),i.addClass("active"),this.sliding=!1,this.$element.trigger("slid")}return s&&this.cycle(),this}};var n=e.fn.carousel;e.fn.carousel=function(n){return this.each(function(){var r=e(this),i=r.data("carousel"),s=e.extend({},e.fn.carousel.defaults,typeof n=="object"&&n),o=typeof n=="string"?n:s.slide;i||r.data("carousel",i=new t(this,s)),typeof n=="number"?i.to(n):o?i[o]():s.interval&&i.pause().cycle()})},e.fn.carousel.defaults={interval:5e3,pause:"hover"},e.fn.carousel.Constructor=t,e.fn.carousel.noConflict=function(){return e.fn.carousel=n,this},e(document).on("click.carousel.data-api","[data-slide], [data-slide-to]",function(t){var n=e(this),r,i=e(n.attr("data-target")||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,"")),s=e.extend({},i.data(),n.data()),o;i.carousel(s),(o=n.attr("data-slide-to"))&&i.data("carousel").pause().to(o).cycle(),t.preventDefault()})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.collapse.defaults,n),this.options.parent&&(this.$parent=e(this.options.parent)),this.options.toggle&&this.toggle()};t.prototype={constructor:t,dimension:function(){var e=this.$element.hasClass("width");return e?"width":"height"},show:function(){var t,n,r,i;if(this.transitioning||this.$element.hasClass("in"))return;t=this.dimension(),n=e.camelCase(["scroll",t].join("-")),r=this.$parent&&this.$parent.find("> .accordion-group > .in");if(r&&r.length){i=r.data("collapse");if(i&&i.transitioning)return;r.collapse("hide"),i||r.data("collapse",null)}this.$element[t](0),this.transition("addClass",e.Event("show"),"shown"),e.support.transition&&this.$element[t](this.$element[0][n])},hide:function(){var t;if(this.transitioning||!this.$element.hasClass("in"))return;t=this.dimension(),this.reset(this.$element[t]()),this.transition("removeClass",e.Event("hide"),"hidden"),this.$element[t](0)},reset:function(e){var t=this.dimension();return this.$element.removeClass("collapse")[t](e||"auto")[0].offsetWidth,this.$element[e!==null?"addClass":"removeClass"]("collapse"),this},transition:function(t,n,r){var i=this,s=function(){n.type=="show"&&i.reset(),i.transitioning=0,i.$element.trigger(r)};this.$element.trigger(n);if(n.isDefaultPrevented())return;this.transitioning=1,this.$element[t]("in"),e.support.transition&&this.$element.hasClass("collapse")?this.$element.one(e.support.transition.end,s):s()},toggle:function(){this[this.$element.hasClass("in")?"hide":"show"]()}};var n=e.fn.collapse;e.fn.collapse=function(n){return this.each(function(){var r=e(this),i=r.data("collapse"),s=e.extend({},e.fn.collapse.defaults,r.data(),typeof n=="object"&&n);i||r.data("collapse",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.collapse.defaults={toggle:!0},e.fn.collapse.Constructor=t,e.fn.collapse.noConflict=function(){return e.fn.collapse=n,this},e(document).on("click.collapse.data-api","[data-toggle=collapse]",function(t){var n=e(this),r,i=n.attr("data-target")||t.preventDefault()||(r=n.attr("href"))&&r.replace(/.*(?=#[^\s]+$)/,""),s=e(i).data("collapse")?"toggle":n.data();n[e(i).hasClass("in")?"addClass":"removeClass"]("collapsed"),e(i).collapse(s)})}(window.jQuery),!function(e){"use strict";function r(){e(".dropdown-backdrop").remove(),e(t).each(function(){i(e(this)).removeClass("open")})}function i(t){var n=t.attr("data-target"),r;n||(n=t.attr("href"),n=n&&/#/.test(n)&&n.replace(/.*(?=#[^\s]*$)/,"")),r=n&&e(n);if(!r||!r.length)r=t.parent();return r}var t="[data-toggle=dropdown]",n=function(t){var n=e(t).on("click.dropdown.data-api",this.toggle);e("html").on("click.dropdown.data-api",function(){n.parent().removeClass("open")})};n.prototype={constructor:n,toggle:function(t){var n=e(this),s,o;if(n.is(".disabled, :disabled"))return;return s=i(n),o=s.hasClass("open"),r(),o||("ontouchstart"in document.documentElement&&e('<div class="dropdown-backdrop"/>').insertBefore(e(this)).on("click",r),s.toggleClass("open")),n.focus(),!1},keydown:function(n){var r,s,o,u,a,f;if(!/(38|40|27)/.test(n.keyCode))return;r=e(this),n.preventDefault(),n.stopPropagation();if(r.is(".disabled, :disabled"))return;u=i(r),a=u.hasClass("open");if(!a||a&&n.keyCode==27)return n.which==27&&u.find(t).focus(),r.click();s=e("[role=menu] li:not(.divider):visible a",u);if(!s.length)return;f=s.index(s.filter(":focus")),n.keyCode==38&&f>0&&f--,n.keyCode==40&&f<s.length-1&&f++,~f||(f=0),s.eq(f).focus()}};var s=e.fn.dropdown;e.fn.dropdown=function(t){return this.each(function(){var r=e(this),i=r.data("dropdown");i||r.data("dropdown",i=new n(this)),typeof t=="string"&&i[t].call(r)})},e.fn.dropdown.Constructor=n,e.fn.dropdown.noConflict=function(){return e.fn.dropdown=s,this},e(document).on("click.dropdown.data-api",r).on("click.dropdown.data-api",".dropdown form",function(e){e.stopPropagation()}).on("click.dropdown.data-api",t,n.prototype.toggle).on("keydown.dropdown.data-api",t+", [role=menu]",n.prototype.keydown)}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=n,this.$element=e(t).delegate('[data-dismiss="modal"]',"click.dismiss.modal",e.proxy(this.hide,this)),this.options.remote&&this.$element.find(".modal-body").load(this.options.remote)};t.prototype={constructor:t,toggle:function(){return this[this.isShown?"hide":"show"]()},show:function(){var t=this,n=e.Event("show");this.$element.trigger(n);if(this.isShown||n.isDefaultPrevented())return;this.isShown=!0,this.escape(),this.backdrop(function(){var n=e.support.transition&&t.$element.hasClass("fade");t.$element.parent().length||t.$element.appendTo(document.body),t.$element.show(),n&&t.$element[0].offsetWidth,t.$element.addClass("in").attr("aria-hidden",!1),t.enforceFocus(),n?t.$element.one(e.support.transition.end,function(){t.$element.focus().trigger("shown")}):t.$element.focus().trigger("shown")})},hide:function(t){t&&t.preventDefault();var n=this;t=e.Event("hide"),this.$element.trigger(t);if(!this.isShown||t.isDefaultPrevented())return;this.isShown=!1,this.escape(),e(document).off("focusin.modal"),this.$element.removeClass("in").attr("aria-hidden",!0),e.support.transition&&this.$element.hasClass("fade")?this.hideWithTransition():this.hideModal()},enforceFocus:function(){var t=this;e(document).on("focusin.modal",function(e){t.$element[0]!==e.target&&!t.$element.has(e.target).length&&t.$element.focus()})},escape:function(){var e=this;this.isShown&&this.options.keyboard?this.$element.on("keyup.dismiss.modal",function(t){t.which==27&&e.hide()}):this.isShown||this.$element.off("keyup.dismiss.modal")},hideWithTransition:function(){var t=this,n=setTimeout(function(){t.$element.off(e.support.transition.end),t.hideModal()},500);this.$element.one(e.support.transition.end,function(){clearTimeout(n),t.hideModal()})},hideModal:function(){var e=this;this.$element.hide(),this.backdrop(function(){e.removeBackdrop(),e.$element.trigger("hidden")})},removeBackdrop:function(){this.$backdrop&&this.$backdrop.remove(),this.$backdrop=null},backdrop:function(t){var n=this,r=this.$element.hasClass("fade")?"fade":"";if(this.isShown&&this.options.backdrop){var i=e.support.transition&&r;this.$backdrop=e('<div class="modal-backdrop '+r+'" />').appendTo(document.body),this.$backdrop.click(this.options.backdrop=="static"?e.proxy(this.$element[0].focus,this.$element[0]):e.proxy(this.hide,this)),i&&this.$backdrop[0].offsetWidth,this.$backdrop.addClass("in");if(!t)return;i?this.$backdrop.one(e.support.transition.end,t):t()}else!this.isShown&&this.$backdrop?(this.$backdrop.removeClass("in"),e.support.transition&&this.$element.hasClass("fade")?this.$backdrop.one(e.support.transition.end,t):t()):t&&t()}};var n=e.fn.modal;e.fn.modal=function(n){return this.each(function(){var r=e(this),i=r.data("modal"),s=e.extend({},e.fn.modal.defaults,r.data(),typeof n=="object"&&n);i||r.data("modal",i=new t(this,s)),typeof n=="string"?i[n]():s.show&&i.show()})},e.fn.modal.defaults={backdrop:!0,keyboard:!0,show:!0},e.fn.modal.Constructor=t,e.fn.modal.noConflict=function(){return e.fn.modal=n,this},e(document).on("click.modal.data-api",'[data-toggle="modal"]',function(t){var n=e(this),r=n.attr("href"),i=e(n.attr("data-target")||r&&r.replace(/.*(?=#[^\s]+$)/,"")),s=i.data("modal")?"toggle":e.extend({remote:!/#/.test(r)&&r},i.data(),n.data());t.preventDefault(),i.modal(s).one("hide",function(){n.focus()})})}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("tooltip",e,t)};t.prototype={constructor:t,init:function(t,n,r){var i,s,o,u,a;this.type=t,this.$element=e(n),this.options=this.getOptions(r),this.enabled=!0,o=this.options.trigger.split(" ");for(a=o.length;a--;)u=o[a],u=="click"?this.$element.on("click."+this.type,this.options.selector,e.proxy(this.toggle,this)):u!="manual"&&(i=u=="hover"?"mouseenter":"focus",s=u=="hover"?"mouseleave":"blur",this.$element.on(i+"."+this.type,this.options.selector,e.proxy(this.enter,this)),this.$element.on(s+"."+this.type,this.options.selector,e.proxy(this.leave,this)));this.options.selector?this._options=e.extend({},this.options,{trigger:"manual",selector:""}):this.fixTitle()},getOptions:function(t){return t=e.extend({},e.fn[this.type].defaults,this.$element.data(),t),t.delay&&typeof t.delay=="number"&&(t.delay={show:t.delay,hide:t.delay}),t},enter:function(t){var n=e.fn[this.type].defaults,r={},i;this._options&&e.each(this._options,function(e,t){n[e]!=t&&(r[e]=t)},this),i=e(t.currentTarget)[this.type](r).data(this.type);if(!i.options.delay||!i.options.delay.show)return i.show();clearTimeout(this.timeout),i.hoverState="in",this.timeout=setTimeout(function(){i.hoverState=="in"&&i.show()},i.options.delay.show)},leave:function(t){var n=e(t.currentTarget)[this.type](this._options).data(this.type);this.timeout&&clearTimeout(this.timeout);if(!n.options.delay||!n.options.delay.hide)return n.hide();n.hoverState="out",this.timeout=setTimeout(function(){n.hoverState=="out"&&n.hide()},n.options.delay.hide)},show:function(){var t,n,r,i,s,o,u=e.Event("show");if(this.hasContent()&&this.enabled){this.$element.trigger(u);if(u.isDefaultPrevented())return;t=this.tip(),this.setContent(),this.options.animation&&t.addClass("fade"),s=typeof this.options.placement=="function"?this.options.placement.call(this,t[0],this.$element[0]):this.options.placement,t.detach().css({top:0,left:0,display:"block"}),this.options.container?t.appendTo(this.options.container):t.insertAfter(this.$element),n=this.getPosition(),r=t[0].offsetWidth,i=t[0].offsetHeight;switch(s){case"bottom":o={top:n.top+n.height,left:n.left+n.width/2-r/2};break;case"top":o={top:n.top-i,left:n.left+n.width/2-r/2};break;case"left":o={top:n.top+n.height/2-i/2,left:n.left-r};break;case"right":o={top:n.top+n.height/2-i/2,left:n.left+n.width}}this.applyPlacement(o,s),this.$element.trigger("shown")}},applyPlacement:function(e,t){var n=this.tip(),r=n[0].offsetWidth,i=n[0].offsetHeight,s,o,u,a;n.offset(e).addClass(t).addClass("in"),s=n[0].offsetWidth,o=n[0].offsetHeight,t=="top"&&o!=i&&(e.top=e.top+i-o,a=!0),t=="bottom"||t=="top"?(u=0,e.left<0&&(u=e.left*-2,e.left=0,n.offset(e),s=n[0].offsetWidth,o=n[0].offsetHeight),this.replaceArrow(u-r+s,s,"left")):this.replaceArrow(o-i,o,"top"),a&&n.offset(e)},replaceArrow:function(e,t,n){this.arrow().css(n,e?50*(1-e/t)+"%":"")},setContent:function(){var e=this.tip(),t=this.getTitle();e.find(".tooltip-inner")[this.options.html?"html":"text"](t),e.removeClass("fade in top bottom left right")},hide:function(){function i(){var t=setTimeout(function(){n.off(e.support.transition.end).detach()},500);n.one(e.support.transition.end,function(){clearTimeout(t),n.detach()})}var t=this,n=this.tip(),r=e.Event("hide");this.$element.trigger(r);if(r.isDefaultPrevented())return;return n.removeClass("in"),e.support.transition&&this.$tip.hasClass("fade")?i():n.detach(),this.$element.trigger("hidden"),this},fixTitle:function(){var e=this.$element;(e.attr("title")||typeof e.attr("data-original-title")!="string")&&e.attr("data-original-title",e.attr("title")||"").attr("title","")},hasContent:function(){return this.getTitle()},getPosition:function(){var t=this.$element[0];return e.extend({},typeof t.getBoundingClientRect=="function"?t.getBoundingClientRect():{width:t.offsetWidth,height:t.offsetHeight},this.$element.offset())},getTitle:function(){var e,t=this.$element,n=this.options;return e=t.attr("data-original-title")||(typeof n.title=="function"?n.title.call(t[0]):n.title),e},tip:function(){return this.$tip=this.$tip||e(this.options.template)},arrow:function(){return this.$arrow=this.$arrow||this.tip().find(".tooltip-arrow")},validate:function(){this.$element[0].parentNode||(this.hide(),this.$element=null,this.options=null)},enable:function(){this.enabled=!0},disable:function(){this.enabled=!1},toggleEnabled:function(){this.enabled=!this.enabled},toggle:function(t){var n=t?e(t.currentTarget)[this.type](this._options).data(this.type):this;n.tip().hasClass("in")?n.hide():n.show()},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}};var n=e.fn.tooltip;e.fn.tooltip=function(n){return this.each(function(){var r=e(this),i=r.data("tooltip"),s=typeof n=="object"&&n;i||r.data("tooltip",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.tooltip.Constructor=t,e.fn.tooltip.defaults={animation:!0,placement:"top",selector:!1,template:'<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',trigger:"hover focus",title:"",delay:0,html:!1,container:!1},e.fn.tooltip.noConflict=function(){return e.fn.tooltip=n,this}}(window.jQuery),!function(e){"use strict";var t=function(e,t){this.init("popover",e,t)};t.prototype=e.extend({},e.fn.tooltip.Constructor.prototype,{constructor:t,setContent:function(){var e=this.tip(),t=this.getTitle(),n=this.getContent();e.find(".popover-title")[this.options.html?"html":"text"](t),e.find(".popover-content")[this.options.html?"html":"text"](n),e.removeClass("fade top bottom left right in")},hasContent:function(){return this.getTitle()||this.getContent()},getContent:function(){var e,t=this.$element,n=this.options;return e=(typeof n.content=="function"?n.content.call(t[0]):n.content)||t.attr("data-content"),e},tip:function(){return this.$tip||(this.$tip=e(this.options.template)),this.$tip},destroy:function(){this.hide().$element.off("."+this.type).removeData(this.type)}});var n=e.fn.popover;e.fn.popover=function(n){return this.each(function(){var r=e(this),i=r.data("popover"),s=typeof n=="object"&&n;i||r.data("popover",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.popover.Constructor=t,e.fn.popover.defaults=e.extend({},e.fn.tooltip.defaults,{placement:"right",trigger:"click",content:"",template:'<div class="popover"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'}),e.fn.popover.noConflict=function(){return e.fn.popover=n,this}}(window.jQuery),!function(e){"use strict";function t(t,n){var r=e.proxy(this.process,this),i=e(t).is("body")?e(window):e(t),s;this.options=e.extend({},e.fn.scrollspy.defaults,n),this.$scrollElement=i.on("scroll.scroll-spy.data-api",r),this.selector=(this.options.target||(s=e(t).attr("href"))&&s.replace(/.*(?=#[^\s]+$)/,"")||"")+" .nav li > a",this.$body=e("body"),this.refresh(),this.process()}t.prototype={constructor:t,refresh:function(){var t=this,n;this.offsets=e([]),this.targets=e([]),n=this.$body.find(this.selector).map(function(){var n=e(this),r=n.data("target")||n.attr("href"),i=/^#\w/.test(r)&&e(r);return i&&i.length&&[[i.position().top+(!e.isWindow(t.$scrollElement.get(0))&&t.$scrollElement.scrollTop()),r]]||null}).sort(function(e,t){return e[0]-t[0]}).each(function(){t.offsets.push(this[0]),t.targets.push(this[1])})},process:function(){var e=this.$scrollElement.scrollTop()+this.options.offset,t=this.$scrollElement[0].scrollHeight||this.$body[0].scrollHeight,n=t-this.$scrollElement.height(),r=this.offsets,i=this.targets,s=this.activeTarget,o;if(e>=n)return s!=(o=i.last()[0])&&this.activate(o);for(o=r.length;o--;)s!=i[o]&&e>=r[o]&&(!r[o+1]||e<=r[o+1])&&this.activate(i[o])},activate:function(t){var n,r;this.activeTarget=t,e(this.selector).parent(".active").removeClass("active"),r=this.selector+'[data-target="'+t+'"],'+this.selector+'[href="'+t+'"]',n=e(r).parent("li").addClass("active"),n.parent(".dropdown-menu").length&&(n=n.closest("li.dropdown").addClass("active")),n.trigger("activate")}};var n=e.fn.scrollspy;e.fn.scrollspy=function(n){return this.each(function(){var r=e(this),i=r.data("scrollspy"),s=typeof n=="object"&&n;i||r.data("scrollspy",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.scrollspy.Constructor=t,e.fn.scrollspy.defaults={offset:10},e.fn.scrollspy.noConflict=function(){return e.fn.scrollspy=n,this},e(window).on("load",function(){e('[data-spy="scroll"]').each(function(){var t=e(this);t.scrollspy(t.data())})})}(window.jQuery),!function(e){"use strict";var t=function(t){this.element=e(t)};t.prototype={constructor:t,show:function(){var t=this.element,n=t.closest("ul:not(.dropdown-menu)"),r=t.attr("data-target"),i,s,o;r||(r=t.attr("href"),r=r&&r.replace(/.*(?=#[^\s]*$)/,""));if(t.parent("li").hasClass("active"))return;i=n.find(".active:last a")[0],o=e.Event("show",{relatedTarget:i}),t.trigger(o);if(o.isDefaultPrevented())return;s=e(r),this.activate(t.parent("li"),n),this.activate(s,s.parent(),function(){t.trigger({type:"shown",relatedTarget:i})})},activate:function(t,n,r){function o(){i.removeClass("active").find("> .dropdown-menu > .active").removeClass("active"),t.addClass("active"),s?(t[0].offsetWidth,t.addClass("in")):t.removeClass("fade"),t.parent(".dropdown-menu")&&t.closest("li.dropdown").addClass("active"),r&&r()}var i=n.find("> .active"),s=r&&e.support.transition&&i.hasClass("fade");s?i.one(e.support.transition.end,o):o(),i.removeClass("in")}};var n=e.fn.tab;e.fn.tab=function(n){return this.each(function(){var r=e(this),i=r.data("tab");i||r.data("tab",i=new t(this)),typeof n=="string"&&i[n]()})},e.fn.tab.Constructor=t,e.fn.tab.noConflict=function(){return e.fn.tab=n,this},e(document).on("click.tab.data-api",'[data-toggle="tab"], [data-toggle="pill"]',function(t){t.preventDefault(),e(this).tab("show")})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.$element=e(t),this.options=e.extend({},e.fn.typeahead.defaults,n),this.matcher=this.options.matcher||this.matcher,this.sorter=this.options.sorter||this.sorter,this.highlighter=this.options.highlighter||this.highlighter,this.updater=this.options.updater||this.updater,this.source=this.options.source,this.$menu=e(this.options.menu),this.shown=!1,this.listen()};t.prototype={constructor:t,select:function(){var e=this.$menu.find(".active").attr("data-value");return this.$element.val(this.updater(e)).change(),this.hide()},updater:function(e){return e},show:function(){var t=e.extend({},this.$element.position(),{height:this.$element[0].offsetHeight});return this.$menu.insertAfter(this.$element).css({top:t.top+t.height,left:t.left}).show(),this.shown=!0,this},hide:function(){return this.$menu.hide(),this.shown=!1,this},lookup:function(t){var n;return this.query=this.$element.val(),!this.query||this.query.length<this.options.minLength?this.shown?this.hide():this:(n=e.isFunction(this.source)?this.source(this.query,e.proxy(this.process,this)):this.source,n?this.process(n):this)},process:function(t){var n=this;return t=e.grep(t,function(e){return n.matcher(e)}),t=this.sorter(t),t.length?this.render(t.slice(0,this.options.items)).show():this.shown?this.hide():this},matcher:function(e){return~e.toLowerCase().indexOf(this.query.toLowerCase())},sorter:function(e){var t=[],n=[],r=[],i;while(i=e.shift())i.toLowerCase().indexOf(this.query.toLowerCase())?~i.indexOf(this.query)?n.push(i):r.push(i):t.push(i);return t.concat(n,r)},highlighter:function(e){var t=this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");return e.replace(new RegExp("("+t+")","ig"),function(e,t){return"<strong>"+t+"</strong>"})},render:function(t){var n=this;return t=e(t).map(function(t,r){return t=e(n.options.item).attr("data-value",r),t.find("a").html(n.highlighter(r)),t[0]}),t.first().addClass("active"),this.$menu.html(t),this},next:function(t){var n=this.$menu.find(".active").removeClass("active"),r=n.next();r.length||(r=e(this.$menu.find("li")[0])),r.addClass("active")},prev:function(e){var t=this.$menu.find(".active").removeClass("active"),n=t.prev();n.length||(n=this.$menu.find("li").last()),n.addClass("active")},listen:function(){this.$element.on("focus",e.proxy(this.focus,this)).on("blur",e.proxy(this.blur,this)).on("keypress",e.proxy(this.keypress,this)).on("keyup",e.proxy(this.keyup,this)),this.eventSupported("keydown")&&this.$element.on("keydown",e.proxy(this.keydown,this)),this.$menu.on("click",e.proxy(this.click,this)).on("mouseenter","li",e.proxy(this.mouseenter,this)).on("mouseleave","li",e.proxy(this.mouseleave,this))},eventSupported:function(e){var t=e in this.$element;return t||(this.$element.setAttribute(e,"return;"),t=typeof this.$element[e]=="function"),t},move:function(e){if(!this.shown)return;switch(e.keyCode){case 9:case 13:case 27:e.preventDefault();break;case 38:e.preventDefault(),this.prev();break;case 40:e.preventDefault(),this.next()}e.stopPropagation()},keydown:function(t){this.suppressKeyPressRepeat=~e.inArray(t.keyCode,[40,38,9,13,27]),this.move(t)},keypress:function(e){if(this.suppressKeyPressRepeat)return;this.move(e)},keyup:function(e){switch(e.keyCode){case 40:case 38:case 16:case 17:case 18:break;case 9:case 13:if(!this.shown)return;this.select();break;case 27:if(!this.shown)return;this.hide();break;default:this.lookup()}e.stopPropagation(),e.preventDefault()},focus:function(e){this.focused=!0},blur:function(e){this.focused=!1,!this.mousedover&&this.shown&&this.hide()},click:function(e){e.stopPropagation(),e.preventDefault(),this.select(),this.$element.focus()},mouseenter:function(t){this.mousedover=!0,this.$menu.find(".active").removeClass("active"),e(t.currentTarget).addClass("active")},mouseleave:function(e){this.mousedover=!1,!this.focused&&this.shown&&this.hide()}};var n=e.fn.typeahead;e.fn.typeahead=function(n){return this.each(function(){var r=e(this),i=r.data("typeahead"),s=typeof n=="object"&&n;i||r.data("typeahead",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.typeahead.defaults={source:[],items:8,menu:'<ul class="typeahead dropdown-menu"></ul>',item:'<li><a href="#"></a></li>',minLength:1},e.fn.typeahead.Constructor=t,e.fn.typeahead.noConflict=function(){return e.fn.typeahead=n,this},e(document).on("focus.typeahead.data-api",'[data-provide="typeahead"]',function(t){var n=e(this);if(n.data("typeahead"))return;n.typeahead(n.data())})}(window.jQuery),!function(e){"use strict";var t=function(t,n){this.options=e.extend({},e.fn.affix.defaults,n),this.$window=e(window).on("scroll.affix.data-api",e.proxy(this.checkPosition,this)).on("click.affix.data-api",e.proxy(function(){setTimeout(e.proxy(this.checkPosition,this),1)},this)),this.$element=e(t),this.checkPosition()};t.prototype.checkPosition=function(){if(!this.$element.is(":visible"))return;var t=e(document).height(),n=this.$window.scrollTop(),r=this.$element.offset(),i=this.options.offset,s=i.bottom,o=i.top,u="affix affix-top affix-bottom",a;typeof i!="object"&&(s=o=i),typeof o=="function"&&(o=i.top()),typeof s=="function"&&(s=i.bottom()),a=this.unpin!=null&&n+this.unpin<=r.top?!1:s!=null&&r.top+this.$element.height()>=t-s?"bottom":o!=null&&n<=o?"top":!1;if(this.affixed===a)return;this.affixed=a,this.unpin=a=="bottom"?r.top-n:null,this.$element.removeClass(u).addClass("affix"+(a?"-"+a:""))};var n=e.fn.affix;e.fn.affix=function(n){return this.each(function(){var r=e(this),i=r.data("affix"),s=typeof n=="object"&&n;i||r.data("affix",i=new t(this,s)),typeof n=="string"&&i[n]()})},e.fn.affix.Constructor=t,e.fn.affix.defaults={offset:0},e.fn.affix.noConflict=function(){return e.fn.affix=n,this},e(window).on("load",function(){e('[data-spy="affix"]').each(function(){var t=e(this),n=t.data();n.offset=n.offset||{},n.offsetBottom&&(n.offset.bottom=n.offsetBottom),n.offsetTop&&(n.offset.top=n.offsetTop),t.affix(n)})})}(window.jQuery);
\ No newline at end of file diff --git a/dgbuilder/public/d3.v3.min.js b/dgbuilder/public/d3.v3.min.js new file mode 100644 index 00000000..2542cedf --- /dev/null +++ b/dgbuilder/public/d3.v3.min.js @@ -0,0 +1,4 @@ +(function(){function t(t){return t.target}function n(t){return t.source}function e(t,n){try{for(var e in n)Object.defineProperty(t.prototype,e,{value:n[e],enumerable:!1})}catch(r){t.prototype=n}}function r(t){for(var n=-1,e=t.length,r=[];e>++n;)r.push(t[n]);return r}function i(t){return Array.prototype.slice.call(t)}function u(){}function a(t){return t}function o(){return!0}function c(t){return"function"==typeof t?t:function(){return t}}function l(t,n,e){return function(){var r=e.apply(n,arguments);return arguments.length?t:r}}function s(t){return null!=t&&!isNaN(t)}function f(t){return t.length}function h(t){return t.trim().replace(/\s+/g," ")}function d(t){for(var n=1;t*n%1;)n*=10;return n}function g(t){return 1===t.length?function(n,e){t(null==n?e:null)}:t}function p(t){return t.responseText}function m(t){return JSON.parse(t.responseText)}function v(t){var n=document.createRange();return n.selectNode(document.body),n.createContextualFragment(t.responseText)}function y(t){return t.responseXML}function M(){}function b(t){function n(){for(var n,r=e,i=-1,u=r.length;u>++i;)(n=r[i].on)&&n.apply(this,arguments);return t}var e=[],r=new u;return n.on=function(n,i){var u,a=r.get(n);return 2>arguments.length?a&&a.on:(a&&(a.on=null,e=e.slice(0,u=e.indexOf(a)).concat(e.slice(u+1)),r.remove(n)),i&&e.push(r.set(n,{on:i})),t)},n}function x(t,n){return n-(t?1+Math.floor(Math.log(t+Math.pow(10,1+Math.floor(Math.log(t)/Math.LN10)-n))/Math.LN10):1)}function _(t){return t+""}function w(t,n){var e=Math.pow(10,3*Math.abs(8-n));return{scale:n>8?function(t){return t/e}:function(t){return t*e},symbol:t}}function S(t){return function(n){return 0>=n?0:n>=1?1:t(n)}}function k(t){return function(n){return 1-t(1-n)}}function E(t){return function(n){return.5*(.5>n?t(2*n):2-t(2-2*n))}}function A(t){return t*t}function N(t){return t*t*t}function T(t){if(0>=t)return 0;if(t>=1)return 1;var n=t*t,e=n*t;return 4*(.5>t?e:3*(t-n)+e-.75)}function q(t){return function(n){return Math.pow(n,t)}}function C(t){return 1-Math.cos(t*Ru/2)}function z(t){return Math.pow(2,10*(t-1))}function D(t){return 1-Math.sqrt(1-t*t)}function L(t,n){var e;return 2>arguments.length&&(n=.45),arguments.length?e=n/(2*Ru)*Math.asin(1/t):(t=1,e=n/4),function(r){return 1+t*Math.pow(2,10*-r)*Math.sin(2*(r-e)*Ru/n)}}function F(t){return t||(t=1.70158),function(n){return n*n*((t+1)*n-t)}}function H(t){return 1/2.75>t?7.5625*t*t:2/2.75>t?7.5625*(t-=1.5/2.75)*t+.75:2.5/2.75>t?7.5625*(t-=2.25/2.75)*t+.9375:7.5625*(t-=2.625/2.75)*t+.984375}function R(){d3.event.stopPropagation(),d3.event.preventDefault()}function P(){for(var t,n=d3.event;t=n.sourceEvent;)n=t;return n}function j(t){for(var n=new M,e=0,r=arguments.length;r>++e;)n[arguments[e]]=b(n);return n.of=function(e,r){return function(i){try{var u=i.sourceEvent=d3.event;i.target=t,d3.event=i,n[i.type].apply(e,r)}finally{d3.event=u}}},n}function O(t){var n=[t.a,t.b],e=[t.c,t.d],r=U(n),i=Y(n,e),u=U(I(e,n,-i))||0;n[0]*e[1]<e[0]*n[1]&&(n[0]*=-1,n[1]*=-1,r*=-1,i*=-1),this.rotate=(r?Math.atan2(n[1],n[0]):Math.atan2(-e[0],e[1]))*Ou,this.translate=[t.e,t.f],this.scale=[r,u],this.skew=u?Math.atan2(i,u)*Ou:0}function Y(t,n){return t[0]*n[0]+t[1]*n[1]}function U(t){var n=Math.sqrt(Y(t,t));return n&&(t[0]/=n,t[1]/=n),n}function I(t,n,e){return t[0]+=e*n[0],t[1]+=e*n[1],t}function V(t){return"transform"==t?d3.interpolateTransform:d3.interpolate}function X(t,n){return n=n-(t=+t)?1/(n-t):0,function(e){return(e-t)*n}}function Z(t,n){return n=n-(t=+t)?1/(n-t):0,function(e){return Math.max(0,Math.min(1,(e-t)*n))}}function B(){}function $(t,n,e){return new J(t,n,e)}function J(t,n,e){this.r=t,this.g=n,this.b=e}function G(t){return 16>t?"0"+Math.max(0,t).toString(16):Math.min(255,t).toString(16)}function K(t,n,e){var r,i,u,a=0,o=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(t))switch(i=r[2].split(","),r[1]){case"hsl":return e(parseFloat(i[0]),parseFloat(i[1])/100,parseFloat(i[2])/100);case"rgb":return n(nn(i[0]),nn(i[1]),nn(i[2]))}return(u=aa.get(t))?n(u.r,u.g,u.b):(null!=t&&"#"===t.charAt(0)&&(4===t.length?(a=t.charAt(1),a+=a,o=t.charAt(2),o+=o,c=t.charAt(3),c+=c):7===t.length&&(a=t.substring(1,3),o=t.substring(3,5),c=t.substring(5,7)),a=parseInt(a,16),o=parseInt(o,16),c=parseInt(c,16)),n(a,o,c))}function W(t,n,e){var r,i,u=Math.min(t/=255,n/=255,e/=255),a=Math.max(t,n,e),o=a-u,c=(a+u)/2;return o?(i=.5>c?o/(a+u):o/(2-a-u),r=t==a?(n-e)/o+(e>n?6:0):n==a?(e-t)/o+2:(t-n)/o+4,r*=60):i=r=0,en(r,i,c)}function Q(t,n,e){t=tn(t),n=tn(n),e=tn(e);var r=gn((.4124564*t+.3575761*n+.1804375*e)/sa),i=gn((.2126729*t+.7151522*n+.072175*e)/fa),u=gn((.0193339*t+.119192*n+.9503041*e)/ha);return ln(116*i-16,500*(r-i),200*(i-u))}function tn(t){return.04045>=(t/=255)?t/12.92:Math.pow((t+.055)/1.055,2.4)}function nn(t){var n=parseFloat(t);return"%"===t.charAt(t.length-1)?Math.round(2.55*n):n}function en(t,n,e){return new rn(t,n,e)}function rn(t,n,e){this.h=t,this.s=n,this.l=e}function un(t,n,e){function r(t){return t>360?t-=360:0>t&&(t+=360),60>t?u+(a-u)*t/60:180>t?a:240>t?u+(a-u)*(240-t)/60:u}function i(t){return Math.round(255*r(t))}var u,a;return t%=360,0>t&&(t+=360),n=0>n?0:n>1?1:n,e=0>e?0:e>1?1:e,a=.5>=e?e*(1+n):e+n-e*n,u=2*e-a,$(i(t+120),i(t),i(t-120))}function an(t,n,e){return new on(t,n,e)}function on(t,n,e){this.h=t,this.c=n,this.l=e}function cn(t,n,e){return ln(e,Math.cos(t*=ju)*n,Math.sin(t)*n)}function ln(t,n,e){return new sn(t,n,e)}function sn(t,n,e){this.l=t,this.a=n,this.b=e}function fn(t,n,e){var r=(t+16)/116,i=r+n/500,u=r-e/200;return i=dn(i)*sa,r=dn(r)*fa,u=dn(u)*ha,$(pn(3.2404542*i-1.5371385*r-.4985314*u),pn(-.969266*i+1.8760108*r+.041556*u),pn(.0556434*i-.2040259*r+1.0572252*u))}function hn(t,n,e){return an(180*(Math.atan2(e,n)/Ru),Math.sqrt(n*n+e*e),t)}function dn(t){return t>.206893034?t*t*t:(t-4/29)/7.787037}function gn(t){return t>.008856?Math.pow(t,1/3):7.787037*t+4/29}function pn(t){return Math.round(255*(.00304>=t?12.92*t:1.055*Math.pow(t,1/2.4)-.055))}function mn(t){return Iu(t,Ma),t}function vn(t){return function(){return ga(t,this)}}function yn(t){return function(){return pa(t,this)}}function Mn(t,n){function e(){this.removeAttribute(t)}function r(){this.removeAttributeNS(t.space,t.local)}function i(){this.setAttribute(t,n)}function u(){this.setAttributeNS(t.space,t.local,n)}function a(){var e=n.apply(this,arguments);null==e?this.removeAttribute(t):this.setAttribute(t,e)}function o(){var e=n.apply(this,arguments);null==e?this.removeAttributeNS(t.space,t.local):this.setAttributeNS(t.space,t.local,e)}return t=d3.ns.qualify(t),null==n?t.local?r:e:"function"==typeof n?t.local?o:a:t.local?u:i}function bn(t){return RegExp("(?:^|\\s+)"+d3.requote(t)+"(?:\\s+|$)","g")}function xn(t,n){function e(){for(var e=-1;i>++e;)t[e](this,n)}function r(){for(var e=-1,r=n.apply(this,arguments);i>++e;)t[e](this,r)}t=t.trim().split(/\s+/).map(_n);var i=t.length;return"function"==typeof n?r:e}function _n(t){var n=bn(t);return function(e,r){if(i=e.classList)return r?i.add(t):i.remove(t);var i=e.className,u=null!=i.baseVal,a=u?i.baseVal:i;r?(n.lastIndex=0,n.test(a)||(a=h(a+" "+t),u?i.baseVal=a:e.className=a)):a&&(a=h(a.replace(n," ")),u?i.baseVal=a:e.className=a)}}function wn(t,n,e){function r(){this.style.removeProperty(t)}function i(){this.style.setProperty(t,n,e)}function u(){var r=n.apply(this,arguments);null==r?this.style.removeProperty(t):this.style.setProperty(t,r,e)}return null==n?r:"function"==typeof n?u:i}function Sn(t,n){function e(){delete this[t]}function r(){this[t]=n}function i(){var e=n.apply(this,arguments);null==e?delete this[t]:this[t]=e}return null==n?e:"function"==typeof n?i:r}function kn(t){return{__data__:t}}function En(t){return function(){return ya(this,t)}}function An(t){return arguments.length||(t=d3.ascending),function(n,e){return t(n&&n.__data__,e&&e.__data__)}}function Nn(t,n,e){function r(){var n=this[u];n&&(this.removeEventListener(t,n,n.$),delete this[u])}function i(){function i(t){var e=d3.event;d3.event=t,o[0]=a.__data__;try{n.apply(a,o)}finally{d3.event=e}}var a=this,o=Yu(arguments);r.call(this),this.addEventListener(t,this[u]=i,i.$=e),i._=n}var u="__on"+t,a=t.indexOf(".");return a>0&&(t=t.substring(0,a)),n?i:r}function Tn(t,n){for(var e=0,r=t.length;r>e;e++)for(var i,u=t[e],a=0,o=u.length;o>a;a++)(i=u[a])&&n(i,a,e);return t}function qn(t){return Iu(t,xa),t}function Cn(t,n){return Iu(t,wa),t.id=n,t}function zn(t,n,e,r){var i=t.__transition__||(t.__transition__={active:0,count:0}),a=i[e];if(!a){var o=r.time;return a=i[e]={tween:new u,event:d3.dispatch("start","end"),time:o,ease:r.ease,delay:r.delay,duration:r.duration},++i.count,d3.timer(function(r){function u(r){return i.active>e?l():(i.active=e,h.start.call(t,s,n),a.tween.forEach(function(e,r){(r=r.call(t,s,n))&&p.push(r)}),c(r)||d3.timer(c,0,o),1)}function c(r){if(i.active!==e)return l();for(var u=(r-d)/g,a=f(u),o=p.length;o>0;)p[--o].call(t,a);return u>=1?(l(),h.end.call(t,s,n),1):void 0}function l(){return--i.count?delete i[e]:delete t.__transition__,1}var s=t.__data__,f=a.ease,h=a.event,d=a.delay,g=a.duration,p=[];return r>=d?u(r):d3.timer(u,d,o),1},0,o),a}}function Dn(t){return null==t&&(t=""),function(){this.textContent=t}}function Ln(t,n,e,r){var i=t.id;return Tn(t,"function"==typeof e?function(t,u,a){t.__transition__[i].tween.set(n,r(e.call(t,t.__data__,u,a)))}:(e=r(e),function(t){t.__transition__[i].tween.set(n,e)}))}function Fn(){for(var t,n=Date.now(),e=qa;e;)t=n-e.then,t>=e.delay&&(e.flush=e.callback(t)),e=e.next;var r=Hn()-n;r>24?(isFinite(r)&&(clearTimeout(Aa),Aa=setTimeout(Fn,r)),Ea=0):(Ea=1,Ca(Fn))}function Hn(){for(var t=null,n=qa,e=1/0;n;)n.flush?(delete Ta[n.callback.id],n=t?t.next=n.next:qa=n.next):(e=Math.min(e,n.then+n.delay),n=(t=n).next);return e}function Rn(t,n){var e=t.ownerSVGElement||t;if(e.createSVGPoint){var r=e.createSVGPoint();if(0>za&&(window.scrollX||window.scrollY)){e=d3.select(document.body).append("svg").style("position","absolute").style("top",0).style("left",0);var i=e[0][0].getScreenCTM();za=!(i.f||i.e),e.remove()}return za?(r.x=n.pageX,r.y=n.pageY):(r.x=n.clientX,r.y=n.clientY),r=r.matrixTransform(t.getScreenCTM().inverse()),[r.x,r.y]}var u=t.getBoundingClientRect();return[n.clientX-u.left-t.clientLeft,n.clientY-u.top-t.clientTop]}function Pn(){}function jn(t){var n=t[0],e=t[t.length-1];return e>n?[n,e]:[e,n]}function On(t){return t.rangeExtent?t.rangeExtent():jn(t.range())}function Yn(t,n){var e,r=0,i=t.length-1,u=t[r],a=t[i];return u>a&&(e=r,r=i,i=e,e=u,u=a,a=e),(n=n(a-u))&&(t[r]=n.floor(u),t[i]=n.ceil(a)),t}function Un(){return Math}function In(t,n,e,r){function i(){var i=Math.min(t.length,n.length)>2?Gn:Jn,c=r?Z:X;return a=i(t,n,c,e),o=i(n,t,c,d3.interpolate),u}function u(t){return a(t)}var a,o;return u.invert=function(t){return o(t)},u.domain=function(n){return arguments.length?(t=n.map(Number),i()):t},u.range=function(t){return arguments.length?(n=t,i()):n},u.rangeRound=function(t){return u.range(t).interpolate(d3.interpolateRound)},u.clamp=function(t){return arguments.length?(r=t,i()):r},u.interpolate=function(t){return arguments.length?(e=t,i()):e},u.ticks=function(n){return Bn(t,n)},u.tickFormat=function(n){return $n(t,n)},u.nice=function(){return Yn(t,Xn),i()},u.copy=function(){return In(t,n,e,r)},i()}function Vn(t,n){return d3.rebind(t,n,"range","rangeRound","interpolate","clamp")}function Xn(t){return t=Math.pow(10,Math.round(Math.log(t)/Math.LN10)-1),t&&{floor:function(n){return Math.floor(n/t)*t},ceil:function(n){return Math.ceil(n/t)*t}}}function Zn(t,n){var e=jn(t),r=e[1]-e[0],i=Math.pow(10,Math.floor(Math.log(r/n)/Math.LN10)),u=n/r*i;return.15>=u?i*=10:.35>=u?i*=5:.75>=u&&(i*=2),e[0]=Math.ceil(e[0]/i)*i,e[1]=Math.floor(e[1]/i)*i+.5*i,e[2]=i,e}function Bn(t,n){return d3.range.apply(d3,Zn(t,n))}function $n(t,n){return d3.format(",."+Math.max(0,-Math.floor(Math.log(Zn(t,n)[2])/Math.LN10+.01))+"f")}function Jn(t,n,e,r){var i=e(t[0],t[1]),u=r(n[0],n[1]);return function(t){return u(i(t))}}function Gn(t,n,e,r){var i=[],u=[],a=0,o=Math.min(t.length,n.length)-1;for(t[o]<t[0]&&(t=t.slice().reverse(),n=n.slice().reverse());o>=++a;)i.push(e(t[a-1],t[a])),u.push(r(n[a-1],n[a]));return function(n){var e=d3.bisect(t,n,1,o)-1;return u[e](i[e](n))}}function Kn(t,n){function e(e){return t(n(e))}var r=n.pow;return e.invert=function(n){return r(t.invert(n))},e.domain=function(i){return arguments.length?(n=0>i[0]?Qn:Wn,r=n.pow,t.domain(i.map(n)),e):t.domain().map(r)},e.nice=function(){return t.domain(Yn(t.domain(),Un)),e},e.ticks=function(){var e=jn(t.domain()),i=[];if(e.every(isFinite)){var u=Math.floor(e[0]),a=Math.ceil(e[1]),o=r(e[0]),c=r(e[1]);if(n===Qn)for(i.push(r(u));a>u++;)for(var l=9;l>0;l--)i.push(r(u)*l);else{for(;a>u;u++)for(var l=1;10>l;l++)i.push(r(u)*l);i.push(r(u))}for(u=0;o>i[u];u++);for(a=i.length;i[a-1]>c;a--);i=i.slice(u,a)}return i},e.tickFormat=function(t,i){if(2>arguments.length&&(i=Da),!arguments.length)return i;var u,a=Math.max(.1,t/e.ticks().length),o=n===Qn?(u=-1e-12,Math.floor):(u=1e-12,Math.ceil);return function(t){return a>=t/r(o(n(t)+u))?i(t):""}},e.copy=function(){return Kn(t.copy(),n)},Vn(e,t)}function Wn(t){return Math.log(0>t?0:t)/Math.LN10}function Qn(t){return-Math.log(t>0?0:-t)/Math.LN10}function te(t,n){function e(n){return t(r(n))}var r=ne(n),i=ne(1/n);return e.invert=function(n){return i(t.invert(n))},e.domain=function(n){return arguments.length?(t.domain(n.map(r)),e):t.domain().map(i)},e.ticks=function(t){return Bn(e.domain(),t)},e.tickFormat=function(t){return $n(e.domain(),t)},e.nice=function(){return e.domain(Yn(e.domain(),Xn))},e.exponent=function(t){if(!arguments.length)return n;var u=e.domain();return r=ne(n=t),i=ne(1/n),e.domain(u)},e.copy=function(){return te(t.copy(),n)},Vn(e,t)}function ne(t){return function(n){return 0>n?-Math.pow(-n,t):Math.pow(n,t)}}function ee(t,n){function e(n){return a[((i.get(n)||i.set(n,t.push(n)))-1)%a.length]}function r(n,e){return d3.range(t.length).map(function(t){return n+e*t})}var i,a,o;return e.domain=function(r){if(!arguments.length)return t;t=[],i=new u;for(var a,o=-1,c=r.length;c>++o;)i.has(a=r[o])||i.set(a,t.push(a));return e[n.t].apply(e,n.a)},e.range=function(t){return arguments.length?(a=t,o=0,n={t:"range",a:arguments},e):a},e.rangePoints=function(i,u){2>arguments.length&&(u=0);var c=i[0],l=i[1],s=(l-c)/(Math.max(1,t.length-1)+u);return a=r(2>t.length?(c+l)/2:c+s*u/2,s),o=0,n={t:"rangePoints",a:arguments},e},e.rangeBands=function(i,u,c){2>arguments.length&&(u=0),3>arguments.length&&(c=u);var l=i[1]<i[0],s=i[l-0],f=i[1-l],h=(f-s)/(t.length-u+2*c);return a=r(s+h*c,h),l&&a.reverse(),o=h*(1-u),n={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(i,u,c){2>arguments.length&&(u=0),3>arguments.length&&(c=u);var l=i[1]<i[0],s=i[l-0],f=i[1-l],h=Math.floor((f-s)/(t.length-u+2*c)),d=f-s-(t.length-u)*h;return a=r(s+Math.round(d/2),h),l&&a.reverse(),o=Math.round(h*(1-u)),n={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return o},e.rangeExtent=function(){return jn(n.a[0])},e.copy=function(){return ee(t,n)},e.domain(t)}function re(t,n){function e(){var e=0,u=n.length;for(i=[];u>++e;)i[e-1]=d3.quantile(t,e/u);return r}function r(t){return isNaN(t=+t)?0/0:n[d3.bisect(i,t)]}var i;return r.domain=function(n){return arguments.length?(t=n.filter(function(t){return!isNaN(t)}).sort(d3.ascending),e()):t},r.range=function(t){return arguments.length?(n=t,e()):n},r.quantiles=function(){return i},r.copy=function(){return re(t,n)},e()}function ie(t,n,e){function r(n){return e[Math.max(0,Math.min(a,Math.floor(u*(n-t))))]}function i(){return u=e.length/(n-t),a=e.length-1,r}var u,a;return r.domain=function(e){return arguments.length?(t=+e[0],n=+e[e.length-1],i()):[t,n]},r.range=function(t){return arguments.length?(e=t,i()):e},r.copy=function(){return ie(t,n,e)},i()}function ue(t,n){function e(e){return n[d3.bisect(t,e)]}return e.domain=function(n){return arguments.length?(t=n,e):t},e.range=function(t){return arguments.length?(n=t,e):n},e.copy=function(){return ue(t,n)},e}function ae(t){function n(t){return+t}return n.invert=n,n.domain=n.range=function(e){return arguments.length?(t=e.map(n),n):t},n.ticks=function(n){return Bn(t,n)},n.tickFormat=function(n){return $n(t,n)},n.copy=function(){return ae(t)},n}function oe(t){return t.innerRadius}function ce(t){return t.outerRadius}function le(t){return t.startAngle}function se(t){return t.endAngle}function fe(t){function n(n){function a(){s.push("M",u(t(f),l))}for(var o,s=[],f=[],h=-1,d=n.length,g=c(e),p=c(r);d>++h;)i.call(this,o=n[h],h)?f.push([+g.call(this,o,h),+p.call(this,o,h)]):f.length&&(a(),f=[]);return f.length&&a(),s.length?s.join(""):null}var e=he,r=de,i=o,u=ge,a=u.key,l=.7;return n.x=function(t){return arguments.length?(e=t,n):e},n.y=function(t){return arguments.length?(r=t,n):r},n.defined=function(t){return arguments.length?(i=t,n):i},n.interpolate=function(t){return arguments.length?(a="function"==typeof t?u=t:(u=Oa.get(t)||ge).key,n):a},n.tension=function(t){return arguments.length?(l=t,n):l},n}function he(t){return t[0]}function de(t){return t[1]}function ge(t){return t.join("L")}function pe(t){return ge(t)+"Z"}function me(t){for(var n=0,e=t.length,r=t[0],i=[r[0],",",r[1]];e>++n;)i.push("V",(r=t[n])[1],"H",r[0]);return i.join("")}function ve(t){for(var n=0,e=t.length,r=t[0],i=[r[0],",",r[1]];e>++n;)i.push("H",(r=t[n])[0],"V",r[1]);return i.join("")}function ye(t,n){return 4>t.length?ge(t):t[1]+xe(t.slice(1,t.length-1),_e(t,n))}function Me(t,n){return 3>t.length?ge(t):t[0]+xe((t.push(t[0]),t),_e([t[t.length-2]].concat(t,[t[1]]),n))}function be(t,n){return 3>t.length?ge(t):t[0]+xe(t,_e(t,n))}function xe(t,n){if(1>n.length||t.length!=n.length&&t.length!=n.length+2)return ge(t);var e=t.length!=n.length,r="",i=t[0],u=t[1],a=n[0],o=a,c=1;if(e&&(r+="Q"+(u[0]-2*a[0]/3)+","+(u[1]-2*a[1]/3)+","+u[0]+","+u[1],i=t[1],c=2),n.length>1){o=n[1],u=t[c],c++,r+="C"+(i[0]+a[0])+","+(i[1]+a[1])+","+(u[0]-o[0])+","+(u[1]-o[1])+","+u[0]+","+u[1];for(var l=2;n.length>l;l++,c++)u=t[c],o=n[l],r+="S"+(u[0]-o[0])+","+(u[1]-o[1])+","+u[0]+","+u[1]}if(e){var s=t[c];r+="Q"+(u[0]+2*o[0]/3)+","+(u[1]+2*o[1]/3)+","+s[0]+","+s[1]}return r}function _e(t,n){for(var e,r=[],i=(1-n)/2,u=t[0],a=t[1],o=1,c=t.length;c>++o;)e=u,u=a,a=t[o],r.push([i*(a[0]-e[0]),i*(a[1]-e[1])]);return r}function we(t){if(3>t.length)return ge(t);var n=1,e=t.length,r=t[0],i=r[0],u=r[1],a=[i,i,i,(r=t[1])[0]],o=[u,u,u,r[1]],c=[i,",",u];for(Ne(c,a,o);e>++n;)r=t[n],a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Ne(c,a,o);for(n=-1;2>++n;)a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Ne(c,a,o);return c.join("")}function Se(t){if(4>t.length)return ge(t);for(var n,e=[],r=-1,i=t.length,u=[0],a=[0];3>++r;)n=t[r],u.push(n[0]),a.push(n[1]);for(e.push(Ae(Ia,u)+","+Ae(Ia,a)),--r;i>++r;)n=t[r],u.shift(),u.push(n[0]),a.shift(),a.push(n[1]),Ne(e,u,a);return e.join("")}function ke(t){for(var n,e,r=-1,i=t.length,u=i+4,a=[],o=[];4>++r;)e=t[r%i],a.push(e[0]),o.push(e[1]);for(n=[Ae(Ia,a),",",Ae(Ia,o)],--r;u>++r;)e=t[r%i],a.shift(),a.push(e[0]),o.shift(),o.push(e[1]),Ne(n,a,o);return n.join("")}function Ee(t,n){var e=t.length-1;if(e)for(var r,i,u=t[0][0],a=t[0][1],o=t[e][0]-u,c=t[e][1]-a,l=-1;e>=++l;)r=t[l],i=l/e,r[0]=n*r[0]+(1-n)*(u+i*o),r[1]=n*r[1]+(1-n)*(a+i*c);return we(t)}function Ae(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]+t[3]*n[3]}function Ne(t,n,e){t.push("C",Ae(Ya,n),",",Ae(Ya,e),",",Ae(Ua,n),",",Ae(Ua,e),",",Ae(Ia,n),",",Ae(Ia,e))}function Te(t,n){return(n[1]-t[1])/(n[0]-t[0])}function qe(t){for(var n=0,e=t.length-1,r=[],i=t[0],u=t[1],a=r[0]=Te(i,u);e>++n;)r[n]=(a+(a=Te(i=u,u=t[n+1])))/2;return r[n]=a,r}function Ce(t){for(var n,e,r,i,u=[],a=qe(t),o=-1,c=t.length-1;c>++o;)n=Te(t[o],t[o+1]),1e-6>Math.abs(n)?a[o]=a[o+1]=0:(e=a[o]/n,r=a[o+1]/n,i=e*e+r*r,i>9&&(i=3*n/Math.sqrt(i),a[o]=i*e,a[o+1]=i*r));for(o=-1;c>=++o;)i=(t[Math.min(c,o+1)][0]-t[Math.max(0,o-1)][0])/(6*(1+a[o]*a[o])),u.push([i||0,a[o]*i||0]);return u}function ze(t){return 3>t.length?ge(t):t[0]+xe(t,Ce(t))}function De(t){for(var n,e,r,i=-1,u=t.length;u>++i;)n=t[i],e=n[0],r=n[1]+Pa,n[0]=e*Math.cos(r),n[1]=e*Math.sin(r);return t}function Le(t){function n(n){function o(){m.push("M",l(t(y),d),h,f(t(v.reverse()),d),"Z")}for(var s,g,p,m=[],v=[],y=[],M=-1,b=n.length,x=c(e),_=c(i),w=e===r?function(){return g}:c(r),S=i===u?function(){return p}:c(u);b>++M;)a.call(this,s=n[M],M)?(v.push([g=+x.call(this,s,M),p=+_.call(this,s,M)]),y.push([+w.call(this,s,M),+S.call(this,s,M)])):v.length&&(o(),v=[],y=[]);return v.length&&o(),m.length?m.join(""):null}var e=he,r=he,i=0,u=de,a=o,l=ge,s=l.key,f=l,h="L",d=.7;return n.x=function(t){return arguments.length?(e=r=t,n):r},n.x0=function(t){return arguments.length?(e=t,n):e},n.x1=function(t){return arguments.length?(r=t,n):r},n.y=function(t){return arguments.length?(i=u=t,n):u},n.y0=function(t){return arguments.length?(i=t,n):i},n.y1=function(t){return arguments.length?(u=t,n):u},n.defined=function(t){return arguments.length?(a=t,n):a},n.interpolate=function(t){return arguments.length?(s="function"==typeof t?l=t:(l=Oa.get(t)||ge).key,f=l.reverse||l,h=l.closed?"M":"L",n):s},n.tension=function(t){return arguments.length?(d=t,n):d},n}function Fe(t){return t.radius}function He(t){return[t.x,t.y]}function Re(t){return function(){var n=t.apply(this,arguments),e=n[0],r=n[1]+Pa;return[e*Math.cos(r),e*Math.sin(r)]}}function Pe(){return 64}function je(){return"circle"}function Oe(t){var n=Math.sqrt(t/Ru);return"M0,"+n+"A"+n+","+n+" 0 1,1 0,"+-n+"A"+n+","+n+" 0 1,1 0,"+n+"Z"}function Ye(t,n){t.attr("transform",function(t){return"translate("+n(t)+",0)"})}function Ue(t,n){t.attr("transform",function(t){return"translate(0,"+n(t)+")"})}function Ie(t,n,e){if(r=[],e&&n.length>1){for(var r,i,u,a=jn(t.domain()),o=-1,c=n.length,l=(n[1]-n[0])/++e;c>++o;)for(i=e;--i>0;)(u=+n[o]-i*l)>=a[0]&&r.push(u);for(--o,i=0;e>++i&&(u=+n[o]+i*l)<a[1];)r.push(u)}return r}function Ve(){Ja||(Ja=d3.select("body").append("div").style("visibility","hidden").style("top",0).style("height",0).style("width",0).style("overflow-y","scroll").append("div").style("height","2000px").node().parentNode);var t,n=d3.event;try{Ja.scrollTop=1e3,Ja.dispatchEvent(n),t=1e3-Ja.scrollTop}catch(e){t=n.wheelDelta||5*-n.detail}return t}function Xe(t){for(var n=t.source,e=t.target,r=Be(n,e),i=[n];n!==r;)n=n.parent,i.push(n);for(var u=i.length;e!==r;)i.splice(u,0,e),e=e.parent;return i}function Ze(t){for(var n=[],e=t.parent;null!=e;)n.push(t),t=e,e=e.parent;return n.push(t),n}function Be(t,n){if(t===n)return t;for(var e=Ze(t),r=Ze(n),i=e.pop(),u=r.pop(),a=null;i===u;)a=i,i=e.pop(),u=r.pop();return a}function $e(t){t.fixed|=2}function Je(t){t.fixed&=1}function Ge(t){t.fixed|=4,t.px=t.x,t.py=t.y}function Ke(t){t.fixed&=3}function We(t,n,e){var r=0,i=0;if(t.charge=0,!t.leaf)for(var u,a=t.nodes,o=a.length,c=-1;o>++c;)u=a[c],null!=u&&(We(u,n,e),t.charge+=u.charge,r+=u.charge*u.cx,i+=u.charge*u.cy);if(t.point){t.leaf||(t.point.x+=Math.random()-.5,t.point.y+=Math.random()-.5);var l=n*e[t.point.index];t.charge+=t.pointCharge=l,r+=l*t.point.x,i+=l*t.point.y}t.cx=r/t.charge,t.cy=i/t.charge}function Qe(){return 20}function tr(){return 1}function nr(t){return t.x}function er(t){return t.y}function rr(t,n,e){t.y0=n,t.y=e}function ir(t){return d3.range(t.length)}function ur(t){for(var n=-1,e=t[0].length,r=[];e>++n;)r[n]=0;return r}function ar(t){for(var n,e=1,r=0,i=t[0][1],u=t.length;u>e;++e)(n=t[e][1])>i&&(r=e,i=n);return r}function or(t){return t.reduce(cr,0)}function cr(t,n){return t+n[1]}function lr(t,n){return sr(t,Math.ceil(Math.log(n.length)/Math.LN2+1))}function sr(t,n){for(var e=-1,r=+t[0],i=(t[1]-r)/n,u=[];n>=++e;)u[e]=i*e+r;return u}function fr(t){return[d3.min(t),d3.max(t)]}function hr(t,n){return d3.rebind(t,n,"sort","children","value"),t.nodes=t,t.links=mr,t}function dr(t){return t.children}function gr(t){return t.value}function pr(t,n){return n.value-t.value}function mr(t){return d3.merge(t.map(function(t){return(t.children||[]).map(function(n){return{source:t,target:n}})}))}function vr(t,n){return t.value-n.value}function yr(t,n){var e=t._pack_next;t._pack_next=n,n._pack_prev=t,n._pack_next=e,e._pack_prev=n}function Mr(t,n){t._pack_next=n,n._pack_prev=t}function br(t,n){var e=n.x-t.x,r=n.y-t.y,i=t.r+n.r;return i*i-e*e-r*r>.001}function xr(t){function n(t){s=Math.min(t.x-t.r,s),f=Math.max(t.x+t.r,f),h=Math.min(t.y-t.r,h),d=Math.max(t.y+t.r,d)}if((e=t.children)&&(l=e.length)){var e,r,i,u,a,o,c,l,s=1/0,f=-1/0,h=1/0,d=-1/0;if(e.forEach(_r),r=e[0],r.x=-r.r,r.y=0,n(r),l>1&&(i=e[1],i.x=i.r,i.y=0,n(i),l>2))for(u=e[2],kr(r,i,u),n(u),yr(r,u),r._pack_prev=u,yr(u,i),i=r._pack_next,a=3;l>a;a++){kr(r,i,u=e[a]);var g=0,p=1,m=1;for(o=i._pack_next;o!==i;o=o._pack_next,p++)if(br(o,u)){g=1;break}if(1==g)for(c=r._pack_prev;c!==o._pack_prev&&!br(c,u);c=c._pack_prev,m++);g?(m>p||p==m&&i.r<r.r?Mr(r,i=o):Mr(r=c,i),a--):(yr(r,u),i=u,n(u))}var v=(s+f)/2,y=(h+d)/2,M=0;for(a=0;l>a;a++)u=e[a],u.x-=v,u.y-=y,M=Math.max(M,u.r+Math.sqrt(u.x*u.x+u.y*u.y));t.r=M,e.forEach(wr)}}function _r(t){t._pack_next=t._pack_prev=t}function wr(t){delete t._pack_next,delete t._pack_prev}function Sr(t,n,e,r){var i=t.children;if(t.x=n+=r*t.x,t.y=e+=r*t.y,t.r*=r,i)for(var u=-1,a=i.length;a>++u;)Sr(i[u],n,e,r)}function kr(t,n,e){var r=t.r+e.r,i=n.x-t.x,u=n.y-t.y;if(r&&(i||u)){var a=n.r+e.r,o=i*i+u*u;a*=a,r*=r;var c=.5+(r-a)/(2*o),l=Math.sqrt(Math.max(0,2*a*(r+o)-(r-=o)*r-a*a))/(2*o);e.x=t.x+c*i+l*u,e.y=t.y+c*u-l*i}else e.x=t.x+r,e.y=t.y}function Er(t){return 1+d3.max(t,function(t){return t.y})}function Ar(t){return t.reduce(function(t,n){return t+n.x},0)/t.length}function Nr(t){var n=t.children;return n&&n.length?Nr(n[0]):t}function Tr(t){var n,e=t.children;return e&&(n=e.length)?Tr(e[n-1]):t}function qr(t,n){return t.parent==n.parent?1:2}function Cr(t){var n=t.children;return n&&n.length?n[0]:t._tree.thread}function zr(t){var n,e=t.children;return e&&(n=e.length)?e[n-1]:t._tree.thread}function Dr(t,n){var e=t.children;if(e&&(i=e.length))for(var r,i,u=-1;i>++u;)n(r=Dr(e[u],n),t)>0&&(t=r);return t}function Lr(t,n){return t.x-n.x}function Fr(t,n){return n.x-t.x}function Hr(t,n){return t.depth-n.depth}function Rr(t,n){function e(t,r){var i=t.children;if(i&&(a=i.length))for(var u,a,o=null,c=-1;a>++c;)u=i[c],e(u,o),o=u;n(t,r)}e(t,null)}function Pr(t){for(var n,e=0,r=0,i=t.children,u=i.length;--u>=0;)n=i[u]._tree,n.prelim+=e,n.mod+=e,e+=n.shift+(r+=n.change)}function jr(t,n,e){t=t._tree,n=n._tree;var r=e/(n.number-t.number);t.change+=r,n.change-=r,n.shift+=e,n.prelim+=e,n.mod+=e}function Or(t,n,e){return t._tree.ancestor.parent==n.parent?t._tree.ancestor:e}function Yr(t){return{x:t.x,y:t.y,dx:t.dx,dy:t.dy}}function Ur(t,n){var e=t.x+n[3],r=t.y+n[0],i=t.dx-n[1]-n[3],u=t.dy-n[0]-n[2];return 0>i&&(e+=i/2,i=0),0>u&&(r+=u/2,u=0),{x:e,y:r,dx:i,dy:u}}function Ir(t,n){function e(t,e){return d3.xhr(t,n,e).response(r)}function r(t){return e.parse(t.responseText)}function i(n){return n.map(u).join(t)}function u(t){return a.test(t)?'"'+t.replace(/\"/g,'""')+'"':t}var a=RegExp('["'+t+"\n]"),o=t.charCodeAt(0);return e.parse=function(t){var n;return e.parseRows(t,function(t){return n?n(t):(n=Function("d","return {"+t.map(function(t,n){return JSON.stringify(t)+": d["+n+"]"}).join(",")+"}"),void 0)})},e.parseRows=function(t,n){function e(){if(s>=l)return a;if(i)return i=!1,u;var n=s;if(34===t.charCodeAt(n)){for(var e=n;l>e++;)if(34===t.charCodeAt(e)){if(34!==t.charCodeAt(e+1))break;++e}s=e+2;var r=t.charCodeAt(e+1);return 13===r?(i=!0,10===t.charCodeAt(e+2)&&++s):10===r&&(i=!0),t.substring(n+1,e).replace(/""/g,'"')}for(;l>s;){var r=t.charCodeAt(s++),c=1;if(10===r)i=!0;else if(13===r)i=!0,10===t.charCodeAt(s)&&(++s,++c);else if(r!==o)continue;return t.substring(n,s-c)}return t.substring(n)}for(var r,i,u={},a={},c=[],l=t.length,s=0,f=0;(r=e())!==a;){for(var h=[];r!==u&&r!==a;)h.push(r),r=e();(!n||(h=n(h,f++)))&&c.push(h)}return c},e.format=function(t){return t.map(i).join("\n")},e}function Vr(t,n){no.hasOwnProperty(t.type)&&no[t.type](t,n)}function Xr(t,n,e){var r,i=-1,u=t.length-e;for(n.lineStart();u>++i;)r=t[i],n.point(r[0],r[1]);n.lineEnd()}function Zr(t,n){var e=-1,r=t.length;for(n.polygonStart();r>++e;)Xr(t[e],n,1);n.polygonEnd()}function Br(t){return[Math.atan2(t[1],t[0]),Math.asin(Math.max(-1,Math.min(1,t[2])))]}function $r(t,n){return Pu>Math.abs(t[0]-n[0])&&Pu>Math.abs(t[1]-n[1])}function Jr(t){var n=t[0],e=t[1],r=Math.cos(e);return[r*Math.cos(n),r*Math.sin(n),Math.sin(e)]}function Gr(t,n){return t[0]*n[0]+t[1]*n[1]+t[2]*n[2]}function Kr(t,n){return[t[1]*n[2]-t[2]*n[1],t[2]*n[0]-t[0]*n[2],t[0]*n[1]-t[1]*n[0]]}function Wr(t,n){t[0]+=n[0],t[1]+=n[1],t[2]+=n[2]}function Qr(t,n){return[t[0]*n,t[1]*n,t[2]*n]}function ti(t){var n=Math.sqrt(t[0]*t[0]+t[1]*t[1]+t[2]*t[2]);t[0]/=n,t[1]/=n,t[2]/=n}function ni(t){function n(n){function r(e,r){e=t(e,r),n.point(e[0],e[1])}function u(){s=0/0,p.point=a,n.lineStart()}function a(r,u){var a=Jr([r,u]),o=t(r,u);e(s,f,l,h,d,g,s=o[0],f=o[1],l=r,h=a[0],d=a[1],g=a[2],i,n),n.point(s,f)}function o(){p.point=r,n.lineEnd()}function c(){var t,r,c,m,v,y,M;u(),p.point=function(n,e){a(t=n,r=e),c=s,m=f,v=h,y=d,M=g,p.point=a},p.lineEnd=function(){e(s,f,l,h,d,g,c,m,t,v,y,M,i,n),p.lineEnd=o,o()}}var l,s,f,h,d,g,p={point:r,lineStart:u,lineEnd:o,polygonStart:function(){n.polygonStart(),p.lineStart=c},polygonEnd:function(){n.polygonEnd(),p.lineStart=u}};return p}function e(n,i,u,a,o,c,l,s,f,h,d,g,p,m){var v=l-n,y=s-i,M=v*v+y*y;if(M>4*r&&p--){var b=a+h,x=o+d,_=c+g,w=Math.sqrt(b*b+x*x+_*_),S=Math.asin(_/=w),k=Pu>Math.abs(Math.abs(_)-1)?(u+f)/2:Math.atan2(x,b),E=t(k,S),A=E[0],N=E[1],T=A-n,q=N-i,C=y*T-v*q;(C*C/M>r||Math.abs((v*T+y*q)/M-.5)>.3)&&(e(n,i,u,a,o,c,A,N,k,b/=w,x/=w,_,p,m),m.point(A,N),e(A,N,k,b,x,_,l,s,f,h,d,g,p,m))}}var r=.5,i=16;return n.precision=function(t){return arguments.length?(i=(r=t*t)>0&&16,n):Math.sqrt(r)},n}function ei(t,n){function e(t,n){var e=Math.sqrt(u-2*i*Math.sin(n))/i;return[e*Math.sin(t*=i),a-e*Math.cos(t)]}var r=Math.sin(t),i=(r+Math.sin(n))/2,u=1+r*(2*i-r),a=Math.sqrt(u)/i;return e.invert=function(t,n){var e=a-n;return[Math.atan2(t,e)/i,Math.asin((u-(t*t+e*e)*i*i)/(2*i))]},e}function ri(t){function n(t,n){r>t&&(r=t),t>u&&(u=t),i>n&&(i=n),n>a&&(a=n)}function e(){o.point=o.lineEnd=Pn}var r,i,u,a,o={point:n,lineStart:Pn,lineEnd:Pn,polygonStart:function(){o.lineEnd=e},polygonEnd:function(){o.point=n}};return function(n){return a=u=-(r=i=1/0),d3.geo.stream(n,t(o)),[[r,i],[u,a]]}}function ii(t,n){if(!io){++uo,t*=ju;var e=Math.cos(n*=ju);ao+=(e*Math.cos(t)-ao)/uo,oo+=(e*Math.sin(t)-oo)/uo,co+=(Math.sin(n)-co)/uo}}function ui(){var t,n;io=1,ai(),io=2;var e=lo.point;lo.point=function(r,i){e(t=r,n=i)},lo.lineEnd=function(){lo.point(t,n),oi(),lo.lineEnd=oi}}function ai(){function t(t,i){t*=ju;var u=Math.cos(i*=ju),a=u*Math.cos(t),o=u*Math.sin(t),c=Math.sin(i),l=Math.atan2(Math.sqrt((l=e*c-r*o)*l+(l=r*a-n*c)*l+(l=n*o-e*a)*l),n*a+e*o+r*c);uo+=l,ao+=l*(n+(n=a)),oo+=l*(e+(e=o)),co+=l*(r+(r=c))}var n,e,r;io>1||(1>io&&(io=1,uo=ao=oo=co=0),lo.point=function(i,u){i*=ju;var a=Math.cos(u*=ju);n=a*Math.cos(i),e=a*Math.sin(i),r=Math.sin(u),lo.point=t})}function oi(){lo.point=ii}function ci(t,n){var e=Math.cos(t),r=Math.sin(t);return function(i,u,a,o){null!=i?(i=li(e,i),u=li(e,u),(a>0?u>i:i>u)&&(i+=2*a*Ru)):(i=t+2*a*Ru,u=t);for(var c,l=a*n,s=i;a>0?s>u:u>s;s-=l)o.point((c=Br([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],c[1])}}function li(t,n){var e=Jr(n);e[0]-=t,ti(e);var r=Math.acos(Math.max(-1,Math.min(1,-e[1])));return((0>-e[2]?-r:r)+2*Math.PI-Pu)%(2*Math.PI)}function si(t,n,e){return function(r){function i(n,e){t(n,e)&&r.point(n,e)}function u(t,n){m.point(t,n)}function a(){v.point=u,m.lineStart()}function o(){v.point=i,m.lineEnd()}function c(t,n){M.point(t,n),p.push([t,n])}function l(){M.lineStart(),p=[]}function s(){c(p[0][0],p[0][1]),M.lineEnd();var t,n=M.clean(),e=y.buffer(),i=e.length;if(!i)return g=!0,d+=mi(p,-1),p=null,void 0;if(p=null,1&n){t=e[0],h+=mi(t,1);var u,i=t.length-1,a=-1;for(r.lineStart();i>++a;)r.point((u=t[a])[0],u[1]);return r.lineEnd(),void 0}i>1&&2&n&&e.push(e.pop().concat(e.shift())),f.push(e.filter(gi))}var f,h,d,g,p,m=n(r),v={point:i,lineStart:a,lineEnd:o,polygonStart:function(){v.point=c,v.lineStart=l,v.lineEnd=s,g=!1,d=h=0,f=[],r.polygonStart() +},polygonEnd:function(){v.point=i,v.lineStart=a,v.lineEnd=o,f=d3.merge(f),f.length?fi(f,e,r):(-Pu>h||g&&-Pu>d)&&(r.lineStart(),e(null,null,1,r),r.lineEnd()),r.polygonEnd(),f=null},sphere:function(){r.polygonStart(),r.lineStart(),e(null,null,1,r),r.lineEnd(),r.polygonEnd()}},y=pi(),M=n(y);return v}}function fi(t,n,e){var r=[],i=[];if(t.forEach(function(t){var n=t.length;if(!(1>=n)){var e=t[0],u=t[n-1],a={point:e,points:t,other:null,visited:!1,entry:!0,subject:!0},o={point:e,points:[e],other:a,visited:!1,entry:!1,subject:!1};a.other=o,r.push(a),i.push(o),a={point:u,points:[u],other:null,visited:!1,entry:!1,subject:!0},o={point:u,points:[u],other:a,visited:!1,entry:!0,subject:!1},a.other=o,r.push(a),i.push(o)}}),i.sort(di),hi(r),hi(i),r.length)for(var u,a,o,c=r[0];;){for(u=c;u.visited;)if((u=u.next)===c)return;a=u.points,e.lineStart();do{if(u.visited=u.other.visited=!0,u.entry){if(u.subject)for(var l=0;a.length>l;l++)e.point((o=a[l])[0],o[1]);else n(u.point,u.next.point,1,e);u=u.next}else{if(u.subject){a=u.prev.points;for(var l=a.length;--l>=0;)e.point((o=a[l])[0],o[1])}else n(u.point,u.prev.point,-1,e);u=u.prev}u=u.other,a=u.points}while(!u.visited);e.lineEnd()}}function hi(t){if(n=t.length){for(var n,e,r=0,i=t[0];n>++r;)i.next=e=t[r],e.prev=i,i=e;i.next=e=t[0],e.prev=i}}function di(t,n){return(0>(t=t.point)[0]?t[1]-Ru/2-Pu:Ru/2-t[1])-(0>(n=n.point)[0]?n[1]-Ru/2-Pu:Ru/2-n[1])}function gi(t){return t.length>1}function pi(){var t,n=[];return{lineStart:function(){n.push(t=[])},point:function(n,e){t.push([n,e])},lineEnd:Pn,buffer:function(){var e=n;return n=[],t=null,e}}}function mi(t,n){if(!(e=t.length))return 0;for(var e,r,i,u=0,a=0,o=t[0],c=o[0],l=o[1],s=Math.cos(l),f=Math.atan2(n*Math.sin(c)*s,Math.sin(l)),h=1-n*Math.cos(c)*s,d=f;e>++u;)o=t[u],s=Math.cos(l=o[1]),r=Math.atan2(n*Math.sin(c=o[0])*s,Math.sin(l)),i=1-n*Math.cos(c)*s,Pu>Math.abs(h-2)&&Pu>Math.abs(i-2)||(Pu>Math.abs(i)||Pu>Math.abs(h)||(Pu>Math.abs(Math.abs(r-f)-Ru)?i+h>2&&(a+=4*(r-f)):a+=Pu>Math.abs(h-2)?4*(r-d):((3*Ru+r-f)%(2*Ru)-Ru)*(h+i)),d=f,f=r,h=i);return a}function vi(t){var n,e=0/0,r=0/0,i=0/0;return{lineStart:function(){t.lineStart(),n=1},point:function(u,a){var o=u>0?Ru:-Ru,c=Math.abs(u-e);Pu>Math.abs(c-Ru)?(t.point(e,r=(r+a)/2>0?Ru/2:-Ru/2),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(o,r),t.point(u,r),n=0):i!==o&&c>=Ru&&(Pu>Math.abs(e-i)&&(e-=i*Pu),Pu>Math.abs(u-o)&&(u-=o*Pu),r=yi(e,r,u,a),t.point(i,r),t.lineEnd(),t.lineStart(),t.point(o,r),n=0),t.point(e=u,r=a),i=o},lineEnd:function(){t.lineEnd(),e=r=0/0},clean:function(){return 2-n}}}function yi(t,n,e,r){var i,u,a=Math.sin(t-e);return Math.abs(a)>Pu?Math.atan((Math.sin(n)*(u=Math.cos(r))*Math.sin(e)-Math.sin(r)*(i=Math.cos(n))*Math.sin(t))/(i*u*a)):(n+r)/2}function Mi(t,n,e,r){var i;if(null==t)i=e*Ru/2,r.point(-Ru,i),r.point(0,i),r.point(Ru,i),r.point(Ru,0),r.point(Ru,-i),r.point(0,-i),r.point(-Ru,-i),r.point(-Ru,0),r.point(-Ru,i);else if(Math.abs(t[0]-n[0])>Pu){var u=(t[0]<n[0]?1:-1)*Ru;i=e*u/2,r.point(-u,i),r.point(0,i),r.point(u,i)}else r.point(n[0],n[1])}function bi(t){function n(t,n){return Math.cos(t)*Math.cos(n)>u}function e(t){var e,i,u,a;return{lineStart:function(){u=i=!1,a=1},point:function(o,c){var l,s=[o,c],f=n(o,c);!e&&(u=i=f)&&t.lineStart(),f!==i&&(l=r(e,s),($r(e,l)||$r(s,l))&&(s[0]+=Pu,s[1]+=Pu,f=n(s[0],s[1]))),f!==i&&(a=0,(i=f)?(t.lineStart(),l=r(s,e),t.point(l[0],l[1])):(l=r(e,s),t.point(l[0],l[1]),t.lineEnd()),e=l),!f||e&&$r(e,s)||t.point(s[0],s[1]),e=s},lineEnd:function(){i&&t.lineEnd(),e=null},clean:function(){return a|(u&&i)<<1}}}function r(t,n){var e=Jr(t,0),r=Jr(n,0),i=[1,0,0],a=Kr(e,r),o=Gr(a,a),c=a[0],l=o-c*c;if(!l)return t;var s=u*o/l,f=-u*c/l,h=Kr(i,a),d=Qr(i,s),g=Qr(a,f);Wr(d,g);var p=h,m=Gr(d,p),v=Gr(p,p),y=Math.sqrt(m*m-v*(Gr(d,d)-1)),M=Qr(p,(-m-y)/v);return Wr(M,d),Br(M)}var i=t*ju,u=Math.cos(i),a=ci(i,6*ju);return si(n,e,a)}function xi(t,n){function e(e,r){return e=t(e,r),n(e[0],e[1])}return t.invert&&n.invert&&(e.invert=function(e,r){return e=n.invert(e,r),e&&t.invert(e[0],e[1])}),e}function _i(t,n){return[t,n]}function wi(t,n,e){var r=d3.range(t,n-Pu,e).concat(n);return function(t){return r.map(function(n){return[t,n]})}}function Si(t,n,e){var r=d3.range(t,n-Pu,e).concat(n);return function(t){return r.map(function(n){return[n,t]})}}function ki(t,n,e,r){function i(t){var n=Math.sin(t*=d)*g,e=Math.sin(d-t)*g,r=e*l+n*f,i=e*s+n*h,u=e*a+n*c;return[Math.atan2(i,r)/ju,Math.atan2(u,Math.sqrt(r*r+i*i))/ju]}var u=Math.cos(n),a=Math.sin(n),o=Math.cos(r),c=Math.sin(r),l=u*Math.cos(t),s=u*Math.sin(t),f=o*Math.cos(e),h=o*Math.sin(e),d=Math.acos(Math.max(-1,Math.min(1,a*c+u*o*Math.cos(e-t)))),g=1/Math.sin(d);return i.distance=d,i}function Ei(t,n){return[t/(2*Ru),Math.max(-.5,Math.min(.5,Math.log(Math.tan(Ru/4+n/2))/(2*Ru)))]}function Ai(t){return"m0,"+t+"a"+t+","+t+" 0 1,1 0,"+-2*t+"a"+t+","+t+" 0 1,1 0,"+2*t+"z"}function Ni(t){var n=ni(function(n,e){return t([n*Ou,e*Ou])});return function(t){return t=n(t),{point:function(n,e){t.point(n*ju,e*ju)},sphere:function(){t.sphere()},lineStart:function(){t.lineStart()},lineEnd:function(){t.lineEnd()},polygonStart:function(){t.polygonStart()},polygonEnd:function(){t.polygonEnd()}}}}function Ti(){function t(t,n){a.push("M",t,",",n,u)}function n(t,n){a.push("M",t,",",n),o.point=e}function e(t,n){a.push("L",t,",",n)}function r(){o.point=t}function i(){a.push("Z")}var u=Ai(4.5),a=[],o={point:t,lineStart:function(){o.point=n},lineEnd:r,polygonStart:function(){o.lineEnd=i},polygonEnd:function(){o.lineEnd=r,o.point=t},pointRadius:function(t){return u=Ai(t),o},result:function(){if(a.length){var t=a.join("");return a=[],t}}};return o}function qi(t){function n(n,e){t.moveTo(n,e),t.arc(n,e,a,0,2*Ru)}function e(n,e){t.moveTo(n,e),o.point=r}function r(n,e){t.lineTo(n,e)}function i(){o.point=n}function u(){t.closePath()}var a=4.5,o={point:n,lineStart:function(){o.point=e},lineEnd:i,polygonStart:function(){o.lineEnd=u},polygonEnd:function(){o.lineEnd=i,o.point=n},pointRadius:function(t){return a=t,o},result:Pn};return o}function Ci(){function t(t,n){po+=i*t-r*n,r=t,i=n}var n,e,r,i;mo.point=function(u,a){mo.point=t,n=r=u,e=i=a},mo.lineEnd=function(){t(n,e)}}function zi(t,n){io||(ao+=t,oo+=n,++co)}function Di(){function t(t,r){var i=t-n,u=r-e,a=Math.sqrt(i*i+u*u);ao+=a*(n+t)/2,oo+=a*(e+r)/2,co+=a,n=t,e=r}var n,e;if(1!==io){if(!(1>io))return;io=1,ao=oo=co=0}vo.point=function(r,i){vo.point=t,n=r,e=i}}function Li(){vo.point=zi}function Fi(){function t(t,n){var e=i*t-r*n;ao+=e*(r+t),oo+=e*(i+n),co+=3*e,r=t,i=n}var n,e,r,i;2>io&&(io=2,ao=oo=co=0),vo.point=function(u,a){vo.point=t,n=r=u,e=i=a},vo.lineEnd=function(){t(n,e)}}function Hi(){function t(t,n){if(t*=ju,n*=ju,!(Pu>Math.abs(Math.abs(u)-Ru/2)&&Pu>Math.abs(Math.abs(n)-Ru/2))){var e=Math.cos(n),c=Math.sin(n);if(Pu>Math.abs(u-Ru/2))Mo+=2*(t-r);else{var l=t-i,s=Math.cos(l),f=Math.atan2(Math.sqrt((f=e*Math.sin(l))*f+(f=a*c-o*e*s)*f),o*c+a*e*s),h=(f+Ru+u+n)/4;Mo+=(0>l&&l>-Ru||l>Ru?-4:4)*Math.atan(Math.sqrt(Math.abs(Math.tan(h)*Math.tan(h-f/2)*Math.tan(h-Ru/4-u/2)*Math.tan(h-Ru/4-n/2))))}r=i,i=t,u=n,a=e,o=c}}var n,e,r,i,u,a,o;bo.point=function(c,l){bo.point=t,r=i=(n=c)*ju,u=(e=l)*ju,a=Math.cos(u),o=Math.sin(u)},bo.lineEnd=function(){t(n,e)}}function Ri(t){return Pi(function(){return t})()}function Pi(t){function n(t){return t=a(t[0]*ju,t[1]*ju),[t[0]*s+o,c-t[1]*s]}function e(t){return t=a.invert((t[0]-o)/s,(c-t[1])/s),t&&[t[0]*Ou,t[1]*Ou]}function r(){a=xi(u=Oi(p,m,v),i);var t=i(d,g);return o=f-t[0]*s,c=h+t[1]*s,n}var i,u,a,o,c,l=ni(function(t,n){return t=i(t,n),[t[0]*s+o,c-t[1]*s]}),s=150,f=480,h=250,d=0,g=0,p=0,m=0,v=0,y=so,M=null;return n.stream=function(t){return ji(u,y(l(t)))},n.clipAngle=function(t){return arguments.length?(y=null==t?(M=t,so):bi(M=+t),n):M},n.scale=function(t){return arguments.length?(s=+t,r()):s},n.translate=function(t){return arguments.length?(f=+t[0],h=+t[1],r()):[f,h]},n.center=function(t){return arguments.length?(d=t[0]%360*ju,g=t[1]%360*ju,r()):[d*Ou,g*Ou]},n.rotate=function(t){return arguments.length?(p=t[0]%360*ju,m=t[1]%360*ju,v=t.length>2?t[2]%360*ju:0,r()):[p*Ou,m*Ou,v*Ou]},d3.rebind(n,l,"precision"),function(){return i=t.apply(this,arguments),n.invert=i.invert&&e,r()}}function ji(t,n){return{point:function(e,r){r=t(e*ju,r*ju),e=r[0],n.point(e>Ru?e-2*Ru:-Ru>e?e+2*Ru:e,r[1])},sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function Oi(t,n,e){return t?n||e?xi(Ui(t),Ii(n,e)):Ui(t):n||e?Ii(n,e):_i}function Yi(t){return function(n,e){return n+=t,[n>Ru?n-2*Ru:-Ru>n?n+2*Ru:n,e]}}function Ui(t){var n=Yi(t);return n.invert=Yi(-t),n}function Ii(t,n){function e(t,n){var e=Math.cos(n),o=Math.cos(t)*e,c=Math.sin(t)*e,l=Math.sin(n),s=l*r+o*i;return[Math.atan2(c*u-s*a,o*r-l*i),Math.asin(Math.max(-1,Math.min(1,s*u+c*a)))]}var r=Math.cos(t),i=Math.sin(t),u=Math.cos(n),a=Math.sin(n);return e.invert=function(t,n){var e=Math.cos(n),o=Math.cos(t)*e,c=Math.sin(t)*e,l=Math.sin(n),s=l*u-c*a;return[Math.atan2(c*u+l*a,o*r+s*i),Math.asin(Math.max(-1,Math.min(1,s*r-o*i)))]},e}function Vi(t,n){function e(n,e){var r=Math.cos(n),i=Math.cos(e),u=t(r*i);return[u*i*Math.sin(n),u*Math.sin(e)]}return e.invert=function(t,e){var r=Math.sqrt(t*t+e*e),i=n(r),u=Math.sin(i),a=Math.cos(i);return[Math.atan2(t*u,r*a),Math.asin(r&&e*u/r)]},e}function Xi(t,n,e,r){var i,u,a,o,c,l,s;return i=r[t],u=i[0],a=i[1],i=r[n],o=i[0],c=i[1],i=r[e],l=i[0],s=i[1],(s-a)*(o-u)-(c-a)*(l-u)>0}function Zi(t,n,e){return(e[0]-n[0])*(t[1]-n[1])<(e[1]-n[1])*(t[0]-n[0])}function Bi(t,n,e,r){var i=t[0],u=e[0],a=n[0]-i,o=r[0]-u,c=t[1],l=e[1],s=n[1]-c,f=r[1]-l,h=(o*(c-l)-f*(i-u))/(f*a-o*s);return[i+h*a,c+h*s]}function $i(t,n){var e={list:t.map(function(t,n){return{index:n,x:t[0],y:t[1]}}).sort(function(t,n){return t.y<n.y?-1:t.y>n.y?1:t.x<n.x?-1:t.x>n.x?1:0}),bottomSite:null},r={list:[],leftEnd:null,rightEnd:null,init:function(){r.leftEnd=r.createHalfEdge(null,"l"),r.rightEnd=r.createHalfEdge(null,"l"),r.leftEnd.r=r.rightEnd,r.rightEnd.l=r.leftEnd,r.list.unshift(r.leftEnd,r.rightEnd)},createHalfEdge:function(t,n){return{edge:t,side:n,vertex:null,l:null,r:null}},insert:function(t,n){n.l=t,n.r=t.r,t.r.l=n,t.r=n},leftBound:function(t){var n=r.leftEnd;do n=n.r;while(n!=r.rightEnd&&i.rightOf(n,t));return n=n.l},del:function(t){t.l.r=t.r,t.r.l=t.l,t.edge=null},right:function(t){return t.r},left:function(t){return t.l},leftRegion:function(t){return null==t.edge?e.bottomSite:t.edge.region[t.side]},rightRegion:function(t){return null==t.edge?e.bottomSite:t.edge.region[_o[t.side]]}},i={bisect:function(t,n){var e={region:{l:t,r:n},ep:{l:null,r:null}},r=n.x-t.x,i=n.y-t.y,u=r>0?r:-r,a=i>0?i:-i;return e.c=t.x*r+t.y*i+.5*(r*r+i*i),u>a?(e.a=1,e.b=i/r,e.c/=r):(e.b=1,e.a=r/i,e.c/=i),e},intersect:function(t,n){var e=t.edge,r=n.edge;if(!e||!r||e.region.r==r.region.r)return null;var i=e.a*r.b-e.b*r.a;if(1e-10>Math.abs(i))return null;var u,a,o=(e.c*r.b-r.c*e.b)/i,c=(r.c*e.a-e.c*r.a)/i,l=e.region.r,s=r.region.r;l.y<s.y||l.y==s.y&&l.x<s.x?(u=t,a=e):(u=n,a=r);var f=o>=a.region.r.x;return f&&"l"===u.side||!f&&"r"===u.side?null:{x:o,y:c}},rightOf:function(t,n){var e=t.edge,r=e.region.r,i=n.x>r.x;if(i&&"l"===t.side)return 1;if(!i&&"r"===t.side)return 0;if(1===e.a){var u=n.y-r.y,a=n.x-r.x,o=0,c=0;if(!i&&0>e.b||i&&e.b>=0?c=o=u>=e.b*a:(c=n.x+n.y*e.b>e.c,0>e.b&&(c=!c),c||(o=1)),!o){var l=r.x-e.region.l.x;c=e.b*(a*a-u*u)<l*u*(1+2*a/l+e.b*e.b),0>e.b&&(c=!c)}}else{var s=e.c-e.a*n.x,f=n.y-s,h=n.x-r.x,d=s-r.y;c=f*f>h*h+d*d}return"l"===t.side?c:!c},endPoint:function(t,e,r){t.ep[e]=r,t.ep[_o[e]]&&n(t)},distance:function(t,n){var e=t.x-n.x,r=t.y-n.y;return Math.sqrt(e*e+r*r)}},u={list:[],insert:function(t,n,e){t.vertex=n,t.ystar=n.y+e;for(var r=0,i=u.list,a=i.length;a>r;r++){var o=i[r];if(!(t.ystar>o.ystar||t.ystar==o.ystar&&n.x>o.vertex.x))break}i.splice(r,0,t)},del:function(t){for(var n=0,e=u.list,r=e.length;r>n&&e[n]!=t;++n);e.splice(n,1)},empty:function(){return 0===u.list.length},nextEvent:function(t){for(var n=0,e=u.list,r=e.length;r>n;++n)if(e[n]==t)return e[n+1];return null},min:function(){var t=u.list[0];return{x:t.vertex.x,y:t.ystar}},extractMin:function(){return u.list.shift()}};r.init(),e.bottomSite=e.list.shift();for(var a,o,c,l,s,f,h,d,g,p,m,v,y,M=e.list.shift();;)if(u.empty()||(a=u.min()),M&&(u.empty()||M.y<a.y||M.y==a.y&&M.x<a.x))o=r.leftBound(M),c=r.right(o),h=r.rightRegion(o),v=i.bisect(h,M),f=r.createHalfEdge(v,"l"),r.insert(o,f),p=i.intersect(o,f),p&&(u.del(o),u.insert(o,p,i.distance(p,M))),o=f,f=r.createHalfEdge(v,"r"),r.insert(o,f),p=i.intersect(f,c),p&&u.insert(f,p,i.distance(p,M)),M=e.list.shift();else{if(u.empty())break;o=u.extractMin(),l=r.left(o),c=r.right(o),s=r.right(c),h=r.leftRegion(o),d=r.rightRegion(c),m=o.vertex,i.endPoint(o.edge,o.side,m),i.endPoint(c.edge,c.side,m),r.del(o),u.del(c),r.del(c),y="l",h.y>d.y&&(g=h,h=d,d=g,y="r"),v=i.bisect(h,d),f=r.createHalfEdge(v,y),r.insert(l,f),i.endPoint(v,_o[y],m),p=i.intersect(l,f),p&&(u.del(l),u.insert(l,p,i.distance(p,h))),p=i.intersect(f,s),p&&u.insert(f,p,i.distance(p,h))}for(o=r.right(r.leftEnd);o!=r.rightEnd;o=r.right(o))n(o.edge)}function Ji(){return{leaf:!0,nodes:[],point:null}}function Gi(t,n,e,r,i,u){if(!t(n,e,r,i,u)){var a=.5*(e+i),o=.5*(r+u),c=n.nodes;c[0]&&Gi(t,c[0],e,r,a,o),c[1]&&Gi(t,c[1],a,r,i,o),c[2]&&Gi(t,c[2],e,o,a,u),c[3]&&Gi(t,c[3],a,o,i,u)}}function Ki(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Wi(t,n,e,r){for(var i,u,a=0,o=n.length,c=e.length;o>a;){if(r>=c)return-1;if(i=n.charCodeAt(a++),37===i){if(u=Yo[n.charAt(a++)],!u||0>(r=u(t,e,r)))return-1}else if(i!=e.charCodeAt(r++))return-1}return r}function Qi(t){return RegExp("^(?:"+t.map(d3.requote).join("|")+")","i")}function tu(t){for(var n=new u,e=-1,r=t.length;r>++e;)n.set(t[e].toLowerCase(),e);return n}function nu(t,n,e){t+="";var r=t.length;return e>r?Array(e-r+1).join(n)+t:t}function eu(t,n,e){Lo.lastIndex=0;var r=Lo.exec(n.substring(e));return r?e+=r[0].length:-1}function ru(t,n,e){Do.lastIndex=0;var r=Do.exec(n.substring(e));return r?e+=r[0].length:-1}function iu(t,n,e){Ro.lastIndex=0;var r=Ro.exec(n.substring(e));return r?(t.m=Po.get(r[0].toLowerCase()),e+=r[0].length):-1}function uu(t,n,e){Fo.lastIndex=0;var r=Fo.exec(n.substring(e));return r?(t.m=Ho.get(r[0].toLowerCase()),e+=r[0].length):-1}function au(t,n,e){return Wi(t,""+Oo.c,n,e)}function ou(t,n,e){return Wi(t,""+Oo.x,n,e)}function cu(t,n,e){return Wi(t,""+Oo.X,n,e)}function lu(t,n,e){Uo.lastIndex=0;var r=Uo.exec(n.substring(e,e+4));return r?(t.y=+r[0],e+=r[0].length):-1}function su(t,n,e){Uo.lastIndex=0;var r=Uo.exec(n.substring(e,e+2));return r?(t.y=fu(+r[0]),e+=r[0].length):-1}function fu(t){return t+(t>68?1900:2e3)}function hu(t,n,e){Uo.lastIndex=0;var r=Uo.exec(n.substring(e,e+2));return r?(t.m=r[0]-1,e+=r[0].length):-1}function du(t,n,e){Uo.lastIndex=0;var r=Uo.exec(n.substring(e,e+2));return r?(t.d=+r[0],e+=r[0].length):-1}function gu(t,n,e){Uo.lastIndex=0;var r=Uo.exec(n.substring(e,e+2));return r?(t.H=+r[0],e+=r[0].length):-1}function pu(t,n,e){Uo.lastIndex=0;var r=Uo.exec(n.substring(e,e+2));return r?(t.M=+r[0],e+=r[0].length):-1}function mu(t,n,e){Uo.lastIndex=0;var r=Uo.exec(n.substring(e,e+2));return r?(t.S=+r[0],e+=r[0].length):-1}function vu(t,n,e){Uo.lastIndex=0;var r=Uo.exec(n.substring(e,e+3));return r?(t.L=+r[0],e+=r[0].length):-1}function yu(t,n,e){var r=Io.get(n.substring(e,e+=2).toLowerCase());return null==r?-1:(t.p=r,e)}function Mu(t){var n=t.getTimezoneOffset(),e=n>0?"-":"+",r=~~(Math.abs(n)/60),i=Math.abs(n)%60;return e+nu(r,"0",2)+nu(i,"0",2)}function bu(t){return t.toISOString()}function xu(t,n,e){function r(n){var e=t(n),r=u(e,1);return r-n>n-e?e:r}function i(e){return n(e=t(new wo(e-1)),1),e}function u(t,e){return n(t=new wo(+t),e),t}function a(t,r,u){var a=i(t),o=[];if(u>1)for(;r>a;)e(a)%u||o.push(new Date(+a)),n(a,1);else for(;r>a;)o.push(new Date(+a)),n(a,1);return o}function o(t,n,e){try{wo=Ki;var r=new Ki;return r._=t,a(r,n,e)}finally{wo=Date}}t.floor=t,t.round=r,t.ceil=i,t.offset=u,t.range=a;var c=t.utc=_u(t);return c.floor=c,c.round=_u(r),c.ceil=_u(i),c.offset=_u(u),c.range=o,t}function _u(t){return function(n,e){try{wo=Ki;var r=new Ki;return r._=n,t(r,e)._}finally{wo=Date}}}function wu(t,n,e){function r(n){return t(n)}return r.invert=function(n){return ku(t.invert(n))},r.domain=function(n){return arguments.length?(t.domain(n),r):t.domain().map(ku)},r.nice=function(t){return r.domain(Yn(r.domain(),function(){return t}))},r.ticks=function(e,i){var u=Su(r.domain());if("function"!=typeof e){var a=u[1]-u[0],o=a/e,c=d3.bisect(Xo,o);if(c==Xo.length)return n.year(u,e);if(!c)return t.ticks(e).map(ku);Math.log(o/Xo[c-1])<Math.log(Xo[c]/o)&&--c,e=n[c],i=e[1],e=e[0].range}return e(u[0],new Date(+u[1]+1),i)},r.tickFormat=function(){return e},r.copy=function(){return wu(t.copy(),n,e)},d3.rebind(r,t,"range","rangeRound","interpolate","clamp")}function Su(t){var n=t[0],e=t[t.length-1];return e>n?[n,e]:[e,n]}function ku(t){return new Date(t)}function Eu(t){return function(n){for(var e=t.length-1,r=t[e];!r[1](n);)r=t[--e];return r[0](n)}}function Au(t){var n=new Date(t,0,1);return n.setFullYear(t),n}function Nu(t){var n=t.getFullYear(),e=Au(n),r=Au(n+1);return n+(t-e)/(r-e)}function Tu(t){var n=new Date(Date.UTC(t,0,1));return n.setUTCFullYear(t),n}function qu(t){var n=t.getUTCFullYear(),e=Tu(n),r=Tu(n+1);return n+(t-e)/(r-e)}var Cu=".",zu=",",Du=[3,3];Date.now||(Date.now=function(){return+new Date});try{document.createElement("div").style.setProperty("opacity",0,"")}catch(Lu){var Fu=CSSStyleDeclaration.prototype,Hu=Fu.setProperty;Fu.setProperty=function(t,n,e){Hu.call(this,t,n+"",e)}}d3={version:"3.0.3"};var Ru=Math.PI,Pu=1e-6,ju=Ru/180,Ou=180/Ru,Yu=i;try{Yu(document.documentElement.childNodes)[0].nodeType}catch(Uu){Yu=r}var Iu=[].__proto__?function(t,n){t.__proto__=n}:function(t,n){for(var e in n)t[e]=n[e]};d3.map=function(t){var n=new u;for(var e in t)n.set(e,t[e]);return n},e(u,{has:function(t){return Vu+t in this},get:function(t){return this[Vu+t]},set:function(t,n){return this[Vu+t]=n},remove:function(t){return t=Vu+t,t in this&&delete this[t]},keys:function(){var t=[];return this.forEach(function(n){t.push(n)}),t},values:function(){var t=[];return this.forEach(function(n,e){t.push(e)}),t},entries:function(){var t=[];return this.forEach(function(n,e){t.push({key:n,value:e})}),t},forEach:function(t){for(var n in this)n.charCodeAt(0)===Xu&&t.call(this,n.substring(1),this[n])}});var Vu="\0",Xu=Vu.charCodeAt(0);d3.functor=c,d3.rebind=function(t,n){for(var e,r=1,i=arguments.length;i>++r;)t[e=arguments[r]]=l(t,n,n[e]);return t},d3.ascending=function(t,n){return n>t?-1:t>n?1:t>=n?0:0/0},d3.descending=function(t,n){return t>n?-1:n>t?1:n>=t?0:0/0},d3.mean=function(t,n){var e,r=t.length,i=0,u=-1,a=0;if(1===arguments.length)for(;r>++u;)s(e=t[u])&&(i+=(e-i)/++a);else for(;r>++u;)s(e=n.call(t,t[u],u))&&(i+=(e-i)/++a);return a?i:void 0},d3.median=function(t,n){return arguments.length>1&&(t=t.map(n)),t=t.filter(s),t.length?d3.quantile(t.sort(d3.ascending),.5):void 0},d3.min=function(t,n){var e,r,i=-1,u=t.length;if(1===arguments.length){for(;u>++i&&(null==(e=t[i])||e!=e);)e=void 0;for(;u>++i;)null!=(r=t[i])&&e>r&&(e=r)}else{for(;u>++i&&(null==(e=n.call(t,t[i],i))||e!=e);)e=void 0;for(;u>++i;)null!=(r=n.call(t,t[i],i))&&e>r&&(e=r)}return e},d3.max=function(t,n){var e,r,i=-1,u=t.length;if(1===arguments.length){for(;u>++i&&(null==(e=t[i])||e!=e);)e=void 0;for(;u>++i;)null!=(r=t[i])&&r>e&&(e=r)}else{for(;u>++i&&(null==(e=n.call(t,t[i],i))||e!=e);)e=void 0;for(;u>++i;)null!=(r=n.call(t,t[i],i))&&r>e&&(e=r)}return e},d3.extent=function(t,n){var e,r,i,u=-1,a=t.length;if(1===arguments.length){for(;a>++u&&(null==(e=i=t[u])||e!=e);)e=i=void 0;for(;a>++u;)null!=(r=t[u])&&(e>r&&(e=r),r>i&&(i=r))}else{for(;a>++u&&(null==(e=i=n.call(t,t[u],u))||e!=e);)e=void 0;for(;a>++u;)null!=(r=n.call(t,t[u],u))&&(e>r&&(e=r),r>i&&(i=r))}return[e,i]},d3.random={normal:function(t,n){var e=arguments.length;return 2>e&&(n=1),1>e&&(t=0),function(){var e,r,i;do e=2*Math.random()-1,r=2*Math.random()-1,i=e*e+r*r;while(!i||i>1);return t+n*e*Math.sqrt(-2*Math.log(i)/i)}},logNormal:function(t,n){var e=arguments.length;2>e&&(n=1),1>e&&(t=0);var r=d3.random.normal();return function(){return Math.exp(t+n*r())}},irwinHall:function(t){return function(){for(var n=0,e=0;t>e;e++)n+=Math.random();return n/t}}},d3.sum=function(t,n){var e,r=0,i=t.length,u=-1;if(1===arguments.length)for(;i>++u;)isNaN(e=+t[u])||(r+=e);else for(;i>++u;)isNaN(e=+n.call(t,t[u],u))||(r+=e);return r},d3.quantile=function(t,n){var e=(t.length-1)*n+1,r=Math.floor(e),i=+t[r-1],u=e-r;return u?i+u*(t[r]-i):i},d3.shuffle=function(t){for(var n,e,r=t.length;r;)e=0|Math.random()*r--,n=t[r],t[r]=t[e],t[e]=n;return t},d3.transpose=function(t){return d3.zip.apply(d3,t)},d3.zip=function(){if(!(r=arguments.length))return[];for(var t=-1,n=d3.min(arguments,f),e=Array(n);n>++t;)for(var r,i=-1,u=e[t]=Array(r);r>++i;)u[i]=arguments[i][t];return e},d3.bisector=function(t){return{left:function(n,e,r,i){for(3>arguments.length&&(r=0),4>arguments.length&&(i=n.length);i>r;){var u=r+i>>>1;e>t.call(n,n[u],u)?r=u+1:i=u}return r},right:function(n,e,r,i){for(3>arguments.length&&(r=0),4>arguments.length&&(i=n.length);i>r;){var u=r+i>>>1;t.call(n,n[u],u)>e?i=u:r=u+1}return r}}};var Zu=d3.bisector(function(t){return t});d3.bisectLeft=Zu.left,d3.bisect=d3.bisectRight=Zu.right,d3.nest=function(){function t(n,o){if(o>=a.length)return r?r.call(i,n):e?n.sort(e):n;for(var c,l,s,f=-1,h=n.length,d=a[o++],g=new u,p={};h>++f;)(s=g.get(c=d(l=n[f])))?s.push(l):g.set(c,[l]);return g.forEach(function(n,e){p[n]=t(e,o)}),p}function n(t,e){if(e>=a.length)return t;var r,i=[],u=o[e++];for(r in t)i.push({key:r,values:n(t[r],e)});return u&&i.sort(function(t,n){return u(t.key,n.key)}),i}var e,r,i={},a=[],o=[];return i.map=function(n){return t(n,0)},i.entries=function(e){return n(t(e,0),0)},i.key=function(t){return a.push(t),i},i.sortKeys=function(t){return o[a.length-1]=t,i},i.sortValues=function(t){return e=t,i},i.rollup=function(t){return r=t,i},i},d3.keys=function(t){var n=[];for(var e in t)n.push(e);return n},d3.values=function(t){var n=[];for(var e in t)n.push(t[e]);return n},d3.entries=function(t){var n=[];for(var e in t)n.push({key:e,value:t[e]});return n},d3.permute=function(t,n){for(var e=[],r=-1,i=n.length;i>++r;)e[r]=t[n[r]];return e},d3.merge=function(t){return Array.prototype.concat.apply([],t)},d3.range=function(t,n,e){if(3>arguments.length&&(e=1,2>arguments.length&&(n=t,t=0)),1/0===(n-t)/e)throw Error("infinite range");var r,i=[],u=d(Math.abs(e)),a=-1;if(t*=u,n*=u,e*=u,0>e)for(;(r=t+e*++a)>n;)i.push(r/u);else for(;n>(r=t+e*++a);)i.push(r/u);return i},d3.requote=function(t){return t.replace(Bu,"\\$&")};var Bu=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;d3.round=function(t,n){return n?Math.round(t*(n=Math.pow(10,n)))/n:Math.round(t)},d3.xhr=function(t,n,e){function r(){var t=l.status;!t&&l.responseText||t>=200&&300>t||304===t?u.load.call(i,c.call(i,l)):u.error.call(i,l)}var i={},u=d3.dispatch("progress","load","error"),o={},c=a,l=new(window.XDomainRequest&&/^(http(s)?:)?\/\//.test(t)?XDomainRequest:XMLHttpRequest);return"onload"in l?l.onload=l.onerror=r:l.onreadystatechange=function(){l.readyState>3&&r()},l.onprogress=function(t){var n=d3.event;d3.event=t;try{u.progress.call(i,l)}finally{d3.event=n}},i.header=function(t,n){return t=(t+"").toLowerCase(),2>arguments.length?o[t]:(null==n?delete o[t]:o[t]=n+"",i)},i.mimeType=function(t){return arguments.length?(n=null==t?null:t+"",i):n},i.response=function(t){return c=t,i},["get","post"].forEach(function(t){i[t]=function(){return i.send.apply(i,[t].concat(Yu(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),l.open(e,t,!0),null==n||"accept"in o||(o.accept=n+",*/*"),l.setRequestHeader)for(var a in o)l.setRequestHeader(a,o[a]);return null!=n&&l.overrideMimeType&&l.overrideMimeType(n),null!=u&&i.on("error",u).on("load",function(t){u(null,t)}),l.send(null==r?null:r),i},i.abort=function(){return l.abort(),i},d3.rebind(i,u,"on"),2===arguments.length&&"function"==typeof n&&(e=n,n=null),null==e?i:i.get(g(e))},d3.text=function(){return d3.xhr.apply(d3,arguments).response(p)},d3.json=function(t,n){return d3.xhr(t,"application/json",n).response(m)},d3.html=function(t,n){return d3.xhr(t,"text/html",n).response(v)},d3.xml=function(){return d3.xhr.apply(d3,arguments).response(y)};var $u={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};d3.ns={prefix:$u,qualify:function(t){var n=t.indexOf(":"),e=t;return n>=0&&(e=t.substring(0,n),t=t.substring(n+1)),$u.hasOwnProperty(e)?{space:$u[e],local:t}:t}},d3.dispatch=function(){for(var t=new M,n=-1,e=arguments.length;e>++n;)t[arguments[n]]=b(t);return t},M.prototype.on=function(t,n){var e=t.indexOf("."),r="";return e>0&&(r=t.substring(e+1),t=t.substring(0,e)),2>arguments.length?this[t].on(r):this[t].on(r,n)},d3.format=function(t){var n=Ju.exec(t),e=n[1]||" ",r=n[2]||">",i=n[3]||"",u=n[4]||"",a=n[5],o=+n[6],c=n[7],l=n[8],s=n[9],f=1,h="",d=!1;switch(l&&(l=+l.substring(1)),(a||"0"===e&&"="===r)&&(a=e="0",r="=",c&&(o-=Math.floor((o-1)/4))),s){case"n":c=!0,s="g";break;case"%":f=100,h="%",s="f";break;case"p":f=100,h="%",s="r";break;case"b":case"o":case"x":case"X":u&&(u="0"+s.toLowerCase());case"c":case"d":d=!0,l=0;break;case"s":f=-1,s="r"}"#"===u&&(u=""),"r"!=s||l||(s="g"),s=Gu.get(s)||_;var g=a&&c;return function(t){if(d&&t%1)return"";var n=0>t||0===t&&0>1/t?(t=-t,"-"):i;if(0>f){var p=d3.formatPrefix(t,l);t=p.scale(t),h=p.symbol}else t*=f;t=s(t,l),!a&&c&&(t=Ku(t));var m=u.length+t.length+(g?0:n.length),v=o>m?Array(m=o-m+1).join(e):"";return g&&(t=Ku(v+t)),Cu&&t.replace(".",Cu),n+=u,("<"===r?n+t+v:">"===r?v+n+t:"^"===r?v.substring(0,m>>=1)+n+t+v.substring(m):n+(g?t:v+t))+h}};var Ju=/(?:([^{])?([<>=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/,Gu=d3.map({b:function(t){return t.toString(2)},c:function(t){return String.fromCharCode(t)},o:function(t){return t.toString(8)},x:function(t){return t.toString(16)},X:function(t){return t.toString(16).toUpperCase()},g:function(t,n){return t.toPrecision(n)},e:function(t,n){return t.toExponential(n)},f:function(t,n){return t.toFixed(n)},r:function(t,n){return d3.round(t,n=x(t,n)).toFixed(Math.max(0,Math.min(20,n)))}}),Ku=a;if(Du){var Wu=Du.length;Ku=function(t){for(var n=t.lastIndexOf("."),e=n>=0?"."+t.substring(n+1):(n=t.length,""),r=[],i=0,u=Du[0];n>0&&u>0;)r.push(t.substring(n-=u,n+u)),u=Du[i=(i+1)%Wu];return r.reverse().join(zu||"")+e}}var Qu=["y","z","a","f","p","n","μ","m","","k","M","G","T","P","E","Z","Y"].map(w);d3.formatPrefix=function(t,n){var e=0;return t&&(0>t&&(t*=-1),n&&(t=d3.round(t,x(t,n))),e=1+Math.floor(1e-12+Math.log(t)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((0>=e?e+1:e-1)/3)))),Qu[8+e/3]};var ta=function(){return a},na=d3.map({linear:ta,poly:q,quad:function(){return A},cubic:function(){return N},sin:function(){return C},exp:function(){return z},circle:function(){return D},elastic:L,back:F,bounce:function(){return H}}),ea=d3.map({"in":a,out:k,"in-out":E,"out-in":function(t){return E(k(t))}});d3.ease=function(t){var n=t.indexOf("-"),e=n>=0?t.substring(0,n):t,r=n>=0?t.substring(n+1):"in";return e=na.get(e)||ta,r=ea.get(r)||a,S(r(e.apply(null,Array.prototype.slice.call(arguments,1))))},d3.event=null,d3.transform=function(t){var n=document.createElementNS(d3.ns.prefix.svg,"g");return(d3.transform=function(t){n.setAttribute("transform",t);var e=n.transform.baseVal.consolidate();return new O(e?e.matrix:ra)})(t)},O.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var ra={a:1,b:0,c:0,d:1,e:0,f:0};d3.interpolate=function(t,n){for(var e,r=d3.interpolators.length;--r>=0&&!(e=d3.interpolators[r](t,n)););return e},d3.interpolateNumber=function(t,n){return n-=t,function(e){return t+n*e}},d3.interpolateRound=function(t,n){return n-=t,function(e){return Math.round(t+n*e)}},d3.interpolateString=function(t,n){var e,r,i,u,a,o=0,c=0,l=[],s=[];for(ia.lastIndex=0,r=0;e=ia.exec(n);++r)e.index&&l.push(n.substring(o,c=e.index)),s.push({i:l.length,x:e[0]}),l.push(null),o=ia.lastIndex;for(n.length>o&&l.push(n.substring(o)),r=0,u=s.length;(e=ia.exec(t))&&u>r;++r)if(a=s[r],a.x==e[0]){if(a.i)if(null==l[a.i+1])for(l[a.i-1]+=a.x,l.splice(a.i,1),i=r+1;u>i;++i)s[i].i--;else for(l[a.i-1]+=a.x+l[a.i+1],l.splice(a.i,2),i=r+1;u>i;++i)s[i].i-=2;else if(null==l[a.i+1])l[a.i]=a.x;else for(l[a.i]=a.x+l[a.i+1],l.splice(a.i+1,1),i=r+1;u>i;++i)s[i].i--;s.splice(r,1),u--,r--}else a.x=d3.interpolateNumber(parseFloat(e[0]),parseFloat(a.x));for(;u>r;)a=s.pop(),null==l[a.i+1]?l[a.i]=a.x:(l[a.i]=a.x+l[a.i+1],l.splice(a.i+1,1)),u--;return 1===l.length?null==l[0]?s[0].x:function(){return n}:function(t){for(r=0;u>r;++r)l[(a=s[r]).i]=a.x(t);return l.join("")}},d3.interpolateTransform=function(t,n){var e,r=[],i=[],u=d3.transform(t),a=d3.transform(n),o=u.translate,c=a.translate,l=u.rotate,s=a.rotate,f=u.skew,h=a.skew,d=u.scale,g=a.scale;return o[0]!=c[0]||o[1]!=c[1]?(r.push("translate(",null,",",null,")"),i.push({i:1,x:d3.interpolateNumber(o[0],c[0])},{i:3,x:d3.interpolateNumber(o[1],c[1])})):c[0]||c[1]?r.push("translate("+c+")"):r.push(""),l!=s?(l-s>180?s+=360:s-l>180&&(l+=360),i.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:d3.interpolateNumber(l,s)})):s&&r.push(r.pop()+"rotate("+s+")"),f!=h?i.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:d3.interpolateNumber(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),d[0]!=g[0]||d[1]!=g[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),i.push({i:e-4,x:d3.interpolateNumber(d[0],g[0])},{i:e-2,x:d3.interpolateNumber(d[1],g[1])})):(1!=g[0]||1!=g[1])&&r.push(r.pop()+"scale("+g+")"),e=i.length,function(t){for(var n,u=-1;e>++u;)r[(n=i[u]).i]=n.x(t);return r.join("")}},d3.interpolateRgb=function(t,n){t=d3.rgb(t),n=d3.rgb(n);var e=t.r,r=t.g,i=t.b,u=n.r-e,a=n.g-r,o=n.b-i;return function(t){return"#"+G(Math.round(e+u*t))+G(Math.round(r+a*t))+G(Math.round(i+o*t))}},d3.interpolateHsl=function(t,n){t=d3.hsl(t),n=d3.hsl(n);var e=t.h,r=t.s,i=t.l,u=n.h-e,a=n.s-r,o=n.l-i;return u>180?u-=360:-180>u&&(u+=360),function(t){return un(e+u*t,r+a*t,i+o*t)+""}},d3.interpolateLab=function(t,n){t=d3.lab(t),n=d3.lab(n);var e=t.l,r=t.a,i=t.b,u=n.l-e,a=n.a-r,o=n.b-i;return function(t){return fn(e+u*t,r+a*t,i+o*t)+""}},d3.interpolateHcl=function(t,n){t=d3.hcl(t),n=d3.hcl(n);var e=t.h,r=t.c,i=t.l,u=n.h-e,a=n.c-r,o=n.l-i;return u>180?u-=360:-180>u&&(u+=360),function(t){return cn(e+u*t,r+a*t,i+o*t)+""}},d3.interpolateArray=function(t,n){var e,r=[],i=[],u=t.length,a=n.length,o=Math.min(t.length,n.length);for(e=0;o>e;++e)r.push(d3.interpolate(t[e],n[e]));for(;u>e;++e)i[e]=t[e];for(;a>e;++e)i[e]=n[e];return function(t){for(e=0;o>e;++e)i[e]=r[e](t);return i}},d3.interpolateObject=function(t,n){var e,r={},i={};for(e in t)e in n?r[e]=V(e)(t[e],n[e]):i[e]=t[e];for(e in n)e in t||(i[e]=n[e]);return function(t){for(e in r)i[e]=r[e](t);return i}};var ia=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;d3.interpolators=[d3.interpolateObject,function(t,n){return n instanceof Array&&d3.interpolateArray(t,n)},function(t,n){return("string"==typeof t||"string"==typeof n)&&d3.interpolateString(t+"",n+"")},function(t,n){return("string"==typeof n?aa.has(n)||/^(#|rgb\(|hsl\()/.test(n):n instanceof B)&&d3.interpolateRgb(t,n)},function(t,n){return!isNaN(t=+t)&&!isNaN(n=+n)&&d3.interpolateNumber(t,n)}],B.prototype.toString=function(){return this.rgb()+""},d3.rgb=function(t,n,e){return 1===arguments.length?t instanceof J?$(t.r,t.g,t.b):K(""+t,$,un):$(~~t,~~n,~~e)};var ua=J.prototype=new B;ua.brighter=function(t){t=Math.pow(.7,arguments.length?t:1);var n=this.r,e=this.g,r=this.b,i=30;return n||e||r?(n&&i>n&&(n=i),e&&i>e&&(e=i),r&&i>r&&(r=i),$(Math.min(255,Math.floor(n/t)),Math.min(255,Math.floor(e/t)),Math.min(255,Math.floor(r/t)))):$(i,i,i)},ua.darker=function(t){return t=Math.pow(.7,arguments.length?t:1),$(Math.floor(t*this.r),Math.floor(t*this.g),Math.floor(t*this.b)) +},ua.hsl=function(){return W(this.r,this.g,this.b)},ua.toString=function(){return"#"+G(this.r)+G(this.g)+G(this.b)};var aa=d3.map({aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen:"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"});aa.forEach(function(t,n){aa.set(t,K(n,$,un))}),d3.hsl=function(t,n,e){return 1===arguments.length?t instanceof rn?en(t.h,t.s,t.l):K(""+t,W,en):en(+t,+n,+e)};var oa=rn.prototype=new B;oa.brighter=function(t){return t=Math.pow(.7,arguments.length?t:1),en(this.h,this.s,this.l/t)},oa.darker=function(t){return t=Math.pow(.7,arguments.length?t:1),en(this.h,this.s,t*this.l)},oa.rgb=function(){return un(this.h,this.s,this.l)},d3.hcl=function(t,n,e){return 1===arguments.length?t instanceof on?an(t.h,t.c,t.l):t instanceof sn?hn(t.l,t.a,t.b):hn((t=Q((t=d3.rgb(t)).r,t.g,t.b)).l,t.a,t.b):an(+t,+n,+e)};var ca=on.prototype=new B;ca.brighter=function(t){return an(this.h,this.c,Math.min(100,this.l+la*(arguments.length?t:1)))},ca.darker=function(t){return an(this.h,this.c,Math.max(0,this.l-la*(arguments.length?t:1)))},ca.rgb=function(){return cn(this.h,this.c,this.l).rgb()},d3.lab=function(t,n,e){return 1===arguments.length?t instanceof sn?ln(t.l,t.a,t.b):t instanceof on?cn(t.l,t.c,t.h):Q((t=d3.rgb(t)).r,t.g,t.b):ln(+t,+n,+e)};var la=18,sa=.95047,fa=1,ha=1.08883,da=sn.prototype=new B;da.brighter=function(t){return ln(Math.min(100,this.l+la*(arguments.length?t:1)),this.a,this.b)},da.darker=function(t){return ln(Math.max(0,this.l-la*(arguments.length?t:1)),this.a,this.b)},da.rgb=function(){return fn(this.l,this.a,this.b)};var ga=function(t,n){return n.querySelector(t)},pa=function(t,n){return n.querySelectorAll(t)},ma=document.documentElement,va=ma.matchesSelector||ma.webkitMatchesSelector||ma.mozMatchesSelector||ma.msMatchesSelector||ma.oMatchesSelector,ya=function(t,n){return va.call(t,n)};"function"==typeof Sizzle&&(ga=function(t,n){return Sizzle(t,n)[0]||null},pa=function(t,n){return Sizzle.uniqueSort(Sizzle(t,n))},ya=Sizzle.matchesSelector);var Ma=[];d3.selection=function(){return ba},d3.selection.prototype=Ma,Ma.select=function(t){var n,e,r,i,u=[];"function"!=typeof t&&(t=vn(t));for(var a=-1,o=this.length;o>++a;){u.push(n=[]),n.parentNode=(r=this[a]).parentNode;for(var c=-1,l=r.length;l>++c;)(i=r[c])?(n.push(e=t.call(i,i.__data__,c)),e&&"__data__"in i&&(e.__data__=i.__data__)):n.push(null)}return mn(u)},Ma.selectAll=function(t){var n,e,r=[];"function"!=typeof t&&(t=yn(t));for(var i=-1,u=this.length;u>++i;)for(var a=this[i],o=-1,c=a.length;c>++o;)(e=a[o])&&(r.push(n=Yu(t.call(e,e.__data__,o))),n.parentNode=e);return mn(r)},Ma.attr=function(t,n){if(2>arguments.length){if("string"==typeof t){var e=this.node();return t=d3.ns.qualify(t),t.local?e.getAttributeNS(t.space,t.local):e.getAttribute(t)}for(n in t)this.each(Mn(n,t[n]));return this}return this.each(Mn(t,n))},Ma.classed=function(t,n){if(2>arguments.length){if("string"==typeof t){var e=this.node(),r=(t=t.trim().split(/^|\s+/g)).length,i=-1;if(n=e.classList){for(;r>++i;)if(!n.contains(t[i]))return!1}else for(n=e.className,null!=n.baseVal&&(n=n.baseVal);r>++i;)if(!bn(t[i]).test(n))return!1;return!0}for(n in t)this.each(xn(n,t[n]));return this}return this.each(xn(t,n))},Ma.style=function(t,n,e){var r=arguments.length;if(3>r){if("string"!=typeof t){2>r&&(n="");for(e in t)this.each(wn(e,t[e],n));return this}if(2>r)return getComputedStyle(this.node(),null).getPropertyValue(t);e=""}return this.each(wn(t,n,e))},Ma.property=function(t,n){if(2>arguments.length){if("string"==typeof t)return this.node()[t];for(n in t)this.each(Sn(n,t[n]));return this}return this.each(Sn(t,n))},Ma.text=function(t){return arguments.length?this.each("function"==typeof t?function(){var n=t.apply(this,arguments);this.textContent=null==n?"":n}:null==t?function(){this.textContent=""}:function(){this.textContent=t}):this.node().textContent},Ma.html=function(t){return arguments.length?this.each("function"==typeof t?function(){var n=t.apply(this,arguments);this.innerHTML=null==n?"":n}:null==t?function(){this.innerHTML=""}:function(){this.innerHTML=t}):this.node().innerHTML},Ma.append=function(t){function n(){return this.appendChild(document.createElementNS(this.namespaceURI,t))}function e(){return this.appendChild(document.createElementNS(t.space,t.local))}return t=d3.ns.qualify(t),this.select(t.local?e:n)},Ma.insert=function(t,n){function e(){return this.insertBefore(document.createElementNS(this.namespaceURI,t),ga(n,this))}function r(){return this.insertBefore(document.createElementNS(t.space,t.local),ga(n,this))}return t=d3.ns.qualify(t),this.select(t.local?r:e)},Ma.remove=function(){return this.each(function(){var t=this.parentNode;t&&t.removeChild(this)})},Ma.data=function(t,n){function e(t,e){var r,i,a,o=t.length,f=e.length,h=Math.min(o,f),d=Array(f),g=Array(f),p=Array(o);if(n){var m,v=new u,y=new u,M=[];for(r=-1;o>++r;)m=n.call(i=t[r],i.__data__,r),v.has(m)?p[r]=i:v.set(m,i),M.push(m);for(r=-1;f>++r;)m=n.call(e,a=e[r],r),(i=v.get(m))?(d[r]=i,i.__data__=a):y.has(m)||(g[r]=kn(a)),y.set(m,a),v.remove(m);for(r=-1;o>++r;)v.has(M[r])&&(p[r]=t[r])}else{for(r=-1;h>++r;)i=t[r],a=e[r],i?(i.__data__=a,d[r]=i):g[r]=kn(a);for(;f>r;++r)g[r]=kn(e[r]);for(;o>r;++r)p[r]=t[r]}g.update=d,g.parentNode=d.parentNode=p.parentNode=t.parentNode,c.push(g),l.push(d),s.push(p)}var r,i,a=-1,o=this.length;if(!arguments.length){for(t=Array(o=(r=this[0]).length);o>++a;)(i=r[a])&&(t[a]=i.__data__);return t}var c=qn([]),l=mn([]),s=mn([]);if("function"==typeof t)for(;o>++a;)e(r=this[a],t.call(r,r.parentNode.__data__,a));else for(;o>++a;)e(r=this[a],t);return l.enter=function(){return c},l.exit=function(){return s},l},Ma.datum=function(t){return arguments.length?this.property("__data__",t):this.property("__data__")},Ma.filter=function(t){var n,e,r,i=[];"function"!=typeof t&&(t=En(t));for(var u=0,a=this.length;a>u;u++){i.push(n=[]),n.parentNode=(e=this[u]).parentNode;for(var o=0,c=e.length;c>o;o++)(r=e[o])&&t.call(r,r.__data__,o)&&n.push(r)}return mn(i)},Ma.order=function(){for(var t=-1,n=this.length;n>++t;)for(var e,r=this[t],i=r.length-1,u=r[i];--i>=0;)(e=r[i])&&(u&&u!==e.nextSibling&&u.parentNode.insertBefore(e,u),u=e);return this},Ma.sort=function(t){t=An.apply(this,arguments);for(var n=-1,e=this.length;e>++n;)this[n].sort(t);return this.order()},Ma.on=function(t,n,e){var r=arguments.length;if(3>r){if("string"!=typeof t){2>r&&(n=!1);for(e in t)this.each(Nn(e,t[e],n));return this}if(2>r)return(r=this.node()["__on"+t])&&r._;e=!1}return this.each(Nn(t,n,e))},Ma.each=function(t){return Tn(this,function(n,e,r){t.call(n,n.__data__,e,r)})},Ma.call=function(t){var n=Yu(arguments);return t.apply(n[0]=this,n),this},Ma.empty=function(){return!this.node()},Ma.node=function(){for(var t=0,n=this.length;n>t;t++)for(var e=this[t],r=0,i=e.length;i>r;r++){var u=e[r];if(u)return u}return null},Ma.transition=function(){var t,n,e=_a||++Sa,r=[],i=Object.create(ka);i.time=Date.now();for(var u=-1,a=this.length;a>++u;){r.push(t=[]);for(var o=this[u],c=-1,l=o.length;l>++c;)(n=o[c])&&zn(n,c,e,i),t.push(n)}return Cn(r,e)};var ba=mn([[document]]);ba[0].parentNode=ma,d3.select=function(t){return"string"==typeof t?ba.select(t):mn([[t]])},d3.selectAll=function(t){return"string"==typeof t?ba.selectAll(t):mn([Yu(t)])};var xa=[];d3.selection.enter=qn,d3.selection.enter.prototype=xa,xa.append=Ma.append,xa.insert=Ma.insert,xa.empty=Ma.empty,xa.node=Ma.node,xa.select=function(t){for(var n,e,r,i,u,a=[],o=-1,c=this.length;c>++o;){r=(i=this[o]).update,a.push(n=[]),n.parentNode=i.parentNode;for(var l=-1,s=i.length;s>++l;)(u=i[l])?(n.push(r[l]=e=t.call(i.parentNode,u.__data__,l)),e.__data__=u.__data__):n.push(null)}return mn(a)};var _a,wa=[],Sa=0,ka={ease:T,delay:0,duration:250};wa.call=Ma.call,wa.empty=Ma.empty,wa.node=Ma.node,d3.transition=function(t){return arguments.length?_a?t.transition():t:ba.transition()},d3.transition.prototype=wa,wa.select=function(t){var n,e,r,i=this.id,u=[];"function"!=typeof t&&(t=vn(t));for(var a=-1,o=this.length;o>++a;){u.push(n=[]);for(var c=this[a],l=-1,s=c.length;s>++l;)(r=c[l])&&(e=t.call(r,r.__data__,l))?("__data__"in r&&(e.__data__=r.__data__),zn(e,l,i,r.__transition__[i]),n.push(e)):n.push(null)}return Cn(u,i)},wa.selectAll=function(t){var n,e,r,i,u,a=this.id,o=[];"function"!=typeof t&&(t=yn(t));for(var c=-1,l=this.length;l>++c;)for(var s=this[c],f=-1,h=s.length;h>++f;)if(r=s[f]){u=r.__transition__[a],e=t.call(r,r.__data__,f),o.push(n=[]);for(var d=-1,g=e.length;g>++d;)zn(i=e[d],d,a,u),n.push(i)}return Cn(o,a)},wa.filter=function(t){var n,e,r,i=[];"function"!=typeof t&&(t=En(t));for(var u=0,a=this.length;a>u;u++){i.push(n=[]);for(var e=this[u],o=0,c=e.length;c>o;o++)(r=e[o])&&t.call(r,r.__data__,o)&&n.push(r)}return Cn(i,this.id,this.time).ease(this.ease())},wa.attr=function(t,n){function e(){this.removeAttribute(u)}function r(){this.removeAttributeNS(u.space,u.local)}if(2>arguments.length){for(n in t)this.attr(n,t[n]);return this}var i=V(t),u=d3.ns.qualify(t);return Ln(this,"attr."+t,n,function(t){function n(){var n,e=this.getAttribute(u);return e!==t&&(n=i(e,t),function(t){this.setAttribute(u,n(t))})}function a(){var n,e=this.getAttributeNS(u.space,u.local);return e!==t&&(n=i(e,t),function(t){this.setAttributeNS(u.space,u.local,n(t))})}return null==t?u.local?r:e:(t+="",u.local?a:n)})},wa.attrTween=function(t,n){function e(t,e){var r=n.call(this,t,e,this.getAttribute(i));return r&&function(t){this.setAttribute(i,r(t))}}function r(t,e){var r=n.call(this,t,e,this.getAttributeNS(i.space,i.local));return r&&function(t){this.setAttributeNS(i.space,i.local,r(t))}}var i=d3.ns.qualify(t);return this.tween("attr."+t,i.local?r:e)},wa.style=function(t,n,e){function r(){this.style.removeProperty(t)}var i=arguments.length;if(3>i){if("string"!=typeof t){2>i&&(n="");for(e in t)this.style(e,t[e],n);return this}e=""}var u=V(t);return Ln(this,"style."+t,n,function(n){function i(){var r,i=getComputedStyle(this,null).getPropertyValue(t);return i!==n&&(r=u(i,n),function(n){this.style.setProperty(t,r(n),e)})}return null==n?r:(n+="",i)})},wa.styleTween=function(t,n,e){return 3>arguments.length&&(e=""),this.tween("style."+t,function(r,i){var u=n.call(this,r,i,getComputedStyle(this,null).getPropertyValue(t));return u&&function(n){this.style.setProperty(t,u(n),e)}})},wa.text=function(t){return Ln(this,"text",t,Dn)},wa.remove=function(){return this.each("end.transition",function(){var t;!this.__transition__&&(t=this.parentNode)&&t.removeChild(this)})},wa.ease=function(t){var n=this.id;return 1>arguments.length?this.node().__transition__[n].ease:("function"!=typeof t&&(t=d3.ease.apply(d3,arguments)),Tn(this,function(e){e.__transition__[n].ease=t}))},wa.delay=function(t){var n=this.id;return Tn(this,"function"==typeof t?function(e,r,i){e.__transition__[n].delay=0|t.call(e,e.__data__,r,i)}:(t|=0,function(e){e.__transition__[n].delay=t}))},wa.duration=function(t){var n=this.id;return Tn(this,"function"==typeof t?function(e,r,i){e.__transition__[n].duration=Math.max(1,0|t.call(e,e.__data__,r,i))}:(t=Math.max(1,0|t),function(e){e.__transition__[n].duration=t}))},wa.each=function(t,n){var e=this.id;if(2>arguments.length){var r=ka,i=_a;_a=e,Tn(this,function(n,r,i){ka=n.__transition__[e],t.call(n,n.__data__,r,i)}),ka=r,_a=i}else Tn(this,function(r){r.__transition__[e].event.on(t,n)});return this},wa.transition=function(){for(var t,n,e,r,i=this.id,u=++Sa,a=[],o=0,c=this.length;c>o;o++){a.push(t=[]);for(var n=this[o],l=0,s=n.length;s>l;l++)(e=n[l])&&(r=Object.create(e.__transition__[i]),r.delay+=r.duration,zn(e,l,u,r)),t.push(e)}return Cn(a,u)},wa.tween=function(t,n){var e=this.id;return 2>arguments.length?this.node().__transition__[e].tween.get(t):Tn(this,null==n?function(n){n.__transition__[e].tween.remove(t)}:function(r){r.__transition__[e].tween.set(t,n)})};var Ea,Aa,Na=0,Ta={},qa=null;d3.timer=function(t,n,e){if(3>arguments.length){if(2>arguments.length)n=0;else if(!isFinite(n))return;e=Date.now()}var r=Ta[t.id];r&&r.callback===t?(r.then=e,r.delay=n):Ta[t.id=++Na]=qa={callback:t,then:e,delay:n,next:qa},Ea||(Aa=clearTimeout(Aa),Ea=1,Ca(Fn))},d3.timer.flush=function(){for(var t,n=Date.now(),e=qa;e;)t=n-e.then,e.delay||(e.flush=e.callback(t)),e=e.next;Hn()};var Ca=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||function(t){setTimeout(t,17)};d3.mouse=function(t){return Rn(t,P())};var za=/WebKit/.test(navigator.userAgent)?-1:0;d3.touches=function(t,n){return 2>arguments.length&&(n=P().touches),n?Yu(n).map(function(n){var e=Rn(t,n);return e.identifier=n.identifier,e}):[]},d3.scale={},d3.scale.linear=function(){return In([0,1],[0,1],d3.interpolate,!1)},d3.scale.log=function(){return Kn(d3.scale.linear(),Wn)};var Da=d3.format(".0e");Wn.pow=function(t){return Math.pow(10,t)},Qn.pow=function(t){return-Math.pow(10,-t)},d3.scale.pow=function(){return te(d3.scale.linear(),1)},d3.scale.sqrt=function(){return d3.scale.pow().exponent(.5)},d3.scale.ordinal=function(){return ee([],{t:"range",a:[[]]})},d3.scale.category10=function(){return d3.scale.ordinal().range(La)},d3.scale.category20=function(){return d3.scale.ordinal().range(Fa)},d3.scale.category20b=function(){return d3.scale.ordinal().range(Ha)},d3.scale.category20c=function(){return d3.scale.ordinal().range(Ra)};var La=["#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd","#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf"],Fa=["#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5","#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f","#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5"],Ha=["#393b79","#5254a3","#6b6ecf","#9c9ede","#637939","#8ca252","#b5cf6b","#cedb9c","#8c6d31","#bd9e39","#e7ba52","#e7cb94","#843c39","#ad494a","#d6616b","#e7969c","#7b4173","#a55194","#ce6dbd","#de9ed6"],Ra=["#3182bd","#6baed6","#9ecae1","#c6dbef","#e6550d","#fd8d3c","#fdae6b","#fdd0a2","#31a354","#74c476","#a1d99b","#c7e9c0","#756bb1","#9e9ac8","#bcbddc","#dadaeb","#636363","#969696","#bdbdbd","#d9d9d9"];d3.scale.quantile=function(){return re([],[])},d3.scale.quantize=function(){return ie(0,1,[0,1])},d3.scale.threshold=function(){return ue([.5],[0,1])},d3.scale.identity=function(){return ae([0,1])},d3.svg={},d3.svg.arc=function(){function t(){var t=n.apply(this,arguments),u=e.apply(this,arguments),a=r.apply(this,arguments)+Pa,o=i.apply(this,arguments)+Pa,c=(a>o&&(c=a,a=o,o=c),o-a),l=Ru>c?"0":"1",s=Math.cos(a),f=Math.sin(a),h=Math.cos(o),d=Math.sin(o);return c>=ja?t?"M0,"+u+"A"+u+","+u+" 0 1,1 0,"+-u+"A"+u+","+u+" 0 1,1 0,"+u+"M0,"+t+"A"+t+","+t+" 0 1,0 0,"+-t+"A"+t+","+t+" 0 1,0 0,"+t+"Z":"M0,"+u+"A"+u+","+u+" 0 1,1 0,"+-u+"A"+u+","+u+" 0 1,1 0,"+u+"Z":t?"M"+u*s+","+u*f+"A"+u+","+u+" 0 "+l+",1 "+u*h+","+u*d+"L"+t*h+","+t*d+"A"+t+","+t+" 0 "+l+",0 "+t*s+","+t*f+"Z":"M"+u*s+","+u*f+"A"+u+","+u+" 0 "+l+",1 "+u*h+","+u*d+"L0,0"+"Z"}var n=oe,e=ce,r=le,i=se;return t.innerRadius=function(e){return arguments.length?(n=c(e),t):n},t.outerRadius=function(n){return arguments.length?(e=c(n),t):e},t.startAngle=function(n){return arguments.length?(r=c(n),t):r},t.endAngle=function(n){return arguments.length?(i=c(n),t):i},t.centroid=function(){var t=(n.apply(this,arguments)+e.apply(this,arguments))/2,u=(r.apply(this,arguments)+i.apply(this,arguments))/2+Pa;return[Math.cos(u)*t,Math.sin(u)*t]},t};var Pa=-Ru/2,ja=2*Ru-1e-6;d3.svg.line=function(){return fe(a)};var Oa=d3.map({linear:ge,"linear-closed":pe,"step-before":me,"step-after":ve,basis:we,"basis-open":Se,"basis-closed":ke,bundle:Ee,cardinal:be,"cardinal-open":ye,"cardinal-closed":Me,monotone:ze});Oa.forEach(function(t,n){n.key=t,n.closed=/-closed$/.test(t)});var Ya=[0,2/3,1/3,0],Ua=[0,1/3,2/3,0],Ia=[0,1/6,2/3,1/6];d3.svg.line.radial=function(){var t=fe(De);return t.radius=t.x,delete t.x,t.angle=t.y,delete t.y,t},me.reverse=ve,ve.reverse=me,d3.svg.area=function(){return Le(a)},d3.svg.area.radial=function(){var t=Le(De);return t.radius=t.x,delete t.x,t.innerRadius=t.x0,delete t.x0,t.outerRadius=t.x1,delete t.x1,t.angle=t.y,delete t.y,t.startAngle=t.y0,delete t.y0,t.endAngle=t.y1,delete t.y1,t},d3.svg.chord=function(){function e(t,n){var e=r(this,o,t,n),c=r(this,l,t,n);return"M"+e.p0+u(e.r,e.p1,e.a1-e.a0)+(i(e,c)?a(e.r,e.p1,e.r,e.p0):a(e.r,e.p1,c.r,c.p0)+u(c.r,c.p1,c.a1-c.a0)+a(c.r,c.p1,e.r,e.p0))+"Z"}function r(t,n,e,r){var i=n.call(t,e,r),u=s.call(t,i,r),a=f.call(t,i,r)+Pa,o=h.call(t,i,r)+Pa;return{r:u,a0:a,a1:o,p0:[u*Math.cos(a),u*Math.sin(a)],p1:[u*Math.cos(o),u*Math.sin(o)]}}function i(t,n){return t.a0==n.a0&&t.a1==n.a1}function u(t,n,e){return"A"+t+","+t+" 0 "+ +(e>Ru)+",1 "+n}function a(t,n,e,r){return"Q 0,0 "+r}var o=n,l=t,s=Fe,f=le,h=se;return e.radius=function(t){return arguments.length?(s=c(t),e):s},e.source=function(t){return arguments.length?(o=c(t),e):o},e.target=function(t){return arguments.length?(l=c(t),e):l},e.startAngle=function(t){return arguments.length?(f=c(t),e):f},e.endAngle=function(t){return arguments.length?(h=c(t),e):h},e},d3.svg.diagonal=function(){function e(t,n){var e=r.call(this,t,n),a=i.call(this,t,n),o=(e.y+a.y)/2,c=[e,{x:e.x,y:o},{x:a.x,y:o},a];return c=c.map(u),"M"+c[0]+"C"+c[1]+" "+c[2]+" "+c[3]}var r=n,i=t,u=He;return e.source=function(t){return arguments.length?(r=c(t),e):r},e.target=function(t){return arguments.length?(i=c(t),e):i},e.projection=function(t){return arguments.length?(u=t,e):u},e},d3.svg.diagonal.radial=function(){var t=d3.svg.diagonal(),n=He,e=t.projection;return t.projection=function(t){return arguments.length?e(Re(n=t)):n},t},d3.svg.symbol=function(){function t(t,r){return(Va.get(n.call(this,t,r))||Oe)(e.call(this,t,r))}var n=je,e=Pe;return t.type=function(e){return arguments.length?(n=c(e),t):n},t.size=function(n){return arguments.length?(e=c(n),t):e},t};var Va=d3.map({circle:Oe,cross:function(t){var n=Math.sqrt(t/5)/2;return"M"+-3*n+","+-n+"H"+-n+"V"+-3*n+"H"+n+"V"+-n+"H"+3*n+"V"+n+"H"+n+"V"+3*n+"H"+-n+"V"+n+"H"+-3*n+"Z"},diamond:function(t){var n=Math.sqrt(t/(2*Za)),e=n*Za;return"M0,"+-n+"L"+e+",0"+" 0,"+n+" "+-e+",0"+"Z"},square:function(t){var n=Math.sqrt(t)/2;return"M"+-n+","+-n+"L"+n+","+-n+" "+n+","+n+" "+-n+","+n+"Z"},"triangle-down":function(t){var n=Math.sqrt(t/Xa),e=n*Xa/2;return"M0,"+e+"L"+n+","+-e+" "+-n+","+-e+"Z"},"triangle-up":function(t){var n=Math.sqrt(t/Xa),e=n*Xa/2;return"M0,"+-e+"L"+n+","+e+" "+-n+","+e+"Z"}});d3.svg.symbolTypes=Va.keys();var Xa=Math.sqrt(3),Za=Math.tan(30*ju);d3.svg.axis=function(){function t(t){t.each(function(){var t,f=d3.select(this),h=null==l?e.ticks?e.ticks.apply(e,c):e.domain():l,d=null==n?e.tickFormat?e.tickFormat.apply(e,c):String:n,g=Ie(e,h,s),p=f.selectAll(".minor").data(g,String),m=p.enter().insert("line","g").attr("class","tick minor").style("opacity",1e-6),v=d3.transition(p.exit()).style("opacity",1e-6).remove(),y=d3.transition(p).style("opacity",1),M=f.selectAll("g").data(h,String),b=M.enter().insert("g","path").style("opacity",1e-6),x=d3.transition(M.exit()).style("opacity",1e-6).remove(),_=d3.transition(M).style("opacity",1),w=On(e),S=f.selectAll(".domain").data([0]),k=d3.transition(S),E=e.copy(),A=this.__chart__||E;this.__chart__=E,S.enter().append("path").attr("class","domain"),b.append("line").attr("class","tick"),b.append("text");var N=b.select("line"),T=_.select("line"),q=M.select("text").text(d),C=b.select("text"),z=_.select("text");switch(r){case"bottom":t=Ye,m.attr("y2",u),y.attr("x2",0).attr("y2",u),N.attr("y2",i),C.attr("y",Math.max(i,0)+o),T.attr("x2",0).attr("y2",i),z.attr("x",0).attr("y",Math.max(i,0)+o),q.attr("dy",".71em").style("text-anchor","middle"),k.attr("d","M"+w[0]+","+a+"V0H"+w[1]+"V"+a);break;case"top":t=Ye,m.attr("y2",-u),y.attr("x2",0).attr("y2",-u),N.attr("y2",-i),C.attr("y",-(Math.max(i,0)+o)),T.attr("x2",0).attr("y2",-i),z.attr("x",0).attr("y",-(Math.max(i,0)+o)),q.attr("dy","0em").style("text-anchor","middle"),k.attr("d","M"+w[0]+","+-a+"V0H"+w[1]+"V"+-a);break;case"left":t=Ue,m.attr("x2",-u),y.attr("x2",-u).attr("y2",0),N.attr("x2",-i),C.attr("x",-(Math.max(i,0)+o)),T.attr("x2",-i).attr("y2",0),z.attr("x",-(Math.max(i,0)+o)).attr("y",0),q.attr("dy",".32em").style("text-anchor","end"),k.attr("d","M"+-a+","+w[0]+"H0V"+w[1]+"H"+-a);break;case"right":t=Ue,m.attr("x2",u),y.attr("x2",u).attr("y2",0),N.attr("x2",i),C.attr("x",Math.max(i,0)+o),T.attr("x2",i).attr("y2",0),z.attr("x",Math.max(i,0)+o).attr("y",0),q.attr("dy",".32em").style("text-anchor","start"),k.attr("d","M"+a+","+w[0]+"H0V"+w[1]+"H"+a)}if(e.ticks)b.call(t,A),_.call(t,E),x.call(t,E),m.call(t,A),y.call(t,E),v.call(t,E);else{var D=E.rangeBand()/2,L=function(t){return E(t)+D};b.call(t,L),_.call(t,L)}})}var n,e=d3.scale.linear(),r="bottom",i=6,u=6,a=6,o=3,c=[10],l=null,s=0;return t.scale=function(n){return arguments.length?(e=n,t):e},t.orient=function(n){return arguments.length?(r=n,t):r},t.ticks=function(){return arguments.length?(c=arguments,t):c},t.tickValues=function(n){return arguments.length?(l=n,t):l},t.tickFormat=function(e){return arguments.length?(n=e,t):n},t.tickSize=function(n,e){if(!arguments.length)return i;var r=arguments.length-1;return i=+n,u=r>1?+e:i,a=r>0?+arguments[r]:i,t},t.tickPadding=function(n){return arguments.length?(o=+n,t):o},t.tickSubdivide=function(n){return arguments.length?(s=+n,t):s},t},d3.svg.brush=function(){function t(u){u.each(function(){var u,a=d3.select(this),s=a.selectAll(".background").data([0]),f=a.selectAll(".extent").data([0]),h=a.selectAll(".resize").data(l,String);a.style("pointer-events","all").on("mousedown.brush",i).on("touchstart.brush",i),s.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),f.enter().append("rect").attr("class","extent").style("cursor","move"),h.enter().append("g").attr("class",function(t){return"resize "+t}).style("cursor",function(t){return Ba[t]}).append("rect").attr("x",function(t){return/[ew]$/.test(t)?-3:null}).attr("y",function(t){return/^[ns]/.test(t)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),h.style("display",t.empty()?"none":null),h.exit().remove(),o&&(u=On(o),s.attr("x",u[0]).attr("width",u[1]-u[0]),e(a)),c&&(u=On(c),s.attr("y",u[0]).attr("height",u[1]-u[0]),r(a)),n(a)})}function n(t){t.selectAll(".resize").attr("transform",function(t){return"translate("+s[+/e$/.test(t)][0]+","+s[+/^s/.test(t)][1]+")"})}function e(t){t.select(".extent").attr("x",s[0][0]),t.selectAll(".extent,.n>rect,.s>rect").attr("width",s[1][0]-s[0][0])}function r(t){t.select(".extent").attr("y",s[0][1]),t.selectAll(".extent,.e>rect,.w>rect").attr("height",s[1][1]-s[0][1])}function i(){function i(){var t=d3.event.changedTouches;return t?d3.touches(v,t)[0]:d3.mouse(v)}function l(){32==d3.event.keyCode&&(S||(p=null,k[0]-=s[1][0],k[1]-=s[1][1],S=2),R())}function f(){32==d3.event.keyCode&&2==S&&(k[0]+=s[1][0],k[1]+=s[1][1],S=0,R())}function h(){var t=i(),u=!1;m&&(t[0]+=m[0],t[1]+=m[1]),S||(d3.event.altKey?(p||(p=[(s[0][0]+s[1][0])/2,(s[0][1]+s[1][1])/2]),k[0]=s[+(t[0]<p[0])][0],k[1]=s[+(t[1]<p[1])][1]):p=null),_&&d(t,o,0)&&(e(b),u=!0),w&&d(t,c,1)&&(r(b),u=!0),u&&(n(b),M({type:"brush",mode:S?"move":"resize"}))}function d(t,n,e){var r,i,a=On(n),o=a[0],c=a[1],l=k[e],f=s[1][e]-s[0][e];return S&&(o-=l,c-=f+l),r=Math.max(o,Math.min(c,t[e])),S?i=(r+=l)+f:(p&&(l=Math.max(o,Math.min(c,2*p[e]-r))),r>l?(i=r,r=l):i=l),s[0][e]!==r||s[1][e]!==i?(u=null,s[0][e]=r,s[1][e]=i,!0):void 0}function g(){h(),b.style("pointer-events","all").selectAll(".resize").style("display",t.empty()?"none":null),d3.select("body").style("cursor",null),E.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),M({type:"brushend"}),R()}var p,m,v=this,y=d3.select(d3.event.target),M=a.of(v,arguments),b=d3.select(v),x=y.datum(),_=!/^(n|s)$/.test(x)&&o,w=!/^(e|w)$/.test(x)&&c,S=y.classed("extent"),k=i(),E=d3.select(window).on("mousemove.brush",h).on("mouseup.brush",g).on("touchmove.brush",h).on("touchend.brush",g).on("keydown.brush",l).on("keyup.brush",f);if(S)k[0]=s[0][0]-k[0],k[1]=s[0][1]-k[1];else if(x){var A=+/w$/.test(x),N=+/^n/.test(x);m=[s[1-A][0]-k[0],s[1-N][1]-k[1]],k[0]=s[A][0],k[1]=s[N][1]}else d3.event.altKey&&(p=k.slice());b.style("pointer-events","none").selectAll(".resize").style("display",null),d3.select("body").style("cursor",y.style("cursor")),M({type:"brushstart"}),h(),R()}var u,a=j(t,"brushstart","brush","brushend"),o=null,c=null,l=$a[0],s=[[0,0],[0,0]];return t.x=function(n){return arguments.length?(o=n,l=$a[!o<<1|!c],t):o},t.y=function(n){return arguments.length?(c=n,l=$a[!o<<1|!c],t):c},t.extent=function(n){var e,r,i,a,l;return arguments.length?(u=[[0,0],[0,0]],o&&(e=n[0],r=n[1],c&&(e=e[0],r=r[0]),u[0][0]=e,u[1][0]=r,o.invert&&(e=o(e),r=o(r)),e>r&&(l=e,e=r,r=l),s[0][0]=0|e,s[1][0]=0|r),c&&(i=n[0],a=n[1],o&&(i=i[1],a=a[1]),u[0][1]=i,u[1][1]=a,c.invert&&(i=c(i),a=c(a)),i>a&&(l=i,i=a,a=l),s[0][1]=0|i,s[1][1]=0|a),t):(n=u||s,o&&(e=n[0][0],r=n[1][0],u||(e=s[0][0],r=s[1][0],o.invert&&(e=o.invert(e),r=o.invert(r)),e>r&&(l=e,e=r,r=l))),c&&(i=n[0][1],a=n[1][1],u||(i=s[0][1],a=s[1][1],c.invert&&(i=c.invert(i),a=c.invert(a)),i>a&&(l=i,i=a,a=l))),o&&c?[[e,i],[r,a]]:o?[e,r]:c&&[i,a])},t.clear=function(){return u=null,s[0][0]=s[0][1]=s[1][0]=s[1][1]=0,t},t.empty=function(){return o&&s[0][0]===s[1][0]||c&&s[0][1]===s[1][1]},d3.rebind(t,a,"on")};var Ba={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},$a=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]];d3.behavior={},d3.behavior.drag=function(){function t(){this.on("mousedown.drag",n).on("touchstart.drag",n)}function n(){function t(){var t=o.parentNode;return null!=s?d3.touches(t).filter(function(t){return t.identifier===s})[0]:d3.mouse(t)}function n(){if(!o.parentNode)return i();var n=t(),e=n[0]-f[0],r=n[1]-f[1];h|=e|r,f=n,R(),c({type:"drag",x:n[0]+a[0],y:n[1]+a[1],dx:e,dy:r})}function i(){c({type:"dragend"}),h&&(R(),d3.event.target===l&&d.on("click.drag",u,!0)),d.on(null!=s?"touchmove.drag-"+s:"mousemove.drag",null).on(null!=s?"touchend.drag-"+s:"mouseup.drag",null)}function u(){R(),d.on("click.drag",null)}var a,o=this,c=e.of(o,arguments),l=d3.event.target,s=d3.event.touches?d3.event.changedTouches[0].identifier:null,f=t(),h=0,d=d3.select(window).on(null!=s?"touchmove.drag-"+s:"mousemove.drag",n).on(null!=s?"touchend.drag-"+s:"mouseup.drag",i,!0);r?(a=r.apply(o,arguments),a=[a.x-f[0],a.y-f[1]]):a=[0,0],null==s&&R(),c({type:"dragstart"})}var e=j(t,"drag","dragstart","dragend"),r=null;return t.origin=function(n){return arguments.length?(r=n,t):r},d3.rebind(t,e,"on")},d3.behavior.zoom=function(){function t(){this.on("mousedown.zoom",o).on("mousewheel.zoom",c).on("mousemove.zoom",l).on("DOMMouseScroll.zoom",c).on("dblclick.zoom",s).on("touchstart.zoom",f).on("touchmove.zoom",h).on("touchend.zoom",f)}function n(t){return[(t[0]-b[0])/x,(t[1]-b[1])/x]}function e(t){return[t[0]*x+b[0],t[1]*x+b[1]]}function r(t){x=Math.max(_[0],Math.min(_[1],t))}function i(t,n){n=e(n),b[0]+=t[0]-n[0],b[1]+=t[1]-n[1]}function u(){m&&m.domain(p.range().map(function(t){return(t-b[0])/x}).map(p.invert)),y&&y.domain(v.range().map(function(t){return(t-b[1])/x}).map(v.invert))}function a(t){u(),d3.event.preventDefault(),t({type:"zoom",scale:x,translate:b})}function o(){function t(){l=1,i(d3.mouse(u),f),a(o)}function e(){l&&R(),s.on("mousemove.zoom",null).on("mouseup.zoom",null),l&&d3.event.target===c&&s.on("click.zoom",r,!0)}function r(){R(),s.on("click.zoom",null)}var u=this,o=w.of(u,arguments),c=d3.event.target,l=0,s=d3.select(window).on("mousemove.zoom",t).on("mouseup.zoom",e),f=n(d3.mouse(u));window.focus(),R()}function c(){d||(d=n(d3.mouse(this))),r(Math.pow(2,.002*Ve())*x),i(d3.mouse(this),d),a(w.of(this,arguments))}function l(){d=null}function s(){var t=d3.mouse(this),e=n(t),u=Math.log(x)/Math.LN2;r(Math.pow(2,d3.event.shiftKey?Math.ceil(u)-1:Math.floor(u)+1)),i(t,e),a(w.of(this,arguments))}function f(){var t=d3.touches(this),e=Date.now();if(g=x,d={},t.forEach(function(t){d[t.identifier]=n(t)}),R(),1===t.length){if(500>e-M){var u=t[0],o=n(t[0]);r(2*x),i(u,o),a(w.of(this,arguments))}M=e}}function h(){var t=d3.touches(this),n=t[0],e=d[n.identifier];if(u=t[1]){var u,o=d[u.identifier];n=[(n[0]+u[0])/2,(n[1]+u[1])/2],e=[(e[0]+o[0])/2,(e[1]+o[1])/2],r(d3.event.scale*g)}i(n,e),M=null,a(w.of(this,arguments))}var d,g,p,m,v,y,M,b=[0,0],x=1,_=Ga,w=j(t,"zoom");return t.translate=function(n){return arguments.length?(b=n.map(Number),u(),t):b},t.scale=function(n){return arguments.length?(x=+n,u(),t):x},t.scaleExtent=function(n){return arguments.length?(_=null==n?Ga:n.map(Number),t):_},t.x=function(n){return arguments.length?(m=n,p=n.copy(),b=[0,0],x=1,t):m},t.y=function(n){return arguments.length?(y=n,v=n.copy(),b=[0,0],x=1,t):y},d3.rebind(t,w,"on")};var Ja,Ga=[0,1/0];d3.layout={},d3.layout.bundle=function(){return function(t){for(var n=[],e=-1,r=t.length;r>++e;)n.push(Xe(t[e]));return n}},d3.layout.chord=function(){function t(){var t,l,f,h,d,g={},p=[],m=d3.range(u),v=[];for(e=[],r=[],t=0,h=-1;u>++h;){for(l=0,d=-1;u>++d;)l+=i[h][d];p.push(l),v.push(d3.range(u)),t+=l}for(a&&m.sort(function(t,n){return a(p[t],p[n])}),o&&v.forEach(function(t,n){t.sort(function(t,e){return o(i[n][t],i[n][e]) +})}),t=(2*Ru-s*u)/t,l=0,h=-1;u>++h;){for(f=l,d=-1;u>++d;){var y=m[h],M=v[y][d],b=i[y][M],x=l,_=l+=b*t;g[y+"-"+M]={index:y,subindex:M,startAngle:x,endAngle:_,value:b}}r[y]={index:y,startAngle:f,endAngle:l,value:(l-f)/t},l+=s}for(h=-1;u>++h;)for(d=h-1;u>++d;){var w=g[h+"-"+d],S=g[d+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}c&&n()}function n(){e.sort(function(t,n){return c((t.source.value+t.target.value)/2,(n.source.value+n.target.value)/2)})}var e,r,i,u,a,o,c,l={},s=0;return l.matrix=function(t){return arguments.length?(u=(i=t)&&i.length,e=r=null,l):i},l.padding=function(t){return arguments.length?(s=t,e=r=null,l):s},l.sortGroups=function(t){return arguments.length?(a=t,e=r=null,l):a},l.sortSubgroups=function(t){return arguments.length?(o=t,e=null,l):o},l.sortChords=function(t){return arguments.length?(c=t,e&&n(),l):c},l.chords=function(){return e||t(),e},l.groups=function(){return r||t(),r},l},d3.layout.force=function(){function t(t){return function(n,e,r,i){if(n.point!==t){var u=n.cx-t.x,a=n.cy-t.y,o=1/Math.sqrt(u*u+a*a);if(v>(i-e)*o){var c=n.charge*o*o;return t.px-=u*c,t.py-=a*c,!0}if(n.point&&isFinite(o)){var c=n.pointCharge*o*o;t.px-=u*c,t.py-=a*c}}return!n.charge}}function n(t){t.px=d3.event.x,t.py=d3.event.y,l.resume()}var e,r,i,u,o,l={},s=d3.dispatch("start","tick","end"),f=[1,1],h=.9,d=Qe,g=tr,p=-30,m=.1,v=.8,y=[],M=[];return l.tick=function(){if(.005>(r*=.99))return s.end({type:"end",alpha:r=0}),!0;var n,e,a,c,l,d,g,v,b,x=y.length,_=M.length;for(e=0;_>e;++e)a=M[e],c=a.source,l=a.target,v=l.x-c.x,b=l.y-c.y,(d=v*v+b*b)&&(d=r*u[e]*((d=Math.sqrt(d))-i[e])/d,v*=d,b*=d,l.x-=v*(g=c.weight/(l.weight+c.weight)),l.y-=b*g,c.x+=v*(g=1-g),c.y+=b*g);if((g=r*m)&&(v=f[0]/2,b=f[1]/2,e=-1,g))for(;x>++e;)a=y[e],a.x+=(v-a.x)*g,a.y+=(b-a.y)*g;if(p)for(We(n=d3.geom.quadtree(y),r,o),e=-1;x>++e;)(a=y[e]).fixed||n.visit(t(a));for(e=-1;x>++e;)a=y[e],a.fixed?(a.x=a.px,a.y=a.py):(a.x-=(a.px-(a.px=a.x))*h,a.y-=(a.py-(a.py=a.y))*h);s.tick({type:"tick",alpha:r})},l.nodes=function(t){return arguments.length?(y=t,l):y},l.links=function(t){return arguments.length?(M=t,l):M},l.size=function(t){return arguments.length?(f=t,l):f},l.linkDistance=function(t){return arguments.length?(d=c(t),l):d},l.distance=l.linkDistance,l.linkStrength=function(t){return arguments.length?(g=c(t),l):g},l.friction=function(t){return arguments.length?(h=t,l):h},l.charge=function(t){return arguments.length?(p="function"==typeof t?t:+t,l):p},l.gravity=function(t){return arguments.length?(m=t,l):m},l.theta=function(t){return arguments.length?(v=t,l):v},l.alpha=function(t){return arguments.length?(r?r=t>0?t:0:t>0&&(s.start({type:"start",alpha:r=t}),d3.timer(l.tick)),l):r},l.start=function(){function t(t,r){for(var i,u=n(e),a=-1,o=u.length;o>++a;)if(!isNaN(i=u[a][t]))return i;return Math.random()*r}function n(){if(!a){for(a=[],r=0;s>r;++r)a[r]=[];for(r=0;h>r;++r){var t=M[r];a[t.source.index].push(t.target),a[t.target.index].push(t.source)}}return a[e]}var e,r,a,c,s=y.length,h=M.length,m=f[0],v=f[1];for(e=0;s>e;++e)(c=y[e]).index=e,c.weight=0;for(i=[],u=[],e=0;h>e;++e)c=M[e],"number"==typeof c.source&&(c.source=y[c.source]),"number"==typeof c.target&&(c.target=y[c.target]),i[e]=d.call(this,c,e),u[e]=g.call(this,c,e),++c.source.weight,++c.target.weight;for(e=0;s>e;++e)c=y[e],isNaN(c.x)&&(c.x=t("x",m)),isNaN(c.y)&&(c.y=t("y",v)),isNaN(c.px)&&(c.px=c.x),isNaN(c.py)&&(c.py=c.y);if(o=[],"function"==typeof p)for(e=0;s>e;++e)o[e]=+p.call(this,y[e],e);else for(e=0;s>e;++e)o[e]=p;return l.resume()},l.resume=function(){return l.alpha(.1)},l.stop=function(){return l.alpha(0)},l.drag=function(){e||(e=d3.behavior.drag().origin(a).on("dragstart",$e).on("drag",n).on("dragend",Je)),this.on("mouseover.force",Ge).on("mouseout.force",Ke).call(e)},d3.rebind(l,s,"on")},d3.layout.partition=function(){function t(n,e,r,i){var u=n.children;if(n.x=e,n.y=n.depth*i,n.dx=r,n.dy=i,u&&(a=u.length)){var a,o,c,l=-1;for(r=n.value?r/n.value:0;a>++l;)t(o=u[l],e,c=o.value*r,i),e+=c}}function n(t){var e=t.children,r=0;if(e&&(i=e.length))for(var i,u=-1;i>++u;)r=Math.max(r,n(e[u]));return 1+r}function e(e,u){var a=r.call(this,e,u);return t(a[0],0,i[0],i[1]/n(a[0])),a}var r=d3.layout.hierarchy(),i=[1,1];return e.size=function(t){return arguments.length?(i=t,e):i},hr(e,r)},d3.layout.pie=function(){function t(u){var a=u.map(function(e,r){return+n.call(t,e,r)}),o=+("function"==typeof r?r.apply(this,arguments):r),c=(("function"==typeof i?i.apply(this,arguments):i)-r)/d3.sum(a),l=d3.range(u.length);null!=e&&l.sort(e===Ka?function(t,n){return a[n]-a[t]}:function(t,n){return e(u[t],u[n])});var s=[];return l.forEach(function(t){var n;s[t]={data:u[t],value:n=a[t],startAngle:o,endAngle:o+=n*c}}),s}var n=Number,e=Ka,r=0,i=2*Ru;return t.value=function(e){return arguments.length?(n=e,t):n},t.sort=function(n){return arguments.length?(e=n,t):e},t.startAngle=function(n){return arguments.length?(r=n,t):r},t.endAngle=function(n){return arguments.length?(i=n,t):i},t};var Ka={};d3.layout.stack=function(){function t(a,c){var l=a.map(function(e,r){return n.call(t,e,r)}),s=l.map(function(n){return n.map(function(n,e){return[u.call(t,n,e),o.call(t,n,e)]})}),f=e.call(t,s,c);l=d3.permute(l,f),s=d3.permute(s,f);var h,d,g,p=r.call(t,s,c),m=l.length,v=l[0].length;for(d=0;v>d;++d)for(i.call(t,l[0][d],g=p[d],s[0][d][1]),h=1;m>h;++h)i.call(t,l[h][d],g+=s[h-1][d][1],s[h][d][1]);return a}var n=a,e=ir,r=ur,i=rr,u=nr,o=er;return t.values=function(e){return arguments.length?(n=e,t):n},t.order=function(n){return arguments.length?(e="function"==typeof n?n:Wa.get(n)||ir,t):e},t.offset=function(n){return arguments.length?(r="function"==typeof n?n:Qa.get(n)||ur,t):r},t.x=function(n){return arguments.length?(u=n,t):u},t.y=function(n){return arguments.length?(o=n,t):o},t.out=function(n){return arguments.length?(i=n,t):i},t};var Wa=d3.map({"inside-out":function(t){var n,e,r=t.length,i=t.map(ar),u=t.map(or),a=d3.range(r).sort(function(t,n){return i[t]-i[n]}),o=0,c=0,l=[],s=[];for(n=0;r>n;++n)e=a[n],c>o?(o+=u[e],l.push(e)):(c+=u[e],s.push(e));return s.reverse().concat(l)},reverse:function(t){return d3.range(t.length).reverse()},"default":ir}),Qa=d3.map({silhouette:function(t){var n,e,r,i=t.length,u=t[0].length,a=[],o=0,c=[];for(e=0;u>e;++e){for(n=0,r=0;i>n;n++)r+=t[n][e][1];r>o&&(o=r),a.push(r)}for(e=0;u>e;++e)c[e]=(o-a[e])/2;return c},wiggle:function(t){var n,e,r,i,u,a,o,c,l,s=t.length,f=t[0],h=f.length,d=[];for(d[0]=c=l=0,e=1;h>e;++e){for(n=0,i=0;s>n;++n)i+=t[n][e][1];for(n=0,u=0,o=f[e][0]-f[e-1][0];s>n;++n){for(r=0,a=(t[n][e][1]-t[n][e-1][1])/(2*o);n>r;++r)a+=(t[r][e][1]-t[r][e-1][1])/o;u+=a*t[n][e][1]}d[e]=c-=i?u/i*o:0,l>c&&(l=c)}for(e=0;h>e;++e)d[e]-=l;return d},expand:function(t){var n,e,r,i=t.length,u=t[0].length,a=1/i,o=[];for(e=0;u>e;++e){for(n=0,r=0;i>n;n++)r+=t[n][e][1];if(r)for(n=0;i>n;n++)t[n][e][1]/=r;else for(n=0;i>n;n++)t[n][e][1]=a}for(e=0;u>e;++e)o[e]=0;return o},zero:ur});d3.layout.histogram=function(){function t(t,u){for(var a,o,c=[],l=t.map(e,this),s=r.call(this,l,u),f=i.call(this,s,l,u),u=-1,h=l.length,d=f.length-1,g=n?1:1/h;d>++u;)a=c[u]=[],a.dx=f[u+1]-(a.x=f[u]),a.y=0;if(d>0)for(u=-1;h>++u;)o=l[u],o>=s[0]&&s[1]>=o&&(a=c[d3.bisect(f,o,1,d)-1],a.y+=g,a.push(t[u]));return c}var n=!0,e=Number,r=fr,i=lr;return t.value=function(n){return arguments.length?(e=n,t):e},t.range=function(n){return arguments.length?(r=c(n),t):r},t.bins=function(n){return arguments.length?(i="number"==typeof n?function(t){return sr(t,n)}:c(n),t):i},t.frequency=function(e){return arguments.length?(n=!!e,t):n},t},d3.layout.hierarchy=function(){function t(n,a,o){var c=i.call(e,n,a);if(n.depth=a,o.push(n),c&&(l=c.length)){for(var l,s,f=-1,h=n.children=[],d=0,g=a+1;l>++f;)s=t(c[f],g,o),s.parent=n,h.push(s),d+=s.value;r&&h.sort(r),u&&(n.value=d)}else u&&(n.value=+u.call(e,n,a)||0);return n}function n(t,r){var i=t.children,a=0;if(i&&(o=i.length))for(var o,c=-1,l=r+1;o>++c;)a+=n(i[c],l);else u&&(a=+u.call(e,t,r)||0);return u&&(t.value=a),a}function e(n){var e=[];return t(n,0,e),e}var r=pr,i=dr,u=gr;return e.sort=function(t){return arguments.length?(r=t,e):r},e.children=function(t){return arguments.length?(i=t,e):i},e.value=function(t){return arguments.length?(u=t,e):u},e.revalue=function(t){return n(t,0),t},e},d3.layout.pack=function(){function t(t,i){var u=n.call(this,t,i),a=u[0];a.x=0,a.y=0,Rr(a,function(t){t.r=Math.sqrt(t.value)}),Rr(a,xr);var o=r[0],c=r[1],l=Math.max(2*a.r/o,2*a.r/c);if(e>0){var s=e*l/2;Rr(a,function(t){t.r+=s}),Rr(a,xr),Rr(a,function(t){t.r-=s}),l=Math.max(2*a.r/o,2*a.r/c)}return Sr(a,o/2,c/2,1/l),u}var n=d3.layout.hierarchy().sort(vr),e=0,r=[1,1];return t.size=function(n){return arguments.length?(r=n,t):r},t.padding=function(n){return arguments.length?(e=+n,t):e},hr(t,n)},d3.layout.cluster=function(){function t(t,i){var u,a=n.call(this,t,i),o=a[0],c=0;Rr(o,function(t){var n=t.children;n&&n.length?(t.x=Ar(n),t.y=Er(n)):(t.x=u?c+=e(t,u):0,t.y=0,u=t)});var l=Nr(o),s=Tr(o),f=l.x-e(l,s)/2,h=s.x+e(s,l)/2;return Rr(o,function(t){t.x=(t.x-f)/(h-f)*r[0],t.y=(1-(o.y?t.y/o.y:1))*r[1]}),a}var n=d3.layout.hierarchy().sort(null).value(null),e=qr,r=[1,1];return t.separation=function(n){return arguments.length?(e=n,t):e},t.size=function(n){return arguments.length?(r=n,t):r},hr(t,n)},d3.layout.tree=function(){function t(t,i){function u(t,n){var r=t.children,i=t._tree;if(r&&(a=r.length)){for(var a,c,l,s=r[0],f=s,h=-1;a>++h;)l=r[h],u(l,c),f=o(l,c,f),c=l;Pr(t);var d=.5*(s._tree.prelim+l._tree.prelim);n?(i.prelim=n._tree.prelim+e(t,n),i.mod=i.prelim-d):i.prelim=d}else n&&(i.prelim=n._tree.prelim+e(t,n))}function a(t,n){t.x=t._tree.prelim+n;var e=t.children;if(e&&(r=e.length)){var r,i=-1;for(n+=t._tree.mod;r>++i;)a(e[i],n)}}function o(t,n,r){if(n){for(var i,u=t,a=t,o=n,c=t.parent.children[0],l=u._tree.mod,s=a._tree.mod,f=o._tree.mod,h=c._tree.mod;o=zr(o),u=Cr(u),o&&u;)c=Cr(c),a=zr(a),a._tree.ancestor=t,i=o._tree.prelim+f-u._tree.prelim-l+e(o,u),i>0&&(jr(Or(o,t,r),t,i),l+=i,s+=i),f+=o._tree.mod,l+=u._tree.mod,h+=c._tree.mod,s+=a._tree.mod;o&&!zr(a)&&(a._tree.thread=o,a._tree.mod+=f-s),u&&!Cr(c)&&(c._tree.thread=u,c._tree.mod+=l-h,r=t)}return r}var c=n.call(this,t,i),l=c[0];Rr(l,function(t,n){t._tree={ancestor:t,prelim:0,mod:0,change:0,shift:0,number:n?n._tree.number+1:0}}),u(l),a(l,-l._tree.prelim);var s=Dr(l,Fr),f=Dr(l,Lr),h=Dr(l,Hr),d=s.x-e(s,f)/2,g=f.x+e(f,s)/2,p=h.depth||1;return Rr(l,function(t){t.x=(t.x-d)/(g-d)*r[0],t.y=t.depth/p*r[1],delete t._tree}),c}var n=d3.layout.hierarchy().sort(null).value(null),e=qr,r=[1,1];return t.separation=function(n){return arguments.length?(e=n,t):e},t.size=function(n){return arguments.length?(r=n,t):r},hr(t,n)},d3.layout.treemap=function(){function t(t,n){for(var e,r,i=-1,u=t.length;u>++i;)r=(e=t[i]).value*(0>n?0:n),e.area=isNaN(r)||0>=r?0:r}function n(e){var u=e.children;if(u&&u.length){var a,o,c,l=f(e),s=[],h=u.slice(),g=1/0,p="slice"===d?l.dx:"dice"===d?l.dy:"slice-dice"===d?1&e.depth?l.dy:l.dx:Math.min(l.dx,l.dy);for(t(h,l.dx*l.dy/e.value),s.area=0;(c=h.length)>0;)s.push(a=h[c-1]),s.area+=a.area,"squarify"!==d||g>=(o=r(s,p))?(h.pop(),g=o):(s.area-=s.pop().area,i(s,p,l,!1),p=Math.min(l.dx,l.dy),s.length=s.area=0,g=1/0);s.length&&(i(s,p,l,!0),s.length=s.area=0),u.forEach(n)}}function e(n){var r=n.children;if(r&&r.length){var u,a=f(n),o=r.slice(),c=[];for(t(o,a.dx*a.dy/n.value),c.area=0;u=o.pop();)c.push(u),c.area+=u.area,null!=u.z&&(i(c,u.z?a.dx:a.dy,a,!o.length),c.length=c.area=0);r.forEach(e)}}function r(t,n){for(var e,r=t.area,i=0,u=1/0,a=-1,o=t.length;o>++a;)(e=t[a].area)&&(u>e&&(u=e),e>i&&(i=e));return r*=r,n*=n,r?Math.max(n*i*g/r,r/(n*u*g)):1/0}function i(t,n,e,r){var i,u=-1,a=t.length,o=e.x,l=e.y,s=n?c(t.area/n):0;if(n==e.dx){for((r||s>e.dy)&&(s=e.dy);a>++u;)i=t[u],i.x=o,i.y=l,i.dy=s,o+=i.dx=Math.min(e.x+e.dx-o,s?c(i.area/s):0);i.z=!0,i.dx+=e.x+e.dx-o,e.y+=s,e.dy-=s}else{for((r||s>e.dx)&&(s=e.dx);a>++u;)i=t[u],i.x=o,i.y=l,i.dx=s,l+=i.dy=Math.min(e.y+e.dy-l,s?c(i.area/s):0);i.z=!1,i.dy+=e.y+e.dy-l,e.x+=s,e.dx-=s}}function u(r){var i=a||o(r),u=i[0];return u.x=0,u.y=0,u.dx=l[0],u.dy=l[1],a&&o.revalue(u),t([u],u.dx*u.dy/u.value),(a?e:n)(u),h&&(a=i),i}var a,o=d3.layout.hierarchy(),c=Math.round,l=[1,1],s=null,f=Yr,h=!1,d="squarify",g=.5*(1+Math.sqrt(5));return u.size=function(t){return arguments.length?(l=t,u):l},u.padding=function(t){function n(n){var e=t.call(u,n,n.depth);return null==e?Yr(n):Ur(n,"number"==typeof e?[e,e,e,e]:e)}function e(n){return Ur(n,t)}if(!arguments.length)return s;var r;return f=null==(s=t)?Yr:"function"==(r=typeof t)?n:"number"===r?(t=[t,t,t,t],e):e,u},u.round=function(t){return arguments.length?(c=t?Math.round:Number,u):c!=Number},u.sticky=function(t){return arguments.length?(h=t,a=null,u):h},u.ratio=function(t){return arguments.length?(g=t,u):g},u.mode=function(t){return arguments.length?(d=t+"",u):d},hr(u,o)},d3.csv=Ir(",","text/csv"),d3.tsv=Ir(" ","text/tab-separated-values"),d3.geo={},d3.geo.stream=function(t,n){to.hasOwnProperty(t.type)?to[t.type](t,n):Vr(t,n)};var to={Feature:function(t,n){Vr(t.geometry,n)},FeatureCollection:function(t,n){for(var e=t.features,r=-1,i=e.length;i>++r;)Vr(e[r].geometry,n)}},no={Sphere:function(t,n){n.sphere()},Point:function(t,n){var e=t.coordinates;n.point(e[0],e[1])},MultiPoint:function(t,n){for(var e,r=t.coordinates,i=-1,u=r.length;u>++i;)e=r[i],n.point(e[0],e[1])},LineString:function(t,n){Xr(t.coordinates,n,0)},MultiLineString:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;i>++r;)Xr(e[r],n,0)},Polygon:function(t,n){Zr(t.coordinates,n)},MultiPolygon:function(t,n){for(var e=t.coordinates,r=-1,i=e.length;i>++r;)Zr(e[r],n)},GeometryCollection:function(t,n){for(var e=t.geometries,r=-1,i=e.length;i>++r;)Vr(e[r],n)}};d3.geo.albersUsa=function(){function t(t){return n(t)(t)}function n(t){var n=t[0],a=t[1];return a>50?r:-140>n?i:21>a?u:e}var e=d3.geo.albers(),r=d3.geo.albers().rotate([160,0]).center([0,60]).parallels([55,65]),i=d3.geo.albers().rotate([160,0]).center([0,20]).parallels([8,18]),u=d3.geo.albers().rotate([60,0]).center([0,10]).parallels([8,18]);return t.scale=function(n){return arguments.length?(e.scale(n),r.scale(.6*n),i.scale(n),u.scale(1.5*n),t.translate(e.translate())):e.scale()},t.translate=function(n){if(!arguments.length)return e.translate();var a=e.scale(),o=n[0],c=n[1];return e.translate(n),r.translate([o-.4*a,c+.17*a]),i.translate([o-.19*a,c+.2*a]),u.translate([o+.58*a,c+.43*a]),t},t.scale(e.scale())},(d3.geo.albers=function(){var t=29.5*ju,n=45.5*ju,e=Pi(ei),r=e(t,n);return r.parallels=function(r){return arguments.length?e(t=r[0]*ju,n=r[1]*ju):[t*Ou,n*Ou]},r.rotate([98,0]).center([0,38]).scale(1e3)}).raw=ei;var eo=Vi(function(t){return Math.sqrt(2/(1+t))},function(t){return 2*Math.asin(t/2)});(d3.geo.azimuthalEqualArea=function(){return Ri(eo)}).raw=eo;var ro=Vi(function(t){var n=Math.acos(t);return n&&n/Math.sin(n)},a);(d3.geo.azimuthalEquidistant=function(){return Ri(ro)}).raw=ro,d3.geo.bounds=ri(a),d3.geo.centroid=function(t){io=uo=ao=oo=co=0,d3.geo.stream(t,lo);var n;return uo&&Math.abs(n=Math.sqrt(ao*ao+oo*oo+co*co))>Pu?[Math.atan2(oo,ao)*Ou,Math.asin(Math.max(-1,Math.min(1,co/n)))*Ou]:void 0};var io,uo,ao,oo,co,lo={sphere:function(){2>io&&(io=2,uo=ao=oo=co=0)},point:ii,lineStart:ai,lineEnd:oi,polygonStart:function(){2>io&&(io=2,uo=ao=oo=co=0),lo.lineStart=ui},polygonEnd:function(){lo.lineStart=ai}};d3.geo.circle=function(){function t(){var t="function"==typeof r?r.apply(this,arguments):r,n=Oi(-t[0]*ju,-t[1]*ju,0).invert,i=[];return e(null,null,1,{point:function(t,e){i.push(t=n(t,e)),t[0]*=Ou,t[1]*=Ou}}),{type:"Polygon",coordinates:[i]}}var n,e,r=[0,0],i=6;return t.origin=function(n){return arguments.length?(r=n,t):r},t.angle=function(r){return arguments.length?(e=ci((n=+r)*ju,i*ju),t):n},t.precision=function(r){return arguments.length?(e=ci(n*ju,(i=+r)*ju),t):i},t.angle(90)};var so=si(o,vi,Mi);(d3.geo.equirectangular=function(){return Ri(_i).scale(250/Ru)}).raw=_i.invert=_i;var fo=Vi(function(t){return 1/t},Math.atan);(d3.geo.gnomonic=function(){return Ri(fo)}).raw=fo,d3.geo.graticule=function(){function t(){return{type:"MultiLineString",coordinates:n()}}function n(){return d3.range(Math.ceil(r/c)*c,e,c).map(a).concat(d3.range(Math.ceil(u/l)*l,i,l).map(o))}var e,r,i,u,a,o,c=22.5,l=c,s=2.5;return t.lines=function(){return n().map(function(t){return{type:"LineString",coordinates:t}})},t.outline=function(){return{type:"Polygon",coordinates:[a(r).concat(o(i).slice(1),a(e).reverse().slice(1),o(u).reverse().slice(1))]}},t.extent=function(n){return arguments.length?(r=+n[0][0],e=+n[1][0],u=+n[0][1],i=+n[1][1],r>e&&(n=r,r=e,e=n),u>i&&(n=u,u=i,i=n),t.precision(s)):[[r,u],[e,i]]},t.step=function(n){return arguments.length?(c=+n[0],l=+n[1],t):[c,l]},t.precision=function(n){return arguments.length?(s=+n,a=wi(u,i,s),o=Si(r,e,s),t):s},t.extent([[-180+Pu,-90+Pu],[180-Pu,90-Pu]])},d3.geo.interpolate=function(t,n){return ki(t[0]*ju,t[1]*ju,n[0]*ju,n[1]*ju)},d3.geo.greatArc=function(){function e(){for(var t=r||a.apply(this,arguments),n=i||o.apply(this,arguments),e=u||d3.geo.interpolate(t,n),i=0,l=c/e.distance,s=[t];1>(i+=l);)s.push(e(i));return s.push(n),{type:"LineString",coordinates:s}}var r,i,u,a=n,o=t,c=6*ju;return e.distance=function(){return(u||d3.geo.interpolate(r||a.apply(this,arguments),i||o.apply(this,arguments))).distance},e.source=function(t){return arguments.length?(a=t,r="function"==typeof t?null:t,u=r&&i?d3.geo.interpolate(r,i):null,e):a},e.target=function(t){return arguments.length?(o=t,i="function"==typeof t?null:t,u=r&&i?d3.geo.interpolate(r,i):null,e):o},e.precision=function(t){return arguments.length?(c=t*ju,e):c/ju},e},Ei.invert=function(t,n){return[2*Ru*t,2*Math.atan(Math.exp(2*Ru*n))-Ru/2]},(d3.geo.mercator=function(){return Ri(Ei).scale(500)}).raw=Ei;var ho=Vi(function(){return 1},Math.asin);(d3.geo.orthographic=function(){return Ri(ho)}).raw=ho,d3.geo.path=function(){function t(t){return t&&d3.geo.stream(t,r(i.pointRadius("function"==typeof u?+u.apply(this,arguments):u))),i.result()}var n,e,r,i,u=4.5;return t.area=function(t){return go=0,d3.geo.stream(t,r(mo)),go},t.centroid=function(t){return io=ao=oo=co=0,d3.geo.stream(t,r(vo)),co?[ao/co,oo/co]:void 0},t.bounds=function(t){return ri(r)(t)},t.projection=function(e){return arguments.length?(r=(n=e)?e.stream||Ni(e):a,t):n},t.context=function(n){return arguments.length?(i=null==(e=n)?new Ti:new qi(n),t):e},t.pointRadius=function(n){return arguments.length?(u="function"==typeof n?n:+n,t):u},t.projection(d3.geo.albersUsa()).context(null)};var go,po,mo={point:Pn,lineStart:Pn,lineEnd:Pn,polygonStart:function(){po=0,mo.lineStart=Ci},polygonEnd:function(){mo.lineStart=mo.lineEnd=mo.point=Pn,go+=Math.abs(po/2)}},vo={point:zi,lineStart:Di,lineEnd:Li,polygonStart:function(){vo.lineStart=Fi},polygonEnd:function(){vo.point=zi,vo.lineStart=Di,vo.lineEnd=Li}};d3.geo.area=function(t){return yo=0,d3.geo.stream(t,bo),yo};var yo,Mo,bo={sphere:function(){yo+=4*Ru},point:Pn,lineStart:Pn,lineEnd:Pn,polygonStart:function(){Mo=0,bo.lineStart=Hi},polygonEnd:function(){yo+=0>Mo?4*Ru+Mo:Mo,bo.lineStart=bo.lineEnd=bo.point=Pn}};d3.geo.projection=Ri,d3.geo.projectionMutator=Pi;var xo=Vi(function(t){return 1/(1+t)},function(t){return 2*Math.atan(t)});(d3.geo.stereographic=function(){return Ri(xo)}).raw=xo,d3.geom={},d3.geom.hull=function(t){if(3>t.length)return[];var n,e,r,i,u,a,o,c,l,s,f=t.length,h=f-1,d=[],g=[],p=0;for(n=1;f>n;++n)t[n][1]<t[p][1]?p=n:t[n][1]==t[p][1]&&(p=t[n][0]<t[p][0]?n:p);for(n=0;f>n;++n)n!==p&&(i=t[n][1]-t[p][1],r=t[n][0]-t[p][0],d.push({angle:Math.atan2(i,r),index:n}));for(d.sort(function(t,n){return t.angle-n.angle}),l=d[0].angle,c=d[0].index,o=0,n=1;h>n;++n)e=d[n].index,l==d[n].angle?(r=t[c][0]-t[p][0],i=t[c][1]-t[p][1],u=t[e][0]-t[p][0],a=t[e][1]-t[p][1],r*r+i*i>=u*u+a*a?d[n].index=-1:(d[o].index=-1,l=d[n].angle,o=n,c=e)):(l=d[n].angle,o=n,c=e);for(g.push(p),n=0,e=0;2>n;++e)-1!==d[e].index&&(g.push(d[e].index),n++);for(s=g.length;h>e;++e)if(-1!==d[e].index){for(;!Xi(g[s-2],g[s-1],d[e].index,t);)--s;g[s++]=d[e].index}var m=[];for(n=0;s>n;++n)m.push(t[g[n]]);return m},d3.geom.polygon=function(t){return t.area=function(){for(var n=0,e=t.length,r=t[e-1][1]*t[0][0]-t[e-1][0]*t[0][1];e>++n;)r+=t[n-1][1]*t[n][0]-t[n-1][0]*t[n][1];return.5*r},t.centroid=function(n){var e,r,i=-1,u=t.length,a=0,o=0,c=t[u-1];for(arguments.length||(n=-1/(6*t.area()));u>++i;)e=c,c=t[i],r=e[0]*c[1]-c[0]*e[1],a+=(e[0]+c[0])*r,o+=(e[1]+c[1])*r;return[a*n,o*n]},t.clip=function(n){for(var e,r,i,u,a,o,c=-1,l=t.length,s=t[l-1];l>++c;){for(e=n.slice(),n.length=0,u=t[c],a=e[(i=e.length)-1],r=-1;i>++r;)o=e[r],Zi(o,s,u)?(Zi(a,s,u)||n.push(Bi(a,o,s,u)),n.push(o)):Zi(a,s,u)&&n.push(Bi(a,o,s,u)),a=o;s=u}return n},t},d3.geom.voronoi=function(t){var n=t.map(function(){return[]}),e=1e6;return $i(t,function(t){var r,i,u,a,o,c;1===t.a&&t.b>=0?(r=t.ep.r,i=t.ep.l):(r=t.ep.l,i=t.ep.r),1===t.a?(o=r?r.y:-e,u=t.c-t.b*o,c=i?i.y:e,a=t.c-t.b*c):(u=r?r.x:-e,o=t.c-t.a*u,a=i?i.x:e,c=t.c-t.a*a);var l=[u,o],s=[a,c];n[t.region.l.index].push(l,s),n[t.region.r.index].push(l,s)}),n=n.map(function(n,e){var r=t[e][0],i=t[e][1],u=n.map(function(t){return Math.atan2(t[0]-r,t[1]-i)});return d3.range(n.length).sort(function(t,n){return u[t]-u[n]}).filter(function(t,n,e){return!n||u[t]-u[e[n-1]]>Pu}).map(function(t){return n[t]})}),n.forEach(function(n,r){var i=n.length;if(!i)return n.push([-e,-e],[-e,e],[e,e],[e,-e]);if(!(i>2)){var u=t[r],a=n[0],o=n[1],c=u[0],l=u[1],s=a[0],f=a[1],h=o[0],d=o[1],g=Math.abs(h-s),p=d-f;if(Pu>Math.abs(p)){var m=f>l?-e:e;n.push([-e,m],[e,m])}else if(Pu>g){var v=s>c?-e:e;n.push([v,-e],[v,e])}else{var m=(s-c)*(d-f)>(h-s)*(f-l)?e:-e,y=Math.abs(p)-g;Pu>Math.abs(y)?n.push([0>p?m:-m,m]):(y>0&&(m*=-1),n.push([-e,m],[e,m]))}}}),n};var _o={l:"r",r:"l"};d3.geom.delaunay=function(t){var n=t.map(function(){return[]}),e=[];return $i(t,function(e){n[e.region.l.index].push(t[e.region.r.index])}),n.forEach(function(n,r){var i=t[r],u=i[0],a=i[1];n.forEach(function(t){t.angle=Math.atan2(t[0]-u,t[1]-a)}),n.sort(function(t,n){return t.angle-n.angle});for(var o=0,c=n.length-1;c>o;o++)e.push([i,n[o],n[o+1]])}),e},d3.geom.quadtree=function(t,n,e,r,i){function u(t,n,e,r,i,u){if(!isNaN(n.x)&&!isNaN(n.y))if(t.leaf){var o=t.point;o?.01>Math.abs(o.x-n.x)+Math.abs(o.y-n.y)?a(t,n,e,r,i,u):(t.point=null,a(t,o,e,r,i,u),a(t,n,e,r,i,u)):t.point=n}else a(t,n,e,r,i,u)}function a(t,n,e,r,i,a){var o=.5*(e+i),c=.5*(r+a),l=n.x>=o,s=n.y>=c,f=(s<<1)+l;t.leaf=!1,t=t.nodes[f]||(t.nodes[f]=Ji()),l?e=o:i=o,s?r=c:a=c,u(t,n,e,r,i,a)}var o,c=-1,l=t.length;if(5>arguments.length)if(3===arguments.length)i=e,r=n,e=n=0;else for(n=e=1/0,r=i=-1/0;l>++c;)o=t[c],n>o.x&&(n=o.x),e>o.y&&(e=o.y),o.x>r&&(r=o.x),o.y>i&&(i=o.y);var s=r-n,f=i-e;s>f?i=e+s:r=n+f;var h=Ji();return h.add=function(t){u(h,t,n,e,r,i)},h.visit=function(t){Gi(t,h,n,e,r,i)},t.forEach(h.add),h},d3.time={};var wo=Date,So=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];Ki.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){ko.setUTCDate.apply(this._,arguments)},setDay:function(){ko.setUTCDay.apply(this._,arguments)},setFullYear:function(){ko.setUTCFullYear.apply(this._,arguments)},setHours:function(){ko.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){ko.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){ko.setUTCMinutes.apply(this._,arguments)},setMonth:function(){ko.setUTCMonth.apply(this._,arguments)},setSeconds:function(){ko.setUTCSeconds.apply(this._,arguments)},setTime:function(){ko.setTime.apply(this._,arguments)}};var ko=Date.prototype,Eo="%a %b %e %X %Y",Ao="%m/%d/%Y",No="%H:%M:%S",To=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],qo=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],Co=["January","February","March","April","May","June","July","August","September","October","November","December"],zo=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];d3.time.format=function(t){function n(n){for(var r,i,u,a=[],o=-1,c=0;e>++o;)37===t.charCodeAt(o)&&(a.push(t.substring(c,o)),null!=(i=jo[r=t.charAt(++o)])&&(r=t.charAt(++o)),(u=Oo[r])&&(r=u(n,null==i?"e"===r?" ":"0":i)),a.push(r),c=o+1);return a.push(t.substring(c,o)),a.join("")}var e=t.length;return n.parse=function(n){var e={y:1900,m:0,d:1,H:0,M:0,S:0,L:0},r=Wi(e,t,n,0);if(r!=n.length)return null;"p"in e&&(e.H=e.H%12+12*e.p);var i=new wo;return i.setFullYear(e.y,e.m,e.d),i.setHours(e.H,e.M,e.S,e.L),i},n.toString=function(){return t},n};var Do=Qi(To),Lo=Qi(qo),Fo=Qi(Co),Ho=tu(Co),Ro=Qi(zo),Po=tu(zo),jo={"-":"",_:" ",0:"0"},Oo={a:function(t){return qo[t.getDay()]},A:function(t){return To[t.getDay()]},b:function(t){return zo[t.getMonth()]},B:function(t){return Co[t.getMonth()]},c:d3.time.format(Eo),d:function(t,n){return nu(t.getDate(),n,2)},e:function(t,n){return nu(t.getDate(),n,2)},H:function(t,n){return nu(t.getHours(),n,2)},I:function(t,n){return nu(t.getHours()%12||12,n,2)},j:function(t,n){return nu(1+d3.time.dayOfYear(t),n,3)},L:function(t,n){return nu(t.getMilliseconds(),n,3)},m:function(t,n){return nu(t.getMonth()+1,n,2)},M:function(t,n){return nu(t.getMinutes(),n,2)},p:function(t){return t.getHours()>=12?"PM":"AM"},S:function(t,n){return nu(t.getSeconds(),n,2)},U:function(t,n){return nu(d3.time.sundayOfYear(t),n,2)},w:function(t){return t.getDay()},W:function(t,n){return nu(d3.time.mondayOfYear(t),n,2)},x:d3.time.format(Ao),X:d3.time.format(No),y:function(t,n){return nu(t.getFullYear()%100,n,2)},Y:function(t,n){return nu(t.getFullYear()%1e4,n,4)},Z:Mu,"%":function(){return"%"}},Yo={a:eu,A:ru,b:iu,B:uu,c:au,d:du,e:du,H:gu,I:gu,L:vu,m:hu,M:pu,p:yu,S:mu,x:ou,X:cu,y:su,Y:lu},Uo=/^\s*\d+/,Io=d3.map({am:0,pm:1});d3.time.format.utc=function(t){function n(t){try{wo=Ki;var n=new wo;return n._=t,e(n)}finally{wo=Date}}var e=d3.time.format(t);return n.parse=function(t){try{wo=Ki;var n=e.parse(t);return n&&n._}finally{wo=Date}},n.toString=e.toString,n};var Vo=d3.time.format.utc("%Y-%m-%dT%H:%M:%S.%LZ");d3.time.format.iso=Date.prototype.toISOString?bu:Vo,bu.parse=function(t){var n=new Date(t);return isNaN(n)?null:n},bu.toString=Vo.toString,d3.time.second=xu(function(t){return new wo(1e3*Math.floor(t/1e3))},function(t,n){t.setTime(t.getTime()+1e3*Math.floor(n))},function(t){return t.getSeconds()}),d3.time.seconds=d3.time.second.range,d3.time.seconds.utc=d3.time.second.utc.range,d3.time.minute=xu(function(t){return new wo(6e4*Math.floor(t/6e4))},function(t,n){t.setTime(t.getTime()+6e4*Math.floor(n))},function(t){return t.getMinutes()}),d3.time.minutes=d3.time.minute.range,d3.time.minutes.utc=d3.time.minute.utc.range,d3.time.hour=xu(function(t){var n=t.getTimezoneOffset()/60;return new wo(36e5*(Math.floor(t/36e5-n)+n))},function(t,n){t.setTime(t.getTime()+36e5*Math.floor(n))},function(t){return t.getHours()}),d3.time.hours=d3.time.hour.range,d3.time.hours.utc=d3.time.hour.utc.range,d3.time.day=xu(function(t){var n=new wo(1970,0);return n.setFullYear(t.getFullYear(),t.getMonth(),t.getDate()),n},function(t,n){t.setDate(t.getDate()+n)},function(t){return t.getDate()-1}),d3.time.days=d3.time.day.range,d3.time.days.utc=d3.time.day.utc.range,d3.time.dayOfYear=function(t){var n=d3.time.year(t);return Math.floor((t-n-6e4*(t.getTimezoneOffset()-n.getTimezoneOffset()))/864e5)},So.forEach(function(t,n){t=t.toLowerCase(),n=7-n;var e=d3.time[t]=xu(function(t){return(t=d3.time.day(t)).setDate(t.getDate()-(t.getDay()+n)%7),t},function(t,n){t.setDate(t.getDate()+7*Math.floor(n))},function(t){var e=d3.time.year(t).getDay();return Math.floor((d3.time.dayOfYear(t)+(e+n)%7)/7)-(e!==n)});d3.time[t+"s"]=e.range,d3.time[t+"s"].utc=e.utc.range,d3.time[t+"OfYear"]=function(t){var e=d3.time.year(t).getDay();return Math.floor((d3.time.dayOfYear(t)+(e+n)%7)/7)}}),d3.time.week=d3.time.sunday,d3.time.weeks=d3.time.sunday.range,d3.time.weeks.utc=d3.time.sunday.utc.range,d3.time.weekOfYear=d3.time.sundayOfYear,d3.time.month=xu(function(t){return t=d3.time.day(t),t.setDate(1),t},function(t,n){t.setMonth(t.getMonth()+n)},function(t){return t.getMonth()}),d3.time.months=d3.time.month.range,d3.time.months.utc=d3.time.month.utc.range,d3.time.year=xu(function(t){return t=d3.time.day(t),t.setMonth(0,1),t},function(t,n){t.setFullYear(t.getFullYear()+n)},function(t){return t.getFullYear()}),d3.time.years=d3.time.year.range,d3.time.years.utc=d3.time.year.utc.range;var Xo=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Zo=[[d3.time.second,1],[d3.time.second,5],[d3.time.second,15],[d3.time.second,30],[d3.time.minute,1],[d3.time.minute,5],[d3.time.minute,15],[d3.time.minute,30],[d3.time.hour,1],[d3.time.hour,3],[d3.time.hour,6],[d3.time.hour,12],[d3.time.day,1],[d3.time.day,2],[d3.time.week,1],[d3.time.month,1],[d3.time.month,3],[d3.time.year,1]],Bo=[[d3.time.format("%Y"),o],[d3.time.format("%B"),function(t){return t.getMonth()}],[d3.time.format("%b %d"),function(t){return 1!=t.getDate()}],[d3.time.format("%a %d"),function(t){return t.getDay()&&1!=t.getDate()}],[d3.time.format("%I %p"),function(t){return t.getHours()}],[d3.time.format("%I:%M"),function(t){return t.getMinutes()}],[d3.time.format(":%S"),function(t){return t.getSeconds()}],[d3.time.format(".%L"),function(t){return t.getMilliseconds()}]],$o=d3.scale.linear(),Jo=Eu(Bo);Zo.year=function(t,n){return $o.domain(t.map(Nu)).ticks(n).map(Au)},d3.time.scale=function(){return wu(d3.scale.linear(),Zo,Jo)};var Go=Zo.map(function(t){return[t[0].utc,t[1]]}),Ko=[[d3.time.format.utc("%Y"),o],[d3.time.format.utc("%B"),function(t){return t.getUTCMonth()}],[d3.time.format.utc("%b %d"),function(t){return 1!=t.getUTCDate()}],[d3.time.format.utc("%a %d"),function(t){return t.getUTCDay()&&1!=t.getUTCDate()}],[d3.time.format.utc("%I %p"),function(t){return t.getUTCHours()}],[d3.time.format.utc("%I:%M"),function(t){return t.getUTCMinutes()}],[d3.time.format.utc(":%S"),function(t){return t.getUTCSeconds()}],[d3.time.format.utc(".%L"),function(t){return t.getUTCMilliseconds()}]],Wo=Eu(Ko);Go.year=function(t,n){return $o.domain(t.map(qu)).ticks(n).map(Tu)},d3.time.scale.utc=function(){return wu(d3.scale.linear(),Go,Wo)}})();
\ No newline at end of file diff --git a/dgbuilder/public/favicon.ico b/dgbuilder/public/favicon.ico Binary files differnew file mode 100644 index 00000000..10210a75 --- /dev/null +++ b/dgbuilder/public/favicon.ico diff --git a/dgbuilder/public/font-awesome/css/font-awesome.min.css b/dgbuilder/public/font-awesome/css/font-awesome.min.css new file mode 100644 index 00000000..ec53d4d6 --- /dev/null +++ b/dgbuilder/public/font-awesome/css/font-awesome.min.css @@ -0,0 +1,4 @@ +/*! + * Font Awesome 4.2.0 by @davegandy - http://fontawesome.io - @fontawesome + * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) + */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.2.0');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.2.0') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff?v=4.2.0') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.2.0') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.2.0#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font:normal normal normal 14px/1 FontAwesome;font-size:inherit;text-rendering:auto;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.33333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.28571429em;text-align:center}.fa-ul{padding-left:0;margin-left:2.14285714em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.14285714em;width:2.14285714em;top:.14285714em;text-align:center}.fa-li.fa-lg{left:-1.85714286em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:fa-spin 2s infinite linear;animation:fa-spin 2s infinite linear}@-webkit-keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes fa-spin{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1);-webkit-transform:scale(-1, 1);-ms-transform:scale(-1, 1);transform:scale(-1, 1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1);-webkit-transform:scale(1, -1);-ms-transform:scale(1, -1);transform:scale(1, -1)}:root .fa-rotate-90,:root .fa-rotate-180,:root .fa-rotate-270,:root .fa-flip-horizontal,:root .fa-flip-vertical{filter:none}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-remove:before,.fa-close:before,.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-photo:before,.fa-image:before,.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before,.fa-bar-chart:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-navicon:before,.fa-reorder:before,.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-desc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-asc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-mail-reply-all:before,.fa-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"}.fa-space-shuttle:before{content:"\f197"}.fa-slack:before{content:"\f198"}.fa-envelope-square:before{content:"\f199"}.fa-wordpress:before{content:"\f19a"}.fa-openid:before{content:"\f19b"}.fa-institution:before,.fa-bank:before,.fa-university:before{content:"\f19c"}.fa-mortar-board:before,.fa-graduation-cap:before{content:"\f19d"}.fa-yahoo:before{content:"\f19e"}.fa-google:before{content:"\f1a0"}.fa-reddit:before{content:"\f1a1"}.fa-reddit-square:before{content:"\f1a2"}.fa-stumbleupon-circle:before{content:"\f1a3"}.fa-stumbleupon:before{content:"\f1a4"}.fa-delicious:before{content:"\f1a5"}.fa-digg:before{content:"\f1a6"}.fa-pied-piper:before{content:"\f1a7"}.fa-pied-piper-alt:before{content:"\f1a8"}.fa-drupal:before{content:"\f1a9"}.fa-joomla:before{content:"\f1aa"}.fa-language:before{content:"\f1ab"}.fa-fax:before{content:"\f1ac"}.fa-building:before{content:"\f1ad"}.fa-child:before{content:"\f1ae"}.fa-paw:before{content:"\f1b0"}.fa-spoon:before{content:"\f1b1"}.fa-cube:before{content:"\f1b2"}.fa-cubes:before{content:"\f1b3"}.fa-behance:before{content:"\f1b4"}.fa-behance-square:before{content:"\f1b5"}.fa-steam:before{content:"\f1b6"}.fa-steam-square:before{content:"\f1b7"}.fa-recycle:before{content:"\f1b8"}.fa-automobile:before,.fa-car:before{content:"\f1b9"}.fa-cab:before,.fa-taxi:before{content:"\f1ba"}.fa-tree:before{content:"\f1bb"}.fa-spotify:before{content:"\f1bc"}.fa-deviantart:before{content:"\f1bd"}.fa-soundcloud:before{content:"\f1be"}.fa-database:before{content:"\f1c0"}.fa-file-pdf-o:before{content:"\f1c1"}.fa-file-word-o:before{content:"\f1c2"}.fa-file-excel-o:before{content:"\f1c3"}.fa-file-powerpoint-o:before{content:"\f1c4"}.fa-file-photo-o:before,.fa-file-picture-o:before,.fa-file-image-o:before{content:"\f1c5"}.fa-file-zip-o:before,.fa-file-archive-o:before{content:"\f1c6"}.fa-file-sound-o:before,.fa-file-audio-o:before{content:"\f1c7"}.fa-file-movie-o:before,.fa-file-video-o:before{content:"\f1c8"}.fa-file-code-o:before{content:"\f1c9"}.fa-vine:before{content:"\f1ca"}.fa-codepen:before{content:"\f1cb"}.fa-jsfiddle:before{content:"\f1cc"}.fa-life-bouy:before,.fa-life-buoy:before,.fa-life-saver:before,.fa-support:before,.fa-life-ring:before{content:"\f1cd"}.fa-circle-o-notch:before{content:"\f1ce"}.fa-ra:before,.fa-rebel:before{content:"\f1d0"}.fa-ge:before,.fa-empire:before{content:"\f1d1"}.fa-git-square:before{content:"\f1d2"}.fa-git:before{content:"\f1d3"}.fa-hacker-news:before{content:"\f1d4"}.fa-tencent-weibo:before{content:"\f1d5"}.fa-qq:before{content:"\f1d6"}.fa-wechat:before,.fa-weixin:before{content:"\f1d7"}.fa-send:before,.fa-paper-plane:before{content:"\f1d8"}.fa-send-o:before,.fa-paper-plane-o:before{content:"\f1d9"}.fa-history:before{content:"\f1da"}.fa-circle-thin:before{content:"\f1db"}.fa-header:before{content:"\f1dc"}.fa-paragraph:before{content:"\f1dd"}.fa-sliders:before{content:"\f1de"}.fa-share-alt:before{content:"\f1e0"}.fa-share-alt-square:before{content:"\f1e1"}.fa-bomb:before{content:"\f1e2"}.fa-soccer-ball-o:before,.fa-futbol-o:before{content:"\f1e3"}.fa-tty:before{content:"\f1e4"}.fa-binoculars:before{content:"\f1e5"}.fa-plug:before{content:"\f1e6"}.fa-slideshare:before{content:"\f1e7"}.fa-twitch:before{content:"\f1e8"}.fa-yelp:before{content:"\f1e9"}.fa-newspaper-o:before{content:"\f1ea"}.fa-wifi:before{content:"\f1eb"}.fa-calculator:before{content:"\f1ec"}.fa-paypal:before{content:"\f1ed"}.fa-google-wallet:before{content:"\f1ee"}.fa-cc-visa:before{content:"\f1f0"}.fa-cc-mastercard:before{content:"\f1f1"}.fa-cc-discover:before{content:"\f1f2"}.fa-cc-amex:before{content:"\f1f3"}.fa-cc-paypal:before{content:"\f1f4"}.fa-cc-stripe:before{content:"\f1f5"}.fa-bell-slash:before{content:"\f1f6"}.fa-bell-slash-o:before{content:"\f1f7"}.fa-trash:before{content:"\f1f8"}.fa-copyright:before{content:"\f1f9"}.fa-at:before{content:"\f1fa"}.fa-eyedropper:before{content:"\f1fb"}.fa-paint-brush:before{content:"\f1fc"}.fa-birthday-cake:before{content:"\f1fd"}.fa-area-chart:before{content:"\f1fe"}.fa-pie-chart:before{content:"\f200"}.fa-line-chart:before{content:"\f201"}.fa-lastfm:before{content:"\f202"}.fa-lastfm-square:before{content:"\f203"}.fa-toggle-off:before{content:"\f204"}.fa-toggle-on:before{content:"\f205"}.fa-bicycle:before{content:"\f206"}.fa-bus:before{content:"\f207"}.fa-ioxhost:before{content:"\f208"}.fa-angellist:before{content:"\f209"}.fa-cc:before{content:"\f20a"}.fa-shekel:before,.fa-sheqel:before,.fa-ils:before{content:"\f20b"}.fa-meanpath:before{content:"\f20c"}
\ No newline at end of file diff --git a/dgbuilder/public/font-awesome/fonts/FontAwesome.otf b/dgbuilder/public/font-awesome/fonts/FontAwesome.otf Binary files differnew file mode 100644 index 00000000..81c9ad94 --- /dev/null +++ b/dgbuilder/public/font-awesome/fonts/FontAwesome.otf diff --git a/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.eot b/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.eot Binary files differnew file mode 100755 index 00000000..84677bc0 --- /dev/null +++ b/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.eot diff --git a/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.svg b/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.svg new file mode 100755 index 00000000..d907b25a --- /dev/null +++ b/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.svg @@ -0,0 +1,520 @@ +<?xml version="1.0" standalone="no"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" > +<svg xmlns="http://www.w3.org/2000/svg"> +<metadata></metadata> +<defs> +<font id="fontawesomeregular" horiz-adv-x="1536" > +<font-face units-per-em="1792" ascent="1536" descent="-256" /> +<missing-glyph horiz-adv-x="448" /> +<glyph unicode=" " horiz-adv-x="448" /> +<glyph unicode="	" horiz-adv-x="448" /> +<glyph unicode=" " horiz-adv-x="448" /> +<glyph unicode="¨" horiz-adv-x="1792" /> +<glyph unicode="©" horiz-adv-x="1792" /> +<glyph unicode="®" horiz-adv-x="1792" /> +<glyph unicode="´" horiz-adv-x="1792" /> +<glyph unicode="Æ" horiz-adv-x="1792" /> +<glyph unicode="Ø" horiz-adv-x="1792" /> +<glyph unicode=" " horiz-adv-x="768" /> +<glyph unicode=" " horiz-adv-x="1537" /> +<glyph unicode=" " horiz-adv-x="768" /> +<glyph unicode=" " horiz-adv-x="1537" /> +<glyph unicode=" " horiz-adv-x="512" /> +<glyph unicode=" " horiz-adv-x="384" /> +<glyph unicode=" " horiz-adv-x="256" /> +<glyph unicode=" " horiz-adv-x="256" /> +<glyph unicode=" " horiz-adv-x="192" /> +<glyph unicode=" " horiz-adv-x="307" /> +<glyph unicode=" " horiz-adv-x="85" /> +<glyph unicode=" " horiz-adv-x="307" /> +<glyph unicode=" " horiz-adv-x="384" /> +<glyph unicode="™" horiz-adv-x="1792" /> +<glyph unicode="∞" horiz-adv-x="1792" /> +<glyph unicode="≠" horiz-adv-x="1792" /> +<glyph unicode="◼" horiz-adv-x="500" d="M0 0z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" /> +<glyph unicode="" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 29.5q208 165 401 317q54 43 100.5 115.5t46.5 131.5z M1792 1120v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47t47 -113z" /> +<glyph unicode="" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45 t45 -19h128q26 0 45 19t19 45zM1792 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 704v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1792 320v128 q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 704v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1792 1088v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19 t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1920 1248v-1344q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1344q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" /> +<glyph unicode="" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68z" /> +<glyph unicode="" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28 h960q40 0 68 -28t28 -68zM1792 1312v-192q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5 t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z " /> +<glyph unicode="" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0 52 38 90t90 38t90 -38t38 -90z" /> +<glyph unicode="" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1472q0 14 9 23t23 9h192q14 0 23 -9t9 -23z" /> +<glyph unicode="" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5t-8 23.5v222q0 12 8 23t19 13 l186 28q14 46 39 92q-40 57 -107 138q-10 12 -10 24q0 10 9 23q26 36 98.5 107.5t94.5 71.5q13 0 26 -10l138 -107q44 23 91 38q16 136 29 186q7 28 36 28h222q14 0 24.5 -8.5t11.5 -21.5l28 -184q49 -16 90 -37l142 107q9 9 24 9q13 0 25 -10q129 -119 165 -170q7 -8 7 -22 q0 -12 -8 -23q-15 -21 -51 -66.5t-54 -70.5q26 -50 41 -98l183 -28q13 -2 21 -12.5t8 -23.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832 q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" /> +<glyph unicode="" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z " /> +<glyph unicode="" d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t26 -33l417 -1044q26 -62 26 -116z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136 q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q42 0 59 -39z" /> +<glyph unicode="" d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273 t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198 t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" /> +<glyph unicode="" d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q14 0 25 -9 l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" /> +<glyph unicode="" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 22.5v7q65 268 270 434.5t480 166.5 q146 0 284 -55.5t245 -156.5l130 129q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5z M1536 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5t9.5 -22.5zM1536 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h960q13 0 22.5 -9.5 t9.5 -22.5zM1664 160v832q0 13 -9.5 22.5t-22.5 9.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1792 1248v-1088q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1472q66 0 113 -47 t47 -113z" /> +<glyph unicode="" horiz-adv-x="1152" d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" /> +<glyph unicode="" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185 33l-20 49q-60 148 -60 314q0 151 67 291t179 242.5 t266 163.5t320 61t320 -61t266 -163.5t179 -242.5t67 -291z" /> +<glyph unicode="" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" /> +<glyph unicode="" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56 29 76 44q74 54 115.5 135.5t41.5 173.5t-41.5 173.5 t-115.5 135.5q-20 15 -76 44q-39 20 -39 59q0 26 19 45t45 19q13 0 26 -5q140 -59 225 -188.5t85 -282.5zM1664 640q0 -230 -127 -422.5t-338 -283.5q-13 -5 -26 -5q-26 0 -45 19t-19 45q0 36 39 59q7 4 22.5 10.5t22.5 10.5q46 25 82 51q123 91 192 227t69 289t-69 289 t-192 227q-36 26 -82 51q-7 4 -22.5 10.5t-22.5 10.5q-39 23 -39 59q0 26 19 45t45 19q13 0 26 -5q211 -91 338 -283.5t127 -422.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" /> +<glyph unicode="" horiz-adv-x="1792" d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" /> +<glyph unicode="" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" /> +<glyph unicode="" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l715 -714q37 -39 37 -91z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 9h761q74 0 114 -56t18 -130l-274 -906 q-36 -119 -71.5 -153.5t-128.5 -34.5h-869q-27 0 -38 -15q-11 -16 -1 -43q24 -70 144 -70h923q29 0 56 15.5t35 41.5l300 987q7 22 5 57q38 -15 59 -43zM575 1056q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5 t-16.5 -22.5zM492 800q-4 -13 2 -22.5t20 -9.5h608q13 0 25.5 9.5t16.5 22.5l21 64q4 13 -2 22.5t-20 9.5h-608q-13 0 -25.5 -9.5t-16.5 -22.5z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" /> +<glyph unicode="" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" /> +<glyph unicode="" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M725 977l-170 -450q33 0 136.5 -2t160.5 -2q19 0 57 2q-87 253 -184 452zM0 -128l2 79q23 7 56 12.5t57 10.5t49.5 14.5t44.5 29t31 50.5l237 616l280 724h75h53q8 -14 11 -21l205 -480q33 -78 106 -257.5t114 -274.5q15 -34 58 -144.5t72 -168.5q20 -45 35 -57 q19 -15 88 -29.5t84 -20.5q6 -38 6 -57q0 -4 -0.5 -13t-0.5 -13q-63 0 -190 8t-191 8q-76 0 -215 -7t-178 -8q0 43 4 78l131 28q1 0 12.5 2.5t15.5 3.5t14.5 4.5t15 6.5t11 8t9 11t2.5 14q0 16 -31 96.5t-72 177.5t-42 100l-450 2q-26 -58 -76.5 -195.5t-50.5 -162.5 q0 -22 14 -37.5t43.5 -24.5t48.5 -13.5t57 -8.5t41 -4q1 -19 1 -58q0 -9 -2 -27q-58 0 -174.5 10t-174.5 10q-8 0 -26.5 -4t-21.5 -4q-80 -14 -188 -14z" /> +<glyph unicode="" horiz-adv-x="1408" d="M555 15q74 -32 140 -32q376 0 376 335q0 114 -41 180q-27 44 -61.5 74t-67.5 46.5t-80.5 25t-84 10.5t-94.5 2q-73 0 -101 -10q0 -53 -0.5 -159t-0.5 -158q0 -8 -1 -67.5t-0.5 -96.5t4.5 -83.5t12 -66.5zM541 761q42 -7 109 -7q82 0 143 13t110 44.5t74.5 89.5t25.5 142 q0 70 -29 122.5t-79 82t-108 43.5t-124 14q-50 0 -130 -13q0 -50 4 -151t4 -152q0 -27 -0.5 -80t-0.5 -79q0 -46 1 -69zM0 -128l2 94q15 4 85 16t106 27q7 12 12.5 27t8.5 33.5t5.5 32.5t3 37.5t0.5 34v35.5v30q0 982 -22 1025q-4 8 -22 14.5t-44.5 11t-49.5 7t-48.5 4.5 t-30.5 3l-4 83q98 2 340 11.5t373 9.5q23 0 68.5 -0.5t67.5 -0.5q70 0 136.5 -13t128.5 -42t108 -71t74 -104.5t28 -137.5q0 -52 -16.5 -95.5t-39 -72t-64.5 -57.5t-73 -45t-84 -40q154 -35 256.5 -134t102.5 -248q0 -100 -35 -179.5t-93.5 -130.5t-138 -85.5t-163.5 -48.5 t-176 -14q-44 0 -132 3t-132 3q-106 0 -307 -11t-231 -12z" /> +<glyph unicode="" horiz-adv-x="1024" d="M0 -126l17 85q6 2 81.5 21.5t111.5 37.5q28 35 41 101q1 7 62 289t114 543.5t52 296.5v25q-24 13 -54.5 18.5t-69.5 8t-58 5.5l19 103q33 -2 120 -6.5t149.5 -7t120.5 -2.5q48 0 98.5 2.5t121 7t98.5 6.5q-5 -39 -19 -89q-30 -10 -101.5 -28.5t-108.5 -33.5 q-8 -19 -14 -42.5t-9 -40t-7.5 -45.5t-6.5 -42q-27 -148 -87.5 -419.5t-77.5 -355.5q-2 -9 -13 -58t-20 -90t-16 -83.5t-6 -57.5l1 -18q17 -4 185 -31q-3 -44 -16 -99q-11 0 -32.5 -1.5t-32.5 -1.5q-29 0 -87 10t-86 10q-138 2 -206 2q-51 0 -143 -9t-121 -11z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1744 128q33 0 42 -18.5t-11 -44.5l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80zM81 1407l54 -27q12 -5 211 -5q44 0 132 2 t132 2q36 0 107.5 -0.5t107.5 -0.5h293q6 0 21 -0.5t20.5 0t16 3t17.5 9t15 17.5l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 48t-14.5 73.5t-7.5 35.5q-6 8 -12 12.5t-15.5 6t-13 2.5t-18 0.5t-16.5 -0.5 q-17 0 -66.5 0.5t-74.5 0.5t-64 -2t-71 -6q-9 -81 -8 -136q0 -94 2 -388t2 -455q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27 q19 42 19 383q0 101 -3 303t-3 303v117q0 2 0.5 15.5t0.5 25t-1 25.5t-3 24t-5 14q-11 12 -162 12q-33 0 -93 -12t-80 -26q-19 -13 -34 -72.5t-31.5 -111t-42.5 -53.5q-42 26 -56 44v383z" /> +<glyph unicode="" d="M81 1407l54 -27q12 -5 211 -5q44 0 132 2t132 2q70 0 246.5 1t304.5 0.5t247 -4.5q33 -1 56 31l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 47.5t-15 73.5t-7 36q-10 13 -27 19q-5 2 -66 2q-30 0 -93 1t-103 1 t-94 -2t-96 -7q-9 -81 -8 -136l1 -152v52q0 -55 1 -154t1.5 -180t0.5 -153q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 52v9q17 27 61.5 43t98.5 29t78 27 q7 16 11.5 74t6 145.5t1.5 155t-0.5 153.5t-0.5 89q0 7 -2.5 21.5t-2.5 22.5q0 7 0.5 44t1 73t0 76.5t-3 67.5t-6.5 32q-11 12 -162 12q-41 0 -163 -13.5t-138 -24.5q-19 -12 -34 -71.5t-31.5 -111.5t-42.5 -54q-42 26 -56 44v383zM1310 125q12 0 42 -19.5t57.5 -41.5 t59.5 -49t36 -30q26 -21 26 -49t-26 -49q-4 -3 -36 -30t-59.5 -49t-57.5 -41.5t-42 -19.5q-13 0 -20.5 10.5t-10 28.5t-2.5 33.5t1.5 33t1.5 19.5h-1024q0 -2 1.5 -19.5t1.5 -33t-2.5 -33.5t-10 -28.5t-20.5 -10.5q-12 0 -42 19.5t-57.5 41.5t-59.5 49t-36 30q-26 21 -26 49 t26 49q4 3 36 30t59.5 49t57.5 41.5t42 19.5q13 0 20.5 -10.5t10 -28.5t2.5 -33.5t-1.5 -33t-1.5 -19.5h1024q0 2 -1.5 19.5t-1.5 33t2.5 33.5t10 28.5t20.5 10.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344 q13 0 22.5 -9.5t9.5 -22.5zM256 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v192 q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088 q13 0 22.5 -9.5t9.5 -22.5zM1792 1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5 q39 -17 39 -59z" /> +<glyph unicode="" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" /> +<glyph unicode="" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" /> +<glyph unicode="" d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" /> +<glyph unicode="" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 1216l288 -288l-672 -672h-288v288zM1756 1084l-92 -92 l-288 288l92 92q28 28 68 28t68 -28l152 -152q28 -28 28 -68t-28 -68z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34q-8 -2 -12 -2q-16 0 -26 13q-10 14 -21 31t-39.5 68.5t-49.5 99.5 t-38.5 114t-17.5 122q0 49 3.5 91t14 90t28 88t47 81.5t68.5 74t94.5 61.5t124.5 48.5t159.5 30.5t196.5 11h160v192q0 42 39 59q13 5 25 5q26 0 45 -19l384 -384q19 -19 19 -45t-19 -45z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263 -263l647 647q24 24 57 24t57 -24l110 -110 q24 -24 24 -57t-24 -57z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" /> +<glyph unicode="" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" /> +<glyph unicode="" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" /> +<glyph unicode="" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" /> +<glyph unicode="" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" /> +<glyph unicode="" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1171 1235l-531 -531l531 -531q19 -19 19 -45t-19 -45l-166 -166q-19 -19 -45 -19t-45 19l-742 742q-19 19 -19 45t19 45l742 742q19 19 45 19t45 -19l166 -166q19 -19 19 -45t-19 -45z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1107 659l-742 -742q-19 -19 -45 -19t-45 19l-166 166q-19 19 -19 45t19 45l531 531l-531 531q-19 19 -19 45t19 45l166 166q19 19 45 19t45 -19l742 -742q19 -19 19 -45t-19 -45z" /> +<glyph unicode="" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" /> +<glyph unicode="" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59 q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v143 q-161 37 -278.5 154.5t-154.5 278.5h-143q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h143q37 161 154.5 278.5t278.5 154.5v143q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-143q161 -37 278.5 -154.5t154.5 -278.5h143q26 0 45 -19t19 -45z" /> +<glyph unicode="" d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23 l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5 t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198 t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61 t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" /> +<glyph unicode="" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" /> +<glyph unicode="" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" /> +<glyph unicode="" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" /> +<glyph unicode="" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" /> +<glyph unicode="" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" /> +<glyph unicode="" d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 77 168 77q93 0 158.5 -65.5t65.5 -158.5 t-65.5 -158.5t-158.5 -65.5h440q14 0 23 -9t9 -23z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 38t-16 44q-9 51 -9 104q0 115 43.5 220t119 184.5 t170.5 139t204 95.5q55 18 145 25.5t179.5 9t178.5 6t163.5 24t113.5 56.5l29.5 29.5t29.5 28t27 20t36.5 16t43.5 4.5q39 0 70.5 -46t47.5 -112t24 -124t8 -96z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150.5t27.5 -184z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 368t499.5 139t499.5 -139t376.5 -368q20 -35 20 -69z" /> +<glyph unicode="" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 18 -6t31 -15.5t33 -18.5t31.5 -18.5t19.5 -11.5 q16 -10 16 -27zM1344 704q0 -139 -79 -253.5t-209 -164.5l280 502q8 -45 8 -84zM1792 576q0 -35 -20 -69q-39 -64 -109 -145q-150 -172 -347.5 -267t-419.5 -95l74 132q212 18 392.5 137t301.5 307q-115 179 -282 294l63 112q95 -64 182.5 -153t144.5 -184q20 -34 20 -69z " /> +<glyph unicode="" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9 q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" /> +<glyph unicode="" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h288v288h-288v-288zM1280 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64 q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47 h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" /> +<glyph unicode="" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5 v192h-256q-48 0 -87 -15t-69 -45t-51 -61.5t-45 -77.5q-32 -62 -78 -171q-29 -66 -49.5 -111t-54 -105t-64 -100t-74 -83t-90 -68.5t-106.5 -42t-128 -16.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q48 0 87 15t69 45t51 61.5t45 77.5q32 62 78 171q29 66 49.5 111 t54 105t64 100t74 83t90 68.5t106.5 42t128 16.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" /> +<glyph unicode="" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1683 205l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5t19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1683 728l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5t19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5 -8t3 -11.5t1 -11.5v-13v-11v-160v-416h192q26 0 45 -19t19 -45z " /> +<glyph unicode="" horiz-adv-x="1664" d="M640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5 l-1044 -122q1 -7 4.5 -21.5t6 -26.5t2.5 -22q0 -16 -24 -64h920q26 0 45 -19t19 -45t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 14 11 39.5t29.5 59.5t20.5 38l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t20 -15.5t13 -24.5t7.5 -26.5 t5.5 -29.5t4.5 -25.5h1201q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" /> +<glyph unicode="" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" /> +<glyph unicode="" horiz-adv-x="2048" d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" /> +<glyph unicode="" d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4 q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5 t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M1536 160q0 -119 -84.5 -203.5t-203.5 -84.5h-192v608h203l30 224h-233v143q0 54 28 83t96 29l132 1v207q-96 9 -180 9q-136 0 -218 -80.5t-82 -225.5v-166h-224v-224h224v-608h-544q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 q119 0 203.5 -84.5t84.5 -203.5v-960z" /> +<glyph unicode="" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 -90.5t-90.5 -37.5h-1536q-53 0 -90.5 37.5t-37.5 90.5v1280 q0 53 37.5 90.5t90.5 37.5h1536q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189 -131 -365l355 -355l96 96q-3 3 -26 24.5t-40 38.5t-33 36.5 t-16 28.5q0 17 49 66t66 49q13 0 23 -10q6 -6 46 -44.5t82 -79.5t86.5 -86t73 -78t28.5 -41z" /> +<glyph unicode="" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11 -108 -23 -155q-7 -24 -30 -24h-186q-11 0 -20 7.5t-10 17.5 l-23 153q-34 10 -75 31l-118 -89q-7 -7 -20 -7q-11 0 -21 8q-144 133 -144 160q0 9 7 19q10 14 41 53t47 61q-23 44 -35 82l-152 24q-10 1 -17 9.5t-7 19.5v185q0 10 7 19.5t16 10.5l155 24q11 35 32 76q-34 48 -90 115q-7 11 -7 20q0 12 7 20q22 30 82 89t79 59q11 0 21 -7 l115 -90q34 18 77 32q11 108 23 154q7 24 30 24h186q11 0 20 -7.5t10 -17.5l23 -153q34 -10 75 -31l118 89q8 7 20 7q11 0 21 -8q144 -133 144 -160q0 -9 -7 -19q-12 -16 -42 -54t-45 -60q23 -48 34 -82l152 -23q10 -2 17 -10.5t7 -19.5zM1920 198v-140q0 -16 -149 -31 q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20 t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31zM1920 1222v-140q0 -16 -149 -31q-12 -27 -30 -52q51 -113 51 -138q0 -4 -4 -7q-122 -71 -124 -71q-8 0 -46 47t-52 68 q-20 -2 -30 -2t-30 2q-14 -21 -52 -68t-46 -47q-2 0 -124 71q-4 3 -4 7q0 25 51 138q-18 25 -30 52q-149 15 -149 31v140q0 16 149 31q13 29 30 52q-51 113 -51 138q0 4 4 7q4 2 35 20t59 34t30 16q8 0 46 -46.5t52 -67.5q20 2 30 2t30 -2q51 71 92 112l6 2q4 0 124 -70 q4 -3 4 -7q0 -25 -51 -138q17 -23 30 -52q149 -15 149 -31z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7 q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230z" /> +<glyph unicode="" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5q32 1 53.5 47t21.5 81zM1536 769 q0 -89 -49 -163q9 -33 9 -69q0 -77 -38 -144q3 -21 3 -43q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5h-36h-93q-96 0 -189.5 22.5t-216.5 65.5q-116 40 -138 40h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h274q36 24 137 155q58 75 107 128 q24 25 35.5 85.5t30.5 126.5t62 108q39 37 90 37q84 0 151 -32.5t102 -101.5t35 -186q0 -93 -48 -192h176q104 0 180 -76t76 -179z" /> +<glyph unicode="" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h352q50 0 89 38.5t39 89.5z M1536 511q0 -103 -76 -179t-180 -76h-176q48 -99 48 -192q0 -118 -35 -186q-35 -69 -102 -101.5t-151 -32.5q-51 0 -90 37q-34 33 -54 82t-25.5 90.5t-17.5 84.5t-31 64q-48 50 -107 127q-101 131 -137 155h-274q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5 h288q22 0 138 40q128 44 223 66t200 22h112q140 0 226.5 -79t85.5 -216v-5q60 -77 60 -178q0 -22 -3 -43q38 -67 38 -144q0 -36 -9 -69q49 -74 49 -163z" /> +<glyph unicode="" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5 q224 0 351 -124t127 -344z" /> +<glyph unicode="" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45z" /> +<glyph unicode="" d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5 q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q26 0 45 -19t19 -45z" /> +<glyph unicode="" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 44.5t-173 97.5t-112 130t-41.5 143v128q0 40 28 68t68 28h288v96 q0 66 47 113t113 47h576q66 0 113 -47t47 -113v-96h288q40 0 68 -28t28 -68z" /> +<glyph unicode="" d="M394 184q-8 -9 -20 3q-13 11 -4 19q8 9 20 -3q12 -11 4 -19zM352 245q9 -12 0 -19q-8 -6 -17 7t0 18q9 7 17 -6zM291 305q-5 -7 -13 -2q-10 5 -7 12q3 5 13 2q10 -5 7 -12zM322 271q-6 -7 -16 3q-9 11 -2 16q6 6 16 -3q9 -11 2 -16zM451 159q-4 -12 -19 -6q-17 4 -13 15 t19 7q16 -5 13 -16zM514 154q0 -11 -16 -11q-17 -2 -17 11q0 11 16 11q17 2 17 -11zM572 164q2 -10 -14 -14t-18 8t14 15q16 2 18 -9zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-224q-16 0 -24.5 1t-19.5 5t-16 14.5t-5 27.5v239q0 97 -52 142q57 6 102.5 18t94 39 t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103 q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -103t0.5 -68q0 -22 -11 -33.5t-22 -13t-33 -1.5 h-224q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92 t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 -19l448 -448q31 -30 14 -69z" /> +<glyph unicode="" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t-281 -180.5q-124 -44 -326 -44 q-57 0 -170 14.5t-169 14.5q-24 0 -72.5 -14.5t-73.5 -14.5q-73 0 -123.5 55.5t-50.5 128.5q0 24 11 68t11 67q0 40 -12.5 120.5t-12.5 121.5q0 111 18 217.5t54.5 209.5t100.5 194t150 156q78 59 232 120q194 78 316 78q60 0 175.5 -24t173.5 -24q19 0 57 5t58 5 q81 0 118 -50.5t37 -134.5q0 -23 -5 -68t-5 -68q0 -10 1 -18.5t3 -17t4 -13.5t6.5 -16t6.5 -17q16 -40 25 -118.5t9 -136.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5 -20.5t14 -24t11.5 -19q76 -137 174 -235t235 -174 q2 -1 19 -11.5t24 -14t20.5 -8.5t22.5 -5q18 0 46 28.5t53 62t55 62t50 28.5q14 0 28.5 -7t35.5 -21.5t25 -17.5q25 -15 53.5 -31t63.5 -35t54 -30q70 -35 76 -53q3 -7 3 -21z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" /> +<glyph unicode="" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216.5 -320.5t320.5 -216.5q6 -2 30 -11t33 -12.5 t29.5 -10t33 -9t30.5 -5t34 -2.5q57 0 130.5 34t94.5 80q22 53 22 101zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41 q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" /> +<glyph unicode="" horiz-adv-x="1024" d="M959 1524v-264h-157q-86 0 -116 -36t-30 -108v-189h293l-39 -296h-254v-759h-306v759h-255v296h255v218q0 186 104 288.5t277 102.5q147 0 228 -12z" /> +<glyph unicode="" d="M1536 640q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -39.5 7t-12.5 30v211q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 121 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-86 13.5 q-44 -113 -7 -204q-79 -85 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-40 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -48.5 52t-49.5 24l-20 3q-21 0 -29 -4.5t-5 -11.5t9 -14t13 -12l7 -5q22 -10 43.5 -38t31.5 -51l10 -23 q13 -38 44 -61.5t67 -30t69.5 -7t55.5 3.5l23 4q0 -38 0.5 -89t0.5 -54q0 -18 -13 -30t-40 -7q-232 77 -378.5 277.5t-146.5 451.5q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5 t316.5 -131.5t131.5 -316.5z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" /> +<glyph unicode="" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5v143q0 28 20 46q18 18 44 18h3q262 -13 501.5 -120t425.5 -294 q187 -186 294 -425.5t120 -501.5z" /> +<glyph unicode="" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q-66 0 -113 47t-47 113v320q0 25 16 75 l197 606q17 53 63 86t101 33h782q55 0 101 -33t63 -86l197 -606q16 -50 16 -75z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" /> +<glyph unicode="" horiz-adv-x="1792" d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM246 128h1300q-266 300 -266 832q0 51 -24 105t-69 103t-121.5 80.5t-169.5 31.5t-169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -532 -266 -832z M1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5 t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" /> +<glyph unicode="" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 -188l186 53q41 12 70 -19q31 -29 19 -70 l-53 -186l188 -48q40 -10 52 -51q10 -42 -20 -70z" /> +<glyph unicode="" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-180.5 -76h-169q-4 -62 -37 -119q3 -21 3 -43 q0 -101 -60 -178q1 -139 -85 -219.5t-227 -80.5q-133 0 -322 69q-164 59 -223 59h-288q-53 0 -90.5 37.5t-37.5 90.5v640q0 53 37.5 90.5t90.5 37.5h288q10 0 21.5 4.5t23.5 14t22.5 18t24 22.5t20.5 21.5t19 21.5t14 17q65 74 100 129q13 21 33 62t37 72t40.5 63t55 49.5 t69.5 17.5q125 0 206.5 -67t81.5 -189q0 -68 -22 -128h374q104 0 180 -76t76 -179z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32zM1664 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45 t45 -19t45 19t19 45zM1792 768v-640q0 -53 -37.5 -90.5t-90.5 -37.5h-288q-59 0 -223 -59q-190 -69 -317 -69q-142 0 -230 77.5t-87 217.5l1 5q-61 76 -61 178q0 22 3 43q-33 57 -37 119h-169q-105 0 -180.5 76t-75.5 181q0 103 76 179t180 76h374q-22 60 -22 128 q0 122 81.5 189t206.5 67q38 0 69.5 -17.5t55 -49.5t40.5 -63t37 -72t33 -62q35 -55 100 -129q2 -3 14 -17t19 -21.5t20.5 -21.5t24 -22.5t22.5 -18t23.5 -14t21.5 -4.5h288q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 -59 -223v-288q0 -53 -37.5 -90.5 t-90.5 -37.5h-640q-53 0 -90.5 37.5t-37.5 90.5v288q0 10 -4.5 21.5t-14 23.5t-18 22.5t-22.5 24t-21.5 20.5t-21.5 19t-17 14q-74 65 -129 100q-21 13 -62 33t-72 37t-63 40.5t-49.5 55t-17.5 69.5q0 125 67 206.5t189 81.5q68 0 128 -22v374q0 104 76 180t179 76 q105 0 181 -75.5t76 -180.5v-169q62 -4 119 -37q21 3 43 3q101 0 178 -60q139 1 219.5 -85t80.5 -227z" /> +<glyph unicode="" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33 t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 580 q0 -142 -77.5 -230t-217.5 -87l-5 1q-76 -61 -178 -61q-22 0 -43 3q-54 -30 -119 -37v-169q0 -105 -76 -180.5t-181 -75.5q-103 0 -179 76t-76 180v374q-54 -22 -128 -22q-121 0 -188.5 81.5t-67.5 206.5q0 38 17.5 69.5t49.5 55t63 40.5t72 37t62 33q55 35 129 100 q3 2 17 14t21.5 19t21.5 20.5t22.5 24t18 22.5t14 23.5t4.5 21.5v288q0 53 37.5 90.5t90.5 37.5h640q53 0 90.5 -37.5t37.5 -90.5v-288q0 -59 59 -223q69 -190 69 -317z" /> +<glyph unicode="" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11 q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 10.5t-9.5 10.5q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5q-3 2 -6 1.5t-4.5 -1t-4.5 -3t-5 -3.5 q-3 -2 -8.5 -3t-8.5 -2q15 5 -1 11q-10 4 -16 3q9 4 7.5 12t-8.5 14h5q-1 4 -8.5 8.5t-17.5 8.5t-13 6q-8 5 -34 9.5t-33 0.5q-5 -6 -4.5 -10.5t4 -14t3.5 -12.5q1 -6 -5.5 -13t-6.5 -12q0 -7 14 -15.5t10 -21.5q-3 -8 -16 -16t-16 -12q-5 -8 -1.5 -18.5t10.5 -16.5 q2 -2 1.5 -4t-3.5 -4.5t-5.5 -4t-6.5 -3.5l-3 -2q-11 -5 -20.5 6t-13.5 26q-7 25 -16 30q-23 8 -29 -1q-5 13 -41 26q-25 9 -58 4q6 1 0 15q-7 15 -19 12q3 6 4 17.5t1 13.5q3 13 12 23q1 1 7 8.5t9.5 13.5t0.5 6q35 -4 50 11q5 5 11.5 17t10.5 17q9 6 14 5.5t14.5 -5.5 t14.5 -5q14 -1 15.5 11t-7.5 20q12 -1 3 17q-5 7 -8 9q-12 4 -27 -5q-8 -4 2 -8q-1 1 -9.5 -10.5t-16.5 -17.5t-16 5q-1 1 -5.5 13.5t-9.5 13.5q-8 0 -16 -15q3 8 -11 15t-24 8q19 12 -8 27q-7 4 -20.5 5t-19.5 -4q-5 -7 -5.5 -11.5t5 -8t10.5 -5.5t11.5 -4t8.5 -3 q14 -10 8 -14q-2 -1 -8.5 -3.5t-11.5 -4.5t-6 -4q-3 -4 0 -14t-2 -14q-5 5 -9 17.5t-7 16.5q7 -9 -25 -6l-10 1q-4 0 -16 -2t-20.5 -1t-13.5 8q-4 8 0 20q1 4 4 2q-4 3 -11 9.5t-10 8.5q-46 -15 -94 -41q6 -1 12 1q5 2 13 6.5t10 5.5q34 14 42 7l5 5q14 -16 20 -25 q-7 4 -30 1q-20 -6 -22 -12q7 -12 5 -18q-4 3 -11.5 10t-14.5 11t-15 5q-16 0 -22 -1q-146 -80 -235 -222q7 -7 12 -8q4 -1 5 -9t2.5 -11t11.5 3q9 -8 3 -19q1 1 44 -27q19 -17 21 -21q3 -11 -10 -18q-1 2 -9 9t-9 4q-3 -5 0.5 -18.5t10.5 -12.5q-7 0 -9.5 -16t-2.5 -35.5 t-1 -23.5l2 -1q-3 -12 5.5 -34.5t21.5 -19.5q-13 -3 20 -43q6 -8 8 -9q3 -2 12 -7.5t15 -10t10 -10.5q4 -5 10 -22.5t14 -23.5q-2 -6 9.5 -20t10.5 -23q-1 0 -2.5 -1t-2.5 -1q3 -7 15.5 -14t15.5 -13q1 -3 2 -10t3 -11t8 -2q2 20 -24 62q-15 25 -17 29q-3 5 -5.5 15.5 t-4.5 14.5q2 0 6 -1.5t8.5 -3.5t7.5 -4t2 -3q-3 -7 2 -17.5t12 -18.5t17 -19t12 -13q6 -6 14 -19.5t0 -13.5q9 0 20 -10t17 -20q5 -8 8 -26t5 -24q2 -7 8.5 -13.5t12.5 -9.5l16 -8t13 -7q5 -2 18.5 -10.5t21.5 -11.5q10 -4 16 -4t14.5 2.5t13.5 3.5q15 2 29 -15t21 -21 q36 -19 55 -11q-2 -1 0.5 -7.5t8 -15.5t9 -14.5t5.5 -8.5q5 -6 18 -15t18 -15q6 4 7 9q-3 -8 7 -20t18 -10q14 3 14 32q-31 -15 -49 18q0 1 -2.5 5.5t-4 8.5t-2.5 8.5t0 7.5t5 3q9 0 10 3.5t-2 12.5t-4 13q-1 8 -11 20t-12 15q-5 -9 -16 -8t-16 9q0 -1 -1.5 -5.5t-1.5 -6.5 q-13 0 -15 1q1 3 2.5 17.5t3.5 22.5q1 4 5.5 12t7.5 14.5t4 12.5t-4.5 9.5t-17.5 2.5q-19 -1 -26 -20q-1 -3 -3 -10.5t-5 -11.5t-9 -7q-7 -3 -24 -2t-24 5q-13 8 -22.5 29t-9.5 37q0 10 2.5 26.5t3 25t-5.5 24.5q3 2 9 9.5t10 10.5q2 1 4.5 1.5t4.5 0t4 1.5t3 6q-1 1 -4 3 q-3 3 -4 3q7 -3 28.5 1.5t27.5 -1.5q15 -11 22 2q0 1 -2.5 9.5t-0.5 13.5q5 -27 29 -9q3 -3 15.5 -5t17.5 -5q3 -2 7 -5.5t5.5 -4.5t5 0.5t8.5 6.5q10 -14 12 -24q11 -40 19 -44q7 -3 11 -2t4.5 9.5t0 14t-1.5 12.5l-1 8v18l-1 8q-15 3 -18.5 12t1.5 18.5t15 18.5q1 1 8 3.5 t15.5 6.5t12.5 8q21 19 15 35q7 0 11 9q-1 0 -5 3t-7.5 5t-4.5 2q9 5 2 16q5 3 7.5 11t7.5 10q9 -12 21 -2q7 8 1 16q5 7 20.5 10.5t18.5 9.5q7 -2 8 2t1 12t3 12q4 5 15 9t13 5l17 11q3 4 0 4q18 -2 31 11q10 11 -6 20q3 6 -3 9.5t-15 5.5q3 1 11.5 0.5t10.5 1.5 q15 10 -7 16q-17 5 -43 -12zM879 10q206 36 351 189q-3 3 -12.5 4.5t-12.5 3.5q-18 7 -24 8q1 7 -2.5 13t-8 9t-12.5 8t-11 7q-2 2 -7 6t-7 5.5t-7.5 4.5t-8.5 2t-10 -1l-3 -1q-3 -1 -5.5 -2.5t-5.5 -3t-4 -3t0 -2.5q-21 17 -36 22q-5 1 -11 5.5t-10.5 7t-10 1.5t-11.5 -7 q-5 -5 -6 -15t-2 -13q-7 5 0 17.5t2 18.5q-3 6 -10.5 4.5t-12 -4.5t-11.5 -8.5t-9 -6.5t-8.5 -5.5t-8.5 -7.5q-3 -4 -6 -12t-5 -11q-2 4 -11.5 6.5t-9.5 5.5q2 -10 4 -35t5 -38q7 -31 -12 -48q-27 -25 -29 -40q-4 -22 12 -26q0 -7 -8 -20.5t-7 -21.5q0 -6 2 -16z" /> +<glyph unicode="" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" /> +<glyph unicode="" horiz-adv-x="1792" d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" /> +<glyph unicode="" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0 -42 -39 -59q-13 -5 -25 -5q-26 0 -45 19z " /> +<glyph unicode="" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75 t75 -181zM1344 896q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5zM1920 671q0 -78 -56 -118.5t-138 -40.5h-134q-103 123 -265 128q81 117 81 256q0 29 -5 66q66 -23 133 -23q59 0 119 21.5t97.5 42.5 t43.5 21q124 0 124 -353zM1792 1280q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3.5 27.5q0 40 28 68t68 28q15 0 27.5 -3.5t25.5 -13t19 -15 t21.5 -21.5t18.5 -19q33 31 33 73zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-206 207q-83 83 -83 203q0 123 88 209l-88 88q-86 -88 -208 -88q-120 0 -204 84l-208 208q-84 84 -84 204t85 203l147 146q83 83 203 83q121 0 204 -85l206 -207 q83 -83 83 -203q0 -123 -88 -209l88 -88q86 88 208 88q120 0 204 -84l208 -208q84 -84 84 -204z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " /> +<glyph unicode="" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" /> +<glyph unicode="" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 79 222 79q145 0 277 -84q83 -52 132 -123t56 -148 q4 -48 -10 -97q4 -1 12 -5l110 -66l690 387q14 8 31 8q16 0 29 -7l128 -64q30 -16 35 -51q3 -36 -25 -56zM579 836q46 42 21 108t-106 117q-92 59 -192 59q-74 0 -113 -36q-46 -42 -21 -108t106 -117q92 -59 192 -59q74 0 113 36zM494 91q81 51 106 117t-21 108 q-39 36 -113 36q-100 0 -192 -59q-81 -51 -106 -117t21 -108q39 -36 113 -36q100 0 192 59zM672 704l96 -58v11q0 36 33 56l14 8l-79 47l-26 -26q-3 -3 -10 -11t-12 -12q-2 -2 -4 -3.5t-3 -2.5zM896 480l96 -32l736 576l-128 64l-768 -431v-113l-160 -96l9 -8q2 -2 7 -6 q4 -4 11 -12t11 -12l26 -26zM1600 64l128 64l-520 408l-177 -138q-2 -3 -13 -7z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0 82 57 139t139 57q88 0 149 -63l581 -581q100 -98 100 -235 z" /> +<glyph unicode="" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 -28 48 -76t20 -88z" /> +<glyph unicode="" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z M1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t-35.5 -52.5h127v60h105zM1792 224v-192q0 -13 -9.5 -22.5 t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1123v-99h-335v99h107q0 41 0.5 122t0.5 121v12h-2q-8 -17 -50 -54l-71 76l136 127h106v-404h108zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5 t-9.5 22.5v192q0 14 9 23t23 9h1216q13 0 22.5 -9.5t9.5 -22.5zM1792 1248v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -35 -109 -81q-80 -48 -153 -66q-80 -21 -203 -21q-114 0 -195 23 l-140 40q-57 16 -72 28q-8 8 -8 22v13q0 108 -2 156q-1 30 0 68l2 37v44l102 2q15 -34 30 -71t22.5 -56t12.5 -27q35 -57 80 -94q43 -36 105 -57q59 -22 132 -22q64 0 139 27q77 26 122 86q47 61 47 129q0 84 -81 157q-34 29 -137 71z" /> +<glyph unicode="" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -13q-73 -11 -79 -17q-15 -15 -15 -41 q0 -7 1.5 -27t1.5 -31q8 -19 22 -396q6 -195 -15 -304q-15 -76 -41 -122q-38 -65 -112 -123q-75 -57 -182 -89q-109 -33 -255 -33q-167 0 -284 46q-119 47 -179 122q-61 76 -83 195q-16 80 -16 237v333q0 188 -17 213q-25 36 -147 39zM1536 -96v64q0 14 -9 23t-23 9h-1472 q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h1472q14 0 23 9t9 23z" /> +<glyph unicode="" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 160v192 q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192 q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1536 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1664 1248v-1088q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1344q66 0 113 -47t47 -113 z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" /> +<glyph unicode="" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" /> +<glyph unicode="" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" /> +<glyph unicode="" d="M829 318q0 -76 -58.5 -112.5t-139.5 -36.5q-41 0 -80.5 9.5t-75.5 28.5t-58 53t-22 78q0 46 25 80t65.5 51.5t82 25t84.5 7.5q20 0 31 -2q2 -1 23 -16.5t26 -19t23 -18t24.5 -22t19 -22.5t17 -26t9 -26.5t4.5 -31.5zM755 863q0 -60 -33 -99.5t-92 -39.5q-53 0 -93 42.5 t-57.5 96.5t-17.5 106q0 61 32 104t92 43q53 0 93.5 -45t58 -101t17.5 -107zM861 1120l88 64h-265q-85 0 -161 -32t-127.5 -98t-51.5 -153q0 -93 64.5 -154.5t158.5 -61.5q22 0 43 3q-13 -29 -13 -54q0 -44 40 -94q-175 -12 -257 -63q-47 -29 -75.5 -73t-28.5 -95 q0 -43 18.5 -77.5t48.5 -56.5t69 -37t77.5 -21t76.5 -6q60 0 120.5 15.5t113.5 46t86 82.5t33 117q0 49 -20 89.5t-49 66.5t-58 47.5t-49 44t-20 44.5t15.5 42.5t37.5 39.5t44 42t37.5 59.5t15.5 82.5q0 60 -22.5 99.5t-72.5 90.5h83zM1152 672h128v64h-128v128h-64v-128 h-128v-64h128v-160h64v160zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M735 740q0 -36 32 -70.5t77.5 -68t90.5 -73.5t77 -104t32 -142q0 -90 -48 -173q-72 -122 -211 -179.5t-298 -57.5q-132 0 -246.5 41.5t-171.5 137.5q-37 60 -37 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 42 -47.5 74t-15.5 73q0 36 21 85q-46 -4 -68 -4 q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q77 66 182.5 98t217.5 32h418l-138 -88h-131q74 -63 112 -133t38 -160q0 -72 -24.5 -129.5t-59 -93t-69.5 -65t-59.5 -61.5t-24.5 -66zM589 836q38 0 78 16.5t66 43.5q53 57 53 159q0 58 -17 125t-48.5 129.5 t-84.5 103.5t-117 41q-42 0 -82.5 -19.5t-65.5 -52.5q-47 -59 -47 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26zM591 -37q58 0 111.5 13t99 39t73 73t27.5 109q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -48 2 q-53 0 -105 -7t-107.5 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -70 35 -123.5t91.5 -83t119 -44t127.5 -14.5zM1401 839h213v-108h-213v-219h-105v219h-212v108h212v217h105v-217z" /> +<glyph unicode="" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" /> +<glyph unicode="" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5 -47t47.5 -113z" /> +<glyph unicode="" d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329 q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" /> +<glyph unicode="" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 -12.5q-14 14 -14 34t14 34l348 348q14 14 34 14t34 -14 q-2 2 -12.5 12t-12.5 13t-10 11.5t-10 13.5t-6 13.5t-5.5 16.5t-1.5 18q0 38 28 68q3 3 16.5 18t19 20.5t18.5 16.5t22 15.5t22 9t26 4.5q40 0 68 -28l408 -408q28 -28 28 -68q0 -13 -4.5 -26t-9 -22t-15.5 -22t-16.5 -18.5t-20.5 -19t-18 -16.5q-30 -28 -68 -28 q-10 0 -18 1.5t-16.5 5.5t-13.5 6t-13.5 10t-11.5 10t-13 12.5t-12 12.5q14 -14 14 -34t-14 -34l-126 -126l256 -256q43 43 96 43q52 0 91 -37l363 -363q37 -39 37 -91z" /> +<glyph unicode="" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 1024q0 53 -37.5 90.5 t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1472 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 384q0 -261 -141 -483q-19 -29 -54 -29h-1402q-35 0 -54 29 q-141 221 -141 483q0 182 71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" /> +<glyph unicode="" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281q0 174 120 321.5 t326 233t450 85.5t450 -85.5t326 -233t120 -321.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224q0 139 94 257t256.5 186.5 t353.5 68.5zM1526 111q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 -5t2 -6t0.5 -6.5t-1 -6.5q-3 -14 -13 -22t-22 -7q-50 7 -86 16q-154 40 -278 128q-90 -16 -176 -16q-271 0 -472 132q58 -4 88 -4q161 0 309 45t264 129 q125 92 192 212t67 254q0 77 -23 152q129 -71 204 -178t75 -230q0 -120 -71 -224.5t-195 -176.5z" /> +<glyph unicode="" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h512q52 0 90 -38t38 -90v-192h96q40 0 68 -28t28 -68 z" /> +<glyph unicode="" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 28q-43 60 -103 97t-128 37q-58 0 -102 -23t-93 -69 q-12 -10 -23 -10q-13 0 -22.5 9.5t-9.5 22.5q0 5 1 7q45 183 172.5 319.5t298 204.5t360.5 68q140 0 274.5 -40t246.5 -113.5t194.5 -187t115.5 -251.5q1 -2 1 -7zM896 1408v-98q-42 2 -64 2t-64 -2v98q0 26 19 45t45 19t45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" /> +<glyph unicode="" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q0 -37 -25 -64q25 -27 25 -64q0 -52 -45 -81q13 -23 13 -47 q0 -46 -31.5 -71t-77.5 -25q-20 -44 -60 -70t-87 -26t-87 26t-60 70q-46 0 -77.5 25t-31.5 71q0 24 13 47q-45 29 -45 81q0 37 25 64q-25 27 -25 64q0 54 47 82q-4 50 -34 107.5t-59.5 95.5t-74.5 87q-103 113 -103 268q0 99 44.5 184.5t117 142t164 89t186.5 32.5 t186.5 -32.5t164 -89t117 -142t44.5 -184.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 38 90t90 38t90 -38t38 -90v-89q-32 -29 -32 -71q0 -40 28 -68 t68 -28t68 28t28 68q0 42 -32 71v89q0 68 -34.5 127.5t-93.5 93.5q0 10 0.5 42.5t0 48t-2.5 41.5t-7 47t-13 40q68 -15 120 -60.5t81 -103t47.5 -132.5t24 -138t5.5 -131zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 -48q10 2 16 2q26 0 45 -19t19 -45v-512q0 -144 -110 -252 t-274 -128v-132q0 -106 94 -181t226 -75t226 75t94 181v395q-57 21 -92.5 70t-35.5 111q0 80 56 136t136 56t136 -56t56 -136z" /> +<glyph unicode="" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" /> +<glyph unicode="" horiz-adv-x="1792" d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5 t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t19 -45z" /> +<glyph unicode="" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M384 736q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64zM1120 512q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704zM1120 256q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704 q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704z" /> +<glyph unicode="" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 992v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 1248v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1536h-1152v-1536h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM1408 1472v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M1152 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM896 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1152 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M896 -128h384v1152h-256v-32q0 -40 -28 -68t-68 -28h-448q-40 0 -68 28t-28 68v32h-256v-1152h384v224q0 13 9.5 22.5t22.5 9.5h320q13 0 22.5 -9.5t9.5 -22.5v-224zM896 1056v320q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-96h-128v96q0 13 -9.5 22.5 t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5v96h128v-96q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1408 1088v-1280q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1280q0 26 19 45t45 19h320 v288q0 40 28 68t68 28h448q40 0 68 -28t28 -68v-288h320q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM1920 1344v-1152 q0 -26 -19 -45t-45 -19h-192q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-128q-26 0 -45 19t-19 45t19 45t45 19v416q0 26 13 58t32 51l198 198q19 19 51 32t58 13h160v320q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 158 -66t66 -158z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96 q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q261 -58 287 -93z" /> +<glyph unicode="" horiz-adv-x="1664" d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" /> +<glyph unicode="" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" /> +<glyph unicode="" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" /> +<glyph unicode="" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" /> +<glyph unicode="" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" /> +<glyph unicode="" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" /> +<glyph unicode="" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" /> +<glyph unicode="" d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103 t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z" /> +<glyph unicode="" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136z" /> +<glyph unicode="" horiz-adv-x="1568" d="M496 192q0 -60 -42.5 -102t-101.5 -42q-60 0 -102 42t-42 102t42 102t102 42q59 0 101.5 -42t42.5 -102zM928 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -66 -47 -113t-113 -47t-113 47t-47 113 t47 113t113 47t113 -47t47 -113zM1360 192q0 -46 -33 -79t-79 -33t-79 33t-33 79t33 79t79 33t79 -33t33 -79zM528 1088q0 -73 -51.5 -124.5t-124.5 -51.5t-124.5 51.5t-51.5 124.5t51.5 124.5t124.5 51.5t124.5 -51.5t51.5 -124.5zM992 1280q0 -80 -56 -136t-136 -56 t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1536 640q0 -40 -28 -68t-68 -28t-68 28t-28 68t28 68t68 28t68 -28t28 -68zM1328 1088q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5z" /> +<glyph unicode="" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" /> +<glyph unicode="" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM1664 496q0 -207 -61 -331q-38 -77 -105.5 -133t-141 -86 t-170 -47.5t-171.5 -22t-167 -4.5q-78 0 -142 3t-147.5 12.5t-152.5 30t-137 51.5t-121 81t-86 115q-62 123 -62 331q0 237 136 396q-27 82 -27 170q0 116 51 218q108 0 190 -39.5t189 -123.5q147 35 309 35q148 0 280 -32q105 82 187 121t189 39q51 -102 51 -218 q0 -87 -27 -168q136 -160 136 -398z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158v-160h192q54 0 99 -24.5t67 -70.5q15 -32 15 -68z " /> +<glyph unicode="" horiz-adv-x="1792" /> +<glyph unicode="" horiz-adv-x="1792" /> +<glyph unicode="" d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5 t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204 t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1920" d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -150q-192 0 -338 128h-220q-146 -128 -338 -128q-212 0 -362 150 t-150 362t150 362t362 150h896q212 0 362 -150t150 -362z" /> +<glyph unicode="" horiz-adv-x="1920" d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16 h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1024 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16 h96q16 0 16 -16zM896 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1280 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1152 880v-96 q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1664 880v-352q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h112v240q0 16 16 16h96q16 0 16 -16zM1792 128v896h-1664v-896 h1664zM1920 1024v-896q0 -53 -37.5 -90.5t-90.5 -37.5h-1664q-53 0 -90.5 37.5t-37.5 90.5v896q0 53 37.5 90.5t90.5 37.5h1664q53 0 90.5 -37.5t37.5 -90.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9 h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102 q-15 -9 -33 -9q-16 0 -32 8q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" /> +<glyph unicode="" horiz-adv-x="1792" d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2 q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v1266 q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -99 48t-91 29t-114 14q-102 0 -235.5 -44t-228.5 -102q-15 -9 -33 -9q-16 0 -32 8 q-32 19 -32 56v742q0 35 31 55q35 21 78.5 42.5t114 52t152.5 49.5t155 19q112 0 209 -31t209 -86q38 -19 89 -19q122 0 310 112q22 12 31 17q31 16 62 -2q31 -20 31 -55z" /> +<glyph unicode="" horiz-adv-x="1664" d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9 t9 -23z" /> +<glyph unicode="" horiz-adv-x="1920" d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5 l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23z" /> +<glyph unicode="" horiz-adv-x="1792" d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1 q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 -173 169 -509z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5 l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23 v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" /> +<glyph unicode="" horiz-adv-x="1024" d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5 q-2 -287 -226 -414q-68 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136q0 -52 -26 -96.5t-70 -69.5v-497 q54 26 154 57q55 17 87.5 29.5t70.5 31t59 39.5t40.5 51t28 69.5t8.5 91.5q-44 25 -70 69.5t-26 96.5q0 80 56 136t136 56t136 -56t56 -136z" /> +<glyph unicode="" horiz-adv-x="1664" d="M439 265l-256 -256q-10 -9 -23 -9q-12 0 -23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320 q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239q35 -21 56 -42l336 -336q84 -86 84 -204zM1031 1044l-239 -18 l-273 274q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l274 -274l-18 -240q-35 21 -56 42l-336 336q-84 86 -84 204q0 120 85 203l147 146q83 83 203 83q121 0 204 -85l334 -335q21 -21 42 -56zM1664 960q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9 t-9 23t9 23t23 9h320q14 0 23 -9t9 -23zM1120 1504v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM1527 1353l-256 -256q-11 -9 -23 -9t-23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" /> +<glyph unicode="" horiz-adv-x="1024" d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5 t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 161 -31t146 -83t106 -127.5t41 -158.5z" /> +<glyph unicode="" horiz-adv-x="640" d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192 q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="640" d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" /> +<glyph unicode="" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1534 846v-206h-514l-3 27 q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t-82 -50.5t-65.5 -51.5t-30.5 -63h232v80 h126z" /> +<glyph unicode="" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1536 -50v-206h-514l-4 27 q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t-87 -63t-41 -73h232v80h126z" /> +<glyph unicode="" horiz-adv-x="1920" d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5 t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t34 -5t21.5 -3.5q150 -24 245 -24q80 0 117 35q46 44 46 89 q0 22 -15 50.5t-33.5 53t-33.5 64.5t-15 83q0 82 59 127.5t144 45.5q80 0 134 -44.5t54 -123.5q0 -41 -17.5 -77.5t-38 -59t-38 -56.5t-17.5 -71q0 -57 42 -83.5t103 -26.5q64 0 180 15t163 17v-2q-1 -2 -3.5 -17.5t-5 -34t-3.5 -21.5q-24 -150 -24 -245q0 -80 35 -117 q44 -46 89 -46q22 0 50.5 15t53 33.5t64.5 33.5t83 15q82 0 127.5 -59t45.5 -143z" /> +<glyph unicode="" horiz-adv-x="1152" d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5 t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" /> +<glyph unicode="" horiz-adv-x="1408" d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128 q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 23l1234 1234q10 10 23 10t23 -10l82 -82q10 -10 10 -23 t-10 -23zM1005 1325l-621 -621v512q0 132 94 226t226 94q102 0 184.5 -59t116.5 -152z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150 t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1664" d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" /> +<glyph unicode="" horiz-adv-x="1408" d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800 q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-25 42 -25 86q0 66 47 113t113 47t113 -47t47 -113 q0 -33 -14 -64h302q0 11 7 20t18 11l448 96q3 1 7 1q12 0 20 -7q12 -9 12 -25z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1 q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" /> +<glyph unicode="" d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" /> +<glyph unicode="" horiz-adv-x="1792" d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" /> +<glyph unicode="" horiz-adv-x="1792" d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-13 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352 q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 -181q0 -70 -35 -128.5t-93 -92.5v-163h192q26 0 45 -19 t19 -45v-128q0 -26 -19 -45t-45 -19h-192v-647q149 20 271.5 82.5t189.5 153.5l-100 100q-15 16 -7 35q8 20 30 20h352q14 0 23 -9t9 -23z" /> +<glyph unicode="" horiz-adv-x="1152" d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181 v-320h736z" /> +<glyph unicode="" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150 t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" /> +<glyph unicode="" horiz-adv-x="384" d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" /> +<glyph unicode="" d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 232 -177 396t-396 177q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128q13 0 23 10 t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56 q16 -8 32 -8q17 0 32 9z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136 t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" /> +<glyph unicode="" d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5 t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1024" d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" /> +<glyph unicode="" horiz-adv-x="1024" d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" /> +<glyph unicode="" d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5 t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q10 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5 t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1024" d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9 t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126 0 -226 -64t-150 -176h468q16 0 25 -12q10 -12 7 -26 l-24 -114q-5 -26 -32 -26h-488q-3 -37 0 -105h459q15 0 25 -12q9 -12 6 -27l-24 -112q-2 -11 -11 -18.5t-20 -7.5h-387q48 -117 149.5 -185.5t228.5 -68.5q18 0 36 1.5t33.5 3.5t29.5 4.5t24.5 5t18.5 4.5l12 3l5 2q13 5 26 -2q12 -7 15 -21z" /> +<glyph unicode="" horiz-adv-x="1024" d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7 q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" /> +<glyph unicode="" horiz-adv-x="1024" d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43 t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5 9.5h135q14 0 23 -9t9 -23v-176q57 -6 110.5 -23t87 -33.5 t63.5 -37.5t39 -29t15 -14q17 -18 5 -38l-81 -146q-8 -15 -23 -16q-14 -3 -27 7q-3 3 -14.5 12t-39 26.5t-58.5 32t-74.5 26t-85.5 11.5q-95 0 -155 -43t-60 -111q0 -26 8.5 -48t29.5 -41.5t39.5 -33t56 -31t60.5 -27t70 -27.5q53 -20 81 -31.5t76 -35t75.5 -42.5t62 -50 t53 -63.5t31.5 -76.5t13 -94z" /> +<glyph unicode="" horiz-adv-x="898" d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102 q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" /> +<glyph unicode="" horiz-adv-x="1027" d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61 l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q0 -13 -9.5 -22.5t-22.5 -9.5z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128 q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" /> +<glyph unicode="" horiz-adv-x="1792" d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23 t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h109l-89 344q-5 15 5 28 q10 12 26 12h137q26 0 31 -24l90 -360h359l97 360q7 24 31 24h126q24 0 31 -24l98 -360h365l93 360q5 24 31 24h137q16 0 26 -12q10 -13 5 -28l-91 -344h111q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-145l-34 -128h179q14 0 23 -9t9 -23z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164 l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0.5t48 -0.5t53 1.5t58.5 4t57 8.5t55.5 14t47.5 21t39.5 30 t24.5 40t9.5 51zM881 827q0 33 -12.5 58.5t-30.5 42t-48 28t-55 16.5t-61.5 8t-58 2.5t-54 -1t-39.5 -0.5v-307q5 0 34.5 -0.5t46.5 0t50 2t55 5.5t51.5 11t48.5 18.5t37 27t27 38.5t9 51z" /> +<glyph unicode="" d="M1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472zM896 992q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544z" /> +<glyph unicode="" d="M1468 1060q14 -14 28 -36h-472v472q22 -14 36 -28zM992 896h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28zM1152 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704 q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23 v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162 l230 -662h70z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150 v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -10v-3l14 3q9 1 30 1h248 v119h121z" /> +<glyph unicode="" horiz-adv-x="1792" d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832 q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1216 1504v-192q0 -14 -9 -23t-23 -9h-256 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192 q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1792 1504v-192q0 -14 -9 -23t-23 -9h-832 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832q14 0 23 -9t9 -23z" /> +<glyph unicode="" d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23 zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5 t82 -252.5zM1456 882v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165z" /> +<glyph unicode="" d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9 t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13 q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 172.5q0 105 72 178t181 73q123 0 205 -94.5t82 -252.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76 q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24 2 76 59t101 121q68 87 101 120q18 18 31 48t17.5 48.5 t13.5 60.5q7 39 12.5 61t19.5 52t34 50q19 19 45 19q46 0 82.5 -10.5t60 -26t40 -40.5t24 -45t12 -50t5 -45t0.5 -39q0 -38 -9.5 -76t-19 -60t-27.5 -56q-3 -6 -10 -18t-11 -22t-8 -24h277q78 0 135 -57t57 -135z" /> +<glyph unicode="" horiz-adv-x="1664" d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135 t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 -13.5 60.5t-17.5 48.5t-31 48q-33 33 -101 120q-49 64 -101 121 t-76 59q-25 2 -43 20.5t-18 43.5v641q0 26 19 44.5t45 19.5q35 1 158 44q77 26 120.5 39.5t121.5 29t144 15.5h17h76h36q133 -2 197 -78q58 -69 49 -181q39 -37 54 -94q17 -61 0 -117q46 -61 43 -137q0 -32 -15 -76z" /> +<glyph unicode="" d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 16 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15 q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86v129q0 59 20 86q29 38 80 38t78 -38 q21 -28 21 -86v-76h-133v-65q0 -51 34 -51q24 0 30 26q0 1 0.5 7t0.5 16.5v21.5h68zM785 1079v-156q0 -51 -32 -51t-32 51v156q0 52 32 52t32 -52zM1318 366q0 177 -19 260q-10 44 -43 73.5t-76 34.5q-136 15 -412 15q-275 0 -411 -15q-44 -5 -76.5 -34.5t-42.5 -73.5 q-20 -87 -20 -260q0 -176 20 -260q10 -43 42.5 -73t75.5 -35q137 -15 412 -15t412 15q43 5 75.5 35t42.5 73q20 84 20 260zM563 1017l90 296h-75l-51 -195l-53 195h-78l24 -69t23 -69q35 -103 46 -158v-201h74v201zM852 936v130q0 58 -21 87q-29 38 -78 38q-51 0 -78 -38 q-21 -29 -21 -87v-130q0 -58 21 -87q27 -38 78 -38q49 0 78 38q21 27 21 87zM1033 816h67v370h-67v-283q-22 -31 -42 -31q-15 0 -16 16q-1 2 -1 26v272h-67v-293q0 -37 6 -55q11 -27 43 -27q36 0 77 45v-40zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73 q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39 51 -106 51q-68 0 -107 -51 q-28 -37 -28 -116v-173q0 -79 29 -116q39 -51 108 -51q72 0 108 53q18 27 21 54q2 9 2 58zM790 1011v210q0 69 -43 69t-43 -69v-210q0 -70 43 -70t43 70zM1509 260q0 -234 -26 -350q-14 -59 -58 -99t-102 -46q-184 -21 -555 -21t-555 21q-58 6 -102.5 46t-57.5 99 q-26 112 -26 350q0 234 26 350q14 59 58 99t103 47q183 20 554 20t555 -20q58 -7 102.5 -47t57.5 -99q26 -112 26 -350zM511 1536h102l-121 -399v-271h-100v271q-14 74 -61 212q-37 103 -65 187h106l71 -263zM881 1203v-175q0 -81 -28 -118q-37 -51 -106 -51q-67 0 -105 51 q-28 38 -28 118v175q0 80 28 117q38 51 105 51q69 0 106 -51q28 -37 28 -117zM1216 1365v-499h-91v55q-53 -62 -103 -62q-46 0 -59 37q-8 24 -8 75v394h91v-367q0 -33 1 -35q3 -22 21 -22q27 0 57 43v381h91z" /> +<glyph unicode="" horiz-adv-x="1408" d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942 q25 45 64 45h241q22 0 31 -15z" /> +<glyph unicode="" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" /> +<glyph unicode="" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" /> +<glyph unicode="" horiz-adv-x="1408" d="M928 135v-151l-707 -1v151zM1169 481v-701l-1 -35v-1h-1132l-35 1h-1v736h121v-618h928v618h120zM241 393l704 -65l-13 -150l-705 65zM309 709l683 -183l-39 -146l-683 183zM472 1058l609 -360l-77 -130l-609 360zM832 1389l398 -585l-124 -85l-399 584zM1285 1536 l121 -697l-149 -26l-121 697z" /> +<glyph unicode="" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" /> +<glyph unicode="" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" /> +<glyph unicode="" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q-86 -48 -189.5 -71.5t-202 -22t-201.5 18.5q-46 8 -81.5 18 t-76.5 27t-73 43.5t-52 61.5q-25 96 -57 292l6 16l18 9q223 -148 506.5 -148t507.5 148q21 -6 24 -23t-5 -45t-8 -37zM1403 1166q-26 -167 -111 -655q-5 -30 -27 -56t-43.5 -40t-54.5 -31q-252 -126 -610 -88q-248 27 -394 139q-15 12 -25.5 26.5t-17 35t-9 34t-6 39.5 t-5.5 35q-9 50 -26.5 150t-28 161.5t-23.5 147.5t-22 158q3 26 17.5 48.5t31.5 37.5t45 30t46 22.5t48 18.5q125 46 313 64q379 37 676 -50q155 -46 215 -122q16 -20 16.5 -51t-5.5 -54z" /> +<glyph unicode="" d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5 t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 428 53q34 19 49 51.5t22.5 85.5t12.5 71z M1272 1020q9 53 -8 75q-43 55 -155 88q-216 63 -487 36q-132 -12 -226 -46q-38 -15 -59.5 -25t-47 -34t-29.5 -54q8 -68 19 -138t29 -171t24 -137q1 -5 5 -31t7 -36t12 -27t22 -28q105 -80 284 -100q259 -28 440 63q24 13 39.5 23t31 29t19.5 40q48 267 80 473zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1024" d="M944 207l80 -237q-23 -35 -111 -66t-177 -32q-104 -2 -190.5 26t-142.5 74t-95 106t-55.5 120t-16.5 118v544h-168v215q72 26 129 69.5t91 90t58 102t34 99t15 88.5q1 5 4.5 8.5t7.5 3.5h244v-424h333v-252h-334v-518q0 -30 6.5 -56t22.5 -52.5t49.5 -41.5t81.5 -14 q78 2 134 29z" /> +<glyph unicode="" d="M1136 75l-62 183q-44 -22 -103 -22q-36 -1 -62 10.5t-38.5 31.5t-17.5 40.5t-5 43.5v398h257v194h-256v326h-188q-8 0 -9 -10q-5 -44 -17.5 -87t-39 -95t-77 -95t-118.5 -68v-165h130v-418q0 -57 21.5 -115t65 -111t121 -85.5t176.5 -30.5q69 1 136.5 25t85.5 50z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="768" d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" /> +<glyph unicode="" horiz-adv-x="768" d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q112 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65 q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11q0 -4 0.5 -10t0.5 -10z" /> +<glyph unicode="" horiz-adv-x="1664" d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" /> +<glyph unicode="" horiz-adv-x="1408" d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30 t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78 32t-32 78v666h918zM931 1255q107 -55 171 -153.5t64 -215.5 h-925q0 117 64 215.5t172 153.5l-71 131q-7 13 5 20q13 6 20 -6l72 -132q95 42 201 42t201 -42l72 132q7 12 20 6q12 -7 5 -20zM1408 767v-430q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73v430q0 43 30 72.5t72 29.5q43 0 73 -29.5t30 -72.5z" /> +<glyph unicode="" d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-7 -10 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69t-19.5 45.5t-15.5 24.5t-13 15t-7.5 7 q-14 62 -31 103t-29.5 56t-23.5 33t-15 40q-4 21 6 53.5t4.5 49.5t-44.5 25q-15 3 -44.5 18t-35.5 16q-8 1 -11 26t8 51t36 27q37 3 51 -30t4 -58q-11 -19 -2 -26.5t30 -0.5q13 4 13 36v37q-5 30 -13.5 50t-21 30.5t-23.5 15t-27 7.5q-107 -8 -89 -134q0 -15 -1 -15 q-9 9 -29.5 10.5t-33 -0.5t-15.5 5q1 57 -16 90t-45 34q-27 1 -41.5 -27.5t-16.5 -59.5q-1 -15 3.5 -37t13 -37.5t15.5 -13.5q10 3 16 14q4 9 -7 8q-7 0 -15.5 14.5t-9.5 33.5q-1 22 9 37t34 14q17 0 27 -21t9.5 -39t-1.5 -22q-22 -15 -31 -29q-8 -12 -27.5 -23.5 t-20.5 -12.5q-13 -14 -15.5 -27t7.5 -18q14 -8 25 -19.5t16 -19t18.5 -13t35.5 -6.5q47 -2 102 15q2 1 23 7t34.5 10.5t29.5 13t21 17.5q9 14 20 8q5 -3 6.5 -8.5t-3 -12t-16.5 -9.5q-20 -6 -56.5 -21.5t-45.5 -19.5q-44 -19 -70 -23q-25 -5 -79 2q-10 2 -9 -2t17 -19 q25 -23 67 -22q17 1 36 7t36 14t33.5 17.5t30 17t24.5 12t17.5 2.5t8.5 -11q0 -2 -1 -4.5t-4 -5t-6 -4.5t-8.5 -5t-9 -4.5t-10 -5t-9.5 -4.5q-28 -14 -67.5 -44t-66.5 -43t-49 -1q-21 11 -63 73q-22 31 -25 22q-1 -3 -1 -10q0 -25 -15 -56.5t-29.5 -55.5t-21 -58t11.5 -63 q-23 -6 -62.5 -90t-47.5 -141q-2 -18 -1.5 -69t-5.5 -59q-8 -24 -29 -3q-32 31 -36 94q-2 28 4 56q4 19 -1 18l-4 -5q-36 -65 10 -166q5 -12 25 -28t24 -20q20 -23 104 -90.5t93 -76.5q16 -15 17.5 -38t-14 -43t-45.5 -23q8 -15 29 -44.5t28 -54t7 -70.5q46 24 7 92 q-4 8 -10.5 16t-9.5 12t-2 6q3 5 13 9.5t20 -2.5q46 -52 166 -36q133 15 177 87q23 38 34 30q12 -6 10 -52q-1 -25 -23 -92q-9 -23 -6 -37.5t24 -15.5q3 19 14.5 77t13.5 90q2 21 -6.5 73.5t-7.5 97t23 70.5q15 18 51 18q1 37 34.5 53t72.5 10.5t60 -22.5zM626 1152 q3 17 -2.5 30t-11.5 15q-9 2 -9 -7q2 -5 5 -6q10 0 7 -15q-3 -20 8 -20q3 0 3 3zM1045 955q-2 8 -6.5 11.5t-13 5t-14.5 5.5q-5 3 -9.5 8t-7 8t-5.5 6.5t-4 4t-4 -1.5q-14 -16 7 -43.5t39 -31.5q9 -1 14.5 8t3.5 20zM867 1168q0 11 -5 19.5t-11 12.5t-9 3q-14 -1 -7 -7l4 -2 q14 -4 18 -31q0 -3 8 2zM921 1401q0 2 -2.5 5t-9 7t-9.5 6q-15 15 -24 15q-9 -1 -11.5 -7.5t-1 -13t-0.5 -12.5q-1 -4 -6 -10.5t-6 -9t3 -8.5q4 -3 8 0t11 9t15 9q1 1 9 1t15 2t9 7zM1486 60q20 -12 31 -24.5t12 -24t-2.5 -22.5t-15.5 -22t-23.5 -19.5t-30 -18.5 t-31.5 -16.5t-32 -15.5t-27 -13q-38 -19 -85.5 -56t-75.5 -64q-17 -16 -68 -19.5t-89 14.5q-18 9 -29.5 23.5t-16.5 25.5t-22 19.5t-47 9.5q-44 1 -130 1q-19 0 -57 -1.5t-58 -2.5q-44 -1 -79.5 -15t-53.5 -30t-43.5 -28.5t-53.5 -11.5q-29 1 -111 31t-146 43q-19 4 -51 9.5 t-50 9t-39.5 9.5t-33.5 14.5t-17 19.5q-10 23 7 66.5t18 54.5q1 16 -4 40t-10 42.5t-4.5 36.5t10.5 27q14 12 57 14t60 12q30 18 42 35t12 51q21 -73 -32 -106q-32 -20 -83 -15q-34 3 -43 -10q-13 -15 5 -57q2 -6 8 -18t8.5 -18t4.5 -17t1 -22q0 -15 -17 -49t-14 -48 q3 -17 37 -26q20 -6 84.5 -18.5t99.5 -20.5q24 -6 74 -22t82.5 -23t55.5 -4q43 6 64.5 28t23 48t-7.5 58.5t-19 52t-20 36.5q-121 190 -169 242q-68 74 -113 40q-11 -9 -15 15q-3 16 -2 38q1 29 10 52t24 47t22 42q8 21 26.5 72t29.5 78t30 61t39 54q110 143 124 195 q-12 112 -16 310q-2 90 24 151.5t106 104.5q39 21 104 21q53 1 106 -13.5t89 -41.5q57 -42 91.5 -121.5t29.5 -147.5q-5 -95 30 -214q34 -113 133 -218q55 -59 99.5 -163t59.5 -191q8 -49 5 -84.5t-12 -55.5t-20 -22q-10 -2 -23.5 -19t-27 -35.5t-40.5 -33.5t-61 -14 q-18 1 -31.5 5t-22.5 13.5t-13.5 15.5t-11.5 20.5t-9 19.5q-22 37 -41 30t-28 -49t7 -97q20 -70 1 -195q-10 -65 18 -100.5t73 -33t85 35.5q59 49 89.5 66.5t103.5 42.5q53 18 77 36.5t18.5 34.5t-25 28.5t-51.5 23.5q-33 11 -49.5 48t-15 72.5t15.5 47.5q1 -31 8 -56.5 t14.5 -40.5t20.5 -28.5t21 -19t21.5 -13t16.5 -9.5z" /> +<glyph unicode="" d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81 t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q-185 164 -433 164q-76 0 -155 -19 q131 -170 246 -382q69 26 130 60.5t96.5 61.5t65.5 57t37.5 40.5zM1424 647q-3 232 -149 410l-1 -1q-9 -12 -19 -24.5t-43.5 -44.5t-71 -60.5t-100 -65t-131.5 -64.5q25 -53 44 -95q2 -6 6.5 -17.5t7.5 -16.5q36 5 74.5 7t73.5 2t69 -1.5t64 -4t56.5 -5.5t48 -6.5t36.5 -6 t25 -4.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5 t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 -92 122 -157.5t291 -65.5 q73 0 140 18.5t122.5 53.5t88.5 93.5t33 131.5zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5q-130 0 -234 80q-77 -16 -150 -16q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5q0 73 16 150q-80 104 -80 234q0 159 112.5 271.5t271.5 112.5q130 0 234 -80 q77 16 150 16q143 0 273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -73 -16 -150q80 -104 80 -234z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1000 1102l37 194q5 23 -9 40t-35 17h-712q-23 0 -38.5 -17t-15.5 -37v-1101q0 -7 6 -1l291 352q23 26 38 33.5t48 7.5h239q22 0 37 14.5t18 29.5q24 130 37 191q4 21 -11.5 40t-36.5 19h-294q-29 0 -48 19t-19 48v42q0 29 19 47.5t48 18.5h346q18 0 35 13.5t20 29.5z M1227 1324q-15 -73 -53.5 -266.5t-69.5 -350t-35 -173.5q-6 -22 -9 -32.5t-14 -32.5t-24.5 -33t-38.5 -21t-58 -10h-271q-13 0 -22 -10q-8 -9 -426 -494q-22 -25 -58.5 -28.5t-48.5 5.5q-55 22 -55 98v1410q0 55 38 102.5t120 47.5h888q95 0 127 -53t10 -159zM1227 1324 l-158 -790q4 17 35 173.5t69.5 350t53.5 266.5z" /> +<glyph unicode="" d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408 q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43 q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="" horiz-adv-x="1024" d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="" d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4 l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 29 4l292 -94l180 248q9 12 26 12t26 -12l180 -248l292 94 q14 6 29 -4q13 -10 13 -26v-306l292 -96q16 -5 20 -20q5 -16 -4 -29l-180 -248l180 -248q9 -12 4 -29z" /> +<glyph unicode="" d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61 t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536 q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207 q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 -19t19 -45t-19 -45l-173 -173v-294h224q26 0 45 -19 t19 -45zM1152 1152h-640q0 133 93.5 226.5t226.5 93.5t226.5 -93.5t93.5 -226.5z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-78 -100 -90 -131q-17 -41 14 -81q17 -21 81 -82h1l1 -1l1 -1l2 -2q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58 t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91t-106 151t-122.5 211t-130.5 272q-6 16 -6 27t3 16l4 6 q15 19 57 19l274 2q12 -2 23 -6.5t16 -8.5l5 -3q16 -11 24 -32q20 -50 46 -103.5t41 -81.5l16 -29q29 -60 56 -104t48.5 -68.5t41.5 -38.5t34 -14t27 5q2 1 5 5t12 22t13.5 47t9.5 81t0 125q-2 40 -9 73t-14 46l-6 12q-25 34 -85 43q-13 2 5 24q17 19 38 30q53 26 239 24 q82 -1 135 -13q20 -5 33.5 -13.5t20.5 -24t10.5 -32t3.5 -45.5t-1 -55t-2.5 -70.5t-1.5 -82.5q0 -11 -1 -42t-0.5 -48t3.5 -40.5t11.5 -39t22.5 -24.5q8 -2 17 -4t26 11t38 34.5t52 67t68 107.5q60 104 107 225q4 10 10 17.5t11 10.5l4 3l5 2.5t13 3t20 0.5l288 2 q39 5 64 -2.5t31 -16.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12 q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 369.5 141.5t132.5 264.5zM1563 422 q0 -68 -37 -139.5t-109 -137t-168.5 -117.5t-226 -83t-270.5 -31t-275 33.5t-240.5 93t-171.5 151t-65 199.5q0 115 69.5 245t197.5 258q169 169 341.5 236t246.5 -7q65 -64 20 -209q-4 -14 -1 -20t10 -7t14.5 0.5t13.5 3.5l6 2q139 59 246 59t153 -61q45 -63 0 -178 q-2 -13 -4.5 -20t4.5 -12.5t12 -7.5t17 -6q57 -18 103 -47t80 -81.5t34 -116.5zM1489 1046q42 -47 54.5 -108.5t-6.5 -117.5q-8 -23 -29.5 -34t-44.5 -4q-23 8 -34 29.5t-4 44.5q20 63 -24 111t-107 35q-24 -5 -45 8t-25 37q-5 24 8 44.5t37 25.5q60 13 119 -5.5t101 -65.5z M1670 1209q87 -96 112.5 -222.5t-13.5 -241.5q-9 -27 -34 -40t-52 -4t-40 34t-5 52q28 82 10 172t-80 158q-62 69 -148 95.5t-173 8.5q-28 -6 -52 9.5t-30 43.5t9.5 51.5t43.5 29.5q123 26 244 -11.5t208 -134.5z" /> +<glyph unicode="" d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495 q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5 t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70 28 133.5 36.5t112.5 -1t92 -30t73.5 -50t56 -61t42 -63t27.5 -56 t16 -39.5l4 -16q12 122 12 195q-8 6 -21.5 16t-49 44.5t-63.5 71.5t-54 93t-33 112.5t12 127t70 138.5q73 -25 127.5 -61.5t84.5 -76.5t48 -85t20.5 -89t-0.5 -85.5t-13 -76.5t-19 -62t-17 -42l-7 -15q1 -5 1 -50.5t-1 -71.5q3 7 10 18.5t30.5 43t50.5 58t71 55.5t91.5 44.5 t112 14.5t132.5 -24q-2 -78 -21.5 -141.5t-50 -104.5t-69.5 -71.5t-81.5 -45.5t-84.5 -24t-80 -9.5t-67.5 1t-46.5 4.5l-17 3q-23 -147 -73 -283q6 7 18 18.5t49.5 41t77.5 52.5t99.5 42t117.5 20t129 -23.5t137 -77.5z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z " /> +<glyph unicode="" d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5 t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128 q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 16 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455q40 0 57 -35l228 -455z" /> +<glyph unicode="" d="M1254 899q16 85 -21 132q-52 65 -187 45q-17 -3 -41 -12.5t-57.5 -30.5t-64.5 -48.5t-59.5 -70t-44.5 -91.5q80 7 113.5 -16t26.5 -99q-5 -52 -52 -143q-43 -78 -71 -99q-44 -32 -87 14q-23 24 -37.5 64.5t-19 73t-10 84t-8.5 71.5q-23 129 -34 164q-12 37 -35.5 69 t-50.5 40q-57 16 -127 -25q-54 -32 -136.5 -106t-122.5 -102v-7q16 -8 25.5 -26t21.5 -20q21 -3 54.5 8.5t58 10.5t41.5 -30q11 -18 18.5 -38.5t15 -48t12.5 -40.5q17 -46 53 -187q36 -146 57 -197q42 -99 103 -125q43 -12 85 -1.5t76 31.5q131 77 250 237 q104 139 172.5 292.5t82.5 226.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1152" d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160 q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" /> +<glyph unicode="" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832 q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="2176" d="M620 416q-110 -64 -268 -64h-128v64h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5t38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40 t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113zM1739 668q53 -36 53 -92t-53 -92l81 -30q68 48 68 122t-68 122zM625 400h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-288 -288q-26 -26 -70.5 -45t-89.5 -19h-96l-93 464h29 q157 0 273 64zM352 816h-29l93 464h96q46 0 90 -19t70 -45l288 -288q4 -4 11 -10.5t30.5 -23t48.5 -29t61.5 -23t72.5 -10.5l456 -80h-1015q-116 64 -273 64z" /> +<glyph unicode="" horiz-adv-x="1664" d="M1519 760q62 0 103.5 -40.5t41.5 -101.5q0 -97 -93 -130l-172 -59l56 -167q7 -21 7 -47q0 -59 -42 -102t-101 -43q-47 0 -85.5 27t-53.5 72l-55 165l-310 -106l55 -164q8 -24 8 -47q0 -59 -42 -102t-102 -43q-47 0 -85 27t-53 72l-55 163l-153 -53q-29 -9 -50 -9 q-61 0 -101.5 40t-40.5 101q0 47 27.5 85t71.5 53l156 53l-105 313l-156 -54q-26 -8 -48 -8q-60 0 -101 40.5t-41 100.5q0 47 27.5 85t71.5 53l157 53l-53 159q-8 24 -8 47q0 60 42 102.5t102 42.5q47 0 85 -27t53 -72l54 -160l310 105l-54 160q-8 24 -8 47q0 59 42.5 102 t101.5 43q47 0 85.5 -27.5t53.5 -71.5l53 -161l162 55q21 6 43 6q60 0 102.5 -39.5t42.5 -98.5q0 -45 -30 -81.5t-74 -51.5l-157 -54l105 -316l164 56q24 8 46 8zM725 498l310 105l-105 315l-310 -107z" /> +<glyph unicode="" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM1280 352v436q-31 -35 -64 -55q-34 -22 -132.5 -85t-151.5 -99q-98 -69 -164 -69v0v0q-66 0 -164 69 q-46 32 -141.5 92.5t-142.5 92.5q-12 8 -33 27t-31 27v-436q0 -40 28 -68t68 -28h832q40 0 68 28t28 68zM1280 925q0 41 -27.5 70t-68.5 29h-832q-40 0 -68 -28t-28 -68q0 -37 30.5 -76.5t67.5 -64.5q47 -32 137.5 -89t129.5 -83q3 -2 17 -11.5t21 -14t21 -13t23.5 -13 t21.5 -9.5t22.5 -7.5t20.5 -2.5t20.5 2.5t22.5 7.5t21.5 9.5t23.5 13t21 13t21 14t17 11.5l267 174q35 23 66.5 62.5t31.5 73.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M127 640q0 163 67 313l367 -1005q-196 95 -315 281t-119 411zM1415 679q0 -19 -2.5 -38.5t-10 -49.5t-11.5 -44t-17.5 -59t-17.5 -58l-76 -256l-278 826q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-75 1 -202 10q-12 1 -20.5 -5t-11.5 -15t-1.5 -18.5t9 -16.5 t19.5 -8l80 -8l120 -328l-168 -504l-280 832q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-7 0 -23 0.5t-26 0.5q105 160 274.5 253.5t367.5 93.5q147 0 280.5 -53t238.5 -149h-10q-55 0 -92 -40.5t-37 -95.5q0 -12 2 -24t4 -21.5t8 -23t9 -21t12 -22.5t12.5 -21 t14.5 -24t14 -23q63 -107 63 -212zM909 573l237 -647q1 -6 5 -11q-126 -44 -255 -44q-112 0 -217 32zM1570 1009q95 -174 95 -369q0 -209 -104 -385.5t-279 -278.5l235 678q59 169 59 276q0 42 -6 79zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286 t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 -215q173 0 331.5 68t273 182.5t182.5 273t68 331.5t-68 331.5t-182.5 273t-273 182.5t-331.5 68t-331.5 -68t-273 -182.5t-182.5 -273t-68 -331.5t68 -331.5t182.5 -273 t273 -182.5t331.5 -68z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1086 1536v-1536l-272 -128q-228 20 -414 102t-293 208.5t-107 272.5q0 140 100.5 263.5t275 205.5t391.5 108v-172q-217 -38 -356.5 -150t-139.5 -255q0 -152 154.5 -267t388.5 -145v1360zM1755 954l37 -390l-525 114l147 83q-119 70 -280 99v172q277 -33 481 -157z" /> +<glyph unicode="" horiz-adv-x="2048" d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64 q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" /> +<glyph unicode="" horiz-adv-x="2304" d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433 q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" /> +<glyph unicode="" d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q43 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0 q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" /> +<glyph unicode="" horiz-adv-x="1280" d="M981 197q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -49 2q-53 0 -104.5 -7t-107 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -56 23.5 -102t61 -75.5t87 -50t100 -29t101.5 -8.5q58 0 111.5 13t99 39t73 73t27.5 109zM864 1055 q0 59 -17 125.5t-48 129t-84 103.5t-117 41q-42 0 -82.5 -19.5t-66.5 -52.5q-46 -59 -46 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26q37 0 77.5 16.5t65.5 43.5q53 56 53 159zM752 1536h417l-137 -88h-132q75 -63 113 -133t38 -160q0 -72 -24.5 -129.5 t-59.5 -93t-69.5 -65t-59 -61.5t-24.5 -66q0 -36 32 -70.5t77 -68t90.5 -73.5t77.5 -104t32 -142q0 -91 -49 -173q-71 -122 -209.5 -179.5t-298.5 -57.5q-132 0 -246.5 41.5t-172.5 137.5q-36 59 -36 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 41 -47.5 73.5 t-15.5 73.5q0 40 21 85q-46 -4 -68 -4q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q76 66 182 98t218 32z" /> +<glyph unicode="" horiz-adv-x="1984" d="M831 572q0 -56 -40.5 -96t-96.5 -40q-57 0 -98 40t-41 96q0 57 41.5 98t97.5 41t96.5 -41t40.5 -98zM1292 711q56 0 96.5 -41t40.5 -98q0 -56 -40.5 -96t-96.5 -40q-57 0 -98 40t-41 96q0 57 41.5 98t97.5 41zM1984 722q0 -62 -31 -114t-83 -82q5 -33 5 -61 q0 -121 -68.5 -230.5t-197.5 -193.5q-125 -82 -285.5 -125.5t-335.5 -43.5q-176 0 -336.5 43.5t-284.5 125.5q-129 84 -197.5 193t-68.5 231q0 29 5 66q-48 31 -77 81.5t-29 109.5q0 94 66 160t160 66q83 0 148 -55q248 158 592 164l134 423q4 14 17.5 21.5t28.5 4.5 l347 -82q22 50 68.5 81t102.5 31q77 0 131.5 -54.5t54.5 -131.5t-54.5 -132t-131.5 -55q-76 0 -130.5 54t-55.5 131l-315 74l-116 -366q327 -14 560 -166q64 58 151 58q94 0 160 -66t66 -160zM1664 1459q-45 0 -77 -32t-32 -77t32 -77t77 -32t77 32t32 77t-32 77t-77 32z M77 722q0 -67 51 -111q49 131 180 235q-36 25 -82 25q-62 0 -105.5 -43.5t-43.5 -105.5zM1567 105q112 73 171.5 166t59.5 194t-59.5 193.5t-171.5 165.5q-116 75 -265.5 115.5t-313.5 40.5t-313.5 -40.5t-265.5 -115.5q-112 -73 -171.5 -165.5t-59.5 -193.5t59.5 -194 t171.5 -166q116 -75 265.5 -115.5t313.5 -40.5t313.5 40.5t265.5 115.5zM1850 605q57 46 57 117q0 62 -43.5 105.5t-105.5 43.5q-49 0 -86 -28q131 -105 178 -238zM1258 237q11 11 27 11t27 -11t11 -27.5t-11 -27.5q-99 -99 -319 -99h-2q-220 0 -319 99q-11 11 -11 27.5 t11 27.5t27 11t27 -11q77 -77 265 -77h2q188 0 265 77z" /> +<glyph unicode="" d="M950 393q7 7 17.5 7t17.5 -7t7 -18t-7 -18q-65 -64 -208 -64h-1h-1q-143 0 -207 64q-8 7 -8 18t8 18q7 7 17.5 7t17.5 -7q49 -51 172 -51h1h1q122 0 173 51zM671 613q0 -37 -26 -64t-63 -27t-63 27t-26 64t26 63t63 26t63 -26t26 -63zM1214 1049q-29 0 -50 21t-21 50 q0 30 21 51t50 21q30 0 51 -21t21 -51q0 -29 -21 -50t-51 -21zM1216 1408q132 0 226 -94t94 -227v-894q0 -133 -94 -227t-226 -94h-896q-132 0 -226 94t-94 227v894q0 133 94 227t226 94h896zM1321 596q35 14 57 45.5t22 70.5q0 51 -36 87.5t-87 36.5q-60 0 -98 -48 q-151 107 -375 115l83 265l206 -49q1 -50 36.5 -85t84.5 -35q50 0 86 35.5t36 85.5t-36 86t-86 36q-36 0 -66 -20.5t-45 -53.5l-227 54q-9 2 -17.5 -2.5t-11.5 -14.5l-95 -302q-224 -4 -381 -113q-36 43 -93 43q-51 0 -87 -36.5t-36 -87.5q0 -37 19.5 -67.5t52.5 -45.5 q-7 -25 -7 -54q0 -98 74 -181.5t201.5 -132t278.5 -48.5q150 0 277.5 48.5t201.5 132t74 181.5q0 27 -6 54zM971 702q37 0 63 -26t26 -63t-26 -64t-63 -27t-63 27t-26 64t26 63t63 26z" /> +<glyph unicode="" d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150 v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103 t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1920" d="M1062 824v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58zM1592 602h328 v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275z" /> +<glyph unicode="" d="M1472 160v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480h704v-704h480q93 0 158.5 65.5t65.5 158.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="2048" d="M328 1254h204v-983h-532v697h328v286zM328 435v369h-123v-369h123zM614 968v-697h205v697h-205zM614 1254v-204h205v204h-205zM901 968h533v-942h-533v163h328v82h-328v697zM1229 435v369h-123v-369h123zM1516 968h532v-942h-532v163h327v82h-327v697zM1843 435v369h-123 v-369h123z" /> +<glyph unicode="" d="M1046 516q0 -64 -38 -109t-91 -45q-43 0 -70 15v277q28 17 70 17q53 0 91 -45.5t38 -109.5zM703 944q0 -64 -38 -109.5t-91 -45.5q-43 0 -70 15v277q28 17 70 17q53 0 91 -45t38 -109zM1265 513q0 134 -88 229t-213 95q-20 0 -39 -3q-23 -78 -78 -136q-87 -95 -211 -101 v-636l211 41v206q51 -19 117 -19q125 0 213 95t88 229zM922 940q0 134 -88.5 229t-213.5 95q-74 0 -141 -36h-186v-840l211 41v206q55 -19 116 -19q125 0 213.5 95t88.5 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="2038" d="M1222 607q75 3 143.5 -20.5t118 -58.5t101 -94.5t84 -108t75.5 -120.5q33 -56 78.5 -109t75.5 -80.5t99 -88.5q-48 -30 -108.5 -57.5t-138.5 -59t-114 -47.5q-44 37 -74 115t-43.5 164.5t-33 180.5t-42.5 168.5t-72.5 123t-122.5 48.5l-10 -2l-6 -4q4 -5 13 -14 q6 -5 28 -23.5t25.5 -22t19 -18t18 -20.5t11.5 -21t10.5 -27.5t4.5 -31t4 -40.5l1 -33q1 -26 -2.5 -57.5t-7.5 -52t-12.5 -58.5t-11.5 -53q-35 1 -101 -9.5t-98 -10.5q-39 0 -72 10q-2 16 -2 47q0 74 3 96q2 13 31.5 41.5t57 59t26.5 51.5q-24 2 -43 -24 q-36 -53 -111.5 -99.5t-136.5 -46.5q-25 0 -75.5 63t-106.5 139.5t-84 96.5q-6 4 -27 30q-482 -112 -513 -112q-16 0 -28 11t-12 27q0 15 8.5 26.5t22.5 14.5l486 106q-8 14 -8 25t5.5 17.5t16 11.5t20 7t23 4.5t18.5 4.5q4 1 15.5 7.5t17.5 6.5q15 0 28 -16t20 -33 q163 37 172 37q17 0 29.5 -11t12.5 -28q0 -15 -8.5 -26t-23.5 -14l-182 -40l-1 -16q-1 -26 81.5 -117.5t104.5 -91.5q47 0 119 80t72 129q0 36 -23.5 53t-51 18.5t-51 11.5t-23.5 34q0 16 10 34l-68 19q43 44 43 117q0 26 -5 58q82 16 144 16q44 0 71.5 -1.5t48.5 -8.5 t31 -13.5t20.5 -24.5t15.5 -33.5t17 -47.5t24 -60l50 25q-3 -40 -23 -60t-42.5 -21t-40 -6.5t-16.5 -20.5zM1282 842q-5 5 -13.5 15.5t-12 14.5t-10.5 11.5t-10 10.5l-8 8t-8.5 7.5t-8 5t-8.5 4.5q-7 3 -14.5 5t-20.5 2.5t-22 0.5h-32.5h-37.5q-126 0 -217 -43 q16 30 36 46.5t54 29.5t65.5 36t46 36.5t50 55t43.5 50.5q12 -9 28 -31.5t32 -36.5t38 -13l12 1v-76l22 -1q247 95 371 190q28 21 50 39t42.5 37.5t33 31t29.5 34t24 31t24.5 37t23 38t27 47.5t29.5 53l7 9q-2 -53 -43 -139q-79 -165 -205 -264t-306 -142q-14 -3 -42 -7.5 t-50 -9.5t-39 -14q3 -19 24.5 -46t21.5 -34q0 -11 -26 -30zM1061 -79q39 26 131.5 47.5t146.5 21.5q9 0 22.5 -15.5t28 -42.5t26 -50t24 -51t14.5 -33q-121 -45 -244 -45q-61 0 -125 11zM822 568l48 12l109 -177l-73 -48zM1323 51q3 -15 3 -16q0 -7 -17.5 -14.5t-46 -13 t-54 -9.5t-53.5 -7.5t-32 -4.5l-7 43q21 2 60.5 8.5t72 10t60.5 3.5h14zM866 679l-96 -20l-6 17q10 1 32.5 7t34.5 6q19 0 35 -10zM1061 45h31l10 -83l-41 -12v95zM1950 1535v1v-1zM1950 1535l-1 -5l-2 -2l1 3zM1950 1535l1 1z" /> +<glyph unicode="" d="M1167 -50q-5 19 -24 5q-30 -22 -87 -39t-131 -17q-129 0 -193 49q-5 4 -13 4q-11 0 -26 -12q-7 -6 -7.5 -16t7.5 -20q34 -32 87.5 -46t102.5 -12.5t99 4.5q41 4 84.5 20.5t65 30t28.5 20.5q12 12 7 29zM1128 65q-19 47 -39 61q-23 15 -76 15q-47 0 -71 -10 q-29 -12 -78 -56q-26 -24 -12 -44q9 -8 17.5 -4.5t31.5 23.5q3 2 10.5 8.5t10.5 8.5t10 7t11.5 7t12.5 5t15 4.5t16.5 2.5t20.5 1q27 0 44.5 -7.5t23 -14.5t13.5 -22q10 -17 12.5 -20t12.5 1q23 12 14 34zM1483 346q0 22 -5 44.5t-16.5 45t-34 36.5t-52.5 14 q-33 0 -97 -41.5t-129 -83.5t-101 -42q-27 -1 -63.5 19t-76 49t-83.5 58t-100 49t-111 19q-115 -1 -197 -78.5t-84 -178.5q-2 -112 74 -164q29 -20 62.5 -28.5t103.5 -8.5q57 0 132 32.5t134 71t120 70.5t93 31q26 -1 65 -31.5t71.5 -67t68 -67.5t55.5 -32q35 -3 58.5 14 t55.5 63q28 41 42.5 101t14.5 106zM1536 506q0 -164 -62 -304.5t-166 -236t-242.5 -149.5t-290.5 -54t-293 57.5t-247.5 157t-170.5 241.5t-64 302q0 89 19.5 172.5t49 145.5t70.5 118.5t78.5 94t78.5 69.5t64.5 46.5t42.5 24.5q14 8 51 26.5t54.5 28.5t48 30t60.5 44 q36 28 58 72.5t30 125.5q129 -155 186 -193q44 -29 130 -68t129 -66q21 -13 39 -25t60.5 -46.5t76 -70.5t75 -95t69 -122t47 -148.5t19.5 -177.5z" /> +<glyph unicode="" d="M1070 463l-160 -160l-151 -152l-30 -30q-65 -64 -151.5 -87t-171.5 -2q-16 -70 -72 -115t-129 -45q-85 0 -145 60.5t-60 145.5q0 72 44.5 128t113.5 72q-22 86 1 173t88 152l12 12l151 -152l-11 -11q-37 -37 -37 -89t37 -90q37 -37 89 -37t89 37l30 30l151 152l161 160z M729 1145l12 -12l-152 -152l-12 12q-37 37 -89 37t-89 -37t-37 -89.5t37 -89.5l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30q-68 67 -90 159.5t5 179.5q-70 15 -115 71t-45 129q0 85 60 145.5t145 60.5q76 0 133.5 -49t69.5 -123q84 20 169.5 -3.5 t149.5 -87.5zM1536 78q0 -85 -60 -145.5t-145 -60.5q-74 0 -131 47t-71 118q-86 -28 -179.5 -6t-161.5 90l-11 12l151 152l12 -12q37 -37 89 -37t89 37t37 89t-37 89l-30 30l-152 152l-160 160l152 152l160 -160l152 -152l29 -30q64 -64 87.5 -150.5t2.5 -171.5 q76 -11 126.5 -68.5t50.5 -134.5zM1534 1202q0 -77 -51 -135t-127 -69q26 -85 3 -176.5t-90 -158.5l-12 -12l-151 152l12 12q37 37 37 89t-37 89t-89 37t-89 -37l-30 -30l-152 -152l-160 -160l-152 152l161 160l152 152l29 30q67 67 159 89.5t178 -3.5q11 75 68.5 126 t135.5 51q85 0 145 -60.5t60 -145.5z" /> +<glyph unicode="" d="M654 458q-1 -3 -12.5 0.5t-31.5 11.5l-20 9q-44 20 -87 49q-7 5 -41 31.5t-38 28.5q-67 -103 -134 -181q-81 -95 -105 -110q-4 -2 -19.5 -4t-18.5 0q6 4 82 92q21 24 85.5 115t78.5 118q17 30 51 98.5t36 77.5q-8 1 -110 -33q-8 -2 -27.5 -7.5t-34.5 -9.5t-17 -5 q-2 -2 -2 -10.5t-1 -9.5q-5 -10 -31 -15q-23 -7 -47 0q-18 4 -28 21q-4 6 -5 23q6 2 24.5 5t29.5 6q58 16 105 32q100 35 102 35q10 2 43 19.5t44 21.5q9 3 21.5 8t14.5 5.5t6 -0.5q2 -12 -1 -33q0 -2 -12.5 -27t-26.5 -53.5t-17 -33.5q-25 -50 -77 -131l64 -28 q12 -6 74.5 -32t67.5 -28q4 -1 10.5 -25.5t4.5 -30.5zM449 944q3 -15 -4 -28q-12 -23 -50 -38q-30 -12 -60 -12q-26 3 -49 26q-14 15 -18 41l1 3q3 -3 19.5 -5t26.5 0t58 16q36 12 55 14q17 0 21 -17zM1147 815l63 -227l-139 42zM39 15l694 232v1032l-694 -233v-1031z M1280 332l102 -31l-181 657l-100 31l-216 -536l102 -31l45 110l211 -65zM777 1294l573 -184v380zM1088 -29l158 -13l-54 -160l-40 66q-130 -83 -276 -108q-58 -12 -91 -12h-84q-79 0 -199.5 39t-183.5 85q-8 7 -8 16q0 8 5 13.5t13 5.5q4 0 18 -7.5t30.5 -16.5t20.5 -11 q73 -37 159.5 -61.5t157.5 -24.5q95 0 167 14.5t157 50.5q15 7 30.5 15.5t34 19t28.5 16.5zM1536 1050v-1079l-774 246q-14 -6 -375 -127.5t-368 -121.5q-13 0 -18 13q0 1 -1 3v1078q3 9 4 10q5 6 20 11q106 35 149 50v384l558 -198q2 0 160.5 55t316 108.5t161.5 53.5 q20 0 20 -21v-418z" /> +<glyph unicode="" horiz-adv-x="1792" d="M288 1152q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-128q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h128zM1664 989q58 -34 93 -93t35 -128v-768q0 -106 -75 -181t-181 -75h-864q-66 0 -113 47t-47 113v1536q0 40 28 68t68 28h672q40 0 88 -20t76 -48 l152 -152q28 -28 48 -76t20 -88v-163zM928 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 512v128q0 14 -9 23 t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1184 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128 q14 0 23 9t9 23zM1184 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 256v128q0 14 -9 23t-23 9h-128 q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1440 512v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM1536 896v256h-160q-40 0 -68 28t-28 68v160h-640v-512h896z" /> +<glyph unicode="" d="M1344 1536q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280zM512 1248v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 992v-64q0 -14 9 -23t23 -9h64q14 0 23 9 t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 736v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 480v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 160v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64 q14 0 23 9t9 23zM384 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM384 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 -96v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9 t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM896 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 928v64 q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM896 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 160v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64 q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 928v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9 t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1152 1184v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1188 988l-292 -292v-824q0 -46 -33 -79t-79 -33t-79 33t-33 79v384h-64v-384q0 -46 -33 -79t-79 -33t-79 33t-33 79v824l-292 292q-28 28 -28 68t28 68t68 28t68 -28l228 -228h368l228 228q28 28 68 28t68 -28t28 -68t-28 -68zM864 1152q0 -93 -65.5 -158.5 t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="" horiz-adv-x="1664" d="M780 1064q0 -60 -19 -113.5t-63 -92.5t-105 -39q-76 0 -138 57.5t-92 135.5t-30 151q0 60 19 113.5t63 92.5t105 39q77 0 138.5 -57.5t91.5 -135t30 -151.5zM438 581q0 -80 -42 -139t-119 -59q-76 0 -141.5 55.5t-100.5 133.5t-35 152q0 80 42 139.5t119 59.5 q76 0 141.5 -55.5t100.5 -134t35 -152.5zM832 608q118 0 255 -97.5t229 -237t92 -254.5q0 -46 -17 -76.5t-48.5 -45t-64.5 -20t-76 -5.5q-68 0 -187.5 45t-182.5 45q-66 0 -192.5 -44.5t-200.5 -44.5q-183 0 -183 146q0 86 56 191.5t139.5 192.5t187.5 146t193 59zM1071 819 q-61 0 -105 39t-63 92.5t-19 113.5q0 74 30 151.5t91.5 135t138.5 57.5q61 0 105 -39t63 -92.5t19 -113.5q0 -73 -30 -151t-92 -135.5t-138 -57.5zM1503 923q77 0 119 -59.5t42 -139.5q0 -74 -35 -152t-100.5 -133.5t-141.5 -55.5q-77 0 -119 59t-42 139q0 74 35 152.5 t100.5 134t141.5 55.5z" /> +<glyph unicode="" horiz-adv-x="768" d="M704 1008q0 -145 -57 -243.5t-152 -135.5l45 -821q2 -26 -16 -45t-44 -19h-192q-26 0 -44 19t-16 45l45 821q-95 37 -152 135.5t-57 243.5q0 128 42.5 249.5t117.5 200t160 78.5t160 -78.5t117.5 -200t42.5 -249.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M896 -93l640 349v636l-640 -233v-752zM832 772l698 254l-698 254l-698 -254zM1664 1024v-768q0 -35 -18 -65t-49 -47l-704 -384q-28 -16 -61 -16t-61 16l-704 384q-31 17 -49 47t-18 65v768q0 40 23 73t61 47l704 256q22 8 44 8t44 -8l704 -256q38 -14 61 -47t23 -73z " /> +<glyph unicode="" horiz-adv-x="2304" d="M640 -96l384 192v314l-384 -164v-342zM576 358l404 173l-404 173l-404 -173zM1664 -96l384 192v314l-384 -164v-342zM1600 358l404 173l-404 173l-404 -173zM1152 651l384 165v266l-384 -164v-267zM1088 1030l441 189l-441 189l-441 -189zM2176 512v-416q0 -36 -19 -67 t-52 -47l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-5 2 -7 4q-2 -2 -7 -4l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-33 16 -52 47t-19 67v416q0 38 21.5 70t56.5 48l434 186v400q0 38 21.5 70t56.5 48l448 192q23 10 50 10t50 -10l448 -192q35 -16 56.5 -48t21.5 -70 v-400l434 -186q36 -16 57 -48t21 -70z" /> +<glyph unicode="" horiz-adv-x="2048" d="M1848 1197h-511v-124h511v124zM1596 771q-90 0 -146 -52.5t-62 -142.5h408q-18 195 -200 195zM1612 186q63 0 122 32t76 87h221q-100 -307 -427 -307q-214 0 -340.5 132t-126.5 347q0 208 130.5 345.5t336.5 137.5q138 0 240.5 -68t153 -179t50.5 -248q0 -17 -2 -47h-658 q0 -111 57.5 -171.5t166.5 -60.5zM277 236h296q205 0 205 167q0 180 -199 180h-302v-347zM277 773h281q78 0 123.5 36.5t45.5 113.5q0 144 -190 144h-260v-294zM0 1282h594q87 0 155 -14t126.5 -47.5t90 -96.5t31.5 -154q0 -181 -172 -263q114 -32 172 -115t58 -204 q0 -75 -24.5 -136.5t-66 -103.5t-98.5 -71t-121 -42t-134 -13h-611v1260z" /> +<glyph unicode="" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM499 1041h-371v-787h382q117 0 197 57.5t80 170.5q0 158 -143 200q107 52 107 164q0 57 -19.5 96.5 t-56.5 60.5t-79 29.5t-97 8.5zM477 723h-176v184h163q119 0 119 -90q0 -94 -106 -94zM486 388h-185v217h189q124 0 124 -113q0 -104 -128 -104zM1136 356q-68 0 -104 38t-36 107h411q1 10 1 30q0 132 -74.5 220.5t-203.5 88.5q-128 0 -210 -86t-82 -216q0 -135 79 -217 t213 -82q205 0 267 191h-138q-11 -34 -47.5 -54t-75.5 -20zM1126 722q113 0 124 -122h-254q4 56 39 89t91 33zM964 988h319v-77h-319v77z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1582 954q0 -101 -71.5 -172.5t-172.5 -71.5t-172.5 71.5t-71.5 172.5t71.5 172.5t172.5 71.5t172.5 -71.5t71.5 -172.5zM812 212q0 104 -73 177t-177 73q-27 0 -54 -6l104 -42q77 -31 109.5 -106.5t1.5 -151.5q-31 -77 -107 -109t-152 -1q-21 8 -62 24.5t-61 24.5 q32 -60 91 -96.5t130 -36.5q104 0 177 73t73 177zM1642 953q0 126 -89.5 215.5t-215.5 89.5q-127 0 -216.5 -89.5t-89.5 -215.5q0 -127 89.5 -216t216.5 -89q126 0 215.5 89t89.5 216zM1792 953q0 -189 -133.5 -322t-321.5 -133l-437 -319q-12 -129 -109 -218t-229 -89 q-121 0 -214 76t-118 192l-230 92v429l389 -157q79 48 173 48q13 0 35 -2l284 407q2 187 135.5 319t320.5 132q188 0 321.5 -133.5t133.5 -321.5z" /> +<glyph unicode="" d="M1242 889q0 80 -57 136.5t-137 56.5t-136.5 -57t-56.5 -136q0 -80 56.5 -136.5t136.5 -56.5t137 56.5t57 136.5zM632 301q0 -83 -58 -140.5t-140 -57.5q-56 0 -103 29t-72 77q52 -20 98 -40q60 -24 120 1.5t85 86.5q24 60 -1.5 120t-86.5 84l-82 33q22 5 42 5 q82 0 140 -57.5t58 -140.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v153l172 -69q20 -92 93.5 -152t168.5 -60q104 0 181 70t87 173l345 252q150 0 255.5 105.5t105.5 254.5q0 150 -105.5 255.5t-255.5 105.5 q-148 0 -253 -104.5t-107 -252.5l-225 -322q-9 1 -28 1q-75 0 -137 -37l-297 119v468q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5zM1289 887q0 -100 -71 -170.5t-171 -70.5t-170.5 70.5t-70.5 170.5t70.5 171t170.5 71q101 0 171.5 -70.5t70.5 -171.5z " /> +<glyph unicode="" horiz-adv-x="1792" d="M836 367l-15 -368l-2 -22l-420 29q-36 3 -67 31.5t-47 65.5q-11 27 -14.5 55t4 65t12 55t21.5 64t19 53q78 -12 509 -28zM449 953l180 -379l-147 92q-63 -72 -111.5 -144.5t-72.5 -125t-39.5 -94.5t-18.5 -63l-4 -21l-190 357q-17 26 -18 56t6 47l8 18q35 63 114 188 l-140 86zM1680 436l-188 -359q-12 -29 -36.5 -46.5t-43.5 -20.5l-18 -4q-71 -7 -219 -12l8 -164l-230 367l211 362l7 -173q170 -16 283 -5t170 33zM895 1360q-47 -63 -265 -435l-317 187l-19 12l225 356q20 31 60 45t80 10q24 -2 48.5 -12t42 -21t41.5 -33t36 -34.5 t36 -39.5t32 -35zM1550 1053l212 -363q18 -37 12.5 -76t-27.5 -74q-13 -20 -33 -37t-38 -28t-48.5 -22t-47 -16t-51.5 -14t-46 -12q-34 72 -265 436l313 195zM1407 1279l142 83l-220 -373l-419 20l151 86q-34 89 -75 166t-75.5 123.5t-64.5 80t-47 46.5l-17 13l405 -1 q31 3 58 -10.5t39 -28.5l11 -15q39 -61 112 -190z" /> +<glyph unicode="" horiz-adv-x="2048" d="M480 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM516 768h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5zM1888 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM2048 544v-384 q0 -14 -9 -23t-23 -9h-96v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-1024v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5t179 63.5h768q98 0 179 -63.5t104 -157.5 l105 -419h28q93 0 158.5 -65.5t65.5 -158.5z" /> +<glyph unicode="" horiz-adv-x="2048" d="M1824 640q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-96v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-1024v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5 t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h128q98 0 179 -63.5t104 -157.5l105 -419h28zM320 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM516 640h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5z M1728 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47z" /> +<glyph unicode="" d="M1504 64q0 -26 -19 -45t-45 -19h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45t19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384 q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45z" /> +<glyph unicode="" d="M1127 326q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5zM1223 541q0 40 -35 61q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64 q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5zM1331 789q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5q0 -31 20.5 -52t51.5 -21q11 0 40 8q133 37 307 37 q159 0 309.5 -34t253.5 -95q21 -12 40 -12q29 0 50.5 20.5t21.5 51.5zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M1397 1408q58 0 98.5 -40.5t40.5 -98.5v-1258q0 -58 -40.5 -98.5t-98.5 -40.5h-1258q-58 0 -98.5 40.5t-40.5 98.5v1258q0 58 40.5 98.5t98.5 40.5h1258zM1465 11v1258q0 28 -20 48t-48 20h-1258q-28 0 -48 -20t-20 -48v-1258q0 -28 20 -48t48 -20h1258q28 0 48 20t20 48 zM694 749l188 -387l533 145v-496q0 -7 -5.5 -12.5t-12.5 -5.5h-1258q-7 0 -12.5 5.5t-5.5 12.5v141l711 195l-212 439q4 1 12 2.5t12 1.5q170 32 303.5 21.5t221 -46t143.5 -94.5q27 -28 -25 -42q-64 -16 -256 -62l-97 198q-111 7 -240 -16zM1397 1287q7 0 12.5 -5.5 t5.5 -12.5v-428q-85 30 -188 52q-294 64 -645 12l-18 -3l-65 134h-233l85 -190q-132 -51 -230 -137v560q0 7 5.5 12.5t12.5 5.5h1258zM286 387q-14 -3 -26 4.5t-14 21.5q-24 203 166 305l129 -270z" /> +<glyph unicode="" horiz-adv-x="2304" d="M784 164l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17l-14 -523l14 -241q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23zM1080 193l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6l-10 -579q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11 q11 0 20 9q9 7 9 20zM35 533l20 -128l-20 -126q-2 -9 -9 -9t-9 9l-17 126l17 128q2 9 9 9t9 -9zM121 612l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10l-23 202l23 207q0 9 9 9q8 0 10 -9zM401 159zM213 650l25 -245l-25 -237q0 -11 -11 -11q-10 0 -12 11l-21 237l21 245 q2 12 12 12q11 0 11 -12zM307 657l23 -252l-23 -244q-2 -13 -14 -13q-13 0 -13 13l-21 244l21 252q0 13 13 13q12 0 14 -13zM401 639l21 -234l-21 -246q-2 -16 -16 -16q-6 0 -10.5 4.5t-4.5 11.5l-20 246l20 234q0 6 4.5 10.5t10.5 4.5q14 0 16 -15zM784 164zM495 785 l21 -380l-21 -246q0 -7 -5 -12.5t-12 -5.5q-16 0 -18 18l-18 246l18 380q2 18 18 18q7 0 12 -5.5t5 -12.5zM589 871l19 -468l-19 -244q0 -8 -5.5 -13.5t-13.5 -5.5q-18 0 -20 19l-16 244l16 468q2 19 20 19q8 0 13.5 -5.5t5.5 -13.5zM687 911l18 -506l-18 -242 q-2 -21 -22 -21q-19 0 -21 21l-16 242l16 506q0 9 6.5 15.5t14.5 6.5q9 0 15 -6.5t7 -15.5zM1079 169v0v0zM881 915l15 -510l-15 -239q0 -10 -7.5 -17.5t-17.5 -7.5t-17 7t-8 18l-14 239l14 510q0 11 7.5 18t17.5 7t17.5 -7t7.5 -18zM980 896l14 -492l-14 -236q0 -11 -8 -19 t-19 -8t-19 8t-9 19l-12 236l12 492q1 12 9 20t19 8t18.5 -8t8.5 -20zM1192 404l-14 -231v0q0 -13 -9 -22t-22 -9t-22 9t-10 22l-6 114l-6 117l12 636v3q2 15 12 24q9 7 20 7q8 0 15 -5q14 -8 16 -26zM2304 423q0 -117 -83 -199.5t-200 -82.5h-786q-13 2 -22 11t-9 22v899 q0 23 28 33q85 34 181 34q195 0 338 -131.5t160 -323.5q53 22 110 22q117 0 200 -83t83 -201z" /> +<glyph unicode="" d="M768 768q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 0q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127 t443 -43zM768 384q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 1536q208 0 385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5 t-103 128v128q0 69 103 128t280 93.5t385 34.5z" /> +<glyph unicode="" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M894 465q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36q9 40 56 91.5t132 96.5q14 9 23 -6q2 -2 2 -4q52 85 107 197 q68 136 104 262q-24 82 -30.5 159.5t6.5 127.5q11 40 42 40h21h1q23 0 35 -15q18 -21 9 -68q-2 -6 -4 -8q1 -3 1 -8v-30q-2 -123 -14 -192q55 -164 146 -238zM318 54q52 24 137 158q-51 -40 -87.5 -84t-49.5 -74zM716 974q-15 -42 -2 -132q1 7 7 44q0 3 7 43q1 4 4 8 q-1 1 -1 2t-0.5 1.5t-0.5 1.5q-1 22 -13 36q0 -1 -1 -2v-2zM592 313q135 54 284 81q-2 1 -13 9.5t-16 13.5q-76 67 -127 176q-27 -86 -83 -197q-30 -56 -45 -83zM1238 329q-24 24 -140 24q76 -28 124 -28q14 0 18 1q0 1 -2 3z" /> +<glyph unicode="" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M233 768v-107h70l164 -661h159l128 485q7 20 10 46q2 16 2 24h4l3 -24q1 -3 3.5 -20t5.5 -26l128 -485h159l164 661h70v107h-300v-107h90l-99 -438q-5 -20 -7 -46l-2 -21h-4l-3 21q-1 5 -4 21t-5 25l-144 545h-114l-144 -545q-2 -9 -4.5 -24.5t-3.5 -21.5l-4 -21h-4l-2 21 q-2 26 -7 46l-99 438h90v107h-300z" /> +<glyph unicode="" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M429 106v-106h281v106h-75l103 161q5 7 10 16.5t7.5 13.5t3.5 4h2q1 -4 5 -10q2 -4 4.5 -7.5t6 -8t6.5 -8.5l107 -161h-76v-106h291v106h-68l-192 273l195 282h67v107h-279v-107h74l-103 -159q-4 -7 -10 -16.5t-9 -13.5l-2 -3h-2q-1 4 -5 10q-6 11 -17 23l-106 159h76v107 h-290v-107h68l189 -272l-194 -283h-68z" /> +<glyph unicode="" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M416 106v-106h327v106h-93v167h137q76 0 118 15q67 23 106.5 87t39.5 146q0 81 -37 141t-100 87q-48 19 -130 19h-368v-107h92v-555h-92zM769 386h-119v268h120q52 0 83 -18q56 -33 56 -115q0 -89 -62 -120q-31 -15 -78 -15z" /> +<glyph unicode="" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M1280 320v-320h-1024v192l192 192l128 -128l384 384zM448 512q-80 0 -136 56t-56 136t56 136t136 56t136 -56t56 -136t-56 -136t-136 -56z" /> +<glyph unicode="" d="M640 1152v128h-128v-128h128zM768 1024v128h-128v-128h128zM640 896v128h-128v-128h128zM768 768v128h-128v-128h128zM1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400 v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-128v-128h-128v128h-512v-1536h1280zM781 593l107 -349q8 -27 8 -52q0 -83 -72.5 -137.5t-183.5 -54.5t-183.5 54.5t-72.5 137.5q0 25 8 52q21 63 120 396v128h128v-128h79 q22 0 39 -13t23 -34zM640 128q53 0 90.5 19t37.5 45t-37.5 45t-90.5 19t-90.5 -19t-37.5 -45t37.5 -45t90.5 -19z" /> +<glyph unicode="" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M620 686q20 -8 20 -30v-544q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-166 167h-131q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h131l166 167q16 15 35 7zM1037 -3q31 0 50 24q129 159 129 363t-129 363q-16 21 -43 24t-47 -14q-21 -17 -23.5 -43.5t14.5 -47.5 q100 -123 100 -282t-100 -282q-17 -21 -14.5 -47.5t23.5 -42.5q18 -15 40 -15zM826 145q27 0 47 20q87 93 87 219t-87 219q-18 19 -45 20t-46 -17t-20 -44.5t18 -46.5q52 -57 52 -131t-52 -131q-19 -20 -18 -46.5t20 -44.5q20 -17 44 -17z" /> +<glyph unicode="" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M768 768q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-384q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h384zM1260 766q20 -8 20 -30v-576q0 -22 -20 -30q-8 -2 -12 -2q-14 0 -23 9l-265 266v90l265 266q9 9 23 9q4 0 12 -2z" /> +<glyph unicode="" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M480 768q8 11 21 12.5t24 -6.5l51 -38q11 -8 12.5 -21t-6.5 -24l-182 -243l182 -243q8 -11 6.5 -24t-12.5 -21l-51 -38q-11 -8 -24 -6.5t-21 12.5l-226 301q-14 19 0 38zM1282 467q14 -19 0 -38l-226 -301q-8 -11 -21 -12.5t-24 6.5l-51 38q-11 8 -12.5 21t6.5 24l182 243 l-182 243q-8 11 -6.5 24t12.5 21l51 38q11 8 24 6.5t21 -12.5zM662 6q-13 2 -20.5 13t-5.5 24l138 831q2 13 13 20.5t24 5.5l63 -10q13 -2 20.5 -13t5.5 -24l-138 -831q-2 -13 -13 -20.5t-24 -5.5z" /> +<glyph unicode="" d="M1497 709v-198q-101 -23 -198 -23q-65 -136 -165.5 -271t-181.5 -215.5t-128 -106.5q-80 -45 -162 3q-28 17 -60.5 43.5t-85 83.5t-102.5 128.5t-107.5 184t-105.5 244t-91.5 314.5t-70.5 390h283q26 -218 70 -398.5t104.5 -317t121.5 -235.5t140 -195q169 169 287 406 q-142 72 -223 220t-81 333q0 192 104 314.5t284 122.5q178 0 273 -105.5t95 -297.5q0 -159 -58 -286q-7 -1 -19.5 -3t-46 -2t-63 6t-62 25.5t-50.5 51.5q31 103 31 184q0 87 -29 132t-79 45q-53 0 -85 -49.5t-32 -140.5q0 -186 105 -293.5t267 -107.5q62 0 121 14z" /> +<glyph unicode="" horiz-adv-x="1792" d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546 q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" /> +<glyph unicode="" horiz-adv-x="2048" d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94 q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55 t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97q14 -16 29.5 -34t34.5 -40t29 -34q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5 t-85 -189.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194 q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5 t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348q0 222 101 414.5t276.5 317t390.5 155.5v-260q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 q0 230 -145.5 406t-366.5 221v260q215 -31 390.5 -155.5t276.5 -317t101 -414.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41 t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170 t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136 q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" /> +<glyph unicode="" horiz-adv-x="1792" d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251 l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162 q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33 q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5 t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71 t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" /> +<glyph unicode="" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392 q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M595 22q0 100 -165 100q-158 0 -158 -104q0 -101 172 -101q151 0 151 105zM536 777q0 61 -30 102t-89 41q-124 0 -124 -145q0 -135 124 -135q119 0 119 137zM805 1101v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58 q0 -31 22.5 -51.5t58 -32t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 108.5t-47.5 165.5q0 139 95 231.5t235 92.5q96 0 178 -47 q98 0 218 47zM1123 220h-222q4 45 4 134v609q0 94 -4 128h222q-4 -33 -4 -124v-613q0 -89 4 -134zM1724 442v-196q-71 -39 -174 -39q-62 0 -107 20t-70 50t-39.5 78t-18.5 92t-4 103v351h2v4q-7 0 -19 1t-18 1q-21 0 -59 -6v190h96v76q0 54 -6 89h227q-6 -41 -6 -165h171 v-190q-15 0 -43.5 2t-42.5 2h-85v-365q0 -131 87 -131q61 0 109 33zM1148 1389q0 -58 -39 -101.5t-96 -43.5q-58 0 -98 43.5t-40 101.5q0 59 39.5 103t98.5 44q58 0 96.5 -44.5t38.5 -102.5z" /> +<glyph unicode="" d="M825 547l343 588h-150q-21 -39 -63.5 -118.5t-68 -128.5t-59.5 -118.5t-60 -128.5h-3q-21 48 -44.5 97t-52 105.5t-46.5 92t-54 104.5t-49 95h-150l323 -589v-435h134v436zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1280" d="M842 964q0 -80 -57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5t29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5 t136.5 -56.5t56.5 -136.5zM1223 953q0 -158 -78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186t-102 153t-153 102t-186 38t-186 -38t-153 -102t-102 -153 t-38 -186q0 -114 52 -218q10 -20 3.5 -40t-25.5 -30t-39.5 -3t-30.5 26q-64 123 -64 265q0 119 46.5 227t124.5 186t186 124t226 46q158 0 292.5 -78t212.5 -212.5t78 -292.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M270 730q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5t3.5 -5t2 -3.5 q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 -4 -16t-7 -18q-64 -97 -302 -97q-53 0 -110.5 9t-98 20 t-104.5 30q-15 5 -23 7q-14 4 -46 4.5t-40 1.5q-41 -45 -127.5 -65t-168.5 -20q-35 0 -69 1.5t-93 9t-101 20.5t-74.5 40t-32.5 64q0 40 10 59.5t41 48.5q11 2 40.5 13t49.5 12q4 0 14 2q2 2 2 4l-2 3q-48 11 -108 105.5t-73 156.5l-5 3q-4 0 -12 -20q-18 -41 -54.5 -74.5 t-77.5 -37.5h-1q-4 0 -6 4.5t-5 5.5q-23 54 -23 100q0 275 252 466z" /> +<glyph unicode="" horiz-adv-x="2048" d="M580 1075q0 41 -25 66t-66 25q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5zM1323 568q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51zM1087 1075q0 41 -24.5 66t-65.5 25 q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5zM1722 568q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51zM1456 965q-31 4 -70 4q-169 0 -311 -77t-223.5 -208.5t-81.5 -287.5 q0 -78 23 -152q-35 -3 -68 -3q-26 0 -50 1.5t-55 6.5t-44.5 7t-54.5 10.5t-50 10.5l-253 -127l72 218q-290 203 -290 490q0 169 97.5 311t264 223.5t363.5 81.5q176 0 332.5 -66t262 -182.5t136.5 -260.5zM2048 404q0 -117 -68.5 -223.5t-185.5 -193.5l55 -181l-199 109 q-150 -37 -218 -37q-169 0 -311 70.5t-223.5 191.5t-81.5 264t81.5 264t223.5 191.5t311 70.5q161 0 303 -70.5t227.5 -192t85.5 -263.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-453 185l-242 -295q-18 -23 -49 -23q-13 0 -22 4q-19 7 -30.5 23.5t-11.5 36.5v349l864 1059l-1069 -925l-395 162q-37 14 -40 55q-2 40 32 59l1664 960q15 9 32 9q20 0 36 -11z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-527 215l-298 -327q-18 -21 -47 -21q-14 0 -23 4q-19 7 -30 23.5t-11 36.5v452l-472 193q-37 14 -40 55q-3 39 32 59l1664 960q35 21 68 -2zM1422 26l221 1323l-1434 -827l336 -137 l863 639l-478 -797z" /> +<glyph unicode="" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 -298zM896 928v-448q0 -14 -9 -23 t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23z" /> +<glyph unicode="" d="M768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1682 -128q-44 0 -132.5 3.5t-133.5 3.5q-44 0 -132 -3.5t-132 -3.5q-24 0 -37 20.5t-13 45.5q0 31 17 46t39 17t51 7t45 15q33 21 33 140l-1 391q0 21 -1 31q-13 4 -50 4h-675q-38 0 -51 -4q-1 -10 -1 -31l-1 -371q0 -142 37 -164q16 -10 48 -13t57 -3.5t45 -15 t20 -45.5q0 -26 -12.5 -48t-36.5 -22q-47 0 -139.5 3.5t-138.5 3.5q-43 0 -128 -3.5t-127 -3.5q-23 0 -35.5 21t-12.5 45q0 30 15.5 45t36 17.5t47.5 7.5t42 15q33 23 33 143l-1 57v813q0 3 0.5 26t0 36.5t-1.5 38.5t-3.5 42t-6.5 36.5t-11 31.5t-16 18q-15 10 -45 12t-53 2 t-41 14t-18 45q0 26 12 48t36 22q46 0 138.5 -3.5t138.5 -3.5q42 0 126.5 3.5t126.5 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17 -43.5t-38.5 -14.5t-49.5 -4t-43 -13q-35 -21 -35 -160l1 -320q0 -21 1 -32q13 -3 39 -3h699q25 0 38 3q1 11 1 32l1 320q0 139 -35 160 q-18 11 -58.5 12.5t-66 13t-25.5 49.5q0 26 12.5 48t37.5 22q44 0 132 -3.5t132 -3.5q43 0 129 3.5t129 3.5q25 0 37.5 -22t12.5 -48q0 -30 -17.5 -44t-40 -14.5t-51.5 -3t-44 -12.5q-35 -23 -35 -161l1 -943q0 -119 34 -140q16 -10 46 -13.5t53.5 -4.5t41.5 -15.5t18 -44.5 q0 -26 -12 -48t-36 -22z" /> +<glyph unicode="" horiz-adv-x="1280" d="M1278 1347v-73q0 -29 -18.5 -61t-42.5 -32q-50 0 -54 -1q-26 -6 -32 -31q-3 -11 -3 -64v-1152q0 -25 -18 -43t-43 -18h-108q-25 0 -43 18t-18 43v1218h-143v-1218q0 -25 -17.5 -43t-43.5 -18h-108q-26 0 -43.5 18t-17.5 43v496q-147 12 -245 59q-126 58 -192 179 q-64 117 -64 259q0 166 88 286q88 118 209 159q111 37 417 37h479q25 0 43 -18t18 -43z" /> +<glyph unicode="" d="M352 128v-128h-352v128h352zM704 256q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280q26 0 45 -19t19 -45v-256 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1216 768q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1536 640v-128h-224v128h224zM1536 1152v-128h-864v128h864z" /> +<glyph unicode="" d="M1216 512q133 0 226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5q0 12 2 34l-360 180q-92 -86 -218 -86q-133 0 -226.5 93.5t-93.5 226.5t93.5 226.5t226.5 93.5q126 0 218 -86l360 180q-2 22 -2 34q0 133 93.5 226.5t226.5 93.5 t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5q-126 0 -218 86l-360 -180q2 -22 2 -34t-2 -34l360 -180q92 86 218 86z" /> +<glyph unicode="" d="M1280 341q0 88 -62.5 151t-150.5 63q-84 0 -145 -58l-241 120q2 16 2 23t-2 23l241 120q61 -58 145 -58q88 0 150.5 63t62.5 151t-62.5 150.5t-150.5 62.5t-151 -62.5t-63 -150.5q0 -7 2 -23l-241 -120q-62 57 -145 57q-88 0 -150.5 -62.5t-62.5 -150.5t62.5 -150.5 t150.5 -62.5q83 0 145 57l241 -120q-2 -16 -2 -23q0 -88 63 -150.5t151 -62.5t150.5 62.5t62.5 150.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M571 947q-10 25 -34 35t-49 0q-108 -44 -191 -127t-127 -191q-10 -25 0 -49t35 -34q13 -5 24 -5q42 0 60 40q34 84 98.5 148.5t148.5 98.5q25 11 35 35t0 49zM1513 1303l46 -46l-244 -243l68 -68q19 -19 19 -45.5t-19 -45.5l-64 -64q89 -161 89 -343q0 -143 -55.5 -273.5 t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5q182 0 343 -89l64 64q19 19 45.5 19t45.5 -19l68 -68zM1521 1359q-10 -10 -22 -10q-13 0 -23 10l-91 90q-9 10 -9 23t9 23q10 9 23 9t23 -9l90 -91 q10 -9 10 -22.5t-10 -22.5zM1751 1129q-11 -9 -23 -9t-23 9l-90 91q-10 9 -10 22.5t10 22.5q9 10 22.5 10t22.5 -10l91 -90q9 -10 9 -23t-9 -23zM1792 1312q0 -14 -9 -23t-23 -9h-96q-14 0 -23 9t-9 23t9 23t23 9h96q14 0 23 -9t9 -23zM1600 1504v-96q0 -14 -9 -23t-23 -9 t-23 9t-9 23v96q0 14 9 23t23 9t23 -9t9 -23zM1751 1449l-91 -90q-10 -10 -22 -10q-13 0 -23 10q-10 9 -10 22.5t10 22.5l90 91q10 9 23 9t23 -9q9 -10 9 -23t-9 -23z" /> +<glyph unicode="" horiz-adv-x="1792" d="M609 720l287 208l287 -208l-109 -336h-355zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM1515 186q149 203 149 454v3l-102 -89l-240 224l63 323 l134 -12q-150 206 -389 282l53 -124l-287 -159l-287 159l53 124q-239 -76 -389 -282l135 12l62 -323l-240 -224l-102 89v-3q0 -251 149 -454l30 132l326 -40l139 -298l-116 -69q117 -39 240 -39t240 39l-116 69l139 298l326 40z" /> +<glyph unicode="" horiz-adv-x="1792" d="M448 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM256 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM832 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM66 768q-28 0 -47 19t-19 46v129h514v-129q0 -27 -19 -46t-46 -19h-383zM1216 224v-192q0 -14 -9 -23t-23 -9h-192 q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1600 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23 zM1408 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1016v-13h-514v10q0 104 -382 102q-382 -1 -382 -102v-10h-514v13q0 17 8.5 43t34 64t65.5 75.5t110.5 76t160 67.5t224 47.5t293.5 18.5t293 -18.5t224 -47.5 t160.5 -67.5t110.5 -76t65.5 -75.5t34 -64t8.5 -43zM1792 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 962v-129q0 -27 -19 -46t-46 -19h-384q-27 0 -46 19t-19 46v129h514z" /> +<glyph unicode="" horiz-adv-x="1792" d="M704 1216v-768q0 -26 -19 -45t-45 -19v-576q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v512l249 873q7 23 31 23h424zM1024 1216v-704h-256v704h256zM1792 320v-512q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v576q-26 0 -45 19t-19 45v768h424q24 0 31 -23z M736 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23zM1408 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1755 1083q37 -37 37 -90t-37 -91l-401 -400l150 -150l-160 -160q-163 -163 -389.5 -186.5t-411.5 100.5l-362 -362h-181v181l362 362q-124 185 -100.5 411.5t186.5 389.5l160 160l150 -150l400 401q38 37 91 37t90 -37t37 -90.5t-37 -90.5l-400 -401l234 -234l401 400 q38 37 91 37t90 -37z" /> +<glyph unicode="" horiz-adv-x="1792" d="M873 796q0 -83 -63.5 -142.5t-152.5 -59.5t-152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59t152.5 -59t63.5 -143zM1375 796q0 -83 -63 -142.5t-153 -59.5q-89 0 -152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59q90 0 153 -59t63 -143zM1600 616v667q0 87 -32 123.5 t-111 36.5h-1112q-83 0 -112.5 -34t-29.5 -126v-673q43 -23 88.5 -40t81 -28t81 -18.5t71 -11t70 -4t58.5 -0.5t56.5 2t44.5 2q68 1 95 -27q6 -6 10 -9q26 -25 61 -51q7 91 118 87q5 0 36.5 -1.5t43 -2t45.5 -1t53 1t54.5 4.5t61 8.5t62 13.5t67 19.5t67.5 27t72 34.5z M1763 621q-121 -149 -372 -252q84 -285 -23 -465q-66 -113 -183 -148q-104 -32 -182 15q-86 51 -82 164l-1 326v1q-8 2 -24.5 6t-23.5 5l-1 -338q4 -114 -83 -164q-79 -47 -183 -15q-117 36 -182 150q-105 180 -22 463q-251 103 -372 252q-25 37 -4 63t60 -1q3 -2 11 -7 t11 -8v694q0 72 47 123t114 51h1257q67 0 114 -51t47 -123v-694l21 15q39 27 60 1t-4 -63z" /> +<glyph unicode="" horiz-adv-x="1792" d="M896 1102v-434h-145v434h145zM1294 1102v-434h-145v434h145zM1294 342l253 254v795h-1194v-1049h326v-217l217 217h398zM1692 1536v-1013l-434 -434h-326l-217 -217h-217v217h-398v1158l109 289h1483z" /> +<glyph unicode="" d="M773 217v-127q-1 -292 -6 -305q-12 -32 -51 -40q-54 -9 -181.5 38t-162.5 89q-13 15 -17 36q-1 12 4 26q4 10 34 47t181 216q1 0 60 70q15 19 39.5 24.5t49.5 -3.5q24 -10 37.5 -29t12.5 -42zM624 468q-3 -55 -52 -70l-120 -39q-275 -88 -292 -88q-35 2 -54 36 q-12 25 -17 75q-8 76 1 166.5t30 124.5t56 32q13 0 202 -77q70 -29 115 -47l84 -34q23 -9 35.5 -30.5t11.5 -48.5zM1450 171q-7 -54 -91.5 -161t-135.5 -127q-37 -14 -63 7q-14 10 -184 287l-47 77q-14 21 -11.5 46t19.5 46q35 43 83 26q1 -1 119 -40q203 -66 242 -79.5 t47 -20.5q28 -22 22 -61zM778 803q5 -102 -54 -122q-58 -17 -114 71l-378 598q-8 35 19 62q41 43 207.5 89.5t224.5 31.5q40 -10 49 -45q3 -18 22 -305.5t24 -379.5zM1440 695q3 -39 -26 -59q-15 -10 -329 -86q-67 -15 -91 -23l1 2q-23 -6 -46 4t-37 32q-30 47 0 87 q1 1 75 102q125 171 150 204t34 39q28 19 65 2q48 -23 123 -133.5t81 -167.5v-3z" /> +<glyph unicode="" horiz-adv-x="2048" d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960q0 -26 19 -45t45 -19t45 19 t19 45zM1920 192v1088h-1536v-1088q0 -33 -11 -64h1483q26 0 45 19t19 45zM2048 1408v-1216q0 -80 -56 -136t-136 -56h-1664q-80 0 -136 56t-56 136v1088h256v128h1792z" /> +<glyph unicode="" horiz-adv-x="2048" d="M1024 13q-20 0 -93 73.5t-73 93.5q0 32 62.5 54t103.5 22t103.5 -22t62.5 -54q0 -20 -73 -93.5t-93 -73.5zM1294 284q-2 0 -40 25t-101.5 50t-128.5 25t-128.5 -25t-101 -50t-40.5 -25q-18 0 -93.5 75t-75.5 93q0 13 10 23q78 77 196 121t233 44t233 -44t196 -121 q10 -10 10 -23q0 -18 -75.5 -93t-93.5 -75zM1567 556q-11 0 -23 8q-136 105 -252 154.5t-268 49.5q-85 0 -170.5 -22t-149 -53t-113.5 -62t-79 -53t-31 -22q-17 0 -92 75t-75 93q0 12 10 22q132 132 320 205t380 73t380 -73t320 -205q10 -10 10 -22q0 -18 -75 -93t-92 -75z M1838 827q-11 0 -22 9q-179 157 -371.5 236.5t-420.5 79.5t-420.5 -79.5t-371.5 -236.5q-11 -9 -22 -9q-17 0 -92.5 75t-75.5 93q0 13 10 23q187 186 445 288t527 102t527 -102t445 -288q10 -10 10 -23q0 -18 -75.5 -93t-92.5 -75z" /> +<glyph unicode="" horiz-adv-x="1792" d="M384 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5 t37.5 90.5zM384 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 768q0 53 -37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1536 0v384q0 52 -38 90t-90 38t-90 -38t-38 -90v-384q0 -52 38 -90t90 -38t90 38t38 90zM1152 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5z M1536 1088v256q0 26 -19 45t-45 19h-1280q-26 0 -45 -19t-19 -45v-256q0 -26 19 -45t45 -19h1280q26 0 45 19t19 45zM1536 768q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1408v-1536q0 -52 -38 -90t-90 -38 h-1408q-52 0 -90 38t-38 90v1536q0 52 38 90t90 38h1408q52 0 90 -38t38 -90z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1112 1090q0 159 -237 159h-70q-32 0 -59.5 -21.5t-34.5 -52.5l-63 -276q-2 -5 -2 -16q0 -24 17 -39.5t41 -15.5h53q69 0 128.5 13t112.5 41t83.5 81.5t30.5 126.5zM1716 938q0 -265 -220 -428q-219 -161 -612 -161h-61q-32 0 -59 -21.5t-34 -52.5l-73 -316 q-8 -36 -40.5 -61.5t-69.5 -25.5h-213q-31 0 -53 20t-22 51q0 10 13 65h151q34 0 64 23.5t38 56.5l73 316q8 33 37.5 57t63.5 24h61q390 0 607 160t217 421q0 129 -51 207q183 -92 183 -335zM1533 1123q0 -264 -221 -428q-218 -161 -612 -161h-60q-32 0 -59.5 -22t-34.5 -53 l-73 -315q-8 -36 -40 -61.5t-69 -25.5h-214q-31 0 -52.5 19.5t-21.5 51.5q0 8 2 20l300 1301q8 36 40.5 61.5t69.5 25.5h444q68 0 125 -4t120.5 -15t113.5 -30t96.5 -50.5t77.5 -74t49.5 -103.5t18.5 -136z" /> +<glyph unicode="" horiz-adv-x="1792" d="M602 949q19 -61 31 -123.5t17 -141.5t-14 -159t-62 -145q-21 81 -67 157t-95.5 127t-99 90.5t-78.5 57.5t-33 19q-62 34 -81.5 100t14.5 128t101 81.5t129 -14.5q138 -83 238 -177zM927 1236q11 -25 20.5 -46t36.5 -100.5t42.5 -150.5t25.5 -179.5t0 -205.5t-47.5 -209.5 t-105.5 -208.5q-51 -72 -138 -72q-54 0 -98 31q-57 40 -69 109t28 127q60 85 81 195t13 199.5t-32 180.5t-39 128t-22 52q-31 63 -8.5 129.5t85.5 97.5q34 17 75 17q47 0 88.5 -25t63.5 -69zM1248 567q-17 -160 -72 -311q-17 131 -63 246q25 174 -5 361q-27 178 -94 342 q114 -90 212 -211q9 -37 15 -80q26 -179 7 -347zM1520 1440q9 -17 23.5 -49.5t43.5 -117.5t50.5 -178t34 -227.5t5 -269t-47 -300t-112.5 -323.5q-22 -48 -66 -75.5t-95 -27.5q-39 0 -74 16q-67 31 -92.5 100t4.5 136q58 126 90 257.5t37.5 239.5t-3.5 213.5t-26.5 180.5 t-38.5 138.5t-32.5 90t-15.5 32.5q-34 65 -11.5 135.5t87.5 104.5q37 20 81 20q49 0 91.5 -25.5t66.5 -70.5z" /> +<glyph unicode="" horiz-adv-x="2304" d="M1975 546h-138q14 37 66 179l3 9q4 10 10 26t9 26l12 -55zM531 611l-58 295q-11 54 -75 54h-268l-2 -13q311 -79 403 -336zM710 960l-162 -438l-17 89q-26 70 -85 129.5t-131 88.5l135 -510h175l261 641h-176zM849 318h166l104 642h-166zM1617 944q-69 27 -149 27 q-123 0 -201 -59t-79 -153q-1 -102 145 -174q48 -23 67 -41t19 -39q0 -30 -30 -46t-69 -16q-86 0 -156 33l-22 11l-23 -144q74 -34 185 -34q130 -1 208.5 59t80.5 160q0 106 -140 174q-49 25 -71 42t-22 38q0 22 24.5 38.5t70.5 16.5q70 1 124 -24l15 -8zM2042 960h-128 q-65 0 -87 -54l-246 -588h174l35 96h212q5 -22 20 -96h154zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" /> +<glyph unicode="" horiz-adv-x="2304" d="M671 603h-13q-47 0 -47 -32q0 -22 20 -22q17 0 28 15t12 39zM1066 639h62v3q1 4 0.5 6.5t-1 7t-2 8t-4.5 6.5t-7.5 5t-11.5 2q-28 0 -36 -38zM1606 603h-12q-48 0 -48 -32q0 -22 20 -22q17 0 28 15t12 39zM1925 629q0 41 -30 41q-19 0 -31 -20t-12 -51q0 -42 28 -42 q20 0 32.5 20t12.5 52zM480 770h87l-44 -262h-56l32 201l-71 -201h-39l-4 200l-34 -200h-53l44 262h81l2 -163zM733 663q0 -6 -4 -42q-16 -101 -17 -113h-47l1 22q-20 -26 -58 -26q-23 0 -37.5 16t-14.5 42q0 39 26 60.5t73 21.5q14 0 23 -1q0 3 0.5 5.5t1 4.5t0.5 3 q0 20 -36 20q-29 0 -59 -10q0 4 7 48q38 11 67 11q74 0 74 -62zM889 721l-8 -49q-22 3 -41 3q-27 0 -27 -17q0 -8 4.5 -12t21.5 -11q40 -19 40 -60q0 -72 -87 -71q-34 0 -58 6q0 2 7 49q29 -8 51 -8q32 0 32 19q0 7 -4.5 11.5t-21.5 12.5q-43 20 -43 59q0 72 84 72 q30 0 50 -4zM977 721h28l-7 -52h-29q-2 -17 -6.5 -40.5t-7 -38.5t-2.5 -18q0 -16 19 -16q8 0 16 2l-8 -47q-21 -7 -40 -7q-43 0 -45 47q0 12 8 56q3 20 25 146h55zM1180 648q0 -23 -7 -52h-111q-3 -22 10 -33t38 -11q30 0 58 14l-9 -54q-30 -8 -57 -8q-95 0 -95 95 q0 55 27.5 90.5t69.5 35.5q35 0 55.5 -21t20.5 -56zM1319 722q-13 -23 -22 -62q-22 2 -31 -24t-25 -128h-56l3 14q22 130 29 199h51l-3 -33q14 21 25.5 29.5t28.5 4.5zM1506 763l-9 -57q-28 14 -50 14q-31 0 -51 -27.5t-20 -70.5q0 -30 13.5 -47t38.5 -17q21 0 48 13 l-10 -59q-28 -8 -50 -8q-45 0 -71.5 30.5t-26.5 82.5q0 70 35.5 114.5t91.5 44.5q26 0 61 -13zM1668 663q0 -18 -4 -42q-13 -79 -17 -113h-46l1 22q-20 -26 -59 -26q-23 0 -37 16t-14 42q0 39 25.5 60.5t72.5 21.5q15 0 23 -1q2 7 2 13q0 20 -36 20q-29 0 -59 -10q0 4 8 48 q38 11 67 11q73 0 73 -62zM1809 722q-14 -24 -21 -62q-23 2 -31.5 -23t-25.5 -129h-56l3 14q19 104 29 199h52q0 -11 -4 -33q15 21 26.5 29.5t27.5 4.5zM1950 770h56l-43 -262h-53l3 19q-23 -23 -52 -23q-31 0 -49.5 24t-18.5 64q0 53 27.5 92t64.5 39q31 0 53 -29z M2061 640q0 148 -72.5 273t-198 198t-273.5 73q-181 0 -328 -110q127 -116 171 -284h-50q-44 150 -158 253q-114 -103 -158 -253h-50q44 168 171 284q-147 110 -328 110q-148 0 -273.5 -73t-198 -198t-72.5 -273t72.5 -273t198 -198t273.5 -73q181 0 328 110 q-120 111 -165 264h50q46 -138 152 -233q106 95 152 233h50q-45 -153 -165 -264q147 -110 328 -110q148 0 273.5 73t198 198t72.5 273zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" /> +<glyph unicode="" horiz-adv-x="2304" d="M313 759q0 -51 -36 -84q-29 -26 -89 -26h-17v220h17q61 0 89 -27q36 -31 36 -83zM2089 824q0 -52 -64 -52h-19v101h20q63 0 63 -49zM380 759q0 74 -50 120.5t-129 46.5h-95v-333h95q74 0 119 38q60 51 60 128zM410 593h65v333h-65v-333zM730 694q0 40 -20.5 62t-75.5 42 q-29 10 -39.5 19t-10.5 23q0 16 13.5 26.5t34.5 10.5q29 0 53 -27l34 44q-41 37 -98 37q-44 0 -74 -27.5t-30 -67.5q0 -35 18 -55.5t64 -36.5q37 -13 45 -19q19 -12 19 -34q0 -20 -14 -33.5t-36 -13.5q-48 0 -71 44l-42 -40q44 -64 115 -64q51 0 83 30.5t32 79.5zM1008 604 v77q-37 -37 -78 -37q-49 0 -80.5 32.5t-31.5 82.5q0 48 31.5 81.5t77.5 33.5q43 0 81 -38v77q-40 20 -80 20q-74 0 -125.5 -50.5t-51.5 -123.5t51 -123.5t125 -50.5q42 0 81 19zM2240 0v527q-65 -40 -144.5 -84t-237.5 -117t-329.5 -137.5t-417.5 -134.5t-504 -118h1569 q26 0 45 19t19 45zM1389 757q0 75 -53 128t-128 53t-128 -53t-53 -128t53 -128t128 -53t128 53t53 128zM1541 584l144 342h-71l-90 -224l-89 224h-71l142 -342h35zM1714 593h184v56h-119v90h115v56h-115v74h119v57h-184v-333zM2105 593h80l-105 140q76 16 76 94q0 47 -31 73 t-87 26h-97v-333h65v133h9zM2304 1274v-1268q0 -56 -38.5 -95t-93.5 -39h-2040q-55 0 -93.5 39t-38.5 95v1268q0 56 38.5 95t93.5 39h2040q55 0 93.5 -39t38.5 -95z" /> +<glyph unicode="" horiz-adv-x="2304" d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453q0 33 -40 33h-84v-69h83q41 0 41 36zM1475 457q0 29 -42 29h-82v-61h81q43 0 43 32zM1197 923q0 29 -42 29h-82v-60h81q43 0 43 31zM1656 854h89l-44 108z M699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453q0 -20 -5.5 -35t-14 -25t-22.5 -16.5t-26 -10t-31.5 -4.5t-31.5 -1t-32.5 0.5t-29.5 0.5v-91h-126l-80 90l-83 -90h-256v271h260 l80 -89l82 89h207q109 0 109 -89zM964 794v-56h-217v271h217v-57h-152v-49h148v-55h-148v-54h152zM2304 235v-229q0 -55 -38.5 -94.5t-93.5 -39.5h-2040q-55 0 -93.5 39.5t-38.5 94.5v678h111l25 61h55l25 -61h218v46l19 -46h113l20 47v-47h541v99l10 1q10 0 10 -14v-86h279 v23q23 -12 55 -18t52.5 -6.5t63 0.5t51.5 1l25 61h56l25 -61h227v58l34 -58h182v378h-180v-44l-25 44h-185v-44l-23 44h-249q-69 0 -109 -22v22h-172v-22q-24 22 -73 22h-628l-43 -97l-43 97h-198v-44l-22 44h-169l-78 -179v391q0 55 38.5 94.5t93.5 39.5h2040 q55 0 93.5 -39.5t38.5 -94.5v-678h-120q-51 0 -81 -22v22h-177q-55 0 -78 -22v22h-316v-22q-31 22 -87 22h-209v-22q-23 22 -91 22h-234l-54 -58l-50 58h-349v-378h343l55 59l52 -59h211v89h21q59 0 90 13v-102h174v99h8q8 0 10 -2t2 -10v-87h529q57 0 88 24v-24h168 q60 0 95 17zM1546 469q0 -23 -12 -43t-34 -29q25 -9 34 -26t9 -46v-54h-65v45q0 33 -12 43.5t-46 10.5h-69v-99h-65v271h154q48 0 77 -15t29 -58zM1269 936q0 -24 -12.5 -44t-33.5 -29q26 -9 34.5 -25.5t8.5 -46.5v-53h-65q0 9 0.5 26.5t0 25t-3 18.5t-8.5 16t-17.5 8.5 t-29.5 3.5h-70v-98h-64v271l153 -1q49 0 78 -14.5t29 -57.5zM1798 327v-56h-216v271h216v-56h-151v-49h148v-55h-148v-54zM1372 1009v-271h-66v271h66zM2065 357q0 -86 -102 -86h-126v58h126q34 0 34 25q0 16 -17 21t-41.5 5t-49.5 3.5t-42 22.5t-17 55q0 39 26 60t66 21 h130v-57h-119q-36 0 -36 -25q0 -16 17.5 -20.5t42 -4t49 -2.5t42 -21.5t17.5 -54.5zM2304 407v-101q-24 -35 -88 -35h-125v58h125q33 0 33 25q0 13 -12.5 19t-31 5.5t-40 2t-40 8t-31 24t-12.5 48.5q0 39 26.5 60t66.5 21h129v-57h-118q-36 0 -36 -25q0 -20 29 -22t68.5 -5 t56.5 -26zM2139 1008v-270h-92l-122 203v-203h-132l-26 60h-134l-25 -60h-75q-129 0 -129 133q0 138 133 138h63v-59q-7 0 -28 1t-28.5 0.5t-23 -2t-21.5 -6.5t-14.5 -13.5t-11.5 -23t-3 -33.5q0 -38 13.5 -58t49.5 -20h29l92 213h97l109 -256v256h99l114 -188v188h66z" /> +<glyph unicode="" horiz-adv-x="2304" d="M322 689h-15q-19 0 -19 18q0 28 19 85q5 15 15 19.5t28 4.5q77 0 77 -49q0 -41 -30.5 -59.5t-74.5 -18.5zM664 528q-47 0 -47 29q0 62 123 62l3 -3q-5 -88 -79 -88zM1438 687h-15q-19 0 -19 19q0 28 19 85q5 15 14.5 19t28.5 4q77 0 77 -49q0 -41 -30.5 -59.5 t-74.5 -18.5zM1780 527q-47 0 -47 30q0 62 123 62l3 -3q-5 -89 -79 -89zM373 894h-128q-8 0 -14.5 -4t-8.5 -7.5t-7 -12.5q-3 -7 -45 -190t-42 -192q0 -7 5.5 -12.5t13.5 -5.5h62q25 0 32.5 34.5l15 69t32.5 34.5q47 0 87.5 7.5t80.5 24.5t63.5 52.5t23.5 84.5 q0 36 -14.5 61t-41 36.5t-53.5 15.5t-62 4zM719 798q-38 0 -74 -6q-2 0 -8.5 -1t-9 -1.5l-7.5 -1.5t-7.5 -2t-6.5 -3t-6.5 -4t-5 -5t-4.5 -7t-4 -9q-9 -29 -9 -39t9 -10q5 0 21.5 5t19.5 6q30 8 58 8q74 0 74 -36q0 -11 -10 -14q-8 -2 -18 -3t-21.5 -1.5t-17.5 -1.5 q-38 -4 -64.5 -10t-56.5 -19.5t-45.5 -39t-15.5 -62.5q0 -38 26 -59.5t64 -21.5q24 0 45.5 6.5t33 13t38.5 23.5q-3 -7 -3 -15t5.5 -13.5t12.5 -5.5h56q1 1 7 3.5t7.5 3.5t5 3.5t5 5.5t2.5 8l45 194q4 13 4 30q0 81 -145 81zM1247 793h-74q-22 0 -39 -23q-5 -7 -29.5 -51 t-46.5 -81.5t-26 -38.5l-5 4q0 77 -27 166q-1 5 -3.5 8.5t-6 6.5t-6.5 5t-8.5 3t-8.5 1.5t-9.5 1t-9 0.5h-10h-8.5q-38 0 -38 -21l1 -5q5 -53 25 -151t25 -143q2 -16 2 -24q0 -19 -30.5 -61.5t-30.5 -58.5q0 -13 40 -13q61 0 76 25l245 415q10 20 10 26q0 9 -8 9zM1489 892 h-129q-18 0 -29 -23q-6 -13 -46.5 -191.5t-40.5 -190.5q0 -20 43 -20h7.5h9h9t9.5 1t8.5 2t8.5 3t6.5 4.5t5.5 6t3 8.5l21 91q2 10 10.5 17t19.5 7q47 0 87.5 7t80.5 24.5t63.5 52.5t23.5 84q0 36 -14.5 61t-41 36.5t-53.5 15.5t-62 4zM1835 798q-26 0 -74 -6 q-38 -6 -48 -16q-7 -8 -11 -19q-8 -24 -8 -39q0 -10 8 -10q1 0 41 12q30 8 58 8q74 0 74 -36q0 -12 -10 -14q-4 -1 -57 -7q-38 -4 -64.5 -10t-56.5 -19.5t-45.5 -39t-15.5 -62.5t26 -58.5t64 -21.5q24 0 45 6t34 13t38 24q-3 -15 -3 -16q0 -5 2 -8.5t6.5 -5.5t8 -3.5 t10.5 -2t9.5 -0.5h9.5h8q42 0 48 25l45 194q3 15 3 31q0 81 -145 81zM2157 889h-55q-25 0 -33 -40q-10 -44 -36.5 -167t-42.5 -190v-5q0 -16 16 -18h1h57q10 0 18.5 6.5t10.5 16.5l83 374h-1l1 5q0 7 -5.5 12.5t-13.5 5.5zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048 q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" /> +<glyph unicode="" horiz-adv-x="2304" d="M1597 633q0 -69 -21 -106q-19 -35 -52 -35q-23 0 -41 9v224q29 30 57 30q57 0 57 -122zM2035 669h-110q6 98 56 98q51 0 54 -98zM476 534q0 59 -33 91.5t-101 57.5q-36 13 -52 24t-16 25q0 26 38 26q58 0 124 -33l18 112q-67 32 -149 32q-77 0 -123 -38q-48 -39 -48 -109 q0 -58 32.5 -90.5t99.5 -56.5q39 -14 54.5 -25.5t15.5 -27.5q0 -31 -48 -31q-29 0 -70 12.5t-72 30.5l-18 -113q72 -41 168 -41q81 0 129 37q51 41 51 117zM771 749l19 111h-96v135l-129 -21l-18 -114l-46 -8l-17 -103h62v-219q0 -84 44 -120q38 -30 111 -30q32 0 79 11v118 q-32 -7 -44 -7q-42 0 -42 50v197h77zM1087 724v139q-15 3 -28 3q-32 0 -55.5 -16t-33.5 -46l-10 56h-131v-471h150v306q26 31 82 31q16 0 26 -2zM1124 389h150v471h-150v-471zM1746 638q0 122 -45 179q-40 52 -111 52q-64 0 -117 -56l-8 47h-132v-645l150 25v151 q36 -11 68 -11q83 0 134 56q61 65 61 202zM1278 986q0 33 -23 56t-56 23t-56 -23t-23 -56t23 -56.5t56 -23.5t56 23.5t23 56.5zM2176 629q0 113 -48 176q-50 64 -144 64q-96 0 -151.5 -66t-55.5 -180q0 -128 63 -188q55 -55 161 -55q101 0 160 40l-16 103q-57 -31 -128 -31 q-43 0 -63 19q-23 19 -28 66h248q2 14 2 52zM2304 1280v-1280q0 -52 -38 -90t-90 -38h-2048q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h2048q52 0 90 -38t38 -90z" /> +<glyph unicode="" horiz-adv-x="2048" d="M1558 684q61 -356 298 -556q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5zM1024 -176q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5zM2026 1424q8 -10 7.5 -23.5t-10.5 -22.5 l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5 l418 363q10 8 23.5 7t21.5 -11z" /> +<glyph unicode="" horiz-adv-x="2048" d="M1040 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM503 315l877 760q-42 88 -132.5 146.5t-223.5 58.5q-93 0 -169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -384 -137 -645zM1856 128 q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5l149 129h757q-166 187 -227 459l111 97q61 -356 298 -556zM1942 1520l84 -96q8 -10 7.5 -23.5t-10.5 -22.5l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161 q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q124 -18 219 -82.5t148 -157.5l418 363q10 8 23.5 7t21.5 -11z" /> +<glyph unicode="" horiz-adv-x="1408" d="M512 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM768 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1024 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704 q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832q-66 0 -113 58.5t-47 141.5v952h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h309l70 167 q15 37 54 63t79 26h320q40 0 79 -26t54 -63l70 -167h309q14 0 23 -9t9 -23z" /> +<glyph unicode="" d="M1150 462v-109q0 -50 -36.5 -89t-94 -60.5t-118 -32.5t-117.5 -11q-205 0 -342.5 139t-137.5 346q0 203 136 339t339 136q34 0 75.5 -4.5t93 -18t92.5 -34t69 -56.5t28 -81v-109q0 -16 -16 -16h-118q-16 0 -16 16v70q0 43 -65.5 67.5t-137.5 24.5q-140 0 -228.5 -91.5 t-88.5 -237.5q0 -151 91.5 -249.5t233.5 -98.5q68 0 138 24t70 66v70q0 7 4.5 11.5t10.5 4.5h119q6 0 11 -4.5t5 -11.5zM768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" d="M972 761q0 108 -53.5 169t-147.5 61q-63 0 -124 -30.5t-110 -84.5t-79.5 -137t-30.5 -180q0 -112 53.5 -173t150.5 -61q96 0 176 66.5t122.5 166t42.5 203.5zM1536 640q0 -111 -37 -197t-98.5 -135t-131.5 -74.5t-145 -27.5q-6 0 -15.5 -0.5t-16.5 -0.5q-95 0 -142 53 q-28 33 -33 83q-52 -66 -131.5 -110t-173.5 -44q-161 0 -249.5 95.5t-88.5 269.5q0 157 66 290t179 210.5t246 77.5q87 0 155 -35.5t106 -99.5l2 19l11 56q1 6 5.5 12t9.5 6h118q5 0 13 -11q5 -5 3 -16l-120 -614q-5 -24 -5 -48q0 -39 12.5 -52t44.5 -13q28 1 57 5.5t73 24 t77 50t57 89.5t24 137q0 292 -174 466t-466 174q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51q228 0 405 144q11 9 24 8t21 -12l41 -49q8 -12 7 -24q-2 -13 -12 -22q-102 -83 -227.5 -128t-258.5 -45q-156 0 -298 61 t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q344 0 556 -212t212 -556z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1698 1442q94 -94 94 -226.5t-94 -225.5l-225 -223l104 -104q10 -10 10 -23t-10 -23l-210 -210q-10 -10 -23 -10t-23 10l-105 105l-603 -603q-37 -37 -90 -37h-203l-256 -128l-64 64l128 256v203q0 53 37 90l603 603l-105 105q-10 10 -10 23t10 23l210 210q10 10 23 10 t23 -10l104 -104l223 225q93 94 225.5 94t226.5 -94zM512 64l576 576l-192 192l-576 -576v-192h192z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1615 1536q70 0 122.5 -46.5t52.5 -116.5q0 -63 -45 -151q-332 -629 -465 -752q-97 -91 -218 -91q-126 0 -216.5 92.5t-90.5 219.5q0 128 92 212l638 579q59 54 130 54zM706 502q39 -76 106.5 -130t150.5 -76l1 -71q4 -213 -129.5 -347t-348.5 -134q-123 0 -218 46.5 t-152.5 127.5t-86.5 183t-29 220q7 -5 41 -30t62 -44.5t59 -36.5t46 -17q41 0 55 37q25 66 57.5 112.5t69.5 76t88 47.5t103 25.5t125 10.5z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1792 128v-384h-1792v384q45 0 85 14t59 27.5t47 37.5q30 27 51.5 38t56.5 11t55.5 -11t52.5 -38q29 -25 47 -38t58 -27t86 -14q45 0 85 14.5t58 27t48 37.5q21 19 32.5 27t31 15t43.5 7q35 0 56.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14t85 14t59 27.5t47 37.5 q30 27 51.5 38t56.5 11q34 0 55.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14zM1792 448v-192q-35 0 -55.5 11t-52.5 38q-29 25 -47 38t-58 27t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-22 -19 -33 -27t-31 -15t-44 -7q-35 0 -56.5 11t-51.5 38q-29 25 -47 38t-58 27 t-86 14q-45 0 -85 -14.5t-58 -27t-48 -37.5q-21 -19 -32.5 -27t-31 -15t-43.5 -7q-35 0 -56.5 11t-51.5 38q-28 24 -47 37.5t-59 27.5t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-30 -27 -51.5 -38t-56.5 -11v192q0 80 56 136t136 56h64v448h256v-448h256v448h256v-448h256v448 h256v-448h64q80 0 136 -56t56 -136zM512 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1024 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51 t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150zM1536 1312q0 -77 -36 -118.5t-92 -41.5q-53 0 -90.5 37.5t-37.5 90.5q0 29 9.5 51t23.5 34t31 28t31 31.5t23.5 44.5t9.5 67q38 0 83 -74t45 -150z" /> +<glyph unicode="" horiz-adv-x="2048" d="M2048 0v-128h-2048v1536h128v-1408h1920zM1664 1024l256 -896h-1664v576l448 576l576 -576z" /> +<glyph unicode="" horiz-adv-x="1792" d="M768 646l546 -546q-106 -108 -247.5 -168t-298.5 -60q-209 0 -385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103v-762zM955 640h773q0 -157 -60 -298.5t-168 -247.5zM1664 768h-768v768q209 0 385.5 -103t279.5 -279.5t103 -385.5z" /> +<glyph unicode="" horiz-adv-x="2048" d="M2048 0v-128h-2048v1536h128v-1408h1920zM1920 1248v-435q0 -21 -19.5 -29.5t-35.5 7.5l-121 121l-633 -633q-10 -10 -23 -10t-23 10l-233 233l-416 -416l-192 192l585 585q10 10 23 10t23 -10l233 -233l464 464l-121 121q-16 16 -7.5 35.5t29.5 19.5h435q14 0 23 -9 t9 -23z" /> +<glyph unicode="" horiz-adv-x="1792" d="M1292 832q0 -6 10 -41q10 -29 25 -49.5t41 -34t44 -20t55 -16.5q325 -91 325 -332q0 -146 -105.5 -242.5t-254.5 -96.5q-59 0 -111.5 18.5t-91.5 45.5t-77 74.5t-63 87.5t-53.5 103.5t-43.5 103t-39.5 106.5t-35.5 95q-32 81 -61.5 133.5t-73.5 96.5t-104 64t-142 20 q-96 0 -183 -55.5t-138 -144.5t-51 -185q0 -160 106.5 -279.5t263.5 -119.5q177 0 258 95q56 63 83 116l84 -152q-15 -34 -44 -70l1 -1q-131 -152 -388 -152q-147 0 -269.5 79t-190.5 207.5t-68 274.5q0 105 43.5 206t116 176.5t172 121.5t204.5 46q87 0 159 -19t123.5 -50 t95 -80t72.5 -99t58.5 -117t50.5 -124.5t50 -130.5t55 -127q96 -200 233 -200q81 0 138.5 48.5t57.5 128.5q0 42 -19 72t-50.5 46t-72.5 31.5t-84.5 27t-87.5 34t-81 52t-65 82t-39 122.5q-3 16 -3 33q0 110 87.5 192t198.5 78q78 -3 120.5 -14.5t90.5 -53.5h-1 q12 -11 23 -24.5t26 -36t19 -27.5l-129 -99q-26 49 -54 70v1q-23 21 -97 21q-49 0 -84 -33t-35 -83z" /> +<glyph unicode="" d="M1432 484q0 173 -234 239q-35 10 -53 16.5t-38 25t-29 46.5q0 2 -2 8.5t-3 12t-1 7.5q0 36 24.5 59.5t60.5 23.5q54 0 71 -15h-1q20 -15 39 -51l93 71q-39 54 -49 64q-33 29 -67.5 39t-85.5 10q-80 0 -142 -57.5t-62 -137.5q0 -7 2 -23q16 -96 64.5 -140t148.5 -73 q29 -8 49 -15.5t45 -21.5t38.5 -34.5t13.5 -46.5v-5q1 -58 -40.5 -93t-100.5 -35q-97 0 -167 144q-23 47 -51.5 121.5t-48 125.5t-54 110.5t-74 95.5t-103.5 60.5t-147 24.5q-101 0 -192 -56t-144 -148t-50 -192v-1q4 -108 50.5 -199t133.5 -147.5t196 -56.5q186 0 279 110 q20 27 31 51l-60 109q-42 -80 -99 -116t-146 -36q-115 0 -191 87t-76 204q0 105 82 189t186 84q112 0 170 -53.5t104 -172.5q8 -21 25.5 -68.5t28.5 -76.5t31.5 -74.5t38.5 -74t45.5 -62.5t55.5 -53.5t66 -33t80 -13.5q107 0 183 69.5t76 174.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" /> +<glyph unicode="" horiz-adv-x="2048" d="M1152 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1920 640q0 104 -40.5 198.5 t-109.5 163.5t-163.5 109.5t-198.5 40.5h-386q119 -90 188.5 -224t69.5 -288t-69.5 -288t-188.5 -224h386q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM2048 640q0 -130 -51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5 t-136.5 204t-51 248.5t51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5z" /> +<glyph unicode="" horiz-adv-x="2048" d="M0 640q0 130 51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5t-51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5t-136.5 204t-51 248.5zM1408 128q104 0 198.5 40.5t163.5 109.5 t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5z" /> +<glyph unicode="" horiz-adv-x="2304" d="M762 384h-314q-40 0 -57.5 35t6.5 67l188 251q-65 31 -137 31q-132 0 -226 -94t-94 -226t94 -226t226 -94q115 0 203 72.5t111 183.5zM576 512h186q-18 85 -75 148zM1056 512l288 384h-480l-99 -132q105 -103 126 -252h165zM2176 448q0 132 -94 226t-226 94 q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94t226 94t94 226zM2304 448q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 97 39.5 183.5t109.5 149.5l-65 98l-353 -469 q-18 -26 -51 -26h-197q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q114 0 215 -55l137 183h-224q-26 0 -45 19t-19 45t19 45t45 19h384v-128h435l-85 128h-222q-26 0 -45 19t-19 45t19 45t45 19h256q33 0 53 -28l267 -400 q91 44 192 44q185 0 316.5 -131.5t131.5 -316.5z" /> +<glyph unicode="" d="M384 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1362 716l-72 384q-5 23 -22.5 37.5t-40.5 14.5 h-918q-23 0 -40.5 -14.5t-22.5 -37.5l-72 -384q-5 -30 14 -53t49 -23h1062q30 0 49 23t14 53zM1136 1328q0 20 -14 34t-34 14h-640q-20 0 -34 -14t-14 -34t14 -34t34 -14h640q20 0 34 14t14 34zM1536 603v-603h-128v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5v128h-768v-128q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5v128h-128v603q0 112 25 223l103 454q9 78 97.5 137t230 89t312.5 30t312.5 -30t230 -89t97.5 -137l105 -454q23 -102 23 -223z" /> +<glyph unicode="" horiz-adv-x="2048" d="M1463 704q0 -35 -25 -60.5t-61 -25.5h-702q-36 0 -61 25.5t-25 60.5t25 60.5t61 25.5h702q36 0 61 -25.5t25 -60.5zM1677 704q0 86 -23 170h-982q-36 0 -61 25t-25 60q0 36 25 61t61 25h908q-88 143 -235 227t-320 84q-177 0 -327.5 -87.5t-238 -237.5t-87.5 -327 q0 -86 23 -170h982q36 0 61 -25t25 -60q0 -36 -25 -61t-61 -25h-908q88 -143 235.5 -227t320.5 -84q132 0 253 51.5t208 139t139 208t52 253.5zM2048 959q0 -35 -25 -60t-61 -25h-131q17 -85 17 -170q0 -167 -65.5 -319.5t-175.5 -263t-262.5 -176t-319.5 -65.5 q-246 0 -448.5 133t-301.5 350h-189q-36 0 -61 25t-25 61q0 35 25 60t61 25h132q-17 85 -17 170q0 167 65.5 319.5t175.5 263t262.5 176t320.5 65.5q245 0 447.5 -133t301.5 -350h188q36 0 61 -25t25 -61z" /> +<glyph unicode="" horiz-adv-x="1280" d="M953 1158l-114 -328l117 -21q165 451 165 518q0 56 -38 56q-57 0 -130 -225zM654 471l33 -88q37 42 71 67l-33 5.5t-38.5 7t-32.5 8.5zM362 1367q0 -98 159 -521q18 10 49 10q15 0 75 -5l-121 351q-75 220 -123 220q-19 0 -29 -17.5t-10 -37.5zM283 608q0 -36 51.5 -119 t117.5 -153t100 -70q14 0 25.5 13t11.5 27q0 24 -32 102q-13 32 -32 72t-47.5 89t-61.5 81t-62 32q-20 0 -45.5 -27t-25.5 -47zM125 273q0 -41 25 -104q59 -145 183.5 -227t281.5 -82q227 0 382 170q152 169 152 427q0 43 -1 67t-11.5 62t-30.5 56q-56 49 -211.5 75.5 t-270.5 26.5q-37 0 -49 -11q-12 -5 -12 -35q0 -34 21.5 -60t55.5 -40t77.5 -23.5t87.5 -11.5t85 -4t70 0h23q24 0 40 -19q15 -19 19 -55q-28 -28 -96 -54q-61 -22 -93 -46q-64 -46 -108.5 -114t-44.5 -137q0 -31 18.5 -88.5t18.5 -87.5l-3 -12q-4 -12 -4 -14 q-137 10 -146 216q-8 -2 -41 -2q2 -7 2 -21q0 -53 -40.5 -89.5t-94.5 -36.5q-82 0 -166.5 78t-84.5 159q0 34 33 67q52 -64 60 -76q77 -104 133 -104q12 0 26.5 8.5t14.5 20.5q0 34 -87.5 145t-116.5 111q-43 0 -70 -44.5t-27 -90.5zM11 264q0 101 42.5 163t136.5 88 q-28 74 -28 104q0 62 61 123t122 61q29 0 70 -15q-163 462 -163 567q0 80 41 130.5t119 50.5q131 0 325 -581q6 -17 8 -23q6 16 29 79.5t43.5 118.5t54 127.5t64.5 123t70.5 86.5t76.5 36q71 0 112 -49t41 -122q0 -108 -159 -550q61 -15 100.5 -46t58.5 -78t26 -93.5 t7 -110.5q0 -150 -47 -280t-132 -225t-211 -150t-278 -55q-111 0 -223 42q-149 57 -258 191.5t-109 286.5z" /> +<glyph unicode="" horiz-adv-x="2048" d="M785 528h207q-14 -158 -98.5 -248.5t-214.5 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-203q-5 64 -35.5 99t-81.5 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t40 -51.5t66 -18q95 0 109 139zM1497 528h206 q-14 -158 -98 -248.5t-214 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-204q-4 64 -35 99t-81 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t39.5 -51.5t65.5 -18q49 0 76.5 38t33.5 101zM1856 647q0 207 -15.5 307 t-60.5 161q-6 8 -13.5 14t-21.5 15t-16 11q-86 63 -697 63q-625 0 -710 -63q-5 -4 -17.5 -11.5t-21 -14t-14.5 -14.5q-45 -60 -60 -159.5t-15 -308.5q0 -208 15 -307.5t60 -160.5q6 -8 15 -15t20.5 -14t17.5 -12q44 -33 239.5 -49t470.5 -16q610 0 697 65q5 4 17 11t20.5 14 t13.5 16q46 60 61 159t15 309zM2048 1408v-1536h-2048v1536h2048z" /> +<glyph unicode="" d="M992 912v-496q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v496q0 112 -80 192t-192 80h-272v-1152q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v1344q0 14 9 23t23 9h464q135 0 249 -66.5t180.5 -180.5t66.5 -249zM1376 1376v-880q0 -135 -66.5 -249t-180.5 -180.5 t-249 -66.5h-464q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-768h272q112 0 192 80t80 192v880q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" /> +<glyph unicode="" d="M1311 694v-114q0 -24 -13.5 -38t-37.5 -14h-202q-24 0 -38 14t-14 38v114q0 24 14 38t38 14h202q24 0 37.5 -14t13.5 -38zM821 464v250q0 53 -32.5 85.5t-85.5 32.5h-133q-68 0 -96 -52q-28 52 -96 52h-130q-53 0 -85.5 -32.5t-32.5 -85.5v-250q0 -22 21 -22h55 q22 0 22 22v230q0 24 13.5 38t38.5 14h94q24 0 38 -14t14 -38v-230q0 -22 21 -22h54q22 0 22 22v230q0 24 14 38t38 14h97q24 0 37.5 -14t13.5 -38v-230q0 -22 22 -22h55q21 0 21 22zM1410 560v154q0 53 -33 85.5t-86 32.5h-264q-53 0 -86 -32.5t-33 -85.5v-410 q0 -21 22 -21h55q21 0 21 21v180q31 -42 94 -42h191q53 0 86 32.5t33 85.5zM1536 1176v-1072q0 -96 -68 -164t-164 -68h-1072q-96 0 -164 68t-68 164v1072q0 96 68 164t164 68h1072q96 0 164 -68t68 -164z" /> +<glyph unicode="" horiz-adv-x="1792" /> +<glyph unicode="" horiz-adv-x="1792" /> +<glyph unicode="" horiz-adv-x="1792" /> +</font> +</defs></svg>
\ No newline at end of file diff --git a/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.ttf b/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.ttf Binary files differnew file mode 100755 index 00000000..96a3639c --- /dev/null +++ b/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.ttf diff --git a/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.woff b/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.woff Binary files differnew file mode 100755 index 00000000..628b6a52 --- /dev/null +++ b/dgbuilder/public/font-awesome/fonts/fontawesome-webfont.woff diff --git a/dgbuilder/public/grip.png b/dgbuilder/public/grip.png Binary files differnew file mode 100644 index 00000000..c01edb56 --- /dev/null +++ b/dgbuilder/public/grip.png diff --git a/dgbuilder/public/icons/alert.png b/dgbuilder/public/icons/alert.png Binary files differnew file mode 100644 index 00000000..a8631110 --- /dev/null +++ b/dgbuilder/public/icons/alert.png diff --git a/dgbuilder/public/icons/arduino.png b/dgbuilder/public/icons/arduino.png Binary files differnew file mode 100644 index 00000000..43e7d4be --- /dev/null +++ b/dgbuilder/public/icons/arduino.png diff --git a/dgbuilder/public/icons/arrow-in.png b/dgbuilder/public/icons/arrow-in.png Binary files differnew file mode 100644 index 00000000..e38f3914 --- /dev/null +++ b/dgbuilder/public/icons/arrow-in.png diff --git a/dgbuilder/public/icons/bridge-dash.png b/dgbuilder/public/icons/bridge-dash.png Binary files differnew file mode 100644 index 00000000..beaf8e65 --- /dev/null +++ b/dgbuilder/public/icons/bridge-dash.png diff --git a/dgbuilder/public/icons/bridge.png b/dgbuilder/public/icons/bridge.png Binary files differnew file mode 100644 index 00000000..2011292d --- /dev/null +++ b/dgbuilder/public/icons/bridge.png diff --git a/dgbuilder/public/icons/comment.png b/dgbuilder/public/icons/comment.png Binary files differnew file mode 100644 index 00000000..d64d12a7 --- /dev/null +++ b/dgbuilder/public/icons/comment.png diff --git a/dgbuilder/public/icons/db.png b/dgbuilder/public/icons/db.png Binary files differnew file mode 100644 index 00000000..5e74f748 --- /dev/null +++ b/dgbuilder/public/icons/db.png diff --git a/dgbuilder/public/icons/debug.png b/dgbuilder/public/icons/debug.png Binary files differnew file mode 100644 index 00000000..05691562 --- /dev/null +++ b/dgbuilder/public/icons/debug.png diff --git a/dgbuilder/public/icons/envelope.png b/dgbuilder/public/icons/envelope.png Binary files differnew file mode 100644 index 00000000..fb0d36b9 --- /dev/null +++ b/dgbuilder/public/icons/envelope.png diff --git a/dgbuilder/public/icons/feed.png b/dgbuilder/public/icons/feed.png Binary files differnew file mode 100644 index 00000000..9f2671c5 --- /dev/null +++ b/dgbuilder/public/icons/feed.png diff --git a/dgbuilder/public/icons/file.png b/dgbuilder/public/icons/file.png Binary files differnew file mode 100644 index 00000000..78ee09f7 --- /dev/null +++ b/dgbuilder/public/icons/file.png diff --git a/dgbuilder/public/icons/function.png b/dgbuilder/public/icons/function.png Binary files differnew file mode 100644 index 00000000..90950500 --- /dev/null +++ b/dgbuilder/public/icons/function.png diff --git a/dgbuilder/public/icons/hash.png b/dgbuilder/public/icons/hash.png Binary files differnew file mode 100644 index 00000000..e68e45df --- /dev/null +++ b/dgbuilder/public/icons/hash.png diff --git a/dgbuilder/public/icons/inject.png b/dgbuilder/public/icons/inject.png Binary files differnew file mode 100644 index 00000000..dbf4711a --- /dev/null +++ b/dgbuilder/public/icons/inject.png diff --git a/dgbuilder/public/icons/leveldb.png b/dgbuilder/public/icons/leveldb.png Binary files differnew file mode 100644 index 00000000..55760c7d --- /dev/null +++ b/dgbuilder/public/icons/leveldb.png diff --git a/dgbuilder/public/icons/light.png b/dgbuilder/public/icons/light.png Binary files differnew file mode 100644 index 00000000..ce21542b --- /dev/null +++ b/dgbuilder/public/icons/light.png diff --git a/dgbuilder/public/icons/mongodb.png b/dgbuilder/public/icons/mongodb.png Binary files differnew file mode 100644 index 00000000..3a1fc11b --- /dev/null +++ b/dgbuilder/public/icons/mongodb.png diff --git a/dgbuilder/public/icons/node-changed.png b/dgbuilder/public/icons/node-changed.png Binary files differnew file mode 100644 index 00000000..38a17944 --- /dev/null +++ b/dgbuilder/public/icons/node-changed.png diff --git a/dgbuilder/public/icons/node-error.png b/dgbuilder/public/icons/node-error.png Binary files differnew file mode 100644 index 00000000..c20c8e85 --- /dev/null +++ b/dgbuilder/public/icons/node-error.png diff --git a/dgbuilder/public/icons/range.png b/dgbuilder/public/icons/range.png Binary files differnew file mode 100644 index 00000000..2e7183ce --- /dev/null +++ b/dgbuilder/public/icons/range.png diff --git a/dgbuilder/public/icons/redis.png b/dgbuilder/public/icons/redis.png Binary files differnew file mode 100644 index 00000000..92e82fd2 --- /dev/null +++ b/dgbuilder/public/icons/redis.png diff --git a/dgbuilder/public/icons/rpi.png b/dgbuilder/public/icons/rpi.png Binary files differnew file mode 100644 index 00000000..162b99dc --- /dev/null +++ b/dgbuilder/public/icons/rpi.png diff --git a/dgbuilder/public/icons/serial.png b/dgbuilder/public/icons/serial.png Binary files differnew file mode 100644 index 00000000..f4bcedc3 --- /dev/null +++ b/dgbuilder/public/icons/serial.png diff --git a/dgbuilder/public/icons/swap.png b/dgbuilder/public/icons/swap.png Binary files differnew file mode 100644 index 00000000..e9e70efb --- /dev/null +++ b/dgbuilder/public/icons/swap.png diff --git a/dgbuilder/public/icons/switch.png b/dgbuilder/public/icons/switch.png Binary files differnew file mode 100644 index 00000000..4d172de6 --- /dev/null +++ b/dgbuilder/public/icons/switch.png diff --git a/dgbuilder/public/icons/template.png b/dgbuilder/public/icons/template.png Binary files differnew file mode 100644 index 00000000..1db6f273 --- /dev/null +++ b/dgbuilder/public/icons/template.png diff --git a/dgbuilder/public/icons/timer.png b/dgbuilder/public/icons/timer.png Binary files differnew file mode 100644 index 00000000..4f02f465 --- /dev/null +++ b/dgbuilder/public/icons/timer.png diff --git a/dgbuilder/public/icons/trigger.png b/dgbuilder/public/icons/trigger.png Binary files differnew file mode 100644 index 00000000..37b60f11 --- /dev/null +++ b/dgbuilder/public/icons/trigger.png diff --git a/dgbuilder/public/icons/twitter.png b/dgbuilder/public/icons/twitter.png Binary files differnew file mode 100644 index 00000000..d0605945 --- /dev/null +++ b/dgbuilder/public/icons/twitter.png diff --git a/dgbuilder/public/icons/watch.png b/dgbuilder/public/icons/watch.png Binary files differnew file mode 100644 index 00000000..a6c1b945 --- /dev/null +++ b/dgbuilder/public/icons/watch.png diff --git a/dgbuilder/public/icons/white-globe.png b/dgbuilder/public/icons/white-globe.png Binary files differnew file mode 100644 index 00000000..8a19079b --- /dev/null +++ b/dgbuilder/public/icons/white-globe.png diff --git a/dgbuilder/public/images/dgstart.png b/dgbuilder/public/images/dgstart.png Binary files differnew file mode 100644 index 00000000..58521afc --- /dev/null +++ b/dgbuilder/public/images/dgstart.png diff --git a/dgbuilder/public/images/page-loading.gif b/dgbuilder/public/images/page-loading.gif Binary files differnew file mode 100644 index 00000000..c25b4367 --- /dev/null +++ b/dgbuilder/public/images/page-loading.gif diff --git a/dgbuilder/public/index.html b/dgbuilder/public/index.html new file mode 100644 index 00000000..07090db8 --- /dev/null +++ b/dgbuilder/public/index.html @@ -0,0 +1,332 @@ +<!DOCTYPE html> +<html> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/> +<meta name="apple-mobile-web-app-capable" content="yes"> +<meta name="mobile-web-app-capable" content="yes"> + +<!-- + Copyright 2013, 2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<head> +<!--<title>Node-RED</title>--> +<title>Directed Graph Builder</title> +<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen"> +<link href="jquery/css/smoothness/jquery-ui-1.10.3.custom.min.css" rel="stylesheet" media="screen"> +<link rel="stylesheet" type="text/css" href="orion/built-editor.css"/> +<link rel="stylesheet" type="text/css" href="font-awesome/css/font-awesome.min.css"/> +<link rel="stylesheet" href="style.css"> +</head> +<body spellcheck="false"> +<div id="header"> + <!--<span class="logo"><img src="node-red.png"> <span>Node-RED</span></span>--> + <!--<span class="logo"><img src="node-red.png"> <span>Directed Graph Builder</span></span>--> + <span class="logo"><img src="node-red.png"> <span>Directed Graph Builder</span><span id='processingStatusId' ></span></span> + <div class="pull-right"> + <span id='releaseId' ></span> + <a id="btn-deploy" class="button action-deploy disabled" href="#"><i id="btn-icn-deploy" class="fa fa-download"></i>Save</a> + <a id="btn-sidemenu" class="button dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-bars"></i></a> + </div> +</div> +<div id="main-container" class="sidebar-closed"> + <div id="palette"> + <img src="spin.svg" class="palette-spinner"/> + <div id="palette-container" class="palette-scroll"> + </div> + <div id="palette-search"> + <i class="fa fa-search"></i><input id="palette-search-input" type="text" placeholder="filter"><a href="#" id="palette-search-clear"><i class="fa fa-times"></i></a></input> + </div> + </div><!-- /palette --> + + <div id="workspace"> + <ul id="workspace-tabs"></ul> + <div id="workspace-add-tab"><a id="btn-workspace-add-tab" href="#"><i class="fa fa-plus"></i></a></div> + <div id="chart"></div> + <div id="workspace-toolbar"> + <div class="btn-group"> + <a class="btn btn-small" href="#"><i class="fa fa-search-minus"></i></a> + <a class="btn btn-small" href="#"><i class="fa fa-dot-circle-o"></i></a> + <a class="btn btn-small" href="#"><i class="fa fa-search-plus"></i></a> + </div> + </div> + </div> + + <div id="chart-zoom-controls"> + <div class="btn-group"> + <a class="btn btn-mini" id="btn-zoom-out" href="#"><i class="fa fa-search-minus"></i></a> + <a class="btn btn-mini" id="btn-zoom-zero" href="#"><i class="fa fa-dot-circle-o"></i></a> + <a class="btn btn-mini" id="btn-zoom-in" href="#"><i class="fa fa-search-plus"></i></a> + </div> + </div> + + <div id="sidebar"> + <ul id="sidebar-tabs"></ul> + <div id="sidebar-content"></div> + </div> + + <div id="sidebar-separator"></div> + +</div> + +<div id="notifications"></div> +<div id="dropTarget"><div>Drop the flow here<br/><i class="fa fa-download"></i></div></div> + +<div id="dialog" class="hide"><form id="dialog-form" class="form-horizontal"></form></div> +<div id="node-config-dialog" class="hide"><form id="dialog-config-form" class="form-horizontal"></form><div class="form-tips" id="node-config-dialog-user-count"></div></div> + +<div id="node-dialog-confirm-deploy" class="hide"> + <form class="form-horizontal"> + <div id="node-dialog-confirm-deploy-config" style="text-align: center; padding-top: 30px;"> + Some of the nodes are not properly configured. Are you sure you want to deploy? + </div> + <div id="node-dialog-confirm-deploy-unknown" style="text-align: center; padding-top: 10px;"> + The workspace contains some unknown node types: + <ul style="width: 300px; margin: auto; text-align: left;" id="node-dialog-confirm-deploy-unknown-list"></ul> + Are you sure you want to deploy? + </div> + </form> +</div> + +<div id="node-help" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="node-help-label" aria-hidden="true"> + <div class="modal-header"> + <h5 id="node-help-label">Keyboard Shortcuts <!-- <span style="float: right;"><a href="http://node-red.github.io/docs" target="_blank">Open help in new window »</a></span> --> +</h5> + </div> + <div class="modal-body"> + <table> + <tr> + <td><span class="help-key">?</span></td><td>Help</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">a</span></td><td>Select all nodes</td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">Space</span></td><td>Toggle sidebar</td> + <td><span class="help-key">Shift</span> <span class="help-key">Click</span></td><td>Select all connected nodes</td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">z</span></td><td>Undo</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">Click</span></td><td>Add/remove node from selection</td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">m</span></td><td>Toggle Node Palette</td> + <td><span class="help-key">Delete</span></td><td>Delete selected nodes or link</td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">x</span></td><td>Cut selected nodes</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">b</span></td><td>Find Node</td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">c</span></td><td>Copy selected nodes</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">v</span></td><td>Paste nodes</td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">i</span></td><td>Import nodes</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">e</span></td><td>Export selected nodes</td> + </tr> + <tr> + <td colspan="2"></td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">+</span></td><td>Zoom in</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">-</span></td><td>Zoom out</td> + </tr> + </table> + </div> + <div class="modal-footer"> + <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button> + </div> +</div> + +<div id="node-dialog-library-save-confirm" class="hide"> + <form class="form-horizontal"> + <div style="text-align: center; padding-top: 30px;"> + A <span id="node-dialog-library-save-type"></span> called <span id="node-dialog-library-save-name"></span> already exists. Overwrite? + </div> + </form> +</div> + +<div id="node-dialog-library-save" class="hide"> + <form class="form-horizontal"> + <div class="form-row"> + <label for="node-dialog-library-save-folder"><i class="fa fa-folder-open"></i> Folder</label> + <input type="text" id="node-dialog-library-save-folder" placeholder="Folder"> + </div> + <div class="form-row"> + <label for="node-dialog-library-save-filename"><i class="fa fa-file"></i> Filename</label> + <input type="text" id="node-dialog-library-save-filename" placeholder="Filename"> + </div> + </form> +</div> + +<div id="node-dialog-library-lookup" class="hide"> + <form class="form-horizontal"> + <div class="form-row"> + <ul id="node-dialog-library-breadcrumbs" class="breadcrumb"> + <li class="active"><a href="#">Library</a></li> + </ul> + </div> + <div class="form-row"> + <div style="vertical-align: top; display: inline-block; height: 100%; width: 30%; padding-right: 20px;"> + <div id="node-select-library" style="border: 1px solid #999; width: 100%; height: 100%; overflow:scroll;"><ul></ul></div> + </div> + <div style="vertical-align: top; display: inline-block;width: 65%; height: 100%;"> + <div style="height: 100%; width: 95%;" class="node-text-editor" id="node-select-library-text" ></div> + </div> + </div> + </form> +</div> +<div id="node-dialog-rename-workspace" class="hide"> + <form class="form-horizontal"> + <div class="form-row"> + <label for="node-input-workspace-name" ><i class="fa fa-tag"></i> Name:</label> + <input type="text" id="node-input-workspace-name"> + </div> + </form> +</div> +<div id="node-dialog-delete-workspace" class="hide"> + <form class="form-horizontal"> + <div style="text-align: center; padding-top: 30px;"> + Are you sure you want to delete '<span id="node-dialog-delete-workspace-name"></span>'? + </div> + </form> +</div> +<div id="xmldialog" class="hide"></div> +<div id="filter-tabs-dialog" class="hide"></div> +<div id="loop-detection-dialog" class="hide"></div> +<div id="dgnumber-find-dialog" class="hide"></div> +<div id="search-text-dialog" class="hide"></div> +<div id="dgstart-generate-xml-dialog" class="hide"></div> +<div id="update-password-dialog" class="hide"></div> +<div id="update-configuration-dialog" class="hide"></div> +<div id="dgflow-browser-dialog" class="hide"></div> +<div id="codecloud-browser-dialog" class="hide"></div> +<div id="gitlocal-browser-dialog" class="hide"></div> +<div id="gitcommands-dialog" class="hide"></div> +<div id="upload-xml-status-dialog" class="hide"></div> +<div id="flow-design-err-dialog" class="hide"></div> +<div id="sli-values-dialog" class="hide"></div> +<div id="comments-dialog" class="hide"></div> +<div id="show-errors-dialog" class="hide"></div> +<div id="yang-upload-dialog" class="hide"></div> +<div id="yang-modules-browser-dialog" class="hide"></div> +<div id="list-yang-browser-dialog" class="hide"></div> +<div id="request-input-dialog" class="hide"></div> +<script type="text/x-red" data-template-name="export-clipboard-dialog"> + <div class="form-row"> + <label for="node-input-export" style="display: block; width:100%;"><i class="fa fa-clipboard"></i> Nodes:</label> + <textarea readonly style="font-family: monospace; font-size: 12px; background:rgb(226, 229, 255); padding-left: 0.5em;" class="input-block-level" id="node-input-export" rows="5"></textarea> + </div> + <div class="form-tips"> + Select the text above and copy to the clipboard with Ctrl-A Ctrl-C. + </div> +</script> +<script type="text/x-red" data-template-name="export-library-dialog"> + <div class="form-row"> + <label for="node-input-filename" ><i class="fa fa-file"></i> Filename:</label> + <input type="text" id="node-input-filename" placeholder="Filename"> + </div> +</script> +<script type="text/x-red" data-template-name="import-dialog"> + <div class="form-row"> + <label for="node-input-import"><i class="fa fa-clipboard"></i> Nodes:</label> + <textarea style="font-family: monospace; font-size: 12px; background:rgb(226, 229, 255); padding-left: 0.5em;" class="input-block-level" id="node-input-import" rows="5" placeholder="Paste nodes here"></textarea> + </div> +</script> + +<script src="jquery/js/jquery-1.11.1.min.js"></script> +<script src="bootstrap/js/bootstrap.min.js"></script> +<script src="jquery/js/jquery-ui-1.10.3.custom.min.js"></script> +<script src="jquery/js/jquery.ui.touch-punch.min.js"></script> +<script src="orion/built-editor.min.js"></script> +<script src="d3.v3.min.js"></script> + +<script src="red/main.js"></script> +<script src="red/comms.js"></script> +<script src="red/ui/state.js"></script> +<script src="red/nodes.js"></script> +<script src="red/history.js"></script> +<script src="red/validators.js"></script> +<script src="red/ui/menu.js"></script> +<script src="red/ui/keyboard.js"></script> +<script src="red/ui/tabs.js"></script> +<script src="red/ui/view.js"></script> +<script src="red/ui/sidebar.js"></script> +<script src="red/ui/palette.js"></script> +<script src="red/ui/tab-info.js"></script> +<script src="red/ui/tab-config.js"></script> +<script src="red/ui/editor.js"></script> +<script src="red/ui/library.js"></script> +<script src="red/ui/notifications.js"></script> +<script src="red/ui/touch/radialMenu.js"></script> + + +<script lang="javascript"> + $(function() { + RED.keyboard.add(/* M */ 77,{ctrl:true},function(){RED.menu.setSelected("btn-node-panel",!RED.menu.isSelected("btn-node-panel"));d3.event.preventDefault();}); + RED.menu.setSelected("btn-node-panel",true); + }); + +var sliValuesObj = {}; +var rpcValues = {}; +var reqInputValues = {}; +$(function(){ + $.get("/initialLoadSelectedModules") + .done(function( data ) { + //console.dir(data); + if(data != undefined && data != null){ + for(var i=0;i<data.sliValuesObj.length;i++){ + var moduleName = data.sliValuesObj[i].moduleName; + //console.dir(data.sliValuesObj[i][ moduleName + '_PROPS']); + //console.dir(data.sliValuesObj[i][moduleName + '_RPCS']); + sliValuesObj[moduleName] = data.sliValuesObj[i][moduleName + '_PROPS']; + rpcValues[moduleName] = data.sliValuesObj[i][ moduleName +'_RPCS']; + for(var k=0;rpcValues[moduleName] != undefined && k<rpcValues[moduleName].length;k++){ + var rpcName = rpcValues[moduleName][k]; + reqInputValues[moduleName + "_" + rpcName] = data.sliValuesObj[i][rpcName +"-input"]; + } + } + } + + }) + .fail(function(err) { + console.dir(err); + }) + .always(function() { + }); +}); + +</script> +<script> + $(document).ready(function() { + +var urlPath="/getRelease"; + $.get(urlPath) + .done(function( data ) { + //console.dir(data); + if(data != undefined && data != null){ + var release = data.release; + //document.title +=" " + release; + $("#releaseId").text("Workspace:" + release); + $("#releaseId").css({color:'lightgrey'}); + + } + }) + .fail(function(err) { + }) + .always(function() { + }); +}); +</script> +</body> +</html> diff --git a/dgbuilder/public/index.html.orig b/dgbuilder/public/index.html.orig new file mode 100644 index 00000000..8141b8a1 --- /dev/null +++ b/dgbuilder/public/index.html.orig @@ -0,0 +1,247 @@ +<!DOCTYPE html> +<html> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/> +<meta name="apple-mobile-web-app-capable" content="yes"> +<meta name="mobile-web-app-capable" content="yes"> + +<!-- + Copyright 2013, 2014 IBM Corp. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +--> +<head> +<title>Node-RED</title> +<link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen"> +<link href="jquery/css/smoothness/jquery-ui-1.10.3.custom.min.css" rel="stylesheet" media="screen"> +<link rel="stylesheet" type="text/css" href="orion/built-editor.css"/> +<link rel="stylesheet" type="text/css" href="font-awesome/css/font-awesome.min.css"/> +<link rel="stylesheet" href="style.css"> +</head> +<body spellcheck="false"> +<div id="header"> + <span class="logo"><img src="node-red.png"> <span>Node-RED</span></span> + <div class="pull-right"> + <a id="btn-deploy" class="button action-deploy disabled" href="#"><i id="btn-icn-deploy" class="fa fa-download"></i> Deploy</a> + <a id="btn-sidemenu" class="button dropdown-toggle" data-toggle="dropdown" href="#"><i class="fa fa-bars"></i></a> + </div> +</div> +<div id="main-container" class="sidebar-closed"> + <div id="palette"> + <img src="spin.svg" class="palette-spinner"/> + <div id="palette-container" class="palette-scroll"> + </div> + <div id="palette-search"> + <i class="fa fa-search"></i><input id="palette-search-input" type="text" placeholder="filter"><a href="#" id="palette-search-clear"><i class="fa fa-times"></i></a></input> + </div> + </div><!-- /palette --> + + <div id="workspace"> + <ul id="workspace-tabs"></ul> + <div id="workspace-add-tab"><a id="btn-workspace-add-tab" href="#"><i class="fa fa-plus"></i></a></div> + <div id="chart"></div> + <div id="workspace-toolbar"> + <div class="btn-group"> + <a class="btn btn-small" href="#"><i class="fa fa-search-minus"></i></a> + <a class="btn btn-small" href="#"><i class="fa fa-dot-circle-o"></i></a> + <a class="btn btn-small" href="#"><i class="fa fa-search-plus"></i></a> + </div> + </div> + </div> + + <div id="chart-zoom-controls"> + <div class="btn-group"> + <a class="btn btn-mini" id="btn-zoom-out" href="#"><i class="fa fa-search-minus"></i></a> + <a class="btn btn-mini" id="btn-zoom-zero" href="#"><i class="fa fa-dot-circle-o"></i></a> + <a class="btn btn-mini" id="btn-zoom-in" href="#"><i class="fa fa-search-plus"></i></a> + </div> + </div> + + <div id="sidebar"> + <ul id="sidebar-tabs"></ul> + <div id="sidebar-content"></div> + </div> + + <div id="sidebar-separator"></div> + +</div> + +<div id="notifications"></div> +<div id="dropTarget"><div>Drop the flow here<br/><i class="fa fa-download"></i></div></div> + +<div id="dialog" class="hide"><form id="dialog-form" class="form-horizontal"></form></div> +<div id="node-config-dialog" class="hide"><form id="dialog-config-form" class="form-horizontal"></form><div class="form-tips" id="node-config-dialog-user-count"></div></div> + +<div id="node-dialog-confirm-deploy" class="hide"> + <form class="form-horizontal"> + <div id="node-dialog-confirm-deploy-config" style="text-align: center; padding-top: 30px;"> + Some of the nodes are not properly configured. Are you sure you want to deploy? + </div> + <div id="node-dialog-confirm-deploy-unknown" style="text-align: center; padding-top: 10px;"> + The workspace contains some unknown node types: + <ul style="width: 300px; margin: auto; text-align: left;" id="node-dialog-confirm-deploy-unknown-list"></ul> + Are you sure you want to deploy? + </div> + </form> +</div> + +<div id="node-help" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="node-help-label" aria-hidden="true"> + <div class="modal-header"> + <h5 id="node-help-label">Keyboard Shortcuts <span style="float: right;"><a href="http://node-red.github.io/docs" target="_blank">Open help in new window »</a></span></h5> + </div> + <div class="modal-body"> + <table> + <tr> + <td><span class="help-key">?</span></td><td>Help</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">a</span></td><td>Select all nodes</td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">Space</span></td><td>Toggle sidebar</td> + <td><span class="help-key">Shift</span> <span class="help-key">Click</span></td><td>Select all connected nodes</td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">z</span></td><td>Undo</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">Click</span></td><td>Add/remove node from selection</td> + </tr> + <tr> + <td></td><td></td> + <td><span class="help-key">Delete</span></td><td>Delete selected nodes or link</td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">x</span></td><td>Cut selected nodes</td> + <td></td><td></td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">c</span></td><td>Copy selected nodes</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">v</span></td><td>Paste nodes</td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">i</span></td><td>Import nodes</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">e</span></td><td>Export selected nodes</td> + </tr> + <tr> + <td colspan="2"></td> + </tr> + <tr> + <td><span class="help-key">Ctrl</span> <span class="help-key">+</span></td><td>Zoom in</td> + <td><span class="help-key">Ctrl</span> <span class="help-key">-</span></td><td>Zoom out</td> + </tr> + </table> + </div> + <div class="modal-footer"> + <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button> + </div> +</div> + +<div id="node-dialog-library-save-confirm" class="hide"> + <form class="form-horizontal"> + <div style="text-align: center; padding-top: 30px;"> + A <span id="node-dialog-library-save-type"></span> called <span id="node-dialog-library-save-name"></span> already exists. Overwrite? + </div> + </form> +</div> + +<div id="node-dialog-library-save" class="hide"> + <form class="form-horizontal"> + <div class="form-row"> + <label for="node-dialog-library-save-folder"><i class="fa fa-folder-open"></i> Folder</label> + <input type="text" id="node-dialog-library-save-folder" placeholder="Folder"> + </div> + <div class="form-row"> + <label for="node-dialog-library-save-filename"><i class="fa fa-file"></i> Filename</label> + <input type="text" id="node-dialog-library-save-filename" placeholder="Filename"> + </div> + </form> +</div> + +<div id="node-dialog-library-lookup" class="hide"> + <form class="form-horizontal"> + <div class="form-row"> + <ul id="node-dialog-library-breadcrumbs" class="breadcrumb"> + <li class="active"><a href="#">Library</a></li> + </ul> + </div> + <div class="form-row"> + <div style="vertical-align: top; display: inline-block; height: 100%; width: 30%; padding-right: 20px;"> + <div id="node-select-library" style="border: 1px solid #999; width: 100%; height: 100%; overflow:scroll;"><ul></ul></div> + </div> + <div style="vertical-align: top; display: inline-block;width: 65%; height: 100%;"> + <div style="height: 100%; width: 95%;" class="node-text-editor" id="node-select-library-text" ></div> + </div> + </div> + </form> +</div> +<div id="node-dialog-rename-workspace" class="hide"> + <form class="form-horizontal"> + <div class="form-row"> + <label for="node-input-workspace-name" ><i class="fa fa-tag"></i> Name:</label> + <input type="text" id="node-input-workspace-name"> + </div> + </form> +</div> +<div id="node-dialog-delete-workspace" class="hide"> + <form class="form-horizontal"> + <div style="text-align: center; padding-top: 30px;"> + Are you sure you want to delete '<span id="node-dialog-delete-workspace-name"></span>'? + </div> + </form> +</div> + +<script type="text/x-red" data-template-name="export-clipboard-dialog"> + <div class="form-row"> + <label for="node-input-export" style="display: block; width:100%;"><i class="fa fa-clipboard"></i> Nodes:</label> + <textarea readonly style="font-family: monospace; font-size: 12px; background:rgb(226, 229, 255); padding-left: 0.5em;" class="input-block-level" id="node-input-export" rows="5"></textarea> + </div> + <div class="form-tips"> + Select the text above and copy to the clipboard with Ctrl-A Ctrl-C. + </div> +</script> +<script type="text/x-red" data-template-name="export-library-dialog"> + <div class="form-row"> + <label for="node-input-filename" ><i class="fa fa-file"></i> Filename:</label> + <input type="text" id="node-input-filename" placeholder="Filename"> + </div> +</script> +<script type="text/x-red" data-template-name="import-dialog"> + <div class="form-row"> + <label for="node-input-import"><i class="fa fa-clipboard"></i> Nodes:</label> + <textarea style="font-family: monospace; font-size: 12px; background:rgb(226, 229, 255); padding-left: 0.5em;" class="input-block-level" id="node-input-import" rows="5" placeholder="Paste nodes here"></textarea> + </div> +</script> + +<script src="jquery/js/jquery-1.11.1.min.js"></script> +<script src="bootstrap/js/bootstrap.min.js"></script> +<script src="jquery/js/jquery-ui-1.10.3.custom.min.js"></script> +<script src="jquery/js/jquery.ui.touch-punch.min.js"></script> +<script src="orion/built-editor.min.js"></script> +<script src="d3.v3.min.js"></script> +<script src="red/main.js"></script> +<script src="red/comms.js"></script> +<script src="red/ui/state.js"></script> +<script src="red/nodes.js"></script> +<script src="red/history.js"></script> +<script src="red/validators.js"></script> +<script src="red/ui/menu.js"></script> +<script src="red/ui/keyboard.js"></script> +<script src="red/ui/tabs.js"></script> +<script src="red/ui/view.js"></script> +<script src="red/ui/sidebar.js"></script> +<script src="red/ui/palette.js"></script> +<script src="red/ui/tab-info.js"></script> +<script src="red/ui/tab-config.js"></script> +<script src="red/ui/editor.js"></script> +<script src="red/ui/library.js"></script> +<script src="red/ui/notifications.js"></script> +<script src="red/ui/touch/radialMenu.js"></script> +</body> +</html> diff --git a/dgbuilder/public/jquery/css/smoothness/images/animated-overlay.gif b/dgbuilder/public/jquery/css/smoothness/images/animated-overlay.gif Binary files differnew file mode 100644 index 00000000..d441f75e --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/animated-overlay.gif diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png Binary files differnew file mode 100644 index 00000000..736b15aa --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png Binary files differnew file mode 100644 index 00000000..450d29ef --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png Binary files differnew file mode 100644 index 00000000..d1f36218 --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png Binary files differnew file mode 100644 index 00000000..a7a65012 --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png Binary files differnew file mode 100644 index 00000000..eadb5fbc --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png Binary files differnew file mode 100644 index 00000000..24ae2b76 --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png Binary files differnew file mode 100644 index 00000000..c48f5200 --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png Binary files differnew file mode 100644 index 00000000..f8e7c296 --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-icons_222222_256x240.png b/dgbuilder/public/jquery/css/smoothness/images/ui-icons_222222_256x240.png Binary files differnew file mode 100644 index 00000000..c1cb1170 --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-icons_222222_256x240.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-icons_2e83ff_256x240.png b/dgbuilder/public/jquery/css/smoothness/images/ui-icons_2e83ff_256x240.png Binary files differnew file mode 100644 index 00000000..84b601bf --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-icons_2e83ff_256x240.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-icons_454545_256x240.png b/dgbuilder/public/jquery/css/smoothness/images/ui-icons_454545_256x240.png Binary files differnew file mode 100644 index 00000000..b6db1acd --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-icons_454545_256x240.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-icons_888888_256x240.png b/dgbuilder/public/jquery/css/smoothness/images/ui-icons_888888_256x240.png Binary files differnew file mode 100644 index 00000000..feea0e20 --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-icons_888888_256x240.png diff --git a/dgbuilder/public/jquery/css/smoothness/images/ui-icons_cd0a0a_256x240.png b/dgbuilder/public/jquery/css/smoothness/images/ui-icons_cd0a0a_256x240.png Binary files differnew file mode 100644 index 00000000..ed5b6b09 --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/images/ui-icons_cd0a0a_256x240.png diff --git a/dgbuilder/public/jquery/css/smoothness/jquery-ui-1.10.3.custom.min.css b/dgbuilder/public/jquery/css/smoothness/jquery-ui-1.10.3.custom.min.css new file mode 100644 index 00000000..8d0e72cd --- /dev/null +++ b/dgbuilder/public/jquery/css/smoothness/jquery-ui-1.10.3.custom.min.css @@ -0,0 +1,5 @@ +/*! jQuery UI - v1.10.3 - 2013-08-17 +* http://jqueryui.com +* Includes: jquery.ui.core.css, jquery.ui.resizable.css, jquery.ui.selectable.css, jquery.ui.accordion.css, jquery.ui.autocomplete.css, jquery.ui.button.css, jquery.ui.datepicker.css, jquery.ui.dialog.css, jquery.ui.menu.css, jquery.ui.progressbar.css, jquery.ui.slider.css, jquery.ui.spinner.css, jquery.ui.tabs.css, jquery.ui.tooltip.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:.1px;display:block}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted #000}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin-top:2px;padding:.5em .5em .5em .7em;min-height:0}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-noicons{padding-left:.7em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-datepicker{width:17em;padding:.2em .2em 0;display:none}.ui-datepicker .ui-datepicker-header{position:relative;padding:.2em 0}.ui-datepicker .ui-datepicker-prev,.ui-datepicker .ui-datepicker-next{position:absolute;top:2px;width:1.8em;height:1.8em}.ui-datepicker .ui-datepicker-prev-hover,.ui-datepicker .ui-datepicker-next-hover{top:1px}.ui-datepicker .ui-datepicker-prev{left:2px}.ui-datepicker .ui-datepicker-next{right:2px}.ui-datepicker .ui-datepicker-prev-hover{left:1px}.ui-datepicker .ui-datepicker-next-hover{right:1px}.ui-datepicker .ui-datepicker-prev span,.ui-datepicker .ui-datepicker-next span{display:block;position:absolute;left:50%;margin-left:-8px;top:50%;margin-top:-8px}.ui-datepicker .ui-datepicker-title{margin:0 2.3em;line-height:1.8em;text-align:center}.ui-datepicker .ui-datepicker-title select{font-size:1em;margin:1px 0}.ui-datepicker select.ui-datepicker-month-year{width:100%}.ui-datepicker select.ui-datepicker-month,.ui-datepicker select.ui-datepicker-year{width:49%}.ui-datepicker table{width:100%;font-size:.9em;border-collapse:collapse;margin:0 0 .4em}.ui-datepicker th{padding:.7em .3em;text-align:center;font-weight:700;border:0}.ui-datepicker td{border:0;padding:1px}.ui-datepicker td span,.ui-datepicker td a{display:block;padding:.2em;text-align:right;text-decoration:none}.ui-datepicker .ui-datepicker-buttonpane{background-image:none;margin:.7em 0 0;padding:0 .2em;border-left:0;border-right:0;border-bottom:0}.ui-datepicker .ui-datepicker-buttonpane button{float:right;margin:.5em .2em .4em;cursor:pointer;padding:.2em .6em .3em;width:auto;overflow:visible}.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current{float:left}.ui-datepicker.ui-datepicker-multi{width:auto}.ui-datepicker-multi .ui-datepicker-group{float:left}.ui-datepicker-multi .ui-datepicker-group table{width:95%;margin:0 auto .4em}.ui-datepicker-multi-2 .ui-datepicker-group{width:50%}.ui-datepicker-multi-3 .ui-datepicker-group{width:33.3%}.ui-datepicker-multi-4 .ui-datepicker-group{width:25%}.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header{border-left-width:0}.ui-datepicker-multi .ui-datepicker-buttonpane{clear:left}.ui-datepicker-row-break{clear:both;width:100%;font-size:0}.ui-datepicker-rtl{direction:rtl}.ui-datepicker-rtl .ui-datepicker-prev{right:2px;left:auto}.ui-datepicker-rtl .ui-datepicker-next{left:2px;right:auto}.ui-datepicker-rtl .ui-datepicker-prev:hover{right:1px;left:auto}.ui-datepicker-rtl .ui-datepicker-next:hover{left:1px;right:auto}.ui-datepicker-rtl .ui-datepicker-buttonpane{clear:right}.ui-datepicker-rtl .ui-datepicker-buttonpane button{float:left}.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,.ui-datepicker-rtl .ui-datepicker-group{float:right}.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header{border-right-width:0;border-left-width:1px}.ui-dialog{position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:21px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:0;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:2px;margin:0;display:block;outline:0}.ui-menu .ui-menu{margin-top:-3px;position:absolute}.ui-menu .ui-menu-item{margin:0;padding:0;width:100%;list-style-image:url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)}.ui-menu .ui-menu-divider{margin:5px -2px 5px -2px;height:0;font-size:0;line-height:0;border-width:1px 0 0}.ui-menu .ui-menu-item a{text-decoration:none;display:block;padding:2px .4em;line-height:1.5;min-height:0;font-weight:400}.ui-menu .ui-menu-item a.ui-state-focus,.ui-menu .ui-menu-item a.ui-state-active{font-weight:400;margin:-1px}.ui-menu .ui-state-disabled{font-weight:400;margin:.4em 0 .2em;line-height:1.5}.ui-menu .ui-state-disabled a{cursor:default}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item a{position:relative;padding-left:2em}.ui-menu .ui-icon{position:absolute;top:.2em;left:.2em}.ui-menu .ui-menu-icon{position:static;float:right}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url(images/animated-overlay.gif);height:100%;filter:alpha(opacity=25);opacity:.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:0;background:0;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:0;border-bottom:0;border-right:0}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav li a{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active a,.ui-tabs .ui-tabs-nav li.ui-state-disabled a,.ui-tabs .ui-tabs-nav li.ui-tabs-loading a{cursor:text}.ui-tabs .ui-tabs-nav li a,.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:0}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px}.ui-widget{font-family:Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #aaa;background:#fff url(images/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x;color:#222}.ui-widget-content a{color:#222}.ui-widget-header{border:1px solid #aaa;background:#ccc url(images/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x;color:#222;font-weight:bold}.ui-widget-header a{color:#222}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #d3d3d3;background:#e6e6e6 url(images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#555}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#555;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #999;background:#dadada url(images/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#212121;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #aaa;background:#fff url(images/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x;font-weight:normal;color:#212121}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#212121;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fcefa1;background:#fbf9ee url(images/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x;color:#cd0a0a}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#cd0a0a}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#cd0a0a}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_888888_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_454545_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_2e83ff_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_cd0a0a_256x240.png)}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30)}.ui-widget-shadow{margin:-8px 0 0 -8px;padding:8px;background:#aaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x;opacity:.3;filter:Alpha(Opacity=30);border-radius:8px}
\ No newline at end of file diff --git a/dgbuilder/public/jquery/js/jquery-1.11.1.min.js b/dgbuilder/public/jquery/js/jquery-1.11.1.min.js new file mode 100644 index 00000000..ab28a247 --- /dev/null +++ b/dgbuilder/public/jquery/js/jquery-1.11.1.min.js @@ -0,0 +1,4 @@ +/*! jQuery v1.11.1 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ +!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=c.slice,e=c.concat,f=c.push,g=c.indexOf,h={},i=h.toString,j=h.hasOwnProperty,k={},l="1.11.1",m=function(a,b){return new m.fn.init(a,b)},n=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,o=/^-ms-/,p=/-([\da-z])/gi,q=function(a,b){return b.toUpperCase()};m.fn=m.prototype={jquery:l,constructor:m,selector:"",length:0,toArray:function(){return d.call(this)},get:function(a){return null!=a?0>a?this[a+this.length]:this[a]:d.call(this)},pushStack:function(a){var b=m.merge(this.constructor(),a);return b.prevObject=this,b.context=this.context,b},each:function(a,b){return m.each(this,a,b)},map:function(a){return this.pushStack(m.map(this,function(b,c){return a.call(b,c,b)}))},slice:function(){return this.pushStack(d.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},eq:function(a){var b=this.length,c=+a+(0>a?b:0);return this.pushStack(c>=0&&b>c?[this[c]]:[])},end:function(){return this.prevObject||this.constructor(null)},push:f,sort:c.sort,splice:c.splice},m.extend=m.fn.extend=function(){var a,b,c,d,e,f,g=arguments[0]||{},h=1,i=arguments.length,j=!1;for("boolean"==typeof g&&(j=g,g=arguments[h]||{},h++),"object"==typeof g||m.isFunction(g)||(g={}),h===i&&(g=this,h--);i>h;h++)if(null!=(e=arguments[h]))for(d in e)a=g[d],c=e[d],g!==c&&(j&&c&&(m.isPlainObject(c)||(b=m.isArray(c)))?(b?(b=!1,f=a&&m.isArray(a)?a:[]):f=a&&m.isPlainObject(a)?a:{},g[d]=m.extend(j,f,c)):void 0!==c&&(g[d]=c));return g},m.extend({expando:"jQuery"+(l+Math.random()).replace(/\D/g,""),isReady:!0,error:function(a){throw new Error(a)},noop:function(){},isFunction:function(a){return"function"===m.type(a)},isArray:Array.isArray||function(a){return"array"===m.type(a)},isWindow:function(a){return null!=a&&a==a.window},isNumeric:function(a){return!m.isArray(a)&&a-parseFloat(a)>=0},isEmptyObject:function(a){var b;for(b in a)return!1;return!0},isPlainObject:function(a){var b;if(!a||"object"!==m.type(a)||a.nodeType||m.isWindow(a))return!1;try{if(a.constructor&&!j.call(a,"constructor")&&!j.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}if(k.ownLast)for(b in a)return j.call(a,b);for(b in a);return void 0===b||j.call(a,b)},type:function(a){return null==a?a+"":"object"==typeof a||"function"==typeof a?h[i.call(a)]||"object":typeof a},globalEval:function(b){b&&m.trim(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(o,"ms-").replace(p,q)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toLowerCase()===b.toLowerCase()},each:function(a,b,c){var d,e=0,f=a.length,g=r(a);if(c){if(g){for(;f>e;e++)if(d=b.apply(a[e],c),d===!1)break}else for(e in a)if(d=b.apply(a[e],c),d===!1)break}else if(g){for(;f>e;e++)if(d=b.call(a[e],e,a[e]),d===!1)break}else for(e in a)if(d=b.call(a[e],e,a[e]),d===!1)break;return a},trim:function(a){return null==a?"":(a+"").replace(n,"")},makeArray:function(a,b){var c=b||[];return null!=a&&(r(Object(a))?m.merge(c,"string"==typeof a?[a]:a):f.call(c,a)),c},inArray:function(a,b,c){var d;if(b){if(g)return g.call(b,a,c);for(d=b.length,c=c?0>c?Math.max(0,d+c):c:0;d>c;c++)if(c in b&&b[c]===a)return c}return-1},merge:function(a,b){var c=+b.length,d=0,e=a.length;while(c>d)a[e++]=b[d++];if(c!==c)while(void 0!==b[d])a[e++]=b[d++];return a.length=e,a},grep:function(a,b,c){for(var d,e=[],f=0,g=a.length,h=!c;g>f;f++)d=!b(a[f],f),d!==h&&e.push(a[f]);return e},map:function(a,b,c){var d,f=0,g=a.length,h=r(a),i=[];if(h)for(;g>f;f++)d=b(a[f],f,c),null!=d&&i.push(d);else for(f in a)d=b(a[f],f,c),null!=d&&i.push(d);return e.apply([],i)},guid:1,proxy:function(a,b){var c,e,f;return"string"==typeof b&&(f=a[b],b=a,a=f),m.isFunction(a)?(c=d.call(arguments,2),e=function(){return a.apply(b||this,c.concat(d.call(arguments)))},e.guid=a.guid=a.guid||m.guid++,e):void 0},now:function(){return+new Date},support:k}),m.each("Boolean Number String Function Array Date RegExp Object Error".split(" "),function(a,b){h["[object "+b+"]"]=b.toLowerCase()});function r(a){var b=a.length,c=m.type(a);return"function"===c||m.isWindow(a)?!1:1===a.nodeType&&b?!0:"array"===c||0===b||"number"==typeof b&&b>0&&b-1 in a}var s=function(a){var b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u="sizzle"+-new Date,v=a.document,w=0,x=0,y=gb(),z=gb(),A=gb(),B=function(a,b){return a===b&&(l=!0),0},C="undefined",D=1<<31,E={}.hasOwnProperty,F=[],G=F.pop,H=F.push,I=F.push,J=F.slice,K=F.indexOf||function(a){for(var b=0,c=this.length;c>b;b++)if(this[b]===a)return b;return-1},L="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",N="(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",O=N.replace("w","w#"),P="\\["+M+"*("+N+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+O+"))|)"+M+"*\\]",Q=":("+N+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+P+")*)|.*)\\)|)",R=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),S=new RegExp("^"+M+"*,"+M+"*"),T=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp("="+M+"*([^\\]'\"]*?)"+M+"*\\]","g"),V=new RegExp(Q),W=new RegExp("^"+O+"$"),X={ID:new RegExp("^#("+N+")"),CLASS:new RegExp("^\\.("+N+")"),TAG:new RegExp("^("+N.replace("w","w*")+")"),ATTR:new RegExp("^"+P),PSEUDO:new RegExp("^"+Q),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+L+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/^(?:input|select|textarea|button)$/i,Z=/^h\d$/i,$=/^[^{]+\{\s*\[native \w/,_=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ab=/[+~]/,bb=/'|\\/g,cb=new RegExp("\\\\([\\da-f]{1,6}"+M+"?|("+M+")|.)","ig"),db=function(a,b,c){var d="0x"+b-65536;return d!==d||c?b:0>d?String.fromCharCode(d+65536):String.fromCharCode(d>>10|55296,1023&d|56320)};try{I.apply(F=J.call(v.childNodes),v.childNodes),F[v.childNodes.length].nodeType}catch(eb){I={apply:F.length?function(a,b){H.apply(a,J.call(b))}:function(a,b){var c=a.length,d=0;while(a[c++]=b[d++]);a.length=c-1}}}function fb(a,b,d,e){var f,h,j,k,l,o,r,s,w,x;if((b?b.ownerDocument||b:v)!==n&&m(b),b=b||n,d=d||[],!a||"string"!=typeof a)return d;if(1!==(k=b.nodeType)&&9!==k)return[];if(p&&!e){if(f=_.exec(a))if(j=f[1]){if(9===k){if(h=b.getElementById(j),!h||!h.parentNode)return d;if(h.id===j)return d.push(h),d}else if(b.ownerDocument&&(h=b.ownerDocument.getElementById(j))&&t(b,h)&&h.id===j)return d.push(h),d}else{if(f[2])return I.apply(d,b.getElementsByTagName(a)),d;if((j=f[3])&&c.getElementsByClassName&&b.getElementsByClassName)return I.apply(d,b.getElementsByClassName(j)),d}if(c.qsa&&(!q||!q.test(a))){if(s=r=u,w=b,x=9===k&&a,1===k&&"object"!==b.nodeName.toLowerCase()){o=g(a),(r=b.getAttribute("id"))?s=r.replace(bb,"\\$&"):b.setAttribute("id",s),s="[id='"+s+"'] ",l=o.length;while(l--)o[l]=s+qb(o[l]);w=ab.test(a)&&ob(b.parentNode)||b,x=o.join(",")}if(x)try{return I.apply(d,w.querySelectorAll(x)),d}catch(y){}finally{r||b.removeAttribute("id")}}}return i(a.replace(R,"$1"),b,d,e)}function gb(){var a=[];function b(c,e){return a.push(c+" ")>d.cacheLength&&delete b[a.shift()],b[c+" "]=e}return b}function hb(a){return a[u]=!0,a}function ib(a){var b=n.createElement("div");try{return!!a(b)}catch(c){return!1}finally{b.parentNode&&b.parentNode.removeChild(b),b=null}}function jb(a,b){var c=a.split("|"),e=a.length;while(e--)d.attrHandle[c[e]]=b}function kb(a,b){var c=b&&a,d=c&&1===a.nodeType&&1===b.nodeType&&(~b.sourceIndex||D)-(~a.sourceIndex||D);if(d)return d;if(c)while(c=c.nextSibling)if(c===b)return-1;return a?1:-1}function lb(a){return function(b){var c=b.nodeName.toLowerCase();return"input"===c&&b.type===a}}function mb(a){return function(b){var c=b.nodeName.toLowerCase();return("input"===c||"button"===c)&&b.type===a}}function nb(a){return hb(function(b){return b=+b,hb(function(c,d){var e,f=a([],c.length,b),g=f.length;while(g--)c[e=f[g]]&&(c[e]=!(d[e]=c[e]))})})}function ob(a){return a&&typeof a.getElementsByTagName!==C&&a}c=fb.support={},f=fb.isXML=function(a){var b=a&&(a.ownerDocument||a).documentElement;return b?"HTML"!==b.nodeName:!1},m=fb.setDocument=function(a){var b,e=a?a.ownerDocument||a:v,g=e.defaultView;return e!==n&&9===e.nodeType&&e.documentElement?(n=e,o=e.documentElement,p=!f(e),g&&g!==g.top&&(g.addEventListener?g.addEventListener("unload",function(){m()},!1):g.attachEvent&&g.attachEvent("onunload",function(){m()})),c.attributes=ib(function(a){return a.className="i",!a.getAttribute("className")}),c.getElementsByTagName=ib(function(a){return a.appendChild(e.createComment("")),!a.getElementsByTagName("*").length}),c.getElementsByClassName=$.test(e.getElementsByClassName)&&ib(function(a){return a.innerHTML="<div class='a'></div><div class='a i'></div>",a.firstChild.className="i",2===a.getElementsByClassName("i").length}),c.getById=ib(function(a){return o.appendChild(a).id=u,!e.getElementsByName||!e.getElementsByName(u).length}),c.getById?(d.find.ID=function(a,b){if(typeof b.getElementById!==C&&p){var c=b.getElementById(a);return c&&c.parentNode?[c]:[]}},d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){return a.getAttribute("id")===b}}):(delete d.find.ID,d.filter.ID=function(a){var b=a.replace(cb,db);return function(a){var c=typeof a.getAttributeNode!==C&&a.getAttributeNode("id");return c&&c.value===b}}),d.find.TAG=c.getElementsByTagName?function(a,b){return typeof b.getElementsByTagName!==C?b.getElementsByTagName(a):void 0}:function(a,b){var c,d=[],e=0,f=b.getElementsByTagName(a);if("*"===a){while(c=f[e++])1===c.nodeType&&d.push(c);return d}return f},d.find.CLASS=c.getElementsByClassName&&function(a,b){return typeof b.getElementsByClassName!==C&&p?b.getElementsByClassName(a):void 0},r=[],q=[],(c.qsa=$.test(e.querySelectorAll))&&(ib(function(a){a.innerHTML="<select msallowclip=''><option selected=''></option></select>",a.querySelectorAll("[msallowclip^='']").length&&q.push("[*^$]="+M+"*(?:''|\"\")"),a.querySelectorAll("[selected]").length||q.push("\\["+M+"*(?:value|"+L+")"),a.querySelectorAll(":checked").length||q.push(":checked")}),ib(function(a){var b=e.createElement("input");b.setAttribute("type","hidden"),a.appendChild(b).setAttribute("name","D"),a.querySelectorAll("[name=d]").length&&q.push("name"+M+"*[*^$|!~]?="),a.querySelectorAll(":enabled").length||q.push(":enabled",":disabled"),a.querySelectorAll("*,:x"),q.push(",.*:")})),(c.matchesSelector=$.test(s=o.matches||o.webkitMatchesSelector||o.mozMatchesSelector||o.oMatchesSelector||o.msMatchesSelector))&&ib(function(a){c.disconnectedMatch=s.call(a,"div"),s.call(a,"[s!='']:x"),r.push("!=",Q)}),q=q.length&&new RegExp(q.join("|")),r=r.length&&new RegExp(r.join("|")),b=$.test(o.compareDocumentPosition),t=b||$.test(o.contains)?function(a,b){var c=9===a.nodeType?a.documentElement:a,d=b&&b.parentNode;return a===d||!(!d||1!==d.nodeType||!(c.contains?c.contains(d):a.compareDocumentPosition&&16&a.compareDocumentPosition(d)))}:function(a,b){if(b)while(b=b.parentNode)if(b===a)return!0;return!1},B=b?function(a,b){if(a===b)return l=!0,0;var d=!a.compareDocumentPosition-!b.compareDocumentPosition;return d?d:(d=(a.ownerDocument||a)===(b.ownerDocument||b)?a.compareDocumentPosition(b):1,1&d||!c.sortDetached&&b.compareDocumentPosition(a)===d?a===e||a.ownerDocument===v&&t(v,a)?-1:b===e||b.ownerDocument===v&&t(v,b)?1:k?K.call(k,a)-K.call(k,b):0:4&d?-1:1)}:function(a,b){if(a===b)return l=!0,0;var c,d=0,f=a.parentNode,g=b.parentNode,h=[a],i=[b];if(!f||!g)return a===e?-1:b===e?1:f?-1:g?1:k?K.call(k,a)-K.call(k,b):0;if(f===g)return kb(a,b);c=a;while(c=c.parentNode)h.unshift(c);c=b;while(c=c.parentNode)i.unshift(c);while(h[d]===i[d])d++;return d?kb(h[d],i[d]):h[d]===v?-1:i[d]===v?1:0},e):n},fb.matches=function(a,b){return fb(a,null,null,b)},fb.matchesSelector=function(a,b){if((a.ownerDocument||a)!==n&&m(a),b=b.replace(U,"='$1']"),!(!c.matchesSelector||!p||r&&r.test(b)||q&&q.test(b)))try{var d=s.call(a,b);if(d||c.disconnectedMatch||a.document&&11!==a.document.nodeType)return d}catch(e){}return fb(b,n,null,[a]).length>0},fb.contains=function(a,b){return(a.ownerDocument||a)!==n&&m(a),t(a,b)},fb.attr=function(a,b){(a.ownerDocument||a)!==n&&m(a);var e=d.attrHandle[b.toLowerCase()],f=e&&E.call(d.attrHandle,b.toLowerCase())?e(a,b,!p):void 0;return void 0!==f?f:c.attributes||!p?a.getAttribute(b):(f=a.getAttributeNode(b))&&f.specified?f.value:null},fb.error=function(a){throw new Error("Syntax error, unrecognized expression: "+a)},fb.uniqueSort=function(a){var b,d=[],e=0,f=0;if(l=!c.detectDuplicates,k=!c.sortStable&&a.slice(0),a.sort(B),l){while(b=a[f++])b===a[f]&&(e=d.push(f));while(e--)a.splice(d[e],1)}return k=null,a},e=fb.getText=function(a){var b,c="",d=0,f=a.nodeType;if(f){if(1===f||9===f||11===f){if("string"==typeof a.textContent)return a.textContent;for(a=a.firstChild;a;a=a.nextSibling)c+=e(a)}else if(3===f||4===f)return a.nodeValue}else while(b=a[d++])c+=e(b);return c},d=fb.selectors={cacheLength:50,createPseudo:hb,match:X,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(a){return a[1]=a[1].replace(cb,db),a[3]=(a[3]||a[4]||a[5]||"").replace(cb,db),"~="===a[2]&&(a[3]=" "+a[3]+" "),a.slice(0,4)},CHILD:function(a){return a[1]=a[1].toLowerCase(),"nth"===a[1].slice(0,3)?(a[3]||fb.error(a[0]),a[4]=+(a[4]?a[5]+(a[6]||1):2*("even"===a[3]||"odd"===a[3])),a[5]=+(a[7]+a[8]||"odd"===a[3])):a[3]&&fb.error(a[0]),a},PSEUDO:function(a){var b,c=!a[6]&&a[2];return X.CHILD.test(a[0])?null:(a[3]?a[2]=a[4]||a[5]||"":c&&V.test(c)&&(b=g(c,!0))&&(b=c.indexOf(")",c.length-b)-c.length)&&(a[0]=a[0].slice(0,b),a[2]=c.slice(0,b)),a.slice(0,3))}},filter:{TAG:function(a){var b=a.replace(cb,db).toLowerCase();return"*"===a?function(){return!0}:function(a){return a.nodeName&&a.nodeName.toLowerCase()===b}},CLASS:function(a){var b=y[a+" "];return b||(b=new RegExp("(^|"+M+")"+a+"("+M+"|$)"))&&y(a,function(a){return b.test("string"==typeof a.className&&a.className||typeof a.getAttribute!==C&&a.getAttribute("class")||"")})},ATTR:function(a,b,c){return function(d){var e=fb.attr(d,a);return null==e?"!="===b:b?(e+="","="===b?e===c:"!="===b?e!==c:"^="===b?c&&0===e.indexOf(c):"*="===b?c&&e.indexOf(c)>-1:"$="===b?c&&e.slice(-c.length)===c:"~="===b?(" "+e+" ").indexOf(c)>-1:"|="===b?e===c||e.slice(0,c.length+1)===c+"-":!1):!0}},CHILD:function(a,b,c,d,e){var f="nth"!==a.slice(0,3),g="last"!==a.slice(-4),h="of-type"===b;return 1===d&&0===e?function(a){return!!a.parentNode}:function(b,c,i){var j,k,l,m,n,o,p=f!==g?"nextSibling":"previousSibling",q=b.parentNode,r=h&&b.nodeName.toLowerCase(),s=!i&&!h;if(q){if(f){while(p){l=b;while(l=l[p])if(h?l.nodeName.toLowerCase()===r:1===l.nodeType)return!1;o=p="only"===a&&!o&&"nextSibling"}return!0}if(o=[g?q.firstChild:q.lastChild],g&&s){k=q[u]||(q[u]={}),j=k[a]||[],n=j[0]===w&&j[1],m=j[0]===w&&j[2],l=n&&q.childNodes[n];while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if(1===l.nodeType&&++m&&l===b){k[a]=[w,n,m];break}}else if(s&&(j=(b[u]||(b[u]={}))[a])&&j[0]===w)m=j[1];else while(l=++n&&l&&l[p]||(m=n=0)||o.pop())if((h?l.nodeName.toLowerCase()===r:1===l.nodeType)&&++m&&(s&&((l[u]||(l[u]={}))[a]=[w,m]),l===b))break;return m-=e,m===d||m%d===0&&m/d>=0}}},PSEUDO:function(a,b){var c,e=d.pseudos[a]||d.setFilters[a.toLowerCase()]||fb.error("unsupported pseudo: "+a);return e[u]?e(b):e.length>1?(c=[a,a,"",b],d.setFilters.hasOwnProperty(a.toLowerCase())?hb(function(a,c){var d,f=e(a,b),g=f.length;while(g--)d=K.call(a,f[g]),a[d]=!(c[d]=f[g])}):function(a){return e(a,0,c)}):e}},pseudos:{not:hb(function(a){var b=[],c=[],d=h(a.replace(R,"$1"));return d[u]?hb(function(a,b,c,e){var f,g=d(a,null,e,[]),h=a.length;while(h--)(f=g[h])&&(a[h]=!(b[h]=f))}):function(a,e,f){return b[0]=a,d(b,null,f,c),!c.pop()}}),has:hb(function(a){return function(b){return fb(a,b).length>0}}),contains:hb(function(a){return function(b){return(b.textContent||b.innerText||e(b)).indexOf(a)>-1}}),lang:hb(function(a){return W.test(a||"")||fb.error("unsupported lang: "+a),a=a.replace(cb,db).toLowerCase(),function(b){var c;do if(c=p?b.lang:b.getAttribute("xml:lang")||b.getAttribute("lang"))return c=c.toLowerCase(),c===a||0===c.indexOf(a+"-");while((b=b.parentNode)&&1===b.nodeType);return!1}}),target:function(b){var c=a.location&&a.location.hash;return c&&c.slice(1)===b.id},root:function(a){return a===o},focus:function(a){return a===n.activeElement&&(!n.hasFocus||n.hasFocus())&&!!(a.type||a.href||~a.tabIndex)},enabled:function(a){return a.disabled===!1},disabled:function(a){return a.disabled===!0},checked:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&!!a.checked||"option"===b&&!!a.selected},selected:function(a){return a.parentNode&&a.parentNode.selectedIndex,a.selected===!0},empty:function(a){for(a=a.firstChild;a;a=a.nextSibling)if(a.nodeType<6)return!1;return!0},parent:function(a){return!d.pseudos.empty(a)},header:function(a){return Z.test(a.nodeName)},input:function(a){return Y.test(a.nodeName)},button:function(a){var b=a.nodeName.toLowerCase();return"input"===b&&"button"===a.type||"button"===b},text:function(a){var b;return"input"===a.nodeName.toLowerCase()&&"text"===a.type&&(null==(b=a.getAttribute("type"))||"text"===b.toLowerCase())},first:nb(function(){return[0]}),last:nb(function(a,b){return[b-1]}),eq:nb(function(a,b,c){return[0>c?c+b:c]}),even:nb(function(a,b){for(var c=0;b>c;c+=2)a.push(c);return a}),odd:nb(function(a,b){for(var c=1;b>c;c+=2)a.push(c);return a}),lt:nb(function(a,b,c){for(var d=0>c?c+b:c;--d>=0;)a.push(d);return a}),gt:nb(function(a,b,c){for(var d=0>c?c+b:c;++d<b;)a.push(d);return a})}},d.pseudos.nth=d.pseudos.eq;for(b in{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})d.pseudos[b]=lb(b);for(b in{submit:!0,reset:!0})d.pseudos[b]=mb(b);function pb(){}pb.prototype=d.filters=d.pseudos,d.setFilters=new pb,g=fb.tokenize=function(a,b){var c,e,f,g,h,i,j,k=z[a+" "];if(k)return b?0:k.slice(0);h=a,i=[],j=d.preFilter;while(h){(!c||(e=S.exec(h)))&&(e&&(h=h.slice(e[0].length)||h),i.push(f=[])),c=!1,(e=T.exec(h))&&(c=e.shift(),f.push({value:c,type:e[0].replace(R," ")}),h=h.slice(c.length));for(g in d.filter)!(e=X[g].exec(h))||j[g]&&!(e=j[g](e))||(c=e.shift(),f.push({value:c,type:g,matches:e}),h=h.slice(c.length));if(!c)break}return b?h.length:h?fb.error(a):z(a,i).slice(0)};function qb(a){for(var b=0,c=a.length,d="";c>b;b++)d+=a[b].value;return d}function rb(a,b,c){var d=b.dir,e=c&&"parentNode"===d,f=x++;return b.first?function(b,c,f){while(b=b[d])if(1===b.nodeType||e)return a(b,c,f)}:function(b,c,g){var h,i,j=[w,f];if(g){while(b=b[d])if((1===b.nodeType||e)&&a(b,c,g))return!0}else while(b=b[d])if(1===b.nodeType||e){if(i=b[u]||(b[u]={}),(h=i[d])&&h[0]===w&&h[1]===f)return j[2]=h[2];if(i[d]=j,j[2]=a(b,c,g))return!0}}}function sb(a){return a.length>1?function(b,c,d){var e=a.length;while(e--)if(!a[e](b,c,d))return!1;return!0}:a[0]}function tb(a,b,c){for(var d=0,e=b.length;e>d;d++)fb(a,b[d],c);return c}function ub(a,b,c,d,e){for(var f,g=[],h=0,i=a.length,j=null!=b;i>h;h++)(f=a[h])&&(!c||c(f,d,e))&&(g.push(f),j&&b.push(h));return g}function vb(a,b,c,d,e,f){return d&&!d[u]&&(d=vb(d)),e&&!e[u]&&(e=vb(e,f)),hb(function(f,g,h,i){var j,k,l,m=[],n=[],o=g.length,p=f||tb(b||"*",h.nodeType?[h]:h,[]),q=!a||!f&&b?p:ub(p,m,a,h,i),r=c?e||(f?a:o||d)?[]:g:q;if(c&&c(q,r,h,i),d){j=ub(r,n),d(j,[],h,i),k=j.length;while(k--)(l=j[k])&&(r[n[k]]=!(q[n[k]]=l))}if(f){if(e||a){if(e){j=[],k=r.length;while(k--)(l=r[k])&&j.push(q[k]=l);e(null,r=[],j,i)}k=r.length;while(k--)(l=r[k])&&(j=e?K.call(f,l):m[k])>-1&&(f[j]=!(g[j]=l))}}else r=ub(r===g?r.splice(o,r.length):r),e?e(null,g,r,i):I.apply(g,r)})}function wb(a){for(var b,c,e,f=a.length,g=d.relative[a[0].type],h=g||d.relative[" "],i=g?1:0,k=rb(function(a){return a===b},h,!0),l=rb(function(a){return K.call(b,a)>-1},h,!0),m=[function(a,c,d){return!g&&(d||c!==j)||((b=c).nodeType?k(a,c,d):l(a,c,d))}];f>i;i++)if(c=d.relative[a[i].type])m=[rb(sb(m),c)];else{if(c=d.filter[a[i].type].apply(null,a[i].matches),c[u]){for(e=++i;f>e;e++)if(d.relative[a[e].type])break;return vb(i>1&&sb(m),i>1&&qb(a.slice(0,i-1).concat({value:" "===a[i-2].type?"*":""})).replace(R,"$1"),c,e>i&&wb(a.slice(i,e)),f>e&&wb(a=a.slice(e)),f>e&&qb(a))}m.push(c)}return sb(m)}function xb(a,b){var c=b.length>0,e=a.length>0,f=function(f,g,h,i,k){var l,m,o,p=0,q="0",r=f&&[],s=[],t=j,u=f||e&&d.find.TAG("*",k),v=w+=null==t?1:Math.random()||.1,x=u.length;for(k&&(j=g!==n&&g);q!==x&&null!=(l=u[q]);q++){if(e&&l){m=0;while(o=a[m++])if(o(l,g,h)){i.push(l);break}k&&(w=v)}c&&((l=!o&&l)&&p--,f&&r.push(l))}if(p+=q,c&&q!==p){m=0;while(o=b[m++])o(r,s,g,h);if(f){if(p>0)while(q--)r[q]||s[q]||(s[q]=G.call(i));s=ub(s)}I.apply(i,s),k&&!f&&s.length>0&&p+b.length>1&&fb.uniqueSort(i)}return k&&(w=v,j=t),r};return c?hb(f):f}return h=fb.compile=function(a,b){var c,d=[],e=[],f=A[a+" "];if(!f){b||(b=g(a)),c=b.length;while(c--)f=wb(b[c]),f[u]?d.push(f):e.push(f);f=A(a,xb(e,d)),f.selector=a}return f},i=fb.select=function(a,b,e,f){var i,j,k,l,m,n="function"==typeof a&&a,o=!f&&g(a=n.selector||a);if(e=e||[],1===o.length){if(j=o[0]=o[0].slice(0),j.length>2&&"ID"===(k=j[0]).type&&c.getById&&9===b.nodeType&&p&&d.relative[j[1].type]){if(b=(d.find.ID(k.matches[0].replace(cb,db),b)||[])[0],!b)return e;n&&(b=b.parentNode),a=a.slice(j.shift().value.length)}i=X.needsContext.test(a)?0:j.length;while(i--){if(k=j[i],d.relative[l=k.type])break;if((m=d.find[l])&&(f=m(k.matches[0].replace(cb,db),ab.test(j[0].type)&&ob(b.parentNode)||b))){if(j.splice(i,1),a=f.length&&qb(j),!a)return I.apply(e,f),e;break}}}return(n||h(a,o))(f,b,!p,e,ab.test(a)&&ob(b.parentNode)||b),e},c.sortStable=u.split("").sort(B).join("")===u,c.detectDuplicates=!!l,m(),c.sortDetached=ib(function(a){return 1&a.compareDocumentPosition(n.createElement("div"))}),ib(function(a){return a.innerHTML="<a href='#'></a>","#"===a.firstChild.getAttribute("href")})||jb("type|href|height|width",function(a,b,c){return c?void 0:a.getAttribute(b,"type"===b.toLowerCase()?1:2)}),c.attributes&&ib(function(a){return a.innerHTML="<input/>",a.firstChild.setAttribute("value",""),""===a.firstChild.getAttribute("value")})||jb("value",function(a,b,c){return c||"input"!==a.nodeName.toLowerCase()?void 0:a.defaultValue}),ib(function(a){return null==a.getAttribute("disabled")})||jb(L,function(a,b,c){var d;return c?void 0:a[b]===!0?b.toLowerCase():(d=a.getAttributeNode(b))&&d.specified?d.value:null}),fb}(a);m.find=s,m.expr=s.selectors,m.expr[":"]=m.expr.pseudos,m.unique=s.uniqueSort,m.text=s.getText,m.isXMLDoc=s.isXML,m.contains=s.contains;var t=m.expr.match.needsContext,u=/^<(\w+)\s*\/?>(?:<\/\1>|)$/,v=/^.[^:#\[\.,]*$/;function w(a,b,c){if(m.isFunction(b))return m.grep(a,function(a,d){return!!b.call(a,d,a)!==c});if(b.nodeType)return m.grep(a,function(a){return a===b!==c});if("string"==typeof b){if(v.test(b))return m.filter(b,a,c);b=m.filter(b,a)}return m.grep(a,function(a){return m.inArray(a,b)>=0!==c})}m.filter=function(a,b,c){var d=b[0];return c&&(a=":not("+a+")"),1===b.length&&1===d.nodeType?m.find.matchesSelector(d,a)?[d]:[]:m.find.matches(a,m.grep(b,function(a){return 1===a.nodeType}))},m.fn.extend({find:function(a){var b,c=[],d=this,e=d.length;if("string"!=typeof a)return this.pushStack(m(a).filter(function(){for(b=0;e>b;b++)if(m.contains(d[b],this))return!0}));for(b=0;e>b;b++)m.find(a,d[b],c);return c=this.pushStack(e>1?m.unique(c):c),c.selector=this.selector?this.selector+" "+a:a,c},filter:function(a){return this.pushStack(w(this,a||[],!1))},not:function(a){return this.pushStack(w(this,a||[],!0))},is:function(a){return!!w(this,"string"==typeof a&&t.test(a)?m(a):a||[],!1).length}});var x,y=a.document,z=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,A=m.fn.init=function(a,b){var c,d;if(!a)return this;if("string"==typeof a){if(c="<"===a.charAt(0)&&">"===a.charAt(a.length-1)&&a.length>=3?[null,a,null]:z.exec(a),!c||!c[1]&&b)return!b||b.jquery?(b||x).find(a):this.constructor(b).find(a);if(c[1]){if(b=b instanceof m?b[0]:b,m.merge(this,m.parseHTML(c[1],b&&b.nodeType?b.ownerDocument||b:y,!0)),u.test(c[1])&&m.isPlainObject(b))for(c in b)m.isFunction(this[c])?this[c](b[c]):this.attr(c,b[c]);return this}if(d=y.getElementById(c[2]),d&&d.parentNode){if(d.id!==c[2])return x.find(a);this.length=1,this[0]=d}return this.context=y,this.selector=a,this}return a.nodeType?(this.context=this[0]=a,this.length=1,this):m.isFunction(a)?"undefined"!=typeof x.ready?x.ready(a):a(m):(void 0!==a.selector&&(this.selector=a.selector,this.context=a.context),m.makeArray(a,this))};A.prototype=m.fn,x=m(y);var B=/^(?:parents|prev(?:Until|All))/,C={children:!0,contents:!0,next:!0,prev:!0};m.extend({dir:function(a,b,c){var d=[],e=a[b];while(e&&9!==e.nodeType&&(void 0===c||1!==e.nodeType||!m(e).is(c)))1===e.nodeType&&d.push(e),e=e[b];return d},sibling:function(a,b){for(var c=[];a;a=a.nextSibling)1===a.nodeType&&a!==b&&c.push(a);return c}}),m.fn.extend({has:function(a){var b,c=m(a,this),d=c.length;return this.filter(function(){for(b=0;d>b;b++)if(m.contains(this,c[b]))return!0})},closest:function(a,b){for(var c,d=0,e=this.length,f=[],g=t.test(a)||"string"!=typeof a?m(a,b||this.context):0;e>d;d++)for(c=this[d];c&&c!==b;c=c.parentNode)if(c.nodeType<11&&(g?g.index(c)>-1:1===c.nodeType&&m.find.matchesSelector(c,a))){f.push(c);break}return this.pushStack(f.length>1?m.unique(f):f)},index:function(a){return a?"string"==typeof a?m.inArray(this[0],m(a)):m.inArray(a.jquery?a[0]:a,this):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(a,b){return this.pushStack(m.unique(m.merge(this.get(),m(a,b))))},addBack:function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}});function D(a,b){do a=a[b];while(a&&1!==a.nodeType);return a}m.each({parent:function(a){var b=a.parentNode;return b&&11!==b.nodeType?b:null},parents:function(a){return m.dir(a,"parentNode")},parentsUntil:function(a,b,c){return m.dir(a,"parentNode",c)},next:function(a){return D(a,"nextSibling")},prev:function(a){return D(a,"previousSibling")},nextAll:function(a){return m.dir(a,"nextSibling")},prevAll:function(a){return m.dir(a,"previousSibling")},nextUntil:function(a,b,c){return m.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return m.dir(a,"previousSibling",c)},siblings:function(a){return m.sibling((a.parentNode||{}).firstChild,a)},children:function(a){return m.sibling(a.firstChild)},contents:function(a){return m.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:m.merge([],a.childNodes)}},function(a,b){m.fn[a]=function(c,d){var e=m.map(this,b,c);return"Until"!==a.slice(-5)&&(d=c),d&&"string"==typeof d&&(e=m.filter(d,e)),this.length>1&&(C[a]||(e=m.unique(e)),B.test(a)&&(e=e.reverse())),this.pushStack(e)}});var E=/\S+/g,F={};function G(a){var b=F[a]={};return m.each(a.match(E)||[],function(a,c){b[c]=!0}),b}m.Callbacks=function(a){a="string"==typeof a?F[a]||G(a):m.extend({},a);var b,c,d,e,f,g,h=[],i=!a.once&&[],j=function(l){for(c=a.memory&&l,d=!0,f=g||0,g=0,e=h.length,b=!0;h&&e>f;f++)if(h[f].apply(l[0],l[1])===!1&&a.stopOnFalse){c=!1;break}b=!1,h&&(i?i.length&&j(i.shift()):c?h=[]:k.disable())},k={add:function(){if(h){var d=h.length;!function f(b){m.each(b,function(b,c){var d=m.type(c);"function"===d?a.unique&&k.has(c)||h.push(c):c&&c.length&&"string"!==d&&f(c)})}(arguments),b?e=h.length:c&&(g=d,j(c))}return this},remove:function(){return h&&m.each(arguments,function(a,c){var d;while((d=m.inArray(c,h,d))>-1)h.splice(d,1),b&&(e>=d&&e--,f>=d&&f--)}),this},has:function(a){return a?m.inArray(a,h)>-1:!(!h||!h.length)},empty:function(){return h=[],e=0,this},disable:function(){return h=i=c=void 0,this},disabled:function(){return!h},lock:function(){return i=void 0,c||k.disable(),this},locked:function(){return!i},fireWith:function(a,c){return!h||d&&!i||(c=c||[],c=[a,c.slice?c.slice():c],b?i.push(c):j(c)),this},fire:function(){return k.fireWith(this,arguments),this},fired:function(){return!!d}};return k},m.extend({Deferred:function(a){var b=[["resolve","done",m.Callbacks("once memory"),"resolved"],["reject","fail",m.Callbacks("once memory"),"rejected"],["notify","progress",m.Callbacks("memory")]],c="pending",d={state:function(){return c},always:function(){return e.done(arguments).fail(arguments),this},then:function(){var a=arguments;return m.Deferred(function(c){m.each(b,function(b,f){var g=m.isFunction(a[b])&&a[b];e[f[1]](function(){var a=g&&g.apply(this,arguments);a&&m.isFunction(a.promise)?a.promise().done(c.resolve).fail(c.reject).progress(c.notify):c[f[0]+"With"](this===d?c.promise():this,g?[a]:arguments)})}),a=null}).promise()},promise:function(a){return null!=a?m.extend(a,d):d}},e={};return d.pipe=d.then,m.each(b,function(a,f){var g=f[2],h=f[3];d[f[1]]=g.add,h&&g.add(function(){c=h},b[1^a][2].disable,b[2][2].lock),e[f[0]]=function(){return e[f[0]+"With"](this===e?d:this,arguments),this},e[f[0]+"With"]=g.fireWith}),d.promise(e),a&&a.call(e,e),e},when:function(a){var b=0,c=d.call(arguments),e=c.length,f=1!==e||a&&m.isFunction(a.promise)?e:0,g=1===f?a:m.Deferred(),h=function(a,b,c){return function(e){b[a]=this,c[a]=arguments.length>1?d.call(arguments):e,c===i?g.notifyWith(b,c):--f||g.resolveWith(b,c)}},i,j,k;if(e>1)for(i=new Array(e),j=new Array(e),k=new Array(e);e>b;b++)c[b]&&m.isFunction(c[b].promise)?c[b].promise().done(h(b,k,c)).fail(g.reject).progress(h(b,j,i)):--f;return f||g.resolveWith(k,c),g.promise()}});var H;m.fn.ready=function(a){return m.ready.promise().done(a),this},m.extend({isReady:!1,readyWait:1,holdReady:function(a){a?m.readyWait++:m.ready(!0)},ready:function(a){if(a===!0?!--m.readyWait:!m.isReady){if(!y.body)return setTimeout(m.ready);m.isReady=!0,a!==!0&&--m.readyWait>0||(H.resolveWith(y,[m]),m.fn.triggerHandler&&(m(y).triggerHandler("ready"),m(y).off("ready")))}}});function I(){y.addEventListener?(y.removeEventListener("DOMContentLoaded",J,!1),a.removeEventListener("load",J,!1)):(y.detachEvent("onreadystatechange",J),a.detachEvent("onload",J))}function J(){(y.addEventListener||"load"===event.type||"complete"===y.readyState)&&(I(),m.ready())}m.ready.promise=function(b){if(!H)if(H=m.Deferred(),"complete"===y.readyState)setTimeout(m.ready);else if(y.addEventListener)y.addEventListener("DOMContentLoaded",J,!1),a.addEventListener("load",J,!1);else{y.attachEvent("onreadystatechange",J),a.attachEvent("onload",J);var c=!1;try{c=null==a.frameElement&&y.documentElement}catch(d){}c&&c.doScroll&&!function e(){if(!m.isReady){try{c.doScroll("left")}catch(a){return setTimeout(e,50)}I(),m.ready()}}()}return H.promise(b)};var K="undefined",L;for(L in m(k))break;k.ownLast="0"!==L,k.inlineBlockNeedsLayout=!1,m(function(){var a,b,c,d;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1",k.inlineBlockNeedsLayout=a=3===b.offsetWidth,a&&(c.style.zoom=1)),c.removeChild(d))}),function(){var a=y.createElement("div");if(null==k.deleteExpando){k.deleteExpando=!0;try{delete a.test}catch(b){k.deleteExpando=!1}}a=null}(),m.acceptData=function(a){var b=m.noData[(a.nodeName+" ").toLowerCase()],c=+a.nodeType||1;return 1!==c&&9!==c?!1:!b||b!==!0&&a.getAttribute("classid")===b};var M=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,N=/([A-Z])/g;function O(a,b,c){if(void 0===c&&1===a.nodeType){var d="data-"+b.replace(N,"-$1").toLowerCase();if(c=a.getAttribute(d),"string"==typeof c){try{c="true"===c?!0:"false"===c?!1:"null"===c?null:+c+""===c?+c:M.test(c)?m.parseJSON(c):c}catch(e){}m.data(a,b,c)}else c=void 0}return c}function P(a){var b;for(b in a)if(("data"!==b||!m.isEmptyObject(a[b]))&&"toJSON"!==b)return!1;return!0}function Q(a,b,d,e){if(m.acceptData(a)){var f,g,h=m.expando,i=a.nodeType,j=i?m.cache:a,k=i?a[h]:a[h]&&h; +if(k&&j[k]&&(e||j[k].data)||void 0!==d||"string"!=typeof b)return k||(k=i?a[h]=c.pop()||m.guid++:h),j[k]||(j[k]=i?{}:{toJSON:m.noop}),("object"==typeof b||"function"==typeof b)&&(e?j[k]=m.extend(j[k],b):j[k].data=m.extend(j[k].data,b)),g=j[k],e||(g.data||(g.data={}),g=g.data),void 0!==d&&(g[m.camelCase(b)]=d),"string"==typeof b?(f=g[b],null==f&&(f=g[m.camelCase(b)])):f=g,f}}function R(a,b,c){if(m.acceptData(a)){var d,e,f=a.nodeType,g=f?m.cache:a,h=f?a[m.expando]:m.expando;if(g[h]){if(b&&(d=c?g[h]:g[h].data)){m.isArray(b)?b=b.concat(m.map(b,m.camelCase)):b in d?b=[b]:(b=m.camelCase(b),b=b in d?[b]:b.split(" ")),e=b.length;while(e--)delete d[b[e]];if(c?!P(d):!m.isEmptyObject(d))return}(c||(delete g[h].data,P(g[h])))&&(f?m.cleanData([a],!0):k.deleteExpando||g!=g.window?delete g[h]:g[h]=null)}}}m.extend({cache:{},noData:{"applet ":!0,"embed ":!0,"object ":"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"},hasData:function(a){return a=a.nodeType?m.cache[a[m.expando]]:a[m.expando],!!a&&!P(a)},data:function(a,b,c){return Q(a,b,c)},removeData:function(a,b){return R(a,b)},_data:function(a,b,c){return Q(a,b,c,!0)},_removeData:function(a,b){return R(a,b,!0)}}),m.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=m.data(f),1===f.nodeType&&!m._data(f,"parsedAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.indexOf("data-")&&(d=m.camelCase(d.slice(5)),O(f,d,e[d])));m._data(f,"parsedAttrs",!0)}return e}return"object"==typeof a?this.each(function(){m.data(this,a)}):arguments.length>1?this.each(function(){m.data(this,a,b)}):f?O(f,a,m.data(f,a)):void 0},removeData:function(a){return this.each(function(){m.removeData(this,a)})}}),m.extend({queue:function(a,b,c){var d;return a?(b=(b||"fx")+"queue",d=m._data(a,b),c&&(!d||m.isArray(c)?d=m._data(a,b,m.makeArray(c)):d.push(c)),d||[]):void 0},dequeue:function(a,b){b=b||"fx";var c=m.queue(a,b),d=c.length,e=c.shift(),f=m._queueHooks(a,b),g=function(){m.dequeue(a,b)};"inprogress"===e&&(e=c.shift(),d--),e&&("fx"===b&&c.unshift("inprogress"),delete f.stop,e.call(a,g,f)),!d&&f&&f.empty.fire()},_queueHooks:function(a,b){var c=b+"queueHooks";return m._data(a,c)||m._data(a,c,{empty:m.Callbacks("once memory").add(function(){m._removeData(a,b+"queue"),m._removeData(a,c)})})}}),m.fn.extend({queue:function(a,b){var c=2;return"string"!=typeof a&&(b=a,a="fx",c--),arguments.length<c?m.queue(this[0],a):void 0===b?this:this.each(function(){var c=m.queue(this,a,b);m._queueHooks(this,a),"fx"===a&&"inprogress"!==c[0]&&m.dequeue(this,a)})},dequeue:function(a){return this.each(function(){m.dequeue(this,a)})},clearQueue:function(a){return this.queue(a||"fx",[])},promise:function(a,b){var c,d=1,e=m.Deferred(),f=this,g=this.length,h=function(){--d||e.resolveWith(f,[f])};"string"!=typeof a&&(b=a,a=void 0),a=a||"fx";while(g--)c=m._data(f[g],a+"queueHooks"),c&&c.empty&&(d++,c.empty.add(h));return h(),e.promise(b)}});var S=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,T=["Top","Right","Bottom","Left"],U=function(a,b){return a=b||a,"none"===m.css(a,"display")||!m.contains(a.ownerDocument,a)},V=m.access=function(a,b,c,d,e,f,g){var h=0,i=a.length,j=null==c;if("object"===m.type(c)){e=!0;for(h in c)m.access(a,b,h,c[h],!0,f,g)}else if(void 0!==d&&(e=!0,m.isFunction(d)||(g=!0),j&&(g?(b.call(a,d),b=null):(j=b,b=function(a,b,c){return j.call(m(a),c)})),b))for(;i>h;h++)b(a[h],c,g?d:d.call(a[h],h,b(a[h],c)));return e?a:j?b.call(a):i?b(a[0],c):f},W=/^(?:checkbox|radio)$/i;!function(){var a=y.createElement("input"),b=y.createElement("div"),c=y.createDocumentFragment();if(b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",k.leadingWhitespace=3===b.firstChild.nodeType,k.tbody=!b.getElementsByTagName("tbody").length,k.htmlSerialize=!!b.getElementsByTagName("link").length,k.html5Clone="<:nav></:nav>"!==y.createElement("nav").cloneNode(!0).outerHTML,a.type="checkbox",a.checked=!0,c.appendChild(a),k.appendChecked=a.checked,b.innerHTML="<textarea>x</textarea>",k.noCloneChecked=!!b.cloneNode(!0).lastChild.defaultValue,c.appendChild(b),b.innerHTML="<input type='radio' checked='checked' name='t'/>",k.checkClone=b.cloneNode(!0).cloneNode(!0).lastChild.checked,k.noCloneEvent=!0,b.attachEvent&&(b.attachEvent("onclick",function(){k.noCloneEvent=!1}),b.cloneNode(!0).click()),null==k.deleteExpando){k.deleteExpando=!0;try{delete b.test}catch(d){k.deleteExpando=!1}}}(),function(){var b,c,d=y.createElement("div");for(b in{submit:!0,change:!0,focusin:!0})c="on"+b,(k[b+"Bubbles"]=c in a)||(d.setAttribute(c,"t"),k[b+"Bubbles"]=d.attributes[c].expando===!1);d=null}();var X=/^(?:input|select|textarea)$/i,Y=/^key/,Z=/^(?:mouse|pointer|contextmenu)|click/,$=/^(?:focusinfocus|focusoutblur)$/,_=/^([^.]*)(?:\.(.+)|)$/;function ab(){return!0}function bb(){return!1}function cb(){try{return y.activeElement}catch(a){}}m.event={global:{},add:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m._data(a);if(r){c.handler&&(i=c,c=i.handler,e=i.selector),c.guid||(c.guid=m.guid++),(g=r.events)||(g=r.events={}),(k=r.handle)||(k=r.handle=function(a){return typeof m===K||a&&m.event.triggered===a.type?void 0:m.event.dispatch.apply(k.elem,arguments)},k.elem=a),b=(b||"").match(E)||[""],h=b.length;while(h--)f=_.exec(b[h])||[],o=q=f[1],p=(f[2]||"").split(".").sort(),o&&(j=m.event.special[o]||{},o=(e?j.delegateType:j.bindType)||o,j=m.event.special[o]||{},l=m.extend({type:o,origType:q,data:d,handler:c,guid:c.guid,selector:e,needsContext:e&&m.expr.match.needsContext.test(e),namespace:p.join(".")},i),(n=g[o])||(n=g[o]=[],n.delegateCount=0,j.setup&&j.setup.call(a,d,p,k)!==!1||(a.addEventListener?a.addEventListener(o,k,!1):a.attachEvent&&a.attachEvent("on"+o,k))),j.add&&(j.add.call(a,l),l.handler.guid||(l.handler.guid=c.guid)),e?n.splice(n.delegateCount++,0,l):n.push(l),m.event.global[o]=!0);a=null}},remove:function(a,b,c,d,e){var f,g,h,i,j,k,l,n,o,p,q,r=m.hasData(a)&&m._data(a);if(r&&(k=r.events)){b=(b||"").match(E)||[""],j=b.length;while(j--)if(h=_.exec(b[j])||[],o=q=h[1],p=(h[2]||"").split(".").sort(),o){l=m.event.special[o]||{},o=(d?l.delegateType:l.bindType)||o,n=k[o]||[],h=h[2]&&new RegExp("(^|\\.)"+p.join("\\.(?:.*\\.|)")+"(\\.|$)"),i=f=n.length;while(f--)g=n[f],!e&&q!==g.origType||c&&c.guid!==g.guid||h&&!h.test(g.namespace)||d&&d!==g.selector&&("**"!==d||!g.selector)||(n.splice(f,1),g.selector&&n.delegateCount--,l.remove&&l.remove.call(a,g));i&&!n.length&&(l.teardown&&l.teardown.call(a,p,r.handle)!==!1||m.removeEvent(a,o,r.handle),delete k[o])}else for(o in k)m.event.remove(a,o+b[j],c,d,!0);m.isEmptyObject(k)&&(delete r.handle,m._removeData(a,"events"))}},trigger:function(b,c,d,e){var f,g,h,i,k,l,n,o=[d||y],p=j.call(b,"type")?b.type:b,q=j.call(b,"namespace")?b.namespace.split("."):[];if(h=l=d=d||y,3!==d.nodeType&&8!==d.nodeType&&!$.test(p+m.event.triggered)&&(p.indexOf(".")>=0&&(q=p.split("."),p=q.shift(),q.sort()),g=p.indexOf(":")<0&&"on"+p,b=b[m.expando]?b:new m.Event(p,"object"==typeof b&&b),b.isTrigger=e?2:3,b.namespace=q.join("."),b.namespace_re=b.namespace?new RegExp("(^|\\.)"+q.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,b.result=void 0,b.target||(b.target=d),c=null==c?[b]:m.makeArray(c,[b]),k=m.event.special[p]||{},e||!k.trigger||k.trigger.apply(d,c)!==!1)){if(!e&&!k.noBubble&&!m.isWindow(d)){for(i=k.delegateType||p,$.test(i+p)||(h=h.parentNode);h;h=h.parentNode)o.push(h),l=h;l===(d.ownerDocument||y)&&o.push(l.defaultView||l.parentWindow||a)}n=0;while((h=o[n++])&&!b.isPropagationStopped())b.type=n>1?i:k.bindType||p,f=(m._data(h,"events")||{})[b.type]&&m._data(h,"handle"),f&&f.apply(h,c),f=g&&h[g],f&&f.apply&&m.acceptData(h)&&(b.result=f.apply(h,c),b.result===!1&&b.preventDefault());if(b.type=p,!e&&!b.isDefaultPrevented()&&(!k._default||k._default.apply(o.pop(),c)===!1)&&m.acceptData(d)&&g&&d[p]&&!m.isWindow(d)){l=d[g],l&&(d[g]=null),m.event.triggered=p;try{d[p]()}catch(r){}m.event.triggered=void 0,l&&(d[g]=l)}return b.result}},dispatch:function(a){a=m.event.fix(a);var b,c,e,f,g,h=[],i=d.call(arguments),j=(m._data(this,"events")||{})[a.type]||[],k=m.event.special[a.type]||{};if(i[0]=a,a.delegateTarget=this,!k.preDispatch||k.preDispatch.call(this,a)!==!1){h=m.event.handlers.call(this,a,j),b=0;while((f=h[b++])&&!a.isPropagationStopped()){a.currentTarget=f.elem,g=0;while((e=f.handlers[g++])&&!a.isImmediatePropagationStopped())(!a.namespace_re||a.namespace_re.test(e.namespace))&&(a.handleObj=e,a.data=e.data,c=((m.event.special[e.origType]||{}).handle||e.handler).apply(f.elem,i),void 0!==c&&(a.result=c)===!1&&(a.preventDefault(),a.stopPropagation()))}return k.postDispatch&&k.postDispatch.call(this,a),a.result}},handlers:function(a,b){var c,d,e,f,g=[],h=b.delegateCount,i=a.target;if(h&&i.nodeType&&(!a.button||"click"!==a.type))for(;i!=this;i=i.parentNode||this)if(1===i.nodeType&&(i.disabled!==!0||"click"!==a.type)){for(e=[],f=0;h>f;f++)d=b[f],c=d.selector+" ",void 0===e[c]&&(e[c]=d.needsContext?m(c,this).index(i)>=0:m.find(c,this,null,[i]).length),e[c]&&e.push(d);e.length&&g.push({elem:i,handlers:e})}return h<b.length&&g.push({elem:this,handlers:b.slice(h)}),g},fix:function(a){if(a[m.expando])return a;var b,c,d,e=a.type,f=a,g=this.fixHooks[e];g||(this.fixHooks[e]=g=Z.test(e)?this.mouseHooks:Y.test(e)?this.keyHooks:{}),d=g.props?this.props.concat(g.props):this.props,a=new m.Event(f),b=d.length;while(b--)c=d[b],a[c]=f[c];return a.target||(a.target=f.srcElement||y),3===a.target.nodeType&&(a.target=a.target.parentNode),a.metaKey=!!a.metaKey,g.filter?g.filter(a,f):a},props:"altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),fixHooks:{},keyHooks:{props:"char charCode key keyCode".split(" "),filter:function(a,b){return null==a.which&&(a.which=null!=b.charCode?b.charCode:b.keyCode),a}},mouseHooks:{props:"button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),filter:function(a,b){var c,d,e,f=b.button,g=b.fromElement;return null==a.pageX&&null!=b.clientX&&(d=a.target.ownerDocument||y,e=d.documentElement,c=d.body,a.pageX=b.clientX+(e&&e.scrollLeft||c&&c.scrollLeft||0)-(e&&e.clientLeft||c&&c.clientLeft||0),a.pageY=b.clientY+(e&&e.scrollTop||c&&c.scrollTop||0)-(e&&e.clientTop||c&&c.clientTop||0)),!a.relatedTarget&&g&&(a.relatedTarget=g===a.target?b.toElement:g),a.which||void 0===f||(a.which=1&f?1:2&f?3:4&f?2:0),a}},special:{load:{noBubble:!0},focus:{trigger:function(){if(this!==cb()&&this.focus)try{return this.focus(),!1}catch(a){}},delegateType:"focusin"},blur:{trigger:function(){return this===cb()&&this.blur?(this.blur(),!1):void 0},delegateType:"focusout"},click:{trigger:function(){return m.nodeName(this,"input")&&"checkbox"===this.type&&this.click?(this.click(),!1):void 0},_default:function(a){return m.nodeName(a.target,"a")}},beforeunload:{postDispatch:function(a){void 0!==a.result&&a.originalEvent&&(a.originalEvent.returnValue=a.result)}}},simulate:function(a,b,c,d){var e=m.extend(new m.Event,c,{type:a,isSimulated:!0,originalEvent:{}});d?m.event.trigger(e,null,b):m.event.dispatch.call(b,e),e.isDefaultPrevented()&&c.preventDefault()}},m.removeEvent=y.removeEventListener?function(a,b,c){a.removeEventListener&&a.removeEventListener(b,c,!1)}:function(a,b,c){var d="on"+b;a.detachEvent&&(typeof a[d]===K&&(a[d]=null),a.detachEvent(d,c))},m.Event=function(a,b){return this instanceof m.Event?(a&&a.type?(this.originalEvent=a,this.type=a.type,this.isDefaultPrevented=a.defaultPrevented||void 0===a.defaultPrevented&&a.returnValue===!1?ab:bb):this.type=a,b&&m.extend(this,b),this.timeStamp=a&&a.timeStamp||m.now(),void(this[m.expando]=!0)):new m.Event(a,b)},m.Event.prototype={isDefaultPrevented:bb,isPropagationStopped:bb,isImmediatePropagationStopped:bb,preventDefault:function(){var a=this.originalEvent;this.isDefaultPrevented=ab,a&&(a.preventDefault?a.preventDefault():a.returnValue=!1)},stopPropagation:function(){var a=this.originalEvent;this.isPropagationStopped=ab,a&&(a.stopPropagation&&a.stopPropagation(),a.cancelBubble=!0)},stopImmediatePropagation:function(){var a=this.originalEvent;this.isImmediatePropagationStopped=ab,a&&a.stopImmediatePropagation&&a.stopImmediatePropagation(),this.stopPropagation()}},m.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(a,b){m.event.special[a]={delegateType:b,bindType:b,handle:function(a){var c,d=this,e=a.relatedTarget,f=a.handleObj;return(!e||e!==d&&!m.contains(d,e))&&(a.type=f.origType,c=f.handler.apply(this,arguments),a.type=b),c}}}),k.submitBubbles||(m.event.special.submit={setup:function(){return m.nodeName(this,"form")?!1:void m.event.add(this,"click._submit keypress._submit",function(a){var b=a.target,c=m.nodeName(b,"input")||m.nodeName(b,"button")?b.form:void 0;c&&!m._data(c,"submitBubbles")&&(m.event.add(c,"submit._submit",function(a){a._submit_bubble=!0}),m._data(c,"submitBubbles",!0))})},postDispatch:function(a){a._submit_bubble&&(delete a._submit_bubble,this.parentNode&&!a.isTrigger&&m.event.simulate("submit",this.parentNode,a,!0))},teardown:function(){return m.nodeName(this,"form")?!1:void m.event.remove(this,"._submit")}}),k.changeBubbles||(m.event.special.change={setup:function(){return X.test(this.nodeName)?(("checkbox"===this.type||"radio"===this.type)&&(m.event.add(this,"propertychange._change",function(a){"checked"===a.originalEvent.propertyName&&(this._just_changed=!0)}),m.event.add(this,"click._change",function(a){this._just_changed&&!a.isTrigger&&(this._just_changed=!1),m.event.simulate("change",this,a,!0)})),!1):void m.event.add(this,"beforeactivate._change",function(a){var b=a.target;X.test(b.nodeName)&&!m._data(b,"changeBubbles")&&(m.event.add(b,"change._change",function(a){!this.parentNode||a.isSimulated||a.isTrigger||m.event.simulate("change",this.parentNode,a,!0)}),m._data(b,"changeBubbles",!0))})},handle:function(a){var b=a.target;return this!==b||a.isSimulated||a.isTrigger||"radio"!==b.type&&"checkbox"!==b.type?a.handleObj.handler.apply(this,arguments):void 0},teardown:function(){return m.event.remove(this,"._change"),!X.test(this.nodeName)}}),k.focusinBubbles||m.each({focus:"focusin",blur:"focusout"},function(a,b){var c=function(a){m.event.simulate(b,a.target,m.event.fix(a),!0)};m.event.special[b]={setup:function(){var d=this.ownerDocument||this,e=m._data(d,b);e||d.addEventListener(a,c,!0),m._data(d,b,(e||0)+1)},teardown:function(){var d=this.ownerDocument||this,e=m._data(d,b)-1;e?m._data(d,b,e):(d.removeEventListener(a,c,!0),m._removeData(d,b))}}}),m.fn.extend({on:function(a,b,c,d,e){var f,g;if("object"==typeof a){"string"!=typeof b&&(c=c||b,b=void 0);for(f in a)this.on(f,b,c,a[f],e);return this}if(null==c&&null==d?(d=b,c=b=void 0):null==d&&("string"==typeof b?(d=c,c=void 0):(d=c,c=b,b=void 0)),d===!1)d=bb;else if(!d)return this;return 1===e&&(g=d,d=function(a){return m().off(a),g.apply(this,arguments)},d.guid=g.guid||(g.guid=m.guid++)),this.each(function(){m.event.add(this,a,d,c,b)})},one:function(a,b,c,d){return this.on(a,b,c,d,1)},off:function(a,b,c){var d,e;if(a&&a.preventDefault&&a.handleObj)return d=a.handleObj,m(a.delegateTarget).off(d.namespace?d.origType+"."+d.namespace:d.origType,d.selector,d.handler),this;if("object"==typeof a){for(e in a)this.off(e,b,a[e]);return this}return(b===!1||"function"==typeof b)&&(c=b,b=void 0),c===!1&&(c=bb),this.each(function(){m.event.remove(this,a,c,b)})},trigger:function(a,b){return this.each(function(){m.event.trigger(a,b,this)})},triggerHandler:function(a,b){var c=this[0];return c?m.event.trigger(a,b,c,!0):void 0}});function db(a){var b=eb.split("|"),c=a.createDocumentFragment();if(c.createElement)while(b.length)c.createElement(b.pop());return c}var eb="abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",fb=/ jQuery\d+="(?:null|\d+)"/g,gb=new RegExp("<(?:"+eb+")[\\s/>]","i"),hb=/^\s+/,ib=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,jb=/<([\w:]+)/,kb=/<tbody/i,lb=/<|&#?\w+;/,mb=/<(?:script|style|link)/i,nb=/checked\s*(?:[^=]|=\s*.checked.)/i,ob=/^$|\/(?:java|ecma)script/i,pb=/^true\/(.*)/,qb=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,rb={option:[1,"<select multiple='multiple'>","</select>"],legend:[1,"<fieldset>","</fieldset>"],area:[1,"<map>","</map>"],param:[1,"<object>","</object>"],thead:[1,"<table>","</table>"],tr:[2,"<table><tbody>","</tbody></table>"],col:[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:k.htmlSerialize?[0,"",""]:[1,"X<div>","</div>"]},sb=db(y),tb=sb.appendChild(y.createElement("div"));rb.optgroup=rb.option,rb.tbody=rb.tfoot=rb.colgroup=rb.caption=rb.thead,rb.th=rb.td;function ub(a,b){var c,d,e=0,f=typeof a.getElementsByTagName!==K?a.getElementsByTagName(b||"*"):typeof a.querySelectorAll!==K?a.querySelectorAll(b||"*"):void 0;if(!f)for(f=[],c=a.childNodes||a;null!=(d=c[e]);e++)!b||m.nodeName(d,b)?f.push(d):m.merge(f,ub(d,b));return void 0===b||b&&m.nodeName(a,b)?m.merge([a],f):f}function vb(a){W.test(a.type)&&(a.defaultChecked=a.checked)}function wb(a,b){return m.nodeName(a,"table")&&m.nodeName(11!==b.nodeType?b:b.firstChild,"tr")?a.getElementsByTagName("tbody")[0]||a.appendChild(a.ownerDocument.createElement("tbody")):a}function xb(a){return a.type=(null!==m.find.attr(a,"type"))+"/"+a.type,a}function yb(a){var b=pb.exec(a.type);return b?a.type=b[1]:a.removeAttribute("type"),a}function zb(a,b){for(var c,d=0;null!=(c=a[d]);d++)m._data(c,"globalEval",!b||m._data(b[d],"globalEval"))}function Ab(a,b){if(1===b.nodeType&&m.hasData(a)){var c,d,e,f=m._data(a),g=m._data(b,f),h=f.events;if(h){delete g.handle,g.events={};for(c in h)for(d=0,e=h[c].length;e>d;d++)m.event.add(b,c,h[c][d])}g.data&&(g.data=m.extend({},g.data))}}function Bb(a,b){var c,d,e;if(1===b.nodeType){if(c=b.nodeName.toLowerCase(),!k.noCloneEvent&&b[m.expando]){e=m._data(b);for(d in e.events)m.removeEvent(b,d,e.handle);b.removeAttribute(m.expando)}"script"===c&&b.text!==a.text?(xb(b).text=a.text,yb(b)):"object"===c?(b.parentNode&&(b.outerHTML=a.outerHTML),k.html5Clone&&a.innerHTML&&!m.trim(b.innerHTML)&&(b.innerHTML=a.innerHTML)):"input"===c&&W.test(a.type)?(b.defaultChecked=b.checked=a.checked,b.value!==a.value&&(b.value=a.value)):"option"===c?b.defaultSelected=b.selected=a.defaultSelected:("input"===c||"textarea"===c)&&(b.defaultValue=a.defaultValue)}}m.extend({clone:function(a,b,c){var d,e,f,g,h,i=m.contains(a.ownerDocument,a);if(k.html5Clone||m.isXMLDoc(a)||!gb.test("<"+a.nodeName+">")?f=a.cloneNode(!0):(tb.innerHTML=a.outerHTML,tb.removeChild(f=tb.firstChild)),!(k.noCloneEvent&&k.noCloneChecked||1!==a.nodeType&&11!==a.nodeType||m.isXMLDoc(a)))for(d=ub(f),h=ub(a),g=0;null!=(e=h[g]);++g)d[g]&&Bb(e,d[g]);if(b)if(c)for(h=h||ub(a),d=d||ub(f),g=0;null!=(e=h[g]);g++)Ab(e,d[g]);else Ab(a,f);return d=ub(f,"script"),d.length>0&&zb(d,!i&&ub(a,"script")),d=h=e=null,f},buildFragment:function(a,b,c,d){for(var e,f,g,h,i,j,l,n=a.length,o=db(b),p=[],q=0;n>q;q++)if(f=a[q],f||0===f)if("object"===m.type(f))m.merge(p,f.nodeType?[f]:f);else if(lb.test(f)){h=h||o.appendChild(b.createElement("div")),i=(jb.exec(f)||["",""])[1].toLowerCase(),l=rb[i]||rb._default,h.innerHTML=l[1]+f.replace(ib,"<$1></$2>")+l[2],e=l[0];while(e--)h=h.lastChild;if(!k.leadingWhitespace&&hb.test(f)&&p.push(b.createTextNode(hb.exec(f)[0])),!k.tbody){f="table"!==i||kb.test(f)?"<table>"!==l[1]||kb.test(f)?0:h:h.firstChild,e=f&&f.childNodes.length;while(e--)m.nodeName(j=f.childNodes[e],"tbody")&&!j.childNodes.length&&f.removeChild(j)}m.merge(p,h.childNodes),h.textContent="";while(h.firstChild)h.removeChild(h.firstChild);h=o.lastChild}else p.push(b.createTextNode(f));h&&o.removeChild(h),k.appendChecked||m.grep(ub(p,"input"),vb),q=0;while(f=p[q++])if((!d||-1===m.inArray(f,d))&&(g=m.contains(f.ownerDocument,f),h=ub(o.appendChild(f),"script"),g&&zb(h),c)){e=0;while(f=h[e++])ob.test(f.type||"")&&c.push(f)}return h=null,o},cleanData:function(a,b){for(var d,e,f,g,h=0,i=m.expando,j=m.cache,l=k.deleteExpando,n=m.event.special;null!=(d=a[h]);h++)if((b||m.acceptData(d))&&(f=d[i],g=f&&j[f])){if(g.events)for(e in g.events)n[e]?m.event.remove(d,e):m.removeEvent(d,e,g.handle);j[f]&&(delete j[f],l?delete d[i]:typeof d.removeAttribute!==K?d.removeAttribute(i):d[i]=null,c.push(f))}}}),m.fn.extend({text:function(a){return V(this,function(a){return void 0===a?m.text(this):this.empty().append((this[0]&&this[0].ownerDocument||y).createTextNode(a))},null,a,arguments.length)},append:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.appendChild(a)}})},prepend:function(){return this.domManip(arguments,function(a){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var b=wb(this,a);b.insertBefore(a,b.firstChild)}})},before:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this)})},after:function(){return this.domManip(arguments,function(a){this.parentNode&&this.parentNode.insertBefore(a,this.nextSibling)})},remove:function(a,b){for(var c,d=a?m.filter(a,this):this,e=0;null!=(c=d[e]);e++)b||1!==c.nodeType||m.cleanData(ub(c)),c.parentNode&&(b&&m.contains(c.ownerDocument,c)&&zb(ub(c,"script")),c.parentNode.removeChild(c));return this},empty:function(){for(var a,b=0;null!=(a=this[b]);b++){1===a.nodeType&&m.cleanData(ub(a,!1));while(a.firstChild)a.removeChild(a.firstChild);a.options&&m.nodeName(a,"select")&&(a.options.length=0)}return this},clone:function(a,b){return a=null==a?!1:a,b=null==b?a:b,this.map(function(){return m.clone(this,a,b)})},html:function(a){return V(this,function(a){var b=this[0]||{},c=0,d=this.length;if(void 0===a)return 1===b.nodeType?b.innerHTML.replace(fb,""):void 0;if(!("string"!=typeof a||mb.test(a)||!k.htmlSerialize&&gb.test(a)||!k.leadingWhitespace&&hb.test(a)||rb[(jb.exec(a)||["",""])[1].toLowerCase()])){a=a.replace(ib,"<$1></$2>");try{for(;d>c;c++)b=this[c]||{},1===b.nodeType&&(m.cleanData(ub(b,!1)),b.innerHTML=a);b=0}catch(e){}}b&&this.empty().append(a)},null,a,arguments.length)},replaceWith:function(){var a=arguments[0];return this.domManip(arguments,function(b){a=this.parentNode,m.cleanData(ub(this)),a&&a.replaceChild(b,this)}),a&&(a.length||a.nodeType)?this:this.remove()},detach:function(a){return this.remove(a,!0)},domManip:function(a,b){a=e.apply([],a);var c,d,f,g,h,i,j=0,l=this.length,n=this,o=l-1,p=a[0],q=m.isFunction(p);if(q||l>1&&"string"==typeof p&&!k.checkClone&&nb.test(p))return this.each(function(c){var d=n.eq(c);q&&(a[0]=p.call(this,c,d.html())),d.domManip(a,b)});if(l&&(i=m.buildFragment(a,this[0].ownerDocument,!1,this),c=i.firstChild,1===i.childNodes.length&&(i=c),c)){for(g=m.map(ub(i,"script"),xb),f=g.length;l>j;j++)d=i,j!==o&&(d=m.clone(d,!0,!0),f&&m.merge(g,ub(d,"script"))),b.call(this[j],d,j);if(f)for(h=g[g.length-1].ownerDocument,m.map(g,yb),j=0;f>j;j++)d=g[j],ob.test(d.type||"")&&!m._data(d,"globalEval")&&m.contains(h,d)&&(d.src?m._evalUrl&&m._evalUrl(d.src):m.globalEval((d.text||d.textContent||d.innerHTML||"").replace(qb,"")));i=c=null}return this}}),m.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(a,b){m.fn[a]=function(a){for(var c,d=0,e=[],g=m(a),h=g.length-1;h>=d;d++)c=d===h?this:this.clone(!0),m(g[d])[b](c),f.apply(e,c.get());return this.pushStack(e)}});var Cb,Db={};function Eb(b,c){var d,e=m(c.createElement(b)).appendTo(c.body),f=a.getDefaultComputedStyle&&(d=a.getDefaultComputedStyle(e[0]))?d.display:m.css(e[0],"display");return e.detach(),f}function Fb(a){var b=y,c=Db[a];return c||(c=Eb(a,b),"none"!==c&&c||(Cb=(Cb||m("<iframe frameborder='0' width='0' height='0'/>")).appendTo(b.documentElement),b=(Cb[0].contentWindow||Cb[0].contentDocument).document,b.write(),b.close(),c=Eb(a,b),Cb.detach()),Db[a]=c),c}!function(){var a;k.shrinkWrapBlocks=function(){if(null!=a)return a;a=!1;var b,c,d;return c=y.getElementsByTagName("body")[0],c&&c.style?(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),typeof b.style.zoom!==K&&(b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:1px;width:1px;zoom:1",b.appendChild(y.createElement("div")).style.width="5px",a=3!==b.offsetWidth),c.removeChild(d),a):void 0}}();var Gb=/^margin/,Hb=new RegExp("^("+S+")(?!px)[a-z%]+$","i"),Ib,Jb,Kb=/^(top|right|bottom|left)$/;a.getComputedStyle?(Ib=function(a){return a.ownerDocument.defaultView.getComputedStyle(a,null)},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c.getPropertyValue(b)||c[b]:void 0,c&&(""!==g||m.contains(a.ownerDocument,a)||(g=m.style(a,b)),Hb.test(g)&&Gb.test(b)&&(d=h.width,e=h.minWidth,f=h.maxWidth,h.minWidth=h.maxWidth=h.width=g,g=c.width,h.width=d,h.minWidth=e,h.maxWidth=f)),void 0===g?g:g+""}):y.documentElement.currentStyle&&(Ib=function(a){return a.currentStyle},Jb=function(a,b,c){var d,e,f,g,h=a.style;return c=c||Ib(a),g=c?c[b]:void 0,null==g&&h&&h[b]&&(g=h[b]),Hb.test(g)&&!Kb.test(b)&&(d=h.left,e=a.runtimeStyle,f=e&&e.left,f&&(e.left=a.currentStyle.left),h.left="fontSize"===b?"1em":g,g=h.pixelLeft+"px",h.left=d,f&&(e.left=f)),void 0===g?g:g+""||"auto"});function Lb(a,b){return{get:function(){var c=a();if(null!=c)return c?void delete this.get:(this.get=b).apply(this,arguments)}}}!function(){var b,c,d,e,f,g,h;if(b=y.createElement("div"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=d&&d.style){c.cssText="float:left;opacity:.5",k.opacity="0.5"===c.opacity,k.cssFloat=!!c.cssFloat,b.style.backgroundClip="content-box",b.cloneNode(!0).style.backgroundClip="",k.clearCloneStyle="content-box"===b.style.backgroundClip,k.boxSizing=""===c.boxSizing||""===c.MozBoxSizing||""===c.WebkitBoxSizing,m.extend(k,{reliableHiddenOffsets:function(){return null==g&&i(),g},boxSizingReliable:function(){return null==f&&i(),f},pixelPosition:function(){return null==e&&i(),e},reliableMarginRight:function(){return null==h&&i(),h}});function i(){var b,c,d,i;c=y.getElementsByTagName("body")[0],c&&c.style&&(b=y.createElement("div"),d=y.createElement("div"),d.style.cssText="position:absolute;border:0;width:0;height:0;top:0;left:-9999px",c.appendChild(d).appendChild(b),b.style.cssText="-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;display:block;margin-top:1%;top:1%;border:1px;padding:1px;width:4px;position:absolute",e=f=!1,h=!0,a.getComputedStyle&&(e="1%"!==(a.getComputedStyle(b,null)||{}).top,f="4px"===(a.getComputedStyle(b,null)||{width:"4px"}).width,i=b.appendChild(y.createElement("div")),i.style.cssText=b.style.cssText="-webkit-box-sizing:content-box;-moz-box-sizing:content-box;box-sizing:content-box;display:block;margin:0;border:0;padding:0",i.style.marginRight=i.style.width="0",b.style.width="1px",h=!parseFloat((a.getComputedStyle(i,null)||{}).marginRight)),b.innerHTML="<table><tr><td></td><td>t</td></tr></table>",i=b.getElementsByTagName("td"),i[0].style.cssText="margin:0;border:0;padding:0;display:none",g=0===i[0].offsetHeight,g&&(i[0].style.display="",i[1].style.display="none",g=0===i[0].offsetHeight),c.removeChild(d))}}}(),m.swap=function(a,b,c,d){var e,f,g={};for(f in b)g[f]=a.style[f],a.style[f]=b[f];e=c.apply(a,d||[]);for(f in b)a.style[f]=g[f];return e};var Mb=/alpha\([^)]*\)/i,Nb=/opacity\s*=\s*([^)]*)/,Ob=/^(none|table(?!-c[ea]).+)/,Pb=new RegExp("^("+S+")(.*)$","i"),Qb=new RegExp("^([+-])=("+S+")","i"),Rb={position:"absolute",visibility:"hidden",display:"block"},Sb={letterSpacing:"0",fontWeight:"400"},Tb=["Webkit","O","Moz","ms"];function Ub(a,b){if(b in a)return b;var c=b.charAt(0).toUpperCase()+b.slice(1),d=b,e=Tb.length;while(e--)if(b=Tb[e]+c,b in a)return b;return d}function Vb(a,b){for(var c,d,e,f=[],g=0,h=a.length;h>g;g++)d=a[g],d.style&&(f[g]=m._data(d,"olddisplay"),c=d.style.display,b?(f[g]||"none"!==c||(d.style.display=""),""===d.style.display&&U(d)&&(f[g]=m._data(d,"olddisplay",Fb(d.nodeName)))):(e=U(d),(c&&"none"!==c||!e)&&m._data(d,"olddisplay",e?c:m.css(d,"display"))));for(g=0;h>g;g++)d=a[g],d.style&&(b&&"none"!==d.style.display&&""!==d.style.display||(d.style.display=b?f[g]||"":"none"));return a}function Wb(a,b,c){var d=Pb.exec(b);return d?Math.max(0,d[1]-(c||0))+(d[2]||"px"):b}function Xb(a,b,c,d,e){for(var f=c===(d?"border":"content")?4:"width"===b?1:0,g=0;4>f;f+=2)"margin"===c&&(g+=m.css(a,c+T[f],!0,e)),d?("content"===c&&(g-=m.css(a,"padding"+T[f],!0,e)),"margin"!==c&&(g-=m.css(a,"border"+T[f]+"Width",!0,e))):(g+=m.css(a,"padding"+T[f],!0,e),"padding"!==c&&(g+=m.css(a,"border"+T[f]+"Width",!0,e)));return g}function Yb(a,b,c){var d=!0,e="width"===b?a.offsetWidth:a.offsetHeight,f=Ib(a),g=k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,f);if(0>=e||null==e){if(e=Jb(a,b,f),(0>e||null==e)&&(e=a.style[b]),Hb.test(e))return e;d=g&&(k.boxSizingReliable()||e===a.style[b]),e=parseFloat(e)||0}return e+Xb(a,b,c||(g?"border":"content"),d,f)+"px"}m.extend({cssHooks:{opacity:{get:function(a,b){if(b){var c=Jb(a,"opacity");return""===c?"1":c}}}},cssNumber:{columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{"float":k.cssFloat?"cssFloat":"styleFloat"},style:function(a,b,c,d){if(a&&3!==a.nodeType&&8!==a.nodeType&&a.style){var e,f,g,h=m.camelCase(b),i=a.style;if(b=m.cssProps[h]||(m.cssProps[h]=Ub(i,h)),g=m.cssHooks[b]||m.cssHooks[h],void 0===c)return g&&"get"in g&&void 0!==(e=g.get(a,!1,d))?e:i[b];if(f=typeof c,"string"===f&&(e=Qb.exec(c))&&(c=(e[1]+1)*e[2]+parseFloat(m.css(a,b)),f="number"),null!=c&&c===c&&("number"!==f||m.cssNumber[h]||(c+="px"),k.clearCloneStyle||""!==c||0!==b.indexOf("background")||(i[b]="inherit"),!(g&&"set"in g&&void 0===(c=g.set(a,c,d)))))try{i[b]=c}catch(j){}}},css:function(a,b,c,d){var e,f,g,h=m.camelCase(b);return b=m.cssProps[h]||(m.cssProps[h]=Ub(a.style,h)),g=m.cssHooks[b]||m.cssHooks[h],g&&"get"in g&&(f=g.get(a,!0,c)),void 0===f&&(f=Jb(a,b,d)),"normal"===f&&b in Sb&&(f=Sb[b]),""===c||c?(e=parseFloat(f),c===!0||m.isNumeric(e)?e||0:f):f}}),m.each(["height","width"],function(a,b){m.cssHooks[b]={get:function(a,c,d){return c?Ob.test(m.css(a,"display"))&&0===a.offsetWidth?m.swap(a,Rb,function(){return Yb(a,b,d)}):Yb(a,b,d):void 0},set:function(a,c,d){var e=d&&Ib(a);return Wb(a,c,d?Xb(a,b,d,k.boxSizing&&"border-box"===m.css(a,"boxSizing",!1,e),e):0)}}}),k.opacity||(m.cssHooks.opacity={get:function(a,b){return Nb.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?.01*parseFloat(RegExp.$1)+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=m.isNumeric(b)?"alpha(opacity="+100*b+")":"",f=d&&d.filter||c.filter||"";c.zoom=1,(b>=1||""===b)&&""===m.trim(f.replace(Mb,""))&&c.removeAttribute&&(c.removeAttribute("filter"),""===b||d&&!d.filter)||(c.filter=Mb.test(f)?f.replace(Mb,e):f+" "+e)}}),m.cssHooks.marginRight=Lb(k.reliableMarginRight,function(a,b){return b?m.swap(a,{display:"inline-block"},Jb,[a,"marginRight"]):void 0}),m.each({margin:"",padding:"",border:"Width"},function(a,b){m.cssHooks[a+b]={expand:function(c){for(var d=0,e={},f="string"==typeof c?c.split(" "):[c];4>d;d++)e[a+T[d]+b]=f[d]||f[d-2]||f[0];return e}},Gb.test(a)||(m.cssHooks[a+b].set=Wb)}),m.fn.extend({css:function(a,b){return V(this,function(a,b,c){var d,e,f={},g=0;if(m.isArray(b)){for(d=Ib(a),e=b.length;e>g;g++)f[b[g]]=m.css(a,b[g],!1,d);return f}return void 0!==c?m.style(a,b,c):m.css(a,b)},a,b,arguments.length>1)},show:function(){return Vb(this,!0)},hide:function(){return Vb(this)},toggle:function(a){return"boolean"==typeof a?a?this.show():this.hide():this.each(function(){U(this)?m(this).show():m(this).hide()})}});function Zb(a,b,c,d,e){return new Zb.prototype.init(a,b,c,d,e)}m.Tween=Zb,Zb.prototype={constructor:Zb,init:function(a,b,c,d,e,f){this.elem=a,this.prop=c,this.easing=e||"swing",this.options=b,this.start=this.now=this.cur(),this.end=d,this.unit=f||(m.cssNumber[c]?"":"px") +},cur:function(){var a=Zb.propHooks[this.prop];return a&&a.get?a.get(this):Zb.propHooks._default.get(this)},run:function(a){var b,c=Zb.propHooks[this.prop];return this.pos=b=this.options.duration?m.easing[this.easing](a,this.options.duration*a,0,1,this.options.duration):a,this.now=(this.end-this.start)*b+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),c&&c.set?c.set(this):Zb.propHooks._default.set(this),this}},Zb.prototype.init.prototype=Zb.prototype,Zb.propHooks={_default:{get:function(a){var b;return null==a.elem[a.prop]||a.elem.style&&null!=a.elem.style[a.prop]?(b=m.css(a.elem,a.prop,""),b&&"auto"!==b?b:0):a.elem[a.prop]},set:function(a){m.fx.step[a.prop]?m.fx.step[a.prop](a):a.elem.style&&(null!=a.elem.style[m.cssProps[a.prop]]||m.cssHooks[a.prop])?m.style(a.elem,a.prop,a.now+a.unit):a.elem[a.prop]=a.now}}},Zb.propHooks.scrollTop=Zb.propHooks.scrollLeft={set:function(a){a.elem.nodeType&&a.elem.parentNode&&(a.elem[a.prop]=a.now)}},m.easing={linear:function(a){return a},swing:function(a){return.5-Math.cos(a*Math.PI)/2}},m.fx=Zb.prototype.init,m.fx.step={};var $b,_b,ac=/^(?:toggle|show|hide)$/,bc=new RegExp("^(?:([+-])=|)("+S+")([a-z%]*)$","i"),cc=/queueHooks$/,dc=[ic],ec={"*":[function(a,b){var c=this.createTween(a,b),d=c.cur(),e=bc.exec(b),f=e&&e[3]||(m.cssNumber[a]?"":"px"),g=(m.cssNumber[a]||"px"!==f&&+d)&&bc.exec(m.css(c.elem,a)),h=1,i=20;if(g&&g[3]!==f){f=f||g[3],e=e||[],g=+d||1;do h=h||".5",g/=h,m.style(c.elem,a,g+f);while(h!==(h=c.cur()/d)&&1!==h&&--i)}return e&&(g=c.start=+g||+d||0,c.unit=f,c.end=e[1]?g+(e[1]+1)*e[2]:+e[2]),c}]};function fc(){return setTimeout(function(){$b=void 0}),$b=m.now()}function gc(a,b){var c,d={height:a},e=0;for(b=b?1:0;4>e;e+=2-b)c=T[e],d["margin"+c]=d["padding"+c]=a;return b&&(d.opacity=d.width=a),d}function hc(a,b,c){for(var d,e=(ec[b]||[]).concat(ec["*"]),f=0,g=e.length;g>f;f++)if(d=e[f].call(c,b,a))return d}function ic(a,b,c){var d,e,f,g,h,i,j,l,n=this,o={},p=a.style,q=a.nodeType&&U(a),r=m._data(a,"fxshow");c.queue||(h=m._queueHooks(a,"fx"),null==h.unqueued&&(h.unqueued=0,i=h.empty.fire,h.empty.fire=function(){h.unqueued||i()}),h.unqueued++,n.always(function(){n.always(function(){h.unqueued--,m.queue(a,"fx").length||h.empty.fire()})})),1===a.nodeType&&("height"in b||"width"in b)&&(c.overflow=[p.overflow,p.overflowX,p.overflowY],j=m.css(a,"display"),l="none"===j?m._data(a,"olddisplay")||Fb(a.nodeName):j,"inline"===l&&"none"===m.css(a,"float")&&(k.inlineBlockNeedsLayout&&"inline"!==Fb(a.nodeName)?p.zoom=1:p.display="inline-block")),c.overflow&&(p.overflow="hidden",k.shrinkWrapBlocks()||n.always(function(){p.overflow=c.overflow[0],p.overflowX=c.overflow[1],p.overflowY=c.overflow[2]}));for(d in b)if(e=b[d],ac.exec(e)){if(delete b[d],f=f||"toggle"===e,e===(q?"hide":"show")){if("show"!==e||!r||void 0===r[d])continue;q=!0}o[d]=r&&r[d]||m.style(a,d)}else j=void 0;if(m.isEmptyObject(o))"inline"===("none"===j?Fb(a.nodeName):j)&&(p.display=j);else{r?"hidden"in r&&(q=r.hidden):r=m._data(a,"fxshow",{}),f&&(r.hidden=!q),q?m(a).show():n.done(function(){m(a).hide()}),n.done(function(){var b;m._removeData(a,"fxshow");for(b in o)m.style(a,b,o[b])});for(d in o)g=hc(q?r[d]:0,d,n),d in r||(r[d]=g.start,q&&(g.end=g.start,g.start="width"===d||"height"===d?1:0))}}function jc(a,b){var c,d,e,f,g;for(c in a)if(d=m.camelCase(c),e=b[d],f=a[c],m.isArray(f)&&(e=f[1],f=a[c]=f[0]),c!==d&&(a[d]=f,delete a[c]),g=m.cssHooks[d],g&&"expand"in g){f=g.expand(f),delete a[d];for(c in f)c in a||(a[c]=f[c],b[c]=e)}else b[d]=e}function kc(a,b,c){var d,e,f=0,g=dc.length,h=m.Deferred().always(function(){delete i.elem}),i=function(){if(e)return!1;for(var b=$b||fc(),c=Math.max(0,j.startTime+j.duration-b),d=c/j.duration||0,f=1-d,g=0,i=j.tweens.length;i>g;g++)j.tweens[g].run(f);return h.notifyWith(a,[j,f,c]),1>f&&i?c:(h.resolveWith(a,[j]),!1)},j=h.promise({elem:a,props:m.extend({},b),opts:m.extend(!0,{specialEasing:{}},c),originalProperties:b,originalOptions:c,startTime:$b||fc(),duration:c.duration,tweens:[],createTween:function(b,c){var d=m.Tween(a,j.opts,b,c,j.opts.specialEasing[b]||j.opts.easing);return j.tweens.push(d),d},stop:function(b){var c=0,d=b?j.tweens.length:0;if(e)return this;for(e=!0;d>c;c++)j.tweens[c].run(1);return b?h.resolveWith(a,[j,b]):h.rejectWith(a,[j,b]),this}}),k=j.props;for(jc(k,j.opts.specialEasing);g>f;f++)if(d=dc[f].call(j,a,k,j.opts))return d;return m.map(k,hc,j),m.isFunction(j.opts.start)&&j.opts.start.call(a,j),m.fx.timer(m.extend(i,{elem:a,anim:j,queue:j.opts.queue})),j.progress(j.opts.progress).done(j.opts.done,j.opts.complete).fail(j.opts.fail).always(j.opts.always)}m.Animation=m.extend(kc,{tweener:function(a,b){m.isFunction(a)?(b=a,a=["*"]):a=a.split(" ");for(var c,d=0,e=a.length;e>d;d++)c=a[d],ec[c]=ec[c]||[],ec[c].unshift(b)},prefilter:function(a,b){b?dc.unshift(a):dc.push(a)}}),m.speed=function(a,b,c){var d=a&&"object"==typeof a?m.extend({},a):{complete:c||!c&&b||m.isFunction(a)&&a,duration:a,easing:c&&b||b&&!m.isFunction(b)&&b};return d.duration=m.fx.off?0:"number"==typeof d.duration?d.duration:d.duration in m.fx.speeds?m.fx.speeds[d.duration]:m.fx.speeds._default,(null==d.queue||d.queue===!0)&&(d.queue="fx"),d.old=d.complete,d.complete=function(){m.isFunction(d.old)&&d.old.call(this),d.queue&&m.dequeue(this,d.queue)},d},m.fn.extend({fadeTo:function(a,b,c,d){return this.filter(U).css("opacity",0).show().end().animate({opacity:b},a,c,d)},animate:function(a,b,c,d){var e=m.isEmptyObject(a),f=m.speed(b,c,d),g=function(){var b=kc(this,m.extend({},a),f);(e||m._data(this,"finish"))&&b.stop(!0)};return g.finish=g,e||f.queue===!1?this.each(g):this.queue(f.queue,g)},stop:function(a,b,c){var d=function(a){var b=a.stop;delete a.stop,b(c)};return"string"!=typeof a&&(c=b,b=a,a=void 0),b&&a!==!1&&this.queue(a||"fx",[]),this.each(function(){var b=!0,e=null!=a&&a+"queueHooks",f=m.timers,g=m._data(this);if(e)g[e]&&g[e].stop&&d(g[e]);else for(e in g)g[e]&&g[e].stop&&cc.test(e)&&d(g[e]);for(e=f.length;e--;)f[e].elem!==this||null!=a&&f[e].queue!==a||(f[e].anim.stop(c),b=!1,f.splice(e,1));(b||!c)&&m.dequeue(this,a)})},finish:function(a){return a!==!1&&(a=a||"fx"),this.each(function(){var b,c=m._data(this),d=c[a+"queue"],e=c[a+"queueHooks"],f=m.timers,g=d?d.length:0;for(c.finish=!0,m.queue(this,a,[]),e&&e.stop&&e.stop.call(this,!0),b=f.length;b--;)f[b].elem===this&&f[b].queue===a&&(f[b].anim.stop(!0),f.splice(b,1));for(b=0;g>b;b++)d[b]&&d[b].finish&&d[b].finish.call(this);delete c.finish})}}),m.each(["toggle","show","hide"],function(a,b){var c=m.fn[b];m.fn[b]=function(a,d,e){return null==a||"boolean"==typeof a?c.apply(this,arguments):this.animate(gc(b,!0),a,d,e)}}),m.each({slideDown:gc("show"),slideUp:gc("hide"),slideToggle:gc("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(a,b){m.fn[a]=function(a,c,d){return this.animate(b,a,c,d)}}),m.timers=[],m.fx.tick=function(){var a,b=m.timers,c=0;for($b=m.now();c<b.length;c++)a=b[c],a()||b[c]!==a||b.splice(c--,1);b.length||m.fx.stop(),$b=void 0},m.fx.timer=function(a){m.timers.push(a),a()?m.fx.start():m.timers.pop()},m.fx.interval=13,m.fx.start=function(){_b||(_b=setInterval(m.fx.tick,m.fx.interval))},m.fx.stop=function(){clearInterval(_b),_b=null},m.fx.speeds={slow:600,fast:200,_default:400},m.fn.delay=function(a,b){return a=m.fx?m.fx.speeds[a]||a:a,b=b||"fx",this.queue(b,function(b,c){var d=setTimeout(b,a);c.stop=function(){clearTimeout(d)}})},function(){var a,b,c,d,e;b=y.createElement("div"),b.setAttribute("className","t"),b.innerHTML=" <link/><table></table><a href='/a'>a</a><input type='checkbox'/>",d=b.getElementsByTagName("a")[0],c=y.createElement("select"),e=c.appendChild(y.createElement("option")),a=b.getElementsByTagName("input")[0],d.style.cssText="top:1px",k.getSetAttribute="t"!==b.className,k.style=/top/.test(d.getAttribute("style")),k.hrefNormalized="/a"===d.getAttribute("href"),k.checkOn=!!a.value,k.optSelected=e.selected,k.enctype=!!y.createElement("form").enctype,c.disabled=!0,k.optDisabled=!e.disabled,a=y.createElement("input"),a.setAttribute("value",""),k.input=""===a.getAttribute("value"),a.value="t",a.setAttribute("type","radio"),k.radioValue="t"===a.value}();var lc=/\r/g;m.fn.extend({val:function(a){var b,c,d,e=this[0];{if(arguments.length)return d=m.isFunction(a),this.each(function(c){var e;1===this.nodeType&&(e=d?a.call(this,c,m(this).val()):a,null==e?e="":"number"==typeof e?e+="":m.isArray(e)&&(e=m.map(e,function(a){return null==a?"":a+""})),b=m.valHooks[this.type]||m.valHooks[this.nodeName.toLowerCase()],b&&"set"in b&&void 0!==b.set(this,e,"value")||(this.value=e))});if(e)return b=m.valHooks[e.type]||m.valHooks[e.nodeName.toLowerCase()],b&&"get"in b&&void 0!==(c=b.get(e,"value"))?c:(c=e.value,"string"==typeof c?c.replace(lc,""):null==c?"":c)}}}),m.extend({valHooks:{option:{get:function(a){var b=m.find.attr(a,"value");return null!=b?b:m.trim(m.text(a))}},select:{get:function(a){for(var b,c,d=a.options,e=a.selectedIndex,f="select-one"===a.type||0>e,g=f?null:[],h=f?e+1:d.length,i=0>e?h:f?e:0;h>i;i++)if(c=d[i],!(!c.selected&&i!==e||(k.optDisabled?c.disabled:null!==c.getAttribute("disabled"))||c.parentNode.disabled&&m.nodeName(c.parentNode,"optgroup"))){if(b=m(c).val(),f)return b;g.push(b)}return g},set:function(a,b){var c,d,e=a.options,f=m.makeArray(b),g=e.length;while(g--)if(d=e[g],m.inArray(m.valHooks.option.get(d),f)>=0)try{d.selected=c=!0}catch(h){d.scrollHeight}else d.selected=!1;return c||(a.selectedIndex=-1),e}}}}),m.each(["radio","checkbox"],function(){m.valHooks[this]={set:function(a,b){return m.isArray(b)?a.checked=m.inArray(m(a).val(),b)>=0:void 0}},k.checkOn||(m.valHooks[this].get=function(a){return null===a.getAttribute("value")?"on":a.value})});var mc,nc,oc=m.expr.attrHandle,pc=/^(?:checked|selected)$/i,qc=k.getSetAttribute,rc=k.input;m.fn.extend({attr:function(a,b){return V(this,m.attr,a,b,arguments.length>1)},removeAttr:function(a){return this.each(function(){m.removeAttr(this,a)})}}),m.extend({attr:function(a,b,c){var d,e,f=a.nodeType;if(a&&3!==f&&8!==f&&2!==f)return typeof a.getAttribute===K?m.prop(a,b,c):(1===f&&m.isXMLDoc(a)||(b=b.toLowerCase(),d=m.attrHooks[b]||(m.expr.match.bool.test(b)?nc:mc)),void 0===c?d&&"get"in d&&null!==(e=d.get(a,b))?e:(e=m.find.attr(a,b),null==e?void 0:e):null!==c?d&&"set"in d&&void 0!==(e=d.set(a,c,b))?e:(a.setAttribute(b,c+""),c):void m.removeAttr(a,b))},removeAttr:function(a,b){var c,d,e=0,f=b&&b.match(E);if(f&&1===a.nodeType)while(c=f[e++])d=m.propFix[c]||c,m.expr.match.bool.test(c)?rc&&qc||!pc.test(c)?a[d]=!1:a[m.camelCase("default-"+c)]=a[d]=!1:m.attr(a,c,""),a.removeAttribute(qc?c:d)},attrHooks:{type:{set:function(a,b){if(!k.radioValue&&"radio"===b&&m.nodeName(a,"input")){var c=a.value;return a.setAttribute("type",b),c&&(a.value=c),b}}}}}),nc={set:function(a,b,c){return b===!1?m.removeAttr(a,c):rc&&qc||!pc.test(c)?a.setAttribute(!qc&&m.propFix[c]||c,c):a[m.camelCase("default-"+c)]=a[c]=!0,c}},m.each(m.expr.match.bool.source.match(/\w+/g),function(a,b){var c=oc[b]||m.find.attr;oc[b]=rc&&qc||!pc.test(b)?function(a,b,d){var e,f;return d||(f=oc[b],oc[b]=e,e=null!=c(a,b,d)?b.toLowerCase():null,oc[b]=f),e}:function(a,b,c){return c?void 0:a[m.camelCase("default-"+b)]?b.toLowerCase():null}}),rc&&qc||(m.attrHooks.value={set:function(a,b,c){return m.nodeName(a,"input")?void(a.defaultValue=b):mc&&mc.set(a,b,c)}}),qc||(mc={set:function(a,b,c){var d=a.getAttributeNode(c);return d||a.setAttributeNode(d=a.ownerDocument.createAttribute(c)),d.value=b+="","value"===c||b===a.getAttribute(c)?b:void 0}},oc.id=oc.name=oc.coords=function(a,b,c){var d;return c?void 0:(d=a.getAttributeNode(b))&&""!==d.value?d.value:null},m.valHooks.button={get:function(a,b){var c=a.getAttributeNode(b);return c&&c.specified?c.value:void 0},set:mc.set},m.attrHooks.contenteditable={set:function(a,b,c){mc.set(a,""===b?!1:b,c)}},m.each(["width","height"],function(a,b){m.attrHooks[b]={set:function(a,c){return""===c?(a.setAttribute(b,"auto"),c):void 0}}})),k.style||(m.attrHooks.style={get:function(a){return a.style.cssText||void 0},set:function(a,b){return a.style.cssText=b+""}});var sc=/^(?:input|select|textarea|button|object)$/i,tc=/^(?:a|area)$/i;m.fn.extend({prop:function(a,b){return V(this,m.prop,a,b,arguments.length>1)},removeProp:function(a){return a=m.propFix[a]||a,this.each(function(){try{this[a]=void 0,delete this[a]}catch(b){}})}}),m.extend({propFix:{"for":"htmlFor","class":"className"},prop:function(a,b,c){var d,e,f,g=a.nodeType;if(a&&3!==g&&8!==g&&2!==g)return f=1!==g||!m.isXMLDoc(a),f&&(b=m.propFix[b]||b,e=m.propHooks[b]),void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=m.find.attr(a,"tabindex");return b?parseInt(b,10):sc.test(a.nodeName)||tc.test(a.nodeName)&&a.href?0:-1}}}}),k.hrefNormalized||m.each(["href","src"],function(a,b){m.propHooks[b]={get:function(a){return a.getAttribute(b,4)}}}),k.optSelected||(m.propHooks.selected={get:function(a){var b=a.parentNode;return b&&(b.selectedIndex,b.parentNode&&b.parentNode.selectedIndex),null}}),m.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){m.propFix[this.toLowerCase()]=this}),k.enctype||(m.propFix.enctype="encoding");var uc=/[\t\r\n\f]/g;m.fn.extend({addClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j="string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).addClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):" ")){f=0;while(e=b[f++])d.indexOf(" "+e+" ")<0&&(d+=e+" ");g=m.trim(d),c.className!==g&&(c.className=g)}return this},removeClass:function(a){var b,c,d,e,f,g,h=0,i=this.length,j=0===arguments.length||"string"==typeof a&&a;if(m.isFunction(a))return this.each(function(b){m(this).removeClass(a.call(this,b,this.className))});if(j)for(b=(a||"").match(E)||[];i>h;h++)if(c=this[h],d=1===c.nodeType&&(c.className?(" "+c.className+" ").replace(uc," "):"")){f=0;while(e=b[f++])while(d.indexOf(" "+e+" ")>=0)d=d.replace(" "+e+" "," ");g=a?m.trim(d):"",c.className!==g&&(c.className=g)}return this},toggleClass:function(a,b){var c=typeof a;return"boolean"==typeof b&&"string"===c?b?this.addClass(a):this.removeClass(a):this.each(m.isFunction(a)?function(c){m(this).toggleClass(a.call(this,c,this.className,b),b)}:function(){if("string"===c){var b,d=0,e=m(this),f=a.match(E)||[];while(b=f[d++])e.hasClass(b)?e.removeClass(b):e.addClass(b)}else(c===K||"boolean"===c)&&(this.className&&m._data(this,"__className__",this.className),this.className=this.className||a===!1?"":m._data(this,"__className__")||"")})},hasClass:function(a){for(var b=" "+a+" ",c=0,d=this.length;d>c;c++)if(1===this[c].nodeType&&(" "+this[c].className+" ").replace(uc," ").indexOf(b)>=0)return!0;return!1}}),m.each("blur focus focusin focusout load resize scroll unload click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup error contextmenu".split(" "),function(a,b){m.fn[b]=function(a,c){return arguments.length>0?this.on(b,null,a,c):this.trigger(b)}}),m.fn.extend({hover:function(a,b){return this.mouseenter(a).mouseleave(b||a)},bind:function(a,b,c){return this.on(a,null,b,c)},unbind:function(a,b){return this.off(a,null,b)},delegate:function(a,b,c,d){return this.on(b,a,c,d)},undelegate:function(a,b,c){return 1===arguments.length?this.off(a,"**"):this.off(b,a||"**",c)}});var vc=m.now(),wc=/\?/,xc=/(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;m.parseJSON=function(b){if(a.JSON&&a.JSON.parse)return a.JSON.parse(b+"");var c,d=null,e=m.trim(b+"");return e&&!m.trim(e.replace(xc,function(a,b,e,f){return c&&b&&(d=0),0===d?a:(c=e||b,d+=!f-!e,"")}))?Function("return "+e)():m.error("Invalid JSON: "+b)},m.parseXML=function(b){var c,d;if(!b||"string"!=typeof b)return null;try{a.DOMParser?(d=new DOMParser,c=d.parseFromString(b,"text/xml")):(c=new ActiveXObject("Microsoft.XMLDOM"),c.async="false",c.loadXML(b))}catch(e){c=void 0}return c&&c.documentElement&&!c.getElementsByTagName("parsererror").length||m.error("Invalid XML: "+b),c};var yc,zc,Ac=/#.*$/,Bc=/([?&])_=[^&]*/,Cc=/^(.*?):[ \t]*([^\r\n]*)\r?$/gm,Dc=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,Ec=/^(?:GET|HEAD)$/,Fc=/^\/\//,Gc=/^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,Hc={},Ic={},Jc="*/".concat("*");try{zc=location.href}catch(Kc){zc=y.createElement("a"),zc.href="",zc=zc.href}yc=Gc.exec(zc.toLowerCase())||[];function Lc(a){return function(b,c){"string"!=typeof b&&(c=b,b="*");var d,e=0,f=b.toLowerCase().match(E)||[];if(m.isFunction(c))while(d=f[e++])"+"===d.charAt(0)?(d=d.slice(1)||"*",(a[d]=a[d]||[]).unshift(c)):(a[d]=a[d]||[]).push(c)}}function Mc(a,b,c,d){var e={},f=a===Ic;function g(h){var i;return e[h]=!0,m.each(a[h]||[],function(a,h){var j=h(b,c,d);return"string"!=typeof j||f||e[j]?f?!(i=j):void 0:(b.dataTypes.unshift(j),g(j),!1)}),i}return g(b.dataTypes[0])||!e["*"]&&g("*")}function Nc(a,b){var c,d,e=m.ajaxSettings.flatOptions||{};for(d in b)void 0!==b[d]&&((e[d]?a:c||(c={}))[d]=b[d]);return c&&m.extend(!0,a,c),a}function Oc(a,b,c){var d,e,f,g,h=a.contents,i=a.dataTypes;while("*"===i[0])i.shift(),void 0===e&&(e=a.mimeType||b.getResponseHeader("Content-Type"));if(e)for(g in h)if(h[g]&&h[g].test(e)){i.unshift(g);break}if(i[0]in c)f=i[0];else{for(g in c){if(!i[0]||a.converters[g+" "+i[0]]){f=g;break}d||(d=g)}f=f||d}return f?(f!==i[0]&&i.unshift(f),c[f]):void 0}function Pc(a,b,c,d){var e,f,g,h,i,j={},k=a.dataTypes.slice();if(k[1])for(g in a.converters)j[g.toLowerCase()]=a.converters[g];f=k.shift();while(f)if(a.responseFields[f]&&(c[a.responseFields[f]]=b),!i&&d&&a.dataFilter&&(b=a.dataFilter(b,a.dataType)),i=f,f=k.shift())if("*"===f)f=i;else if("*"!==i&&i!==f){if(g=j[i+" "+f]||j["* "+f],!g)for(e in j)if(h=e.split(" "),h[1]===f&&(g=j[i+" "+h[0]]||j["* "+h[0]])){g===!0?g=j[e]:j[e]!==!0&&(f=h[0],k.unshift(h[1]));break}if(g!==!0)if(g&&a["throws"])b=g(b);else try{b=g(b)}catch(l){return{state:"parsererror",error:g?l:"No conversion from "+i+" to "+f}}}return{state:"success",data:b}}m.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:zc,type:"GET",isLocal:Dc.test(yc[1]),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":Jc,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":m.parseJSON,"text xml":m.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(a,b){return b?Nc(Nc(a,m.ajaxSettings),b):Nc(m.ajaxSettings,a)},ajaxPrefilter:Lc(Hc),ajaxTransport:Lc(Ic),ajax:function(a,b){"object"==typeof a&&(b=a,a=void 0),b=b||{};var c,d,e,f,g,h,i,j,k=m.ajaxSetup({},b),l=k.context||k,n=k.context&&(l.nodeType||l.jquery)?m(l):m.event,o=m.Deferred(),p=m.Callbacks("once memory"),q=k.statusCode||{},r={},s={},t=0,u="canceled",v={readyState:0,getResponseHeader:function(a){var b;if(2===t){if(!j){j={};while(b=Cc.exec(f))j[b[1].toLowerCase()]=b[2]}b=j[a.toLowerCase()]}return null==b?null:b},getAllResponseHeaders:function(){return 2===t?f:null},setRequestHeader:function(a,b){var c=a.toLowerCase();return t||(a=s[c]=s[c]||a,r[a]=b),this},overrideMimeType:function(a){return t||(k.mimeType=a),this},statusCode:function(a){var b;if(a)if(2>t)for(b in a)q[b]=[q[b],a[b]];else v.always(a[v.status]);return this},abort:function(a){var b=a||u;return i&&i.abort(b),x(0,b),this}};if(o.promise(v).complete=p.add,v.success=v.done,v.error=v.fail,k.url=((a||k.url||zc)+"").replace(Ac,"").replace(Fc,yc[1]+"//"),k.type=b.method||b.type||k.method||k.type,k.dataTypes=m.trim(k.dataType||"*").toLowerCase().match(E)||[""],null==k.crossDomain&&(c=Gc.exec(k.url.toLowerCase()),k.crossDomain=!(!c||c[1]===yc[1]&&c[2]===yc[2]&&(c[3]||("http:"===c[1]?"80":"443"))===(yc[3]||("http:"===yc[1]?"80":"443")))),k.data&&k.processData&&"string"!=typeof k.data&&(k.data=m.param(k.data,k.traditional)),Mc(Hc,k,b,v),2===t)return v;h=k.global,h&&0===m.active++&&m.event.trigger("ajaxStart"),k.type=k.type.toUpperCase(),k.hasContent=!Ec.test(k.type),e=k.url,k.hasContent||(k.data&&(e=k.url+=(wc.test(e)?"&":"?")+k.data,delete k.data),k.cache===!1&&(k.url=Bc.test(e)?e.replace(Bc,"$1_="+vc++):e+(wc.test(e)?"&":"?")+"_="+vc++)),k.ifModified&&(m.lastModified[e]&&v.setRequestHeader("If-Modified-Since",m.lastModified[e]),m.etag[e]&&v.setRequestHeader("If-None-Match",m.etag[e])),(k.data&&k.hasContent&&k.contentType!==!1||b.contentType)&&v.setRequestHeader("Content-Type",k.contentType),v.setRequestHeader("Accept",k.dataTypes[0]&&k.accepts[k.dataTypes[0]]?k.accepts[k.dataTypes[0]]+("*"!==k.dataTypes[0]?", "+Jc+"; q=0.01":""):k.accepts["*"]);for(d in k.headers)v.setRequestHeader(d,k.headers[d]);if(k.beforeSend&&(k.beforeSend.call(l,v,k)===!1||2===t))return v.abort();u="abort";for(d in{success:1,error:1,complete:1})v[d](k[d]);if(i=Mc(Ic,k,b,v)){v.readyState=1,h&&n.trigger("ajaxSend",[v,k]),k.async&&k.timeout>0&&(g=setTimeout(function(){v.abort("timeout")},k.timeout));try{t=1,i.send(r,x)}catch(w){if(!(2>t))throw w;x(-1,w)}}else x(-1,"No Transport");function x(a,b,c,d){var j,r,s,u,w,x=b;2!==t&&(t=2,g&&clearTimeout(g),i=void 0,f=d||"",v.readyState=a>0?4:0,j=a>=200&&300>a||304===a,c&&(u=Oc(k,v,c)),u=Pc(k,u,v,j),j?(k.ifModified&&(w=v.getResponseHeader("Last-Modified"),w&&(m.lastModified[e]=w),w=v.getResponseHeader("etag"),w&&(m.etag[e]=w)),204===a||"HEAD"===k.type?x="nocontent":304===a?x="notmodified":(x=u.state,r=u.data,s=u.error,j=!s)):(s=x,(a||!x)&&(x="error",0>a&&(a=0))),v.status=a,v.statusText=(b||x)+"",j?o.resolveWith(l,[r,x,v]):o.rejectWith(l,[v,x,s]),v.statusCode(q),q=void 0,h&&n.trigger(j?"ajaxSuccess":"ajaxError",[v,k,j?r:s]),p.fireWith(l,[v,x]),h&&(n.trigger("ajaxComplete",[v,k]),--m.active||m.event.trigger("ajaxStop")))}return v},getJSON:function(a,b,c){return m.get(a,b,c,"json")},getScript:function(a,b){return m.get(a,void 0,b,"script")}}),m.each(["get","post"],function(a,b){m[b]=function(a,c,d,e){return m.isFunction(c)&&(e=e||d,d=c,c=void 0),m.ajax({url:a,type:b,dataType:e,data:c,success:d})}}),m.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(a,b){m.fn[b]=function(a){return this.on(b,a)}}),m._evalUrl=function(a){return m.ajax({url:a,type:"GET",dataType:"script",async:!1,global:!1,"throws":!0})},m.fn.extend({wrapAll:function(a){if(m.isFunction(a))return this.each(function(b){m(this).wrapAll(a.call(this,b))});if(this[0]){var b=m(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&1===a.firstChild.nodeType)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){return this.each(m.isFunction(a)?function(b){m(this).wrapInner(a.call(this,b))}:function(){var b=m(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=m.isFunction(a);return this.each(function(c){m(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){m.nodeName(this,"body")||m(this).replaceWith(this.childNodes)}).end()}}),m.expr.filters.hidden=function(a){return a.offsetWidth<=0&&a.offsetHeight<=0||!k.reliableHiddenOffsets()&&"none"===(a.style&&a.style.display||m.css(a,"display"))},m.expr.filters.visible=function(a){return!m.expr.filters.hidden(a)};var Qc=/%20/g,Rc=/\[\]$/,Sc=/\r?\n/g,Tc=/^(?:submit|button|image|reset|file)$/i,Uc=/^(?:input|select|textarea|keygen)/i;function Vc(a,b,c,d){var e;if(m.isArray(b))m.each(b,function(b,e){c||Rc.test(a)?d(a,e):Vc(a+"["+("object"==typeof e?b:"")+"]",e,c,d)});else if(c||"object"!==m.type(b))d(a,b);else for(e in b)Vc(a+"["+e+"]",b[e],c,d)}m.param=function(a,b){var c,d=[],e=function(a,b){b=m.isFunction(b)?b():null==b?"":b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};if(void 0===b&&(b=m.ajaxSettings&&m.ajaxSettings.traditional),m.isArray(a)||a.jquery&&!m.isPlainObject(a))m.each(a,function(){e(this.name,this.value)});else for(c in a)Vc(c,a[c],b,e);return d.join("&").replace(Qc,"+")},m.fn.extend({serialize:function(){return m.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var a=m.prop(this,"elements");return a?m.makeArray(a):this}).filter(function(){var a=this.type;return this.name&&!m(this).is(":disabled")&&Uc.test(this.nodeName)&&!Tc.test(a)&&(this.checked||!W.test(a))}).map(function(a,b){var c=m(this).val();return null==c?null:m.isArray(c)?m.map(c,function(a){return{name:b.name,value:a.replace(Sc,"\r\n")}}):{name:b.name,value:c.replace(Sc,"\r\n")}}).get()}}),m.ajaxSettings.xhr=void 0!==a.ActiveXObject?function(){return!this.isLocal&&/^(get|post|head|put|delete|options)$/i.test(this.type)&&Zc()||$c()}:Zc;var Wc=0,Xc={},Yc=m.ajaxSettings.xhr();a.ActiveXObject&&m(a).on("unload",function(){for(var a in Xc)Xc[a](void 0,!0)}),k.cors=!!Yc&&"withCredentials"in Yc,Yc=k.ajax=!!Yc,Yc&&m.ajaxTransport(function(a){if(!a.crossDomain||k.cors){var b;return{send:function(c,d){var e,f=a.xhr(),g=++Wc;if(f.open(a.type,a.url,a.async,a.username,a.password),a.xhrFields)for(e in a.xhrFields)f[e]=a.xhrFields[e];a.mimeType&&f.overrideMimeType&&f.overrideMimeType(a.mimeType),a.crossDomain||c["X-Requested-With"]||(c["X-Requested-With"]="XMLHttpRequest");for(e in c)void 0!==c[e]&&f.setRequestHeader(e,c[e]+"");f.send(a.hasContent&&a.data||null),b=function(c,e){var h,i,j;if(b&&(e||4===f.readyState))if(delete Xc[g],b=void 0,f.onreadystatechange=m.noop,e)4!==f.readyState&&f.abort();else{j={},h=f.status,"string"==typeof f.responseText&&(j.text=f.responseText);try{i=f.statusText}catch(k){i=""}h||!a.isLocal||a.crossDomain?1223===h&&(h=204):h=j.text?200:404}j&&d(h,i,j,f.getAllResponseHeaders())},a.async?4===f.readyState?setTimeout(b):f.onreadystatechange=Xc[g]=b:b()},abort:function(){b&&b(void 0,!0)}}}});function Zc(){try{return new a.XMLHttpRequest}catch(b){}}function $c(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}m.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/(?:java|ecma)script/},converters:{"text script":function(a){return m.globalEval(a),a}}}),m.ajaxPrefilter("script",function(a){void 0===a.cache&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),m.ajaxTransport("script",function(a){if(a.crossDomain){var b,c=y.head||m("head")[0]||y.documentElement;return{send:function(d,e){b=y.createElement("script"),b.async=!0,a.scriptCharset&&(b.charset=a.scriptCharset),b.src=a.url,b.onload=b.onreadystatechange=function(a,c){(c||!b.readyState||/loaded|complete/.test(b.readyState))&&(b.onload=b.onreadystatechange=null,b.parentNode&&b.parentNode.removeChild(b),b=null,c||e(200,"success"))},c.insertBefore(b,c.firstChild)},abort:function(){b&&b.onload(void 0,!0)}}}});var _c=[],ad=/(=)\?(?=&|$)|\?\?/;m.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var a=_c.pop()||m.expando+"_"+vc++;return this[a]=!0,a}}),m.ajaxPrefilter("json jsonp",function(b,c,d){var e,f,g,h=b.jsonp!==!1&&(ad.test(b.url)?"url":"string"==typeof b.data&&!(b.contentType||"").indexOf("application/x-www-form-urlencoded")&&ad.test(b.data)&&"data");return h||"jsonp"===b.dataTypes[0]?(e=b.jsonpCallback=m.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,h?b[h]=b[h].replace(ad,"$1"+e):b.jsonp!==!1&&(b.url+=(wc.test(b.url)?"&":"?")+b.jsonp+"="+e),b.converters["script json"]=function(){return g||m.error(e+" was not called"),g[0]},b.dataTypes[0]="json",f=a[e],a[e]=function(){g=arguments},d.always(function(){a[e]=f,b[e]&&(b.jsonpCallback=c.jsonpCallback,_c.push(e)),g&&m.isFunction(f)&&f(g[0]),g=f=void 0}),"script"):void 0}),m.parseHTML=function(a,b,c){if(!a||"string"!=typeof a)return null;"boolean"==typeof b&&(c=b,b=!1),b=b||y;var d=u.exec(a),e=!c&&[];return d?[b.createElement(d[1])]:(d=m.buildFragment([a],b,e),e&&e.length&&m(e).remove(),m.merge([],d.childNodes))};var bd=m.fn.load;m.fn.load=function(a,b,c){if("string"!=typeof a&&bd)return bd.apply(this,arguments);var d,e,f,g=this,h=a.indexOf(" ");return h>=0&&(d=m.trim(a.slice(h,a.length)),a=a.slice(0,h)),m.isFunction(b)?(c=b,b=void 0):b&&"object"==typeof b&&(f="POST"),g.length>0&&m.ajax({url:a,type:f,dataType:"html",data:b}).done(function(a){e=arguments,g.html(d?m("<div>").append(m.parseHTML(a)).find(d):a)}).complete(c&&function(a,b){g.each(c,e||[a.responseText,b,a])}),this},m.expr.filters.animated=function(a){return m.grep(m.timers,function(b){return a===b.elem}).length};var cd=a.document.documentElement;function dd(a){return m.isWindow(a)?a:9===a.nodeType?a.defaultView||a.parentWindow:!1}m.offset={setOffset:function(a,b,c){var d,e,f,g,h,i,j,k=m.css(a,"position"),l=m(a),n={};"static"===k&&(a.style.position="relative"),h=l.offset(),f=m.css(a,"top"),i=m.css(a,"left"),j=("absolute"===k||"fixed"===k)&&m.inArray("auto",[f,i])>-1,j?(d=l.position(),g=d.top,e=d.left):(g=parseFloat(f)||0,e=parseFloat(i)||0),m.isFunction(b)&&(b=b.call(a,c,h)),null!=b.top&&(n.top=b.top-h.top+g),null!=b.left&&(n.left=b.left-h.left+e),"using"in b?b.using.call(a,n):l.css(n)}},m.fn.extend({offset:function(a){if(arguments.length)return void 0===a?this:this.each(function(b){m.offset.setOffset(this,a,b)});var b,c,d={top:0,left:0},e=this[0],f=e&&e.ownerDocument;if(f)return b=f.documentElement,m.contains(b,e)?(typeof e.getBoundingClientRect!==K&&(d=e.getBoundingClientRect()),c=dd(f),{top:d.top+(c.pageYOffset||b.scrollTop)-(b.clientTop||0),left:d.left+(c.pageXOffset||b.scrollLeft)-(b.clientLeft||0)}):d},position:function(){if(this[0]){var a,b,c={top:0,left:0},d=this[0];return"fixed"===m.css(d,"position")?b=d.getBoundingClientRect():(a=this.offsetParent(),b=this.offset(),m.nodeName(a[0],"html")||(c=a.offset()),c.top+=m.css(a[0],"borderTopWidth",!0),c.left+=m.css(a[0],"borderLeftWidth",!0)),{top:b.top-c.top-m.css(d,"marginTop",!0),left:b.left-c.left-m.css(d,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||cd;while(a&&!m.nodeName(a,"html")&&"static"===m.css(a,"position"))a=a.offsetParent;return a||cd})}}),m.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(a,b){var c=/Y/.test(b);m.fn[a]=function(d){return V(this,function(a,d,e){var f=dd(a);return void 0===e?f?b in f?f[b]:f.document.documentElement[d]:a[d]:void(f?f.scrollTo(c?m(f).scrollLeft():e,c?e:m(f).scrollTop()):a[d]=e)},a,d,arguments.length,null)}}),m.each(["top","left"],function(a,b){m.cssHooks[b]=Lb(k.pixelPosition,function(a,c){return c?(c=Jb(a,b),Hb.test(c)?m(a).position()[b]+"px":c):void 0})}),m.each({Height:"height",Width:"width"},function(a,b){m.each({padding:"inner"+a,content:b,"":"outer"+a},function(c,d){m.fn[d]=function(d,e){var f=arguments.length&&(c||"boolean"!=typeof d),g=c||(d===!0||e===!0?"margin":"border");return V(this,function(b,c,d){var e;return m.isWindow(b)?b.document.documentElement["client"+a]:9===b.nodeType?(e=b.documentElement,Math.max(b.body["scroll"+a],e["scroll"+a],b.body["offset"+a],e["offset"+a],e["client"+a])):void 0===d?m.css(b,c,g):m.style(b,c,d,g)},b,f?d:void 0,f,null)}})}),m.fn.size=function(){return this.length},m.fn.andSelf=m.fn.addBack,"function"==typeof define&&define.amd&&define("jquery",[],function(){return m});var ed=a.jQuery,fd=a.$;return m.noConflict=function(b){return a.$===m&&(a.$=fd),b&&a.jQuery===m&&(a.jQuery=ed),m},typeof b===K&&(a.jQuery=a.$=m),m}); diff --git a/dgbuilder/public/jquery/js/jquery-ui-1.10.3.custom.min.js b/dgbuilder/public/jquery/js/jquery-ui-1.10.3.custom.min.js new file mode 100644 index 00000000..491cda7a --- /dev/null +++ b/dgbuilder/public/jquery/js/jquery-ui-1.10.3.custom.min.js @@ -0,0 +1,7 @@ +/*! jQuery UI - v1.10.3 - 2013-08-17 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.position.js, jquery.ui.draggable.js, jquery.ui.droppable.js, jquery.ui.resizable.js, jquery.ui.selectable.js, jquery.ui.sortable.js, jquery.ui.accordion.js, jquery.ui.autocomplete.js, jquery.ui.button.js, jquery.ui.datepicker.js, jquery.ui.dialog.js, jquery.ui.menu.js, jquery.ui.progressbar.js, jquery.ui.slider.js, jquery.ui.spinner.js, jquery.ui.tabs.js, jquery.ui.tooltip.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 +* Copyright 2013 jQuery Foundation and other contributors Licensed MIT */ + +(function(e,t){function i(t,i){var a,n,r,o=t.nodeName.toLowerCase();return"area"===o?(a=t.parentNode,n=a.name,t.href&&n&&"map"===a.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&s(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&s(t)}function s(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var a=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,s){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),s&&s.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var s,a,n=e(this[0]);n.length&&n[0]!==document;){if(s=n.css("position"),("absolute"===s||"relative"===s||"fixed"===s)&&(a=parseInt(n.css("zIndex"),10),!isNaN(a)&&0!==a))return a;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++a)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,s){return!!e.data(t,s[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var s=e.attr(t,"tabindex"),a=isNaN(s);return(a||s>=0)&&i(t,!a)}}),e("<a>").outerWidth(1).jquery||e.each(["Width","Height"],function(i,s){function a(t,i,s,a){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,s&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),a&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===s?["Left","Right"]:["Top","Bottom"],r=s.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+s]=function(i){return i===t?o["inner"+s].call(this):this.each(function(){e(this).css(r,a(this,i)+"px")})},e.fn["outer"+s]=function(t,i){return"number"!=typeof t?o["outer"+s].call(this,t):this.each(function(){e(this).css(r,a(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("<a>").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,s){var a,n=e.ui[t].prototype;for(a in s)n.plugins[a]=n.plugins[a]||[],n.plugins[a].push([i,s[a]])},call:function(e,t,i){var s,a=e.plugins[t];if(a&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(s=0;a.length>s;s++)e.options[a[s][0]]&&a[s][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var s=i&&"left"===i?"scrollLeft":"scrollTop",a=!1;return t[s]>0?!0:(t[s]=1,a=t[s]>0,t[s]=0,a)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,n=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(a){}n(t)},e.widget=function(i,s,n){var a,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],a=u+"-"+i,n||(n=s,s=e.Widget),e.expr[":"][a.toLowerCase()]=function(t){return!!e.data(t,a)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:n.version,_proto:e.extend({},n),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(n,function(i,n){return e.isFunction(n)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,a=this._superApply;return this._super=e,this._superApply=t,i=n.apply(this,arguments),this._super=s,this._superApply=a,i}}(),t):(l[i]=n,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:a}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var n,a,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(n in r[o])a=r[o][n],r[o].hasOwnProperty(n)&&a!==t&&(i[n]=e.isPlainObject(a)?e.isPlainObject(i[n])?e.widget.extend({},i[n],a):e.widget.extend({},a):a);return i},e.widget.bridge=function(i,n){var a=n.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,n=e.data(this,a);return n?e.isFunction(n[r])&&"_"!==r.charAt(0)?(s=n[r].apply(n,h),s!==n&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,a);t?t.option(r||{})._init():e.data(this,a,new n(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"<div>",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var n,a,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},n=i.split("."),i=n.shift(),n.length){for(a=o[i]=e.widget.extend({},this.options[i]),r=0;n.length-1>r;r++)a[n[r]]=a[n[r]]||{},a=a[n[r]];if(i=n.pop(),s===t)return a[i]===t?null:a[i];a[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,n){var a,r=this;"boolean"!=typeof i&&(n=s,s=i,i=!1),n?(s=a=e(s),this.bindings=this.bindings.add(s)):(n=s,s=this.element,a=this.widget()),e.each(n,function(n,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=n.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?a.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var n,a,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],a=i.originalEvent)for(n in a)n in i||(i[n]=a[n]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,n,a){"string"==typeof n&&(n={effect:n});var r,o=n?n===!0||"number"==typeof n?i:n.effect||i:t;n=n||{},"number"==typeof n&&(n={duration:n}),r=!e.isEmptyObject(n),n.complete=a,n.delay&&s.delay(n.delay),r&&e.effects&&e.effects.effect[o]?s[t](n):o!==t&&s[o]?s[o](n.duration,n.easing,a):s.queue(function(i){e(this)[t](),a&&a.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,n=1===i.which,a="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return n&&!a&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(t,e){function i(t,e,i){return[parseFloat(t[0])*(p.test(t[0])?e/100:1),parseFloat(t[1])*(p.test(t[1])?i/100:1)]}function s(e,i){return parseInt(t.css(e,i),10)||0}function n(e){var i=e[0];return 9===i.nodeType?{width:e.width(),height:e.height(),offset:{top:0,left:0}}:t.isWindow(i)?{width:e.width(),height:e.height(),offset:{top:e.scrollTop(),left:e.scrollLeft()}}:i.preventDefault?{width:0,height:0,offset:{top:i.pageY,left:i.pageX}}:{width:e.outerWidth(),height:e.outerHeight(),offset:e.offset()}}t.ui=t.ui||{};var a,o=Math.max,r=Math.abs,h=Math.round,l=/left|center|right/,c=/top|center|bottom/,u=/[\+\-]\d+(\.[\d]+)?%?/,d=/^\w+/,p=/%$/,f=t.fn.position;t.position={scrollbarWidth:function(){if(a!==e)return a;var i,s,n=t("<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>"),o=n.children()[0];return t("body").append(n),i=o.offsetWidth,n.css("overflow","scroll"),s=o.offsetWidth,i===s&&(s=n[0].clientWidth),n.remove(),a=i-s},getScrollInfo:function(e){var i=e.isWindow?"":e.element.css("overflow-x"),s=e.isWindow?"":e.element.css("overflow-y"),n="scroll"===i||"auto"===i&&e.width<e.element[0].scrollWidth,a="scroll"===s||"auto"===s&&e.height<e.element[0].scrollHeight;return{width:a?t.position.scrollbarWidth():0,height:n?t.position.scrollbarWidth():0}},getWithinInfo:function(e){var i=t(e||window),s=t.isWindow(i[0]);return{element:i,isWindow:s,offset:i.offset()||{left:0,top:0},scrollLeft:i.scrollLeft(),scrollTop:i.scrollTop(),width:s?i.width():i.outerWidth(),height:s?i.height():i.outerHeight()}}},t.fn.position=function(e){if(!e||!e.of)return f.apply(this,arguments);e=t.extend({},e);var a,p,m,g,v,b,_=t(e.of),y=t.position.getWithinInfo(e.within),w=t.position.getScrollInfo(y),x=(e.collision||"flip").split(" "),k={};return b=n(_),_[0].preventDefault&&(e.at="left top"),p=b.width,m=b.height,g=b.offset,v=t.extend({},g),t.each(["my","at"],function(){var t,i,s=(e[this]||"").split(" ");1===s.length&&(s=l.test(s[0])?s.concat(["center"]):c.test(s[0])?["center"].concat(s):["center","center"]),s[0]=l.test(s[0])?s[0]:"center",s[1]=c.test(s[1])?s[1]:"center",t=u.exec(s[0]),i=u.exec(s[1]),k[this]=[t?t[0]:0,i?i[0]:0],e[this]=[d.exec(s[0])[0],d.exec(s[1])[0]]}),1===x.length&&(x[1]=x[0]),"right"===e.at[0]?v.left+=p:"center"===e.at[0]&&(v.left+=p/2),"bottom"===e.at[1]?v.top+=m:"center"===e.at[1]&&(v.top+=m/2),a=i(k.at,p,m),v.left+=a[0],v.top+=a[1],this.each(function(){var n,l,c=t(this),u=c.outerWidth(),d=c.outerHeight(),f=s(this,"marginLeft"),b=s(this,"marginTop"),D=u+f+s(this,"marginRight")+w.width,T=d+b+s(this,"marginBottom")+w.height,C=t.extend({},v),M=i(k.my,c.outerWidth(),c.outerHeight());"right"===e.my[0]?C.left-=u:"center"===e.my[0]&&(C.left-=u/2),"bottom"===e.my[1]?C.top-=d:"center"===e.my[1]&&(C.top-=d/2),C.left+=M[0],C.top+=M[1],t.support.offsetFractions||(C.left=h(C.left),C.top=h(C.top)),n={marginLeft:f,marginTop:b},t.each(["left","top"],function(i,s){t.ui.position[x[i]]&&t.ui.position[x[i]][s](C,{targetWidth:p,targetHeight:m,elemWidth:u,elemHeight:d,collisionPosition:n,collisionWidth:D,collisionHeight:T,offset:[a[0]+M[0],a[1]+M[1]],my:e.my,at:e.at,within:y,elem:c})}),e.using&&(l=function(t){var i=g.left-C.left,s=i+p-u,n=g.top-C.top,a=n+m-d,h={target:{element:_,left:g.left,top:g.top,width:p,height:m},element:{element:c,left:C.left,top:C.top,width:u,height:d},horizontal:0>s?"left":i>0?"right":"center",vertical:0>a?"top":n>0?"bottom":"middle"};u>p&&p>r(i+s)&&(h.horizontal="center"),d>m&&m>r(n+a)&&(h.vertical="middle"),h.important=o(r(i),r(s))>o(r(n),r(a))?"horizontal":"vertical",e.using.call(this,t,h)}),c.offset(t.extend(C,{using:l}))})},t.ui.position={fit:{left:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollLeft:s.offset.left,a=s.width,r=t.left-e.collisionPosition.marginLeft,h=n-r,l=r+e.collisionWidth-a-n;e.collisionWidth>a?h>0&&0>=l?(i=t.left+h+e.collisionWidth-a-n,t.left+=h-i):t.left=l>0&&0>=h?n:h>l?n+a-e.collisionWidth:n:h>0?t.left+=h:l>0?t.left-=l:t.left=o(t.left-r,t.left)},top:function(t,e){var i,s=e.within,n=s.isWindow?s.scrollTop:s.offset.top,a=e.within.height,r=t.top-e.collisionPosition.marginTop,h=n-r,l=r+e.collisionHeight-a-n;e.collisionHeight>a?h>0&&0>=l?(i=t.top+h+e.collisionHeight-a-n,t.top+=h-i):t.top=l>0&&0>=h?n:h>l?n+a-e.collisionHeight:n:h>0?t.top+=h:l>0?t.top-=l:t.top=o(t.top-r,t.top)}},flip:{left:function(t,e){var i,s,n=e.within,a=n.offset.left+n.scrollLeft,o=n.width,h=n.isWindow?n.scrollLeft:n.offset.left,l=t.left-e.collisionPosition.marginLeft,c=l-h,u=l+e.collisionWidth-o-h,d="left"===e.my[0]?-e.elemWidth:"right"===e.my[0]?e.elemWidth:0,p="left"===e.at[0]?e.targetWidth:"right"===e.at[0]?-e.targetWidth:0,f=-2*e.offset[0];0>c?(i=t.left+d+p+f+e.collisionWidth-o-a,(0>i||r(c)>i)&&(t.left+=d+p+f)):u>0&&(s=t.left-e.collisionPosition.marginLeft+d+p+f-h,(s>0||u>r(s))&&(t.left+=d+p+f))},top:function(t,e){var i,s,n=e.within,a=n.offset.top+n.scrollTop,o=n.height,h=n.isWindow?n.scrollTop:n.offset.top,l=t.top-e.collisionPosition.marginTop,c=l-h,u=l+e.collisionHeight-o-h,d="top"===e.my[1],p=d?-e.elemHeight:"bottom"===e.my[1]?e.elemHeight:0,f="top"===e.at[1]?e.targetHeight:"bottom"===e.at[1]?-e.targetHeight:0,m=-2*e.offset[1];0>c?(s=t.top+p+f+m+e.collisionHeight-o-a,t.top+p+f+m>c&&(0>s||r(c)>s)&&(t.top+=p+f+m)):u>0&&(i=t.top-e.collisionPosition.marginTop+p+f+m-h,t.top+p+f+m>u&&(i>0||u>r(i))&&(t.top+=p+f+m))}},flipfit:{left:function(){t.ui.position.flip.left.apply(this,arguments),t.ui.position.fit.left.apply(this,arguments)},top:function(){t.ui.position.flip.top.apply(this,arguments),t.ui.position.fit.top.apply(this,arguments)}}},function(){var e,i,s,n,a,o=document.getElementsByTagName("body")[0],r=document.createElement("div");e=document.createElement(o?"div":"body"),s={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},o&&t.extend(s,{position:"absolute",left:"-1000px",top:"-1000px"});for(a in s)e.style[a]=s[a];e.appendChild(r),i=o||document.documentElement,i.insertBefore(e,i.firstChild),r.style.cssText="position: absolute; left: 10.7432222px;",n=t(r).offset().left,t.support.offsetFractions=n>10&&11>n,e.innerHTML="",i.removeChild(e)}()})(jQuery);(function(e){e.widget("ui.draggable",e.ui.mouse,{version:"1.10.3",widgetEventPrefix:"drag",options:{addClasses:!0,appendTo:"parent",axis:!1,connectToSortable:!1,containment:!1,cursor:"auto",cursorAt:!1,grid:!1,handle:!1,helper:"original",iframeFix:!1,opacity:!1,refreshPositions:!1,revert:!1,revertDuration:500,scope:"default",scroll:!0,scrollSensitivity:20,scrollSpeed:20,snap:!1,snapMode:"both",snapTolerance:20,stack:!1,zIndex:!1,drag:null,start:null,stop:null},_create:function(){"original"!==this.options.helper||/^(?:r|a|f)/.test(this.element.css("position"))||(this.element[0].style.position="relative"),this.options.addClasses&&this.element.addClass("ui-draggable"),this.options.disabled&&this.element.addClass("ui-draggable-disabled"),this._mouseInit()},_destroy:function(){this.element.removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled"),this._mouseDestroy()},_mouseCapture:function(t){var i=this.options;return this.helper||i.disabled||e(t.target).closest(".ui-resizable-handle").length>0?!1:(this.handle=this._getHandle(t),this.handle?(e(i.iframeFix===!0?"iframe":i.iframeFix).each(function(){e("<div class='ui-draggable-iframeFix' style='background: #fff;'></div>").css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1e3}).css(e(this).offset()).appendTo("body")}),!0):!1)},_mouseStart:function(t){var i=this.options;return this.helper=this._createHelper(t),this.helper.addClass("ui-draggable-dragging"),this._cacheHelperProportions(),e.ui.ddmanager&&(e.ui.ddmanager.current=this),this._cacheMargins(),this.cssPosition=this.helper.css("position"),this.scrollParent=this.helper.scrollParent(),this.offsetParent=this.helper.offsetParent(),this.offsetParentCssPosition=this.offsetParent.css("position"),this.offset=this.positionAbs=this.element.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},this.offset.scroll=!1,e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.originalPosition=this.position=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,i.cursorAt&&this._adjustOffsetFromHelper(i.cursorAt),this._setContainment(),this._trigger("start",t)===!1?(this._clear(),!1):(this._cacheHelperProportions(),e.ui.ddmanager&&!i.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this._mouseDrag(t,!0),e.ui.ddmanager&&e.ui.ddmanager.dragStart(this,t),!0)},_mouseDrag:function(t,i){if("fixed"===this.offsetParentCssPosition&&(this.offset.parent=this._getParentOffset()),this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),!i){var s=this._uiHash();if(this._trigger("drag",t,s)===!1)return this._mouseUp({}),!1;this.position=s.position}return this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),!1},_mouseStop:function(t){var i=this,s=!1;return e.ui.ddmanager&&!this.options.dropBehaviour&&(s=e.ui.ddmanager.drop(this,t)),this.dropped&&(s=this.dropped,this.dropped=!1),"original"!==this.options.helper||e.contains(this.element[0].ownerDocument,this.element[0])?("invalid"===this.options.revert&&!s||"valid"===this.options.revert&&s||this.options.revert===!0||e.isFunction(this.options.revert)&&this.options.revert.call(this.element,s)?e(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){i._trigger("stop",t)!==!1&&i._clear()}):this._trigger("stop",t)!==!1&&this._clear(),!1):!1},_mouseUp:function(t){return e("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)}),e.ui.ddmanager&&e.ui.ddmanager.dragStop(this,t),e.ui.mouse.prototype._mouseUp.call(this,t)},cancel:function(){return this.helper.is(".ui-draggable-dragging")?this._mouseUp({}):this._clear(),this},_getHandle:function(t){return this.options.handle?!!e(t.target).closest(this.element.find(this.options.handle)).length:!0},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t])):"clone"===i.helper?this.element.clone().removeAttr("id"):this.element;return s.parents("body").length||s.appendTo("parent"===i.appendTo?this.element[0].parentNode:i.appendTo),s[0]===this.element[0]||/(fixed|absolute)/.test(s.css("position"))||s.css("position","absolute"),s},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.element.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.element.css("marginLeft"),10)||0,top:parseInt(this.element.css("marginTop"),10)||0,right:parseInt(this.element.css("marginRight"),10)||0,bottom:parseInt(this.element.css("marginBottom"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,n=this.options;return n.containment?"window"===n.containment?(this.containment=[e(window).scrollLeft()-this.offset.relative.left-this.offset.parent.left,e(window).scrollTop()-this.offset.relative.top-this.offset.parent.top,e(window).scrollLeft()+e(window).width()-this.helperProportions.width-this.margins.left,e(window).scrollTop()+(e(window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):"document"===n.containment?(this.containment=[0,0,e(document).width()-this.helperProportions.width-this.margins.left,(e(document).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top],undefined):n.containment.constructor===Array?(this.containment=n.containment,undefined):("parent"===n.containment&&(n.containment=this.helper[0].parentNode),i=e(n.containment),s=i[0],s&&(t="hidden"!==i.css("overflow"),this.containment=[(parseInt(i.css("borderLeftWidth"),10)||0)+(parseInt(i.css("paddingLeft"),10)||0),(parseInt(i.css("borderTopWidth"),10)||0)+(parseInt(i.css("paddingTop"),10)||0),(t?Math.max(s.scrollWidth,s.offsetWidth):s.offsetWidth)-(parseInt(i.css("borderRightWidth"),10)||0)-(parseInt(i.css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left-this.margins.right,(t?Math.max(s.scrollHeight,s.offsetHeight):s.offsetHeight)-(parseInt(i.css("borderBottomWidth"),10)||0)-(parseInt(i.css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top-this.margins.bottom],this.relative_container=i),undefined):(this.containment=null,undefined)},_convertPositionTo:function(t,i){i||(i=this.position);var s="absolute"===t?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent;return this.offset.scroll||(this.offset.scroll={top:n.scrollTop(),left:n.scrollLeft()}),{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top)*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)*s}},_generatePosition:function(t){var i,s,n,a,o=this.options,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=t.pageX,l=t.pageY;return this.offset.scroll||(this.offset.scroll={top:r.scrollTop(),left:r.scrollLeft()}),this.originalPosition&&(this.containment&&(this.relative_container?(s=this.relative_container.offset(),i=[this.containment[0]+s.left,this.containment[1]+s.top,this.containment[2]+s.left,this.containment[3]+s.top]):i=this.containment,t.pageX-this.offset.click.left<i[0]&&(h=i[0]+this.offset.click.left),t.pageY-this.offset.click.top<i[1]&&(l=i[1]+this.offset.click.top),t.pageX-this.offset.click.left>i[2]&&(h=i[2]+this.offset.click.left),t.pageY-this.offset.click.top>i[3]&&(l=i[3]+this.offset.click.top)),o.grid&&(n=o.grid[1]?this.originalPageY+Math.round((l-this.originalPageY)/o.grid[1])*o.grid[1]:this.originalPageY,l=i?n-this.offset.click.top>=i[1]||n-this.offset.click.top>i[3]?n:n-this.offset.click.top>=i[1]?n-o.grid[1]:n+o.grid[1]:n,a=o.grid[0]?this.originalPageX+Math.round((h-this.originalPageX)/o.grid[0])*o.grid[0]:this.originalPageX,h=i?a-this.offset.click.left>=i[0]||a-this.offset.click.left>i[2]?a:a-this.offset.click.left>=i[0]?a-o.grid[0]:a+o.grid[0]:a)),{top:l-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():this.offset.scroll.top),left:h-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():this.offset.scroll.left)}},_clear:function(){this.helper.removeClass("ui-draggable-dragging"),this.helper[0]===this.element[0]||this.cancelHelperRemoval||this.helper.remove(),this.helper=null,this.cancelHelperRemoval=!1},_trigger:function(t,i,s){return s=s||this._uiHash(),e.ui.plugin.call(this,t,[i,s]),"drag"===t&&(this.positionAbs=this._convertPositionTo("absolute")),e.Widget.prototype._trigger.call(this,t,i,s)},plugins:{},_uiHash:function(){return{helper:this.helper,position:this.position,originalPosition:this.originalPosition,offset:this.positionAbs}}}),e.ui.plugin.add("draggable","connectToSortable",{start:function(t,i){var s=e(this).data("ui-draggable"),n=s.options,a=e.extend({},i,{item:s.element});s.sortables=[],e(n.connectToSortable).each(function(){var i=e.data(this,"ui-sortable");i&&!i.options.disabled&&(s.sortables.push({instance:i,shouldRevert:i.options.revert}),i.refreshPositions(),i._trigger("activate",t,a))})},stop:function(t,i){var s=e(this).data("ui-draggable"),n=e.extend({},i,{item:s.element});e.each(s.sortables,function(){this.instance.isOver?(this.instance.isOver=0,s.cancelHelperRemoval=!0,this.instance.cancelHelperRemoval=!1,this.shouldRevert&&(this.instance.options.revert=this.shouldRevert),this.instance._mouseStop(t),this.instance.options.helper=this.instance.options._helper,"original"===s.options.helper&&this.instance.currentItem.css({top:"auto",left:"auto"})):(this.instance.cancelHelperRemoval=!1,this.instance._trigger("deactivate",t,n))})},drag:function(t,i){var s=e(this).data("ui-draggable"),n=this;e.each(s.sortables,function(){var a=!1,o=this;this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this.instance._intersectsWith(this.instance.containerCache)&&(a=!0,e.each(s.sortables,function(){return this.instance.positionAbs=s.positionAbs,this.instance.helperProportions=s.helperProportions,this.instance.offset.click=s.offset.click,this!==o&&this.instance._intersectsWith(this.instance.containerCache)&&e.contains(o.instance.element[0],this.instance.element[0])&&(a=!1),a})),a?(this.instance.isOver||(this.instance.isOver=1,this.instance.currentItem=e(n).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item",!0),this.instance.options._helper=this.instance.options.helper,this.instance.options.helper=function(){return i.helper[0]},t.target=this.instance.currentItem[0],this.instance._mouseCapture(t,!0),this.instance._mouseStart(t,!0,!0),this.instance.offset.click.top=s.offset.click.top,this.instance.offset.click.left=s.offset.click.left,this.instance.offset.parent.left-=s.offset.parent.left-this.instance.offset.parent.left,this.instance.offset.parent.top-=s.offset.parent.top-this.instance.offset.parent.top,s._trigger("toSortable",t),s.dropped=this.instance.element,s.currentItem=s.element,this.instance.fromOutside=s),this.instance.currentItem&&this.instance._mouseDrag(t)):this.instance.isOver&&(this.instance.isOver=0,this.instance.cancelHelperRemoval=!0,this.instance.options.revert=!1,this.instance._trigger("out",t,this.instance._uiHash(this.instance)),this.instance._mouseStop(t,!0),this.instance.options.helper=this.instance.options._helper,this.instance.currentItem.remove(),this.instance.placeholder&&this.instance.placeholder.remove(),s._trigger("fromSortable",t),s.dropped=!1)})}}),e.ui.plugin.add("draggable","cursor",{start:function(){var t=e("body"),i=e(this).data("ui-draggable").options;t.css("cursor")&&(i._cursor=t.css("cursor")),t.css("cursor",i.cursor)},stop:function(){var t=e(this).data("ui-draggable").options;t._cursor&&e("body").css("cursor",t._cursor)}}),e.ui.plugin.add("draggable","opacity",{start:function(t,i){var s=e(i.helper),n=e(this).data("ui-draggable").options;s.css("opacity")&&(n._opacity=s.css("opacity")),s.css("opacity",n.opacity)},stop:function(t,i){var s=e(this).data("ui-draggable").options;s._opacity&&e(i.helper).css("opacity",s._opacity)}}),e.ui.plugin.add("draggable","scroll",{start:function(){var t=e(this).data("ui-draggable");t.scrollParent[0]!==document&&"HTML"!==t.scrollParent[0].tagName&&(t.overflowOffset=t.scrollParent.offset())},drag:function(t){var i=e(this).data("ui-draggable"),s=i.options,n=!1;i.scrollParent[0]!==document&&"HTML"!==i.scrollParent[0].tagName?(s.axis&&"x"===s.axis||(i.overflowOffset.top+i.scrollParent[0].offsetHeight-t.pageY<s.scrollSensitivity?i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop+s.scrollSpeed:t.pageY-i.overflowOffset.top<s.scrollSensitivity&&(i.scrollParent[0].scrollTop=n=i.scrollParent[0].scrollTop-s.scrollSpeed)),s.axis&&"y"===s.axis||(i.overflowOffset.left+i.scrollParent[0].offsetWidth-t.pageX<s.scrollSensitivity?i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft+s.scrollSpeed:t.pageX-i.overflowOffset.left<s.scrollSensitivity&&(i.scrollParent[0].scrollLeft=n=i.scrollParent[0].scrollLeft-s.scrollSpeed))):(s.axis&&"x"===s.axis||(t.pageY-e(document).scrollTop()<s.scrollSensitivity?n=e(document).scrollTop(e(document).scrollTop()-s.scrollSpeed):e(window).height()-(t.pageY-e(document).scrollTop())<s.scrollSensitivity&&(n=e(document).scrollTop(e(document).scrollTop()+s.scrollSpeed))),s.axis&&"y"===s.axis||(t.pageX-e(document).scrollLeft()<s.scrollSensitivity?n=e(document).scrollLeft(e(document).scrollLeft()-s.scrollSpeed):e(window).width()-(t.pageX-e(document).scrollLeft())<s.scrollSensitivity&&(n=e(document).scrollLeft(e(document).scrollLeft()+s.scrollSpeed)))),n!==!1&&e.ui.ddmanager&&!s.dropBehaviour&&e.ui.ddmanager.prepareOffsets(i,t)}}),e.ui.plugin.add("draggable","snap",{start:function(){var t=e(this).data("ui-draggable"),i=t.options;t.snapElements=[],e(i.snap.constructor!==String?i.snap.items||":data(ui-draggable)":i.snap).each(function(){var i=e(this),s=i.offset();this!==t.element[0]&&t.snapElements.push({item:this,width:i.outerWidth(),height:i.outerHeight(),top:s.top,left:s.left})})},drag:function(t,i){var s,n,a,o,r,h,l,u,c,d,p=e(this).data("ui-draggable"),f=p.options,m=f.snapTolerance,g=i.offset.left,v=g+p.helperProportions.width,b=i.offset.top,y=b+p.helperProportions.height;for(c=p.snapElements.length-1;c>=0;c--)r=p.snapElements[c].left,h=r+p.snapElements[c].width,l=p.snapElements[c].top,u=l+p.snapElements[c].height,r-m>v||g>h+m||l-m>y||b>u+m||!e.contains(p.snapElements[c].item.ownerDocument,p.snapElements[c].item)?(p.snapElements[c].snapping&&p.options.snap.release&&p.options.snap.release.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=!1):("inner"!==f.snapMode&&(s=m>=Math.abs(l-y),n=m>=Math.abs(u-b),a=m>=Math.abs(r-v),o=m>=Math.abs(h-g),s&&(i.position.top=p._convertPositionTo("relative",{top:l-p.helperProportions.height,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:u,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r-p.helperProportions.width}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h}).left-p.margins.left)),d=s||n||a||o,"outer"!==f.snapMode&&(s=m>=Math.abs(l-b),n=m>=Math.abs(u-y),a=m>=Math.abs(r-g),o=m>=Math.abs(h-v),s&&(i.position.top=p._convertPositionTo("relative",{top:l,left:0}).top-p.margins.top),n&&(i.position.top=p._convertPositionTo("relative",{top:u-p.helperProportions.height,left:0}).top-p.margins.top),a&&(i.position.left=p._convertPositionTo("relative",{top:0,left:r}).left-p.margins.left),o&&(i.position.left=p._convertPositionTo("relative",{top:0,left:h-p.helperProportions.width}).left-p.margins.left)),!p.snapElements[c].snapping&&(s||n||a||o||d)&&p.options.snap.snap&&p.options.snap.snap.call(p.element,t,e.extend(p._uiHash(),{snapItem:p.snapElements[c].item})),p.snapElements[c].snapping=s||n||a||o||d)}}),e.ui.plugin.add("draggable","stack",{start:function(){var t,i=this.data("ui-draggable").options,s=e.makeArray(e(i.stack)).sort(function(t,i){return(parseInt(e(t).css("zIndex"),10)||0)-(parseInt(e(i).css("zIndex"),10)||0)});s.length&&(t=parseInt(e(s[0]).css("zIndex"),10)||0,e(s).each(function(i){e(this).css("zIndex",t+i)}),this.css("zIndex",t+s.length))}}),e.ui.plugin.add("draggable","zIndex",{start:function(t,i){var s=e(i.helper),n=e(this).data("ui-draggable").options;s.css("zIndex")&&(n._zIndex=s.css("zIndex")),s.css("zIndex",n.zIndex)},stop:function(t,i){var s=e(this).data("ui-draggable").options;s._zIndex&&e(i.helper).css("zIndex",s._zIndex)}})})(jQuery);(function(e){function t(e,t,i){return e>t&&t+i>e}e.widget("ui.droppable",{version:"1.10.3",widgetEventPrefix:"drop",options:{accept:"*",activeClass:!1,addClasses:!0,greedy:!1,hoverClass:!1,scope:"default",tolerance:"intersect",activate:null,deactivate:null,drop:null,out:null,over:null},_create:function(){var t=this.options,i=t.accept;this.isover=!1,this.isout=!0,this.accept=e.isFunction(i)?i:function(e){return e.is(i)},this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight},e.ui.ddmanager.droppables[t.scope]=e.ui.ddmanager.droppables[t.scope]||[],e.ui.ddmanager.droppables[t.scope].push(this),t.addClasses&&this.element.addClass("ui-droppable")},_destroy:function(){for(var t=0,i=e.ui.ddmanager.droppables[this.options.scope];i.length>t;t++)i[t]===this&&i.splice(t,1);this.element.removeClass("ui-droppable ui-droppable-disabled")},_setOption:function(t,i){"accept"===t&&(this.accept=e.isFunction(i)?i:function(e){return e.is(i)}),e.Widget.prototype._setOption.apply(this,arguments)},_activate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.addClass(this.options.activeClass),i&&this._trigger("activate",t,this.ui(i))},_deactivate:function(t){var i=e.ui.ddmanager.current;this.options.activeClass&&this.element.removeClass(this.options.activeClass),i&&this._trigger("deactivate",t,this.ui(i))},_over:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.addClass(this.options.hoverClass),this._trigger("over",t,this.ui(i)))},_out:function(t){var i=e.ui.ddmanager.current;i&&(i.currentItem||i.element)[0]!==this.element[0]&&this.accept.call(this.element[0],i.currentItem||i.element)&&(this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("out",t,this.ui(i)))},_drop:function(t,i){var s=i||e.ui.ddmanager.current,n=!1;return s&&(s.currentItem||s.element)[0]!==this.element[0]?(this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function(){var t=e.data(this,"ui-droppable");return t.options.greedy&&!t.options.disabled&&t.options.scope===s.options.scope&&t.accept.call(t.element[0],s.currentItem||s.element)&&e.ui.intersect(s,e.extend(t,{offset:t.element.offset()}),t.options.tolerance)?(n=!0,!1):undefined}),n?!1:this.accept.call(this.element[0],s.currentItem||s.element)?(this.options.activeClass&&this.element.removeClass(this.options.activeClass),this.options.hoverClass&&this.element.removeClass(this.options.hoverClass),this._trigger("drop",t,this.ui(s)),this.element):!1):!1},ui:function(e){return{draggable:e.currentItem||e.element,helper:e.helper,position:e.position,offset:e.positionAbs}}}),e.ui.intersect=function(e,i,s){if(!i.offset)return!1;var n,a,o=(e.positionAbs||e.position.absolute).left,r=o+e.helperProportions.width,h=(e.positionAbs||e.position.absolute).top,l=h+e.helperProportions.height,u=i.offset.left,c=u+i.proportions.width,d=i.offset.top,p=d+i.proportions.height;switch(s){case"fit":return o>=u&&c>=r&&h>=d&&p>=l;case"intersect":return o+e.helperProportions.width/2>u&&c>r-e.helperProportions.width/2&&h+e.helperProportions.height/2>d&&p>l-e.helperProportions.height/2;case"pointer":return n=(e.positionAbs||e.position.absolute).left+(e.clickOffset||e.offset.click).left,a=(e.positionAbs||e.position.absolute).top+(e.clickOffset||e.offset.click).top,t(a,d,i.proportions.height)&&t(n,u,i.proportions.width);case"touch":return(h>=d&&p>=h||l>=d&&p>=l||d>h&&l>p)&&(o>=u&&c>=o||r>=u&&c>=r||u>o&&r>c);default:return!1}},e.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(t,i){var s,n,a=e.ui.ddmanager.droppables[t.options.scope]||[],o=i?i.type:null,r=(t.currentItem||t.element).find(":data(ui-droppable)").addBack();e:for(s=0;a.length>s;s++)if(!(a[s].options.disabled||t&&!a[s].accept.call(a[s].element[0],t.currentItem||t.element))){for(n=0;r.length>n;n++)if(r[n]===a[s].element[0]){a[s].proportions.height=0;continue e}a[s].visible="none"!==a[s].element.css("display"),a[s].visible&&("mousedown"===o&&a[s]._activate.call(a[s],i),a[s].offset=a[s].element.offset(),a[s].proportions={width:a[s].element[0].offsetWidth,height:a[s].element[0].offsetHeight})}},drop:function(t,i){var s=!1;return e.each((e.ui.ddmanager.droppables[t.options.scope]||[]).slice(),function(){this.options&&(!this.options.disabled&&this.visible&&e.ui.intersect(t,this,this.options.tolerance)&&(s=this._drop.call(this,i)||s),!this.options.disabled&&this.visible&&this.accept.call(this.element[0],t.currentItem||t.element)&&(this.isout=!0,this.isover=!1,this._deactivate.call(this,i)))}),s},dragStart:function(t,i){t.element.parentsUntil("body").bind("scroll.droppable",function(){t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)})},drag:function(t,i){t.options.refreshPositions&&e.ui.ddmanager.prepareOffsets(t,i),e.each(e.ui.ddmanager.droppables[t.options.scope]||[],function(){if(!this.options.disabled&&!this.greedyChild&&this.visible){var s,n,a,o=e.ui.intersect(t,this,this.options.tolerance),r=!o&&this.isover?"isout":o&&!this.isover?"isover":null;r&&(this.options.greedy&&(n=this.options.scope,a=this.element.parents(":data(ui-droppable)").filter(function(){return e.data(this,"ui-droppable").options.scope===n}),a.length&&(s=e.data(a[0],"ui-droppable"),s.greedyChild="isover"===r)),s&&"isover"===r&&(s.isover=!1,s.isout=!0,s._out.call(s,i)),this[r]=!0,this["isout"===r?"isover":"isout"]=!1,this["isover"===r?"_over":"_out"].call(this,i),s&&"isout"===r&&(s.isout=!1,s.isover=!0,s._over.call(s,i)))}})},dragStop:function(t,i){t.element.parentsUntil("body").unbind("scroll.droppable"),t.options.refreshPositions||e.ui.ddmanager.prepareOffsets(t,i)}}})(jQuery);(function(e){function t(e){return parseInt(e,10)||0}function i(e){return!isNaN(parseInt(e,10))}e.widget("ui.resizable",e.ui.mouse,{version:"1.10.3",widgetEventPrefix:"resize",options:{alsoResize:!1,animate:!1,animateDuration:"slow",animateEasing:"swing",aspectRatio:!1,autoHide:!1,containment:!1,ghost:!1,grid:!1,handles:"e,s,se",helper:!1,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:90,resize:null,start:null,stop:null},_create:function(){var t,i,s,n,a,o=this,r=this.options;if(this.element.addClass("ui-resizable"),e.extend(this,{_aspectRatio:!!r.aspectRatio,aspectRatio:r.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:r.helper||r.ghost||r.animate?r.helper||"ui-resizable-helper":null}),this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)&&(this.element.wrap(e("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")})),this.element=this.element.parent().data("ui-resizable",this.element.data("ui-resizable")),this.elementIsWrapper=!0,this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")}),this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0}),this.originalResizeStyle=this.originalElement.css("resize"),this.originalElement.css("resize","none"),this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"})),this.originalElement.css({margin:this.originalElement.css("margin")}),this._proportionallyResize()),this.handles=r.handles||(e(".ui-resizable-handle",this.element).length?{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"}:"e,s,se"),this.handles.constructor===String)for("all"===this.handles&&(this.handles="n,e,s,w,se,sw,ne,nw"),t=this.handles.split(","),this.handles={},i=0;t.length>i;i++)s=e.trim(t[i]),a="ui-resizable-"+s,n=e("<div class='ui-resizable-handle "+a+"'></div>"),n.css({zIndex:r.zIndex}),"se"===s&&n.addClass("ui-icon ui-icon-gripsmall-diagonal-se"),this.handles[s]=".ui-resizable-"+s,this.element.append(n);this._renderAxis=function(t){var i,s,n,a;t=t||this.element;for(i in this.handles)this.handles[i].constructor===String&&(this.handles[i]=e(this.handles[i],this.element).show()),this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)&&(s=e(this.handles[i],this.element),a=/sw|ne|nw|se|n|s/.test(i)?s.outerHeight():s.outerWidth(),n=["padding",/ne|nw|n/.test(i)?"Top":/se|sw|s/.test(i)?"Bottom":/^e$/.test(i)?"Right":"Left"].join(""),t.css(n,a),this._proportionallyResize()),e(this.handles[i]).length},this._renderAxis(this.element),this._handles=e(".ui-resizable-handle",this.element).disableSelection(),this._handles.mouseover(function(){o.resizing||(this.className&&(n=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)),o.axis=n&&n[1]?n[1]:"se")}),r.autoHide&&(this._handles.hide(),e(this.element).addClass("ui-resizable-autohide").mouseenter(function(){r.disabled||(e(this).removeClass("ui-resizable-autohide"),o._handles.show())}).mouseleave(function(){r.disabled||o.resizing||(e(this).addClass("ui-resizable-autohide"),o._handles.hide())})),this._mouseInit()},_destroy:function(){this._mouseDestroy();var t,i=function(t){e(t).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};return this.elementIsWrapper&&(i(this.element),t=this.element,this.originalElement.css({position:t.css("position"),width:t.outerWidth(),height:t.outerHeight(),top:t.css("top"),left:t.css("left")}).insertAfter(t),t.remove()),this.originalElement.css("resize",this.originalResizeStyle),i(this.originalElement),this},_mouseCapture:function(t){var i,s,n=!1;for(i in this.handles)s=e(this.handles[i])[0],(s===t.target||e.contains(s,t.target))&&(n=!0);return!this.options.disabled&&n},_mouseStart:function(i){var s,n,a,o=this.options,r=this.element.position(),h=this.element;return this.resizing=!0,/absolute/.test(h.css("position"))?h.css({position:"absolute",top:h.css("top"),left:h.css("left")}):h.is(".ui-draggable")&&h.css({position:"absolute",top:r.top,left:r.left}),this._renderProxy(),s=t(this.helper.css("left")),n=t(this.helper.css("top")),o.containment&&(s+=e(o.containment).scrollLeft()||0,n+=e(o.containment).scrollTop()||0),this.offset=this.helper.offset(),this.position={left:s,top:n},this.size=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalSize=this._helper?{width:h.outerWidth(),height:h.outerHeight()}:{width:h.width(),height:h.height()},this.originalPosition={left:s,top:n},this.sizeDiff={width:h.outerWidth()-h.width(),height:h.outerHeight()-h.height()},this.originalMousePosition={left:i.pageX,top:i.pageY},this.aspectRatio="number"==typeof o.aspectRatio?o.aspectRatio:this.originalSize.width/this.originalSize.height||1,a=e(".ui-resizable-"+this.axis).css("cursor"),e("body").css("cursor","auto"===a?this.axis+"-resize":a),h.addClass("ui-resizable-resizing"),this._propagate("start",i),!0},_mouseDrag:function(t){var i,s=this.helper,n={},a=this.originalMousePosition,o=this.axis,r=this.position.top,h=this.position.left,l=this.size.width,u=this.size.height,c=t.pageX-a.left||0,d=t.pageY-a.top||0,p=this._change[o];return p?(i=p.apply(this,[t,c,d]),this._updateVirtualBoundaries(t.shiftKey),(this._aspectRatio||t.shiftKey)&&(i=this._updateRatio(i,t)),i=this._respectSize(i,t),this._updateCache(i),this._propagate("resize",t),this.position.top!==r&&(n.top=this.position.top+"px"),this.position.left!==h&&(n.left=this.position.left+"px"),this.size.width!==l&&(n.width=this.size.width+"px"),this.size.height!==u&&(n.height=this.size.height+"px"),s.css(n),!this._helper&&this._proportionallyResizeElements.length&&this._proportionallyResize(),e.isEmptyObject(n)||this._trigger("resize",t,this.ui()),!1):!1},_mouseStop:function(t){this.resizing=!1;var i,s,n,a,o,r,h,l=this.options,u=this;return this._helper&&(i=this._proportionallyResizeElements,s=i.length&&/textarea/i.test(i[0].nodeName),n=s&&e.ui.hasScroll(i[0],"left")?0:u.sizeDiff.height,a=s?0:u.sizeDiff.width,o={width:u.helper.width()-a,height:u.helper.height()-n},r=parseInt(u.element.css("left"),10)+(u.position.left-u.originalPosition.left)||null,h=parseInt(u.element.css("top"),10)+(u.position.top-u.originalPosition.top)||null,l.animate||this.element.css(e.extend(o,{top:h,left:r})),u.helper.height(u.size.height),u.helper.width(u.size.width),this._helper&&!l.animate&&this._proportionallyResize()),e("body").css("cursor","auto"),this.element.removeClass("ui-resizable-resizing"),this._propagate("stop",t),this._helper&&this.helper.remove(),!1},_updateVirtualBoundaries:function(e){var t,s,n,a,o,r=this.options;o={minWidth:i(r.minWidth)?r.minWidth:0,maxWidth:i(r.maxWidth)?r.maxWidth:1/0,minHeight:i(r.minHeight)?r.minHeight:0,maxHeight:i(r.maxHeight)?r.maxHeight:1/0},(this._aspectRatio||e)&&(t=o.minHeight*this.aspectRatio,n=o.minWidth/this.aspectRatio,s=o.maxHeight*this.aspectRatio,a=o.maxWidth/this.aspectRatio,t>o.minWidth&&(o.minWidth=t),n>o.minHeight&&(o.minHeight=n),o.maxWidth>s&&(o.maxWidth=s),o.maxHeight>a&&(o.maxHeight=a)),this._vBoundaries=o},_updateCache:function(e){this.offset=this.helper.offset(),i(e.left)&&(this.position.left=e.left),i(e.top)&&(this.position.top=e.top),i(e.height)&&(this.size.height=e.height),i(e.width)&&(this.size.width=e.width)},_updateRatio:function(e){var t=this.position,s=this.size,n=this.axis;return i(e.height)?e.width=e.height*this.aspectRatio:i(e.width)&&(e.height=e.width/this.aspectRatio),"sw"===n&&(e.left=t.left+(s.width-e.width),e.top=null),"nw"===n&&(e.top=t.top+(s.height-e.height),e.left=t.left+(s.width-e.width)),e},_respectSize:function(e){var t=this._vBoundaries,s=this.axis,n=i(e.width)&&t.maxWidth&&t.maxWidth<e.width,a=i(e.height)&&t.maxHeight&&t.maxHeight<e.height,o=i(e.width)&&t.minWidth&&t.minWidth>e.width,r=i(e.height)&&t.minHeight&&t.minHeight>e.height,h=this.originalPosition.left+this.originalSize.width,l=this.position.top+this.size.height,u=/sw|nw|w/.test(s),c=/nw|ne|n/.test(s);return o&&(e.width=t.minWidth),r&&(e.height=t.minHeight),n&&(e.width=t.maxWidth),a&&(e.height=t.maxHeight),o&&u&&(e.left=h-t.minWidth),n&&u&&(e.left=h-t.maxWidth),r&&c&&(e.top=l-t.minHeight),a&&c&&(e.top=l-t.maxHeight),e.width||e.height||e.left||!e.top?e.width||e.height||e.top||!e.left||(e.left=null):e.top=null,e},_proportionallyResize:function(){if(this._proportionallyResizeElements.length){var e,t,i,s,n,a=this.helper||this.element;for(e=0;this._proportionallyResizeElements.length>e;e++){if(n=this._proportionallyResizeElements[e],!this.borderDif)for(this.borderDif=[],i=[n.css("borderTopWidth"),n.css("borderRightWidth"),n.css("borderBottomWidth"),n.css("borderLeftWidth")],s=[n.css("paddingTop"),n.css("paddingRight"),n.css("paddingBottom"),n.css("paddingLeft")],t=0;i.length>t;t++)this.borderDif[t]=(parseInt(i[t],10)||0)+(parseInt(s[t],10)||0);n.css({height:a.height()-this.borderDif[0]-this.borderDif[2]||0,width:a.width()-this.borderDif[1]-this.borderDif[3]||0})}}},_renderProxy:function(){var t=this.element,i=this.options;this.elementOffset=t.offset(),this._helper?(this.helper=this.helper||e("<div style='overflow:hidden;'></div>"),this.helper.addClass(this._helper).css({width:this.element.outerWidth()-1,height:this.element.outerHeight()-1,position:"absolute",left:this.elementOffset.left+"px",top:this.elementOffset.top+"px",zIndex:++i.zIndex}),this.helper.appendTo("body").disableSelection()):this.helper=this.element},_change:{e:function(e,t){return{width:this.originalSize.width+t}},w:function(e,t){var i=this.originalSize,s=this.originalPosition;return{left:s.left+t,width:i.width-t}},n:function(e,t,i){var s=this.originalSize,n=this.originalPosition;return{top:n.top+i,height:s.height-i}},s:function(e,t,i){return{height:this.originalSize.height+i}},se:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},sw:function(t,i,s){return e.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[t,i,s]))},ne:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[t,i,s]))},nw:function(t,i,s){return e.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[t,i,s]))}},_propagate:function(t,i){e.ui.plugin.call(this,t,[i,this.ui()]),"resize"!==t&&this._trigger(t,i,this.ui())},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}),e.ui.plugin.add("resizable","animate",{stop:function(t){var i=e(this).data("ui-resizable"),s=i.options,n=i._proportionallyResizeElements,a=n.length&&/textarea/i.test(n[0].nodeName),o=a&&e.ui.hasScroll(n[0],"left")?0:i.sizeDiff.height,r=a?0:i.sizeDiff.width,h={width:i.size.width-r,height:i.size.height-o},l=parseInt(i.element.css("left"),10)+(i.position.left-i.originalPosition.left)||null,u=parseInt(i.element.css("top"),10)+(i.position.top-i.originalPosition.top)||null;i.element.animate(e.extend(h,u&&l?{top:u,left:l}:{}),{duration:s.animateDuration,easing:s.animateEasing,step:function(){var s={width:parseInt(i.element.css("width"),10),height:parseInt(i.element.css("height"),10),top:parseInt(i.element.css("top"),10),left:parseInt(i.element.css("left"),10)};n&&n.length&&e(n[0]).css({width:s.width,height:s.height}),i._updateCache(s),i._propagate("resize",t)}})}}),e.ui.plugin.add("resizable","containment",{start:function(){var i,s,n,a,o,r,h,l=e(this).data("ui-resizable"),u=l.options,c=l.element,d=u.containment,p=d instanceof e?d.get(0):/parent/.test(d)?c.parent().get(0):d;p&&(l.containerElement=e(p),/document/.test(d)||d===document?(l.containerOffset={left:0,top:0},l.containerPosition={left:0,top:0},l.parentData={element:e(document),left:0,top:0,width:e(document).width(),height:e(document).height()||document.body.parentNode.scrollHeight}):(i=e(p),s=[],e(["Top","Right","Left","Bottom"]).each(function(e,n){s[e]=t(i.css("padding"+n))}),l.containerOffset=i.offset(),l.containerPosition=i.position(),l.containerSize={height:i.innerHeight()-s[3],width:i.innerWidth()-s[1]},n=l.containerOffset,a=l.containerSize.height,o=l.containerSize.width,r=e.ui.hasScroll(p,"left")?p.scrollWidth:o,h=e.ui.hasScroll(p)?p.scrollHeight:a,l.parentData={element:p,left:n.left,top:n.top,width:r,height:h}))},resize:function(t){var i,s,n,a,o=e(this).data("ui-resizable"),r=o.options,h=o.containerOffset,l=o.position,u=o._aspectRatio||t.shiftKey,c={top:0,left:0},d=o.containerElement;d[0]!==document&&/static/.test(d.css("position"))&&(c=h),l.left<(o._helper?h.left:0)&&(o.size.width=o.size.width+(o._helper?o.position.left-h.left:o.position.left-c.left),u&&(o.size.height=o.size.width/o.aspectRatio),o.position.left=r.helper?h.left:0),l.top<(o._helper?h.top:0)&&(o.size.height=o.size.height+(o._helper?o.position.top-h.top:o.position.top),u&&(o.size.width=o.size.height*o.aspectRatio),o.position.top=o._helper?h.top:0),o.offset.left=o.parentData.left+o.position.left,o.offset.top=o.parentData.top+o.position.top,i=Math.abs((o._helper?o.offset.left-c.left:o.offset.left-c.left)+o.sizeDiff.width),s=Math.abs((o._helper?o.offset.top-c.top:o.offset.top-h.top)+o.sizeDiff.height),n=o.containerElement.get(0)===o.element.parent().get(0),a=/relative|absolute/.test(o.containerElement.css("position")),n&&a&&(i-=o.parentData.left),i+o.size.width>=o.parentData.width&&(o.size.width=o.parentData.width-i,u&&(o.size.height=o.size.width/o.aspectRatio)),s+o.size.height>=o.parentData.height&&(o.size.height=o.parentData.height-s,u&&(o.size.width=o.size.height*o.aspectRatio))},stop:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.containerOffset,n=t.containerPosition,a=t.containerElement,o=e(t.helper),r=o.offset(),h=o.outerWidth()-t.sizeDiff.width,l=o.outerHeight()-t.sizeDiff.height;t._helper&&!i.animate&&/relative/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l}),t._helper&&!i.animate&&/static/.test(a.css("position"))&&e(this).css({left:r.left-n.left-s.left,width:h,height:l})}}),e.ui.plugin.add("resizable","alsoResize",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=function(t){e(t).each(function(){var t=e(this);t.data("ui-resizable-alsoresize",{width:parseInt(t.width(),10),height:parseInt(t.height(),10),left:parseInt(t.css("left"),10),top:parseInt(t.css("top"),10)})})};"object"!=typeof i.alsoResize||i.alsoResize.parentNode?s(i.alsoResize):i.alsoResize.length?(i.alsoResize=i.alsoResize[0],s(i.alsoResize)):e.each(i.alsoResize,function(e){s(e)})},resize:function(t,i){var s=e(this).data("ui-resizable"),n=s.options,a=s.originalSize,o=s.originalPosition,r={height:s.size.height-a.height||0,width:s.size.width-a.width||0,top:s.position.top-o.top||0,left:s.position.left-o.left||0},h=function(t,s){e(t).each(function(){var t=e(this),n=e(this).data("ui-resizable-alsoresize"),a={},o=s&&s.length?s:t.parents(i.originalElement[0]).length?["width","height"]:["width","height","top","left"];e.each(o,function(e,t){var i=(n[t]||0)+(r[t]||0);i&&i>=0&&(a[t]=i||null)}),t.css(a)})};"object"!=typeof n.alsoResize||n.alsoResize.nodeType?h(n.alsoResize):e.each(n.alsoResize,function(e,t){h(e,t)})},stop:function(){e(this).removeData("resizable-alsoresize")}}),e.ui.plugin.add("resizable","ghost",{start:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size;t.ghost=t.originalElement.clone(),t.ghost.css({opacity:.25,display:"block",position:"relative",height:s.height,width:s.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass("string"==typeof i.ghost?i.ghost:""),t.ghost.appendTo(t.helper)},resize:function(){var t=e(this).data("ui-resizable");t.ghost&&t.ghost.css({position:"relative",height:t.size.height,width:t.size.width})},stop:function(){var t=e(this).data("ui-resizable");t.ghost&&t.helper&&t.helper.get(0).removeChild(t.ghost.get(0))}}),e.ui.plugin.add("resizable","grid",{resize:function(){var t=e(this).data("ui-resizable"),i=t.options,s=t.size,n=t.originalSize,a=t.originalPosition,o=t.axis,r="number"==typeof i.grid?[i.grid,i.grid]:i.grid,h=r[0]||1,l=r[1]||1,u=Math.round((s.width-n.width)/h)*h,c=Math.round((s.height-n.height)/l)*l,d=n.width+u,p=n.height+c,f=i.maxWidth&&d>i.maxWidth,m=i.maxHeight&&p>i.maxHeight,g=i.minWidth&&i.minWidth>d,v=i.minHeight&&i.minHeight>p;i.grid=r,g&&(d+=h),v&&(p+=l),f&&(d-=h),m&&(p-=l),/^(se|s|e)$/.test(o)?(t.size.width=d,t.size.height=p):/^(ne)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.top=a.top-c):/^(sw)$/.test(o)?(t.size.width=d,t.size.height=p,t.position.left=a.left-u):(t.size.width=d,t.size.height=p,t.position.top=a.top-c,t.position.left=a.left-u)}})})(jQuery);(function(e){e.widget("ui.selectable",e.ui.mouse,{version:"1.10.3",options:{appendTo:"body",autoRefresh:!0,distance:0,filter:"*",tolerance:"touch",selected:null,selecting:null,start:null,stop:null,unselected:null,unselecting:null},_create:function(){var t,i=this;this.element.addClass("ui-selectable"),this.dragged=!1,this.refresh=function(){t=e(i.options.filter,i.element[0]),t.addClass("ui-selectee"),t.each(function(){var t=e(this),i=t.offset();e.data(this,"selectable-item",{element:this,$element:t,left:i.left,top:i.top,right:i.left+t.outerWidth(),bottom:i.top+t.outerHeight(),startselected:!1,selected:t.hasClass("ui-selected"),selecting:t.hasClass("ui-selecting"),unselecting:t.hasClass("ui-unselecting")})})},this.refresh(),this.selectees=t.addClass("ui-selectee"),this._mouseInit(),this.helper=e("<div class='ui-selectable-helper'></div>")},_destroy:function(){this.selectees.removeClass("ui-selectee").removeData("selectable-item"),this.element.removeClass("ui-selectable ui-selectable-disabled"),this._mouseDestroy()},_mouseStart:function(t){var i=this,s=this.options;this.opos=[t.pageX,t.pageY],this.options.disabled||(this.selectees=e(s.filter,this.element[0]),this._trigger("start",t),e(s.appendTo).append(this.helper),this.helper.css({left:t.pageX,top:t.pageY,width:0,height:0}),s.autoRefresh&&this.refresh(),this.selectees.filter(".ui-selected").each(function(){var s=e.data(this,"selectable-item");s.startselected=!0,t.metaKey||t.ctrlKey||(s.$element.removeClass("ui-selected"),s.selected=!1,s.$element.addClass("ui-unselecting"),s.unselecting=!0,i._trigger("unselecting",t,{unselecting:s.element}))}),e(t.target).parents().addBack().each(function(){var s,n=e.data(this,"selectable-item");return n?(s=!t.metaKey&&!t.ctrlKey||!n.$element.hasClass("ui-selected"),n.$element.removeClass(s?"ui-unselecting":"ui-selected").addClass(s?"ui-selecting":"ui-unselecting"),n.unselecting=!s,n.selecting=s,n.selected=s,s?i._trigger("selecting",t,{selecting:n.element}):i._trigger("unselecting",t,{unselecting:n.element}),!1):undefined}))},_mouseDrag:function(t){if(this.dragged=!0,!this.options.disabled){var i,s=this,n=this.options,a=this.opos[0],o=this.opos[1],r=t.pageX,h=t.pageY;return a>r&&(i=r,r=a,a=i),o>h&&(i=h,h=o,o=i),this.helper.css({left:a,top:o,width:r-a,height:h-o}),this.selectees.each(function(){var i=e.data(this,"selectable-item"),l=!1;i&&i.element!==s.element[0]&&("touch"===n.tolerance?l=!(i.left>r||a>i.right||i.top>h||o>i.bottom):"fit"===n.tolerance&&(l=i.left>a&&r>i.right&&i.top>o&&h>i.bottom),l?(i.selected&&(i.$element.removeClass("ui-selected"),i.selected=!1),i.unselecting&&(i.$element.removeClass("ui-unselecting"),i.unselecting=!1),i.selecting||(i.$element.addClass("ui-selecting"),i.selecting=!0,s._trigger("selecting",t,{selecting:i.element}))):(i.selecting&&((t.metaKey||t.ctrlKey)&&i.startselected?(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.$element.addClass("ui-selected"),i.selected=!0):(i.$element.removeClass("ui-selecting"),i.selecting=!1,i.startselected&&(i.$element.addClass("ui-unselecting"),i.unselecting=!0),s._trigger("unselecting",t,{unselecting:i.element}))),i.selected&&(t.metaKey||t.ctrlKey||i.startselected||(i.$element.removeClass("ui-selected"),i.selected=!1,i.$element.addClass("ui-unselecting"),i.unselecting=!0,s._trigger("unselecting",t,{unselecting:i.element})))))}),!1}},_mouseStop:function(t){var i=this;return this.dragged=!1,e(".ui-unselecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-unselecting"),s.unselecting=!1,s.startselected=!1,i._trigger("unselected",t,{unselected:s.element})}),e(".ui-selecting",this.element[0]).each(function(){var s=e.data(this,"selectable-item");s.$element.removeClass("ui-selecting").addClass("ui-selected"),s.selecting=!1,s.selected=!0,s.startselected=!0,i._trigger("selected",t,{selected:s.element})}),this._trigger("stop",t),this.helper.remove(),!1}})})(jQuery);(function(t){function e(t,e,i){return t>e&&e+i>t}function i(t){return/left|right/.test(t.css("float"))||/inline|table-cell/.test(t.css("display"))}t.widget("ui.sortable",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var t=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===t.axis||i(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var t=this.items.length-1;t>=0;t--)this.items[t].item.removeData(this.widgetName+"-item");return this},_setOption:function(e,i){"disabled"===e?(this.options[e]=i,this.widget().toggleClass("ui-sortable-disabled",!!i)):t.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(e,i){var s=null,n=!1,a=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(e),t(e.target).parents().each(function(){return t.data(this,a.widgetName+"-item")===a?(s=t(this),!1):undefined}),t.data(e.target,a.widgetName+"-item")===a&&(s=t(e.target)),s?!this.options.handle||i||(t(this.options.handle,s).find("*").addBack().each(function(){this===e.target&&(n=!0)}),n)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(e,i,s){var n,a,o=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(e),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},t.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(e),this.originalPageX=e.pageX,this.originalPageY=e.pageY,o.cursorAt&&this._adjustOffsetFromHelper(o.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),o.containment&&this._setContainment(),o.cursor&&"auto"!==o.cursor&&(a=this.document.find("body"),this.storedCursor=a.css("cursor"),a.css("cursor",o.cursor),this.storedStylesheet=t("<style>*{ cursor: "+o.cursor+" !important; }</style>").appendTo(a)),o.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",o.opacity)),o.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",o.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",e,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(n=this.containers.length-1;n>=0;n--)this.containers[n]._trigger("activate",e,this._uiHash(this));return t.ui.ddmanager&&(t.ui.ddmanager.current=this),t.ui.ddmanager&&!o.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(e),!0},_mouseDrag:function(e){var i,s,n,a,o=this.options,r=!1;for(this.position=this._generatePosition(e),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-e.pageY<o.scrollSensitivity?this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop+o.scrollSpeed:e.pageY-this.overflowOffset.top<o.scrollSensitivity&&(this.scrollParent[0].scrollTop=r=this.scrollParent[0].scrollTop-o.scrollSpeed),this.overflowOffset.left+this.scrollParent[0].offsetWidth-e.pageX<o.scrollSensitivity?this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft+o.scrollSpeed:e.pageX-this.overflowOffset.left<o.scrollSensitivity&&(this.scrollParent[0].scrollLeft=r=this.scrollParent[0].scrollLeft-o.scrollSpeed)):(e.pageY-t(document).scrollTop()<o.scrollSensitivity?r=t(document).scrollTop(t(document).scrollTop()-o.scrollSpeed):t(window).height()-(e.pageY-t(document).scrollTop())<o.scrollSensitivity&&(r=t(document).scrollTop(t(document).scrollTop()+o.scrollSpeed)),e.pageX-t(document).scrollLeft()<o.scrollSensitivity?r=t(document).scrollLeft(t(document).scrollLeft()-o.scrollSpeed):t(window).width()-(e.pageX-t(document).scrollLeft())<o.scrollSensitivity&&(r=t(document).scrollLeft(t(document).scrollLeft()+o.scrollSpeed))),r!==!1&&t.ui.ddmanager&&!o.dropBehaviour&&t.ui.ddmanager.prepareOffsets(this,e)),this.positionAbs=this._convertPositionTo("absolute"),this.options.axis&&"y"===this.options.axis||(this.helper[0].style.left=this.position.left+"px"),this.options.axis&&"x"===this.options.axis||(this.helper[0].style.top=this.position.top+"px"),i=this.items.length-1;i>=0;i--)if(s=this.items[i],n=s.item[0],a=this._intersectsWithPointer(s),a&&s.instance===this.currentContainer&&n!==this.currentItem[0]&&this.placeholder[1===a?"next":"prev"]()[0]!==n&&!t.contains(this.placeholder[0],n)&&("semi-dynamic"===this.options.type?!t.contains(this.element[0],n):!0)){if(this.direction=1===a?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(e,s),this._trigger("change",e,this._uiHash());break}return this._contactContainers(e),t.ui.ddmanager&&t.ui.ddmanager.drag(this,e),this._trigger("sort",e,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(e,i){if(e){if(t.ui.ddmanager&&!this.options.dropBehaviour&&t.ui.ddmanager.drop(this,e),this.options.revert){var s=this,n=this.placeholder.offset(),a=this.options.axis,o={};a&&"x"!==a||(o.left=n.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),a&&"y"!==a||(o.top=n.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,t(this.helper).animate(o,parseInt(this.options.revert,10)||500,function(){s._clear(e)})}else this._clear(e,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var e=this.containers.length-1;e>=0;e--)this.containers[e]._trigger("deactivate",null,this._uiHash(this)),this.containers[e].containerCache.over&&(this.containers[e]._trigger("out",null,this._uiHash(this)),this.containers[e].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),t.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?t(this.domPosition.prev).after(this.currentItem):t(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},t(i).each(function(){var i=(t(e.item||this).attr(e.attribute||"id")||"").match(e.expression||/(.+)[\-=_](.+)/);i&&s.push((e.key||i[1]+"[]")+"="+(e.key&&e.expression?i[1]:i[2]))}),!s.length&&e.key&&s.push(e.key+"="),s.join("&")},toArray:function(e){var i=this._getItemsAsjQuery(e&&e.connected),s=[];return e=e||{},i.each(function(){s.push(t(e.item||this).attr(e.attribute||"id")||"")}),s},_intersectsWith:function(t){var e=this.positionAbs.left,i=e+this.helperProportions.width,s=this.positionAbs.top,n=s+this.helperProportions.height,a=t.left,o=a+t.width,r=t.top,h=r+t.height,l=this.offset.click.top,c=this.offset.click.left,u="x"===this.options.axis||s+l>r&&h>s+l,d="y"===this.options.axis||e+c>a&&o>e+c,p=u&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>t[this.floating?"width":"height"]?p:e+this.helperProportions.width/2>a&&o>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>r&&h>n-this.helperProportions.height/2},_intersectsWithPointer:function(t){var i="x"===this.options.axis||e(this.positionAbs.top+this.offset.click.top,t.top,t.height),s="y"===this.options.axis||e(this.positionAbs.left+this.offset.click.left,t.left,t.width),n=i&&s,a=this._getDragVerticalDirection(),o=this._getDragHorizontalDirection();return n?this.floating?o&&"right"===o||"down"===a?2:1:a&&("down"===a?2:1):!1},_intersectsWithSides:function(t){var i=e(this.positionAbs.top+this.offset.click.top,t.top+t.height/2,t.height),s=e(this.positionAbs.left+this.offset.click.left,t.left+t.width/2,t.width),n=this._getDragVerticalDirection(),a=this._getDragHorizontalDirection();return this.floating&&a?"right"===a&&s||"left"===a&&!s:n&&("down"===n&&i||"up"===n&&!i)},_getDragVerticalDirection:function(){var t=this.positionAbs.top-this.lastPositionAbs.top;return 0!==t&&(t>0?"down":"up")},_getDragHorizontalDirection:function(){var t=this.positionAbs.left-this.lastPositionAbs.left;return 0!==t&&(t>0?"right":"left")},refresh:function(t){return this._refreshItems(t),this.refreshPositions(),this},_connectWith:function(){var t=this.options;return t.connectWith.constructor===String?[t.connectWith]:t.connectWith},_getItemsAsjQuery:function(e){var i,s,n,a,o=[],r=[],h=this._connectWith();if(h&&e)for(i=h.length-1;i>=0;i--)for(n=t(h[i]),s=n.length-1;s>=0;s--)a=t.data(n[s],this.widgetFullName),a&&a!==this&&!a.options.disabled&&r.push([t.isFunction(a.options.items)?a.options.items.call(a.element):t(a.options.items,a.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),a]);for(r.push([t.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):t(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),i=r.length-1;i>=0;i--)r[i][0].each(function(){o.push(this)});return t(o)},_removeCurrentsFromItems:function(){var e=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=t.grep(this.items,function(t){for(var i=0;e.length>i;i++)if(e[i]===t.item[0])return!1;return!0})},_refreshItems:function(e){this.items=[],this.containers=[this];var i,s,n,a,o,r,h,l,c=this.items,u=[[t.isFunction(this.options.items)?this.options.items.call(this.element[0],e,{item:this.currentItem}):t(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(n=t(d[i]),s=n.length-1;s>=0;s--)a=t.data(n[s],this.widgetFullName),a&&a!==this&&!a.options.disabled&&(u.push([t.isFunction(a.options.items)?a.options.items.call(a.element[0],e,{item:this.currentItem}):t(a.options.items,a.element),a]),this.containers.push(a));for(i=u.length-1;i>=0;i--)for(o=u[i][1],r=u[i][0],s=0,l=r.length;l>s;s++)h=t(r[s]),h.data(this.widgetName+"-item",o),c.push({item:h,instance:o,width:0,height:0,left:0,top:0})},refreshPositions:function(e){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,n,a;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(n=this.options.toleranceElement?t(this.options.toleranceElement,s.item):s.item,e||(s.width=n.outerWidth(),s.height=n.outerHeight()),a=n.offset(),s.left=a.left,s.top=a.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)a=this.containers[i].element.offset(),this.containers[i].containerCache.left=a.left,this.containers[i].containerCache.top=a.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(e){e=e||this;var i,s=e.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=e.currentItem[0].nodeName.toLowerCase(),n=t("<"+s+">",e.document[0]).addClass(i||e.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?e.currentItem.children().each(function(){t("<td> </td>",e.document[0]).attr("colspan",t(this).attr("colspan")||1).appendTo(n)}):"img"===s&&n.attr("src",e.currentItem.attr("src")),i||n.css("visibility","hidden"),n},update:function(t,n){(!i||s.forcePlaceholderSize)&&(n.height()||n.height(e.currentItem.innerHeight()-parseInt(e.currentItem.css("paddingTop")||0,10)-parseInt(e.currentItem.css("paddingBottom")||0,10)),n.width()||n.width(e.currentItem.innerWidth()-parseInt(e.currentItem.css("paddingLeft")||0,10)-parseInt(e.currentItem.css("paddingRight")||0,10)))}}),e.placeholder=t(s.placeholder.element.call(e.element,e.currentItem)),e.currentItem.after(e.placeholder),s.placeholder.update(e,e.placeholder)},_contactContainers:function(s){var n,a,o,r,h,l,c,u,d,p,f=null,m=null;for(n=this.containers.length-1;n>=0;n--)if(!t.contains(this.currentItem[0],this.containers[n].element[0]))if(this._intersectsWith(this.containers[n].containerCache)){if(f&&t.contains(this.containers[n].element[0],f.element[0]))continue;f=this.containers[n],m=n}else this.containers[n].containerCache.over&&(this.containers[n]._trigger("out",s,this._uiHash(this)),this.containers[n].containerCache.over=0);if(f)if(1===this.containers.length)this.containers[m].containerCache.over||(this.containers[m]._trigger("over",s,this._uiHash(this)),this.containers[m].containerCache.over=1);else{for(o=1e4,r=null,p=f.floating||i(this.currentItem),h=p?"left":"top",l=p?"width":"height",c=this.positionAbs[h]+this.offset.click[h],a=this.items.length-1;a>=0;a--)t.contains(this.containers[m].element[0],this.items[a].item[0])&&this.items[a].item[0]!==this.currentItem[0]&&(!p||e(this.positionAbs.top+this.offset.click.top,this.items[a].top,this.items[a].height))&&(u=this.items[a].item.offset()[h],d=!1,Math.abs(u-c)>Math.abs(u+this.items[a][l]-c)&&(d=!0,u+=this.items[a][l]),o>Math.abs(u-c)&&(o=Math.abs(u-c),r=this.items[a],this.direction=d?"up":"down"));if(!r&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[m])return;r?this._rearrange(s,r,null,!0):this._rearrange(s,null,this.containers[m].element,!0),this._trigger("change",s,this._uiHash()),this.containers[m]._trigger("change",s,this._uiHash(this)),this.currentContainer=this.containers[m],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[m]._trigger("over",s,this._uiHash(this)),this.containers[m].containerCache.over=1}},_createHelper:function(e){var i=this.options,s=t.isFunction(i.helper)?t(i.helper.apply(this.element[0],[e,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||t("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._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")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(e){"string"==typeof e&&(e=e.split(" ")),t.isArray(e)&&(e={left:+e[0],top:+e[1]||0}),"left"in e&&(this.offset.click.left=e.left+this.margins.left),"right"in e&&(this.offset.click.left=this.helperProportions.width-e.right+this.margins.left),"top"in e&&(this.offset.click.top=e.top+this.margins.top),"bottom"in e&&(this.offset.click.top=this.helperProportions.height-e.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var e=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])&&(e.left+=this.scrollParent.scrollLeft(),e.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&t.ui.ie)&&(e={top:0,left:0}),{top:e.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:e.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var t=this.currentItem.position();return{top:t.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:t.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e,i,s,n=this.options;"parent"===n.containment&&(n.containment=this.helper[0].parentNode),("document"===n.containment||"window"===n.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,t("document"===n.containment?document:window).width()-this.helperProportions.width-this.margins.left,(t("document"===n.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(n.containment)||(e=t(n.containment)[0],i=t(n.containment).offset(),s="hidden"!==t(e).css("overflow"),this.containment=[i.left+(parseInt(t(e).css("borderLeftWidth"),10)||0)+(parseInt(t(e).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(t(e).css("borderTopWidth"),10)||0)+(parseInt(t(e).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(e.scrollWidth,e.offsetWidth):e.offsetWidth)-(parseInt(t(e).css("borderLeftWidth"),10)||0)-(parseInt(t(e).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(e.scrollHeight,e.offsetHeight):e.offsetHeight)-(parseInt(t(e).css("borderTopWidth"),10)||0)-(parseInt(t(e).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(e,i){i||(i=this.position);var s="absolute"===e?1:-1,n="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,a=/(html|body)/i.test(n[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():a?0:n.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():a?0:n.scrollLeft())*s}},_generatePosition:function(e){var i,s,n=this.options,a=e.pageX,o=e.pageY,r="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&t.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(r[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(e.pageX-this.offset.click.left<this.containment[0]&&(a=this.containment[0]+this.offset.click.left),e.pageY-this.offset.click.top<this.containment[1]&&(o=this.containment[1]+this.offset.click.top),e.pageX-this.offset.click.left>this.containment[2]&&(a=this.containment[2]+this.offset.click.left),e.pageY-this.offset.click.top>this.containment[3]&&(o=this.containment[3]+this.offset.click.top)),n.grid&&(i=this.originalPageY+Math.round((o-this.originalPageY)/n.grid[1])*n.grid[1],o=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-n.grid[1]:i+n.grid[1]:i,s=this.originalPageX+Math.round((a-this.originalPageX)/n.grid[0])*n.grid[0],a=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-n.grid[0]:s+n.grid[0]:s)),{top:o-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:r.scrollTop()),left:a-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:r.scrollLeft())}},_rearrange:function(t,e,i,s){i?i[0].appendChild(this.placeholder[0]):e.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?e.item[0]:e.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var n=this.counter;this._delay(function(){n===this.counter&&this.refreshPositions(!s)})},_clear:function(t,e){this.reverting=!1;var i,s=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(i in this._storedCSS)("auto"===this._storedCSS[i]||"static"===this._storedCSS[i])&&(this._storedCSS[i]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!e&&s.push(function(t){this._trigger("receive",t,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||e||s.push(function(t){this._trigger("update",t,this._uiHash())}),this!==this.currentContainer&&(e||(s.push(function(t){this._trigger("remove",t,this._uiHash())}),s.push(function(t){return function(e){t._trigger("receive",e,this._uiHash(this))}}.call(this,this.currentContainer)),s.push(function(t){return function(e){t._trigger("update",e,this._uiHash(this))}}.call(this,this.currentContainer)))),i=this.containers.length-1;i>=0;i--)e||s.push(function(t){return function(e){t._trigger("deactivate",e,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(s.push(function(t){return function(e){t._trigger("out",e,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!e){for(this._trigger("beforeStop",t,this._uiHash()),i=0;s.length>i;i++)s[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!1}if(e||this._trigger("beforeStop",t,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null,!e){for(i=0;s.length>i;i++)s[i].call(this,t);this._trigger("stop",t,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){t.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(e){var i=e||this;return{helper:i.helper,placeholder:i.placeholder||t([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:e?e.element:null}}})})(jQuery);(function(t){var e=0,i={},s={};i.height=i.paddingTop=i.paddingBottom=i.borderTopWidth=i.borderBottomWidth="hide",s.height=s.paddingTop=s.paddingBottom=s.borderTopWidth=s.borderBottomWidth="show",t.widget("ui.accordion",{version:"1.10.3",options:{active:0,animate:{},collapsible:!1,event:"click",header:"> li > :first-child,> :not(li):even",heightStyle:"auto",icons:{activeHeader:"ui-icon-triangle-1-s",header:"ui-icon-triangle-1-e"},activate:null,beforeActivate:null},_create:function(){var e=this.options;this.prevShow=this.prevHide=t(),this.element.addClass("ui-accordion ui-widget ui-helper-reset").attr("role","tablist"),e.collapsible||e.active!==!1&&null!=e.active||(e.active=0),this._processPanels(),0>e.active&&(e.active+=this.headers.length),this._refresh()},_getCreateEventData:function(){return{header:this.active,panel:this.active.length?this.active.next():t(),content:this.active.length?this.active.next():t()}},_createIcons:function(){var e=this.options.icons;e&&(t("<span>").addClass("ui-accordion-header-icon ui-icon "+e.header).prependTo(this.headers),this.active.children(".ui-accordion-header-icon").removeClass(e.header).addClass(e.activeHeader),this.headers.addClass("ui-accordion-icons"))},_destroyIcons:function(){this.headers.removeClass("ui-accordion-icons").children(".ui-accordion-header-icon").remove()},_destroy:function(){var t;this.element.removeClass("ui-accordion ui-widget ui-helper-reset").removeAttr("role"),this.headers.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").removeAttr("role").removeAttr("aria-selected").removeAttr("aria-controls").removeAttr("tabIndex").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),this._destroyIcons(),t=this.headers.next().css("display","").removeAttr("role").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-labelledby").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled").each(function(){/^ui-accordion/.test(this.id)&&this.removeAttribute("id")}),"content"!==this.options.heightStyle&&t.css("height","")},_setOption:function(t,e){return"active"===t?(this._activate(e),undefined):("event"===t&&(this.options.event&&this._off(this.headers,this.options.event),this._setupEvents(e)),this._super(t,e),"collapsible"!==t||e||this.options.active!==!1||this._activate(0),"icons"===t&&(this._destroyIcons(),e&&this._createIcons()),"disabled"===t&&this.headers.add(this.headers.next()).toggleClass("ui-state-disabled",!!e),undefined)},_keydown:function(e){if(!e.altKey&&!e.ctrlKey){var i=t.ui.keyCode,s=this.headers.length,n=this.headers.index(e.target),a=!1;switch(e.keyCode){case i.RIGHT:case i.DOWN:a=this.headers[(n+1)%s];break;case i.LEFT:case i.UP:a=this.headers[(n-1+s)%s];break;case i.SPACE:case i.ENTER:this._eventHandler(e);break;case i.HOME:a=this.headers[0];break;case i.END:a=this.headers[s-1]}a&&(t(e.target).attr("tabIndex",-1),t(a).attr("tabIndex",0),a.focus(),e.preventDefault())}},_panelKeyDown:function(e){e.keyCode===t.ui.keyCode.UP&&e.ctrlKey&&t(e.currentTarget).prev().focus()},refresh:function(){var e=this.options;this._processPanels(),e.active===!1&&e.collapsible===!0||!this.headers.length?(e.active=!1,this.active=t()):e.active===!1?this._activate(0):this.active.length&&!t.contains(this.element[0],this.active[0])?this.headers.length===this.headers.find(".ui-state-disabled").length?(e.active=!1,this.active=t()):this._activate(Math.max(0,e.active-1)):e.active=this.headers.index(this.active),this._destroyIcons(),this._refresh()},_processPanels:function(){this.headers=this.element.find(this.options.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all"),this.headers.next().addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom").filter(":not(.ui-accordion-content-active)").hide()},_refresh:function(){var i,s=this.options,n=s.heightStyle,a=this.element.parent(),o=this.accordionId="ui-accordion-"+(this.element.attr("id")||++e);this.active=this._findActive(s.active).addClass("ui-accordion-header-active ui-state-active ui-corner-top").removeClass("ui-corner-all"),this.active.next().addClass("ui-accordion-content-active").show(),this.headers.attr("role","tab").each(function(e){var i=t(this),s=i.attr("id"),n=i.next(),a=n.attr("id");s||(s=o+"-header-"+e,i.attr("id",s)),a||(a=o+"-panel-"+e,n.attr("id",a)),i.attr("aria-controls",a),n.attr("aria-labelledby",s)}).next().attr("role","tabpanel"),this.headers.not(this.active).attr({"aria-selected":"false",tabIndex:-1}).next().attr({"aria-expanded":"false","aria-hidden":"true"}).hide(),this.active.length?this.active.attr({"aria-selected":"true",tabIndex:0}).next().attr({"aria-expanded":"true","aria-hidden":"false"}):this.headers.eq(0).attr("tabIndex",0),this._createIcons(),this._setupEvents(s.event),"fill"===n?(i=a.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.headers.each(function(){i-=t(this).outerHeight(!0)}),this.headers.next().each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===n&&(i=0,this.headers.next().each(function(){i=Math.max(i,t(this).css("height","").height())}).height(i))},_activate:function(e){var i=this._findActive(e)[0];i!==this.active[0]&&(i=i||this.active[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return"number"==typeof e?this.headers.eq(e):t()},_setupEvents:function(e){var i={keydown:"_keydown"};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.headers.add(this.headers.next())),this._on(this.headers,i),this._on(this.headers.next(),{keydown:"_panelKeyDown"}),this._hoverable(this.headers),this._focusable(this.headers)},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),a=n[0]===s[0],o=a&&i.collapsible,r=o?t():n.next(),h=s.next(),l={oldHeader:s,oldPanel:h,newHeader:o?t():n,newPanel:r};e.preventDefault(),a&&!i.collapsible||this._trigger("beforeActivate",e,l)===!1||(i.active=o?!1:this.headers.index(n),this.active=a?t():n,this._toggle(l),s.removeClass("ui-accordion-header-active ui-state-active"),i.icons&&s.children(".ui-accordion-header-icon").removeClass(i.icons.activeHeader).addClass(i.icons.header),a||(n.removeClass("ui-corner-all").addClass("ui-accordion-header-active ui-state-active ui-corner-top"),i.icons&&n.children(".ui-accordion-header-icon").removeClass(i.icons.header).addClass(i.icons.activeHeader),n.next().addClass("ui-accordion-content-active")))},_toggle:function(e){var i=e.newPanel,s=this.prevShow.length?this.prevShow:e.oldPanel;this.prevShow.add(this.prevHide).stop(!0,!0),this.prevShow=i,this.prevHide=s,this.options.animate?this._animate(i,s,e):(s.hide(),i.show(),this._toggleComplete(e)),s.attr({"aria-expanded":"false","aria-hidden":"true"}),s.prev().attr("aria-selected","false"),i.length&&s.length?s.prev().attr("tabIndex",-1):i.length&&this.headers.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),i.attr({"aria-expanded":"true","aria-hidden":"false"}).prev().attr({"aria-selected":"true",tabIndex:0})},_animate:function(t,e,n){var a,o,r,h=this,l=0,c=t.length&&(!e.length||t.index()<e.index()),u=this.options.animate||{},d=c&&u.down||u,p=function(){h._toggleComplete(n)};return"number"==typeof d&&(r=d),"string"==typeof d&&(o=d),o=o||d.easing||u.easing,r=r||d.duration||u.duration,e.length?t.length?(a=t.show().outerHeight(),e.animate(i,{duration:r,easing:o,step:function(t,e){e.now=Math.round(t)}}),t.hide().animate(s,{duration:r,easing:o,complete:p,step:function(t,i){i.now=Math.round(t),"height"!==i.prop?l+=i.now:"content"!==h.options.heightStyle&&(i.now=Math.round(a-e.outerHeight()-l),l=0)}}),undefined):e.animate(i,r,o,p):t.animate(s,r,o,p)},_toggleComplete:function(t){var e=t.oldPanel;e.removeClass("ui-accordion-content-active").prev().removeClass("ui-corner-top").addClass("ui-corner-all"),e.length&&(e.parent()[0].className=e.parent()[0].className),this._trigger("activate",null,t)}})})(jQuery);(function(t){var e=0;t.widget("ui.autocomplete",{version:"1.10.3",defaultElement:"<input>",options:{appendTo:null,autoFocus:!1,delay:300,minLength:1,position:{my:"left top",at:"left bottom",collision:"none"},source:null,change:null,close:null,focus:null,open:null,response:null,search:null,select:null},pending:0,_create:function(){var e,i,s,n=this.element[0].nodeName.toLowerCase(),a="textarea"===n,o="input"===n;this.isMultiLine=a?!0:o?!1:this.element.prop("isContentEditable"),this.valueMethod=this.element[a||o?"val":"text"],this.isNewMenu=!0,this.element.addClass("ui-autocomplete-input").attr("autocomplete","off"),this._on(this.element,{keydown:function(n){if(this.element.prop("readOnly"))return e=!0,s=!0,i=!0,undefined;e=!1,s=!1,i=!1;var a=t.ui.keyCode;switch(n.keyCode){case a.PAGE_UP:e=!0,this._move("previousPage",n);break;case a.PAGE_DOWN:e=!0,this._move("nextPage",n);break;case a.UP:e=!0,this._keyEvent("previous",n);break;case a.DOWN:e=!0,this._keyEvent("next",n);break;case a.ENTER:case a.NUMPAD_ENTER:this.menu.active&&(e=!0,n.preventDefault(),this.menu.select(n));break;case a.TAB:this.menu.active&&this.menu.select(n);break;case a.ESCAPE:this.menu.element.is(":visible")&&(this._value(this.term),this.close(n),n.preventDefault());break;default:i=!0,this._searchTimeout(n)}},keypress:function(s){if(e)return e=!1,(!this.isMultiLine||this.menu.element.is(":visible"))&&s.preventDefault(),undefined;if(!i){var n=t.ui.keyCode;switch(s.keyCode){case n.PAGE_UP:this._move("previousPage",s);break;case n.PAGE_DOWN:this._move("nextPage",s);break;case n.UP:this._keyEvent("previous",s);break;case n.DOWN:this._keyEvent("next",s)}}},input:function(t){return s?(s=!1,t.preventDefault(),undefined):(this._searchTimeout(t),undefined)},focus:function(){this.selectedItem=null,this.previous=this._value()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,undefined):(clearTimeout(this.searching),this.close(t),this._change(t),undefined)}}),this._initSource(),this.menu=t("<ul>").addClass("ui-autocomplete ui-front").appendTo(this._appendTo()).menu({role:null}).hide().data("ui-menu"),this._on(this.menu.element,{mousedown:function(e){e.preventDefault(),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur});var i=this.menu.element[0];t(e.target).closest(".ui-menu-item").length||this._delay(function(){var e=this;this.document.one("mousedown",function(s){s.target===e.element[0]||s.target===i||t.contains(i,s.target)||e.close()})})},menufocus:function(e,i){if(this.isNewMenu&&(this.isNewMenu=!1,e.originalEvent&&/^mouse/.test(e.originalEvent.type)))return this.menu.blur(),this.document.one("mousemove",function(){t(e.target).trigger(e.originalEvent)}),undefined;var s=i.item.data("ui-autocomplete-item");!1!==this._trigger("focus",e,{item:s})?e.originalEvent&&/^key/.test(e.originalEvent.type)&&this._value(s.value):this.liveRegion.text(s.value)},menuselect:function(t,e){var i=e.item.data("ui-autocomplete-item"),s=this.previous;this.element[0]!==this.document[0].activeElement&&(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s,this.selectedItem=i})),!1!==this._trigger("select",t,{item:i})&&this._value(i.value),this.term=this._value(),this.close(t),this.selectedItem=i}}),this.liveRegion=t("<span>",{role:"status","aria-live":"polite"}).addClass("ui-helper-hidden-accessible").insertBefore(this.element),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_destroy:function(){clearTimeout(this.searching),this.element.removeClass("ui-autocomplete-input").removeAttr("autocomplete"),this.menu.element.remove(),this.liveRegion.remove()},_setOption:function(t,e){this._super(t,e),"source"===t&&this._initSource(),"appendTo"===t&&this.menu.element.appendTo(this._appendTo()),"disabled"===t&&e&&this.xhr&&this.xhr.abort()},_appendTo:function(){var e=this.options.appendTo;return e&&(e=e.jquery||e.nodeType?t(e):this.document.find(e).eq(0)),e||(e=this.element.closest(".ui-front")),e.length||(e=this.document[0].body),e},_initSource:function(){var e,i,s=this;t.isArray(this.options.source)?(e=this.options.source,this.source=function(i,s){s(t.ui.autocomplete.filter(e,i.term))}):"string"==typeof this.options.source?(i=this.options.source,this.source=function(e,n){s.xhr&&s.xhr.abort(),s.xhr=t.ajax({url:i,data:e,dataType:"json",success:function(t){n(t)},error:function(){n([])}})}):this.source=this.options.source},_searchTimeout:function(t){clearTimeout(this.searching),this.searching=this._delay(function(){this.term!==this._value()&&(this.selectedItem=null,this.search(null,t))},this.options.delay)},search:function(t,e){return t=null!=t?t:this._value(),this.term=this._value(),t.length<this.options.minLength?this.close(e):this._trigger("search",e)!==!1?this._search(t):undefined},_search:function(t){this.pending++,this.element.addClass("ui-autocomplete-loading"),this.cancelSearch=!1,this.source({term:t},this._response())},_response:function(){var t=this,i=++e;return function(s){i===e&&t.__response(s),t.pending--,t.pending||t.element.removeClass("ui-autocomplete-loading")}},__response:function(t){t&&(t=this._normalize(t)),this._trigger("response",null,{content:t}),!this.options.disabled&&t&&t.length&&!this.cancelSearch?(this._suggest(t),this._trigger("open")):this._close()},close:function(t){this.cancelSearch=!0,this._close(t)},_close:function(t){this.menu.element.is(":visible")&&(this.menu.element.hide(),this.menu.blur(),this.isNewMenu=!0,this._trigger("close",t))},_change:function(t){this.previous!==this._value()&&this._trigger("change",t,{item:this.selectedItem})},_normalize:function(e){return e.length&&e[0].label&&e[0].value?e:t.map(e,function(e){return"string"==typeof e?{label:e,value:e}:t.extend({label:e.label||e.value,value:e.value||e.label},e)})},_suggest:function(e){var i=this.menu.element.empty();this._renderMenu(i,e),this.isNewMenu=!0,this.menu.refresh(),i.show(),this._resizeMenu(),i.position(t.extend({of:this.element},this.options.position)),this.options.autoFocus&&this.menu.next()},_resizeMenu:function(){var t=this.menu.element;t.outerWidth(Math.max(t.width("").outerWidth()+1,this.element.outerWidth()))},_renderMenu:function(e,i){var s=this;t.each(i,function(t,i){s._renderItemData(e,i)})},_renderItemData:function(t,e){return this._renderItem(t,e).data("ui-autocomplete-item",e)},_renderItem:function(e,i){return t("<li>").append(t("<a>").text(i.label)).appendTo(e)},_move:function(t,e){return this.menu.element.is(":visible")?this.menu.isFirstItem()&&/^previous/.test(t)||this.menu.isLastItem()&&/^next/.test(t)?(this._value(this.term),this.menu.blur(),undefined):(this.menu[t](e),undefined):(this.search(null,e),undefined)},widget:function(){return this.menu.element},_value:function(){return this.valueMethod.apply(this.element,arguments)},_keyEvent:function(t,e){(!this.isMultiLine||this.menu.element.is(":visible"))&&(this._move(t,e),e.preventDefault())}}),t.extend(t.ui.autocomplete,{escapeRegex:function(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")},filter:function(e,i){var s=RegExp(t.ui.autocomplete.escapeRegex(i),"i");return t.grep(e,function(t){return s.test(t.label||t.value||t)})}}),t.widget("ui.autocomplete",t.ui.autocomplete,{options:{messages:{noResults:"No search results.",results:function(t){return t+(t>1?" results are":" result is")+" available, use up and down arrow keys to navigate."}}},__response:function(t){var e;this._superApply(arguments),this.options.disabled||this.cancelSearch||(e=t&&t.length?this.options.messages.results(t.length):this.options.messages.noResults,this.liveRegion.text(e))}})})(jQuery);(function(t){var e,i,s,n,a="ui-button ui-widget ui-state-default ui-corner-all",o="ui-state-hover ui-state-active ",r="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",h=function(){var e=t(this);setTimeout(function(){e.find(":ui-button").button("refresh")},1)},l=function(e){var i=e.name,s=e.form,n=t([]);return i&&(i=i.replace(/'/g,"\\'"),n=s?t(s).find("[name='"+i+"']"):t("[name='"+i+"']",e.ownerDocument).filter(function(){return!this.form})),n};t.widget("ui.button",{version:"1.10.3",defaultElement:"<button>",options:{disabled:null,text:!0,label:null,icons:{primary:null,secondary:null}},_create:function(){this.element.closest("form").unbind("reset"+this.eventNamespace).bind("reset"+this.eventNamespace,h),"boolean"!=typeof this.options.disabled?this.options.disabled=!!this.element.prop("disabled"):this.element.prop("disabled",this.options.disabled),this._determineButtonType(),this.hasTitle=!!this.buttonElement.attr("title");var o=this,r=this.options,c="checkbox"===this.type||"radio"===this.type,u=c?"":"ui-state-active",d="ui-state-focus";null===r.label&&(r.label="input"===this.type?this.buttonElement.val():this.buttonElement.html()),this._hoverable(this.buttonElement),this.buttonElement.addClass(a).attr("role","button").bind("mouseenter"+this.eventNamespace,function(){r.disabled||this===e&&t(this).addClass("ui-state-active")}).bind("mouseleave"+this.eventNamespace,function(){r.disabled||t(this).removeClass(u)}).bind("click"+this.eventNamespace,function(t){r.disabled&&(t.preventDefault(),t.stopImmediatePropagation())}),this.element.bind("focus"+this.eventNamespace,function(){o.buttonElement.addClass(d)}).bind("blur"+this.eventNamespace,function(){o.buttonElement.removeClass(d)}),c&&(this.element.bind("change"+this.eventNamespace,function(){n||o.refresh()}),this.buttonElement.bind("mousedown"+this.eventNamespace,function(t){r.disabled||(n=!1,i=t.pageX,s=t.pageY)}).bind("mouseup"+this.eventNamespace,function(t){r.disabled||(i!==t.pageX||s!==t.pageY)&&(n=!0)})),"checkbox"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){return r.disabled||n?!1:undefined}):"radio"===this.type?this.buttonElement.bind("click"+this.eventNamespace,function(){if(r.disabled||n)return!1;t(this).addClass("ui-state-active"),o.buttonElement.attr("aria-pressed","true");var e=o.element[0];l(e).not(e).map(function(){return t(this).button("widget")[0]}).removeClass("ui-state-active").attr("aria-pressed","false")}):(this.buttonElement.bind("mousedown"+this.eventNamespace,function(){return r.disabled?!1:(t(this).addClass("ui-state-active"),e=this,o.document.one("mouseup",function(){e=null}),undefined)}).bind("mouseup"+this.eventNamespace,function(){return r.disabled?!1:(t(this).removeClass("ui-state-active"),undefined)}).bind("keydown"+this.eventNamespace,function(e){return r.disabled?!1:((e.keyCode===t.ui.keyCode.SPACE||e.keyCode===t.ui.keyCode.ENTER)&&t(this).addClass("ui-state-active"),undefined)}).bind("keyup"+this.eventNamespace+" blur"+this.eventNamespace,function(){t(this).removeClass("ui-state-active")}),this.buttonElement.is("a")&&this.buttonElement.keyup(function(e){e.keyCode===t.ui.keyCode.SPACE&&t(this).click()})),this._setOption("disabled",r.disabled),this._resetButton()},_determineButtonType:function(){var t,e,i;this.type=this.element.is("[type=checkbox]")?"checkbox":this.element.is("[type=radio]")?"radio":this.element.is("input")?"input":"button","checkbox"===this.type||"radio"===this.type?(t=this.element.parents().last(),e="label[for='"+this.element.attr("id")+"']",this.buttonElement=t.find(e),this.buttonElement.length||(t=t.length?t.siblings():this.element.siblings(),this.buttonElement=t.filter(e),this.buttonElement.length||(this.buttonElement=t.find(e))),this.element.addClass("ui-helper-hidden-accessible"),i=this.element.is(":checked"),i&&this.buttonElement.addClass("ui-state-active"),this.buttonElement.prop("aria-pressed",i)):this.buttonElement=this.element},widget:function(){return this.buttonElement},_destroy:function(){this.element.removeClass("ui-helper-hidden-accessible"),this.buttonElement.removeClass(a+" "+o+" "+r).removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()),this.hasTitle||this.buttonElement.removeAttr("title")},_setOption:function(t,e){return this._super(t,e),"disabled"===t?(e?this.element.prop("disabled",!0):this.element.prop("disabled",!1),undefined):(this._resetButton(),undefined)},refresh:function(){var e=this.element.is("input, button")?this.element.is(":disabled"):this.element.hasClass("ui-button-disabled");e!==this.options.disabled&&this._setOption("disabled",e),"radio"===this.type?l(this.element[0]).each(function(){t(this).is(":checked")?t(this).button("widget").addClass("ui-state-active").attr("aria-pressed","true"):t(this).button("widget").removeClass("ui-state-active").attr("aria-pressed","false")}):"checkbox"===this.type&&(this.element.is(":checked")?this.buttonElement.addClass("ui-state-active").attr("aria-pressed","true"):this.buttonElement.removeClass("ui-state-active").attr("aria-pressed","false"))},_resetButton:function(){if("input"===this.type)return this.options.label&&this.element.val(this.options.label),undefined;var e=this.buttonElement.removeClass(r),i=t("<span></span>",this.document[0]).addClass("ui-button-text").html(this.options.label).appendTo(e.empty()).text(),s=this.options.icons,n=s.primary&&s.secondary,a=[];s.primary||s.secondary?(this.options.text&&a.push("ui-button-text-icon"+(n?"s":s.primary?"-primary":"-secondary")),s.primary&&e.prepend("<span class='ui-button-icon-primary ui-icon "+s.primary+"'></span>"),s.secondary&&e.append("<span class='ui-button-icon-secondary ui-icon "+s.secondary+"'></span>"),this.options.text||(a.push(n?"ui-button-icons-only":"ui-button-icon-only"),this.hasTitle||e.attr("title",t.trim(i)))):a.push("ui-button-text-only"),e.addClass(a.join(" "))}}),t.widget("ui.buttonset",{version:"1.10.3",options:{items:"button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"},_create:function(){this.element.addClass("ui-buttonset")},_init:function(){this.refresh()},_setOption:function(t,e){"disabled"===t&&this.buttons.button("option",t,e),this._super(t,e)},refresh:function(){var e="rtl"===this.element.css("direction");this.buttons=this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function(){return t(this).button("widget")[0]}).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass(e?"ui-corner-right":"ui-corner-left").end().filter(":last").addClass(e?"ui-corner-left":"ui-corner-right").end().end()},_destroy:function(){this.element.removeClass("ui-buttonset"),this.buttons.map(function(){return t(this).button("widget")[0]}).removeClass("ui-corner-left ui-corner-right").end().button("destroy")}})})(jQuery);(function(t,e){function i(){this._curInst=null,this._keyEvent=!1,this._disabledInputs=[],this._datepickerShowing=!1,this._inDialog=!1,this._mainDivId="ui-datepicker-div",this._inlineClass="ui-datepicker-inline",this._appendClass="ui-datepicker-append",this._triggerClass="ui-datepicker-trigger",this._dialogClass="ui-datepicker-dialog",this._disableClass="ui-datepicker-disabled",this._unselectableClass="ui-datepicker-unselectable",this._currentClass="ui-datepicker-current-day",this._dayOverClass="ui-datepicker-days-cell-over",this.regional=[],this.regional[""]={closeText:"Done",prevText:"Prev",nextText:"Next",currentText:"Today",monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],monthNamesShort:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],dayNamesShort:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],dayNamesMin:["Su","Mo","Tu","We","Th","Fr","Sa"],weekHeader:"Wk",dateFormat:"mm/dd/yy",firstDay:0,isRTL:!1,showMonthAfterYear:!1,yearSuffix:""},this._defaults={showOn:"focus",showAnim:"fadeIn",showOptions:{},defaultDate:null,appendText:"",buttonText:"...",buttonImage:"",buttonImageOnly:!1,hideIfNoPrevNext:!1,navigationAsDateFormat:!1,gotoCurrent:!1,changeMonth:!1,changeYear:!1,yearRange:"c-10:c+10",showOtherMonths:!1,selectOtherMonths:!1,showWeek:!1,calculateWeek:this.iso8601Week,shortYearCutoff:"+10",minDate:null,maxDate:null,duration:"fast",beforeShowDay:null,beforeShow:null,onSelect:null,onChangeMonthYear:null,onClose:null,numberOfMonths:1,showCurrentAtPos:0,stepMonths:1,stepBigMonths:12,altField:"",altFormat:"",constrainInput:!0,showButtonPanel:!1,autoSize:!1,disabled:!1},t.extend(this._defaults,this.regional[""]),this.dpDiv=s(t("<div id='"+this._mainDivId+"' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"))}function s(e){var i="button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";return e.delegate(i,"mouseout",function(){t(this).removeClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).removeClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).removeClass("ui-datepicker-next-hover")}).delegate(i,"mouseover",function(){t.datepicker._isDisabledDatepicker(a.inline?e.parent()[0]:a.input[0])||(t(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover"),t(this).addClass("ui-state-hover"),-1!==this.className.indexOf("ui-datepicker-prev")&&t(this).addClass("ui-datepicker-prev-hover"),-1!==this.className.indexOf("ui-datepicker-next")&&t(this).addClass("ui-datepicker-next-hover"))})}function n(e,i){t.extend(e,i);for(var s in i)null==i[s]&&(e[s]=i[s]);return e}t.extend(t.ui,{datepicker:{version:"1.10.3"}});var a,r="datepicker";t.extend(i.prototype,{markerClassName:"hasDatepicker",maxRows:4,_widgetDatepicker:function(){return this.dpDiv},setDefaults:function(t){return n(this._defaults,t||{}),this},_attachDatepicker:function(e,i){var s,n,a;s=e.nodeName.toLowerCase(),n="div"===s||"span"===s,e.id||(this.uuid+=1,e.id="dp"+this.uuid),a=this._newInst(t(e),n),a.settings=t.extend({},i||{}),"input"===s?this._connectDatepicker(e,a):n&&this._inlineDatepicker(e,a)},_newInst:function(e,i){var n=e[0].id.replace(/([^A-Za-z0-9_\-])/g,"\\\\$1");return{id:n,input:e,selectedDay:0,selectedMonth:0,selectedYear:0,drawMonth:0,drawYear:0,inline:i,dpDiv:i?s(t("<div class='"+this._inlineClass+" ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")):this.dpDiv}},_connectDatepicker:function(e,i){var s=t(e);i.append=t([]),i.trigger=t([]),s.hasClass(this.markerClassName)||(this._attachments(s,i),s.addClass(this.markerClassName).keydown(this._doKeyDown).keypress(this._doKeyPress).keyup(this._doKeyUp),this._autoSize(i),t.data(e,r,i),i.settings.disabled&&this._disableDatepicker(e))},_attachments:function(e,i){var s,n,a,r=this._get(i,"appendText"),o=this._get(i,"isRTL");i.append&&i.append.remove(),r&&(i.append=t("<span class='"+this._appendClass+"'>"+r+"</span>"),e[o?"before":"after"](i.append)),e.unbind("focus",this._showDatepicker),i.trigger&&i.trigger.remove(),s=this._get(i,"showOn"),("focus"===s||"both"===s)&&e.focus(this._showDatepicker),("button"===s||"both"===s)&&(n=this._get(i,"buttonText"),a=this._get(i,"buttonImage"),i.trigger=t(this._get(i,"buttonImageOnly")?t("<img/>").addClass(this._triggerClass).attr({src:a,alt:n,title:n}):t("<button type='button'></button>").addClass(this._triggerClass).html(a?t("<img/>").attr({src:a,alt:n,title:n}):n)),e[o?"before":"after"](i.trigger),i.trigger.click(function(){return t.datepicker._datepickerShowing&&t.datepicker._lastInput===e[0]?t.datepicker._hideDatepicker():t.datepicker._datepickerShowing&&t.datepicker._lastInput!==e[0]?(t.datepicker._hideDatepicker(),t.datepicker._showDatepicker(e[0])):t.datepicker._showDatepicker(e[0]),!1}))},_autoSize:function(t){if(this._get(t,"autoSize")&&!t.inline){var e,i,s,n,a=new Date(2009,11,20),r=this._get(t,"dateFormat");r.match(/[DM]/)&&(e=function(t){for(i=0,s=0,n=0;t.length>n;n++)t[n].length>i&&(i=t[n].length,s=n);return s},a.setMonth(e(this._get(t,r.match(/MM/)?"monthNames":"monthNamesShort"))),a.setDate(e(this._get(t,r.match(/DD/)?"dayNames":"dayNamesShort"))+20-a.getDay())),t.input.attr("size",this._formatDate(t,a).length)}},_inlineDatepicker:function(e,i){var s=t(e);s.hasClass(this.markerClassName)||(s.addClass(this.markerClassName).append(i.dpDiv),t.data(e,r,i),this._setDate(i,this._getDefaultDate(i),!0),this._updateDatepicker(i),this._updateAlternate(i),i.settings.disabled&&this._disableDatepicker(e),i.dpDiv.css("display","block"))},_dialogDatepicker:function(e,i,s,a,o){var h,l,c,u,d,p=this._dialogInst;return p||(this.uuid+=1,h="dp"+this.uuid,this._dialogInput=t("<input type='text' id='"+h+"' style='position: absolute; top: -100px; width: 0px;'/>"),this._dialogInput.keydown(this._doKeyDown),t("body").append(this._dialogInput),p=this._dialogInst=this._newInst(this._dialogInput,!1),p.settings={},t.data(this._dialogInput[0],r,p)),n(p.settings,a||{}),i=i&&i.constructor===Date?this._formatDate(p,i):i,this._dialogInput.val(i),this._pos=o?o.length?o:[o.pageX,o.pageY]:null,this._pos||(l=document.documentElement.clientWidth,c=document.documentElement.clientHeight,u=document.documentElement.scrollLeft||document.body.scrollLeft,d=document.documentElement.scrollTop||document.body.scrollTop,this._pos=[l/2-100+u,c/2-150+d]),this._dialogInput.css("left",this._pos[0]+20+"px").css("top",this._pos[1]+"px"),p.settings.onSelect=s,this._inDialog=!0,this.dpDiv.addClass(this._dialogClass),this._showDatepicker(this._dialogInput[0]),t.blockUI&&t.blockUI(this.dpDiv),t.data(this._dialogInput[0],r,p),this},_destroyDatepicker:function(e){var i,s=t(e),n=t.data(e,r);s.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),t.removeData(e,r),"input"===i?(n.append.remove(),n.trigger.remove(),s.removeClass(this.markerClassName).unbind("focus",this._showDatepicker).unbind("keydown",this._doKeyDown).unbind("keypress",this._doKeyPress).unbind("keyup",this._doKeyUp)):("div"===i||"span"===i)&&s.removeClass(this.markerClassName).empty())},_enableDatepicker:function(e){var i,s,n=t(e),a=t.data(e,r);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!1,a.trigger.filter("button").each(function(){this.disabled=!1}).end().filter("img").css({opacity:"1.0",cursor:""})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().removeClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!1)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}))},_disableDatepicker:function(e){var i,s,n=t(e),a=t.data(e,r);n.hasClass(this.markerClassName)&&(i=e.nodeName.toLowerCase(),"input"===i?(e.disabled=!0,a.trigger.filter("button").each(function(){this.disabled=!0}).end().filter("img").css({opacity:"0.5",cursor:"default"})):("div"===i||"span"===i)&&(s=n.children("."+this._inlineClass),s.children().addClass("ui-state-disabled"),s.find("select.ui-datepicker-month, select.ui-datepicker-year").prop("disabled",!0)),this._disabledInputs=t.map(this._disabledInputs,function(t){return t===e?null:t}),this._disabledInputs[this._disabledInputs.length]=e)},_isDisabledDatepicker:function(t){if(!t)return!1;for(var e=0;this._disabledInputs.length>e;e++)if(this._disabledInputs[e]===t)return!0;return!1},_getInst:function(e){try{return t.data(e,r)}catch(i){throw"Missing instance data for this datepicker"}},_optionDatepicker:function(i,s,a){var r,o,h,l,c=this._getInst(i);return 2===arguments.length&&"string"==typeof s?"defaults"===s?t.extend({},t.datepicker._defaults):c?"all"===s?t.extend({},c.settings):this._get(c,s):null:(r=s||{},"string"==typeof s&&(r={},r[s]=a),c&&(this._curInst===c&&this._hideDatepicker(),o=this._getDateDatepicker(i,!0),h=this._getMinMaxDate(c,"min"),l=this._getMinMaxDate(c,"max"),n(c.settings,r),null!==h&&r.dateFormat!==e&&r.minDate===e&&(c.settings.minDate=this._formatDate(c,h)),null!==l&&r.dateFormat!==e&&r.maxDate===e&&(c.settings.maxDate=this._formatDate(c,l)),"disabled"in r&&(r.disabled?this._disableDatepicker(i):this._enableDatepicker(i)),this._attachments(t(i),c),this._autoSize(c),this._setDate(c,o),this._updateAlternate(c),this._updateDatepicker(c)),e)},_changeDatepicker:function(t,e,i){this._optionDatepicker(t,e,i)},_refreshDatepicker:function(t){var e=this._getInst(t);e&&this._updateDatepicker(e)},_setDateDatepicker:function(t,e){var i=this._getInst(t);i&&(this._setDate(i,e),this._updateDatepicker(i),this._updateAlternate(i))},_getDateDatepicker:function(t,e){var i=this._getInst(t);return i&&!i.inline&&this._setDateFromField(i,e),i?this._getDate(i):null},_doKeyDown:function(e){var i,s,n,a=t.datepicker._getInst(e.target),r=!0,o=a.dpDiv.is(".ui-datepicker-rtl");if(a._keyEvent=!0,t.datepicker._datepickerShowing)switch(e.keyCode){case 9:t.datepicker._hideDatepicker(),r=!1;break;case 13:return n=t("td."+t.datepicker._dayOverClass+":not(."+t.datepicker._currentClass+")",a.dpDiv),n[0]&&t.datepicker._selectDay(e.target,a.selectedMonth,a.selectedYear,n[0]),i=t.datepicker._get(a,"onSelect"),i?(s=t.datepicker._formatDate(a),i.apply(a.input?a.input[0]:null,[s,a])):t.datepicker._hideDatepicker(),!1;case 27:t.datepicker._hideDatepicker();break;case 33:t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(a,"stepBigMonths"):-t.datepicker._get(a,"stepMonths"),"M");break;case 34:t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(a,"stepBigMonths"):+t.datepicker._get(a,"stepMonths"),"M");break;case 35:(e.ctrlKey||e.metaKey)&&t.datepicker._clearDate(e.target),r=e.ctrlKey||e.metaKey;break;case 36:(e.ctrlKey||e.metaKey)&&t.datepicker._gotoToday(e.target),r=e.ctrlKey||e.metaKey;break;case 37:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,o?1:-1,"D"),r=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?-t.datepicker._get(a,"stepBigMonths"):-t.datepicker._get(a,"stepMonths"),"M");break;case 38:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,-7,"D"),r=e.ctrlKey||e.metaKey;break;case 39:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,o?-1:1,"D"),r=e.ctrlKey||e.metaKey,e.originalEvent.altKey&&t.datepicker._adjustDate(e.target,e.ctrlKey?+t.datepicker._get(a,"stepBigMonths"):+t.datepicker._get(a,"stepMonths"),"M");break;case 40:(e.ctrlKey||e.metaKey)&&t.datepicker._adjustDate(e.target,7,"D"),r=e.ctrlKey||e.metaKey;break;default:r=!1}else 36===e.keyCode&&e.ctrlKey?t.datepicker._showDatepicker(this):r=!1;r&&(e.preventDefault(),e.stopPropagation())},_doKeyPress:function(i){var s,n,a=t.datepicker._getInst(i.target);return t.datepicker._get(a,"constrainInput")?(s=t.datepicker._possibleChars(t.datepicker._get(a,"dateFormat")),n=String.fromCharCode(null==i.charCode?i.keyCode:i.charCode),i.ctrlKey||i.metaKey||" ">n||!s||s.indexOf(n)>-1):e},_doKeyUp:function(e){var i,s=t.datepicker._getInst(e.target);if(s.input.val()!==s.lastVal)try{i=t.datepicker.parseDate(t.datepicker._get(s,"dateFormat"),s.input?s.input.val():null,t.datepicker._getFormatConfig(s)),i&&(t.datepicker._setDateFromField(s),t.datepicker._updateAlternate(s),t.datepicker._updateDatepicker(s))}catch(n){}return!0},_showDatepicker:function(e){if(e=e.target||e,"input"!==e.nodeName.toLowerCase()&&(e=t("input",e.parentNode)[0]),!t.datepicker._isDisabledDatepicker(e)&&t.datepicker._lastInput!==e){var i,s,a,r,o,h,l;i=t.datepicker._getInst(e),t.datepicker._curInst&&t.datepicker._curInst!==i&&(t.datepicker._curInst.dpDiv.stop(!0,!0),i&&t.datepicker._datepickerShowing&&t.datepicker._hideDatepicker(t.datepicker._curInst.input[0])),s=t.datepicker._get(i,"beforeShow"),a=s?s.apply(e,[e,i]):{},a!==!1&&(n(i.settings,a),i.lastVal=null,t.datepicker._lastInput=e,t.datepicker._setDateFromField(i),t.datepicker._inDialog&&(e.value=""),t.datepicker._pos||(t.datepicker._pos=t.datepicker._findPos(e),t.datepicker._pos[1]+=e.offsetHeight),r=!1,t(e).parents().each(function(){return r|="fixed"===t(this).css("position"),!r}),o={left:t.datepicker._pos[0],top:t.datepicker._pos[1]},t.datepicker._pos=null,i.dpDiv.empty(),i.dpDiv.css({position:"absolute",display:"block",top:"-1000px"}),t.datepicker._updateDatepicker(i),o=t.datepicker._checkOffset(i,o,r),i.dpDiv.css({position:t.datepicker._inDialog&&t.blockUI?"static":r?"fixed":"absolute",display:"none",left:o.left+"px",top:o.top+"px"}),i.inline||(h=t.datepicker._get(i,"showAnim"),l=t.datepicker._get(i,"duration"),i.dpDiv.zIndex(t(e).zIndex()+1),t.datepicker._datepickerShowing=!0,t.effects&&t.effects.effect[h]?i.dpDiv.show(h,t.datepicker._get(i,"showOptions"),l):i.dpDiv[h||"show"](h?l:null),t.datepicker._shouldFocusInput(i)&&i.input.focus(),t.datepicker._curInst=i))}},_updateDatepicker:function(e){this.maxRows=4,a=e,e.dpDiv.empty().append(this._generateHTML(e)),this._attachHandlers(e),e.dpDiv.find("."+this._dayOverClass+" a").mouseover();var i,s=this._getNumberOfMonths(e),n=s[1],r=17;e.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width(""),n>1&&e.dpDiv.addClass("ui-datepicker-multi-"+n).css("width",r*n+"em"),e.dpDiv[(1!==s[0]||1!==s[1]?"add":"remove")+"Class"]("ui-datepicker-multi"),e.dpDiv[(this._get(e,"isRTL")?"add":"remove")+"Class"]("ui-datepicker-rtl"),e===t.datepicker._curInst&&t.datepicker._datepickerShowing&&t.datepicker._shouldFocusInput(e)&&e.input.focus(),e.yearshtml&&(i=e.yearshtml,setTimeout(function(){i===e.yearshtml&&e.yearshtml&&e.dpDiv.find("select.ui-datepicker-year:first").replaceWith(e.yearshtml),i=e.yearshtml=null},0))},_shouldFocusInput:function(t){return t.input&&t.input.is(":visible")&&!t.input.is(":disabled")&&!t.input.is(":focus")},_checkOffset:function(e,i,s){var n=e.dpDiv.outerWidth(),a=e.dpDiv.outerHeight(),r=e.input?e.input.outerWidth():0,o=e.input?e.input.outerHeight():0,h=document.documentElement.clientWidth+(s?0:t(document).scrollLeft()),l=document.documentElement.clientHeight+(s?0:t(document).scrollTop());return i.left-=this._get(e,"isRTL")?n-r:0,i.left-=s&&i.left===e.input.offset().left?t(document).scrollLeft():0,i.top-=s&&i.top===e.input.offset().top+o?t(document).scrollTop():0,i.left-=Math.min(i.left,i.left+n>h&&h>n?Math.abs(i.left+n-h):0),i.top-=Math.min(i.top,i.top+a>l&&l>a?Math.abs(a+o):0),i},_findPos:function(e){for(var i,s=this._getInst(e),n=this._get(s,"isRTL");e&&("hidden"===e.type||1!==e.nodeType||t.expr.filters.hidden(e));)e=e[n?"previousSibling":"nextSibling"];return i=t(e).offset(),[i.left,i.top]},_hideDatepicker:function(e){var i,s,n,a,o=this._curInst;!o||e&&o!==t.data(e,r)||this._datepickerShowing&&(i=this._get(o,"showAnim"),s=this._get(o,"duration"),n=function(){t.datepicker._tidyDialog(o)},t.effects&&(t.effects.effect[i]||t.effects[i])?o.dpDiv.hide(i,t.datepicker._get(o,"showOptions"),s,n):o.dpDiv["slideDown"===i?"slideUp":"fadeIn"===i?"fadeOut":"hide"](i?s:null,n),i||n(),this._datepickerShowing=!1,a=this._get(o,"onClose"),a&&a.apply(o.input?o.input[0]:null,[o.input?o.input.val():"",o]),this._lastInput=null,this._inDialog&&(this._dialogInput.css({position:"absolute",left:"0",top:"-100px"}),t.blockUI&&(t.unblockUI(),t("body").append(this.dpDiv))),this._inDialog=!1)},_tidyDialog:function(t){t.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar")},_checkExternalClick:function(e){if(t.datepicker._curInst){var i=t(e.target),s=t.datepicker._getInst(i[0]);(i[0].id!==t.datepicker._mainDivId&&0===i.parents("#"+t.datepicker._mainDivId).length&&!i.hasClass(t.datepicker.markerClassName)&&!i.closest("."+t.datepicker._triggerClass).length&&t.datepicker._datepickerShowing&&(!t.datepicker._inDialog||!t.blockUI)||i.hasClass(t.datepicker.markerClassName)&&t.datepicker._curInst!==s)&&t.datepicker._hideDatepicker()}},_adjustDate:function(e,i,s){var n=t(e),a=this._getInst(n[0]);this._isDisabledDatepicker(n[0])||(this._adjustInstDate(a,i+("M"===s?this._get(a,"showCurrentAtPos"):0),s),this._updateDatepicker(a))},_gotoToday:function(e){var i,s=t(e),n=this._getInst(s[0]);this._get(n,"gotoCurrent")&&n.currentDay?(n.selectedDay=n.currentDay,n.drawMonth=n.selectedMonth=n.currentMonth,n.drawYear=n.selectedYear=n.currentYear):(i=new Date,n.selectedDay=i.getDate(),n.drawMonth=n.selectedMonth=i.getMonth(),n.drawYear=n.selectedYear=i.getFullYear()),this._notifyChange(n),this._adjustDate(s)},_selectMonthYear:function(e,i,s){var n=t(e),a=this._getInst(n[0]);a["selected"+("M"===s?"Month":"Year")]=a["draw"+("M"===s?"Month":"Year")]=parseInt(i.options[i.selectedIndex].value,10),this._notifyChange(a),this._adjustDate(n)},_selectDay:function(e,i,s,n){var a,r=t(e);t(n).hasClass(this._unselectableClass)||this._isDisabledDatepicker(r[0])||(a=this._getInst(r[0]),a.selectedDay=a.currentDay=t("a",n).html(),a.selectedMonth=a.currentMonth=i,a.selectedYear=a.currentYear=s,this._selectDate(e,this._formatDate(a,a.currentDay,a.currentMonth,a.currentYear)))},_clearDate:function(e){var i=t(e);this._selectDate(i,"")},_selectDate:function(e,i){var s,n=t(e),a=this._getInst(n[0]);i=null!=i?i:this._formatDate(a),a.input&&a.input.val(i),this._updateAlternate(a),s=this._get(a,"onSelect"),s?s.apply(a.input?a.input[0]:null,[i,a]):a.input&&a.input.trigger("change"),a.inline?this._updateDatepicker(a):(this._hideDatepicker(),this._lastInput=a.input[0],"object"!=typeof a.input[0]&&a.input.focus(),this._lastInput=null)},_updateAlternate:function(e){var i,s,n,a=this._get(e,"altField");a&&(i=this._get(e,"altFormat")||this._get(e,"dateFormat"),s=this._getDate(e),n=this.formatDate(i,s,this._getFormatConfig(e)),t(a).each(function(){t(this).val(n)}))},noWeekends:function(t){var e=t.getDay();return[e>0&&6>e,""]},iso8601Week:function(t){var e,i=new Date(t.getTime());return i.setDate(i.getDate()+4-(i.getDay()||7)),e=i.getTime(),i.setMonth(0),i.setDate(1),Math.floor(Math.round((e-i)/864e5)/7)+1},parseDate:function(i,s,n){if(null==i||null==s)throw"Invalid arguments";if(s="object"==typeof s?""+s:s+"",""===s)return null;var a,r,o,h,l=0,c=(n?n.shortYearCutoff:null)||this._defaults.shortYearCutoff,u="string"!=typeof c?c:(new Date).getFullYear()%100+parseInt(c,10),d=(n?n.dayNamesShort:null)||this._defaults.dayNamesShort,p=(n?n.dayNames:null)||this._defaults.dayNames,f=(n?n.monthNamesShort:null)||this._defaults.monthNamesShort,m=(n?n.monthNames:null)||this._defaults.monthNames,g=-1,v=-1,_=-1,b=-1,y=!1,x=function(t){var e=i.length>a+1&&i.charAt(a+1)===t;return e&&a++,e},k=function(t){var e=x(t),i="@"===t?14:"!"===t?20:"y"===t&&e?4:"o"===t?3:2,n=RegExp("^\\d{1,"+i+"}"),a=s.substring(l).match(n);if(!a)throw"Missing number at position "+l;return l+=a[0].length,parseInt(a[0],10)},w=function(i,n,a){var r=-1,o=t.map(x(i)?a:n,function(t,e){return[[e,t]]}).sort(function(t,e){return-(t[1].length-e[1].length)});if(t.each(o,function(t,i){var n=i[1];return s.substr(l,n.length).toLowerCase()===n.toLowerCase()?(r=i[0],l+=n.length,!1):e}),-1!==r)return r+1;throw"Unknown name at position "+l},D=function(){if(s.charAt(l)!==i.charAt(a))throw"Unexpected literal at position "+l;l++};for(a=0;i.length>a;a++)if(y)"'"!==i.charAt(a)||x("'")?D():y=!1;else switch(i.charAt(a)){case"d":_=k("d");break;case"D":w("D",d,p);break;case"o":b=k("o");break;case"m":v=k("m");break;case"M":v=w("M",f,m);break;case"y":g=k("y");break;case"@":h=new Date(k("@")),g=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"!":h=new Date((k("!")-this._ticksTo1970)/1e4),g=h.getFullYear(),v=h.getMonth()+1,_=h.getDate();break;case"'":x("'")?D():y=!0;break;default:D()}if(s.length>l&&(o=s.substr(l),!/^\s+/.test(o)))throw"Extra/unparsed characters found in date: "+o;if(-1===g?g=(new Date).getFullYear():100>g&&(g+=(new Date).getFullYear()-(new Date).getFullYear()%100+(u>=g?0:-100)),b>-1)for(v=1,_=b;;){if(r=this._getDaysInMonth(g,v-1),r>=_)break;v++,_-=r}if(h=this._daylightSavingAdjust(new Date(g,v-1,_)),h.getFullYear()!==g||h.getMonth()+1!==v||h.getDate()!==_)throw"Invalid date";return h},ATOM:"yy-mm-dd",COOKIE:"D, dd M yy",ISO_8601:"yy-mm-dd",RFC_822:"D, d M y",RFC_850:"DD, dd-M-y",RFC_1036:"D, d M y",RFC_1123:"D, d M yy",RFC_2822:"D, d M yy",RSS:"D, d M y",TICKS:"!",TIMESTAMP:"@",W3C:"yy-mm-dd",_ticksTo1970:1e7*60*60*24*(718685+Math.floor(492.5)-Math.floor(19.7)+Math.floor(4.925)),formatDate:function(t,e,i){if(!e)return"";var s,n=(i?i.dayNamesShort:null)||this._defaults.dayNamesShort,a=(i?i.dayNames:null)||this._defaults.dayNames,r=(i?i.monthNamesShort:null)||this._defaults.monthNamesShort,o=(i?i.monthNames:null)||this._defaults.monthNames,h=function(e){var i=t.length>s+1&&t.charAt(s+1)===e;return i&&s++,i},l=function(t,e,i){var s=""+e;if(h(t))for(;i>s.length;)s="0"+s;return s},c=function(t,e,i,s){return h(t)?s[e]:i[e]},u="",d=!1;if(e)for(s=0;t.length>s;s++)if(d)"'"!==t.charAt(s)||h("'")?u+=t.charAt(s):d=!1;else switch(t.charAt(s)){case"d":u+=l("d",e.getDate(),2);break;case"D":u+=c("D",e.getDay(),n,a);break;case"o":u+=l("o",Math.round((new Date(e.getFullYear(),e.getMonth(),e.getDate()).getTime()-new Date(e.getFullYear(),0,0).getTime())/864e5),3);break;case"m":u+=l("m",e.getMonth()+1,2);break;case"M":u+=c("M",e.getMonth(),r,o);break;case"y":u+=h("y")?e.getFullYear():(10>e.getYear()%100?"0":"")+e.getYear()%100;break;case"@":u+=e.getTime();break;case"!":u+=1e4*e.getTime()+this._ticksTo1970;break;case"'":h("'")?u+="'":d=!0;break;default:u+=t.charAt(s)}return u},_possibleChars:function(t){var e,i="",s=!1,n=function(i){var s=t.length>e+1&&t.charAt(e+1)===i;return s&&e++,s};for(e=0;t.length>e;e++)if(s)"'"!==t.charAt(e)||n("'")?i+=t.charAt(e):s=!1;else switch(t.charAt(e)){case"d":case"m":case"y":case"@":i+="0123456789";break;case"D":case"M":return null;case"'":n("'")?i+="'":s=!0;break;default:i+=t.charAt(e)}return i},_get:function(t,i){return t.settings[i]!==e?t.settings[i]:this._defaults[i]},_setDateFromField:function(t,e){if(t.input.val()!==t.lastVal){var i=this._get(t,"dateFormat"),s=t.lastVal=t.input?t.input.val():null,n=this._getDefaultDate(t),a=n,r=this._getFormatConfig(t);try{a=this.parseDate(i,s,r)||n}catch(o){s=e?"":s}t.selectedDay=a.getDate(),t.drawMonth=t.selectedMonth=a.getMonth(),t.drawYear=t.selectedYear=a.getFullYear(),t.currentDay=s?a.getDate():0,t.currentMonth=s?a.getMonth():0,t.currentYear=s?a.getFullYear():0,this._adjustInstDate(t)}},_getDefaultDate:function(t){return this._restrictMinMax(t,this._determineDate(t,this._get(t,"defaultDate"),new Date))},_determineDate:function(e,i,s){var n=function(t){var e=new Date;return e.setDate(e.getDate()+t),e},a=function(i){try{return t.datepicker.parseDate(t.datepicker._get(e,"dateFormat"),i,t.datepicker._getFormatConfig(e))}catch(s){}for(var n=(i.toLowerCase().match(/^c/)?t.datepicker._getDate(e):null)||new Date,a=n.getFullYear(),r=n.getMonth(),o=n.getDate(),h=/([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,l=h.exec(i);l;){switch(l[2]||"d"){case"d":case"D":o+=parseInt(l[1],10);break;case"w":case"W":o+=7*parseInt(l[1],10);break;case"m":case"M":r+=parseInt(l[1],10),o=Math.min(o,t.datepicker._getDaysInMonth(a,r));break;case"y":case"Y":a+=parseInt(l[1],10),o=Math.min(o,t.datepicker._getDaysInMonth(a,r))}l=h.exec(i)}return new Date(a,r,o)},r=null==i||""===i?s:"string"==typeof i?a(i):"number"==typeof i?isNaN(i)?s:n(i):new Date(i.getTime());return r=r&&"Invalid Date"==""+r?s:r,r&&(r.setHours(0),r.setMinutes(0),r.setSeconds(0),r.setMilliseconds(0)),this._daylightSavingAdjust(r)},_daylightSavingAdjust:function(t){return t?(t.setHours(t.getHours()>12?t.getHours()+2:0),t):null},_setDate:function(t,e,i){var s=!e,n=t.selectedMonth,a=t.selectedYear,r=this._restrictMinMax(t,this._determineDate(t,e,new Date));t.selectedDay=t.currentDay=r.getDate(),t.drawMonth=t.selectedMonth=t.currentMonth=r.getMonth(),t.drawYear=t.selectedYear=t.currentYear=r.getFullYear(),n===t.selectedMonth&&a===t.selectedYear||i||this._notifyChange(t),this._adjustInstDate(t),t.input&&t.input.val(s?"":this._formatDate(t))},_getDate:function(t){var e=!t.currentYear||t.input&&""===t.input.val()?null:this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return e},_attachHandlers:function(e){var i=this._get(e,"stepMonths"),s="#"+e.id.replace(/\\\\/g,"\\");e.dpDiv.find("[data-handler]").map(function(){var e={prev:function(){t.datepicker._adjustDate(s,-i,"M")},next:function(){t.datepicker._adjustDate(s,+i,"M")},hide:function(){t.datepicker._hideDatepicker()},today:function(){t.datepicker._gotoToday(s)},selectDay:function(){return t.datepicker._selectDay(s,+this.getAttribute("data-month"),+this.getAttribute("data-year"),this),!1},selectMonth:function(){return t.datepicker._selectMonthYear(s,this,"M"),!1},selectYear:function(){return t.datepicker._selectMonthYear(s,this,"Y"),!1}};t(this).bind(this.getAttribute("data-event"),e[this.getAttribute("data-handler")])})},_generateHTML:function(t){var e,i,s,n,a,r,o,h,l,c,u,d,p,f,m,g,v,_,b,y,x,k,w,D,T,C,M,S,N,I,P,A,z,H,E,F,O,W,j,R=new Date,L=this._daylightSavingAdjust(new Date(R.getFullYear(),R.getMonth(),R.getDate())),Y=this._get(t,"isRTL"),B=this._get(t,"showButtonPanel"),J=this._get(t,"hideIfNoPrevNext"),K=this._get(t,"navigationAsDateFormat"),Q=this._getNumberOfMonths(t),V=this._get(t,"showCurrentAtPos"),U=this._get(t,"stepMonths"),q=1!==Q[0]||1!==Q[1],X=this._daylightSavingAdjust(t.currentDay?new Date(t.currentYear,t.currentMonth,t.currentDay):new Date(9999,9,9)),G=this._getMinMaxDate(t,"min"),$=this._getMinMaxDate(t,"max"),Z=t.drawMonth-V,te=t.drawYear;if(0>Z&&(Z+=12,te--),$)for(e=this._daylightSavingAdjust(new Date($.getFullYear(),$.getMonth()-Q[0]*Q[1]+1,$.getDate())),e=G&&G>e?G:e;this._daylightSavingAdjust(new Date(te,Z,1))>e;)Z--,0>Z&&(Z=11,te--);for(t.drawMonth=Z,t.drawYear=te,i=this._get(t,"prevText"),i=K?this.formatDate(i,this._daylightSavingAdjust(new Date(te,Z-U,1)),this._getFormatConfig(t)):i,s=this._canAdjustMonth(t,-1,te,Z)?"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>":J?"":"<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+i+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"e":"w")+"'>"+i+"</span></a>",n=this._get(t,"nextText"),n=K?this.formatDate(n,this._daylightSavingAdjust(new Date(te,Z+U,1)),this._getFormatConfig(t)):n,a=this._canAdjustMonth(t,1,te,Z)?"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>":J?"":"<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+n+"'><span class='ui-icon ui-icon-circle-triangle-"+(Y?"w":"e")+"'>"+n+"</span></a>",r=this._get(t,"currentText"),o=this._get(t,"gotoCurrent")&&t.currentDay?X:L,r=K?this.formatDate(r,o,this._getFormatConfig(t)):r,h=t.inline?"":"<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>"+this._get(t,"closeText")+"</button>",l=B?"<div class='ui-datepicker-buttonpane ui-widget-content'>"+(Y?h:"")+(this._isInRange(t,o)?"<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'>"+r+"</button>":"")+(Y?"":h)+"</div>":"",c=parseInt(this._get(t,"firstDay"),10),c=isNaN(c)?0:c,u=this._get(t,"showWeek"),d=this._get(t,"dayNames"),p=this._get(t,"dayNamesMin"),f=this._get(t,"monthNames"),m=this._get(t,"monthNamesShort"),g=this._get(t,"beforeShowDay"),v=this._get(t,"showOtherMonths"),_=this._get(t,"selectOtherMonths"),b=this._getDefaultDate(t),y="",k=0;Q[0]>k;k++){for(w="",this.maxRows=4,D=0;Q[1]>D;D++){if(T=this._daylightSavingAdjust(new Date(te,Z,t.selectedDay)),C=" ui-corner-all",M="",q){if(M+="<div class='ui-datepicker-group",Q[1]>1)switch(D){case 0:M+=" ui-datepicker-group-first",C=" ui-corner-"+(Y?"right":"left");break;case Q[1]-1:M+=" ui-datepicker-group-last",C=" ui-corner-"+(Y?"left":"right");break;default:M+=" ui-datepicker-group-middle",C=""}M+="'>"}for(M+="<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix"+C+"'>"+(/all|left/.test(C)&&0===k?Y?a:s:"")+(/all|right/.test(C)&&0===k?Y?s:a:"")+this._generateMonthYearHeader(t,Z,te,G,$,k>0||D>0,f,m)+"</div><table class='ui-datepicker-calendar'><thead>"+"<tr>",S=u?"<th class='ui-datepicker-week-col'>"+this._get(t,"weekHeader")+"</th>":"",x=0;7>x;x++)N=(x+c)%7,S+="<th"+((x+c+6)%7>=5?" class='ui-datepicker-week-end'":"")+">"+"<span title='"+d[N]+"'>"+p[N]+"</span></th>";for(M+=S+"</tr></thead><tbody>",I=this._getDaysInMonth(te,Z),te===t.selectedYear&&Z===t.selectedMonth&&(t.selectedDay=Math.min(t.selectedDay,I)),P=(this._getFirstDayOfMonth(te,Z)-c+7)%7,A=Math.ceil((P+I)/7),z=q?this.maxRows>A?this.maxRows:A:A,this.maxRows=z,H=this._daylightSavingAdjust(new Date(te,Z,1-P)),E=0;z>E;E++){for(M+="<tr>",F=u?"<td class='ui-datepicker-week-col'>"+this._get(t,"calculateWeek")(H)+"</td>":"",x=0;7>x;x++)O=g?g.apply(t.input?t.input[0]:null,[H]):[!0,""],W=H.getMonth()!==Z,j=W&&!_||!O[0]||G&&G>H||$&&H>$,F+="<td class='"+((x+c+6)%7>=5?" ui-datepicker-week-end":"")+(W?" ui-datepicker-other-month":"")+(H.getTime()===T.getTime()&&Z===t.selectedMonth&&t._keyEvent||b.getTime()===H.getTime()&&b.getTime()===T.getTime()?" "+this._dayOverClass:"")+(j?" "+this._unselectableClass+" ui-state-disabled":"")+(W&&!v?"":" "+O[1]+(H.getTime()===X.getTime()?" "+this._currentClass:"")+(H.getTime()===L.getTime()?" ui-datepicker-today":""))+"'"+(W&&!v||!O[2]?"":" title='"+O[2].replace(/'/g,"'")+"'")+(j?"":" data-handler='selectDay' data-event='click' data-month='"+H.getMonth()+"' data-year='"+H.getFullYear()+"'")+">"+(W&&!v?" ":j?"<span class='ui-state-default'>"+H.getDate()+"</span>":"<a class='ui-state-default"+(H.getTime()===L.getTime()?" ui-state-highlight":"")+(H.getTime()===X.getTime()?" ui-state-active":"")+(W?" ui-priority-secondary":"")+"' href='#'>"+H.getDate()+"</a>")+"</td>",H.setDate(H.getDate()+1),H=this._daylightSavingAdjust(H);M+=F+"</tr>"}Z++,Z>11&&(Z=0,te++),M+="</tbody></table>"+(q?"</div>"+(Q[0]>0&&D===Q[1]-1?"<div class='ui-datepicker-row-break'></div>":""):""),w+=M}y+=w}return y+=l,t._keyEvent=!1,y},_generateMonthYearHeader:function(t,e,i,s,n,a,r,o){var h,l,c,u,d,p,f,m,g=this._get(t,"changeMonth"),v=this._get(t,"changeYear"),_=this._get(t,"showMonthAfterYear"),b="<div class='ui-datepicker-title'>",y="";if(a||!g)y+="<span class='ui-datepicker-month'>"+r[e]+"</span>";else{for(h=s&&s.getFullYear()===i,l=n&&n.getFullYear()===i,y+="<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>",c=0;12>c;c++)(!h||c>=s.getMonth())&&(!l||n.getMonth()>=c)&&(y+="<option value='"+c+"'"+(c===e?" selected='selected'":"")+">"+o[c]+"</option>");y+="</select>"}if(_||(b+=y+(!a&&g&&v?"":" ")),!t.yearshtml)if(t.yearshtml="",a||!v)b+="<span class='ui-datepicker-year'>"+i+"</span>";else{for(u=this._get(t,"yearRange").split(":"),d=(new Date).getFullYear(),p=function(t){var e=t.match(/c[+\-].*/)?i+parseInt(t.substring(1),10):t.match(/[+\-].*/)?d+parseInt(t,10):parseInt(t,10); +return isNaN(e)?d:e},f=p(u[0]),m=Math.max(f,p(u[1]||"")),f=s?Math.max(f,s.getFullYear()):f,m=n?Math.min(m,n.getFullYear()):m,t.yearshtml+="<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";m>=f;f++)t.yearshtml+="<option value='"+f+"'"+(f===i?" selected='selected'":"")+">"+f+"</option>";t.yearshtml+="</select>",b+=t.yearshtml,t.yearshtml=null}return b+=this._get(t,"yearSuffix"),_&&(b+=(!a&&g&&v?"":" ")+y),b+="</div>"},_adjustInstDate:function(t,e,i){var s=t.drawYear+("Y"===i?e:0),n=t.drawMonth+("M"===i?e:0),a=Math.min(t.selectedDay,this._getDaysInMonth(s,n))+("D"===i?e:0),r=this._restrictMinMax(t,this._daylightSavingAdjust(new Date(s,n,a)));t.selectedDay=r.getDate(),t.drawMonth=t.selectedMonth=r.getMonth(),t.drawYear=t.selectedYear=r.getFullYear(),("M"===i||"Y"===i)&&this._notifyChange(t)},_restrictMinMax:function(t,e){var i=this._getMinMaxDate(t,"min"),s=this._getMinMaxDate(t,"max"),n=i&&i>e?i:e;return s&&n>s?s:n},_notifyChange:function(t){var e=this._get(t,"onChangeMonthYear");e&&e.apply(t.input?t.input[0]:null,[t.selectedYear,t.selectedMonth+1,t])},_getNumberOfMonths:function(t){var e=this._get(t,"numberOfMonths");return null==e?[1,1]:"number"==typeof e?[1,e]:e},_getMinMaxDate:function(t,e){return this._determineDate(t,this._get(t,e+"Date"),null)},_getDaysInMonth:function(t,e){return 32-this._daylightSavingAdjust(new Date(t,e,32)).getDate()},_getFirstDayOfMonth:function(t,e){return new Date(t,e,1).getDay()},_canAdjustMonth:function(t,e,i,s){var n=this._getNumberOfMonths(t),a=this._daylightSavingAdjust(new Date(i,s+(0>e?e:n[0]*n[1]),1));return 0>e&&a.setDate(this._getDaysInMonth(a.getFullYear(),a.getMonth())),this._isInRange(t,a)},_isInRange:function(t,e){var i,s,n=this._getMinMaxDate(t,"min"),a=this._getMinMaxDate(t,"max"),r=null,o=null,h=this._get(t,"yearRange");return h&&(i=h.split(":"),s=(new Date).getFullYear(),r=parseInt(i[0],10),o=parseInt(i[1],10),i[0].match(/[+\-].*/)&&(r+=s),i[1].match(/[+\-].*/)&&(o+=s)),(!n||e.getTime()>=n.getTime())&&(!a||e.getTime()<=a.getTime())&&(!r||e.getFullYear()>=r)&&(!o||o>=e.getFullYear())},_getFormatConfig:function(t){var e=this._get(t,"shortYearCutoff");return e="string"!=typeof e?e:(new Date).getFullYear()%100+parseInt(e,10),{shortYearCutoff:e,dayNamesShort:this._get(t,"dayNamesShort"),dayNames:this._get(t,"dayNames"),monthNamesShort:this._get(t,"monthNamesShort"),monthNames:this._get(t,"monthNames")}},_formatDate:function(t,e,i,s){e||(t.currentDay=t.selectedDay,t.currentMonth=t.selectedMonth,t.currentYear=t.selectedYear);var n=e?"object"==typeof e?e:this._daylightSavingAdjust(new Date(s,i,e)):this._daylightSavingAdjust(new Date(t.currentYear,t.currentMonth,t.currentDay));return this.formatDate(this._get(t,"dateFormat"),n,this._getFormatConfig(t))}}),t.fn.datepicker=function(e){if(!this.length)return this;t.datepicker.initialized||(t(document).mousedown(t.datepicker._checkExternalClick),t.datepicker.initialized=!0),0===t("#"+t.datepicker._mainDivId).length&&t("body").append(t.datepicker.dpDiv);var i=Array.prototype.slice.call(arguments,1);return"string"!=typeof e||"isDisabled"!==e&&"getDate"!==e&&"widget"!==e?"option"===e&&2===arguments.length&&"string"==typeof arguments[1]?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i)):this.each(function(){"string"==typeof e?t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this].concat(i)):t.datepicker._attachDatepicker(this,e)}):t.datepicker["_"+e+"Datepicker"].apply(t.datepicker,[this[0]].concat(i))},t.datepicker=new i,t.datepicker.initialized=!1,t.datepicker.uuid=(new Date).getTime(),t.datepicker.version="1.10.3"})(jQuery);(function(t){var e={buttons:!0,height:!0,maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0,width:!0},i={maxHeight:!0,maxWidth:!0,minHeight:!0,minWidth:!0};t.widget("ui.dialog",{version:"1.10.3",options:{appendTo:"body",autoOpen:!0,buttons:[],closeOnEscape:!0,closeText:"close",dialogClass:"",draggable:!0,hide:null,height:"auto",maxHeight:null,maxWidth:null,minHeight:150,minWidth:150,modal:!1,position:{my:"center",at:"center",of:window,collision:"fit",using:function(e){var i=t(this).css(e).offset().top;0>i&&t(this).css("top",e.top-i)}},resizable:!0,show:null,title:null,width:300,beforeClose:null,close:null,drag:null,dragStart:null,dragStop:null,focus:null,open:null,resize:null,resizeStart:null,resizeStop:null},_create:function(){this.originalCss={display:this.element[0].style.display,width:this.element[0].style.width,minHeight:this.element[0].style.minHeight,maxHeight:this.element[0].style.maxHeight,height:this.element[0].style.height},this.originalPosition={parent:this.element.parent(),index:this.element.parent().children().index(this.element)},this.originalTitle=this.element.attr("title"),this.options.title=this.options.title||this.originalTitle,this._createWrapper(),this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(this.uiDialog),this._createTitlebar(),this._createButtonPane(),this.options.draggable&&t.fn.draggable&&this._makeDraggable(),this.options.resizable&&t.fn.resizable&&this._makeResizable(),this._isOpen=!1},_init:function(){this.options.autoOpen&&this.open()},_appendTo:function(){var e=this.options.appendTo;return e&&(e.jquery||e.nodeType)?t(e):this.document.find(e||"body").eq(0)},_destroy:function(){var t,e=this.originalPosition;this._destroyOverlay(),this.element.removeUniqueId().removeClass("ui-dialog-content ui-widget-content").css(this.originalCss).detach(),this.uiDialog.stop(!0,!0).remove(),this.originalTitle&&this.element.attr("title",this.originalTitle),t=e.parent.children().eq(e.index),t.length&&t[0]!==this.element[0]?t.before(this.element):e.parent.append(this.element)},widget:function(){return this.uiDialog},disable:t.noop,enable:t.noop,close:function(e){var i=this;this._isOpen&&this._trigger("beforeClose",e)!==!1&&(this._isOpen=!1,this._destroyOverlay(),this.opener.filter(":focusable").focus().length||t(this.document[0].activeElement).blur(),this._hide(this.uiDialog,this.options.hide,function(){i._trigger("close",e)}))},isOpen:function(){return this._isOpen},moveToTop:function(){this._moveToTop()},_moveToTop:function(t,e){var i=!!this.uiDialog.nextAll(":visible").insertBefore(this.uiDialog).length;return i&&!e&&this._trigger("focus",t),i},open:function(){var e=this;return this._isOpen?(this._moveToTop()&&this._focusTabbable(),undefined):(this._isOpen=!0,this.opener=t(this.document[0].activeElement),this._size(),this._position(),this._createOverlay(),this._moveToTop(null,!0),this._show(this.uiDialog,this.options.show,function(){e._focusTabbable(),e._trigger("focus")}),this._trigger("open"),undefined)},_focusTabbable:function(){var t=this.element.find("[autofocus]");t.length||(t=this.element.find(":tabbable")),t.length||(t=this.uiDialogButtonPane.find(":tabbable")),t.length||(t=this.uiDialogTitlebarClose.filter(":tabbable")),t.length||(t=this.uiDialog),t.eq(0).focus()},_keepFocus:function(e){function i(){var e=this.document[0].activeElement,i=this.uiDialog[0]===e||t.contains(this.uiDialog[0],e);i||this._focusTabbable()}e.preventDefault(),i.call(this),this._delay(i)},_createWrapper:function(){this.uiDialog=t("<div>").addClass("ui-dialog ui-widget ui-widget-content ui-corner-all ui-front "+this.options.dialogClass).hide().attr({tabIndex:-1,role:"dialog"}).appendTo(this._appendTo()),this._on(this.uiDialog,{keydown:function(e){if(this.options.closeOnEscape&&!e.isDefaultPrevented()&&e.keyCode&&e.keyCode===t.ui.keyCode.ESCAPE)return e.preventDefault(),this.close(e),undefined;if(e.keyCode===t.ui.keyCode.TAB){var i=this.uiDialog.find(":tabbable"),s=i.filter(":first"),n=i.filter(":last");e.target!==n[0]&&e.target!==this.uiDialog[0]||e.shiftKey?e.target!==s[0]&&e.target!==this.uiDialog[0]||!e.shiftKey||(n.focus(1),e.preventDefault()):(s.focus(1),e.preventDefault())}},mousedown:function(t){this._moveToTop(t)&&this._focusTabbable()}}),this.element.find("[aria-describedby]").length||this.uiDialog.attr({"aria-describedby":this.element.uniqueId().attr("id")})},_createTitlebar:function(){var e;this.uiDialogTitlebar=t("<div>").addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(this.uiDialog),this._on(this.uiDialogTitlebar,{mousedown:function(e){t(e.target).closest(".ui-dialog-titlebar-close")||this.uiDialog.focus()}}),this.uiDialogTitlebarClose=t("<button></button>").button({label:this.options.closeText,icons:{primary:"ui-icon-closethick"},text:!1}).addClass("ui-dialog-titlebar-close").appendTo(this.uiDialogTitlebar),this._on(this.uiDialogTitlebarClose,{click:function(t){t.preventDefault(),this.close(t)}}),e=t("<span>").uniqueId().addClass("ui-dialog-title").prependTo(this.uiDialogTitlebar),this._title(e),this.uiDialog.attr({"aria-labelledby":e.attr("id")})},_title:function(t){this.options.title||t.html(" "),t.text(this.options.title)},_createButtonPane:function(){this.uiDialogButtonPane=t("<div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix"),this.uiButtonSet=t("<div>").addClass("ui-dialog-buttonset").appendTo(this.uiDialogButtonPane),this._createButtons()},_createButtons:function(){var e=this,i=this.options.buttons;return this.uiDialogButtonPane.remove(),this.uiButtonSet.empty(),t.isEmptyObject(i)||t.isArray(i)&&!i.length?(this.uiDialog.removeClass("ui-dialog-buttons"),undefined):(t.each(i,function(i,s){var n,a;s=t.isFunction(s)?{click:s,text:i}:s,s=t.extend({type:"button"},s),n=s.click,s.click=function(){n.apply(e.element[0],arguments)},a={icons:s.icons,text:s.showText},delete s.icons,delete s.showText,t("<button></button>",s).button(a).appendTo(e.uiButtonSet)}),this.uiDialog.addClass("ui-dialog-buttons"),this.uiDialogButtonPane.appendTo(this.uiDialog),undefined)},_makeDraggable:function(){function e(t){return{position:t.position,offset:t.offset}}var i=this,s=this.options;this.uiDialog.draggable({cancel:".ui-dialog-content, .ui-dialog-titlebar-close",handle:".ui-dialog-titlebar",containment:"document",start:function(s,n){t(this).addClass("ui-dialog-dragging"),i._blockFrames(),i._trigger("dragStart",s,e(n))},drag:function(t,s){i._trigger("drag",t,e(s))},stop:function(n,a){s.position=[a.position.left-i.document.scrollLeft(),a.position.top-i.document.scrollTop()],t(this).removeClass("ui-dialog-dragging"),i._unblockFrames(),i._trigger("dragStop",n,e(a))}})},_makeResizable:function(){function e(t){return{originalPosition:t.originalPosition,originalSize:t.originalSize,position:t.position,size:t.size}}var i=this,s=this.options,n=s.resizable,a=this.uiDialog.css("position"),o="string"==typeof n?n:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",containment:"document",alsoResize:this.element,maxWidth:s.maxWidth,maxHeight:s.maxHeight,minWidth:s.minWidth,minHeight:this._minHeight(),handles:o,start:function(s,n){t(this).addClass("ui-dialog-resizing"),i._blockFrames(),i._trigger("resizeStart",s,e(n))},resize:function(t,s){i._trigger("resize",t,e(s))},stop:function(n,a){s.height=t(this).height(),s.width=t(this).width(),t(this).removeClass("ui-dialog-resizing"),i._unblockFrames(),i._trigger("resizeStop",n,e(a))}}).css("position",a)},_minHeight:function(){var t=this.options;return"auto"===t.height?t.minHeight:Math.min(t.minHeight,t.height)},_position:function(){var t=this.uiDialog.is(":visible");t||this.uiDialog.show(),this.uiDialog.position(this.options.position),t||this.uiDialog.hide()},_setOptions:function(s){var n=this,a=!1,o={};t.each(s,function(t,s){n._setOption(t,s),t in e&&(a=!0),t in i&&(o[t]=s)}),a&&(this._size(),this._position()),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option",o)},_setOption:function(t,e){var i,s,n=this.uiDialog;"dialogClass"===t&&n.removeClass(this.options.dialogClass).addClass(e),"disabled"!==t&&(this._super(t,e),"appendTo"===t&&this.uiDialog.appendTo(this._appendTo()),"buttons"===t&&this._createButtons(),"closeText"===t&&this.uiDialogTitlebarClose.button({label:""+e}),"draggable"===t&&(i=n.is(":data(ui-draggable)"),i&&!e&&n.draggable("destroy"),!i&&e&&this._makeDraggable()),"position"===t&&this._position(),"resizable"===t&&(s=n.is(":data(ui-resizable)"),s&&!e&&n.resizable("destroy"),s&&"string"==typeof e&&n.resizable("option","handles",e),s||e===!1||this._makeResizable()),"title"===t&&this._title(this.uiDialogTitlebar.find(".ui-dialog-title")))},_size:function(){var t,e,i,s=this.options;this.element.show().css({width:"auto",minHeight:0,maxHeight:"none",height:0}),s.minWidth>s.width&&(s.width=s.minWidth),t=this.uiDialog.css({height:"auto",width:s.width}).outerHeight(),e=Math.max(0,s.minHeight-t),i="number"==typeof s.maxHeight?Math.max(0,s.maxHeight-t):"none","auto"===s.height?this.element.css({minHeight:e,maxHeight:i,height:"auto"}):this.element.height(Math.max(0,s.height-t)),this.uiDialog.is(":data(ui-resizable)")&&this.uiDialog.resizable("option","minHeight",this._minHeight())},_blockFrames:function(){this.iframeBlocks=this.document.find("iframe").map(function(){var e=t(this);return t("<div>").css({position:"absolute",width:e.outerWidth(),height:e.outerHeight()}).appendTo(e.parent()).offset(e.offset())[0]})},_unblockFrames:function(){this.iframeBlocks&&(this.iframeBlocks.remove(),delete this.iframeBlocks)},_allowInteraction:function(e){return t(e.target).closest(".ui-dialog").length?!0:!!t(e.target).closest(".ui-datepicker").length},_createOverlay:function(){if(this.options.modal){var e=this,i=this.widgetFullName;t.ui.dialog.overlayInstances||this._delay(function(){t.ui.dialog.overlayInstances&&this.document.bind("focusin.dialog",function(s){e._allowInteraction(s)||(s.preventDefault(),t(".ui-dialog:visible:last .ui-dialog-content").data(i)._focusTabbable())})}),this.overlay=t("<div>").addClass("ui-widget-overlay ui-front").appendTo(this._appendTo()),this._on(this.overlay,{mousedown:"_keepFocus"}),t.ui.dialog.overlayInstances++}},_destroyOverlay:function(){this.options.modal&&this.overlay&&(t.ui.dialog.overlayInstances--,t.ui.dialog.overlayInstances||this.document.unbind("focusin.dialog"),this.overlay.remove(),this.overlay=null)}}),t.ui.dialog.overlayInstances=0,t.uiBackCompat!==!1&&t.widget("ui.dialog",t.ui.dialog,{_position:function(){var e,i=this.options.position,s=[],n=[0,0];i?(("string"==typeof i||"object"==typeof i&&"0"in i)&&(s=i.split?i.split(" "):[i[0],i[1]],1===s.length&&(s[1]=s[0]),t.each(["left","top"],function(t,e){+s[t]===s[t]&&(n[t]=s[t],s[t]=e)}),i={my:s[0]+(0>n[0]?n[0]:"+"+n[0])+" "+s[1]+(0>n[1]?n[1]:"+"+n[1]),at:s.join(" ")}),i=t.extend({},t.ui.dialog.prototype.options.position,i)):i=t.ui.dialog.prototype.options.position,e=this.uiDialog.is(":visible"),e||this.uiDialog.show(),this.uiDialog.position(i),e||this.uiDialog.hide()}})})(jQuery);(function(t){t.widget("ui.menu",{version:"1.10.3",defaultElement:"<ul>",delay:300,options:{icons:{submenu:"ui-icon-carat-1-e"},menus:"ul",position:{my:"left top",at:"right top"},role:"menu",blur:null,focus:null,select:null},_create:function(){this.activeMenu=this.element,this.mouseHandled=!1,this.element.uniqueId().addClass("ui-menu ui-widget ui-widget-content ui-corner-all").toggleClass("ui-menu-icons",!!this.element.find(".ui-icon").length).attr({role:this.options.role,tabIndex:0}).bind("click"+this.eventNamespace,t.proxy(function(t){this.options.disabled&&t.preventDefault()},this)),this.options.disabled&&this.element.addClass("ui-state-disabled").attr("aria-disabled","true"),this._on({"mousedown .ui-menu-item > a":function(t){t.preventDefault()},"click .ui-state-disabled > a":function(t){t.preventDefault()},"click .ui-menu-item:has(a)":function(e){var i=t(e.target).closest(".ui-menu-item");!this.mouseHandled&&i.not(".ui-state-disabled").length&&(this.mouseHandled=!0,this.select(e),i.has(".ui-menu").length?this.expand(e):this.element.is(":focus")||(this.element.trigger("focus",[!0]),this.active&&1===this.active.parents(".ui-menu").length&&clearTimeout(this.timer)))},"mouseenter .ui-menu-item":function(e){var i=t(e.currentTarget);i.siblings().children(".ui-state-active").removeClass("ui-state-active"),this.focus(e,i)},mouseleave:"collapseAll","mouseleave .ui-menu":"collapseAll",focus:function(t,e){var i=this.active||this.element.children(".ui-menu-item").eq(0);e||this.focus(t,i)},blur:function(e){this._delay(function(){t.contains(this.element[0],this.document[0].activeElement)||this.collapseAll(e)})},keydown:"_keydown"}),this.refresh(),this._on(this.document,{click:function(e){t(e.target).closest(".ui-menu").length||this.collapseAll(e),this.mouseHandled=!1}})},_destroy:function(){this.element.removeAttr("aria-activedescendant").find(".ui-menu").addBack().removeClass("ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons").removeAttr("role").removeAttr("tabIndex").removeAttr("aria-labelledby").removeAttr("aria-expanded").removeAttr("aria-hidden").removeAttr("aria-disabled").removeUniqueId().show(),this.element.find(".ui-menu-item").removeClass("ui-menu-item").removeAttr("role").removeAttr("aria-disabled").children("a").removeUniqueId().removeClass("ui-corner-all ui-state-hover").removeAttr("tabIndex").removeAttr("role").removeAttr("aria-haspopup").children().each(function(){var e=t(this);e.data("ui-menu-submenu-carat")&&e.remove()}),this.element.find(".ui-menu-divider").removeClass("ui-menu-divider ui-widget-content")},_keydown:function(e){function i(t){return t.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}var s,n,a,o,r,h=!0;switch(e.keyCode){case t.ui.keyCode.PAGE_UP:this.previousPage(e);break;case t.ui.keyCode.PAGE_DOWN:this.nextPage(e);break;case t.ui.keyCode.HOME:this._move("first","first",e);break;case t.ui.keyCode.END:this._move("last","last",e);break;case t.ui.keyCode.UP:this.previous(e);break;case t.ui.keyCode.DOWN:this.next(e);break;case t.ui.keyCode.LEFT:this.collapse(e);break;case t.ui.keyCode.RIGHT:this.active&&!this.active.is(".ui-state-disabled")&&this.expand(e);break;case t.ui.keyCode.ENTER:case t.ui.keyCode.SPACE:this._activate(e);break;case t.ui.keyCode.ESCAPE:this.collapse(e);break;default:h=!1,n=this.previousFilter||"",a=String.fromCharCode(e.keyCode),o=!1,clearTimeout(this.filterTimer),a===n?o=!0:a=n+a,r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())}),s=o&&-1!==s.index(this.active.next())?this.active.nextAll(".ui-menu-item"):s,s.length||(a=String.fromCharCode(e.keyCode),r=RegExp("^"+i(a),"i"),s=this.activeMenu.children(".ui-menu-item").filter(function(){return r.test(t(this).children("a").text())})),s.length?(this.focus(e,s),s.length>1?(this.previousFilter=a,this.filterTimer=this._delay(function(){delete this.previousFilter},1e3)):delete this.previousFilter):delete this.previousFilter}h&&e.preventDefault()},_activate:function(t){this.active.is(".ui-state-disabled")||(this.active.children("a[aria-haspopup='true']").length?this.expand(t):this.select(t))},refresh:function(){var e,i=this.options.icons.submenu,s=this.element.find(this.options.menus);s.filter(":not(.ui-menu)").addClass("ui-menu ui-widget ui-widget-content ui-corner-all").hide().attr({role:this.options.role,"aria-hidden":"true","aria-expanded":"false"}).each(function(){var e=t(this),s=e.prev("a"),n=t("<span>").addClass("ui-menu-icon ui-icon "+i).data("ui-menu-submenu-carat",!0);s.attr("aria-haspopup","true").prepend(n),e.attr("aria-labelledby",s.attr("id"))}),e=s.add(this.element),e.children(":not(.ui-menu-item):has(a)").addClass("ui-menu-item").attr("role","presentation").children("a").uniqueId().addClass("ui-corner-all").attr({tabIndex:-1,role:this._itemRole()}),e.children(":not(.ui-menu-item)").each(function(){var e=t(this);/[^\-\u2014\u2013\s]/.test(e.text())||e.addClass("ui-widget-content ui-menu-divider")}),e.children(".ui-state-disabled").attr("aria-disabled","true"),this.active&&!t.contains(this.element[0],this.active[0])&&this.blur()},_itemRole:function(){return{menu:"menuitem",listbox:"option"}[this.options.role]},_setOption:function(t,e){"icons"===t&&this.element.find(".ui-menu-icon").removeClass(this.options.icons.submenu).addClass(e.submenu),this._super(t,e)},focus:function(t,e){var i,s;this.blur(t,t&&"focus"===t.type),this._scrollIntoView(e),this.active=e.first(),s=this.active.children("a").addClass("ui-state-focus"),this.options.role&&this.element.attr("aria-activedescendant",s.attr("id")),this.active.parent().closest(".ui-menu-item").children("a:first").addClass("ui-state-active"),t&&"keydown"===t.type?this._close():this.timer=this._delay(function(){this._close()},this.delay),i=e.children(".ui-menu"),i.length&&/^mouse/.test(t.type)&&this._startOpening(i),this.activeMenu=e.parent(),this._trigger("focus",t,{item:e})},_scrollIntoView:function(e){var i,s,n,a,o,r;this._hasScroll()&&(i=parseFloat(t.css(this.activeMenu[0],"borderTopWidth"))||0,s=parseFloat(t.css(this.activeMenu[0],"paddingTop"))||0,n=e.offset().top-this.activeMenu.offset().top-i-s,a=this.activeMenu.scrollTop(),o=this.activeMenu.height(),r=e.height(),0>n?this.activeMenu.scrollTop(a+n):n+r>o&&this.activeMenu.scrollTop(a+n-o+r))},blur:function(t,e){e||clearTimeout(this.timer),this.active&&(this.active.children("a").removeClass("ui-state-focus"),this.active=null,this._trigger("blur",t,{item:this.active}))},_startOpening:function(t){clearTimeout(this.timer),"true"===t.attr("aria-hidden")&&(this.timer=this._delay(function(){this._close(),this._open(t)},this.delay))},_open:function(e){var i=t.extend({of:this.active},this.options.position);clearTimeout(this.timer),this.element.find(".ui-menu").not(e.parents(".ui-menu")).hide().attr("aria-hidden","true"),e.show().removeAttr("aria-hidden").attr("aria-expanded","true").position(i)},collapseAll:function(e,i){clearTimeout(this.timer),this.timer=this._delay(function(){var s=i?this.element:t(e&&e.target).closest(this.element.find(".ui-menu"));s.length||(s=this.element),this._close(s),this.blur(e),this.activeMenu=s},this.delay)},_close:function(t){t||(t=this.active?this.active.parent():this.element),t.find(".ui-menu").hide().attr("aria-hidden","true").attr("aria-expanded","false").end().find("a.ui-state-active").removeClass("ui-state-active")},collapse:function(t){var e=this.active&&this.active.parent().closest(".ui-menu-item",this.element);e&&e.length&&(this._close(),this.focus(t,e))},expand:function(t){var e=this.active&&this.active.children(".ui-menu ").children(".ui-menu-item").first();e&&e.length&&(this._open(e.parent()),this._delay(function(){this.focus(t,e)}))},next:function(t){this._move("next","first",t)},previous:function(t){this._move("prev","last",t)},isFirstItem:function(){return this.active&&!this.active.prevAll(".ui-menu-item").length},isLastItem:function(){return this.active&&!this.active.nextAll(".ui-menu-item").length},_move:function(t,e,i){var s;this.active&&(s="first"===t||"last"===t?this.active["first"===t?"prevAll":"nextAll"](".ui-menu-item").eq(-1):this.active[t+"All"](".ui-menu-item").eq(0)),s&&s.length&&this.active||(s=this.activeMenu.children(".ui-menu-item")[e]()),this.focus(i,s)},nextPage:function(e){var i,s,n;return this.active?(this.isLastItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.nextAll(".ui-menu-item").each(function(){return i=t(this),0>i.offset().top-s-n}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item")[this.active?"last":"first"]())),undefined):(this.next(e),undefined)},previousPage:function(e){var i,s,n;return this.active?(this.isFirstItem()||(this._hasScroll()?(s=this.active.offset().top,n=this.element.height(),this.active.prevAll(".ui-menu-item").each(function(){return i=t(this),i.offset().top-s+n>0}),this.focus(e,i)):this.focus(e,this.activeMenu.children(".ui-menu-item").first())),undefined):(this.next(e),undefined)},_hasScroll:function(){return this.element.outerHeight()<this.element.prop("scrollHeight")},select:function(e){this.active=this.active||t(e.target).closest(".ui-menu-item");var i={item:this.active};this.active.has(".ui-menu").length||this.collapseAll(e,!0),this._trigger("select",e,i)}})})(jQuery);(function(t,e){t.widget("ui.progressbar",{version:"1.10.3",options:{max:100,value:0,change:null,complete:null},min:0,_create:function(){this.oldValue=this.options.value=this._constrainedValue(),this.element.addClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").attr({role:"progressbar","aria-valuemin":this.min}),this.valueDiv=t("<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>").appendTo(this.element),this._refreshValue()},_destroy:function(){this.element.removeClass("ui-progressbar ui-widget ui-widget-content ui-corner-all").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.valueDiv.remove()},value:function(t){return t===e?this.options.value:(this.options.value=this._constrainedValue(t),this._refreshValue(),e)},_constrainedValue:function(t){return t===e&&(t=this.options.value),this.indeterminate=t===!1,"number"!=typeof t&&(t=0),this.indeterminate?!1:Math.min(this.options.max,Math.max(this.min,t))},_setOptions:function(t){var e=t.value;delete t.value,this._super(t),this.options.value=this._constrainedValue(e),this._refreshValue()},_setOption:function(t,e){"max"===t&&(e=Math.max(this.min,e)),this._super(t,e)},_percentage:function(){return this.indeterminate?100:100*(this.options.value-this.min)/(this.options.max-this.min)},_refreshValue:function(){var e=this.options.value,i=this._percentage();this.valueDiv.toggle(this.indeterminate||e>this.min).toggleClass("ui-corner-right",e===this.options.max).width(i.toFixed(0)+"%"),this.element.toggleClass("ui-progressbar-indeterminate",this.indeterminate),this.indeterminate?(this.element.removeAttr("aria-valuenow"),this.overlayDiv||(this.overlayDiv=t("<div class='ui-progressbar-overlay'></div>").appendTo(this.valueDiv))):(this.element.attr({"aria-valuemax":this.options.max,"aria-valuenow":e}),this.overlayDiv&&(this.overlayDiv.remove(),this.overlayDiv=null)),this.oldValue!==e&&(this.oldValue=e,this._trigger("change")),e===this.options.max&&this._trigger("complete")}})})(jQuery);(function(t){var e=5;t.widget("ui.slider",t.ui.mouse,{version:"1.10.3",widgetEventPrefix:"slide",options:{animate:!1,distance:0,max:100,min:0,orientation:"horizontal",range:!1,step:1,value:0,values:null,change:null,slide:null,start:null,stop:null},_create:function(){this._keySliding=!1,this._mouseSliding=!1,this._animateOff=!0,this._handleIndex=null,this._detectOrientation(),this._mouseInit(),this.element.addClass("ui-slider ui-slider-"+this.orientation+" ui-widget"+" ui-widget-content"+" ui-corner-all"),this._refresh(),this._setOption("disabled",this.options.disabled),this._animateOff=!1},_refresh:function(){this._createRange(),this._createHandles(),this._setupEvents(),this._refreshValue()},_createHandles:function(){var e,i,s=this.options,n=this.element.find(".ui-slider-handle").addClass("ui-state-default ui-corner-all"),a="<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",o=[];for(i=s.values&&s.values.length||1,n.length>i&&(n.slice(i).remove(),n=n.slice(0,i)),e=n.length;i>e;e++)o.push(a);this.handles=n.add(t(o.join("")).appendTo(this.element)),this.handle=this.handles.eq(0),this.handles.each(function(e){t(this).data("ui-slider-handle-index",e)})},_createRange:function(){var e=this.options,i="";e.range?(e.range===!0&&(e.values?e.values.length&&2!==e.values.length?e.values=[e.values[0],e.values[0]]:t.isArray(e.values)&&(e.values=e.values.slice(0)):e.values=[this._valueMin(),this._valueMin()]),this.range&&this.range.length?this.range.removeClass("ui-slider-range-min ui-slider-range-max").css({left:"",bottom:""}):(this.range=t("<div></div>").appendTo(this.element),i="ui-slider-range ui-widget-header ui-corner-all"),this.range.addClass(i+("min"===e.range||"max"===e.range?" ui-slider-range-"+e.range:""))):this.range=t([])},_setupEvents:function(){var t=this.handles.add(this.range).filter("a");this._off(t),this._on(t,this._handleEvents),this._hoverable(t),this._focusable(t)},_destroy:function(){this.handles.remove(),this.range.remove(),this.element.removeClass("ui-slider ui-slider-horizontal ui-slider-vertical ui-widget ui-widget-content ui-corner-all"),this._mouseDestroy()},_mouseCapture:function(e){var i,s,n,a,o,r,h,l,u=this,c=this.options;return c.disabled?!1:(this.elementSize={width:this.element.outerWidth(),height:this.element.outerHeight()},this.elementOffset=this.element.offset(),i={x:e.pageX,y:e.pageY},s=this._normValueFromMouse(i),n=this._valueMax()-this._valueMin()+1,this.handles.each(function(e){var i=Math.abs(s-u.values(e));(n>i||n===i&&(e===u._lastChangedValue||u.values(e)===c.min))&&(n=i,a=t(this),o=e)}),r=this._start(e,o),r===!1?!1:(this._mouseSliding=!0,this._handleIndex=o,a.addClass("ui-state-active").focus(),h=a.offset(),l=!t(e.target).parents().addBack().is(".ui-slider-handle"),this._clickOffset=l?{left:0,top:0}:{left:e.pageX-h.left-a.width()/2,top:e.pageY-h.top-a.height()/2-(parseInt(a.css("borderTopWidth"),10)||0)-(parseInt(a.css("borderBottomWidth"),10)||0)+(parseInt(a.css("marginTop"),10)||0)},this.handles.hasClass("ui-state-hover")||this._slide(e,o,s),this._animateOff=!0,!0))},_mouseStart:function(){return!0},_mouseDrag:function(t){var e={x:t.pageX,y:t.pageY},i=this._normValueFromMouse(e);return this._slide(t,this._handleIndex,i),!1},_mouseStop:function(t){return this.handles.removeClass("ui-state-active"),this._mouseSliding=!1,this._stop(t,this._handleIndex),this._change(t,this._handleIndex),this._handleIndex=null,this._clickOffset=null,this._animateOff=!1,!1},_detectOrientation:function(){this.orientation="vertical"===this.options.orientation?"vertical":"horizontal"},_normValueFromMouse:function(t){var e,i,s,n,a;return"horizontal"===this.orientation?(e=this.elementSize.width,i=t.x-this.elementOffset.left-(this._clickOffset?this._clickOffset.left:0)):(e=this.elementSize.height,i=t.y-this.elementOffset.top-(this._clickOffset?this._clickOffset.top:0)),s=i/e,s>1&&(s=1),0>s&&(s=0),"vertical"===this.orientation&&(s=1-s),n=this._valueMax()-this._valueMin(),a=this._valueMin()+s*n,this._trimAlignValue(a)},_start:function(t,e){var i={handle:this.handles[e],value:this.value()};return this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("start",t,i)},_slide:function(t,e,i){var s,n,a;this.options.values&&this.options.values.length?(s=this.values(e?0:1),2===this.options.values.length&&this.options.range===!0&&(0===e&&i>s||1===e&&s>i)&&(i=s),i!==this.values(e)&&(n=this.values(),n[e]=i,a=this._trigger("slide",t,{handle:this.handles[e],value:i,values:n}),s=this.values(e?0:1),a!==!1&&this.values(e,i,!0))):i!==this.value()&&(a=this._trigger("slide",t,{handle:this.handles[e],value:i}),a!==!1&&this.value(i))},_stop:function(t,e){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._trigger("stop",t,i)},_change:function(t,e){if(!this._keySliding&&!this._mouseSliding){var i={handle:this.handles[e],value:this.value()};this.options.values&&this.options.values.length&&(i.value=this.values(e),i.values=this.values()),this._lastChangedValue=e,this._trigger("change",t,i)}},value:function(t){return arguments.length?(this.options.value=this._trimAlignValue(t),this._refreshValue(),this._change(null,0),undefined):this._value()},values:function(e,i){var s,n,a;if(arguments.length>1)return this.options.values[e]=this._trimAlignValue(i),this._refreshValue(),this._change(null,e),undefined;if(!arguments.length)return this._values();if(!t.isArray(arguments[0]))return this.options.values&&this.options.values.length?this._values(e):this.value();for(s=this.options.values,n=arguments[0],a=0;s.length>a;a+=1)s[a]=this._trimAlignValue(n[a]),this._change(null,a);this._refreshValue()},_setOption:function(e,i){var s,n=0;switch("range"===e&&this.options.range===!0&&("min"===i?(this.options.value=this._values(0),this.options.values=null):"max"===i&&(this.options.value=this._values(this.options.values.length-1),this.options.values=null)),t.isArray(this.options.values)&&(n=this.options.values.length),t.Widget.prototype._setOption.apply(this,arguments),e){case"orientation":this._detectOrientation(),this.element.removeClass("ui-slider-horizontal ui-slider-vertical").addClass("ui-slider-"+this.orientation),this._refreshValue();break;case"value":this._animateOff=!0,this._refreshValue(),this._change(null,0),this._animateOff=!1;break;case"values":for(this._animateOff=!0,this._refreshValue(),s=0;n>s;s+=1)this._change(null,s);this._animateOff=!1;break;case"min":case"max":this._animateOff=!0,this._refreshValue(),this._animateOff=!1;break;case"range":this._animateOff=!0,this._refresh(),this._animateOff=!1}},_value:function(){var t=this.options.value;return t=this._trimAlignValue(t)},_values:function(t){var e,i,s;if(arguments.length)return e=this.options.values[t],e=this._trimAlignValue(e);if(this.options.values&&this.options.values.length){for(i=this.options.values.slice(),s=0;i.length>s;s+=1)i[s]=this._trimAlignValue(i[s]);return i}return[]},_trimAlignValue:function(t){if(this._valueMin()>=t)return this._valueMin();if(t>=this._valueMax())return this._valueMax();var e=this.options.step>0?this.options.step:1,i=(t-this._valueMin())%e,s=t-i;return 2*Math.abs(i)>=e&&(s+=i>0?e:-e),parseFloat(s.toFixed(5))},_valueMin:function(){return this.options.min},_valueMax:function(){return this.options.max},_refreshValue:function(){var e,i,s,n,a,o=this.options.range,r=this.options,h=this,l=this._animateOff?!1:r.animate,u={};this.options.values&&this.options.values.length?this.handles.each(function(s){i=100*((h.values(s)-h._valueMin())/(h._valueMax()-h._valueMin())),u["horizontal"===h.orientation?"left":"bottom"]=i+"%",t(this).stop(1,1)[l?"animate":"css"](u,r.animate),h.options.range===!0&&("horizontal"===h.orientation?(0===s&&h.range.stop(1,1)[l?"animate":"css"]({left:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({width:i-e+"%"},{queue:!1,duration:r.animate})):(0===s&&h.range.stop(1,1)[l?"animate":"css"]({bottom:i+"%"},r.animate),1===s&&h.range[l?"animate":"css"]({height:i-e+"%"},{queue:!1,duration:r.animate}))),e=i}):(s=this.value(),n=this._valueMin(),a=this._valueMax(),i=a!==n?100*((s-n)/(a-n)):0,u["horizontal"===this.orientation?"left":"bottom"]=i+"%",this.handle.stop(1,1)[l?"animate":"css"](u,r.animate),"min"===o&&"horizontal"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({width:i+"%"},r.animate),"max"===o&&"horizontal"===this.orientation&&this.range[l?"animate":"css"]({width:100-i+"%"},{queue:!1,duration:r.animate}),"min"===o&&"vertical"===this.orientation&&this.range.stop(1,1)[l?"animate":"css"]({height:i+"%"},r.animate),"max"===o&&"vertical"===this.orientation&&this.range[l?"animate":"css"]({height:100-i+"%"},{queue:!1,duration:r.animate}))},_handleEvents:{keydown:function(i){var s,n,a,o,r=t(i.target).data("ui-slider-handle-index");switch(i.keyCode){case t.ui.keyCode.HOME:case t.ui.keyCode.END:case t.ui.keyCode.PAGE_UP:case t.ui.keyCode.PAGE_DOWN:case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(i.preventDefault(),!this._keySliding&&(this._keySliding=!0,t(i.target).addClass("ui-state-active"),s=this._start(i,r),s===!1))return}switch(o=this.options.step,n=a=this.options.values&&this.options.values.length?this.values(r):this.value(),i.keyCode){case t.ui.keyCode.HOME:a=this._valueMin();break;case t.ui.keyCode.END:a=this._valueMax();break;case t.ui.keyCode.PAGE_UP:a=this._trimAlignValue(n+(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.PAGE_DOWN:a=this._trimAlignValue(n-(this._valueMax()-this._valueMin())/e);break;case t.ui.keyCode.UP:case t.ui.keyCode.RIGHT:if(n===this._valueMax())return;a=this._trimAlignValue(n+o);break;case t.ui.keyCode.DOWN:case t.ui.keyCode.LEFT:if(n===this._valueMin())return;a=this._trimAlignValue(n-o)}this._slide(i,r,a)},click:function(t){t.preventDefault()},keyup:function(e){var i=t(e.target).data("ui-slider-handle-index");this._keySliding&&(this._keySliding=!1,this._stop(e,i),this._change(e,i),t(e.target).removeClass("ui-state-active"))}}})})(jQuery);(function(t){function e(t){return function(){var e=this.element.val();t.apply(this,arguments),this._refresh(),e!==this.element.val()&&this._trigger("change")}}t.widget("ui.spinner",{version:"1.10.3",defaultElement:"<input>",widgetEventPrefix:"spin",options:{culture:null,icons:{down:"ui-icon-triangle-1-s",up:"ui-icon-triangle-1-n"},incremental:!0,max:null,min:null,numberFormat:null,page:10,step:1,change:null,spin:null,start:null,stop:null},_create:function(){this._setOption("max",this.options.max),this._setOption("min",this.options.min),this._setOption("step",this.options.step),this._value(this.element.val(),!0),this._draw(),this._on(this._events),this._refresh(),this._on(this.window,{beforeunload:function(){this.element.removeAttr("autocomplete")}})},_getCreateOptions:function(){var e={},i=this.element;return t.each(["min","max","step"],function(t,s){var n=i.attr(s);void 0!==n&&n.length&&(e[s]=n)}),e},_events:{keydown:function(t){this._start(t)&&this._keydown(t)&&t.preventDefault()},keyup:"_stop",focus:function(){this.previous=this.element.val()},blur:function(t){return this.cancelBlur?(delete this.cancelBlur,void 0):(this._stop(),this._refresh(),this.previous!==this.element.val()&&this._trigger("change",t),void 0)},mousewheel:function(t,e){if(e){if(!this.spinning&&!this._start(t))return!1;this._spin((e>0?1:-1)*this.options.step,t),clearTimeout(this.mousewheelTimer),this.mousewheelTimer=this._delay(function(){this.spinning&&this._stop(t)},100),t.preventDefault()}},"mousedown .ui-spinner-button":function(e){function i(){var t=this.element[0]===this.document[0].activeElement;t||(this.element.focus(),this.previous=s,this._delay(function(){this.previous=s}))}var s;s=this.element[0]===this.document[0].activeElement?this.previous:this.element.val(),e.preventDefault(),i.call(this),this.cancelBlur=!0,this._delay(function(){delete this.cancelBlur,i.call(this)}),this._start(e)!==!1&&this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e)},"mouseup .ui-spinner-button":"_stop","mouseenter .ui-spinner-button":function(e){return t(e.currentTarget).hasClass("ui-state-active")?this._start(e)===!1?!1:(this._repeat(null,t(e.currentTarget).hasClass("ui-spinner-up")?1:-1,e),void 0):void 0},"mouseleave .ui-spinner-button":"_stop"},_draw:function(){var t=this.uiSpinner=this.element.addClass("ui-spinner-input").attr("autocomplete","off").wrap(this._uiSpinnerHtml()).parent().append(this._buttonHtml());this.element.attr("role","spinbutton"),this.buttons=t.find(".ui-spinner-button").attr("tabIndex",-1).button().removeClass("ui-corner-all"),this.buttons.height()>Math.ceil(.5*t.height())&&t.height()>0&&t.height(t.height()),this.options.disabled&&this.disable()},_keydown:function(e){var i=this.options,s=t.ui.keyCode;switch(e.keyCode){case s.UP:return this._repeat(null,1,e),!0;case s.DOWN:return this._repeat(null,-1,e),!0;case s.PAGE_UP:return this._repeat(null,i.page,e),!0;case s.PAGE_DOWN:return this._repeat(null,-i.page,e),!0}return!1},_uiSpinnerHtml:function(){return"<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>"},_buttonHtml:function(){return"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'><span class='ui-icon "+this.options.icons.up+"'>▲</span>"+"</a>"+"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>"+"<span class='ui-icon "+this.options.icons.down+"'>▼</span>"+"</a>"},_start:function(t){return this.spinning||this._trigger("start",t)!==!1?(this.counter||(this.counter=1),this.spinning=!0,!0):!1},_repeat:function(t,e,i){t=t||500,clearTimeout(this.timer),this.timer=this._delay(function(){this._repeat(40,e,i)},t),this._spin(e*this.options.step,i)},_spin:function(t,e){var i=this.value()||0;this.counter||(this.counter=1),i=this._adjustValue(i+t*this._increment(this.counter)),this.spinning&&this._trigger("spin",e,{value:i})===!1||(this._value(i),this.counter++)},_increment:function(e){var i=this.options.incremental;return i?t.isFunction(i)?i(e):Math.floor(e*e*e/5e4-e*e/500+17*e/200+1):1},_precision:function(){var t=this._precisionOf(this.options.step);return null!==this.options.min&&(t=Math.max(t,this._precisionOf(this.options.min))),t},_precisionOf:function(t){var e=""+t,i=e.indexOf(".");return-1===i?0:e.length-i-1},_adjustValue:function(t){var e,i,s=this.options;return e=null!==s.min?s.min:0,i=t-e,i=Math.round(i/s.step)*s.step,t=e+i,t=parseFloat(t.toFixed(this._precision())),null!==s.max&&t>s.max?s.max:null!==s.min&&s.min>t?s.min:t},_stop:function(t){this.spinning&&(clearTimeout(this.timer),clearTimeout(this.mousewheelTimer),this.counter=0,this.spinning=!1,this._trigger("stop",t))},_setOption:function(t,e){if("culture"===t||"numberFormat"===t){var i=this._parse(this.element.val());return this.options[t]=e,this.element.val(this._format(i)),void 0}("max"===t||"min"===t||"step"===t)&&"string"==typeof e&&(e=this._parse(e)),"icons"===t&&(this.buttons.first().find(".ui-icon").removeClass(this.options.icons.up).addClass(e.up),this.buttons.last().find(".ui-icon").removeClass(this.options.icons.down).addClass(e.down)),this._super(t,e),"disabled"===t&&(e?(this.element.prop("disabled",!0),this.buttons.button("disable")):(this.element.prop("disabled",!1),this.buttons.button("enable")))},_setOptions:e(function(t){this._super(t),this._value(this.element.val())}),_parse:function(t){return"string"==typeof t&&""!==t&&(t=window.Globalize&&this.options.numberFormat?Globalize.parseFloat(t,10,this.options.culture):+t),""===t||isNaN(t)?null:t},_format:function(t){return""===t?"":window.Globalize&&this.options.numberFormat?Globalize.format(t,this.options.numberFormat,this.options.culture):t},_refresh:function(){this.element.attr({"aria-valuemin":this.options.min,"aria-valuemax":this.options.max,"aria-valuenow":this._parse(this.element.val())})},_value:function(t,e){var i;""!==t&&(i=this._parse(t),null!==i&&(e||(i=this._adjustValue(i)),t=this._format(i))),this.element.val(t),this._refresh()},_destroy:function(){this.element.removeClass("ui-spinner-input").prop("disabled",!1).removeAttr("autocomplete").removeAttr("role").removeAttr("aria-valuemin").removeAttr("aria-valuemax").removeAttr("aria-valuenow"),this.uiSpinner.replaceWith(this.element)},stepUp:e(function(t){this._stepUp(t)}),_stepUp:function(t){this._start()&&(this._spin((t||1)*this.options.step),this._stop())},stepDown:e(function(t){this._stepDown(t)}),_stepDown:function(t){this._start()&&(this._spin((t||1)*-this.options.step),this._stop())},pageUp:e(function(t){this._stepUp((t||1)*this.options.page)}),pageDown:e(function(t){this._stepDown((t||1)*this.options.page)}),value:function(t){return arguments.length?(e(this._value).call(this,t),void 0):this._parse(this.element.val())},widget:function(){return this.uiSpinner}})})(jQuery);(function(t,e){function i(){return++n}function s(t){return t.hash.length>1&&decodeURIComponent(t.href.replace(a,""))===decodeURIComponent(location.href.replace(a,""))}var n=0,a=/#.*$/;t.widget("ui.tabs",{version:"1.10.3",delay:300,options:{active:null,collapsible:!1,event:"click",heightStyle:"content",hide:null,show:null,activate:null,beforeActivate:null,beforeLoad:null,load:null},_create:function(){var e=this,i=this.options;this.running=!1,this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all").toggleClass("ui-tabs-collapsible",i.collapsible).delegate(".ui-tabs-nav > li","mousedown"+this.eventNamespace,function(e){t(this).is(".ui-state-disabled")&&e.preventDefault()}).delegate(".ui-tabs-anchor","focus"+this.eventNamespace,function(){t(this).closest("li").is(".ui-state-disabled")&&this.blur()}),this._processTabs(),i.active=this._initialActive(),t.isArray(i.disabled)&&(i.disabled=t.unique(i.disabled.concat(t.map(this.tabs.filter(".ui-state-disabled"),function(t){return e.tabs.index(t)}))).sort()),this.active=this.options.active!==!1&&this.anchors.length?this._findActive(i.active):t(),this._refresh(),this.active.length&&this.load(i.active)},_initialActive:function(){var i=this.options.active,s=this.options.collapsible,n=location.hash.substring(1);return null===i&&(n&&this.tabs.each(function(s,a){return t(a).attr("aria-controls")===n?(i=s,!1):e}),null===i&&(i=this.tabs.index(this.tabs.filter(".ui-tabs-active"))),(null===i||-1===i)&&(i=this.tabs.length?0:!1)),i!==!1&&(i=this.tabs.index(this.tabs.eq(i)),-1===i&&(i=s?!1:0)),!s&&i===!1&&this.anchors.length&&(i=0),i},_getCreateEventData:function(){return{tab:this.active,panel:this.active.length?this._getPanelForTab(this.active):t()}},_tabKeydown:function(i){var s=t(this.document[0].activeElement).closest("li"),n=this.tabs.index(s),a=!0;if(!this._handlePageNav(i)){switch(i.keyCode){case t.ui.keyCode.RIGHT:case t.ui.keyCode.DOWN:n++;break;case t.ui.keyCode.UP:case t.ui.keyCode.LEFT:a=!1,n--;break;case t.ui.keyCode.END:n=this.anchors.length-1;break;case t.ui.keyCode.HOME:n=0;break;case t.ui.keyCode.SPACE:return i.preventDefault(),clearTimeout(this.activating),this._activate(n),e;case t.ui.keyCode.ENTER:return i.preventDefault(),clearTimeout(this.activating),this._activate(n===this.options.active?!1:n),e;default:return}i.preventDefault(),clearTimeout(this.activating),n=this._focusNextTab(n,a),i.ctrlKey||(s.attr("aria-selected","false"),this.tabs.eq(n).attr("aria-selected","true"),this.activating=this._delay(function(){this.option("active",n)},this.delay))}},_panelKeydown:function(e){this._handlePageNav(e)||e.ctrlKey&&e.keyCode===t.ui.keyCode.UP&&(e.preventDefault(),this.active.focus())},_handlePageNav:function(i){return i.altKey&&i.keyCode===t.ui.keyCode.PAGE_UP?(this._activate(this._focusNextTab(this.options.active-1,!1)),!0):i.altKey&&i.keyCode===t.ui.keyCode.PAGE_DOWN?(this._activate(this._focusNextTab(this.options.active+1,!0)),!0):e},_findNextTab:function(e,i){function s(){return e>n&&(e=0),0>e&&(e=n),e}for(var n=this.tabs.length-1;-1!==t.inArray(s(),this.options.disabled);)e=i?e+1:e-1;return e},_focusNextTab:function(t,e){return t=this._findNextTab(t,e),this.tabs.eq(t).focus(),t},_setOption:function(t,i){return"active"===t?(this._activate(i),e):"disabled"===t?(this._setupDisabled(i),e):(this._super(t,i),"collapsible"===t&&(this.element.toggleClass("ui-tabs-collapsible",i),i||this.options.active!==!1||this._activate(0)),"event"===t&&this._setupEvents(i),"heightStyle"===t&&this._setupHeightStyle(i),e)},_tabId:function(t){return t.attr("aria-controls")||"ui-tabs-"+i()},_sanitizeSelector:function(t){return t?t.replace(/[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g,"\\$&"):""},refresh:function(){var e=this.options,i=this.tablist.children(":has(a[href])");e.disabled=t.map(i.filter(".ui-state-disabled"),function(t){return i.index(t)}),this._processTabs(),e.active!==!1&&this.anchors.length?this.active.length&&!t.contains(this.tablist[0],this.active[0])?this.tabs.length===e.disabled.length?(e.active=!1,this.active=t()):this._activate(this._findNextTab(Math.max(0,e.active-1),!1)):e.active=this.tabs.index(this.active):(e.active=!1,this.active=t()),this._refresh()},_refresh:function(){this._setupDisabled(this.options.disabled),this._setupEvents(this.options.event),this._setupHeightStyle(this.options.heightStyle),this.tabs.not(this.active).attr({"aria-selected":"false",tabIndex:-1}),this.panels.not(this._getPanelForTab(this.active)).hide().attr({"aria-expanded":"false","aria-hidden":"true"}),this.active.length?(this.active.addClass("ui-tabs-active ui-state-active").attr({"aria-selected":"true",tabIndex:0}),this._getPanelForTab(this.active).show().attr({"aria-expanded":"true","aria-hidden":"false"})):this.tabs.eq(0).attr("tabIndex",0)},_processTabs:function(){var e=this;this.tablist=this._getList().addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").attr("role","tablist"),this.tabs=this.tablist.find("> li:has(a[href])").addClass("ui-state-default ui-corner-top").attr({role:"tab",tabIndex:-1}),this.anchors=this.tabs.map(function(){return t("a",this)[0]}).addClass("ui-tabs-anchor").attr({role:"presentation",tabIndex:-1}),this.panels=t(),this.anchors.each(function(i,n){var a,o,r,h=t(n).uniqueId().attr("id"),l=t(n).closest("li"),u=l.attr("aria-controls");s(n)?(a=n.hash,o=e.element.find(e._sanitizeSelector(a))):(r=e._tabId(l),a="#"+r,o=e.element.find(a),o.length||(o=e._createPanel(r),o.insertAfter(e.panels[i-1]||e.tablist)),o.attr("aria-live","polite")),o.length&&(e.panels=e.panels.add(o)),u&&l.data("ui-tabs-aria-controls",u),l.attr({"aria-controls":a.substring(1),"aria-labelledby":h}),o.attr("aria-labelledby",h)}),this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").attr("role","tabpanel")},_getList:function(){return this.element.find("ol,ul").eq(0)},_createPanel:function(e){return t("<div>").attr("id",e).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").data("ui-tabs-destroy",!0)},_setupDisabled:function(e){t.isArray(e)&&(e.length?e.length===this.anchors.length&&(e=!0):e=!1);for(var i,s=0;i=this.tabs[s];s++)e===!0||-1!==t.inArray(s,e)?t(i).addClass("ui-state-disabled").attr("aria-disabled","true"):t(i).removeClass("ui-state-disabled").removeAttr("aria-disabled");this.options.disabled=e},_setupEvents:function(e){var i={click:function(t){t.preventDefault()}};e&&t.each(e.split(" "),function(t,e){i[e]="_eventHandler"}),this._off(this.anchors.add(this.tabs).add(this.panels)),this._on(this.anchors,i),this._on(this.tabs,{keydown:"_tabKeydown"}),this._on(this.panels,{keydown:"_panelKeydown"}),this._focusable(this.tabs),this._hoverable(this.tabs)},_setupHeightStyle:function(e){var i,s=this.element.parent();"fill"===e?(i=s.height(),i-=this.element.outerHeight()-this.element.height(),this.element.siblings(":visible").each(function(){var e=t(this),s=e.css("position");"absolute"!==s&&"fixed"!==s&&(i-=e.outerHeight(!0))}),this.element.children().not(this.panels).each(function(){i-=t(this).outerHeight(!0)}),this.panels.each(function(){t(this).height(Math.max(0,i-t(this).innerHeight()+t(this).height()))}).css("overflow","auto")):"auto"===e&&(i=0,this.panels.each(function(){i=Math.max(i,t(this).height("").height())}).height(i))},_eventHandler:function(e){var i=this.options,s=this.active,n=t(e.currentTarget),a=n.closest("li"),o=a[0]===s[0],r=o&&i.collapsible,h=r?t():this._getPanelForTab(a),l=s.length?this._getPanelForTab(s):t(),u={oldTab:s,oldPanel:l,newTab:r?t():a,newPanel:h};e.preventDefault(),a.hasClass("ui-state-disabled")||a.hasClass("ui-tabs-loading")||this.running||o&&!i.collapsible||this._trigger("beforeActivate",e,u)===!1||(i.active=r?!1:this.tabs.index(a),this.active=o?t():a,this.xhr&&this.xhr.abort(),l.length||h.length||t.error("jQuery UI Tabs: Mismatching fragment identifier."),h.length&&this.load(this.tabs.index(a),e),this._toggle(e,u))},_toggle:function(e,i){function s(){a.running=!1,a._trigger("activate",e,i)}function n(){i.newTab.closest("li").addClass("ui-tabs-active ui-state-active"),o.length&&a.options.show?a._show(o,a.options.show,s):(o.show(),s())}var a=this,o=i.newPanel,r=i.oldPanel;this.running=!0,r.length&&this.options.hide?this._hide(r,this.options.hide,function(){i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),n()}):(i.oldTab.closest("li").removeClass("ui-tabs-active ui-state-active"),r.hide(),n()),r.attr({"aria-expanded":"false","aria-hidden":"true"}),i.oldTab.attr("aria-selected","false"),o.length&&r.length?i.oldTab.attr("tabIndex",-1):o.length&&this.tabs.filter(function(){return 0===t(this).attr("tabIndex")}).attr("tabIndex",-1),o.attr({"aria-expanded":"true","aria-hidden":"false"}),i.newTab.attr({"aria-selected":"true",tabIndex:0})},_activate:function(e){var i,s=this._findActive(e);s[0]!==this.active[0]&&(s.length||(s=this.active),i=s.find(".ui-tabs-anchor")[0],this._eventHandler({target:i,currentTarget:i,preventDefault:t.noop}))},_findActive:function(e){return e===!1?t():this.tabs.eq(e)},_getIndex:function(t){return"string"==typeof t&&(t=this.anchors.index(this.anchors.filter("[href$='"+t+"']"))),t},_destroy:function(){this.xhr&&this.xhr.abort(),this.element.removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible"),this.tablist.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all").removeAttr("role"),this.anchors.removeClass("ui-tabs-anchor").removeAttr("role").removeAttr("tabIndex").removeUniqueId(),this.tabs.add(this.panels).each(function(){t.data(this,"ui-tabs-destroy")?t(this).remove():t(this).removeClass("ui-state-default ui-state-active ui-state-disabled ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel").removeAttr("tabIndex").removeAttr("aria-live").removeAttr("aria-busy").removeAttr("aria-selected").removeAttr("aria-labelledby").removeAttr("aria-hidden").removeAttr("aria-expanded").removeAttr("role")}),this.tabs.each(function(){var e=t(this),i=e.data("ui-tabs-aria-controls");i?e.attr("aria-controls",i).removeData("ui-tabs-aria-controls"):e.removeAttr("aria-controls")}),this.panels.show(),"content"!==this.options.heightStyle&&this.panels.css("height","")},enable:function(i){var s=this.options.disabled;s!==!1&&(i===e?s=!1:(i=this._getIndex(i),s=t.isArray(s)?t.map(s,function(t){return t!==i?t:null}):t.map(this.tabs,function(t,e){return e!==i?e:null})),this._setupDisabled(s))},disable:function(i){var s=this.options.disabled;if(s!==!0){if(i===e)s=!0;else{if(i=this._getIndex(i),-1!==t.inArray(i,s))return;s=t.isArray(s)?t.merge([i],s).sort():[i]}this._setupDisabled(s)}},load:function(e,i){e=this._getIndex(e);var n=this,a=this.tabs.eq(e),o=a.find(".ui-tabs-anchor"),r=this._getPanelForTab(a),h={tab:a,panel:r};s(o[0])||(this.xhr=t.ajax(this._ajaxSettings(o,i,h)),this.xhr&&"canceled"!==this.xhr.statusText&&(a.addClass("ui-tabs-loading"),r.attr("aria-busy","true"),this.xhr.success(function(t){setTimeout(function(){r.html(t),n._trigger("load",i,h)},1)}).complete(function(t,e){setTimeout(function(){"abort"===e&&n.panels.stop(!1,!0),a.removeClass("ui-tabs-loading"),r.removeAttr("aria-busy"),t===n.xhr&&delete n.xhr},1)})))},_ajaxSettings:function(e,i,s){var n=this;return{url:e.attr("href"),beforeSend:function(e,a){return n._trigger("beforeLoad",i,t.extend({jqXHR:e,ajaxSettings:a},s))}}},_getPanelForTab:function(e){var i=t(e).attr("aria-controls");return this.element.find(this._sanitizeSelector("#"+i))}})})(jQuery);(function(t){function e(e,i){var s=(e.attr("aria-describedby")||"").split(/\s+/);s.push(i),e.data("ui-tooltip-id",i).attr("aria-describedby",t.trim(s.join(" ")))}function i(e){var i=e.data("ui-tooltip-id"),s=(e.attr("aria-describedby")||"").split(/\s+/),n=t.inArray(i,s);-1!==n&&s.splice(n,1),e.removeData("ui-tooltip-id"),s=t.trim(s.join(" ")),s?e.attr("aria-describedby",s):e.removeAttr("aria-describedby")}var s=0;t.widget("ui.tooltip",{version:"1.10.3",options:{content:function(){var e=t(this).attr("title")||"";return t("<a>").text(e).html()},hide:!0,items:"[title]:not([disabled])",position:{my:"left top+15",at:"left bottom",collision:"flipfit flip"},show:!0,tooltipClass:null,track:!1,close:null,open:null},_create:function(){this._on({mouseover:"open",focusin:"open"}),this.tooltips={},this.parents={},this.options.disabled&&this._disable()},_setOption:function(e,i){var s=this;return"disabled"===e?(this[i?"_disable":"_enable"](),this.options[e]=i,void 0):(this._super(e,i),"content"===e&&t.each(this.tooltips,function(t,e){s._updateContent(e)}),void 0)},_disable:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0)}),this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.is("[title]")&&e.data("ui-tooltip-title",e.attr("title")).attr("title","")})},_enable:function(){this.element.find(this.options.items).addBack().each(function(){var e=t(this);e.data("ui-tooltip-title")&&e.attr("title",e.data("ui-tooltip-title"))})},open:function(e){var i=this,s=t(e?e.target:this.element).closest(this.options.items);s.length&&!s.data("ui-tooltip-id")&&(s.attr("title")&&s.data("ui-tooltip-title",s.attr("title")),s.data("ui-tooltip-open",!0),e&&"mouseover"===e.type&&s.parents().each(function(){var e,s=t(this);s.data("ui-tooltip-open")&&(e=t.Event("blur"),e.target=e.currentTarget=this,i.close(e,!0)),s.attr("title")&&(s.uniqueId(),i.parents[this.id]={element:this,title:s.attr("title")},s.attr("title",""))}),this._updateContent(s,e))},_updateContent:function(t,e){var i,s=this.options.content,n=this,a=e?e.type:null;return"string"==typeof s?this._open(e,t,s):(i=s.call(t[0],function(i){t.data("ui-tooltip-open")&&n._delay(function(){e&&(e.type=a),this._open(e,t,i)})}),i&&this._open(e,t,i),void 0)},_open:function(i,s,n){function a(t){l.of=t,o.is(":hidden")||o.position(l)}var o,r,h,l=t.extend({},this.options.position);if(n){if(o=this._find(s),o.length)return o.find(".ui-tooltip-content").html(n),void 0;s.is("[title]")&&(i&&"mouseover"===i.type?s.attr("title",""):s.removeAttr("title")),o=this._tooltip(s),e(s,o.attr("id")),o.find(".ui-tooltip-content").html(n),this.options.track&&i&&/^mouse/.test(i.type)?(this._on(this.document,{mousemove:a}),a(i)):o.position(t.extend({of:s},this.options.position)),o.hide(),this._show(o,this.options.show),this.options.show&&this.options.show.delay&&(h=this.delayedShow=setInterval(function(){o.is(":visible")&&(a(l.of),clearInterval(h))},t.fx.interval)),this._trigger("open",i,{tooltip:o}),r={keyup:function(e){if(e.keyCode===t.ui.keyCode.ESCAPE){var i=t.Event(e);i.currentTarget=s[0],this.close(i,!0)}},remove:function(){this._removeTooltip(o)}},i&&"mouseover"!==i.type||(r.mouseleave="close"),i&&"focusin"!==i.type||(r.focusout="close"),this._on(!0,s,r)}},close:function(e){var s=this,n=t(e?e.currentTarget:this.element),a=this._find(n);this.closing||(clearInterval(this.delayedShow),n.data("ui-tooltip-title")&&n.attr("title",n.data("ui-tooltip-title")),i(n),a.stop(!0),this._hide(a,this.options.hide,function(){s._removeTooltip(t(this))}),n.removeData("ui-tooltip-open"),this._off(n,"mouseleave focusout keyup"),n[0]!==this.element[0]&&this._off(n,"remove"),this._off(this.document,"mousemove"),e&&"mouseleave"===e.type&&t.each(this.parents,function(e,i){t(i.element).attr("title",i.title),delete s.parents[e]}),this.closing=!0,this._trigger("close",e,{tooltip:a}),this.closing=!1)},_tooltip:function(e){var i="ui-tooltip-"+s++,n=t("<div>").attr({id:i,role:"tooltip"}).addClass("ui-tooltip ui-widget ui-corner-all ui-widget-content "+(this.options.tooltipClass||""));return t("<div>").addClass("ui-tooltip-content").appendTo(n),n.appendTo(this.document[0].body),this.tooltips[i]=e,n},_find:function(e){var i=e.data("ui-tooltip-id");return i?t("#"+i):t()},_removeTooltip:function(t){t.remove(),delete this.tooltips[t.attr("id")]},_destroy:function(){var e=this;t.each(this.tooltips,function(i,s){var n=t.Event("blur");n.target=n.currentTarget=s[0],e.close(n,!0),t("#"+i).remove(),s.data("ui-tooltip-title")&&(s.attr("title",s.data("ui-tooltip-title")),s.removeData("ui-tooltip-title"))})}})})(jQuery);(function(t,e){var i="ui-effects-";t.effects={effect:{}},function(t,e){function i(t,e,i){var s=u[e.type]||{};return null==t?i||!e.def?null:e.def:(t=s.floor?~~t:parseFloat(t),isNaN(t)?e.def:s.mod?(t+s.mod)%s.mod:0>t?0:t>s.max?s.max:t)}function s(i){var s=l(),n=s._rgba=[];return i=i.toLowerCase(),f(h,function(t,a){var o,r=a.re.exec(i),h=r&&a.parse(r),l=a.space||"rgba";return h?(o=s[l](h),s[c[l].cache]=o[c[l].cache],n=s._rgba=o._rgba,!1):e}),n.length?("0,0,0,0"===n.join()&&t.extend(n,a.transparent),s):a[i]}function n(t,e,i){return i=(i+1)%1,1>6*i?t+6*(e-t)*i:1>2*i?e:2>3*i?t+6*(e-t)*(2/3-i):t}var a,o="backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",r=/^([\-+])=\s*(\d+\.?\d*)/,h=[{re:/rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[t[1],t[2],t[3],t[4]]}},{re:/rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,parse:function(t){return[2.55*t[1],2.55*t[2],2.55*t[3],t[4]]}},{re:/#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,parse:function(t){return[parseInt(t[1],16),parseInt(t[2],16),parseInt(t[3],16)]}},{re:/#([a-f0-9])([a-f0-9])([a-f0-9])/,parse:function(t){return[parseInt(t[1]+t[1],16),parseInt(t[2]+t[2],16),parseInt(t[3]+t[3],16)]}},{re:/hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,space:"hsla",parse:function(t){return[t[1],t[2]/100,t[3]/100,t[4]]}}],l=t.Color=function(e,i,s,n){return new t.Color.fn.parse(e,i,s,n)},c={rgba:{props:{red:{idx:0,type:"byte"},green:{idx:1,type:"byte"},blue:{idx:2,type:"byte"}}},hsla:{props:{hue:{idx:0,type:"degrees"},saturation:{idx:1,type:"percent"},lightness:{idx:2,type:"percent"}}}},u={"byte":{floor:!0,max:255},percent:{max:1},degrees:{mod:360,floor:!0}},d=l.support={},p=t("<p>")[0],f=t.each;p.style.cssText="background-color:rgba(1,1,1,.5)",d.rgba=p.style.backgroundColor.indexOf("rgba")>-1,f(c,function(t,e){e.cache="_"+t,e.props.alpha={idx:3,type:"percent",def:1}}),l.fn=t.extend(l.prototype,{parse:function(n,o,r,h){if(n===e)return this._rgba=[null,null,null,null],this;(n.jquery||n.nodeType)&&(n=t(n).css(o),o=e);var u=this,d=t.type(n),p=this._rgba=[];return o!==e&&(n=[n,o,r,h],d="array"),"string"===d?this.parse(s(n)||a._default):"array"===d?(f(c.rgba.props,function(t,e){p[e.idx]=i(n[e.idx],e)}),this):"object"===d?(n instanceof l?f(c,function(t,e){n[e.cache]&&(u[e.cache]=n[e.cache].slice())}):f(c,function(e,s){var a=s.cache;f(s.props,function(t,e){if(!u[a]&&s.to){if("alpha"===t||null==n[t])return;u[a]=s.to(u._rgba)}u[a][e.idx]=i(n[t],e,!0)}),u[a]&&0>t.inArray(null,u[a].slice(0,3))&&(u[a][3]=1,s.from&&(u._rgba=s.from(u[a])))}),this):e},is:function(t){var i=l(t),s=!0,n=this;return f(c,function(t,a){var o,r=i[a.cache];return r&&(o=n[a.cache]||a.to&&a.to(n._rgba)||[],f(a.props,function(t,i){return null!=r[i.idx]?s=r[i.idx]===o[i.idx]:e})),s}),s},_space:function(){var t=[],e=this;return f(c,function(i,s){e[s.cache]&&t.push(i)}),t.pop()},transition:function(t,e){var s=l(t),n=s._space(),a=c[n],o=0===this.alpha()?l("transparent"):this,r=o[a.cache]||a.to(o._rgba),h=r.slice();return s=s[a.cache],f(a.props,function(t,n){var a=n.idx,o=r[a],l=s[a],c=u[n.type]||{};null!==l&&(null===o?h[a]=l:(c.mod&&(l-o>c.mod/2?o+=c.mod:o-l>c.mod/2&&(o-=c.mod)),h[a]=i((l-o)*e+o,n)))}),this[n](h)},blend:function(e){if(1===this._rgba[3])return this;var i=this._rgba.slice(),s=i.pop(),n=l(e)._rgba;return l(t.map(i,function(t,e){return(1-s)*n[e]+s*t}))},toRgbaString:function(){var e="rgba(",i=t.map(this._rgba,function(t,e){return null==t?e>2?1:0:t});return 1===i[3]&&(i.pop(),e="rgb("),e+i.join()+")"},toHslaString:function(){var e="hsla(",i=t.map(this.hsla(),function(t,e){return null==t&&(t=e>2?1:0),e&&3>e&&(t=Math.round(100*t)+"%"),t});return 1===i[3]&&(i.pop(),e="hsl("),e+i.join()+")"},toHexString:function(e){var i=this._rgba.slice(),s=i.pop();return e&&i.push(~~(255*s)),"#"+t.map(i,function(t){return t=(t||0).toString(16),1===t.length?"0"+t:t}).join("")},toString:function(){return 0===this._rgba[3]?"transparent":this.toRgbaString()}}),l.fn.parse.prototype=l.fn,c.hsla.to=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e,i,s=t[0]/255,n=t[1]/255,a=t[2]/255,o=t[3],r=Math.max(s,n,a),h=Math.min(s,n,a),l=r-h,c=r+h,u=.5*c;return e=h===r?0:s===r?60*(n-a)/l+360:n===r?60*(a-s)/l+120:60*(s-n)/l+240,i=0===l?0:.5>=u?l/c:l/(2-c),[Math.round(e)%360,i,u,null==o?1:o]},c.hsla.from=function(t){if(null==t[0]||null==t[1]||null==t[2])return[null,null,null,t[3]];var e=t[0]/360,i=t[1],s=t[2],a=t[3],o=.5>=s?s*(1+i):s+i-s*i,r=2*s-o;return[Math.round(255*n(r,o,e+1/3)),Math.round(255*n(r,o,e)),Math.round(255*n(r,o,e-1/3)),a]},f(c,function(s,n){var a=n.props,o=n.cache,h=n.to,c=n.from;l.fn[s]=function(s){if(h&&!this[o]&&(this[o]=h(this._rgba)),s===e)return this[o].slice();var n,r=t.type(s),u="array"===r||"object"===r?s:arguments,d=this[o].slice();return f(a,function(t,e){var s=u["object"===r?t:e.idx];null==s&&(s=d[e.idx]),d[e.idx]=i(s,e)}),c?(n=l(c(d)),n[o]=d,n):l(d)},f(a,function(e,i){l.fn[e]||(l.fn[e]=function(n){var a,o=t.type(n),h="alpha"===e?this._hsla?"hsla":"rgba":s,l=this[h](),c=l[i.idx];return"undefined"===o?c:("function"===o&&(n=n.call(this,c),o=t.type(n)),null==n&&i.empty?this:("string"===o&&(a=r.exec(n),a&&(n=c+parseFloat(a[2])*("+"===a[1]?1:-1))),l[i.idx]=n,this[h](l)))})})}),l.hook=function(e){var i=e.split(" ");f(i,function(e,i){t.cssHooks[i]={set:function(e,n){var a,o,r="";if("transparent"!==n&&("string"!==t.type(n)||(a=s(n)))){if(n=l(a||n),!d.rgba&&1!==n._rgba[3]){for(o="backgroundColor"===i?e.parentNode:e;(""===r||"transparent"===r)&&o&&o.style;)try{r=t.css(o,"backgroundColor"),o=o.parentNode}catch(h){}n=n.blend(r&&"transparent"!==r?r:"_default")}n=n.toRgbaString()}try{e.style[i]=n}catch(h){}}},t.fx.step[i]=function(e){e.colorInit||(e.start=l(e.elem,i),e.end=l(e.end),e.colorInit=!0),t.cssHooks[i].set(e.elem,e.start.transition(e.end,e.pos))}})},l.hook(o),t.cssHooks.borderColor={expand:function(t){var e={};return f(["Top","Right","Bottom","Left"],function(i,s){e["border"+s+"Color"]=t}),e}},a=t.Color.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00",transparent:[null,null,null,0],_default:"#ffffff"}}(jQuery),function(){function i(e){var i,s,n=e.ownerDocument.defaultView?e.ownerDocument.defaultView.getComputedStyle(e,null):e.currentStyle,a={};if(n&&n.length&&n[0]&&n[n[0]])for(s=n.length;s--;)i=n[s],"string"==typeof n[i]&&(a[t.camelCase(i)]=n[i]);else for(i in n)"string"==typeof n[i]&&(a[i]=n[i]);return a}function s(e,i){var s,n,o={};for(s in i)n=i[s],e[s]!==n&&(a[s]||(t.fx.step[s]||!isNaN(parseFloat(n)))&&(o[s]=n));return o}var n=["add","remove","toggle"],a={border:1,borderBottom:1,borderColor:1,borderLeft:1,borderRight:1,borderTop:1,borderWidth:1,margin:1,padding:1};t.each(["borderLeftStyle","borderRightStyle","borderBottomStyle","borderTopStyle"],function(e,i){t.fx.step[i]=function(t){("none"!==t.end&&!t.setAttr||1===t.pos&&!t.setAttr)&&(jQuery.style(t.elem,i,t.end),t.setAttr=!0)}}),t.fn.addBack||(t.fn.addBack=function(t){return this.add(null==t?this.prevObject:this.prevObject.filter(t))}),t.effects.animateClass=function(e,a,o,r){var h=t.speed(a,o,r);return this.queue(function(){var a,o=t(this),r=o.attr("class")||"",l=h.children?o.find("*").addBack():o;l=l.map(function(){var e=t(this);return{el:e,start:i(this)}}),a=function(){t.each(n,function(t,i){e[i]&&o[i+"Class"](e[i])})},a(),l=l.map(function(){return this.end=i(this.el[0]),this.diff=s(this.start,this.end),this}),o.attr("class",r),l=l.map(function(){var e=this,i=t.Deferred(),s=t.extend({},h,{queue:!1,complete:function(){i.resolve(e)}});return this.el.animate(this.diff,s),i.promise()}),t.when.apply(t,l.get()).done(function(){a(),t.each(arguments,function(){var e=this.el;t.each(this.diff,function(t){e.css(t,"")})}),h.complete.call(o[0])})})},t.fn.extend({addClass:function(e){return function(i,s,n,a){return s?t.effects.animateClass.call(this,{add:i},s,n,a):e.apply(this,arguments)}}(t.fn.addClass),removeClass:function(e){return function(i,s,n,a){return arguments.length>1?t.effects.animateClass.call(this,{remove:i},s,n,a):e.apply(this,arguments)}}(t.fn.removeClass),toggleClass:function(i){return function(s,n,a,o,r){return"boolean"==typeof n||n===e?a?t.effects.animateClass.call(this,n?{add:s}:{remove:s},a,o,r):i.apply(this,arguments):t.effects.animateClass.call(this,{toggle:s},n,a,o)}}(t.fn.toggleClass),switchClass:function(e,i,s,n,a){return t.effects.animateClass.call(this,{add:i,remove:e},s,n,a)}})}(),function(){function s(e,i,s,n){return t.isPlainObject(e)&&(i=e,e=e.effect),e={effect:e},null==i&&(i={}),t.isFunction(i)&&(n=i,s=null,i={}),("number"==typeof i||t.fx.speeds[i])&&(n=s,s=i,i={}),t.isFunction(s)&&(n=s,s=null),i&&t.extend(e,i),s=s||i.duration,e.duration=t.fx.off?0:"number"==typeof s?s:s in t.fx.speeds?t.fx.speeds[s]:t.fx.speeds._default,e.complete=n||i.complete,e}function n(e){return!e||"number"==typeof e||t.fx.speeds[e]?!0:"string"!=typeof e||t.effects.effect[e]?t.isFunction(e)?!0:"object"!=typeof e||e.effect?!1:!0:!0}t.extend(t.effects,{version:"1.10.3",save:function(t,e){for(var s=0;e.length>s;s++)null!==e[s]&&t.data(i+e[s],t[0].style[e[s]])},restore:function(t,s){var n,a;for(a=0;s.length>a;a++)null!==s[a]&&(n=t.data(i+s[a]),n===e&&(n=""),t.css(s[a],n))},setMode:function(t,e){return"toggle"===e&&(e=t.is(":hidden")?"show":"hide"),e},getBaseline:function(t,e){var i,s;switch(t[0]){case"top":i=0;break;case"middle":i=.5;break;case"bottom":i=1;break;default:i=t[0]/e.height}switch(t[1]){case"left":s=0;break;case"center":s=.5;break;case"right":s=1;break;default:s=t[1]/e.width}return{x:s,y:i}},createWrapper:function(e){if(e.parent().is(".ui-effects-wrapper"))return e.parent();var i={width:e.outerWidth(!0),height:e.outerHeight(!0),"float":e.css("float")},s=t("<div></div>").addClass("ui-effects-wrapper").css({fontSize:"100%",background:"transparent",border:"none",margin:0,padding:0}),n={width:e.width(),height:e.height()},a=document.activeElement;try{a.id}catch(o){a=document.body}return e.wrap(s),(e[0]===a||t.contains(e[0],a))&&t(a).focus(),s=e.parent(),"static"===e.css("position")?(s.css({position:"relative"}),e.css({position:"relative"})):(t.extend(i,{position:e.css("position"),zIndex:e.css("z-index")}),t.each(["top","left","bottom","right"],function(t,s){i[s]=e.css(s),isNaN(parseInt(i[s],10))&&(i[s]="auto")}),e.css({position:"relative",top:0,left:0,right:"auto",bottom:"auto"})),e.css(n),s.css(i).show()},removeWrapper:function(e){var i=document.activeElement;return e.parent().is(".ui-effects-wrapper")&&(e.parent().replaceWith(e),(e[0]===i||t.contains(e[0],i))&&t(i).focus()),e},setTransition:function(e,i,s,n){return n=n||{},t.each(i,function(t,i){var a=e.cssUnit(i);a[0]>0&&(n[i]=a[0]*s+a[1])}),n}}),t.fn.extend({effect:function(){function e(e){function s(){t.isFunction(a)&&a.call(n[0]),t.isFunction(e)&&e()}var n=t(this),a=i.complete,r=i.mode;(n.is(":hidden")?"hide"===r:"show"===r)?(n[r](),s()):o.call(n[0],i,s)}var i=s.apply(this,arguments),n=i.mode,a=i.queue,o=t.effects.effect[i.effect];return t.fx.off||!o?n?this[n](i.duration,i.complete):this.each(function(){i.complete&&i.complete.call(this)}):a===!1?this.each(e):this.queue(a||"fx",e)},show:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="show",this.effect.call(this,i)}}(t.fn.show),hide:function(t){return function(e){if(n(e))return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="hide",this.effect.call(this,i)}}(t.fn.hide),toggle:function(t){return function(e){if(n(e)||"boolean"==typeof e)return t.apply(this,arguments);var i=s.apply(this,arguments);return i.mode="toggle",this.effect.call(this,i)}}(t.fn.toggle),cssUnit:function(e){var i=this.css(e),s=[];return t.each(["em","px","%","pt"],function(t,e){i.indexOf(e)>0&&(s=[parseFloat(i),e])}),s}})}(),function(){var e={};t.each(["Quad","Cubic","Quart","Quint","Expo"],function(t,i){e[i]=function(e){return Math.pow(e,t+2)}}),t.extend(e,{Sine:function(t){return 1-Math.cos(t*Math.PI/2)},Circ:function(t){return 1-Math.sqrt(1-t*t)},Elastic:function(t){return 0===t||1===t?t:-Math.pow(2,8*(t-1))*Math.sin((80*(t-1)-7.5)*Math.PI/15)},Back:function(t){return t*t*(3*t-2)},Bounce:function(t){for(var e,i=4;((e=Math.pow(2,--i))-1)/11>t;);return 1/Math.pow(4,3-i)-7.5625*Math.pow((3*e-2)/22-t,2)}}),t.each(e,function(e,i){t.easing["easeIn"+e]=i,t.easing["easeOut"+e]=function(t){return 1-i(1-t)},t.easing["easeInOut"+e]=function(t){return.5>t?i(2*t)/2:1-i(-2*t+2)/2}})}()})(jQuery);(function(t){var e=/up|down|vertical/,i=/up|left|vertical|horizontal/;t.effects.effect.blind=function(s,n){var a,o,r,h=t(this),l=["position","top","bottom","left","right","height","width"],c=t.effects.setMode(h,s.mode||"hide"),u=s.direction||"up",d=e.test(u),p=d?"height":"width",f=d?"top":"left",m=i.test(u),g={},v="show"===c;h.parent().is(".ui-effects-wrapper")?t.effects.save(h.parent(),l):t.effects.save(h,l),h.show(),a=t.effects.createWrapper(h).css({overflow:"hidden"}),o=a[p](),r=parseFloat(a.css(f))||0,g[p]=v?o:0,m||(h.css(d?"bottom":"right",0).css(d?"top":"left","auto").css({position:"absolute"}),g[f]=v?r:o+r),v&&(a.css(p,0),m||a.css(f,r+o)),a.animate(g,{duration:s.duration,easing:s.easing,queue:!1,complete:function(){"hide"===c&&h.hide(),t.effects.restore(h,l),t.effects.removeWrapper(h),n()}})}})(jQuery);(function(t){t.effects.effect.bounce=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","height","width"],h=t.effects.setMode(o,e.mode||"effect"),l="hide"===h,c="show"===h,u=e.direction||"up",d=e.distance,p=e.times||5,f=2*p+(c||l?1:0),m=e.duration/f,g=e.easing,v="up"===u||"down"===u?"top":"left",_="up"===u||"left"===u,b=o.queue(),y=b.length;for((c||l)&&r.push("opacity"),t.effects.save(o,r),o.show(),t.effects.createWrapper(o),d||(d=o["top"===v?"outerHeight":"outerWidth"]()/3),c&&(a={opacity:1},a[v]=0,o.css("opacity",0).css(v,_?2*-d:2*d).animate(a,m,g)),l&&(d/=Math.pow(2,p-1)),a={},a[v]=0,s=0;p>s;s++)n={},n[v]=(_?"-=":"+=")+d,o.animate(n,m,g).animate(a,m,g),d=l?2*d:d/2;l&&(n={opacity:0},n[v]=(_?"-=":"+=")+d,o.animate(n,m,g)),o.queue(function(){l&&o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),i()}),y>1&&b.splice.apply(b,[1,0].concat(b.splice(y,f+1))),o.dequeue()}})(jQuery);(function(t){t.effects.effect.clip=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","height","width"],h=t.effects.setMode(o,e.mode||"hide"),l="show"===h,c=e.direction||"vertical",u="vertical"===c,d=u?"height":"width",p=u?"top":"left",f={};t.effects.save(o,r),o.show(),s=t.effects.createWrapper(o).css({overflow:"hidden"}),n="IMG"===o[0].tagName?s:o,a=n[d](),l&&(n.css(d,0),n.css(p,a/2)),f[d]=l?a:0,f[p]=l?0:a/2,n.animate(f,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){l||o.hide(),t.effects.restore(o,r),t.effects.removeWrapper(o),i()}})}})(jQuery);(function(t){t.effects.effect.drop=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","opacity","height","width"],o=t.effects.setMode(n,e.mode||"hide"),r="show"===o,h=e.direction||"left",l="up"===h||"down"===h?"top":"left",c="up"===h||"left"===h?"pos":"neg",u={opacity:r?1:0};t.effects.save(n,a),n.show(),t.effects.createWrapper(n),s=e.distance||n["top"===l?"outerHeight":"outerWidth"](!0)/2,r&&n.css("opacity",0).css(l,"pos"===c?-s:s),u[l]=(r?"pos"===c?"+=":"-=":"pos"===c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}})}})(jQuery);(function(t){t.effects.effect.explode=function(e,i){function s(){b.push(this),b.length===u*d&&n()}function n(){p.css({visibility:"visible"}),t(b).remove(),m||p.hide(),i()}var a,o,r,h,l,c,u=e.pieces?Math.round(Math.sqrt(e.pieces)):3,d=u,p=t(this),f=t.effects.setMode(p,e.mode||"hide"),m="show"===f,g=p.show().css("visibility","hidden").offset(),v=Math.ceil(p.outerWidth()/d),_=Math.ceil(p.outerHeight()/u),b=[];for(a=0;u>a;a++)for(h=g.top+a*_,c=a-(u-1)/2,o=0;d>o;o++)r=g.left+o*v,l=o-(d-1)/2,p.clone().appendTo("body").wrap("<div></div>").css({position:"absolute",visibility:"visible",left:-o*v,top:-a*_}).parent().addClass("ui-effects-explode").css({position:"absolute",overflow:"hidden",width:v,height:_,left:r+(m?l*v:0),top:h+(m?c*_:0),opacity:m?0:1}).animate({left:r+(m?0:l*v),top:h+(m?0:c*_),opacity:m?1:0},e.duration||500,e.easing,s)}})(jQuery);(function(t){t.effects.effect.fade=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"toggle");s.animate({opacity:n},{queue:!1,duration:e.duration,easing:e.easing,complete:i})}})(jQuery);(function(t){t.effects.effect.fold=function(e,i){var s,n,a=t(this),o=["position","top","bottom","left","right","height","width"],r=t.effects.setMode(a,e.mode||"hide"),h="show"===r,l="hide"===r,c=e.size||15,u=/([0-9]+)%/.exec(c),d=!!e.horizFirst,p=h!==d,f=p?["width","height"]:["height","width"],m=e.duration/2,g={},v={};t.effects.save(a,o),a.show(),s=t.effects.createWrapper(a).css({overflow:"hidden"}),n=p?[s.width(),s.height()]:[s.height(),s.width()],u&&(c=parseInt(u[1],10)/100*n[l?0:1]),h&&s.css(d?{height:0,width:c}:{height:c,width:0}),g[f[0]]=h?n[0]:c,v[f[1]]=h?n[1]:0,s.animate(g,m,e.easing).animate(v,m,e.easing,function(){l&&a.hide(),t.effects.restore(a,o),t.effects.removeWrapper(a),i()})}})(jQuery);(function(t){t.effects.effect.highlight=function(e,i){var s=t(this),n=["backgroundImage","backgroundColor","opacity"],a=t.effects.setMode(s,e.mode||"show"),o={backgroundColor:s.css("backgroundColor")};"hide"===a&&(o.opacity=0),t.effects.save(s,n),s.show().css({backgroundImage:"none",backgroundColor:e.color||"#ffff99"}).animate(o,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===a&&s.hide(),t.effects.restore(s,n),i()}})}})(jQuery);(function(t){t.effects.effect.pulsate=function(e,i){var s,n=t(this),a=t.effects.setMode(n,e.mode||"show"),o="show"===a,r="hide"===a,h=o||"hide"===a,l=2*(e.times||5)+(h?1:0),c=e.duration/l,u=0,d=n.queue(),p=d.length;for((o||!n.is(":visible"))&&(n.css("opacity",0).show(),u=1),s=1;l>s;s++)n.animate({opacity:u},c,e.easing),u=1-u;n.animate({opacity:u},c,e.easing),n.queue(function(){r&&n.hide(),i()}),p>1&&d.splice.apply(d,[1,0].concat(d.splice(p,l+1))),n.dequeue()}})(jQuery);(function(t){t.effects.effect.puff=function(e,i){var s=t(this),n=t.effects.setMode(s,e.mode||"hide"),a="hide"===n,o=parseInt(e.percent,10)||150,r=o/100,h={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()};t.extend(e,{effect:"scale",queue:!1,fade:!0,mode:n,complete:i,percent:a?o:100,from:a?h:{height:h.height*r,width:h.width*r,outerHeight:h.outerHeight*r,outerWidth:h.outerWidth*r}}),s.effect(e)},t.effects.effect.scale=function(e,i){var s=t(this),n=t.extend(!0,{},e),a=t.effects.setMode(s,e.mode||"effect"),o=parseInt(e.percent,10)||(0===parseInt(e.percent,10)?0:"hide"===a?0:100),r=e.direction||"both",h=e.origin,l={height:s.height(),width:s.width(),outerHeight:s.outerHeight(),outerWidth:s.outerWidth()},c={y:"horizontal"!==r?o/100:1,x:"vertical"!==r?o/100:1};n.effect="size",n.queue=!1,n.complete=i,"effect"!==a&&(n.origin=h||["middle","center"],n.restore=!0),n.from=e.from||("show"===a?{height:0,width:0,outerHeight:0,outerWidth:0}:l),n.to={height:l.height*c.y,width:l.width*c.x,outerHeight:l.outerHeight*c.y,outerWidth:l.outerWidth*c.x},n.fade&&("show"===a&&(n.from.opacity=0,n.to.opacity=1),"hide"===a&&(n.from.opacity=1,n.to.opacity=0)),s.effect(n)},t.effects.effect.size=function(e,i){var s,n,a,o=t(this),r=["position","top","bottom","left","right","width","height","overflow","opacity"],h=["position","top","bottom","left","right","overflow","opacity"],l=["width","height","overflow"],c=["fontSize"],u=["borderTopWidth","borderBottomWidth","paddingTop","paddingBottom"],d=["borderLeftWidth","borderRightWidth","paddingLeft","paddingRight"],p=t.effects.setMode(o,e.mode||"effect"),f=e.restore||"effect"!==p,m=e.scale||"both",g=e.origin||["middle","center"],v=o.css("position"),_=f?r:h,b={height:0,width:0,outerHeight:0,outerWidth:0};"show"===p&&o.show(),s={height:o.height(),width:o.width(),outerHeight:o.outerHeight(),outerWidth:o.outerWidth()},"toggle"===e.mode&&"show"===p?(o.from=e.to||b,o.to=e.from||s):(o.from=e.from||("show"===p?b:s),o.to=e.to||("hide"===p?b:s)),a={from:{y:o.from.height/s.height,x:o.from.width/s.width},to:{y:o.to.height/s.height,x:o.to.width/s.width}},("box"===m||"both"===m)&&(a.from.y!==a.to.y&&(_=_.concat(u),o.from=t.effects.setTransition(o,u,a.from.y,o.from),o.to=t.effects.setTransition(o,u,a.to.y,o.to)),a.from.x!==a.to.x&&(_=_.concat(d),o.from=t.effects.setTransition(o,d,a.from.x,o.from),o.to=t.effects.setTransition(o,d,a.to.x,o.to))),("content"===m||"both"===m)&&a.from.y!==a.to.y&&(_=_.concat(c).concat(l),o.from=t.effects.setTransition(o,c,a.from.y,o.from),o.to=t.effects.setTransition(o,c,a.to.y,o.to)),t.effects.save(o,_),o.show(),t.effects.createWrapper(o),o.css("overflow","hidden").css(o.from),g&&(n=t.effects.getBaseline(g,s),o.from.top=(s.outerHeight-o.outerHeight())*n.y,o.from.left=(s.outerWidth-o.outerWidth())*n.x,o.to.top=(s.outerHeight-o.to.outerHeight)*n.y,o.to.left=(s.outerWidth-o.to.outerWidth)*n.x),o.css(o.from),("content"===m||"both"===m)&&(u=u.concat(["marginTop","marginBottom"]).concat(c),d=d.concat(["marginLeft","marginRight"]),l=r.concat(u).concat(d),o.find("*[width]").each(function(){var i=t(this),s={height:i.height(),width:i.width(),outerHeight:i.outerHeight(),outerWidth:i.outerWidth()};f&&t.effects.save(i,l),i.from={height:s.height*a.from.y,width:s.width*a.from.x,outerHeight:s.outerHeight*a.from.y,outerWidth:s.outerWidth*a.from.x},i.to={height:s.height*a.to.y,width:s.width*a.to.x,outerHeight:s.height*a.to.y,outerWidth:s.width*a.to.x},a.from.y!==a.to.y&&(i.from=t.effects.setTransition(i,u,a.from.y,i.from),i.to=t.effects.setTransition(i,u,a.to.y,i.to)),a.from.x!==a.to.x&&(i.from=t.effects.setTransition(i,d,a.from.x,i.from),i.to=t.effects.setTransition(i,d,a.to.x,i.to)),i.css(i.from),i.animate(i.to,e.duration,e.easing,function(){f&&t.effects.restore(i,l)})})),o.animate(o.to,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){0===o.to.opacity&&o.css("opacity",o.from.opacity),"hide"===p&&o.hide(),t.effects.restore(o,_),f||("static"===v?o.css({position:"relative",top:o.to.top,left:o.to.left}):t.each(["top","left"],function(t,e){o.css(e,function(e,i){var s=parseInt(i,10),n=t?o.to.left:o.to.top;return"auto"===i?n+"px":s+n+"px"})})),t.effects.removeWrapper(o),i()}})}})(jQuery);(function(t){t.effects.effect.shake=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","height","width"],o=t.effects.setMode(n,e.mode||"effect"),r=e.direction||"left",h=e.distance||20,l=e.times||3,c=2*l+1,u=Math.round(e.duration/c),d="up"===r||"down"===r?"top":"left",p="up"===r||"left"===r,f={},m={},g={},v=n.queue(),_=v.length;for(t.effects.save(n,a),n.show(),t.effects.createWrapper(n),f[d]=(p?"-=":"+=")+h,m[d]=(p?"+=":"-=")+2*h,g[d]=(p?"-=":"+=")+2*h,n.animate(f,u,e.easing),s=1;l>s;s++)n.animate(m,u,e.easing).animate(g,u,e.easing);n.animate(m,u,e.easing).animate(f,u/2,e.easing).queue(function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}),_>1&&v.splice.apply(v,[1,0].concat(v.splice(_,c+1))),n.dequeue()}})(jQuery);(function(t){t.effects.effect.slide=function(e,i){var s,n=t(this),a=["position","top","bottom","left","right","width","height"],o=t.effects.setMode(n,e.mode||"show"),r="show"===o,h=e.direction||"left",l="up"===h||"down"===h?"top":"left",c="up"===h||"left"===h,u={};t.effects.save(n,a),n.show(),s=e.distance||n["top"===l?"outerHeight":"outerWidth"](!0),t.effects.createWrapper(n).css({overflow:"hidden"}),r&&n.css(l,c?isNaN(s)?"-"+s:-s:s),u[l]=(r?c?"+=":"-=":c?"-=":"+=")+s,n.animate(u,{queue:!1,duration:e.duration,easing:e.easing,complete:function(){"hide"===o&&n.hide(),t.effects.restore(n,a),t.effects.removeWrapper(n),i()}})}})(jQuery);(function(t){t.effects.effect.transfer=function(e,i){var s=t(this),n=t(e.to),a="fixed"===n.css("position"),o=t("body"),r=a?o.scrollTop():0,h=a?o.scrollLeft():0,l=n.offset(),c={top:l.top-r,left:l.left-h,height:n.innerHeight(),width:n.innerWidth()},u=s.offset(),d=t("<div class='ui-effects-transfer'></div>").appendTo(document.body).addClass(e.className).css({top:u.top-r,left:u.left-h,height:s.innerHeight(),width:s.innerWidth(),position:a?"fixed":"absolute"}).animate(c,e.duration,e.easing,function(){d.remove(),i()})}})(jQuery);
\ No newline at end of file diff --git a/dgbuilder/public/jquery/js/jquery.ui.touch-punch.min.js b/dgbuilder/public/jquery/js/jquery.ui.touch-punch.min.js new file mode 100644 index 00000000..31272ce6 --- /dev/null +++ b/dgbuilder/public/jquery/js/jquery.ui.touch-punch.min.js @@ -0,0 +1,11 @@ +/*! + * jQuery UI Touch Punch 0.2.3 + * + * Copyright 2011–2014, Dave Furfero + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Depends: + * jquery.ui.widget.js + * jquery.ui.mouse.js + */ +!function(a){function f(a,b){if(!(a.originalEvent.touches.length>1)){a.preventDefault();var c=a.originalEvent.changedTouches[0],d=document.createEvent("MouseEvents");d.initMouseEvent(b,!0,!0,window,1,c.screenX,c.screenY,c.clientX,c.clientY,!1,!1,!1,!1,0,null),a.target.dispatchEvent(d)}}if(a.support.touch="ontouchend"in document,a.support.touch){var e,b=a.ui.mouse.prototype,c=b._mouseInit,d=b._mouseDestroy;b._touchStart=function(a){var b=this;!e&&b._mouseCapture(a.originalEvent.changedTouches[0])&&(e=!0,b._touchMoved=!1,f(a,"mouseover"),f(a,"mousemove"),f(a,"mousedown"))},b._touchMove=function(a){e&&(this._touchMoved=!0,f(a,"mousemove"))},b._touchEnd=function(a){e&&(f(a,"mouseup"),f(a,"mouseout"),this._touchMoved||f(a,"click"),e=!1)},b._mouseInit=function(){var b=this;b.element.bind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),c.call(b)},b._mouseDestroy=function(){var b=this;b.element.unbind({touchstart:a.proxy(b,"_touchStart"),touchmove:a.proxy(b,"_touchMove"),touchend:a.proxy(b,"_touchEnd")}),d.call(b)}}}(jQuery);
\ No newline at end of file diff --git a/dgbuilder/public/node-red.png b/dgbuilder/public/node-red.png Binary files differnew file mode 100644 index 00000000..a60c2672 --- /dev/null +++ b/dgbuilder/public/node-red.png diff --git a/dgbuilder/public/orion/built-editor.css b/dgbuilder/public/orion/built-editor.css new file mode 100644 index 00000000..02045786 --- /dev/null +++ b/dgbuilder/public/orion/built-editor.css @@ -0,0 +1,526 @@ +.textview { + background-color: white; + font-family: "Consolas", "Monaco", "Vera Mono", "monospace"; + font-size: 10pt; + min-width: 50px; + min-height: 50px; +} +.textviewScroll { + padding: 1px 2px; +} +.textviewContent { + cursor: auto; +} +.textviewLeftRuler { + border-right: 1px solid #eaeaea; +} +.textviewRightRuler { + border-left: 1px solid #eaeaea; +} +.textviewMarginRuler { + border-left: 1px solid #eaeaea; +} +.textviewBlockCursor { + background: black; + opacity: 0.4; +} +.ruler { +} +.ruler.annotations { + width: 16px; +} +.ruler.folding { + width: 14px; +} +.ruler.lines { + text-align: right; +} +.ruler.overview { + width: 14px; +} +.rulerLines { + color: silver; +} +.rulerLines.even +.rulerLines.odd { +} +.tooltipTheme.textview { + background-color: InfoBackground !important; + color: InfoText !important; +} +.tooltipTheme .textviewScroll { + padding: 0px; +} +.textviewTooltip { + font-family: "Consolas", "Monaco", "Vera Mono", "monospace"; + font-size: 10pt; + background-color: InfoBackground; + color: InfoText; + padding: 2px; + border-radius: 4px; + border: 1px solid black; + z-index: 100; + position: fixed; + overflow: hidden; +} +.textviewTooltip em { + font-style: normal; + font-weight: bold; +} +.textviewTooltip span { + vertical-align: baseline; +} +.textviewTooltip .tooltipRow { + display: table-row; +} +.textviewTooltip .tooltipTitle { + float: right; +} +.tooltipTheme .annotationLine.currentLine { + background-color: transparent !important; +} +.contentassist { + font-size:9pt; + display: none; + background-color: white; + position: fixed; + top: 100px; + left: 100px; + z-index:100; + cursor: default; + min-width: 70px; + max-width: 350px; + max-height: 170px; + overflow: hidden; + white-space: nowrap; + border-radius: 5px; + box-shadow: rgba(0, 0, 0, 0.3) 2px 2px 10px; + line-height: 18px; +} +.contentassist:focus { + outline: none; +} +.contentassist:hover { + overflow-y: auto; +} +.contentassist .proposal-emphasis { + font-weight: normal; +} +.contentassist hr{ + border: 0; + height: 0; + border-top: 1px solid rgba(0, 0, 0, 0.1); + border-bottom: 1px solid rgba(255, 255, 255, 0.3); +} +.contentassist .proposal-noemphasis-keyword { + background-color: aliceblue; + color: #CC4C07; + font-weight: bold; +} +.contentassist .proposal-noemphasis { + background-color: aliceblue; + font-weight: lighter; + color: black; +} +.contentassist .proposal-noemphasis-title-keywords { + background-color: aliceblue; + color: grey; +} +.contentassist .proposal-noemphasis-title { + background-color: aliceblue; + color: grey; + padding-top: 5px; +} +.contentassist .proposal-noemphasis-title::before { + content: "- "; +} +.contentassist .proposal-noemphasis-title::after { + content: " -"; +} +.contentassist .proposal-default { + +} +.contentassist .proposal-name { + font-weight: bold; +} +.contentassist > div:hover { + background-color: #fab467; + background: linear-gradient(#fabb76, #e1a25c); + border-radius: 3px; +} +.contentassist>div.proposal-hr:hover { + background-color: white; + background: none; +} +.contentassist .selected { + background-color: rgb(48, 135, 179); + background: linear-gradient(rgb(60, 150, 190), rgb(30, 120, 160)); + border-radius: 3px; + color: white; +} +.contentassist .cloneProposal { + box-shadow: rgba(0, 0, 0, 0.9) 2px 2px 8px; + position: fixed; + z-index: 1000; +} +.contentassist>div { + padding: 1px 3px 1px 5px; +} +.cloneWrapper { + display: block; + overflow: visible; + z-index: 1000; +} +.contentassist.cloneWrapper:hover { + overflow: visible; +} +.comment.block.documentation, .comment-block-documentation { + color: #00008F; +} +.comment { + color: #3C802C; +} +.constant.character.entity, .constant-character-entity { + font-style: normal; +} +.constant { + color: blue; +} +.entity.name.function, .entity.name.type, .entity-name-function, .entity-name-type { + font-weight: bold; +} +.entity.name.tag, .entity-name-tag { + color: #CC4C07; +} +.entity.other.attribute.name, .entity-other-attribute-name { + color: #3C802C; +} +.entity { + color: #3f7f7f; +} +.invalid.illegal, .invalid-illegal { + color: white; + background-color: red; +} +.invalid.deprecated, .invalid-deprecated { + text-decoration: line-through; +} +.invalid { + color: red; + font-weight: bold; +} +.keyword.other.documentation.markup { + color: #7F7F9F; +} +.keyword.other.documentation { + color: #7F9FBF; +} +.keyword.operator, .keyword-operator { + color: #ddd; +} +.keyword { + color: #CC4C07; + font-weight: bold; +} +.markup.heading, .markup-heading { + font-weight: bold; +} +.markup.quote, .markup-quote { + font-style: italic; +} +.meta.annotation.currentLine { + background-color: #EAF2FE; +} +.meta.tag { + color: #3f7f7f; +} +.punctuation.definition.comment, .punctuation-definition-comment { + color: #3f5fbf; +} +.punctuation.definition.string, .punctuation-definition-string { + color: blue; +} +.punctuation.separator.space { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAAXNSR0IArs4c6QAAABVJREFUCNdj3L17938GBgYGJgYoAAAxOAM004kASgAAAABJRU5ErkJggg=="); + background-repeat: no-repeat; + background-position: center center; +} +.punctuation.separator.tab { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAFCAYAAABmWJ3mAAAAAXNSR0IArs4c6QAAABtJREFUCNdj2L17938GKEBmYwgQJ0m8IAMDAwDemh/hgxuOkwAAAABJRU5ErkJggg=="); + background-repeat: no-repeat; + background-position: left center; +} +.storage { + color: #7F0055; +} +.string { + color: #446fbd; +} +.support { + color: #21439c; +} +.variable.parameter, .variable-parameter { + color: black; +} +.variable.language, .variable-language { + color: #7F0055; + font-weight: bold; +} +.variable { + color: #0000c0; +} +.cm-meta { color: #00008F; } +.cm-keyword { font-weight: bold; color: #7F0055; } +.cm-atom { color: #21439c; } +.cm-number { color: black; } +.cm-def { color: green; } +.cm-variable { color: black; } +.cm-variable-2 { color: #004080; } +.cm-variable-3 { color: #004080; } +.cm-property { color: black; } +.cm-operator { color: #222; } +.cm-comment { color: green; } +.cm-string { color: blue; } +.cm-error { color: #ff0000; } +.cm-qualifier { color: gray; } +.cm-builtin { color: #7F0055; } +.cm-bracket { color: white; background-color: gray; } +.cm-tag { color: #3f7f7f; } +.cm-attribute { color: #7f007f; } +.annotation { +} +.annotation.error, +.annotation.warning, +.annotation.task, +.annotation.bookmark, +.annotation.breakpoint, +.annotation.collapsed, +.annotation.expanded, +.annotation.currentBracket, +.annotation.matchingBracket, +.annotation.currentLine, +.annotation.matchingSearch, +.annotation.currentSearch, +.annotation.readOccurrence, +.annotation.writeOccurrence, +.annotation.linkedGroup, +.annotation.currentLinkedGroup, +.annotation.selectedLinkedGroup { +} +.annotation.blame { + color: gray; + background-color: rgb(255, 132, 44); +} +.annotation.currentBlame { + color: black; + background-color: rgb(184, 103, 163); +} +.annotationHTML { + cursor: pointer; + width: 16px; + height: 16px; + display: inline-block; + vertical-align: middle; + background-position: center; + background-repeat: no-repeat; +} +.annotationHTML.error { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjNGNTlDOUMxMUVDNDExRTM4NDU4RjQ3Q0I3NkI4OTBDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjNGNTlDOUMyMUVDNDExRTM4NDU4RjQ3Q0I3NkI4OTBDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6M0Y1OUM5QkYxRUM0MTFFMzg0NThGNDdDQjc2Qjg5MEMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6M0Y1OUM5QzAxRUM0MTFFMzg0NThGNDdDQjc2Qjg5MEMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4Be44kAAAAqklEQVR42mL8//8/AyWAiYFCQLEBLNgEX+aURgGpAiA2gAqdB+KJ4lO6l6GrZUQPA6DmqUAqC4eF04CGZOP0AtRmkOZ/QHwLSeoWVCwLqgZnGORD6TtA7ArEp6DYFSqGrAZrGBhCaTUgXg3EoVD+aqgYshraRON5JD+HQm2GueQWmhqsBkyE0ipAvBuIzaB4N1QMWQ11opERW16ARlU+UoARn5CGXmYCCDAAPz09iI0KJ9QAAAAASUVORK5CYII="); +} +.annotationHTML.warning { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkREMTE1OUNDMUVDMjExRTM4NDU4RjQ3Q0I3NkI4OTBDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkREMTE1OUNEMUVDMjExRTM4NDU4RjQ3Q0I3NkI4OTBDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6REQxMTU5Q0ExRUMyMTFFMzg0NThGNDdDQjc2Qjg5MEMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6REQxMTU5Q0IxRUMyMTFFMzg0NThGNDdDQjc2Qjg5MEMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4Kzt/qAAAA0ElEQVR42mL8//8/AyWAiYFCQLEBLLgkfl8obARSZUD8HYiLWQ3652NTx4gtDICao4HUbCDeBRVyBmI3oCHHCRoA1MwOpO4A8V+gBgWo2AMg9QaITYFi/wl5IRaIZYD4K1AjI8gSIBYBYnkg9gLirYQCMRdKc0M1KUDZIFCM1wtAG02B1Ckk+WlQSzKQxLSA3riOywUpaHxHILZHE8vA54VQNL4XFCODaHyB+B6IBZH4s7CE0Ud8LvCHhsFfKN8VihmgYqegavAnpKGVmQACDACxJDv3vmRk+gAAAABJRU5ErkJggg=="); +} +.annotationHTML.task { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjdEMjg0RkI2MUVFMzExRTM4NDU4RjQ3Q0I3NkI4OTBDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjdEMjg0RkI3MUVFMzExRTM4NDU4RjQ3Q0I3NkI4OTBDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6N0QyODRGQjQxRUUzMTFFMzg0NThGNDdDQjc2Qjg5MEMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6N0QyODRGQjUxRUUzMTFFMzg0NThGNDdDQjc2Qjg5MEMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6Utm8RAAAAl0lEQVR42mL8//8/AyWAiYFCQLEBLMicqtVRRPmnLXQZIzkuuEuJF04BsTEQ15JjAEizGxB/AmJpYgz4DsTLoewrQOwJ9PNHID0ViDPwBiIURAPxBqjm2UDN74CB2wFkZxKMBSioAOJ9QI1t0JgBaS4nKhqhwAyIdwE1ugLpLHyacRkAM+QcECtTkhKViYlfxqGfmQACDAAjXCa0hW/NdQAAAABJRU5ErkJggg=="); +} +.annotationHTML.bookmark { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjdEMjg0RkIyMUVFMzExRTM4NDU4RjQ3Q0I3NkI4OTBDIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjdEMjg0RkIzMUVFMzExRTM4NDU4RjQ3Q0I3NkI4OTBDIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6N0QyODRGQjAxRUUzMTFFMzg0NThGNDdDQjc2Qjg5MEMiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6N0QyODRGQjExRUUzMTFFMzg0NThGNDdDQjc2Qjg5MEMiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz54SgjJAAAAuUlEQVR42mL8//8/AyWAiYFCQFsDWrdcMAViY3xqWAhYEADEv4H4LLle8IVinIARORaAzpUHiUG5qkC8C8p2AOKHQPwDhKt9DD7gcoEREJ8H4vtImkHgAFTsKhB743QB1BWyQGo+EDujGb4JiNOBtr/AawDUEH0gdQFNWBGo+QGxgRgEpV8C8SsoO4KUWAAZsAeIDYBYB4g3A3EUwViAOl8Falsb0Mn/kMRTQYYCxe4TDIOhlZkAAgwAunFAhB2QB2cAAAAASUVORK5CYII="); +} +.annotationHTML.breakpoint { + + background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAFheoFxkoFxnpmt0pmZxpnF7rYyWwmJwpnaFs3aDrWt8rXGBrYycwmZ3mXuNs42cu77F03GIs3aJrYGVu2J5oKCuxeDj6LK/03GLrYieu3aIoIygu6m4zcLN3MTM1m6Rs2aLriRgkSZilXGXtoGcs7LD0QBLhSZikihol3ScubrO2Yaqu5q4xpO0wpm7yabF0ZO9yaXI0r3X3tHj6P///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADQALAAAAAAQABAAAAafQJpwSCwWLYZBIDAwWIw0A+FFpW6aRUPCxe1yE4ahhdCCxWSzmSwGgxGeUceKpUqhUCkVa7UK0wgkJCUjJoUmIyWBBEIEGhoeJ4YmJx6OAUIADQ0QIZIhEJoAQgEUFBUgkiAVpZdRCxIPFx8iIh8XDw4FfhYHDhgZHB0dHBkYEwdwUQoTEc3OEwp+QwYHCBMMDBMIB9JESAJLAk5Q5EVBADs="); +} +.annotationHTML.collapsed { + + width: 14px; + height: 14px; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAWBJREFUeNpi/P//PwMlgImBQkCxASzoAp++fo+6de+Z+fXbD/Jev/nAICoiwKCpqrBBTUlqNR835zJ09YzIYfDxy7eo/cevLmXlYGNQUJAEahZieP3mHcODB08Zfv/4w+BoqR3Nz8O1DKcXzt94HPqXmZlBU1+LgZNfkMHazIOBA0hr6uswgMTP33gYijcMLlx/EMAnLs7w7sc/hg9AG0HgPZB+B8S84hJA+UcBeMPg+at3DJIMnAxZzt5wsUhnXzDdsmIVWB6vAcLCfAys3z4wzN64huEfkJ/uH8IwexOQDQymD2/fgeXxekFLRWHD51evGDhZGRi4WSFSnCwgNjB2Xr1m0AbK4zXAQkdhNdPf3wx3r91g+PruLcOqnasYvn54x3Dv2k0G5r+/GMyB8nijEQTefvoadeH6w9Cbtx8GvH//kUFQkJ9BQ1V+g76m/GphPu5lBA0YenmBYgMAAgwA34GIKjmLxOUAAAAASUVORK5CYII="); +} +.annotationHTML.expanded { + + width: 14px; + height: 14px; + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAT5JREFUeNrUksFKw0AURW+mTWw67SSEiG209U90r4jddFO34l+5U0HdZCHiFwiCOz9AlMSmGEpMOqk1TWJSFGyFbATR2dyZd+Dw3mOENE3xkyP8PYHrBT3OX7uW43ZefA6FUaw1dJPSyrmu1k8KBYOh37Od4XFZLEPXFdRrFMGIw3U9TKMYqw1tb0VjcxLy9eEF425CCIxWE5JcxSQGxCyNloG87gXhwWIHc4J767lTZQw8ShFGSZbxRyaQmZJxd3NRUJ6ffwQNEi6PzG/L2tjdmvFCgcKqKL2F2Olu43MzggDka+IjPuOFI7Sbujn2fUglYKkkzFIi+R0I/QDrGS8UqDX5QkhiOHYfE84hkhSTkGNgOyDJFCzjhYLTq+vDtrG8r1LZtB6fcHtzB+uhD5VWzLx+lvF/8JV/XfAuwADsrJbMGG4l4AAAAABJRU5ErkJggg=="); +} +.annotationHTML.multiple { + + background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAOdpa+yJiuFYXOFYXeBYXONwded8f+NwdmhwkHB4iPr7/ezx+fP2+2h4kOzy+Wh4iPr8/gCBwTaczjaXyjaYyjaXyTaYyfr8/QCMzQCMzACHxzao2jal2Dak1zag03iAgI/Ckn64fZrHmX+4fZLCianPopPCiarOoqbLlafLlbnXq7nWq6fLlMTcsoCIeJCQcIiIeKCYaJiQcO16ee16evGVlfGWlfahn/ahoPWhn/WhoPe1tP///////wAAAAAAACH5BAEAAD0ALAAAAAAQABAAAAaRwJ5wSCwaj8WYcslcDmObaDTGq1Zjzw4mk+FQIRcFTzaUeTRoj4zHaI+HL0lkLnnxFgsH7zWEWSoTFBMwVlUwQy6JMDCJjYwuQx8tk5MfOzk4OjcfkSssKCkqHzY0MzQ1nEIJJSYkJCcJAQCzAQlDDyIjISMiCQYEAgMGD0MNIMfHDQUHBc3EQgjR0tPSSNY9QQA7"); +} +.annotationHTML.overlay { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAcAAAAHCAYAAADEUlfTAAAAAXNSR0IArs4c6QAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJEAQvB2JVdrAAAAAdaVRYdENvbW1lbnQAAAAAAENyZWF0ZWQgd2l0aCBHSU1QZC5lBwAAAD1JREFUCNdtjkESADAEAzemf69f66HMqGlOIhYiFRFRtSQBWAY7mzx+EDTL6sSgb1jTk7Q87rxyqe37fXsAa78gLyZnRgEAAAAASUVORK5CYII="); + background-position: right bottom; + position: relative; + top: -16px; +} +.annotationHTML.currentBracket { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sLEBULCGQmEKAAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAnklEQVQ4y7VTsRHDIBATJg1HCUzAHEzFBExAzwZsRMkE9gifKhc72ODYibr/+xcnoQdugq0LAujEwmbn0UxQh4OxpjX1XgshwFqLnPM5PQTQGlprWpbl3RhJ/CSQUm7qPYLp7i8cEpRSoJT6ju0lIaVEQgiKMQ4lHHpQayVjzHWCn5jIOcc8z9dMBADvPZxz3SC1tzCI8vgWdvL+VzwB8JSj2GFTyxIAAAAASUVORK5CYII="); +} +.annotationHTML.matchingBracket { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sLEBUMAsuyb3kAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAoklEQVQ4y61TsQ3EIAw80DcI0USKGIApWIsB2IGGKbJPugxBR3VfvfRRCOSTvw7LPuPzGXgI8f0gwAsFu5rXIYMdDiEOIdnKW5YFzjnEGH+bhwA/KKVwmibu0BhRnpEZY1BrHTaVT7fQJZjnGeu63tOAJFNKVEox53yqQZfAWstt27oidgm01ve3UEqBaBjnspG89wgh3LiFgZXHt3Dh23/FGxKViehm0X85AAAAAElFTkSuQmCC"); +} +.annotationHTML.currentLine { + + background-image: url("data:image/gif;base64,R0lGODlhEAAQAMQAALxe0bNWzbdZzrlb0KpPx61RybBTy6VLxadNxZGctIeUroyYsG92hHyMqIKRq2l9nmyAoHGDonaIpStXj6q80k1aXf///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAABYALAAAAAAQABAAAAVCoCWOZGmeKDql5ppOMGXBk/zOoltSNO6XrlXwxIPNYiMGq8SoLC2MaNPygEQkDYdikUg6LQcEoWAICAaA5HPNLoUAADs="); +} +.annotationHTML.matchingSearch { + + background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAALClrLu1ubOpsKqdp6eapKufqMTAw7attLSrsrGnr62jq8C7v765vaebpb22vLmyuMbCxsnGycfEx8G+wcrIysTBxUltof//yf///v70jergpPvws+nWc/npqvrpqvrpq/raffffnvXVkfTVkvXUkd+9f+SiOemvV+uyXa2OX7mYZqeIXKuNX/ClO7KQYqiIXJ59Vp19VpFvTo9uTZBvTpNyUJNyUf///////wAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADgALAAAAAAQABAAAAZ4QJxwSCwajS2aS1U6DlunzcagcuKgG4sn5HJiLZ2QiHbEbj6hEapVTKVYr3OItG5TIhVGLF0npigUEAsPAjV9Q24pEhMBCAoybEUmGRcrDgcAAzNGkxcYNzAJBQSbRJ0YqBc2DaVEHJ6pGTStRBqfGBcZILRWvThBADs="); +} +.annotationHTML.currentSearch { + + background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAALClrLu1ubOpsKqdp6eapKufqMTAw7attLSrsrGnr62jq8C7v765vaebpb22vLmyuMbCxsnGycfEx8G+wcrIysTBxUltof//yf///v70jergpPvws+nWc/npqvrpqvrpq/raffffnvXVkfTVkvXUkd+9f+SiOemvV+uyXa2OX7mYZqeIXKuNX/ClO7KQYqiIXJ59Vp19VpFvTo9uTZBvTpNyUJNyUf///////wAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAADgALAAAAAAQABAAAAZ4QJxwSCwajS2aS1U6DlunzcagcuKgG4sn5HJiLZ2QiHbEbj6hEapVTKVYr3OItG5TIhVGLF0npigUEAsPAjV9Q24pEhMBCAoybEUmGRcrDgcAAzNGkxcYNzAJBQSbRJ0YqBc2DaVEHJ6pGTStRBqfGBcZILRWvThBADs="); +} +.annotationHTML.readOccurrence { + + background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAP3ykf3zn/7lIv7kI/fbI/7nRf7scLe0oMXDtfXXHsG4gaKdgOXBF+rIJqKdhaijjNWxHeLBL6GafLuYJpmQcvvdg5OHZpyRcJ+UdLavm4+BXqGWeYZ1TYx7VZ6QcJ2NbI+Ebv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACEALAAAAAAQABAAAAZewJBwSCwaj0KMBFlULphDJwIakh6gGckCcXgyLxjuYol0PA6YMQbZqFAOhw/Gc2wHABaJhAMy2gEGBRoSHRtFf4ECDRpGERV3iQ0TRwyQBQSSRAmbAwEMnxAQClRQQQA7"); +} +.annotationHTML.writeOccurrence { + + background-image: url("data:image/gif;base64,R0lGODlhEAAQANUAAP3ykf3zn/7lIv7kI/fbI/7nRf7scLe0oMXDtfXXHsG4gaKdgOXBF+rIJqKdhaijjNWxHeLBL6GafLuYJpmQcvvdg5OHZpyRcJ+UdLavm4+BXqGWeYZ1TYx7VZ6QcJ2NbI+Ebv///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAACEALAAAAAAQABAAAAZewJBwSCwaj0KMBFlULphDJwIakh6gGckCcXgyLxjuYol0PA6YMQbZqFAOhw/Gc2wHABaJhAMy2gEGBRoSHRtFf4ECDRpGERV3iQ0TRwyQBQSSRAmbAwEMnxAQClRQQQA7"); +} +.annotationHTML.blame { + float: left; +} +.annotationHTML.currentBlame { + float: left; +} +.annotationHTML.blame.single { + width: 32px; + height: 32px; +} +.annotationHTML.currentBlame.single { + width: 32px; + height: 32px; +} +.annotationOverview { + cursor: pointer; + border-radius: 2px; + left: 2px; + width: 8px; +} +.annotationOverview.task { + background-color: #93bb7a; + border: 1px solid #79aa59; +} +.annotationOverview.breakpoint { + background-color: lightblue; + border: 1px solid blue; +} +.annotationOverview.bookmark { + background-color: #84b3cf; + border: 1px solid #9cc2d8; +} +.annotationOverview.error { + background-color: #EFA1A7; + border: 1px solid #ec8a91; +} +.annotationOverview.warning { + background-color: #fce1a9; + border: 1px solid #face70; +} +.annotationOverview.currentBracket { + background-color: lightgray; + border: 1px solid red; +} +.annotationOverview.matchingBracket { + background-color: #ff7f7f; + border: 1px solid #ff3232; +} +.annotationOverview.currentLine { + background-color: #f8a852; + border: 1px solid #f79327; +} +.annotationOverview.matchingSearch { +background-color: #C3E1FF; +border: 1px solid #afcae5; +} +.annotationOverview.currentSearch { + background-color: #53D1FF; + border: 1px solid #42a7cc; +} +.annotationOverview.readOccurrence { + background-color: lightgray; + border: 1px solid black; +} +.annotationOverview.writeOccurrence { + background-color: Gold; + border: 1px solid darkred; +} +.annotationOverview.currentBlame { + background-color: rgb(184, 103, 163); + border: 1px solid black; +} +.annotationRange { + background-repeat: repeat-x; + background-position: left bottom; +} +.annotationRange.task { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sLDhEoIrb7JmcAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAGUlEQVQI12NggIH/DGdhDCM45z/DfyiBAADgdQjGhI/4DAAAAABJRU5ErkJggg=="); +} +.annotationRange.breakpoint { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sLDhEqHTKradgAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAIklEQVQI11XJMQ0AMAzAMGMafwrFlD19+sUKIJTFo9k+B/kQ+Qr2bIVKOgAAAABJRU5ErkJggg=="); +} +.annotationRange.bookmark { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII="); +} +.annotationRange.error { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJDw4cOCW1/KIAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAHElEQVQI12NggIL/DAz/GdA5/xkY/qPKMDAwAADLZwf5rvm+LQAAAABJRU5ErkJggg=="); +} +.annotationRange.warning { + + background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAADCAYAAAC09K7GAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sJFhQXEbhTg7YAAAAZdEVYdENvbW1lbnQAQ3JlYXRlZCB3aXRoIEdJTVBXgQ4XAAAAMklEQVQI12NkgIIvJ3QXMjAwdDN+OaEbysDA4MPAwNDNwMCwiOHLCd1zX07o6kBVGQEAKBANtobskNMAAAAASUVORK5CYII="); +} +.annotationRange.currentBracket { +} +.annotationRange.matchingBracket { + outline: 1px solid red; +} +.annotationRange.readOccurrence { + background-color: lightgray; +} +.annotationRange.writeOccurrence { + background-color: yellow; +} +.annotationRange.matchingSearch { + background-color: #C3E1FF; +} +.annotationRange.currentSearch { + background-color: #53D1FF; +} +.annotationRange.linkedGroup { + outline: 1px solid grey; +} +.annotationRange.currentLinkedGroup { + background-color: #C3E1FF; +} +.annotationRange.selectedLinkedGroup { + background-color: #53D1FF; +} +.annotationLine { +} +.annotationLine.currentLine { + background-color: #EAF2FE; +} diff --git a/dgbuilder/public/orion/built-editor.min.js b/dgbuilder/public/orion/built-editor.min.js new file mode 100644 index 00000000..b7d1209b --- /dev/null +++ b/dgbuilder/public/orion/built-editor.min.js @@ -0,0 +1,1081 @@ +/* + + Copyright (c) 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2010, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + Felipe Heidrich (IBM Corporation) - initial API and implementation + Silenio Quarti (IBM Corporation) - initial API and implementation + + Copyright (c) 2010, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + Felipe Heidrich (IBM Corporation) - initial API and implementation + Silenio Quarti (IBM Corporation) - initial API and implementation + + Copyright (c) 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2010, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + Felipe Heidrich (IBM Corporation) - initial API and implementation + Silenio Quarti (IBM Corporation) - initial API and implementation + + Copyright (c) 2010, 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + Felipe Heidrich (IBM Corporation) - initial API and implementation + Silenio Quarti (IBM Corporation) - initial API and implementation + + Copyright (c) 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2010, 2014 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + Felipe Heidrich (IBM Corporation) - initial API and implementation + Silenio Quarti (IBM Corporation) - initial API and implementation + Mihai Sucan (Mozilla Foundation) - fix for Bug#334583 Bug#348471 Bug#349485 Bug#350595 Bug#360726 Bug#361180 Bug#362835 Bug#362428 Bug#362286 Bug#354270 Bug#361474 Bug#363945 Bug#366312 Bug#370584 + + Copyright (c) 2010, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + Felipe Heidrich (IBM Corporation) - initial API and implementation + Silenio Quarti (IBM Corporation) - initial API and implementation + + Copyright (c) 2010, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + Felipe Heidrich (IBM Corporation) - initial API and implementation + Silenio Quarti (IBM Corporation) - initial API and implementation + + Copyright (c) 2010, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2010, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2010, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2010, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + Felipe Heidrich (IBM Corporation) - initial API and implementation + Silenio Quarti (IBM Corporation) - initial API and implementation + + Copyright (c) 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2009, 2014 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2010, 2014 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2011, 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2011, 2014 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2014 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2014 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2011, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2011, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2014 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2011, 2014 IBM Corporation and others. + Copyright (c) 2012 VMware, Inc. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + Andrew Eisenberg - rename to jsTemplateContentAssist.js + + Copyright (c) 2011, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2011, 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + + Copyright (c) 2011, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2011, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2010, 2012 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + Alex Lakatos - fix for bug#369781 + + Copyright (c) 2014 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2014 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2014 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: IBM Corporation - initial API and implementation + + Copyright (c) 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation + RequireJS i18n 2.0.2 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. + Available via the MIT or new BSD license. + see: http://github.com/requirejs/i18n for details + + Copyright (c) 2011, 2013 IBM Corporation and others. + All rights reserved. This program and the accompanying materials are made + available under the terms of the Eclipse Public License v1.0 + (http://www.eclipse.org/legal/epl-v10.html), and the Eclipse Distribution + License v1.0 (http://www.eclipse.org/org/documents/edl-v10.html). + + Contributors: + IBM Corporation - initial API and implementation +*/ +var requirejs,require,define; +(function(k){function m(a,b){var e,j,w,x,f,l,c,d,o,g=b&&b.split("/"),h=q.map,p=h&&h["*"]||{};if(a&&a.charAt(0)===".")if(b){g=g.slice(0,g.length-1);a=g.concat(a.split("/"));for(d=0;d<a.length;d+=1)if(e=a[d],e===".")a.splice(d,1),d-=1;else if(e==="..")if(d===1&&(a[2]===".."||a[0]===".."))break;else d>0&&(a.splice(d-1,2),d-=2);a=a.join("/")}else a.indexOf("./")===0&&(a=a.substring(2));if((g||p)&&h){e=a.split("/");for(d=e.length;d>0;d-=1){j=e.slice(0,d).join("/");if(g)for(o=g.length;o>0;o-=1)if(w=h[g.slice(0, +o).join("/")])if(w=w[j]){x=w;f=d;break}if(x)break;!l&&p&&p[j]&&(l=p[j],c=d)}!x&&l&&(x=l,f=c);x&&(e.splice(0,f,x),a=e.join("/"))}return a}function n(a,e){return function(){return b.apply(k,t.call(arguments,0).concat([a,e]))}}function i(a){return function(b){return m(b,a)}}function c(a){return function(b){l[a]=b}}function d(a){if(p.call(o,a)){var b=o[a];delete o[a];r[a]=!0;h.apply(k,b)}if(!p.call(l,a)&&!p.call(r,a))throw Error("No "+a);return l[a]}function f(a){var b,e=a?a.indexOf("!"):-1;e>-1&&(b= +a.substring(0,e),a=a.substring(e+1,a.length));return[b,a]}function g(a){return function(){return q&&q.config&&q.config[a]||{}}}var h,b,a,e,l={},o={},q={},r={},p=Object.prototype.hasOwnProperty,t=[].slice;a=function(a,b){var e,j=f(a),w=j[0],a=j[1];w&&(w=m(w,b),e=d(w));w?a=e&&e.normalize?e.normalize(a,i(b)):m(a,b):(a=m(a,b),j=f(a),w=j[0],a=j[1],w&&(e=d(w)));return{f:w?w+"!"+a:a,n:a,pr:w,p:e}};e={require:function(a){return n(a)},exports:function(a){var b=l[a];return typeof b!=="undefined"?b:l[a]={}}, +module:function(a){return{id:a,uri:"",exports:l[a],config:g(a)}}};h=function(b,f,g,j){var w,x,D,y,h=[],q,j=j||b;if(typeof g==="function"){f=!f.length&&g.length?["require","exports","module"]:f;for(y=0;y<f.length;y+=1)if(D=a(f[y],j),x=D.f,x==="require")h[y]=e.require(b);else if(x==="exports")h[y]=e.exports(b),q=!0;else if(x==="module")w=h[y]=e.module(b);else if(p.call(l,x)||p.call(o,x)||p.call(r,x))h[y]=d(x);else if(D.p)D.p.load(D.n,n(j,!0),c(x),{}),h[y]=l[x];else throw Error(b+" missing "+x);f=g.apply(l[b], +h);if(b)if(w&&w.exports!==k&&w.exports!==l[b])l[b]=w.exports;else if(f!==k||!q)l[b]=f}else b&&(l[b]=g)};requirejs=require=b=function(f,l,c,j,w){if(typeof f==="string")return e[f]?e[f](l):d(a(f,l).f);else f.splice||(q=f,l.splice?(f=l,l=c,c=null):f=k);l=l||function(){};typeof c==="function"&&(c=j,j=w);j?h(k,f,l,c):setTimeout(function(){h(k,f,l,c)},4);return b};b.config=function(a){q=a;return b};define=function(a,b,e){b.splice||(e=b,b=[]);!p.call(l,a)&&!p.call(o,a)&&(o[a]=[a,b,e])};define.amd={jQuery:!0}})(); +define("almond",function(){}); +define("orion/editor/shim",[],function(){if(!Object.create)Object.create=function(k,m){function n(){}n.prototype=k;var i=new n;if(m)for(var c in m)m.hasOwnProperty(c)&&(i[c]=m[c].hasOwnProperty("value")?m[c].value:function(){if(arguments.length>0)return m[c].get();else m[c].set(arguments)});return i};if(!Object.keys)Object.keys=function(k){var m=[],n;for(n in k)k.hasOwnProperty(n)&&m.push(n);return m};if(!Function.prototype.bind)Function.prototype.bind=function(k){var m=this,n=Array.prototype.slice.call(arguments, +1);return n.length?function(){return arguments.length?m.apply(k,n.concat(Array.prototype.slice.call(arguments))):m.apply(k,n)}:function(){return arguments.length?m.apply(k,arguments):m.call(k)}};if(!Array.isArray)Array.isArray=function(k){return Object.prototype.toString.call(k)==="[object Array]"};if(!Array.prototype.indexOf)Array.prototype.indexOf=function(k){for(var m=0;m<this.length;m++)if(this[m]===k)return m;return-1};if(!Array.prototype.forEach)Array.prototype.forEach=function(k){for(var m= +0;m<this.length;m++)k(this[m],m)};if(!Array.prototype.map)Array.prototype.map=function(k){for(var m=Array(this.length),n=0;n<this.length;n++)m[n]=k(this[n]);return m};if(!Array.prototype.reduce)Array.prototype.reduce=function(k,m){var n,i=!1;1<arguments.length&&(n=m,i=!0);for(var c=0;this.length>c;++c)i?n=k(n,this[c],c,this):(n=this[c],i=!0);return n};if(!String.prototype.trim)String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,"")};if(!String.prototype.trimLeft)String.prototype.trimLeft= +function(){return this.replace(/^\s+/g,"")};if(!String.prototype.trimRight)String.prototype.trimRight=function(){return this.replace(/\s+$/g,"")};return{}}); +(function(){function k(c,d,f,g,h,b){d[c]&&(f.push(c),(d[c]===!0||d[c]===1)&&g.push(h+c+"/"+b))}function m(c,d,f,g,h){d=g+d+"/"+h;require._fileExists(c.toUrl(d+".js"))&&f.push(d)}function n(c,d,f){for(var g in d)d.hasOwnProperty(g)&&(!c.hasOwnProperty(g)||f)?c[g]=d[g]:typeof d[g]==="object"&&n(c[g],d[g],f)}var i=/(^.*(^|\/)nls(\/|$))([^\/]*)\/?([^\/]*)/;define("i18n",["module"],function(c){var d=c.config?c.config():{};return{version:"2.0.1+",load:function(f,c,h,b){b=b||{};if(b.locale)d.locale=b.locale; +var a=i.exec(f),e=a[1],l=a[4],o=a[5],q=l.split("-"),r=[],p={},t,v="";if(a[5])e=a[1],f=e+o;else{o=a[4];l=d.locale;if(!l)l=d.locale=typeof navigator==="undefined"?"root":(navigator.language||navigator.userLanguage||"root").toLowerCase();q=l.split("-")}if(b.isBuild){r.push(f);m(c,"root",r,e,o);for(t=0;t<q.length;t++)b=q[t],v+=(v?"-":"")+b,m(c,v,r,e,o);c(r,function(){h()})}else c([f],function(a){var b=[],j;k("root",a,b,r,e,o);for(t=0;t<q.length;t++)j=q[t],v+=(v?"-":"")+j,k(v,a,b,r,e,o);c(r,function(){var j, +x,f;for(j=b.length-1;j>-1&&b[j];j--){f=b[j];x=a[f];if(x===!0||x===1)x=c(e+f+"/"+o);n(p,x)}h(p)})})}}})})();define("orion/editor/i18n",{load:function(k,m,n){m.specified&&m.specified("orion/bootstrap")?m(["orion/i18n!"+k],function(i){n(i)}):n({})}}); +define("orion/editor/nls/root/messages",{multipleAnnotations:"Multiple annotations:",line:"Line: ${0}",breakpoint:"Breakpoint",bookmark:"Bookmark",task:"Task",error:"Error",warning:"Warning",matchingSearch:"Matching Search",currentSearch:"Current Search",currentLine:"Current Line",matchingBracket:"Matching Bracket",currentBracket:"Current Bracket",lineUp:"Line Up",lineDown:"Line Down",lineStart:"Line Start",lineEnd:"Line End",charPrevious:"Previous Character",charNext:"Next Character",pageUp:"Page Up", +pageDown:"Page Down",scrollPageUp:"Scroll Page Up",scrollPageDown:"Scroll Page Down",scrollLineUp:"Scroll Line Up",scrollLineDown:"Scroll Line Down",wordPrevious:"Previous Word",wordNext:"Next Word",textStart:"Document Start",textEnd:"Document End",scrollTextStart:"Scroll Document Start",scrollTextEnd:"Scroll Document End",centerLine:"Center Line",selectLineUp:"Select Line Up",selectLineDown:"Select Line Down",selectWholeLineUp:" Select Whole Line Up",selectWholeLineDown:"Select Whole Line Down", +selectLineStart:"Select Line Start",selectLineEnd:"Select Line End",selectCharPrevious:"Select Previous Character",selectCharNext:"Select Next Character",selectPageUp:"Select Page Up",selectPageDown:"Select Page Down",selectWordPrevious:"Select Previous Word",selectWordNext:"Select Next Word",selectTextStart:"Select Document Start",selectTextEnd:"Select Document End",deletePrevious:"Delete Previous Character",deleteNext:"Delete Next Character",deleteWordPrevious:"Delete Previous Word",deleteWordNext:"Delete Next Word", +deleteLineStart:"Delete Line Start",deleteLineEnd:"Delete Line End",tab:"Insert Tab",enter:"Insert Line Delimiter",enterNoCursor:"Insert Line Delimiter",selectAll:"Select All",copy:"Copy",cut:"Cut",paste:"Paste",uppercase:"To Upper Case",lowercase:"To Lower Case",capitalize:"Capitalize",reversecase:"Reverse Case",toggleWrapMode:"Toggle Wrap Mode",toggleTabMode:"Toggle Tab Mode",toggleOverwriteMode:"Toggle Overwrite Mode",committerOnTime:"${0} on ${1}",emacs:"Emacs",exchangeMarkPoint:"Exchange Mark and Point", +setMarkCommand:"Set Mark",clearMark:"Clear Mark",digitArgument:"Digit Argument ${0}",negativeArgument:"Negative Argument",Comment:"Comment","Flat outline":"Flat outline",incrementalFindStr:"Incremental find: ${0}",incrementalFindStrNotFound:"Incremental find: ${0} (not found)",incrementalFindReverseStr:"Reverse Incremental find: ${0}",incrementalFindReverseStrNotFound:"Reverse Incremental find: ${0} (not found)",find:"Find...",undo:"Undo",redo:"Redo",cancelMode:"Cancel Current Mode",findNext:"Find Next Occurrence", +findPrevious:"Find Previous Occurrence",incrementalFind:"Incremental Find",incrementalFindReverse:"Incremental Find Reverse",indentLines:"Indent Lines",unindentLines:"Unindent Lines",moveLinesUp:"Move Lines Up",moveLinesDown:"Move Lines Down",copyLinesUp:"Copy Lines Up",copyLinesDown:"Copy Lines Down",deleteLines:"Delete Lines",gotoLine:"Goto Line...",gotoLinePrompty:"Goto Line:",nextAnnotation:"Next Annotation",prevAnnotation:"Previous Annotation",expand:"Expand",collapse:"Collapse",expandAll:"Expand All", +collapseAll:"Collapse All",lastEdit:"Last Edit Location",trimTrailingWhitespaces:"Trim Trailing Whitespaces",toggleLineComment:"Toggle Line Comment",addBlockComment:"Add Block Comment",removeBlockComment:"Remove Block Comment",linkedModeEntered:"Linked Mode entered",linkedModeExited:"Linked Mode exited",syntaxError:"Syntax Error",contentAssist:"Content Assist",lineColumn:"Line ${0} : Col ${1}",vi:"vi",vimove:"(Move)",viyank:"(Yank)",videlete:"(Delete)",vichange:"(Change)",viLeft:"${0} Left",viRight:"${0} Right", +viUp:"${0} Up",viDown:"${0} Down",viw:"${0} Next Word",vib:"${0} Beginning of Word",viW:"${0} Next Word (ws stop)",viB:"${0} Beginning of Word (ws stop)",vie:"${0} End of Word",viE:"${0} End of Word (ws stop)",vi$:"${0} End of the line","vi^_":"${0} First non-blank Char Current Line","vi+":"${0} First Char Next Line","vi-":"${0} First Char Previous Line","vi|":"${0} nth Column in Line",viH:"${0} Top of Page",viM:"${0} Middle of Page",viL:"${0} Bottom of Page","vi/":"${0} Search Forward","vi?":"${0} Search Backward", +vin:"${0} Next Search",viN:"${0} Previous Search",vif:"${0} Search Char Fwd",viF:"${0} Search Char Bckwd",vit:"${0} Search Before Char Fwd",viT:"${0} Search Before Char Bckwd","vi,":"${0} Repeat Reverse Char Search","vi;":"${0} Repeat Char Search",viG:"${0} Go to Line",viycd:"${0} Current Line",via:"Append After Cursor",viA:"Append to End of Line",vii:"Insert Before Cursor",viI:"Insert at Beginning of Line",viO:"Insert Line Above",vio:"Insert Line Below",viR:"Begin Overwriting Text",vis:"Substitute a Character", +viS:"Substitute Entire Line",viC:"Change Text Until Line End",vip:"Paste After Char or Line",viP:"Paste Before Char or Line",viStar:"Search Word Under Cursor",replaceAll:"Replacing all...",replacedMatches:"Replaced ${0} matches",nothingReplaced:"Nothing replaced",notFound:"Not found"}); +define("orion/editor/nls/messages",["orion/editor/i18n!orion/editor/nls/messages","orion/editor/nls/root/messages"],function(k,m){var n={root:m},i;for(i in k)k.hasOwnProperty(i)&&typeof n[i]==="undefined"&&(n[i]=k[i]);return n}); +define("orion/editor/eventTarget",[],function(){function k(){}k.addMixin=function(m){var n=k.prototype,i;for(i in n)n.hasOwnProperty(i)&&(m[i]=n[i])};k.prototype={addEventListener:function(k,n,i){if(!this._eventTypes)this._eventTypes={};var c=this._eventTypes[k];c||(c=this._eventTypes[k]={level:0,listeners:[]});c.listeners.push({listener:n,useCapture:i})},dispatchEvent:function(k){var n=k.type;this._dispatchEvent("pre"+n,k);this._dispatchEvent(n,k);this._dispatchEvent("post"+n,k)},_dispatchEvent:function(k, +n){var i=this._eventTypes?this._eventTypes[k]:null;if(i){var c=i.listeners;try{if(i.level++,c)for(var d=0,f=c.length;d<f;d++)if(c[d]){var g=c[d].listener;typeof g==="function"?g.call(this,n):g.handleEvent&&typeof g.handleEvent==="function"&&g.handleEvent(n)}}finally{if(i.level--,i.compact&&i.level===0){for(d=c.length-1;d>=0;d--)c[d]||c.splice(d,1);c.length===0&&delete this._eventTypes[k];i.compact=!1}}}},isListening:function(k){return!this._eventTypes?!1:this._eventTypes[k]!==void 0},removeEventListener:function(k, +n,i){if(this._eventTypes){var c=this._eventTypes[k];if(c){for(var d=c.listeners,f=0,g=d.length;f<g;f++){var h=d[f];if(h&&h.listener===n&&h.useCapture===i){c.level!==0?(d[f]=null,c.compact=!0):d.splice(f,1);break}}d.length===0&&delete this._eventTypes[k]}}}};return{EventTarget:k}});define("orion/regex",[],function(){return{escape:function(k){return k.replace(/([\\$\^*\/+?\.\(\)|{}\[\]])/g,"\\$&")},parse:function(k){return(k=/^\s*\/(.+)\/([gim]{0,3})\s*$/.exec(k))?{pattern:k[1],flags:k[2]}:null}}}); +define("orion/util",[],function(){var k=navigator.userAgent,m=k.indexOf("MSIE")!==-1||k.indexOf("Trident")!==-1?document.documentMode:void 0,n=parseFloat(k.split("Firefox/")[1]||k.split("Minefield/")[1])||void 0,i=k.indexOf("Opera")!==-1?parseFloat(k.split("Version/")[1]):void 0,c=parseFloat(k.split("Chrome/")[1])||void 0,d=k.indexOf("Safari")!==-1&&!c,f=parseFloat(k.split("WebKit/")[1])||void 0,g=k.indexOf("Android")!==-1,h=k.indexOf("iPad")!==-1,k=k.indexOf("iPhone")!==-1,b=h||k,a=navigator.platform.indexOf("Mac")!== +-1,e=navigator.platform.indexOf("Win")!==-1,l=navigator.platform.indexOf("Linux")!==-1;return{formatMessage:function(a){var b=arguments;return a.replace(/\$\{([^\}]+)\}/g,function(a,e){return b[(e<<0)+1]})},createElement:function(a,b){return a.createElementNS?a.createElementNS("http://www.w3.org/1999/xhtml",b):a.createElement(b)},isIE:m,isFirefox:n,isOpera:i,isChrome:c,isSafari:d,isWebkit:f,isAndroid:g,isIPad:h,isIPhone:k,isIOS:b,isMac:a,isWindows:e,isLinux:l,platformDelimiter:e?"\r\n":"\n"}}); +define("orion/editor/textModel",["orion/editor/eventTarget","orion/regex","orion/util"],function(k,m,n){function i(c,d){this._lastLineIndex=-1;this._text=[""];this._lineOffsets=[0];this.setText(c);this.setLineDelimiter(d)}i.prototype={destroy:function(){},find:function(c){if(this._text.length>1)this._text=[this._text.join("")];var d=c.string,f=c.regex,g=d,h="",b=c.caseInsensitive;if(g)if(f){if(d=m.parse(g))g=d.pattern,h=d.flags}else g=d.replace(/([\\$\^*\/+?\.\(\)|{}\[\]])/g,"\\$&"),b&&(g=g.replace(/[iI\u0130\u0131]/g, +"[Ii\u0130\u0131]"));var a=null,e;if(g){var d=c.reverse,l=c.wrap,f=c.wholeWord,o=c.start||0,c=c.end,q=c!==null&&c!==void 0;h.indexOf("g")===-1&&(h+="g");h.indexOf("m")===-1&&(h+="m");b&&h.indexOf("i")===-1&&(h+="i");f&&(g="\\b"+g+"\\b");var i=this._text[0],p,t,v=0;q&&(b=o<c?o:c,i=i.substring(b,o<c?c:o),v=b);var s=RegExp(g,h);if(d)e=function(){var a=null;for(s.lastIndex=0;;){t=s.lastIndex;p=s.exec(i);if(t===s.lastIndex)return null;if(p){if(!(p.index+v<o)){if(!l||a)break;o=i.length+v}a={start:p.index+ +v,end:s.lastIndex+v}}else break}if(a)o=a.start;return a};else{if(!q)s.lastIndex=o;e=function(){for(;;){t=s.lastIndex;p=s.exec(i);if(t===s.lastIndex)break;if(p)return{start:p.index+v,end:s.lastIndex+v};if(!(t!==0&&l))break}return null}}a=e()}return{next:function(){var b=a;b&&(a=e());return b},hasNext:function(){return a!==null}}},getCharCount:function(){for(var c=0,d=0;d<this._text.length;d++)c+=this._text[d].length;return c},getLine:function(c,d){var f=this.getLineCount();if(!(0<=c&&c<f))return null; +var g=this._lineOffsets[c];if(c+1<f){f=this.getText(g,this._lineOffsets[c+1]);if(d)return f;for(var g=f.length,h;(h=f.charCodeAt(g-1))===10||h===13;)g--;return f.substring(0,g)}else return this.getText(g)},getLineAtOffset:function(c){var d=this.getCharCount();if(!(0<=c&&c<=d))return-1;var f=this.getLineCount();if(c===d)return f-1;var g,h,b=this._lastLineIndex;if(0<=b&&b<f&&(g=this._lineOffsets[b],h=b+1<f?this._lineOffsets[b+1]:d,g<=c&&c<h))return b;for(var a=f,e=-1;a-e>1;)if(b=Math.floor((a+e)/2), +g=this._lineOffsets[b],h=b+1<f?this._lineOffsets[b+1]:d,c<=g)a=b;else if(c<h){a=b;break}else e=b;return this._lastLineIndex=a},getLineCount:function(){return this._lineOffsets.length},getLineDelimiter:function(){return this._lineDelimiter},getLineEnd:function(c,d){var f=this.getLineCount();if(!(0<=c&&c<f))return-1;if(c+1<f){f=this._lineOffsets[c+1];if(d)return f;for(var g=this.getText(Math.max(this._lineOffsets[c],f-2),f),h=g.length,b;(b=g.charCodeAt(h-1))===10||b===13;)h--;return f-(g.length-h)}else return this.getCharCount()}, +getLineStart:function(c){return!(0<=c&&c<this.getLineCount())?-1:this._lineOffsets[c]},getText:function(c,d){c===void 0&&(c=0);d===void 0&&(d=this.getCharCount());if(c===d)return"";for(var f=0,g=0,h;g<this._text.length;){h=this._text[g].length;if(c<=f+h)break;f+=h;g++}for(var b=f,a=g;g<this._text.length;){h=this._text[g].length;if(d<=f+h)break;f+=h;g++}if(a===g)return this._text[a].substring(c-b,d-f);b=this._text[a].substring(c-b);f=this._text[g].substring(0,d-f);return b+this._text.slice(a+1,g).join("")+ +f},onChanging:function(c){return this.dispatchEvent(c)},onChanged:function(c){return this.dispatchEvent(c)},setLineDelimiter:function(c,d){c==="auto"&&(c=void 0,this.getLineCount()>1&&(c=this.getText(this.getLineEnd(0),this.getLineEnd(0,!0))));this._lineDelimiter=c?c:n.platformDelimiter;if(d){var f=this.getLineCount();if(f>1){for(var g=Array(f),h=0;h<f;h++)g[h]=this.getLine(h);this.setText(g.join(this._lineDelimiter))}}},setText:function(c,d,f){c===void 0&&(c="");d===void 0&&(d=0);f===void 0&&(f= +this.getCharCount());if(!(d===f&&c==="")){for(var g=this.getLineAtOffset(d),h=this.getLineAtOffset(f),b=d,a=f-d,e=h-g,l=c.length,o=0,i=this.getLineCount(),r=0,p=0,t=0,v=[];;){r!==-1&&r<=t&&(r=c.indexOf("\r",t));p!==-1&&p<=t&&(p=c.indexOf("\n",t));if(p===-1&&r===-1)break;t=r!==-1&&p!==-1?r+1===p?p+1:(r<p?r:p)+1:r!==-1?r+1:p+1;v.push(d+t);o++}this.onChanging({type:"Changing",text:c,start:b,removedCharCount:a,addedCharCount:l,removedLineCount:e,addedLineCount:o});v.length===0&&(t=this.getLineStart(g), +h=h+1<i?this.getLineStart(h+1):this.getCharCount(),d!==t&&(c=this.getText(t,d)+c,d=t),f!==h&&(c+=this.getText(f,h),f=h));t=l-a;for(h=g+e+1;h<i;h++)this._lineOffsets[h]+=t;if(v.length<5E4)g=[g+1,e].concat(v),Array.prototype.splice.apply(this._lineOffsets,g);else{t=g+1;this._lineOffsets.splice(t,e);for(i=0;i<v.length;i+=5E4)g=[t,0].concat(v.slice(i,Math.min(v.length,i+5E4))),Array.prototype.splice.apply(this._lineOffsets,g),t+=5E4}for(t=i=0;t<this._text.length;){h=this._text[t].length;if(d<=i+h)break; +i+=h;t++}g=i;for(v=t;t<this._text.length;){h=this._text[t].length;if(f<=i+h)break;i+=h;t++}h=this._text[t];d=this._text[v].substring(0,d-g);f=h.substring(f-i);v=[v,t-v+1];d&&v.push(d);c&&v.push(c);f&&v.push(f);Array.prototype.splice.apply(this._text,v);if(this._text.length===0)this._text=[""];this.onChanged({type:"Changed",start:b,removedCharCount:a,addedCharCount:l,removedLineCount:e,addedLineCount:o})}}};k.EventTarget.addMixin(i.prototype);return{TextModel:i}}); +define("orion/keyBinding",["orion/util"],function(k){function m(i,c,d,f,g,h){this.type=h||"keydown";this.keyCode=typeof i==="string"&&this.type==="keydown"?i.toUpperCase().charCodeAt(0):i;this.mod1=c!==void 0&&c!==null?c:!1;this.mod2=d!==void 0&&d!==null?d:!1;this.mod3=f!==void 0&&f!==null?f:!1;this.mod4=g!==void 0&&g!==null?g:!1}function n(i){this.keys=i}m.prototype={getKeys:function(){return[this]},match:function(i,c){if(c!==void 0){if(c!==0)return!1}else if(i instanceof Array){if(i.length>1)return!1; +i=i[0]}return i.type!==this.type?!1:this.keyCode===i.keyCode||this.keyCode===String.fromCharCode(k.isOpera?i.which:i.charCode!==void 0?i.charCode:i.keyCode)?this.mod1!==(k.isMac?i.metaKey:i.ctrlKey)?!1:this.type==="keydown"&&this.mod2!==i.shiftKey?!1:this.mod3!==i.altKey?!1:k.isMac&&this.mod4!==i.ctrlKey?!1:!0:!1},equals:function(i){return!i?!1:this.keyCode!==i.keyCode?!1:this.mod1!==i.mod1?!1:this.mod2!==i.mod2?!1:this.mod3!==i.mod3?!1:this.mod4!==i.mod4?!1:this.type!==i.type?!1:!0}};n.prototype= +{getKeys:function(){return this.keys.slice(0)},match:function(i,c){var d=this.keys;if(c!==void 0)return c>d.length?!1:d[c].match(i)?c===d.length-1?!0:c+1:!1;else{i instanceof Array||(i=[i]);if(i.length>d.length)return!1;var f;for(f=0;f<i.length;f++)if(!d[f].match(i[f]))return!1;return f===d.length?!0:f}},equals:function(i){if(!i.keys)return!1;if(i.keys.length!==this.keys.length)return!1;for(var c=0;c<i.keys.length;c++)if(!i.keys[c].equals(this.keys[c]))return!1;return!0}};return{KeyBinding:m,KeyStroke:m, +KeySequence:n}}); +define("orion/editor/keyModes",["orion/keyBinding","orion/util"],function(k,m){function n(c){if(c)this._view=c,this._keyBindings=this.createKeyBindings(),this._keyBindingIndex=0}function i(c){n.call(this,c)}n.prototype={createKeyBindings:function(){return[]},getKeyBindings:function(c){for(var d=[],f=this._keyBindings,g=0;g<f.length;g++)f[g].actionID===c&&d.push(f[g].keyBinding);return d},getView:function(){return this._view},isActive:function(){return this._view.getKeyModes().indexOf(this)!==-1}, +match:function(c){if(c.type==="keydown")switch(c.keyCode){case 16:case 17:case 18:case 91:return}for(var d=this._keyBindingIndex,f=this._matchingKeyBindings||this._keyBindings,g=[],h=0;h<f.length;h++){var b=f[h],a=b.keyBinding.match(c,d);if(a===!0)return this._keyBindingIndex=0,this._matchingKeyBindings=null,b.actionID;else typeof a==="number"&&g.push(b)}if(g.length===0)this._keyBindingIndex=0,this._matchingKeyBindings=null;else return this._keyBindingIndex++,this._matchingKeyBindings=g,"noop"},setKeyBinding:function(c, +d){for(var f=this._keyBindings,g=0;g<f.length;g++){var h=f[g];if(h.keyBinding.equals(c)){d?h.actionID=d:h.predefined?h.actionID="noop":f.splice(g,1);return}}d&&f.push({keyBinding:c,actionID:d})},setView:function(c){this._view=c}};i.prototype=new n;i.prototype.createKeyBindings=function(){var c=k.KeyBinding,d=[];d.push({actionID:"lineUp",keyBinding:new c(38),predefined:!0});d.push({actionID:"lineDown",keyBinding:new c(40),predefined:!0});d.push({actionID:"charPrevious",keyBinding:new c(37),predefined:!0}); +d.push({actionID:"charNext",keyBinding:new c(39),predefined:!0});m.isMac?(d.push({actionID:"scrollPageUp",keyBinding:new c(33),predefined:!0}),d.push({actionID:"scrollPageDown",keyBinding:new c(34),predefined:!0}),d.push({actionID:"pageUp",keyBinding:new c(33,null,null,!0),predefined:!0}),d.push({actionID:"pageDown",keyBinding:new c(34,null,null,!0),predefined:!0}),d.push({actionID:"lineStart",keyBinding:new c(37,!0),predefined:!0}),d.push({actionID:"lineEnd",keyBinding:new c(39,!0),predefined:!0}), +d.push({actionID:"wordPrevious",keyBinding:new c(37,null,null,!0),predefined:!0}),d.push({actionID:"wordNext",keyBinding:new c(39,null,null,!0),predefined:!0}),d.push({actionID:"scrollTextStart",keyBinding:new c(36),predefined:!0}),d.push({actionID:"scrollTextEnd",keyBinding:new c(35),predefined:!0}),d.push({actionID:"textStart",keyBinding:new c(38,!0),predefined:!0}),d.push({actionID:"textEnd",keyBinding:new c(40,!0),predefined:!0}),d.push({actionID:"scrollPageUp",keyBinding:new c(38,null,null,null, +!0),predefined:!0}),d.push({actionID:"scrollPageDown",keyBinding:new c(40,null,null,null,!0),predefined:!0}),d.push({actionID:"lineStart",keyBinding:new c(37,null,null,null,!0),predefined:!0}),d.push({actionID:"lineEnd",keyBinding:new c(39,null,null,null,!0),predefined:!0}),d.push({actionID:"lineStart",keyBinding:new c(38,null,null,!0),predefined:!0}),d.push({actionID:"lineEnd",keyBinding:new c(40,null,null,!0),predefined:!0})):(d.push({actionID:"pageUp",keyBinding:new c(33),predefined:!0}),d.push({actionID:"pageDown", +keyBinding:new c(34),predefined:!0}),d.push({actionID:"lineStart",keyBinding:new c(36),predefined:!0}),d.push({actionID:"lineEnd",keyBinding:new c(35),predefined:!0}),d.push({actionID:"wordPrevious",keyBinding:new c(37,!0),predefined:!0}),d.push({actionID:"wordNext",keyBinding:new c(39,!0),predefined:!0}),d.push({actionID:"textStart",keyBinding:new c(36,!0),predefined:!0}),d.push({actionID:"textEnd",keyBinding:new c(35,!0),predefined:!0}));m.isFirefox&&m.isLinux&&(d.push({actionID:"lineUp",keyBinding:new c(38, +!0),predefined:!0}),d.push({actionID:"lineDown",keyBinding:new c(40,!0),predefined:!0}));m.isWindows&&(d.push({actionID:"scrollLineUp",keyBinding:new c(38,!0),predefined:!0}),d.push({actionID:"scrollLineDown",keyBinding:new c(40,!0),predefined:!0}));d.push({actionID:"selectLineUp",keyBinding:new c(38,null,!0),predefined:!0});d.push({actionID:"selectLineDown",keyBinding:new c(40,null,!0),predefined:!0});d.push({actionID:"selectCharPrevious",keyBinding:new c(37,null,!0),predefined:!0});d.push({actionID:"selectCharNext", +keyBinding:new c(39,null,!0),predefined:!0});d.push({actionID:"selectPageUp",keyBinding:new c(33,null,!0),predefined:!0});d.push({actionID:"selectPageDown",keyBinding:new c(34,null,!0),predefined:!0});m.isMac?(d.push({actionID:"selectLineStart",keyBinding:new c(37,!0,!0),predefined:!0}),d.push({actionID:"selectLineEnd",keyBinding:new c(39,!0,!0),predefined:!0}),d.push({actionID:"selectWordPrevious",keyBinding:new c(37,null,!0,!0),predefined:!0}),d.push({actionID:"selectWordNext",keyBinding:new c(39, +null,!0,!0),predefined:!0}),d.push({actionID:"selectTextStart",keyBinding:new c(36,null,!0),predefined:!0}),d.push({actionID:"selectTextEnd",keyBinding:new c(35,null,!0),predefined:!0}),d.push({actionID:"selectTextStart",keyBinding:new c(38,!0,!0),predefined:!0}),d.push({actionID:"selectTextEnd",keyBinding:new c(40,!0,!0),predefined:!0}),d.push({actionID:"selectLineStart",keyBinding:new c(37,null,!0,null,!0),predefined:!0}),d.push({actionID:"selectLineEnd",keyBinding:new c(39,null,!0,null,!0),predefined:!0}), +d.push({actionID:"selectLineStart",keyBinding:new c(38,null,!0,!0),predefined:!0}),d.push({actionID:"selectLineEnd",keyBinding:new c(40,null,!0,!0),predefined:!0})):(m.isLinux&&(d.push({actionID:"selectWholeLineUp",keyBinding:new c(38,!0,!0),predefined:!0}),d.push({actionID:"selectWholeLineDown",keyBinding:new c(40,!0,!0),predefined:!0})),d.push({actionID:"selectLineStart",keyBinding:new c(36,null,!0),predefined:!0}),d.push({actionID:"selectLineEnd",keyBinding:new c(35,null,!0),predefined:!0}),d.push({actionID:"selectWordPrevious", +keyBinding:new c(37,!0,!0),predefined:!0}),d.push({actionID:"selectWordNext",keyBinding:new c(39,!0,!0),predefined:!0}),d.push({actionID:"selectTextStart",keyBinding:new c(36,!0,!0),predefined:!0}),d.push({actionID:"selectTextEnd",keyBinding:new c(35,!0,!0),predefined:!0}));d.push({actionID:"undo",keyBinding:new k.KeyBinding("z",!0),predefined:!0});m.isMac?d.push({actionID:"redo",keyBinding:new k.KeyBinding("z",!0,!0),predefined:!0}):d.push({actionID:"redo",keyBinding:new k.KeyBinding("y",!0),predefined:!0}); +d.push({actionID:"deletePrevious",keyBinding:new c(8),predefined:!0});d.push({actionID:"deletePrevious",keyBinding:new c(8,null,!0),predefined:!0});d.push({actionID:"deleteNext",keyBinding:new c(46),predefined:!0});d.push({actionID:"deleteWordPrevious",keyBinding:new c(8,!0),predefined:!0});d.push({actionID:"deleteWordPrevious",keyBinding:new c(8,!0,!0),predefined:!0});d.push({actionID:"deleteWordNext",keyBinding:new c(46,!0),predefined:!0});d.push({actionID:"tab",keyBinding:new c(9),predefined:!0}); +d.push({actionID:"shiftTab",keyBinding:new c(9,null,!0),predefined:!0});d.push({actionID:"enter",keyBinding:new c(13),predefined:!0});d.push({actionID:"enter",keyBinding:new c(13,null,!0),predefined:!0});d.push({actionID:"selectAll",keyBinding:new c("a",!0),predefined:!0});d.push({actionID:"toggleTabMode",keyBinding:new c("m",!0),predefined:!0});m.isMac&&(d.push({actionID:"deleteNext",keyBinding:new c(46,null,!0),predefined:!0}),d.push({actionID:"deleteWordPrevious",keyBinding:new c(8,null,null,!0), +predefined:!0}),d.push({actionID:"deleteWordNext",keyBinding:new c(46,null,null,!0),predefined:!0}));d.push({actionID:"toggleWrapMode",keyBinding:new k.KeyBinding("w",!0,!1,!0)});d.push({actionID:"toggleOverwriteMode",keyBinding:new k.KeyBinding(45)});if(!m.isFirefox){var f=m.isMac&&m.isChrome;d.push({actionID:"noop",keyBinding:new c("u",!f,!1,!1,f),predefined:!0});d.push({actionID:"noop",keyBinding:new c("i",!f,!1,!1,f),predefined:!0});d.push({actionID:"noop",keyBinding:new c("b",!f,!1,!1,f),predefined:!0})}m.isFirefox&& +(d.push({actionID:"copy",keyBinding:new c(45,!0),predefined:!0}),d.push({actionID:"paste",keyBinding:new c(45,null,!0),predefined:!0}),d.push({actionID:"cut",keyBinding:new c(46,null,!0),predefined:!0}));m.isMac&&(d.push({actionID:"lineStart",keyBinding:new c("a",!1,!1,!1,!0),predefined:!0}),d.push({actionID:"lineEnd",keyBinding:new c("e",!1,!1,!1,!0),predefined:!0}),d.push({actionID:"lineUp",keyBinding:new c("p",!1,!1,!1,!0),predefined:!0}),d.push({actionID:"lineDown",keyBinding:new c("n",!1,!1, +!1,!0),predefined:!0}),d.push({actionID:"charPrevious",keyBinding:new c("b",!1,!1,!1,!0),predefined:!0}),d.push({actionID:"charNext",keyBinding:new c("f",!1,!1,!1,!0),predefined:!0}),d.push({actionID:"deletePrevious",keyBinding:new c("h",!1,!1,!1,!0),predefined:!0}),d.push({actionID:"deleteNext",keyBinding:new c("d",!1,!1,!1,!0),predefined:!0}),d.push({actionID:"deleteLineEnd",keyBinding:new c("k",!1,!1,!1,!0),predefined:!0}),m.isFirefox?(d.push({actionID:"scrollPageDown",keyBinding:new c("v",!1, +!1,!1,!0),predefined:!0}),d.push({actionID:"deleteLineStart",keyBinding:new c("u",!1,!1,!1,!0),predefined:!0}),d.push({actionID:"deleteWordPrevious",keyBinding:new c("w",!1,!1,!1,!0),predefined:!0})):(d.push({actionID:"pageDown",keyBinding:new c("v",!1,!1,!1,!0),predefined:!0}),d.push({actionID:"centerLine",keyBinding:new c("l",!1,!1,!1,!0),predefined:!0}),d.push({actionID:"enterNoCursor",keyBinding:new c("o",!1,!1,!1,!0),predefined:!0})));return d};return{KeyMode:n,DefaultKeyMode:i}}); +define("orion/editor/textTheme",["require","orion/editor/eventTarget","orion/util"],function(k,m,n){function i(c){c=c||{};this._document=c.document||document}var c={};i.getTheme=function(d){var d=d||"default",f=c[d];f||(f=c[d]=new i);return f};i.prototype={getThemeClass:function(){return this._themeClass},setThemeClass:function(c,f){var g=this,h=g._themeClass;g._themeClass=c;this._load(c,f,function(){g.onThemeChanged({type:"ThemeChanged",oldValue:h,newValue:g.getThemeClass()})})},onThemeChanged:function(c){return this.dispatchEvent(c)}, +buildStyleSheet:function(c,f){function g(b,a,e){a&&(h.push("."+c+" ."+b+" {"),h.push("\t"+(e?"background-color":"color")+": "+a+";"),h.push("}"))}var h=[];h.push("");h.push("."+c+" {");f.fontFamily&&h.push("\tfont-family: "+f.fontFamily+";");f.fontSize&&h.push("\tfont-size: "+f.fontSize+";");f.fontSize&&h.push("\tcolor: "+f.text+";");h.push("}");h.push("."+c+".textview {");f.background&&h.push("\tbackground-color: "+f.background+";");h.push("}");g("ruler.annotations",f.annotationRuler,!0);g("ruler.lines", +f.annotationRuler,!0);g("ruler.folding",f.annotationRuler,!0);g("ruler.overview",f.overviewRuler,!0);g("rulerLines",f.lineNumber,!1);g("rulerLines.even",f.lineNumberEven,!1);g("rulerLines.odd",f.lineNumberOdd,!1);g("annotationLine.currentLine",f.currentLine,!0);g("entity-name-tag",f.keyword,!1);g("entity-other-attribute-name",f.attribute,!1);g("string-quoted",f.string,!1);g("meta.annotation.currentLine",f.currentLine,!0);g("keyword",f.keyword,!1);g("string",f.string,!1);g("comment",f.comment,!1); +g("comment.block.documentation",f.comment,!1);g("keyword.other.documentation.markup",f.comment,!1);return h.join("\n")},_createStyle:function(c,f,g,h){var b=this._document,c="orion-theme-"+c,a=b.getElementById(c);if(a){if(h||a.firstChild.data===f)return;a.removeChild(a.firstChild);a.appendChild(b.createTextNode(f))}else h?(a=n.createElement(b,"link"),a.rel="stylesheet",a.type="text/css",a.href=f,a.addEventListener("load",function(){g()})):(a=n.createElement(b,"style"),a.appendChild(b.createTextNode(f))), +a.id=c,(b.getElementsByTagName("head")[0]||b.documentElement).appendChild(a);h||g()},_load:function(c,f,g){if(c)if(typeof f==="string")this._createStyle(c,f,g);else if(f=f.href,f.substring(f.length-4)!==".css"&&(f+=".css"),/^\//.test(f)||/[a-zA-Z0-9]+:\/\//i.test(f)||!k.toUrl)this._createStyle(c,f,g,!0);else{var h=this;k(["text!"+f],function(b){h._createStyle(c,b,g,!1)})}else g()}};m.EventTarget.addMixin(i.prototype);return{TextTheme:i}}); +define("orion/editor/util",[],function(){return{contains:function(k,m){if(!m)return!1;if(!k.compareDocumentPosition){for(var n=m;n;){if(k===n)return!0;n=n.parentNode}return!1}return k===m||(k.compareDocumentPosition(m)&16)!==0},addEventListener:function(k,m,n,i){typeof k.addEventListener==="function"?k.addEventListener(m,n,i===!0):k.attachEvent("on"+m,n)},removeEventListener:function(k,m,n,i){typeof k.removeEventListener==="function"?k.removeEventListener(m,n,i===!0):k.detachEvent("on"+m,n)}}}); +define("orion/editor/textView","i18n!orion/editor/nls/messages,orion/editor/textModel,orion/editor/keyModes,orion/editor/eventTarget,orion/editor/textTheme,orion/editor/util,orion/util".split(","),function(k,m,n,i,c,d,f){function g(j,a,b){if(b){a.className="";for(var b=a.attributes,e=b.length;e-- >0;)(!f.isIE||f.isIE>=9||f.isIE<9&&b[e].specified)&&a.removeAttribute(b[e].name)}if(j){if(j.styleClass)a.className=j.styleClass;if(b=j.style)for(var c in b)b.hasOwnProperty(c)&&(a.style[c]=b[c]);if(j=j.attributes)for(var l in j)j.hasOwnProperty(l)&& +a.setAttribute(l,j[l])}}function h(j){return j instanceof Array?j.slice(0):j}function b(j,a){if(!j)return a;if(!a)return j;for(var b in a)a.hasOwnProperty(b)&&(j.hasOwnProperty(b)||(j[b]=a[b]));return j}function a(j,w){if(j===w)return!0;if(j&&!w||!j&&w)return!1;if(j&&j.constructor===String||w&&w.constructor===String)return!1;if(j instanceof Array||w instanceof Array){if(!(j instanceof Array&&w instanceof Array))return!1;if(j.length!==w.length)return!1;for(var b=0;b<j.length;b++)if(!a(j[b],w[b]))return!1; +return!0}if(!(j instanceof Object)||!(w instanceof Object))return!1;for(b in j)if(j.hasOwnProperty(b)){if(!w.hasOwnProperty(b))return!1;if(!a(j[b],w[b]))return!1}for(b in w)if(!j.hasOwnProperty(b))return!1;return!0}function e(j,a,b){for(var e=0,c=0,f=0,l=j.length;f<l;){e!==-1&&e<=f&&(e=j.indexOf("\r",f));c!==-1&&c<=f&&(c=j.indexOf("\n",f));var d=f,o;if(c===-1&&e===-1){a(j.substring(f));break}e!==-1&&c!==-1?e+1===c?(o=e,f=c+1):(o=e<c?e:c,f=(e<c?e:c)+1):e!==-1?(o=e,f=e+1):(o=c,f=c+1);a(j.substring(d, +o));b()}}function l(j){var a,b,e,c,f=j.ownerDocument.defaultView||j.ownerDocument.parentWindow;if(f.getComputedStyle)j=f.getComputedStyle(j,null),a=j.getPropertyValue("padding-left"),b=j.getPropertyValue("padding-top"),e=j.getPropertyValue("padding-right"),c=j.getPropertyValue("padding-bottom");else if(j.currentStyle)a=j.currentStyle.paddingLeft,b=j.currentStyle.paddingTop,e=j.currentStyle.paddingRight,c=j.currentStyle.paddingBottom;return{left:parseInt(a,10)||0,top:parseInt(b,10)||0,right:parseInt(e, +10)||0,bottom:parseInt(c,10)||0}}function o(j){var a,b,e,c,f=j._trim;if(!f){var f=l(j),d=j.ownerDocument.defaultView||j.ownerDocument.parentWindow;if(d.getComputedStyle)c=d.getComputedStyle(j,null),a=c.getPropertyValue("border-left-width"),b=c.getPropertyValue("border-top-width"),e=c.getPropertyValue("border-right-width"),c=c.getPropertyValue("border-bottom-width");else if(j.currentStyle)a=j.currentStyle.borderLeftWidth,b=j.currentStyle.borderTopWidth,e=j.currentStyle.borderRightWidth,c=j.currentStyle.borderBottomWidth; +a=parseInt(a,10)||0;b=parseInt(b,10)||0;e=parseInt(e,10)||0;c=parseInt(c,10)||0;f.left+=a;f.top+=b;f.right+=e;f.bottom+=c;j._trim=f}return f}function q(j,a,b){this.start=j;this.end=a;this.caret=b}function r(j){this.left=j.left;this.top=j.top;this.right=j.right;this.bottom=j.bottom}function p(j,a,b){this.view=j;this.lineIndex=a;this._lineDiv=b}function t(j){this._init(j||{})}var v=d.addEventListener,s=d.removeEventListener,u=function(){function j(j){this.options=j}j.prototype.play=function(){var j= +typeof this.options.duration==="number"?this.options.duration:350,a=this.options.easing||this.defaultEasing,b=this.options.onAnimate||function(){},e=this.options.curve[0],c=this.options.curve[1],f=c-e,l=-1,d,o=this;this.interval=this.options.window.setInterval(function(){l=l===-1?(new Date).getTime():l;var g=((new Date).getTime()-l)/j;g<1?(g=a(g),d=e+g*f,b(d)):(b(c),o.stop())},typeof this.options.rate==="number"?this.options.rate:20)};j.prototype.stop=function(){this.options.window.clearInterval(this.interval); +(this.options.onEnd||function(){})()};j.prototype.defaultEasing=function(j){return Math.sin(j*(Math.PI/2))};return j}();q.prototype={clone:function(){return new q(this.start,this.end,this.caret)},collapse:function(){this.caret?this.end=this.start:this.start=this.end},extend:function(j){this.caret?this.start=j:this.end=j;if(this.start>this.end)j=this.start,this.start=this.end,this.end=j,this.caret=!this.caret},setCaret:function(j){this.end=this.start=j;this.caret=!1},getCaret:function(){return this.caret? +this.start:this.end},toString:function(){return"start="+this.start+" end="+this.end+(this.caret?" caret is at start":" caret is at end")},isEmpty:function(){return this.start===this.end},equals:function(j){return this.caret===j.caret&&this.start===j.start&&this.end===j.end}};r.prototype={toString:function(){return"{l="+this.left+", t="+this.top+", r="+this.right+", b="+this.bottom+"}"}};p.prototype={create:function(j,a){if(!this._lineDiv){var b=this._lineDiv=this._createLine(j,a,this.lineIndex);b._line= +this;return b}},_createLine:function(j,w,b){var e=this.view,c=e._model,l=c.getLine(b),d=c.getLineStart(b),o={type:"LineStyle",textView:e,lineIndex:b,lineText:l,lineStart:d};if(l.length<2E3)e.onLineStyle(o);c=w||f.createElement(j.ownerDocument,"div");if(!w||!a(w.viewStyle,o.style)){g(o.style,c,w);if(w)w._trim=null;c.viewStyle=o.style;c.setAttribute("role","presentation")}c.lineIndex=b;b=[];this._createRanges(o.ranges,l,0,l.length,d,{tabOffset:0,ranges:b});l=" ";!e._fullSelection&&f.isIE<9&&(l="\ufeff"); +o={text:l,style:e._metrics.largestFontStyle,ignoreChars:1};b.length===0||!b[b.length-1].style||b[b.length-1].style.tagName!=="div"?b.push(o):b.splice(b.length-1,0,o);var h,p,i,q,r,l=e=0,s,t;if(w){if(p=w.modelChangedEvent)p.removedLineCount===0&&p.addedLineCount===0?(t=p.start-d,s=p.addedCharCount-p.removedCharCount):t=-1,w.modelChangedEvent=void 0;p=w.firstChild}for(d=0;d<b.length;d++){o=b[d];q=o.text;e+=q.length;h=o.style;if(p)if(r=p.firstChild.data,i=p.viewStyle,r===q&&a(h,i)){l+=r.length;p._rectsCache= +void 0;h=p=p.nextSibling;continue}else for(;p;){if(t!==-1){i=e;i>=t&&(i-=s);r=(r=p.firstChild.data)?r.length:0;if(l+r>i)break;l+=r}i=p.nextSibling;c.removeChild(p);p=i}h=this._createSpan(c,q,h,o.ignoreChars);p?c.insertBefore(h,p):c.appendChild(h);if(w)w.lineWidth=void 0}if(w)for(j=h?h.nextSibling:null;j;)i=j.nextSibling,w.removeChild(j),j=i;else j.appendChild(c);return c},_createRanges:function(j,w,b,e,c,f){if(!(b>e)){if(j)for(var l=0;l<j.length;l++){var d=j[l];if(!(d.end<c+b)){var o=Math.max(c+b, +d.start)-c;if(o>e)break;var g=Math.min(c+e,d.end)-c;if(o<=g){o=Math.max(b,o);g=Math.min(e,g);b<o&&this._createRange(w,b,o,null,f);if(!d.style||!d.style.unmergeable)for(;l+1<j.length&&j[l+1].start-c===g&&a(d.style,j[l+1].style);)d=j[l+1],g=Math.min(c+e,d.end)-c,l++;this._createRange(w,o,g,d.style,f);b=g}}}b<e&&this._createRange(w,b,e,null,f)}},_createRange:function(j,a,b,e,c){if(!(a>b)){var f=this.view._customTabSize;if(f&&f!==8)for(var l=j.indexOf("\t",a);l!==-1&&l<b;){a<l&&(a={text:j.substring(a, +l),style:e},c.ranges.push(a),c.tabOffset+=a.text.length);a=f-c.tabOffset%f;if(a>0){for(var d="\u00a0",o=1;o<a;o++)d+=" ";a={text:d,style:e,ignoreChars:a-1};c.ranges.push(a);c.tabOffset+=a.text.length}a=l+1;if(a===b)return;l=j.indexOf("\t",a)}a<=b&&(a={text:j.substring(a,b),style:e},c.ranges.push(a),c.tabOffset+=a.text.length)}},_createSpan:function(j,a,b,e){var c=this.view,l="span";b&&b.tagName&&(l=b.tagName.toLowerCase());var d=l==="a";if(d)j.hasLink=!0;d&&!c._linksVisible&&(l="span");d=j.ownerDocument; +j=f.createElement(j.ownerDocument,l);b&&b.html?(j.innerHTML=b.html,j.ignore=!0):b&&b.node?(j.appendChild(b.node),j.ignore=!0):j.appendChild(d.createTextNode(b&&b.text?b.text:a));g(b,j);if(l==="a"){var o=c._getWindow();v(j,"click",function(j){return c._handleLinkClick(j?j:o.event)},!1)}j.viewStyle=b;if(e)j.ignoreChars=e;return j},_ensureCreated:function(){return this._lineDiv?this._lineDiv:this._createdDiv=this.create(this.view._clientDiv,null)},getBoundingClientRect:function(j,a){var b=this._ensureCreated(), +e=this.view;if(j===void 0)return this._getLineBoundingClientRect(b,!0);var c=e._model,l=b.ownerDocument,d=this.lineIndex,o=null;if(j<c.getLineEnd(d)){d=c.getLineStart(d);for(c=b.firstChild;c;){if(!c.ignore){var g=c.firstChild,p=g.length;c.ignoreChars&&(p-=c.ignoreChars);if(d+p>j){o=j-d;if(g.length===1)o=new r(c.getBoundingClientRect());else if(e._isRangeRects)l=l.createRange(),l.setStart(g,o),l.setEnd(g,o+1),o=new r(l.getBoundingClientRect());else if(f.isIE){if(l=l.body.createTextRange(),l.moveToElementText(c), +l.collapse(),(d=o===0&&f.isIE===8)&&(o=1),l.moveEnd("character",o+1),l.moveStart("character",o),o=new r(l.getBoundingClientRect()),d)o.left=c.getClientRects()[0].left}else{var h=g.data;c.removeChild(g);c.appendChild(l.createTextNode(h.substring(0,o)));var i=f.createElement(l,"span");i.appendChild(l.createTextNode(h.substring(o,o+1)));c.appendChild(i);c.appendChild(l.createTextNode(h.substring(o+1)));o=new r(i.getBoundingClientRect());c.innerHTML="";c.appendChild(g);this._createdDiv||(l=e._getSelection(), +(d<=l.start&&l.start<d+p||d<=l.end&&l.end<d+p)&&e._updateDOMSelection())}f.isIE&&(l=b.ownerDocument.defaultView||b.ownerDocument.parentWindow,b=l.screen.logicalXDPI/l.screen.deviceXDPI,l=l.screen.logicalYDPI/l.screen.deviceYDPI,o.left*=b,o.right*=b,o.top*=l,o.bottom*=l);break}d+=p}c=c.nextSibling}}b=this.getBoundingClientRect();if(!o)e._wrapMode?(e=this.getClientRects(),o=e[e.length-1],o.left=o.right,o.left+=b.left,o.top+=b.top,o.right+=b.left,o.bottom+=b.top):(o=new r(b),o.left=o.right);if(a||a=== +void 0)o.left-=b.left,o.top-=b.top,o.right-=b.left,o.bottom-=b.top;return o},_getClientRects:function(j,a){var b,e,c,l;if(!j._rectsCache){b=j.getClientRects();e=Array(b.length);for(l=0;l<b.length;l++)c=e[l]=new r(b[l]),c.left-=a.left,c.top-=a.top,c.right-=a.left,c.bottom-=a.top;j._rectsCache=e}b=j._rectsCache;e=[b.length];for(l=0;l<b.length;l++)e[l]=new r(b[l]);return e},getClientRects:function(j){if(!this.view._wrapMode)return[this.getBoundingClientRect()];for(var a=this._ensureCreated(),b=[],e= +a.firstChild,c,l=a.getBoundingClientRect();e;){if(!e.ignore)for(var f=this._getClientRects(e,l),a=0;a<f.length;a++){var o=f[a],d;if(o.top!==o.bottom){var g=o.top+(o.bottom-o.top)/2;for(d=0;d<b.length;d++)if(c=b[d],c.top<=g&&g<c.bottom)break;if(d===b.length)b.push(o);else{if(o.left<c.left)c.left=o.left;if(o.top<c.top)c.top=o.top;if(o.right>c.right)c.right=o.right;if(o.bottom>c.bottom)c.bottom=o.bottom}}}e=e.nextSibling}return j!==void 0?b[j]:b},_getLineBoundingClientRect:function(j,a){var b=new r(j.getBoundingClientRect()); +if(!this.view._wrapMode){b.right=b.left;for(var e=j.lastChild;e&&e.ignoreChars===e.firstChild.length;)e=e.previousSibling;if(e)e=e.getBoundingClientRect(),b.right=e.right+o(j).right}a&&(e=o(j),b.left+=e.left,b.right-=e.right);return b},getLineCount:function(){return!this.view._wrapMode?1:this.getClientRects().length},getLineIndex:function(j){if(!this.view._wrapMode)return 0;for(var a=this.getClientRects(),j=this.getBoundingClientRect(j),j=j.top+(j.bottom-j.top)/2,b=0;b<a.length;b++)if(a[b].top<=j&& +j<a[b].bottom)return b;return a.length-1},getLineStart:function(j){if(!this.view._wrapMode||j===0)return this.view._model.getLineStart(j);var a=this.getClientRects();return this.getOffset(a[j].left+1,a[j].top+1)},getOffset:function(j,a){var b=this.view,e=b._model,c=this.lineIndex,l=e.getLineStart(c),o=e.getLineEnd(c);if(l===o)return l;var d=this._ensureCreated(),g=this.getBoundingClientRect(),p,h;if(b._wrapMode){p=this.getClientRects();if(a<p[0].top)a=p[0].top;for(var i=0;i<p.length;i++)if(h=p[i], +h.top<=a&&a<h.bottom)break;if(j<h.left)j=h.left;j>h.right&&(j=h.right-1)}else j<0&&(j=0),j>g.right-g.left&&(j=g.right-g.left);var q=d.ownerDocument,i=q.defaultView||q.parentWindow,r=f.isIE?i.screen.logicalXDPI/i.screen.deviceXDPI:1,s=f.isIE?i.screen.logicalYDPI/i.screen.deviceYDPI:1,i=l,t=d.firstChild;a:for(;t;){if(!t.ignore){var u=t.firstChild,d=u.length;t.ignoreChars&&(d-=t.ignoreChars);var v,k,n;p=this._getClientRects(t,g);for(var m=0;m<p.length;m++)if(h=p[m],h.left<=j&&j<h.right&&(!b._wrapMode|| +h.top<=a&&a<h.bottom)){var m=h.left+g.left,A;if(f.isIE||b._isRangeRects){for(var q=b._isRangeRects?q.createRange():q.body.createTextRange(),z=d,C=-1;z-C>1;){var J=Math.floor((z+C)/2);p=C+1;h=J===d-1&&t.ignoreChars?u.length:J+1;A=p===0&&f.isIE===8;b._isRangeRects?(q.setStart(u,p),q.setEnd(u,h)):(A&&(p=1),q.moveToElementText(t),q.move("character",p),q.moveEnd("character",h-p));p=q.getClientRects();for(var N=!1,L=0;L<p.length;L++)if(h=p[L],v=(A?m:h.left)*r-g.left,n=h.right*r-g.left,k=h.top*s-g.top,h= +h.bottom*s-g.top,v<=j&&j<n&&(!b._wrapMode||k<=a&&a<h)){N=!0;break}N?z=J:C=J}i+=z;p=z;h=z===d-1&&t.ignoreChars?u.length:Math.min(z+1,u.length);b._isRangeRects?(q.setStart(u,p),q.setEnd(u,h)):(q.moveToElementText(t),q.move("character",p),q.moveEnd("character",h-p));p=q.getClientRects();b=!1;p.length>0&&(h=p[0],v=(A?m:h.left)*r-g.left,n=h.right*r-g.left,b=j>v+(n-v)/2);g=i-l;e=e.getLine(c);c=e.charCodeAt(g);55296<=c&&c<=56319&&b?g<e.length&&(c=e.charCodeAt(g+1),56320<=c&&c<=57343&&(i+=1)):56320<=c&&c<= +57343&&!b&&g>0&&(c=e.charCodeAt(g-1),55296<=c&&c<=56319&&(i-=1));b&&i++}else{e=[];for(c=0;c<d;c++)e.push("<span>"),c===d-1?e.push(u.data.substring(c)):e.push(u.data.substring(c,c+1)),e.push("</span>");t.innerHTML=e.join("");for(e=t.firstChild;e;){h=e.getBoundingClientRect();v=h.left-g.left;n=h.right-g.left;if(v<=j&&j<n){j>v+(n-v)/2&&i++;break}i++;e=e.nextSibling}if(!this._createdDiv)t.innerHTML="",t.appendChild(u),g=b._getSelection(),(i<=g.start&&g.start<i+d||i<=g.end&&g.end<i+d)&&b._updateDOMSelection()}break a}i+= +d}t=t.nextSibling}return Math.min(o,Math.max(l,i))},getNextOffset:function(j,a){if(a.unit==="line"){var b=this.view._model,e=b.getLineAtOffset(j);if(a.count>0)return a.count--,b.getLineEnd(e);a.count++;return b.getLineStart(e)}return a.unit==="wordend"||a.unit==="wordWS"||a.unit==="wordendWS"?this._getNextOffset_W3C(j,a):f.isIE?this._getNextOffset_IE(j,a):this._getNextOffset_W3C(j,a)},_getNextOffset_W3C:function(j,a){function b(j){return 33<=j&&j<=47||58<=j&&j<=64||91<=j&&j<=94||j===96||123<=j&&j<= +126}function e(j){return j===32||j===9}var c=this.view._model,l=c.getLineAtOffset(j),f=c.getLine(l),o=c.getLineStart(l),c=c.getLineEnd(l),l=f.length,d=j-o,g,h=a.count<0?-1:1;if(a.unit==="word"||a.unit==="wordend"||a.unit==="wordWS"||a.unit==="wordendWS")for(var p,i,q;a.count!==0;){if(a.count>0){if(d===l)return c;g=f.charCodeAt(d);p=b(g);i=!p&&!e(g);for(d++;d<l;){g=f.charCodeAt(d);if(a.unit!=="wordWS"&&a.unit!=="wordendWS"){q=b(g);if(a.unit==="wordend"){if(!q&&p)break}else if(q&&!p)break;g=!q&&!e(g)}else g= +!e(g);if(a.unit==="wordend"||a.unit==="wordendWS"){if(!g&&i)break}else if(g&&!i)break;i=g;p=q;d++}}else{if(d===0)return o;d--;g=f.charCodeAt(d);p=b(g);for(i=!p&&!e(g);0<d;){g=f.charCodeAt(d-1);if(a.unit!=="wordWS"&&a.unit!=="wordendWS"){q=b(g);if(a.unit==="wordend"){if(q&&!p)break}else if(!q&&p)break;g=!q&&!e(g)}else g=!e(g);if(a.unit==="wordend"||a.unit==="wordendWS"){if(g&&!i)break}else if(!g&&i)break;i=g;p=q;d--}}a.count-=h}else for(;a.count!==0&&0<=d+h&&d+h<=l;)d+=h,g=f.charCodeAt(d),56320<=g&& +g<=57343&&d>0&&(g=f.charCodeAt(d-1),55296<=g&&g<=56319&&(d+=h)),a.count-=h;return o+d},_getNextOffset_IE:function(j,a){var b=this._ensureCreated(),e=this.view._model,c=this.lineIndex,l=0,f;f=e.getLineStart(c);var d=b.ownerDocument,o=a.count<0?-1:1;if(j===e.getLineEnd(c)){for(b=b.lastChild;b&&b.ignoreChars===b.firstChild.length;)b=b.previousSibling;if(!b)return f;l=d.body.createTextRange();l.moveToElementText(b);f=l.text.length;l.moveEnd(a.unit,o);l=j+l.text.length-f}else if(j===f&&a.count<0)l=f;else for(b= +b.firstChild;b;){e=b.firstChild.length;b.ignoreChars&&(e-=b.ignoreChars);if(f+e>j){l=d.body.createTextRange();if(j===f&&a.count<0){for(f=b.previousSibling;f;){if(f.firstChild&&f.firstChild.length)break;f=f.previousSibling}l.moveToElementText(f?f:b.previousSibling)}else l.moveToElementText(b),l.collapse(),l.moveEnd("character",j-f);f=l.text.length;l.moveEnd(a.unit,o);l=j+l.text.length-f;break}f=e+f;b=b.nextSibling}a.count-=o;return l},destroy:function(){var j=this._createdDiv;if(j)j.parentNode.removeChild(j), +this._createdDiv=null}};t.prototype={addKeyMode:function(j,a){var b=this._keyModes;a!==void 0?b.splice(a,0,j):b.push(j);j._modeAdded&&j._modeAdded()},addRuler:function(j,a){j.setView(this);var b=this._rulers;if(a!==void 0){var e,c;for(e=0,c=0;e<b.length&&c<a;e++)j.getLocation()===b[e].getLocation()&&c++;b.splice(c,0,j);a=c}else b.push(j);this._createRuler(j,a);this._update()},computeSize:function(){var j=0,a=0,b=this._model,e=this._clientDiv;if(!e)return{width:j,height:a};var c=e.style.width;if(f.isWebkit)e.style.width= +"0x7fffffffpx";for(var b=b.getLineCount(),l=0;l<b;l++){var d=this._getLine(l),o=d.getBoundingClientRect(),j=Math.max(j,o.right-o.left);a+=o.bottom-o.top;d.destroy()}if(f.isWebkit)e.style.width=c;e=this._getViewPadding();j+=e.right+e.left+this._metrics.scrollWidth;a+=e.bottom+e.top+this._metrics.scrollWidth;return{width:j,height:a}},convert:function(j,a,b){if(this._clientDiv){var e=this._getScroll(),c=this._getViewPadding(),l=this._viewDiv.getBoundingClientRect();a==="document"&&(j.x!==void 0&&(j.x+= +-e.x+l.left+c.left),j.y!==void 0&&(j.y+=-e.y+l.top+c.top));b==="document"&&(j.x!==void 0&&(j.x+=e.x-l.left-c.left),j.y!==void 0&&(j.y+=e.y-l.top-c.top));return j}},destroy:function(){for(var j=0;j<this._rulers.length;j++)this._rulers[j].setView(null);this.rulers=null;this._destroyView();this.onDestroy({type:"Destroy"});this._parent=null;this._model&&this._model.destroy&&this._model.destroy();this._actions=this._keyModes=this._doubleClickSelection=this._selection=this._theme=this._model=null},focus:function(){this._clientDiv&& +(this._updateDOMSelection(),this._clientDiv.focus(),this._updateDOMSelection())},hasFocus:function(){return this._hasFocus},getActionDescription:function(j){if(j=this._actions[j])return j.actionDescription},getActions:function(j){var a=[],b=this._actions,e;for(e in b)b.hasOwnProperty(e)&&(j||!b[e].defaultHandler)&&a.push(e);return a},getBottomIndex:function(j){return!this._clientDiv?0:this._getBottomIndex(j)},getBottomPixel:function(){return!this._clientDiv?0:this._getScroll().y+this._getClientHeight()}, +getCaretOffset:function(){return this._getSelection().getCaret()},getClientArea:function(){if(!this._clientDiv)return{x:0,y:0,width:0,height:0};var j=this._getScroll();return{x:j.x,y:j.y,width:this._getClientWidth(),height:this._getClientHeight()}},getHorizontalPixel:function(){return!this._clientDiv?0:this._getScroll().x},getKeyBindings:function(j){for(var a=[],b=this._keyModes,e=0;e<b.length;e++)a=a.concat(b[e].getKeyBindings(j));return a},getKeyModes:function(){return this._keyModes.slice(0)}, +getLineHeight:function(j){return!this._clientDiv?0:this._getLineHeight(j)},getLineIndex:function(j){return!this._clientDiv?0:this._getLineIndex(j)},getLinePixel:function(j){return!this._clientDiv?0:this._getLinePixel(j)},getLocationAtOffset:function(j){if(!this._clientDiv)return{x:0,y:0};var a=this._model,j=Math.min(Math.max(0,j),a.getCharCount()),a=a.getLineAtOffset(j),b=this._getLine(a),j=b.getBoundingClientRect(j);b.destroy();b=j.left;a=this._getLinePixel(a)+j.top;return{x:b,y:a}},getNextOffset:function(j, +a){var b=new q(j,j,!1);this._doMove(a,b);return b.getCaret()},getOptions:function(){var j;if(arguments.length===0)j=this._defaultOptions();else if(arguments.length===1){if(j=arguments[0],typeof j==="string")return h(this["_"+j])}else{j={};for(var a in arguments)arguments.hasOwnProperty(a)&&(j[arguments[a]]=void 0)}for(var b in j)j.hasOwnProperty(b)&&(j[b]=h(this["_"+b]));return j},getModel:function(){return this._model},getOffsetAtLocation:function(j,a){if(!this._clientDiv)return 0;var b=this._getLineIndex(a), +e=this._getLine(b),b=e.getOffset(j,a-this._getLinePixel(b));e.destroy();return b},getLineAtOffset:function(j){this.getModel().getLineAtOffset(j)},getLineStart:function(j){this.getModel().getLineStart(j)},getRulers:function(){return this._rulers.slice(0)},getSelection:function(){var j=this._getSelection();return{start:j.start,end:j.end}},getText:function(j,a){return this._model.getText(j,a)},getTopIndex:function(j){return!this._clientDiv?0:this._getTopIndex(j)},getTopPixel:function(){return!this._clientDiv? +0:this._getScroll().y},invokeAction:function(j,a,b){if(this._clientDiv){if(j=this._actions[j]){if(!a&&j.handler&&j.handler(b))return!0;if(j.defaultHandler)return typeof j.defaultHandler(b)==="boolean"}return!1}},isDestroyed:function(){return!this._clientDiv},onContextMenu:function(j){return this.dispatchEvent(j)},onDragStart:function(j){return this.dispatchEvent(j)},onDrag:function(j){return this.dispatchEvent(j)},onDragEnd:function(j){return this.dispatchEvent(j)},onDragEnter:function(j){return this.dispatchEvent(j)}, +onDragOver:function(j){return this.dispatchEvent(j)},onDragLeave:function(j){return this.dispatchEvent(j)},onDrop:function(j){return this.dispatchEvent(j)},onDestroy:function(j){return this.dispatchEvent(j)},onLineStyle:function(j){return this.dispatchEvent(j)},onKeyDown:function(j){return this.dispatchEvent(j)},onKeyPress:function(j){return this.dispatchEvent(j)},onKeyUp:function(j){return this.dispatchEvent(j)},onModelChanged:function(j){return this.dispatchEvent(j)},onModelChanging:function(j){return this.dispatchEvent(j)}, +onModify:function(j){return this.dispatchEvent(j)},onMouseDown:function(j){return this.dispatchEvent(j)},onMouseUp:function(j){return this.dispatchEvent(j)},onMouseMove:function(j){return this.dispatchEvent(j)},onMouseOver:function(j){return this.dispatchEvent(j)},onMouseOut:function(j){return this.dispatchEvent(j)},onSelection:function(j){return this.dispatchEvent(j)},onScroll:function(j){return this.dispatchEvent(j)},onVerify:function(j){return this.dispatchEvent(j)},onFocus:function(j){return this.dispatchEvent(j)}, +onBlur:function(j){return this.dispatchEvent(j)},redraw:function(){if(!(this._redrawCount>0)){var j=this._model.getLineCount();this.redrawRulers(0,j);this.redrawLines(0,j)}},redrawRulers:function(j,a){if(!(this._redrawCount>0))for(var b=this.getRulers(),e=0;e<b.length;e++)this.redrawLines(j,a,b[e])},redrawLines:function(j,a,b){if(!(this._redrawCount>0)&&(j===void 0&&(j=0),a===void 0&&(a=this._model.getLineCount()),j!==a)){var e=this._clientDiv;if(e){if(b)for(e=this._getRulerParent(b).firstChild;e;){if(e._ruler=== +b)break;e=e.nextSibling}b?e.rulerChanged=!0:this._lineHeight&&this._resetLineHeight(j,a);if(!b||b.getOverview()==="page")for(e=e.firstChild;e;){var c=e.lineIndex;if(j<=c&&c<a)e.lineChanged=!0;e=e.nextSibling}if(!b&&!this._wrapMode&&j<=this._maxLineIndex&&this._maxLineIndex<a)this._checkMaxLineIndex=this._maxLineIndex,this._maxLineIndex=-1,this._maxLineWidth=0;this._queueUpdate()}}},redrawRange:function(j,a){if(!(this._redrawCount>0)){var b=this._model;j===void 0&&(j=0);a===void 0&&(a=b.getCharCount()); +var e=b.getLineAtOffset(j),b=b.getLineAtOffset(Math.max(j,a-1))+1;this.redrawLines(e,b)}},removeKeyMode:function(j){for(var a=this._keyModes,b=0;b<a.length;b++)if(a[b]===j){a.splice(b,1);break}j._modeRemoved&&j._modeRemoved()},removeRuler:function(j){for(var a=this._rulers,b=0;b<a.length;b++)if(a[b]===j){a.splice(b,1);j.setView(null);this._destroyRuler(j);this._update();break}},resize:function(){this._clientDiv&&this._handleResize(null)},setAction:function(j,a,b){if(j){var e=this._actions,c=e[j]; +c||(c=e[j]={});c.handler=a;if(b!==void 0)c.actionDescription=b}},setKeyBinding:function(j,a){this._keyModes[0].setKeyBinding(j,a)},setCaretOffset:function(j,a,b){var e=this._model.getCharCount(),j=Math.max(0,Math.min(j,e));this._setSelection(new q(j,j,!1),a===void 0||a,!0,b)},setHorizontalPixel:function(j){this._clientDiv&&(j=Math.max(0,j),this._scrollView(j-this._getScroll().x,0))},setRedraw:function(j){j?--this._redrawCount===0&&this.redraw():this._redrawCount++},setModel:function(j){if(j&&j!== +this._model){this._model.removeEventListener("preChanging",this._modelListener.onChanging);this._model.removeEventListener("postChanged",this._modelListener.onChanged);var a=this._model.getLineCount(),b=this._model.getCharCount(),e=j.getLineCount(),c=j.getCharCount(),l={type:"ModelChanging",text:j.getText(),start:0,removedCharCount:b,addedCharCount:c,removedLineCount:a,addedLineCount:e};this.onModelChanging(l);this._model=j;l={type:"ModelChanged",start:0,removedCharCount:b,addedCharCount:c,removedLineCount:a, +addedLineCount:e};this.onModelChanged(l);this._model.addEventListener("preChanging",this._modelListener.onChanging);this._model.addEventListener("postChanged",this._modelListener.onChanged);this._reset();this._update()}},setOptions:function(j){var b=this._defaultOptions(),e;for(e in j)if(j.hasOwnProperty(e)){var c=j[e];if(!a(this["_"+e],c)){var l=b[e]?b[e].update:null;l?l.call(this,c):this["_"+e]=h(c)}}},setSelection:function(j,a,b,e){var c=j>a;if(c)var l=j,j=a,a=l;l=this._model.getCharCount();j= +Math.max(0,Math.min(j,l));a=Math.max(0,Math.min(a,l));this._setSelection(new q(j,a,c),b===void 0||b,!0,e)},setText:function(j,a,b){var e=a===void 0&&b===void 0;a===void 0&&(a=0);b===void 0&&(b=this._model.getCharCount());if(e)this._variableLineHeight=!1;this._modifyContent({text:j,start:a,end:b,_code:!0},!e);if(e)this._columnX=-1,this._setSelection(new q(0,0,!1),!0),f.isFirefox&&this._fixCaret()},setTopIndex:function(j){this._clientDiv&&this._scrollView(0,this._getLinePixel(Math.max(0,j))-this._getScroll().y)}, +setTopPixel:function(j){this._clientDiv&&this._scrollView(0,Math.max(0,j)-this._getScroll().y)},showSelection:function(){return this._showCaret(!0)},update:function(j,a){this._clientDiv&&(j&&this._updateStyle(),a===void 0||a?this._update():this._queueUpdate())},_handleRootMouseDown:function(j){if(!this._ignoreEvent(j)){if(f.isFirefox&&j.which===1)this._clientDiv.contentEditable=!1,this._ignoreBlur=(this._overlayDiv||this._clientDiv).draggable=!0;var a=this._overlayDiv||this._clientDiv;if(f.isIE<9)a= +this._viewDiv;for(var b=j.target?j.target:j.srcElement;b;){if(a===b)return;b=b.parentNode}j.preventDefault&&j.preventDefault();j.stopPropagation&&j.stopPropagation();if(!this._isW3CEvents){var e=this;this._getWindow().setTimeout(function(){e._clientDiv.focus()},0)}}},_handleRootMouseUp:function(j){if(!this._ignoreEvent(j)&&f.isFirefox&&j.which===1)this._clientDiv.contentEditable=!0,(this._overlayDiv||this._clientDiv).draggable=!1,this._fixCaret(),this._ignoreBlur=!1},_handleBlur:function(){if(!this._ignoreBlur){this._hasFocus= +!1;if(f.isIE<9&&!this._getSelection().isEmpty()){var j=this._rootDiv,a=f.createElement(j.ownerDocument,"div");j.appendChild(a);j.removeChild(a)}if(this._cursorDiv)this._cursorDiv.style.display="none";if(this._selDiv1)if(this._selDiv1.style.background="lightgray",this._selDiv2.style.background="lightgray",this._selDiv3.style.background="lightgray",j=this._getWindow(),a=this._selDiv1.ownerDocument,j.getSelection){a=j.getSelection();for(j=a.anchorNode;j;){if(j===this._clientDiv){a.rangeCount>0&&a.removeAllRanges(); +break}j=j.parentNode}}else if(a.selection){this._ignoreSelect=!1;for(j=a.selection.createRange().parentElement();j;){if(j===this._clientDiv){a.selection.empty();break}j=j.parentNode}this._ignoreSelect=!0}if(!this._ignoreFocus)this.onBlur({type:"Blur"})}},_handleContextMenu:function(j){if(!this._ignoreEvent(j)){f.isIE&&this._lastMouseButton===3&&this._updateDOMSelection();var a=!1;this.isListening("ContextMenu")?(a=this._createMouseEvent("ContextMenu",j),a.screenX=j.screenX,a.screenY=j.screenY,this.onContextMenu(a), +a=a.defaultPrevented):f.isMac&&f.isFirefox&&j.button===0&&(a=!0);if(a)return j.preventDefault&&j.preventDefault(),!1}},_handleCopy:function(j){if(!this._ignoreEvent(j)&&!this._ignoreCopy&&this._doCopy(j))return j.preventDefault&&j.preventDefault(),!1},_handleCut:function(j){if(!this._ignoreEvent(j)&&this._doCut(j))return j.preventDefault&&j.preventDefault(),!1},_handleDataModified:function(j){this._ignoreEvent(j)||this._startIME()},_handleDblclick:function(j){if(!this._ignoreEvent(j)&&(this._lastMouseTime= +j.timeStamp?j.timeStamp:(new Date).getTime(),this._clickCount!==2))this._clickCount=2,this._handleMouse(j)},_handleDragStart:function(j){if(!this._ignoreEvent(j)){if(f.isFirefox){var a=this;this._getWindow().setTimeout(function(){a._clientDiv.contentEditable=!0;a._clientDiv.draggable=!1;a._ignoreBlur=!1},0)}if(this.isListening("DragStart")&&this._dragOffset!==-1)this._isMouseDown=!1,this.onDragStart(this._createMouseEvent("DragStart",j)),this._dragOffset=-1;else return j.preventDefault&&j.preventDefault(), +!1}},_handleDrag:function(j){if(!this._ignoreEvent(j)&&this.isListening("Drag"))this.onDrag(this._createMouseEvent("Drag",j))},_handleDragEnd:function(j){if(!this._ignoreEvent(j)){this._dropTarget=!1;this._dragOffset=-1;if(this.isListening("DragEnd"))this.onDragEnd(this._createMouseEvent("DragEnd",j));f.isFirefox&&(this._fixCaret(),j.dataTransfer.dropEffect==="none"&&!j.dataTransfer.mozUserCancelled&&this._fixCaret())}},_handleDragEnter:function(j){if(!this._ignoreEvent(j)){var a=!0;this._dropTarget= +!0;this.isListening("DragEnter")&&(a=!1,this.onDragEnter(this._createMouseEvent("DragEnter",j)));if(f.isWebkit||a)return j.preventDefault&&j.preventDefault(),!1}},_handleDragOver:function(j){if(!this._ignoreEvent(j)){var a=!0;this.isListening("DragOver")&&(a=!1,this.onDragOver(this._createMouseEvent("DragOver",j)));if(f.isWebkit||a){if(a)j.dataTransfer.dropEffect="none";j.preventDefault&&j.preventDefault();return!1}}},_handleDragLeave:function(j){if(!this._ignoreEvent(j)&&(this._dropTarget=!1,this.isListening("DragLeave")))this.onDragLeave(this._createMouseEvent("DragLeave", +j))},_handleDrop:function(j){if(!this._ignoreEvent(j)){this._dropTarget=!1;if(this.isListening("Drop"))this.onDrop(this._createMouseEvent("Drop",j));j.preventDefault&&j.preventDefault();return!1}},_handleFocus:function(){this._hasFocus=!0;f.isIOS&&this._lastTouchOffset!==void 0?(this.setCaretOffset(this._lastTouchOffset,!0),this._lastTouchOffset=void 0):this._updateDOMSelection();if(this._cursorDiv)this._cursorDiv.style.display="block";if(this._selDiv1){var j=this._highlightRGB;this._selDiv1.style.background= +j;this._selDiv2.style.background=j;this._selDiv3.style.background=j}if(!this._ignoreFocus)this.onFocus({type:"Focus"})},_handleKeyDown:function(j){if(!this._ignoreEvent(j)){if(this.isListening("KeyDown")){var a=this._createKeyEvent("KeyDown",j);this.onKeyDown(a);if(a.defaultPrevented){if(f.isFirefox)this._keyDownPrevented=!0;j.preventDefault();return}}a=!1;switch(j.keyCode){case 16:case 17:case 18:case 91:a=!0;break;default:this._setLinksVisible(!1)}if(j.keyCode===229){if(this._readonly)return j.preventDefault&& +j.preventDefault(),!1;a=!0;if(f.isSafari&&f.isMac&&j.ctrlKey)a=!1,j.keyCode=129;a&&this._startIME()}else a||this._commitIME();if((f.isMac||f.isLinux)&&f.isFirefox<4||f.isOpera<12.16)return this._keyDownEvent=j,!0;if(this._doAction(j))return j.preventDefault?(j.preventDefault(),j.stopPropagation()):(j.cancelBubble=!0,j.returnValue=!1,j.keyCode=0),!1}},_handleKeyPress:function(j){if(!this._ignoreEvent(j))if(this._keyDownPrevented)j.preventDefault&&(j.preventDefault(),j.stopPropagation()),this._keyDownPrevented= +void 0;else{if(f.isMac&&f.isWebkit&&(63232<=j.keyCode&&j.keyCode<=63487||j.keyCode===13||j.keyCode===8))return j.preventDefault&&j.preventDefault(),!1;if(((f.isMac||f.isLinux)&&f.isFirefox<4||f.isOpera<12.16)&&this._doAction(this._keyDownEvent))return j.preventDefault&&j.preventDefault(),!1;var a=f.isMac?j.metaKey:j.ctrlKey;if(j.charCode!==void 0&&a)switch(j.charCode){case 99:case 118:case 120:return!0}if(this.isListening("KeyPress")&&(a=this._createKeyEvent("KeyPress",j),this.onKeyPress(a),a.defaultPrevented)){j.preventDefault(); +return}if(this._doAction(j))return j.preventDefault?(j.preventDefault(),j.stopPropagation()):(j.cancelBubble=!0,j.returnValue=!1,j.keyCode=0),!1;a=!1;if(f.isMac){if(j.ctrlKey||j.metaKey)a=!0}else if(f.isFirefox){if(j.ctrlKey||j.altKey)a=!0}else j.ctrlKey^j.altKey&&(a=!0);if(!a&&(a=f.isOpera?j.which:j.charCode!==void 0?j.charCode:j.keyCode,a>31))return this._doContent(String.fromCharCode(a)),j.preventDefault&&j.preventDefault(),!1}},_handleDocKeyUp:function(j){(f.isMac?j.metaKey:j.ctrlKey)||this._setLinksVisible(!1)}, +_handleKeyUp:function(j){if(!this._ignoreEvent(j)){if(this.isListening("KeyUp")){var a=this._createKeyEvent("KeyUp",j);this.onKeyUp(a);if(a.defaultPrevented){j.preventDefault();return}}this._handleDocKeyUp(j);j.keyCode===13&&this._commitIME()}},_handleLinkClick:function(j){if(!(f.isMac?j.metaKey:j.ctrlKey))return j.preventDefault&&j.preventDefault(),!1},_handleMouse:function(j){var a=this._getWindow(),b=!0,e=a;if(f.isIE||f.isFirefox&&!this._overlayDiv)e=this._clientDiv;if(this._overlayDiv){if(this._hasFocus)this._ignoreFocus= +!0;var c=this;a.setTimeout(function(){c.focus();c._ignoreFocus=!1},0)}this._clickCount===1?(b=this._setSelectionTo(j.clientX,j.clientY,j.shiftKey,(!f.isOpera||f.isOpera>=12.16)&&this._hasFocus&&this.isListening("DragStart")))&&this._setGrab(e):(this._isW3CEvents&&this._setGrab(e),this._doubleClickSelection=null,this._setSelectionTo(j.clientX,j.clientY,j.shiftKey),this._doubleClickSelection=this._getSelection());return b},_handleMouseDown:function(j){if(!this._ignoreEvent(j)){if(this._linksVisible)if((j.target|| +j.srcElement).tagName!=="A")this._setLinksVisible(!1);else return;this._commitIME();var a=j.which;a||(j.button===4&&(a=2),j.button===2&&(a=3),j.button===1&&(a=1));var b=a!==2&&j.timeStamp?j.timeStamp:(new Date).getTime(),e=b-this._lastMouseTime,c=Math.abs(this._lastMouseX-j.clientX),l=Math.abs(this._lastMouseY-j.clientY),d=this._lastMouseButton===a;this._lastMouseX=j.clientX;this._lastMouseY=j.clientY;this._lastMouseTime=b;this._lastMouseButton=a;if(a===1)this._isMouseDown=!0,d&&e<=this._clickTime&& +c<=this._clickDist&&l<=this._clickDist?this._clickCount++:this._clickCount=1;if(this.isListening("MouseDown")&&(b=this._createMouseEvent("MouseDown",j),this.onMouseDown(b),b.defaultPrevented)){j.preventDefault();return}if(a===1&&this._handleMouse(j)&&(f.isIE>=9||f.isOpera||f.isChrome||f.isSafari||f.isFirefox&&!this._overlayDiv))this._hasFocus||this.focus(),j.preventDefault();f.isFirefox&&this._lastMouseButton===3&&this._updateDOMSelection()}},_handleMouseOver:function(j){if(!this._ignoreEvent(j)&& +!this._animation&&this.isListening("MouseOver"))this.onMouseOver(this._createMouseEvent("MouseOver",j))},_handleMouseOut:function(j){if(!this._ignoreEvent(j)&&!this._animation&&this.isListening("MouseOut"))this.onMouseOut(this._createMouseEvent("MouseOut",j))},_handleMouseMove:function(j){if(!this._animation){var a=this._isClientDiv(j);if(this.isListening("MouseMove")&&a)this.onMouseMove(this._createMouseEvent("MouseMove",j));if(!this._dropTarget){var b=this._linksVisible||this._lastMouseMoveX!== +j.clientX||this._lastMouseMoveY!==j.clientY;this._lastMouseMoveX=j.clientX;this._lastMouseMoveY=j.clientY;this._setLinksVisible(b&&!this._isMouseDown&&(f.isMac?j.metaKey:j.ctrlKey));if(!this._isW3CEvents){if(j.button===0)return this._setGrab(null),!0;if(!this._isMouseDown&&j.button===1&&(this._clickCount&1)!==0&&a)return this._clickCount=2,this._handleMouse(j,this._clickCount)}if(this._isMouseDown&&this._dragOffset===-1){var a=j.clientX,j=j.clientY,e=this._getViewPadding(),c=this._viewDiv.getBoundingClientRect(), +l=this._getClientWidth(),d=this._getClientHeight(),b=c.left+e.left,o=c.top+e.top,l=c.left+e.left+l,e=c.top+e.top+d;j<o?this._doAutoScroll("up",a,j-o):j>e?this._doAutoScroll("down",a,j-e):a<b&&!this._wrapMode?this._doAutoScroll("left",a-b,j):a>l&&!this._wrapMode?this._doAutoScroll("right",a-l,j):(this._endAutoScroll(),this._setSelectionTo(a,j,!0))}}}},_isClientDiv:function(j){for(var a=this._overlayDiv||this._clientDiv,j=j.target?j.target:j.srcElement;j;){if(a===j)return!0;j=j.parentNode}return!1}, +_createKeyEvent:function(j,a){return{type:j,event:a,preventDefault:function(){this.defaultPrevented=!0}}},_createMouseEvent:function(j,a){var b=this.convert({x:a.clientX,y:a.clientY},"page","document");return{type:j,event:a,clickCount:this._clickCount,x:b.x,y:b.y,preventDefault:function(){this.defaultPrevented=!0}}},_handleMouseUp:function(j){var a=j.which?j.button===0:j.button===1;if(this.isListening("MouseUp")&&(this._isClientDiv(j)||a&&this._isMouseDown))this.onMouseUp(this._createMouseEvent("MouseUp", +j));if(!this._linksVisible&&a&&this._isMouseDown){if(this._dragOffset!==-1)a=this._getSelection(),a.extend(this._dragOffset),a.collapse(),this._setSelection(a,!0,!0),this._dragOffset=-1;this._isMouseDown=!1;this._endAutoScroll();this._isW3CEvents&&this._setGrab(null);f.isFirefox&&j.preventDefault()}},_handleMouseWheel:function(j){var a=this._getLineHeight(),b=0,e=0;f.isIE||f.isOpera?e=-j.wheelDelta/40*a:f.isFirefox?(a=f.isMac?j.detail*3:Math.max(-256,Math.min(256,j.detail))*a,j.axis===j.HORIZONTAL_AXIS? +b=a:e=a):f.isMac?(e=j.timeStamp-this._wheelTimeStamp,this._wheelTimeStamp=j.timeStamp,b=j.wheelDeltaX%120!==0?1:e<40?40/(40-e):40,e=j.wheelDeltaY%120!==0?1:e<40?40/(40-e):40,b=Math.ceil(-j.wheelDeltaX/b),-1<b&&b<0&&(b=-1),0<b&&b<1&&(b=1),e=Math.ceil(-j.wheelDeltaY/e),-1<e&&e<0&&(e=-1),0<e&&e<1&&(e=1)):(b=-j.wheelDeltaX,e=-j.wheelDeltaY/120*8*a);if(f.isSafari){for(a=j.target;a&&a.lineIndex===void 0;)a=a.parentNode;this._mouseWheelLine=a}a=this._getScroll();this._scrollView(b,e);b=this._getScroll(); +if(a.x!==b.x||a.y!==b.y)return j.preventDefault&&j.preventDefault(),!1},_handlePaste:function(j){if(!this._ignoreEvent(j)&&!this._ignorePaste&&this._doPaste(j)){if(f.isIE){var a=this;this._ignoreFocus=!0;this._getWindow().setTimeout(function(){a._updateDOMSelection();a._ignoreFocus=!1},0)}j.preventDefault&&j.preventDefault();return!1}},_handleResize:function(){var j=this._rootDiv.clientWidth,b=this._rootDiv.clientHeight;if(this._rootWidth!==j||this._rootHeight!==b){this._rootWidth!==j&&this._wrapMode&& +this._resetLineHeight();this._rootWidth=j;this._rootHeight=b;j=f.isIE<9;b=this._calculateMetrics();if(!a(b,this._metrics)){if(this._variableLineHeight)this._variableLineHeight=!1,this._resetLineHeight();this._metrics=b;j=!0}j?this._queueUpdate():this._update()}},_handleRulerEvent:function(j){for(var a=j.target?j.target:j.srcElement,b=a.lineIndex;a&&!a._ruler;){if(b===void 0&&a.lineIndex!==void 0)b=a.lineIndex;a=a.parentNode}var e=a?a._ruler:null;if(b===void 0&&e&&e.getOverview()==="document"){var b= +this._getClientHeight(),c=this._model.getLineCount(),l=this._getViewPadding(),f=this._viewDiv.getBoundingClientRect(),b=Math.floor((j.clientY-f.top-this._metrics.scrollWidth)*c/(b+l.top+l.bottom-2*this._metrics.scrollWidth));0<=b&&b<c||(b=void 0)}if(e)switch(j.type){case "click":if(e.onClick)e.onClick(b,j);break;case "dblclick":if(e.onDblClick)e.onDblClick(b,j);break;case "mousemove":if(e.onMouseMove)e.onMouseMove(b,j);break;case "mouseover":if(e.onMouseOver)e.onMouseOver(b,j);break;case "mouseout":if(e.onMouseOut){for(c= +j.relatedTarget;c&&c!==this._rootDiv;){if(c===a)return;c=c.parentNode}e.onMouseOut(b,j)}}},_handleScroll:function(){var j=this._getScroll(!1),a=this._hScroll,b=this._vScroll;if(a!==j.x||b!==j.y)this._hScroll=j.x,this._vScroll=j.y,this._commitIME(),this._update(b===j.y),this.onScroll({type:"Scroll",oldValue:{x:a,y:b},newValue:j})},_handleSelectStart:function(j){if(this._ignoreSelect)return j&&j.preventDefault&&j.preventDefault(),!1},_getModelOffset:function(j,a){if(j){var b;b=j.tagName==="DIV"?j:j.parentNode.parentNode; +var e=0,c=b.lineIndex;if(j.tagName!=="DIV")for(b=b.firstChild;b;){var l=b.firstChild;if(l===j){b.ignoreChars&&(e-=b.ignoreChars);e+=a;break}b.ignoreChars&&(e-=b.ignoreChars);e+=l.data.length;b=b.nextSibling}return Math.max(0,e)+this._model.getLineStart(c)}},_updateSelectionFromDOM:function(){var j=this._getWindow().getSelection(),a=this._getModelOffset(j.anchorNode,j.anchorOffset),j=this._getModelOffset(j.focusNode,j.focusOffset);a===void 0||j===void 0||this._setSelection(new q(a,j),!1,!1)},_handleSelectionChange:function(){if(this._imeOffset=== +-1)if(f.isAndroid){var j=this._getWindow();this._selTimer&&j.clearTimeout(this._selTimer);var a=this;this._selTimer=j.setTimeout(function(){if(a._clientDiv)a._selTimer=null,a._updateSelectionFromDOM()},250)}else this._updateSelectionFromDOM()},_handleTextInput:function(j){if(!this._ignoreEvent(j)){this._imeOffset=-1;var a=this._getWindow().getSelection();if(a.anchorNode!==this._anchorNode||a.focusNode!==this._focusNode||a.anchorOffset!==this._anchorOffset||a.focusOffset!==this._focusOffset){for(var b= +a.anchorNode;b;){if(b.lineIndex!==void 0)break;b=b.parentNode}if(b){var e=this._model,c=b.lineIndex,l=e.getLine(c),f=l,d=0,e=e.getLineStart(c);if(a.rangeCount>0)a.getRangeAt(0).deleteContents(),c=b.ownerDocument.createTextNode(j.data),a.getRangeAt(0).insertNode(c),d=this._getDOMText(b,c),f=d.text,d=d.offset,c.parentNode.removeChild(c);b.lineRemoved=!0;for(b=0;l.charCodeAt(b)===f.charCodeAt(b)&&b<d;)b++;a=l.length-1;for(c=f.length-l.length;l.charCodeAt(a)===f.charCodeAt(a+c)&&a+c>=d+j.data.length;)a--; +a++;l=f.substring(b,a+c);b+=e;a+=e;this._modifyContent({text:l,start:b,end:a,_ignoreDOMSelection:!0},!0)}}else this._doContent(j.data);j.preventDefault()}},_handleTouchStart:function(j){this._commitIME();var a=this._getWindow();if(this._touchScrollTimer)this._vScrollDiv.style.display="none",this._hScrollDiv.style.display="none",a.clearInterval(this._touchScrollTimer),this._touchScrollTimer=null;var b=j.touches;if(b.length===1){var b=b[0],e=b.clientX,c=b.clientY;this._touchStartX=e;this._touchStartY= +c;if(f.isAndroid&&(c<b.pageY-a.pageYOffset||e<b.pageX-a.pageXOffset))e=b.pageX-a.pageXOffset,c=b.pageY-a.pageYOffset;a=this.convert({x:e,y:c},"page","document");this._lastTouchOffset=this.getOffsetAtLocation(a.x,a.y);this._touchStartTime=j.timeStamp;this._touching=!0}},_handleTouchMove:function(j){var a=j.touches;if(a.length===1){a=a[0];this._touchCurrentX=a.clientX;this._touchCurrentY=a.clientY;if(!this._touchScrollTimer&&j.timeStamp-this._touchStartTime<200){this._vScrollDiv.style.display="block"; +if(!this._wrapMode)this._hScrollDiv.style.display="block";var b=this,e=this._getWindow();this._touchScrollTimer=e.setInterval(function(){var j=0,a=0;if(b._touching)j=b._touchStartX-b._touchCurrentX,a=b._touchStartY-b._touchCurrentY,b._touchSpeedX=j/10,b._touchSpeedY=a/10,b._touchStartX=b._touchCurrentX,b._touchStartY=b._touchCurrentY;else if(Math.abs(b._touchSpeedX)<0.1&&Math.abs(b._touchSpeedY)<0.1){b._vScrollDiv.style.display="none";b._hScrollDiv.style.display="none";e.clearInterval(b._touchScrollTimer); +b._touchScrollTimer=null;return}else j=b._touchSpeedX*10,a=b._touchSpeedY*10,b._touchSpeedX*=0.95,b._touchSpeedY*=0.95;b._scrollView(j,a)},10)}this._touchScrollTimer&&j.preventDefault()}},_handleTouchEnd:function(j){if(j.touches.length===0)this._touching=!1},_doAction:function(j){var a,b,e=this._keyModes;for(b=e.length-1;b>=0;b--)if(a=e[b],typeof a.match==="function"&&(a=a.match(j),a!==void 0))return this.invokeAction(a);return!1},_doMove:function(j,a){var b=this._model,e=a.getCaret(),c=b.getLineAtOffset(e); +if(!j.count)j.count=1;for(;j.count!==0;){var l=b.getLineStart(c);if(j.count<0&&e===l)if(c>0)j.unit==="character"&&j.count++,c--,a.extend(b.getLineEnd(c));else break;else if(j.count>0&&e===b.getLineEnd(c))if(c+1<b.getLineCount())j.unit==="character"&&j.count--,c++,a.extend(b.getLineStart(c));else break;else{var f=!1;j.expandTab&&j.unit==="character"&&(e-l)%this._tabSize===0&&(f=!/[^ ]/.test(b.getText(l,e)));f?(a.extend(e-this._tabSize),j.count+=j.count<0?1:-1):(l=this._getLine(c),a.extend(l.getNextOffset(e, +j)),l.destroy())}e=a.getCaret()}return a},_doBackspace:function(j){var a=this._getSelection();if(a.isEmpty()){if(!j.count)j.count=1;j.count*=-1;j.expandTab=this._expandTab;this._doMove(j,a)}this._modifyContent({text:"",start:a.start,end:a.end},!0);return!0},_doCase:function(j){var a=this._getSelection();this._doMove(j,a);var b=this.getText(a.start,a.end);this._setSelection(a,!0);switch(j.type){case "lower":b=b.toLowerCase();break;case "capitalize":b=b.replace(/(?:^|\s)\S/g,function(j){return j.toUpperCase()}); +break;case "reverse":j="";for(a=0;a<b.length;a++){var e=b[a],c=e.toLowerCase(),e=c!==e?c:e.toUpperCase();j+=e}b=j;break;default:b=b.toUpperCase()}this._doContent(b);return!0},_doContent:function(j){var a=this._getSelection();if(this._overwriteMode&&a.isEmpty()){var b=this._model,e=b.getLineAtOffset(a.end);a.end<b.getLineEnd(e)&&(b=this._getLine(e),a.extend(b.getNextOffset(a.getCaret(),{unit:"character",count:1})),b.destroy())}this._modifyContent({text:j,start:a.start,end:a.end,_ignoreDOMSelection:!0}, +!0)},_doCopy:function(j){var a=this._getSelection();return!a.isEmpty()?this._setClipboardText(this._getBaseText(a.start,a.end),j):!0},_doCursorNext:function(j){var a=this._getSelection();!a.isEmpty()&&!j.select?a.start=a.end:this._doMove(j,a);j.select||a.collapse();this._setSelection(a,!0);return!0},_doCursorPrevious:function(j){var a=this._getSelection();if(!a.isEmpty()&&!j.select)a.end=a.start;else{if(!j.count)j.count=1;j.count*=-1;this._doMove(j,a)}j.select||a.collapse();this._setSelection(a,!0); +return!0},_doCut:function(j){var a=this._getSelection();return!a.isEmpty()?(a=this._getBaseText(a.start,a.end),this._doContent(""),this._setClipboardText(a,j)):!0},_doDelete:function(j){var a=this._getSelection();a.isEmpty()&&this._doMove(j,a);this._modifyContent({text:"",start:a.start,end:a.end},!0);return!0},_doEnd:function(j){var a=this._getSelection(),b=this._model,e;if(j.ctrl)a.extend(b.getCharCount()),e=function(){};else{var c=a.getCaret(),l=b.getLineAtOffset(c);if(this._wrapMode){var f=this._getLine(l), +c=f.getLineIndex(c),c=c===f.getLineCount()-1?b.getLineEnd(l):f.getLineStart(c+1)-1;f.destroy()}else j.count&&j.count>0&&(l=Math.min(l+j.count-1,b.getLineCount()-1)),c=b.getLineEnd(l);a.extend(c)}j.select||a.collapse();this._setSelection(a,!0,!0,e);return!0},_doEnter:function(j){var a=this._model,b=this._getSelection();this._doContent(a.getLineDelimiter());if(j&&j.noCursor)b.end=b.start,this._setSelection(b,!0);return!0},_doHome:function(j){var a=this._getSelection(),b=this._model,e;if(j.ctrl)a.extend(0), +e=function(){};else{var c=a.getCaret(),l=b.getLineAtOffset(c);this._wrapMode?(b=this._getLine(l),c=b.getLineIndex(c),c=b.getLineStart(c),b.destroy()):c=b.getLineStart(l);a.extend(c)}j.select||a.collapse();this._setSelection(a,!0,!0,e);return!0},_doLineDown:function(j){var a=this._model,b=this._getSelection(),e=b.getCaret(),c=a.getLineAtOffset(e),l=this._getLine(c),d=this._columnX,o=1,g=!1;if(d===-1||j.wholeLine||j.select&&f.isIE)d=j.wholeLine?a.getLineEnd(c+1):e,d=l.getBoundingClientRect(d).left; +(e=l.getLineIndex(e))<l.getLineCount()-1?o=l.getClientRects(e+1).top+1:(e=a.getLineCount()-1,g=c===e,j.count&&j.count>0?c=Math.min(c+j.count,e):c++);e=!1;if(g){if(j.select||f.isMac||f.isLinux)b.extend(a.getCharCount()),e=!0}else l.lineIndex!==c&&(l.destroy(),l=this._getLine(c)),b.extend(l.getOffset(d,o)),e=!0;e&&(j.select||b.collapse(),this._setSelection(b,!0,!0));this._columnX=d;l.destroy();return!0},_doLineUp:function(a){var b=this._model,e=this._getSelection(),c=e.getCaret(),l=b.getLineAtOffset(c), +d=this._getLine(l),o=this._columnX,g=!1,h;if(o===-1||a.wholeLine||a.select&&f.isIE)o=a.wholeLine?b.getLineStart(l-1):c,o=d.getBoundingClientRect(o).left;(c=d.getLineIndex(c))>0?h=d.getClientRects(c-1).top+1:(g=l===0,g||(a.count&&a.count>0?l=Math.max(l-a.count,0):l--,h=this._getLineHeight(l)-1));c=!1;if(g){if(a.select||f.isMac||f.isLinux)e.extend(0),c=!0}else d.lineIndex!==l&&(d.destroy(),d=this._getLine(l)),e.extend(d.getOffset(o,h)),c=!0;c&&(a.select||e.collapse(),this._setSelection(e,!0,!0));this._columnX= +o;d.destroy();return!0},_doNoop:function(){return!0},_doPageDown:function(a){var b=this,e=this._model,c=this._getSelection(),l=c.getCaret(),d=e.getLineAtOffset(l),o=e.getLineCount(),g=this._getScroll(),e=this._getClientHeight(),h,p;if(this._lineHeight){h=this._columnX;g=this._getBoundsAtOffset(l);if(h===-1||a.select&&f.isIE)h=g.left;l=this._getLineIndex(g.top+e);p=this._getLine(l);d=this._getLinePixel(l);l=p.getOffset(h,g.top+e-d);e=p.getBoundingClientRect(l);p.destroy();c.extend(l);a.select||c.collapse(); +this._setSelection(c,!0,!0,function(){b._columnX=h},e.top+d-g.top);return!0}if(d<o-1){var i=this._getLineHeight(),q=Math.min(o-d-1,Math.floor(e/i)),q=Math.max(1,q);h=this._columnX;if(h===-1||a.select&&f.isIE)p=this._getLine(d),h=p.getBoundingClientRect(l).left,p.destroy();p=this._getLine(d+q);c.extend(p.getOffset(h,0));p.destroy();a.select||c.collapse();a=o*i;l=g.y+q*i;l+e>a&&(l=a-e);this._setSelection(c,!0,!0,function(){b._columnX=h},l-g.y)}return!0},_doPageUp:function(a){var b=this,e=this._model, +c=this._getSelection(),l=c.getCaret(),d=e.getLineAtOffset(l),o=this._getScroll(),g=this._getClientHeight(),h;if(this._lineHeight){h=this._columnX;o=this._getBoundsAtOffset(l);if(h===-1||a.select&&f.isIE)h=o.left;l=this._getLineIndex(o.bottom-g);e=this._getLine(l);d=this._getLinePixel(l);l=e.getOffset(h,o.bottom-g-d);g=e.getBoundingClientRect(l);e.destroy();c.extend(l);a.select||c.collapse();this._setSelection(c,!0,!0,function(){b._columnX=h},g.top+d-o.top);return!0}if(d>0){var p=this._getLineHeight(), +g=Math.max(1,Math.min(d,Math.floor(g/p)));h=this._columnX;if(h===-1||a.select&&f.isIE)e=this._getLine(d),h=e.getBoundingClientRect(l).left,e.destroy();e=this._getLine(d-g);c.extend(e.getOffset(h,this._getLineHeight(d-g)-1));e.destroy();a.select||c.collapse();a=Math.max(0,o.y-g*p);this._setSelection(c,!0,!0,function(){b._columnX=h},a-o.y)}return!0},_doPaste:function(a){var b=this;return this._getClipboardText(a,function(a){a&&(f.isLinux&&b._lastMouseButton===2&&(new Date).getTime()-b._lastMouseTime<= +b._clickTime&&b._setSelectionTo(b._lastMouseX,b._lastMouseY),b._doContent(a))})!==null},_doScroll:function(a){var b=a.type,e=this._model,c=e.getLineCount(),a=this._getClientHeight(),l=this._getLineHeight();c*=l;var f=this._getScroll().y,d;switch(b){case "textStart":d=0;break;case "textEnd":d=c-a;break;case "pageDown":d=f+a;break;case "pageUp":d=f-a;break;case "lineDown":d=f+l;break;case "lineUp":d=f-l;break;case "centerLine":b=this._getSelection(),d=e.getLineAtOffset(b.start),e=(e.getLineAtOffset(b.end)- +d+1)*l,d=d*l-a/2+e/2}d!==void 0&&(d=Math.min(Math.max(0,d),c-a),this._scrollViewAnimated(0,d-f,function(){}));return!0},_doSelectAll:function(){var a=this._model,b=this._getSelection();b.setCaret(0);b.extend(a.getCharCount());this._setSelection(b,!1);return!0},_doTab:function(){if(this._tabMode&&!this._readonly){var a="\t";if(this._expandTab)var b=this._model,a=this._getSelection().getCaret(),e=b.getLineAtOffset(a),b=b.getLineStart(e),a=Array(this._tabSize-(a-b)%this._tabSize+1).join(" ");this._doContent(a); +return!0}},_doShiftTab:function(){return!this._tabMode||this._readonly?void 0:!0},_doOverwriteMode:function(){if(!this._readonly)return this.setOptions({overwriteMode:!this.getOptions("overwriteMode")}),!0},_doTabMode:function(){this._tabMode=!this._tabMode;return!0},_doWrapMode:function(){this.setOptions({wrapMode:!this.getOptions("wrapMode")});return!0},_autoScroll:function(){var a=this._model,b=this._getSelection(),e=this.convert({x:this._autoScrollX,y:this._autoScrollY},"page","document"),c=b.getCaret(), +l=a.getLineCount(),d=a.getLineAtOffset(c),o;if(this._autoScrollDir==="up"||this._autoScrollDir==="down")c=this._autoScrollY/this._getLineHeight(),c=c<0?Math.floor(c):Math.ceil(c),o=Math.max(0,Math.min(l-1,d+c));else if(this._autoScrollDir==="left"||this._autoScrollDir==="right")o=this._getLineIndex(e.y),d=this._getLine(d),e.x+=d.getBoundingClientRect(c,!1).left,d.destroy();o===0&&(f.isMac||f.isLinux)?b.extend(0):o===l-1&&(f.isMac||f.isLinux)?b.extend(a.getCharCount()):(d=this._getLine(o),b.extend(d.getOffset(e.x, +e.y-this._getLinePixel(o))),d.destroy());this._setSelection(b,!0)},_autoScrollTimer:function(){this._autoScroll();var a=this;this._autoScrollTimerID=this._getWindow().setTimeout(function(){a._autoScrollTimer()},this._AUTO_SCROLL_RATE)},_calculateLineHeightTimer:function(a){if(this._lineHeight&&!this._calculateLHTimer){var b=this._model.getLineCount(),e=0;if(a){for(var a=0,c=(new Date).getTime(),l=0;e<b;)if(this._lineHeight[e]||(a++,l||(l=e),this._lineHeight[e]=this._calculateLineHeight(e)),e++,(new Date).getTime()- +c>100)break;this.redrawRulers(0,b);this._queueUpdate()}a=this._getWindow();if(e!==b){var f=this;this._calculateLHTimer=a.setTimeout(function(){f._calculateLHTimer=null;f._calculateLineHeightTimer(!0)},0)}else if(this._calculateLHTimer)a.clearTimeout(this._calculateLHTimer),this._calculateLHTimer=void 0}},_calculateLineHeight:function(a){var a=this._getLine(a),b=a.getBoundingClientRect();a.destroy();return Math.max(1,b.bottom-b.top)},_calculateMetrics:function(){var a=this._clientDiv,b=a.ownerDocument, +e=f.createElement(b,"div");e.style.lineHeight="normal";var c={type:"LineStyle",textView:this,0:0,lineText:this._model.getLine(0),lineStart:0};this.onLineStyle(c);g(c.style,e);e.style.position="fixed";e.style.left="-1000px";var d=f.createElement(b,"span");d.appendChild(b.createTextNode(" "));e.appendChild(d);var h=f.createElement(b,"span");h.style.fontStyle="italic";h.appendChild(b.createTextNode(" "));e.appendChild(h);var p=f.createElement(b,"span");p.style.fontWeight="bold";p.appendChild(b.createTextNode(" ")); +e.appendChild(p);c=f.createElement(b,"span");c.style.fontWeight="bold";c.style.fontStyle="italic";c.appendChild(b.createTextNode(" "));e.appendChild(c);a.appendChild(e);var i=e.getBoundingClientRect(),d=d.getBoundingClientRect(),h=h.getBoundingClientRect(),p=p.getBoundingClientRect(),c=c.getBoundingClientRect(),d=d.bottom-d.top,h=h.bottom-h.top,p=p.bottom-p.top,q=c.bottom-c.top,r=0,c=i.bottom-i.top<=0,i=Math.max(1,i.bottom-i.top);h>d&&(r=1);p>h&&(r=2);q>p&&(r=3);var s;if(r!==0){s={style:{}};if((r& +1)!==0)s.style.fontStyle="italic";if((r&2)!==0)s.style.fontWeight="bold"}d=o(e);a.removeChild(e);q=l(this._viewDiv);e=f.createElement(b,"div");e.style.position="fixed";e.style.left="-1000px";e.style.paddingLeft=q.left+"px";e.style.paddingTop=q.top+"px";e.style.paddingRight=q.right+"px";e.style.paddingBottom=q.bottom+"px";e.style.width="100px";e.style.height="100px";q=f.createElement(b,"div");q.style.width="100%";q.style.height="100%";e.appendChild(q);a.appendChild(e);r=e.getBoundingClientRect();h= +q.getBoundingClientRect();p=0;if(!this._singleMode)e.style.overflow="hidden",q.style.height="200px",p=e.clientWidth,e.style.overflow="scroll",p-=e.clientWidth;a.removeChild(e);q={left:h.left-r.left,top:h.top-r.top,right:r.right-h.right,bottom:r.bottom-h.bottom};h=r=0;if(!c&&(this._wrapOffset||this._marginOffset))e=f.createElement(b,"div"),e.style.position="fixed",e.style.left="-1000px",e.innerHTML=Array(this._wrapOffset+1).join(" "),a.appendChild(e),r=e.getBoundingClientRect(),r=Math.ceil(r.right- +r.left),e.innerHTML=Array(this._marginOffset+1).join(" "),h=e.getBoundingClientRect(),h=Math.ceil(h.right-h.left),a.removeChild(e);return{lineHeight:i,largestFontStyle:s,lineTrim:d,viewPadding:q,scrollWidth:p,wrapWidth:r,marginWidth:h,invalid:c}},_cancelAnimation:function(){if(this._animation)this._animation.stop(),this._animation=null},_clearSelection:function(a){var b=this._getSelection();if(b.isEmpty())return!1;a==="next"?b.start=b.end:b.end=b.start;this._setSelection(b,!0);return!0},_commitIME:function(){if(this._imeOffset!== +-1){this._scrollDiv.focus();this._clientDiv.focus();var a=this._model,b=a.getLineAtOffset(this._imeOffset),e=a.getLineStart(b),c=this._getDOMText(this._getLineNode(b)).text,a=a.getLine(b),e=this._imeOffset-e,a=e+c.length-a.length;e!==a&&this._doContent(c.substring(e,a));this._imeOffset=-1}},_createActions:function(){this.addKeyMode(new n.DefaultKeyMode(this));var a=this;this._actions={noop:{defaultHandler:function(){return a._doNoop()}},lineUp:{defaultHandler:function(e){return a._doLineUp(b(e,{select:!1}))}, +actionDescription:{name:k.lineUp}},lineDown:{defaultHandler:function(e){return a._doLineDown(b(e,{select:!1}))},actionDescription:{name:k.lineDown}},lineStart:{defaultHandler:function(e){return a._doHome(b(e,{select:!1,ctrl:!1}))},actionDescription:{name:k.lineStart}},lineEnd:{defaultHandler:function(e){return a._doEnd(b(e,{select:!1,ctrl:!1}))},actionDescription:{name:k.lineEnd}},charPrevious:{defaultHandler:function(e){return a._doCursorPrevious(b(e,{select:!1,unit:"character"}))},actionDescription:{name:k.charPrevious}}, +charNext:{defaultHandler:function(e){return a._doCursorNext(b(e,{select:!1,unit:"character"}))},actionDescription:{name:k.charNext}},pageUp:{defaultHandler:function(e){return a._doPageUp(b(e,{select:!1}))},actionDescription:{name:k.pageUp}},pageDown:{defaultHandler:function(e){return a._doPageDown(b(e,{select:!1}))},actionDescription:{name:k.pageDown}},scrollPageUp:{defaultHandler:function(e){return a._doScroll(b(e,{type:"pageUp"}))},actionDescription:{name:k.scrollPageUp}},scrollPageDown:{defaultHandler:function(e){return a._doScroll(b(e, +{type:"pageDown"}))},actionDescription:{name:k.scrollPageDown}},scrollLineUp:{defaultHandler:function(e){return a._doScroll(b(e,{type:"lineUp"}))},actionDescription:{name:k.scrollLineUp}},scrollLineDown:{defaultHandler:function(e){return a._doScroll(b(e,{type:"lineDown"}))},actionDescription:{name:k.scrollLineDown}},wordPrevious:{defaultHandler:function(e){return a._doCursorPrevious(b(e,{select:!1,unit:"word"}))},actionDescription:{name:k.wordPrevious}},wordNext:{defaultHandler:function(e){return a._doCursorNext(b(e, +{select:!1,unit:"word"}))},actionDescription:{name:k.wordNext}},textStart:{defaultHandler:function(e){return a._doHome(b(e,{select:!1,ctrl:!0}))},actionDescription:{name:k.textStart}},textEnd:{defaultHandler:function(e){return a._doEnd(b(e,{select:!1,ctrl:!0}))},actionDescription:{name:k.textEnd}},scrollTextStart:{defaultHandler:function(e){return a._doScroll(b(e,{type:"textStart"}))},actionDescription:{name:k.scrollTextStart}},scrollTextEnd:{defaultHandler:function(e){return a._doScroll(b(e,{type:"textEnd"}))}, +actionDescription:{name:k.scrollTextEnd}},centerLine:{defaultHandler:function(e){return a._doScroll(b(e,{type:"centerLine"}))},actionDescription:{name:k.centerLine}},selectLineUp:{defaultHandler:function(e){return a._doLineUp(b(e,{select:!0}))},actionDescription:{name:k.selectLineUp}},selectLineDown:{defaultHandler:function(e){return a._doLineDown(b(e,{select:!0}))},actionDescription:{name:k.selectLineDown}},selectWholeLineUp:{defaultHandler:function(e){return a._doLineUp(b(e,{select:!0,wholeLine:!0}))}, +actionDescription:{name:k.selectWholeLineUp}},selectWholeLineDown:{defaultHandler:function(e){return a._doLineDown(b(e,{select:!0,wholeLine:!0}))},actionDescription:{name:k.selectWholeLineDown}},selectLineStart:{defaultHandler:function(e){return a._doHome(b(e,{select:!0,ctrl:!1}))},actionDescription:{name:k.selectLineStart}},selectLineEnd:{defaultHandler:function(e){return a._doEnd(b(e,{select:!0,ctrl:!1}))},actionDescription:{name:k.selectLineEnd}},selectCharPrevious:{defaultHandler:function(e){return a._doCursorPrevious(b(e, +{select:!0,unit:"character"}))},actionDescription:{name:k.selectCharPrevious}},selectCharNext:{defaultHandler:function(e){return a._doCursorNext(b(e,{select:!0,unit:"character"}))},actionDescription:{name:k.selectCharNext}},selectPageUp:{defaultHandler:function(e){return a._doPageUp(b(e,{select:!0}))},actionDescription:{name:k.selectPageUp}},selectPageDown:{defaultHandler:function(e){return a._doPageDown(b(e,{select:!0}))},actionDescription:{name:k.selectPageDown}},selectWordPrevious:{defaultHandler:function(e){return a._doCursorPrevious(b(e, +{select:!0,unit:"word"}))},actionDescription:{name:k.selectWordPrevious}},selectWordNext:{defaultHandler:function(e){return a._doCursorNext(b(e,{select:!0,unit:"word"}))},actionDescription:{name:k.selectWordNext}},selectTextStart:{defaultHandler:function(e){return a._doHome(b(e,{select:!0,ctrl:!0}))},actionDescription:{name:k.selectTextStart}},selectTextEnd:{defaultHandler:function(e){return a._doEnd(b(e,{select:!0,ctrl:!0}))},actionDescription:{name:k.selectTextEnd}},deletePrevious:{defaultHandler:function(e){return a._doBackspace(b(e, +{unit:"character"}))},actionDescription:{name:k.deletePrevious}},deleteNext:{defaultHandler:function(e){return a._doDelete(b(e,{unit:"character"}))},actionDescription:{name:k.deleteNext}},deleteWordPrevious:{defaultHandler:function(e){return a._doBackspace(b(e,{unit:"word"}))},actionDescription:{name:k.deleteWordPrevious}},deleteWordNext:{defaultHandler:function(e){return a._doDelete(b(e,{unit:"word"}))},actionDescription:{name:k.deleteWordNext}},deleteLineStart:{defaultHandler:function(e){return a._doBackspace(b(e, +{unit:"line"}))},actionDescription:{name:k.deleteLineStart}},deleteLineEnd:{defaultHandler:function(e){return a._doDelete(b(e,{unit:"line"}))},actionDescription:{name:k.deleteLineEnd}},tab:{defaultHandler:function(){return a._doTab()},actionDescription:{name:k.tab}},shiftTab:{defaultHandler:function(){return a._doShiftTab()},actionDescription:{name:k.shiftTab}},enter:{defaultHandler:function(){return a._doEnter()},actionDescription:{name:k.enter}},enterNoCursor:{defaultHandler:function(e){return a._doEnter(b(e, +{noCursor:!0}))},actionDescription:{name:k.enterNoCursor}},selectAll:{defaultHandler:function(){return a._doSelectAll()},actionDescription:{name:k.selectAll}},copy:{defaultHandler:function(){return a._doCopy()},actionDescription:{name:k.copy}},cut:{defaultHandler:function(){return a._doCut()},actionDescription:{name:k.cut}},paste:{defaultHandler:function(){return a._doPaste()},actionDescription:{name:k.paste}},uppercase:{defaultHandler:function(e){return a._doCase(b(e,{type:"upper"}))},actionDescription:{name:k.uppercase}}, +lowercase:{defaultHandler:function(e){return a._doCase(b(e,{type:"lower"}))},actionDescription:{name:k.lowercase}},capitalize:{defaultHandler:function(e){return a._doCase(b(e,{unit:"word",type:"capitalize"}))},actionDescription:{name:k.capitalize}},reversecase:{defaultHandler:function(e){return a._doCase(b(e,{type:"reverse"}))},actionDescription:{name:k.reversecase}},toggleOverwriteMode:{defaultHandler:function(){return a._doOverwriteMode()},actionDescription:{name:k.toggleOverwriteMode}},toggleTabMode:{defaultHandler:function(){return a._doTabMode()}, +actionDescription:{name:k.toggleTabMode}},toggleWrapMode:{defaultHandler:function(){return a._doWrapMode()},actionDescription:{name:k.toggleWrapMode}}}},_createRulerParent:function(a){var b=f.createElement(document,"div");b.className=a;b.tabIndex=-1;b.style.overflow="hidden";b.style.MozUserSelect="none";b.style.WebkitUserSelect="none";b.style.position="absolute";b.style.top="0px";b.style.bottom="0px";b.style.cursor="default";b.style.display="none";b.setAttribute("aria-hidden","true");this._rootDiv.appendChild(b); +return b},_createRuler:function(a,b){if(this._clientDiv){var e=this._getRulerParent(a);if(e){if(e!==this._marginDiv||this._marginOffset)e.style.display="block";var c=f.createElement(e.ownerDocument,"div");c._ruler=a;c.rulerChanged=!0;c.style.position="relative";c.style.cssFloat="left";c.style.styleFloat="left";c.style.outline="none";if(b===void 0||b<0||b>=e.children.length)e.appendChild(c);else{for(var l=e.firstChild;l&&b-- >0;)l=l.nextSibling;e.insertBefore(c,l)}}}},_createView:function(){if(!this._clientDiv){for(var a= +this._parent;a.hasChildNodes();)a.removeChild(a.lastChild);var b=a.ownerDocument,e=f.createElement(b,"div");this._rootDiv=e;e.tabIndex=-1;e.style.position="relative";e.style.overflow="hidden";e.style.width="100%";e.style.height="100%";e.style.overflow="hidden";e.style.WebkitTextSizeAdjust="100%";e.setAttribute("role","application");a.appendChild(e);this._leftDiv=this._createRulerParent("textviewLeftRuler");a=f.createElement(b,"div");a.className="textviewScroll";this._viewDiv=a;a.tabIndex=-1;a.style.position= +"absolute";a.style.top="0px";a.style.bottom="0px";a.style.borderWidth="0px";a.style.margin="0px";a.style.outline="none";a.style.background="transparent";if(f.isMac&&f.isWebkit)a.style.pointerEvents="none",a.style.zIndex="2";e.appendChild(a);var c=this._createRulerParent("textviewRightRuler");this._rightDiv=c;c.style.right="0px";this._scrollDiv=c=f.createElement(b,"div");c.style.margin="0px";c.style.borderWidth="0px";c.style.padding="0px";a.appendChild(c);(this._marginDiv=this._createRulerParent("textviewMarginRuler")).style.zIndex= +"4";if(!f.isIE&&!f.isIOS)this._clipDiv=a=f.createElement(b,"div"),a.style.position="absolute",a.style.overflow="hidden",a.style.margin="0px",a.style.borderWidth="0px",a.style.padding="0px",a.style.background="transparent",e.appendChild(a),this._clipScrollDiv=c=f.createElement(b,"div"),c.style.position="absolute",c.style.height="1px",c.style.top="-1000px",c.style.background="transparent",a.appendChild(c);this._setFullSelection(this._fullSelection,!0);a=f.createElement(b,"div");a.className="textviewContent"; +this._clientDiv=a;a.tabIndex=0;a.style.position="absolute";a.style.borderWidth="0px";a.style.margin="0px";a.style.padding="0px";a.style.outline="none";a.style.zIndex="1";a.style.WebkitUserSelect="text";a.setAttribute("spellcheck","false");if(f.isIOS||f.isAndroid)a.style.WebkitTapHighlightColor="transparent";(this._clipDiv||e).appendChild(a);if(f.isIOS||f.isAndroid)this._vScrollDiv=c=f.createElement(b,"div"),c.style.position="absolute",c.style.borderWidth="1px",c.style.borderColor="white",c.style.borderStyle= +"solid",c.style.borderRadius="4px",c.style.backgroundColor="black",c.style.opacity="0.5",c.style.margin="0px",c.style.padding="0px",c.style.outline="none",c.style.zIndex="3",c.style.width="8px",c.style.display="none",e.appendChild(c),this._hScrollDiv=c=f.createElement(b,"div"),c.style.position="absolute",c.style.borderWidth="1px",c.style.borderColor="white",c.style.borderStyle="solid",c.style.borderRadius="4px",c.style.backgroundColor="black",c.style.opacity="0.5",c.style.margin="0px",c.style.padding= +"0px",c.style.outline="none",c.style.zIndex="3",c.style.height="8px",c.style.display="none",e.appendChild(c);if(f.isFirefox&&!a.setCapture)this._overlayDiv=b=f.createElement(b,"div"),b.style.position=a.style.position,b.style.borderWidth=a.style.borderWidth,b.style.margin=a.style.margin,b.style.padding=a.style.padding,b.style.cursor="text",b.style.zIndex="2",(this._clipDiv||e).appendChild(b);a.contentEditable="true";a.setAttribute("role","textbox");a.setAttribute("aria-multiline","true");this._setWrapMode(this._wrapMode, +!0);this._setReadOnly(this._readonly);this._setThemeClass(this._themeClass,!0);this._setTabSize(this._tabSize,!0);this._setMarginOffset(this._marginOffset,!0);this._hookEvents();e=this._rulers;for(b=0;b<e.length;b++)this._createRuler(e[b]);this._update()}},_defaultOptions:function(){return{parent:{value:void 0,update:null},model:{value:void 0,update:this.setModel},scrollAnimation:{value:0,update:null},readonly:{value:!1,update:this._setReadOnly},fullSelection:{value:!0,update:this._setFullSelection}, +tabMode:{value:!0,update:null},tabSize:{value:8,update:this._setTabSize},expandTab:{value:!1,update:null},singleMode:{value:!1,update:this._setSingleMode},overwriteMode:{value:!1,update:this._setOverwriteMode},blockCursorVisible:{value:!1,update:this._setBlockCursor},marginOffset:{value:0,update:this._setMarginOffset},wrapOffset:{value:0,update:this._setWrapOffset},wrapMode:{value:!1,update:this._setWrapMode},wrappable:{value:!1,update:null},theme:{value:c.TextTheme.getTheme(),update:this._setTheme}, +themeClass:{value:void 0,update:this._setThemeClass}}},_destroyRuler:function(a){var b=this._getRulerParent(a);if(b)for(var e=b.firstChild;e;){if(e._ruler===a){e._ruler=void 0;b.removeChild(e);if(b.children.length===0&&(b!==this._marginDiv||!this._marginOffset))b.style.display="none";break}e=e.nextSibling}},_destroyView:function(){if(this._clientDiv){this._setGrab(null);this._unhookEvents();var a=this._getWindow();if(this._autoScrollTimerID)a.clearTimeout(this._autoScrollTimerID),this._autoScrollTimerID= +null;if(this._updateTimer)a.clearTimeout(this._updateTimer),this._updateTimer=null;a=this._rootDiv;a.parentNode.removeChild(a);this._hScrollDiv=this._vScrollDiv=this._cursorDiv=this._marginDiv=this._rightDiv=this._leftDiv=this._overlayDiv=this._clientDiv=this._clipScrollDiv=this._clipDiv=this._viewDiv=this._scrollDiv=this._rootDiv=this._clipboardDiv=this._selDiv3=this._selDiv2=this._selDiv1=null}},_doAutoScroll:function(a,b,e){this._autoScrollDir=a;this._autoScrollX=b;this._autoScrollY=e;this._autoScrollTimerID|| +this._autoScrollTimer()},_endAutoScroll:function(){this._autoScrollTimerID&&this._getWindow().clearTimeout(this._autoScrollTimerID);this._autoScrollTimerID=this._autoScrollDir=void 0},_fixCaret:function(){var a=this._clientDiv;if(a){var b=this._hasFocus;this._ignoreFocus=!0;b&&a.blur();a.contentEditable=!1;a.contentEditable=!0;b&&a.focus();this._ignoreFocus=!1}},_getBaseText:function(a,b){var e=this._model;e.getBaseModel&&(a=e.mapOffset(a),b=e.mapOffset(b),e=e.getBaseModel());return e.getText(a,b)}, +_getBottomIndex:function(a){var b=this._bottomChild;if(a&&this._getClientHeight()>this._getLineHeight()){var a=b.getBoundingClientRect(),e=this._clientDiv.getBoundingClientRect();a.bottom>e.bottom&&(b=this._getLinePrevious(b)||b)}return b.lineIndex},_getBoundsAtOffset:function(a){var b=this._getLine(this._model.getLineAtOffset(a)),a=b.getBoundingClientRect(a),e=this._getLinePixel(b.lineIndex);a.top+=e;a.bottom+=e;b.destroy();return a},_getClientHeight:function(){var a=this._getViewPadding();return Math.max(0, +this._viewDiv.clientHeight-a.top-a.bottom)},_getClientWidth:function(){var a=this._getViewPadding();return Math.max(0,this._viewDiv.clientWidth-a.left-a.right)},_getClipboardText:function(a,b){var c=this._model.getLineDelimiter(),l,d,o=this._getWindow(),g=o.clipboardData;if(!g&&a)g=a.clipboardData;if(g)return l=[],d=g.getData(f.isIE?"Text":"text/plain"),e(d,function(a){l.push(a)},function(){l.push(c)}),d=l.join(""),b&&b(d),d;if(f.isFirefox){this._ignoreFocus=!0;var h=this._clipboardDiv,g=this._rootDiv.ownerDocument; +if(!h)this._clipboardDiv=h=f.createElement(g,"div"),h.style.position="fixed",h.style.whiteSpace="pre",h.style.left="-1000px",this._rootDiv.appendChild(h);h.innerHTML="<pre contenteditable=''></pre>";h.firstChild.focus();var p=this,i=function(){var a=p._getTextFromElement(h);h.innerHTML="";l=[];e(a,function(a){l.push(a)},function(){l.push(c)});return l.join("")},q=!1;this._ignorePaste=!0;if(!f.isLinux||this._lastMouseButton!==2)try{q=g.execCommand("paste",!1,null)}catch(r){q=h.childNodes.length>1|| +h.firstChild&&h.firstChild.childNodes.length>0}this._ignorePaste=!1;if(!q)return a?(o.setTimeout(function(){p.focus();(d=i())&&b&&b(d);p._ignoreFocus=!1},0),null):(this.focus(),this._ignoreFocus=!1,"");this.focus();this._ignoreFocus=!1;(d=i())&&b&&b(d);return d}return""},_getDOMText:function(a,b){for(var e=a.firstChild,c="",l=0;e;){var f;if(!e.ignore)if(e.ignoreChars){f=e.lastChild;for(var d=0,o=[],g=-1;f;){var h=f.data;if(h)for(var p=h.length-1;p>=0;p--){var i=h.substring(p,p+1);d<e.ignoreChars&& +(i===" "||i==="\u200b"||i==="\ufeff")?d++:o.push(i==="\u00a0"?"\t":i)}if(b===f)g=o.length;f=f.previousSibling}o=o.reverse().join("");g!==-1&&(l=c.length+o.length-g);c+=o}else for(f=e.firstChild;f;){if(b===f)l=c.length;c+=f.data;f=f.nextSibling}e=e.nextSibling}return{text:c,offset:l}},_getTextFromElement:function(a){var b=a.ownerDocument,e=b.defaultView;if(!e.getSelection)return a.innerText||a.textContent;b=b.createRange();b.selectNode(a);var a=e.getSelection(),e=[],c;for(c=0;c<a.rangeCount;c++)e.push(a.getRangeAt(c)); +this._ignoreSelect=!0;a.removeAllRanges();a.addRange(b);b=a.toString();a.removeAllRanges();for(c=0;c<e.length;c++)a.addRange(e[c]);this._ignoreSelect=!1;return b},_getViewPadding:function(){return this._metrics.viewPadding},_getLine:function(a){var b=this._getLineNode(a);return b&&!b.lineChanged&&!b.lineRemoved?b._line:new p(this,a)},_getLineHeight:function(a,b){if(a!==void 0&&this._lineHeight){var e=this._lineHeight[a];if(e)return e;if(b||b===void 0)return this._lineHeight[a]=this._calculateLineHeight(a)}return this._metrics.lineHeight}, +_getLineNode:function(a){for(var b=this._clientDiv.firstChild;b;){if(a===b.lineIndex)return b;b=b.nextSibling}},_getLineNext:function(a){for(a=a?a.nextSibling:this._clientDiv.firstChild;a&&a.lineIndex===-1;)a=a.nextSibling;return a},_getLinePrevious:function(a){for(a=a?a.previousSibling:this._clientDiv.lastChild;a&&a.lineIndex===-1;)a=a.previousSibling;return a},_getLinePixel:function(a){a=Math.min(Math.max(0,a),this._model.getLineCount());if(this._lineHeight){var b=this._getTopIndex(),e=-this._topIndexY+ +this._getScroll().y;if(a>b)for(;b<a;b++)e+=this._getLineHeight(b);else for(b-=1;b>=a;b--)e-=this._getLineHeight(b);return e}return this._getLineHeight()*a},_getLineIndex:function(a){var b,e=0,c=this._model.getLineCount();if(this._lineHeight){var e=this._getTopIndex(),l=-this._topIndexY+this._getScroll().y;if(a!==l)if(a<l)for(;a<l&&e>0;)a+=this._getLineHeight(--e);else for(b=this._getLineHeight(e);a-b>=l&&e<c-1;)a-=b,b=this._getLineHeight(++e)}else b=this._getLineHeight(),e=Math.floor(a/b);return Math.max(0, +Math.min(c-1,e))},_getRulerParent:function(a){switch(a.getLocation()){case "left":return this._leftDiv;case "right":return this._rightDiv;case "margin":return this._marginDiv}return null},_getScroll:function(a){(a===void 0||a)&&this._cancelAnimation();a=this._viewDiv;return{x:a.scrollLeft,y:a.scrollTop}},_getSelection:function(){return this._selection.clone()},_getTopIndex:function(a){var b=this._topChild;if(a&&this._getClientHeight()>this._getLineHeight()){var a=b.getBoundingClientRect(),e=this._getViewPadding(), +c=this._viewDiv.getBoundingClientRect();a.top<c.top+e.top&&(b=this._getLineNext(b)||b)}return b.lineIndex},_hookEvents:function(){var a=this;this._modelListener={onChanging:function(b){a._onModelChanging(b)},onChanged:function(b){a._onModelChanged(b)}};this._model.addEventListener("preChanging",this._modelListener.onChanging);this._model.addEventListener("postChanged",this._modelListener.onChanged);this._themeListener={onChanged:function(){a._setThemeClass(a._themeClass)}};this._theme.addEventListener("ThemeChanged", +this._themeListener.onChanged);var b=this._handlers=[],e=this._clientDiv,c=this._viewDiv,l=this._rootDiv,d=this._overlayDiv||e,o=e.ownerDocument,g=this._getWindow(),h=f.isIE?o:g;b.push({target:g,type:"resize",handler:function(b){return a._handleResize(b?b:g.event)}});b.push({target:e,type:"blur",handler:function(b){return a._handleBlur(b?b:g.event)}});b.push({target:e,type:"focus",handler:function(b){return a._handleFocus(b?b:g.event)}});b.push({target:c,type:"focus",handler:function(){e.focus()}}); +b.push({target:c,type:"scroll",handler:function(b){return a._handleScroll(b?b:g.event)}});b.push({target:e,type:"textInput",handler:function(b){return a._handleTextInput(b?b:g.event)}});b.push({target:e,type:"keydown",handler:function(b){return a._handleKeyDown(b?b:g.event)}});b.push({target:e,type:"keypress",handler:function(b){return a._handleKeyPress(b?b:g.event)}});b.push({target:e,type:"keyup",handler:function(b){return a._handleKeyUp(b?b:g.event)}});f.isIE&&b.push({target:o,type:"keyup",handler:function(b){return a._handleDocKeyUp(b? +b:g.event)}});b.push({target:e,type:"contextmenu",handler:function(b){return a._handleContextMenu(b?b:g.event)}});b.push({target:e,type:"copy",handler:function(b){return a._handleCopy(b?b:g.event)}});b.push({target:e,type:"cut",handler:function(b){return a._handleCut(b?b:g.event)}});b.push({target:e,type:"paste",handler:function(b){return a._handlePaste(b?b:g.event)}});if(f.isIOS||f.isAndroid)b.push({target:o,type:"selectionchange",handler:function(b){return a._handleSelectionChange(b?b:g.event)}}), +b.push({target:e,type:"touchstart",handler:function(b){return a._handleTouchStart(b?b:g.event)}}),b.push({target:e,type:"touchmove",handler:function(b){return a._handleTouchMove(b?b:g.event)}}),b.push({target:e,type:"touchend",handler:function(b){return a._handleTouchEnd(b?b:g.event)}});else{b.push({target:e,type:"selectstart",handler:function(b){return a._handleSelectStart(b?b:g.event)}});b.push({target:e,type:"mousedown",handler:function(b){return a._handleMouseDown(b?b:g.event)}});b.push({target:e, +type:"mouseover",handler:function(b){return a._handleMouseOver(b?b:g.event)}});b.push({target:e,type:"mouseout",handler:function(b){return a._handleMouseOut(b?b:g.event)}});b.push({target:h,type:"mouseup",handler:function(b){return a._handleMouseUp(b?b:g.event)}});b.push({target:h,type:"mousemove",handler:function(b){return a._handleMouseMove(b?b:g.event)}});b.push({target:l,type:"mousedown",handler:function(b){return a._handleRootMouseDown(b?b:g.event)}});b.push({target:l,type:"mouseup",handler:function(b){return a._handleRootMouseUp(b? +b:g.event)}});b.push({target:d,type:"dragstart",handler:function(b){return a._handleDragStart(b?b:g.event)}});b.push({target:d,type:"drag",handler:function(b){return a._handleDrag(b?b:g.event)}});b.push({target:d,type:"dragend",handler:function(b){return a._handleDragEnd(b?b:g.event)}});b.push({target:d,type:"dragenter",handler:function(b){return a._handleDragEnter(b?b:g.event)}});b.push({target:d,type:"dragover",handler:function(b){return a._handleDragOver(b?b:g.event)}});b.push({target:d,type:"dragleave", +handler:function(b){return a._handleDragLeave(b?b:g.event)}});b.push({target:d,type:"drop",handler:function(b){return a._handleDrop(b?b:g.event)}});b.push({target:this._clientDiv,type:f.isFirefox?"DOMMouseScroll":"mousewheel",handler:function(b){return a._handleMouseWheel(b?b:g.event)}});this._clipDiv&&b.push({target:this._clipDiv,type:f.isFirefox?"DOMMouseScroll":"mousewheel",handler:function(b){return a._handleMouseWheel(b?b:g.event)}});if(f.isFirefox&&(!f.isWindows||f.isFirefox>=15))(c=g.MutationObserver|| +g.MozMutationObserver)?(this._mutationObserver=new c(function(b){a._handleDataModified(b)}),this._mutationObserver.observe(e,{subtree:!0,characterData:!0})):b.push({target:this._clientDiv,type:"DOMCharacterDataModified",handler:function(b){return a._handleDataModified(b?b:g.event)}});this._overlayDiv&&(b.push({target:this._overlayDiv,type:"mousedown",handler:function(b){return a._handleMouseDown(b?b:g.event)}}),b.push({target:this._overlayDiv,type:"mouseover",handler:function(b){return a._handleMouseOver(b? +b:g.event)}}),b.push({target:this._overlayDiv,type:"mouseout",handler:function(b){return a._handleMouseOut(b?b:g.event)}}),b.push({target:this._overlayDiv,type:"contextmenu",handler:function(b){return a._handleContextMenu(b?b:g.event)}}));this._isW3CEvents||b.push({target:this._clientDiv,type:"dblclick",handler:function(b){return a._handleDblclick(b?b:g.event)}})}this._hookRulerEvents(this._leftDiv,b);this._hookRulerEvents(this._rightDiv,b);this._hookRulerEvents(this._marginDiv,b);for(c=0;c<b.length;c++)l= +b[c],v(l.target,l.type,l.handler,l.capture)},_hookRulerEvents:function(a,b){if(a){var e=this,c=this._getWindow();f.isIE&&b.push({target:a,type:"selectstart",handler:function(){return!1}});b.push({target:a,type:f.isFirefox?"DOMMouseScroll":"mousewheel",handler:function(a){return e._handleMouseWheel(a?a:c.event)}});b.push({target:a,type:"click",handler:function(a){e._handleRulerEvent(a?a:c.event)}});b.push({target:a,type:"dblclick",handler:function(a){e._handleRulerEvent(a?a:c.event)}});b.push({target:a, +type:"mousemove",handler:function(a){e._handleRulerEvent(a?a:c.event)}});b.push({target:a,type:"mouseover",handler:function(a){e._handleRulerEvent(a?a:c.event)}});b.push({target:a,type:"mouseout",handler:function(a){e._handleRulerEvent(a?a:c.event)}})}},_getWindow:function(){return this._parent.ownerDocument.defaultView||this._parent.ownerDocument.parentWindow},_ignoreEvent:function(a){for(a=a.target;a&&a!==this._clientDiv;){if(a.ignore)return!0;a=a.parentNode}return!1},_init:function(a){var b=a.parent; +typeof b==="string"&&(b=(a.document||document).getElementById(b));if(!b)throw"no parent";a.parent=b;a.model=a.model||new m.TextModel;var e=this._defaultOptions(),c;for(c in e)e.hasOwnProperty(c)&&(this["_"+c]=a[c]!==void 0?a[c]:e[c].value);this._keyModes=[];this._rulers=[];this._selection=new q(0,0,!1);this._linksVisible=!1;this._maxLineWidth=this._redrawCount=0;this._maxLineIndex=-1;this._ignoreSelect=!0;this._hasFocus=this._ignoreFocus=!1;this._dragOffset=this._columnX=-1;this._isRangeRects=(!f.isIE|| +f.isIE>=9)&&typeof b.ownerDocument.createRange().getBoundingClientRect==="function";this._isW3CEvents=b.addEventListener;this._autoScrollTimerID=this._autoScrollY=this._autoScrollX=null;this._AUTO_SCROLL_RATE=50;this._mouseUpClosure=this._moseMoveClosure=this._grabControl=null;this._clickCount=this._lastMouseTime=this._lastMouseY=this._lastMouseX=0;this._clickTime=250;this._clickDist=5;this._isMouseDown=!1;this._doubleClickSelection=null;this._vScroll=this._hScroll=0;this._imeOffset=-1;this._createActions(); +this._createView()},_modifyContent:function(a,b){if(!this._readonly||a._code)if(a.type="Verify",this.onVerify(a),!(a.text===null||a.text===void 0)){var e=this._model;try{if(a._ignoreDOMSelection)this._ignoreDOMSelection=!0;e.setText(a.text,a.start,a.end)}finally{if(a._ignoreDOMSelection)this._ignoreDOMSelection=!1}b&&(e=this._getSelection(),e.setCaret(a.start+a.text.length),this._setSelection(e,!0));this.onModify({type:"Modify"})}},_onModelChanged:function(a){a.type="ModelChanged";this.onModelChanged(a); +a.type="Changed";var b=a.start,e=a.addedCharCount,c=a.removedCharCount,l=a.addedLineCount,f=a.removedLineCount,d=this._getSelection();d.end>b&&(d.end>b&&d.start<b+c?d.setCaret(b+e):(d.start+=e-c,d.end+=e-c),this._setSelection(d,!1,!1));b=this._model.getLineAtOffset(b);for(e=this._getLineNext();e;){c=e.lineIndex;if(b<=c&&c<=b+f)b===c&&!e.modelChangedEvent&&!e.lineRemoved?(e.modelChangedEvent=a,e.lineChanged=!0):(e.lineRemoved=!0,e.lineChanged=!1,e.modelChangedEvent=null);if(c>b+f)e.lineIndex=c+l-f, +e._line.lineIndex=e.lineIndex;e=this._getLineNext(e)}this._lineHeight&&(a=[b,f].concat(Array(l)),Array.prototype.splice.apply(this._lineHeight,a));if(!this._wrapMode&&b<=this._maxLineIndex&&this._maxLineIndex<=b+f)this._checkMaxLineIndex=this._maxLineIndex,this._maxLineIndex=-1,this._maxLineWidth=0;this._update()},_onModelChanging:function(a){a.type="ModelChanging";this.onModelChanging(a);a.type="Changing"},_queueUpdate:function(){if(!this._updateTimer&&!this._ignoreQueueUpdate){var a=this;this._updateTimer= +this._getWindow().setTimeout(function(){a._updateTimer=null;a._update()},0)}},_resetLineHeight:function(a,b){if(this._wrapMode||this._variableLineHeight){if(a!==void 0&&b!==void 0)for(var e=a;e<b;e++)this._lineHeight[e]=void 0;else this._lineHeight=Array(this._model.getLineCount());this._calculateLineHeightTimer()}else this._lineHeight=null},_resetLineWidth:function(){var a=this._clientDiv;if(a)for(a=a.firstChild;a;)a.lineWidth=void 0,a=a.nextSibling},_reset:function(){this._maxLineIndex=-1;this._maxLineWidth= +0;this._columnX=-1;this._bottomChild=this._topChild=null;this._topIndexY=0;this._variableLineHeight=!1;this._resetLineHeight();this._setSelection(new q(0,0,!1),!1,!1);if(this._viewDiv)this._viewDiv.scrollLeft=0,this._viewDiv.scrollTop=0;var a=this._clientDiv;if(a){for(var b=a.firstChild;b;)b.lineRemoved=!0,b=b.nextSibling;if(f.isFirefox)this._ignoreFocus=!1,(b=this._hasFocus)&&a.blur(),a.contentEditable=!1,a.contentEditable=!0,b&&a.focus(),this._ignoreFocus=!1}},_scrollViewAnimated:function(a,b,e){var c= +this._getWindow();if(e&&this._scrollAnimation){var l=this;this._animation=new u({window:c,duration:this._scrollAnimation,curve:[b,0],onAnimate:function(a){a=b-Math.floor(a);l._scrollView(0,a);b-=a},onEnd:function(){l._animation=null;l._scrollView(a,b);e&&c.setTimeout(e,0)}});this._animation.play()}else this._scrollView(a,b),e&&c.setTimeout(e,0)},_scrollView:function(a,b){this._ensureCaretVisible=!1;var e=this._viewDiv;a&&(e.scrollLeft+=a);b&&(e.scrollTop+=b)},_setClipboardText:function(a,b){var c, +l=this._getWindow(),d=l.clipboardData;if(!d&&b)d=b.clipboardData;if(d&&(c=[],e(a,function(a){c.push(a)},function(){c.push(f.platformDelimiter)}),d.setData(f.isIE?"Text":"text/plain",c.join(""))))return!0;var o=this._parent.ownerDocument,g=f.createElement(o,"pre");g.style.position="fixed";g.style.left="-1000px";e(a,function(a){g.appendChild(o.createTextNode(a))},function(){g.appendChild(f.createElement(o,"br"))});g.appendChild(o.createTextNode(" "));this._clientDiv.appendChild(g);d=o.createRange(); +d.setStart(g.firstChild,0);d.setEndBefore(g.lastChild);var h=l.getSelection();h.rangeCount>0&&h.removeAllRanges();h.addRange(d);var p=this,d=function(){g&&g.parentNode===p._clientDiv&&p._clientDiv.removeChild(g);p._updateDOMSelection()},h=!1;this._ignoreCopy=!0;try{h=o.execCommand("copy",!1,null)}catch(i){}this._ignoreCopy=!1;if(!h&&b)return l.setTimeout(d,0),!1;d();return!0},_setDOMSelection:function(a,b,e,c,l){for(var d,o,g,h,p=0,i=a.firstChild,q,r,s=this._model.getLine(a.lineIndex).length;i;){if(!i.ignore){q= +i.firstChild;r=q.length;i.ignoreChars&&(r-=i.ignoreChars);if(p+r>b||p+r>=s){d=q;o=b-p;i.ignoreChars&&r>0&&o===r&&(o+=i.ignoreChars);break}p+=r}i=i.nextSibling}for(var p=0,i=e.firstChild,t=this._model.getLine(e.lineIndex).length;i;){if(!i.ignore){q=i.firstChild;r=q.length;i.ignoreChars&&(r-=i.ignoreChars);if(r+p>c||p+r>=t){g=q;h=c-p;i.ignoreChars&&r>0&&h===r&&(h+=i.ignoreChars);break}p+=r}i=i.nextSibling}this._setDOMFullSelection(a,b,s,e,c,t);a=this._getWindow();b=this._parent.ownerDocument;if(a.getSelection){e= +a.getSelection();a=b.createRange();a.setStart(d,o);a.setEnd(g,h);if(this._hasFocus&&(e.anchorNode!==d||e.anchorOffset!==o||e.focusNode!==g||e.focusOffset!==h||e.anchorNode!==g||e.anchorOffset!==h||e.focusNode!==d||e.focusOffset!==o))this._anchorNode=d,this._anchorOffset=o,this._focusNode=g,this._focusOffset=h,this._ignoreSelect=!1,e.rangeCount>0&&e.removeAllRanges(),e.addRange(a),this._ignoreSelect=!0;if(this._cursorDiv&&(a=b.createRange(),l?(a.setStart(d,o),a.setEnd(d,o)):(a.setStart(g,h),a.setEnd(g, +h)),g=a.getClientRects()[0],h=this._cursorDiv.parentNode,d=h.getBoundingClientRect(),g&&d))this._cursorDiv.style.top=g.top-d.top+h.scrollTop+"px",this._cursorDiv.style.left=g.left-d.left+h.scrollLeft+"px"}else if(b.selection&&this._hasFocus)l=b.body,a=f.createElement(b,"div"),l.appendChild(a),l.removeChild(a),a=l.createTextRange(),a.moveToElementText(d.parentNode),a.moveStart("character",o),d=l.createTextRange(),d.moveToElementText(g.parentNode),d.moveStart("character",h),a.setEndPoint("EndToStart", +d),this._ignoreSelect=!1,a.select(),this._ignoreSelect=!0},_setDOMFullSelection:function(a,b,e,c,l){if(this._selDiv1&&(e=this._selDiv1,e.style.width="0px",e.style.height="0px",e=this._selDiv2,e.style.width="0px",e.style.height="0px",e=this._selDiv3,e.style.width="0px",e.style.height="0px",!(a===c&&b===l))){var f=this._model,d=this._getViewPadding(),o=this._clientDiv.getBoundingClientRect(),g=this._viewDiv.getBoundingClientRect(),e=g.left+d.left,h=o.right,d=g.top+d.top,i=o.bottom,g=o=0;this._clipDiv? +(g=this._clipDiv.getBoundingClientRect(),o=g.left-this._clipDiv.scrollLeft):(g=this._rootDiv.getBoundingClientRect(),o=g.left);g=g.top;this._ignoreDOMSelection=!0;var q=(new p(this,a.lineIndex,a)).getBoundingClientRect(f.getLineStart(a.lineIndex)+b,!1),r=q.left,b=(new p(this,c.lineIndex,c)).getBoundingClientRect(f.getLineStart(c.lineIndex)+l,!1),f=b.left;this._ignoreDOMSelection=!1;var s=this._selDiv1,r=Math.min(h,Math.max(e,r)),t=Math.min(i,Math.max(d,q.top)),u=h,l=Math.min(i,Math.max(d,q.bottom)); +s.style.left=r-o+"px";s.style.top=t-g+"px";s.style.width=Math.max(0,u-r)+"px";s.style.height=Math.max(0,l-t)+"px";if(a.lineIndex===c.lineIndex)u=Math.min(f,h),s.style.width=Math.max(0,u-r)+"px";else if(q=Math.min(i,Math.max(d,b.top)),f=Math.min(h,Math.max(e,f)),d=Math.min(i,Math.max(d,b.bottom)),i=this._selDiv3,i.style.left=e-o+"px",i.style.top=q-g+"px",i.style.width=Math.max(0,f-e)+"px",i.style.height=Math.max(0,d-q)+"px",Math.abs(a.lineIndex-c.lineIndex)>1)a=this._selDiv2,a.style.left=e-o+"px", +a.style.top=l-g+"px",a.style.width=Math.max(0,h-e)+"px",a.style.height=Math.max(0,q-l)+"px"}},_setGrab:function(a){if(a!==this._grabControl)a?(a.setCapture&&a.setCapture(),this._grabControl=a):(this._grabControl.releaseCapture&&this._grabControl.releaseCapture(),this._grabControl=null)},_setLinksVisible:function(a){if(this._linksVisible!==a){this._linksVisible=a;if(f.isIE&&a)this._hadFocus=this._hasFocus;var b=this._clientDiv;b.contentEditable=!a;this._hadFocus&&!a&&b.focus();if(this._overlayDiv)this._overlayDiv.style.zIndex= +a?"-1":"1";for(a=this._getLineNext();a;){if(a.hasLink)for(b=a.firstChild;b;)if(b.ignore)b=b.nextSibling;else{var e=b.nextSibling,c=b.viewStyle;c&&c.tagName&&c.tagName.toLowerCase()==="a"&&a.replaceChild(a._line._createSpan(a,b.firstChild.data,c),b);b=e}a=this._getLineNext(a)}this._updateDOMSelection()}},_setSelection:function(a,b,e,c,l){if(a){this._columnX=-1;e===void 0&&(e=!0);var f=this._selection;this._selection=a;b!==!1&&this._showCaret(!1,c,b,l);e&&this._updateDOMSelection();if(!f.equals(a))this.onSelection({type:"Selection", +oldValue:{start:f.start,end:f.end},newValue:{start:a.start,end:a.end}})}},_setSelectionTo:function(a,b,e,c){var l=this._model,f=this._getSelection(),b=this.convert({x:a,y:b},"page","document"),a=this._getLineIndex(b.y);if(this._clickCount===1){l=this._getLine(a);a=l.getOffset(b.x,b.y-this._getLinePixel(a));l.destroy();if(c&&!e&&f.start<=a&&a<f.end)return this._dragOffset=a,!1;f.extend(a);e||f.collapse()}else(this._clickCount&1)===0?(l=this._getLine(a),a=l.getOffset(b.x,b.y-this._getLinePixel(a)), +this._doubleClickSelection?a>=this._doubleClickSelection.start?(e=this._doubleClickSelection.start,c=l.getNextOffset(a,{unit:"wordend",count:1})):(e=l.getNextOffset(a,{unit:"word",count:-1}),c=this._doubleClickSelection.end):(e=l.getNextOffset(a,{unit:"word",count:-1}),c=l.getNextOffset(e,{unit:"wordend",count:1})),l.destroy()):this._doubleClickSelection?(c=l.getLineAtOffset(this._doubleClickSelection.start),a>=c?(e=l.getLineStart(c),c=l.getLineEnd(a)):(e=l.getLineStart(a),c=l.getLineEnd(c))):(e= +l.getLineStart(a),c=l.getLineEnd(a)),f.setCaret(e),f.extend(c);this._setSelection(f,!0,!0);return!0},_setFullSelection:function(a,b){this._fullSelection=a;if(f.isWebkit)this._fullSelection=!0;var e=this._clipDiv||this._rootDiv;if(e)if(this._fullSelection){if(!this._selDiv1&&this._fullSelection&&!f.isIOS){var c=e.ownerDocument;this._highlightRGB=f.isWebkit?"transparent":"Highlight";var l=f.createElement(c,"div");this._selDiv1=l;l.style.position="absolute";l.style.borderWidth="0px";l.style.margin="0px"; +l.style.padding="0px";l.style.outline="none";l.style.background=this._highlightRGB;l.style.width="0px";l.style.height="0px";l.style.zIndex="0";e.appendChild(l);var d=f.createElement(c,"div");this._selDiv2=d;d.style.position="absolute";d.style.borderWidth="0px";d.style.margin="0px";d.style.padding="0px";d.style.outline="none";d.style.background=this._highlightRGB;d.style.width="0px";d.style.height="0px";d.style.zIndex="0";e.appendChild(d);this._selDiv3=c=f.createElement(c,"div");c.style.position="absolute"; +c.style.borderWidth="0px";c.style.margin="0px";c.style.padding="0px";c.style.outline="none";c.style.background=this._highlightRGB;c.style.width="0px";c.style.height="0px";c.style.zIndex="0";e.appendChild(c);if(f.isFirefox&&f.isMac){e=this._getWindow().getComputedStyle(c,null).getPropertyValue("background-color");switch(e){case "rgb(119, 141, 168)":e="rgb(199, 208, 218)";break;case "rgb(127, 127, 127)":e="rgb(198, 198, 198)";break;case "rgb(255, 193, 31)":e="rgb(250, 236, 115)";break;case "rgb(243, 70, 72)":e= +"rgb(255, 176, 139)";break;case "rgb(255, 138, 34)":e="rgb(255, 209, 129)";break;case "rgb(102, 197, 71)":e="rgb(194, 249, 144)";break;case "rgb(140, 78, 184)":e="rgb(232, 184, 255)";break;default:e="rgb(180, 213, 255)"}this._highlightRGB=e;l.style.background=e;d.style.background=e;c.style.background=e}b||this._updateDOMSelection()}}else{if(this._selDiv1)e.removeChild(this._selDiv1),this._selDiv1=null;if(this._selDiv2)e.removeChild(this._selDiv2),this._selDiv2=null;if(this._selDiv3)e.removeChild(this._selDiv3), +this._selDiv3=null}},_setBlockCursor:function(a){this._blockCursorVisible=a;this._updateBlockCursorVisible()},_setOverwriteMode:function(a){this._overwriteMode=a;this._updateBlockCursorVisible()},_updateBlockCursorVisible:function(){if(this._blockCursorVisible||this._overwriteMode){if(!this._cursorDiv){var a=f.createElement(document,"div");a.className="textviewBlockCursor";this._cursorDiv=a;a.tabIndex=-1;a.style.zIndex="2";a.style.color="transparent";a.style.position="absolute";a.style.pointerEvents= +"none";a.innerHTML=" ";this._viewDiv.appendChild(a);this._updateDOMSelection()}}else if(this._cursorDiv)this._cursorDiv.parentNode.removeChild(this._cursorDiv),this._cursorDiv=null},_setMarginOffset:function(a,b){this._marginOffset=a;this._marginDiv.style.display=a?"block":"none";if(!b)this._metrics=this._calculateMetrics(),this._queueUpdate()},_setWrapOffset:function(a,b){this._wrapOffset=a;if(!b)this._metrics=this._calculateMetrics(),this._queueUpdate()},_setReadOnly:function(a){this._readonly= +a;this._clientDiv.setAttribute("aria-readonly",a?"true":"false")},_setSingleMode:function(a,b){this._singleMode=a;this._updateOverflow();this._updateStyle(b)},_setTabSize:function(a,b){this._tabSize=a;this._customTabSize=void 0;var e=this._clientDiv;if(f.isOpera){if(e)e.style.OTabSize=this._tabSize+""}else if(f.isWebkit>=537.1){if(e)e.style.tabSize=this._tabSize+""}else if(f.isFirefox>=4){if(e)e.style.MozTabSize=this._tabSize+""}else if(this._tabSize!==8)this._customTabSize=this._tabSize;b||(this.redrawLines(), +this._resetLineWidth())},_setTheme:function(a){this._theme&&this._theme.removeEventListener("ThemeChanged",this._themeListener.onChanged);(this._theme=a)&&this._theme.addEventListener("ThemeChanged",this._themeListener.onChanged);this._setThemeClass(this._themeClass)},_setThemeClass:function(a,b){this._themeClass=a;var e="textview",c=this._theme.getThemeClass();c&&(e+=" "+c);this._themeClass&&c!==this._themeClass&&(e+=" "+this._themeClass);this._rootDiv.className=e;this._updateStyle(b)},_setWrapMode:function(a, +b){this._wrapMode=a&&this._wrappable;var e=this._clientDiv;this._wrapMode?(e.style.whiteSpace="pre-wrap",e.style.wordWrap="break-word"):(e.style.whiteSpace="pre",e.style.wordWrap="normal");this._updateOverflow();b||(this.redraw(),this._resetLineWidth());this._resetLineHeight()},_showCaret:function(a,b,e,c){if(this._clientDiv){var l=this._model,f=this._getSelection(),d=this._getScroll(),o=f.getCaret(),g=f.start,h=f.end,p=l.getLineAtOffset(h),i=Math.max(Math.max(g,l.getLineStart(p)),h-1),l=this._getClientWidth(), +p=this._getClientHeight(),q=l/4,r=this._getBoundsAtOffset(o===g?g:i),s=r.left,t=r.right,u=r.top,v=r.bottom;a&&!f.isEmpty()&&(r=this._getBoundsAtOffset(o===h?g:i),r.top===u?o===g?t=s+Math.min(r.right-s,l):s=t-Math.min(t-r.left,l):o===g?v=u+Math.min(r.bottom-u,p):u=v-Math.min(v-r.top,p));a=0;s<d.x&&(a=Math.min(s-d.x,-q));t>d.x+l&&(a=Math.max(t-d.x-l,q));f=0;u<d.y?f=u-d.y:v>d.y+p&&(f=v-d.y-p);c&&(c>0?f>0&&(f=Math.max(f,c)):f<0&&(f=Math.min(f,c)));if(a!==0||f!==0)return f!==0&&typeof e==="number"&&(e< +0&&(e=0),e>1&&(e=1),f+=Math.floor(f>0?e*p:-e*p)),this._scrollViewAnimated(a,f,b),p!==this._getClientHeight()||l!==this._getClientWidth()?this._showCaret():this._ensureCaretVisible=!0,!0;else b&&b();return!1}},_startIME:function(){if(this._imeOffset===-1){var a=this._getSelection();a.isEmpty()||this._modifyContent({text:"",start:a.start,end:a.end},!0);this._imeOffset=a.start}},_unhookEvents:function(){this._model.removeEventListener("preChanging",this._modelListener.onChanging);this._model.removeEventListener("postChanged", +this._modelListener.onChanged);this._theme.removeEventListener("ThemeChanged",this._themeListener.onChanged);this._modelListener=null;for(var a=0;a<this._handlers.length;a++){var b=this._handlers[a];s(b.target,b.type,b.handler)}this._handlers=null;if(this._mutationObserver)this._mutationObserver.disconnect(),this._mutationObserver=null},_updateDOMSelection:function(){if(!(this._redrawCount>0)&&!this._ignoreDOMSelection&&this._clientDiv){var a=this._getSelection(),b=this._model,e=b.getLineAtOffset(a.start), +c=b.getLineAtOffset(a.end),l=this._getLineNext();if(l){var f=this._getLinePrevious(),d;e<l.lineIndex?(d=l,e=0):e>f.lineIndex?(d=f,e=0):(d=this._getLineNode(e),e=a.start-b.getLineStart(e));c<l.lineIndex?b=0:c>f.lineIndex?(l=f,b=0):(l=this._getLineNode(c),b=a.end-b.getLineStart(c));this._setDOMSelection(d,e,l,b,a.caret)}}},_update:function(a){if(!(this._redrawCount>0)){if(this._updateTimer)this._getWindow().clearTimeout(this._updateTimer),this._updateTimer=null,a=!1;var b=this._clientDiv,e=this._viewDiv; +if(b){if(this._metrics.invalid)this._ignoreQueueUpdate=!0,this._updateStyle(),this._ignoreQueueUpdate=!1;var c=this._model,l=this._getScroll(!1),d=this._getViewPadding(),o=c.getLineCount(),g=this._getLineHeight(),h=!1,i=!1,q=!1,r=this._metrics.scrollWidth;if(this._wrapMode)b.style.width=(this._metrics.wrapWidth||this._getClientWidth())+"px";var s,t,u,v,k=0,n=0,m;if(this._lineHeight){for(;n<o;){m=this._getLineHeight(n);if(k+m>l.y)break;k+=m;n++}s=n;t=Math.max(0,s-1);u=c=l.y-k;s>0&&(c+=this._getLineHeight(s- +1))}else v=Math.max(0,l.y)/g,s=Math.floor(v),t=Math.max(0,s-1),c=Math.round((v-t)*g),u=Math.round((v-s)*g);this._topIndexY=u;v=this._rootDiv;var I=v.clientWidth,F=v.clientHeight;if(a){g=0;this._leftDiv&&(s=this._leftDiv.getBoundingClientRect(),g=s.right-s.left);s=this._getClientWidth();v=this._getClientHeight();i=s;if(this._wrapMode){if(this._metrics.wrapWidth)i=this._metrics.wrapWidth}else i=Math.max(this._maxLineWidth,i);for(;n<o;)m=this._getLineHeight(n,!1),k+=m,n++;o=k}else{v=this._getClientHeight(); +u=Math.min(s+Math.floor((v+u)/g),o-1);var l=Math.min(u+1,o-1),A;for(m=b.firstChild;m;){A=m.lineIndex;var z=m.nextSibling;if(!(t<=A&&A<=l)||m.lineRemoved||m.lineIndex===-1)this._mouseWheelLine===m?(m.style.display="none",m.lineIndex=-1):b.removeChild(m);m=z}m=this._getLineNext();var z=e.ownerDocument,C=z.createDocumentFragment();for(A=t;A<=l;A++)if(!m||m.lineIndex>A)(new p(this,A)).create(C,null);else{C.firstChild&&(b.insertBefore(C,m),C=z.createDocumentFragment());if(m&&m.lineChanged)m=(new p(this, +A)).create(C,m),m.lineChanged=!1;m=this._getLineNext(m)}C.firstChild&&b.insertBefore(C,m);if(f.isWebkit&&!this._wrapMode)b.style.width="0x7fffffffpx";m=this._getLineNext();A=v+c;for(C=!1;m;){t=m.lineWidth;if(t===void 0)if(z=m._line.getBoundingClientRect(),t=m.lineWidth=Math.ceil(z.right-z.left),z=z.bottom-z.top,this._lineHeight)this._lineHeight[m.lineIndex]=z;else if(g!==0&&z!==0&&Math.ceil(g)!==Math.ceil(z))this._variableLineHeight=!0,this._lineHeight=[],this._lineHeight[m.lineIndex]=z;if(this._lineHeight&& +!C&&(A-=this._lineHeight[m.lineIndex],A<0))u=m.lineIndex,C=!0;if(!this._wrapMode){if(t>=this._maxLineWidth)this._maxLineWidth=t,this._maxLineIndex=m.lineIndex;if(this._checkMaxLineIndex===m.lineIndex)this._checkMaxLineIndex=-1}if(m.lineIndex===s)this._topChild=m;if(m.lineIndex===u)this._bottomChild=m;m=this._getLineNext(m)}if(this._checkMaxLineIndex!==-1&&(A=this._checkMaxLineIndex,this._checkMaxLineIndex=-1,0<=A&&A<o)){g=new p(this,A);z=g.getBoundingClientRect();t=z.right-z.left;if(t>=this._maxLineWidth)this._maxLineWidth= +t,this._maxLineIndex=A;g.destroy()}for(;n<o;)m=this._getLineHeight(n,n<=u),k+=m,n++;o=k;this._updateRuler(this._leftDiv,s,l,F);this._updateRuler(this._rightDiv,s,l,F);this._updateRuler(this._marginDiv,s,l,F);g=0;this._leftDiv&&(s=this._leftDiv.getBoundingClientRect(),g=s.right-s.left);l=0;this._rightDiv&&(l=this._rightDiv.getBoundingClientRect(),l=l.right-l.left);e.style.left=g+"px";e.style.right=l+"px";l=this._scrollDiv;l.style.height=o+"px";s=this._getClientWidth();if(!this._singleMode&&!this._wrapMode){k= +h=v;(n=e.style.overflowX==="scroll")?h+=r:k-=r;m=u=s;(t=e.style.overflowY==="scroll")?u+=r:m-=r;v=h;s=u;o>v&&(q=!0,s=m);this._maxLineWidth>s&&(i=!0,v=k,o>v&&(q=!0,s=m));if(n!==i)e.style.overflowX=i?"scroll":"hidden";if(t!==q)e.style.overflowY=q?"scroll":"hidden";h=n!==i||t!==q}q=s;if(this._wrapMode){if(this._metrics.wrapWidth)q=this._metrics.wrapWidth}else q=Math.max(this._maxLineWidth,q);i=q;if((!f.isIE||f.isIE>=9)&&this._maxLineWidth>s)q+=d.right+d.left;l.style.width=q+"px";if(this._clipScrollDiv)this._clipScrollDiv.style.width= +q+"px";l=this._getScroll(!1)}if(this._vScrollDiv)q=v-8,k=Math.max(15,Math.ceil(Math.min(1,q/(o+d.top+d.bottom))*q)),this._vScrollDiv.style.left=g+s-8+"px",this._vScrollDiv.style.top=Math.floor(Math.max(0,l.y*q/o))+"px",this._vScrollDiv.style.height=k+"px";if(!this._wrapMode&&this._hScrollDiv)q=s-8,k=Math.max(15,Math.ceil(Math.min(1,q/(this._maxLineWidth+d.left+d.right))*q)),this._hScrollDiv.style.left=g+Math.floor(Math.max(0,Math.floor(l.x*q/this._maxLineWidth)))+"px",this._hScrollDiv.style.top=v- +9+"px",this._hScrollDiv.style.width=k+"px";n=l.x;k=this._clipDiv;q=this._overlayDiv;if(u=this._marginDiv)u.style.left=-n+g+this._metrics.marginWidth+d.left+"px",u.style.bottom=(e.style.overflowX==="scroll"?r:0)+"px";if(k){k.scrollLeft=n;k.scrollTop=0;e=g+d.left;r=d.top;a=s;g=v;n=0;u=-c;if(l.x===0)e-=d.left,a+=d.left,n=d.left;l.x+s===i&&(a+=d.right);l.y===0&&(r-=d.top,g+=d.top,u+=d.top);l.y+v===o&&(g+=d.bottom);k.style.left=e+"px";k.style.top=r+"px";k.style.right=I-a-e+"px";k.style.bottom=F-g-r+"px"; +b.style.left=n+"px";b.style.top=u+"px";b.style.width=i+"px";b.style.height=v+c+"px";if(q)q.style.left=b.style.left,q.style.top=b.style.top,q.style.width=b.style.width,q.style.height=b.style.height}else{e=n;r=c;I=n+s;F=c+v;e===0&&(e-=d.left);r===0&&(r-=d.top);I===i&&(I+=d.right);l.y+v===o&&(F+=d.bottom);b.style.clip="rect("+r+"px,"+I+"px,"+F+"px,"+e+"px)";b.style.left=-n+g+d.left+"px";b.style.width=(this._wrapMode||f.isWebkit?i:s+n)+"px";if(!a)b.style.top=-c+d.top+"px",b.style.height=v+c+"px";if(q&& +(q.style.clip=b.style.clip,q.style.left=b.style.left,q.style.width=b.style.width,!a))q.style.top=b.style.top,q.style.height=b.style.height}this._updateDOMSelection();if(h)b=this._ensureCaretVisible,this._ensureCaretVisible=!1,b&&this._showCaret(),this._queueUpdate()}}},_updateOverflow:function(){var a=this._viewDiv;this._wrapMode?(a.style.overflowX="hidden",a.style.overflowY="scroll"):a.style.overflow="hidden"},_updateRuler:function(a,b,e,c){if(a)for(var l=this._parent.ownerDocument,d=this._getLineHeight(), +o=this._getViewPadding(),a=a.firstChild;a;){var h=a._ruler,p=d,i=h.getOverview();i==="page"&&(p+=this._topIndexY);a.style.top=-p+"px";a.style.height=c+p+"px";a.rulerChanged&&g(h.getRulerStyle(),a);var q,r=a.firstChild;r?(q=r,r=r.nextSibling):(q=f.createElement(l,"div"),q.style.visibility="hidden",a.appendChild(q));var s;if(a.rulerChanged&&q){p=-1;if(s=h.getWidestAnnotation())if(g(s.style,q),s.html)q.innerHTML=s.html;q.lineIndex=p;q.style.height=d+o.top+"px"}var t;if(i==="page"){for(h=h.getAnnotations(b, +e+1);r;)p=r.lineIndex,s=r.nextSibling,(!(b<=p&&p<=e)||r.lineChanged)&&a.removeChild(r),r=s;r=a.firstChild.nextSibling;t=l.createDocumentFragment();for(p=b;p<=e;p++)if(!r||r.lineIndex>p){q=f.createElement(l,"div");if(s=h[p]){g(s.style,q);if(s.html)q.innerHTML=s.html;q.annotation=s}q.lineIndex=p;q.style.height=this._getLineHeight(p)+"px";t.appendChild(q)}else if(t.firstChild&&(a.insertBefore(t,r),t=l.createDocumentFragment()),r)r=r.nextSibling;t.firstChild&&a.insertBefore(t,r)}else{s=this._getClientHeight(); +p=this._model.getLineCount();r=s+o.top+o.bottom-2*this._metrics.scrollWidth;i=d*p<r?d:r/p;if(a.rulerChanged){for(s=a.childNodes.length;s>1;)a.removeChild(a.lastChild),s--;h=h.getAnnotations(0,p);t=l.createDocumentFragment();for(var u in h)if(p=u>>>0,!(p<0)){q=f.createElement(l,"div");s=h[u];g(s.style,q);q.style.position="absolute";q.style.top=this._metrics.scrollWidth+d+Math.floor(p*i)+"px";if(s.html)q.innerHTML=s.html;q.annotation=s;q.lineIndex=p;t.appendChild(q)}a.appendChild(t)}else if(a._oldTrackHeight!== +r)for(q=a.firstChild?a.firstChild.nextSibling:null;q;)q.style.top=this._metrics.scrollWidth+d+Math.floor(q.lineIndex*i)+"px",q=q.nextSibling;a._oldTrackHeight=r}a.rulerChanged=!1;a=a.nextSibling}},_updateStyleSheet:function(){var a="";f.isWebkit&&this._metrics.scrollWidth>0&&(a+="\n.textview ::-webkit-scrollbar-corner {background: #eeeeee;}");f.isFirefox&&f.isMac&&this._highlightRGB&&this._highlightRGB!=="Highlight"&&(a+="\n.textview ::-moz-selection {background: "+this._highlightRGB+";}");if(a){var b= +document.getElementById("_textviewStyle");if(b)b.removeChild(b.firstChild),b.appendChild(document.createTextNode(a));else{b=f.createElement(document,"style");b.id="_textviewStyle";var e=document.getElementsByTagName("head")[0]||document.documentElement;b.appendChild(document.createTextNode(a));e.insertBefore(b,e.firstChild)}}},_updateStyle:function(a){if(!a&&f.isIE)this._rootDiv.style.lineHeight="normal";var b=this._metrics=this._calculateMetrics();this._rootDiv.style.lineHeight=f.isIE?b.lineHeight- +(b.lineTrim.top+b.lineTrim.bottom)+"px":"normal";this._updateStyleSheet();a||(this.redraw(),this._resetLineWidth())}};i.EventTarget.addMixin(t.prototype);return{TextView:t}}); +define("orion/editor/projectionTextModel",["orion/editor/textModel","orion/editor/eventTarget"],function(k,m){function n(i){this._model=i;this._projections=[];var c=this;this._listener={onChanged:function(d){c._onChanged(d)},onChanging:function(d){c._onChanging(d)}};i.addEventListener("postChanged",this._listener.onChanged);i.addEventListener("preChanging",this._listener.onChanging)}n.prototype={destroy:function(){if(this._model)this._model.removeEventListener("postChanged",this._listener.onChanged), +this._model.removeEventListener("preChanging",this._listener.onChanging),this._model=null},addProjection:function(i){if(i){var c=this._model,d=this._projections;i._lineIndex=c.getLineAtOffset(i.start);i._lineCount=c.getLineAtOffset(i.end)-i._lineIndex;var f=i.text;f||(f="");i._model=typeof f==="string"?new k.TextModel(f,c.getLineDelimiter()):f;var c=this.mapOffset(i.start,!0),f=i.end-i.start,g=i._lineCount,h=i._model.getCharCount(),b=i._model.getLineCount()-1;this.onChanging({type:"Changing",text:i._model.getText(), +start:c,removedCharCount:f,addedCharCount:h,removedLineCount:g,addedLineCount:b});var a=this._binarySearch(d,i.start);d.splice(a,0,i);this.onChanged({type:"Changed",start:c,removedCharCount:f,addedCharCount:h,removedLineCount:g,addedLineCount:b})}},getProjections:function(){return this._projections.slice(0)},getBaseModel:function(){return this._model},mapOffset:function(i,c){var d=this._projections,f=0,g,h;if(c){for(g=0;g<d.length;g++){h=d[g];if(h.start>i)break;if(h.end>i)return-1;f+=h._model.getCharCount()- +(h.end-h.start)}return i+f}for(g=0;g<d.length;g++){h=d[g];if(h.start>i-f)break;var b=h._model.getCharCount();if(h.start+b>i-f)return-1;f+=b-(h.end-h.start)}return i-f},removeProjection:function(i){var c,d=0;for(c=0;c<this._projections.length;c++){var f=this._projections[c];if(f===i){i=f;break}d+=f._model.getCharCount()-(f.end-f.start)}if(c<this._projections.length){var f=this._model,d=i.start+d,g=i.end-i.start,h=i._lineCount,b=i._model.getCharCount(),a=i._model.getLineCount()-1;this.onChanging({type:"Changing", +text:f.getText(i.start,i.end),start:d,removedCharCount:b,addedCharCount:g,removedLineCount:a,addedLineCount:h});this._projections.splice(c,1);this.onChanged({type:"Changed",start:d,removedCharCount:b,addedCharCount:g,removedLineCount:a,addedLineCount:h})}},_binarySearch:function(i,c){for(var d=i.length,f=-1,g;d-f>1;)g=Math.floor((d+f)/2),c<=i[g].start?d=g:f=g;return d},getCharCount:function(){for(var i=this._model.getCharCount(),c=this._projections,d=0;d<c.length;d++){var f=c[d];i+=f._model.getCharCount()- +(f.end-f.start)}return i},getLine:function(i,c){if(i<0)return null;var d=this._model,f=this._projections,g=0,h=[],b=0,a,e,l;for(a=0;a<f.length;a++){l=f[a];if(l._lineIndex>=i-g)break;e=l._model.getLineCount()-1;if(l._lineIndex+e>=i-g)if(b=i-(l._lineIndex+g),b<e)return l._model.getLine(b,c);else h.push(l._model.getLine(e));b=l.end;g+=e-l._lineCount}for(b=Math.max(b,d.getLineStart(i-g));a<f.length;a++){l=f[a];if(l._lineIndex>i-g)break;h.push(d.getText(b,l.start));e=l._model.getLineCount()-1;if(l._lineIndex+ +e>i-g)return h.push(l._model.getLine(0,c)),h.join("");h.push(l._model.getText());b=l.end;g+=e-l._lineCount}f=d.getLineEnd(i-g,c);b<f&&h.push(d.getText(b,f));return h.join("")},getLineAtOffset:function(i){for(var c=this._model,d=this._projections,f=0,g=0,h=0;h<d.length;h++){var b=d[h];if(b.start>i-f)break;var a=b._model.getCharCount();if(b.start+a>i-f){d=i-(b.start+f);g+=b._model.getLineAtOffset(d);f+=d;break}g+=b._model.getLineCount()-1-b._lineCount;f+=a-(b.end-b.start)}return c.getLineAtOffset(i- +f)+g},getLineCount:function(){for(var i=this._projections,c=this._model.getLineCount(),d=0;d<i.length;d++){var f=i[d];c+=f._model.getLineCount()-1-f._lineCount}return c},getLineDelimiter:function(){return this._model.getLineDelimiter()},getLineEnd:function(i,c){if(i<0)return-1;for(var d=this._model,f=this._projections,g=0,h=0,b=0;b<f.length;b++){var a=f[b];if(a._lineIndex>i-g)break;var e=a._model.getLineCount()-1;if(a._lineIndex+e>i-g)return a._model.getLineEnd(i-(a._lineIndex+g),c)+a.start+h;h+= +a._model.getCharCount()-(a.end-a.start);g+=e-a._lineCount}return d.getLineEnd(i-g,c)+h},getLineStart:function(i){if(i<0)return-1;for(var c=this._model,d=this._projections,f=0,g=0,h=0;h<d.length;h++){var b=d[h];if(b._lineIndex>=i-f)break;var a=b._model.getLineCount()-1;if(b._lineIndex+a>=i-f)return b._model.getLineStart(i-(b._lineIndex+f))+b.start+g;g+=b._model.getCharCount()-(b.end-b.start);f+=a-b._lineCount}return c.getLineStart(i-f)+g},getText:function(i,c){i===void 0&&(i=0);var d=this._model,f= +this._projections,g=0,h=[],b,a,e;for(b=0;b<f.length;b++){a=f[b];if(a.start>i-g)break;e=a._model.getCharCount();if(a.start+e>i-g)if(c!==void 0&&a.start+e>c-g)return a._model.getText(i-(a.start+g),c-(a.start+g));else h.push(a._model.getText(i-(a.start+g))),i=a.end+g+e-(a.end-a.start);g+=e-(a.end-a.start)}var l=i-g;if(c!==void 0){for(;b<f.length;b++){a=f[b];if(a.start>c-g)break;h.push(d.getText(l,a.start));e=a._model.getCharCount();if(a.start+e>c-g)return h.push(a._model.getText(0,c-(a.start+g))),h.join(""); +h.push(a._model.getText());l=a.end;g+=e-(a.end-a.start)}h.push(d.getText(l,c-g))}else{for(;b<f.length;b++)a=f[b],h.push(d.getText(l,a.start)),h.push(a._model.getText()),l=a.end;h.push(d.getText(l))}return h.join("")},_onChanged:function(){var i=this._change,c=i.baseStart,d=i.baseEnd,f,g,h=this._projections;for(f=0;f<h.length;f++)if(g=h[f],g.end>c)break;var b=f;for(f=0;f<h.length;f++)if(g=h[f],g.start>=d)break;var a=f,e=this._model,c=i.baseText.length-(d-c);for(f=a;f<h.length;f++)g=h[f],g.start+=c, +g.end+=c,g._lineIndex=e.getLineAtOffset(g.start);g=h.splice(b,a-b);for(f=0;f<g.length;f++)g[f].annotation&&g[f].annotation._expand();this.onChanged({type:"Changed",start:i.start,removedCharCount:i.removedCharCount,addedCharCount:i.addedCharCount,removedLineCount:i.removedLineCount,addedLineCount:i.addedLineCount});this._change=void 0},_onChanging:function(i){var c=!!this._change,d=this._change||{},f=i.start,g=f+i.removedCharCount;d.baseStart=f;d.baseEnd=g;d.baseText=i.text;d.addedLineCount=i.addedLineCount; +if(!c){this._change=d;d.text=i.text;var h=this._projections,b,a,e,i=function(c){for(a=0,b=0;a<h.length;a++){e=h[a];if(e.start>c)break;if(e.end>c)return-1;b+=e._model.getCharCount()-(e.end-e.start)}return c+b};d.start=i(f);if(d.start===-1)d.text=this._model.getText(e.start,f)+d.text,d.addedLineCount+=this._model.getLineAtOffset(f)-this._model.getLineAtOffset(e.start),d.start=e.start+b;d.end=i(g);if(d.end===-1)d.text+=this._model.getText(g,e.end),d.addedLineCount+=this._model.getLineAtOffset(e.end)- +this._model.getLineAtOffset(g),d.end=e.start+b}d.addedCharCount=d.text.length;d.removedCharCount=d.end-d.start;d.removedLineCount=this.getLineAtOffset(d.end)-this.getLineAtOffset(d.start);this.onChanging({type:"Changing",text:d.text,start:d.start,removedCharCount:d.removedCharCount,addedCharCount:d.addedCharCount,removedLineCount:d.removedLineCount,addedLineCount:d.addedLineCount})},onChanging:function(i){return this.dispatchEvent(i)},onChanged:function(i){return this.dispatchEvent(i)},setLineDelimiter:function(i){this._model.setLineDelimiter(i)}, +setText:function(i,c,d){function f(e){for(b=0,h=0;b<g.length;b++){a=g[b];if(a.start>e-h)break;var c=a._model.getCharCount();if(a.start+c>e-h)return-1;h+=c-(a.end-a.start)}return e-h}this._change={text:i||"",start:c||0,end:d===void 0?this.getCharCount():d};var g=this._projections,h,b,a,e,l,i=f(this._change.start);if(i===-1)e={projection:a,start:this._change.start-(a.start+h)},i=a.end;c=f(this._change.end);if(c===-1)l={projection:a,end:this._change.end-(a.start+h)},c=a.start;if(e&&l&&e.projection=== +l.projection)a._model.setText(this._change.text,e.start,l.end);else{this._model.setText(this._change.text,i,c);if(e)a=e.projection,a._model.setText("",e.start);if(l)a=l.projection,a._model.setText("",0,l.end),a.start=a.end,a._lineCount=0}this._change=void 0}};m.EventTarget.addMixin(n.prototype);return{ProjectionTextModel:n}}); +define("orion/editor/annotations",["i18n!orion/editor/nls/messages","orion/editor/eventTarget"],function(k,m){function n(b,a,e){this.start=b;this.end=a;this._projectionModel=e;this.html=this._expandedHTML;this.style=this._expandedStyle;this.expanded=!0}function i(){}function c(b,a){var e=b.lastIndexOf("."),e=b.substring(e+1),c={title:k[e],style:{styleClass:"annotation "+e},html:"<div class='annotationHTML "+e+"'></div>",overviewStyle:{styleClass:"annotationOverview "+e}};a?c.lineStyle={styleClass:"annotationLine "+ +e}:c.rangeStyle={styleClass:"annotationRange "+e};i.registerType(b,c)}function d(){}function f(b){this._annotations=[];var a=this;this._listener={onChanged:function(b){a._onChanged(b)}};this.setTextModel(b)}function g(b,a){this._view=b;this._annotationModel=a;var e=this;this._listener={onDestroy:function(a){e._onDestroy(a)},onLineStyle:function(a){e._onLineStyle(a)},onChanged:function(a){e._onAnnotationModelChanged(a)}};b.addEventListener("Destroy",this._listener.onDestroy);b.addEventListener("postLineStyle", +this._listener.onLineStyle);a.addEventListener("Changed",this._listener.onChanged)}n.prototype={_expandedHTML:"<div class='annotationHTML expanded'></div>",_expandedStyle:{styleClass:"annotation expanded"},_collapsedHTML:"<div class='annotationHTML collapsed'></div>",_collapsedStyle:{styleClass:"annotation collapsed"},_collapse:function(){if(!this.expanded)return!1;this.expanded=!1;this.html=this._collapsedHTML;this.style=this._collapsedStyle;this._annotationModel&&this._annotationModel.modifyAnnotation(this); +return!0},_expand:function(){if(this.expanded)return!1;this.expanded=!0;this.html=this._expandedHTML;this.style=this._expandedStyle;this._annotationModel&&this._annotationModel.modifyAnnotation(this);return!0},collapse:function(){if(this._collapse()){var b=this._projectionModel,a=b.getBaseModel();this._projection={annotation:this,start:a.getLineStart(a.getLineAtOffset(this.start)+1),end:a.getLineEnd(a.getLineAtOffset(this.end),!0)};b.addProjection(this._projection)}},expand:function(){this._expand()&& +this._projectionModel.removeProjection(this._projection)}};i.ANNOTATION_ERROR="orion.annotation.error";i.ANNOTATION_WARNING="orion.annotation.warning";i.ANNOTATION_TASK="orion.annotation.task";i.ANNOTATION_BREAKPOINT="orion.annotation.breakpoint";i.ANNOTATION_BOOKMARK="orion.annotation.bookmark";i.ANNOTATION_FOLDING="orion.annotation.folding";i.ANNOTATION_CURRENT_BRACKET="orion.annotation.currentBracket";i.ANNOTATION_MATCHING_BRACKET="orion.annotation.matchingBracket";i.ANNOTATION_CURRENT_LINE="orion.annotation.currentLine"; +i.ANNOTATION_CURRENT_SEARCH="orion.annotation.currentSearch";i.ANNOTATION_MATCHING_SEARCH="orion.annotation.matchingSearch";i.ANNOTATION_READ_OCCURRENCE="orion.annotation.readOccurrence";i.ANNOTATION_WRITE_OCCURRENCE="orion.annotation.writeOccurrence";i.ANNOTATION_SELECTED_LINKED_GROUP="orion.annotation.selectedLinkedGroup";i.ANNOTATION_CURRENT_LINKED_GROUP="orion.annotation.currentLinkedGroup";i.ANNOTATION_LINKED_GROUP="orion.annotation.linkedGroup";i.ANNOTATION_BLAME="orion.annotation.blame";i.ANNOTATION_CURRENT_BLAME= +"orion.annotation.currentBlame";var h={};i.registerType=function(b,a){var e=a;if(typeof e!=="function")e=function(a,b,e){this.start=a;this.end=b;if(e!==void 0)this.title=e},e.prototype=a;e.prototype.type=b;h[b]=e;return b};i.createAnnotation=function(b,a,e,c){return new (this.getType(b))(a,e,c)};i.getType=function(b){return h[b]};c(i.ANNOTATION_ERROR);c(i.ANNOTATION_WARNING);c(i.ANNOTATION_TASK);c(i.ANNOTATION_BREAKPOINT);c(i.ANNOTATION_BOOKMARK);c(i.ANNOTATION_CURRENT_BRACKET);c(i.ANNOTATION_MATCHING_BRACKET); +c(i.ANNOTATION_CURRENT_SEARCH);c(i.ANNOTATION_MATCHING_SEARCH);c(i.ANNOTATION_READ_OCCURRENCE);c(i.ANNOTATION_WRITE_OCCURRENCE);c(i.ANNOTATION_SELECTED_LINKED_GROUP);c(i.ANNOTATION_CURRENT_LINKED_GROUP);c(i.ANNOTATION_LINKED_GROUP);c(i.ANNOTATION_CURRENT_LINE,!0);c(i.ANNOTATION_BLAME,!0);c(i.ANNOTATION_CURRENT_BLAME,!0);i.registerType(i.ANNOTATION_FOLDING,n);d.addMixin=function(b){var a=d.prototype,e;for(e in a)a.hasOwnProperty(e)&&(b[e]=a[e])};d.prototype={addAnnotationType:function(b){if(!this._annotationTypes)this._annotationTypes= +[];this._annotationTypes.push(b)},getAnnotationTypePriority:function(b){if(this._annotationTypes)for(var a=0;a<this._annotationTypes.length;a++)if(this._annotationTypes[a]===b)return a+1;return 0},getAnnotationsByType:function(b,a,e){b=b.getAnnotations(a,e);for(e=[];b.hasNext();)a=b.next(),this.getAnnotationTypePriority(a.type)!==0&&e.push(a);var c=this;e.sort(function(a,b){return c.getAnnotationTypePriority(a.type)-c.getAnnotationTypePriority(b.type)});return e},isAnnotationTypeVisible:function(b){return this.getAnnotationTypePriority(b)!== +0},removeAnnotationType:function(b){if(this._annotationTypes)for(var a=0;a<this._annotationTypes.length;a++)if(this._annotationTypes[a]===b){this._annotationTypes.splice(a,1);break}}};f.prototype={addAnnotation:function(b){if(b){var a=this._annotations,e=this._binarySearch(a,b.start);a.splice(e,0,b);b._annotationModel=this;this.onChanged({type:"Changed",added:[b],removed:[],changed:[]})}},getTextModel:function(){return this._model},getAnnotations:function(b,a){var e=this._annotations,c,d=0,f;f=b=== +void 0&&a===void 0?function(){return d<e.length?e[d++]:null}:function(){for(;d<e.length;){var c=e[d++];if(b===c.start||(b>c.start?b<c.end:c.start<a))return c;if(c.start>=a)break}return null};c=f();return{next:function(){var a=c;a&&(c=f());return a},hasNext:function(){return c!==null}}},modifyAnnotation:function(b){if(b&&!(this._getAnnotationIndex(b)<0))this.onChanged({type:"Changed",added:[],removed:[],changed:[b]})},onChanged:function(b){return this.dispatchEvent(b)},removeAnnotations:function(b){var a= +this._annotations,e,c;if(b){e=[];for(c=a.length-1;c>=0;c--){var d=a[c];if(d.type===b)a.splice(c,1),e.splice(0,0,d),d._annotationModel=null}}else e=a;this.onChanged({type:"Changed",removed:e,added:[],changed:[]})},removeAnnotation:function(b){if(b){var a=this._getAnnotationIndex(b);if(!(a<0))b._annotationModel=null,this.onChanged({type:"Changed",removed:this._annotations.splice(a,1),added:[],changed:[]})}},replaceAnnotations:function(b,a){var e=this._annotations,c,d,f,g=[];if(b)for(c=b.length-1;c>= +0;c--)if(f=b[c],d=this._getAnnotationIndex(f),!(d<0))f._annotationModel=null,e.splice(d,1),g.splice(0,0,f);a||(a=[]);for(c=0;c<a.length;c++)f=a[c],d=this._binarySearch(e,f.start),f._annotationModel=this,e.splice(d,0,f);this.onChanged({type:"Changed",removed:g,added:a,changed:[]})},setTextModel:function(b){this._model&&this._model.removeEventListener("Changed",this._listener.onChanged);(this._model=b)&&this._model.addEventListener("Changed",this._listener.onChanged)},_binarySearch:function(b,a){for(var e= +b.length,c=-1,d;e-c>1;)d=Math.floor((e+c)/2),a<=b[d].start?e=d:c=d;return e},_getAnnotationIndex:function(b){for(var a=this._annotations,e=this._binarySearch(a,b.start);e<a.length&&a[e].start===b.start;){if(a[e]===b)return e;e++}return-1},_onChanged:function(b){var a=b.start,e=b.removedCharCount,c=this._annotations,d=a+e;if(0<c.length){for(var f={type:"Changed",added:[],removed:[],changed:[],textModelChangedEvent:b},b=b.addedCharCount-e,e=0;e<c.length;e++){var g=c[e];if(g.start>=d)g._oldStart=g.start, +g._oldEnd=g.end,g.start+=b,g.end+=b,f.changed.push(g);else if(!(g.end<=a))g.start<a&&d<g.end?(g._oldStart=g.start,g._oldEnd=g.end,g.end+=b,f.changed.push(g)):(c.splice(e,1),f.removed.push(g),g._annotationModel=null,g.expand&&g.expand(),e--)}if(f.added.length>0||f.removed.length>0||f.changed.length>0)this.onChanged(f)}}};m.EventTarget.addMixin(f.prototype);g.prototype={destroy:function(){var b=this._view;if(b)b.removeEventListener("Destroy",this._listener.onDestroy),b.removeEventListener("LineStyle", +this._listener.onLineStyle),this.view=null;(b=this._annotationModel)&&b.removeEventListener("Changed",this._listener.onChanged)},_mergeStyle:function(b,a){if(a){b||(b={});b.styleClass&&a.styleClass&&b.styleClass!==a.styleClass?b.styleClass+=" "+a.styleClass:b.styleClass=a.styleClass;var e;if(a.tagName&&!b.tagName)b.tagName=a.tagName;if(a.style){if(!b.style)b.style={};for(e in a.style)b.style[e]||(b.style[e]=a.style[e])}if(a.attributes){if(!b.attributes)b.attributes={};for(e in a.attributes)b.attributes[e]|| +(b.attributes[e]=a.attributes[e])}}return b},_mergeStyleRanges:function(b,a){b||(b=[]);var e,c;for(c=0;c<b.length&&a;c++){var d=b[c];if(a.end<=d.start)break;if(!(a.start>=d.end)){e=this._mergeStyle({},d.style);e=this._mergeStyle(e,a.style);var f=[];f.push(c,1);a.start<d.start&&f.push({start:a.start,end:d.start,style:a.style});a.start>d.start&&f.push({start:d.start,end:a.start,style:d.style});f.push({start:Math.max(d.start,a.start),end:Math.min(d.end,a.end),style:e});a.end<d.end&&f.push({start:a.end, +end:d.end,style:d.style});a=a.end>d.end?{start:d.end,end:a.end,style:a.style}:null;Array.prototype.splice.apply(b,f)}}a&&(e=this._mergeStyle({},a.style),b.splice(c,0,{start:a.start,end:a.end,style:e}));return b},_onAnnotationModelChanged:function(b){function a(a,b){f.getBaseModel&&(a=f.mapOffset(a,!0),b=f.mapOffset(b,!0));a!==-1&&b!==-1&&c.redrawRange(a,b)}function e(b,e){for(var c=0;c<b.length;c++)if(d.isAnnotationTypeVisible(b[c].type)){var l=b[c];a(l.start,l.end);e&&l._oldStart!==void 0&&l._oldEnd&& +a(l._oldStart,l._oldEnd)}}var c=this._view;if(c){var d=this,f=c.getModel();e(b.added);e(b.removed);e(b.changed,!0)}},_onDestroy:function(){this.destroy()},_onLineStyle:function(b){var a=this._annotationModel,e=b.textView.getModel(),c=a.getTextModel(),d=b.lineStart,f=b.lineStart+b.lineText.length;c!==e&&(d=e.mapOffset(d),f=e.mapOffset(f));for(a=a.getAnnotations(d,f);a.hasNext();)if(d=a.next(),this.isAnnotationTypeVisible(d.type)){if(d.rangeStyle){var f=d.start,g=d.end;c!==e&&(f=e.mapOffset(f,!0),g= +e.mapOffset(g,!0));b.ranges=this._mergeStyleRanges(b.ranges,{start:f,end:g,style:d.rangeStyle})}if(d.lineStyle)b.style=this._mergeStyle({},b.style),b.style=this._mergeStyle(b.style,d.lineStyle)}}};d.addMixin(g.prototype);return{FoldingAnnotation:n,AnnotationType:i,AnnotationTypeList:d,AnnotationModel:f,AnnotationStyler:g}}); +define("orion/editor/tooltip","i18n!orion/editor/nls/messages,orion/editor/textView,orion/editor/textModel,orion/editor/projectionTextModel,orion/editor/util,orion/util".split(","),function(k,m,n,i,c,d){function f(c){this._view=c;this._fadeDelay=500;this._hideDelay=200;this._showDelay=500;this._autoHideDelay=5E3;this._create(c.getOptions("parent").ownerDocument)}f.getTooltip=function(c){if(!c._tooltip)c._tooltip=new f(c);return c._tooltip};f.prototype={_create:function(f){if(!this._tooltipDiv){var h= +this._tooltipDiv=d.createElement(f,"div");h.tabIndex=0;h.className="textviewTooltip";h.setAttribute("aria-live","assertive");h.setAttribute("aria-atomic","true");var b=this._tooltipContents=d.createElement(f,"div");h.appendChild(b);f.body.appendChild(h);var a=this;c.addEventListener(h,"mouseover",function(){if(a._hideDelay){var b=a._getWindow();if(a._delayedHideTimeout)b.clearTimeout(a._delayedHideTimeout),a._delayedHideTimeout=null;if(a._hideTimeout)b.clearTimeout(a._hideTimeout),a._hideTimeout= +null;a._nextTarget=null}},!1);c.addEventListener(h,"mouseout",function(b){b=b.relatedTarget||b.toElement;b===h||a._hasFocus()||(!b||!c.contains(h,b))&&a._hide()},!1);c.addEventListener(h,"keydown",function(b){b.keyCode===27&&a._hide()},!1);c.addEventListener(f,"mousedown",this._mouseDownHandler=function(b){a.isVisible()&&(c.contains(h,b.target||b.srcElement)||a._hide())},!0);this._view.addEventListener("Destroy",function(){a.destroy()});this._hide()}},_getWindow:function(){var c=this._tooltipDiv.ownerDocument; +return c.defaultView||c.parentWindow},destroy:function(){if(this._tooltipDiv){this._hide();var d=this._tooltipDiv.parentNode;d&&d.removeChild(this._tooltipDiv);c.removeEventListener(this._tooltipDiv.ownerDocument,"mousedown",this._mouseDownHandler,!0);this._tooltipDiv=null}},_hasFocus:function(){var d=this._tooltipDiv;return!d?!1:c.contains(d,d.ownerDocument.activeElement)},hide:function(c){if(c===void 0)c=this._hideDelay;var d=this._getWindow();if(this._delayedHideTimeout)d.clearTimeout(this._delayedHideTimeout), +this._delayedHideTimeout=null;var b=this;c?b._delayedHideTimeout=d.setTimeout(function(){b._delayedHideTimeout=null;b._hide();b.setTarget(b._nextTarget,0)},c):(b._hide(),b.setTarget(b._nextTarget,0))},_hide:function(){var c=this._tooltipDiv;if(c){this._hasFocus()&&this._view.focus();if(this._contentsView)this._contentsView.destroy(),this._contentsView=null;if(this._tooltipContents)this._tooltipContents.innerHTML="";c.style.visibility="hidden";c=this._getWindow();if(this._showTimeout)c.clearTimeout(this._showTimeout), +this._showTimeout=null;if(this._delayedHideTimeout)c.clearTimeout(this._delayedHideTimeout),this._delayedHideTimeout=null;if(this._hideTimeout)c.clearTimeout(this._hideTimeout),this._hideTimeout=null;if(this._fadeTimeout)c.clearInterval(this._fadeTimeout),this._fadeTimeout=null}},isVisible:function(){return this._tooltipDiv&&this._tooltipDiv.style.visibility==="visible"},setTarget:function(c,d,b){if(this.isVisible()){if(!this._hasFocus())this._nextTarget=c,this.hide(b)}else if(this._target=c){var a= +this,c=a._getWindow();if(a._showTimeout)c.clearTimeout(a._showTimeout),a._showTimeout=null;d===0?a.show(!0):a._showTimeout=c.setTimeout(function(){a._showTimeout=null;a.show(!0)},d?d:a._showDelay)}},show:function(c){if(this._target){var d=this._target.getTooltipInfo();if(d){var b=this._tooltipDiv,a=this._tooltipContents;b.style.left=b.style.right=b.style.width=b.style.height=a.style.width=a.style.height="auto";var e=d.contents;e instanceof Array&&(e=this._getAnnotationContents(e));if(typeof e==="string")a.innerHTML= +e;else if(this._isNode(e))a.appendChild(e);else if(e instanceof i.ProjectionTextModel){var l=this._view,f=l.getOptions();f.wrapMode=!1;f.parent=a;var q=f.themeClass;q?((q=q.replace("tooltipTheme",""))&&(q=" "+q),q="tooltipTheme"+q):q="tooltipTheme";f.themeClass=q;f=this._contentsView=new m.TextView(f);f.addEventListener("LineStyle",function(a){l.onLineStyle(a)});f.setModel(e);e=f.computeSize();a.style.width=e.width+"px";a.style.height=e.height+"px";f.resize()}else return;a=b.ownerDocument.documentElement; +d.anchor==="right"?(e=a.clientWidth-d.x,b.style.right=e+"px"):(e=parseInt(this._getNodeStyle(b,"padding-left","0"),10),e+=parseInt(this._getNodeStyle(b,"border-left-width","0"),10),e=d.x-e,b.style.left=e+"px");b.style.maxWidth=a.clientWidth-e-10+"px";e=parseInt(this._getNodeStyle(b,"padding-top","0"),10);e+=parseInt(this._getNodeStyle(b,"border-top-width","0"),10);e=d.y-e;b.style.top=e+"px";b.style.maxHeight=a.clientHeight-e-10+"px";b.style.opacity="1";b.style.visibility="visible";if(c){var r=this, +p=this._getWindow();r._hideTimeout=p.setTimeout(function(){r._hideTimeout=null;var a=parseFloat(r._getNodeStyle(b,"opacity","1"));r._fadeTimeout=p.setInterval(function(){b.style.visibility==="visible"&&a>0?(a-=0.1,b.style.opacity=a):r._hide()},r._fadeDelay/10)},r._autoHideDelay)}}}},_getAnnotationContents:function(f){function h(a,b){var e=t.getLineStart(t.getLineAtOffset(a)),c=t.getLineEnd(t.getLineAtOffset(b),!0);return t.getText(e,c)}function b(a){var b=a.title,e=d.createElement(q,"div");e.className= +"tooltipRow";if(a.html)e.innerHTML=a.html,e.lastChild&&c.addEventListener(e.lastChild,"click",function(){var b=a.start,e=a.end;p.getBaseModel&&(b=p.mapOffset(b,!0),e=p.mapOffset(e,!0));r.setSelection(b,e,1/3,function(){o._hide()})},!1),e.appendChild(q.createTextNode("\u00a0"));b||(b=h(a.start,a.end));typeof b==="function"&&(b=a.title());if(typeof b==="string"){var j=d.createElement(q,"span");j.appendChild(q.createTextNode(b));b=j}e.appendChild(b);return e}for(var a,e=[],l=0;l<f.length;l++)a=f[l], +a.title!==""&&!a.groupAnnotation&&e.push(a);f=e;if(f.length===0)return null;var o=this,q=this._tooltipDiv.ownerDocument,r=this._view,p=r.getModel(),t=p.getBaseModel?p.getBaseModel():p;if(f.length===1)if(a=f[0],a.title!==void 0){a=b(a);if(a.firstChild)(f=a.firstChild.className)&&(f+=" "),f+="single",a.firstChild.className=f;return a}else return f=new i.ProjectionTextModel(t),e=t.getLineStart(t.getLineAtOffset(a.start)),l=t.getCharCount(),a.end!==l&&f.addProjection({start:a.end,end:l}),e>0&&f.addProjection({start:0, +end:e}),f;else{e=d.createElement(q,"div");a=d.createElement(q,"em");a.appendChild(q.createTextNode(k.multipleAnnotations));e.appendChild(a);for(l=0;l<f.length;l++)a=f[l],(a=b(a))&&e.appendChild(a);return e}},_getNodeStyle:function(c,d,b){var a;if(c&&(a=c.style[d],!a))if(c.currentStyle){for(a=0;(a=d.indexOf("-",a))!==-1;)d=d.substring(0,a)+d.substring(a+1,a+2).toUpperCase()+d.substring(a+2);a=c.currentStyle[d]}else a=(c=c.ownerDocument.defaultView.getComputedStyle(c,null))?c.getPropertyValue(d):null; +return a||b},_isNode:function(c){return typeof Node==="object"?c instanceof Node:c&&typeof c==="object"&&typeof c.nodeType==="number"&&typeof c.nodeName==="string"}};return{Tooltip:f}}); +define("orion/editor/rulers",["i18n!orion/editor/nls/messages","orion/editor/annotations","orion/editor/tooltip","orion/util"],function(k,m,n,i){function c(b,a,e,c){this._location=a||"left";this._overview=e||"page";this._rulerStyle=c;this._view=null;var d=this;this._listener={onTextModelChanged:function(a){d._onTextModelChanged(a)},onAnnotationModelChanged:function(a){d._onAnnotationModelChanged(a)}};this.setAnnotationModel(b)}function d(b,a,e,l,d){c.call(this,b,a,"page",e);this._oddStyle=l||{style:{backgroundColor:"white"}}; +this._evenStyle=d||{style:{backgroundColor:"white"}};this._numOfDigits=0;this._firstLine=1}function f(b,a,e){c.call(this,b,a,"page",e)}function g(b,a,e){c.call(this,b,a,"document",e)}function h(b,a,e){f.call(this,b,a,e)}c.prototype={getAnnotations:function(b,a){var e=this._annotationModel;if(!e)return[];var c=this._view.getModel(),d=c.getLineStart(b),f=c.getLineEnd(a-1),g=c;c.getBaseModel&&(g=c.getBaseModel(),d=c.mapOffset(d),f=c.mapOffset(f));for(var h=[],e=this.getAnnotationsByType(e,d,f),d=0;d< +e.length;d++)for(var f=e[d],i=g.getLineAtOffset(f.start),v=g.getLineAtOffset(Math.max(f.start,f.end-1)),s=i;s<=v;s++){var u=s;if(c!==g){u=g.getLineStart(s);u=c.mapOffset(u,!0);if(u===-1)continue;u=c.getLineAtOffset(u)}if(b<=u&&u<a){var j=this._mergeAnnotation(h[u],f,s-i,v-i+1);j&&(h[u]=j)}}if(!this._multiAnnotation&&this._multiAnnotationOverlay)for(var k in h)h[k]._multiple&&(h[k].html+=this._multiAnnotationOverlay.html);return h},getAnnotationModel:function(){return this._annotationModel},getLocation:function(){return this._location}, +getOverview:function(){return this._overview},getRulerStyle:function(){return this._rulerStyle},getView:function(){return this._view},getWidestAnnotation:function(){return null},setAnnotationModel:function(b){this._annotationModel&&this._annotationModel.removEventListener("Changed",this._listener.onAnnotationModelChanged);(this._annotationModel=b)&&this._annotationModel.addEventListener("Changed",this._listener.onAnnotationModelChanged)},setMultiAnnotation:function(b){this._multiAnnotation=b},setMultiAnnotationOverlay:function(b){this._multiAnnotationOverlay= +b},setView:function(b){this._onTextModelChanged&&this._view&&this._view.removeEventListener("ModelChanged",this._listener.onTextModelChanged);this._view=b;this._onTextModelChanged&&this._view&&this._view.addEventListener("ModelChanged",this._listener.onTextModelChanged)},onClick:function(b){if(b!==void 0){var a=this._view,e=a.getModel(),c=e,d=e.getLineStart(b),f=d,g=d,h=this._annotationModel;if(h){a=a.getSelection();g=e.getLineEnd(b,!0);if(d<=a.start&&a.start<g)d=a.start;e.getBaseModel&&(d=e.mapOffset(d), +g=e.mapOffset(g),c=e.getBaseModel());for(var i,g=h.getAnnotations(d,g),h=null;!i&&g.hasNext();)a=g.next(),this.isAnnotationTypeVisible(a.type)&&(h=a,a.start<=d||(i=a));if(h&&h.groupId!==void 0)this._currentClickGroup=this._currentClickGroup===h.groupId?null:h.groupId,this._setCurrentGroup(b);i&&c.getLineAtOffset(i.start)===c.getLineAtOffset(d)?(d=i.start,g=i.end):g=d=f;e.getBaseModel&&(d=e.mapOffset(d,!0),g=e.mapOffset(g,!0))}(b=n.Tooltip.getTooltip(this._view))&&b.setTarget(null);this._view.setSelection(g, +d,1/3,function(){})}},onDblClick:function(){},onMouseMove:function(b,a){var e=n.Tooltip.getTooltip(this._view);if(e&&!(e.isVisible()&&this._tooltipLineIndex===b)){this._tooltipLineIndex=b;var c=this;e.setTarget({y:a.clientY,getTooltipInfo:function(){return c._getTooltipInfo(c._tooltipLineIndex,this.y)}})}},onMouseOver:function(b,a){this.onMouseMove(b,a);this._currentClickGroup||this._setCurrentGroup(b)},onMouseOut:function(){this._currentClickGroup||this._setCurrentGroup(-1);var b=n.Tooltip.getTooltip(this._view); +b&&b.setTarget(null)},_getTooltipInfo:function(b,a){if(b!==void 0){var e=this._view,c=e.getModel(),d=this._annotationModel,f=[];if(d){var f=c.getLineStart(b),g=c.getLineEnd(b);c.getBaseModel&&(f=c.mapOffset(f),g=c.mapOffset(g));f=this.getAnnotationsByType(d,f,g)}d=this._getTooltipContents(b,f);if(!d)return null;d={contents:d,anchor:this.getLocation()};f=e.getClientArea();f.y=this.getOverview()==="document"?e.convert({y:a},"view","document").y:e.getLocationAtOffset(c.getLineStart(b)).y;e.convert(f, +"document","page");d.x=f.x;d.y=f.y;d.anchor==="right"&&(d.x+=f.width);return d}},_getTooltipContents:function(b,a){return a},_onAnnotationModelChanged:function(b){function a(a){for(var b=0;b<a.length;b++)if(d.isAnnotationTypeVisible(a[b].type)){var f=a[b].start,g=a[b].end;c.getBaseModel&&(f=c.mapOffset(f,!0),g=c.mapOffset(g,!0));f!==-1&&g!==-1&&e.redrawLines(c.getLineAtOffset(f),c.getLineAtOffset(Math.max(f,g-1))+1,d)}}var e=this._view;if(e){var c=e.getModel(),d=this,f=c.getLineCount();b.textModelChangedEvent? +(b=b.textModelChangedEvent.start,c.getBaseModel&&(b=c.mapOffset(b,!0)),b=c.getLineAtOffset(b),e.redrawLines(b,f,d)):(a(b.added),a(b.removed),a(b.changed))}},_mergeAnnotation:function(b,a,e){b||(b={});if(e===0)if(b.html&&a.html){if(a.html!==b.html&&!b._multiple&&this._multiAnnotation)b.html=this._multiAnnotation.html;b._multiple=!0}else b.html=a.html;b.style=this._mergeStyle(b.style,a.style);return b},_mergeStyle:function(b,a){if(a){b||(b={});b.styleClass&&a.styleClass&&b.styleClass!==a.styleClass? +b.styleClass+=" "+a.styleClass:b.styleClass=a.styleClass;var e;if(a.style){if(!b.style)b.style={};for(e in a.style)b.style[e]===void 0&&(b.style[e]=a.style[e])}if(a.attributes){if(!b.attributes)b.attributes={};for(e in a.attributes)b.attributes[e]===void 0&&(b.attributes[e]=a.attributes[e])}}return b},_setCurrentGroup:function(b){var a=this._annotationModel,e=null,c=a.getTextModel(),d,f=this._currentGroupAnnotation;if(b!==-1){var g=c.getLineStart(b),h=c.getLineEnd(b);c.getBaseModel&&(g=c.mapOffset(g), +h=c.mapOffset(h));for(d=a.getAnnotations(g,h);d.hasNext();)if(c=d.next(),this.isAnnotationTypeVisible(c.type)&&c.start<=g&&c.end>=h&&c.groupId!==void 0){e=c;break}if(f&&e&&f.groupId===e.groupId)return}this._currentGroupAnnotation=null;f&&a.removeAnnotations(f.groupType);if(e&&b!==-1){this._currentGroupAnnotation=e;d=a.getAnnotations();for(b=[];d.hasNext();)c=d.next(),delete c.groupAnnotation,c.groupId===e.groupId&&(c=c.createGroupAnnotation(),b.push(c));a.replaceAnnotations(null,b)}}};m.AnnotationTypeList.addMixin(c.prototype); +d.prototype=new c;d.prototype.getAnnotations=function(b,a){for(var e=c.prototype.getAnnotations.call(this,b,a),d=this._view.getModel(),f=b;f<a;f++){var g=f&1?this._oddStyle:this._evenStyle,h=f;d.getBaseModel&&(h=d.getLineStart(h),h=d.getBaseModel().getLineAtOffset(d.mapOffset(h)));e[f]||(e[f]={});e[f].html=this._firstLine+h+"";if(!e[f].style)e[f].style=g}return e};d.prototype.getWidestAnnotation=function(){var b=this._view.getModel().getLineCount();return this.getAnnotations(b-1,b)[b-1]};d.prototype.setFirstLine= +function(b){this._firstLine=b!==void 0?b:1};d.prototype._onTextModelChanged=function(b){var b=b.start,a=this._view.getModel(),e=(this._firstLine+(a.getBaseModel?a.getBaseModel().getLineCount():a.getLineCount())-1+"").length;if(this._numOfDigits!==e)this._numOfDigits=e,this._view.redrawLines(a.getLineAtOffset(b),a.getLineCount(),this)};f.prototype=new c;g.prototype=new c;g.prototype.getRulerStyle=function(){var b={style:{lineHeight:"1px",fontSize:"1px"}};return b=this._mergeStyle(b,this._rulerStyle)}; +g.prototype._getTooltipContents=function(b,a){if(a.length===0){var e=this._view.getModel(),d=b;e.getBaseModel&&(d=e.getLineStart(d),d=e.getBaseModel().getLineAtOffset(e.mapOffset(d)));return i.formatMessage(k.line,d+1)}return c.prototype._getTooltipContents.call(this,b,a)};g.prototype._mergeAnnotation=function(b,a,e,c){if(e===0){if(!b)b={html:" ",style:{style:{height:3*c+"px"}}},b.style=this._mergeStyle(b.style,a.overviewStyle);return b}};h.prototype=new f;h.prototype.onClick=function(b){if(b!== +void 0){var a=this._annotationModel;if(a){var e=this._view.getModel(),c=e.getLineStart(b),b=e.getLineEnd(b,!0);e.getBaseModel&&(c=e.mapOffset(c),b=e.mapOffset(b),e=e.getBaseModel());for(var d,a=a.getAnnotations(c,b);!d&&a.hasNext();)b=a.next(),this.isAnnotationTypeVisible(b.type)&&(d=b);d&&e.getLineAtOffset(d.start)===e.getLineAtOffset(c)&&((e=n.Tooltip.getTooltip(this._view))&&e.setTarget(null),d.expanded?d.collapse():d.expand())}}};h.prototype._getTooltipContents=function(b,a){return a.length=== +1&&a[0].expanded?null:f.prototype._getTooltipContents.call(this,b,a)};h.prototype._onAnnotationModelChanged=function(b){function a(a){for(g=0;g<a.length;g++)if(d.isAnnotationTypeVisible(a[g].type)){var b=a[g].start;c.getBaseModel&&(b=c.mapOffset(b,!0));b!==-1&&(p=Math.min(p,c.getLineAtOffset(b)))}}if(b.textModelChangedEvent)f.prototype._onAnnotationModelChanged.call(this,b);else{var e=this._view;if(e){var c=e.getModel(),d=this,g,h=c.getLineCount(),p=h;a(b.added);a(b.removed);a(b.changed);b=e.getRulers(); +for(g=0;g<b.length;g++)e.redrawLines(p,h,b[g])}}};return{Ruler:c,AnnotationRuler:f,LineNumberRuler:d,OverviewRuler:g,FoldingRuler:h}}); +define("orion/editor/undoStack",[],function(){function k(i,c,d,f,g){this.model=i;this.offset=c;this.text=d;this.previousText=f;this.type=g}function m(i){this.owner=i;this.changes=[]}function n(i,c){this.size=c!==void 0?c:100;this.reset();var d=this;this._listener={onChanging:function(c){d._onChanging(c)},onDestroy:function(c){d._onDestroy(c)}};if(i.getModel){var f=i.getModel();f.getBaseModel&&(f=f.getBaseModel());this.model=f;this.setView(i)}else this.shared=!0,this.model=i;this.model.addEventListener("Changing", +this._listener.onChanging)}k.prototype={getRedoChanges:function(){return[{start:this.offset,end:this.offset+this.previousText.length,text:this.text}]},getUndoChanges:function(){return[{start:this.offset,end:this.offset+this.text.length,text:this.previousText}]},undo:function(i,c){this._doUndoRedo(this.offset,this.previousText,this.text,i,c);return!0},redo:function(i,c){this._doUndoRedo(this.offset,this.text,this.previousText,i,c);return!0},merge:function(i,c,d,f,g){if(f===this.type)if(f===1&&i=== +this.offset+this.text.length)return this.text+=c,!0;else if(f===-1&&g===this.offset)return this.offset=i,this.previousText=d+this.previousText,!0;else if(f===-1&&i===this.offset)return this.previousText+=d,!0;return!1},_doUndoRedo:function(i,c,d,f,g){this.model.setText(c,i,i+d.length);g&&f&&(d=f.getModel(),d!==this.model&&(i=d.mapOffset(i,!0)),f.setSelection(i,i+c.length))}};m.prototype={getRedoChanges:function(){for(var i=[],c=0;c<this.changes.length;c++)i=i.concat(this.changes[c].getRedoChanges()); +return i},getUndoChanges:function(){for(var i=[],c=this.changes.length-1;c>=0;c--)i=i.concat(this.changes[c].getUndoChanges());return i},add:function(i){this.changes.push(i)},end:function(i){if(i)this.endSelection=i.getSelection(),this.endCaret=i.getCaretOffset();(i=this.owner)&&i.end&&i.end()},undo:function(i,c){this.changes.length>1&&i&&i.setRedraw(!1);for(var d=this.changes.length-1;d>=0;d--)this.changes[d].undo(i,!1);this.changes.length>1&&i&&i.setRedraw(!0);if(c&&i){var d=this.startSelection.start, +f=this.startSelection.end;i.setSelection(this.startCaret?d:f,this.startCaret?f:d)}(d=this.owner)&&d.undo&&d.undo();return this.changes.length>0},redo:function(i,c){this.changes.length>1&&i&&i.setRedraw(!1);for(var d=0;d<this.changes.length;d++)this.changes[d].redo(i,!1);i&&i.setRedraw(!0);if(c&&i){var d=this.endSelection.start,f=this.endSelection.end;i.setSelection(this.endCaret?d:f,this.endCaret?f:d)}(d=this.owner)&&d.redo&&d.redo();return this.changes.length>0},merge:function(i,c,d,f,g){var h=this.changes.length; +return h>0?this.changes[h-1].merge(i,c,d,f,g):!1},start:function(i){if(i)this.startSelection=i.getSelection(),this.startCaret=i.getCaretOffset();(i=this.owner)&&i.start&&i.start()}};n.prototype={destroy:function(){this._onDestroy()},add:function(i){this.compoundChange?this.compoundChange.add(i):(this.stack.splice(this.index,this.stack.length-this.index,i),this.index++,this.stack.length>this.size&&(this.stack.shift(),this.index--))},markClean:function(){this._commitUndo();if(this.cleanChange=this.stack[this.index- +1])this.cleanChange.type=2},isClean:function(){return this.cleanChange===this.stack[this.index-1]},canUndo:function(){return this.index>0},canRedo:function(){return this.stack.length-this.index>0},endCompoundChange:function(){this.compoundChange&&this.compoundChange.end(this.view);this.compoundChange=void 0},getSize:function(){return{undo:this.index,redo:this.stack.length-this.index}},getRedoChanges:function(){this._commitUndo();for(var i=[],c=this.index;c<this.stack.length;c++)i=i.concat(this.stack[c].getRedoChanges()); +return i},getUndoChanges:function(){this._commitUndo();for(var i=[],c=this.index;c>=0;c--)i=i.concat(this.stack[c].getUndoChanges());return i},undo:function(){this._commitUndo();var i;i=!1;this._ignoreUndo=!0;do{if(this.index<=0)break;i=this.stack[--this.index]}while(!(i=i.undo(this.view,!0)));this._ignoreUndo=!1;return i},redo:function(){this._commitUndo();var i;this._ignoreUndo=!0;do{if(this.index>=this.stack.length)break;i=this.stack[this.index++]}while(!i.redo(this.view,!0));this._ignoreUndo= +!1;return!0},reset:function(){this.index=0;this.cleanChange=void 0;this.stack=[];this._ignoreUndo=!1;this._compoundChange=void 0},setView:function(i){if(this.view!==i)this.view&&i.removeEventListener("Destroy",this._listener.onDestroy),(this.view=i)&&i.addEventListener("Destroy",this._listener.onDestroy)},startCompoundChange:function(i){this._commitUndo();i=new m(i);this.add(i);this.compoundChange=i;this.compoundChange.start(this.view);return this.compoundChange},_commitUndo:function(){this.endCompoundChange()}, +_onDestroy:function(i){(!i||!this.shared)&&this.model.removeEventListener("Changing",this._listener.onChanging);if(this.view)this.view.removeEventListener("Destroy",this._listener.onDestroy),this.view=null},_onChanging:function(i){if(!this._ignoreUndo){var c=i.text,d=i.start,f=i.addedCharCount,g=i.removedCharCount,i=d+g,h=0;f===0&&g===1?h=-1:f===1&&g===0&&(h=1);f=this.stack.length;g=this.model.getText(d,i);(!(f>0&&this.index===f)||!this.stack[f-1].merge(d,c,g,h,i))&&this.add(new k(this.model,d,c, +g,h))}}};return{UndoStack:n}}); +define("orion/editor/textDND",["orion/util"],function(k){function m(k,i){this._view=k;this._undoStack=i;this._dragSelection=null;this._dropOffset=-1;this._dropText=null;var c=this;this._listener={onDragStart:function(d){c._onDragStart(d)},onDragEnd:function(d){c._onDragEnd(d)},onDragEnter:function(d){c._onDragEnter(d)},onDragOver:function(d){c._onDragOver(d)},onDrop:function(d){c._onDrop(d)},onDestroy:function(d){c._onDestroy(d)}};k.addEventListener("DragStart",this._listener.onDragStart);k.addEventListener("DragEnd", +this._listener.onDragEnd);k.addEventListener("DragEnter",this._listener.onDragEnter);k.addEventListener("DragOver",this._listener.onDragOver);k.addEventListener("Drop",this._listener.onDrop);k.addEventListener("Destroy",this._listener.onDestroy)}m.prototype={destroy:function(){var k=this._view;if(k)k.removeEventListener("DragStart",this._listener.onDragStart),k.removeEventListener("DragEnd",this._listener.onDragEnd),k.removeEventListener("DragEnter",this._listener.onDragEnter),k.removeEventListener("DragOver", +this._listener.onDragOver),k.removeEventListener("Drop",this._listener.onDrop),k.removeEventListener("Destroy",this._listener.onDestroy),this._view=null},_onDestroy:function(){this.destroy()},_onDragStart:function(k){var i=this._view,c=i.getSelection(),i=i.getModel();if(i.getBaseModel)c.start=i.mapOffset(c.start),c.end=i.mapOffset(c.end),i=i.getBaseModel();if(i=i.getText(c.start,c.end))this._dragSelection=c,k.event.dataTransfer.effectAllowed="copyMove",k.event.dataTransfer.setData("Text",i)},_onDragEnd:function(m){if(this._dragSelection){var i= +this._view,c=m.event.dataTransfer.dropEffect;if(!k.isFirefox&&(c!=="none"||this._dropText))c=m.event.dataTransfer.dropEffect=this._dropEffect;this._undoStack&&this._undoStack.startCompoundChange();(m=c==="move")&&i.setText("",this._dragSelection.start,this._dragSelection.end);if(this._dropText){var c=this._dropText,d=this._dropOffset;if(m)if(d>=this._dragSelection.end)d-=this._dragSelection.end-this._dragSelection.start;else if(d>=this._dragSelection.start)d=this._dragSelection.start;i.setText(c, +d,d);i.setSelection(d,d+c.length);this._dropText=null;this._dropOffset=-1}this._undoStack&&this._undoStack.endCompoundChange()}this._dragSelection=null},_onDragEnter:function(k){this._onDragOver(k)},_onDragOver:function(m){var i=m.event.dataTransfer.types,c=!this._view.getOptions("readonly");c&&i&&(c=i.contains?i.contains("text/plain")||i.contains("Text"):i.indexOf("text/plain")!==-1||i.indexOf("Text")!==-1);if(c){if(!k.isFirefox)this._dropEffect=m.event.dataTransfer.dropEffect=(k.isMac?m.event.altKey: +m.event.ctrlKey)?"copy":"move"}else m.event.dataTransfer.dropEffect="none"},_onDrop:function(m){var i=this._view,c=m.event.dataTransfer.getData("Text");if(c){if(!k.isFirefox)m.event.dataTransfer.dropEffect=this._dropEffect;m=i.getOffsetAtLocation(m.x,m.y);this._dragSelection?(this._dropOffset=m,this._dropText=c):(i.setText(c,m,m),i.setSelection(m,m+c.length))}}};return{TextDND:m}}); +define("orion/objects",[],function(){function k(k){for(var n=1;n<arguments.length;n++){var i=arguments[n],c;for(c in i)Object.prototype.hasOwnProperty.call(i,c)&&(k[c]=i[c])}return k}return{clone:function(m){if(Array.isArray(m))return Array.prototype.slice.call(m);var n=Object.create(Object.getPrototypeOf(m));k(n,m);return n},mixin:k,toArray:function(k){return Array.isArray(k)?k:[k]}}}); +define("orion/editor/editor","i18n!orion/editor/nls/messages,orion/editor/eventTarget,orion/editor/tooltip,orion/editor/annotations,orion/objects,orion/util".split(","),function(k,m,n,i,c,d){function f(b){b=b||{};this._domNode=b.domNode;this._model=b.model;this._undoStack=b.undoStack;this._statusReporter=b.statusReporter;this._title=null;var a=this;this._listener={onChanged:function(b){a.onChanged(b)}};this._model&&this._model.addEventListener("Changed",this._listener.onChanged);this.checkDirty()} +function g(b){b=b||{};f.call(this,b);this._textViewFactory=b.textViewFactory;this._undoStackFactory=b.undoStackFactory;this._textDNDFactory=b.textDNDFactory;this._annotationFactory=b.annotationFactory;this._foldingRulerFactory=b.foldingRulerFactory;this._lineNumberRulerFactory=b.lineNumberRulerFactory;this._contentAssistFactory=b.contentAssistFactory;this._keyBindingFactory=b.keyBindingFactory;this._contentAssist=this._foldingRuler=this._overviewRuler=this._lineNumberRuler=this._annotationRuler=this._annotationModel= +this._annotationStyler=null}var h=i.AnnotationType;f.prototype={destroy:function(){this.uninstall();this._statusReporter=this._domNode=null;this._model&&this._model.removeEventListener("Changed",this._listener.onChanged)},checkDirty:function(){this.setDirty(this._undoStack&&!this._undoStack.isClean())},focus:function(){},getModel:function(){return this._model},getText:function(b,a){return this.getModel().getText(b,a)},getTitle:function(){return this._title},getUndoStack:function(){return this._undoStack}, +install:function(){this.installed=!0},isDirty:function(){return this._dirty},markClean:function(){this.getUndoStack().markClean();this.setDirty(!1)},onDirtyChanged:function(b){return this.dispatchEvent(b)},onInputChanged:function(b){return this.dispatchEvent(b)},onChanged:function(){this.checkDirty()},reportStatus:function(b,a,e){this._statusReporter&&this._statusReporter(b,a,e)},resize:function(){},setDirty:function(b){if(this._dirty!==b)this._dirty=b,this.onDirtyChanged({type:"DirtyChanged"})}, +_setModelText:function(b){this._model&&this._model.setText(b)},setInput:function(b,a,e,c){this._title=b;c||(a?this.reportStatus(a,"error"):e!==null&&e!==void 0&&typeof e==="string"&&this._setModelText(e),this._undoStack&&this._undoStack.reset());this.checkDirty();this.onInputChanged({type:"InputChanged",title:b,message:a,contents:e,contentsSaved:c})},setText:function(b,a,e){this.getModel().setText(b,a,e)},uninstall:function(){this.installed=!1}};m.EventTarget.addMixin(f.prototype);g.prototype=new f; +c.mixin(g.prototype,{destroy:function(){f.prototype.destroy.call(this);this._textViewFactory=this._undoStackFactory=this._textDNDFactory=this._annotationFactory=this._foldingRulerFactory=this._lineNumberRulerFactory=this._contentAssistFactory=this._keyBindingFactory=null},getAnnotationModel:function(){return this._annotationModel},getAnnotationRuler:function(){return this._annotationRuler},getAnnotationStyler:function(){return this._annotationStyler},getContentAssist:function(){return this._contentAssist}, +getFoldingRuler:function(){return this._foldingRuler},getLineNumberRuler:function(){return this._lineNumberRuler},getModel:function(){if(!this._textView)return null;var b=this._textView.getModel();b.getBaseModel&&(b=b.getBaseModel());return b},getOverviewRuler:function(){return this._overviewRuler},getTextView:function(){return this._textView},getKeyModes:function(){return this._textView.getKeyModes()},getSourceCodeActions:function(){return this._sourceCodeActions},getLinkedMode:function(){return this._linkedMode}, +getTextActions:function(){return this._textActions},focus:function(){this._textView&&this._textView.focus()},resize:function(){this._textView&&this._textView.resize()},setAnnotationRulerVisible:function(b,a){if(this._annotationRulerVisible!==b||a)if(this._annotationRulerVisible=b,this._annotationRuler){var e=this._textView;b?e.addRuler(this._annotationRuler,0):e.removeRuler(this._annotationRuler)}},setFoldingRulerVisible:function(b,a){if(this._foldingRulerVisible!==b||a)if(this._foldingRulerVisible= +b,this._foldingRuler){var e=this._textView;e.getModel().getBaseModel&&(b?e.addRuler(this._foldingRuler):e.removeRuler(this._foldingRuler))}},setLineNumberRulerVisible:function(b,a){if(this._lineNumberRulerVisible!==b||a)if(this._lineNumberRulerVisible=b,this._lineNumberRuler){var e=this._textView;b?e.addRuler(this._lineNumberRuler,!this._annotationRulerVisible?0:1):e.removeRuler(this._lineNumberRuler)}},setOverviewRulerVisible:function(b,a){if(this._overviewRulerVisible!==b||a)if(this._overviewRulerVisible= +b,this._overviewRuler){var e=this._textView;b?e.addRuler(this._overviewRuler):e.removeRuler(this._overviewRuler)}},mapOffset:function(b,a){var e=this._textView.getModel();e.getBaseModel&&(b=e.mapOffset(b,a));return b},getLineAtOffset:function(b){return this.getModel().getLineAtOffset(this.mapOffset(b))},getLineStart:function(b){return this.getModel().getLineStart(b)},getCaretOffset:function(){return this.mapOffset(this._textView.getCaretOffset())},getSelection:function(){var b=this._textView,a=b.getSelection(), +b=b.getModel();if(b.getBaseModel)a.start=b.mapOffset(a.start),a.end=b.mapOffset(a.end);return a},_expandOffset:function(b){var a=this._textView.getModel(),e=this._annotationModel;if(e&&a.getBaseModel)for(b=e.getAnnotations(b,b+1);b.hasNext();)a=b.next(),a.type===h.ANNOTATION_FOLDING&&a.expand&&a.expand()},setCaretOffset:function(b,a,e){var c=this._textView,d=c.getModel();d.getBaseModel&&(this._expandOffset(b),b=d.mapOffset(b,!0));c.setCaretOffset(b,a,e)},setText:function(b,a,e){var c=this._textView, +d=c.getModel();d.getBaseModel&&(a!==void 0&&(this._expandOffset(a),a=d.mapOffset(a,!0)),e!==void 0&&(this._expandOffset(e),e=d.mapOffset(e,!0)));c.setText(b,a,e)},setSelection:function(b,a,e,c){var d=this._textView,f=d.getModel();f.getBaseModel&&(this._expandOffset(b),this._expandOffset(a),b=f.mapOffset(b,!0),a=f.mapOffset(a,!0));d.setSelection(b,a,e,c)},moveSelection:function(b,a,e,c){var d=this._textView;this.setSelection(b,a||b,1/3,function(){(c===void 0||c)&&d.focus();e&&e()})},_getTooltipInfo:function(b, +a){var e=this._textView,c=this.getAnnotationModel();if(!c)return null;var d=this._annotationStyler;if(!d)return null;var f=e.getOffsetAtLocation(b,a);if(f===-1)return null;f=this.mapOffset(f);d=d.getAnnotationsByType(c,f,f+1);c=[];for(f=0;f<d.length;f++)d[f].rangeStyle&&c.push(d[f]);if(c.length===0)return null;e=e.convert({x:b,y:a},"document","page");return{contents:c,anchor:"left",x:e.x+10,y:e.y+20}},_highlightCurrentLine:function(b,a){var e=this._annotationModel;if(e){var c=this._textView;if(!c.getOptions("singleMode")){var d= +c.getModel(),f=a?d.getLineAtOffset(a.start):-1,g=d.getLineAtOffset(b.start),c=b.start===b.end,p=!a||a.start===a.end,i=d.getLineStart(g),k=d.getLineEnd(g);d.getBaseModel&&(i=d.mapOffset(i),k=d.mapOffset(k));d=this._currentLineAnnotation;if(!(f===g&&p&&c&&d&&d.start===i&&d.end===k)){var f=d?[d]:null,s;c&&(d=h.createAnnotation(h.ANNOTATION_CURRENT_LINE,i,k),s=[d]);this._currentLineAnnotation=d;e.replaceAnnotations(f,s)}}}},installTextView:function(){this.install()},install:function(){if(!this._textView){this._textView= +this._textViewFactory();if(this._undoStackFactory)this._undoStack=this._undoStackFactory.createUndoStack(this),this.checkDirty();if(this._textDNDFactory)this._textDND=this._textDNDFactory.createTextDND(this,this._undoStack);if(this._contentAssistFactory)this._contentAssist=this._contentAssistFactory.createContentAssistMode(this).getContentAssist();var b=this,a=this._textView,e=this;this._listener={onModelChanged:function(){e.checkDirty()},onMouseOver:function(a){e._listener.onMouseMove(a)},onMouseMove:function(b){var c= +n.Tooltip.getTooltip(a);if(c&&!(e._listener.lastMouseX===b.event.clientX&&e._listener.lastMouseY===b.event.clientY))e._listener.lastMouseX=b.event.clientX,e._listener.lastMouseY=b.event.clientY,c.setTarget({x:b.x,y:b.y,getTooltipInfo:function(){return e._getTooltipInfo(this.x,this.y)}})},onMouseOut:function(b){var c=n.Tooltip.getTooltip(a);if(c&&!(e._listener.lastMouseX===b.event.clientX&&e._listener.lastMouseY===b.event.clientY))e._listener.lastMouseX=b.event.clientX,e._listener.lastMouseY=b.event.clientY, +c.setTarget(null)},onScroll:function(){var b=n.Tooltip.getTooltip(a);b&&b.setTarget(null,0,0)},onSelection:function(a){e._updateCursorStatus();e._highlightCurrentLine(a.newValue,a.oldValue)}};a.addEventListener("ModelChanged",this._listener.onModelChanged);a.addEventListener("Selection",this._listener.onSelection);a.addEventListener("MouseOver",this._listener.onMouseOver);a.addEventListener("MouseOut",this._listener.onMouseOut);a.addEventListener("MouseMove",this._listener.onMouseMove);a.addEventListener("Scroll", +this._listener.onScroll);if(this._keyBindingFactory){var c;if(c=typeof this._keyBindingFactory==="function"?this._keyBindingFactory(this,this.getKeyModes(),this._undoStack,this._contentAssist):this._keyBindingFactory.createKeyBindings(b,this._undoStack,this._contentAssist))this._textActions=c.textActions,this._linkedMode=c.linkedMode,this._sourceCodeActions=c.sourceCodeActions}c=function(a){if(a!==void 0&&a!==-1){for(var e=this.getView().getModel(),c=this.getAnnotationModel(),d=b.mapOffset(e.getLineStart(a)), +a=b.mapOffset(e.getLineEnd(a)),e=c.getAnnotations(d,a),f=null;e.hasNext();){var l=e.next();if(l.type===h.ANNOTATION_BOOKMARK){f=l;break}}f?c.removeAnnotation(f):(f=h.createAnnotation(h.ANNOTATION_BOOKMARK,d,a),f.title=void 0,c.addAnnotation(f))}};if(this._annotationFactory){var d=a.getModel();d.getBaseModel&&(d=d.getBaseModel());if(this._annotationModel=this._annotationFactory.createAnnotationModel(d))if(d=this._annotationStyler=this._annotationFactory.createAnnotationStyler(a,this._annotationModel))d.addAnnotationType(h.ANNOTATION_CURRENT_SEARCH), +d.addAnnotationType(h.ANNOTATION_MATCHING_SEARCH),d.addAnnotationType(h.ANNOTATION_ERROR),d.addAnnotationType(h.ANNOTATION_WARNING),d.addAnnotationType(h.ANNOTATION_MATCHING_BRACKET),d.addAnnotationType(h.ANNOTATION_CURRENT_BRACKET),d.addAnnotationType(h.ANNOTATION_CURRENT_LINE),d.addAnnotationType(h.ANNOTATION_READ_OCCURRENCE),d.addAnnotationType(h.ANNOTATION_WRITE_OCCURRENCE),d.addAnnotationType(h.ANNOTATION_SELECTED_LINKED_GROUP),d.addAnnotationType(h.ANNOTATION_CURRENT_LINKED_GROUP),d.addAnnotationType(h.ANNOTATION_LINKED_GROUP), +d.addAnnotationType("orion.annotation.highlightError");var d=this._annotationFactory.createAnnotationRulers(this._annotationModel),g=this._annotationRuler=d.annotationRuler;if(g)g.onDblClick=c,g.setMultiAnnotationOverlay({html:"<div class='annotationHTML overlay'></div>"}),g.addAnnotationType(h.ANNOTATION_ERROR),g.addAnnotationType(h.ANNOTATION_WARNING),g.addAnnotationType(h.ANNOTATION_TASK),g.addAnnotationType(h.ANNOTATION_BOOKMARK);this.setAnnotationRulerVisible(this._annotationRulerVisible||this._annotationRulerVisible=== +void 0,!0);if(g=this._overviewRuler=d.overviewRuler)g.addAnnotationType(h.ANNOTATION_CURRENT_SEARCH),g.addAnnotationType(h.ANNOTATION_MATCHING_SEARCH),g.addAnnotationType(h.ANNOTATION_READ_OCCURRENCE),g.addAnnotationType(h.ANNOTATION_WRITE_OCCURRENCE),g.addAnnotationType(h.ANNOTATION_CURRENT_BLAME),g.addAnnotationType(h.ANNOTATION_ERROR),g.addAnnotationType(h.ANNOTATION_WARNING),g.addAnnotationType(h.ANNOTATION_TASK),g.addAnnotationType(h.ANNOTATION_BOOKMARK),g.addAnnotationType(h.ANNOTATION_MATCHING_BRACKET), +g.addAnnotationType(h.ANNOTATION_CURRENT_BRACKET),g.addAnnotationType(h.ANNOTATION_CURRENT_LINE);this.setOverviewRulerVisible(this._overviewRulerVisible||this._overviewRulerVisible===void 0,!0)}if(this._lineNumberRulerFactory)this._lineNumberRuler=this._lineNumberRulerFactory.createLineNumberRuler(this._annotationModel),this._lineNumberRuler.addAnnotationType(h.ANNOTATION_CURRENT_BLAME),this._lineNumberRuler.addAnnotationType(h.ANNOTATION_BLAME),this._lineNumberRuler.onDblClick=c,this.setLineNumberRulerVisible(this._lineNumberRulerVisible|| +this._lineNumberRulerVisible===void 0,!0);if(this._foldingRulerFactory)this._foldingRuler=this._foldingRulerFactory.createFoldingRuler(this._annotationModel),this._foldingRuler.addAnnotationType(h.ANNOTATION_FOLDING),this.setFoldingRulerVisible(this._foldingRulerVisible||this._foldingRulerVisible===void 0,!0);this.dispatchEvent({type:"TextViewInstalled",textView:a});f.prototype.install.call(this)}},uninstallTextView:function(){this.uninstall()},uninstall:function(){var b=this._textView;if(b)b.destroy(), +this._textView=this._undoStack=this._textDND=this._contentAssist=this._listener=this._annotationModel=this._annotationStyler=this._annotationRuler=this._overviewRuler=this._lineNumberRuler=this._foldingRuler=this._currentLineAnnotation=this._title=null,this._dirty=!1,this._foldingRulerVisible=this._overviewRulerVisible=this._lineNumberRulerVisible=this._annotationRulerVisible=void 0,this.dispatchEvent({type:"TextViewUninstalled",textView:b}),f.prototype.uninstall.call(this)},_updateCursorStatus:function(){var b= +this.getModel(),a=this.getCaretOffset(),e=b.getLineAtOffset(a),b=b.getLineStart(e);a-=b;for(var b=this.getKeyModes(),c=0;c<b.length;c++){var f=b[c];if(f.isActive()&&f.isStatusActive&&f.isStatusActive())return}this.reportStatus(d.formatMessage(k.lineColumn,e+1,a+1))},showAnnotations:function(b,a,e,c){var d=this._annotationModel;if(d){for(var f=[],g=[],i=d.getTextModel(),t=d.getAnnotations(),k;t.hasNext();)k=t.next(),a.indexOf(k.type)!==-1&&k.creatorID===this&&f.push(k);if(b)for(a=0;a<b.length;a++)if(k= +b[a]){if(e)k=e(k);else{var s;typeof k.line==="number"?(s=i.getLineStart(k.line-1),t=s+k.start-1,s=s+k.end-1):(t=k.start,s=k.end);var u=c(k);if(!u)continue;k=h.createAnnotation(u,t,s,k.description)}k.creatorID=this;g.push(k)}d.replaceAnnotations(f,g)}},showProblems:function(b){this.showAnnotations(b,[h.ANNOTATION_ERROR,h.ANNOTATION_WARNING,h.ANNOTATION_TASK],null,function(a){switch(a.severity){case "error":return h.ANNOTATION_ERROR;case "warning":return h.ANNOTATION_WARNING;case "task":return h.ANNOTATION_TASK}return null})}, +showOccurrences:function(b){this.showAnnotations(b,[h.ANNOTATION_READ_OCCURRENCE,h.ANNOTATION_WRITE_OCCURRENCE],null,function(a){return a.readAccess?h.ANNOTATION_READ_OCCURRENCE:h.ANNOTATION_WRITE_OCCURRENCE})},showBlame:function(b){var a=this._blameRGB,e=this.getTextView().getOptions("parent").ownerDocument;if(!a){var f=d.createElement(e,"div");f.className="annotation blame";e.body.appendChild(f);var g=(e.defaultView||e.parentWindow).getComputedStyle(f).getPropertyValue("background-color");f.parentNode.removeChild(f); +var f=g.indexOf("("),q=g.indexOf(")"),g=g.substring(f+1,q);this._blameRGB=a=g.split(",").slice(0,3)}var r=function(){var a=i.AnnotationType.createAnnotation(this.groupType,this.start,this.end,this.title);a.style=c.mixin({},a.style);a.style.style=c.mixin({},a.style.style);a.style.style.backgroundColor="";this.groupAnnotation=a;a.blame=this.blame;a.html=this.html;a.creatorID=this.creatorID;return a},p=function(){var a=d.createElement(e,"div");a.className="tooltipTitle";var b=this.blame.Message.indexOf("\n"); +if(b===-1)b=this.blame.Message.length;var c=d.createElement(e,"a");c.href=this.blame.CommitLink;c.appendChild(e.createTextNode(this.blame.Message.substring(0,b)));a.appendChild(c);a.appendChild(d.createElement(e,"br"));a.appendChild(e.createTextNode(d.formatMessage(k.committerOnTime,this.blame.AuthorName,this.blame.Time)));return a},t=this.getModel();this.showAnnotations(b,[h.ANNOTATION_BLAME,h.ANNOTATION_CURRENT_BLAME],function(b){var e=t.getLineStart(b.Start-1),d=t.getLineEnd(b.End-1,!0),e=i.AnnotationType.createAnnotation(h.ANNOTATION_BLAME, +e,d,p),d=a.slice(0);d.push(b.Shade);e.style=c.mixin({},e.style);e.style.style=c.mixin({},e.style.style);e.style.style.backgroundColor="rgba("+d.join()+")";e.groupId=b.Name;e.groupType=h.ANNOTATION_CURRENT_BLAME;e.createGroupAnnotation=r;e.html='<img class="annotationHTML blame" src="'+b.AuthorImage+'"/>';e.blame=b;return e})},showSelection:function(b,a,e,c,d){typeof b==="number"?(typeof a!=="number"&&(a=b),this.moveSelection(b,a)):typeof e==="number"&&(b=this.getModel().getLineStart(e-1),typeof c=== +"number"&&(b+=c),typeof d!=="number"&&(d=0),this.moveSelection(b,b+d))},_setModelText:function(b){this._textView&&(this._textView.setText(b),this._textView.getModel().setLineDelimiter("auto"),this._highlightCurrentLine(this._textView.getSelection()))},setInput:function(b,a,e,c,d){f.prototype.setInput.call(this,b,a,e,c);this._textView&&!c&&!d&&this._textView.focus()},onGotoLine:function(b,a,e,c){if(this._textView){var d=this.getModel(),b=Math.max(0,Math.min(b,d.getLineCount()-1)),f=d.getLineStart(b), +g=0;e===void 0&&(e=0);typeof a==="string"?(b=d.getLine(b).indexOf(a),b!==-1&&(g=b,e=g+a.length)):(g=a,a=d.getLineEnd(b)-f,g=Math.min(g,a),e=Math.min(e,a));this.moveSelection(f+g,f+e,c)}}});return{BaseEditor:f,Editor:g}}); +define("orion/editor/find","i18n!orion/editor/nls/messages,orion/keyBinding,orion/editor/keyModes,orion/editor/annotations,orion/regex,orion/objects,orion/util".split(","),function(k,m,n,i,c,d,f){function g(a){var b=a.getTextView();n.KeyMode.call(this,b);this.editor=a;this._active=!1;this._success=!0;this._ignoreSelection=!1;this._prefix="";b.setAction("incrementalFindCancel",function(){this.setActive(!1);return!0}.bind(this));b.setAction("incrementalFindBackspace",function(){return this._backspace()}.bind(this)); +var d=this;this._listener={onVerify:function(a){var b=d.editor,e=b.getModel(),f=b.mapOffset(a.start),b=b.mapOffset(a.end),e=e.getText(f,b);if((e=d._prefix.match(RegExp("^"+c.escape(e),"i")))&&e.length>0)d._prefix+=a.text,d._success=!0,d._status(),d.find(d._forward,!0),a.text=null},onSelection:function(){d._ignoreSelection||d.setActive(!1)}}}function h(a,b,c){if(a){this._editor=a;this._undoStack=b;this._showAll=!0;this._visible=!1;this._wrap=this._caseInsensitive=!0;this._wholeWord=!1;this._incremental= +!0;this._regex=!1;this._findAfterReplace=!0;this._reverse=this._hideAfterFind=!1;this._timer=this._end=this._start=void 0;this._lastString="";var d=this;this._listeners={onEditorFocus:function(a){d._removeCurrentAnnotation(a)}};this.setOptions(c)}}var b={};g.prototype=new n.KeyMode;d.mixin(g.prototype,{createKeyBindings:function(){var a=m.KeyBinding,b=[];b.push({actionID:"incrementalFindBackspace",keyBinding:new a(8)});b.push({actionID:"incrementalFindCancel",keyBinding:new a(13)});b.push({actionID:"incrementalFindCancel", +keyBinding:new a(27)});b.push({actionID:"incrementalFindReverse",keyBinding:new a(38)});b.push({actionID:"incrementalFind",keyBinding:new a(40)});b.push({actionID:"incrementalFindReverse",keyBinding:new a("k",!0,!0)});b.push({actionID:"incrementalFind",keyBinding:new a("k",!0)});return b},find:function(a,b){this._forward=a;if(!this.isActive())return this.setActive(!0),!1;var c=this._prefix;if(c.length===0)return!1;var d=this.editor,f=d.getModel(),f=a?this._success?b?this._start:d.getCaretOffset()+ +1:0:this._success?b?this._start:d.getCaretOffset():f.getCharCount()-1;if(c=d.getModel().find({string:c,start:f,reverse:!a,caseInsensitive:c.toLowerCase()===c}).next()){if(!b)this._start=f;this._ignoreSelection=this._success=!0;d.moveSelection(a?c.start:c.end,a?c.end:c.start);this._ignoreSelection=!1}else this._success=!1;this._status();return!0},isActive:function(){return this._active},isStatusActive:function(){return this.isActive()},setActive:function(a){if(this._active!==a)this._active=a,this._prefix= +"",this._success=!0,a=this.editor.getTextView(),this._start=this.editor.getCaretOffset(),this.editor.setCaretOffset(this._start),this._active?(a.addEventListener("Verify",this._listener.onVerify),a.addEventListener("Selection",this._listener.onSelection),a.addKeyMode(this)):(a.removeEventListener("Verify",this._listener.onVerify),a.removeEventListener("Selection",this._listener.onSelection),a.removeKeyMode(this)),this._status()},_backspace:function(){var a=this._prefix,a=this._prefix=a.substring(0, +a.length-1);return a.length===0?(this._ignoreSelection=this._success=!0,this.editor.setCaretOffset(this.editor.getSelection().start),this._ignoreSelection=!1,this._status(),!0):this.find(this._forward,!0)},_status:function(){if(this.isActive()){var a;a=this._forward?this._success?k.incrementalFindStr:k.incrementalFindStrNotFound:this._success?k.incrementalFindReverseStr:k.incrementalFindReverseStrNotFound;a=f.formatMessage(a,this._prefix);this.editor.reportStatus(a,this._success?"":"error")}else this.editor.reportStatus("")}}); +b.IncrementalFind=g;h.prototype={find:function(a,b,c){this.setOptions({reverse:!a});var d=this.getFindString(),f;if(b)d=b.findString||d,f=b.count;a=this.getOptions();this.setOptions(b);b=c?this._startOffset:this.getStartOffset();if((f=this._doFind(d,b,f))&&!c)this._startOffset=f.start;this.setOptions(a);this._hideAfterFind&&this.hide();return f},getStartOffset:function(){return this._start!==void 0?this._start:this._reverse?this._editor.getSelection().start-1:this._editor.getCaretOffset()},getFindString:function(){var a= +this._editor.getSelection(),a=this._editor.getText(a.start,a.end);this._regex&&(a=c.escape(a));return a||this._lastString},getOptions:function(){return{showAll:this._showAll,caseInsensitive:this._caseInsensitive,wrap:this._wrap,wholeWord:this._wholeWord,incremental:this._incremental,regex:this._regex,findAfterReplace:this._findAfterReplace,hideAfterFind:this._hideAfterFind,reverse:this._reverse,findCallback:this._findCallback,start:this._start,end:this._end}},getReplaceString:function(){return""}, +hide:function(){this._visible=!1;if(this._savedOptions&&(this.setOptions(this._savedOptions.pop()),this._savedOptions.length===0))this._savedOptions=null;this._removeAllAnnotations();var a=this._editor.getTextView();a&&(a.removeEventListener("Focus",this._listeners.onEditorFocus),a.focus())},_processReplaceString:function(a){var b=a;if(this._regex){for(var b="",c=!1,d=this._editor.getModel().getLineDelimiter(),f=0;f<a.length;f++){var g=a.substring(f,f+1);if(c){switch(g){case "R":b+=d;break;case "r":b+= +"\r";break;case "n":b+="\n";break;case "t":b+="\t";break;case "\\":b+="\\";break;default:b+="\\"+g}c=!1}else g==="\\"?c=!0:b+=g}c&&(b+="\\")}return b},isVisible:function(){return this._visible},replace:function(){var a=this.getFindString();if(a){var b=this._editor,c=this._processReplaceString(this.getReplaceString()),d=b.getSelection().start;if(b=b.getModel().find({string:a,start:d,reverse:!1,wrap:this._wrap,regex:this._regex,wholeWord:this._wholeWord,caseInsensitive:this._caseInsensitive}).next())this.startUndo(), +this._doReplace(b.start,b.end,a,c),this.endUndo()}this._findAfterReplace&&a&&this._doFind(a,this.getStartOffset())},replaceAll:function(){var a=this.getFindString();if(a){this._replacingAll=!0;var b=this._editor,c=b.getTextView();b.reportStatus(k.replaceAll);var d=this._processReplaceString(this.getReplaceString()),g=this;window.setTimeout(function(){for(var h=0,i=0;;){var t=g._doFind(a,h,null,!0);if(!t)break;i++;i===1&&(c.setRedraw(!1),g.startUndo());g._doReplace(t.start,t.end,a,d);h=g.getStartOffset()}i> +0&&(g.endUndo(),c.setRedraw(!0));h>0?b.reportStatus(f.formatMessage(k.replacedMatches,i)):b.reportStatus(k.nothingReplaced,"error");g._replacingAll=!1},100)}},setOptions:function(a){if(a){if((a.showAll===!0||a.showAll===!1)&&this._showAll!==a.showAll)if(this._showAll=a.showAll,this.isVisible())if(this._showAll)this._markAllOccurrences();else{var b=this._editor.getAnnotationModel();b&&b.removeAnnotations(i.AnnotationType.ANNOTATION_MATCHING_SEARCH)}if(a.caseInsensitive===!0||a.caseInsensitive===!1)this._caseInsensitive= +a.caseInsensitive;if(a.wrap===!0||a.wrap===!1)this._wrap=a.wrap;if(a.wholeWord===!0||a.wholeWord===!1)this._wholeWord=a.wholeWord;if(a.incremental===!0||a.incremental===!1)this._incremental=a.incremental;if(a.regex===!0||a.regex===!1)this._regex=a.regex;if(a.findAfterReplace===!0||a.findAfterReplace===!1)this._findAfterReplace=a.findAfterReplace;if(a.hideAfterFind===!0||a.hideAfterFind===!1)this._hideAfterFind=a.hideAfterFind;if(a.reverse===!0||a.reverse===!1)this._reverse=a.reverse;if(a.hasOwnProperty("findCallback"))this._findCallback= +a.findCallback;if(a.hasOwnProperty("start"))this._start=a.start;if(a.hasOwnProperty("end"))this._end=a.end}},show:function(a){this._visible=!0;if(a){if(!this._savedOptions)this._savedOptions=[];this._savedOptions.push(this.getOptions());this.setOptions(a)}this._startOffset=this._editor.getSelection().start;this._editor.getTextView().addEventListener("Focus",this._listeners.onEditorFocus);var b=this;window.setTimeout(function(){b._incremental&&b.find(!0,null,!0)},0)},startUndo:function(){this._undoStack&& +this._undoStack.startCompoundChange()},endUndo:function(){this._undoStack&&this._undoStack.endCompoundChange()},_find:function(a,b,c){return this._editor.getModel().find({string:a,start:b,end:this._end,reverse:this._reverse,wrap:c?!1:this._wrap,regex:this._regex,wholeWord:this._wholeWord,caseInsensitive:this._caseInsensitive})},_doFind:function(a,b,c,d){var c=c||1,f=this._editor;if(!a)return this._removeAllAnnotations(),null;this._lastString=a;var g,h;if(this._regex)try{h=this._find(a,b,d)}catch(t){f.reportStatus(t.message, +"error");return}else h=this._find(a,b,d);for(a=0;a<c&&h.hasNext();a++)g=h.next();if(!this._replacingAll){g?this._editor.reportStatus(""):this._editor.reportStatus(k.notFound,"error");if(this.isVisible()){c=i.AnnotationType.ANNOTATION_CURRENT_SEARCH;if(h=f.getAnnotationModel())h.removeAnnotations(c),g&&h.addAnnotation(i.AnnotationType.createAnnotation(c,g.start,g.end));if(this._showAll){this._timer&&window.clearTimeout(this._timer);var v=this;this._timer=window.setTimeout(function(){v._markAllOccurrences(); +v._timer=null},500)}}this._findCallback?this._findCallback(g):g&&f.moveSelection(g.start,g.end,null,!1)}return g},_doReplace:function(a,b,c,d){var f=this._editor;if(this._regex&&(d=f.getText(a,b).replace(RegExp(c,this._caseInsensitive?"i":""),d),!d))return;f.setText(d,a,b);f.setSelection(a,a+d.length,!0)},_markAllOccurrences:function(){var a=this._editor.getAnnotationModel();if(a){for(var b=i.AnnotationType.ANNOTATION_MATCHING_SEARCH,c=a.getAnnotations(),d=[],f;c.hasNext();){var g=c.next();g.type=== +b&&d.push(g)}if(this.isVisible()){c=this.getFindString();c=this._editor.getModel().find({string:c,regex:this._regex,wholeWord:this._wholeWord,caseInsensitive:this._caseInsensitive});for(f=[];c.hasNext();)g=c.next(),f.push(i.AnnotationType.createAnnotation(b,g.start,g.end))}a.replaceAnnotations(d,f)}},_removeAllAnnotations:function(){var a=this._editor.getAnnotationModel();a&&(a.removeAnnotations(i.AnnotationType.ANNOTATION_CURRENT_SEARCH),a.removeAnnotations(i.AnnotationType.ANNOTATION_MATCHING_SEARCH))}, +_removeCurrentAnnotation:function(){var a=this._editor.getAnnotationModel();a&&a.removeAnnotations(i.AnnotationType.ANNOTATION_CURRENT_SEARCH)}};b.Find=h;return b}); +define("orion/editor/actions","i18n!orion/editor/nls/messages,orion/keyBinding,orion/editor/annotations,orion/editor/tooltip,orion/editor/find,orion/util".split(","),function(k,m,n,i,c,d){function f(a,b,d){this.editor=a;this.undoStack=b;this._incrementalFind=new c.IncrementalFind(a);this._find=d?d:new c.Find(a,b);this._lastEditLocation=null;this.init()}function g(a,b,c,d){this.editor=a;this.undoStack=b;this.contentAssist=c;this.linkedMode=d;this.contentAssist&&this.contentAssist.addEventListener("ProposalApplied", +this.contentAssistProposalApplied.bind(this));this.init()}var h=n.AnnotationType,b={};f.prototype={init:function(){var a=this.editor.getTextView();this._lastEditListener={onModelChanged:function(a){if(this.editor.isDirty())this._lastEditLocation=a.start+a.addedCharCount}.bind(this)};a.addEventListener("ModelChanged",this._lastEditListener.onModelChanged);a.setAction("undo",function(a){if(this.undoStack){var b=1;if(a&&a.count)b=a.count;for(;b>0;)this.undoStack.undo(),--b;return!0}return!1}.bind(this), +{name:k.undo});a.setAction("redo",function(a){if(this.undoStack){var b=1;if(a&&a.count)b=a.count;for(;b>0;)this.undoStack.redo(),--b;return!0}return!1}.bind(this),{name:k.redo});a.setKeyBinding(new m.KeyBinding("f",!0),"find");a.setAction("find",function(){if(this._find){var a=this.editor.getSelection();(a=prompt(k.find,this.editor.getText(a.start,a.end)))&&this._find.find(!0,{findString:a})}}.bind(this),{name:k.find});a.setKeyBinding(new m.KeyBinding("k",!0),"findNext");a.setAction("findNext",function(a){return this._find? +(this._find.find(!0,a),!0):!1}.bind(this),{name:k.findNext});a.setKeyBinding(new m.KeyBinding("k",!0,!0),"findPrevious");a.setAction("findPrevious",function(a){return this._find?(this._find.find(!1,a),!0):!1}.bind(this),{name:k.findPrevious});a.setKeyBinding(new m.KeyBinding("j",!0),"incrementalFind");a.setAction("incrementalFind",function(){this._incrementalFind&&this._incrementalFind.find(!0);return!0}.bind(this),{name:k.incrementalFind});a.setKeyBinding(new m.KeyBinding("j",!0,!0),"incrementalFindReverse"); +a.setAction("incrementalFindReverse",function(){this._incrementalFind&&this._incrementalFind.find(!1);return!0}.bind(this),{name:k.incrementalFindReverse});a.setAction("tab",function(){return this.indentLines()}.bind(this));a.setAction("shiftTab",function(){return this.unindentLines()}.bind(this),{name:k.unindentLines});a.setKeyBinding(new m.KeyBinding(38,!1,!1,!0),"moveLinesUp");a.setAction("moveLinesUp",function(){return this.moveLinesUp()}.bind(this),{name:k.moveLinesUp});a.setKeyBinding(new m.KeyBinding(40, +!1,!1,!0),"moveLinesDown");a.setAction("moveLinesDown",function(){return this.moveLinesDown()}.bind(this),{name:k.moveLinesDown});a.setKeyBinding(new m.KeyBinding(38,!0,!1,!0),"copyLinesUp");a.setAction("copyLinesUp",function(){return this.copyLinesUp()}.bind(this),{name:k.copyLinesUp});a.setKeyBinding(new m.KeyBinding(40,!0,!1,!0),"copyLinesDown");a.setAction("copyLinesDown",function(){return this.copyLinesDown()}.bind(this),{name:k.copyLinesDown});a.setKeyBinding(new m.KeyBinding("d",!0,!1,!1), +"deleteLines");a.setAction("deleteLines",function(a){return this.deleteLines(a)}.bind(this),{name:k.deleteLines});a.setKeyBinding(new m.KeyBinding("l",!d.isMac,!1,!1,d.isMac),"gotoLine");a.setAction("gotoLine",function(){return this.gotoLine()}.bind(this),{name:k.gotoLine});a.setKeyBinding(new m.KeyBinding(190,!0),"nextAnnotation");a.setAction("nextAnnotation",function(){return this.nextAnnotation(!0)}.bind(this),{name:k.nextAnnotation});a.setKeyBinding(new m.KeyBinding(188,!0),"previousAnnotation"); +a.setAction("previousAnnotation",function(){return this.nextAnnotation(!1)}.bind(this),{name:k.prevAnnotation});a.setKeyBinding(new m.KeyBinding("e",!0,!1,!0,!1),"expand");a.setAction("expand",function(){return this.expandAnnotation(!0)}.bind(this),{name:k.expand});a.setKeyBinding(new m.KeyBinding("c",!0,!1,!0,!1),"collapse");a.setAction("collapse",function(){return this.expandAnnotation(!1)}.bind(this),{name:k.collapse});a.setKeyBinding(new m.KeyBinding("e",!0,!0,!0,!1),"expandAll");a.setAction("expandAll", +function(){return this.expandAnnotations(!0)}.bind(this),{name:k.expandAll});a.setKeyBinding(new m.KeyBinding("c",!0,!0,!0,!1),"collapseAll");a.setAction("collapseAll",function(){return this.expandAnnotations(!1)}.bind(this),{name:k.collapseAll});a.setKeyBinding(new m.KeyBinding("q",!d.isMac,!1,!1,d.isMac),"lastEdit");a.setAction("lastEdit",function(){return this.gotoLastEdit()}.bind(this),{name:k.lastEdit})},copyLinesDown:function(){var a=this.editor;if(a.getTextView().getOptions("readonly"))return!1; +var b=a.getModel(),c=a.getSelection(),d=b.getLineAtOffset(c.start),c=b.getLineAtOffset(c.end>c.start?c.end-1:c.end),f=b.getLineStart(d),d=b.getLineEnd(c,!0),g=b.getLineCount(),h="",f=b.getText(f,d);c===g-1&&(f=(h=b.getLineDelimiter())+f);a.setText(f,d,d);a.setSelection(d+h.length,d+f.length);return!0},copyLinesUp:function(){var a=this.editor;if(a.getTextView().getOptions("readonly"))return!1;var b=a.getModel(),c=a.getSelection(),d=b.getLineAtOffset(c.start),c=b.getLineAtOffset(c.end>c.start?c.end- +1:c.end),d=b.getLineStart(d),f=b.getLineEnd(c,!0),g=b.getLineCount(),h="",f=b.getText(d,f);c===g-1&&(f+=h=b.getLineDelimiter());a.setText(f,d,d);a.setSelection(d,d+f.length-h.length);return!0},deleteLines:function(a){var b=this.editor;if(b.getTextView().getOptions("readonly"))return!1;var c=1;if(a&&a.count)c=a.count;var d=b.getSelection(),f=b.getModel(),g=f.getLineAtOffset(d.start),a=f.getLineStart(g),c=d.start!==d.end||c===1?f.getLineAtOffset(d.end>d.start?d.end-1:d.end):Math.min(g+c-1,f.getLineCount()- +1),c=f.getLineEnd(c,!0);b.setText("",a,c);return!0},expandAnnotation:function(a){var b=this.editor,c=b.getAnnotationModel();if(!c)return!0;var d=b.getModel(),f=b.getCaretOffset(),g=d.getLineAtOffset(f),f=d.getLineStart(g),g=d.getLineEnd(g,!0);d.getBaseModel&&(f=d.mapOffset(f),g=d.mapOffset(g),d.getBaseModel());for(var h,c=c.getAnnotations(f,g);!h&&c.hasNext();)d=c.next(),d.type===n.AnnotationType.ANNOTATION_FOLDING&&(h=d);h&&a!==h.expanded&&(a?h.expand():(b.setCaretOffset(h.start),h.collapse())); +return!0},expandAnnotations:function(a){var b=this.editor,c=b.getTextView(),d=b.getAnnotationModel();if(!d)return!0;b.getModel();d=d.getAnnotations();for(c.setRedraw(!1);d.hasNext();)b=d.next(),b.type===n.AnnotationType.ANNOTATION_FOLDING&&a!==b.expanded&&(a?b.expand():b.collapse());c.setRedraw(!0);return!0},indentLines:function(){var a=this.editor,b=a.getTextView();if(b.getOptions("readonly"))return!1;if(b.getOptions("tabMode")){var c=a.getModel(),d=a.getSelection(),f=c.getLineAtOffset(d.start), +g=c.getLineAtOffset(d.end>d.start?d.end-1:d.end);if(f!==g){var h=[];h.push("");for(var i=f;i<=g;i++)h.push(c.getLine(i,!0));i=c.getLineStart(f);c=c.getLineEnd(g,!0);b=b.getOptions("tabSize","expandTab");b=b.expandTab?Array(b.tabSize+1).join(" "):"\t";a.setText(h.join(b),i,c);a.setSelection(i===d.start?d.start:d.start+b.length,d.end+(g-f+1)*b.length);return!0}return!1}},gotoLastEdit:function(){typeof this._lastEditLocation==="number"&&this.editor.showSelection(this._lastEditLocation);return!0},gotoLine:function(){var a= +this.editor,b=a.getModel().getLineAtOffset(a.getCaretOffset());if(b=prompt(k.gotoLinePrompty,b+1))b=parseInt(b,10),a.onGotoLine(b-1,0);return!0},moveLinesDown:function(){var a=this.editor;if(a.getTextView().getOptions("readonly"))return!1;var b=a.getModel(),c=a.getSelection(),d=b.getLineAtOffset(c.start),f=b.getLineAtOffset(c.end>c.start?c.end-1:c.end),g=b.getLineCount();if(f===g-1)return!0;var d=b.getLineStart(d),c=b.getLineEnd(f,!0),h=b.getLineEnd(f+1,!0)-(c-d),i=0;f!==g-2?b=b.getText(d,c):(f=b.getLineEnd(f), +b=b.getText(f,c)+b.getText(d,f),i+=c-f);this.startUndo();a.setText("",d,c);a.setText(b,h,h);a.setSelection(h+i,h+i+b.length);this.endUndo();return!0},moveLinesUp:function(){var a=this.editor;if(a.getTextView().getOptions("readonly"))return!1;var b=a.getModel(),c=a.getSelection(),d=b.getLineAtOffset(c.start);if(d===0)return!0;var f=b.getLineAtOffset(c.end>c.start?c.end-1:c.end),g=b.getLineCount(),c=b.getLineStart(d-1),h=b.getLineStart(d),i=b.getLineEnd(f,!0),k=b.getText(h,i),s=0;f===g-1&&(f=b.getLineEnd(d- +1),d=b.getLineEnd(d-1,!0),k+=b.getText(f,d),h=f,s=d-f);this.startUndo();a.setText("",h,i);a.setText(k,c,c);a.setSelection(c,c+k.length-s);this.endUndo();return!0},nextAnnotation:function(a){function b(a){return!!a.lineStyle||a.type===h.ANNOTATION_MATCHING_BRACKET||a.type===h.ANNOTATION_CURRENT_BRACKET||!f.isAnnotationTypeVisible(a.type)}var c=this.editor,d=c.getAnnotationModel();if(!d)return!0;var f=c.getOverviewRuler()||c.getAnnotationStyler();if(!f)return!0;for(var g=c.getModel(),p=c.getCaretOffset(), +t=d.getAnnotations(a?p:0,a?g.getCharCount():p),k=null;t.hasNext();){var s=t.next();if(a){if(s.start<=p)continue}else if(s.start>=p)continue;if(!b(s)&&(k=s,a))break}if(k){for(var u=[k],t=d.getAnnotations(k.start,k.start);t.hasNext();)s=t.next(),s!==k&&!b(s)&&u.push(s);var j=c.getTextView(),m=g.getLineAtOffset(k.start),n=i.Tooltip.getTooltip(j);if(!n)return c.moveSelection(k.start),!0;c.moveSelection(k.start,k.start,function(){n.setTarget({getTooltipInfo:function(){var a=j.convert({x:j.getLocationAtOffset(k.start).x, +y:j.getLocationAtOffset(g.getLineStart(m)).y},"document","page");return{contents:u,x:a.x,y:a.y+Math.floor(j.getLineHeight(m)*1.33)}}},0)})}return!0},unindentLines:function(){var a=this.editor,b=a.getTextView();if(b.getOptions("readonly"))return!1;if(b.getOptions("tabMode")){for(var c=a.getModel(),d=a.getSelection(),f=c.getLineAtOffset(d.start),g=c.getLineAtOffset(d.end>d.start?d.end-1:d.end),h=b.getOptions("tabSize"),i=Array(h+1).join(" "),k=[],s=b=0,u=f;u<=g;u++){var j=c.getLine(u,!0);if(c.getLineStart(u)!== +c.getLineEnd(u))if(j.indexOf("\t")===0)j=j.substring(1),b++;else if(j.indexOf(i)===0)j=j.substring(h),b+=h;else return!0;u===f&&(s=b);k.push(j)}f=c.getLineStart(f);h=c.getLineEnd(g,!0);c=c.getLineStart(g);a.setText(k.join(""),f,h);g=f===d.start?d.start:d.start-s;d=Math.max(g,d.end-b+(d.end===c+1&&d.start!==d.end?1:0));a.setSelection(g,d);return!0}},startUndo:function(){this.undoStack&&this.undoStack.startCompoundChange()},endUndo:function(){this.undoStack&&this.undoStack.endCompoundChange()}};b.TextActions= +f;g.prototype={init:function(){var a=this.editor.getTextView();a.setAction("lineStart",function(){return this.lineStart()}.bind(this));a.setAction("enter",function(){return this.autoIndent()}.bind(this));a.setKeyBinding(new m.KeyBinding("t",!0,!1,!0),"trimTrailingWhitespaces");a.setAction("trimTrailingWhitespaces",function(){return this.trimTrailingWhitespaces()}.bind(this),{name:k.trimTrailingWhitespaces});a.setKeyBinding(new m.KeyBinding(191,!0),"toggleLineComment");a.setAction("toggleLineComment", +function(){return this.toggleLineComment()}.bind(this),{name:k.toggleLineComment});a.setKeyBinding(new m.KeyBinding(191,!0,!d.isMac,!1,d.isMac),"addBlockComment");a.setAction("addBlockComment",function(){return this.addBlockComment()}.bind(this),{name:k.addBlockComment});a.setKeyBinding(new m.KeyBinding(220,!0,!d.isMac,!1,d.isMac),"removeBlockComment");a.setAction("removeBlockComment",function(){return this.removeBlockComment()}.bind(this),{name:k.removeBlockComment});a.setKeyBinding(new m.KeyBinding("[", +!1,!1,!1,!1,"keypress"),"autoPairSquareBracket");a.setAction("autoPairSquareBracket",function(){return this.autoPairBrackets("[","]")}.bind(this));a.setKeyBinding(new m.KeyBinding("]",!1,!1,!1,!1,"keypress"),"skipClosingSquareBracket");a.setAction("skipClosingSquareBracket",function(){return this.skipClosingBracket("]")}.bind(this));a.setKeyBinding(new m.KeyBinding("<",!1,!1,!1,!1,"keypress"),"autoPairAngleBracket");a.setAction("autoPairAngleBracket",function(){return this.autoPairBrackets("<",">")}.bind(this)); +a.setKeyBinding(new m.KeyBinding(">",!1,!1,!1,!1,"keypress"),"skipClosingAngleBracket");a.setAction("skipClosingAngleBracket",function(){return this.skipClosingBracket(">")}.bind(this));a.setKeyBinding(new m.KeyBinding("(",!1,!1,!1,!1,"keypress"),"autoPairParentheses");a.setAction("autoPairParentheses",function(){return this.autoPairBrackets("(",")")}.bind(this));a.setKeyBinding(new m.KeyBinding(")",!1,!1,!1,!1,"keypress"),"skipClosingParenthesis");a.setAction("skipClosingParenthesis",function(){return this.skipClosingBracket(")")}.bind(this)); +a.setKeyBinding(new m.KeyBinding("{",!1,!1,!1,!1,"keypress"),"autoPairBraces");a.setAction("autoPairBraces",function(){return this.autoPairBrackets("{","}")}.bind(this));a.setKeyBinding(new m.KeyBinding("}",!1,!1,!1,!1,"keypress"),"skipClosingBrace");a.setAction("skipClosingBrace",function(){return this.skipClosingBracket("}")}.bind(this));a.setKeyBinding(new m.KeyBinding("'",!1,!1,!1,!1,"keypress"),"autoPairSingleQuotation");a.setAction("autoPairSingleQuotation",function(){return this.autoPairQuotations("'")}.bind(this)); +a.setKeyBinding(new m.KeyBinding('"',!1,!1,!1,!1,"keypress"),"autoPairDblQuotation");a.setAction("autoPairDblQuotation",function(){return this.autoPairQuotations('"')}.bind(this));a.setAction("deletePrevious",function(){return this.deletePrevious()}.bind(this))},autoIndent:function(){var a=this.editor,b=a.getTextView();if(b.getOptions("readonly"))return!1;var c=a.getSelection();if(c.start===c.end){for(var d=a.getModel(),f=d.getLineAtOffset(c.start),g=d.getLine(f,!1),h=d.getLineStart(f),i=0,k=c.start- +h,s;i<k&&((s=g.charCodeAt(i))===32||s===9);)i++;var h=g.substring(0,i),b=b.getOptions("tabSize","expandTab"),u=b.expandTab?Array(b.tabSize+1).join(" "):"\t",b=d.getLineDelimiter(),j=/^[\s]*\/\*[\*]*[\s]*$/,m=/^[\s]*\*/,n=/\*\/[\s]*$/,D=g.substring(0,k),y=g.substring(k),K;if(this.smartIndentation&&g.charCodeAt(K=D.trimRight().length-1)===123)return d=k-K-1,y=y.length-y.trimLeft().length,g=g.charCodeAt(k+y)===125?b+h+u+b+h:b+h+u,a.setText(g,c.start-d,c.end+y),a.setCaretOffset(c.start+b.length+h.length+ +u.length-d),!0;else if(this.autoCompleteComments&&!n.test(D)&&(j.test(D)||m.test(D))){if(i=j.exec(D)){g=b+h+" * ";g+=n.test(y)?y.substring(0,y.length-2).trim():y.trim();if(d.getLineCount()===f+1||!m.test(d.getLine(f+1)))g+=b+h+" */";a.setText(g,c.start,c.end+y.length);a.setCaretOffset(c.start+b.length+h.length+3);return!0}if(i=m.exec(D))for(f-=1;f>=0;f--)if(i=d.getLine(f,!1),j.test(i))return n.test(y)||g.charCodeAt(k)===47?(g=b+h+"*"+y,h=c.start+b.length+h.length+1):(g=b+h+"* "+y,h=c.start+b.length+ +h.length+2),a.setText(g,c.start,c.end+y.length),a.setCaretOffset(h),!0;else if(!m.test(i))break}else if(n.test(D)&&h.charCodeAt(h.length-1)===32)return g=b+h.substring(0,h.length-1),a.setText(g,c.start,c.end),a.setCaretOffset(c.start+g.length),!0;else if(i>0){for(i=k;i<g.length&&((s=g.charCodeAt(i++))===32||s===9);)c.end++;a.setText(d.getLineDelimiter()+h,c.start,c.end);return!0}}return!1},addBlockComment:function(){var a=this.editor;if(a.getTextView().getOptions("readonly"))return!1;var b=a.getModel(), +c=a.getSelection(),d=this._findEnclosingComment(b,c.start,c.end);if(d.commentStart!==void 0&&d.commentEnd!==void 0)return!0;b=b.getText(c.start,c.end);if(b.length===0)return!0;var d=b.length,b=b.replace(/\/\*|\*\//g,""),f=b.length;a.setText("/*"+b+"*/",c.start,c.end);a.setSelection(c.start+2,c.end+2+(f-d));return!0},autoPairBrackets:function(a,b){if(a==="["&&!this.autoPairSquareBrackets)return!1;else if(a==="{"&&!this.autoPairBraces)return!1;else if(a==="("&&!this.autoPairParentheses)return!1;else if(a=== +"<"&&!this.autoPairAngleBrackets)return!1;var c=this.editor;if(c.getTextView().getOptions("readonly"))return!1;var d=c.getSelection(),f=c.getModel(),g=c.getCaretOffset()===f.getCharCount()?"":f.getText(d.start,d.start+1).trim(),h=/^$|[)}\]>]/;if(d.start===d.end&&h.test(g))return c.setText(a+b,d.start,d.start),c.setCaretOffset(d.start+1),!0;else if(d.start!==d.end)return f=f.getText(d.start,d.end),c.setText(a+f+b,d.start,d.end),c.setSelection(d.start+1,d.end+1),!0;return!1},autoPairQuotations:function(a){if(!this.autoPairQuotation)return!1; +var b=this.editor;if(b.getTextView().getOptions("readonly"))return!1;var c=b.getSelection(),d=b.getModel(),f=b.getCaretOffset(),g=f===0?"":d.getText(c.start-1,c.start).trim(),h=f===d.getCharCount()?"":d.getText(c.start,c.start+1).trim(),f=/^"$|^'$/,i=/\w/,k=/^$|[)}\]>]/;if(c.start!==c.end){d=d.getText(c.start,c.end);if(f.test(d))return!1;b.setText(a+d+a,c.start,c.end);b.setSelection(c.start+1,c.end+1)}else if(h===a)b.setCaretOffset(c.start+1);else if(g===a||f.test(h)||i.test(g)||!k.test(h))return!1; +else b.setText(a+a,c.start,c.start),b.setCaretOffset(c.start+1);return!0},contentAssistProposalApplied:function(a){a=a.data.proposal;if(a.positions&&a.positions.length>0&&this.linkedMode){for(var b=[],c=0;c<a.positions.length;++c)b[c]={positions:[{offset:a.positions[c].offset,length:a.positions[c].length}]};this.linkedMode.enterLinkedMode({groups:b,escapePosition:a.escapePosition})}else a.groups&&a.groups.length>0&&this.linkedMode?this.linkedMode.enterLinkedMode({groups:a.groups,escapePosition:a.escapePosition}): +a.escapePosition&&this.editor.getTextView().setCaretOffset(a.escapePosition);return!0},deletePrevious:function(){var a=this.editor;if(a.getTextView().getOptions("readonly"))return!1;var b=a.getSelection();if(b.start!==b.end)return!1;var c=a.getModel(),d=a.getCaretOffset(),f=d===0?"":c.getText(b.start-1,b.start),c=d===c.getCharCount()?"":c.getText(b.start,b.start+1);(f==="("&&c===")"||f==="["&&c==="]"||f==="{"&&c==="}"||f==="<"&&c===">"||f==='"'&&c==='"'||f==="'"&&c==="'")&&a.setText("",b.start,b.start+ +1);return!1},_findEnclosingComment:function(a,b,c){var d=a.getLineAtOffset(b),f=a.getLineAtOffset(c),g,h,i,k,s,u;for(g=d;g>=0;g--)if(h=a.getLine(g),i=g===d?b-a.getLineStart(d):h.length,k=h.lastIndexOf("/*",i),h=h.lastIndexOf("*/",i),h>k)break;else if(k!==-1){s=a.getLineStart(g)+k;break}for(g=f;g<a.getLineCount();g++)if(h=a.getLine(g),i=g===f?c-a.getLineStart(f):0,k=h.indexOf("/*",i),h=h.indexOf("*/",i),k!==-1&&k<h)break;else if(h!==-1){u=a.getLineStart(g)+h;break}return{commentStart:s,commentEnd:u}}, +lineStart:function(){for(var a=this.editor,b=a.getModel(),c=a.getCaretOffset(),d=b.getLineAtOffset(c),f=b.getLineStart(d),b=b.getLine(d),d=0;d<b.length;d++){var g=b.charCodeAt(d);if(!(g===32||g===9))break}d+=f;return c!==d?(a.setSelection(d,d),!0):!1},removeBlockComment:function(){var a=this.editor;if(a.getTextView().getOptions("readonly"))return!1;var b=a.getModel(),c=a.getSelection(),d=b.getText(c.start,c.end),f,g,h;for(h=0;h<d.length;h++)if(d.substring(h,h+2)==="/*"){f=c.start+h;break}for(;h<d.length;h++)if(d.substring(h, +h+2)==="*/"){g=c.start+h;break}if(f!==void 0&&g!==void 0)a.setText(b.getText(f+2,g),f,g+2),a.setSelection(f,g);else{d=this._findEnclosingComment(b,c.start,c.end);if(d.commentStart===void 0||d.commentEnd===void 0)return!0;b=b.getText(d.commentStart+2,d.commentEnd);a.setText(b,d.commentStart,d.commentEnd+2);a.setSelection(c.start-2,c.end-2)}return!0},toggleLineComment:function(){var a=this.editor;if(a.getTextView().getOptions("readonly"))return!1;for(var b=a.getModel(),c=a.getSelection(),d=b.getLineAtOffset(c.start), +f=b.getLineAtOffset(c.end>c.start?c.end-1:c.end),g=!0,h=[],i,k,s=d;s<=f;s++)if(i=b.getLine(s,!0),h.push(i),!g||(k=i.indexOf("//"))===-1)g=!1;else if(k!==0){var u;for(u=0;u<k;u++)if(g=i.charCodeAt(u),!(g===32||g===9))break;g=u===k}s=b.getLineStart(d);u=b.getLineEnd(f,!0);if(g){for(g=0;g<h.length;g++)i=h[g],k=i.indexOf("//"),h[g]=i.substring(0,k)+i.substring(k+2);h=h.join("");i=b.getLineStart(f);b=s===c.start?c.start:c.start-2;c=c.end-2*(f-d+1)+(c.end===i+1?2:0)}else h.splice(0,0,""),h=h.join("//"), +b=s===c.start?c.start:c.start+2,c=c.end+2*(f-d+1);a.setText(h,s,u);a.setSelection(b,c);return!0},trimTrailingWhitespaces:function(){var a=this.editor,b=a.getModel(),c=a.getSelection();a.getTextView().setRedraw(!1);a.getUndoStack().startCompoundChange();for(var d=/(\s+$)/,f=b.getLineCount(),g=0;g<f;g++){var h=b.getLine(g),i=d.exec(h);if(i){var k=b.getLineStart(g),h=i[0].length,i=k+i.index;b.setText("",i,i+h);if(c.start>i)c.start=Math.max(i,c.start-h);if(c.start!==c.end&&c.end>i)c.end=Math.max(i,c.end- +h)}}a.getUndoStack().endCompoundChange();a.getTextView().setRedraw(!0);a.setSelection(c.start,c.end,!1)},startUndo:function(){this.undoStack&&this.undoStack.startCompoundChange()},skipClosingBracket:function(a){var b=this.editor;if(b.getTextView().getOptions("readonly"))return!1;var c=b.getSelection(),d=b.getModel();return(b.getCaretOffset()===d.getCharCount()?"":d.getText(c.start,c.start+1))===a?(b.setCaretOffset(c.start+1),!0):!1},endUndo:function(){this.undoStack&&this.undoStack.endCompoundChange()}, +setAutoPairParentheses:function(a){this.autoPairParentheses=a},setAutoPairBraces:function(a){this.autoPairBraces=a},setAutoPairSquareBrackets:function(a){this.autoPairSquareBrackets=a},setAutoPairAngleBrackets:function(a){this.autoPairAngleBrackets=a},setAutoPairQuotations:function(a){this.autoPairQuotation=a},setAutoCompleteComments:function(a){this.autoCompleteComments=a},setSmartIndentation:function(a){this.smartIndentation=a}};b.SourceCodeActions=g;if(!String.prototype.trimLeft)String.prototype.trimLeft= +function(){return this.replace(/^\s+/g,"")};if(!String.prototype.trimRight)String.prototype.trimRight=function(){return this.replace(/\s+$/g,"")};return b}); +define("orion/editor/templates",[],function(){function k(k,i,c,d){this.prefix=k;this.description=i;this.template=c;this.name=d;this._parse()}function m(k,i){this._keywords=k||[];this._templates=[];this.addTemplates(i||[])}k.prototype={getProposal:function(k,i,c){var k=i-k.length,i={},d,f=c.delimiter!==void 0?c.delimiter:"\n";c.indentation&&(f+=c.indentation);for(var g=c.tab!==void 0?c.tab:"\t",h=0,b=this.variables,a=this.segments,c=[],e=0;e<a.length;e++){var l=a[e],o=b[l];if(o!==void 0)switch(l){case "${tab}":l= +g;break;case "${delimiter}":l=f;break;case "${cursor}":l="";d=h;break;default:var q=i[l];q||(q=i[l]={data:o.data,positions:[]});l=o.substitution;q.data&&q.data.values&&(l=q.data.values[0]);q.positions.push({offset:k+h,length:l.length})}c.push(l);h+=l.length}var f=[],r;for(r in i)i.hasOwnProperty(r)&&f.push(i[r]);c=c.join("");if(d===void 0)d=c.length;return{proposal:c,name:this.name,description:this.description,groups:f,escapePosition:k+d,style:"noemphasis"}},match:function(k){return this.prefix.indexOf(k)=== +0},_parse:function(){var k=this.template,i=[],c={},d,f=0,k=k.replace(/\n/g,"${delimiter}"),k=k.replace(/\t/g,"${tab}");k.replace(/\$\{((?:[^\\}]+|\\.))*\}/g,function(g,h,b){var a=g.substring(2,g.length-1),h=g,e=a,l=null,o=e.indexOf(":");o!==-1&&(e=e.substring(0,o),h="${"+e+"}",l=JSON.parse(a.substring(o+1).replace("\\}","}").trim()));(a=c[h])||(a=c[h]={});a.substitution=e;if(l)a.data=l;(d=k.substring(f,b))&&i.push(d);i.push(h);f=b+g.length;return e});(d=k.substring(f,k.length))&&i.push(d);this.segments= +i;this.variables=c}};m.prototype={addTemplates:function(m){for(var i=this.getTemplates(),c=0;c<m.length;c++)i.push(new k(m[c].prefix,m[c].description,m[c].template,m[c].name))},computeProposals:function(k,i,c){var d=this.getPrefix(k,i,c),f=[];this.isValid(d,k,i,c)&&(f=f.concat(this.getTemplateProposals(d,i,c)),f=f.concat(this.getKeywordProposals(d)));return f},getKeywords:function(){return this._keywords},getKeywordProposals:function(k){var i=[],c=this.getKeywords();if(c){for(var d=0;d<c.length;d++)c[d].indexOf(k)=== +0&&i.push({proposal:c[d].substring(k.length),description:c[d],style:"noemphasis_keyword"});0<i.length&&i.splice(0,0,{proposal:"",description:"Keywords",style:"noemphasis_title_keywords",unselectable:!0})}return i},getPrefix:function(k,i,c){return c.prefix},getTemplates:function(){return this._templates},getTemplateProposals:function(k,i,c){for(var d=[],f=this.getTemplates(),g=0;g<f.length;g++){var h=f[g];h.match(k)&&(h=h.getProposal(k,i,c),this.removePrefix(k,h),d.push(h))}0<d.length&&(d.sort(function(b, +a){return b.name<a.name?-1:b.name>a.name?1:0}),d.splice(0,0,{proposal:"",description:"Templates",style:"noemphasis_title",unselectable:!0}));return d},removePrefix:function(k,i){if(!(i.overwrite=i.proposal.substring(0,k.length)!==k))i.proposal=i.proposal.substring(k.length)},isValid:function(){return!0}};return{Template:k,TemplateContentAssist:m}}); +define("orion/editor/linkedMode","i18n!orion/editor/nls/messages,orion/keyBinding,orion/editor/keyModes,orion/editor/annotations,orion/editor/templates,orion/objects,orion/util".split(","),function(k,m,n,i,c,d){function f(c,b,a){var e=c.getTextView();n.KeyMode.call(this,e);this.editor=c;this.undoStack=b;this.contentAssist=a;this.linkedModeModel=null;e.setAction("linkedModeEnter",function(){this.exitLinkedMode(!0);return!0}.bind(this));e.setAction("linkedModeCancel",function(){this.exitLinkedMode(!1); +return!0}.bind(this));e.setAction("linkedModeNextGroup",function(){var a=this.linkedModeModel;this.selectLinkedGroup((a.selectedGroupIndex+1)%a.groups.length);return!0}.bind(this));e.setAction("linkedModePreviousGroup",function(){var a=this.linkedModeModel;this.selectLinkedGroup(a.selectedGroupIndex>0?a.selectedGroupIndex-1:a.groups.length-1);return!0}.bind(this));this.linkedModeListener={onActivating:function(){this._groupContentAssistProvider&&(this.contentAssist.setProviders([this._groupContentAssistProvider]), +this.contentAssist.setProgress(null))}.bind(this),onModelChanged:function(a){if(!this.ignoreVerify){for(var b=this.editor.mapOffset(a.start),c=this.linkedModeModel,e,d;c;)if(e=this._getPositionChanged(c,b,b+a.removedCharCount),d=e.position,d===void 0||d.model!==c)this.exitLinkedMode(!1),c=this.linkedModeModel;else break;if(c){c=0;a=a.addedCharCount-a.removedCharCount;e=e.positions;for(var f,g=0;g<e.length;++g){f=e[g];d=f.position;var h=d.offset<=b&&b<=d.offset+d.length;h&&!f.ansestor?(d.offset+=c, +d.length+=a,c+=a):(d.offset+=c,f.ansestor&&h&&(d.length+=a));if(f.escape)f.model.escapePosition=d.offset}this._updateAnnotations(e)}}}.bind(this),onVerify:function(a){if(!this.ignoreVerify){for(var b=this.editor,c=b.mapOffset(a.start),e=this.editor.mapOffset(a.end),d=this.linkedModeModel,f,g;d;)if(f=this._getPositionChanged(d,c,e),g=f.position,g===void 0||g.model!==d)this.exitLinkedMode(!1),d=this.linkedModeModel;else break;if(d){var h=this._compoundChange;h?h.owner.model===d&&h.owner.group===g.group|| +(this.endUndo(),this.startUndo()):this.startUndo();d.selectedGroupIndex=g.group;var h=0,i=a.text.length-(e-c);f=f.positions;var j;c-=g.position.offset;for(var k=e-g.position.offset,m=0;m<f.length;++m)if(j=f[m],e=j.position,j.oldOffset=e.offset,j.model===d&&j.group===g.group?(e.offset+=h,e.length+=i,h+=i):(e.offset+=h,j.ansestor&&(e.length+=g.count*i)),j.escape)j.model.escapePosition=e.offset;this.ignoreVerify=!0;for(m=f.length-1;m>=0;m--)j=f[m],j.model===d&&j.group===g.group&&b.setText(a.text,j.oldOffset+ +c,j.oldOffset+k);this.ignoreVerify=!1;a.text=null;this._updateAnnotations(f)}}}.bind(this)}}var g={};f.prototype=new n.KeyMode;d.mixin(f.prototype,{createKeyBindings:function(){var c=m.KeyBinding,b=[];b.push({actionID:"linkedModeEnter",keyBinding:new c(13)});b.push({actionID:"linkedModeCancel",keyBinding:new c(27)});b.push({actionID:"linkedModeNextGroup",keyBinding:new c(9)});b.push({actionID:"linkedModePreviousGroup",keyBinding:new c(9,!1,!0)});return b},enterLinkedMode:function(c){if(!this.linkedModeModel){var b= +this.editor.getTextView();b.addKeyMode(this);b.addEventListener("Verify",this.linkedModeListener.onVerify);b.addEventListener("ModelChanged",this.linkedModeListener.onModelChanged);this.contentAssist.addEventListener("Activating",this.linkedModeListener.onActivating);this.editor.reportStatus(k.linkedModeEntered,null,!0)}this._sortedPositions=null;if(this.linkedModeModel)c.previousModel=this.linkedModeModel,c.parentGroup=this.linkedModeModel.selectedGroupIndex,this.linkedModeModel.nextModel=c;this.linkedModeModel= +c;this.selectLinkedGroup(0)},exitLinkedMode:function(c){if(this.isActive()){if(this._compoundChange)this.endUndo(),this._compoundChange=null;this._sortedPositions=null;var b=this.linkedModeModel;this.linkedModeModel=b.previousModel;b.parentGroup=b.previousModel=void 0;if(this.linkedModeModel)this.linkedModeModel.nextModel=void 0;if(!this.linkedModeModel){var a=this.editor,e=a.getTextView();e.removeKeyMode(this);e.removeEventListener("Verify",this.linkedModeListener.onVerify);e.removeEventListener("ModelChanged", +this.linkedModeListener.onModelChanged);e=this.contentAssist;e.removeEventListener("Activating",this.linkedModeListener.onActivating);e.offset=void 0;this.editor.reportStatus(k.linkedModeExited,null,!0);c&&a.setCaretOffset(b.escapePosition,!1)}this.selectLinkedGroup(0)}},startUndo:function(){if(this.undoStack){var c=this,b=this.linkedModeModel;this._compoundChange=this.undoStack.startCompoundChange({model:b,group:b.selectedGroupIndex,end:function(){c._compoundChange=null}})}},endUndo:function(){this.undoStack&& +this.undoStack.endCompoundChange()},isActive:function(){return!!this.linkedModeModel},isStatusActive:function(){return!!this.linkedModeModel},selectLinkedGroup:function(d){var b=this.linkedModeModel;if(b){b.selectedGroupIndex=d;var d=b.groups[d],a=d.positions[0],e=this.editor;e.setSelection(a.offset,a.offset+a.length);if(b=this.contentAssist)if(b.offset=void 0,d.data&&d.data.type==="link"&&d.data.values)(this._groupContentAssistProvider=new c.TemplateContentAssist(d.data.values)).getPrefix=function(){var b= +e.getSelection();return b.start===b.end&&(b=e.getCaretOffset(),a.offset<=b&&b<=a.offset+a.length)?e.getText(a.offset,b):""},b.offset=a.offset,b.deactivate(),b.activate();else if(this._groupContentAssistProvider)this._groupContentAssistProvider=null,b.deactivate()}this._updateAnnotations()},_getModelPositions:function(c,b,a){for(var e=b.groups,d=0;d<e.length;d++)for(var f=e[d].positions,g=0;g<f.length;g++){var i=f[g];a&&(i={offset:i.offset+a,length:i.length});i={index:g,group:d,count:f.length,model:b, +position:i};c.push(i);if(b.nextModel&&b.nextModel.parentGroup===d)i.ansestor=!0,this._getModelPositions(c,b.nextModel,(a||0)+f[g].offset-f[0].offset)}},_getSortedPositions:function(c){var b=this._sortedPositions;if(!b){for(b=[];c.previousModel;)c=c.previousModel;for(this._getModelPositions(b,c);c;)c.escapePosition!==void 0&&b.push({escape:!0,model:c,position:{offset:c.escapePosition,length:0}}),c=c.nextModel;b.sort(function(a,b){return a.position.offset-b.position.offset});this._sortedPositions=b}return b}, +_getPositionChanged:function(c,b,a){for(var e,c=this._getSortedPositions(c),d=c.length-1;d>=0;d--){var f=c[d].position;if(f.offset<=b&&a<=f.offset+f.length){e=c[d];break}}return{position:e,positions:c}},_updateAnnotations:function(c){var b=this.editor.getAnnotationModel();if(b){var a=[],e=[];b.getTextModel();for(var d=b.getAnnotations(),f;d.hasNext();)switch(f=d.next(),f.type){case i.AnnotationType.ANNOTATION_LINKED_GROUP:case i.AnnotationType.ANNOTATION_CURRENT_LINKED_GROUP:case i.AnnotationType.ANNOTATION_SELECTED_LINKED_GROUP:a.push(f)}if(d= +this.linkedModeModel)for(var c=c||this._getSortedPositions(d),g=0;g<c.length;g++)if(f=c[g],f.model===d){var k=i.AnnotationType.ANNOTATION_LINKED_GROUP;f.group===d.selectedGroupIndex&&(k=f.index===0?i.AnnotationType.ANNOTATION_SELECTED_LINKED_GROUP:i.AnnotationType.ANNOTATION_CURRENT_LINKED_GROUP);f=f.position;f=i.AnnotationType.createAnnotation(k,f.offset,f.offset+f.length,"");e.push(f)}b.replaceAnnotations(a,e)}}});g.LinkedMode=f;return g}); +define("orion/editor/factories","orion/editor/actions,orion/editor/undoStack,orion/editor/rulers,orion/editor/annotations,orion/editor/textDND,orion/editor/linkedMode".split(","),function(k,m,n,i,c,d){function f(){}function g(){}function h(){}function b(){}function a(){}function e(){}var l={};f.prototype={createKeyBindings:function(a,b,c,e){var e=new k.TextActions(a,b,e),f=new d.LinkedMode(a,b,c),a=new k.SourceCodeActions(a,b,c,f);return{textActions:e,linkedMode:f,sourceCodeActions:a}}};l.KeyBindingsFactory= +f;g.prototype={createUndoStack:function(a){a=a.getTextView();return new m.UndoStack(a,200)}};l.UndoFactory=g;h.prototype={createLineNumberRuler:function(a){return new n.LineNumberRuler(a,"left",{styleClass:"ruler lines"},{styleClass:"rulerLines odd"},{styleClass:"rulerLines even"})}};l.LineNumberRulerFactory=h;b.prototype={createFoldingRuler:function(a){return new n.FoldingRuler(a,"left",{styleClass:"ruler folding"})}};l.FoldingRulerFactory=b;a.prototype={createAnnotationModel:function(a){return new i.AnnotationModel(a)}, +createAnnotationStyler:function(a,b){return new i.AnnotationStyler(a,b)},createAnnotationRulers:function(a){var b=new n.AnnotationRuler(a,"left",{styleClass:"ruler annotations"}),a=new n.OverviewRuler(a,"right",{styleClass:"ruler overview"});return{annotationRuler:b,overviewRuler:a}}};l.AnnotationFactory=a;e.prototype={createTextDND:function(a,b){return new c.TextDND(a.getTextView(),b)}};l.TextDNDFactory=e;return l}); +define("orion/editor/editorFeatures",["orion/editor/factories","orion/editor/actions","orion/editor/linkedMode","orion/objects"],function(k,m,n,i){return i.mixin({},k,m,n)}); +(function(k,m){typeof define==="function"&&define.amd?define("orion/Deferred",m):typeof exports==="object"?module.exports=m():(k.orion=k.orion||{},k.orion.Deferred=m())})(this,function(){function k(){for(var f;f=c.shift();)f();d=!1}function m(f){c.push(f);d||(d=!0,setTimeout(k,0))}function n(c){return function(){c.apply(void 0,arguments)}}function i(){function d(){for(var b;b=l.shift();){var f=b.deferred,g=e==="fulfilled"?"resolve":"reject";if(typeof b[g]==="function")try{var h=(0,b[g])(a),i=h&&(typeof h=== +"object"||typeof h==="function")&&h.then;if(typeof i==="function")if(h===f.promise)f.reject(new TypeError);else{var k=h.cancel;typeof k==="function"?f._protected(c).parentCancel=k.bind(h):delete f._protected(c).parentCancel;i.call(h,n(f.resolve),n(f.reject),n(f.progress))}else f.resolve(h)}catch(j){f.reject(j)}else f[g](a)}}function g(b){delete q.parentCancel;e="rejected";a=b;l.length&&m(d)}function h(b){function c(a){return function(b){t||(t=!0,a(b))}}var t=!1;delete q.parentCancel;try{var v=b&& +(typeof b==="object"||typeof b==="function")&&b.then;if(typeof v==="function")if(b===k)g(new TypeError);else{e="assumed";var s=b&&b.cancel;if(typeof s!=="function"){var u=new i,b=u.promise;try{v(u.resolve,u.reject,u.progress)}catch(j){u.reject(j)}s=b.cancel;v=b.then}a=b;v.call(b,c(h),c(g));q.parentCancel=s.bind(b)}else e="fulfilled",a=b,l.length&&m(d)}catch(w){c(g)(w)}}function b(){var a=q.parentCancel;if(a)delete q.parentCancel,a();else if(!e)a=Error("Cancel"),a.name="Cancel",g(a)}var a,e,l=[],k= +this,q={};Object.defineProperty(this,"_protected",{value:function(a){if(a!==c)throw Error("protected");return q}});this.resolve=function(a){e||h(a);return k};this.reject=function(a){e||g(a);return k};this.progress=function(a){e||l.forEach(function(b){if(b.progress)try{b.progress(a)}catch(c){}});return k.promise};this.cancel=function(){q.parentCancel?setTimeout(b,0):b();return k};this.then=function(a,b,g){a={resolve:a,reject:b,progress:g,deferred:new i};l.push(a);a.deferred._protected(c).parentCancel= +k.promise.cancel.bind(k);(e==="fulfilled"||e==="rejected")&&m(d);return a.deferred.promise};this.promise={then:k.then,cancel:k.cancel}}var c=[],d=!1;i.all=function(c,d){function h(b,c){l||(e[b]=c,--a===0&&k.resolve(e))}function b(a,b){if(!l){if(d)try{h(a,d(b));return}catch(c){b=c}k.reject(b)}}var a=c.length,e=[],l=!1,k=new i;k.then(void 0,function(){l=!0;c.forEach(function(a){a.cancel&&a.cancel()})});a===0?k.resolve(e):c.forEach(function(a,c){a.then(h.bind(void 0,c),b.bind(void 0,c))});return k.promise}; +i.when=function(c,d,h,b){var a;if(!(c&&typeof c.then==="function"))a=new i,a.resolve(c),c=a.promise;return c.then(d,h,b)};return i}); +define("orion/webui/littlelib",["orion/util"],function(k){function m(c,d){d||(d=document);return d.querySelectorAll(c)}function n(c){if(c.tabIndex>=0)return c;if(c.hasChildNodes())for(var d=0;d<c.childNodes.length;d++){var b=n(c.childNodes[d]);if(b)return b}return null}function i(c){if(c.tabIndex>=0)return c;if(c.hasChildNodes())for(var d=c.childNodes.length-1;d>=0;d--){var b=i(c.childNodes[d]);if(b)return b}return null}function c(f,h){if(f.nodeType===3){var b=d.exec(f.nodeValue);b&&b.length>1&&h(f, +b)}if(f.hasChildNodes())for(b=0;b<f.childNodes.length;b++)c(f.childNodes[b],h)}var d=/\$\{([^\}]+)\}/,f=null;return{$:function(c,d){d||(d=document);return d.querySelector(c)},$$:m,$$array:function(c,d){return Array.prototype.slice.call(m(c,d))},node:function(c){var d=c;typeof c==="string"&&(d=document.getElementById(c));return d},contains:function(c,d){if(!c||!d)return!1;if(c===d)return!0;var b=c.compareDocumentPosition(d);return Boolean(b&16)},bounds:function(c){c=c.getBoundingClientRect();return{left:c.left+ +document.documentElement.scrollLeft,top:c.top+document.documentElement.scrollTop,width:c.width,height:c.height}},empty:function(c){for(;c.hasChildNodes();)c.removeChild(c.firstChild)},firstTabbable:n,lastTabbable:i,stop:function(c){if(window.document.all)c.keyCode=0;c.preventDefault&&(c.preventDefault(),c.stopPropagation())},processTextNodes:function(d,f){c(d,function(b,a){b.parentNode.replaceChild(document.createTextNode(f[a[1]]||a[1]),b)})},processDOMNodes:function(d,f){c(d,function(b,a){var c= +f[a[1]];if(c){var d=document.createRange(),g=a.index;d.setStart(b,g);d.setEnd(b,g+a[0].length);d.deleteContents();d.insertNode(c)}})},addAutoDismiss:function(c,d){function b(a){f.forEach(function(b){var c=!1,d=b.excludeNodes.some(function(b){return document.body.contains(b)?(c=!0,b.contains(a.target)):!1});if(c&&!d)try{b.dismiss(a)}catch(f){typeof console!=="undefined"&&console&&console.error(f&&f.message)}});f=f.filter(function(a){return a.excludeNodes.some(function(a){return document.body.contains(a)})})} +f===null&&(f=[],document.addEventListener("click",b,!0),k.isIOS&&document.addEventListener("touchend",function(a){function b(){a.target.removeEventListener("click",b)}a.touches.length===0&&a.target.addEventListener("click",b)},!1));f.push({excludeNodes:c,dismiss:d})},setFramesEnabled:function(c){for(var d=document.getElementsByTagName("iframe"),b=0;b<d.length;b++)d[b].parentNode.style.pointerEvents=c?"":"none"},removeAutoDismiss:function(c){f=f.filter(function(d){return c!==d.dismiss})},KEY:{BKSPC:8, +TAB:9,ENTER:13,ESCAPE:27,SPACE:32,PAGEUP:33,PAGEDOWN:34,END:35,HOME:36,LEFT:37,UP:38,RIGHT:39,DOWN:40,INSERT:45,DEL:46}}}); +define("orion/editor/contentAssist","i18n!orion/editor/nls/messages,orion/keyBinding,orion/editor/keyModes,orion/editor/eventTarget,orion/Deferred,orion/objects,orion/editor/util,orion/util,orion/webui/littlelib".split(","),function(k,m,n,i,c,d,f,g,h){var b,a,e;function l(c){this.textView=c;this.state=b;this.resetProviderInfoArray();var d=this;this.contentAssistListener={onModelChanging:function(a){this._latestModelChangingEvent=a}.bind(this),onSelection:function(c){this.isDeactivatingChange(this._latestModelChangingEvent, +c)?this.setState(b):this.isActive()&&(this.state===a&&this.setState(e),this.filterProposals(c));this._latestModelChangingEvent=null}.bind(this),onScroll:function(){this.setState(b)}.bind(this)};c.setKeyBinding(g.isMac?new m.KeyBinding(" ",!1,!1,!1,!0):new m.KeyBinding(" ",!0),"contentAssist");c.setKeyBinding(g.isMac?new m.KeyBinding(" ",!1,!1,!0,!0):new m.KeyBinding(" ",!0,!1,!0),"contentAssist");c.setAction("contentAssist",function(){c.getOptions("readonly")||d.activate();return!0},{name:k.contentAssist})} +function o(a,b){var c=a.textView;n.KeyMode.call(this,c);this.contentAssist=a;this.widget=b;this.proposals=[];var d=this;this.contentAssist.addEventListener("ProposalsComputed",function(a){d.proposals=a.data.proposals;if(d.proposals.length===0)d.selectedIndex=-1,d.cancel();else{for(d.selectedIndex=0;d.proposals[d.selectedIndex]&&d.proposals[d.selectedIndex].unselectable;)d.selectedIndex++;if(d.proposals[d.selectedIndex]){if(d.widget){var b=!0;if(a.autoApply){for(a=d.selectedIndex+1;d.proposals[a]&& +d.proposals[a].unselectable;)a++;d.proposals[a]||(b=!1,d.contentAssist.apply(d.proposals[d.selectedIndex]))}b&&(d.widget.show(),d.widget.selectNode(d.selectedIndex))}}else d.selectedIndex=-1,d.cancel()}});c.setAction("contentAssistApply",function(){return this.enter()}.bind(this));c.setAction("contentAssistCancel",function(){return this.cancel()}.bind(this));c.setAction("contentAssistNextProposal",function(){return this.lineDown()}.bind(this));c.setAction("contentAssistPreviousProposal",function(){return this.lineUp()}.bind(this)); +c.setAction("contentAssistNextPage",function(){return this.pageDown()}.bind(this));c.setAction("contentAssistPreviousPage",function(){return this.pageUp()}.bind(this));c.setAction("contentAssistHome",function(){this.widget&&this.widget.scrollIndex(0,!0);return this.lineDown(0)}.bind(this));c.setAction("contentAssistEnd",function(){return this.lineUp(this.proposals.length-1)}.bind(this));c.setAction("contentAssistTab",function(){return this.tab()}.bind(this));this.widget&&(this.widget.setContentAssistMode(this), +this.widget.createAccessible())}function q(a,b){this.contentAssist=a;this.textView=this.contentAssist.getTextView();this.isShowing=this.textViewListenerAdded=!1;var c=this.textView.getOptions("parent").ownerDocument;this.parentNode=typeof b==="string"?c.getElementById(b):b;if(!this.parentNode){this.parentNode=g.createElement(c,"div");this.parentNode.className="contentassist";var d=c.getElementsByTagName("body")[0];if(d)d.appendChild(this.parentNode);else throw Error("parentNode is required");}this.parentNode.addEventListener("scroll", +this.onScroll.bind(this));var e=this;this.textViewListener={onMouseDown:function(a){(a.event.target||a.event.srcElement).parentElement!==e.parentNode&&e.contentAssist.deactivate()}};this.contentAssist.addEventListener("Deactivating",function(){e.hide()});this.scrollListener=function(){e.isShowing&&e.position()};f.addEventListener(c,"scroll",this.scrollListener)}b=1;a=2;e=3;var r={selected:"selected",hr:"proposal-hr",emphasis:"proposal-emphasis",noemphasis:"proposal-noemphasis",noemphasis_keyword:"proposal-noemphasis-keyword", +noemphasis_title:"proposal-noemphasis-title",noemphasis_title_keywords:"proposal-noemphasis-title-keywords",dfault:"proposal-default"};l.prototype={apply:function(a){if(!a)return!1;var c=this.textView,d=c.getSelection(),e=this._initialCaretOffset,f=e,j=d=Math.max(d.start,d.end),g=c.getModel();g.getBaseModel&&(f=g.mapOffset(f),j=g.mapOffset(j),g=g.getBaseModel());a.overwrite&&(e=this.getPrefixStart(g,f));f={proposal:a,start:f,end:j};this.setState(b);c.setText(typeof a==="string"?a:a.proposal,e,d); +this.dispatchEvent({type:"ProposalApplied",data:f});return!0},activate:function(c,d){if(this.state===b)this._autoTriggered=d?!0:!1,this.setState(a,c)},deactivate:function(){this.setState(b)},getTextView:function(){return this.textView},isActive:function(){return this.state===a||this.state===e},isDeactivatingChange:function(a,b){var c=!1;b.newValue.start<this._initialCaretOffset?c=!0:a&&(c=a.removedLineCount>0||a.addedLineCount>0);return c},setState:function(c,d){var e;if(c===a)this._filterText="", +e="Activating",this._mode&&this._mode.setActive(!0);else if(c===b)e="Deactivating",this._mode&&this._mode.setActive(!1),this._initialCaretOffset=-1,this._filterText="";e&&this.dispatchEvent({type:e,providerInfoArray:d});this.state=c;this.onStateChange(c)},setMode:function(a){this._mode=a},onStateChange:function(c){if(c===b){if(this.listenerAdded)this._latestModelChangingEvent=null,this.textView.removeEventListener("ModelChanging",this.contentAssistListener.onModelChanging),this.textView.removeEventListener("Scroll", +this.contentAssistListener.onScroll),this.textView.removeEventListener("Selection",this.contentAssistListener.onSelection),this.listenerAdded=!1}else if(c===a){if(!this.listenerAdded)this.textView.addEventListener("ModelChanging",this.contentAssistListener.onModelChanging),this.textView.addEventListener("Scroll",this.contentAssistListener.onScroll),this.textView.addEventListener("Selection",this.contentAssistListener.onSelection),this.listenerAdded=!0;this.computeProposals()}},computeProposals:function(){var a= +this,b=this.textView.getCaretOffset(),c=this.textView.getSelection(),c=Math.min(c.start,c.end);this._initialCaretOffset=Math.min(b,c);this._computeProposals(this._initialCaretOffset).then(function(b){a._computedProposals=b;a.isActive()&&(b=a._flatten(b),a.dispatchEvent({type:"ProposalsComputed",data:{proposals:b},autoApply:!a._autoTriggered}))})},getPrefixStart:function(a,b){for(var c=b;c>0&&/[A-Za-z0-9_]/.test(a.getText(c-1,c));)c--;return c},handleError:function(a){typeof console!=="undefined"&& +(console.log("Error retrieving content assist proposals"),console.log(a&&a.stack))},_computeProposals:function(a){var b=this._providerInfoArray,e=this.textView,f=e.getSelection(),g=e.getModel(),j=a;if(g.getBaseModel)j=g.mapOffset(j),f.start=g.mapOffset(f.start),f.end=g.mapOffset(f.end),g=g.getBaseModel();for(var a=g.getLine(g.getLineAtOffset(j)),h=0;h<a.length&&/\s/.test(a.charAt(h));)h++;var h=a.substring(0,h),e=e.getOptions("tabSize","expandTab"),e=e.expandTab?Array(e.tabSize+1).join(" "):"\t", +i={line:a,offset:j,prefix:g.getText(this.getPrefixStart(g,j),j),selection:f,delimiter:g.getLineDelimiter(),tab:e,indentation:h},l=this,b=b.map(function(a){var a=a.provider,b;try{var e,f;if(e=a.computeContentAssist){var h=l.editorContextProvider,k=h.getEditorContext();i=d.mixin(i,h.getOptions());f=e.apply(a,[k,i])}else if(e=a.getProposals||a.computeProposals)f=e.apply(a,[g.getText(),j,i]);b=l.progress?l.progress.progress(f,"Generating content assist proposal"):f}catch(s){l.handleError(s)}return c.when(b)}); +return c.all(b,this.handleError)},filterProposals:function(){var a="",b=0;if(this._latestModelChangingEvent){a=this._latestModelChangingEvent.text;if(b=this._latestModelChangingEvent.removedCharCount)this._filterText=this._filterText.substring(0,this._filterText.length-b);if(a)this._filterText=this._filterText.concat(a);a=this.textView.getModel();a.getBaseModel&&(a=a.getBaseModel());var c=this.textView.getText(this.getPrefixStart(a,this._initialCaretOffset),this._initialCaretOffset),d=[];this._computedProposals.forEach(function(a){a= +a.filter(function(a){if(r[a.style]===r.hr||r[a.style]===r.noemphasis_title)return!0;var b="";if(a.overwrite){if(a.name)b=a.name;else if(a.proposal)b=a.proposal;else return!1;return 0===b.indexOf(c+this._filterText)}else return a.name||a.proposal?(b=!1,a.name&&(b=0===a.name.indexOf(c+this._filterText)),!b&&a.proposal&&(b=0===a.proposal.indexOf(this._filterText)),b):typeof a==="string"?0===a.indexOf(this._filterText):!1},this);a.length>0&&d.push(a)},this);d=this._removeExtraUnselectableElements(d); +this.dispatchEvent({type:"ProposalsComputed",data:{proposals:this._flatten(d)},autoApply:!1})}},_removeExtraUnselectableElements:function(a){return a.map(function(a){return a.filter(function(b,c){var d=!0;if(r[b.style]===r.hr)0===c||a.length-1===c?d=!1:r.hr===r[a[c-1].style]&&(d=!1);else if(r[b.style]===r.noemphasis_title){var e=a[c+1];e?r[e.style]===r.noemphasis_title&&(d=!1):d=!1}return d})})},setEditorContextProvider:function(a){this.editorContextProvider=a},_generateProviderId:function(){this._uniqueProviderIdCounter? +this._uniqueProviderIdCounter++:this._uniqueProviderIdCounter=0;return"ContentAssistGeneratedID_"+this._uniqueProviderIdCounter},setAutoTriggerEnabled:function(a){this._autoTriggerEnabled=a;this._updateAutoTriggerListenerState()},setProviders:function(a){this.setProviderInfoArray(a.map(function(a){return{provider:a,id:this._generateProviderId()}},this))},setProviderInfoArray:function(a){this.resetProviderInfoArray();this._providerInfoArray=a;this._charTriggersInstalled=a.some(function(a){return a.charTriggers}); +this._updateAutoTriggerListenerState()},resetProviderInfoArray:function(){this._providerInfoArray=[];this._charTriggersInstalled=!1;this._updateAutoTriggerListenerState()},setProgress:function(a){this.progress=a},setStyleAccessor:function(a){this._styleAccessor=a},_flatten:function(a){return a.reduce(function(a,b){var c=a;if(Array.isArray(b)&&b.length>0){var c=b,d=a;b[0].style&&0===r[b[0].style].indexOf(r.noemphasis)&&(c=a,d=b);c.length>0&&c[c.length-1].style&&r.hr!==r[c[c.length-1].style]&&(c=c.concat({proposal:"", +name:"",description:"---------------------------------",style:"hr",unselectable:!0}));c=c.concat(d)}return c},[])},_triggerListener:function(){if(this._styleAccessor){var a=this.textView.getCaretOffset(),b=null,c=[];if(this._charTriggersInstalled){var d=this.textView.getText(a-1,a);this._providerInfoArray.forEach(function(e){var f=e.charTriggers;if(f&&f.test(d)){var f=!1,g=e.excludedStyles;g&&(b||(b=this._styleAccessor.getStyles(a-1)),f=b.some(function(a){return g.test(a.style)}));f||c.push(e)}}, +this);c.length>0&&this.activate(c,!0)}}},_updateAutoTriggerListenerState:function(){if(!this._boundTriggerListener)this._boundTriggerListener=this._triggerListener.bind(this);if(this._triggerListenerInstalled){if(!this._autoTriggerEnabled||!this._charTriggersInstalled)this.textView.removeEventListener("Modify",this._boundTriggerListener),this._triggerListenerInstalled=!1}else if(this._autoTriggerEnabled&&this._charTriggersInstalled)this.textView.addEventListener("Modify",this._boundTriggerListener), +this._triggerListenerInstalled=!0}};i.EventTarget.addMixin(l.prototype);o.prototype=new n.KeyMode;d.mixin(o.prototype,{createKeyBindings:function(){var a=m.KeyBinding,b=[];b.push({actionID:"contentAssistApply",keyBinding:new a(13)});b.push({actionID:"contentAssistCancel",keyBinding:new a(27)});b.push({actionID:"contentAssistNextProposal",keyBinding:new a(40)});b.push({actionID:"contentAssistPreviousProposal",keyBinding:new a(38)});b.push({actionID:"contentAssistNextPage",keyBinding:new a(34)});b.push({actionID:"contentAssistPreviousPage", +keyBinding:new a(33)});b.push({actionID:"contentAssistHome",keyBinding:new a(h.KEY.HOME)});b.push({actionID:"contentAssistEnd",keyBinding:new a(h.KEY.END)});b.push({actionID:"contentAssistTab",keyBinding:new a(9)});return b},cancel:function(){this.getContentAssist().deactivate()},getContentAssist:function(){return this.contentAssist},getProposals:function(){return this.proposals},isActive:function(){return this.getContentAssist().isActive()},setActive:function(a){a?this.contentAssist.textView.addKeyMode(this): +this.contentAssist.textView.removeKeyMode(this)},lineUp:function(a,b){return this.selectNew(a,b,!1)},lineDown:function(a,b){return this.selectNew(a,b,!0)},selectNew:function(a,b,c){if(c){if(void 0===a&&(a=this.selectedIndex+1),a>=this.proposals.length)if(b)return!0;else a=0}else if(void 0===a&&(a=this.selectedIndex-1),0>a)if(b)return!0;else a=this.proposals.length-1;for(var d=a;this.proposals[a]&&this.proposals[a].unselectable;){if(c){if(a++,a>=this.proposals.length)if(b)return!0;else a=0}else if(a--, +0>a)if(b)return!0;else a=this.proposals.length-1;if(a===d){a=-1;break}}this.selectedIndex=a;this.widget&&this.widget.selectNode(a);return!0},pageUp:function(){if(this.widget){var a=this.widget.getTopIndex();a===this.selectedIndex&&(this.widget.scrollIndex(a,!1),a=this.widget.getTopIndex());return 0===a?this.lineDown(a,!0):this.lineUp(a,!0)}else return this.lineUp()},pageDown:function(){if(this.widget){var a=this.widget.getBottomIndex();a===this.selectedIndex&&(this.widget.scrollIndex(a,!0),a=this.widget.getBottomIndex()); +return this.lineDown(a,!0)}else return this.lineDown()},enter:function(){return this.contentAssist.apply(this.proposals[this.selectedIndex]||null)},tab:function(){return this.widget?(this.widget.parentNode.focus(),!0):!1}});q.prototype={onClick:function(a){if(!a)a=window.event;this.contentAssist.apply(this.getProposal(a.target||a.srcElement));this.textView.focus()},onScroll:function(){this.previousCloneNode&&!this.preserveCloneThroughScroll&&(this._removeCloneNode(),this.previousSelectedNode.classList.add(r.selected)); +this.preserveCloneThroughScroll=!1},createDiv:function(a,b,c){var d=b.ownerDocument,e=g.createElement(d,"div");e.id="contentoption"+c;e.setAttribute("role","option");e.className=r[a.style]?r[a.style]:r.dfault;a.style==="hr"?a=g.createElement(d,"hr"):(a=this._createDisplayNode(e,a,c),e.contentAssistProposalIndex=c);e.appendChild(a);b.appendChild(e)},createAccessible:function(){var a=this._contentAssistMode,b=this;this.parentNode.addEventListener("keydown",function(c){if(!c)c=window.event;c.preventDefault&& +c.preventDefault();if(c.keyCode===h.KEY.ESCAPE)return a.cancel();else if(c.keyCode===h.KEY.UP)return a.lineUp();else if(c.keyCode===h.KEY.DOWN)return a.lineDown();else if(c.keyCode===h.KEY.ENTER)return a.enter();else if(c.keyCode===h.KEY.PAGEDOWN)return a.pageDown();else if(c.keyCode===h.KEY.PAGEUP)return a.pageUp();else if(c.keyCode===h.KEY.HOME)return b.scrollIndex(0,!0),a.lineDown(0);else if(c.keyCode===h.KEY.END)return a.lineUp(a.getProposals().length-1);return!1})},_createDisplayNode:function(a, +b,c){var d=null,e=null;if(typeof b==="string")e=b;else if(b.description&&typeof b.description==="string")if(b.name&&typeof b.name==="string"){var f=this._createNameNode(b.name);f.contentAssistProposalIndex=c;d=document.createElement("span");d.appendChild(f);f=document.createTextNode(b.description);d.appendChild(f);a.setAttribute("title",b.name+b.description)}else e=b.description;else e=b.proposal;e&&(d=this._createNameNode(e),a.setAttribute("title",e));d.contentAssistProposalIndex=c;return d},_createNameNode:function(a){var b= +document.createElement("span");b.classList.add("proposal-name");b.appendChild(document.createTextNode(a));return b},getProposal:function(a){var b=null,a=a.contentAssistProposalIndex;void 0!==a&&(b=this._contentAssistMode.getProposals()[a]||null);return b},getTopIndex:function(){for(var a=this.parentNode.childNodes,b=0;b<a.length;b++)if(a[b].offsetTop>=this.parentNode.scrollTop)return b;return 0},getBottomIndex:function(){for(var a=this.parentNode.childNodes,b=0;b<a.length;b++){var c=a[b];if(c.offsetTop+ +c.offsetHeight>this.parentNode.scrollTop+this.parentNode.clientHeight)return Math.max(0,b-1)}return a.length-1},scrollIndex:function(a,b){this.parentNode.childNodes[a].scrollIntoView(b);this.preserveCloneThroughScroll=!0},selectNode:function(a){var b=null;if(this.previousSelectedNode)this.previousSelectedNode.classList.remove(r.selected),this.previousSelectedNode=null,this.previousCloneNode&&this._removeCloneNode();if(-1!==a){b=this.parentNode.childNodes[a];b.classList.add(r.selected);this.parentNode.setAttribute("aria-activedescendant", +b.id);b.focus();if(b.offsetTop<this.parentNode.scrollTop)b.scrollIntoView(!0),this.preserveCloneThroughScroll=!0;else if(b.offsetTop+b.offsetHeight>this.parentNode.scrollTop+this.parentNode.clientHeight)b.scrollIntoView(!1),this.preserveCloneThroughScroll=!0;var c=h.bounds(b.firstChild||b),d=h.bounds(this.parentNode),a=window.getComputedStyle(this.parentNode),e=window.getComputedStyle(b),e=parseInt(a.paddingLeft)+parseInt(a.paddingRight)+parseInt(e.paddingLeft)+parseInt(e.paddingRight);if(c.width>= +d.width-e){e=parseInt(a.top);d=b.cloneNode(!0);d.classList.add("cloneProposal");d.style.top=e+b.offsetTop-this.parentNode.scrollTop+"px";d.style.left=a.left;d.setAttribute("id",d.id+"_clone");c=c.left+c.width-parseInt(document.documentElement.clientWidth);if(c>0)a=parseInt(a.left)-c,0>a&&(a=0),d.style.left=a+"px";a=document.createElement("div");a.id="clone_contentassist";a.classList.add("contentassist");a.classList.add("cloneWrapper");a.appendChild(d);a.onclick=this.parentNode.onclick;this.parentNode.parentNode.insertBefore(a, +this.parentNode);var f=function(a){a.contentAssistProposalIndex=b.contentAssistProposalIndex;if(a.hasChildNodes())for(var c=0;c<a.childNodes.length;c++)f(a.childNodes[c])};f(a);b.classList.remove(r.selected);this.previousCloneNode=a}}this.previousSelectedNode=b},setContentAssistMode:function(a){this._contentAssistMode=a},show:function(){var a=this._contentAssistMode.getProposals();if(a.length===0)this.hide();else{this.parentNode.innerHTML="";for(var b=0;b<a.length;b++)this.createDiv(a[b],this.parentNode, +b);this.position();this.parentNode.onclick=this.onClick.bind(this);this.isShowing=!0;if(!this.textViewListenerAdded)this.textView.addEventListener("MouseDown",this.textViewListener.onMouseDown),this.textViewListenerAdded=!0}},hide:function(){this.parentNode.ownerDocument.activeElement===this.parentNode&&this.textView.focus();this.parentNode.style.display="none";this.parentNode.onclick=null;this.isShowing=!1;if(this.textViewListenerAdded)this.textView.removeEventListener("MouseDown",this.textViewListener.onMouseDown), +this.textViewListenerAdded=!1;if(this.previousSelectedNode)this.previousSelectedNode=null,this.previousCloneNode&&this._removeCloneNode()},position:function(){var a=this.contentAssist,b=this.textView;if(a.offset!==void 0){var a=a.offset,c=b.getModel();c.getBaseModel&&(a=c.mapOffset(a,!0))}else a=this.textView.getCaretOffset();a=b.getLocationAtOffset(a);a.y+=b.getLineHeight();this.textView.convert(a,"document","page");this.parentNode.style.position="fixed";this.parentNode.style.left=a.x+"px";this.parentNode.style.top= +a.y+"px";this.parentNode.style.display="block";this.parentNode.scrollTop=0;b=this.parentNode.ownerDocument;c=b.documentElement.clientWidth;if(a.y+this.parentNode.offsetHeight>b.documentElement.clientHeight)this.parentNode.style.top=a.y-this.parentNode.offsetHeight-this.textView.getLineHeight()+"px";if(a.x+this.parentNode.offsetWidth>c)this.parentNode.style.left=c-this.parentNode.offsetWidth+"px"},_removeCloneNode:function(){this.parentNode.parentNode.contains(this.previousCloneNode)&&this.parentNode.parentNode.removeChild(this.previousCloneNode); +this.previousCloneNode=null}};return{ContentAssist:l,ContentAssistMode:o,ContentAssistWidget:q}}); +define("orion/editor/stylers/lib/syntax",[],function(){return{id:"orion.lib",grammars:[{id:"orion.lib",patterns:[{include:"#brace_open"},{include:"#brace_close"},{include:"#bracket_open"},{include:"#bracket_close"},{include:"#parenthesis_open"},{include:"#parenthesis_close"},{include:"#number_decimal"},{include:"#number_hex"},{include:"#string_doubleQuote"},{include:"#string_singleQuote"}],repository:{brace_open:{match:"{",name:"punctuation.section.block.begin"},brace_close:{match:"}",name:"punctuation.section.block.end"}, +bracket_open:{match:"\\[",name:"punctuation.section.bracket.begin"},bracket_close:{match:"\\]",name:"punctuation.section.bracket.end"},parenthesis_open:{match:"\\(",name:"punctuation.section.parens.begin"},parenthesis_close:{match:"\\)",name:"punctuation.section.parens.end"},doc_block:{begin:"/\\*\\*",end:"\\*/",name:"comment.block.documentation",patterns:[{match:"@(?:(?!\\*/)\\S)*",name:"keyword.other.documentation.tag"},{match:"\\<\\S*\\>",name:"keyword.other.documentation.markup"},{match:"(\\b)(TODO)(\\b)(((?!\\*/).)*)", +name:"meta.annotation.task.todo",captures:{2:{name:"keyword.other.documentation.task"},4:{name:"comment.block"}}}]},number_decimal:{match:"\\b-?(?:\\.\\d+|\\d+\\.?\\d*)(?:[eE][+-]?\\d+)?\\b",name:"constant.numeric.number"},number_hex:{match:"\\b0[xX][0-9A-Fa-f]+\\b",name:"constant.numeric.hex"},string_doubleQuote:{match:'"(?:\\\\.|[^"])*"?',name:"string.quoted.double"},string_singleQuote:{match:"'(?:\\\\.|[^'])*'?",name:"string.quoted.single"},todo_comment_singleLine:{match:"(\\b)(TODO)(\\b)(.*)", +name:"meta.annotation.task.todo",captures:{2:{name:"keyword.other.documentation.task"},4:{name:"comment.line"}}}}},{id:"orion.c-like",patterns:[{include:"orion.lib"},{include:"#comment_singleLine"},{include:"#comment_block"}],repository:{comment_singleLine:{match:"//.*",name:"comment.line.double-slash",patterns:[{include:"orion.lib#todo_comment_singleLine"}]},comment_block:{begin:"/\\*",end:"\\*/",name:"comment.block",patterns:[{match:"(\\b)(TODO)(\\b)(((?!\\*/).)*)",name:"meta.annotation.task.todo", +captures:{2:{name:"keyword.other.documentation.task"},4:{name:"comment.block"}}}]}}}],keywords:[]}}); +define("orion/editor/stylers/text_css/syntax",["orion/editor/stylers/lib/syntax"],function(k){var m="alignment-adjust,alignment-baseline,animation-delay,animation-direction,animation-duration,animation-iteration-count,animation-name,animation-play-state,animation-timing-function,animation,appearance,azimuth,backface-visibility,background-attachment,background-clip,background-color,background-image,background-origin,background-position,background-repeat,background-size,background,baseline-shift,binding,bleed,bookmark-label,bookmark-level,bookmark-state,bookmark-target,border-bottom-color,border-bottom-left-radius,border-bottom-right-radius,border-bottom-style,border-bottom-width,border-bottom,border-collapse,border-color,border-image-outset,border-image-repeat,border-image-slice,border-image-source,border-image-width,border-image,border-left-color,border-left-style,border-left-width,border-left,border-radius,border-right-color,border-right-style,border-right-width,border-right,border-spacing,border-style,border-top-color,border-top-left-radius,border-top-right-radius,border-top-style,border-top-width,border-top,border-width,border,bottom,box-align,box-decoration-break,box-direction,box-flex-group,box-flex,box-lines,box-ordinal-group,box-orient,box-pack,box-shadow,box-sizing,break-after,break-before,break-inside,caption-side,clear,clip,color-profile,color,column-count,column-fill,column-gap,column-rule-color,column-rule-style,column-rule-width,column-rule,column-span,column-width,columns,content,counter-increment,counter-reset,crop,cue-after,cue-before,cue,cursor,direction,display,dominant-baseline,drop-initial-after-adjust,drop-initial-after-align,drop-initial-before-adjust,drop-initial-before-align,drop-initial-size,drop-initial-value,elevation,empty-cells,fit-position,fit,flex-align,flex-flow,flex-inline-pack,flex-order,flex-pack,float-offset,float,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,font,grid-columns,grid-rows,hanging-punctuation,height,hyphenate-after,hyphenate-before,hyphenate-character,hyphenate-lines,hyphenate-resource,hyphens,icon,image-orientation,image-rendering,image-resolution,inline-box-align,left,letter-spacing,line-height,line-stacking-ruby,line-stacking-shift,line-stacking-strategy,line-stacking,list-style-image,list-style-position,list-style-type,list-style,margin-bottom,margin-left,margin-right,margin-top,margin,mark-after,mark-before,mark,marker-offset,marks,marquee-direction,marquee-loop,marquee-play-count,marquee-speed,marquee-style,max-height,max-width,min-height,min-width,move-to,nav-down,nav-index,nav-left,nav-right,nav-up,opacity,orphans,outline-color,outline-offset,outline-style,outline-width,outline,overflow-style,overflow-x,overflow-y,overflow,padding-bottom,padding-left,padding-right,padding-top,padding,page-break-after,page-break-before,page-break-inside,page-policy,page,pause-after,pause-before,pause,perspective-origin,perspective,phonemes,pitch-range,pitch,play-during,position,presentation-level,punctuation-trim,quotes,rendering-intent,resize,rest-after,rest-before,rest,richness,right,rotation-point,rotation,ruby-align,ruby-overhang,ruby-position,ruby-span,size,speak-header,speak-numeral,speak-punctuation,speak,speech-rate,stress,string-set,table-layout,target-name,target-new,target-position,target,text-align-last,text-align,text-decoration,text-emphasis,text-height,text-indent,text-justify,text-outline,text-shadow,text-transform,text-wrap,top,transform-origin,transform-style,transform,transition-delay,transition-duration,transition-property,transition-timing-function,transition,unicode-bidi,vertical-align,visibility,voice-balance,voice-duration,voice-family,voice-pitch-range,voice-pitch,voice-rate,voice-stress,voice-volume,volume,white-space-collapse,white-space,widows,width,word-break,word-spacing,word-wrap,z-index".split(","),k= +k.grammars;k.push({id:"orion.css",contentTypes:["text/css"],patterns:[{include:"orion.lib"},{include:"orion.c-like#comment_block"},{match:"(?:-webkit-|-moz-|-ms-|\\b)(?:"+m.join("|")+")\\b",name:"keyword.control.css"},{match:"(?i)\\b-?(?:\\.\\d+|\\d+\\.?\\d*)(?:%|em|ex|ch|rem|vw|vh|vmin|vmax|in|cm|mm|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?\\b",name:"constant.numeric.value.css"},{begin:"(['\"])(?:\\\\.|[^\\\\\\1])*\\\\$",end:"^(?:$|(?:\\\\.|[^\\\\\\1])*(\\1|[^\\\\]$))",name:"string.quoted.multiline.css"}], +repository:{number_hex:{match:"#[0-9A-Fa-f]+\\b",name:"constant.numeric.hex.css"}}});return{id:k[k.length-1].id,grammars:k,keywords:m}}); +define("orion/editor/cssContentAssist",["orion/editor/templates","orion/editor/stylers/text_css/syntax"],function(k,m){function n(a){return JSON.stringify(a).replace("}","\\}")}function i(){}for(var c={type:"link",values:"visible,hidden,scroll,auto,no-display,no-content".split(",")},d={type:"link",values:"solid,dashed,dotted,double,groove,ridge,inset,outset".split(",")},f={type:"link",values:[]},g=0;g<10;g++)f.values.push(g.toString());for(var h={type:"link",values:"black,white,red,green,blue,magenta,yellow,cyan,grey,darkred,darkgreen,darkblue,darkmagenta,darkcyan,darkyellow,darkgray,lightgray".split(",")}, +b=[{prefix:"rule",description:"rule - class selector rule",template:".${class} {\n\t${cursor}\n}"},{prefix:"rule",description:"rule - id selector rule",template:"#${id} {\n\t${cursor}\n}"},{prefix:"outline",description:"outline - outline style",template:"outline: ${color:"+n(h)+"} ${style:"+n(d)+"} ${width:"+n(f)+"}px;"},{prefix:"background-image",description:"background-image - image style",template:'background-image: url("${uri}");'},{prefix:"url",description:"url - url image",template:'url("${uri}");'}, +{prefix:"rgb",description:"rgb - rgb color",template:"rgb(${red},${green},${blue});"},{prefix:"@",description:"import - import style sheet",template:'@import "${uri}";'}],a=[{prop:"display",values:{type:"link",values:"none,block,box,flex,inline,inline-block,inline-flex,inline-table,list-item,table,table-caption,table-cell,table-column,table-column-group,table-footer-group,table-header-group,table-row,table-row-group,inherit".split(",")}},{prop:"overflow",values:c},{prop:"overflow-x",values:c},{prop:"overflow-y", +values:c},{prop:"float",values:{type:"link",values:["left","right","none","inherit"]}},{prop:"position",values:{type:"link",values:["absolute","fixed","relative","static","inherit"]}},{prop:"cursor",values:{type:"link",values:"auto,crosshair,default,e-resize,help,move,n-resize,ne-resize,nw-resize,pointer,progress,s-resize,se-resize,sw-resize,text,w-resize,wait,inherit".split(",")}},{prop:"color",values:h},{prop:"border-top-color",values:h},{prop:"border-bottom-color",values:h},{prop:"border-right-color", +values:h},{prop:"border-left-color",values:h},{prop:"background-color",values:h},{prop:"font-style",values:{type:"link",values:["italic","normal","oblique","inherit"]}},{prop:"font-weight",values:{type:"link",values:"bold,normal,bolder,lighter,100,200,300,400,500,600,700,800,900,inherit".split(",")}},{prop:"white-space",values:{type:"link",values:"pre,pre-line,pre-wrap,nowrap,normal,inherit".split(",")}},{prop:"word-wrap",values:{type:"link",values:["normal","break-word"]}},{prop:"visibility",values:{type:"link", +values:["hidden","visible","collapse","inherit"]}}],g=0;g<a.length;g++)c=a[g],b.push({prefix:c.prop,description:c.prop+" - "+c.prop+" style",template:c.prop+": ${value:"+n(c.values)+"};"});a="width,height,top,bottom,left,right,min-width,min-height,max-width,max-height,margin,padding,padding-left,padding-right,padding-top,padding-bottom,margin-left,margin-top,margin-bottom,margin-right".split(",");for(g=0;g<a.length;g++)c=a[g],b.push({prefix:c,description:c+" - "+c+" pixel style",template:c+": ${value}px;"}); +a=["padding","margin"];for(g=0;g<a.length;g++)c=a[g],b.push({prefix:c,description:c+" - "+c+" top right bottom left style",template:c+": ${top}px ${left}px ${bottom}px ${right}px;"}),b.push({prefix:c,description:c+" - "+c+" top right,left bottom style",template:c+": ${top}px ${right_left}px ${bottom}px;"}),b.push({prefix:c,description:c+" - "+c+" top,bottom right,left style",template:c+": ${top_bottom}px ${right_left}px"});a=["border","border-top","border-bottom","border-left","border-right"];for(g= +0;g<a.length;g++)c=a[g],b.push({prefix:c,description:c+" - "+c+" style",template:c+": ${width:"+n(f)+"}px ${style:"+n(d)+"} ${color:"+n(h)+"};"});i.prototype=new k.TemplateContentAssist(m.keywords,b);i.prototype.getPrefix=function(a,b){for(var c=b;c&&/[A-Za-z\-\@]/.test(a.charAt(c-1));)c--;return c?a.substring(c,b):""};return{CssContentAssistProvider:i}}); +define("orion/editor/htmlContentAssist",["orion/editor/templates"],function(k){function m(){}var n=new k.Template("","Simple HTML document",'<!DOCTYPE html>\n<html lang="en">\n\t<head>\n\t\t<meta charset=utf-8>\n\t\t<title>${title}</title>\n\t</head>\n\t<body>\n\t\t<h1>${header}</h1>\n\t\t<p>\n\t\t\t${cursor}\n\t\t</p>\n\t</body>\n</html>'),i=[{prefix:"<img",name:"<img>",description:" - HTML image element",template:'<img src="${cursor}" alt="${Image}"/>'},{prefix:"<a",name:"<a>",description:" - HTML anchor element", +template:'<a href="${cursor}"></a>'},{prefix:"<ul",name:"<ul>",description:" - HTML unordered list",template:"<ul>\n\t<li>${cursor}</li>\n</ul>"},{prefix:"<ol",name:"<ol>",description:" - HTML ordered list",template:"<ol>\n\t<li>${cursor}</li>\n</ol>"},{prefix:"<dl",name:"<dl>",description:" - HTML definition list",template:"<dl>\n\t<dt>${cursor}</dt>\n\t<dd></dd>\n</dl>"},{prefix:"<table",name:"<table>",description:" - basic HTML table",template:"<table>\n\t<tr>\n\t\t<td>${cursor}</td>\n\t</tr>\n</table>"}, +{prefix:"<\!--",name:"<\!-- --\>",description:" - HTML comment",template:"<\!-- ${cursor} --\>"}],c,d,f,g,h="abbr,b,button,canvas,cite,command,dd,del,dfn,dt,em,embed,font,h1,h2,h3,h4,h5,h6,i,ins,kbd,label,li,mark,meter,object,option,output,progress,q,rp,rt,samp,small,strong,sub,sup,td,time,title,tt,u,var".split(",");for(g=0;g<h.length;g++)c=h[g],f="<"+c+"></"+c+">",d="<"+c+">${cursor}</"+c+">",i.push({prefix:"<"+c,description:f,template:d});h="address,article,aside,audio,bdo,blockquote,body,caption,code,colgroup,datalist,details,div,fieldset,figure,footer,form,head,header,hgroup,iframe,legend,map,menu,nav,noframes,noscript,optgroup,p,pre,ruby,script,section,select,span,style,tbody,textarea,tfoot,th,thead,tr,video".split(","); +for(g=0;g<h.length;g++)c=h[g],f="<"+c+"></"+c+">",d="<"+c+">\n\t${cursor}\n</"+c+">",i.push({prefix:"<"+c,description:f,template:d});h="area,base,br,col,hr,input,link,meta,param,keygen,source".split(",");for(g=0;g<h.length;g++)c=h[g],d=f="<"+c+"/>",i.push({prefix:"<"+c,description:f,template:d});m.prototype=new k.TemplateContentAssist([],i);m.prototype.getPrefix=function(b,a){for(var c="",d=a;d&&/[A-Za-z0-9<!-]/.test(b.charAt(d-1));)if(d--,b.charAt(d)==="<"){c=b.substring(d,a);break}return c};m.prototype.computeProposals= +function(b,a,c){return b.length===0?[n.getProposal("",a,c)]:k.TemplateContentAssist.prototype.computeProposals.call(this,b,a,c).sort(function(a,b){var c=a.prefix||a.proposal,d=b.prefix||b.proposal;if(c){if(!d)return 1}else return-1;return c.toLowerCase().localeCompare(d.toLowerCase())})};return{HTMLContentAssistProvider:m}}); +define("orion/editor/stylers/application_javascript/syntax",["orion/editor/stylers/lib/syntax"],function(k){var m="break,case,class,catch,continue,const,debugger,default,delete,do,else,enum,export,extends,false,finally,for,function,if,implements,import,in,instanceof,interface,let,new,null,package,private,protected,public,return,static,super,switch,this,throw,true,try,typeof,undefined,var,void,while,with,yield".split(","),k=k.grammars;k.push({id:"orion.js",contentTypes:["application/javascript"],patterns:[{include:"orion.lib#doc_block"}, +{include:"orion.c-like"},{match:"\\b(?:"+m.join("|")+")\\b",name:"keyword.control.js"},{begin:"(['\"])(?:\\\\.|[^\\\\\\1])*\\\\$",end:"^(?:$|(?:\\\\.|[^\\\\\\1])*(\\1|[^\\\\]$))",name:"string.quoted.multiline.js"}]});return{id:k[k.length-1].id,grammars:k,keywords:m}}); +define("orion/editor/jsTemplateContentAssist",["orion/editor/templates","orion/editor/stylers/application_javascript/syntax"],function(k,m){function n(){}var i=[{prefix:"if",name:"if",description:" - if statement",template:"if (${condition}) {\n\t${cursor}\n}"},{prefix:"if",name:"if",description:" - if else statement",template:"if (${condition}) {\n\t${cursor}\n} else {\n\t\n}"},{prefix:"for",name:"for",description:" - iterate over array",template:"for (var ${i}=0; ${i}<${array}.length; ${i}++) {\n\t${cursor}\n}"}, +{prefix:"for",name:"for",description:" - iterate over array with local var",template:"for (var ${i}=0; ${i}<${array}.length; ${i}++) {\n\tvar ${value} = ${array}[${i}];\n\t${cursor}\n}"},{prefix:"for",name:"for..in",description:" - iterate over properties of an object",template:"for (var ${property} in ${object}) {\n\tif (${object}.hasOwnProperty(${property})) {\n\t\t${cursor}\n\t}\n}"},{prefix:"while",name:"while",description:" - while loop with condition",template:"while (${condition}) {\n\t${cursor}\n}"}, +{prefix:"do",name:"do",description:" - do while loop with condition",template:"do {\n\t${cursor}\n} while (${condition});"},{prefix:"switch",name:"switch",description:" - switch case statement",template:"switch (${expression}) {\n\tcase ${value1}:\n\t\t${cursor}\n\t\tbreak;\n\tdefault:\n}"},{prefix:"case",name:"case",description:" - case statement",template:"case ${value}:\n\t${cursor}\n\tbreak;"},{prefix:"try",name:"try",description:" - try..catch statement",template:"try {\n\t${cursor}\n} catch (${err}) {\n}"}, +{prefix:"try",name:"try",description:" - try..catch statement with finally block",template:"try {\n\t${cursor}\n} catch (${err}) {\n} finally {\n}"},{prefix:"typeof",name:"typeof",description:" - typeof statement",template:'typeof ${object} === "${type:'+JSON.stringify({type:"link",values:"undefined,object,boolean,number,string,function,xml".split(",")}).replace("}","\\}")+'}"'},{prefix:"instanceof",name:"instanceof",description:" - instanceof statement",template:"${object} instanceof ${type}"},{prefix:"with", +name:"with",description:" - with statement",template:"with (${object}) {\n\t${cursor}\n}"},{prefix:"function",name:"function",description:" - function declaration",template:"/**\n * @name ${name}\n * @param ${parameter}\n */\nfunction ${name} (${parameter}) {\n\t${cursor}\n}"},{prefix:"function",name:"function",description:" - function expression",template:"/**\n * @name ${name}\n * @function\n * @param ${parameter}\n */\n${name}: function(${parameter}) {\n\t${cursor}\n}"},{prefix:"define",name:"define", +description:" - define function call",template:"/* global define */\ndefine('${name}',[\n'${import}'\n], function(${importname}) {\n\t${cursor}\n});"},{prefix:"nls",name:"nls",description:" - non NLS string",template:"${cursor} //$NON-NLS-${0}$"},{prefix:"log",name:"log",description:" - console log",template:"console.log(${object});"},{prefix:"mongodb",name:"mongodb",description:" - Node.js require statement for MongoDB",template:"var ${name} = require('mongodb');\n"},{prefix:"mongodb",name:"mongodb client", +description:" - create a new MongoDB client",template:"var MongoClient = require('mongodb').MongoClient;\nvar Server = require('mongodb').Server;\n${cursor}"},{prefix:"mongodb",name:"mongodb open",description:" - create a new MongoDB client and open a connection",template:"var MongoClient = require('mongodb').MongoClient;\nvar Server = require('mongodb').Server;\nvar ${client} = new MongoClient(new Server(${host}, ${port}));\ntry {\n\t${client}.open(function(error, ${client}) {\n\t\tvar ${db} = ${client}.db(${name});\n\t\t${cursor}\n\t});\n} finally {\n\t${client}.close();\n};"}, +{prefix:"mongodb",name:"mongodb connect",description:" - connect to an existing MongoDB database",template:"var MongoClient = require('mongodb').MongoClient;\nMongoClient.connect(${url}, function(error, db) {\n\t${cursor}\n});\n"},{prefix:"mongodb",name:"mongodb connect (Cloud Foundry)",description:" - connect to an existing MongoDB database using Cloud Foundry",template:"if (${process}.env.VCAP_SERVICES) {\n\tvar env = JSON.parse(${process}.env.VCAP_SERVICES);\n\tvar mongo = env['${mongo-version}'][0].credentials;\n} else {\n\tvar mongo = {\n\t\tusername : 'username',\n\t\tpassword : 'password',\n\t\turl : 'mongodb://username:password@localhost:27017/database'\n\t};\n}\nvar MongoClient = require('mongodb').MongoClient;\nMongoClient.connect(mongo.url, function(error, db) {\n\t${cursor}\n});\n"}, +{prefix:"mongodb",name:"mongodb collection",description:" - create a MongoDB database collection",template:"${db}.collection(${id}, function(${error}, collection) {\n\t${cursor}\n});"},{prefix:"mongodb",name:"mongodb strict collection",description:" - create a MongoDB database strict collection",template:"${db}.collection(${id}, {strict:true}, function(${error}, collection) {\n\t${cursor}\n});"},{prefix:"redis",name:"redis",description:" - Node.js require statement for Redis",template:"var ${name} = require('redis');\n"}, +{prefix:"redis",name:"redis client",description:" - create a new Redis client",template:"var ${name} = require('redis');\nvar ${client} = ${name}.createClient(${port}, ${host}, ${options});\n"},{prefix:"redis",name:"redis connect",description:" - create a new Redis client and connect",template:"var ${name} = require('redis');\nvar ${client} = ${name}.createClient(${port}, ${host}, ${options});\ntry {\n\t${cursor}\n} finally {\n\t${client}.close();\n}\n"},{prefix:"redis",name:"redis set",description:" - create a new Redis client set call", +template:"client.set(${key}, ${value});\n"},{prefix:"redis",name:"redis get",description:" - create a new Redis client get call",template:"client.get(${key}, function(${error}, ${reply}) {\n\t${cursor}\n});\n"},{prefix:"redis",name:"redis on",description:" - create a new Redis client event handler",template:"client.on(${event}, function(${arg}) {\n\t${cursor}});\n"},{prefix:"pg",name:"postgres",description:" - Node.js require statement for Postgres DB",template:"var pg = require('pg');\n"},{prefix:"pg", +name:"postgres client",description:" - create a new Postgres DB client",template:"var pg = require('pg');\nvar url = \"postgres://postgres:${port}@${host}/${database}\";\nvar ${client} = new pg.Client(url);\n"},{prefix:"pg",name:"postgres connect",description:" - create a new Postgres DB client and connect",template:"var pg = require('pg');\nvar url = \"postgres://postgres:${port}@${host}/${database}\";\nvar ${client} = new pg.Client(url);\n${client}.connect(function(error) {\n\t${cursor}\n});\n"}, +{prefix:"pg",name:"postgres query",description:" - create a new Postgres DB query statement",template:"${client}.query(${sql}, function(error, result) {\n\t${cursor}\n});\n"},{prefix:"mysql",name:"mysql",description:" - Node.js require statement for MySQL DB",template:"var mysql = require('mysql');\n"},{prefix:"mysql",name:"mysql connection",description:" - create a new MySQL DB connection",template:"var mysql = require('mysql');\nvar ${connection} = mysql.createConnection({\n\thost : ${host},\n\tuser : ${username},\n\tpassword : ${password}\n});\ntry {\n\t${connection}.connect();\n\t${cursor}\n} finally {\n\t${connection}.end();\n}"}, +{prefix:"mysql",name:"mysql query",description:" - create a new MySQL DB query statement",template:"${connection}.query(${sql}, function(error, rows, fields) {\n\t${cursor}\n});\n"},{prefix:"express",name:"express",description:" - Node.js require statement for Express",template:"var ${name} = require('express');"},{prefix:"express",name:"express app",description:" - create a new Express app",template:"var express = require('express');\nvar ${app} = express();\n${cursor}\napp.listen(${timeout});\n"}, +{prefix:"express",name:"express configure",description:" - create an Express app configure statement",template:"app.configure(function() {\n\tapp.set(${id}, ${value});\n});"},{prefix:"express",name:"express specific configure",description:" - create a specific Express app configure statement",template:"app.configure(${name}, function() {\n\tapp.set(${id}, ${value});\n});"},{prefix:"express",name:"express app get",description:" - create a new Express app.get call",template:"var value = app.get(${id}, function(request, result){\n\t${cursor}\n});\n"}, +{prefix:"express",name:"express app set",description:" - create a new Express app set call",template:"app.set(${id}, ${value});\n"},{prefix:"express",name:"express app use",description:" - create a new Express app use statement",template:"app.use(${fnOrObject});\n"},{prefix:"express",name:"express app engine",description:" - create a new Express app engine statement",template:"app.engine(${fnOrObject});\n"},{prefix:"express",name:"express app param",description:" - create a new Express app param statement", +template:"app.param(${id}, ${value});\n"},{prefix:"express",name:"express app error use",description:" - create a new Express app error handling use statement",template:"app.use(function(error, request, result, next) {\n\tresult.send(${code}, ${message});\n});\n"},{prefix:"amqp",name:"amqp",description:" - Node.js require statement for AMQP framework",template:"var amqp = require('amqp');\n"},{prefix:"amqp",name:"amqp connection",description:" - create a new AMQP connection ",template:"var amqp = require('amqp');\nvar ${connection} = amqp.createConnection({\n\thost: ${host},\n\tport: ${port},\n\tlogin: ${login},\n\tpassword: ${password}\n});\n"}, +{prefix:"amqp",name:"amqp on",description:" - create a new AMQP connection on statement",template:"${connection}.on(${event}, function() {\n\t${cursor}\n});\n"},{prefix:"amqp",name:"amqp queue",description:" - create a new AMQP connection queue statement",template:"${connection}.queue(${id}, function(queue) {\n\tqueue.bind('#'); //catch all messages\n\tqueue.subscribe(function (message, headers, deliveryInfo) {\n\t\t// Receive messages\n\t});\n\t${cursor}\n});\n"},{prefix:"amqp",name:"amqp exchange", +description:" - create a new AMQP connection exchange",template:"var exchange = ${connection}.exchange(${id}, {type: 'topic'}, function(exchange) {\n\t${cursor}\n});\n"}];n.prototype=new k.TemplateContentAssist(m.keywords,i);n.prototype.isValid=function(c,d,f){c=d.charAt(f-c.length-1);return!c||":!@#$^&*.?<>".indexOf(c)===-1};return{JSTemplateContentAssistProvider:n}}); +define("orion/editor/AsyncStyler",["i18n!orion/editor/nls/messages","orion/editor/annotations"],function(k,m){function n(d){return d.getProperty("objectClass").indexOf(c)!==-1&&d.getProperty("type")==="highlighter"}function i(c,d,h){this.initialize(c,d,h);this.lineStyles=[]}var c="orion.edit.highlighter",d=c+" service must be an event emitter";m.AnnotationType.registerType("orion.annotation.highlightError",{title:k.syntaxError,html:"<div class='annotationHTML error'></div>",rangeStyle:{styleClass:"annotationRange error"}}); +i.prototype={initialize:function(d,g,h){this.textView=d;this.serviceRegistry=g;this.annotationModel=h;this.services=[];var b=this;this.listener={onModelChanging:function(a){b.onModelChanging(a)},onModelChanged:function(a){b.onModelChanged(a)},onDestroy:function(a){b.onDestroy(a)},onLineStyle:function(a){b.onLineStyle(a)},onStyleReady:function(a){b.onStyleReady(a)},onServiceAdded:function(a){b.onServiceAdded(a.serviceReference,b.serviceRegistry.getService(a.serviceReference))},onServiceRemoved:function(a){b.onServiceRemoved(a.serviceReference, +b.serviceRegistry.getService(a.serviceReference))}};d.addEventListener("ModelChanging",this.listener.onModelChanging);d.addEventListener("ModelChanged",this.listener.onModelChanged);d.addEventListener("Destroy",this.listener.onDestroy);d.addEventListener("LineStyle",this.listener.onLineStyle);g.addEventListener("registered",this.listener.onServiceAdded);g.addEventListener("unregistering",this.listener.onServiceRemoved);d=g.getServiceReferences(c);for(h=0;h<d.length;h++){var a=d[h];n(a)&&this.addServiceListener(g.getService(a))}}, +onDestroy:function(){this.destroy()},destroy:function(){if(this.textView)this.textView.removeEventListener("ModelChanging",this.listener.onModelChanging),this.textView.removeEventListener("ModelChanged",this.listener.onModelChanged),this.textView.removeEventListener("Destroy",this.listener.onDestroy),this.textView.removeEventListener("LineStyle",this.listener.onLineStyle),this.textView=null;if(this.services){for(var c=0;c<this.services.length;c++)this.removeServiceListener(this.services[c]);this.services= +null}if(this.serviceRegistry)this.serviceRegistry.removeEventListener("registered",this.listener.onServiceAdded),this.serviceRegistry.removeEventListener("unregistering",this.listener.onServiceRemoved),this.serviceRegistry=null;this.lineStyles=this.listener=null},onModelChanging:function(c){this.startLine=this.textView.getModel().getLineAtOffset(c.start)},onModelChanged:function(c){var d=this.startLine;(c.addedLineCount||c.removedLineCount)&&Array.prototype.splice.apply(this.lineStyles,[d,c.removedLineCount].concat(this._getEmptyStyle(c.addedLineCount)))}, +onStyleReady:function(c){var d=c.lineStyles||c.style,c=Number.MAX_VALUE,h=-1,b=this.textView.getModel(),a;for(a in d)Object.prototype.hasOwnProperty.call(d,a)&&(this.lineStyles[a]=d[a],c=Math.min(c,a),h=Math.max(h,a));c=Math.max(c,0);h=Math.min(h,b.getLineCount());if(d=this.annotationModel){for(var e=d.getAnnotations(b.getLineStart(c),b.getLineEnd(h)),i=[];e.hasNext();){var k=e.next();k.type==="orion.annotation.highlightError"&&i.push(k)}e=[];for(k=c;k<=h;k++){a=k;var q=this.lineStyles[a],q=q&&q.errors; +a=b.getLineStart(a);if(q)for(var r=0;r<q.length;r++){var p=q[r];e.push(m.AnnotationType.createAnnotation("orion.annotation.highlightError",p.start+a,p.end+a))}}d.replaceAnnotations(i,e)}this.textView.redrawLines(c,h+1)},onLineStyle:function(c){function d(b,a){for(var c=b.length,f=[],g=0;g<c;g++){var h=b[g];f.push({start:h.start+a,end:h.end+a,style:h.style})}return f}var h=this.lineStyles[c.lineIndex];if(h)if(h.ranges)c.ranges=d(h.ranges,c.lineStart);else if(h.style)c.style=h.style},_getEmptyStyle:function(c){for(var d= +[],h=0;h<c;h++)d.push(null);return d},setContentType:function(c){this.contentType=c;if(this.services)for(c=0;c<this.services.length;c++){var d=this.services[c];if(d.setContentType){var h=this.serviceRegistry.getService("orion.page.progress");h?h.progress(d.setContentType(this.contentType),"Styling content type: "+this.contentType.id?this.contentType.id:this.contentType):d.setContentType(this.contentType)}}},onServiceAdded:function(c,d){n(c)&&this.addServiceListener(d)},onServiceRemoved:function(c, +d){this.services.indexOf(d)!==-1&&this.removeServiceListener(d)},addServiceListener:function(c){if(typeof c.addEventListener==="function"){if(c.addEventListener("orion.edit.highlighter.styleReady",this.listener.onStyleReady),this.services.push(c),c.setContentType&&this.contentType){var g=this.serviceRegistry.getService("orion.page.progress");g?g.progress(c.setContentType(this.contentType),"Styling content type: "+this.contentType.id?this.contentType.id:this.contentType):c.setContentType(this.contentType)}}else typeof console!== +"undefined"&&console.log(Error(d))},removeServiceListener:function(c){typeof c.removeEventListener==="function"?(c.removeEventListener("orion.edit.highlighter.styleReady",this.listener.onStyleReady),c=this.services.indexOf(c),c!==-1&&this.services.splice(c,1)):typeof console!=="undefined"&&console.log(Error(d))}};return i}); +define("orion/editor/mirror",["i18n!orion/editor/nls/messages","orion/editor/eventTarget","orion/editor/annotations"],function(k,m,n){function i(b){this.string=b;this.tokenStart=this.pos=0}function c(){return{token:function(b){return b.skipToEnd()}}}function d(){this._modes={};this.mimeModes={};this.options={};this.StringStream=i;this.defineMode("null",c);this.defineMIME("text/plain","null")}function f(b){var a=[],c;for(c in b)Object.prototype.hasOwnProperty.call(b,c)&&a.push(c);return a}function g(b, +a,c){c=c||{};this.model=b;this.codeMirror=a;this.isWhitespaceVisible=typeof c.whitespacesVisible==="undefined"?!1:c.whitespacesVisible;this.mode=null;this.isModeLoaded=!1;this.lines=[];this.dirtyLines=[];this.startLine=Number.MAX_VALUE;this.endLine=-1;this.timer=null;this.initialize(b)}function h(b,a,c){this.init(b,a,c)}i.prototype={eol:function(){return this.pos>=this.string.length},sol:function(){return this.pos===0},peek:function(){return this.string[this.pos]},next:function(){return this.string[this.pos++]}, +eat:function(b){var a=this.string[this.pos];return typeof a==="string"&&(a===b||b.test&&b.test(a)||typeof b==="function"&&b(a))?this.string[this.pos++]:void 0},eatWhile:function(b){for(var a=!1;this.eat(b)!==void 0;)a=!0;return a},eatSpace:function(){return this.eatWhile(/\s/)},skipToEnd:function(){this.pos=this.string.length},skipTo:function(b){b=this.string.indexOf(b,this.pos);return b!==-1?(this.pos=b,!0):!1},match:function(b,a,c){a=a===!0||typeof a==="undefined";if(typeof b==="string"){var d= +c?this.string.toLowerCase():this.string,b=c?b.toLowerCase():b,c=d.indexOf(b,this.pos);if(c!==-1&&a)this.pos=c+b.length;return c!==-1}else return(b=this.string.substring(this.pos).match(b))&&a&&typeof b[0]==="string"&&(this.pos+=b.index+b[0].length),b},backUp:function(b){this.pos-=b},column:function(){for(var b=0,a=0;a<this.tokenStart;)b+=this.string[a++]==="\t"?4:1;return b},indentation:function(){for(var b=this.string.search(/\S/),a=0,c=0;c<b;)a+=this.string[c++]==="\t"?4:1;return a},current:function(){return this.string.substring(this.tokenStart, +this.pos)},advance:function(){this.tokenStart=this.pos}};d.prototype={options:{},setOption:function(b,a){this.options[b]=a},getOption:function(b){return this.options[b]},copyState:function(b,a){if(typeof b.copyState==="function")return b.copyState(a);var c={},d;for(d in a){var f=a[d];c[d]=f instanceof Array?f.slice():f}return c},startState:function(b,a){return b.startState(a)},defineMode:function(b,a){this._modes[b]=a},defineMIME:function(b,a){this.mimeModes[b]=a},getMode:function(b,a){var c={},d; +typeof a==="string"&&this.mimeModes[a]&&(a=this.mimeModes[a]);typeof a==="object"&&(c=a,d=this._modes[a.name]);d=d||this._modes[a];return typeof d!=="function"?(typeof console!=="undefined"&&console&&console.log("Mode not found: "+a),this.getMode(b,"null")):d(b,c)},listModes:function(){return f(this._modes)},listMIMEs:function(){return f(this.mimeModes)},_getModeName:function(b){b=this.mimeModes[b];if(typeof b==="object")b=b.name;return b}};g.prototype={initialize:function(){var b=this;this.listener= +{onModelChanging:function(a){b._onModelChanging(a)},onModelChanged:function(a){b._onModelChanged(a)},onDestroy:function(a){b._onDestroy(a)}};this.model.addEventListener("Changing",this.listener.onModelChanging);this.model.addEventListener("Changed",this.listener.onModelChanged);this.model.addEventListener("Destroy",this.listener.onDestroy)},destroy:function(){this.model&&(this.model.removeEventListener("Changing",this.listener.onModelChanging),this.model.removeEventListener("Changed",this.listener.onModelChanged), +this.model.removeEventListener("Destroy",this.listener.onDestroy));this.dirtyLines=this.lines=this.mode=this.codeMirror=this.model=null;clearTimeout(this.timer);this.timer=null},_onModelChanging:function(b){this.startLine=this.model.getLineAtOffset(b.start)},_onModelChanged:function(b){this._dbgEvent(b);var a=this.startLine;(b.removedLineCount||b.addedLineCount)&&Array.prototype.splice.apply(this.lines,[a+1,b.removedLineCount].concat(this._newLines(b.addedLineCount)));this.mode&&(b=Math.max(b.addedLineCount, +b.removedLineCount),b=a+Math.min(b,500),this.highlight(a,b),this.highlightLater(b+1))},_onDestroy:function(){this.destroy()},setViewportIndex:function(b){this.viewportIndex=b},_dbgEvent:function(){},_dbgStyle:function(){},_newLines:function(b){for(var a=[],c=0;c<b;c++)a.push({style:null,eolState:null});return a},setMode:function(b,a){if(b)this.mode=this.codeMirror.getMode(this.codeMirror.options,b),this.lines=this._newLines(this.model.getLineCount()),a&&this.highlight()},highlight:function(b,a,c){if(this.mode){for(var d= +this.model.getLineCount(),b=typeof b==="undefined"?0:b,a=typeof a==="undefined"?d-1:Math.min(a,d-1),d=this.mode,f=this.getState(b),g=b;g<=a;g++){var h=this.lines[g];this.highlightLine(g,h,f);h.eolState=this.codeMirror.copyState(d,f)}this._expandRange(b,a);if(!c)this.onHighlightDone()}},highlightLater:function(b){this.dirtyLines.push(b);var a=this;this.timer=setTimeout(function(){a._highlightJob()},50)},_highlightJob:function(){for(var b=+new Date+30,a=this.mode.compareStates,c=this.model.getLineCount();this.dirtyLines.length;){var d= +this.viewportIndex,f=this.lines[d],d=f&&!f.eolState?d:this.dirtyLines.pop();if(d>=c)break;this._expandRange(d,d);for(var f=this._getResumeLineIndex(d),d=f+1,f=(f=f>=0&&this.lines[f].eolState)?this.codeMirror.copyState(this.mode,f):this.mode.startState(),g=0,h=d;h<c;h++){var i=this.lines[h],k=i.eolState,m=this.highlightLine(h,i,f);i.eolState=this.codeMirror.copyState(this.mode,f);m&&this._expandRange(d,h+1);var i=a&&k&&a(k,i.eolState),s=!a&&!m&&g++>3;if(i||s)break;else if(!k||m)g=0;k=h<c||this.dirtyLines.length; +if(+new Date>b&&k){this.highlightLater(h+1);this.onHighlightDone();return}}}this.onHighlightDone()},onHighlightDone:function(){this.startLine!==Number.MAX_VALUE&&this.endLine!==-1&&this.dispatchEvent({type:"Highlight",start:this.startLine,end:this.endLine});this.startLine=Number.MAX_VALUE;this.endLine=-1},_getResumeLineIndex:function(b){for(var a=this.lines,c=b-1;c>=0;c--)if(a[c].eolState||b-c>40)return c;return-1},getState:function(b){var a=this.mode,c=this.lines,d,f;for(d=b-1;d>=0;d--)if(f=c[d], +f.eolState||b-d>40)break;var g=d>=0&&c[d].eolState;if(g){g=this.codeMirror.copyState(a,g);for(d=Math.max(0,d);d<b-1;d++)f=c[d],this.highlightLine(d,f,g),f.eolState=this.codeMirror.copyState(a,g);return g}else return a.startState()},highlightLine:function(b,a,c){if(this.mode){var d=this.model;d.getLineStart(b)===d.getLineEnd(b)&&this.mode.blankLine&&this.mode.blankLine(c);for(var f=a.style||[],b=d.getLine(b),b=new i(b),d=!a.style,g=[],h=0;!b.eol();h++){var k=this.mode.token(b,c)||null,m=b.current(); +this._whitespaceStyle(k,m,b.tokenStart);k=[b.tokenStart,b.pos,k];m=f[h];g.push(k);d=d||!m||m[0]!==k[0]||m[1]!==k[1]||m[2]!==k[2];b.advance()}if(d=d||g.length!==f.length)a.style=g.length?g:null;return d}},_whitespaceStyle:function(b,a,c){if(!b&&this.isWhitespaceVisible&&/\s+/.test(a)){for(var b=[],d,f,g=0;g<a.length;g++){var h=a[g];h!==f&&(f&&b.push([c+d,c+g,f==="\t"?"punctuation separator tab":"punctuation separator space"]),d=g,f=h)}b.push([c+d,c+g,f==="\t"?"punctuation separator tab":"punctuation separator space"]); +return b}return null},_expandRange:function(b,a){this.startLine=Math.min(this.startLine,b);this.endLine=Math.max(this.endLine,a)},toStyleRangesAndErrors:function(b,a){var c=b.style;if(!c)return null;for(var d=[],f=[],g=typeof a==="undefined"?0:this.model.getLineStart(a),h=0;h<c.length;h++){var i=c[h],k=!i[2]?null:i[2]==="punctuation separator tab"||i[2]==="punctuation separator space"?i[2]:"cm-"+i[2];k&&(i={start:g+i[0],end:g+i[1],style:{styleClass:k}},d.push(i),k==="cm-error"&&f.push(i))}return[d, +f]},getLineStyle:function(b){return this.lines[b]},getLineStyles:function(){return this.lines}};m.EventTarget.addMixin(g.prototype);n.AnnotationType.registerType("orion.annotation.highlightError",{title:k.syntaxError,html:"<div class='annotationHTML error'></div>",rangeStyle:{styleClass:"annotationRange error"}});h.prototype={init:function(b,a,c){this.textView=b;this.annotationModel=c;this.modeApplier=new g(b.getModel(),a);var d=this;this.listener={onLineStyle:function(a){d.onLineStyle(a)},onDestroy:function(a){d.onDestroy(a)}, +onHighlight:function(a){d.onHighlight(a)}};b.addEventListener("LineStyle",this.listener.onLineStyle);b.addEventListener("Destroy",this.listener.onDestroy);this.modeApplier.addEventListener("Highlight",this.listener.onHighlight)},destroy:function(){this.modeApplier&&(this.modeApplier.removeEventListener("Highlight",this.listener.onHighlight),this.modeApplier.destroy());this.textView&&(this.textView.removeEventListener("LineStyle",this.listener.onLineStyle),this.textView.removeEventListener("Destroy", +this.listener.onDestroy));this.listener=this.modeApplier=this.annotationModel=this.textView=null},setMode:function(b){this.modeApplier.setMode(b)},onLineStyle:function(b){var a=b.lineIndex,c=this.modeApplier,d=c.getLineStyle(a);if(!d||!d.eolState){var f=this.textView.getModel().getLineCount();c.highlight(a,Math.min(a+20,f-1),!0);d=c.getLineStyle(a)}f=this.textView.getModel();if(d){var g=c.toStyleRangesAndErrors(d,a);if(g&&(b.ranges=g[0],b=this.annotationModel)){c=[];d=[];if(g=g[1])for(var h=0;h<g.length;h++){var i= +g[h];i.style.styleClass==="cm-error"&&d.push(n.AnnotationType.createAnnotation("orion.annotation.highlightError",i.start,i.end))}for(a=b.getAnnotations(f.getLineStart(a),f.getLineEnd(a));a.hasNext();)f=a.next(),f.type==="orion.annotation.highlightError"&&c.push(f);b.replaceAnnotations(c,d)}}},onHighlight:function(b){this.textView.redrawLines(b.start,b.end)},onDestroy:function(){this.destroy()}};return{Mirror:d,ModeApplier:g,CodeMirrorStyler:h}}); +define("orion/editor/textMateStyler",["orion/regex"],function(k){function m(c){var d;if(c instanceof Array){d=Array(c.length);for(var f=0;f<c.length;f++)d[f]=m(c[f])}else for(f in d={},c)if(Object.prototype.hasOwnProperty.call(c,f)){var g=c[f];d[f]=typeof g==="object"&&g!==null?m(g):g}return d}function n(c,d,f){this.initialize(c);this.grammar=m(d);this.externalGrammars=f?m(f):[];this._styles={};this._tree=null;this._allGrammars={};this.preprocess(this.grammar)}var i={unsupported:[{regex:/\(\?[ims\-]:/, +func:function(){return"option on/off for subexp"}},{regex:/\(\?<([=!])/,func:function(c){return c[1]==="="?"lookbehind":"negative lookbehind"}},{regex:/\(\?>/,func:function(){return"atomic group"}}],toRegExp:function(c){function d(b,a){throw Error('Unsupported regex feature "'+b+'": "'+a[0]+'" at index: '+a.index+" in "+a.input);}var f="",g,c=i.processGlobalFlag("x",c,function(b){for(var a="",c=!1,d=b.length,f=0;f<d;){var g=b.charAt(f);if(!c&&g==="#")for(;f<d&&g!=="\r"&&g!=="\n";)g=b.charAt(++f); +else if(!c&&/\s/.test(g))for(;f<d&&/\s/.test(g);)g=b.charAt(++f);else g==="\\"?(a+=g,/\s/.test(b.charAt(f+1))||(a+=b.charAt(f+1),f+=1)):(g==="["?c=!0:g==="]"&&(c=!1),a+=g),f+=1}return a}),c=i.processGlobalFlag("i",c,function(b){f+="i";return b});for(g=0;g<this.unsupported.length;g++){var h;(h=this.unsupported[g].regex.exec(c))&&d(this.unsupported[g].func(h),h)}return RegExp(c,f)},processGlobalFlag:function(c,d,f){function g(b,a){for(var c=0,d=b.length,f=-1,g=a;g<d&&f===-1;g++)switch(b.charAt(g)){case "\\":g++; +break;case "(":c++;break;case ")":c--,c===0&&(f=g)}return f}var h="(?"+c+")",c="(?"+c+":";if(d.substring(0,h.length)===h)return f(d.substring(h.length));else if(d.substring(0,c.length)===c){h=g(d,0);if(h<d.length-1)throw Error("Only a "+c+") group that encloses the entire regex is supported in: "+d);return f(d.substring(c.length,h))}return d},hasBackReference:function(c){return/\\\d+/.test(c.source)},getSubstitutedRegex:function(c,d,f){for(var f=typeof f==="undefined"?!0:!1,c=c.source.split(/(\\\d+)/g), +g=[],h=0;h<c.length;h++){var b=c[h],a=/\\(\d+)/.exec(b);a?(b=d[a[1]]||"",g.push(f?k.escape(b):b)):g.push(b)}return RegExp(g.join(""))},groupify:function(c,d){for(var f=c.source,g=f.length,h=[],b=0,a=[],e=1,i=1,k=[],m={},r={},p=0;p<g;p++){var n=h[h.length-1],v=f.charAt(p);switch(v){case "(":if(n===4)h.pop(),k.push(")"),a[a.length-1].end=p;var s=p+2<g?f.charAt(p+1)+""+f.charAt(p+2):null;if(s==="?:"||s==="?="||s==="?!"){var u;s==="?:"?u=1:(u=3,b++);h.push(u);a.push({start:p,end:-1,type:u});k.push(v); +k.push(s);p+=s.length}else h.push(2),a.push({start:p,end:-1,type:2,oldNum:e,num:i}),k.push(v),b===0&&(r[i]=null),m[e]=i,e++,i++;break;case ")":n=h.pop();n===3&&b--;a[a.length-1].end=p;k.push(v);break;case "*":case "+":case "?":case "}":var j=v,w=f.charAt(p-1),s=p-1;if(v==="}"){for(u=p-1;f.charAt(u)!=="{"&&u>=0;u--);w=f.charAt(u-1);s=u-1;j=f.substring(u,p+1)}u=a[a.length-1];if(w===")"&&(u.type===2||u.type===4)){k.splice(u.start,0,"(");k.push(j);k.push(")");v={start:u.start,end:k.length-1,type:4,num:u.num}; +for(w=0;w<a.length;w++)if(n=a[w],(n.type===2||n.type===4)&&n.start>=u.start&&n.end<=s)if(n.start+=1,n.end+=1,n.num+=1,n.type===2)m[n.oldNum]=n.num;a.push(v);i++;break}default:v!=="|"&&n!==2&&n!==4&&b===0&&(h.push(4),a.push({start:p,end:-1,type:4,num:i}),k.push("("),r[i]=null,i++),k.push(v),v==="\\"&&(v=f.charAt(p+1),k.push(v),p+=1)}}for(;h.length;)h.pop(),k.push(")");var f=RegExp(k.join("")),g={},d=d||m,x;for(x in d)d.hasOwnProperty(x)&&(g[x]="\\"+d[x]);f=this.getSubstitutedRegex(f,g,!1);return[f, +m,r]},complexCaptures:function(c){if(!c)return!1;for(var d in c)if(c.hasOwnProperty(d)&&d!=="0")return!0;return!1}};n.prototype={initialize:function(c){this.textView=c;this.textView.stylerOptions=this;var d=this;this._listener={onModelChanged:function(c){d.onModelChanged(c)},onDestroy:function(c){d.onDestroy(c)},onLineStyle:function(c){d.onLineStyle(c)},onStorage:function(c){d.onStorage(c)}};c.addEventListener("ModelChanged",this._listener.onModelChanged);c.addEventListener("Destroy",this._listener.onDestroy); +c.addEventListener("LineStyle",this._listener.onLineStyle);c.redrawLines()},onDestroy:function(){this.destroy()},destroy:function(){if(this.textView)this.textView.removeEventListener("ModelChanged",this._listener.onModelChanged),this.textView.removeEventListener("Destroy",this._listener.onDestroy),this.textView.removeEventListener("LineStyle",this._listener.onLineStyle),this.textView=null;this._listener=this._tree=this._styles=this.grammar=null},preprocess:function(c){for(c=[c];c.length!==0;){var d= +c.pop();if(!d._resolvedRule||!d._typedRule)if(d._resolvedRule=this._resolve(d),d._typedRule=this._createTypedRule(d),this.addStyles(d.name),this.addStyles(d.contentName),this.addStylesForCaptures(d.captures),this.addStylesForCaptures(d.beginCaptures),this.addStylesForCaptures(d.endCaptures),d._resolvedRule!==d&&c.push(d._resolvedRule),d.patterns)for(var f=0;f<d.patterns.length;f++)c.push(d.patterns[f])}},addStyles:function(c){if(c&&!this._styles[c]){this._styles[c]=[];for(var d=c.split("."),f=0;f< +d.length;f++)this._styles[c].push(d.slice(0,f+1).join("-"))}},addStylesForCaptures:function(c){for(var d in c)c.hasOwnProperty(d)&&this.addStyles(c[d].name)},ContainerRule:function(){function c(c){this.rule=c;this.subrules=c.patterns}c.prototype.valueOf=function(){return"aa"};return c}(),BeginEndRule:function(){function c(c){this.rule=c;this.beginRegex=i.toRegExp(c.begin);this.endRegex=i.toRegExp(c.end);this.subrules=c.patterns||[];this.endRegexHasBackRef=i.hasBackReference(this.endRegex);var f=i.complexCaptures(c.captures), +c=i.complexCaptures(c.beginCaptures)||i.complexCaptures(c.endCaptures);if(this.isComplex=f||c)f=i.groupify(this.beginRegex),this.beginRegex=f[0],this.beginOld2New=f[1],this.beginConsuming=f[2],f=i.groupify(this.endRegex,this.beginOld2New),this.endRegex=f[0],this.endOld2New=f[1],this.endConsuming=f[2]}c.prototype.valueOf=function(){return this.beginRegex};return c}(),MatchRule:function(){function c(c){this.rule=c;this.matchRegex=i.toRegExp(c.match);if(this.isComplex=i.complexCaptures(c.captures))c= +i.groupify(this.matchRegex),this.matchRegex=c[0],this.matchOld2New=c[1],this.matchConsuming=c[2]}c.prototype.valueOf=function(){return this.matchRegex};return c}(),_createTypedRule:function(c){return c.match?new this.MatchRule(c):c.begin?new this.BeginEndRule(c):new this.ContainerRule(c)},_resolve:function(c){var d=c;if(c.include){if(c.begin||c.end||c.match)throw Error('Unexpected regex pattern in "include" rule '+c.include);c=c.include;if(c.charAt(0)==="#"){if(d=this.grammar.repository&&this.grammar.repository[c.substring(1)], +!d)throw Error("Couldn't find included rule "+c+" in grammar repository");}else if(c==="$self")d=this.grammar;else if(c==="$base")throw Error('Include "$base" is not supported');else if(d=this._allGrammars[c],!d)for(var f=0;f<this.externalGrammars.length;f++){var g=this.externalGrammars[f];if(g.scopeName===c){this.preprocess(g);d=this._allGrammars[c]=g;break}}}return d},ContainerNode:function(){function c(c,f){this.parent=c;this.rule=f;this.children=[];this.end=this.start=null}c.prototype.addChild= +function(c){this.children.push(c)};c.prototype.valueOf=function(){var c=this.rule;return"ContainerNode { "+(c.include||"")+" "+(c.name||"")+(c.comment||"")+"}"};return c}(),BeginEndNode:function(){function c(c,f,g){this.parent=c;this.rule=f;this.children=[];this.setStart(g);this.endMatch=this.end=null;this.endRegexSubstituted=f.endRegexHasBackRef?i.getSubstitutedRegex(f.endRegex,g):null}c.prototype.addChild=function(c){this.children.push(c)};c.prototype.getIndexInParent=function(){return this.parent? +this.parent.children.indexOf(this):-1};c.prototype.setStart=function(c){this.start=c.index;this.beginMatch=c};c.prototype.setEnd=function(c){c&&typeof c==="object"?(this.endMatch=c,this.end=c.index+c[0].length):(this.endMatch=null,this.end=c)};c.prototype.shiftStart=function(c){this.start+=c;this.beginMatch.index+=c};c.prototype.shiftEnd=function(c){this.end+=c;this.endMatch&&(this.endMatch.index+=c)};c.prototype.valueOf=function(){return"{"+this.rule.beginRegex+" range="+this.start+".."+this.end+ +"}"};return c}(),push:function(c,d){if(d)for(var f=d.length;f>0;)c.push(d[--f])},exec:function(c,d,f){(d=c.exec(d))&&(d.index+=f);c.lastIndex=0;return d},afterMatch:function(c){return c.index+c[0].length},getEndMatch:function(c,d,f){if(c instanceof this.BeginEndNode){var g=c.rule,c=c.endRegexSubstituted||g.endRegex;return!c?null:this.exec(c,d,f)}return null},initialParse:function(){this.textView.getModel().getCharCount();this._tree=new this.ContainerNode(null,this.grammar._typedRule);this.parse(this._tree, +!1,0)},onModelChanged:function(c){var d=c.addedCharCount,f=c.removedCharCount,c=c.start;if(this._tree){var g=this.textView.getModel(),h=g.getCharCount(),g=g.getLineEnd(g.getLineAtOffset(c)-1),b=this.getFirstDamaged(g,g),g=g===-1?0:g,d=b?this.parse(b,!0,g,c,d,f):h;this.textView.redrawRange(g,d)}else this.initialParse()},getFirstDamaged:function(c,d){if(c<0)return this._tree;for(var f=[this._tree],g=null;f.length;){var h=f.pop();if(!h.parent||this.isDamaged(h,c,d)){h instanceof this.BeginEndNode&&(g= +h);for(var b=0;b<h.children.length;b++)f.push(h.children[b])}}return g||this._tree},isDamaged:function(c,d,f){return c.start<=f&&c.end>d},parse:function(c,d,f,g,h,b){var a=this.textView.getModel(),e=a.getLineStart(a.getLineCount()-1),i=a.getCharCount(),k=this.getInitialExpected(c,f),m=-1;if(d)c.repaired=!0,c.endNeedsUpdate=!0,m=(m=c.children[c.children.length-1])?a.getLineEnd(a.getLineAtOffset(m.end+(h-b))):-1,g=a.getLineEnd(a.getLineAtOffset(g+b)),m=Math.max(m,g);for(var m=m===-1?i:m,g=k,n=c,p=!1, +t=f,v=-1;n&&(!d||t<m);){var s=this.getNextMatch(a,n,t);s||(t=t>=e?i:a.getLineStart(a.getLineAtOffset(t)+1));var u=s&&s.match,j=s&&s.rule,w=s&&s.isEnd;if(s&&s.isSub){if(t=this.afterMatch(u),j instanceof this.BeginEndRule)p=!0,d&&j===g.rule&&n===g.parent?(n=g,n.setStart(u),n.repaired=!0,n.endNeedsUpdate=!0,g=this.getNextExpected(g,"begin")):(d&&(this.prune(n,g),d=!1),u=new this.BeginEndNode(n,j,u),n.addChild(u),n=u)}else if(w||t===i){if(n instanceof this.BeginEndNode)u?(p=!0,v=Math.max(v,n.end),n.setEnd(u), +t=this.afterMatch(u),d&&n===g&&n.parent===g.parent?(n.repaired=!0,delete n.endNeedsUpdate,g=this.getNextExpected(g,"end")):d&&(this.prune(n,g),d=!1)):(n.setEnd(i),delete n.endNeedsUpdate);n=n.parent}d&&t>=m&&!p&&(this.prune(c,k),d=!1)}this.removeUnrepairedChildren(c,d,f);this.cleanup(d,c,f,m,i,h,b);return d?Math.max(v,t):t},removeUnrepairedChildren:function(c,d,f){if(d){for(var d=c.children,g=-1,h=0;h<d.length;h++){var b=d[h];if(!b.repaired&&this.isDamaged(b,f,Number.MAX_VALUE)){g=h;break}}if(g!== +-1)c.children.length=g}},cleanup:function(c,d,f,g,h,b,a){if(c){c=b-a;h=this.getIntersecting(g-c+1,h);d=this.getIntersecting(f,g);for(f=0;f<h.length;f++)g=h[f],!g.repaired&&g instanceof this.BeginEndNode&&(g.shiftEnd(c),g.shiftStart(c));for(f=0;f<d.length;f++)g=d[f],g.repaired&&g.endNeedsUpdate&&g.shiftEnd(c),delete g.endNeedsUpdate,delete g.repaired}else{d=this.getIntersecting(f,g);for(f=0;f<d.length;f++)delete d[f].repaired}},getNextMatch:function(c,d,f,g){var h=c.getLineAtOffset(f),h=c.getLineEnd(h), +b=c.getText(f,h),a=[],e=[],c=[],h=[];for(this.push(a,d.rule.subrules);a.length;){var i=a.length?a.pop():null,i=i&&i._resolvedRule._typedRule;if(i instanceof this.ContainerRule&&e.indexOf(i)===-1)e.push(i),this.push(a,i.subrules);else if(!i||!g||i.matchRegex){var k=i&&this.exec(i.matchRegex||i.beginRegex,b,f);k&&(c.push(k),h.push(i))}}a=Number.MAX_VALUE;e=-1;for(i=0;i<c.length;i++)if(k=c[i],k.index<a)a=k.index,e=i;if(!g&&(f=this.getEndMatch(d,b,f)))if(g=d.rule.applyEndPatternLast,e===-1||f.index<a|| +!g&&f.index===a)return{isEnd:!0,rule:d.rule,match:f};return e===-1?null:{isSub:!0,rule:h[e],match:c[e]}},getInitialExpected:function(c,d){var f,g;if(c===this._tree)for(f=0;f<c.children.length;f++){if(g=c.children[f],g.start>=d)return g}else if(c instanceof this.BeginEndNode&&c.endMatch){var h=c.endMatch.index;for(f=0;f<c.children.length;f++)if(g=c.children[f],g.start>=d)break;if(g&&g.start<h)return g}return c},getNextExpected:function(c,d){if(d==="begin"){var f=c.children[0];return f?f:c}else if(d=== +"end"&&(f=c.parent)){var g=f.children[f.children.indexOf(c)+1];return g?g:f}return null},prune:function(c,d){if(d.parent===c)c.children.length=d.getIndexInParent();else if(c instanceof this.BeginEndNode)c.endMatch=null,c.end=null;if(c.parent)c.parent.children.length=c.getIndexInParent()+1},onLineStyle:function(c){this._tree||this.initialParse();var d=c.lineStart,f=this.textView.getModel(),g=f.getLineEnd(c.lineIndex),h=f.getLineEnd(f.getLineAtOffset(d)-1),h=this.getFirstDamaged(h,h),d=this.getLineScope(f, +h,d,g);c.ranges=this.toStyleRanges(d);c.ranges.sort(function(b,a){return b.start-a.start})},getLineScope:function(c,d,f,g){for(var h=f,b=this.getInitialExpected(d,f),a=[],e=[];d&&h<g;){var i=this.getNextMatch(c,d,h);if(!i)break;var k=i&&i.match,m=i&&i.rule,n=i&&i.isSub,i=i&&i.isEnd;k.index!==h&&e.push({start:h,end:k.index,node:d});if(n)h=this.afterMatch(k),m instanceof this.BeginEndRule?(this.addBeginScope(a,k,m),d=b,b=this.getNextExpected(b,"begin")):this.addMatchScope(a,k,m);else if(i)h=this.afterMatch(k), +this.addEndScope(a,k,m),b=this.getNextExpected(b,"end"),d=d.parent}h<g&&e.push({start:h,end:g,node:d});c=this.getInheritedLineScope(e,f,g);return a.concat(c)},getInheritedLineScope:function(c){for(var d=[],f=0;f<c.length;f++)for(var g=c[f],h=g.node;h;){var b=h.rule.rule,a=b.name;if(b=b.contentName||a){this.addScopeRange(d,g.start,g.end,b);break}h=h.parent}return d},addBeginScope:function(c,d,f){var g=f.rule;this.addCapturesScope(c,d,g.beginCaptures||g.captures,f.isComplex,f.beginOld2New,f.beginConsuming)}, +addEndScope:function(c,d,f){var g=f.rule;this.addCapturesScope(c,d,g.endCaptures||g.captures,f.isComplex,f.endOld2New,f.endConsuming)},addMatchScope:function(c,d,f){var g=f.rule,h=g.name;(g=g.captures)?this.addCapturesScope(c,d,g,f.isComplex,f.matchOld2New,f.matchConsuming):this.addScope(c,d,h)},addScope:function(c,d,f){f&&c.push({start:d.index,end:this.afterMatch(d),scope:f})},addScopeRange:function(c,d,f,g){g&&c.push({start:d,end:f,scope:g})},addCapturesScope:function(c,d,f,g,h,b){if(f)if(g){for(var g= +{1:0},a=0,e=1;d[e]!==void 0;e++)b[e]!==void 0&&(a+=d[e].length),d[e+1]!==void 0&&(g[e+1]=a);b=d.index;for(a=1;f[a];a++){var e=f[a].name,i=h[a],k=b+g[i];typeof d[i]!=="undefined"&&this.addScopeRange(c,k,k+d[i].length,e)}}else this.addScope(c,d,f[0]&&f[0].name)},getIntersecting:function(c,d){for(var f=[],g=this._tree?[this._tree]:[];g.length;){var h=g.pop(),b=!1;h instanceof this.ContainerNode?b=!0:this.isDamaged(h,c,d)&&(b=!0,f.push(h));if(b)for(var b=h.children.length,a=0;a<b;a++)g.push(h.children[a])}return f.reverse()}, +toStyleRanges:function(c){for(var d=[],f=0;f<c.length;f++){var g=c[f],h=this._styles[g.scope];if(!h)throw Error("styles not found for "+g.scope);h=h.join(" ");d.push({start:g.start,end:g.end,style:{styleClass:h}})}return d}};return{RegexUtil:i,TextMateStyler:n}}); +define("orion/editor/htmlGrammar",[],function(){return{HtmlGrammar:function(){return{scopeName:"source.html",uuid:"3B5C76FB-EBB5-D930-F40C-047D082CE99B",patterns:[{begin:"<!(doctype|DOCTYPE)",end:">",contentName:"entity.name.tag.doctype.html",beginCaptures:{0:{name:"entity.name.tag.doctype.html"}},endCaptures:{0:{name:"entity.name.tag.doctype.html"}}},{begin:"<\!--",end:"--\>",beginCaptures:{0:{name:"punctuation.definition.comment.html"}},endCaptures:{0:{name:"punctuation.definition.comment.html"}}, +patterns:[{match:"--",name:"invalid.illegal.badcomment.html"}],contentName:"comment.block.html"},{match:"<[A-Za-z0-9_\\-:]+(?= ?)",name:"entity.name.tag.html"},{include:"#attrName"},{include:"#qString"},{include:"#qqString"},{include:"#entity"},{match:"</[A-Za-z0-9_\\-:]+>",name:"entity.name.tag.html"},{match:">",name:"entity.name.tag.html"}],repository:{attrName:{match:"[A-Za-z\\-:]+(?=\\s*=\\s*['\"])",name:"entity.other.attribute.name.html"},qqString:{match:'(")[^"]+(")',name:"string.quoted.double.html"}, +qString:{match:"(')[^']+(')",name:"string.quoted.single.html"},entity:{match:"&[A-Za-z0-9]+;",name:"constant.character.entity.html"}}}}}}); +define("orion/editor/textStyler",["orion/editor/annotations"],function(k){function m(a,b){this._unnamedCounter=0;this._patterns=[];this._rootId=b;a.forEach(function(a){this._addRepositoryPatterns(a.repository||{},a.id);this._addPatterns(a.patterns||[],a.id)}.bind(this))}function n(a,b,c,d,e){this.start=a.start;this.end=a.end;this.contentStart=a.contentStart;this.contentEnd=a.contentEnd;this.pattern=b;this._styler=c;this._parent=e;this._linePatterns=[];this._blockPatterns=[];this._enclosurePatterns= +{};if(d)this._initPatterns(),this._subBlocks=t(d,d.getText(this.start,this.end),this,this.start)}function i(a){this._styler=a}function c(a,b,c,d){this.highlightCaretLine=this.whitespacesVisible=this.spacesVisible=this.tabsVisible=!1;this.detectTasks=this.foldingEnabled=!0;this.view=a;this.annotationModel=b;this.patternManager=new m(c,d);this._accessor=new i(this);this._bracketAnnotations=void 0;var e=this;this._listener={onChanged:function(a){e._onModelChanged(a)},onDestroy:function(a){e._onDestroy(a)}, +onLineStyle:function(a){e._onLineStyle(a)},onMouseDown:function(a){e._onMouseDown(a)},onSelection:function(a){e._onSelection(a)}};c=a.getModel();c.getBaseModel&&(c=c.getBaseModel());c.addEventListener("Changed",this._listener.onChanged);a.addEventListener("MouseDown",this._listener.onMouseDown);a.addEventListener("Selection",this._listener.onSelection);a.addEventListener("Destroy",this._listener.onDestroy);a.addEventListener("LineStyle",this._listener.onLineStyle);d=c.getCharCount();this._rootBlock= +new n({start:0,contentStart:0,end:d,contentEnd:d},null,this,c);this._computeFolding(this._rootBlock.getBlocks());b&&this.detectTasks&&(d=[],v(this._rootBlock,c,d),b.replaceAnnotations([],d));a.redrawLines()}var d={styleClass:"meta annotation currentLine"},f=/$/,g=/\\(\d)/g,h=/(.*)(?:[\r\n]|$)/g,b={regex:/ /g,style:{styleClass:"punctuation separator space",unmergeable:!0}},a={regex:/\t/g,style:{styleClass:"punctuation separator tab",unmergeable:!0}},e=function(a,b,c,d){var e=c,f=a.lastIndex;h.lastIndex= +c;var c=h.exec(b),g,i;a.lastIndex=0;if(c){for(i=c.index;0<=--i;)if(g=b.charAt(i),g==="\n"||g==="\r")break;g=b.substring(i+1,c.index+c[1].length);a.lastIndex=i=c.index-i-1}for(;c&&c.index<b.length;){var k;if(d){var l=a.lastIndex;if(a.test(g))a.lastIndex=l,k=a.exec(g)}else k=a.exec(g);if(k)return k.index+=e,k.index-=i,a.lastIndex=f,k;i=0;e+=c[0].length;if(c=h.exec(b))g=c[1],a.lastIndex=0}a.lastIndex=f;return null},l=function(a,b){var c=a.toString();g.lastIndex=0;if(!g.test(c))return a;g.lastIndex=0; +for(var d=g.exec(c);d;)c=c.replace(d[0],b[d[1]]||""),g.lastIndex=0,d=g.exec(c);return RegExp(c.substring(1,c.length-2),"g")},o=function(a,b,c,d){if(b=e(a.pattern.regex?a.pattern.regex:a.pattern.regexBegin,b,d,!0)){a.result=b;for(d=0;d<c.length;d++)if(b.index<c[d].result.index||b.index===c[d].result.index&&a.pattern.pattern.index<c[d].pattern.pattern.index){c.splice(d,0,a);return}c.push(a)}},q=function(a,b,c,d){if(b[0])d.push({start:c,end:c+a[0].length,style:b[0].name});else for(var e=0,f=1;f<a.length;f++)if(a[f]){var g= +b[f];if(g){var i=c+e;d.push({start:i,end:i+a[f].length,style:g.name})}e+=a[f].length}},r=function(a,b,c){var d=a.start;b.forEach(function(b){d<=b.start&&c.push({start:d,end:b.start,style:a.style});c.push(b);d=b.end});d<a.end&&c.push({start:d,end:a.end,style:a.style})},p=function(a,b,c,d,g){if(c=c.getLinePatterns()){var i=[];c.forEach(function(b){var c=b.regex||b.regexBegin;c.oldLastIndex=c.lastIndex;(c=e(c,a,0))&&i.push({result:c,pattern:b})});i.sort(function(a,b){return a.result.index<b.result.index? +-1:a.result.index>b.result.index?1:a.pattern.pattern.index<b.pattern.pattern.index?-1:1});for(var h=0;i.length>0;){var k=i[0];i.splice(0,1);if(!(k.result.index<h)){var m=k.result.index,p,n=[];if(k.pattern.regex){h=k.result;p=m+h[0].length;p={start:b+m,end:b+p,style:k.pattern.pattern.name};if(!g){k.pattern.pattern.captures&&q(h,k.pattern.pattern.captures,b+m,n);n.sort(function(a,b){return a.start<b.start?-1:a.start>b.start?1:0});for(m=0;m<n.length-1;m++)if(n[m+1].start<n[m].end){var t={start:n[m+1].end, +end:n[m].end,style:n[m].style};n[m].end=n[m+1].start;n.splice(m+2,0,t)}}r(p,n,d)}else{h=k.pattern.regexEnd;h=l(h,k.result);h=e(h,a,k.result.index+k.result[0].length);if(!h)f.lastIndex=0,h=f.exec(a);p=h.index+h[0].length;d.push({start:b+m,end:b+p,style:k.pattern.pattern.name})}h=h.index+h[0].length}o(k,a,i,h)}c.forEach(function(a){a=a.regex||a.regexBegin;a.lastIndex=a.oldLastIndex})}},t=function(a,b,c,d){var g=[];c.getBlockPatterns().forEach(function(a){var c=e(a.regexBegin||a.regex,b,0);c&&g.push({result:c, +pattern:a})}.bind(this));if(!g.length)return g;g.sort(function(a,b){return a.result.index<b.result.index?-1:a.result.index>b.result.index?1:a.pattern.pattern.index<b.pattern.pattern.index?-1:1});for(var h=0,i=[];g.length>0;){var k=g[0];g.splice(0,1);if(!(k.result.index<h)){var m=a.getLineAtOffset(d+k.result.index),q=a.getLine(m),r=[];p(q,a.getLineStart(m),c,r);m=d+k.result.index;for(q=0;q<r.length;q++)if(r[q].start===m){var h=k.result.index,t=null,v=k.pattern.regexEnd;if(v){h+=k.result[0].length; +for(var v=l(v,k.result),B=h;!t;){B=e(v,b,B);if(!B)f.lastIndex=0,B=f.exec(b);var E=[],G=new n({start:m,end:d+B.index+B[0].length,contentStart:d+h,contentEnd:d+B.index},k.pattern,c.getStyler(),a,c);p(b.substring(h,B.index+B[0].length),h,G,E);if(!E.length||E[E.length-1].end<=B.index)t=G;B=B.index+B[0].length}}else t=new n({start:m,end:m+k.result[0].length,contentStart:m,contentEnd:m+k.result[0].length},k.pattern,c.getStyler(),a,c);i.push(t);h=t.end-d;break}q===r.length&&(h=k.result.index+1)}o(k,b,g, +h)}return i},v=function(a,b,c){if(a.getAnnotationModel()){var d=k.AnnotationType.ANNOTATION_TASK;if(a.getLinePatterns().length&&a.pattern&&a.pattern.pattern.name&&a.pattern.pattern.name.indexOf("comment")===0){var e=[];p(b.getText(a.contentStart,a.end),a.contentStart,a,e,!0);for(var f=0;f<e.length;f++)e[f].style==="meta.annotation.task.todo"&&c.push(k.AnnotationType.createAnnotation(d,e[f].start,e[f].end,b.getText(e[f].start,e[f].end)))}a.getBlocks().forEach(function(a){v(a,b,c)}.bind(this))}};m.prototype= +{getPatterns:function(a){var b=[0],c={},d=RegExp("^"+(a?typeof a==="string"?a:a.qualifiedId:this._rootId)+"#[^#]+$"),e=[];this._patterns.forEach(function(a){if(d.test(a.qualifiedId))a.include?e.push(a):(a.index=b[0]++,c[a.id]=a)}.bind(this));e.forEach(function(a){this._processInclude(a,b,c)}.bind(this));var f=[];Object.keys(c).forEach(function(a){f.push(c[a])});return f},_addPatterns:function(a,b){a.forEach(function(a){this._addPattern(a,this._NO_ID+this._unnamedCounter++,b)}.bind(this))},_addRepositoryPatterns:function(a, +b){Object.keys(a).forEach(function(c){this._addPattern(a[c],c,b)}.bind(this))},_addPattern:function(a,b,c){a.parentId=c;a.id=b;a.qualifiedId=a.parentId+"#"+a.id;this._patterns.push(a);a.patterns&&!a.include&&this._addPatterns(a.patterns,a.qualifiedId)},_processInclude:function(a,b,c){var d,e=a.include.indexOf("#");d=e===0?RegExp("^"+a.qualifiedId.substring(0,a.qualifiedId.indexOf("#"))+a.include+"$"):e===-1?RegExp("^"+a.include+"#"+this._NO_ID+"[^#]+$"):RegExp("^"+a.include+"$");var f=[];this._patterns.forEach(function(a){if(d.test(a.qualifiedId))if(a.include)f.push(a); +else if(!c[a.id])a.index=b[0]++,c[a.id]=a}.bind(this));f.forEach(function(a){this._processInclude(a,b,c)}.bind(this))},_NO_ID:"NoID"};n.prototype={adjustEnd:function(a){this.end+=a;this.contentEnd+=a;this._subBlocks.forEach(function(b){b.adjustEnd(a)})},adjustStart:function(a){this.start+=a;this.contentStart+=a;this._subBlocks.forEach(function(b){b.adjustStart(a)})},computeStyle:function(a,b){if(!this.pattern||!(this.start<=b&&b<this.end))return null;var c={start:this.start,end:this.end,style:this.pattern.pattern.name}; +if(this.contentStart<=b&&b<this.contentEnd)return this.pattern.pattern.contentName?{start:this.contentStart,end:this.contentEnd,style:this.pattern.pattern.contentName}:c;var d,e,f,g;if(b<this.contentStart){e=this.pattern.pattern.beginCaptures||this.pattern.pattern.captures;if(!e)return c;d=this.pattern.regexBegin;f=a.getText(this.start,this.contentStart);g=this.start}else{e=this.pattern.pattern.endCaptures||this.pattern.pattern.captures;if(!e)return c;d=this.pattern.regexEnd;f=a.getText(this.contentEnd, +this.end);g=this.contentEnd}d.lastIndex=0;if(f=d.exec(f)){d=[];q(f,e,g,d);for(e=0;e<d.length;e++)if(d[e].start<=b&&b<d[e].end)return d[e]}return c},getAnnotationModel:function(){return this._styler._getAnnotationModel()},getBlockPatterns:function(){return this._blockPatterns},getBlocks:function(){return this._subBlocks},getEnclosurePatterns:function(){return this._enclosurePatterns},getLinePatterns:function(){return this._linePatterns},getParent:function(){return this._parent},getPatternManager:function(){return this._styler._getPatternManager()}, +getStyler:function(){return this._styler},isRenderingWhitespace:function(){return this._styler._isRenderingWhitespace()},_initPatterns:function(){var a=function(a){var b=/^\(\?i\)\s*/.exec(a);b&&(a=a.substring(b[0].length));return a};this.getPatternManager().getPatterns(this.pattern?this.pattern.pattern:null).forEach(function(b){var c;if(b.match&&!b.begin&&!b.end){c="g";var d=a(b.match);d!==b.match&&(c+="i");c={regex:RegExp(d,c),pattern:b};this._linePatterns.push(c);if(b.patterns)this._blockPatterns.push(c); +else if(b.name&&b.name.indexOf("punctuation.section")===0&&(b.name.indexOf(".begin")!==-1||b.name.indexOf(".end")!==-1))this._enclosurePatterns[b.name]=c}else if(!b.match&&b.begin&&b.end){c="g";d=a(b.begin);d!==b.begin&&(c+="i");var e="g",f=a(b.end);f!==b.end&&(e+="i");c={regexBegin:RegExp(d,c),regexEnd:RegExp(f,e),pattern:b};this._linePatterns.push(c);this._blockPatterns.push(c)}}.bind(this))}};i.prototype={getStyles:function(a){return this._styler.getStyles(a)}};c.prototype={destroy:function(){var a= +this.view;if(a){var b=a.getModel();b.getBaseModel&&(b=b.getBaseModel());b.removeEventListener("Changed",this._listener.onChanged);a.removeEventListener("MouseDown",this._listener.onMouseDown);a.removeEventListener("Selection",this._listener.onSelection);a.removeEventListener("Destroy",this._listener.onDestroy);a.removeEventListener("LineStyle",this._listener.onLineStyle);this.view=null}},getStyleAccessor:function(){return this._accessor},getStyles:function(a){var b=[],c=this.view.getModel();c.getBaseModel&& +(c=c.getBaseModel());var d=this._findBlock(this._rootBlock,a),e=c.getLineAtOffset(a),f=c.getLine(e),g=[];p(f,c.getLineStart(e),d,g);for(e=0;e<g.length;e++){if(a<g[e].start)break;if(g[e].start<=a&&a<g[e].end){b.push(g[e]);break}}for(;d;)(g=d.computeStyle(c,a))&&b.splice(0,0,g),d=d.getParent();return b},setHighlightCaretLine:function(a){this.highlightCaretLine=a},setWhitespacesVisible:function(a,b){if(this.whitespacesVisible!==a)this.whitespacesVisible=a,b&&this.view.redraw()},setTabsVisible:function(a){if(this.tabsVisible!== +a)this.tabsVisible=a,this.setWhitespacesVisible(this.tabsVisible||this.spacesVisible,!1),this.view.redraw()},setSpacesVisible:function(a){if(this.spacesVisible!==a)this.spacesVisible=a,this.setWhitespacesVisible(this.tabsVisible||this.spacesVisible,!1),this.view.redraw()},setDetectHyperlinks:function(){},setFoldingEnabled:function(a){this.foldingEnabled=a},setDetectTasks:function(a){this.detectTasks=a},_binarySearch:function(a,b,c,d,e){var f;d===void 0&&(d=-1);if(e===void 0)e=a.length;for(;e-d>1;)if(f= +Math.floor((e+d)/2),b<=a[f].start)e=f;else if(c&&b<a[f].end){e=f;break}else d=f;return e},_computeFolding:function(a){if(this.foldingEnabled){var b=this.view.getModel();if(b.getBaseModel){var c=this.annotationModel;if(c){c.removeAnnotations(k.AnnotationType.ANNOTATION_FOLDING);for(var d=[],e=b.getBaseModel(),f=0;f<a.length;f++){var g=a[f];(g=this._createFoldingAnnotation(b,e,g.start,g.end))&&d.push(g)}c.replaceAnnotations(null,d)}}}},_createFoldingAnnotation:function(a,b,c,d){var e=b.getLineAtOffset(c), +b=b.getLineAtOffset(d);return e===b?null:new (k.AnnotationType.getType(k.AnnotationType.ANNOTATION_FOLDING))(c,d,a)},_findBlock:function(a,b){var c=a.getBlocks();if(!c.length)return a;var d=this._binarySearch(c,b,!0);return d<c.length&&c[d].start<=b&&b<c[d].end?this._findBlock(c[d],b):a},_findBrackets:function(a,b,c,d,e,f){for(var g=[],h=[],i=e,k=c.getBlocks(),l=this._binarySearch(k,e,!0);l<k.length;l++){if(k[l].start>=f)break;var m=k[l].start,n=k[l].end;i<m&&(p(d.substring(i-e,m-e),i,c,h),h.forEach(function(c){c.style.indexOf(a.pattern.name)=== +0?g.push(c.start+1):c.style.indexOf(b.pattern.name)===0&&g.push(-(c.start+1))}),h=[]);i=n}i<f&&(p(d.substring(i-e,f-e),i,c,h),h.forEach(function(c){c.style.indexOf(a.pattern.name)===0?g.push(c.start+1):c.style.indexOf(b.pattern.name)===0&&g.push(-(c.start+1))}));return g},_findMatchingBracket:function(a,b,c){for(var d=a.getLineAtOffset(c),f=a.getLineEnd(d),g=a.getText(c,f),h,i=b.getEnclosurePatterns(),k=Object.keys(i),l=0;l<k.length;l++){var m=i[k[l]],n=e(m.regex,g,0);if(n&&n.index===0){h=m;break}}if(!h)return-1; +g=!1;h.pattern.name.indexOf(".begin")!==-1?(g=!0,l=h.pattern.name.replace(".begin",".end")):l=h.pattern.name.replace(".end",".begin");i=i[l];if(!i)return-1;k=a.getLine(d);m=a.getLineStart(d);f=this._findBrackets(h,i,b,k,m,f);for(l=0;l<f.length;l++)if(k=f[l]>=0?1:-1,f[l]*k-1===c){c=1;if(g){for(l++;l<f.length;l++)if(k=f[l]>=0?1:-1,c+=k,c===0)return f[l]*k-1;d+=1;for(l=a.getLineCount();d<l;){k=a.getLine(d);m=a.getLineStart(d);f=a.getLineEnd(d);f=this._findBrackets(h,i,b,k,m,f);for(g=0;g<f.length;g++)if(k= +f[g]>=0?1:-1,c+=k,c===0)return f[g]*k-1;d++}}else{for(l--;l>=0;l--)if(k=f[l]>=0?1:-1,c+=k,c===0)return f[l]*k-1;for(d-=1;d>=0;){k=a.getLine(d);m=a.getLineStart(d);f=a.getLineEnd(d);f=this._findBrackets(h,i,b,k,m,f);for(l=f.length-1;l>=0;l--)if(k=f[l]>=0?1:-1,c+=k,c===0)return f[l]*k-1;d--}}break}return-1},_getAnnotationModel:function(){return this.annotationModel},_getLineStyle:function(a){if(this.highlightCaretLine){var b=this.view,c=b.getModel(),b=b.getSelection();if(b.start===b.end&&c.getLineAtOffset(b.start)=== +a)return d}return null},_getPatternManager:function(){return this.patternManager},_getStyles:function(a,b,c,d){b.getBaseModel&&(d=b.mapOffset(d));for(var f=d+c.length,g=[],h=d,i=a.getBlocks(),k=this._binarySearch(i,d,!0);k<i.length;k++){if(i[k].start>=f)break;var l=i[k].start,m=i[k].end;h<l&&p(c.substring(h-d,l-d),h,a,g);var n=Math.max(h,l);if(n===l&&i[k].pattern.regexBegin){var o=e(i[k].pattern.regexBegin,c.substring(n-d),0);if(o){var r=i[k].pattern.pattern.beginCaptures||i[k].pattern.pattern.captures; +r?q(o,r,n,g):g.push({start:n,end:n+o[0].length,style:i[k].pattern.pattern.name});n+=o[0].length}}var l=Math.min(f,m),t=[];if(l===m&&i[k].pattern.regexEnd&&(h=c.substring(l-h-(i[k].end-i[k].contentEnd)),o=e(i[k].pattern.regexEnd,h,0)))(r=i[k].pattern.pattern.endCaptures||i[k].pattern.pattern.captures)?q(o,r,l-o[0].length,t):i[k].pattern.pattern.name&&t.push({start:l-o[0].length,end:l,style:i[k].pattern.pattern.name}),l-=o[0].length;var h=this._getStyles(i[k],b,c.substring(n-d,l-d),n),v=i[k].pattern.pattern.contentName|| +i[k].pattern.pattern.name;if(v){var H=n;h.forEach(function(a){a.start-H&&g.push({start:H,end:a.start,style:v});g.push(a);H=a.end});l-H&&g.push({start:H,end:l,style:v})}else g=g.concat(h);g=g.concat(t);h=m}h<f&&p(c.substring(h-d,f-d),h,a,g);if(b.getBaseModel)for(a=0;a<g.length;a++)c=g[a].end-g[a].start,g[a].start=b.mapOffset(g[a].start,!0),g[a].end=g[a].start+c;return g},_isRenderingWhitespace:function(){return this.whitespacesVisible&&(this.tabsVisible||this.spacesVisible)},_onDestroy:function(){this.destroy()}, +_onLineStyle:function(c){if(c.textView===this.view)c.style=this._getLineStyle(c.lineIndex);c.ranges=this._getStyles(this._rootBlock,c.textView.getModel(),c.lineText,c.lineStart);c.ranges.forEach(function(a){if(a.style)a.style={styleClass:a.style.replace(/\./g," ")}});this._isRenderingWhitespace()&&(this.spacesVisible&&this._spliceStyles(b,c.ranges,c.lineText,c.lineStart),this.tabsVisible&&this._spliceStyles(a,c.ranges,c.lineText,c.lineStart))},_onSelection:function(a){var b=a.oldValue,c=a.newValue, +d=this.view,a=d.getModel(),e;if(this.highlightCaretLine){var f=a.getLineAtOffset(b.start);e=a.getLineAtOffset(c.start);var g=c.start===c.end,b=b.start===b.end;f===e&&b&&g||(b&&d.redrawLines(f,f+1),(f!==e||!b)&&g&&d.redrawLines(e,e+1))}if(this.annotationModel){var b=this._bracketAnnotations,h,i;if(c.start===c.end&&(i=d.getCaretOffset())>0)i-=1,a.getBaseModel&&(i=a.mapOffset(i),a=a.getBaseModel()),c=this._findBlock(this._rootBlock,i),a=this._findMatchingBracket(a,c,i),a!==-1&&(h=[k.AnnotationType.createAnnotation(k.AnnotationType.ANNOTATION_MATCHING_BRACKET, +a,a+1),k.AnnotationType.createAnnotation(k.AnnotationType.ANNOTATION_CURRENT_BRACKET,i,i+1)]);this._bracketAnnotations=h;this.annotationModel.replaceAnnotations(b,h)}},_onMouseDown:function(a){if(a.clickCount===2){var b=this.view,c=b.getModel(),d=b.getOffsetAtLocation(a.x,a.y);if(d>0){var e=d-1,f=c;c.getBaseModel&&(e=c.mapOffset(e),f=c.getBaseModel());var g=this._findBlock(this._rootBlock,e),e=this._findMatchingBracket(f,g,e);e!==-1&&(a.preventDefault(),a=e,c.getBaseModel&&(a=c.mapOffset(a,!0)),d> +a&&(d--,a++),b.setSelection(a,d))}}},_onModelChanged:function(a){var b=a.start,c=a.removedCharCount,a=a.addedCharCount-c,d=this.view,e=d.getModel(),f=e.getBaseModel?e.getBaseModel():e,c=b+c,g=f.getCharCount(),i=this._rootBlock.getBlocks(),h=i.length,l=f.getLineStart(f.getLineAtOffset(b)),m=this._binarySearch(i,l,!0),n=this._binarySearch(i,c,!1,m-1,h),o;m<h&&i[m].start<=l&&l<i[m].end?(o=i[m].start,o>b&&(o+=a)):o=m===h&&h>0&&g-a===i[h-1].end?i[h-1].start:l;var p;do n<h?(p=i[n].end,p>b&&(p+=a),n+=1): +(n=h,p=g),l=f.getText(o,p),l=t(f,l,this._rootBlock,o);while(l.length&&i.length&&n<h&&l[l.length-1].pattern.pattern.id!==i[n-1].pattern.pattern.id);for(g=m;g<i.length;g++)h=i[g],h.start>b&&h.adjustStart(a),h.start>b&&h.adjustEnd(a);var q=n-m!==l.length;if(!q)for(g=0;g<l.length;g++){var h=i[m+g],r=l[g];if(h.start!==r.start||h.end!==r.end||h.type!==r.type){q=!0;break}}g=[m,n-m].concat(l);Array.prototype.splice.apply(i,g);q&&(g=o,h=p,e!==f&&(g=e.mapOffset(g,!0),h=e.mapOffset(h,!0)),d.redrawRange(g,h)); +if(this.annotationModel){d=[];i=[];m=[];o=this.annotationModel.getAnnotations(o,p);for(p=this.foldingEnabled&&f!==e;o.hasNext();)if(h=o.next(),p&&h.type===k.AnnotationType.ANNOTATION_FOLDING){m.push(h);for(g=0;g<l.length;g++)if(h.start===l[g].start&&h.end===l[g].end)break;g===l.length?(d.push(h),h.expand()):(g=h.start,n=h.end,g>b&&(g-=a),n>b&&(n-=a),g<=b&&b<n&&g<=c&&c<n&&(g=f.getLineAtOffset(h.start),n=f.getLineAtOffset(h.end),g!==n?h.expanded||h.expand():this.annotationModel.removeAnnotation(h))); +for(g=0;g<l.length;g++){h=l[g];for(n=0;n<m.length;n++)if(m[n].start===h.start&&m[n].end===h.end)break;n===m.length&&(h=this._createFoldingAnnotation(e,f,h.start,h.end))&&i.push(h)}}else h.type===k.AnnotationType.ANNOTATION_TASK&&d.push(h);if(this.detectTasks)for(g=0;g<l.length;g++)v(l[g],f,i);this.annotationModel.replaceAnnotations(d,i)}},_spliceStyles:function(a,b,c,d){for(var e=a.regex,f=e.lastIndex=0,g=e.exec(c);g;){for(g=d+g.index;f<b.length;){if(g<b[f].end)break;f++}var h={start:g,end:g+1,style:a.style}; +if(f<b.length&&b[f].start<=g){var i={start:g+1,end:b[f].end,style:b[f].style};b[f].end=g;b.splice(f+1,0,i);b.splice(f+1,0,h);f+=2}else b.splice(f,0,h),f++;g=e.exec(c)}}};return{TextStyler:c}}); +define("orion/editor/stylers/text_x-php/syntax",["orion/editor/stylers/lib/syntax"],function(k){var m="abstract,and,array,as,break,callable,case,catch,class,clone,const,continue,declare,default,die,do,echo,else,elseif,empty,enddeclare,endfor,endforeach,endif,endswitch,endwhile,eval,exit,extends,false,FALSE,final,finally,for,foreach,function,global,goto,if,implements,include,include_once,insteadof,interface,instanceof,isset,list,namespace,new,null,NULL,or,parent,print,private,protected,public,require,require_once,return,self,static,switch,throw,trait,try,true,TRUE,unset,use,var,while,xor,yield,__halt_compiler,__CLASS__,__DIR__,__FILE__,__FUNCTION__,__LINE__,__METHOD__,__NAMESPACE__,__TRAIT__".split(","),k= +k.grammars;k.push({id:"orion.php",contentTypes:["text/x-php"],patterns:[{include:"orion.lib#doc_block"},{include:"orion.c-like"},{match:"(?i)<\\?(?:=|php)?(?:\\s|$)",name:"entity.name.declaration.php"},{match:"<%=?(?:\\s|$)",name:"entity.name.declaration.php"},{match:"#.*",name:"comment.line.number-sign.php",patterns:[{include:"orion.lib#todo_comment_singleLine"}]},{begin:"<<<(\\w+)$",end:"^\\1;$",name:"string.unquoted.heredoc.php"},{begin:"<<<'(\\w+)'$",end:"^\\1;$",name:"string.unquoted.heredoc.nowdoc.php"}, +{match:"\\b0[bB][01]+\\b",name:"constant.numeric.binary.php"},{match:"\\b(?:"+m.join("|")+")\\b",name:"keyword.control.php"}]});return{id:"orion.php",grammars:k,keywords:m}}); +define("orion/editor/stylers/application_xml/syntax",["orion/editor/stylers/lib/syntax"],function(k){k=k.grammars;k.push({id:"orion.xml",contentTypes:["application/xml","application/xhtml+xml"],patterns:[{include:"#comment"},{include:"#xmlDeclaration"},{begin:"<!(?:doctype|DOCTYPE)",end:">",captures:{0:{name:"entity.name.tag.doctype.xml"}},patterns:[{include:"#comment"},{include:"orion.lib#string_doubleQuote"},{include:"orion.lib#string_singleQuote"}],name:"meta.tag.doctype.xml"},{begin:"</?[A-Za-z0-9]+", +end:"/?>",captures:{0:{name:"entity.name.tag.xml"}},name:"meta.tag.xml",patterns:[{include:"#comment"},{include:"orion.lib#string_doubleQuote"},{include:"orion.lib#string_singleQuote"}]},{match:"<|>|&",name:"constant.character"}],repository:{comment:{begin:"<\!--",end:"--\>",name:"comment.block.xml",patterns:[{match:"(\\b)(TODO)(\\b)(((?!--\>).)*)",name:"meta.annotation.task.todo",captures:{2:{name:"keyword.other.documentation.task"},4:{name:"comment.line"}}}]},xmlDeclaration:{begin:"<\\?xml", +end:"\\?>",captures:{0:{name:"entity.name.tag.declaration.xml"}},patterns:[{include:"#comment"},{include:"orion.lib#string_doubleQuote"},{include:"orion.lib#string_singleQuote"}],name:"meta.tag.declaration.xml"}}});return{id:k[k.length-1].id,grammars:k,keywords:[]}}); +define("orion/editor/stylers/text_html/syntax",["orion/editor/stylers/lib/syntax","orion/editor/stylers/application_javascript/syntax","orion/editor/stylers/text_css/syntax","orion/editor/stylers/text_x-php/syntax","orion/editor/stylers/application_xml/syntax"],function(k,m,n,i,c){k=k.grammars.concat(m.grammars).concat(n.grammars).concat(i.grammars).concat(c.grammars);k.push({id:"orion.html",contentTypes:["text/html"],patterns:[{include:"orion.xml"},{begin:"(?i)(<style)([^>]*)(>)",end:"(?i)(</style>)", +captures:{1:{name:"entity.name.tag.html"},3:{name:"entity.name.tag.html"}},contentName:"source.css.embedded.html",patterns:[{include:"orion.css"}]},{begin:"(?i)<script\\s*>|<script\\s.*?(?:language\\s*=\\s*(['\"])javascript\\1|type\\s*=\\s*(['\"])(?:text|application)/(?:javascript|ecmascript)\\2).*?>",end:"(?i)<\/script>",captures:{0:{name:"entity.name.tag.html"}},contentName:"source.js.embedded.html",patterns:[{include:"orion.js"}]},{begin:"(?i)<script\\s.*?(?:language\\s*=\\s*(['\"])php\\1|type\\s*=\\s*(['\"])text/x-php\\2).*?>", +end:"(?i)<\/script>",captures:{0:{name:"entity.name.tag.html"}},contentName:"source.php.embedded.html",patterns:[{include:"orion.php"}]},{begin:"(?i)<\\?(?:=|php)?(?:\\s|$)",end:"\\?>",captures:{0:{name:"entity.name.declaration.php"}},contentName:"source.php.embedded.html",patterns:[{include:"orion.php"}]},{begin:"<%=?(?:\\s|$)",end:"%>",captures:{0:{name:"entity.name.declaration.php"}},contentName:"source.php.embedded.html",patterns:[{include:"orion.php"}]}],repository:{xmlDeclaration:{}}});return{id:k[k.length- +1].id,grammars:k,keywords:[]}}); +define("orion/editor/edit","require,orion/editor/shim,orion/editor/textView,orion/editor/textModel,orion/editor/textTheme,orion/editor/projectionTextModel,orion/editor/eventTarget,orion/keyBinding,orion/editor/rulers,orion/editor/annotations,orion/editor/tooltip,orion/editor/undoStack,orion/editor/textDND,orion/editor/editor,orion/editor/editorFeatures,orion/editor/contentAssist,orion/editor/cssContentAssist,orion/editor/htmlContentAssist,orion/editor/jsTemplateContentAssist,orion/editor/AsyncStyler,orion/editor/mirror,orion/editor/textMateStyler,orion/editor/htmlGrammar,orion/editor/textStyler,orion/editor/stylers/application_javascript/syntax,orion/editor/stylers/text_css/syntax,orion/editor/stylers/text_html/syntax".split(","),function(k, +m,n,i,c,d,f,g,h,b,a,e,l,o,q,r,p,t,v,s,u,j,w,x,D,y,K){function O(a){var b=a.firstChild;if(b&&b.tagName==="TEXTAREA")return b.value;var c=a.ownerDocument,d=c.defaultView||c.parentWindow,e;if(!(e=!d.getSelection)){if(!(b=a.childNodes.length===1&&b.nodeType===Node.TEXT_NODE)){for(var f,b=a;b&&b!==c&&f!=="none";)f=d.getComputedStyle?d.getComputedStyle(b,null).getPropertyValue("display"):b.currentStyle.display,b=b.parentNode;b=f==="none"}e=b}if(e)return a.innerText||a.textContent;c=c.createRange();c.selectNode(a); +a=d.getSelection();d=[];for(f=0;f<a.rangeCount;f++)d.push(a.getRangeAt(f));a.removeAllRanges();a.addRange(c);c=a.toString();a.removeAllRanges();for(f=0;f<d.length;f++)a.addRange(d[f]);return c}function P(a){if(a.substring(0,12)==="data-editor-")return a=a.substring(12),a=a.replace(/-([a-z])/ig,function(a,b){return b.toUpperCase()})}function M(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}function Q(a,b){var c={};M(c,b);for(var d,e=0,f=a.attributes,g=f.length;e<g;e++){d=f.item(e);var h=P(d.nodeName); +if(h){d=d.nodeValue;if(d==="true"||d==="false")d=d==="true";c[h]=d}}return c}function R(a,b){if(a.getElementsByClassName)return a.getElementsByClassName(b);b=b.replace(/ *$/,"");return a.querySelectorAll?a.querySelectorAll((" "+b).replace(/ +/g,".")):null}function B(a){var b=a.document||document,e=a.parent;e||(e="editor");typeof e==="string"&&(e=b.getElementById(e));if(!e&&a.className&&(b=R(b,a.className))){a.className=void 0;if(b.length>1&&a.noFocus===void 0)a.noFocus=!0;for(var f=[],g=b.length- +1;g>=0;g--)a.parent=b[g],f.push(B(a));return f}if(!e)throw"no parent";a=Q(e,a);if(typeof a.theme==="string"){var b=c.TextTheme.getTheme(a.theme),g=a.theme.lastIndexOf("/"),h=a.theme;g!==-1&&(h=h.substring(g+1));h.substring(h.length-4)===".css"&&(h=h.substring(0,h.length-4));b.setThemeClass(h,{href:a.theme});a.theme=b}var j;a.readonly||(f={createContentAssistMode:function(a){j=new r.ContentAssist(a.getTextView());a=new r.ContentAssistWidget(j);a=new r.ContentAssistMode(j,a);j.setMode(a);return a}}); +var l=new o.Editor({textViewFactory:function(){return new n.TextView({parent:e,model:new d.ProjectionTextModel(a.model?a.model:new i.TextModel("")),tabSize:a.tabSize?a.tabSize:4,readonly:a.readonly,fullSelection:a.fullSelection,tabMode:a.tabMode,expandTab:a.expandTab,singleMode:a.singleMode,themeClass:a.themeClass,theme:a.theme,wrapMode:a.wrapMode,wrappable:a.wrappable})},undoStackFactory:new q.UndoFactory,annotationFactory:new q.AnnotationFactory,lineNumberRulerFactory:new q.LineNumberRulerFactory, +foldingRulerFactory:new q.FoldingRulerFactory,textDNDFactory:new q.TextDNDFactory,contentAssistFactory:f,keyBindingFactory:new q.KeyBindingsFactory,statusReporter:a.statusReporter,domNode:e});l.addEventListener("TextViewInstalled",function(){var b=l.getLineNumberRuler();b&&a.firstLineIndex!==void 0&&b.setFirstLine(a.firstLineIndex);if(b=l.getSourceCodeActions())b.setAutoPairParentheses(a.autoPairParentheses),b.setAutoPairBraces(a.autoPairBraces),b.setAutoPairSquareBrackets(a.autoPairSquareBrackets), +b.setAutoPairAngleBrackets(a.autoPairAngleBrackets),b.setAutoPairQuotations(a.autoPairQuotations),b.setAutoCompleteComments(a.autoCompleteComments),b.setSmartIndentation(a.smartIndentation)});f=a.contents;f===void 0&&(f=O(e));f||(f="");l.installTextView();l.setLineNumberRulerVisible(a.showLinesRuler===void 0||a.showLinesRuler);l.setAnnotationRulerVisible(a.showAnnotationRuler===void 0||a.showFoldingRuler);l.setOverviewRulerVisible(a.showOverviewRuler===void 0||a.showOverviewRuler);l.setFoldingRulerVisible(a.showFoldingRuler=== +void 0||a.showFoldingRuler);l.setInput(a.title,null,f,!1,a.noFocus);({styler:null,highlight:function(b,c){this.styler&&this.styler.destroy&&this.styler.destroy();this.styler=null;b==="js"?b="application/javascript":b==="css"?b="text/css":b==="html"?b="text/html":b==="java"&&(b="text/x-java-source");var d=c.getTextView(),e=c.getAnnotationModel();b&&(b=b.replace(/[*|:/".<>?+]/g,"_"),k(["./stylers/"+b+"/syntax"],function(a){this.styler=new x.TextStyler(d,e,a.grammars,a.id)}));b==="text/css"&&c.setFoldingRulerVisible(a.showFoldingRuler=== +void 0||a.showFoldingRuler)}}).highlight(a.contentType||a.lang,l);if(j){var m=new p.CssContentAssistProvider,s=new t.HTMLContentAssistProvider,u=new v.JSTemplateContentAssistProvider;j.addEventListener("Activating",function(){/css$/.test(a.lang)?j.setProviders([m]):/js$/.test(a.lang)?j.setProviders([u]):/html$/.test(a.lang)&&j.setProviders([s])})}if(e.clientHeight<=50)f=l.getTextView().computeSize().height,e.style.height=f+"px";return l}var E=this.orion?this.orion.editor:void 0;if(E)for(var G=0;G< +arguments.length;G++)M(E,arguments[G]);return B});var orion=this.orion||(this.orion={}),editor=orion.editor||(orion.editor={});editor.edit=require("orion/editor/edit");
\ No newline at end of file diff --git a/dgbuilder/public/pw_maze_white.png b/dgbuilder/public/pw_maze_white.png Binary files differnew file mode 100644 index 00000000..66464831 --- /dev/null +++ b/dgbuilder/public/pw_maze_white.png diff --git a/dgbuilder/public/red/comms.js b/dgbuilder/public/red/comms.js new file mode 100644 index 00000000..64912476 --- /dev/null +++ b/dgbuilder/public/red/comms.js @@ -0,0 +1,93 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +RED.comms = (function() { + + var errornotification = null; + var subscriptions = {}; + var ws; + function connectWS() { + var path = location.hostname+":"+location.port+document.location.pathname; + path = path+(path.slice(-1) == "/"?"":"/")+"comms"; + path = "ws"+(document.location.protocol=="https:"?"s":"")+"://"+path; + ws = new WebSocket(path); + ws.onopen = function() { + if (errornotification) { + errornotification.close(); + errornotification = null; + } + for (var t in subscriptions) { + if (subscriptions.hasOwnProperty(t)) { + ws.send(JSON.stringify({subscribe:t})); + } + } + } + ws.onmessage = function(event) { + var msg = JSON.parse(event.data); + if (msg.topic) { + for (var t in subscriptions) { + if (subscriptions.hasOwnProperty(t)) { + var re = new RegExp("^"+t.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$"); + if (re.test(msg.topic)) { + var subscribers = subscriptions[t]; + if (subscribers) { + for (var i=0;i<subscribers.length;i++) { + subscribers[i](msg.topic,msg.data); + } + } + } + } + } + } + }; + ws.onclose = function() { + if (errornotification == null) { + errornotification = RED.notify("<b>Error</b>: Lost connection to server","error",true); + } + setTimeout(connectWS,1000); + } + } + + function subscribe(topic,callback) { + if (subscriptions[topic] == null) { + subscriptions[topic] = []; + } + subscriptions[topic].push(callback); + if (ws && ws.readyState == 1) { + ws.send(JSON.stringify({subscribe:topic})); + } + } + + function unsubscribe(topic,callback) { + if (subscriptions.topic) { + for (var i=0;i<subscriptions.topic.length;i++) { + if (subscriptions.topic[i] === callback) { + subscriptions.topic.splice(i,1); + break; + } + } + if (subscriptions.topic.length === 0) { + delete subscriptions.topic; + } + } + } + + return { + connect: connectWS, + subscribe: subscribe, + unsubscribe:unsubscribe + } +})(); diff --git a/dgbuilder/public/red/history.js b/dgbuilder/public/red/history.js new file mode 100644 index 00000000..3a6d5513 --- /dev/null +++ b/dgbuilder/public/red/history.js @@ -0,0 +1,99 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.history = (function() { + var undo_history = []; + + return { + //TODO: this function is a placeholder until there is a 'save' event that can be listened to + markAllDirty: function() { + for (var i=0;i<undo_history.length;i++) { + undo_history[i].dirty = true; + } + }, + depth: function() { + return undo_history.length; + }, + push: function(ev) { + undo_history.push(ev); + }, + pop: function() { + var ev = undo_history.pop(); + var i; + if (ev) { + if (ev.t == 'add') { + if (ev.nodes) { + for (i=0;i<ev.nodes.length;i++) { + RED.nodes.remove(ev.nodes[i]); + } + } + if (ev.links) { + for (i=0;i<ev.links.length;i++) { + RED.nodes.removeLink(ev.links[i]); + } + } + if (ev.workspaces) { + for (i=0;i<ev.workspaces.length;i++) { + RED.nodes.removeWorkspace(ev.workspaces[i].id); + RED.view.removeWorkspace(ev.workspaces[i]); + } + } + } else if (ev.t == "delete") { + if (ev.workspaces) { + for (i=0;i<ev.workspaces.length;i++) { + RED.nodes.addWorkspace(ev.workspaces[i]); + RED.view.addWorkspace(ev.workspaces[i]); + } + } + if (ev.nodes) { + for (i=0;i<ev.nodes.length;i++) { + RED.nodes.add(ev.nodes[i]); + } + } + if (ev.links) { + for (i=0;i<ev.links.length;i++) { + RED.nodes.addLink(ev.links[i]); + } + } + } else if (ev.t == "move") { + for (i=0;i<ev.nodes.length;i++) { + var n = ev.nodes[i]; + n.n.x = n.ox; + n.n.y = n.oy; + n.n.dirty = true; + } + } else if (ev.t == "edit") { + for (i in ev.changes) { + if (ev.changes.hasOwnProperty(i)) { + ev.node[i] = ev.changes[i]; + } + } + RED.editor.updateNodeProperties(ev.node); + if (ev.links) { + for (i=0;i<ev.links.length;i++) { + RED.nodes.addLink(ev.links[i]); + } + } + RED.editor.validateNode(ev.node); + ev.node.dirty = true; + ev.node.changed = ev.changed; + } + RED.view.dirty(ev.dirty); + RED.view.redraw(); + } + } + } + +})(); diff --git a/dgbuilder/public/red/main.js b/dgbuilder/public/red/main.js new file mode 100644 index 00000000..27032a26 --- /dev/null +++ b/dgbuilder/public/red/main.js @@ -0,0 +1,1620 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var RED = (function() { + + function hideDropTarget() { + $("#dropTarget").hide(); + RED.keyboard.remove(/* ESCAPE */ 27); + } + + $('#chart').on("dragenter",function(event) { + if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { + $("#dropTarget").css({display:'table'}); + RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget); + } + }); + + $('#dropTarget').on("dragover",function(event) { + if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { + event.preventDefault(); + } + }) + .on("dragleave",function(event) { + hideDropTarget(); + }) + .on("drop",function(event) { + var data = event.originalEvent.dataTransfer.getData("text/plain"); + hideDropTarget(); + RED.view.importNodes(data); + event.preventDefault(); + }); + + + function save(force) { + if (RED.view.dirty()) { + //$("#debug-tab-clear").click(); // uncomment this to auto clear debug on deploy + + if (!force) { + var invalid = false; + var unknownNodes = []; + RED.nodes.eachNode(function(node) { + invalid = invalid || !node.valid; + if (node.type === "unknown") { + if (unknownNodes.indexOf(node.name) == -1) { + unknownNodes.push(node.name); + } + invalid = true; + } + }); + if (invalid) { + if (unknownNodes.length > 0) { + $( "#node-dialog-confirm-deploy-config" ).hide(); + $( "#node-dialog-confirm-deploy-unknown" ).show(); + var list = "<li>"+unknownNodes.join("</li><li>")+"</li>"; + $( "#node-dialog-confirm-deploy-unknown-list" ).html(list); + } else { + $( "#node-dialog-confirm-deploy-config" ).show(); + $( "#node-dialog-confirm-deploy-unknown" ).hide(); + } + $( "#node-dialog-confirm-deploy" ).dialog( "open" ); + return; + } + } + var nns = RED.nodes.createCompleteNodeSet(); + /****************************************/ + /*added new code to save the Tabs order */ + /****************************************/ + //console.log("nns before changes."); + //console.dir(nns); + var allTabsObj={}; + var allTabsList=[]; + var nnsTabIdsArr = []; + var guiTabIdsArr = []; + nns.forEach(function(n) { + if(n.type == 'tab'){ + allTabsObj[n.id] = n; + allTabsList.push(n); + nnsTabIdsArr.push(n.id); + } + }); + var idx =0; + $("#workspace-tabs li a").each(function(){ + var href = $(this).prop("href"); + var indexOfHash = href.indexOf("#"); + var idVal = href.slice(indexOfHash+1); + guiTabIdsArr.push(idVal); + nns.splice(idx,1,allTabsObj[idVal]);; + idx++; + }); + //console.log(nnsTabIdsArr.join(",")); + //console.log(guiTabIdsArr.join(",")); + //console.log("nns after changes."); + //console.dir(nns); + /****************************/ + $("#btn-icn-deploy").removeClass('fa-download'); + $("#btn-icn-deploy").addClass('spinner'); + RED.view.dirty(false); + + $.ajax({ + url:"flows", + type: "POST", + data: JSON.stringify(nns), + contentType: "application/json; charset=utf-8" + }).done(function(data,textStatus,xhr) { + RED.notify("Successfully saved","success"); + RED.nodes.eachNode(function(node) { + if (node.changed) { + node.dirty = true; + node.changed = false; + } + if(node.credentials) { + delete node.credentials; + } + }); + RED.nodes.eachConfig(function (confNode) { + if (confNode.credentials) { + delete confNode.credentials; + } + }); + // Once deployed, cannot undo back to a clean state + RED.history.markAllDirty(); + RED.view.redraw(); + }).fail(function(xhr,textStatus,err) { + RED.view.dirty(true); + if (xhr.responseText) { + RED.notify("<strong>Error</strong>: "+xhr.responseText,"error"); + } else { + RED.notify("<strong>Error</strong>: no response from server","error"); + } + }).always(function() { + $("#btn-icn-deploy").removeClass('spinner'); + $("#btn-icn-deploy").addClass('fa-download'); + }); + } + } + + $('#btn-deploy').click(function() { save(); }); + + $( "#node-dialog-confirm-deploy" ).dialog({ + title: "Confirm deploy", + modal: true, + autoOpen: false, + width: 530, + height: 230, + buttons: [ + { + text: "Confirm deploy", + click: function() { + save(true); + $( this ).dialog( "close" ); + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ] + }); + + function loadSettings() { + $.get('settings', function(data) { + RED.settings = data; + console.log("Node-RED: "+data.version); + loadNodeList(); + }); + } + + function loadNodeList() { + $.ajax({ + headers: { + "Accept":"application/json" + }, + cache: false, + url: 'nodes', + success: function(data) { + RED.nodes.setNodeList(data); + loadNodes(); + } + }); + } + + function loadNodes() { + $.ajax({ + headers: { + "Accept":"text/html" + }, + cache: false, + url: 'nodes', + success: function(data) { + $("body").append(data); + $(".palette-spinner").hide(); + $(".palette-scroll").show(); + $("#palette-search").show(); + loadFlows(); + } + }); + } + + function loadFlows() { + $.ajax({ + headers: { + "Accept":"application/json" + }, + cache: false, + url: 'flows', + success: function(nodes) { + RED.nodes.import(nodes); + RED.view.dirty(false); + RED.view.redraw(); + RED.comms.subscribe("status/#",function(topic,msg) { + var parts = topic.split("/"); + var node = RED.nodes.node(parts[1]); + if (node) { + node.status = msg; + if (statusEnabled) { + node.dirty = true; + RED.view.redraw(); + } + } + }); + RED.comms.subscribe("node/#",function(topic,msg) { + var i,m; + var typeList; + var info; + + if (topic == "node/added") { + var addedTypes = []; + for (i=0;i<msg.length;i++) { + m = msg[i]; + var id = m.id; + RED.nodes.addNodeSet(m); + if (m.loaded) { + addedTypes = addedTypes.concat(m.types); + $.get('nodes/'+id, function(data) { + $("body").append(data); + }); + } + } + if (addedTypes.length) { + typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>"; + RED.notify("Node"+(addedTypes.length!=1 ? "s":"")+" added to palette:"+typeList,"success"); + } + } else if (topic == "node/removed") { + for (i=0;i<msg.length;i++) { + m = msg[i]; + info = RED.nodes.removeNodeSet(m.id); + if (info.added) { + typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>"; + RED.notify("Node"+(m.types.length!=1 ? "s":"")+" removed from palette:"+typeList,"success"); + } + } + } else if (topic == "node/enabled") { + if (msg.types) { + info = RED.nodes.getNodeSet(msg.id); + if (info.added) { + RED.nodes.enableNodeSet(msg.id); + typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; + RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" enabled:"+typeList,"success"); + } else { + $.get('nodes/'+msg.id, function(data) { + $("body").append(data); + typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; + RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" added to palette:"+typeList,"success"); + }); + } + } + } else if (topic == "node/disabled") { + if (msg.types) { + RED.nodes.disableNodeSet(msg.id); + typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; + RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" disabled:"+typeList,"success"); + } + } + }); + } + }); + } + + var statusEnabled = false; + function toggleStatus(state) { + statusEnabled = state; + RED.view.status(statusEnabled); + } + + function performLoopDetection(state) { + loopDetectionEnabled = state; + console.log("loopDetectionEnabled:" + loopDetectionEnabled); + } + + var dgNumberEnabled = false; + function toggleDgNumberDisplay(state) { + dgNumberEnabled = state; + RED.view.showNumbers(dgNumberEnabled); + } + + var nodePaletteDisplay = false; + function toggleNodePaletteDisplay(state) { + nodePaletteDisplay = state; + RED.view.showNodePalette(nodePaletteDisplay); + } + function displayAllDGs(state) { + //defined showSLa() in dgstart.html + showSLA(); + } + + + function showHelp() { + + var dialog = $('#node-help'); + + //$("#node-help").draggable({ + // handle: ".modal-header" + //}); + + dialog.on('show',function() { + RED.keyboard.disable(); + }); + dialog.on('hidden',function() { + RED.keyboard.enable(); + }); + + dialog.modal(); + } + + +//Custom Functions Added here + function showCodeCloudFlows(){ + codeCloudFlowFiles=[]; + var divStyle="<style>#codecloud-data-container a { color: #067ab4; font-size: 0.75em;} #codecloud-data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>"; + $.get( "/getCodeCloudFlows") + .done(function( data ) { + + var header="<div class='header'>List of DG Flows in Code Cloud</div><div><input id='flowFilterBoxId' type='text' onkeyup='filterFlows(this.value)'></div>"; + var html= divStyle + header + "<div id='codecloud-data-container'>"; + html+="<ul>"; + if(data != null){ + var files=data.files; + codeCloudFlowFiles=files; + //console.dir(files); + files.sort(function (a,b){ + if(a > b){ + return 1; + }else if(a < b){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;files != null && i<files.length;i++){ + html+="<li><a href=\"#\" onclick=\"getCommits('" + files[i] + "')\">" + files[i] + "</a></li>"; + } + } + html+="</ul>"; + html+="</div>"; + $( "#codecloud-browser-dialog" ).dialog({ + title: "Code Cloud DG Flow Browser", + modal: true, + autoOpen: true, + width: 830, + height: 630, + buttons: [ + { + text: "Close", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + close: function(ev,ui){ + $(this).dialog("destroy"); + } + }).html(html); + $("#codecloud-browser-dialog").show(); + }) + .fail(function(err) { + RED.notify("Failed to get users."); + }) + .always(function() { + }); + } + /* + function listYangFiles(){ + yangFilesList=[]; + var divStyle="<style>#list-yang-data-container a { color: #067ab4; font-size: 0.75em;} #list-yang-data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>"; + $.get( "/getYangFiles") + .done(function( data ) { + + var header="<div class='header'>List of Yang Files </div><div><input id='flowFilterBoxId' type='text' onkeyup='filterYangFiles(this.value)'></div>"; + var html= divStyle + header + "<div id='list-yang-data-container'>"; + html+="<ul>"; + if(data != null){ + var files=data.files; + yangFilesList=files; + //console.dir(files); + files.sort(function (a,b){ + if(a > b){ + return 1; + }else if(a < b){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;files != null && i<files.length;i++){ + html+="<li><a href=\"#\" onclick=\"getYangFile('" + files[i] + "')\">" + files[i] + "</a></li>"; + } + } + html+="</ul>"; + html+="</div>"; + $( "#list-yang-browser-dialog" ).dialog({ + title: "List Yang Files", + modal: true, + autoOpen: true, + width: 830, + height: 630, + buttons: [ + { + text: "Close", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + close: function(ev,ui){ + $(this).dialog("destroy"); + } + }).html(html); + $("#list-yang-browser-dialog").show(); + }) + .fail(function(err) { + RED.notify("Failed to get yang files."); + }) + .always(function() { + }); + } + */ + + function listYangFiles(){ + yangFilesList=[]; + + var divStyle="<style>#yang-files-data-container a { color: #067ab4; font-size: 0.75em;} #yang-files-data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; } table#yang-file-list-table { width:100%; } table#yang-file-list-table th,table#yang-file-list-table td { border: 1px solid black; border-collapse: collapse; } table#yang-file-list-table th,table#yang-file-list-table td { padding: 5px; text-align: left; } table#yang-file-list-table tr:nth-child(even) { background-color: #eee; } table#yang-file-list-table tr:nth-child(odd) { background-color:#fff; } table#yang-file-list-table th { background-color: #65a9d7; color: white; } table#yang-file-list-table a { color: #337ab7; } table#yang-file-list-table a:link { color: #65a9d7; } table#yang-file-list-table a:visited { color: #636; } table#yang-file-list-table a:hover { color: #3366CC; cursor: pointer } table#yang-file-list-table a:active { color: #65a9d7 }</style>"; + $.get( "/getYangFiles") + .done(function( data ) { + + var header="<div class='header'>List of Yang Files </div><div><input id='flowFilterBoxId' type='text' onkeyup='filterYangFiles(this.value)'></div>"; + var html= divStyle + header + "<div id='yang-files-data-container'>"; + html+="<table id='yang-file-list-table' border=1>"; + html+="<tr>"; + html+="<th>File</th>"; + html+="<th>Delete</th>"; + html+="</tr>"; + if(data != null){ + var files=data.files; + yangFilesList=files; + //console.dir(files); + files.sort(function (a,b){ + if(a > b){ + return 1; + }else if(a < b){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;files != null && i<files.length;i++){ + html+="<tr><td><a href=\"#\" onclick=\"getYangFile('" + files[i] + "')\">" + files[i] + "</a></td><td>" + "<input type='button' onclick='deleteYangFile(\"" + files[i] + "\")' value='Delete'></td></td></td></tr>"; + } + } + html+="</table>"; + html+="</div>"; + $( "#list-yang-browser-dialog" ).dialog({ + title: "List Yang Files", + modal: true, + autoOpen: true, + width: 830, + height: 630, + buttons: [ + { + text: "Close", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + close: function(ev,ui){ + $(this).dialog("destroy"); + } + }).html(html); + $("#list-yang-browser-dialog").show(); + }) + .fail(function(err) { + RED.notify("Failed to get yang files."); + }) + .always(function() { + }); + } + + + function showGitPullDialog(){ + $.get( "/getCurrentGitBranch") + .done(function( data ) { + if(data != null){ + if(data.output == "GIT_LOCAL_REPOSITORY_NOT_SET" ){ + RED.notify("Git Local Repository path is not set. Please set it by choosing Configuration from the menu."); + return; + } + + var html= "<div id='gitcheckout-container'>"; + html+="<table>"; + html+="<tr>"; + html+="<td>Branch</td>"; + html+="<td>" + data.output + "</td>"; + html+="</tr>"; + html+="<tr>"; + html+="<td><input id='gitPullBtnId' type='button' value='Pull' onclick='performGitPull()'></td>"; + html+="<td> </td>" + html+="</tr>"; + html+="<tr>"; + //html+="<td colspan=3><textarea readonly='1' rows='5' cols='200' id='responseId'></textarea></td>"; + html+="</tr>"; + html+="</table>"; + html+="<br><div id='responseId'></div>"; + html+="</div>"; + $( "#gitcommands-dialog" ).dialog({ + title: "Git Pull", + modal: true, + autoOpen: true, + width: 630, + height: 500, + buttons: [ + { + text: "Close", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + close: function(ev,ui){ + $(this).dialog("destroy"); + } + }).html(html); + $("#responseId").css({width:'550',height:'275px', border: '2px solid lightgrey',overflow:'scroll', padding: '20px' }); + $("#responseId").hide(); + $("#gitcommands-dialog").show(); + } + }) + .fail(function(err) { + RED.notify("Failed to get gitBranch."); + }) + .always(function() { + }); + } + + function showGitStatusDialog(){ + $.get( "/getCurrentGitBranch") + .done(function( data ) { + if(data != null){ + if(data.output == "GIT_LOCAL_REPOSITORY_NOT_SET" ){ + RED.notify("Git Local Repository path is not set. Please set it by choosing Configuration from the menu."); + return; + } + + var html= "<div id='gitcheckout-container'>"; + html+="<table>"; + html+="<tr>"; + html+="<td>Branch</td>"; + html+="<td>" + data.output + "</td>"; + html+="</tr>"; + html+="<tr>"; + html+="<td><input id='gitStatusBtnId' type='button' value='Status' onclick='performGitStatus()'></td>"; + html+="<td> </td>" + html+="</tr>"; + html+="<tr>"; + //html+="<td colspan=3><textarea readonly='1' rows='5' cols='200' id='responseId'></textarea></td>"; + html+="</tr>"; + html+="</table>"; + html+="<br><div id='responseId'></div>"; + html+="</div>"; + $( "#gitcommands-dialog" ).dialog({ + title: "Git Status", + modal: true, + autoOpen: true, + width: 630, + height: 500, + buttons: [ + { + text: "Close", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + close: function(ev,ui){ + $(this).dialog("destroy"); + } + }).html(html); + //$("#responseId").css({width:'600px',height:'100px','border-radius' : '25px', border: '2px solid lightgrey', padding: '20px' }); + $("#responseId").css({width:'550px',height:'100px', border: '2px solid lightgrey',overflow:'scroll', padding: '20px' }); + $("#responseId").hide(); + $("#gitcommands-dialog").show(); + } + }) + .fail(function(err) { + RED.notify("Failed to get gitBranch."); + }) + .always(function() { + }); + } + + function showGitCheckoutDialog(){ + $.get( "/getCurrentGitBranch") + .done(function( data ) { + if(data != null){ + if(data.output == "GIT_LOCAL_REPOSITORY_NOT_SET" ){ + RED.notify("Git Local Repository path is not set. Please set it by choosing Configuration from the menu."); + return; + } + + var html= "<div id='gitcheckout-container'>"; + html+="<table>"; + html+="<tr>"; + html+="<td>Branch</td>"; + html+="<td><input id='branchId' type='text' value='" + data.output + "'></td>"; + html+="</tr>"; + html+="<tr>"; + html+="<td><input id='checkoutBtnId' type='button' value='Checkout' onclick='performGitCheckout()'></td>"; + html+="<td> </td>" + html+="</tr>"; + html+="<tr>"; + //html+="<td colspan=3><textarea readonly='1' rows='5' cols='200' id='responseId'></textarea></td>"; + html+="</tr>"; + html+="</table>"; + html+="<br><div id='responseId'></div>"; + html+="</div>"; + $( "#gitcommands-dialog" ).dialog({ + title: "Git Checkout", + modal: true, + autoOpen: true, + width: 430, + height: 350, + buttons: [ + { + text: "Close", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + close: function(ev,ui){ + $(this).dialog("destroy"); + } + }).html(html); + $("#responseId").css({width:'300',height:'100px', border: '2px solid lightgrey',overflow:'scroll', padding: '20px' }); + $("#responseId").hide(); + $("#gitcommands-dialog").show(); + } + }) + .fail(function(err) { + RED.notify("Failed to get gitBranch."); + }) + .always(function() { + }); + } + + function showGitLocalFlows(){ + giLocalFlowFiles=[]; + var divStyle="<style>#gitlocal-data-container a { color: #067ab4; font-size: 0.75em;} #gitlocal-data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>"; + $.get( "/getGitLocalFlows") + .done(function( data ) { + if(data != null && data.files != null && data.files.length == 1){ + if(data.files[0] == "GIT_LOCAL_REPOSITORY_NOT_SET" ){ + RED.notify("Git Local Repository path is not set. Please set it by choosing Configuration from the menu."); + return; + } + } + //console.log("got response from server."); + + var header="<div class='header'>List of DG Flows from Git Local Repository </div><div><input id='flowFilterBoxId' type='text' onkeyup='filterGitLocalFlows(this.value)'></div>"; + var html= divStyle + header + "<div id='gitlocal-data-container'>"; + html+="<ul>"; + if(data != null){ + var files=data.files; + gitLocalFlowFiles=files; + //console.dir(files); + files.sort(function (a,b){ + if(a > b){ + return 1; + }else if(a < b){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;files != null && i<files.length;i++){ + html+="<li><a href=\"#\" onclick=\"importGitLocalFlow('" + files[i] + "')\">" + files[i] + "</a></li>"; + } + } + html+="</ul>"; + html+="</div>"; + $( "#gitlocal-browser-dialog" ).dialog({ + title: "Git Local Repository DG Flow Browser", + modal: true, + autoOpen: true, + width: 830, + height: 630, + buttons: [ + { + text: "Close", + click: function() { + $(this).dialog("close"); + } + } + ] + }).html(html); + $("#gitlocal-browser-dialog").show(); + /* + if ($("#gitlocal-browser-dialog").dialog( "isOpen" )===true) { + console.log("gitlocal dialog box is open"); + //true + } else { + console.log("gitlocal dialog box is not open"); + // $( "#gitlocal-browser-dialog" ).dialog("destroy").remove(); + console.log($("#gitlocal-browser-dialog").dialog( "widget" )); + $("#gitlocal-browser-dialog").dialog( "open" ); + if ($("#gitlocal-browser-dialog").dialog( "isOpen" )===true) { + console.log("gitlocal dialog box is now open"); + } + $("#gitlocal-browser-dialog").show(); + //false + } + */ + }) + .fail(function(err) { + RED.notify("Failed to get flows."); + }) + .always(function() { + console.log("Done displaying"); + }); + } + + function showFlowShareUsers(){ + var divStyle="<style>#data-container a { color: #067ab4; font-size: 0.75em;} #data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>"; + $.get("/flowShareUsers") + .done(function (data){ + + var header="<div class='header'>List of Downloaded DG Flows</div>"; + var html= divStyle + header + "<div id='data-container'>"; + html+="<ul>"; + if(data != null){ + var users=data.flowShareUsers; + users.sort(function (a,b){ + if(a.name > b.name){ + return 1; + }else if(a.name < b.name){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;users != null && i<users.length;i++){ + html+="<li><a href=\"#\" onclick=\"showFlowFiles('" + users[i].rootDir + "')\">" + users[i].name + "</a></li>"; + } + } + html+="</ul>"; + html+="</div>"; + $( "#dgflow-browser-dialog" ).dialog({ + title: "Downloaded DG Flows Browser", + modal: true, + autoOpen: true, + width: 530, + height: 530, + buttons: [ + { + text: "Close", + click: function() { + $( this ).dialog( "close" ); + //$(this).dialog('destroy').remove(); + } + } + ] + }).html(html); + $("#dgflow-browser-dialog").show(); + /* + if ($("#dgflow-browser-dialog").dialog( "isOpen" )===true) { + console.log("dgflow dialog box is open"); + //true + } else { + console.log("dgflow dialog box is not open"); + $("#dgflow-browser-dialog").dialog( "open" ); + $("#dgflow-browser-dialog").show(); + //false + } + */ + }) + .fail(function(err) { + RED.notify("Failed to get users."); + }) + .always(function() { + }); + } + +/* function showFlowShareUsers(){ + var divStyle="<style>#data-container a { color: #067ab4; font-size: 0.75em;} #data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>"; + $.get( "/flowShareUsers") + .done(function( data ) { + + var header="<div class='header'>List of Downloaded DG Flows</div>"; + var html= divStyle + header + "<div id='data-container'>"; + html+="<ul>"; + if(data != null){ + var users=data.flowShareUsers; + users.sort(function (a,b){ + if(a.name > b.name){ + return 1; + }else if(a.name < b.name){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;users != null && i<users.length;i++){ + html+="<li><a href=\"#\" onclick=\"showFlowFiles('" + users[i].rootDir + "')\">" + users[i].name + "</a></li>"; + } + } + html+="</ul>"; + html+="</div>"; + $( "#dgflow-browser-dialog" ).dialog({ + title: "Downloaded DG Flows Browser", + modal: true, + autoOpen: true, + width: 530, + height: 530, + buttons: [ + { + text: "Close", + click: function() { + //$( this ).dialog( "close" ); + $(this).dialog('destroy').remove(); + } + } + ] + }).html(html); + //$("#dgflow-browser-dialog").show(); + $( "#dgflow-browser-dialog" ).dialog( "open" ); + }) + .fail(function(err) { + RED.notify("Failed to get users."); + }) + .always(function() { + }); + } + */ + + +function detectLoopInFlow(){ + var errList = []; + var activeWorkspace=RED.view.getWorkspace(); + var nSet=[]; + + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + nSet.push({n:n}); + } + }); + + var nodeSet = RED.nodes.createExportableNodeSet(nSet); + + var isLoopDetected = false; + var dgStartNode = getDgStartNode(nodeSet); + if(dgStartNode == null || dgStartNode == undefined) { + console.log("dgstart node not linked."); + return null; + } + + var wires = dgStartNode.wires; + var nodesInPath = {}; + var dgStartNodeId = dgStartNode.id; + if(wires != null && wires != undefined && wires[0] != undefined){ + for(var k=0;k<wires[0].length;k++){ + var val = wires[0][k]; + nodesInPath[dgStartNodeId + "->" + val] = ""; + } + }else{ + nodesInPath[dgStartNodeId + "->" + ""] = ""; + } + + var loopDetectedObj = {}; + /* the nodes will not be in order so will need to loop thru again */ + for(var m=0;nodeSet != null && m<nodeSet.length;m++){ + for(var i=0;nodeSet != null && i<nodeSet.length;i++){ + var link=nodeSet[i].id; + //console.log("NAME:" + nodeSet[i].name + ":" + link); + if(link == dgStartNodeId) continue; + var wires = nodeSet[i].wires; + //console.log("link:" + link); + var delKeys = []; + if(wires != null && wires != undefined && wires[0] != undefined){ + for(var k=0;k<wires[0].length;k++){ + var val = (wires[0])[k]; + var keys = Object.keys(nodesInPath); + //console.log("keys:" + keys); + for (var j=0;j<keys.length;j++){ + //console.log("key:" + keys[j]); + //console.log("val:" + val); + var index = keys[j].indexOf("->" + link); + var lastIndex = keys[j].lastIndexOf("->"); + if(index != -1 && index == lastIndex){ + //delete nodesInPath[key]; + var previousNodeId = keys[j].substr(lastIndex +2); + var indexOfArrow = -1; + if(previousNodeId != ""){ + indexOfArrow = previousNodeId.indexOf("->"); + } + if(previousNodeId != null && indexOfArrow != -1){ + previousNodeId = previousNodeId.substr(0,indexOfArrow); + } + nodesInPath[keys[j] + "->" + val] = ""; + //console.log("keys[j]:" + keys[j]); + delKeys.push(keys[j]); + var prevNodeIdIndex = keys[j].indexOf("->" + previousNodeId); + var priorOccurence = keys[j].indexOf(val + "->"); + if(priorOccurence != -1 && priorOccurence<prevNodeIdIndex){ + //console.log("previousNodeId:" + previousNodeId); + //console.log("val:" + val); + var n1 = getNode(nodeSet,previousNodeId); + var n2 = getNode(nodeSet,val); + //console.log("loop detected for node " + n1.name + " and " + n2.name); + loopDetectedObj[n1.name + "->" + n2.name] ="looped"; + console.dir(loopDetectedObj); + errList.push("Loop detected between " + n1.name + " and " + n2.name); + isLoopDetected = true; + } + } + } + } + } + for(var l=0;delKeys != null && l<delKeys.length;l++){ + delete nodesInPath[delKeys[l]]; + } + } + + + } + /* + if(loopDetectedObj != null ){ + var msg = ""; + for(var key in loopDetectedObj){ + if(loopDetectedObj.hasOwnProperty(key)) { + console.log("Loop detected " + key); + msg += "<strong>Loop detected for:" + key + "</strong><br>"; + } + } + if(msg != ""){ + isLoopDetected = true; + //RED.notify(msg); + } + } + */ + //images/page-loading.gif + return errList; +} + +function showLoopDetectionBox(){ + $(function() { + var htmlStr="<div id='loop-box-div' style='width:375;height:225'><p>Loop detection in Progress ...</p><img src='images/page-loading.gif'></div>" + $("#loop-detection-dialog").dialog({ + modal:true, + autoOpen :true, + title: "DG Flow Loop Detection", + width: 400, + height: 250, + minWidth : 400, + minHeight :200, + }).html(htmlStr); + if($("#loop-detection-dialog").dialog("isOpen") == true){ + var errList = detectLoopInFlow(); + var errList=[]; + if(errList == null){ + $("#loop-detection-dialog").dialog("close"); + } + var msgHtml = ""; + for(var i=0;errList != null && i<errList.length;i++){ + msgHtml += "<p>" + errList[i] + "</p>"; + } + if(msgHtml == ""){ + $("loop-box-div").html("<p>SUCCESS. No Loop detected.</p>"); + }else{ + $("loop-box-div").html(msgHtml); + } + } + }); + +} + +function showSelectedTabs(){ + var tabSheets = []; + var beforeTabsOrder=[]; + $(".red-ui-tabs li a").each(function(i){ + var id=$(this).attr("href").replace('#',''); + var title=$(this).attr("title"); + var isVisible = $(this).parent().is(":visible"); + if(title != 'info'){ + tabSheets.push({"id" : id ,"title":title,"module":"NOT_SET","version" : "NOT_SET","rpc":"NOT_SET","isVisible":isVisible}); + beforeTabsOrder.push(id); + } + }); + + RED.nodes.eachNode(function(n) { + if(n.type == 'service-logic'){ + var id = n.z; + var module = n.module; + tabSheets.forEach(function(tab){ + if(tab.id == id){ + tab.module=module; + tab.version=n.version; + } + }); + }else if(n.type == 'method'){ + var id = n.z; + tabSheets.forEach(function(tab){ + if(tab.id == id){ + var rpc=getAttributeValue(n.xml,"rpc"); + tab.rpc=rpc; + } + }); + } + }); + //console.dir(tabSheets); + var htmlStr = getHtmlStr(tabSheets); + $("#filter-tabs-dialog").dialog({ + modal:true, + title: "DG Builder Tabs", + width: 1200, + height: 750, + minWidth : 600, + minHeight :450, + }).html(htmlStr); +/* This code allows for the drag-drop of the rows in the table */ + var fixHelperModified = function(e, tr) { + var $originals = tr.children(); + var $helper = tr.clone(); + $helper.children().each(function(index) { + $(this).width($originals.eq(index).width()) + }); + return $helper; + }, + updateIndex = function(e, ui) { + var afterTabsOrder=[]; + $('td.index', ui.item.parent()).each(function (i) { + $(this).html(i + 1); + }); + //RE-ARRANGE the tabs + var ul = $("#workspace-tabs"); + $("#ftab02 tr td:nth-child(1)").each(function(i){ + var idStr = $(this).prop("id").replace("tab-td_",""); + afterTabsOrder.push(idStr); + link = ul.find("a[href='#"+ idStr+"']"); + li = link.parent(); + //li.remove(); + firstTab = $("#workspace-tabs li:first-child"); + lastTab = $("#workspace-tabs li:last-child"); + li.insertAfter(lastTab); + //console.log( idStr); + }); + var beforeTabsStr = beforeTabsOrder.join(","); + var afterTabsStr = afterTabsOrder.join(","); + //console.log("beforeTabsStr:" +beforeTabsStr); + //console.log("afterTabsStr:" +afterTabsStr); + if(beforeTabsStr !== afterTabsStr){ + //activate only when order has changed + //activate the deploy button + RED.view.dirty(true); + $("#btn-deploy").removeClass("disabled"); + } + }; + + $("#ftab02 tbody").sortable({ + helper: fixHelperModified, + stop: updateIndex + }).disableSelection(); + +} + +function getHtmlStr(rows){ + var styleStr = "<style> " + + "table#ftab02 { width:100%; } \n" + + "table#ftab02 th,table#ftab02 td { border: 1px solid black; border-collapse: collapse; } \n" + + /*"table, th, td { border: 1px solid #65a9d7; border-collapse: collapse; } \n" +*/ + "table#ftab02 th,table#ftab02 td { padding: 5px; text-align: left; } \n" + + "table#ftab02 tr:nth-child(even) { background-color: #eee; }\n" + + "table#ftab02 tr:nth-child(odd) { background-color:#fff; }\n" + + "table#ftab02 th { background-color: #65a9d7; color: white; }\n" + + "table#ftab02 a { color: #337ab7; }\n" + + "table#ftab02 a:link { color: #65a9d7; }\n" + + "table#ftab02 a:visited { color: #636; }\n" + + "table#ftab02 a:hover { color: #3366CC; cursor: pointer }\n" + + "table#ftab02 a:active { color: #65a9d7 }\n" + + "</style>"; + if(rows != null && rows != undefined){ + //var alertDialog = '<div id="confdialog"></div>'; + //htmlStr= alertDialog + "<div style='width:1050;height:650'>" + styleStr; + var alertDialog = '<div id="tabAlertDialog"></div>'; + htmlStr= alertDialog + "<div id='tabs-div' style='width:1050;height:650'>" + styleStr; + htmlStr += "<table id='ftab02' >"; + htmlStr += "<tr>"; + htmlStr += "<th class='index'>No.</th>" ; + htmlStr += "<th>Tab Title</th>" ; + htmlStr += "<th>Module</th>" ; + htmlStr += "<th>RPC</th>" ; + htmlStr += "<th>Version</th>" ; + htmlStr += "<th>Rename</th>" ; + htmlStr += "<th>Delete</th>" ; + htmlStr += "</tr>"; + htmlStr += "<tbody>"; + if(rows != null && rows.length == 0){ + htmlStr += "<tr>"; + htmlStr += "<td><b>No rows found</b></td>"; + htmlStr += "</tr></table></div>"; + return htmlStr; + } + for(var i=0;i<rows.length;i++){ + var row = rows[i]; + var title = row.title; + var _module = row.module; + var version = row.version; + var rpc = row.rpc; + var idVal = row.id; + var isVisible = row.isVisible; + htmlStr += "<tr id='tab-tr_" + idVal + "'>"; + //htmlStr += "<td id=" + "'tab-td_" + idVal + "' ><a href='javascript:activateClickedTab(\"" + idVal + "\")'>" + (i+1) + "</a></td>"; + htmlStr += "<td class='index' id=" + "'tab-td_" + idVal + "' >" + (i+1) + "</td>"; + htmlStr += "<td><a href='javascript:activateClickedTab(\"" + idVal + "\")'>" + title + "</a></td>"; + htmlStr += "<td>" + _module + "</td>"; + htmlStr += "<td>" + rpc + "</td>"; + htmlStr += "<td>" + version + "</td>"; + //htmlStr += "<td><a href='javascript:deleteOrRenameTab(\"" + idVal + "\")'>Delete/Rename</a></td>"; + htmlStr += "<td><input type='button' onclick='renameSelectedTab(\"" + idVal + "\",\"" + title + "\",\"" + _module + "\",\"" + rpc + "\",\"" + version + "\")' value='Rename'></td>"; + if(rows.length == 1){ + htmlStr += "<td><input type='button' disabled='1' onclick='deleteSelectedTab(\"" + idVal + "\",\"" + title + "\",\"" + _module + "\",\"" + rpc + "\",\"" + version + "\")' value='Delete'></td>"; + }else{ + htmlStr += "<td><input type='button' onclick='deleteSelectedTab(\"" + idVal + "\",\"" + title + "\",\"" + _module + "\",\"" + rpc + "\",\"" + version + "\")' value='Delete'></td>"; + } + /* + if(isVisible){ + htmlStr += "<td><input type='checkbox' onclick=\"showOrHideTab(this,'" + idVal + "')\" checked='true'></td>"; + }else{ + htmlStr += "<td><input type='checkbox' onclick=\"showOrHideTab(this,'" + idVal + "')\"></td>"; + } + */ + htmlStr += "</tr>"; + } + htmlStr += "</tbody>"; + htmlStr += "</table>"; + htmlStr += "</div>"; + } + return htmlStr; +} +/* +Added this logic because , when the configuration item is choosen in the menu the other dialog boxes were not poping up +*/ +(function(){ + //var msecs1= Date.now(); + $( "#gitlocal-browser-dialog" ).dialog(); + $( "#gitlocal-browser-dialog" ).dialog("close"); + $( "#dgflow-browser-dialog" ).dialog(); + $( "#dgflow-browser-dialog" ).dialog("close"); + $( "#update-password-dialog" ).dialog(); + $( "#update-password-dialog" ).dialog("close"); + $( "#codecloud-browser-dialog" ).dialog(); + $( "#codecloud-browser-dialog" ).dialog("close"); + $( "#update-configuration-dialog" ).dialog(); + $( "#update-configuration-dialog" ).dialog("close"); + $( "#gitcommands-dialog" ).dialog(); + $( "#gitcommands-dialog" ).dialog("close"); + $("#filter-tabs-dialog").dialog(); + $("#filter-tabs-dialog").dialog("close"); + $("#loop-detection-dialog").dialog(); + $("#loop-detection-dialog").dialog("close"); + $("#dgstart-generate-xml-dialog").dialog(); + $("#dgstart-generate-xml-dialog").dialog("close"); + $("#xmldialog").dialog(); + $("#xmldialog").dialog("close"); + $("#upload-xml-status-dialog").dialog(); + $("#upload-xml-status-dialog").dialog("close"); + $("#flow-design-err-dialog").dialog(); + $("#flow-design-err-dialog").dialog("close"); + $("#sli-values-dialog").dialog(); + $("#sli-values-dialog").dialog("close"); + $("#comments-dialog").dialog(); + $("#comments-dialog").dialog("close"); + $("#show-errors-dialog").dialog(); + $("#show-errors-dialog").dialog("close"); + $("#dgnumber-find-dialog").dialog(); + $("#dgnumber-find-dialog").dialog("close"); + $("#search-text-dialog").dialog(); + $("#search-text-dialog").dialog("close"); + $("#yang-upload-dialog").dialog(); + $("#yang-upload-dialog").dialog("close"); + $("#yang-modules-browser-dialog").dialog(); + $("#yang-modules-browser-dialog").dialog("close"); + $("#list-yang-browser-dialog").dialog(); + $("#list-yang-browser-dialog").dialog("close"); + $("#request-input-dialog").dialog(); + $("#request-input-dialog").dialog("close"); + //var msecs2= Date.now(); + //console.log("Time taken for dialog boxes:" + (msecs2 - msecs1)); +})(); + + function updateConfiguration(){ + //console.log("in updateConfiguration"); + $.get("/getCurrentSettings",function (data){ + var dbHost = data.dbHost; + var dbPort = data.dbPort; + var dbName = data.dbName; + var dbUser = data.dbUser; + var dbPassword = data.dbPassword; + var gitLocalRepository = data.gitLocalRepository; + var performGitPull = data.performGitPull; + + if(dbHost == undefined) dbHost=""; + if(dbPort == undefined) dbPort=""; + if(dbName == undefined) dbName=""; + if(dbUser == undefined) dbUser=""; + if(dbPassword == undefined) dbPassword=""; + if(gitLocalRepository == undefined) gitLocalRepository=""; + if(performGitPull == undefined || performGitPull == null) performGitPull="N"; + + var divStyle="border: 1px solid #a1a1a1; padding: 10px 40px; background: #dddddd; width: 500px; border-radius: 25px;"; + //var divStyle="border: 2px solid #a1a1a1; padding: 10px 40px; background: #99CCFF; width: 400px; border-radius: 25px;"; + + + var html = "<div>"; + html += "<script>function changeType(obj,targetId){if( obj.checked== true){$('#' + targetId).prop('type','password');}else{$('#'+ targetId).prop('type','text');}} function changeTitle(){ document.getElementById(\"gitLocalRepository\").title=document.getElementById(\"gitLocalRepository\").value;}</script>"; + html += "<div style='" + divStyle + "' >"; + html += "<table border='0' cellpadding='5' >"; + html += "<tr>"; + html += "<td style='font-size:12px;align:center'><b>DB Host IP</b></td>"; + html += "<td><input style='align:center;font-size:11px;font-weight:bold' id='dbhost' name='dbhost' type='text' value='" + dbHost + "'></td>"; + html += "</tr>"; + html += "<tr>"; + html += "<td style='font-size:12px;align:center'><b>DB Port</b></td>"; + html += "<td><input style='align:center;font-size:11px;font-weight:bold' id='dbport' name='dbport' type='text' value='" + dbPort + "'></td>"; + html += "</tr>"; + html += "<tr>"; + html += "<td style='font-size:12px;align:center'><b>DB Name</b></td>"; + html += "<td><input style='align:center;font-size:11px;font-weight:bold' id='dbname' name='dbname' type='text' value='" + dbName + "'></td>"; + html += "</tr>"; + html += "<tr>"; + html += "<td style='font-size:12px;align:center'><b>DB UserName</b></td>"; + html += "<td><input style='align:center;font-size:11px;font-weight:bold' id='dbuser' name='dbuser' type='password' value='" + dbUser + "'></td>"; + html += "<td><input style='background:background:white;width:20px;height:20px' type='checkbox' checked value='1' onclick=\"changeType(this,'dbuser')\">Hide</td>"; + html += "</tr>"; + html += "<tr>"; + html += "<td style='font-size:12px;align:center'><b>DB Password</b></td>"; + html += "<td><input style='align:center;font-size:11px;font-weight:bold' id='dbpassword' name='dbpassword' type='password' value='" + dbPassword + "'></td>"; + html += "<td><input style='background:background:white;width:20px;height:20px' type='checkbox' checked value='1' onclick=\"changeType(this,'dbpassword')\">Hide</td>"; + html += "</tr>"; + html += "</table>"; + html += "</div>"; + html += "<div style='fill:both;clear:both'></div><br>"; + + html += "<div style='" + divStyle + "' >"; + html += "<table border='0' cellpadding='5' >"; + html += "<tr>"; + html += "<td style='font-size:12px;align:center'><b>Git Local Repository Path</b></td>"; + html += "<td><textarea style='align:center;font-size:14px;' cols='50' rows='4' id='gitLocalRepository' name='gitLocalRepository' onkeyup='changeTitle()' title='" + gitLocalRepository + "'>" + gitLocalRepository + "</textarea></td>"; + html += "</tr>"; + html += "</table>"; + html += "<table border='0' cellpadding='5' >"; + html += "<tr>"; + if(performGitPull == "N"){ + html += "<td style='align:center;'><input style='color:blue;width:20px;height:20px;' id='performGitPull' type='checkbox' value='Y'>Perform Git Pull in Local Git Repository prior to import</td>"; + }else{ + html += "<td style='align:center;'><input style='color:blue;width:20px;height:20px;' id='performGitPull' type='checkbox' value='Y' checked>Perform Git Pull in Local Git Repository prior to import</td>"; + } + html += "</tr>"; + html += "</table>"; + html += "</div>"; + html += "</div>"; + //console.log("html:" + html); + $( "#update-configuration-dialog" ).dialog({ + title: "Configuration", + modal: true, + autoOpen: true, + width: 630, + height: 630, + buttons: [ + { + text: "Save", + click: function() { + var newDBHost = $("#dbhost").val().trim(); + var newDBPort = $("#dbport").val().trim(); + var newDBName = $("#dbname").val().trim(); + var newDBUser = $("#dbuser").val().trim(); + var newDBPassword = $("#dbpassword").val().trim(); + var newGitLocalRepository = $("#gitLocalRepository").val().trim(); + var isPerformGitPullChecked = $('#performGitPull').is(':checked'); + var newPerformGitPull = "N"; + if(isPerformGitPullChecked){ + newPerformGitPull = "Y"; + } + if(newDBHost == ""){ + RED.notify("Error: DB Host is required."); + $("#dbhost").focus(); + return; + }else if(newDBPort == ""){ + RED.notify("Error: DB Port is required."); + $("#dbport").focus(); + return; + }else if(newDBName == ""){ + RED.notify("Error: DB Name is required."); + $("#dbname").focus(); + return; + }else if(newDBUser == ""){ + RED.notify("Error: DB User is required."); + $("#dbuser").focus(); + return; + }else if(newDBPassword == ""){ + RED.notify("Error: DB Password is required."); + $("#dbpassword").focus(); + return; + }else{ + console.log("newGitLocalRepository:" + newGitLocalRepository); + var reqData= {"dbHost":newDBHost, + "dbPort" : newDBPort, + "dbName" : newDBName, + "dbUser" : newDBUser, + "dbPassword" : newDBPassword, + "gitLocalRepository" : newGitLocalRepository, + "performGitPull" : newPerformGitPull + }; + $.post( "/updateConfiguration",reqData ) + .done(function( data ) { + RED.notify("Configuration updated successfully"); + //loadSettings(); + //RED.comms.connect(); + //$( "#update-configuration-dialog" ).dialog('close'); + $("#update-configuration-dialog").dialog("close"); + //location.reload(); + + }) + .fail(function(err) { + console.log( "error" + err ); + RED.notify("Failed to update the Configuration."); + }) + .always(function() { + }); + } + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ] + }).html(html); + //$("#update-configuration-dialog").show(); + $("#gitLocalRepository").css({"width" : 300}); + + }); + } + + function updatePassword(){ + var html="<div>"; + html += "<div><span><b>New Password</b></span><br>"; + html += "<input id='passwd1' name='passwd1' type='password' value=''>"; + html += "</div>"; + html += "<div><span><b>Confirm Password</b></span><br>"; + html += "<input id='passwd2' name='passwd2' type='password' value=''>"; + html += "</div>"; + $( "#update-password-dialog" ).dialog({ + title: "Update Password", + modal: true, + autoOpen: true, + width: 530, + height: 230, + buttons: [ + { + text: "Update Password", + click: function() { + var passwd1 = $("#passwd1").val().trim(); + var passwd2 = $("#passwd2").val().trim(); + if((passwd1 != passwd2) || (passwd1 == "" || passwd2 == "")){ + RED.notify("Error:Passwords entered must be same and must be populated."); + return; + }else{ + var reqData= {"password":passwd1}; + $.post( "/updatePassword",reqData ) + .done(function( data ) { + RED.notify("Password updated successfully"); + //loadSettings(); + $( "#update-password-dialog" ).dialog('close'); + }) + .fail(function(err) { + console.log( "error" + err ); + RED.notify("Failed to update the password."); + }) + .always(function() { + }); + } + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ] + }).html(html); + $("#update-password-dialog").show(); + + } + + function showAvailableYangModules(){ + availableYangModules=[]; + var divStyle="<style>#yang-modules-data-container a { color: #067ab4; font-size: 0.75em;} #yang-modules-data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; } table#yang-list-table { width:100%; } table#yang-list-table th,table#yang-list-table td { border: 1px solid black; border-collapse: collapse; } table#yang-list-table th,table#yang-list-table td { padding: 5px; text-align: left; } table#yang-list-table tr:nth-child(even) { background-color: #eee; } table#yang-list-table tr:nth-child(odd) { background-color:#fff; } table#yang-list-table th { background-color: #65a9d7; color: white; } table#yang-list-table a { color: #337ab7; } table#yang-list-table a:link { color: #65a9d7; } table#yang-list-table a:visited { color: #636; } table#yang-list-table a:hover { color: #3366CC; cursor: pointer } table#yang-list-table a:active { color: #65a9d7 }</style>"; + $.get( "/listAvailableModules") + .done(function( data ) { + var header="<div class='header'>List of Available Yang Modules</div>"; + header += "<div><p><i>Check the modules that you want to load and click on the Load button.</i></p></div>"; + //header += "<div><input id='yangModuleFilterBoxId' type='text' onkeyup='filterYangModules(this.value)'></div>"; + var html= divStyle + header + "<div id='yang-modules-data-container'>"; + html+="<table id='yang-list-table' border=1>"; + html+="<tr>"; + html+="<th>#</th>"; + html+="<th>Load</th>"; + html+="<th>Module</th>"; + html+="</tr>"; + if(data != null){ + var files=data.files; + availableYangModules=files; + //console.dir(files); + files.sort(function (a,b){ + if(a > b){ + return 1; + }else if(a < b){ + return -1; + }else{ + return 0; + } + }); + var count=1; + for(var i=0;files != null && i<files.length;i++){ + var val = files[i].replace(/:.*/,""); + if(files[i].indexOf(":checked") != -1){ + html+="<tr><td>" + count + "</td><td><input type='checkbox' checked value='" + val + "'></td><td>" + val + "</td></tr>"; + }else{ + html+="<tr><td>" + count + "</td><td><input type='checkbox' value='" + val + "'></td><td>" + val + "</td></tr>"; + } + count++; + } + } + html+="</table>"; + html+="</div>"; + $( "#yang-modules-browser-dialog" ).dialog({ + title: "Available Yang Modules", + modal: true, + autoOpen: true, + width: 830, + height: 630, + buttons: [ + { + text: "Load", + click: function() { + var allVals = []; + function getValuesForSelected() { + $('#yang-modules-data-container :checked').each(function() { + allVals.push($(this).val()); + }); + return allVals; + } + var selectedModules = getValuesForSelected().toString(); + console.log(selectedModules); + $.ajax({ + type: 'GET', + /*contentType: "application/x-www-form-urlencoded",*/ + url: '/loadSelectedModules?selectedModules=' + selectedModules, + success: function(data) { + RED.notify("Modules Loaded successfully"); + //emptying existing g;obal variables + sliValuesObj = {}; + rpcValues = {}; + reqInputValues = {}; + + if(data != undefined && data != null){ + for(var i=0;i<data.sliValuesObj.length;i++){ + var moduleName = data.sliValuesObj[i].moduleName; + sliValuesObj[moduleName] = data.sliValuesObj[i][moduleName + '_PROPS']; + rpcValues[moduleName] = data.sliValuesObj[i][ moduleName +'_RPCS']; + for(var k=0;rpcValues[moduleName] != undefined && k<rpcValues[moduleName].length;k++){ + var rpcName = rpcValues[moduleName][k]; + reqInputValues[moduleName + "_" + rpcName] = data.sliValuesObj[i][rpcName +"-input"]; + //console.dir(reqInputValues); + } + } + } + $( "#yang-modules-browser-dialog" ).dialog('close'); + console.log('success'); + //console.log(JSON.stringify(data)); + }, + error: function(error) { + RED.notify("Failed to load modules."); + console.log("some error in fetching the notifications"); + } + }); + } + }, + { + text: "Close", + click: function() { + $(this).dialog("close"); + } + } + ] + }).html(html); + $("#yang-modules-browser-dialog").show(); + }) + .fail(function(err) { + RED.notify("Failed to get yang modules."); + }) + .always(function() { + console.log("Done displaying"); + }); + } + + + $(function() { + RED.menu.init({id:"btn-sidemenu", + options: [ + {id:"btn-sidebar",icon:"fa fa-columns",label:"Sidebar (Ctrl+Space)",toggle:true,onselect:RED.sidebar.toggleSidebar}, + null, + {id:"btn-manage-yang-modules-menu",icon:"fa fa-sign-in",label:"Manage Yang Modules",options:[ + {id:"btn-yang-upload",icon:"fa fa-clipboard",label:"Upload Yang File",onselect:RED.view.showYangUploadDialog}, + {id:"btn-available-yang-modules",icon:"fa fa-clipboard",label:"Available Yang Modules",onselect:showAvailableYangModules}, + {id:"btn-list-yang-files",icon:"fa fa-clipboard",label:"List Yang Files",onselect:listYangFiles}, + ]}, + null, + {id:"btn-configure-upload",icon:"fa fa-book",label:"Configuration",toggle:false,onselect:updateConfiguration}, + null, + {id:"btn-manage-tabs",icon:"fa fa-info",label:"Manage Tabs",toggle:false,onselect:showSelectedTabs}, + null, + {id:"btn-search-text",icon:"fa fa-info",label:"Search Text (Ctrl+[)",toggle:false,onselect:RED.view.showSearchTextDialog}, + null, + {id:"btn-find-dgnumber",icon:"fa fa-info",label:"Find Node (Ctrl+B)",toggle:false,onselect:RED.view.showDgNumberDialog}, + null, + {id:"btn-request-input",icon:"fa fa-info",label:"RPC Input (Ctrl+O)",toggle:false,onselect:RED.view.showRequestTemplateDialog}, + null, + {id:"btn-node-status",icon:"fa fa-info",label:"Node Status",toggle:true,onselect:toggleStatus}, + null, + {id:"btn-node-dgnumber",icon:"fa fa-info",label:"Show Node Numbers",toggle:true,onselect:toggleDgNumberDisplay}, + null, + {id:"btn-node-panel",icon:"fa fa-columns",label:"Node Palette (Ctrl+M)",toggle:true,onselect:toggleNodePaletteDisplay}, + null, + {id:"btn-node-viewdgs",icon:"fa fa-info",label:"View All DG List",toggle:false,onselect:displayAllDGs}, + null, + /* + {id:"btn-node-gitmenu",icon:"fa fa-info",label:"Git Commands",options: [ + {id:"btn-node-gitcheckout",icon:"fa fa-info",label:"Git Checkout",onselect:showGitCheckoutDialog}, + {id:"btn-node-gitpull",icon:"fa fa-info",label:"Git Pull",onselect:showGitPullDialog}, + {id:"btn-node-gitstatus",icon:"fa fa-info",label:"Git Status",onselect:showGitStatusDialog} + ]}, + null, + */ + {id:"btn-import-menu",icon:"fa fa-sign-in",label:"Import...",options:[ + /*{id:"btn-import-codecloud",icon:"fa fa-clipboard",label:"Code Cloud",onselect:showCodeCloudFlows}, + */ + {id:"btn-import-codecloud",icon:"fa fa-clipboard",label:"Git Local Repository",onselect:showGitLocalFlows}, + {id:"btn-import-userflows",icon:"fa fa-clipboard",label:"Downloaded DG Flows...",onselect:showFlowShareUsers}, + {id:"btn-import-clipboard",icon:"fa fa-clipboard",label:"Clipboard...",onselect:RED.view.showImportNodesDialog}, + {id:"btn-import-library",icon:"fa fa-book",label:"Library",options:[]} + ]}, + {id:"btn-export-menu",icon:"fa fa-sign-out",label:"Export...",disabled:true,options:[ + {id:"btn-export-clipboard",icon:"fa fa-clipboard",label:"Clipboard...",disabled:true,onselect:RED.view.showExportNodesDialog}, + {id:"btn-export-library",icon:"fa fa-book",label:"Library...",disabled:true,onselect:RED.view.showExportNodesLibraryDialog} + ]}, + null, + {id:"btn-change-password",icon:"fa fa-columns",label:"Change Password",toggle:false,onselect:updatePassword}, + null, + /*{id:"btn-config-nodes",icon:"fa fa-th-list",label:"Configuration nodes...",onselect:RED.sidebar.config.show}, + null,*/ + {id:"btn-workspace-menu",icon:"fa fa-th-large",label:"Workspaces",options:[ + {id:"btn-workspace-add",icon:"fa fa-plus",label:"Add"}, + {id:"btn-workspace-edit",icon:"fa fa-pencil",label:"Rename"}, + {id:"btn-workspace-delete",icon:"fa fa-minus",label:"Delete"}, + null + ]}, + null, + {id:"btn-keyboard-shortcuts",icon:"fa fa-keyboard-o",label:"Keyboard Shortcuts",onselect:showHelp} + /*{id:"btn-help",icon:"fa fa-question",label:"Help...", href:"http://nodered.org/docs"}*/ + ] + }); + + //Making default loop detection on and display check mark in the menu + //$("#btn-loop-detection").addClass("active"); + + RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); + loadSettings(); + RED.comms.connect(); + }); + + return { + }; +})(); diff --git a/dgbuilder/public/red/main.js.orig b/dgbuilder/public/red/main.js.orig new file mode 100644 index 00000000..a47e9958 --- /dev/null +++ b/dgbuilder/public/red/main.js.orig @@ -0,0 +1,323 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var RED = (function() { + + function hideDropTarget() { + $("#dropTarget").hide(); + RED.keyboard.remove(/* ESCAPE */ 27); + } + + $('#chart').on("dragenter",function(event) { + if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { + $("#dropTarget").css({display:'table'}); + RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget); + } + }); + + $('#dropTarget').on("dragover",function(event) { + if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) { + event.preventDefault(); + } + }) + .on("dragleave",function(event) { + hideDropTarget(); + }) + .on("drop",function(event) { + var data = event.originalEvent.dataTransfer.getData("text/plain"); + hideDropTarget(); + RED.view.importNodes(data); + event.preventDefault(); + }); + + function save(force) { + if (RED.view.dirty()) { + //$("#debug-tab-clear").click(); // uncomment this to auto clear debug on deploy + + if (!force) { + var invalid = false; + var unknownNodes = []; + RED.nodes.eachNode(function(node) { + invalid = invalid || !node.valid; + if (node.type === "unknown") { + if (unknownNodes.indexOf(node.name) == -1) { + unknownNodes.push(node.name); + } + invalid = true; + } + }); + if (invalid) { + if (unknownNodes.length > 0) { + $( "#node-dialog-confirm-deploy-config" ).hide(); + $( "#node-dialog-confirm-deploy-unknown" ).show(); + var list = "<li>"+unknownNodes.join("</li><li>")+"</li>"; + $( "#node-dialog-confirm-deploy-unknown-list" ).html(list); + } else { + $( "#node-dialog-confirm-deploy-config" ).show(); + $( "#node-dialog-confirm-deploy-unknown" ).hide(); + } + $( "#node-dialog-confirm-deploy" ).dialog( "open" ); + return; + } + } + var nns = RED.nodes.createCompleteNodeSet(); + + $("#btn-icn-deploy").removeClass('fa-download'); + $("#btn-icn-deploy").addClass('spinner'); + RED.view.dirty(false); + + $.ajax({ + url:"flows", + type: "POST", + data: JSON.stringify(nns), + contentType: "application/json; charset=utf-8" + }).done(function(data,textStatus,xhr) { + RED.notify("Successfully deployed","success"); + RED.nodes.eachNode(function(node) { + if (node.changed) { + node.dirty = true; + node.changed = false; + } + if(node.credentials) { + delete node.credentials; + } + }); + RED.nodes.eachConfig(function (confNode) { + if (confNode.credentials) { + delete confNode.credentials; + } + }); + // Once deployed, cannot undo back to a clean state + RED.history.markAllDirty(); + RED.view.redraw(); + }).fail(function(xhr,textStatus,err) { + RED.view.dirty(true); + if (xhr.responseText) { + RED.notify("<strong>Error</strong>: "+xhr.responseText,"error"); + } else { + RED.notify("<strong>Error</strong>: no response from server","error"); + } + }).always(function() { + $("#btn-icn-deploy").removeClass('spinner'); + $("#btn-icn-deploy").addClass('fa-download'); + }); + } + } + + $('#btn-deploy').click(function() { save(); }); + + $( "#node-dialog-confirm-deploy" ).dialog({ + title: "Confirm deploy", + modal: true, + autoOpen: false, + width: 530, + height: 230, + buttons: [ + { + text: "Confirm deploy", + click: function() { + save(true); + $( this ).dialog( "close" ); + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ] + }); + + function loadSettings() { + $.get('settings', function(data) { + RED.settings = data; + console.log("Node-RED: "+data.version); + loadNodeList(); + }); + } + function loadNodeList() { + $.ajax({ + headers: { + "Accept":"application/json" + }, + cache: false, + url: 'nodes', + success: function(data) { + RED.nodes.setNodeList(data); + loadNodes(); + } + }); + } + + function loadNodes() { + $.ajax({ + headers: { + "Accept":"text/html" + }, + cache: false, + url: 'nodes', + success: function(data) { + $("body").append(data); + $(".palette-spinner").hide(); + $(".palette-scroll").show(); + $("#palette-search").show(); + loadFlows(); + } + }); + } + + function loadFlows() { + $.ajax({ + headers: { + "Accept":"application/json" + }, + cache: false, + url: 'flows', + success: function(nodes) { + RED.nodes.import(nodes); + RED.view.dirty(false); + RED.view.redraw(); + RED.comms.subscribe("status/#",function(topic,msg) { + var parts = topic.split("/"); + var node = RED.nodes.node(parts[1]); + if (node) { + node.status = msg; + if (statusEnabled) { + node.dirty = true; + RED.view.redraw(); + } + } + }); + RED.comms.subscribe("node/#",function(topic,msg) { + var i,m; + var typeList; + var info; + + if (topic == "node/added") { + var addedTypes = []; + for (i=0;i<msg.length;i++) { + m = msg[i]; + var id = m.id; + RED.nodes.addNodeSet(m); + if (m.loaded) { + addedTypes = addedTypes.concat(m.types); + $.get('nodes/'+id, function(data) { + $("body").append(data); + }); + } + } + if (addedTypes.length) { + typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>"; + RED.notify("Node"+(addedTypes.length!=1 ? "s":"")+" added to palette:"+typeList,"success"); + } + } else if (topic == "node/removed") { + for (i=0;i<msg.length;i++) { + m = msg[i]; + info = RED.nodes.removeNodeSet(m.id); + if (info.added) { + typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>"; + RED.notify("Node"+(m.types.length!=1 ? "s":"")+" removed from palette:"+typeList,"success"); + } + } + } else if (topic == "node/enabled") { + if (msg.types) { + info = RED.nodes.getNodeSet(msg.id); + if (info.added) { + RED.nodes.enableNodeSet(msg.id); + typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; + RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" enabled:"+typeList,"success"); + } else { + $.get('nodes/'+msg.id, function(data) { + $("body").append(data); + typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; + RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" added to palette:"+typeList,"success"); + }); + } + } + } else if (topic == "node/disabled") { + if (msg.types) { + RED.nodes.disableNodeSet(msg.id); + typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; + RED.notify("Node"+(msg.types.length!=1 ? "s":"")+" disabled:"+typeList,"success"); + } + } + }); + } + }); + } + + var statusEnabled = false; + function toggleStatus(state) { + statusEnabled = state; + RED.view.status(statusEnabled); + } + + function showHelp() { + + var dialog = $('#node-help'); + + //$("#node-help").draggable({ + // handle: ".modal-header" + //}); + + dialog.on('show',function() { + RED.keyboard.disable(); + }); + dialog.on('hidden',function() { + RED.keyboard.enable(); + }); + + dialog.modal(); + } + + $(function() { + RED.menu.init({id:"btn-sidemenu", + options: [ + {id:"btn-sidebar",icon:"fa fa-columns",label:"Sidebar",toggle:true,onselect:RED.sidebar.toggleSidebar}, + null, + {id:"btn-node-status",icon:"fa fa-info",label:"Node Status",toggle:true,onselect:toggleStatus}, + null, + {id:"btn-import-menu",icon:"fa fa-sign-in",label:"Import...",options:[ + {id:"btn-import-clipboard",icon:"fa fa-clipboard",label:"Clipboard...",onselect:RED.view.showImportNodesDialog}, + {id:"btn-import-library",icon:"fa fa-book",label:"Library",options:[]} + ]}, + {id:"btn-export-menu",icon:"fa fa-sign-out",label:"Export...",disabled:true,options:[ + {id:"btn-export-clipboard",icon:"fa fa-clipboard",label:"Clipboard...",disabled:true,onselect:RED.view.showExportNodesDialog}, + {id:"btn-export-library",icon:"fa fa-book",label:"Library...",disabled:true,onselect:RED.view.showExportNodesLibraryDialog} + ]}, + null, + {id:"btn-config-nodes",icon:"fa fa-th-list",label:"Configuration nodes...",onselect:RED.sidebar.config.show}, + null, + {id:"btn-workspace-menu",icon:"fa fa-th-large",label:"Workspaces",options:[ + {id:"btn-workspace-add",icon:"fa fa-plus",label:"Add"}, + {id:"btn-workspace-edit",icon:"fa fa-pencil",label:"Rename"}, + {id:"btn-workspace-delete",icon:"fa fa-minus",label:"Delete"}, + null + ]}, + null, + {id:"btn-keyboard-shortcuts",icon:"fa fa-keyboard-o",label:"Keyboard Shortcuts",onselect:showHelp}, + {id:"btn-help",icon:"fa fa-question",label:"Help...", href:"http://nodered.org/docs"} + ] + }); + + RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); + loadSettings(); + RED.comms.connect(); + }); + + return { + }; +})(); diff --git a/dgbuilder/public/red/nodes.js b/dgbuilder/public/red/nodes.js new file mode 100644 index 00000000..dc0827a6 --- /dev/null +++ b/dgbuilder/public/red/nodes.js @@ -0,0 +1,553 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.nodes = (function() { + + var node_defs = {}; + var nodes = []; + var configNodes = {}; + var links = []; + var defaultWorkspace; + var workspaces = {}; + + var registry = (function() { + var nodeList = []; + var nodeSets = {}; + var typeToId = {}; + var nodeDefinitions = {}; + + var exports = { + getNodeList: function() { + return nodeList; + }, + setNodeList: function(list) { + nodeList = []; + for(var i=0;i<list.length;i++) { + var ns = list[i]; + exports.addNodeSet(ns); + } + }, + addNodeSet: function(ns) { + ns.added = false; + nodeSets[ns.id] = ns; + for (var j=0;j<ns.types.length;j++) { + typeToId[ns.types[j]] = ns.id; + } + nodeList.push(ns); + }, + removeNodeSet: function(id) { + var ns = nodeSets[id]; + for (var j=0;j<ns.types.length;j++) { + if (ns.added) { + // TODO: too tightly coupled into palette UI + RED.palette.remove(ns.types[j]); + var def = nodeDefinitions[ns.types[j]]; + if (def.onpaletteremove && typeof def.onpaletteremove === "function") { + def.onpaletteremove.call(def); + } + } + delete typeToId[ns.types[j]]; + } + delete nodeSets[id]; + for (var i=0;i<nodeList.length;i++) { + if (nodeList[i].id == id) { + nodeList.splice(i,1); + break; + } + } + return ns; + }, + getNodeSet: function(id) { + return nodeSets[id]; + }, + enableNodeSet: function(id) { + var ns = nodeSets[id]; + ns.enabled = true; + for (var j=0;j<ns.types.length;j++) { + // TODO: too tightly coupled into palette UI + RED.palette.show(ns.types[j]); + var def = nodeDefinitions[ns.types[j]]; + if (def.onpaletteadd && typeof def.onpaletteadd === "function") { + def.onpaletteadd.call(def); + } + } + }, + disableNodeSet: function(id) { + var ns = nodeSets[id]; + ns.enabled = false; + for (var j=0;j<ns.types.length;j++) { + // TODO: too tightly coupled into palette UI + RED.palette.hide(ns.types[j]); + var def = nodeDefinitions[ns.types[j]]; + if (def.onpaletteremove && typeof def.onpaletteremove === "function") { + def.onpaletteremove.call(def); + } + } + }, + registerNodeType: function(nt,def) { + nodeDefinitions[nt] = def; + nodeSets[typeToId[nt]].added = true; + // TODO: too tightly coupled into palette UI + RED.palette.add(nt,def); + if (def.onpaletteadd && typeof def.onpaletteadd === "function") { + def.onpaletteadd.call(def); + } + }, + getNodeType: function(nt) { + return nodeDefinitions[nt]; + } + }; + return exports; + })(); + + function getID() { + return (1+Math.random()*4294967295).toString(16); + } + + function addNode(n) { + if (n._def.category == "config") { + configNodes[n.id] = n; + RED.sidebar.config.refresh(); + } else { + n.dirty = true; + nodes.push(n); + var updatedConfigNode = false; + for (var d in n._def.defaults) { + if (n._def.defaults.hasOwnProperty(d)) { + var property = n._def.defaults[d]; + if (property.type) { + var type = registry.getNodeType(property.type); + if (type && type.category == "config") { + var configNode = configNodes[n[d]]; + if (configNode) { + updatedConfigNode = true; + configNode.users.push(n); + } + } + } + } + } + if (updatedConfigNode) { + RED.sidebar.config.refresh(); + } + } + } + function addLink(l) { + links.push(l); + } + function addConfig(c) { + configNodes[c.id] = c; + } + + function getNode(id) { + if (id in configNodes) { + return configNodes[id]; + } else { + for (var n in nodes) { + if (nodes[n].id == id) { + return nodes[n]; + } + } + } + return null; + } + + function removeNode(id) { + var removedLinks = []; + if (id in configNodes) { + delete configNodes[id]; + RED.sidebar.config.refresh(); + } else { + var node = getNode(id); + if (node) { + nodes.splice(nodes.indexOf(node),1); + removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); }); + removedLinks.map(function(l) {links.splice(links.indexOf(l), 1); }); + } + var updatedConfigNode = false; + for (var d in node._def.defaults) { + if (node._def.defaults.hasOwnProperty(d)) { + var property = node._def.defaults[d]; + if (property.type) { + var type = registry.getNodeType(property.type); + if (type && type.category == "config") { + var configNode = configNodes[node[d]]; + if (configNode) { + updatedConfigNode = true; + var users = configNode.users; + users.splice(users.indexOf(node),1); + } + } + } + } + } + if (updatedConfigNode) { + RED.sidebar.config.refresh(); + } + } + return removedLinks; + } + + function removeLink(l) { + var index = links.indexOf(l); + if (index != -1) { + links.splice(index,1); + } + } + + function refreshValidation() { + for (var n=0;n<nodes.length;n++) { + RED.editor.validateNode(nodes[n]); + } + } + + function addWorkspace(ws) { + workspaces[ws.id] = ws; + } + function getWorkspace(id) { + return workspaces[id]; + } + function removeWorkspace(id) { + delete workspaces[id]; + var removedNodes = []; + var removedLinks = []; + var n; + for (n=0;n<nodes.length;n++) { + var node = nodes[n]; + if (node.z == id) { + removedNodes.push(node); + } + } + for (n=0;n<removedNodes.length;n++) { + var rmlinks = removeNode(removedNodes[n].id); + removedLinks = removedLinks.concat(rmlinks); + } + return {nodes:removedNodes,links:removedLinks}; + } + + function getAllFlowNodes(node) { + var visited = {}; + visited[node.id] = true; + var nns = [node]; + var stack = [node]; + while(stack.length !== 0) { + var n = stack.shift(); + var childLinks = links.filter(function(d) { return (d.source === n) || (d.target === n);}); + for (var i=0;i<childLinks.length;i++) { + var child = (childLinks[i].source === n)?childLinks[i].target:childLinks[i].source; + if (!visited[child.id]) { + visited[child.id] = true; + nns.push(child); + stack.push(child); + } + } + } + return nns; + } + + /** + * Converts a node to an exportable JSON Object + **/ + function convertNode(n, exportCreds) { + exportCreds = exportCreds || false; + var node = {}; + node.id = n.id; + node.type = n.type; + for (var d in n._def.defaults) { + if (n._def.defaults.hasOwnProperty(d)) { + node[d] = n[d]; + } + } + if(exportCreds && n.credentials) { + node.credentials = {}; + for (var cred in n._def.credentials) { + if (n._def.credentials.hasOwnProperty(cred)) { + if (n.credentials[cred] != null) { + node.credentials[cred] = n.credentials[cred]; + } + } + } + } + if (n._def.category != "config") { + node.x = n.x; + node.y = n.y; + node.z = n.z; + node.wires = []; + for(var i=0;i<n.outputs;i++) { + node.wires.push([]); + } + var wires = links.filter(function(d){return d.source === n;}); + for (var j=0;j<wires.length;j++) { + var w = wires[j]; + node.wires[w.sourcePort].push(w.target.id); + } + } + return node; + } + + /** + * Converts the current node selection to an exportable JSON Object + **/ + function createExportableNodeSet(set) { + var nns = []; + var exportedConfigNodes = {}; + for (var n=0;n<set.length;n++) { + var node = set[n].n; + var convertedNode = RED.nodes.convertNode(node); + for (var d in node._def.defaults) { + if (node._def.defaults[d].type && node[d] in configNodes) { + var confNode = configNodes[node[d]]; + var exportable = registry.getNodeType(node._def.defaults[d].type).exportable; + if ((exportable == null || exportable)) { + if (!(node[d] in exportedConfigNodes)) { + exportedConfigNodes[node[d]] = true; + nns.unshift(RED.nodes.convertNode(confNode)); + } + } else { + convertedNode[d] = ""; + } + } + } + + nns.push(convertedNode); + } + return nns; + } + + //TODO: rename this (createCompleteNodeSet) + function createCompleteNodeSet() { + var nns = []; + var i; + for (i in workspaces) { + if (workspaces.hasOwnProperty(i)) { + nns.push(workspaces[i]); + } + } + for (i in configNodes) { + if (configNodes.hasOwnProperty(i)) { + nns.push(convertNode(configNodes[i], true)); + } + } + for (i=0;i<nodes.length;i++) { + var node = nodes[i]; + nns.push(convertNode(node, true)); + } + return nns; + } + + function importNodes(newNodesObj,createNewIds) { + try { + var i; + var n; + var newNodes; + if (typeof newNodesObj === "string") { + if (newNodesObj === "") { + return; + } + newNodes = JSON.parse(newNodesObj); + } else { + newNodes = newNodesObj; + } + + if (!$.isArray(newNodes)) { + newNodes = [newNodes]; + } + var unknownTypes = []; + for (i=0;i<newNodes.length;i++) { + n = newNodes[i]; + // TODO: remove workspace in next release+1 + if (n.type != "workspace" && n.type != "tab" && !registry.getNodeType(n.type)) { + // TODO: get this UI thing out of here! (see below as well) + n.name = n.type; + n.type = "unknown"; + if (unknownTypes.indexOf(n.name)==-1) { + unknownTypes.push(n.name); + } + if (n.x == null && n.y == null) { + // config node - remove it + newNodes.splice(i,1); + i--; + } + } + } + if (unknownTypes.length > 0) { + var typeList = "<ul><li>"+unknownTypes.join("</li><li>")+"</li></ul>"; + var type = "type"+(unknownTypes.length > 1?"s":""); + RED.notify("<strong>Imported unrecognised "+type+":</strong>"+typeList,"error",false,10000); + //"DO NOT DEPLOY while in this state.<br/>Either, add missing types to Node-RED, restart and then reload page,<br/>or delete unknown "+n.name+", rewire as required, and then deploy.","error"); + } + + var new_workspaces = []; + var workspace_map = {}; + + for (i=0;i<newNodes.length;i++) { + n = newNodes[i]; + // TODO: remove workspace in next release+1 + if (n.type === "workspace" || n.type === "tab") { + if (n.type === "workspace") { + n.type = "tab"; + } + if (defaultWorkspace == null) { + defaultWorkspace = n; + } + if (createNewIds) { + var nid = getID(); + workspace_map[n.id] = nid; + n.id = nid; + } + addWorkspace(n); + RED.view.addWorkspace(n); + new_workspaces.push(n); + } + } + if (defaultWorkspace == null) { + defaultWorkspace = { type:"tab", id:getID(), label:"Sheet 1" }; + addWorkspace(defaultWorkspace); + RED.view.addWorkspace(defaultWorkspace); + new_workspaces.push(defaultWorkspace); + } + + var node_map = {}; + var new_nodes = []; + var new_links = []; + + for (i=0;i<newNodes.length;i++) { + n = newNodes[i]; + // TODO: remove workspace in next release+1 + if (n.type !== "workspace" && n.type !== "tab") { + var def = registry.getNodeType(n.type); + if (def && def.category == "config") { + if (!RED.nodes.node(n.id)) { + var configNode = {id:n.id,type:n.type,users:[]}; + for (var d in def.defaults) { + if (def.defaults.hasOwnProperty(d)) { + configNode[d] = n[d]; + } + } + configNode.label = def.label; + configNode._def = def; + RED.nodes.add(configNode); + } + } else { + var node = {x:n.x,y:n.y,z:n.z,type:0,wires:n.wires,changed:false}; + if (createNewIds) { + node.z = workspace_map[node.z]; + if (!workspaces[node.z]) { + node.z = RED.view.getWorkspace(); + } + node.id = getID(); + } else { + node.id = n.id; + if (node.z == null || !workspaces[node.z]) { + node.z = RED.view.getWorkspace(); + } + } + node.type = n.type; + node._def = def; + if (!node._def) { + node._def = { + color:"#fee", + defaults: {}, + label: "unknown: "+n.type, + labelStyle: "node_label_italic", + outputs: n.outputs||n.wires.length + } + } + node.outputs = n.outputs||node._def.outputs; + + for (var d2 in node._def.defaults) { + if (node._def.defaults.hasOwnProperty(d2)) { + node[d2] = n[d2]; + } + } + + addNode(node); + RED.editor.validateNode(node); + node_map[n.id] = node; + new_nodes.push(node); + } + } + } + for (i=0;i<new_nodes.length;i++) { + n = new_nodes[i]; + for (var w1=0;w1<n.wires.length;w1++) { + var wires = (n.wires[w1] instanceof Array)?n.wires[w1]:[n.wires[w1]]; + for (var w2=0;w2<wires.length;w2++) { + if (wires[w2] in node_map) { + var link = {source:n,sourcePort:w1,target:node_map[wires[w2]]}; + addLink(link); + new_links.push(link); + } + } + } + delete n.wires; + } + return [new_nodes,new_links,new_workspaces]; + } catch(error) { + //TODO: get this UI thing out of here! (see above as well) + RED.notify("<strong>Error</strong>: "+error,"error"); + return null; + } + + } + + return { + registry:registry, + setNodeList: registry.setNodeList, + + getNodeSet: registry.getNodeSet, + addNodeSet: registry.addNodeSet, + removeNodeSet: registry.removeNodeSet, + enableNodeSet: registry.enableNodeSet, + disableNodeSet: registry.disableNodeSet, + + registerType: registry.registerNodeType, + getType: registry.getNodeType, + convertNode: convertNode, + add: addNode, + addLink: addLink, + remove: removeNode, + removeLink: removeLink, + addWorkspace: addWorkspace, + removeWorkspace: removeWorkspace, + workspace: getWorkspace, + eachNode: function(cb) { + for (var n=0;n<nodes.length;n++) { + cb(nodes[n]); + } + }, + eachLink: function(cb) { + for (var l=0;l<links.length;l++) { + cb(links[l]); + } + }, + eachConfig: function(cb) { + for (var id in configNodes) { + if (configNodes.hasOwnProperty(id)) { + cb(configNodes[id]); + } + } + }, + node: getNode, + import: importNodes, + refreshValidation: refreshValidation, + getAllFlowNodes: getAllFlowNodes, + createExportableNodeSet: createExportableNodeSet, + createCompleteNodeSet: createCompleteNodeSet, + id: getID, + nodes: nodes, // TODO: exposed for d3 vis + links: links // TODO: exposed for d3 vis + }; +})(); diff --git a/dgbuilder/public/red/ui/editor.js b/dgbuilder/public/red/ui/editor.js new file mode 100644 index 00000000..c5f7986e --- /dev/null +++ b/dgbuilder/public/red/ui/editor.js @@ -0,0 +1,665 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.editor = (function() { + var editing_node = null; + // TODO: should IMPORT/EXPORT get their own dialogs? + + function getCredentialsURL(nodeType, nodeID) { + var dashedType = nodeType.replace(/\s+/g, '-'); + return 'credentials/' + dashedType + "/" + nodeID; + } + + /** + * Validate a node + * @param node - the node being validated + * @returns {boolean} whether the node is valid. Sets node.dirty if needed + */ + function validateNode(node) { + var oldValue = node.valid; + node.valid = validateNodeProperties(node, node._def.defaults, node); + if (node._def._creds) { + node.valid = node.valid && validateNodeProperties(node, node._def.credentials, node._def._creds); + } + if (oldValue != node.valid) { + node.dirty = true; + } + } + + /** + * Validate a node's properties for the given set of property definitions + * @param node - the node being validated + * @param definition - the node property definitions (either def.defaults or def.creds) + * @param properties - the node property values to validate + * @returns {boolean} whether the node's properties are valid + */ + function validateNodeProperties(node, definition, properties) { + var isValid = true; + for (var prop in definition) { + if (definition.hasOwnProperty(prop)) { + if (!validateNodeProperty(node, definition, prop, properties[prop])) { + isValid = false; + } + } + } + return isValid; + } + + /** + * Validate a individual node property + * @param node - the node being validated + * @param definition - the node property definitions (either def.defaults or def.creds) + * @param property - the property name being validated + * @param value - the property value being validated + * @returns {boolean} whether the node proprty is valid + */ + function validateNodeProperty(node,definition,property,value) { + var valid = true; + if ("required" in definition[property] && definition[property].required) { + valid = value !== ""; + } + if (valid && "validate" in definition[property]) { + valid = definition[property].validate.call(node,value); + } + if (valid && definition[property].type && RED.nodes.getType(definition[property].type) && !("validate" in definition[property])) { + if (!value || value == "_ADD_") { + valid = false; + } else { + var v = RED.nodes.node(value).valid; + valid = (v==null || v); + } + } + return valid; + } + + /** + * Called when the node's properties have changed. + * Marks the node as dirty and needing a size check. + * Removes any links to non-existant outputs. + * @param node - the node that has been updated + * @returns {array} the links that were removed due to this update + */ + function updateNodeProperties(node) { + node.resize = true; + node.dirty = true; + var removedLinks = []; + if (node.outputs < node.ports.length) { + while (node.outputs < node.ports.length) { + node.ports.pop(); + } + RED.nodes.eachLink(function(l) { + if (l.source === node && l.sourcePort >= node.outputs) { + removedLinks.push(l); + } + }); + for (var l=0;l<removedLinks.length;l++) { + RED.nodes.removeLink(removedLinks[l]); + } + } else if (node.outputs > node.ports.length) { + while (node.outputs > node.ports.length) { + node.ports.push(node.ports.length); + } + } + return removedLinks; + } + + + + $( "#dialog" ).dialog({ + modal: true, + autoOpen: false, + closeOnEscape: false, + width: 500, + buttons: [ + { + id: "node-dialog-ok", + text: "Ok", + click: function() { + if (editing_node) { + var changes = {}; + var changed = false; + var wasDirty = RED.view.dirty(); + var d; + + if (editing_node._def.oneditsave) { + var oldValues = {}; + for (d in editing_node._def.defaults) { + if (editing_node._def.defaults.hasOwnProperty(d)) { + if (typeof editing_node[d] === "string" || typeof editing_node[d] === "number") { + oldValues[d] = editing_node[d]; + } else { + oldValues[d] = $.extend(true,{},{v:editing_node[d]}).v; + } + } + } + var rc = editing_node._def.oneditsave.call(editing_node); + if (rc === true) { + changed = true; + } + + for (d in editing_node._def.defaults) { + if (editing_node._def.defaults.hasOwnProperty(d)) { + if (oldValues[d] === null || typeof oldValues[d] === "string" || typeof oldValues[d] === "number") { + if (oldValues[d] !== editing_node[d]) { + changes[d] = oldValues[d]; + changed = true; + } + } else { + if (JSON.stringify(oldValues[d]) !== JSON.stringify(editing_node[d])) { + changes[d] = oldValues[d]; + changed = true; + } + } + } + } + + + } + + if (editing_node._def.defaults) { + for (d in editing_node._def.defaults) { + if (editing_node._def.defaults.hasOwnProperty(d)) { + var input = $("#node-input-"+d); + var newValue; + if (input.attr('type') === "checkbox") { + newValue = input.prop('checked'); + } else { + newValue = input.val(); + } + if (newValue != null) { + if (editing_node[d] != newValue) { + if (editing_node._def.defaults[d].type) { + if (newValue == "_ADD_") { + newValue = ""; + } + // Change to a related config node + var configNode = RED.nodes.node(editing_node[d]); + if (configNode) { + var users = configNode.users; + users.splice(users.indexOf(editing_node),1); + } + configNode = RED.nodes.node(newValue); + if (configNode) { + configNode.users.push(editing_node); + } + } + + changes[d] = editing_node[d]; + editing_node[d] = newValue; + changed = true; + } + } + } + } + } + if (editing_node._def.credentials) { + var prefix = 'node-input'; + var credDefinition = editing_node._def.credentials; + var credsChanged = updateNodeCredentials(editing_node,credDefinition,prefix); + changed = changed || credsChanged; + } + + + var removedLinks = updateNodeProperties(editing_node); + if (changed) { + var wasChanged = editing_node.changed; + editing_node.changed = true; + RED.view.dirty(true); + RED.history.push({t:'edit',node:editing_node,changes:changes,links:removedLinks,dirty:wasDirty,changed:wasChanged}); + } + editing_node.dirty = true; + validateNode(editing_node); + RED.view.redraw(); + } else if (RED.view.state() == RED.state.EXPORT) { + if (/library/.test($( "#dialog" ).dialog("option","title"))) { + //TODO: move this to RED.library + var flowName = $("#node-input-filename").val(); + if (!/^\s*$/.test(flowName)) { + $.post('library/flows/'+flowName,$("#node-input-filename").attr('nodes'),function() { + RED.library.loadFlowLibrary(); + RED.notify("Saved nodes","success"); + }); + } + } + } else if (RED.view.state() == RED.state.IMPORT) { + RED.view.importNodes($("#node-input-import").val()); + } + $( this ).dialog( "close" ); + } + }, + { + id: "node-dialog-cancel", + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + resize: function(e,ui) { + if (editing_node) { + $(this).dialog('option',"sizeCache-"+editing_node.type,ui.size); + } + }, + open: function(e) { + RED.keyboard.disable(); + if (editing_node) { + var size = $(this).dialog('option','sizeCache-'+editing_node.type); + if (size) { + $(this).dialog('option','width',size.width); + $(this).dialog('option','height',size.height); + } + } + }, + close: function(e) { + RED.keyboard.enable(); + + if (RED.view.state() != RED.state.IMPORT_DRAGGING) { + RED.view.state(RED.state.DEFAULT); + } + $( this ).dialog('option','height','auto'); + $( this ).dialog('option','width','500'); + if (editing_node) { + RED.sidebar.info.refresh(editing_node); + } + RED.sidebar.config.refresh(); + editing_node = null; + } + }); + + /** + * Create a config-node select box for this property + * @param node - the node being edited + * @param property - the name of the field + * @param type - the type of the config-node + */ + function prepareConfigNodeSelect(node,property,type) { + var input = $("#node-input-"+property); + var node_def = RED.nodes.getType(type); + + input.replaceWith('<select style="width: 60%;" id="node-input-'+property+'"></select>'); + updateConfigNodeSelect(property,type,node[property]); + var select = $("#node-input-"+property); + select.after(' <a id="node-input-lookup-'+property+'" class="btn"><i class="fa fa-pencil"></i></a>'); + $('#node-input-lookup-'+property).click(function(e) { + showEditConfigNodeDialog(property,type,select.find(":selected").val()); + e.preventDefault(); + }); + var label = ""; + var configNode = RED.nodes.node(node[property]); + if (configNode && node_def.label) { + if (typeof node_def.label == "function") { + label = node_def.label.call(configNode); + } else { + label = node_def.label; + } + } + input.val(label); + } + + /** + * Populate the editor dialog input field for this property + * @param node - the node being edited + * @param property - the name of the field + * @param prefix - the prefix to use in the input element ids (node-input|node-config-input) + */ + function preparePropertyEditor(node,property,prefix) { + var input = $("#"+prefix+"-"+property); + if (input.attr('type') === "checkbox") { + input.prop('checked',node[property]); + } else { + var val = node[property]; + if (val == null) { + val = ""; + } + input.val(val); + } + } + + /** + * Add an on-change handler to revalidate a node field + * @param node - the node being edited + * @param definition - the definition of the node + * @param property - the name of the field + * @param prefix - the prefix to use in the input element ids (node-input|node-config-input) + */ + function attachPropertyChangeHandler(node,definition,property,prefix) { + $("#"+prefix+"-"+property).change(function() { + if (!validateNodeProperty(node, definition, property,this.value)) { + $(this).addClass("input-error"); + } else { + $(this).removeClass("input-error"); + } + }); + } + + /** + * Assign the value to each credential field + * @param node + * @param credDef + * @param credData + * @param prefix + */ + function populateCredentialsInputs(node, credDef, credData, prefix) { + var cred; + for (cred in credDef) { + if (credDef.hasOwnProperty(cred)) { + if (credDef[cred].type == 'password') { + if (credData[cred]) { + $('#' + prefix + '-' + cred).val(credData[cred]); + } else if (credData['has_' + cred]) { + $('#' + prefix + '-' + cred).val('__PWRD__'); + } + else { + $('#' + prefix + '-' + cred).val(''); + } + } else { + preparePropertyEditor(credData, cred, prefix); + } + attachPropertyChangeHandler(node, credDef, cred, prefix); + } + } + for (cred in credDef) { + if (credDef.hasOwnProperty(cred)) { + $("#" + prefix + "-" + cred).change(); + } + } + } + + /** + * Update the node credentials from the edit form + * @param node - the node containing the credentials + * @param credDefinition - definition of the credentials + * @param prefix - prefix of the input fields + * @return {boolean} whether anything has changed + */ + function updateNodeCredentials(node, credDefinition, prefix) { + var changed = false; + if(!node.credentials) { + node.credentials = {_:{}}; + } + + for (var cred in credDefinition) { + if (credDefinition.hasOwnProperty(cred)) { + var input = $("#" + prefix + '-' + cred); + var value = input.val(); + if (credDefinition[cred].type == 'password') { + node.credentials['has_' + cred] = (value !== ""); + if (value == '__PWRD__') { + continue; + } + changed = true; + + } + node.credentials[cred] = value; + if (value != node.credentials._[cred]) { + changed = true; + } + } + } + return changed; + } + + /** + * Prepare all of the editor dialog fields + * @param node - the node being edited + * @param definition - the node definition + * @param prefix - the prefix to use in the input element ids (node-input|node-config-input) + */ + function prepareEditDialog(node,definition,prefix) { + for (var d in definition.defaults) { + if (definition.defaults.hasOwnProperty(d)) { + if (definition.defaults[d].type) { + prepareConfigNodeSelect(node,d,definition.defaults[d].type); + } else { + preparePropertyEditor(node,d,prefix); + } + attachPropertyChangeHandler(node,definition.defaults,d,prefix); + } + } + var completePrepare = function() { + if (definition.oneditprepare) { + definition.oneditprepare.call(node); + } + for (var d in definition.defaults) { + if (definition.defaults.hasOwnProperty(d)) { + $("#"+prefix+"-"+d).change(); + } + } + } + + if (definition.credentials) { + if (node.credentials) { + populateCredentialsInputs(node, definition.credentials, node.credentials, prefix); + completePrepare(); + } else { + $.getJSON(getCredentialsURL(node.type, node.id), function (data) { + node.credentials = data; + node.credentials._ = $.extend(true,{},data); + populateCredentialsInputs(node, definition.credentials, node.credentials, prefix); + completePrepare(); + }); + } + } else { + completePrepare(); + } + } + + function showEditDialog(node) { + editing_node = node; + RED.view.state(RED.state.EDITING); + $("#dialog-form").html($("script[data-template-name='"+node.type+"']").html()); + $('<input type="text" style="display: none;" />').appendTo("#dialog-form"); + prepareEditDialog(node,node._def,"node-input"); + $( "#dialog" ).dialog("option","title","Edit "+node.type+" node").dialog( "open" ); + } + + function showEditConfigNodeDialog(name,type,id) { + var adding = (id == "_ADD_"); + var node_def = RED.nodes.getType(type); + + var configNode = RED.nodes.node(id); + if (configNode == null) { + configNode = { + id: (1+Math.random()*4294967295).toString(16), + _def: node_def, + type: type + } + for (var d in node_def.defaults) { + if (node_def.defaults[d].value) { + configNode[d] = node_def.defaults[d].value; + } + } + } + + $("#dialog-config-form").html($("script[data-template-name='"+type+"']").html()); + prepareEditDialog(configNode,node_def,"node-config-input"); + + var buttons = $( "#node-config-dialog" ).dialog("option","buttons"); + if (adding) { + if (buttons.length == 3) { + buttons = buttons.splice(1); + } + buttons[0].text = "Add"; + $("#node-config-dialog-user-count").html("").hide(); + } else { + if (buttons.length == 2) { + buttons.unshift({ + class: 'leftButton', + text: "Delete", + click: function() { + var configProperty = $(this).dialog('option','node-property'); + var configId = $(this).dialog('option','node-id'); + var configType = $(this).dialog('option','node-type'); + var configNode = RED.nodes.node(configId); + var configTypeDef = RED.nodes.getType(configType); + + if (configTypeDef.ondelete) { + configTypeDef.ondelete.call(RED.nodes.node(configId)); + } + RED.nodes.remove(configId); + for (var i=0;i<configNode.users.length;i++) { + var user = configNode.users[i]; + for (var d in user._def.defaults) { + if (user._def.defaults.hasOwnProperty(d) && user[d] == configId) { + user[d] = ""; + } + } + validateNode(user); + } + updateConfigNodeSelect(configProperty,configType,""); + RED.view.dirty(true); + $( this ).dialog( "close" ); + RED.view.redraw(); + } + }); + } + buttons[1].text = "Update"; + $("#node-config-dialog-user-count").html(configNode.users.length+" node"+(configNode.users.length==1?" uses":"s use")+" this config").show(); + } + $( "#node-config-dialog" ).dialog("option","buttons",buttons); + + $( "#node-config-dialog" ) + .dialog("option","node-adding",adding) + .dialog("option","node-property",name) + .dialog("option","node-id",configNode.id) + .dialog("option","node-type",type) + .dialog("option","title",(adding?"Add new ":"Edit ")+type+" config node") + .dialog( "open" ); + } + + function updateConfigNodeSelect(name,type,value) { + var select = $("#node-input-"+name); + var node_def = RED.nodes.getType(type); + select.children().remove(); + RED.nodes.eachConfig(function(config) { + if (config.type == type) { + var label = ""; + if (typeof node_def.label == "function") { + label = node_def.label.call(config); + } else { + label = node_def.label; + } + select.append('<option value="'+config.id+'"'+(value==config.id?" selected":"")+'>'+label+'</option>'); + } + }); + + select.append('<option value="_ADD_"'+(value===""?" selected":"")+'>Add new '+type+'...</option>'); + window.setTimeout(function() { select.change();},50); + } + + $( "#node-config-dialog" ).dialog({ + modal: true, + autoOpen: false, + width: 500, + closeOnEscape: false, + buttons: [ + { + id: "node-config-dialog-ok", + text: "Ok", + click: function() { + var configProperty = $(this).dialog('option','node-property'); + var configId = $(this).dialog('option','node-id'); + var configType = $(this).dialog('option','node-type'); + var configAdding = $(this).dialog('option','node-adding'); + var configTypeDef = RED.nodes.getType(configType); + var configNode; + var d; + + if (configAdding) { + configNode = {type:configType,id:configId,users:[]}; + for (d in configTypeDef.defaults) { + if (configTypeDef.defaults.hasOwnProperty(d)) { + configNode[d] = $("#node-config-input-"+d).val(); + } + } + configNode.label = configTypeDef.label; + configNode._def = configTypeDef; + RED.nodes.add(configNode); + updateConfigNodeSelect(configProperty,configType,configNode.id); + } else { + configNode = RED.nodes.node(configId); + for (d in configTypeDef.defaults) { + if (configTypeDef.defaults.hasOwnProperty(d)) { + var input = $("#node-config-input-"+d); + if (input.attr('type') === "checkbox") { + configNode[d] = input.prop('checked'); + } else { + configNode[d] = input.val(); + } + } + } + updateConfigNodeSelect(configProperty,configType,configId); + } + if (configTypeDef.credentials) { + updateNodeCredentials(configNode,configTypeDef.credentials,"node-config-input"); + } + if (configTypeDef.oneditsave) { + configTypeDef.oneditsave.call(RED.nodes.node(configId)); + } + validateNode(configNode); + + RED.view.dirty(true); + $(this).dialog("close"); + + } + }, + { + id: "node-config-dialog-cancel", + text: "Cancel", + click: function() { + var configType = $(this).dialog('option','node-type'); + var configId = $(this).dialog('option','node-id'); + var configAdding = $(this).dialog('option','node-adding'); + var configTypeDef = RED.nodes.getType(configType); + + if (configTypeDef.oneditcancel) { + // TODO: what to pass as this to call + if (configTypeDef.oneditcancel) { + var cn = RED.nodes.node(configId); + if (cn) { + configTypeDef.oneditcancel.call(cn,false); + } else { + configTypeDef.oneditcancel.call({id:configId},true); + } + } + } + $( this ).dialog( "close" ); + } + } + ], + resize: function(e,ui) { + }, + open: function(e) { + if (RED.view.state() != RED.state.EDITING) { + RED.keyboard.disable(); + } + }, + close: function(e) { + $("#dialog-config-form").html(""); + if (RED.view.state() != RED.state.EDITING) { + RED.keyboard.enable(); + } + RED.sidebar.config.refresh(); + } + }); + + + return { + edit: showEditDialog, + editConfig: showEditConfigNodeDialog, + validateNode: validateNode, + updateNodeProperties: updateNodeProperties // TODO: only exposed for edit-undo + } +})(); diff --git a/dgbuilder/public/red/ui/keyboard.js b/dgbuilder/public/red/ui/keyboard.js new file mode 100644 index 00000000..3bc28c4d --- /dev/null +++ b/dgbuilder/public/red/ui/keyboard.js @@ -0,0 +1,68 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.keyboard = (function() { + + var active = true; + var handlers = {}; + + d3.select(window).on("keydown",function() { + if (!active) { return; } + var handler = handlers[d3.event.keyCode]; + if (handler && handler.ondown) { + if (!handler.modifiers || + ((!handler.modifiers.shift || d3.event.shiftKey) && + (!handler.modifiers.ctrl || d3.event.ctrlKey ) && + (!handler.modifiers.alt || d3.event.altKey ) )) { + handler.ondown(); + } + } + }); + d3.select(window).on("keyup",function() { + if (!active) { return; } + var handler = handlers[d3.event.keyCode]; + if (handler && handler.onup) { + if (!handler.modifiers || + ((!handler.modifiers.shift || d3.event.shiftKey) && + (!handler.modifiers.ctrl || d3.event.ctrlKey ) && + (!handler.modifiers.alt || d3.event.altKey ) )) { + handler.onup(); + } + } + }); + function addHandler(key,modifiers,ondown,onup) { + var mod = modifiers; + var cbdown = ondown; + var cbup = onup; + + if (typeof modifiers == "function") { + mod = {}; + cbdown = modifiers; + cbup = ondown; + } + handlers[key] = {modifiers:mod, ondown:cbdown, onup:cbup}; + } + function removeHandler(key) { + delete handlers[key]; + } + + return { + add: addHandler, + remove: removeHandler, + disable: function(){ active = false;}, + enable: function(){ active = true; } + } + +})(); diff --git a/dgbuilder/public/red/ui/library.js b/dgbuilder/public/red/ui/library.js new file mode 100644 index 00000000..0c803bf0 --- /dev/null +++ b/dgbuilder/public/red/ui/library.js @@ -0,0 +1,370 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.library = (function() { + + + function loadFlowLibrary() { + $.getJSON("library/flows",function(data) { + //console.log(data); + + var buildMenu = function(data,root) { + var i; + var li; + var a; + var ul = document.createElement("ul"); + ul.id = "btn-import-library-submenu"; + ul.className = "dropdown-menu"; + if (data.d) { + for (i in data.d) { + if (data.d.hasOwnProperty(i)) { + li = document.createElement("li"); + li.className = "dropdown-submenu pull-left"; + a = document.createElement("a"); + a.href="#"; + a.innerHTML = i; + li.appendChild(a); + li.appendChild(buildMenu(data.d[i],root+(root!==""?"/":"")+i)); + ul.appendChild(li); + } + } + } + if (data.f) { + for (i in data.f) { + if (data.f.hasOwnProperty(i)) { + li = document.createElement("li"); + a = document.createElement("a"); + a.href="#"; + a.innerHTML = data.f[i]; + a.flowName = root+(root!==""?"/":"")+data.f[i]; + a.onclick = function() { + $.get('library/flows/'+this.flowName, function(data) { + RED.view.importNodes(data); + }); + }; + li.appendChild(a); + ul.appendChild(li); + } + } + } + return ul; + }; + var menu = buildMenu(data,""); + //TODO: need an api in RED.menu for this + $("#btn-import-library-submenu").replaceWith(menu); + }); + } + loadFlowLibrary(); + + + + function createUI(options) { + var libraryData = {}; + var selectedLibraryItem = null; + var libraryEditor = null; + + function buildFileListItem(item) { + var li = document.createElement("li"); + li.onmouseover = function(e) { $(this).addClass("list-hover"); }; + li.onmouseout = function(e) { $(this).removeClass("list-hover"); }; + return li; + } + + function buildFileList(root,data) { + var ul = document.createElement("ul"); + var li; + for (var i=0;i<data.length;i++) { + var v = data[i]; + if (typeof v === "string") { + // directory + li = buildFileListItem(v); + li.onclick = (function () { + var dirName = v; + return function(e) { + var bcli = $('<li class="active"><span class="divider">/</span> <a href="#">'+dirName+'</a></li>'); + $("a",bcli).click(function(e) { + $(this).parent().nextAll().remove(); + $.getJSON("library/"+options.url+root+dirName,function(data) { + $("#node-select-library").children().first().replaceWith(buildFileList(root+dirName+"/",data)); + }); + e.stopPropagation(); + }); + var bc = $("#node-dialog-library-breadcrumbs"); + $(".active",bc).removeClass("active"); + bc.append(bcli); + $.getJSON("library/"+options.url+root+dirName,function(data) { + $("#node-select-library").children().first().replaceWith(buildFileList(root+dirName+"/",data)); + }); + } + })(); + li.innerHTML = '<i class="fa fa-folder"></i> '+v+"</i>"; + ul.appendChild(li); + } else { + // file + li = buildFileListItem(v); + li.innerHTML = v.name; + li.onclick = (function() { + var item = v; + return function(e) { + $(".list-selected",ul).removeClass("list-selected"); + $(this).addClass("list-selected"); + $.get("library/"+options.url+root+item.fn, function(data) { + selectedLibraryItem = item; + libraryEditor.setText(data); + }); + } + })(); + ul.appendChild(li); + } + } + return ul; + } + +/* +//Commented this portion as is not used by the DGBuilder application + $('#node-input-name').addClass('input-append-left').css("width","65%").after( + '<div class="btn-group" style="margin-left: 0px;">'+ + '<button id="node-input-'+options.type+'-lookup" class="btn input-append-right" data-toggle="dropdown"><i class="fa fa-book"></i> <i class="fa fa-caret-down"></i></button>'+ + '<ul class="dropdown-menu pull-right" role="menu">'+ + '<li><a id="node-input-'+options.type+'-menu-open-library" tabindex="-1" href="#">Open Library...</a></li>'+ + '<li><a id="node-input-'+options.type+'-menu-save-library" tabindex="-1" href="#">Save to Library...</a></li>'+ + '</ul></div>' + ); + + + + $('#node-input-'+options.type+'-menu-open-library').click(function(e) { + $("#node-select-library").children().remove(); + var bc = $("#node-dialog-library-breadcrumbs"); + bc.children().first().nextAll().remove(); + libraryEditor.setText(''); + + $.getJSON("library/"+options.url,function(data) { + $("#node-select-library").append(buildFileList("/",data)); + $("#node-dialog-library-breadcrumbs a").click(function(e) { + $(this).parent().nextAll().remove(); + $("#node-select-library").children().first().replaceWith(buildFileList("/",data)); + e.stopPropagation(); + }); + $( "#node-dialog-library-lookup" ).dialog( "open" ); + }); + + e.preventDefault(); + }); + + $('#node-input-'+options.type+'-menu-save-library').click(function(e) { + //var found = false; + var name = $("#node-input-name").val().replace(/(^\s*)|(\s*$)/g,""); + + //var buildPathList = function(data,root) { + // var paths = []; + // if (data.d) { + // for (var i in data.d) { + // var dn = root+(root==""?"":"/")+i; + // var d = { + // label:dn, + // files:[] + // }; + // for (var f in data.d[i].f) { + // d.files.push(data.d[i].f[f].fn.split("/").slice(-1)[0]); + // } + // paths.push(d); + // paths = paths.concat(buildPathList(data.d[i],root+(root==""?"":"/")+i)); + // } + // } + // return paths; + //}; + $("#node-dialog-library-save-folder").attr("value",""); + + var filename = name.replace(/[^\w-]/g,"-"); + if (filename === "") { + filename = "unnamed-"+options.type; + } + $("#node-dialog-library-save-filename").attr("value",filename+".js"); + + //var paths = buildPathList(libraryData,""); + //$("#node-dialog-library-save-folder").autocomplete({ + // minLength: 0, + // source: paths, + // select: function( event, ui ) { + // $("#node-dialog-library-save-filename").autocomplete({ + // minLength: 0, + // source: ui.item.files + // }); + // } + //}); + + $( "#node-dialog-library-save" ).dialog( "open" ); + e.preventDefault(); + }); + require(["orion/editor/edit"], function(edit) { + libraryEditor = edit({ + parent:document.getElementById('node-select-library-text'), + lang:"js", + readonly: true + }); + }); + + + $( "#node-dialog-library-lookup" ).dialog({ + title: options.type+" library", + modal: true, + autoOpen: false, + width: 800, + height: 450, + buttons: [ + { + text: "Ok", + click: function() { + if (selectedLibraryItem) { + for (var i=0;i<options.fields.length;i++) { + var field = options.fields[i]; + $("#node-input-"+field).val(selectedLibraryItem[field]); + } + options.editor.setText(libraryEditor.getText()); + } + $( this ).dialog( "close" ); + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + open: function(e) { + var form = $("form",this); + form.height(form.parent().height()-30); + $("#node-select-library-text").height("100%"); + $(".form-row:last-child",form).children().height(form.height()-60); + }, + resize: function(e) { + var form = $("form",this); + form.height(form.parent().height()-30); + $(".form-row:last-child",form).children().height(form.height()-60); + } + }); + + */ + function saveToLibrary(overwrite) { + var name = $("#node-input-name").val().replace(/(^\s*)|(\s*$)/g,""); + if (name === "") { + name = "Unnamed "+options.type; + } + var filename = $("#node-dialog-library-save-filename").val().replace(/(^\s*)|(\s*$)/g,""); + var pathname = $("#node-dialog-library-save-folder").val().replace(/(^\s*)|(\s*$)/g,""); + if (filename === "" || !/.+\.js$/.test(filename)) { + RED.notify("Invalid filename","warning"); + return; + } + var fullpath = pathname+(pathname===""?"":"/")+filename; + if (!overwrite) { + //var pathnameParts = pathname.split("/"); + //var exists = false; + //var ds = libraryData; + //for (var pnp in pathnameParts) { + // if (ds.d && pathnameParts[pnp] in ds.d) { + // ds = ds.d[pathnameParts[pnp]]; + // } else { + // ds = null; + // break; + // } + //} + //if (ds && ds.f) { + // for (var f in ds.f) { + // if (ds.f[f].fn == fullpath) { + // exists = true; + // break; + // } + // } + //} + //if (exists) { + // $("#node-dialog-library-save-type").html(options.type); + // $("#node-dialog-library-save-name").html(fullpath); + // $("#node-dialog-library-save-confirm").dialog( "open" ); + // return; + //} + } + var queryArgs = []; + for (var i=0;i<options.fields.length;i++) { + var field = options.fields[i]; + if (field == "name") { + queryArgs.push("name="+encodeURIComponent(name)); + } else { + queryArgs.push(encodeURIComponent(field)+"="+encodeURIComponent($("#node-input-"+field).val())); + } + } + var queryString = queryArgs.join("&"); + + var text = options.editor.getText(); + $.post("library/"+options.url+'/'+fullpath+"?"+queryString,text,function() { + RED.notify("Saved "+options.type,"success"); + }); + } + $( "#node-dialog-library-save-confirm" ).dialog({ + title: "Save to library", + modal: true, + autoOpen: false, + width: 530, + height: 230, + buttons: [ + { + text: "Ok", + click: function() { + saveToLibrary(true); + $( this ).dialog( "close" ); + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ] + }); + $( "#node-dialog-library-save" ).dialog({ + title: "Save to library", + modal: true, + autoOpen: false, + width: 530, + height: 230, + buttons: [ + { + text: "Ok", + click: function() { + saveToLibrary(false); + $( this ).dialog( "close" ); + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ] + }); + + } + + return { + create: createUI, + loadFlowLibrary: loadFlowLibrary + } +})(); + + diff --git a/dgbuilder/public/red/ui/menu.js b/dgbuilder/public/red/ui/menu.js new file mode 100644 index 00000000..07ea5fd2 --- /dev/null +++ b/dgbuilder/public/red/ui/menu.js @@ -0,0 +1,122 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + + + +RED.menu = (function() { + + var menuItems = {}; + + function createMenuItem(opt) { + var item; + if (opt === null) { + item = $('<li class="divider"></li>'); + } else { + item = $('<li></li>'); + var link = $('<a '+(opt.id?'id="'+opt.id+'" ':'')+'tabindex="-1" href="#">'+ + (opt.toggle?'<i class="fa fa-check pull-right"></i>':'')+ + (opt.icon?'<i class="'+opt.icon+'"></i> ':'')+ + opt.label+ + '</a>').appendTo(item); + + menuItems[opt.id] = opt; + + if (opt.onselect) { + link.click(function() { + if ($(this).parent().hasClass("disabled")) { + return; + } + if (opt.toggle) { + setSelected(opt.id,!isSelected(opt.id)); + } else { + opt.onselect.call(opt); + } + }) + } else if (opt.href) { + link.attr("target","_blank").attr("href",opt.href); + } + if (opt.options) { + item.addClass("dropdown-submenu pull-left"); + var submenu = $('<ul id="'+opt.id+'-submenu" class="dropdown-menu"></ul>').appendTo(item); + + for (var i=0;i<opt.options.length;i++) { + createMenuItem(opt.options[i]).appendTo(submenu); + } + } + if (opt.disabled) { + item.addClass("disabled"); + } + } + + + return item; + + } + function createMenu(options) { + + var button = $("#"+options.id); + + var topMenu = $("<ul/>",{class:"dropdown-menu"}).insertAfter(button); + + for (var i=0;i<options.options.length;i++) { + var opt = options.options[i]; + createMenuItem(opt).appendTo(topMenu); + } + } + + function isSelected(id) { + return $("#"+id).hasClass("active"); + } + function setSelected(id,state) { + if (isSelected(id) == state) { + return; + } + var opt = menuItems[id]; + if (state) { + $("#"+id).addClass("active"); + } else { + $("#"+id).removeClass("active"); + } + if (opt.onselect) { + opt.onselect.call(opt,state); + } + } + + function setDisabled(id,state) { + if (state) { + $("#"+id).parent().addClass("disabled"); + } else { + $("#"+id).parent().removeClass("disabled"); + } + } + + function addItem(id,opt) { + createMenuItem(opt).appendTo("#"+id+"-submenu"); + } + function removeItem(id) { + $("#"+id).parent().remove(); + } + + return { + init: createMenu, + setSelected: setSelected, + isSelected: isSelected, + setDisabled: setDisabled, + addItem: addItem, + removeItem: removeItem + //TODO: add an api for replacing a submenu - see library.js:loadFlowLibrary + } +})(); diff --git a/dgbuilder/public/red/ui/notifications.js b/dgbuilder/public/red/ui/notifications.js new file mode 100644 index 00000000..c9436c68 --- /dev/null +++ b/dgbuilder/public/red/ui/notifications.js @@ -0,0 +1,59 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.notify = (function() { + var currentNotifications = []; + var c = 0; + return function(msg,type,fixed,timeout) { + if (currentNotifications.length > 4) { + var ll = currentNotifications.length; + for (var i = 0;ll > 4 && i<currentNotifications.length;i+=1) { + var notifiction = currentNotifications[i]; + if (!notifiction.fixed) { + window.clearTimeout(notifiction.timeoutid); + notifiction.close(); + ll -= 1; + } + } + } + var n = document.createElement("div"); + n.id="red-notification-"+c; + n.className = "alert"; + n.fixed = fixed; + if (type) { + n.className = "alert alert-"+type; + } + n.style.display = "none"; + n.innerHTML = msg; + $("#notifications").append(n); + $(n).slideDown(300); + n.close = (function() { + var nn = n; + return function() { + currentNotifications.splice(currentNotifications.indexOf(nn),1); + $(nn).slideUp(300, function() { + nn.parentNode.removeChild(nn); + }); + }; + })(); + if (!fixed) { + n.timeoutid = window.setTimeout(n.close,timeout||3000); + } + currentNotifications.push(n); + c+=1; + return n; + } +})(); + diff --git a/dgbuilder/public/red/ui/palette.js b/dgbuilder/public/red/ui/palette.js new file mode 100644 index 00000000..f0524e55 --- /dev/null +++ b/dgbuilder/public/red/ui/palette.js @@ -0,0 +1,230 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +RED.palette = (function() { + + var exclusion = ['config','unknown','deprecated']; + //var core = ['input', 'output', 'function', 'social', 'storage', 'analysis', 'advanced']; + var core = ['DGEmain','DGEoutcome','DGEreturn','DGElogic']; + function createCategoryContainer(category){ + var escapedCategory = category.replace(" ","_"); + $("#palette-container").append('<div class="palette-category">'+ + '<div id="header-'+category+'" class="palette-header"><i class="expanded fa fa-caret-down"></i><span>'+category.replace("_"," ")+'</span></div>'+ + '<div class="palette-content" id="palette-base-category-'+category+'">'+ + '<div id="palette-'+category+'-input"></div>'+ + '<div id="palette-'+category+'-output"></div>'+ + '<div id="palette-'+category+'-function"></div>'+ + '</div>'+ + '</div>'); + + $("#header-"+category).on('click', function(e) { + $(this).next().slideToggle(); + $(this).children("i").toggleClass("expanded"); + }); + } + + core.forEach(createCategoryContainer); + + function addNodeType(nt,def) { + + var nodeTypeId = nt.replace(" ","_"); + + if ($("#palette_node_"+nodeTypeId).length) { + return; + } + + if (exclusion.indexOf(def.category)===-1) { + + var category = def.category.replace(" ","_"); + var rootCategory = category.split("-")[0]; + + var d = document.createElement("div"); + d.id = "palette_node_"+nodeTypeId; + d.type = nt; + + // calculate width of label text + $.fn.textWidth = function(text, font) { + if (!$.fn.textWidth.fakeEl) { + $.fn.textWidth.fakeEl = $('<span>').hide().appendTo(document.body); + } + $.fn.textWidth.fakeEl.text(text || this.val() || this.text()).css('font', font || this.css('font')); + return $.fn.textWidth.fakeEl.width(); + }; + + var label; + + if (typeof def.paletteLabel === "undefined") { + label = /^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1]; + } else { + label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||""; + } + + var pixels = $.fn.textWidth(label, '13px helvetica'); + var nodeWidth = 90; + var labelWidth = nodeWidth - 10; + var numLines = Math.ceil(pixels / nodeWidth); + var multiLine = numLines > 1; + + // styles matching with style.css + var nodeHeight = 25; + var lineHeight = 16; + var portHeight = 10; + var multiLineNodeHeight = lineHeight * numLines + (nodeHeight - lineHeight); + + d.innerHTML = '<div class="palette_label"'+ + (multiLine ? 'style="line-height: '+ + lineHeight + 'px; margin-top: 5px"' : '')+ + '>'+label+"</div>"; + d.className="palette_node"; + if (def.icon) { + d.style.backgroundImage = "url(icons/"+def.icon+")"; + if (multiLine) { + d.style.backgroundSize = "18px 27px"; + } + if (def.align == "right") { + d.style.backgroundPosition = "95% 50%"; + } else if (def.inputs > 0) { + d.style.backgroundPosition = "10% 50%"; + } + } + + d.style.backgroundColor = def.color; + d.style.height = multiLineNodeHeight + "px"; + + if (def.outputs > 0) { + var portOut = document.createElement("div"); + portOut.className = "palette_port palette_port_output"; + if (multiLine) { + portOut.style.top = ((multiLineNodeHeight - portHeight) / 2) + "px"; + } + d.appendChild(portOut); + } + + if (def.inputs > 0) { + var portIn = document.createElement("div"); + portIn.className = "palette_port"; + if (multiLine) { + portIn.style.top = ((multiLineNodeHeight - portHeight) / 2) + "px"; + } + d.appendChild(portIn); + } + + if ($("#palette-base-category-"+rootCategory).length === 0) { + createCategoryContainer(rootCategory); + } + + if ($("#palette-"+category).length === 0) { + $("#palette-base-category-"+rootCategory).append('<div id="palette-'+category+'"></div>'); + } + + $("#palette-"+category).append(d); + d.onmousedown = function(e) { e.preventDefault(); }; + + var popOverContent; + try { + popOverContent = $("<p><b>"+label+"</b></p>"+($("script[data-help-name|='"+nt+"']").html().trim()||"<p>no information available</p>")).slice(0,2); + } catch(err) { + // Malformed HTML may cause errors. TODO: need to understand what can break + console.log("Error generating pop-over label for '"+nt+"'."); + console.log(err.toString()); + popOverContent = "<p><b>"+label+"</b></p><p>no information available</p>"; + } + $(d).popover({ + title:d.type, + placement:"right", + trigger: "hover", + delay: { show: 750, hide: 50 }, + html: true, + container:'body', + content: popOverContent + }); + $(d).click(function() { + var help = '<div class="node-help">'+($("script[data-help-name|='"+d.type+"']").html()||"")+"</div>"; + $("#tab-info").html(help); + }); + $(d).draggable({ + helper: 'clone', + appendTo: 'body', + revert: true, + revertDuration: 50 + }); + } + } + + function removeNodeType(nt) { + var nodeTypeId = nt.replace(" ","_"); + $("#palette_node_"+nodeTypeId).remove(); + } + function hideNodeType(nt) { + var nodeTypeId = nt.replace(" ","_"); + $("#palette_node_"+nodeTypeId).hide(); + } + + function showNodeType(nt) { + var nodeTypeId = nt.replace(" ","_"); + $("#palette_node_"+nodeTypeId).show(); + } + + function filterChange() { + var val = $("#palette-search-input").val(); + if (val === "") { + $("#palette-search-clear").hide(); + } else { + $("#palette-search-clear").show(); + } + + var re = new RegExp(val); + $(".palette_node").each(function(i,el) { + if (val === "" || re.test(el.id)) { + $(this).show(); + } else { + $(this).hide(); + } + }); + } + + $("#palette-search-input").focus(function(e) { + RED.keyboard.disable(); + }); + $("#palette-search-input").blur(function(e) { + RED.keyboard.enable(); + }); + + $("#palette-search-clear").on("click",function(e) { + e.preventDefault(); + $("#palette-search-input").val(""); + filterChange(); + $("#palette-search-input").focus(); + }); + + $("#palette-search-input").val(""); + $("#palette-search-input").on("keyup",function() { + filterChange(); + }); + + $("#palette-search-input").on("focus",function() { + $("body").one("mousedown",function() { + $("#palette-search-input").blur(); + }); + }); + + return { + add:addNodeType, + remove:removeNodeType, + hide:hideNodeType, + show:showNodeType + }; +})(); diff --git a/dgbuilder/public/red/ui/sidebar.js b/dgbuilder/public/red/ui/sidebar.js new file mode 100644 index 00000000..f55e516c --- /dev/null +++ b/dgbuilder/public/red/ui/sidebar.js @@ -0,0 +1,154 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.sidebar = (function() { + + //$('#sidebar').tabs(); + var sidebar_tabs = RED.tabs.create({ + id:"sidebar-tabs", + onchange:function(tab) { + $("#sidebar-content").children().hide(); + $("#"+tab.id).show(); + }, + onremove: function(tab) { + $("#"+tab.id).remove(); + } + }); + function addTab(title,content,closeable) { + $("#sidebar-content").append(content); + $(content).hide(); + sidebar_tabs.addTab({id:"tab-"+title,label:title,closeable:closeable}); + //content.style.position = "absolute"; + //$('#sidebar').tabs("refresh"); + } + + function removeTab(title) { + sidebar_tabs.removeTab("tab-"+title); + } + + var sidebarSeparator = {}; + $("#sidebar-separator").draggable({ + axis: "x", + start:function(event,ui) { + sidebarSeparator.closing = false; + sidebarSeparator.opening = false; + var winWidth = $(window).width(); + sidebarSeparator.start = ui.position.left; + sidebarSeparator.chartWidth = $("#workspace").width(); + sidebarSeparator.chartRight = winWidth-$("#workspace").width()-$("#workspace").offset().left-2; + + + if (!RED.menu.isSelected("btn-sidebar")) { + sidebarSeparator.opening = true; + var newChartRight = 15; + $("#sidebar").addClass("closing"); + $("#workspace").css("right",newChartRight); + $("#chart-zoom-controls").css("right",newChartRight+20); + $("#sidebar").width(0); + RED.menu.setSelected("btn-sidebar",true); + RED.view.resize(); + } + + + sidebarSeparator.width = $("#sidebar").width(); + }, + drag: function(event,ui) { + var d = ui.position.left-sidebarSeparator.start; + var newSidebarWidth = sidebarSeparator.width-d; + if (sidebarSeparator.opening) { + newSidebarWidth -= 13; + } + + if (newSidebarWidth > 150) { + if (sidebarSeparator.chartWidth+d < 200) { + ui.position.left = 200+sidebarSeparator.start-sidebarSeparator.chartWidth; + d = ui.position.left-sidebarSeparator.start; + newSidebarWidth = sidebarSeparator.width-d; + } + } + + if (newSidebarWidth < 150) { + if (!sidebarSeparator.closing) { + $("#sidebar").addClass("closing"); + sidebarSeparator.closing = true; + } + if (!sidebarSeparator.opening) { + newSidebarWidth = 150; + ui.position.left = sidebarSeparator.width-(150 - sidebarSeparator.start); + d = ui.position.left-sidebarSeparator.start; + } + } else if (newSidebarWidth > 150 && (sidebarSeparator.closing || sidebarSeparator.opening)) { + sidebarSeparator.closing = false; + $("#sidebar").removeClass("closing"); + } + + var newChartRight = sidebarSeparator.chartRight-d; + $("#workspace").css("right",newChartRight); + $("#chart-zoom-controls").css("right",newChartRight+20); + $("#sidebar").width(newSidebarWidth); + + sidebar_tabs.resize(); + RED.view.resize(); + + }, + stop:function(event,ui) { + RED.view.resize(); + if (sidebarSeparator.closing) { + $("#sidebar").removeClass("closing"); + RED.menu.setSelected("btn-sidebar",false); + if ($("#sidebar").width() < 180) { + $("#sidebar").width(180); + $("#workspace").css("right",208); + $("#chart-zoom-controls").css("right",228); + } + } + $("#sidebar-separator").css("left","auto"); + $("#sidebar-separator").css("right",($("#sidebar").width()+13)+"px"); + } + }); + + function toggleSidebar(state) { + if (!state) { + $("#main-container").addClass("sidebar-closed"); + } else { + $("#main-container").removeClass("sidebar-closed"); + } + } + + function showSidebar(id) { + RED.menu.setSelected("btn-sidebar",true); + sidebar_tabs.activateTab("tab-"+id); + } + + function containsTab(id) { + return sidebar_tabs.contains("tab-"+id); + } + + + $(function() { + RED.keyboard.add(/* SPACE */ 32,{ctrl:true},function(){RED.menu.setSelected("btn-sidebar",!RED.menu.isSelected("btn-sidebar"));d3.event.preventDefault();}); + showSidebar("info"); + }); + + + return { + addTab: addTab, + removeTab: removeTab, + show: showSidebar, + containsTab: containsTab, + toggleSidebar: toggleSidebar + } + +})(); diff --git a/dgbuilder/public/red/ui/state.js b/dgbuilder/public/red/ui/state.js new file mode 100644 index 00000000..419b04b8 --- /dev/null +++ b/dgbuilder/public/red/ui/state.js @@ -0,0 +1,26 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.state = { + DEFAULT: 0, + MOVING: 1, + JOINING: 2, + MOVING_ACTIVE: 3, + ADDING: 4, + EDITING: 5, + EXPORT: 6, + IMPORT: 7, + IMPORT_DRAGGING: 8 +} diff --git a/dgbuilder/public/red/ui/tab-config.js b/dgbuilder/public/red/ui/tab-config.js new file mode 100644 index 00000000..6ef6ba00 --- /dev/null +++ b/dgbuilder/public/red/ui/tab-config.js @@ -0,0 +1,84 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.sidebar.config = (function() { + + var content = document.createElement("div"); + content.id = "tab-config"; + content.style.paddingTop = "4px"; + content.style.paddingLeft = "4px"; + content.style.paddingRight = "4px"; + + var list = $("<ul>",{class:"tab-config-list"}).appendTo(content); + + function show() { + if (!RED.sidebar.containsTab("config")) { + RED.sidebar.addTab("config",content,true); + } + refresh(); + RED.sidebar.show("config"); + } + + function refresh() { + list.empty(); + RED.nodes.eachConfig(function(node) { + var li = list.find("#tab-config-list-type-"+node.type); + if (li.length === 0) { + li = $("<li>",{id:"tab-config-list-type-"+node.type}).appendTo(list); + $('<div class="tab-config-list-type">'+node.type+'</div>').appendTo(li); + } + var label = ""; + if (typeof node._def.label == "function") { + label = node._def.label.call(node); + } else { + label = node._def.label; + } + label = label || " "; + + var entry = $('<div class="tab-config-list-entry"></div>').appendTo(li); + entry.on('dblclick',function(e) { + RED.editor.editConfig("", node.type, node.id); + }); + + var userArray = node.users.map(function(n) { return n.id }); + entry.on('mouseover',function(e) { + RED.nodes.eachNode(function(node) { + if( userArray.indexOf(node.id) != -1) { + node.highlighted = true; + node.dirty = true; + } + }); + RED.view.redraw(); + }); + + entry.on('mouseout',function(e) { + RED.nodes.eachNode(function(node) { + if(node.highlighted) { + node.highlighted = false; + node.dirty = true; + } + }); + RED.view.redraw(); + }); + + $('<div class="tab-config-list-label">'+label+'</div>').appendTo(entry); + $('<div class="tab-config-list-users">'+node.users.length+'</div>').appendTo(entry); + }); + } + return { + show:show, + refresh:refresh + } +})(); diff --git a/dgbuilder/public/red/ui/tab-info.js b/dgbuilder/public/red/ui/tab-info.js new file mode 100644 index 00000000..bb8eb044 --- /dev/null +++ b/dgbuilder/public/red/ui/tab-info.js @@ -0,0 +1,90 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.sidebar.info = (function() { + + var content = document.createElement("div"); + content.id = "tab-info"; + content.style.paddingTop = "4px"; + content.style.paddingLeft = "4px"; + content.style.paddingRight = "4px"; + + RED.sidebar.addTab("info",content); + + function jsonFilter(key,value) { + if (key === "") { + return value; + } + var t = typeof value; + if ($.isArray(value)) { + return "[array:"+value.length+"]"; + } else if (t === "object") { + return "[object]" + } else if (t === "string") { + if (value.length > 30) { + return value.substring(0,30)+" ..."; + } + } + return value; + } + + function refresh(node) { + var table = '<table class="node-info"><tbody>'; + + table += '<tr class="blank"><td colspan="2">Node</td></tr>'; + table += "<tr><td>Type</td><td> "+node.type+"</td></tr>"; + table += "<tr><td>ID</td><td> "+node.id+"</td></tr>"; + table += '<tr class="blank"><td colspan="2">Properties</td></tr>'; + for (var n in node._def.defaults) { + if (node._def.defaults.hasOwnProperty(n)) { + var val = node[n]||""; + var type = typeof val; + if (type === "string") { + if (val.length > 30) { + val = val.substring(0,30)+" ..."; + } + val = val.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); + } else if (type === "number") { + val = val.toString(); + } else if ($.isArray(val)) { + val = "[<br/>"; + for (var i=0;i<Math.min(node[n].length,10);i++) { + var vv = JSON.stringify(node[n][i],jsonFilter," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); + val += " "+i+": "+vv+"<br/>"; + } + if (node[n].length > 10) { + val += " ... "+node[n].length+" items<br/>"; + } + val += "]"; + } else { + val = JSON.stringify(val,jsonFilter," "); + val = val.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); + } + + table += "<tr><td> "+n+"</td><td>"+val+"</td></tr>"; + } + } + table += "</tbody></table><br/>"; + table += '<div class="node-help">'+($("script[data-help-name|='"+node.type+"']").html()||"")+"</div>"; + $("#tab-info").html(table); + } + + return { + refresh:refresh, + clear: function() { + $("#tab-info").html(""); + } + } +})(); diff --git a/dgbuilder/public/red/ui/tabs.js b/dgbuilder/public/red/ui/tabs.js new file mode 100644 index 00000000..aa207583 --- /dev/null +++ b/dgbuilder/public/red/ui/tabs.js @@ -0,0 +1,127 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + + + +RED.tabs = (function() { + + + function createTabs(options) { + var tabs = {}; + + var ul = $("#"+options.id) + ul.addClass("red-ui-tabs"); + ul.children().first().addClass("active"); + ul.children().addClass("red-ui-tab"); + + function onTabClick() { + activateTab($(this)); + return false; + } + + function onTabDblClick() { + if (options.ondblclick) { + options.ondblclick(tabs[$(this).attr('href').slice(1)]); + } + return false; + } + + function activateTab(link) { + if (typeof link === "string") { + link = ul.find("a[href='#"+link+"']"); + } + if (!link.parent().hasClass("active")) { + ul.children().removeClass("active"); + link.parent().addClass("active"); + if (options.onchange) { + options.onchange(tabs[link.attr('href').slice(1)]); + } + } + } + + function updateTabWidths() { + var tabs = ul.find("li.red-ui-tab"); + var width = ul.width(); + var tabCount = tabs.size(); + var tabWidth = (width-6-(tabCount*7))/tabCount; + var pct = 100*tabWidth/width; + tabs.css({width:pct+"%"}); + } + + ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick); + updateTabWidths(); + + + function removeTab(id) { + var li = ul.find("a[href='#"+id+"']").parent(); + if (li.hasClass("active")) { + var tab = li.prev(); + if (tab.size() === 0) { + tab = li.next(); + } + activateTab(tab.find("a")); + } + li.remove(); + if (options.onremove) { + options.onremove(tabs[id]); + } + delete tabs[id]; + updateTabWidths(); + } + + return { + addTab: function(tab) { + tabs[tab.id] = tab; + var li = $("<li/>",{class:"red-ui-tab"}).appendTo(ul); + var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li); + link.html(tab.label); + + link.on("click",onTabClick); + link.on("dblclick",onTabDblClick); + if (tab.closeable) { + var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li); + closeLink.html('<i class="fa fa-times" />'); + + closeLink.on("click",function(event) { + removeTab(tab.id); + }); + } + updateTabWidths(); + if (options.onadd) { + options.onadd(tab); + } + link.attr("title",tab.label); + if (ul.find("li.red-ui-tab").size() == 1) { + activateTab(link); + } + }, + removeTab: removeTab, + activateTab: activateTab, + resize: updateTabWidths, + count: function() { + return ul.find("li.red-ui-tab").size(); + }, + contains: function(id) { + return ul.find("a[href='#"+id+"']").length > 0; + } + + } + } + + return { + create: createTabs + } +})(); diff --git a/dgbuilder/public/red/ui/touch/radialMenu.js b/dgbuilder/public/red/ui/touch/radialMenu.js new file mode 100644 index 00000000..ffb6a71c --- /dev/null +++ b/dgbuilder/public/red/ui/touch/radialMenu.js @@ -0,0 +1,184 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +RED.touch = RED.touch||{}; +RED.touch.radialMenu = (function() { + + + var touchMenu = null; + var isActive = false; + var isOutside = false; + var activeOption = null; + + + function createRadial(obj,pos,options) { + isActive = true; + try { + var w = $("body").width(); + var h = $("body").height(); + + touchMenu = d3.select("body").append("div") + .style({ + position:"absolute", + top: 0, + left:0, + bottom:0, + right:0, + "z-index": 1000 + }) + .on('touchstart',function() { + hide(); + d3.event.preventDefault(); + }); + + + + + var menu = touchMenu.append("div") + .style({ + position: "absolute", + top: (pos[1]-80)+"px", + left:(pos[0]-80)+"px", + "border-radius": "80px", + width: "160px", + height: "160px", + background: "rgba(255,255,255,0.6)", + border: "1px solid #666" + }); + + var menuOpts = []; + var createMenuOpt = function(x,y,opt) { + opt.el = menu.append("div") + .style({ + position: "absolute", + top: (y+80-25)+"px", + left:(x+80-25)+"px", + "border-radius": "20px", + width: "50px", + height: "50px", + background: "#fff", + border: "2px solid #666", + "text-align": "center", + "line-height":"50px" + }); + + opt.el.html(opt.name); + + if (opt.disabled) { + opt.el.style({"border-color":"#ccc",color:"#ccc"}); + } + opt.x = x; + opt.y = y; + menuOpts.push(opt); + + opt.el.on('touchstart',function() { + opt.el.style("background","#999"); + d3.event.preventDefault(); + d3.event.stopPropagation(); + }); + opt.el.on('touchend',function() { + hide(); + opt.onselect(); + d3.event.preventDefault(); + d3.event.stopPropagation(); + }); + } + + var n = options.length; + var dang = Math.max(Math.PI/(n-1),Math.PI/4); + var ang = Math.PI; + for (var i=0;i<n;i++) { + var x = Math.floor(Math.cos(ang)*80); + var y = Math.floor(Math.sin(ang)*80); + if (options[i].name) { + createMenuOpt(x,y,options[i]); + } + ang += dang; + } + + + var hide = function() { + isActive = false; + activeOption = null; + touchMenu.remove(); + touchMenu = null; + } + + obj.on('touchend.radial',function() { + obj.on('touchend.radial',null); + obj.on('touchmenu.radial',null); + + if (activeOption) { + try { + activeOption.onselect(); + } catch(err) { + RED._debug(err); + } + hide(); + } else if (isOutside) { + hide(); + } + }); + + + + obj.on('touchmove.radial',function() { + try { + var touch0 = d3.event.touches.item(0); + var p = [touch0.pageX - pos[0],touch0.pageY-pos[1]]; + for (var i=0;i<menuOpts.length;i++) { + var opt = menuOpts[i]; + if (!opt.disabled) { + if (p[0]>opt.x-30 && p[0]<opt.x+30 && p[1]>opt.y-30 && p[1]<opt.y+30) { + if (opt !== activeOption) { + opt.el.style("background","#999"); + activeOption = opt; + } + } else if (opt === activeOption) { + opt.el.style("background","#fff"); + activeOption = null; + } else { + opt.el.style("background","#fff"); + } + } + } + if (!activeOption) { + var d = Math.abs((p[0]*p[0])+(p[1]*p[1])); + isOutside = (d > 80*80); + } + + } catch(err) { + RED._debug(err); + } + + + }); + + } catch(err) { + RED._debug(err); + } + } + + + return { + show: createRadial, + active: function() { + return isActive; + } + } + +})(); + diff --git a/dgbuilder/public/red/ui/view.js b/dgbuilder/public/red/ui/view.js new file mode 100644 index 00000000..707bde9e --- /dev/null +++ b/dgbuilder/public/red/ui/view.js @@ -0,0 +1,2053 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + + +RED.view = (function() { + /* increasing the width and height from 5000 to 7500*/ + var space_width = 7500, + space_height = 7500, + lineCurveScale = 0.75, + scaleFactor = 1, + node_width = 100, + node_height = 30; + + var touchLongPressTimeout = 1000, + startTouchDistance = 0, + startTouchCenter = [], + moveTouchCenter = [], + touchStartTime = 0; + + + var activeWorkspace = 0; + var workspaceScrollPositions = {}; + + var selected_link = null, + mousedown_link = null, + mousedown_node = null, + mousedown_port_type = null, + mousedown_port_index = 0, + mouseup_node = null, + mouse_offset = [0,0], + mouse_position = null, + mouse_mode = 0, + moving_set = [], + dirty = false, + lasso = null, + showStatus = false, + showNumbers = false, + showNodePalette = true, + lastClickNode = null, + dblClickPrimed = null, + clickTime = 0, + clickElapsed = 0; + + var clipboard = ""; + + var status_colours = { + "red": "#c00", + "green": "#5a8", + "yellow": "#F9DF31", + "blue": "#53A3F3", + "grey": "#d3d3d3" + } + + var outer = d3.select("#chart") + .append("svg:svg") + .attr("width", space_width) + .attr("height", space_height) + .attr("pointer-events", "all") + .style("cursor","crosshair"); + + var vis = outer + .append('svg:g') + .on("dblclick.zoom", null) + .append('svg:g') + .on("mousemove", canvasMouseMove) + .on("mousedown", canvasMouseDown) + .on("mouseup", canvasMouseUp) + .on("touchend", function() { + clearTimeout(touchStartTime); + touchStartTime = null; + if (RED.touch.radialMenu.active()) { + return; + } + if (lasso) { + outer_background.attr("fill","#fff"); + } + canvasMouseUp.call(this); + }) + .on("touchcancel", canvasMouseUp) + .on("touchstart", function() { + var touch0; + if (d3.event.touches.length>1) { + clearTimeout(touchStartTime); + touchStartTime = null; + d3.event.preventDefault(); + touch0 = d3.event.touches.item(0); + var touch1 = d3.event.touches.item(1); + var a = touch0['pageY']-touch1['pageY']; + var b = touch0['pageX']-touch1['pageX']; + + var offset = $("#chart").offset(); + var scrollPos = [$("#chart").scrollLeft(),$("#chart").scrollTop()]; + startTouchCenter = [ + (touch1['pageX']+(b/2)-offset.left+scrollPos[0])/scaleFactor, + (touch1['pageY']+(a/2)-offset.top+scrollPos[1])/scaleFactor + ]; + moveTouchCenter = [ + touch1['pageX']+(b/2), + touch1['pageY']+(a/2) + ] + startTouchDistance = Math.sqrt((a*a)+(b*b)); + } else { + var obj = d3.select(document.body); + touch0 = d3.event.touches.item(0); + var pos = [touch0.pageX,touch0.pageY]; + startTouchCenter = [touch0.pageX,touch0.pageY]; + startTouchDistance = 0; + var point = d3.touches(this)[0]; + touchStartTime = setTimeout(function() { + touchStartTime = null; + showTouchMenu(obj,pos); + //lasso = vis.append('rect') + // .attr("ox",point[0]) + // .attr("oy",point[1]) + // .attr("rx",2) + // .attr("ry",2) + // .attr("x",point[0]) + // .attr("y",point[1]) + // .attr("width",0) + // .attr("height",0) + // .attr("class","lasso"); + //outer_background.attr("fill","#e3e3f3"); + },touchLongPressTimeout); + } + }) + .on("touchmove", function(){ + if (RED.touch.radialMenu.active()) { + d3.event.preventDefault(); + return; + } + var touch0; + if (d3.event.touches.length<2) { + if (touchStartTime) { + touch0 = d3.event.touches.item(0); + var dx = (touch0.pageX-startTouchCenter[0]); + var dy = (touch0.pageY-startTouchCenter[1]); + var d = Math.abs(dx*dx+dy*dy); + if (d > 64) { + clearTimeout(touchStartTime); + touchStartTime = null; + } + } else if (lasso) { + d3.event.preventDefault(); + } + canvasMouseMove.call(this); + } else { + touch0 = d3.event.touches.item(0); + var touch1 = d3.event.touches.item(1); + var a = touch0['pageY']-touch1['pageY']; + var b = touch0['pageX']-touch1['pageX']; + var offset = $("#chart").offset(); + var scrollPos = [$("#chart").scrollLeft(),$("#chart").scrollTop()]; + var moveTouchDistance = Math.sqrt((a*a)+(b*b)); + var touchCenter = [ + touch1['pageX']+(b/2), + touch1['pageY']+(a/2) + ]; + + if (!isNaN(moveTouchDistance)) { + oldScaleFactor = scaleFactor; + scaleFactor = Math.min(2,Math.max(0.3, scaleFactor + (Math.floor(((moveTouchDistance*100)-(startTouchDistance*100)))/10000))); + + var deltaTouchCenter = [ // Try to pan whilst zooming - not 100% + startTouchCenter[0]*(scaleFactor-oldScaleFactor),//-(touchCenter[0]-moveTouchCenter[0]), + startTouchCenter[1]*(scaleFactor-oldScaleFactor) //-(touchCenter[1]-moveTouchCenter[1]) + ]; + + startTouchDistance = moveTouchDistance; + moveTouchCenter = touchCenter; + + $("#chart").scrollLeft(scrollPos[0]+deltaTouchCenter[0]); + $("#chart").scrollTop(scrollPos[1]+deltaTouchCenter[1]); + redraw(); + } + } + }); + + var outer_background = vis.append('svg:rect') + .attr('width', space_width) + .attr('height', space_height) + .attr('fill','#fff'); + + //var gridScale = d3.scale.linear().range([0,2000]).domain([0,2000]); + //var grid = vis.append('g'); + // + //grid.selectAll("line.horizontal").data(gridScale.ticks(100)).enter() + // .append("line") + // .attr( + // { + // "class":"horizontal", + // "x1" : 0, + // "x2" : 2000, + // "y1" : function(d){ return gridScale(d);}, + // "y2" : function(d){ return gridScale(d);}, + // "fill" : "none", + // "shape-rendering" : "crispEdges", + // "stroke" : "#eee", + // "stroke-width" : "1px" + // }); + //grid.selectAll("line.vertical").data(gridScale.ticks(100)).enter() + // .append("line") + // .attr( + // { + // "class":"vertical", + // "y1" : 0, + // "y2" : 2000, + // "x1" : function(d){ return gridScale(d);}, + // "x2" : function(d){ return gridScale(d);}, + // "fill" : "none", + // "shape-rendering" : "crispEdges", + // "stroke" : "#eee", + // "stroke-width" : "1px" + // }); + + + var drag_line = vis.append("svg:path").attr("class", "drag_line"); + + var workspace_tabs = RED.tabs.create({ + id: "workspace-tabs", + onchange: function(tab) { + if (tab.type == "subflow") { + $("#workspace-toolbar").show(); + } else { + $("#workspace-toolbar").hide(); + } + var chart = $("#chart"); + if (activeWorkspace !== 0) { + workspaceScrollPositions[activeWorkspace] = { + left:chart.scrollLeft(), + top:chart.scrollTop() + }; + } + var scrollStartLeft = chart.scrollLeft(); + var scrollStartTop = chart.scrollTop(); + + activeWorkspace = tab.id; + if (workspaceScrollPositions[activeWorkspace]) { + chart.scrollLeft(workspaceScrollPositions[activeWorkspace].left); + chart.scrollTop(workspaceScrollPositions[activeWorkspace].top); + } else { + chart.scrollLeft(0); + chart.scrollTop(0); + } + var scrollDeltaLeft = chart.scrollLeft() - scrollStartLeft; + var scrollDeltaTop = chart.scrollTop() - scrollStartTop; + if (mouse_position != null) { + mouse_position[0] += scrollDeltaLeft; + mouse_position[1] += scrollDeltaTop; + } + + clearSelection(); + RED.nodes.eachNode(function(n) { + n.dirty = true; + }); + redraw(); + }, + ondblclick: function(tab) { + showRenameWorkspaceDialog(tab.id); + }, + onadd: function(tab) { + RED.menu.addItem("btn-workspace-menu",{ + id:"btn-workspace-menu-"+tab.id.replace(".","-"), + label:tab.label, + onselect:function() { + workspace_tabs.activateTab(tab.id); + } + }); + RED.menu.setDisabled("btn-workspace-delete",workspace_tabs.count() == 1); + }, + onremove: function(tab) { + RED.menu.setDisabled("btn-workspace-delete",workspace_tabs.count() == 1); + RED.menu.removeItem("btn-workspace-menu-"+tab.id.replace(".","-")); + } + }); + + var workspaceIndex = 0; + + function addWorkspace() { + var tabId = RED.nodes.id(); + do { + workspaceIndex += 1; + } while($("#workspace-tabs a[title='Sheet "+workspaceIndex+"']").size() !== 0); + + var ws = {type:"tab",id:tabId,label:"Sheet "+workspaceIndex}; + RED.nodes.addWorkspace(ws); + workspace_tabs.addTab(ws); + workspace_tabs.activateTab(tabId); + RED.history.push({t:'add',workspaces:[ws],dirty:dirty}); + RED.view.dirty(true); + } + $(function() { + $('#btn-workspace-add-tab').on("click",addWorkspace); + $('#btn-workspace-add').on("click",addWorkspace); + $('#btn-workspace-edit').on("click",function() { + showRenameWorkspaceDialog(activeWorkspace); + }); + $('#btn-workspace-delete').on("click",function() { + deleteWorkspace(activeWorkspace); + }); + }); + + function deleteWorkspace(id) { + if (workspace_tabs.count() == 1) { + return; + } + var ws = RED.nodes.workspace(id); + $( "#node-dialog-delete-workspace" ).dialog('option','workspace',ws); + $( "#node-dialog-delete-workspace-name" ).text(ws.label); + $( "#node-dialog-delete-workspace" ).dialog('open'); + } + + function canvasMouseDown() { + if (!mousedown_node && !mousedown_link) { + selected_link = null; + updateSelection(); + } + if (mouse_mode === 0) { + if (lasso) { + lasso.remove(); + lasso = null; + } + + if (!touchStartTime) { + var point = d3.mouse(this); + lasso = vis.append('rect') + .attr("ox",point[0]) + .attr("oy",point[1]) + .attr("rx",2) + .attr("ry",2) + .attr("x",point[0]) + .attr("y",point[1]) + .attr("width",0) + .attr("height",0) + .attr("class","lasso"); + d3.event.preventDefault(); + } + } + } + + function canvasMouseMove() { + mouse_position = d3.touches(this)[0]||d3.mouse(this); + + // Prevent touch scrolling... + //if (d3.touches(this)[0]) { + // d3.event.preventDefault(); + //} + + // TODO: auto scroll the container + //var point = d3.mouse(this); + //if (point[0]-container.scrollLeft < 30 && container.scrollLeft > 0) { container.scrollLeft -= 15; } + //console.log(d3.mouse(this),container.offsetWidth,container.offsetHeight,container.scrollLeft,container.scrollTop); + + if (lasso) { + var ox = parseInt(lasso.attr("ox")); + var oy = parseInt(lasso.attr("oy")); + var x = parseInt(lasso.attr("x")); + var y = parseInt(lasso.attr("y")); + var w; + var h; + if (mouse_position[0] < ox) { + x = mouse_position[0]; + w = ox-x; + } else { + w = mouse_position[0]-x; + } + if (mouse_position[1] < oy) { + y = mouse_position[1]; + h = oy-y; + } else { + h = mouse_position[1]-y; + } + lasso + .attr("x",x) + .attr("y",y) + .attr("width",w) + .attr("height",h) + ; + return; + } + + if (mouse_mode != RED.state.IMPORT_DRAGGING && !mousedown_node && selected_link == null) { + return; + } + + var mousePos; + if (mouse_mode == RED.state.JOINING) { + // update drag line + drag_line.attr("class", "drag_line"); + mousePos = mouse_position; + var numOutputs = (mousedown_port_type === 0)?(mousedown_node.outputs || 1):1; + var sourcePort = mousedown_port_index; + var portY = -((numOutputs-1)/2)*13 +13*sourcePort; + + var sc = (mousedown_port_type === 0)?1:-1; + + var dy = mousePos[1]-(mousedown_node.y+portY); + var dx = mousePos[0]-(mousedown_node.x+sc*mousedown_node.w/2); + var delta = Math.sqrt(dy*dy+dx*dx); + var scale = lineCurveScale; + var scaleY = 0; + + if (delta < node_width) { + scale = 0.75-0.75*((node_width-delta)/node_width); + } + if (dx*sc < 0) { + scale += 2*(Math.min(5*node_width,Math.abs(dx))/(5*node_width)); + if (Math.abs(dy) < 3*node_height) { + scaleY = ((dy>0)?0.5:-0.5)*(((3*node_height)-Math.abs(dy))/(3*node_height))*(Math.min(node_width,Math.abs(dx))/(node_width)) ; + } + } + + drag_line.attr("d", + "M "+(mousedown_node.x+sc*mousedown_node.w/2)+" "+(mousedown_node.y+portY)+ + " C "+(mousedown_node.x+sc*(mousedown_node.w/2+node_width*scale))+" "+(mousedown_node.y+portY+scaleY*node_height)+" "+ + (mousePos[0]-sc*(scale)*node_width)+" "+(mousePos[1]-scaleY*node_height)+" "+ + mousePos[0]+" "+mousePos[1] + ); + d3.event.preventDefault(); + } else if (mouse_mode == RED.state.MOVING) { + //console.log("node mouse moving"); + mousePos = mouse_position; + var d = (mouse_offset[0]-mousePos[0])*(mouse_offset[0]-mousePos[0]) + (mouse_offset[1]-mousePos[1])*(mouse_offset[1]-mousePos[1]); + if (d > 2) { + mouse_mode = RED.state.MOVING_ACTIVE; + clickElapsed = 0; + } + } else if (mouse_mode == RED.state.MOVING_ACTIVE || mouse_mode == RED.state.IMPORT_DRAGGING) { + //console.log("node mouse moving active or IMPORT_DRAGGING"); + mousePos = mouse_position; + var node; + var i; + var minX = 0; + var minY = 0; + for (var n = 0; n<moving_set.length; n++) { + node = moving_set[n]; + if (d3.event.shiftKey) { + node.n.ox = node.n.x; + node.n.oy = node.n.y; + } + node.n.x = mousePos[0]+node.dx; + node.n.y = mousePos[1]+node.dy; + node.n.dirty = true; + minX = Math.min(node.n.x-node.n.w/2-5,minX); + minY = Math.min(node.n.y-node.n.h/2-5,minY); + } + if (minX !== 0 || minY !== 0) { + for (i = 0; i<moving_set.length; i++) { + node = moving_set[i]; + node.n.x -= minX; + node.n.y -= minY; + } + } + if (d3.event.shiftKey && moving_set.length > 0) { + var gridOffset = [0,0]; + node = moving_set[0]; + gridOffset[0] = node.n.x-(20*Math.floor((node.n.x-node.n.w/2)/20)+node.n.w/2); + gridOffset[1] = node.n.y-(20*Math.floor(node.n.y/20)); + if (gridOffset[0] !== 0 || gridOffset[1] !== 0) { + for (i = 0; i<moving_set.length; i++) { + node = moving_set[i]; + node.n.x -= gridOffset[0]; + node.n.y -= gridOffset[1]; + if (node.n.x == node.n.ox && node.n.y == node.n.oy) { + node.dirty = false; + } + } + } + } + } + redraw(); + } + + function canvasMouseUp() { + if (mousedown_node && mouse_mode == RED.state.JOINING) { + drag_line.attr("class", "drag_line_hidden"); + } + if (lasso) { + var x = parseInt(lasso.attr("x")); + var y = parseInt(lasso.attr("y")); + var x2 = x+parseInt(lasso.attr("width")); + var y2 = y+parseInt(lasso.attr("height")); + if (!d3.event.ctrlKey) { + clearSelection(); + } + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace && !n.selected) { + n.selected = (n.x > x && n.x < x2 && n.y > y && n.y < y2); + if (n.selected) { + n.dirty = true; + moving_set.push({n:n}); + } + } + }); + updateSelection(); + lasso.remove(); + lasso = null; + } else if (mouse_mode == RED.state.DEFAULT && mousedown_link == null && !d3.event.ctrlKey ) { + clearSelection(); + updateSelection(); + } + if (mouse_mode == RED.state.MOVING_ACTIVE) { + //console.log("node moved active."); + //CSS setting view dirty if the node was moved + //RED.view.dirty(true); + if (moving_set.length > 0) { + var ns = []; + for (var j=0;j<moving_set.length;j++) { + ns.push({n:moving_set[j].n,ox:moving_set[j].ox,oy:moving_set[j].oy}); + } + RED.history.push({t:'move',nodes:ns,dirty:dirty}); + } + } + if (mouse_mode == RED.state.MOVING || mouse_mode == RED.state.MOVING_ACTIVE) { + //console.log("node moving or MOVING_ACTIVE."); + for (var i=0;i<moving_set.length;i++) { + delete moving_set[i].ox; + delete moving_set[i].oy; + } + } + if (mouse_mode == RED.state.IMPORT_DRAGGING) { + RED.keyboard.remove(/* ESCAPE */ 27); + setDirty(true); + } + redraw(); + // clear mouse event vars + resetMouseVars(); + } + + $('#btn-zoom-out').click(function() {zoomOut();}); + $('#btn-zoom-zero').click(function() {zoomZero();}); + $('#btn-zoom-in').click(function() {zoomIn();}); + $("#chart").on('DOMMouseScroll mousewheel', function (evt) { + if ( evt.altKey ) { + evt.preventDefault(); + evt.stopPropagation(); + var move = -(evt.originalEvent.detail) || evt.originalEvent.wheelDelta; + if (move <= 0) { zoomOut(); } + else { zoomIn(); } + } + }); + $("#chart").droppable({ + accept:".palette_node", + drop: function( event, ui ) { + d3.event = event; + var selected_tool = ui.draggable[0].type; + var mousePos = d3.touches(this)[0]||d3.mouse(this); + mousePos[1] += this.scrollTop; + mousePos[0] += this.scrollLeft; + mousePos[1] /= scaleFactor; + mousePos[0] /= scaleFactor; + + var nn = { id:(1+Math.random()*4294967295).toString(16),x: mousePos[0],y:mousePos[1],w:node_width,z:activeWorkspace}; + + nn.type = selected_tool; + nn._def = RED.nodes.getType(nn.type); + nn.outputs = nn._def.outputs; + nn.changed = true; + + for (var d in nn._def.defaults) { + if (nn._def.defaults.hasOwnProperty(d)) { + nn[d] = nn._def.defaults[d].value; + } + } + + if (nn._def.onadd) { + nn._def.onadd.call(nn); + } + + nn.h = Math.max(node_height,(nn.outputs||0) * 15); + RED.history.push({t:'add',nodes:[nn.id],dirty:dirty}); + RED.nodes.add(nn); + RED.editor.validateNode(nn); + setDirty(true); + // auto select dropped node - so info shows (if visible) + clearSelection(); + nn.selected = true; + moving_set.push({n:nn}); + updateSelection(); + redraw(); + + if (nn._def.autoedit) { + RED.editor.edit(nn); + } + } + }); + + function zoomIn() { + if (scaleFactor < 2) { + scaleFactor += 0.1; + redraw(); + } + } + function zoomOut() { + if (scaleFactor > 0.3) { + scaleFactor -= 0.1; + redraw(); + } + } + function zoomZero() { + scaleFactor = 1; + redraw(); + } + + function selectAll() { + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + if (!n.selected) { + n.selected = true; + n.dirty = true; + moving_set.push({n:n}); + } + } + }); + selected_link = null; + updateSelection(); + redraw(); + } + + function clearSelection() { + for (var i=0;i<moving_set.length;i++) { + var n = moving_set[i]; + n.n.dirty = true; + n.n.selected = false; + } + moving_set = []; + selected_link = null; + } + + function updateSelection() { + if (moving_set.length === 0) { + RED.menu.setDisabled("btn-export-menu",true); + RED.menu.setDisabled("btn-export-clipboard",true); + RED.menu.setDisabled("btn-export-library",true); + } else { + RED.menu.setDisabled("btn-export-menu",false); + RED.menu.setDisabled("btn-export-clipboard",false); + RED.menu.setDisabled("btn-export-library",false); + } + if (moving_set.length === 0 && selected_link == null) { + //RED.keyboard.remove(/* backspace */ 8); + RED.keyboard.remove(/* delete */ 46); + RED.keyboard.remove(/* c */ 67); + RED.keyboard.remove(/* x */ 88); + } else { + //RED.keyboard.add(/* backspace */ 8,function(){deleteSelection();d3.event.preventDefault();}); + RED.keyboard.add(/* delete */ 46,function(){deleteSelection();d3.event.preventDefault();}); + RED.keyboard.add(/* c */ 67,{ctrl:true},function(){copySelection();d3.event.preventDefault();}); + RED.keyboard.add(/* x */ 88,{ctrl:true},function(){copySelection();deleteSelection();d3.event.preventDefault();}); + } + if (moving_set.length === 0) { + RED.keyboard.remove(/* up */ 38); + RED.keyboard.remove(/* down */ 40); + RED.keyboard.remove(/* left */ 37); + RED.keyboard.remove(/* right*/ 39); + } else { + RED.keyboard.add(/* up */ 38, function() { if(d3.event.shiftKey){moveSelection( 0,-20)}else{moveSelection( 0,-1);}d3.event.preventDefault();},endKeyboardMove); + RED.keyboard.add(/* down */ 40, function() { if(d3.event.shiftKey){moveSelection( 0, 20)}else{moveSelection( 0, 1);}d3.event.preventDefault();},endKeyboardMove); + RED.keyboard.add(/* left */ 37, function() { if(d3.event.shiftKey){moveSelection(-20, 0)}else{moveSelection(-1, 0);}d3.event.preventDefault();},endKeyboardMove); + RED.keyboard.add(/* right*/ 39, function() { if(d3.event.shiftKey){moveSelection( 20, 0)}else{moveSelection( 1, 0);}d3.event.preventDefault();},endKeyboardMove); + } + if (moving_set.length == 1) { + RED.sidebar.info.refresh(moving_set[0].n); + } else { + RED.sidebar.info.clear(); + } + } + function endKeyboardMove() { + //console.log("end keyboard move."); + //CSS setting view dirty if the node was moved + //RED.view.dirty(true); + var ns = []; + for (var i=0;i<moving_set.length;i++) { + ns.push({n:moving_set[i].n,ox:moving_set[i].ox,oy:moving_set[i].oy}); + delete moving_set[i].ox; + delete moving_set[i].oy; + } + RED.history.push({t:'move',nodes:ns,dirty:dirty}); + } + function moveSelection(dx,dy) { + var minX = 0; + var minY = 0; + var node; + + for (var i=0;i<moving_set.length;i++) { + node = moving_set[i]; + if (node.ox == null && node.oy == null) { + node.ox = node.n.x; + node.oy = node.n.y; + } + node.n.x += dx; + node.n.y += dy; + node.n.dirty = true; + minX = Math.min(node.n.x-node.n.w/2-5,minX); + minY = Math.min(node.n.y-node.n.h/2-5,minY); + } + + if (minX !== 0 || minY !== 0) { + for (var n = 0; n<moving_set.length; n++) { + node = moving_set[n]; + node.n.x -= minX; + node.n.y -= minY; + } + } + + redraw(); + } + function deleteSelection() { + var removedNodes = []; + var removedLinks = []; + var startDirty = dirty; + if (moving_set.length > 0) { + for (var i=0;i<moving_set.length;i++) { + var node = moving_set[i].n; + node.selected = false; + if (node.x < 0) { + node.x = 25 + } + var rmlinks = RED.nodes.remove(node.id); + removedNodes.push(node); + removedLinks = removedLinks.concat(rmlinks); + } + moving_set = []; + setDirty(true); + } + if (selected_link) { + RED.nodes.removeLink(selected_link); + removedLinks.push(selected_link); + setDirty(true); + } + RED.history.push({t:'delete',nodes:removedNodes,links:removedLinks,dirty:startDirty}); + + selected_link = null; + updateSelection(); + redraw(); + } + + function copySelection() { + if (moving_set.length > 0) { + var nns = []; + for (var n=0;n<moving_set.length;n++) { + var node = moving_set[n].n; + nns.push(RED.nodes.convertNode(node)); + } + clipboard = JSON.stringify(nns); + RED.notify(moving_set.length+" node"+(moving_set.length>1?"s":"")+" copied"); + } + } + + + function calculateTextWidth(str) { + var sp = document.createElement("span"); + sp.className = "node_label"; + sp.style.position = "absolute"; + sp.style.top = "-1000px"; + sp.innerHTML = (str||"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); + document.body.appendChild(sp); + var w = sp.offsetWidth; + document.body.removeChild(sp); + return 50+w; + } + + function resetMouseVars() { + mousedown_node = null; + mouseup_node = null; + mousedown_link = null; + mouse_mode = 0; + mousedown_port_type = 0; + } + + function portMouseDown(d,portType,portIndex) { + // disable zoom + //vis.call(d3.behavior.zoom().on("zoom"), null); + mousedown_node = d; + selected_link = null; + mouse_mode = RED.state.JOINING; + mousedown_port_type = portType; + mousedown_port_index = portIndex || 0; + document.body.style.cursor = "crosshair"; + d3.event.preventDefault(); + } + + function portMouseUp(d,portType,portIndex) { + document.body.style.cursor = ""; + if (mouse_mode == RED.state.JOINING && mousedown_node) { + if (typeof TouchEvent != "undefined" && d3.event instanceof TouchEvent) { + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + var hw = n.w/2; + var hh = n.h/2; + if (n.x-hw<mouse_position[0] && n.x+hw> mouse_position[0] && + n.y-hh<mouse_position[1] && n.y+hh>mouse_position[1]) { + mouseup_node = n; + portType = mouseup_node._def.inputs>0?1:0; + portIndex = 0; + } + } + }); + } else { + mouseup_node = d; + } + if (portType == mousedown_port_type || mouseup_node === mousedown_node) { + drag_line.attr("class", "drag_line_hidden"); + resetMouseVars(); + return; + } + var src,dst,src_port; + if (mousedown_port_type === 0) { + src = mousedown_node; + src_port = mousedown_port_index; + dst = mouseup_node; + } else if (mousedown_port_type == 1) { + src = mouseup_node; + dst = mousedown_node; + src_port = portIndex; + } + + var existingLink = false; + RED.nodes.eachLink(function(d) { + existingLink = existingLink || (d.source === src && d.target === dst && d.sourcePort == src_port); + }); + if (!existingLink) { + var link = {source: src, sourcePort:src_port, target: dst}; + RED.nodes.addLink(link); + RED.history.push({t:'add',links:[link],dirty:dirty}); + setDirty(true); + } + selected_link = null; + redraw(); + } + } + + function nodeMouseUp(d) { + if (dblClickPrimed && mousedown_node == d && clickElapsed > 0 && clickElapsed < 750) { + RED.editor.edit(d); + clickElapsed = 0; + d3.event.stopPropagation(); + return; + } + portMouseUp(d, d._def.inputs > 0 ? 1 : 0, 0); + } + + function nodeMouseDown(d) { + //var touch0 = d3.event; + //var pos = [touch0.pageX,touch0.pageY]; + //RED.touch.radialMenu.show(d3.select(this),pos); + if (mouse_mode == RED.state.IMPORT_DRAGGING) { + RED.keyboard.remove(/* ESCAPE */ 27); + updateSelection(); + setDirty(true); + redraw(); + resetMouseVars(); + d3.event.stopPropagation(); + return; + } + mousedown_node = d; + var now = Date.now(); + clickElapsed = now-clickTime; + clickTime = now; + + dblClickPrimed = (lastClickNode == mousedown_node); + lastClickNode = mousedown_node; + + var i; + + if (d.selected && d3.event.ctrlKey) { + d.selected = false; + for (i=0;i<moving_set.length;i+=1) { + if (moving_set[i].n === d) { + moving_set.splice(i,1); + break; + } + } + } else { + if (d3.event.shiftKey) { + clearSelection(); + var cnodes = RED.nodes.getAllFlowNodes(mousedown_node); + for (var n=0;n<cnodes.length;n++) { + cnodes[n].selected = true; + cnodes[n].dirty = true; + moving_set.push({n:cnodes[n]}); + } + } else if (!d.selected) { + if (!d3.event.ctrlKey) { + clearSelection(); + } + mousedown_node.selected = true; + moving_set.push({n:mousedown_node}); + } + selected_link = null; + if (d3.event.button != 2) { + mouse_mode = RED.state.MOVING; + var mouse = d3.touches(this)[0]||d3.mouse(this); + mouse[0] += d.x-d.w/2; + mouse[1] += d.y-d.h/2; + for (i=0;i<moving_set.length;i++) { + moving_set[i].ox = moving_set[i].n.x; + moving_set[i].oy = moving_set[i].n.y; + moving_set[i].dx = moving_set[i].n.x-mouse[0]; + moving_set[i].dy = moving_set[i].n.y-mouse[1]; + } + mouse_offset = d3.mouse(document.body); + if (isNaN(mouse_offset[0])) { + mouse_offset = d3.touches(document.body)[0]; + } + } + } + d.dirty = true; + updateSelection(); + redraw(); + d3.event.stopPropagation(); + } + + function nodeButtonClicked(d) { + if (d._def.button.toggle) { + d[d._def.button.toggle] = !d[d._def.button.toggle]; + d.dirty = true; + } + if (d._def.button.onclick) { + d._def.button.onclick.call(d); + } + if (d.dirty) { + redraw(); + } + d3.event.preventDefault(); + } + + function showTouchMenu(obj,pos) { + var mdn = mousedown_node; + var options = []; + options.push({name:"delete",disabled:(moving_set.length===0),onselect:function() {deleteSelection();}}); + options.push({name:"cut",disabled:(moving_set.length===0),onselect:function() {copySelection();deleteSelection();}}); + options.push({name:"copy",disabled:(moving_set.length===0),onselect:function() {copySelection();}}); + options.push({name:"paste",disabled:(clipboard.length===0),onselect:function() {importNodes(clipboard,true);}}); + options.push({name:"edit",disabled:(moving_set.length != 1),onselect:function() { RED.editor.edit(mdn);}}); + options.push({name:"select",onselect:function() {selectAll();}}); + options.push({name:"undo",disabled:(RED.history.depth() === 0),onselect:function() {RED.history.pop();}}); + + RED.touch.radialMenu.show(obj,pos,options); + resetMouseVars(); + } + function redraw() { + vis.attr("transform","scale("+scaleFactor+")"); + outer.attr("width", space_width*scaleFactor).attr("height", space_height*scaleFactor); + + if (mouse_mode != RED.state.JOINING) { + // Don't bother redrawing nodes if we're drawing links + + var node = vis.selectAll(".nodegroup").data(RED.nodes.nodes.filter(function(d) { return d.z == activeWorkspace }),function(d){return d.id}); + node.exit().remove(); + + var nodeEnter = node.enter().insert("svg:g").attr("class", "node nodegroup"); + nodeEnter.each(function(d,i) { + var node = d3.select(this); + node.attr("id",d.id); + var l = d._def.label; + l = (typeof l === "function" ? l.call(d) : l)||""; + d.w = Math.max(node_width,calculateTextWidth(l)+(d._def.inputs>0?7:0) ); + d.h = Math.max(node_height,(d.outputs||0) * 15); + + if (d._def.badge) { + var badge = node.append("svg:g").attr("class","node_badge_group"); + var badgeRect = badge.append("rect").attr("class","node_badge").attr("rx",5).attr("ry",5).attr("width",40).attr("height",15); + badge.append("svg:text").attr("class","node_badge_label").attr("x",35).attr("y",11).attr('text-anchor','end').text(d._def.badge()); + if (d._def.onbadgeclick) { + badgeRect.attr("cursor","pointer") + .on("click",function(d) { d._def.onbadgeclick.call(d);d3.event.preventDefault();}); + } + } + + if (d._def.button) { + var nodeButtonGroup = node.append('svg:g') + .attr("transform",function(d) { return "translate("+((d._def.align == "right") ? 94 : -25)+",2)"; }) + .attr("class",function(d) { return "node_button "+((d._def.align == "right") ? "node_right_button" : "node_left_button"); }); + nodeButtonGroup.append('rect') + .attr("rx",8) + .attr("ry",8) + .attr("width",32) + .attr("height",node_height-4) + .attr("fill","#eee");//function(d) { return d._def.color;}) + nodeButtonGroup.append('rect') + .attr("x",function(d) { return d._def.align == "right"? 10:5}) + .attr("y",4) + .attr("rx",5) + .attr("ry",5) + .attr("width",16) + .attr("height",node_height-12) + .attr("fill",function(d) { return d._def.color;}) + .attr("cursor","pointer") + .on("mousedown",function(d) {if (!lasso) { d3.select(this).attr("fill-opacity",0.2);d3.event.preventDefault(); d3.event.stopPropagation();}}) + .on("mouseup",function(d) {if (!lasso) { d3.select(this).attr("fill-opacity",0.4);d3.event.preventDefault();d3.event.stopPropagation();}}) + .on("mouseover",function(d) {if (!lasso) { d3.select(this).attr("fill-opacity",0.4);}}) + .on("mouseout",function(d) {if (!lasso) { + var op = 1; + if (d._def.button.toggle) { + op = d[d._def.button.toggle]?1:0.2; + } + d3.select(this).attr("fill-opacity",op); + }}) + .on("click",nodeButtonClicked) + .on("touchstart",nodeButtonClicked) + } + + var mainRect = node.append("rect") + .attr("class", "node") + .classed("node_unknown",function(d) { return d.type == "unknown"; }) + .attr("rx", 6) + .attr("ry", 6) + .attr("fill",function(d) { return d._def.color;}) + .on("mouseup",nodeMouseUp) + .on("mousedown",nodeMouseDown) + .on("touchstart",function(d) { + var obj = d3.select(this); + var touch0 = d3.event.touches.item(0); + var pos = [touch0.pageX,touch0.pageY]; + startTouchCenter = [touch0.pageX,touch0.pageY]; + startTouchDistance = 0; + touchStartTime = setTimeout(function() { + showTouchMenu(obj,pos); + },touchLongPressTimeout); + nodeMouseDown.call(this,d) + }) + .on("touchend", function(d) { + clearTimeout(touchStartTime); + touchStartTime = null; + if (RED.touch.radialMenu.active()) { + d3.event.stopPropagation(); + return; + } + nodeMouseUp.call(this,d); + }) + .on("mouseover",function(d) { + if (mouse_mode === 0) { + var node = d3.select(this); + node.classed("node_hovered",true); + } + }) + .on("mouseout",function(d) { + var node = d3.select(this); + node.classed("node_hovered",false); + }); + + //node.append("rect").attr("class", "node-gradient-top").attr("rx", 6).attr("ry", 6).attr("height",30).attr("stroke","none").attr("fill","url(#gradient-top)").style("pointer-events","none"); + //node.append("rect").attr("class", "node-gradient-bottom").attr("rx", 6).attr("ry", 6).attr("height",30).attr("stroke","none").attr("fill","url(#gradient-bottom)").style("pointer-events","none"); + + if (d._def.icon) { + + var icon_group = node.append("g") + .attr("class","node_icon_group") + .attr("x",0).attr("y",0); + + var icon_shade = icon_group.append("rect") + .attr("x",0).attr("y",0) + .attr("class","node_icon_shade") + .attr("width","30") + .attr("stroke","none") + .attr("fill","#000") + .attr("fill-opacity","0.05") + .attr("height",function(d){return Math.min(50,d.h-4);}); + + var icon = icon_group.append("image") + .attr("xlink:href","icons/"+d._def.icon) + .attr("class","node_icon") + .attr("x",0) + .attr("width","30") + .attr("height","30"); + + var icon_shade_border = icon_group.append("path") + .attr("d",function(d) { return "M 30 1 l 0 "+(d.h-2)}) + .attr("class","node_icon_shade_border") + .attr("stroke-opacity","0.1") + .attr("stroke","#000") + .attr("stroke-width","2"); + + if ("right" == d._def.align) { + icon_group.attr('class','node_icon_group node_icon_group_'+d._def.align); + icon_shade_border.attr("d",function(d) { return "M 0 1 l 0 "+(d.h-2)}) + //icon.attr('class','node_icon node_icon_'+d._def.align); + //icon.attr('class','node_icon_shade node_icon_shade_'+d._def.align); + //icon.attr('class','node_icon_shade_border node_icon_shade_border_'+d._def.align); + } + + //if (d._def.inputs > 0 && d._def.align == null) { + // icon_shade.attr("width",35); + // icon.attr("transform","translate(5,0)"); + // icon_shade_border.attr("transform","translate(5,0)"); + //} + //if (d._def.outputs > 0 && "right" == d._def.align) { + // icon_shade.attr("width",35); //icon.attr("x",5); + //} + + var img = new Image(); + img.src = "icons/"+d._def.icon; + img.onload = function() { + icon.attr("width",Math.min(img.width,30)); + icon.attr("height",Math.min(img.height,30)); + icon.attr("x",15-Math.min(img.width,30)/2); + //if ("right" == d._def.align) { + // icon.attr("x",function(d){return d.w-img.width-1-(d.outputs>0?5:0);}); + // icon_shade.attr("x",function(d){return d.w-30}); + // icon_shade_border.attr("d",function(d){return "M "+(d.w-30)+" 1 l 0 "+(d.h-2);}); + //} + } + + //icon.style("pointer-events","none"); + icon_group.style("pointer-events","none"); + } + var text = node.append('svg:text').attr('class','node_label').attr('x', 38).attr('dy', '.35em').attr('text-anchor','start'); + if (d._def.align) { + text.attr('class','node_label node_label_'+d._def.align); + text.attr('text-anchor','end'); + } + + var status = node.append("svg:g").attr("class","node_status_group").style("display","none"); + + var statusRect = status.append("rect").attr("class","node_status") + .attr("x",6).attr("y",1).attr("width",9).attr("height",9) + .attr("rx",2).attr("ry",2).attr("stroke-width","3"); + + var statusLabel = status.append("svg:text") + .attr("class","node_status_label") + .attr('x',20).attr('y',9) + .style({ + 'stroke-width': 0, + 'fill': '#888', + 'font-size':'9pt', + 'stroke':'#000', + 'text-anchor':'start' + }); + + var dgNumber = node.append("svg:g").attr("class","node_dgnumber_group").style("display","none"); + + /*var dgNumberRect = dgNumber.append("rect").attr("class","node_dgnumber") + .attr("x",6).attr("y",-49).attr("width",9).attr("height",9) + .attr("rx",2).attr("ry",2).attr("stroke-width","3"); + */ + + var dgNumberLabel = dgNumber.append("svg:text") + .attr("class","node_dgnumber_label") + .attr('x',1).attr('y',-43) + .style({ + 'stroke-width': 0, + /*'fill': '#2E4F83',*/ + 'fill': 'blue', + 'font-size':'12pt', + 'stroke':'#000', + 'text-anchor':'start' + }); + + var dgNumberTitle = dgNumber.append("title") + .attr("class","node_dgnumber_title"); + + //node.append("circle").attr({"class":"centerDot","cx":0,"cy":0,"r":5}); + + if (d._def.inputs > 0) { + text.attr("x",38); + node.append("rect").attr("class","port port_input").attr("rx",3).attr("ry",3).attr("x",-5).attr("width",10).attr("height",10) + .on("mousedown",function(d){portMouseDown(d,1,0);}) + .on("touchstart",function(d){portMouseDown(d,1,0);}) + .on("mouseup",function(d){portMouseUp(d,1,0);} ) + .on("touchend",function(d){portMouseUp(d,1,0);} ) + .on("mouseover",function(d) { var port = d3.select(this); port.classed("port_hovered",(mouse_mode!=RED.state.JOINING || mousedown_port_type != 1 ));}) + .on("mouseout",function(d) { var port = d3.select(this); port.classed("port_hovered",false);}) + } + + //node.append("path").attr("class","node_error").attr("d","M 3,-3 l 10,0 l -5,-8 z"); + node.append("image").attr("class","node_error hidden").attr("xlink:href","icons/node-error.png").attr("x",0).attr("y",-6).attr("width",10).attr("height",9); + node.append("image").attr("class","node_changed hidden").attr("xlink:href","icons/node-changed.png").attr("x",12).attr("y",-6).attr("width",10).attr("height",10); + }); + + node.each(function(d,i) { + if (d.dirty) { + //if (d.x < -50) deleteSelection(); // Delete nodes if dragged back to palette + if (d.resize) { + var l = d._def.label; + l = (typeof l === "function" ? l.call(d) : l)||""; + d.w = Math.max(node_width,calculateTextWidth(l)+(d._def.inputs>0?7:0) ); + d.h = Math.max(node_height,(d.outputs||0) * 15); + } + var thisNode = d3.select(this); + //thisNode.selectAll(".centerDot").attr({"cx":function(d) { return d.w/2;},"cy":function(d){return d.h/2}}); + thisNode.attr("transform", function(d) { return "translate(" + (d.x-d.w/2) + "," + (d.y-d.h/2) + ")"; }); + thisNode.selectAll(".node") + .attr("width",function(d){return d.w}) + .attr("height",function(d){return d.h}) + .classed("node_selected",function(d) { return d.selected; }) + .classed("node_highlighted",function(d) { return d.highlighted; }) + ; + //thisNode.selectAll(".node-gradient-top").attr("width",function(d){return d.w}); + //thisNode.selectAll(".node-gradient-bottom").attr("width",function(d){return d.w}).attr("y",function(d){return d.h-30}); + + thisNode.selectAll(".node_icon_group_right").attr('transform', function(d){return "translate("+(d.w-30)+",0)"}); + thisNode.selectAll(".node_label_right").attr('x', function(d){return d.w-38}); + //thisNode.selectAll(".node_icon_right").attr("x",function(d){return d.w-d3.select(this).attr("width")-1-(d.outputs>0?5:0);}); + //thisNode.selectAll(".node_icon_shade_right").attr("x",function(d){return d.w-30;}); + //thisNode.selectAll(".node_icon_shade_border_right").attr("d",function(d){return "M "+(d.w-30)+" 1 l 0 "+(d.h-2)}); + + + var numOutputs = d.outputs; + var y = (d.h/2)-((numOutputs-1)/2)*13; + d.ports = d.ports || d3.range(numOutputs); + d._ports = thisNode.selectAll(".port_output").data(d.ports); + d._ports.enter().append("rect").attr("class","port port_output").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10) + .on("mousedown",(function(){var node = d; return function(d,i){portMouseDown(node,0,i);}})() ) + .on("touchstart",(function(){var node = d; return function(d,i){portMouseDown(node,0,i);}})() ) + .on("mouseup",(function(){var node = d; return function(d,i){portMouseUp(node,0,i);}})() ) + .on("touchend",(function(){var node = d; return function(d,i){portMouseUp(node,0,i);}})() ) + .on("mouseover",function(d,i) { var port = d3.select(this); port.classed("port_hovered",(mouse_mode!=RED.state.JOINING || mousedown_port_type !== 0 ));}) + .on("mouseout",function(d,i) { var port = d3.select(this); port.classed("port_hovered",false);}); + d._ports.exit().remove(); + if (d._ports) { + numOutputs = d.outputs || 1; + y = (d.h/2)-((numOutputs-1)/2)*13; + var x = d.w - 5; + d._ports.each(function(d,i) { + var port = d3.select(this); + port.attr("y",(y+13*i)-5).attr("x",x); + }); + } + thisNode.selectAll('text.node_label').text(function(d,i){ + if (d._def.label) { + if (typeof d._def.label == "function") { + return d._def.label.call(d); + } else { + return d._def.label; + } + } + return ""; + }) + .attr('y', function(d){return (d.h/2)-1;}) + .attr('class',function(d){ + return 'node_label'+ + (d._def.align?' node_label_'+d._def.align:'')+ + (d._def.labelStyle?' '+(typeof d._def.labelStyle == "function" ? d._def.labelStyle.call(d):d._def.labelStyle):'') ; + }); + thisNode.selectAll(".node_tools").attr("x",function(d){return d.w-35;}).attr("y",function(d){return d.h-20;}); + + thisNode.selectAll(".node_changed") + .attr("x",function(d){return d.w-10}) + .classed("hidden",function(d) { return !d.changed; }); + + thisNode.selectAll(".node_error") + .attr("x",function(d){return d.w-10-(d.changed?13:0)}) + .classed("hidden",function(d) { return d.valid; }); + + thisNode.selectAll(".port_input").each(function(d,i) { + var port = d3.select(this); + port.attr("y",function(d){return (d.h/2)-5;}) + }); + + thisNode.selectAll(".node_icon").attr("y",function(d){return (d.h-d3.select(this).attr("height"))/2;}); + thisNode.selectAll(".node_icon_shade").attr("height",function(d){return d.h;}); + thisNode.selectAll(".node_icon_shade_border").attr("d",function(d){ return "M "+(("right" == d._def.align) ?0:30)+" 1 l 0 "+(d.h-2)}); + + + thisNode.selectAll('.node_right_button').attr("transform",function(d){ + var x = d.w-6; + if (d._def.button.toggle && !d[d._def.button.toggle]) { + x = x - 8; + } + return "translate("+x+",2)"; + }); + thisNode.selectAll('.node_right_button rect').attr("fill-opacity",function(d){ + if (d._def.button.toggle) { + return d[d._def.button.toggle]?1:0.2; + } + return 1; + }); + + //thisNode.selectAll('.node_right_button').attr("transform",function(d){return "translate("+(d.w - d._def.button.width.call(d))+","+0+")";}).attr("fill",function(d) { + // return typeof d._def.button.color === "function" ? d._def.button.color.call(d):(d._def.button.color != null ? d._def.button.color : d._def.color) + //}); + + thisNode.selectAll('.node_badge_group').attr("transform",function(d){return "translate("+(d.w-40)+","+(d.h+3)+")";}); + thisNode.selectAll('text.node_badge_label').text(function(d,i) { + if (d._def.badge) { + if (typeof d._def.badge == "function") { + return d._def.badge.call(d); + } else { + return d._def.badge; + } + } + return ""; + }); + if (!showStatus || !d.status) { + thisNode.selectAll('.node_status_group').style("display","none"); + } else { + thisNode.selectAll('.node_status_group').style("display","inline").attr("transform","translate(3,"+(d.h+3)+")"); + var fill = status_colours[d.status.fill]; // Only allow our colours for now + if (d.status.shape == null && fill == null) { + thisNode.selectAll('.node_status').style("display","none"); + } else { + var style; + if (d.status.shape == null || d.status.shape == "dot") { + style = { + display: "inline", + fill: fill, + stroke: fill + }; + } else if (d.status.shape == "ring" ){ + style = { + display: "inline", + fill: '#fff', + stroke: fill + } + } + thisNode.selectAll('.node_status').style(style); + } + if (d.status.text) { + thisNode.selectAll('.node_status_label').text(d.status.text); + } else { + thisNode.selectAll('.node_status_label').text(""); + } + } + //console.dir("d value"); + //console.dir(d); + if (showNumbers && d.dgnumber != null && d.dgnumber != undefined && d.dgnumber.length >0) { + thisNode.selectAll('.node_dgnumber_group').style("display","inline").attr("transform","translate(9,"+(d.h+9)+")"); + thisNode.selectAll('.node_dgnumber_label').text(d.dgnumber.toString()); + var dgnumberList = d.dgnumber; + var dgnum = ""; + if(dgnumberList != null && dgnumberList.length >=1){ + dgnum = dgnumberList[0]; + thisNode.select('.node_dgnumber_label').text(dgnum); + //console.log(dgnumberList); + thisNode.select('.node_dgnumber_title').text(dgnumberList); + } + /* + if(d.dgnumber.length > 1){ + thisNode.selectAll('.node_dgnumber_group').style("display","inline").attr("transform","translate(9,"+(d.h-15)+")"); + thisNode.selectAll('.node_dgnumber_label').text(d.dgnumber.toString()); + }else{ + thisNode.selectAll('.node_dgnumber_group').style("display","inline").attr("transform","translate(9,"+(d.h+9)+")"); + thisNode.selectAll('.node_dgnumber_label').text(d.dgnumber.toString()); + } + */ + } else { + //console.log("fhfjhfjh "); + thisNode.select('.node_dgnumber').style("display","none"); + thisNode.select('.node_dgnumber_label').text(""); + thisNode.select('.node_dgnumber_title').text(""); + } + + d.dirty = false; + } + }); + } + + var link = vis.selectAll(".link").data(RED.nodes.links.filter(function(d) { return d.source.z == activeWorkspace && d.target.z == activeWorkspace }),function(d) { return d.source.id+":"+d.sourcePort+":"+d.target.id;}); + + var linkEnter = link.enter().insert("g",".node").attr("class","link"); + + linkEnter.each(function(d,i) { + var l = d3.select(this); + l.append("svg:path").attr("class","link_background link_path") + .on("mousedown",function(d) { + mousedown_link = d; + clearSelection(); + selected_link = mousedown_link; + updateSelection(); + redraw(); + d3.event.stopPropagation(); + }) + .on("touchstart",function(d) { + mousedown_link = d; + clearSelection(); + selected_link = mousedown_link; + updateSelection(); + redraw(); + d3.event.stopPropagation(); + }); + l.append("svg:path").attr("class","link_outline link_path"); + l.append("svg:path").attr("class","link_line link_path"); + }); + + link.exit().remove(); + + var links = vis.selectAll(".link_path") + links.attr("d",function(d){ + var numOutputs = d.source.outputs || 1; + var sourcePort = d.sourcePort || 0; + var y = -((numOutputs-1)/2)*13 +13*sourcePort; + + var dy = d.target.y-(d.source.y+y); + var dx = (d.target.x-d.target.w/2)-(d.source.x+d.source.w/2); + var delta = Math.sqrt(dy*dy+dx*dx); + var scale = lineCurveScale; + var scaleY = 0; + if (delta < node_width) { + scale = 0.75-0.75*((node_width-delta)/node_width); + } + + if (dx < 0) { + scale += 2*(Math.min(5*node_width,Math.abs(dx))/(5*node_width)); + if (Math.abs(dy) < 3*node_height) { + scaleY = ((dy>0)?0.5:-0.5)*(((3*node_height)-Math.abs(dy))/(3*node_height))*(Math.min(node_width,Math.abs(dx))/(node_width)) ; + } + } + + d.x1 = d.source.x+d.source.w/2; + d.y1 = d.source.y+y; + d.x2 = d.target.x-d.target.w/2; + d.y2 = d.target.y; + + return "M "+(d.source.x+d.source.w/2)+" "+(d.source.y+y)+ + " C "+(d.source.x+d.source.w/2+scale*node_width)+" "+(d.source.y+y+scaleY*node_height)+" "+ + (d.target.x-d.target.w/2-scale*node_width)+" "+(d.target.y-scaleY*node_height)+" "+ + (d.target.x-d.target.w/2)+" "+d.target.y; + }) + + link.classed("link_selected", function(d) { return d === selected_link || d.selected; }); + link.classed("link_unknown",function(d) { return d.target.type == "unknown" || d.source.type == "unknown"}); + + if (d3.event) { + d3.event.preventDefault(); + } + } + + RED.keyboard.add(/* z */ 90,{ctrl:true},function(){RED.history.pop();}); + RED.keyboard.add(/* a */ 65,{ctrl:true},function(){selectAll();d3.event.preventDefault();}); + RED.keyboard.add(/* = */ 187,{ctrl:true},function(){zoomIn();d3.event.preventDefault();}); + RED.keyboard.add(/* - */ 189,{ctrl:true},function(){zoomOut();d3.event.preventDefault();}); + RED.keyboard.add(/* 0 */ 48,{ctrl:true},function(){zoomZero();d3.event.preventDefault();}); + RED.keyboard.add(/* v */ 86,{ctrl:true},function(){importNodes(clipboard);d3.event.preventDefault();}); + RED.keyboard.add(/* e */ 69,{ctrl:true},function(){showExportNodesDialog();d3.event.preventDefault();}); + RED.keyboard.add(/* i */ 73,{ctrl:true},function(){showImportNodesDialog();d3.event.preventDefault();}); + RED.keyboard.add(/* B */ 66,{ctrl:true},function(){RED.view.showDgNumberDialog();d3.event.preventDefault();}); + RED.keyboard.add(/* [ */ 219,{ctrl:true},function(){RED.view.showSearchTextDialog();d3.event.preventDefault();}); + RED.keyboard.add(/* O */ 79,{ctrl:true},function(){RED.view.showRequestTemplateDialog();d3.event.preventDefault();}); + + + // TODO: 'dirty' should be a property of RED.nodes - with an event callback for ui hooks + function setDirty(d) { + dirty = d; + if (dirty) { + $("#btn-deploy").removeClass("disabled"); + } else { + $("#btn-deploy").addClass("disabled"); + } + } + + /** + * Imports a new collection of nodes from a JSON String. + * - all get new IDs assigned + * - all 'selected' + * - attached to mouse for placing - 'IMPORT_DRAGGING' + */ + function importNodes(newNodesStr,touchImport) { + try { + var result = RED.nodes.import(newNodesStr,true); + if (result) { + var new_nodes = result[0]; + var new_links = result[1]; + var new_workspaces = result[2]; + + var new_ms = new_nodes.filter(function(n) { return n.z == activeWorkspace }).map(function(n) { return {n:n};}); + var new_node_ids = new_nodes.map(function(n){ return n.id; }); + + // TODO: pick a more sensible root node + if (new_ms.length > 0) { + var root_node = new_ms[0].n; + var dx = root_node.x; + var dy = root_node.y; + + if (mouse_position == null) { + mouse_position = [0,0]; + } + + var minX = 0; + var minY = 0; + var i; + var node; + + for (i=0;i<new_ms.length;i++) { + node = new_ms[i]; + node.n.selected = true; + node.n.changed = true; + node.n.x -= dx - mouse_position[0]; + node.n.y -= dy - mouse_position[1]; + node.dx = node.n.x - mouse_position[0]; + node.dy = node.n.y - mouse_position[1]; + minX = Math.min(node.n.x-node_width/2-5,minX); + minY = Math.min(node.n.y-node_height/2-5,minY); + } + for (i=0;i<new_ms.length;i++) { + node = new_ms[i]; + node.n.x -= minX; + node.n.y -= minY; + node.dx -= minX; + node.dy -= minY; + } + if (!touchImport) { + mouse_mode = RED.state.IMPORT_DRAGGING; + } + + RED.keyboard.add(/* ESCAPE */ 27,function(){ + RED.keyboard.remove(/* ESCAPE */ 27); + clearSelection(); + RED.history.pop(); + mouse_mode = 0; + }); + clearSelection(); + moving_set = new_ms; + } + + RED.history.push({t:'add',nodes:new_node_ids,links:new_links,workspaces:new_workspaces,dirty:RED.view.dirty()}); + + + redraw(); + } + } catch(error) { + console.log(error.stack); + RED.notify("<strong>Error</strong>: "+error,"error"); + } + } + + function showExportNodesDialog() { + mouse_mode = RED.state.EXPORT; + var nns = RED.nodes.createExportableNodeSet(moving_set); + $("#dialog-form").html($("script[data-template-name='export-clipboard-dialog']").html()); + $("#node-input-export").val(JSON.stringify(nns)); + $("#node-input-export").focus(function() { + var textarea = $(this); + textarea.select(); + textarea.mouseup(function() { + textarea.unbind("mouseup"); + return false; + }); + }); + $( "#dialog" ).dialog("option","title","Export nodes to clipboard").dialog( "open" ); + $("#node-input-export").focus(); + } + + function showExportNodesLibraryDialog() { + mouse_mode = RED.state.EXPORT; + var nns = RED.nodes.createExportableNodeSet(moving_set); + $("#dialog-form").html($("script[data-template-name='export-library-dialog']").html()); + $("#node-input-filename").attr('nodes',JSON.stringify(nns)); + $( "#dialog" ).dialog("option","title","Export nodes to library").dialog( "open" ); + } + + function showImportNodesDialog() { + mouse_mode = RED.state.IMPORT; + $("#dialog-form").html($("script[data-template-name='import-dialog']").html()); + $("#node-input-import").val(""); + $( "#dialog" ).dialog("option","title","Import nodes").dialog( "open" ); + } + + function showRenameWorkspaceDialog(id) { + var ws = RED.nodes.workspace(id); + $( "#node-dialog-rename-workspace" ).dialog("option","workspace",ws); + + if (workspace_tabs.count() == 1) { + $( "#node-dialog-rename-workspace").next().find(".leftButton") + .prop('disabled',true) + .addClass("ui-state-disabled"); + } else { + $( "#node-dialog-rename-workspace").next().find(".leftButton") + .prop('disabled',false) + .removeClass("ui-state-disabled"); + } + + $( "#node-input-workspace-name" ).val(ws.label); + $( "#node-dialog-rename-workspace" ).dialog("open"); + } + + $("#node-dialog-rename-workspace form" ).submit(function(e) { e.preventDefault();}); + $( "#node-dialog-rename-workspace" ).dialog({ + modal: true, + autoOpen: false, + width: 500, + title: "Rename sheet", + buttons: [ + { + class: 'leftButton', + text: "Delete", + click: function() { + var workspace = $(this).dialog('option','workspace'); + $( this ).dialog( "close" ); + deleteWorkspace(workspace.id); + } + }, + { + text: "Ok", + click: function() { + var workspace = $(this).dialog('option','workspace'); + var label = $( "#node-input-workspace-name" ).val(); + if (workspace.label != label) { + workspace.label = label; + var link = $("#workspace-tabs a[href='#"+workspace.id+"']"); + link.attr("title",label); + link.text(label); + RED.view.dirty(true); + } + $( this ).dialog( "close" ); + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + open: function(e) { + RED.keyboard.disable(); + }, + close: function(e) { + RED.keyboard.enable(); + } + }); + $( "#node-dialog-delete-workspace" ).dialog({ + modal: true, + autoOpen: false, + width: 500, + title: "Confirm delete", + buttons: [ + { + text: "Ok", + click: function() { + var workspace = $(this).dialog('option','workspace'); + RED.view.removeWorkspace(workspace); + var historyEvent = RED.nodes.removeWorkspace(workspace.id); + historyEvent.t = 'delete'; + historyEvent.dirty = dirty; + historyEvent.workspaces = [workspace]; + RED.history.push(historyEvent); + RED.view.dirty(true); + $( this ).dialog( "close" ); + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + open: function(e) { + RED.keyboard.disable(); + }, + close: function(e) { + RED.keyboard.enable(); + } + + }); + return { + state:function(state) { + if (state == null) { + return mouse_mode + } else { + mouse_mode = state; + } + }, + addWorkspace: function(ws) { + workspace_tabs.addTab(ws); + workspace_tabs.resize(); + }, + removeWorkspace: function(ws) { + workspace_tabs.removeTab(ws.id); + }, + getWorkspace: function() { + return activeWorkspace; + }, + showWorkspace: function(id) { + workspace_tabs.activateTab(id); + }, + redraw:redraw, + dirty: function(d) { + if (d == null) { + return dirty; + } else { + setDirty(d); + } + }, + importNodes: importNodes, + resize: function() { + workspace_tabs.resize(); + }, + status: function(s) { + validateEachNodeXml(); + showStatus = s; + RED.nodes.eachNode(function(n) { n.dirty = true;}); + //TODO: subscribe/unsubscribe here + redraw(); + }, + showYangUploadDialog:function showYangUploadDialog(){ + $(function() { + var htmlStr= "<div id='yang-upload-div' style='width:375;height:225'>" + + '<form id="uploadForm" name="uploadForm" enctype="multipart/form-data" action="/api/uploadyang" method="post" >' + + "<input id='yang-file-id' name='yangFile' type='file' accept='.yang,.zip'><p style='font-size:0.7em'><i>For Module depending on multiple yang files, zip them and upload the zip file. The zip file name should match the exact name of the module with .zip extension</i</p><br><br><br><br><br><p id='yang-upload-status'></p>" + + //'<input id="upload-yang-button-id" style="font-size:1em;font-weight:bold" type="button" value="Upload Yang" name="upload-yang-button">' + + "</form></div>"; + + $("#yang-upload-dialog").dialog({ + modal:true, + autoOpen :false, + title: "Upload Yang", + width: 500, + height: 260, + minWidth : 300, + minHeight :260, + buttons :[ + { + text: "Upload Yang", + click: function() { + if( document.getElementById("yang-file-id").files.length == 0 ){ + $("#yang-upload-status").html("<span>No files selected.</span>"); + return ; + } + $('#yang-upload-dialog').parent().find('.ui-dialog-buttonpane button:first').button("disable"); + //$("#yang-upload-status").empty().text("File is uploading..."); + $("#yang-upload-status").html("<span>Processing...Please wait</span><img src='images/page-loading.gif'>"); + $.ajax({ + url: "/api/uploadyang", + type: "POST", + data: new FormData(document.forms['uploadForm']), + contentType: false, + cache: false, + processData:false, + success: function(data) { + $("#yang-upload-status").html(""); + $("#yang-upload-status").text(data.msg); + $('#yang-upload-dialog').parent().find('.ui-dialog-buttonpane button:first').button("enable"); + /* + sliValuesObj = {}; + rpcValues = {}; + reqInputValues = {}; + for(var i=0;i<data.sliValuesObj.length;i++){ + var moduleName = data.sliValuesObj[i].moduleName; + sliValuesObj[moduleName] = data.sliValuesObj[i][moduleName + '_PROPS']; + rpcValues[moduleName] = data.sliValuesObj[i][ moduleName +'_RPCS']; + for(var k=0;rpcValues[moduleName] != undefined && k<rpcValues[moduleName].length;k++){ + var rpcName = rpcValues[moduleName][k]; + reqInputValues[moduleName + "_" + rpcName] = data.sliValuesObj[i][rpcName +"-input"]; + } + } + */ + //close the yang upload dialogog box and open the load dialogbox + $('#yang-upload-dialog').dialog("close"); + $("#btn-available-yang-modules").trigger("click"); + }, + error:function (xhr, desc, err){ + $("#yang-upload-status").html(err); + $('#yang-upload-dialog').parent().find('.ui-dialog-buttonpane button:first').button("enable"); + } + }); + } + }, + { + text: "Close", + click: function() { + $("#yang-upload-dialog").dialog("close"); + } + } + ] + }).dialog("open").html(htmlStr); + }); + }, + showDgNumberDialog: function showDgNumberDialog(){ + $(function() { + var isLoopDetected = detectLoop(); + console.log("isLoopDetected:" + isLoopDetected); + if(isLoopDetected){ + return false; + } + updateDgNumbers(); + var htmlStr="<div id='find-dgnumber-div' style='width:375;height:225'><label>DG Number</label><input id='dgnumber-val-id' type='text' value=''><p id='find-dgnumber-status' style='color:red'></p></div>"; + $("#dgnumber-find-dialog").dialog({ + modal:true, + autoOpen :false, + title: "Find Node By DGNumber", + width: 300, + height: 215, + minWidth : 300, + minHeight :215, + buttons :[ + { + text: "Find", + click: function() { + var dgnumVal = $("#dgnumber-val-id").val(); + $("#find-dgnumber-status").text(""); + if(dgnumVal != undefined && dgnumVal != '' && dgnumVal != ''){ + dgnumVal = dgnumVal.trim(); + }else{ + dgnumVal =""; + } + + var dgNumberFound = false; + var node = vis.selectAll(".nodegroup").data(RED.nodes.nodes.filter(function(d) { return d.z == activeWorkspace }),function(d){return d.id}); + node.each(function(d,i) { + var thisNode = d3.select(this); + var dgn = d.dgnumber; + + if(dgn != undefined && typeof dgn == 'object'){ + var found = false; + for(var k=0;k<dgn.length;k++){ + if(dgn[k] == dgnumVal){ + found = true; + break; + } + } + if(found){ + //thisNode.select("rect").style({"stroke":"blue","stroke-width" :"3","stroke-dasharray":"5,1"}); + //$("#" + d.id).find("rect").attr("class","node-found-selected"); + //$("#" + d.id).find("rect").attr("class","node node_selected"); + //thisNode.select("rect").attr("class","node node_selected"); + thisNode.select("rect").attr("class","node node_found"); + document.getElementById( d.id ).scrollIntoView(); + $("#dgnumber-find-dialog").dialog("close"); + + //display the node edit dialogbox + RED.editor.edit(d); + dgNumberFound = true; + }else{ + //thisNode.select("rect").style({"stroke":"#999","stroke-width" :"2","stroke-dasharray":"none"}); + //$("#" + d.id ).find("rect").attr("class","node-found-clear"); + thisNode.select("rect").attr("class","node"); + //$("#" + d.id ).find("rect").attr("class","node"); + //$("#find-dgnumber-status").text("DGNumber :" + dgnumVal + " Not found"); + + } + } + }); + if(!dgNumberFound){ + $("#find-dgnumber-status").text("DGNumber :" + dgnumVal + " Not found"); + } + } + }, + { + text: "Close", + click: function() { + $("#dgnumber-find-dialog").dialog("close"); + } + } + ], + open:function(){ + //Bind the Enter key to Find button + $('#dgnumber-find-dialog').keypress(function(e) { + if (e.keyCode == $.ui.keyCode.ENTER) { + $('#dgnumber-find-dialog').parent().find('.ui-dialog-buttonpane button:first').click(); + return false; + } + }); + $(function(){ + //set focus on the input box + $("#dgnumber-val-id").focus(); + }); + } + }).dialog("open").html(htmlStr); + }); + }, + showSearchTextDialog: function showSearchTextDialog(){ + $(function() { + var isLoopDetected = detectLoop(); + console.log("isLoopDetected:" + isLoopDetected); + if(isLoopDetected){ + return false; + } + updateDgNumbers(); + //console.log("In the showSearchTextDialog."); + var htmlStr="<div id='search-text-div' style='width:675;height:525'><label>Search Text</label><input style='width:500px;' id='search-text-val-id' type='text' value=''><br><input id='ignore-case-id' type='checkbox' name='ignorecase' value='1' >Ignore Case<br><p id='search-text-status' style='color:red'></p></div>"; + //console.log("setting up search-text-dialog."); + $("#search-text-dialog").dialog({ + modal:true, + autoOpen :false, + title: "Search text in DG", + width: 600, + height: 515, + minWidth : 500, + minHeight :415, + buttons :[ + { + text: "Search", + click: function() { + + var node = vis.selectAll(".nodegroup").data(RED.nodes.nodes.filter(function(d) { return d.z == activeWorkspace }),function(d){return d.id}); + var searchText = $("#search-text-val-id").val(); + $("#search-text-status").text(""); + if(searchText != undefined && searchText != '' && searchText != ''){ + searchText = searchText.trim(); + }else{ + searchText =""; + node.each(function(d,i) { + var thisNode = d3.select(this); + thisNode.select("rect").attr("class","node"); + }); + return; + } + + var foundSearchText = false; + var foundInDgNumArr = []; + //console.log("In search function"); + node.each(function(d,i) { + var thisNode = d3.select(this); + var dgn = d.dgnumber; + var xml = d.xml; + var nName = d.name; + + var ignoreCase = $('#ignore-case-id').prop('checked') + var options = 'g'; + if(ignoreCase){ + options='gi'; + } + var searchPattern = new RegExp(searchText, options ); + if(xml == undefined || xml == null){ + xml = ""; + } + if(nName == undefined || nName == null){ + nName = ""; + } + //console.log(searchPattern); + var count1 = (xml.match(searchPattern) || []).length; + //console.log(count1); + var count2 = (nName.match(searchPattern) || []).length; + //console.log(count2); + + if(count1 >0 || count2 > 0){ + thisNode.select("rect").attr("class","node text_found"); + var dgn = d.dgnumber; + + var dgNumber = dgn; + if(dgn != undefined && typeof dgn == 'object'){ + console.log("DGNUMBERS:" + dgn); + dgNumber = dgn[0]; + } + if(dgn != undefined ){ + foundInDgNumArr.push(dgNumber); + }else{ + foundInDgNumArr.push(d.type); + } + foundSearchText=true; + }else{ + thisNode.select("rect").attr("class","node"); + } + }); + if(!foundSearchText){ + $("#search-text-status").text("Search Text :" + searchText + " Not found"); + }else{ + //console.log("closing dialog"); + //$("#search-text-dialog").dialog("close"); + console.log(foundInDgNumArr); + $("#search-text-status").text("Found in DG numbers :" + foundInDgNumArr); + } + } + }, + { + text: "Close", + click: function() { + //console.log("closing dialog"); + $("#search-text-dialog").dialog("close"); + } + } + ], + open:function(){ + //console.log("called open."); + //Bind the Enter key to Find button + $('#search-text-dialog').keypress(function(e) { + if (e.keyCode == $.ui.keyCode.ENTER) { + $('#search-text-dialog').parent().find('.ui-dialog-buttonpane button:first').click(); + return false; + } + }); + $(function(){ + //set focus on the input box + $("#search-text-id").focus(); + }); + //console.log("done open call."); + } + }).dialog('open').html(htmlStr); + }); + }, + showRequestTemplateDialog: function showRequestTemplateDialog(){ + $(function() { + var currNodes = RED.nodes.nodes.filter(function(d) { return d.z == activeWorkspace }) + var moduleName = ""; + var rpcName = ""; + if(currNodes != null && currNodes.length > 1){ + currNodes.forEach(function(n){ + if(n.type == 'service-logic'){ + moduleName = getAttributeValue(n.xml,"module"); + }else if(n.type == 'method'){ + rpcName = getAttributeValue(n.xml,"rpc"); + } + }); + } + console.log("moduleName:" + moduleName); + console.log("rpcName:" + rpcName); + var inputValObj = reqInputValues[moduleName + "_" + rpcName]; + var inputValStr = "Not found. Please make sure that the Module is loaded and the rpc has input."; + if(inputValObj != undefined && inputValObj != null){ + inputValStr = "{\n\"input\" : " + JSON.stringify(inputValObj,null,4)+ "\n}"; + } + + //var htmlStr="<div id='request-template-div' style='width:875px;height:575px'><textarea style='width:875px;height:575px'>" + inputValStr + "</textarea></div>" + //var htmlStr="<div id='request-template-div' style='width:750px;height:550px;font-weight:bold;font-size:1em'><pre>" + inputValStr + "</pre></div>" + var htmlStr="<textarea readonly='1' id='request-template-textarea' style='width:750px;height:550px;font-weight:bold;font-size:1em'>" + inputValStr + "</textarea>" + $("#request-input-dialog").dialog({ + dialogClass :"no-close", + modal:true, + autoOpen :false, + title: "Request Template for Module:" + moduleName + " RPC:" + rpcName, + width: 800, + height: "auto", + buttons :[ + { + text: "Close", + click: function() { + $("#request-input-dialog").dialog("close"); + } + } + ], + open:function(){ + $('#request-input-dialog').css('overflow', 'hidden'); + } + }).dialog("open").html(htmlStr); + }); + }, + showNumbers: function(s) { + console.log("showNumbers:" + s); + showNumbers = s; + RED.nodes.eachNode(function(n) { n.dirty = true;}); + redraw(); + }, + showNodePalette: function(s) { + showNodePalette=s; + if(!s){ + $("#main-container").addClass("palette-bar-closed"); + //RED.menu.setSelected("btn-node-panel",true); + }else{ + $("#main-container").removeClass("palette-bar-closed"); + } + //console.log("showNodePalette:" + showNodePalette); + }, + + //TODO: should these move to an import/export module? + showImportNodesDialog: showImportNodesDialog, + showExportNodesDialog: showExportNodesDialog, + showExportNodesLibraryDialog: showExportNodesLibraryDialog + }; +})(); diff --git a/dgbuilder/public/red/ui/view.js.orig b/dgbuilder/public/red/ui/view.js.orig new file mode 100644 index 00000000..73981fd6 --- /dev/null +++ b/dgbuilder/public/red/ui/view.js.orig @@ -0,0 +1,1639 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + + +RED.view = (function() { + var space_width = 5000, + space_height = 5000, + lineCurveScale = 0.75, + scaleFactor = 1, + node_width = 100, + node_height = 30; + + var touchLongPressTimeout = 1000, + startTouchDistance = 0, + startTouchCenter = [], + moveTouchCenter = [], + touchStartTime = 0; + + + var activeWorkspace = 0; + var workspaceScrollPositions = {}; + + var selected_link = null, + mousedown_link = null, + mousedown_node = null, + mousedown_port_type = null, + mousedown_port_index = 0, + mouseup_node = null, + mouse_offset = [0,0], + mouse_position = null, + mouse_mode = 0, + moving_set = [], + dirty = false, + lasso = null, + showStatus = false, + lastClickNode = null, + dblClickPrimed = null, + clickTime = 0, + clickElapsed = 0; + + var clipboard = ""; + + var status_colours = { + "red": "#c00", + "green": "#5a8", + "yellow": "#F9DF31", + "blue": "#53A3F3", + "grey": "#d3d3d3" + } + + var outer = d3.select("#chart") + .append("svg:svg") + .attr("width", space_width) + .attr("height", space_height) + .attr("pointer-events", "all") + .style("cursor","crosshair"); + + var vis = outer + .append('svg:g') + .on("dblclick.zoom", null) + .append('svg:g') + .on("mousemove", canvasMouseMove) + .on("mousedown", canvasMouseDown) + .on("mouseup", canvasMouseUp) + .on("touchend", function() { + clearTimeout(touchStartTime); + touchStartTime = null; + if (RED.touch.radialMenu.active()) { + return; + } + if (lasso) { + outer_background.attr("fill","#fff"); + } + canvasMouseUp.call(this); + }) + .on("touchcancel", canvasMouseUp) + .on("touchstart", function() { + var touch0; + if (d3.event.touches.length>1) { + clearTimeout(touchStartTime); + touchStartTime = null; + d3.event.preventDefault(); + touch0 = d3.event.touches.item(0); + var touch1 = d3.event.touches.item(1); + var a = touch0['pageY']-touch1['pageY']; + var b = touch0['pageX']-touch1['pageX']; + + var offset = $("#chart").offset(); + var scrollPos = [$("#chart").scrollLeft(),$("#chart").scrollTop()]; + startTouchCenter = [ + (touch1['pageX']+(b/2)-offset.left+scrollPos[0])/scaleFactor, + (touch1['pageY']+(a/2)-offset.top+scrollPos[1])/scaleFactor + ]; + moveTouchCenter = [ + touch1['pageX']+(b/2), + touch1['pageY']+(a/2) + ] + startTouchDistance = Math.sqrt((a*a)+(b*b)); + } else { + var obj = d3.select(document.body); + touch0 = d3.event.touches.item(0); + var pos = [touch0.pageX,touch0.pageY]; + startTouchCenter = [touch0.pageX,touch0.pageY]; + startTouchDistance = 0; + var point = d3.touches(this)[0]; + touchStartTime = setTimeout(function() { + touchStartTime = null; + showTouchMenu(obj,pos); + //lasso = vis.append('rect') + // .attr("ox",point[0]) + // .attr("oy",point[1]) + // .attr("rx",2) + // .attr("ry",2) + // .attr("x",point[0]) + // .attr("y",point[1]) + // .attr("width",0) + // .attr("height",0) + // .attr("class","lasso"); + //outer_background.attr("fill","#e3e3f3"); + },touchLongPressTimeout); + } + }) + .on("touchmove", function(){ + if (RED.touch.radialMenu.active()) { + d3.event.preventDefault(); + return; + } + var touch0; + if (d3.event.touches.length<2) { + if (touchStartTime) { + touch0 = d3.event.touches.item(0); + var dx = (touch0.pageX-startTouchCenter[0]); + var dy = (touch0.pageY-startTouchCenter[1]); + var d = Math.abs(dx*dx+dy*dy); + if (d > 64) { + clearTimeout(touchStartTime); + touchStartTime = null; + } + } else if (lasso) { + d3.event.preventDefault(); + } + canvasMouseMove.call(this); + } else { + touch0 = d3.event.touches.item(0); + var touch1 = d3.event.touches.item(1); + var a = touch0['pageY']-touch1['pageY']; + var b = touch0['pageX']-touch1['pageX']; + var offset = $("#chart").offset(); + var scrollPos = [$("#chart").scrollLeft(),$("#chart").scrollTop()]; + var moveTouchDistance = Math.sqrt((a*a)+(b*b)); + var touchCenter = [ + touch1['pageX']+(b/2), + touch1['pageY']+(a/2) + ]; + + if (!isNaN(moveTouchDistance)) { + oldScaleFactor = scaleFactor; + scaleFactor = Math.min(2,Math.max(0.3, scaleFactor + (Math.floor(((moveTouchDistance*100)-(startTouchDistance*100)))/10000))); + + var deltaTouchCenter = [ // Try to pan whilst zooming - not 100% + startTouchCenter[0]*(scaleFactor-oldScaleFactor),//-(touchCenter[0]-moveTouchCenter[0]), + startTouchCenter[1]*(scaleFactor-oldScaleFactor) //-(touchCenter[1]-moveTouchCenter[1]) + ]; + + startTouchDistance = moveTouchDistance; + moveTouchCenter = touchCenter; + + $("#chart").scrollLeft(scrollPos[0]+deltaTouchCenter[0]); + $("#chart").scrollTop(scrollPos[1]+deltaTouchCenter[1]); + redraw(); + } + } + }); + + var outer_background = vis.append('svg:rect') + .attr('width', space_width) + .attr('height', space_height) + .attr('fill','#fff'); + + //var gridScale = d3.scale.linear().range([0,2000]).domain([0,2000]); + //var grid = vis.append('g'); + // + //grid.selectAll("line.horizontal").data(gridScale.ticks(100)).enter() + // .append("line") + // .attr( + // { + // "class":"horizontal", + // "x1" : 0, + // "x2" : 2000, + // "y1" : function(d){ return gridScale(d);}, + // "y2" : function(d){ return gridScale(d);}, + // "fill" : "none", + // "shape-rendering" : "crispEdges", + // "stroke" : "#eee", + // "stroke-width" : "1px" + // }); + //grid.selectAll("line.vertical").data(gridScale.ticks(100)).enter() + // .append("line") + // .attr( + // { + // "class":"vertical", + // "y1" : 0, + // "y2" : 2000, + // "x1" : function(d){ return gridScale(d);}, + // "x2" : function(d){ return gridScale(d);}, + // "fill" : "none", + // "shape-rendering" : "crispEdges", + // "stroke" : "#eee", + // "stroke-width" : "1px" + // }); + + + var drag_line = vis.append("svg:path").attr("class", "drag_line"); + + var workspace_tabs = RED.tabs.create({ + id: "workspace-tabs", + onchange: function(tab) { + if (tab.type == "subflow") { + $("#workspace-toolbar").show(); + } else { + $("#workspace-toolbar").hide(); + } + var chart = $("#chart"); + if (activeWorkspace !== 0) { + workspaceScrollPositions[activeWorkspace] = { + left:chart.scrollLeft(), + top:chart.scrollTop() + }; + } + var scrollStartLeft = chart.scrollLeft(); + var scrollStartTop = chart.scrollTop(); + + activeWorkspace = tab.id; + if (workspaceScrollPositions[activeWorkspace]) { + chart.scrollLeft(workspaceScrollPositions[activeWorkspace].left); + chart.scrollTop(workspaceScrollPositions[activeWorkspace].top); + } else { + chart.scrollLeft(0); + chart.scrollTop(0); + } + var scrollDeltaLeft = chart.scrollLeft() - scrollStartLeft; + var scrollDeltaTop = chart.scrollTop() - scrollStartTop; + if (mouse_position != null) { + mouse_position[0] += scrollDeltaLeft; + mouse_position[1] += scrollDeltaTop; + } + + clearSelection(); + RED.nodes.eachNode(function(n) { + n.dirty = true; + }); + redraw(); + }, + ondblclick: function(tab) { + showRenameWorkspaceDialog(tab.id); + }, + onadd: function(tab) { + RED.menu.addItem("btn-workspace-menu",{ + id:"btn-workspace-menu-"+tab.id.replace(".","-"), + label:tab.label, + onselect:function() { + workspace_tabs.activateTab(tab.id); + } + }); + RED.menu.setDisabled("btn-workspace-delete",workspace_tabs.count() == 1); + }, + onremove: function(tab) { + RED.menu.setDisabled("btn-workspace-delete",workspace_tabs.count() == 1); + RED.menu.removeItem("btn-workspace-menu-"+tab.id.replace(".","-")); + } + }); + + var workspaceIndex = 0; + + function addWorkspace() { + var tabId = RED.nodes.id(); + do { + workspaceIndex += 1; + } while($("#workspace-tabs a[title='Sheet "+workspaceIndex+"']").size() !== 0); + + var ws = {type:"tab",id:tabId,label:"Sheet "+workspaceIndex}; + RED.nodes.addWorkspace(ws); + workspace_tabs.addTab(ws); + workspace_tabs.activateTab(tabId); + RED.history.push({t:'add',workspaces:[ws],dirty:dirty}); + RED.view.dirty(true); + } + $(function() { + $('#btn-workspace-add-tab').on("click",addWorkspace); + $('#btn-workspace-add').on("click",addWorkspace); + $('#btn-workspace-edit').on("click",function() { + showRenameWorkspaceDialog(activeWorkspace); + }); + $('#btn-workspace-delete').on("click",function() { + deleteWorkspace(activeWorkspace); + }); + }); + + function deleteWorkspace(id) { + if (workspace_tabs.count() == 1) { + return; + } + var ws = RED.nodes.workspace(id); + $( "#node-dialog-delete-workspace" ).dialog('option','workspace',ws); + $( "#node-dialog-delete-workspace-name" ).text(ws.label); + $( "#node-dialog-delete-workspace" ).dialog('open'); + } + + function canvasMouseDown() { + if (!mousedown_node && !mousedown_link) { + selected_link = null; + updateSelection(); + } + if (mouse_mode === 0) { + if (lasso) { + lasso.remove(); + lasso = null; + } + + if (!touchStartTime) { + var point = d3.mouse(this); + lasso = vis.append('rect') + .attr("ox",point[0]) + .attr("oy",point[1]) + .attr("rx",2) + .attr("ry",2) + .attr("x",point[0]) + .attr("y",point[1]) + .attr("width",0) + .attr("height",0) + .attr("class","lasso"); + d3.event.preventDefault(); + } + } + } + + function canvasMouseMove() { + mouse_position = d3.touches(this)[0]||d3.mouse(this); + + // Prevent touch scrolling... + //if (d3.touches(this)[0]) { + // d3.event.preventDefault(); + //} + + // TODO: auto scroll the container + //var point = d3.mouse(this); + //if (point[0]-container.scrollLeft < 30 && container.scrollLeft > 0) { container.scrollLeft -= 15; } + //console.log(d3.mouse(this),container.offsetWidth,container.offsetHeight,container.scrollLeft,container.scrollTop); + + if (lasso) { + var ox = parseInt(lasso.attr("ox")); + var oy = parseInt(lasso.attr("oy")); + var x = parseInt(lasso.attr("x")); + var y = parseInt(lasso.attr("y")); + var w; + var h; + if (mouse_position[0] < ox) { + x = mouse_position[0]; + w = ox-x; + } else { + w = mouse_position[0]-x; + } + if (mouse_position[1] < oy) { + y = mouse_position[1]; + h = oy-y; + } else { + h = mouse_position[1]-y; + } + lasso + .attr("x",x) + .attr("y",y) + .attr("width",w) + .attr("height",h) + ; + return; + } + + if (mouse_mode != RED.state.IMPORT_DRAGGING && !mousedown_node && selected_link == null) { + return; + } + + var mousePos; + if (mouse_mode == RED.state.JOINING) { + // update drag line + drag_line.attr("class", "drag_line"); + mousePos = mouse_position; + var numOutputs = (mousedown_port_type === 0)?(mousedown_node.outputs || 1):1; + var sourcePort = mousedown_port_index; + var portY = -((numOutputs-1)/2)*13 +13*sourcePort; + + var sc = (mousedown_port_type === 0)?1:-1; + + var dy = mousePos[1]-(mousedown_node.y+portY); + var dx = mousePos[0]-(mousedown_node.x+sc*mousedown_node.w/2); + var delta = Math.sqrt(dy*dy+dx*dx); + var scale = lineCurveScale; + var scaleY = 0; + + if (delta < node_width) { + scale = 0.75-0.75*((node_width-delta)/node_width); + } + if (dx*sc < 0) { + scale += 2*(Math.min(5*node_width,Math.abs(dx))/(5*node_width)); + if (Math.abs(dy) < 3*node_height) { + scaleY = ((dy>0)?0.5:-0.5)*(((3*node_height)-Math.abs(dy))/(3*node_height))*(Math.min(node_width,Math.abs(dx))/(node_width)) ; + } + } + + drag_line.attr("d", + "M "+(mousedown_node.x+sc*mousedown_node.w/2)+" "+(mousedown_node.y+portY)+ + " C "+(mousedown_node.x+sc*(mousedown_node.w/2+node_width*scale))+" "+(mousedown_node.y+portY+scaleY*node_height)+" "+ + (mousePos[0]-sc*(scale)*node_width)+" "+(mousePos[1]-scaleY*node_height)+" "+ + mousePos[0]+" "+mousePos[1] + ); + d3.event.preventDefault(); + } else if (mouse_mode == RED.state.MOVING) { + mousePos = mouse_position; + var d = (mouse_offset[0]-mousePos[0])*(mouse_offset[0]-mousePos[0]) + (mouse_offset[1]-mousePos[1])*(mouse_offset[1]-mousePos[1]); + if (d > 2) { + mouse_mode = RED.state.MOVING_ACTIVE; + clickElapsed = 0; + } + } else if (mouse_mode == RED.state.MOVING_ACTIVE || mouse_mode == RED.state.IMPORT_DRAGGING) { + mousePos = mouse_position; + var node; + var i; + var minX = 0; + var minY = 0; + for (var n = 0; n<moving_set.length; n++) { + node = moving_set[n]; + if (d3.event.shiftKey) { + node.n.ox = node.n.x; + node.n.oy = node.n.y; + } + node.n.x = mousePos[0]+node.dx; + node.n.y = mousePos[1]+node.dy; + node.n.dirty = true; + minX = Math.min(node.n.x-node.n.w/2-5,minX); + minY = Math.min(node.n.y-node.n.h/2-5,minY); + } + if (minX !== 0 || minY !== 0) { + for (i = 0; i<moving_set.length; i++) { + node = moving_set[i]; + node.n.x -= minX; + node.n.y -= minY; + } + } + if (d3.event.shiftKey && moving_set.length > 0) { + var gridOffset = [0,0]; + node = moving_set[0]; + gridOffset[0] = node.n.x-(20*Math.floor((node.n.x-node.n.w/2)/20)+node.n.w/2); + gridOffset[1] = node.n.y-(20*Math.floor(node.n.y/20)); + if (gridOffset[0] !== 0 || gridOffset[1] !== 0) { + for (i = 0; i<moving_set.length; i++) { + node = moving_set[i]; + node.n.x -= gridOffset[0]; + node.n.y -= gridOffset[1]; + if (node.n.x == node.n.ox && node.n.y == node.n.oy) { + node.dirty = false; + } + } + } + } + } + redraw(); + } + + function canvasMouseUp() { + if (mousedown_node && mouse_mode == RED.state.JOINING) { + drag_line.attr("class", "drag_line_hidden"); + } + if (lasso) { + var x = parseInt(lasso.attr("x")); + var y = parseInt(lasso.attr("y")); + var x2 = x+parseInt(lasso.attr("width")); + var y2 = y+parseInt(lasso.attr("height")); + if (!d3.event.ctrlKey) { + clearSelection(); + } + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace && !n.selected) { + n.selected = (n.x > x && n.x < x2 && n.y > y && n.y < y2); + if (n.selected) { + n.dirty = true; + moving_set.push({n:n}); + } + } + }); + updateSelection(); + lasso.remove(); + lasso = null; + } else if (mouse_mode == RED.state.DEFAULT && mousedown_link == null && !d3.event.ctrlKey ) { + clearSelection(); + updateSelection(); + } + if (mouse_mode == RED.state.MOVING_ACTIVE) { + if (moving_set.length > 0) { + var ns = []; + for (var j=0;j<moving_set.length;j++) { + ns.push({n:moving_set[j].n,ox:moving_set[j].ox,oy:moving_set[j].oy}); + } + RED.history.push({t:'move',nodes:ns,dirty:dirty}); + } + } + if (mouse_mode == RED.state.MOVING || mouse_mode == RED.state.MOVING_ACTIVE) { + for (var i=0;i<moving_set.length;i++) { + delete moving_set[i].ox; + delete moving_set[i].oy; + } + } + if (mouse_mode == RED.state.IMPORT_DRAGGING) { + RED.keyboard.remove(/* ESCAPE */ 27); + setDirty(true); + } + redraw(); + // clear mouse event vars + resetMouseVars(); + } + + $('#btn-zoom-out').click(function() {zoomOut();}); + $('#btn-zoom-zero').click(function() {zoomZero();}); + $('#btn-zoom-in').click(function() {zoomIn();}); + $("#chart").on('DOMMouseScroll mousewheel', function (evt) { + if ( evt.altKey ) { + evt.preventDefault(); + evt.stopPropagation(); + var move = -(evt.originalEvent.detail) || evt.originalEvent.wheelDelta; + if (move <= 0) { zoomOut(); } + else { zoomIn(); } + } + }); + $("#chart").droppable({ + accept:".palette_node", + drop: function( event, ui ) { + d3.event = event; + var selected_tool = ui.draggable[0].type; + var mousePos = d3.touches(this)[0]||d3.mouse(this); + mousePos[1] += this.scrollTop; + mousePos[0] += this.scrollLeft; + mousePos[1] /= scaleFactor; + mousePos[0] /= scaleFactor; + + var nn = { id:(1+Math.random()*4294967295).toString(16),x: mousePos[0],y:mousePos[1],w:node_width,z:activeWorkspace}; + + nn.type = selected_tool; + nn._def = RED.nodes.getType(nn.type); + nn.outputs = nn._def.outputs; + nn.changed = true; + + for (var d in nn._def.defaults) { + if (nn._def.defaults.hasOwnProperty(d)) { + nn[d] = nn._def.defaults[d].value; + } + } + + if (nn._def.onadd) { + nn._def.onadd.call(nn); + } + + nn.h = Math.max(node_height,(nn.outputs||0) * 15); + RED.history.push({t:'add',nodes:[nn.id],dirty:dirty}); + RED.nodes.add(nn); + RED.editor.validateNode(nn); + setDirty(true); + // auto select dropped node - so info shows (if visible) + clearSelection(); + nn.selected = true; + moving_set.push({n:nn}); + updateSelection(); + redraw(); + + if (nn._def.autoedit) { + RED.editor.edit(nn); + } + } + }); + + function zoomIn() { + if (scaleFactor < 2) { + scaleFactor += 0.1; + redraw(); + } + } + function zoomOut() { + if (scaleFactor > 0.3) { + scaleFactor -= 0.1; + redraw(); + } + } + function zoomZero() { + scaleFactor = 1; + redraw(); + } + + function selectAll() { + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + if (!n.selected) { + n.selected = true; + n.dirty = true; + moving_set.push({n:n}); + } + } + }); + selected_link = null; + updateSelection(); + redraw(); + } + + function clearSelection() { + for (var i=0;i<moving_set.length;i++) { + var n = moving_set[i]; + n.n.dirty = true; + n.n.selected = false; + } + moving_set = []; + selected_link = null; + } + + function updateSelection() { + if (moving_set.length === 0) { + RED.menu.setDisabled("btn-export-menu",true); + RED.menu.setDisabled("btn-export-clipboard",true); + RED.menu.setDisabled("btn-export-library",true); + } else { + RED.menu.setDisabled("btn-export-menu",false); + RED.menu.setDisabled("btn-export-clipboard",false); + RED.menu.setDisabled("btn-export-library",false); + } + if (moving_set.length === 0 && selected_link == null) { + RED.keyboard.remove(/* backspace */ 8); + RED.keyboard.remove(/* delete */ 46); + RED.keyboard.remove(/* c */ 67); + RED.keyboard.remove(/* x */ 88); + } else { + RED.keyboard.add(/* backspace */ 8,function(){deleteSelection();d3.event.preventDefault();}); + RED.keyboard.add(/* delete */ 46,function(){deleteSelection();d3.event.preventDefault();}); + RED.keyboard.add(/* c */ 67,{ctrl:true},function(){copySelection();d3.event.preventDefault();}); + RED.keyboard.add(/* x */ 88,{ctrl:true},function(){copySelection();deleteSelection();d3.event.preventDefault();}); + } + if (moving_set.length === 0) { + RED.keyboard.remove(/* up */ 38); + RED.keyboard.remove(/* down */ 40); + RED.keyboard.remove(/* left */ 37); + RED.keyboard.remove(/* right*/ 39); + } else { + RED.keyboard.add(/* up */ 38, function() { if(d3.event.shiftKey){moveSelection( 0,-20)}else{moveSelection( 0,-1);}d3.event.preventDefault();},endKeyboardMove); + RED.keyboard.add(/* down */ 40, function() { if(d3.event.shiftKey){moveSelection( 0, 20)}else{moveSelection( 0, 1);}d3.event.preventDefault();},endKeyboardMove); + RED.keyboard.add(/* left */ 37, function() { if(d3.event.shiftKey){moveSelection(-20, 0)}else{moveSelection(-1, 0);}d3.event.preventDefault();},endKeyboardMove); + RED.keyboard.add(/* right*/ 39, function() { if(d3.event.shiftKey){moveSelection( 20, 0)}else{moveSelection( 1, 0);}d3.event.preventDefault();},endKeyboardMove); + } + if (moving_set.length == 1) { + RED.sidebar.info.refresh(moving_set[0].n); + } else { + RED.sidebar.info.clear(); + } + } + function endKeyboardMove() { + var ns = []; + for (var i=0;i<moving_set.length;i++) { + ns.push({n:moving_set[i].n,ox:moving_set[i].ox,oy:moving_set[i].oy}); + delete moving_set[i].ox; + delete moving_set[i].oy; + } + RED.history.push({t:'move',nodes:ns,dirty:dirty}); + } + function moveSelection(dx,dy) { + var minX = 0; + var minY = 0; + var node; + + for (var i=0;i<moving_set.length;i++) { + node = moving_set[i]; + if (node.ox == null && node.oy == null) { + node.ox = node.n.x; + node.oy = node.n.y; + } + node.n.x += dx; + node.n.y += dy; + node.n.dirty = true; + minX = Math.min(node.n.x-node.n.w/2-5,minX); + minY = Math.min(node.n.y-node.n.h/2-5,minY); + } + + if (minX !== 0 || minY !== 0) { + for (var n = 0; n<moving_set.length; n++) { + node = moving_set[n]; + node.n.x -= minX; + node.n.y -= minY; + } + } + + redraw(); + } + function deleteSelection() { + var removedNodes = []; + var removedLinks = []; + var startDirty = dirty; + if (moving_set.length > 0) { + for (var i=0;i<moving_set.length;i++) { + var node = moving_set[i].n; + node.selected = false; + if (node.x < 0) { + node.x = 25 + } + var rmlinks = RED.nodes.remove(node.id); + removedNodes.push(node); + removedLinks = removedLinks.concat(rmlinks); + } + moving_set = []; + setDirty(true); + } + if (selected_link) { + RED.nodes.removeLink(selected_link); + removedLinks.push(selected_link); + setDirty(true); + } + RED.history.push({t:'delete',nodes:removedNodes,links:removedLinks,dirty:startDirty}); + + selected_link = null; + updateSelection(); + redraw(); + } + + function copySelection() { + if (moving_set.length > 0) { + var nns = []; + for (var n=0;n<moving_set.length;n++) { + var node = moving_set[n].n; + nns.push(RED.nodes.convertNode(node)); + } + clipboard = JSON.stringify(nns); + RED.notify(moving_set.length+" node"+(moving_set.length>1?"s":"")+" copied"); + } + } + + + function calculateTextWidth(str) { + var sp = document.createElement("span"); + sp.className = "node_label"; + sp.style.position = "absolute"; + sp.style.top = "-1000px"; + sp.innerHTML = (str||"").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"); + document.body.appendChild(sp); + var w = sp.offsetWidth; + document.body.removeChild(sp); + return 50+w; + } + + function resetMouseVars() { + mousedown_node = null; + mouseup_node = null; + mousedown_link = null; + mouse_mode = 0; + mousedown_port_type = 0; + } + + function portMouseDown(d,portType,portIndex) { + // disable zoom + //vis.call(d3.behavior.zoom().on("zoom"), null); + mousedown_node = d; + selected_link = null; + mouse_mode = RED.state.JOINING; + mousedown_port_type = portType; + mousedown_port_index = portIndex || 0; + document.body.style.cursor = "crosshair"; + d3.event.preventDefault(); + } + + function portMouseUp(d,portType,portIndex) { + document.body.style.cursor = ""; + if (mouse_mode == RED.state.JOINING && mousedown_node) { + if (typeof TouchEvent != "undefined" && d3.event instanceof TouchEvent) { + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + var hw = n.w/2; + var hh = n.h/2; + if (n.x-hw<mouse_position[0] && n.x+hw> mouse_position[0] && + n.y-hh<mouse_position[1] && n.y+hh>mouse_position[1]) { + mouseup_node = n; + portType = mouseup_node._def.inputs>0?1:0; + portIndex = 0; + } + } + }); + } else { + mouseup_node = d; + } + if (portType == mousedown_port_type || mouseup_node === mousedown_node) { + drag_line.attr("class", "drag_line_hidden"); + resetMouseVars(); + return; + } + var src,dst,src_port; + if (mousedown_port_type === 0) { + src = mousedown_node; + src_port = mousedown_port_index; + dst = mouseup_node; + } else if (mousedown_port_type == 1) { + src = mouseup_node; + dst = mousedown_node; + src_port = portIndex; + } + + var existingLink = false; + RED.nodes.eachLink(function(d) { + existingLink = existingLink || (d.source === src && d.target === dst && d.sourcePort == src_port); + }); + if (!existingLink) { + var link = {source: src, sourcePort:src_port, target: dst}; + RED.nodes.addLink(link); + RED.history.push({t:'add',links:[link],dirty:dirty}); + setDirty(true); + } + selected_link = null; + redraw(); + } + } + + function nodeMouseUp(d) { + if (dblClickPrimed && mousedown_node == d && clickElapsed > 0 && clickElapsed < 750) { + RED.editor.edit(d); + clickElapsed = 0; + d3.event.stopPropagation(); + return; + } + portMouseUp(d, d._def.inputs > 0 ? 1 : 0, 0); + } + + function nodeMouseDown(d) { + //var touch0 = d3.event; + //var pos = [touch0.pageX,touch0.pageY]; + //RED.touch.radialMenu.show(d3.select(this),pos); + if (mouse_mode == RED.state.IMPORT_DRAGGING) { + RED.keyboard.remove(/* ESCAPE */ 27); + updateSelection(); + setDirty(true); + redraw(); + resetMouseVars(); + d3.event.stopPropagation(); + return; + } + mousedown_node = d; + var now = Date.now(); + clickElapsed = now-clickTime; + clickTime = now; + + dblClickPrimed = (lastClickNode == mousedown_node); + lastClickNode = mousedown_node; + + var i; + + if (d.selected && d3.event.ctrlKey) { + d.selected = false; + for (i=0;i<moving_set.length;i+=1) { + if (moving_set[i].n === d) { + moving_set.splice(i,1); + break; + } + } + } else { + if (d3.event.shiftKey) { + clearSelection(); + var cnodes = RED.nodes.getAllFlowNodes(mousedown_node); + for (var n=0;n<cnodes.length;n++) { + cnodes[n].selected = true; + cnodes[n].dirty = true; + moving_set.push({n:cnodes[n]}); + } + } else if (!d.selected) { + if (!d3.event.ctrlKey) { + clearSelection(); + } + mousedown_node.selected = true; + moving_set.push({n:mousedown_node}); + } + selected_link = null; + if (d3.event.button != 2) { + mouse_mode = RED.state.MOVING; + var mouse = d3.touches(this)[0]||d3.mouse(this); + mouse[0] += d.x-d.w/2; + mouse[1] += d.y-d.h/2; + for (i=0;i<moving_set.length;i++) { + moving_set[i].ox = moving_set[i].n.x; + moving_set[i].oy = moving_set[i].n.y; + moving_set[i].dx = moving_set[i].n.x-mouse[0]; + moving_set[i].dy = moving_set[i].n.y-mouse[1]; + } + mouse_offset = d3.mouse(document.body); + if (isNaN(mouse_offset[0])) { + mouse_offset = d3.touches(document.body)[0]; + } + } + } + d.dirty = true; + updateSelection(); + redraw(); + d3.event.stopPropagation(); + } + + function nodeButtonClicked(d) { + if (d._def.button.toggle) { + d[d._def.button.toggle] = !d[d._def.button.toggle]; + d.dirty = true; + } + if (d._def.button.onclick) { + d._def.button.onclick.call(d); + } + if (d.dirty) { + redraw(); + } + d3.event.preventDefault(); + } + + function showTouchMenu(obj,pos) { + var mdn = mousedown_node; + var options = []; + options.push({name:"delete",disabled:(moving_set.length===0),onselect:function() {deleteSelection();}}); + options.push({name:"cut",disabled:(moving_set.length===0),onselect:function() {copySelection();deleteSelection();}}); + options.push({name:"copy",disabled:(moving_set.length===0),onselect:function() {copySelection();}}); + options.push({name:"paste",disabled:(clipboard.length===0),onselect:function() {importNodes(clipboard,true);}}); + options.push({name:"edit",disabled:(moving_set.length != 1),onselect:function() { RED.editor.edit(mdn);}}); + options.push({name:"select",onselect:function() {selectAll();}}); + options.push({name:"undo",disabled:(RED.history.depth() === 0),onselect:function() {RED.history.pop();}}); + + RED.touch.radialMenu.show(obj,pos,options); + resetMouseVars(); + } + function redraw() { + vis.attr("transform","scale("+scaleFactor+")"); + outer.attr("width", space_width*scaleFactor).attr("height", space_height*scaleFactor); + + if (mouse_mode != RED.state.JOINING) { + // Don't bother redrawing nodes if we're drawing links + + var node = vis.selectAll(".nodegroup").data(RED.nodes.nodes.filter(function(d) { return d.z == activeWorkspace }),function(d){return d.id}); + node.exit().remove(); + + var nodeEnter = node.enter().insert("svg:g").attr("class", "node nodegroup"); + nodeEnter.each(function(d,i) { + var node = d3.select(this); + node.attr("id",d.id); + var l = d._def.label; + l = (typeof l === "function" ? l.call(d) : l)||""; + d.w = Math.max(node_width,calculateTextWidth(l)+(d._def.inputs>0?7:0) ); + d.h = Math.max(node_height,(d.outputs||0) * 15); + + if (d._def.badge) { + var badge = node.append("svg:g").attr("class","node_badge_group"); + var badgeRect = badge.append("rect").attr("class","node_badge").attr("rx",5).attr("ry",5).attr("width",40).attr("height",15); + badge.append("svg:text").attr("class","node_badge_label").attr("x",35).attr("y",11).attr('text-anchor','end').text(d._def.badge()); + if (d._def.onbadgeclick) { + badgeRect.attr("cursor","pointer") + .on("click",function(d) { d._def.onbadgeclick.call(d);d3.event.preventDefault();}); + } + } + + if (d._def.button) { + var nodeButtonGroup = node.append('svg:g') + .attr("transform",function(d) { return "translate("+((d._def.align == "right") ? 94 : -25)+",2)"; }) + .attr("class",function(d) { return "node_button "+((d._def.align == "right") ? "node_right_button" : "node_left_button"); }); + nodeButtonGroup.append('rect') + .attr("rx",8) + .attr("ry",8) + .attr("width",32) + .attr("height",node_height-4) + .attr("fill","#eee");//function(d) { return d._def.color;}) + nodeButtonGroup.append('rect') + .attr("x",function(d) { return d._def.align == "right"? 10:5}) + .attr("y",4) + .attr("rx",5) + .attr("ry",5) + .attr("width",16) + .attr("height",node_height-12) + .attr("fill",function(d) { return d._def.color;}) + .attr("cursor","pointer") + .on("mousedown",function(d) {if (!lasso) { d3.select(this).attr("fill-opacity",0.2);d3.event.preventDefault(); d3.event.stopPropagation();}}) + .on("mouseup",function(d) {if (!lasso) { d3.select(this).attr("fill-opacity",0.4);d3.event.preventDefault();d3.event.stopPropagation();}}) + .on("mouseover",function(d) {if (!lasso) { d3.select(this).attr("fill-opacity",0.4);}}) + .on("mouseout",function(d) {if (!lasso) { + var op = 1; + if (d._def.button.toggle) { + op = d[d._def.button.toggle]?1:0.2; + } + d3.select(this).attr("fill-opacity",op); + }}) + .on("click",nodeButtonClicked) + .on("touchstart",nodeButtonClicked) + } + + var mainRect = node.append("rect") + .attr("class", "node") + .classed("node_unknown",function(d) { return d.type == "unknown"; }) + .attr("rx", 6) + .attr("ry", 6) + .attr("fill",function(d) { return d._def.color;}) + .on("mouseup",nodeMouseUp) + .on("mousedown",nodeMouseDown) + .on("touchstart",function(d) { + var obj = d3.select(this); + var touch0 = d3.event.touches.item(0); + var pos = [touch0.pageX,touch0.pageY]; + startTouchCenter = [touch0.pageX,touch0.pageY]; + startTouchDistance = 0; + touchStartTime = setTimeout(function() { + showTouchMenu(obj,pos); + },touchLongPressTimeout); + nodeMouseDown.call(this,d) + }) + .on("touchend", function(d) { + clearTimeout(touchStartTime); + touchStartTime = null; + if (RED.touch.radialMenu.active()) { + d3.event.stopPropagation(); + return; + } + nodeMouseUp.call(this,d); + }) + .on("mouseover",function(d) { + if (mouse_mode === 0) { + var node = d3.select(this); + node.classed("node_hovered",true); + } + }) + .on("mouseout",function(d) { + var node = d3.select(this); + node.classed("node_hovered",false); + }); + + //node.append("rect").attr("class", "node-gradient-top").attr("rx", 6).attr("ry", 6).attr("height",30).attr("stroke","none").attr("fill","url(#gradient-top)").style("pointer-events","none"); + //node.append("rect").attr("class", "node-gradient-bottom").attr("rx", 6).attr("ry", 6).attr("height",30).attr("stroke","none").attr("fill","url(#gradient-bottom)").style("pointer-events","none"); + + if (d._def.icon) { + + var icon_group = node.append("g") + .attr("class","node_icon_group") + .attr("x",0).attr("y",0); + + var icon_shade = icon_group.append("rect") + .attr("x",0).attr("y",0) + .attr("class","node_icon_shade") + .attr("width","30") + .attr("stroke","none") + .attr("fill","#000") + .attr("fill-opacity","0.05") + .attr("height",function(d){return Math.min(50,d.h-4);}); + + var icon = icon_group.append("image") + .attr("xlink:href","icons/"+d._def.icon) + .attr("class","node_icon") + .attr("x",0) + .attr("width","30") + .attr("height","30"); + + var icon_shade_border = icon_group.append("path") + .attr("d",function(d) { return "M 30 1 l 0 "+(d.h-2)}) + .attr("class","node_icon_shade_border") + .attr("stroke-opacity","0.1") + .attr("stroke","#000") + .attr("stroke-width","2"); + + if ("right" == d._def.align) { + icon_group.attr('class','node_icon_group node_icon_group_'+d._def.align); + icon_shade_border.attr("d",function(d) { return "M 0 1 l 0 "+(d.h-2)}) + //icon.attr('class','node_icon node_icon_'+d._def.align); + //icon.attr('class','node_icon_shade node_icon_shade_'+d._def.align); + //icon.attr('class','node_icon_shade_border node_icon_shade_border_'+d._def.align); + } + + //if (d._def.inputs > 0 && d._def.align == null) { + // icon_shade.attr("width",35); + // icon.attr("transform","translate(5,0)"); + // icon_shade_border.attr("transform","translate(5,0)"); + //} + //if (d._def.outputs > 0 && "right" == d._def.align) { + // icon_shade.attr("width",35); //icon.attr("x",5); + //} + + var img = new Image(); + img.src = "icons/"+d._def.icon; + img.onload = function() { + icon.attr("width",Math.min(img.width,30)); + icon.attr("height",Math.min(img.height,30)); + icon.attr("x",15-Math.min(img.width,30)/2); + //if ("right" == d._def.align) { + // icon.attr("x",function(d){return d.w-img.width-1-(d.outputs>0?5:0);}); + // icon_shade.attr("x",function(d){return d.w-30}); + // icon_shade_border.attr("d",function(d){return "M "+(d.w-30)+" 1 l 0 "+(d.h-2);}); + //} + } + + //icon.style("pointer-events","none"); + icon_group.style("pointer-events","none"); + } + var text = node.append('svg:text').attr('class','node_label').attr('x', 38).attr('dy', '.35em').attr('text-anchor','start'); + if (d._def.align) { + text.attr('class','node_label node_label_'+d._def.align); + text.attr('text-anchor','end'); + } + + var status = node.append("svg:g").attr("class","node_status_group").style("display","none"); + + var statusRect = status.append("rect").attr("class","node_status") + .attr("x",6).attr("y",1).attr("width",9).attr("height",9) + .attr("rx",2).attr("ry",2).attr("stroke-width","3"); + + var statusLabel = status.append("svg:text") + .attr("class","node_status_label") + .attr('x',20).attr('y',9) + .style({ + 'stroke-width': 0, + 'fill': '#888', + 'font-size':'9pt', + 'stroke':'#000', + 'text-anchor':'start' + }); + + //node.append("circle").attr({"class":"centerDot","cx":0,"cy":0,"r":5}); + + if (d._def.inputs > 0) { + text.attr("x",38); + node.append("rect").attr("class","port port_input").attr("rx",3).attr("ry",3).attr("x",-5).attr("width",10).attr("height",10) + .on("mousedown",function(d){portMouseDown(d,1,0);}) + .on("touchstart",function(d){portMouseDown(d,1,0);}) + .on("mouseup",function(d){portMouseUp(d,1,0);} ) + .on("touchend",function(d){portMouseUp(d,1,0);} ) + .on("mouseover",function(d) { var port = d3.select(this); port.classed("port_hovered",(mouse_mode!=RED.state.JOINING || mousedown_port_type != 1 ));}) + .on("mouseout",function(d) { var port = d3.select(this); port.classed("port_hovered",false);}) + } + + //node.append("path").attr("class","node_error").attr("d","M 3,-3 l 10,0 l -5,-8 z"); + node.append("image").attr("class","node_error hidden").attr("xlink:href","icons/node-error.png").attr("x",0).attr("y",-6).attr("width",10).attr("height",9); + node.append("image").attr("class","node_changed hidden").attr("xlink:href","icons/node-changed.png").attr("x",12).attr("y",-6).attr("width",10).attr("height",10); + }); + + node.each(function(d,i) { + if (d.dirty) { + //if (d.x < -50) deleteSelection(); // Delete nodes if dragged back to palette + if (d.resize) { + var l = d._def.label; + l = (typeof l === "function" ? l.call(d) : l)||""; + d.w = Math.max(node_width,calculateTextWidth(l)+(d._def.inputs>0?7:0) ); + d.h = Math.max(node_height,(d.outputs||0) * 15); + } + var thisNode = d3.select(this); + //thisNode.selectAll(".centerDot").attr({"cx":function(d) { return d.w/2;},"cy":function(d){return d.h/2}}); + thisNode.attr("transform", function(d) { return "translate(" + (d.x-d.w/2) + "," + (d.y-d.h/2) + ")"; }); + thisNode.selectAll(".node") + .attr("width",function(d){return d.w}) + .attr("height",function(d){return d.h}) + .classed("node_selected",function(d) { return d.selected; }) + .classed("node_highlighted",function(d) { return d.highlighted; }) + ; + //thisNode.selectAll(".node-gradient-top").attr("width",function(d){return d.w}); + //thisNode.selectAll(".node-gradient-bottom").attr("width",function(d){return d.w}).attr("y",function(d){return d.h-30}); + + thisNode.selectAll(".node_icon_group_right").attr('transform', function(d){return "translate("+(d.w-30)+",0)"}); + thisNode.selectAll(".node_label_right").attr('x', function(d){return d.w-38}); + //thisNode.selectAll(".node_icon_right").attr("x",function(d){return d.w-d3.select(this).attr("width")-1-(d.outputs>0?5:0);}); + //thisNode.selectAll(".node_icon_shade_right").attr("x",function(d){return d.w-30;}); + //thisNode.selectAll(".node_icon_shade_border_right").attr("d",function(d){return "M "+(d.w-30)+" 1 l 0 "+(d.h-2)}); + + + var numOutputs = d.outputs; + var y = (d.h/2)-((numOutputs-1)/2)*13; + d.ports = d.ports || d3.range(numOutputs); + d._ports = thisNode.selectAll(".port_output").data(d.ports); + d._ports.enter().append("rect").attr("class","port port_output").attr("rx",3).attr("ry",3).attr("width",10).attr("height",10) + .on("mousedown",(function(){var node = d; return function(d,i){portMouseDown(node,0,i);}})() ) + .on("touchstart",(function(){var node = d; return function(d,i){portMouseDown(node,0,i);}})() ) + .on("mouseup",(function(){var node = d; return function(d,i){portMouseUp(node,0,i);}})() ) + .on("touchend",(function(){var node = d; return function(d,i){portMouseUp(node,0,i);}})() ) + .on("mouseover",function(d,i) { var port = d3.select(this); port.classed("port_hovered",(mouse_mode!=RED.state.JOINING || mousedown_port_type !== 0 ));}) + .on("mouseout",function(d,i) { var port = d3.select(this); port.classed("port_hovered",false);}); + d._ports.exit().remove(); + if (d._ports) { + numOutputs = d.outputs || 1; + y = (d.h/2)-((numOutputs-1)/2)*13; + var x = d.w - 5; + d._ports.each(function(d,i) { + var port = d3.select(this); + port.attr("y",(y+13*i)-5).attr("x",x); + }); + } + thisNode.selectAll('text.node_label').text(function(d,i){ + if (d._def.label) { + if (typeof d._def.label == "function") { + return d._def.label.call(d); + } else { + return d._def.label; + } + } + return ""; + }) + .attr('y', function(d){return (d.h/2)-1;}) + .attr('class',function(d){ + return 'node_label'+ + (d._def.align?' node_label_'+d._def.align:'')+ + (d._def.labelStyle?' '+(typeof d._def.labelStyle == "function" ? d._def.labelStyle.call(d):d._def.labelStyle):'') ; + }); + thisNode.selectAll(".node_tools").attr("x",function(d){return d.w-35;}).attr("y",function(d){return d.h-20;}); + + thisNode.selectAll(".node_changed") + .attr("x",function(d){return d.w-10}) + .classed("hidden",function(d) { return !d.changed; }); + + thisNode.selectAll(".node_error") + .attr("x",function(d){return d.w-10-(d.changed?13:0)}) + .classed("hidden",function(d) { return d.valid; }); + + thisNode.selectAll(".port_input").each(function(d,i) { + var port = d3.select(this); + port.attr("y",function(d){return (d.h/2)-5;}) + }); + + thisNode.selectAll(".node_icon").attr("y",function(d){return (d.h-d3.select(this).attr("height"))/2;}); + thisNode.selectAll(".node_icon_shade").attr("height",function(d){return d.h;}); + thisNode.selectAll(".node_icon_shade_border").attr("d",function(d){ return "M "+(("right" == d._def.align) ?0:30)+" 1 l 0 "+(d.h-2)}); + + + thisNode.selectAll('.node_right_button').attr("transform",function(d){ + var x = d.w-6; + if (d._def.button.toggle && !d[d._def.button.toggle]) { + x = x - 8; + } + return "translate("+x+",2)"; + }); + thisNode.selectAll('.node_right_button rect').attr("fill-opacity",function(d){ + if (d._def.button.toggle) { + return d[d._def.button.toggle]?1:0.2; + } + return 1; + }); + + //thisNode.selectAll('.node_right_button').attr("transform",function(d){return "translate("+(d.w - d._def.button.width.call(d))+","+0+")";}).attr("fill",function(d) { + // return typeof d._def.button.color === "function" ? d._def.button.color.call(d):(d._def.button.color != null ? d._def.button.color : d._def.color) + //}); + + thisNode.selectAll('.node_badge_group').attr("transform",function(d){return "translate("+(d.w-40)+","+(d.h+3)+")";}); + thisNode.selectAll('text.node_badge_label').text(function(d,i) { + if (d._def.badge) { + if (typeof d._def.badge == "function") { + return d._def.badge.call(d); + } else { + return d._def.badge; + } + } + return ""; + }); + if (!showStatus || !d.status) { + thisNode.selectAll('.node_status_group').style("display","none"); + } else { + thisNode.selectAll('.node_status_group').style("display","inline").attr("transform","translate(3,"+(d.h+3)+")"); + var fill = status_colours[d.status.fill]; // Only allow our colours for now + if (d.status.shape == null && fill == null) { + thisNode.selectAll('.node_status').style("display","none"); + } else { + var style; + if (d.status.shape == null || d.status.shape == "dot") { + style = { + display: "inline", + fill: fill, + stroke: fill + }; + } else if (d.status.shape == "ring" ){ + style = { + display: "inline", + fill: '#fff', + stroke: fill + } + } + thisNode.selectAll('.node_status').style(style); + } + if (d.status.text) { + thisNode.selectAll('.node_status_label').text(d.status.text); + } else { + thisNode.selectAll('.node_status_label').text(""); + } + } + + d.dirty = false; + } + }); + } + + var link = vis.selectAll(".link").data(RED.nodes.links.filter(function(d) { return d.source.z == activeWorkspace && d.target.z == activeWorkspace }),function(d) { return d.source.id+":"+d.sourcePort+":"+d.target.id;}); + + var linkEnter = link.enter().insert("g",".node").attr("class","link"); + + linkEnter.each(function(d,i) { + var l = d3.select(this); + l.append("svg:path").attr("class","link_background link_path") + .on("mousedown",function(d) { + mousedown_link = d; + clearSelection(); + selected_link = mousedown_link; + updateSelection(); + redraw(); + d3.event.stopPropagation(); + }) + .on("touchstart",function(d) { + mousedown_link = d; + clearSelection(); + selected_link = mousedown_link; + updateSelection(); + redraw(); + d3.event.stopPropagation(); + }); + l.append("svg:path").attr("class","link_outline link_path"); + l.append("svg:path").attr("class","link_line link_path"); + }); + + link.exit().remove(); + + var links = vis.selectAll(".link_path") + links.attr("d",function(d){ + var numOutputs = d.source.outputs || 1; + var sourcePort = d.sourcePort || 0; + var y = -((numOutputs-1)/2)*13 +13*sourcePort; + + var dy = d.target.y-(d.source.y+y); + var dx = (d.target.x-d.target.w/2)-(d.source.x+d.source.w/2); + var delta = Math.sqrt(dy*dy+dx*dx); + var scale = lineCurveScale; + var scaleY = 0; + if (delta < node_width) { + scale = 0.75-0.75*((node_width-delta)/node_width); + } + + if (dx < 0) { + scale += 2*(Math.min(5*node_width,Math.abs(dx))/(5*node_width)); + if (Math.abs(dy) < 3*node_height) { + scaleY = ((dy>0)?0.5:-0.5)*(((3*node_height)-Math.abs(dy))/(3*node_height))*(Math.min(node_width,Math.abs(dx))/(node_width)) ; + } + } + + d.x1 = d.source.x+d.source.w/2; + d.y1 = d.source.y+y; + d.x2 = d.target.x-d.target.w/2; + d.y2 = d.target.y; + + return "M "+(d.source.x+d.source.w/2)+" "+(d.source.y+y)+ + " C "+(d.source.x+d.source.w/2+scale*node_width)+" "+(d.source.y+y+scaleY*node_height)+" "+ + (d.target.x-d.target.w/2-scale*node_width)+" "+(d.target.y-scaleY*node_height)+" "+ + (d.target.x-d.target.w/2)+" "+d.target.y; + }) + + link.classed("link_selected", function(d) { return d === selected_link || d.selected; }); + link.classed("link_unknown",function(d) { return d.target.type == "unknown" || d.source.type == "unknown"}); + + if (d3.event) { + d3.event.preventDefault(); + } + } + + RED.keyboard.add(/* z */ 90,{ctrl:true},function(){RED.history.pop();}); + RED.keyboard.add(/* a */ 65,{ctrl:true},function(){selectAll();d3.event.preventDefault();}); + RED.keyboard.add(/* = */ 187,{ctrl:true},function(){zoomIn();d3.event.preventDefault();}); + RED.keyboard.add(/* - */ 189,{ctrl:true},function(){zoomOut();d3.event.preventDefault();}); + RED.keyboard.add(/* 0 */ 48,{ctrl:true},function(){zoomZero();d3.event.preventDefault();}); + RED.keyboard.add(/* v */ 86,{ctrl:true},function(){importNodes(clipboard);d3.event.preventDefault();}); + RED.keyboard.add(/* e */ 69,{ctrl:true},function(){showExportNodesDialog();d3.event.preventDefault();}); + RED.keyboard.add(/* i */ 73,{ctrl:true},function(){showImportNodesDialog();d3.event.preventDefault();}); + + // TODO: 'dirty' should be a property of RED.nodes - with an event callback for ui hooks + function setDirty(d) { + dirty = d; + if (dirty) { + $("#btn-deploy").removeClass("disabled"); + } else { + $("#btn-deploy").addClass("disabled"); + } + } + + /** + * Imports a new collection of nodes from a JSON String. + * - all get new IDs assigned + * - all 'selected' + * - attached to mouse for placing - 'IMPORT_DRAGGING' + */ + function importNodes(newNodesStr,touchImport) { + try { + var result = RED.nodes.import(newNodesStr,true); + if (result) { + var new_nodes = result[0]; + var new_links = result[1]; + var new_workspaces = result[2]; + + var new_ms = new_nodes.filter(function(n) { return n.z == activeWorkspace }).map(function(n) { return {n:n};}); + var new_node_ids = new_nodes.map(function(n){ return n.id; }); + + // TODO: pick a more sensible root node + if (new_ms.length > 0) { + var root_node = new_ms[0].n; + var dx = root_node.x; + var dy = root_node.y; + + if (mouse_position == null) { + mouse_position = [0,0]; + } + + var minX = 0; + var minY = 0; + var i; + var node; + + for (i=0;i<new_ms.length;i++) { + node = new_ms[i]; + node.n.selected = true; + node.n.changed = true; + node.n.x -= dx - mouse_position[0]; + node.n.y -= dy - mouse_position[1]; + node.dx = node.n.x - mouse_position[0]; + node.dy = node.n.y - mouse_position[1]; + minX = Math.min(node.n.x-node_width/2-5,minX); + minY = Math.min(node.n.y-node_height/2-5,minY); + } + for (i=0;i<new_ms.length;i++) { + node = new_ms[i]; + node.n.x -= minX; + node.n.y -= minY; + node.dx -= minX; + node.dy -= minY; + } + if (!touchImport) { + mouse_mode = RED.state.IMPORT_DRAGGING; + } + + RED.keyboard.add(/* ESCAPE */ 27,function(){ + RED.keyboard.remove(/* ESCAPE */ 27); + clearSelection(); + RED.history.pop(); + mouse_mode = 0; + }); + clearSelection(); + moving_set = new_ms; + } + + RED.history.push({t:'add',nodes:new_node_ids,links:new_links,workspaces:new_workspaces,dirty:RED.view.dirty()}); + + + redraw(); + } + } catch(error) { + console.log(error.stack); + RED.notify("<strong>Error</strong>: "+error,"error"); + } + } + + function showExportNodesDialog() { + mouse_mode = RED.state.EXPORT; + var nns = RED.nodes.createExportableNodeSet(moving_set); + $("#dialog-form").html($("script[data-template-name='export-clipboard-dialog']").html()); + $("#node-input-export").val(JSON.stringify(nns)); + $("#node-input-export").focus(function() { + var textarea = $(this); + textarea.select(); + textarea.mouseup(function() { + textarea.unbind("mouseup"); + return false; + }); + }); + $( "#dialog" ).dialog("option","title","Export nodes to clipboard").dialog( "open" ); + $("#node-input-export").focus(); + } + + function showExportNodesLibraryDialog() { + mouse_mode = RED.state.EXPORT; + var nns = RED.nodes.createExportableNodeSet(moving_set); + $("#dialog-form").html($("script[data-template-name='export-library-dialog']").html()); + $("#node-input-filename").attr('nodes',JSON.stringify(nns)); + $( "#dialog" ).dialog("option","title","Export nodes to library").dialog( "open" ); + } + + function showImportNodesDialog() { + mouse_mode = RED.state.IMPORT; + $("#dialog-form").html($("script[data-template-name='import-dialog']").html()); + $("#node-input-import").val(""); + $( "#dialog" ).dialog("option","title","Import nodes").dialog( "open" ); + } + + function showRenameWorkspaceDialog(id) { + var ws = RED.nodes.workspace(id); + $( "#node-dialog-rename-workspace" ).dialog("option","workspace",ws); + + if (workspace_tabs.count() == 1) { + $( "#node-dialog-rename-workspace").next().find(".leftButton") + .prop('disabled',true) + .addClass("ui-state-disabled"); + } else { + $( "#node-dialog-rename-workspace").next().find(".leftButton") + .prop('disabled',false) + .removeClass("ui-state-disabled"); + } + + $( "#node-input-workspace-name" ).val(ws.label); + $( "#node-dialog-rename-workspace" ).dialog("open"); + } + + $("#node-dialog-rename-workspace form" ).submit(function(e) { e.preventDefault();}); + $( "#node-dialog-rename-workspace" ).dialog({ + modal: true, + autoOpen: false, + width: 500, + title: "Rename sheet", + buttons: [ + { + class: 'leftButton', + text: "Delete", + click: function() { + var workspace = $(this).dialog('option','workspace'); + $( this ).dialog( "close" ); + deleteWorkspace(workspace.id); + } + }, + { + text: "Ok", + click: function() { + var workspace = $(this).dialog('option','workspace'); + var label = $( "#node-input-workspace-name" ).val(); + if (workspace.label != label) { + workspace.label = label; + var link = $("#workspace-tabs a[href='#"+workspace.id+"']"); + link.attr("title",label); + link.text(label); + RED.view.dirty(true); + } + $( this ).dialog( "close" ); + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + open: function(e) { + RED.keyboard.disable(); + }, + close: function(e) { + RED.keyboard.enable(); + } + }); + $( "#node-dialog-delete-workspace" ).dialog({ + modal: true, + autoOpen: false, + width: 500, + title: "Confirm delete", + buttons: [ + { + text: "Ok", + click: function() { + var workspace = $(this).dialog('option','workspace'); + RED.view.removeWorkspace(workspace); + var historyEvent = RED.nodes.removeWorkspace(workspace.id); + historyEvent.t = 'delete'; + historyEvent.dirty = dirty; + historyEvent.workspaces = [workspace]; + RED.history.push(historyEvent); + RED.view.dirty(true); + $( this ).dialog( "close" ); + } + }, + { + text: "Cancel", + click: function() { + $( this ).dialog( "close" ); + } + } + ], + open: function(e) { + RED.keyboard.disable(); + }, + close: function(e) { + RED.keyboard.enable(); + } + + }); + + return { + state:function(state) { + if (state == null) { + return mouse_mode + } else { + mouse_mode = state; + } + }, + addWorkspace: function(ws) { + workspace_tabs.addTab(ws); + workspace_tabs.resize(); + }, + removeWorkspace: function(ws) { + workspace_tabs.removeTab(ws.id); + }, + getWorkspace: function() { + return activeWorkspace; + }, + showWorkspace: function(id) { + workspace_tabs.activateTab(id); + }, + redraw:redraw, + dirty: function(d) { + if (d == null) { + return dirty; + } else { + setDirty(d); + } + }, + importNodes: importNodes, + resize: function() { + workspace_tabs.resize(); + }, + status: function(s) { + showStatus = s; + RED.nodes.eachNode(function(n) { n.dirty = true;}); + //TODO: subscribe/unsubscribe here + redraw(); + }, + + //TODO: should these move to an import/export module? + showImportNodesDialog: showImportNodesDialog, + showExportNodesDialog: showExportNodesDialog, + showExportNodesLibraryDialog: showExportNodesLibraryDialog + }; +})(); diff --git a/dgbuilder/public/red/validators.js b/dgbuilder/public/red/validators.js new file mode 100644 index 00000000..5e740973 --- /dev/null +++ b/dgbuilder/public/red/validators.js @@ -0,0 +1,19 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +RED.validators = { + number: function(){return function(v) { return v!=='' && !isNaN(v);}}, + regex: function(re){return function(v) { return re.test(v);}} +}; diff --git a/dgbuilder/public/spin.svg b/dgbuilder/public/spin.svg new file mode 100644 index 00000000..e609530a --- /dev/null +++ b/dgbuilder/public/spin.svg @@ -0,0 +1,41 @@ +<!-- +The MIT License (MIT) + +Copyright (c) 2014 Brent Jackson + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to use, +copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +https://github.com/jxnblk/loading +--> +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32" fill="#999"> + <path transform="translate(2)" d="M0 12 V20 H4 V12z"> + <animate attributeName="d" values="M0 12 V20 H4 V12z; M0 4 V28 H4 V4z; M0 12 V20 H4 V12z; M0 12 V20 H4 V12z" dur="1.2s" repeatCount="indefinite" begin="0" keytimes="0;.2;.5;1" keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.8 0.4 0.8" calcMode="spline" /> + </path> + <path transform="translate(8)" d="M0 12 V20 H4 V12z"> + <animate attributeName="d" values="M0 12 V20 H4 V12z; M0 4 V28 H4 V4z; M0 12 V20 H4 V12z; M0 12 V20 H4 V12z" dur="1.2s" repeatCount="indefinite" begin="0.2" keytimes="0;.2;.5;1" keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.8 0.4 0.8" calcMode="spline" /> + </path> + <path transform="translate(14)" d="M0 12 V20 H4 V12z"> + <animate attributeName="d" values="M0 12 V20 H4 V12z; M0 4 V28 H4 V4z; M0 12 V20 H4 V12z; M0 12 V20 H4 V12z" dur="1.2s" repeatCount="indefinite" begin="0.4" keytimes="0;.2;.5;1" keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.8 0.4 0.8" calcMode="spline" /> + </path> + <path transform="translate(20)" d="M0 12 V20 H4 V12z"> + <animate attributeName="d" values="M0 12 V20 H4 V12z; M0 4 V28 H4 V4z; M0 12 V20 H4 V12z; M0 12 V20 H4 V12z" dur="1.2s" repeatCount="indefinite" begin="0.6" keytimes="0;.2;.5;1" keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.8 0.4 0.8" calcMode="spline" /> + </path> + <path transform="translate(26)" d="M0 12 V20 H4 V12z"> + <animate attributeName="d" values="M0 12 V20 H4 V12z; M0 4 V28 H4 V4z; M0 12 V20 H4 V12z; M0 12 V20 H4 V12z" dur="1.2s" repeatCount="indefinite" begin="0.8" keytimes="0;.2;.5;1" keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.8 0.4 0.8" calcMode="spline" /> + </path> +</svg> diff --git a/dgbuilder/public/style.css b/dgbuilder/public/style.css new file mode 100644 index 00000000..3a1917b0 --- /dev/null +++ b/dgbuilder/public/style.css @@ -0,0 +1,980 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +body { + font: 13px "Helvetica" !important; + padding-top: 100px; + background: url("pw_maze_white.png"); +} + +#header { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 40px; + background: #000; + box-sizing: border-box; + padding: 5px 0px 5px 20px; +} + +#dropTarget { + position: absolute; + top: 0; bottom: 0; + left: 0; right: 0; + background: rgba(100,100,100,0.5); + display:table; + width: 100%; + height: 100%; + display: none; +} +#dropTarget div { + display: table-cell; + vertical-align: middle; + text-align: center; + font-size: 40px; + color: #fff; +} +#dropTarget div i { + font-size: 80px; +} +div.btn-group, a.btn { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +span.logo { + pointer-events: none; + float: left; + font-size: 30px; + line-height: 30px; + text-decoration: none; + color: #ccc; +} +span.logo span { + vertical-align: middle; + font-size: 16px !important; +} +span.logo img { + height: 18px; +} +#header .button { + line-height: 22px; + display: inline-block; + font-size: 14px; + padding: 4px 12px; + text-decoration: none; + border-radius: 3px; + color: #ccc; + margin: auto 10px; + vertical-align: middle; +} +#header .button:not(.disabled):hover { + box-shadow: 0 0 2px #fff; +} +#btn-deploy:not(.disabled):hover { + background: #ca3f39; +} + +#btn-deploy { + color: #fff !important; + background: #d24741; + box-shadow: 0 0 2px #fff; +} +#btn-deploy:not(.disabled):active { + background: #aa1f19 !important; + color: #ccc !important; + box-shadow: 0 0 2px #999; +} +#btn-deploy.disabled { + cursor: default; + background: #444 ; + color: #999 !important; +} + +#btn-sidemenu { + font-size: 20px !important; +} +#btn-sidemenu:active, #btn-sidemenu.active { + background: #333 ; +} +#header .button:focus { + outline: none; +} + + + +#workspace { + margin-left: 160px; + overflow: hidden; +} + +#chart { + overflow: auto; + background: #e3e3e3; + position: absolute; + bottom:0px; + top: 30px; + left:0px; + right:0px; +} + +#workspace-toolbar { + display: none; + position: absolute; + top: 30px; + left:0; + right: 18px; + padding: 5px; + background: #f3f3f3; +} + +#chart-zoom-controls { + padding-top: 3px; + text-align: right; + float: right; +} + +#palette { + background: #f3f3f3; + width: 140px; + text-align: center; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.palette-scroll { + display: none; + position: absolute; + top: 0; + left:0; + right: 0; + bottom: 35px; + padding: 5px; + overflow-y: auto; + box-sizing:border-box; + -moz-box-sizing: border-box; +} +.palette-spinner { + padding-top: 40px; +} +#palette-search { + position: absolute; + display: none; + bottom: 0; + left:0; + right:0; + overflow: hidden; + background: #f3f3f3; + text-align: center; + height: 35px; + padding: 3px; + border-top: 1px solid #999; + box-sizing:border-box; + -moz-box-sizing: border-box; +} +#palette-search i.fa-search { + position: absolute; + pointer-events: none; + left: 4px; + top: 10px; +} +#palette-search i.fa-times { + position: absolute; + right: 6px; + top: 10px; +} + +#palette-search-clear { + display: none; + color: #000; +} + +#palette-search input { + border-radius: 0; + border: none; + width: 100%; + box-shadow: none; + -webkit-box-shadow: none; + padding: 3px 17px; + margin: 0px; + height: 30px; + box-sizing:border-box; + -moz-box-sizing: border-box; + +} +#palette-search input:focus { + border: none; + box-shadow: none; + -webkit-box-shadow: none; +} + +.palette-category { + border: 1px solid #999; + border-radius: 3px; + margin-bottom: 5px; +} +.palette-content { + background: #fff; + border-top: 1px solid #aaa; + padding-bottom: 3px; +} + +.palette-header { + background: #f3f3f3; + border-radius: 3px; + cursor: pointer; + text-align: left; + padding: 1px; +} +.palette-header i { + margin: 3px 4px 3px 3px; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -o-transform: rotate(-90deg); +} +.palette-header i.expanded { + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); +} +.palette-header span { + clear: both; +} +.palette_label { + line-height: 25px; + text-align: center; + +} +.palette_node { + cursor:move; + font-size:13px; + background: #ddd; + margin: 10px auto; + height: 25px; + border-radius: 6px; + border: 2px solid #999; + background-position: 5% 50%; + background-repeat: no-repeat; + width: 90px; + background-size: contain; + position: relative; +} +.palette_node:hover { + border-color: #ff7f0e; + background-color: #eee; +} +.palette_port { + position: absolute; + top:8px; + left: -5px; + box-sizing: border-box; + -moz-box-sizing: border-box; + background:#d9d9d9; + border-radius: 3px; + width: 10px; + height: 10px; + border: 1px solid #999; +} +.palette_port_output { + left:85px; +} + +.palette_node:hover .palette_port { + border-color: #999; + background-color: #eee; +} + +#sidebar { + background: #fff; + box-sizing: border-box; + -moz-box-sizing: border-box; +} +#sidebar.closing { + background: #eee; + border-color: #900; + border-style: dashed; +} + +/* ---------- Layout ---------- */ +#main-container { + position: absolute; + top:50px; left:0; bottom: 0; right:0; + overflow:hidden; +} +#palette { + position: absolute; + top: 5px; left:10px; bottom: 10px; +} +#workspace { + position: absolute; + margin: 0; + top:5px; left:160px; bottom: 10px; right: 330px; +} +#chart-zoom-controls { + position: absolute; + bottom:30px; right: 350px; +} +#sidebar { + width: 305px; + position: absolute; + right: 10px; top: 5px; bottom:10px; +} +#sidebar-separator { + width: 15px; + background: url(grip.png) no-repeat 50% 50%; + position: absolute; + right: 316px; top: 5px; bottom:10px; + cursor: col-resize; +} + +.sidebar-closed > #sidebar { display: none; } +.sidebar-closed > #sidebar-separator { right: 0px !important; } +.sidebar-closed > #workspace { right: 15px !important; } +.sidebar-closed > #chart-zoom-controls { right: 35px !important; } + +.palette-bar-closed > #palette { display: none; } +.palette-bar-closed > #workspace { margin-left: -140px !important; } +/* ---------- end layout ---------- */ + +.lasso { + stroke-width: 2px; + stroke: #ff7f0e; + fill: rgba(20,125,255,0.1); + stroke-dasharray: 10 5; +} + +.group-box { + stroke-width: 1px; + stroke: #aaaaaa; + fill: rgba(208, 211, 238, 0.1); + stroke-dasharray: 3 3; +} +.group-box-active { + fill: #fff; + stroke: #ff7f0e; +} + +.group_label { + stroke-width: 0; + fill: #999; + font-size: 11px; + pointer-events: none; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.pull-right { + margin-left: 20px; +} + +#workspace, #palette, #sidebar { + border: 1px solid #000; + border-radius: 3px; +} +#sidebar-content { + font-size: 1.2em; + overflow-y: auto; + position: absolute; + top: 30px; left: 0px; right: 0; bottom: 1px; +} + +.node_label_italic { + font-style: italic; +} +.node_label_unknown { + font-style: italic; + fill: #e00 !important; +} +.node_label_white { + fill: #eee !important; +} +.node_label { + stroke-width: 0; + fill: #333; + font-size: 14px; + pointer-events: none; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.function_label { + font-size: 12px; +} +.node { + stroke: #999; + cursor: move; + stroke-width: 2; +} +.node_unknown { + stroke-dasharray:10,4; + stroke: #f33; +} +.tool_arrow { + stroke-width: 1; + stroke: #999; + fill: #999; + cursor: pointer; +} +.node_tools { + fill: #ddd; + stroke: #999; + cursor: move; + stroke-width: 1; + cursor: pointer; +} +.node_tools_hovered { + stroke: #ff7f0e; + fill: #eee; +} + +.node_button { + fill: inherit; + +} +.port { + fill: #ddd; + cursor: crosshair; +} +.node_error { + stroke: #ff0000; + stroke-width: 2; + fill: #ff7f0e; +} + +.node_badge { + stroke: rgb(93, 114, 145); + stroke-width: 1; + fill: rgb(190, 209, 255); +} +.node_badge_label { + stroke-width:0; + fill: #fff; + font-size: 11px; + pointer-events: none; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + +} +.node_invalid { + stroke: #ff0000; +} +.node_selected { + stroke: #ff7f0e; +} +.node_found { + stroke:blue; + /* + stroke-width :3; + stroke-dasharray:5,1; +*/ +} +.text_found { + stroke:green; + stroke-width :3; + stroke-dasharray:5,1; +} +.node_highlighted { + stroke: #dd1616; + stroke-width: 3; + stroke-dasharray: 10, 4; +} +.node_hovered { +} + +.port_hovered { + stroke: #ff7f0e; + fill: #ff7f0e; +} + +.drag_line { + stroke: #ff7f0e; + stroke-width: 5; + fill: none; + pointer-events: none; +} + +.drag_line_hidden { + stroke: #ff7f0e; + stroke-width: 0; + pointer-events: none; + fill: none; +} + +.link_line { + stroke: #7f7f7f; + stroke-width: 4; + fill: none; + pointer-events: none; +} + +.link_outline { + stroke: #fff; + stroke-width: 6; + cursor: crosshair; + fill: none; + pointer-events: none; +} +.link_background { + stroke: #fff; + opacity: 0; + stroke-width: 25; + cursor: crosshair; + fill: none; +} + +g.link_selected path.link_line { + stroke: #ff7f0e; +} +g.link_unknown path.link_line { + stroke: #f00; + stroke-width: 2; + stroke-dasharray: 10, 4; +} + +#shade { + position: absolute; + top:0; + left:0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.5); + text-align: center; + display: none; +} + +#dialog { +} + +.container { +} + +.notification { + position: absolute; +} +#notifications { + z-index: 10000; + width: 500px; + margin-left: -250px; + left: 50%; + position: absolute; + top: 1px; +} +#notifications .alert { + box-shadow: 0 0 1px 1px; + margin-bottom: 5px; +} + +.form-row { + clear: both; + margin-bottom: 7px; +} +.form-row label { + display: inline-block; + width: 100px; +} +.form-row input { + width:70%; +} + +input.input-append-left { + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; +} +button.input-append-right { + border-top-left-radius: 0px !important; + border-bottom-left-radius: 0px !important; + border-top-right-radius: 4px !important; + border-bottom-right-radius: 4px !important; + margin-left: -1px !important; + padding-left: 4px !important; + padding-right: 4px !important; +} + +.form-tips { + background: lightgoldenrodyellow; + font-size: 12px; + padding: 8px; + border-radius: 5px; + border: 1px solid #999; +} +.form-tips code { + border: none; + padding: auto; +} + +.ui-tabs .ui-tabs-panel { + padding: 0px; +} + +table.node-info { + margin: 5px; + width: 97%; +} +table.node-info tr { + border: 1px solid #ddd; +} +table.node-info tr.blank { + border: none; +} +table.node-info tr.blank td { + padding-top: 8px; + border: none; + font-weight: bold; + padding-left: 0px; +} +table.node-info td:first-child{ + color: #000; + vertical-align: top; + width: 90px; + padding: 3px; + border-right: 1px solid #ddd; +} +table.node-info td:last-child{ + padding-left: 5px; + color: #666; +} + +div.node-info { + margin: 5px; +} + +.input-error { + border-color: rgb(214, 97, 95) !important; +} + +.hidden { + display: none; +} +/* +.dropdown-menu { + font-size: 14px; + background: #000; +} +.dropdown-menu .divider { + background: #666; + border-bottom: #666; +} +.dropdown-menu>li>a { + color: #ddd; +} +.dropdown-submenu>ul { + border: 1px solid white; + border-radius: 6px !important; +} +.dropdown-menu li.disabled a { + color: #666; +} +.dropdown-menu li.disabled a:hover { + background: none; +} +*/ +.dropdown-menu>li>a:hover, .dropdown-menu>li>a:focus, .dropdown-submenu:hover>a, .dropdown-submenu:focus>a { + background: #999; +} + +.dropdown-menu * .fa-check { + display: none; + margin-right: -15px; + margin-top: 3px; +} +.dropdown-menu * a.active > .fa-check { + display: inline-block; +} +.dropdown-menu>li.disabled>a:hover>[class^="icon-"] { + background-image: url("bootstrap/img/glyphicons-halflings.png") !important; +} +/** Fix for unreachable dropdown menu **/ +.dropdown-menu { + width: 200px !important; +} +.dropdown-menu > li > a > i { + width: 10px; + text-align: center; + margin-left: -8px; +} +.dropdown-menu > li > a { + padding-left: 38px ; + text-indent: -8px ; + white-space: normal !important; +} + +.popover-title { display: none; } + +.ui-autocomplete { + max-height: 250px; + overflow-x: hidden; + overflow-y: scroll; +} + +.leftButton { + margin-right: 200px !important; +} +#node-help { + width: 700px; +} +#node-help * td { + padding: 0.8em 0.5em; +} +#node-help * tr > td:first-child+td+td { + padding-left: 5em; +} + +.help-key { + border: 1px solid #ddd; + padding: 4px; + border-radius: 3px; + background: #f6f6f6; + font-family: Courier, monospace; + box-shadow: #999 1px 1px 1px; +} + +#helpcontent { + padding: 20px; + border: 1px solid #ddd; + border-radius: 10px; + + background: #fff; +} +#helpnavigation { + overflow: hidden; + border: 1px solid #ddd; + border-radius: 10px; + background: #fff; +} +#helpnavigation li a{ + font-size: 1.2em; + padding: 10px; + border-bottom: 1px solid #ddd; +} + +#node-select-library { + overflow: hidden; +} +#node-select-library ul { + list-style: none; + padding: 0px; + margin: 2px; +} +#node-select-library li { + cursor: pointer; +} +#node-select-library li.list-selected { + background: #eee; +} +#node-select-library li.list-hover { + background: #ffffd0; +} +.node-text-editor { + border:1px solid #ccc; + border-radius:5px; + overflow: hidden; +} +#workspace-tabs { + margin-right: 28px; +} +#workspace-add-tab { + position: absolute; + top: 0; + right: 0; + height: 29px; + width: 28px; + border-bottom: 1px solid #999; +} +#btn-workspace-add-tab { + display: inline-block; + width: 100%; + background: #e3e3e3; + height: 100%; + line-height: 30px; + text-align: center; + color: #000; +} +#btn-workspace-add-tab:hover { + background: #efefef; +} + +ul.red-ui-tabs { + list-style-type: none; + padding:5px 2px 0px 5px; + margin: 0; + display: block; + height: 24px; + border-bottom: 1px solid #999; + background: #e3e3e3; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +ul.red-ui-tabs li { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + display: inline-block; + border-left: 1px solid #999; + border-top: 1px solid #999; + border-right: 1px solid #999; + border-bottom: 1px solid #999; + background: #e3e3e3; + margin: 0 5px 0 0; + height: 23px; + line-height: 17px; + max-width: 150px; + width: 14%; + overflow: hidden; + white-space: nowrap; +} + +ul.red-ui-tabs li a.red-ui-tab-label { + display: block; + padding: 3px 16px; + color: #666; +} +ul.red-ui-tabs li { + position: relative; +} + +ul.red-ui-tabs li a.red-ui-tab-close { + background: rgba(227,227,227,0.8); + position: absolute; + right: 2px; + top: 2px; + display: block; + width: 20px; + height: 20px; + line-height: 20px; + text-align: center; + padding: 0px; + border-radius: 5px; + color: #666; +} +ul.red-ui-tabs li a.red-ui-tab-close:hover { + background: #bbb !important; +} +ul.red-ui-tabs li a:hover { + text-decoration: none; + background: #f0f0f0; +} + +ul.red-ui-tabs li.active { + background: #fff; + border-bottom: 1px solid #fff; +} +ul.red-ui-tabs li.active a { + color: #333; +} +ul.red-ui-tabs li.active a.red-ui-tab-close { + background: rgba(255,255,255,0.8); +} +ul.red-ui-tabs li.active a.red-ui-tab-label:hover { + background: #fff; +} +ul.red-ui-tabs li.red-ui-add-tab { + width: 25px; + border-top-right-radius: 15px; + line-height: 22px; +} +ul.red-ui-tabs li.red-ui-add-tab a { + padding: 2px 4px; +} + +ul.tab-config-list { + list-style-type: none; + padding: 3px; + margin: 0; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +ul.tab-config-list li { + max-width: 400px; + font-size: 13px; + background: #f3f3f3; + margin: 10px auto; + border-radius: 3px; + border: 1px solid #ccc; + padding: 3px 8px; +} +div.tab-config-list-type { +} + +div.tab-config-list-entry { + position: relative; + margin: 4px 0; + padding: 8px 4px 8px 10px; + background: #fff; + border: 1px solid #ccc; + border-radius: 4px; + cursor: pointer; +} +div.tab-config-list-entry:hover { + background: #f6f6f6; +} + +div.tab-config-list-label { +} +div.tab-config-list-users { + position: absolute; + right: 3px; + top: 3px; + bottom: 3px; + line-height: 27px; + font-size: 11px; + background: #f6f6f6; + float: right; + border: 1px solid #eee; + border-radius: 3px; + padding: 1px 5px; +} + +i.spinner { + display: inline-block; + width: 14px; + height: 14px; + line-height: 14px; + vertical-align: text-top; + margin-top: 0px; + background: url(spin.svg) no-repeat 50% 50%; + background-size: contain +} + + + diff --git a/dgbuilder/public/style.css.orig b/dgbuilder/public/style.css.orig new file mode 100644 index 00000000..8c37abfb --- /dev/null +++ b/dgbuilder/public/style.css.orig @@ -0,0 +1,966 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +body { + font: 13px "Helvetica" !important; + padding-top: 100px; + background: url("pw_maze_white.png"); +} + +#header { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 40px; + background: #000; + box-sizing: border-box; + padding: 5px 0px 5px 20px; +} + +#dropTarget { + position: absolute; + top: 0; bottom: 0; + left: 0; right: 0; + background: rgba(100,100,100,0.5); + display:table; + width: 100%; + height: 100%; + display: none; +} +#dropTarget div { + display: table-cell; + vertical-align: middle; + text-align: center; + font-size: 40px; + color: #fff; +} +#dropTarget div i { + font-size: 80px; +} +div.btn-group, a.btn { + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +span.logo { + pointer-events: none; + float: left; + font-size: 30px; + line-height: 30px; + text-decoration: none; + color: #ccc; +} +span.logo span { + vertical-align: middle; + font-size: 16px !important; +} +span.logo img { + height: 18px; +} +#header .button { + line-height: 22px; + display: inline-block; + font-size: 14px; + padding: 4px 12px; + text-decoration: none; + border-radius: 3px; + color: #ccc; + margin: auto 10px; + vertical-align: middle; +} +#header .button:not(.disabled):hover { + box-shadow: 0 0 2px #fff; +} +#btn-deploy:not(.disabled):hover { + background: #ca3f39; +} + +#btn-deploy { + color: #fff !important; + background: #d24741; + box-shadow: 0 0 2px #fff; +} +#btn-deploy:not(.disabled):active { + background: #aa1f19 !important; + color: #ccc !important; + box-shadow: 0 0 2px #999; +} +#btn-deploy.disabled { + cursor: default; + background: #444 ; + color: #999 !important; +} + +#btn-sidemenu { + font-size: 20px !important; +} +#btn-sidemenu:active, #btn-sidemenu.active { + background: #333 ; +} +#header .button:focus { + outline: none; +} + + + +#workspace { + margin-left: 160px; + overflow: hidden; +} + +#chart { + overflow: auto; + background: #e3e3e3; + position: absolute; + bottom:0px; + top: 30px; + left:0px; + right:0px; +} + +#workspace-toolbar { + display: none; + position: absolute; + top: 30px; + left:0; + right: 18px; + padding: 5px; + background: #f3f3f3; +} + +#chart-zoom-controls { + padding-top: 3px; + text-align: right; + float: right; +} + +#palette { + background: #f3f3f3; + width: 140px; + text-align: center; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +.palette-scroll { + display: none; + position: absolute; + top: 0; + left:0; + right: 0; + bottom: 35px; + padding: 5px; + overflow-y: auto; + box-sizing:border-box; + -moz-box-sizing: border-box; +} +.palette-spinner { + padding-top: 40px; +} +#palette-search { + position: absolute; + display: none; + bottom: 0; + left:0; + right:0; + overflow: hidden; + background: #f3f3f3; + text-align: center; + height: 35px; + padding: 3px; + border-top: 1px solid #999; + box-sizing:border-box; + -moz-box-sizing: border-box; +} +#palette-search i.fa-search { + position: absolute; + pointer-events: none; + left: 4px; + top: 10px; +} +#palette-search i.fa-times { + position: absolute; + right: 6px; + top: 10px; +} + +#palette-search-clear { + display: none; + color: #000; +} + +#palette-search input { + border-radius: 0; + border: none; + width: 100%; + box-shadow: none; + -webkit-box-shadow: none; + padding: 3px 17px; + margin: 0px; + height: 30px; + box-sizing:border-box; + -moz-box-sizing: border-box; + +} +#palette-search input:focus { + border: none; + box-shadow: none; + -webkit-box-shadow: none; +} + +.palette-category { + border: 1px solid #999; + border-radius: 3px; + margin-bottom: 5px; +} +.palette-content { + background: #fff; + border-top: 1px solid #aaa; + padding-bottom: 3px; +} + +.palette-header { + background: #f3f3f3; + border-radius: 3px; + cursor: pointer; + text-align: left; + padding: 1px; +} +.palette-header i { + margin: 3px 4px 3px 3px; + -webkit-transition: all 0.2s ease-in-out; + -moz-transition: all 0.2s ease-in-out; + -o-transition: all 0.2s ease-in-out; + -webkit-transform: rotate(-90deg); + -moz-transform: rotate(-90deg); + -o-transform: rotate(-90deg); +} +.palette-header i.expanded { + -webkit-transform: rotate(0deg); + -moz-transform: rotate(0deg); + -o-transform: rotate(0deg); +} +.palette-header span { + clear: both; +} +.palette_label { + line-height: 25px; + text-align: center; + +} +.palette_node { + cursor:move; + font-size:13px; + background: #ddd; + margin: 10px auto; + height: 25px; + border-radius: 6px; + border: 2px solid #999; + background-position: 5% 50%; + background-repeat: no-repeat; + width: 90px; + background-size: contain; + position: relative; +} +.palette_node:hover { + border-color: #ff7f0e; + background-color: #eee; +} +.palette_port { + position: absolute; + top:8px; + left: -5px; + box-sizing: border-box; + -moz-box-sizing: border-box; + background:#d9d9d9; + border-radius: 3px; + width: 10px; + height: 10px; + border: 1px solid #999; +} +.palette_port_output { + left:85px; +} + +.palette_node:hover .palette_port { + border-color: #999; + background-color: #eee; +} + +#sidebar { + background: #fff; + box-sizing: border-box; + -moz-box-sizing: border-box; +} +#sidebar.closing { + background: #eee; + border-color: #900; + border-style: dashed; +} + +/* ---------- Layout ---------- */ +#main-container { + position: absolute; + top:50px; left:0; bottom: 0; right:0; + overflow:hidden; +} +#palette { + position: absolute; + top: 5px; left:10px; bottom: 10px; +} +#workspace { + position: absolute; + margin: 0; + top:5px; left:160px; bottom: 10px; right: 330px; +} +#chart-zoom-controls { + position: absolute; + bottom:30px; right: 350px; +} +#sidebar { + width: 305px; + position: absolute; + right: 10px; top: 5px; bottom:10px; +} +#sidebar-separator { + width: 15px; + background: url(grip.png) no-repeat 50% 50%; + position: absolute; + right: 316px; top: 5px; bottom:10px; + cursor: col-resize; +} + +.sidebar-closed > #sidebar { display: none; } +.sidebar-closed > #sidebar-separator { right: 0px !important; } +.sidebar-closed > #workspace { right: 15px !important; } +.sidebar-closed > #chart-zoom-controls { right: 35px !important; } + +/* ---------- end layout ---------- */ + +.lasso { + stroke-width: 2px; + stroke: #ff7f0e; + fill: rgba(20,125,255,0.1); + stroke-dasharray: 10 5; +} + +.group-box { + stroke-width: 1px; + stroke: #aaaaaa; + fill: rgba(208, 211, 238, 0.1); + stroke-dasharray: 3 3; +} +.group-box-active { + fill: #fff; + stroke: #ff7f0e; +} + +.group_label { + stroke-width: 0; + fill: #999; + font-size: 11px; + pointer-events: none; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.pull-right { + margin-left: 20px; +} + +#workspace, #palette, #sidebar { + border: 1px solid #000; + border-radius: 3px; +} +#sidebar-content { + font-size: 1.2em; + overflow-y: auto; + position: absolute; + top: 30px; left: 0px; right: 0; bottom: 1px; +} + +.node_label_italic { + font-style: italic; +} +.node_label_unknown { + font-style: italic; + fill: #e00 !important; +} +.node_label_white { + fill: #eee !important; +} +.node_label { + stroke-width: 0; + fill: #333; + font-size: 14px; + pointer-events: none; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.function_label { + font-size: 12px; +} +.node { + stroke: #999; + cursor: move; + stroke-width: 2; +} +.node_unknown { + stroke-dasharray:10,4; + stroke: #f33; +} +.tool_arrow { + stroke-width: 1; + stroke: #999; + fill: #999; + cursor: pointer; +} +.node_tools { + fill: #ddd; + stroke: #999; + cursor: move; + stroke-width: 1; + cursor: pointer; +} +.node_tools_hovered { + stroke: #ff7f0e; + fill: #eee; +} + +.node_button { + fill: inherit; + +} +.port { + fill: #ddd; + cursor: crosshair; +} +.node_error { + stroke: #ff0000; + stroke-width: 2; + fill: #ff7f0e; +} + +.node_badge { + stroke: rgb(93, 114, 145); + stroke-width: 1; + fill: rgb(190, 209, 255); +} +.node_badge_label { + stroke-width:0; + fill: #fff; + font-size: 11px; + pointer-events: none; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + +} +.node_invalid { + stroke: #ff0000; +} +.node_selected { + stroke: #ff7f0e; +} +.node_highlighted { + stroke: #dd1616; + stroke-width: 3; + stroke-dasharray: 10, 4; +} +.node_hovered { +} + +.port_hovered { + stroke: #ff7f0e; + fill: #ff7f0e; +} + +.drag_line { + stroke: #ff7f0e; + stroke-width: 5; + fill: none; + pointer-events: none; +} + +.drag_line_hidden { + stroke: #ff7f0e; + stroke-width: 0; + pointer-events: none; + fill: none; +} + +.link_line { + stroke: #7f7f7f; + stroke-width: 4; + fill: none; + pointer-events: none; +} + +.link_outline { + stroke: #fff; + stroke-width: 6; + cursor: crosshair; + fill: none; + pointer-events: none; +} +.link_background { + stroke: #fff; + opacity: 0; + stroke-width: 25; + cursor: crosshair; + fill: none; +} + +g.link_selected path.link_line { + stroke: #ff7f0e; +} +g.link_unknown path.link_line { + stroke: #f00; + stroke-width: 2; + stroke-dasharray: 10, 4; +} + +#shade { + position: absolute; + top:0; + left:0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.5); + text-align: center; + display: none; +} + +#dialog { +} + +.container { +} + +.notification { + position: absolute; +} +#notifications { + z-index: 10000; + width: 500px; + margin-left: -250px; + left: 50%; + position: absolute; + top: 1px; +} +#notifications .alert { + box-shadow: 0 0 1px 1px; + margin-bottom: 5px; +} + +.form-row { + clear: both; + margin-bottom: 7px; +} +.form-row label { + display: inline-block; + width: 100px; +} +.form-row input { + width:70%; +} + +input.input-append-left { + border-top-right-radius: 0px; + border-bottom-right-radius: 0px; +} +button.input-append-right { + border-top-left-radius: 0px !important; + border-bottom-left-radius: 0px !important; + border-top-right-radius: 4px !important; + border-bottom-right-radius: 4px !important; + margin-left: -1px !important; + padding-left: 4px !important; + padding-right: 4px !important; +} + +.form-tips { + background: lightgoldenrodyellow; + font-size: 12px; + padding: 8px; + border-radius: 5px; + border: 1px solid #999; +} +.form-tips code { + border: none; + padding: auto; +} + +.ui-tabs .ui-tabs-panel { + padding: 0px; +} + +table.node-info { + margin: 5px; + width: 97%; +} +table.node-info tr { + border: 1px solid #ddd; +} +table.node-info tr.blank { + border: none; +} +table.node-info tr.blank td { + padding-top: 8px; + border: none; + font-weight: bold; + padding-left: 0px; +} +table.node-info td:first-child{ + color: #000; + vertical-align: top; + width: 90px; + padding: 3px; + border-right: 1px solid #ddd; +} +table.node-info td:last-child{ + padding-left: 5px; + color: #666; +} + +div.node-info { + margin: 5px; +} + +.input-error { + border-color: rgb(214, 97, 95) !important; +} + +.hidden { + display: none; +} +/* +.dropdown-menu { + font-size: 14px; + background: #000; +} +.dropdown-menu .divider { + background: #666; + border-bottom: #666; +} +.dropdown-menu>li>a { + color: #ddd; +} +.dropdown-submenu>ul { + border: 1px solid white; + border-radius: 6px !important; +} +.dropdown-menu li.disabled a { + color: #666; +} +.dropdown-menu li.disabled a:hover { + background: none; +} +*/ +.dropdown-menu>li>a:hover, .dropdown-menu>li>a:focus, .dropdown-submenu:hover>a, .dropdown-submenu:focus>a { + background: #999; +} + +.dropdown-menu * .fa-check { + display: none; + margin-right: -15px; + margin-top: 3px; +} +.dropdown-menu * a.active > .fa-check { + display: inline-block; +} +.dropdown-menu>li.disabled>a:hover>[class^="icon-"] { + background-image: url("bootstrap/img/glyphicons-halflings.png") !important; +} +/** Fix for unreachable dropdown menu **/ +.dropdown-menu { + width: 200px !important; +} +.dropdown-menu > li > a > i { + width: 10px; + text-align: center; + margin-left: -8px; +} +.dropdown-menu > li > a { + padding-left: 38px ; + text-indent: -8px ; + white-space: normal !important; +} + +.popover-title { display: none; } + +.ui-autocomplete { + max-height: 250px; + overflow-x: hidden; + overflow-y: scroll; +} + +.leftButton { + margin-right: 200px !important; +} +#node-help { + width: 700px; +} +#node-help * td { + padding: 0.8em 0.5em; +} +#node-help * tr > td:first-child+td+td { + padding-left: 5em; +} + +.help-key { + border: 1px solid #ddd; + padding: 4px; + border-radius: 3px; + background: #f6f6f6; + font-family: Courier, monospace; + box-shadow: #999 1px 1px 1px; +} + +#helpcontent { + padding: 20px; + border: 1px solid #ddd; + border-radius: 10px; + + background: #fff; +} +#helpnavigation { + overflow: hidden; + border: 1px solid #ddd; + border-radius: 10px; + background: #fff; +} +#helpnavigation li a{ + font-size: 1.2em; + padding: 10px; + border-bottom: 1px solid #ddd; +} + +#node-select-library { + overflow: hidden; +} +#node-select-library ul { + list-style: none; + padding: 0px; + margin: 2px; +} +#node-select-library li { + cursor: pointer; +} +#node-select-library li.list-selected { + background: #eee; +} +#node-select-library li.list-hover { + background: #ffffd0; +} +.node-text-editor { + border:1px solid #ccc; + border-radius:5px; + overflow: hidden; +} +#workspace-tabs { + margin-right: 28px; +} +#workspace-add-tab { + position: absolute; + top: 0; + right: 0; + height: 29px; + width: 28px; + border-bottom: 1px solid #999; +} +#btn-workspace-add-tab { + display: inline-block; + width: 100%; + background: #e3e3e3; + height: 100%; + line-height: 30px; + text-align: center; + color: #000; +} +#btn-workspace-add-tab:hover { + background: #efefef; +} + +ul.red-ui-tabs { + list-style-type: none; + padding:5px 2px 0px 5px; + margin: 0; + display: block; + height: 24px; + border-bottom: 1px solid #999; + background: #e3e3e3; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +ul.red-ui-tabs li { + border-top-left-radius: 5px; + border-top-right-radius: 5px; + display: inline-block; + border-left: 1px solid #999; + border-top: 1px solid #999; + border-right: 1px solid #999; + border-bottom: 1px solid #999; + background: #e3e3e3; + margin: 0 5px 0 0; + height: 23px; + line-height: 17px; + max-width: 150px; + width: 14%; + overflow: hidden; + white-space: nowrap; +} + +ul.red-ui-tabs li a.red-ui-tab-label { + display: block; + padding: 3px 16px; + color: #666; +} +ul.red-ui-tabs li { + position: relative; +} + +ul.red-ui-tabs li a.red-ui-tab-close { + background: rgba(227,227,227,0.8); + position: absolute; + right: 2px; + top: 2px; + display: block; + width: 20px; + height: 20px; + line-height: 20px; + text-align: center; + padding: 0px; + border-radius: 5px; + color: #666; +} +ul.red-ui-tabs li a.red-ui-tab-close:hover { + background: #bbb !important; +} +ul.red-ui-tabs li a:hover { + text-decoration: none; + background: #f0f0f0; +} + +ul.red-ui-tabs li.active { + background: #fff; + border-bottom: 1px solid #fff; +} +ul.red-ui-tabs li.active a { + color: #333; +} +ul.red-ui-tabs li.active a.red-ui-tab-close { + background: rgba(255,255,255,0.8); +} +ul.red-ui-tabs li.active a.red-ui-tab-label:hover { + background: #fff; +} +ul.red-ui-tabs li.red-ui-add-tab { + width: 25px; + border-top-right-radius: 15px; + line-height: 22px; +} +ul.red-ui-tabs li.red-ui-add-tab a { + padding: 2px 4px; +} + +ul.tab-config-list { + list-style-type: none; + padding: 3px; + margin: 0; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +ul.tab-config-list li { + max-width: 400px; + font-size: 13px; + background: #f3f3f3; + margin: 10px auto; + border-radius: 3px; + border: 1px solid #ccc; + padding: 3px 8px; +} +div.tab-config-list-type { +} + +div.tab-config-list-entry { + position: relative; + margin: 4px 0; + padding: 8px 4px 8px 10px; + background: #fff; + border: 1px solid #ccc; + border-radius: 4px; + cursor: pointer; +} +div.tab-config-list-entry:hover { + background: #f6f6f6; +} + +div.tab-config-list-label { +} +div.tab-config-list-users { + position: absolute; + right: 3px; + top: 3px; + bottom: 3px; + line-height: 27px; + font-size: 11px; + background: #f6f6f6; + float: right; + border: 1px solid #eee; + border-radius: 3px; + padding: 1px 5px; +} + +i.spinner { + display: inline-block; + width: 14px; + height: 14px; + line-height: 14px; + vertical-align: text-top; + margin-top: 0px; + background: url(spin.svg) no-repeat 50% 50%; + background-size: contain +} + + + diff --git a/dgbuilder/public/util/css/validateNodeXml.css b/dgbuilder/public/util/css/validateNodeXml.css new file mode 100644 index 00000000..895ad7fd --- /dev/null +++ b/dgbuilder/public/util/css/validateNodeXml.css @@ -0,0 +1,86 @@ +#error-list-div{ +overflow:scroll; +color:brown; +width:480px; +height:300px; +} + +#node-validate-result a{ + text-decoration: underline; + color:blue; + cursor:pointer; +} + +table#errTable tr td:first-child { + border-left: 0px solid #e5e5e5; + text-align: center; +} + +table#errTable tr td:last-child { + border-right: 0px solid #e5e5e5; +} +table#errTable tr:nth-of-type(odd) { + background-color: #FFF0F0; +} + +table#errTable tr td { + border-width: 0px 0px 0px 0px; + border-style: solid; + border-color: #fff; + text-align: center; + font-size: 1.0em; +} + +#sli-values-div{ +overflow:auto; +color:blue; +width:850px; +height:600px; +} + +#sli-values-div input[type="text"] { + padding: 1px; + border: solid 1px grey; + /*border: solid 1px #dcdcdc;*/ + width:800px; + transition: box-shadow 0.3s, border 0.3s; + box-shadow: 0 0 5px 1px #969696; + cursor:pointer; +} + +.valueBoxDiv { + border-width: 1px 2px 1px 1px; + border-style: solid; + /*border-color: #9999FF;*/ + border-color: grey; + /*border-color: #fff;*/ + font-size: 1.0em; + border-left: 1px solid #fff; + border-right: 1px solid #fff; + border-top: 1px solid #fff; + border-bottom: 1px solid #fff; + padding-left: 5px; + padding-right: 5px; + padding-top: 5px; + padding-bottom: 5px; + /*background-color:#FFE6E6;*/ + background-color:#fff; +} + +/*#sli-values-div input[type="text"]:focus, + +#sli-values-div input[type="text"].focus { + border: solid 1px #707070; + box-shadow: 0 0 5px 1px #969696; +} +*/ +/* +#getFixed { + color: #c00; + font: bold 15px arial; + padding: 10px; + margin: 10px; + border: 1px solid #c00; + width: 200px; +} +*/ diff --git a/dgbuilder/public/util/js/dgeToXml.js b/dgbuilder/public/util/js/dgeToXml.js new file mode 100644 index 00000000..7582d275 --- /dev/null +++ b/dgbuilder/public/util/js/dgeToXml.js @@ -0,0 +1,1328 @@ +function getDgStartNode(nodeList){ + for(var i=0;i<nodeList.length;i++){ + if(nodeList[i].type == 'dgstart' && nodeList[i].wires != null && nodeList[i].wires != undefined){ + return nodeList[i]; + } + } + RED.notify("DGSTART node not found."); + return null; +} + + +var loopDetectionEnabled = true; + +function detectLoopPrev(){ + var activeWorkspace=RED.view.getWorkspace(); + /* + RED.nodes.links.filter(function(d) { + if(d.source.z == activeWorkspace && d.target.z == activeWorkspace){ + console.log(d.source.id+":"+d.sourcePort+":"+d.target.id); + } + }); + */ + //console.dir(RED.nodes.links); + var nSet=[]; + + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + nSet.push({'n':n}); + } + }); + + var nodeSet = RED.nodes.createExportableNodeSet(nSet); + //console.dir(nodeSet); + + //console.log("nodeSet length:" + nodeSet.length); + + var isLoopDetected = false; + var dgStartNode = getDgStartNode(nodeSet); + if(dgStartNode == null || dgStartNode == undefined) { + console.log("dgstart node not linked."); + return true; + } + + var wires = dgStartNode.wires; + var nodesInPath = {}; + var dgStartNodeId = dgStartNode.id; + if(wires != null && wires != undefined && wires[0] != undefined){ + for(var k=0;k<wires[0].length;k++){ + var val = wires[0][k]; + nodesInPath[dgStartNodeId + "->" + val] = ""; + } + }else{ + nodesInPath[dgStartNodeId + "->" + ""] = ""; + } + + //console.dir(nodesInPath); + var loopDetectedObj = {}; + /* the nodes will not be order so will need to loop thru again */ + for(var m=0;nodeSet != null && m<nodeSet.length;m++){ + for(var i=0;nodeSet != null && i<nodeSet.length;i++){ + var link=nodeSet[i].id; + //console.log("NAME:" + nodeSet[i].name + ":" + link); + if(link == dgStartNodeId) continue; + var wires = nodeSet[i].wires; + //console.log("link:" + link); + var delKeys = []; + if(wires != null && wires != undefined && wires[0] != undefined){ + for(var k=0;k<wires[0].length;k++){ + var val = (wires[0])[k]; + var keys = Object.keys(nodesInPath); + //console.log("keys:" + keys); + for (var j=0;j<keys.length;j++){ + //console.log("key:" + keys[j]); + //console.log("val:" + val); + var index = -1; + if(keys[j] != null){ + index = keys[j].indexOf("->" + link); + } + var lastIndex = keys[j].lastIndexOf("->"); + if(index != -1 && index == lastIndex){ + //delete nodesInPath[key]; + var previousNodeId = keys[j].substr(lastIndex +2); + var indexOfArrow = -1; + if(previousNodeId != ""){ + indexOfArrow = previousNodeId.indexOf("->"); + } + if(previousNodeId != null && indexOfArrow != -1){ + previousNodeId = previousNodeId.substr(0,indexOfArrow); + } + nodesInPath[keys[j] + "->" + val] = ""; + //console.log("keys[j]:" + keys[j]); + delKeys.push(keys[j]); + var prevNodeIdIndex = keys[j].indexOf("->" + previousNodeId); + var priorOccurence = keys[j].indexOf(val + "->"); + if(priorOccurence != -1 && priorOccurence<prevNodeIdIndex){ + //console.log("previousNodeId:" + previousNodeId); + //console.log("val:" + val); + var n1 = getNode(nodeSet,previousNodeId); + var n2 = getNode(nodeSet,val); + //console.log("loop detected for node " + n1.name + " and " + n2.name); + loopDetectedObj[n1.name + "->" + n2.name] ="looped"; + //console.dir(loopDetectedObj); + isLoopDetected = true; + } + } + } + } + } + for(var l=0;delKeys != null && l<delKeys.length;l++){ + delete nodesInPath[delKeys[l]]; + } + } + + + } + if(loopDetectedObj != null ){ + var msg = ""; + for(var key in loopDetectedObj){ + if(loopDetectedObj.hasOwnProperty(key)) { + console.log("Loop detected " + key); + msg += "<strong>Loop detected for:" + key + "</strong><br>"; + } + } + if(msg != ""){ + isLoopDetected = true; + RED.notify(msg); + } + } +/* + for(var i=0;nodeSet != null && i<nodeSet.length;i++){ + var foundCount=0; + var nodeId = nodeSet[i].id; + var nodeName = nodeSet[i].name; + for(var j=0;nodeSet != null && j<nodeSet.length;j++){ + var node = nodeSet[j]; + if(node.id == nodeId){ + continue; + } + var wires = node.wires; + console.log(node.type + ":wires:" + wires); + for(var k=0;wires != null && wires != undefined && wires[0] != undefined && k<wires[0].length;k++){ + var id = (wires[0])[k]; + console.log(nodeName + ":" + nodeId + ":" + id); + if(id == nodeId ){ + foundCount++; + if(foundCount>1){ + console.log("Loop detected for node " + nodeName + "with node:" + node.name); + RED.notify("<strong>Flow error detected for node '" + nodeName + "' with node '" + node.name + "'</strong>"); + //RED.nodes.eachLink(function(d){ + // if(d.source.id == nodeSet[i] || d.target.id == nodeSet[j]){ + // d.selected = true; + // }else if(d.source.id == nodeSet[j] || d.target.id == nodeSet[i]){ + // d.selected = true; + // } + //}); + //RED.view.redraw(); + isLoopDetected = true; + return true; + } + } + } + + } + } +*/ + //console.log("isLoopDetected:" + isLoopDetected); + return isLoopDetected; +} + +function generateNodePath(nodeIdToNodeObj,nodeId,pathStr,nodesInPath,errList){ + var node = nodeIdToNodeObj[nodeId]; + var wires = node.wires; + if(wires != null && wires != undefined && wires[0] != undefined){ + for(var k=0;k<wires[0].length;k++){ + var val = wires[0][k]; + if(pathStr.indexOf(val + "->") != -1){ + //console.log("pathStr:" + pathStr); + var n1= nodeIdToNodeObj[nodeId].name; + var n2= nodeIdToNodeObj[val].name; + errList.push("Loop detected between nodes '" + n1 + "' and " + "'" + n2 + "'"); + }else{ + pathStr += "->" + val ; + generateNodePath(nodeIdToNodeObj,val,pathStr,nodesInPath,errList); + } + } + }else{ + //pathStr += nodeId + "->" + ""; + nodesInPath.push(pathStr); + } +} + +function detectLoop(){ + var activeWorkspace=RED.view.getWorkspace(); + var nSet=[]; + var nodeIdToNodeObj = {}; + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + nSet.push({'n':n}); + } + }); + + var nodeSet = RED.nodes.createExportableNodeSet(nSet); + nodeIdToNodeObj = getNodeIdToNodeMap(nodeSet); + var isLoopDetected = false; + //var dgStartNode = getDgStartNode(nodeSet); + var dgStartNode = nodeIdToNodeObj["dgstart"]; + var errList = []; + var dgStartNodeId = dgStartNode.id; + var nodesInPathArr = []; + generateNodePath(nodeIdToNodeObj,dgStartNodeId,dgStartNodeId,nodesInPathArr,errList); + if(errList != null && errList != undefined && errList.length > 0){ + isLoopDetected = true; + var htmlStr="<div id='loop-detect-err-list-div'><table id='loopErrListTable' border='1'><tr><th>Error List</th></tr>"; + for(var j=0;errList != null && j<errList.length;j++){ + var errSeq = j+1; + htmlStr += "<tr><td>" + errSeq + ")" + errList[j] + "</td></tr>"; + } + htmlStr += "</table></div>"; + + $("#loop-detection-dialog").dialog({ + autoOpen : false, + modal: true, + title: "DG Flow validation Error List ", + width: 500, + buttons: { + Close: function () { + $("#loop-detection-dialog").dialog("close"); + } + } + }).dialog("open").html(htmlStr); // end dialog div + } + nodesInPathArr=null; + nodeSet ={}; + nodeIdToNodeObj={}; + return isLoopDetected; +} + + +var xmlNumberCnt = 0; +function processForXmlNumbers(nodeSet,node){ + if( node != null && node.type != 'dgstart'){ + if(node.xmlnumber != null && node.xmlnumber){ + node.xmlnumber.push(++xmlNumberCnt); + }else{ + node.xmlnumber = [++xmlNumberCnt]; + } + } + + if(node != null && node.wires != null && node.wires.length>0){ + var wiredNodes=node.wires[0]; + var wiredNodesArr=[]; + for(var k=0;wiredNodes != undefined && wiredNodes != null && k<wiredNodes.length;k++){ + wiredNodesArr.push(getNode(nodeSet,wiredNodes[k])); + } + + //use this sort to sort by y position + wiredNodesArr.sort(function(a, b){ + return a.y-b.y; + }); + + for(var k=0;k<wiredNodesArr.length;k++){ + var n = wiredNodesArr[k]; + processForXmlNumbers(nodeSet,n); + } + } +} + +function updateXmlNumbers(){ + xmlNumberCnt = 0; + var nodeSet = getCurrentFlowNodeSet(); + if(nodeSet == null && nodeSet.length >0){ + nodeSet.forEach(function(n){ + if(n.xmlnumber){ + delete n.xmlnumber; + } + }); + } + var dgStartNode = getDgStartNode(nodeSet); + processForXmlNumbers(nodeSet,dgStartNode); + var activeWorkspace=RED.view.getWorkspace(); + RED.nodes.eachNode(function(n) { + //console.log("Node processed in eachNode"); + if (n.z == activeWorkspace) { + if(n != null){ + var updatedNode = getNode(nodeSet,n.id); + //console.log("updated Node processed in eachNode"); + //console.dir(updatedNode); + + if (n.id == updatedNode.id) { + n.xmlnumber = updatedNode.xmlnumber; + n.dirty = true; + } + } + } + }); +} + +function getOutcomeValue(node){ + var xmlStr = ""; + if(node != null && node.xml != undefined && node.xml !=""){ + xmlStr = node.xml + "</outcome>"; + } + var xmlDoc; + if (window.DOMParser){ + try{ + var parser=new DOMParser(); + xmlDoc=parser.parseFromString(xmlStr,'text/xml'); + //console.log("Not IE"); + var n = xmlDoc.documentElement.nodeName; + if(n == "html"){ + resp=false; + console.log("Error parsing"); + return resp; + } + }catch(e){ + console.log("xmlStr:" + xmlStr); + console.log("Error parsing" +e); + return null; + } + }else{ + try{ + //console.log("IE"); + // code for IE + xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async=false; + xmlDoc.loadXMLString(xmlStr); + }catch(e){ + console.log("xmlStr:" + xmlStr); + console.log("Error parsing" +e); + return null; + } + } + if(xmlDoc != null){ + var xmlNode = xmlDoc.documentElement; + //console.dir(xmlNode); + var processedNode = xmlNode.nodeName; + //console.log("processedNode:" + processedNode); + var attrs = xmlNode.attributes; + for(var i=0;i<attrs.length;i++){ + if(attrs[i].nodeName == "value"){ + return attrs[i].value; + } + } + } + return null; +} + +var dgNumberCnt = 0; +function processForDgNumbers(nodeSet,node){ + var outcomeTypes = [ "already-active", "failure", "not-found", "other", "outcomeFalse", "outcome", "outcomeTrue", "success" ]; + if( node != null && node.type != 'dgstart' && node.type != 'service-logic' && node.type != 'method' ){ + //console.log("child of " + parentNodeType + " :" + nodeType); + //check if NOT outcome node + if(outcomeTypes.indexOf(node.type) == -1){ + if(node.type == "GenericXML"){ + if(node.xml != undefined && node.xml != null && node.xml.indexOf("<outcome ") != -1){ + //this GenericXML node is used for outcome , so need to skip + }else{ + if(node.dgnumber != undefined && node.dgnumber != null && node.dgnumber){ + node.dgnumber.push(++dgNumberCnt); + }else{ + node.dgnumber = [++dgNumberCnt]; + } + } + + }else{ + if(node.dgnumber != undefined && node.dgnumber != null && node.dgnumber){ + node.dgnumber.push(++dgNumberCnt); + }else{ + node.dgnumber = [++dgNumberCnt]; + } + } + } + } + + var hasOutcomeNodes = false; + if(node != null && node.wires != null && node.wires.length>0){ + var wiredNodes=node.wires[0]; + var wiredNodesArr=[]; + for(var k=0;wiredNodes != undefined && wiredNodes != null && k<wiredNodes.length;k++){ + var wiredNode = getNode(nodeSet,wiredNodes[k]); + //check if outcome node + if(outcomeTypes.indexOf(wiredNode.type) != -1){ + hasOutcomeNodes = true; + } + if(wiredNode.type == "GenericXML"){ + if( node.xml != undefined && node.xml != null && node.xml.indexOf("<outcome ") != -1){ + //this GenericXML node is used for outcome + hasOutcomeNodes = true; + } + } + wiredNodesArr.push(wiredNode); + + } + + //use this sort to sort by y position + wiredNodesArr.sort(function(a, b){ + return a.y-b.y; + }); + + /* + //USE THIS LOGIC TO SORT BY OUTCOME VALUE FOR SPECIFIC NODES + var parentNodeType = node.type; + if(hasOutcomeNodes && parentNodeType != 'switchNode' && parentNodeType != 'block' && parentNodeType != 'configure' ){ + //use the value of outcome to sort the wired nodes + wiredNodesArr.sort(function(a, b){ + var val1 = getOutcomeValue(a); + var val2 = getOutcomeValue(b); + //console.log("val1:" + val1); + //console.log("val2:" + val2); + if ( val1 < val2 ){ + return -1; + }else if ( val1 > val2 ){ + return 1; + }else{ + return 0; + } + }); + }else{ + //use this sort to sort by y position + wiredNodesArr.sort(function(a, b){ + return a.y-b.y; + }); + } + + */ + + for(var k=0;k<wiredNodesArr.length;k++){ + var n = wiredNodesArr[k]; + processForDgNumbers(nodeSet,n); + } + } +} + +function updateDgNumbers(){ + dgNumberCnt = 0; + var nodeSet = getCurrentFlowNodeSet(); + if(nodeSet == null && nodeSet.length >0){ + nodeSet.forEach(function(n){ + if(n.dgnumber){ + delete n.dgnumber; + } + }); + } + var dgStartNode = getDgStartNode(nodeSet); + processForDgNumbers(nodeSet,dgStartNode); + var activeWorkspace=RED.view.getWorkspace(); + RED.nodes.eachNode(function(n) { + //console.log("Node processed in eachNode"); + if (n.z == activeWorkspace) { + if(n != null){ + var updatedNode = getNode(nodeSet,n.id); + //console.log("updated Node processed in eachNode"); + //console.dir(updatedNode); + + if (n.id == updatedNode.id) { + //console.log(n.type + ":" + updatedNode.dgnumber); + n.dgnumber = updatedNode.dgnumber; + n.dirty = true; + } + } + } + }); + return nodeSet; +} + +function customValidation(currNodeSet){ + //validation to make sure there a block node infront of mutiple dgelogic nodes + flowDesignErrors=[]; + var dgStartCnt=0; + var serviceLogicCnt=0; + var methodCnt=0; + for(var i=0;currNodeSet != null && i<currNodeSet.length;i++){ + var node = currNodeSet[i]; + var parentNodeName = node.name; + var parentNodeType = node.type; + var dgNumber = node.dgnumber; + if(parentNodeType == 'dgstart'){ + dgStartCnt++; + } + if(parentNodeType == 'service-logic'){ + serviceLogicCnt++; + } + if(parentNodeType == 'method'){ + methodCnt++; + } + if(parentNodeType == "GenericXML"){ + if( node.xml != undefined && node.xml != null && node.xml.indexOf("<service-logic ") != -1 ){ + //this GenericXML node is used for service-logic + serviceLogicCnt++; + }else if( node.xml != undefined && node.xml != null && node.xml.indexOf("<method ") != -1 ){ + //this GenericXML node is used for method + methodCnt++; + }else if( node.xml != undefined && node.xml != null && node.xml.indexOf("<block") != -1 ){ + //this GenericXML node is used for block + parentNodeType = "block"; + } + } + if(node != null && node.wires != null && node.wires.length>0){ + var wiredNodes=node.wires[0]; + var wiredNodesArr=[]; + for(var k=0;wiredNodes != undefined && wiredNodes != null && k<wiredNodes.length;k++){ + wiredNodesArr.push(getNode(currNodeSet,wiredNodes[k])); + } + var countChildLogicNodes =0; + for(var k=0;k<wiredNodesArr.length;k++){ + var n = wiredNodesArr[k]; + var nodeType = n.type; + var outcomeTypes = [ "already-active", "failure", "not-found", "other", "outcomeFalse", "outcome", "outcomeTrue", "success" ]; + var isOutcomeOrSetNode = false; + if(nodeType == "GenericXML"){ + if( n.xml != undefined && n.xml != null && (n.xml.indexOf("<outcome ") != -1 || n.xml.indexOf("<set ") != -1)){ + //this GenericXML node is used for outcome + isOutcomeOrSetNode = true; + } + } + //console.log("child of " + parentNodeType + " :" + nodeType); + if(outcomeTypes.indexOf(nodeType) > -1 ||nodeType == 'set' || isOutcomeOrSetNode){ + //its a outcome or set node + }else{ + countChildLogicNodes++; + } + + //console.log("parentNodeType:" + parentNodeType); + if(countChildLogicNodes >1 && parentNodeType != 'block' && parentNodeType != 'for' ){ + if(node.dgnumber != undefined && node.dgnumber){ + flowDesignErrors.push("Warning:May need a block Node after Node. <br><span style='color:red'>Node Name:</span>" + node.name + "<br><span style='color:red'>DG Number:</span>" + node.dgnumber[0] ); + }else{ + flowDesignErrors.push("Warning:May need a block Node after Node <br><span style='color:red'>Node name:</span>" + parentNodeName); + } + break; + } + } + } + } + if(dgStartCnt > 1){ + flowDesignErrors.push("Error:There should only be 1 dgstart Node in the current workspace."); + } + + if(serviceLogicCnt > 1){ + flowDesignErrors.push("Error:There should only be 1 service-logic Node in the current workspace."); + } + + if(methodCnt > 1){ + flowDesignErrors.push("Error:There should only be 1 method Node in the current workspace."); + } + + if(flowDesignErrors != null && flowDesignErrors.length >0){ + return false; + } + return true; +} + +var flowDesignErrors = []; +function showFlowDesignErrorBox(){ + if(flowDesignErrors != null && flowDesignErrors.length >0){ + var htmlStr="<div id='flowpath-err-list-div'><table id='fpeTable' border='1'><tr><th>Error List</th></tr>"; + for(var j=0;flowDesignErrors != null && j<flowDesignErrors.length;j++){ + var errSeq = j+1; + htmlStr += "<tr><td>" + errSeq + ")" + flowDesignErrors[j] + "</td></tr>"; + } + htmlStr += "</table></div>"; + + //$('<div></div>').dialog({ + + $('#flow-design-err-dialog').dialog({ + modal: true, + title: "Flow design Error List ", + width: 500, + /*open: function () { + $(this).html(htmlStr); + },*/ + buttons: { + Close: function () { + $(this).dialog("close"); + } + } + }).html(htmlStr); // end dialog div + } +} + + +function getCurrentFlowNodeSet(){ + var nodeSet=[]; + //console.dir(RED); + //RED.view.dirty(); + //RED.view.redraw(); + var activeWorkspace=RED.view.getWorkspace(); + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + nodeSet.push({'n':n}); + } + }); + + var exportableNodeSet = RED.nodes.createExportableNodeSet(nodeSet); + //console.dir(exportableNodeSet); + //console.log(JSON.stringify(exportableNodeSet)); + return exportableNodeSet; +} + +function getNode(nodeSet,id){ + for(var i=0;i<nodeSet.length;i++){ + if(nodeSet[i].id == id){ + return nodeSet[i]; + } + } + return null; +} +function getNodeIdToNodeMap(nodeSet){ + var nodeIdToNodeMap ={}; + for(var i=0;i<nodeSet.length;i++){ + nodeIdToNodeMap[nodeSet[i].id] = nodeSet[i]; + if(nodeSet[i].type == "dgstart"){ + nodeIdToNodeMap["dgstart"] = nodeSet[i]; + } + } + return nodeIdToNodeMap; +} + +function validateEachNodeXml(){ + var activeWorkspace=RED.view.getWorkspace(); + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + var xml = n.xml; + if( xml != null && xml != ''){ + var validationSuccess = validateXML(n.xml); + if(validationSuccess){ + n.status = {fill:"green",shape:"dot",text:"OK"}; + }else{ + n.status = {fill:"red",shape:"dot",text:"ERROR"}; + } + } + } + }); +} + + +function getNodeToXml(inputNodeSet){ + var exportableNodeSet; + //uses inputNodeSet if passed otherwise build the latest nodeSet + + //$("#btn-deploy").removeClass("disabled"); + + + function getNode(id){ + for(var i=0;i<exportableNodeSet.length;i++){ + if(exportableNodeSet[i].id == id){ + return exportableNodeSet[i]; + } + } + return null; + } + + function getStartTag(node){ + var startTag=""; + var xmlStr=""; + if(node != null && node.type != 'dgstart'){ + xmlStr=node.xml; + var regex = /(<)([\w-]+)(.*)?/; + var match = regex.exec(xmlStr); + if(match != null){ + if(match[1] != undefined && match[2] != undefined){ + startTag = match[2]; + } + }else{ + console.log("startTag not found."); + } + } + return startTag; + } + + if(inputNodeSet == null || inputNodeSet == undefined){ + exportableNodeSet = getCurrentFlowNodeSet(); + }else{ + exportableNodeSet = JSON.parse(inputNodeSet); + } + var dgstartNode = getDgStartNode(exportableNodeSet); + + var level=0; + var fullXmlStr=""; + + printXml(dgstartNode); + + + function printXml(node){ + var xmlStr=""; + var startTag = ""; + if(node != null && node.type != 'dgstart'){ + var comments=node.comments; + if(comments != null && comments != ""){ + //if xml comments field already has the <!-- and --> remove them + comments=comments.replace("<!--",""); + comments=comments.replace("-->",""); + xmlStr="<!--" + comments + "-->"; + } + xmlStr+=node.xml; + startTag = getStartTag(node); + fullXmlStr +=xmlStr; + /* + if(level > 0){ + var spacing = Array(level).join(" "); + xmlStr=xmlStr.replace(/\n/g,spacing); + fullXmlStr +=xmlStr; + + console.log(xmlStr); + }else{ + fullXmlStr +=xmlStr; + console.log(xmlStr); + } + */ + } + + //console.log("startTag:" + startTag); + + var wiredNodes = []; + var wiredNodesArr = []; + if(node != null && node.wires != null && node.wires[0] != null && node.wires[0] != undefined && node.wires[0].length >0 ){ + wiredNodes=node.wires[0]; + //console.log("Before sort"); + for(var k=0;wiredNodes != undefined && wiredNodes != null && k<wiredNodes.length;k++){ + wiredNodesArr.push(getNode(wiredNodes[k])); + } + //console.dir(wiredNodesArr); + //sort based on y position + wiredNodesArr.sort(function(a, b){ + return a.y-b.y; + }); + //console.log("After sort"); + //console.dir(wiredNodesArr); + } + + for(var k=0;wiredNodesArr != null && k<wiredNodesArr.length;k++){ + level++; + var nd = wiredNodesArr[k]; + printXml(nd); + } + + //append end tag + if(startTag != ""){ + fullXmlStr += "</" + startTag + ">"; + /* + if(level >0){ + var spacing = Array(level).join(" "); + fullXmlStr += spacing + "</" + startTag + ">"; + console.log(spacing + "</" + startTag + ">"); + }else{ + fullXmlStr += "</" + startTag + ">"; + console.log("</" + startTag + ">"); + } + */ + } + + /*if(level>0){ + level=level-1; + } + */ + //console.log("endTag:" + startTag); + //console.log("xml:" + fullXmlStr); + } + //console.log("fullXmlStr:" + fullXmlStr); + return fullXmlStr; +} + +function showFlow(filePath){ +var jqxhr = $.post( "/getSharedFlow",{"filePath":filePath}) + .done(function(data) { + $( "#dgflow-browser-dialog").dialog("close"); + var migratedNodes = migrateNodes(data); + //RED.view.importNodes(data) + RED.view.importNodes(JSON.stringify(migratedNodes)); + //console.log( "import done"); + }) + .fail(function() { + RED.notify("Could not import user flow ."); + $( "#dgflow-browser-dialog").dialog("close"); + console.log( "error occured importing flow."); + }) + .always(function() { + //console.log( "complete" ); + }); +} + +function showFlowXml(filePath){ +var jqxhr = $.post( "/getSharedFlow",{"filePath":filePath}) + .done(function(data) { + //console.dir(data); + var xmlStr=getNodeToXml(data); + showImportedXml(xmlStr,this); + }) + .fail(function() { + RED.notify("Could not convert to XML."); + $( "#dgflow-browser-dialog").dialog("close"); + console.log( "error occured importing flow."); + }) + .always(function() { + //console.log( "complete" ); + }); +} + +function showFlowFiles(userName){ + //var divStyle="color:#07c; margin-bottom: 1.2em; font-size: 16px;"; + //var divStyle="<style>#data-container a { color: #067ab4; font-size: 0.75em;} #data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } </style>"; + var divStyle="<style>#data-container a { color: #067ab4; font-size: 0.75em;} #data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>"; + + var htmlStr=divStyle + "<div class='header'>List of Flow files of User " + userName + "</div><div id='data-container'><ul>" ; + $.post( "/getFiles/" + userName) + .done(function( data ) { + //console.dir(data); + //console.log("found " + data.length + " files"); + if(data != null && data.length != undefined && data.length != 0){ + if(data != null && data.length>0){ + for(var k=0;k<data.length;k++){ + htmlStr += "<li><a href=\"#\" onclick=\"showFlow('" +data[k].filePath + "')\">" + data[k].name + "</a></li>"; + /* + //Use this code to display the View Xml Link + htmlStr += "<li><a href=\"#\" onclick=\"showFlow('" +data[k].filePath + "')\">" + data[k].name + "</a><span style=\"margin-left:15px;color:blue\"><a href=\#\" onclick=\"showFlowXml('" +data[k].filePath + "')\">[View Xml]</a></span></li>"; + */ + } + htmlStr+="</ul></div>"; + } + $( "#dgflow-browser-dialog").html(htmlStr); + }else{ + //console.log("no flow files found for user " + userName); + var noFlowFilesHtml = divStyle + "<div id='data-container'><p>No downloaded Flow files found in " + userName + " directory</p><a href='#' onclick='javascript:closeAndShowFlowShareUsers()'>Back to List.</a></div>"; + $( "#dgflow-browser-dialog").html(noFlowFilesHtml); + } + }) + .fail(function(err) { + console.log( "error" + err ); + }) + .always(function() { + //console.log("done"); + }); + +} + + function closeAndShowFlowShareUsers(){ + $("#dgflow-browser-dialog").dialog( "close" ); + var divStyle="<style>#data-container a { color: #067ab4; font-size: 0.75em;} #data-container a:hover { text-decoration: underline; padding: -15px -15px -15px 15px; } .header { height: 40px; border-bottom: 1px solid #EEE; background-color: #ffffff; height: 40px; -webkit-border-top-left-radius: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px; border-top-left-radius: 5px; border-top-right-radius: 5px; } .footer { height: 40px; background-color: whiteSmoke; border-top: 1px solid #DDD; -webkit-border-bottom-left-radius: 5px; -webkit-border-bottom-right-radius: 5px; -moz-border-radius-bottomleft: 5px; -moz-border-radius-bottomright: 5px; border-bottom-left-radius: 5px; border-bottom-right-radius: 5px; }</style>"; + $.get( "/flowShareUsers") + .done(function( data ) { + + var header="<div class='header'>List of downloaded DG Flows </div>"; + var html= divStyle + header + "<div id='data-container'>"; + html+="<ul>"; + if(data != null){ + var users=data.flowShareUsers; + users.sort(function (a,b){ + if(a.name > b.name){ + return 1; + }else if(a.name < b.name){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;users != null && i<users.length;i++){ + html+="<li><a href=\"#\" onclick=\"showFlowFiles('" + users[i].rootDir + "')\">" + users[i].name + "</a></li>"; + } + } + html+="</ul>"; + html+="</div>"; + $( "#dgflow-browser-dialog" ).dialog({ + title: "Dowloaded DG Flow Browser", + modal: true, + autoOpen: true, + width: 530, + height: 530, + buttons: [ + { + text: "Close", + click: function() { + $( this ).dialog( "close" ); + } + } + ] + }).html(html); + $("#dgflow-browser-dialog").show(); + }) + .fail(function(err) { + RED.notify("Failed to get users."); + }) + .always(function() { + }); + } + +function showImportedXml(xmlStr,dialogBox){ + var formattedXml=vkbeautify.xml(xmlStr); + var that = dialogBox; + require(["orion/editor/edit"], function(edit) { + that.editor = edit({ + parent:document.getElementById('dgflow-browser-dialog'), + lang:"html", + readonly:true, + contents: formattedXml + }); + RED.library.create({ + url:"functions", // where to get the data from + type:"function", // the type of object the library is for + editor:that.editor, // the field name the main text body goes to + fields:['name','outputs'] + }); + }); +} + +function getTag(xmlStr){ + var tag= null ; + if(xmlStr != null){ + xmlStr = xmlStr.trim(); + } + try{ + var regex = new RegExp("(<)([^ >]+)"); + var match = regex.exec(xmlStr); + if(match != null){ + if(match[1] != undefined && match[2] != undefined){ + tag = match[2]; + } + } + }catch(e){ + console.log(e); + } + return tag; + +} + +function getAttributeValue(xmlStr,attribute){ + + var attrVal=null; + try{ + var myRe = new RegExp(attribute + "[\s+]?=[\s+]?['\"]([^'\"]+)['\"]","m"); + var myArray = myRe.exec(xmlStr); + if(myArray != null && myArray[1] != null){ + attrVal=myArray[1]; + } + }catch(err){ + console.log(err); + } + return attrVal; +} + +function showOrHideTab(checkbox,idVal){ + + var activeWorkspace=RED.view.getWorkspace(); + var table = $("#ftab02"); + $('td input:checkbox',table).each(function(i){ + console.log(this.checked); + }); + //console.dir($('td input:checkbox',table).prop('checked',this.checked)); + + $(".red-ui-tabs li a").each(function(i){ + var id=$(this).attr("href").replace('#',''); + if(id == idVal){ + $(this).parent().toggle(); + var isVisible = $(this).parent().is(":visible"); + if(isVisible){ + checkbox.checked = true; + }else{ + checkbox.checked = false; + } + if(activeWorkspace == id){ + //$("#chart").hide(); + //var li = ul.find("a[href='#"+id+"']").parent(); + var li = $(this).parent(); + if (li.hasClass("active")) { + li.removeClass("active"); + if(li.parent().children().size() != 0){ + } + console.log("has Class active"); + var tab = li.prev(); + if (tab.size() === 0) { + console.log("li prev size 0"); + tab = li.next(); + } + if(tab.is(":visible")){ + console.log("added active"); + tab.addClass("active"); + tab.click(); + //tab.trigger("click"); + } + //console.dir(tab); + //tab.parent().addClass("active"); + //tab.click(); + } + }else{ + console.log("added active id" +id); + if(isVisible){ + var li = $(this).parent(); + li.addClass("active"); + li.click(); + //console.dir(li); + }else{ + var li = $(this).parent(); + li.removeClass("active"); + } + } + } + }); +/* + $(".red-ui-tabs li a").each(function(i){ + var id=$(this).attr("href").replace('#',''); + if(id != idVal){ + $(this).trigger("click"); + if(activeWorkspace == idVal){ + $("#chart").show(); + } + return false; + } + }); +*/ +} + +function performGitCheckout(){ + $("#responseId").text(""); + if(!event) event = window.event; + var target = $(event.target); + target.val("Processing"); + target.css({ "background-image": "url('images/page-loading.gif')" }); + target.css({ "background-repeat": "no-repeat" }); + target.css({ "background-size": "25px 25px" }); + + var branch = document.getElementById("branchId").value.trim(); + var statusObj = document.getElementById("responseId"); + if(branch == null || branch == ''){ + statusObj.innerText = "Branch is required."; + return; + } + var urlVal = "/gitcheckout?branch=" + branch; + $.get(urlVal) + .done(function( data ) { + var output = data.output; + if(output != null){ + output=output.replace(/\n/g,"<br>"); + statusObj.innerHTML = output; + } + }) + .fail(function(err) { + statusObj.innerText = "Failed to do git checkout."; + }) + .always(function() { + $("#responseId").show(); + target.val("Checkout"); + target.css({ "background-image": "none" }); + }); +} + +function performGitPull(){ + $("#responseId").text(""); + if(!event) event = window.event; + var target = $(event.target); + target.val("Processing"); + target.css({ "background-image": "url('images/page-loading.gif')" }); + target.css({ "background-repeat": "no-repeat" }); + target.css({ "background-size": "25px 25px" }); + + var statusObj = document.getElementById("responseId"); + var urlVal = "/gitpull"; + $.get(urlVal) + .done(function( data ) { + var output = data.output; + if(output != null){ + output=output.replace(/\n/g,"<br>"); + statusObj.innerHTML = output; + } + }) + .fail(function(err) { + statusObj.innerText = "Failed to do git pull."; + }) + .always(function() { + $("#responseId").show(); + target.val("Pull"); + target.css({ "background-image": "none" }); + }); +} + + +function activateClickedTab(idVal) { + + $("#filter-tabs-dialog").dialog( "close" ); + var ul = $("#workspace-tabs"); + ul.children().each(function(){ + var li = $(this); + var link =li.find("a"); + var href = link.prop("href"); + var hrefId = href.split("#"); + if(hrefId[1] == idVal){ + link.trigger("click"); + } + }); +} + +function deleteOrRenameTab(idVal) { + $("#filter-tabs-dialog").dialog( "close" ); + var ul = $("#workspace-tabs"); + ul.children().each(function(){ + var li = $(this); + var link =li.find("a"); + var href = link.prop("href"); + var hrefId = href.split("#"); + if(hrefId[1] == idVal){ + link.trigger("click"); + link.trigger("dblclick"); + } + }); +} + +function deleteSelectedTab(idVal,title,_module,rpc,version){ + var dgInfo = "<div><table width='100%' border='1'><tr style='background-color:#65a9d7;color:white;' ><th>Tab Title</th><th>Module</th><th>RPC</th><th>Version</th></tr><tr style='background-color:white'><td>" + title + "</td><td>" + _module +"</td><td>" + rpc + "</td><td>" +version + "</td></tr></table></div><br>"; + var alertMsg = dgInfo + "<p>Are you sure you want to Delete this Tab ?</p>"; + +$( "#tabAlertDialog" ).dialog({ + dialogClass: "no-close", + modal:true, + draggable : true, + /*dialogClass: "alert",*/ + title: "Confirm Tab sheet Delete", + width: 600, + buttons: [ + { + text: "Delete", + class:"alertDialogButton", + click: function() { + var ws = RED.nodes.workspace(idVal); + RED.view.removeWorkspace(ws); + var historyEvent = RED.nodes.removeWorkspace(idVal); + historyEvent.t = 'delete'; + historyEvent.dirty = true; + historyEvent.workspaces = [ws]; + RED.history.push(historyEvent); + RED.view.dirty(true); + $( this ).dialog( "close" ); + $("#filter-tabs-dialog").dialog( "close" ); + $("#btn-manage-tabs").trigger("click"); + } + }, + { + text: "Cancel", + class:"alertDialogButton", + click: function() { + $( this ).dialog( "close" ); + } + } + ] +}).html(alertMsg); +} + +function renameSelectedTab(idVal,title,_module,rpc,version){ + var dgInfo = "<div><table width='100%' border='1'><tr style='background-color:#65a9d7;color:white;' ><th>Tab Title</th><th>Module</th><th>RPC</th><th>Version</th></tr><tr style='background-color:white'><td><input id='tab-name-" + idVal + "' type='text' value='" + title + "'></td><td>" + _module +"</td><td>" + rpc + "</td><td>" +version + "</td></tr></table></div><br>"; + var alertMsg = dgInfo + "<p>Change the title and click Rename.</p>"; + +$( "#tabAlertDialog" ).dialog({ + dialogClass: "no-close", + modal:true, + draggable : true, + /*dialogClass: "alert",*/ + title: "Rename Tab sheet", + width: 600, + buttons: [ + { + text: "Rename", + class:"alertDialogButton", + click: function() { + var ws = RED.nodes.workspace(idVal); + var label = document.getElementById("tab-name-" + idVal).value; + //console.log("label:" +label); + //console.log("ws.label:" + ws.label); + if (ws.label != label) { + ws.label = label; + var link = $("#workspace-tabs a[href='#"+idVal+"']"); + link.attr("title",label); + link.text(label); + RED.view.dirty(true); + } + $("#tabAlertDialog").dialog('destroy').remove(); + //$(this).dialog( "close" ); + $("#filter-tabs-dialog").dialog( "close" ); + $("#btn-manage-tabs").trigger("click"); + } + }, + { + text: "Cancel", + class:"alertDialogButton", + click: function() { + $( this ).dialog( "close" ); + } + } + ] +}).html(alertMsg); +} + +function performGitStatus(){ + $("#responseId").text(""); + if(!event) event = window.event; + var target = $(event.target); + target.val("Processing"); + target.css({ "background-image": "url('images/page-loading.gif')" }); + target.css({ "background-repeat": "no-repeat" }); + target.css({ "background-size": "25px 25px" }); + + var statusObj = document.getElementById("responseId"); + var urlVal = "/gitstatus"; + $.get(urlVal) + .done(function( data ) { + var output = data.output; + if(output != null){ + output=output.replace(/\n/g,"<br>"); + statusObj.innerHTML = output; + } + //statusObj.innerText = data.output; + }) + .fail(function(err) { + statusObj.innerText = "Failed to do git status."; + }) + .always(function() { + $("#responseId").show(); + target.val("Status"); + target.css({ "background-image": "none" }); + }); +} + +function migrateNodes(jsonStr){ + var nodes = JSON.parse(jsonStr); + nodes.forEach( function(node) { + if( node.xml != undefined && node.xml != null && node.xml.indexOf("<service-logic") != -1){ + //console.log(node.xml); + var module=""; + var version=""; + module=getAttributeValue(node.xml,"module"); + /* + var myRe = new RegExp("module=\"(.*)\" ", "m"); + var myArray = myRe.exec(node.xml); + if(myArray != null && myArray[1] != null){ + module=myArray[1]; + } + myRe = new RegExp("version=\"(.*)\">", "m"); + myArray = myRe.exec(node.xml); + if(myArray != null && myArray[1] != null){ + version=myArray[1]; + //console.dir(myArray); + } + */ + version=getAttributeValue(node.xml,"version"); + node.type="service-logic"; + //node.category="DGEmain"; + node.module=module; + node.version=version; + if(module != null && version != null){ + node.name=module+ " " + version; + } + console.log("module=" + module); + console.log("version=" + version); + }else if( node.xml != undefined && node.xml != null && node.xml.indexOf("<method") != -1){ + var rpc=getAttributeValue(node.xml,"rpc"); + node.type="method"; + if(rpc != null){ + node.name=rpc; + } + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<outcome") != -1){ + var uxml = node.xml.toUpperCase(); + if(uxml.indexOf("FAILURE") != -1){ + node.type="failure"; + }else if(uxml.indexOf("SUCCESS") != -1){ + node.type="success"; + }else if(uxml.indexOf("TRUE") != -1){ + node.type="outcomeTrue"; + }else if(uxml.indexOf("FALSE") != -1){ + node.type="outcomeFalse"; + }else if(uxml.indexOf("ALREADY-ACTIVE") != -1){ + node.type="already-active"; + }else if(uxml.indexOf("NOT-FOUND") != -1){ + node.type="not-found"; + }else{ + node.type="other"; + } + }else if( node.xml != undefined &&node.xml != null && node.xml.indexOf("<return") != -1){ + var uxml = node.xml.toUpperCase(); + if(uxml.indexOf("FAILURE") != -1){ + node.type="returnFailure"; + }else if(uxml.indexOf("SUCCESS") != -1){ + node.type="returnSuccess"; + } + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<exists") != -1){ + node.type="exists"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<block") != -1){ + node.type="block"; + var atomic=getAttributeValue(node.xml,"atomic"); + + if(atomic=='true'){ + node.atomic="true"; + node.name="block : atomic"; + }else{ + node.atomic="false"; + node.name="block"; + } + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<save") != -1){ + node.type="save"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<switch") != -1){ + node.type="switchNode"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<record") != -1){ + node.type="record"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<call") != -1){ + node.type="call"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<release") != -1){ + node.type="release"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<set") != -1){ + node.type="set"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<for") != -1){ + node.type="for"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<is-available") != -1){ + node.type="is-available"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<reserve") != -1){ + node.type="reserve"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<get-resource") != -1){ + node.type="get-resource"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<configure") != -1){ + node.type="configure"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<delete") != -1){ + node.type="delete"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<execute") != -1){ + node.type="execute"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<notify") != -1){ + node.type="notify"; + }else if(node.xml != undefined && node.xml != null && node.xml.indexOf("<update") != -1){ + node.type="update"; + } + //console.dir(node); + }); + return nodes; +} diff --git a/dgbuilder/public/util/js/dgeToXml.js.imp b/dgbuilder/public/util/js/dgeToXml.js.imp new file mode 100644 index 00000000..199b1c6c --- /dev/null +++ b/dgbuilder/public/util/js/dgeToXml.js.imp @@ -0,0 +1,147 @@ +function getNodeToXml(){ + var nodeSet=[]; + var activeWorkspace=RED.view.getWorkspace(); + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + nodeSet.push({n:n}); + } + }); + + var exportableNodeSet = RED.nodes.createExportableNodeSet(nodeSet); + console.dir(exportableNodeSet); + console.log(JSON.stringify(exportableNodeSet)); + + function getDgStartNode(nodeList){ + for(var i=0;i<nodeList.length;i++){ + if(nodeList[i].type == 'dgstart'){ + return nodeList[i]; + } + } + return null; + } + function getNode(id){ + for(var i=0;i<exportableNodeSet.length;i++){ + if(exportableNodeSet[i].id == id){ + return exportableNodeSet[i]; + } + } + return null; + } + + function getStartTag(node){ + var startTag=""; + var xmlStr=""; + if(node != null && node.type != 'dgstart'){ + xmlStr=node.xml; + var regex = /(<)([\w-]+)(.*)?/; + var match = regex.exec(xmlStr); + if(match != null){ + if(match[1] != undefined && match[2] != undefined){ + startTag = match[2]; + } + }else{ + console.log("startTag not found."); + } + } + return startTag; + } + + var dgstartNode = getDgStartNode(exportableNodeSet); + + var level=0; + var fullXmlStr=""; + + printXml(dgstartNode); + + + function printXml(node){ + var xmlStr=""; + var startTag = ""; + if(node != null && node.type != 'dgstart'){ + xmlStr=node.xml; + startTag = getStartTag(node); + if(level > 0){ + var spacing = Array(level).join(" "); + xmlStr=xmlStr.replace(/\n/g,spacing); + fullXmlStr +=xmlStr; + + console.log(xmlStr); + }else{ + fullXmlStr +=xmlStr; + console.log(xmlStr); + } + } + + //console.log("startTag:" + startTag); + + var wiredNodes = []; + if(node != null && node.wires != null && node.wires[0] != null && node.wires[0] != undefined && node.wires[0].length >0 ){ + wiredNodes=node.wires[0]; + //sort based on y position + wiredNodes.sort(function(a, b){ + return a.y-b.y; + }); + } + + for(var k=0;wiredNodes != null && k<wiredNodes.length;k++){ + level++; + var nd = getNode(wiredNodes[k]); + printXml(nd); + } + + //append end tag + if(startTag != ""){ + if(level >0){ + var spacing = Array(level).join(" "); + fullXmlStr += spacing + "</" + startTag + ">"; + console.log(spacing + "</" + startTag + ">"); + }else{ + fullXmlStr += "</" + startTag + ">"; + console.log("</" + startTag + ">"); + } + } + + if(level>0){ + level=level-1; + } + console.log("endTag:" + startTag); + //console.log("xml:" + fullXmlStr); + } + console.log("fullXmlStr:" + fullXmlStr); + + /* + for (var link in allLinks){ + var nd = RED.nodes.node(link); + console.dir(nd); + var obj = RED.nodes.getNodeSet(RED.view.getWorkspace()); + console.dir(obj); + } + */ + + + //console.dir(RED.nodes.getAllFlowNodes()); + //console.dir(RED.nodes.getType()); + /* + console.dir(RED.nodes.nodes); + RED.nodes.nodes.forEach(function (node){ + console.dir(node); + }); + */ + + /*var map = {68: false, 69: false, 86: false}; + $("#node-input-validate").keydown(function(e) { + if (e.keyCode in map) { + map[e.keyCode] = true; + if (map[68] && map[69] && map[86]) { + // FIRE EVENT + return "abcd"; + } + } + }).keyup(function(e) { + if (e.keyCode in map) { + map[e.keyCode] = false; + } + }); + */ + return fullXmlStr; +} diff --git a/dgbuilder/public/util/js/jsonTool.js b/dgbuilder/public/util/js/jsonTool.js new file mode 100644 index 00000000..f4d0de36 --- /dev/null +++ b/dgbuilder/public/util/js/jsonTool.js @@ -0,0 +1,67 @@ +var obj={}; +function dotToJson(str,value,obj){ + //var objArr = path.split("."), part; + var objArr = str.split("."); + var prevStr; + var currObj; + var prevObj; + console.log(str); + for(var i=0;i<objArr.length -1;i++){ + var subStr= objArr[i] ; + //console.log("subStr:" + subStr); + if(i==0 && obj[subStr] == undefined ){ + obj[subStr] = {}; + currObj= obj[subStr]; + }else if(i==0 && obj[subStr] != undefined ){ + currObj=obj[subStr]; + //console.log("in gkjgjkg"); + }else{ + if(i == 1){ + prevObj=obj[prevStr]; + if(prevObj[subStr] == undefined){ + prevObj[subStr] = {}; + currObj = prevObj[subStr]; + }else{ + currObj = prevObj[subStr]; + } + }else{ + if(prevObj[subStr] == undefined){ + prevObj[subStr] = {}; + currObj = prevObj[subStr]; + }else{ + currObj = prevObj[subStr]; + } + } + //console.dir(currObj); + } + prevStr=subStr; + if(i <objArr.length-2){ + prevObj=currObj; + } + } + var lastStr = objArr[objArr.length-1]; + currObj[lastStr] = value; + //prevObj[lastStr] = value; + //console.dir(currObj); + return obj; +} +n=dotToJson('abcfdfghdghdghdghdhdhd.efhfjhfjhfjhfjhfjhfjhfbg.hfjhfjhfjhfjhfjhfjh.l',"1234",obj); +//console.dir(n); +JSON.stringify(n,undefined,2); +m=dotToJson('abc.ebg.h.n',"5678",n); +console.dir(m); +function printObj(obj){ +for( j in obj){ + console.log(j + ":" + obj[j]); + if(typeof obj[j] == "object" ){ + printObj(obj[j]); + } + +} +} +printObj(m); +a=JSON.parse(JSON.stringify(m,null,2)); +console.dir(a); + + +//console.log (stringToObj('abc.ebg.h',"",{})); diff --git a/dgbuilder/public/util/js/migrateFlow.js b/dgbuilder/public/util/js/migrateFlow.js new file mode 100644 index 00000000..399db606 --- /dev/null +++ b/dgbuilder/public/util/js/migrateFlow.js @@ -0,0 +1,184 @@ +fs=require('fs'); +_=require('lodash'); +//extras=require("/home/users/schinthakayala/nodered/sheshi/dgxml/extras"); +//puts=extras.puts; +var path = require('path'); +var appDir = path.dirname(require.main.filename); + +var dgjson = []; +var level = 0; + +function getJSON() { +var filename = process.argv[2]; + console.log("reading json from flows file" + filename); + //flowsJson=fs.readFileSync(appDir + "/flows_ss4nj01dev01.localdomain.json").toString(); + flowsJson=fs.readFileSync(filename).toString(); + // Let's make a backup while we're here... + ts=Date.now().toString(); + flows=JSON.parse(flowsJson); + //console.log("returning flows"); + return(flows); +} + +function getStartTag(xmlStr){ + var startTag= null ; + if(xmlStr != null){ + xmlStr = xmlStr.trim(); + } + try{ + var regex = new RegExp("(<)([^ >]+)"); + var match = regex.exec(xmlStr); + if(match != null){ + if(match[1] != undefined && match[2] != undefined){ + startTag = match[2]; + } + } + }catch(e){ + console.log(e); + } + return startTag; + +} + +function getAttributeValue(xmlStr,attribute){ + var attrVal=null; + try{ + var myRe = new RegExp(attribute + "=['\"](.*)['\"] ","m"); + var myArray = myRe.exec(xmlStr); + if(myArray != null && myArray[1] != null){ + attrVal=myArray[1]; + } + }catch(err){ + console.log(err); + } + return attrVal; +} + +function processNodes(){ + var nodes = getJSON(); + //console.dir(nodes); + + nodes.forEach( function(node) { + if( node.xml != null && node.xml.indexOf("<service-logic") != -1){ + //console.log(node.xml); + var module=""; + var version=""; + module=getAttributeValue(node.xml,"module"); + /* + var myRe = new RegExp("module=\"(.*)\" ", "m"); + var myArray = myRe.exec(node.xml); + if(myArray != null && myArray[1] != null){ + module=myArray[1]; + } + myRe = new RegExp("version=\"(.*)\">", "m"); + myArray = myRe.exec(node.xml); + if(myArray != null && myArray[1] != null){ + version=myArray[1]; + //console.dir(myArray); + } + */ + version=getAttributeValue(node.xml,"version"); + node.type="service-logic"; + //node.category="DGEmain"; + node.module=module; + node.version=version; + if(module != null && version != null){ + node.name=module+ "_" + version; + } + console.log("module=" + module); + console.log("version=" + version); + }else if( node.xml != null && node.xml.indexOf("<method") != -1){ + var rpc=getAttributeValue(node.xml,"rpc"); + node.type="method"; + if(rpc != null){ + node.name=rpc; + } + }else if( node.xml != null && node.xml.indexOf("<outcome") != -1){ + var uxml = node.xml.toUpperCase(); + if(uxml.indexOf("FAILURE") != -1){ + node.type="failure"; + }else if(uxml.indexOf("SUCCESS") != -1){ + node.type="success"; + }else if(uxml.indexOf("TRUE") != -1){ + node.type="outcomeTrue"; + }else if(uxml.indexOf("FALSE") != -1){ + node.type="outcomeFalse"; + }else if(uxml.indexOf("ALREADY-ACTIVE") != -1){ + node.type="already-active"; + }else if(uxml.indexOf("NOT-FOUND") != -1){ + node.type="not-found"; + }else{ + node.type="other"; + } + }else if( node.xml != null && node.xml.indexOf("<return") != -1){ + var uxml = node.xml.toUpperCase(); + if(uxml.indexOf("FAILURE") != -1){ + node.type="returnFailure"; + }else if(uxml.indexOf("SUCCESS") != -1){ + node.type="returnSuccess"; + } + }else if( node.xml != null && node.xml.indexOf("<exists") != -1){ + node.type="exists"; + }else if( node.xml != null && node.xml.indexOf("<block") != -1){ + node.type="block"; + var atomic=getAttributeValue(node.xml,"atomic"); + + if(atomic=='true'){ + node.atomic="true"; + node.name="block : atomic"; + }else{ + node.atomic="false"; + node.name="block"; + } + }else if( node.xml != null && node.xml.indexOf("<save") != -1){ + node.type="save"; + }else if( node.xml != null && node.xml.indexOf("<switch") != -1){ + node.type="switchNode"; + }else if( node.xml != null && node.xml.indexOf("<record") != -1){ + node.type="record"; + }else if( node.xml != null && node.xml.indexOf("<call") != -1){ + node.type="call"; + }else if( node.xml != null && node.xml.indexOf("<release") != -1){ + node.type="release"; + }else if( node.xml != null && node.xml.indexOf("<set") != -1){ + node.type="set"; + }else if( node.xml != null && node.xml.indexOf("<for") != -1){ + node.type="for"; + }else if( node.xml != null && node.xml.indexOf("<is-available") != -1){ + node.type="is-available"; + }else if( node.xml != null && node.xml.indexOf("<reserve") != -1){ + node.type="reserve"; + }else if( node.xml != null && node.xml.indexOf("<get-resource") != -1){ + node.type="get-resource"; + }else if( node.xml != null && node.xml.indexOf("<configure") != -1){ + node.type="configure"; + }else if( node.xml != null && node.xml.indexOf("<delete") != -1){ + node.type="delete"; + }else if( node.xml != null && node.xml.indexOf("<execute") != -1){ + node.type="execute"; + } + //console.dir(node); + }); +/* + var moduleName = "service-logic"; + var methodName = "method"; + for(var i=0;nodes != null && i<nodes.length;i++){ + if(nodes[i].type == "service-logic"){ + moduleName = nodes[i].name; + } + if(nodes[i].type == "method"){ + methodName = nodes[i].name; + } + } + var fName = moduleName + "_" + methodName + ".json"; + fName = fName.replace(/\s/g, "_"); + + var newFilename = process.argv[3]; + var filename = newFilename + "/" + fName; + console.log("filename" + filename); + fs.writeFileSync(filename, JSON.stringify(nodes,null,4)); + */ +} + + +processNodes(); diff --git a/dgbuilder/public/util/js/sliValues.js b/dgbuilder/public/util/js/sliValues.js new file mode 100644 index 00000000..eae10601 --- /dev/null +++ b/dgbuilder/public/util/js/sliValues.js @@ -0,0 +1,763 @@ +var global_editor ; +function addParam(idVal){ + //console.log(val); + //console.log(global_editor.getText()); + if(global_added_obj["a" + idVal] != undefined && global_added_obj["a" + idVal] != null){ + global_added_obj["a" + idVal]= global_added_obj["a" + idVal]+1; + $("#addCnt" + + idVal).text("added " + global_added_obj["a" + idVal] + " times"); + }else{ + global_added_obj["a" + idVal]= 1; + $("#addCnt" + + idVal).text("added " + global_added_obj["a" + idVal] + " time"); + } + var nameVal = document.getElementById("a" + idVal).value; + var valueBoxVal = document.getElementById("valbox" + idVal).value; + //$("#btn" + idVal).val('Added'); + //$("#btn" + idVal).attr('disabled','disabled'); + //console.dir(nameVal); + //console.dir(valueBoxVal); + + + var paramElement = "<parameter name='" + nameVal + "' value='" + valueBoxVal + "'/>\n"; + global_editor.setText(global_editor.getText() + paramElement); +} + +var g_currValuesObj={}; + +function filterValues(filterVal){ + global_added_obj={}; + var matchedCnt =0; + var valuesObj = g_currValuesObj; + var newValuesObj ={}; + var searchValues =[]; + if(filterVal != null && filterVal != undefined){ + filterVal=filterVal.trim(); + } + searchValues = filterVal.split(/ /); + //console.log("filterVal:" + filterVal); + if(searchValues != null && searchValues != undefined){ + for (var key in valuesObj) { + if (valuesObj.hasOwnProperty(key)) { + var newArrObj = []; + if(Array.isArray(valuesObj[key])){ + var arrObj=valuesObj[key]; + var cnt=1; + for(var i=0;i<arrObj.length;i++){ + var foundCount = 0; + for(var k=0;k<searchValues.length;k++){ + if(arrObj[i].indexOf(searchValues[k]) != -1){ + foundCount++; + } + } + if(foundCount == searchValues.length){ + matchedCnt++; + newArrObj.push(arrObj[i]); + } + } + newValuesObj[key] = newArrObj; + } + } + } + $("#matchedCntId").html(matchedCnt); + }else{ + newValuesObj = valuesObj; + } + var valuesHtml=buildValuesHtml(newValuesObj); + valuesHtml+="</div>"; + $("#sli-values-div").html(valuesHtml); +} + +function buildValuesHtml(valuesObj){ + var idCounter=0; + var htmlVal = ""; + + for (var key in valuesObj) { + if (valuesObj.hasOwnProperty(key)) { + var v = "<div style='font-weight:bold;font-size:1.0em;'><label>" + key + "<b/label>"; + if(Array.isArray(valuesObj[key])){ + var arrObj=valuesObj[key]; + var cnt=1; + for(var i=0;i<arrObj.length;i++){ + var idVal = idCounter++; + var addBtn = "<input id='btn" + idVal + "' type='button' style='background-color:#D6EBFF;' value='Add as Parameter'" + "onclick='addParam(\"" + idVal + "\")'><div style='float:right' id='addCnt" + idVal + "'></div>"; + var variableBox = ""; + var valBox = "<input id='valbox" + idVal + "' type='text' style='width:500px;height:30px;' value=''>"; + if(arrObj[i] != undefined && arrObj[i].length <150){ + //v += "<div style='width:1150px;background:aliceblue;border-color:aliceblue' class='valueBoxDiv' id='valueBoxDiv" + idVal + "'>" + "<input style='width:1125px;background:rgb(223, 191, 191);color:rgb(32, 45, 87);' type='text' readonly='1' id='a" + idVal + "' onclick='selectText(\"" + idVal+"\",\"" + key + "\")' value='" +arrObj[i] + "' title='" + arrObj[i] + "' >" ; + v += "<div style='width:1150px;background:aliceblue;border-color:aliceblue' class='valueBoxDiv' id='valueBoxDiv" + idVal + "'>" + "<input style='width:1125px;background:aliceblue;color:rgb(32, 45, 87);' type='text' readonly='1' id='a" + idVal + "' onclick='selectText(\"" + idVal+"\",\"" + key + "\")' value='" +arrObj[i] + "' title='" + arrObj[i] + "' >" ; + variableBox = "<input style='width:1125px' id='variableBox" + idVal + "' type='text' value='`$" + arrObj[i] + "`'>"; + }else{ + v+= "<div style='width:1150px;background:aliceblue;border-color:aliceblue' class='valueBoxDiv' id='valueBoxDiv" + idVal + "'>" + "<textarea style='width:1125px;background:aliceblue;color:rgb(32, 45, 87);' readonly='1' id='a" + idVal + "' onclick='selectText(\"" + idVal+"\",\"" + key + "\")' title='" + arrObj[i] + "' >" + arrObj[i] + "</textarea>"; + variableBox = "<textarea style='width:1125px' id='variableBox" + idVal + "' >`$" + arrObj[i] + "`'</textarea>"; + } + v += "<div id='valAddDiv" + idVal + "' style='display:none;'>" + valBox + " " + addBtn + "</div>" + + "<div id='variableBoxDiv" + idVal + "' style='display:none;color:rgb(32, 45, 87);'>Display as a variable<br>" + variableBox + "</div>" + "</div>"; + cnt++; + } + htmlVal+= v + "</div>"; + } + } + } + return htmlVal; +} + +function getModuleName(){ + var activeWorkspace=RED.view.getWorkspace(); + var moduleName=""; + RED.nodes.eachNode(function(n) { + if (n.z == activeWorkspace) { + if(n.type == 'service-logic'){ + //console.log("getModuleName():<" + n.module + ">"); + moduleName=n.module; + } + } + }); + return moduleName; +} +var global_added_obj={}; +var displayingRpcs = false; +function showRpcsValuesBox(editor,valuesObj){ + displayingRpcs = true; + showValuesBox(editor,valuesObj); +} + +function showValuesBox(editor,valuesObj){ + var moduleName = getModuleName(); + var obj = valuesObj[moduleName]; + //console.dir(valuesObj); + //console.dir(obj); + var moduleObj ={}; + if(obj == undefined){ + moduleObj[moduleName] = ["No SLI values setup for this module " + moduleName + ".Upload the yang file for this module or if already uploaded ,load it from the Available Modules from the Menu."]; + }else{ + moduleObj[moduleName] = obj; + } + showValuesBoxForModule(editor,moduleObj,moduleName); +} + +function showValuesBoxForModule(editor,valuesObj,moduleName){ + global_editor=editor; + g_currValuesObj = valuesObj; + //console.log(editor.getText()); + //populate the valid SLI values + var valuesHtml="<style>.color-dialog {background:aliceblue;border-color:lightgrey;border-width:3px;border-style:solid; }</style><div style='float:left;width:1200px;background:aliceblue'><input style='width:1125px' id='filter-id' type='text' value='' placeholder='To filter the values type words seperated by space in this box' onkeyup='filterValues(this.value)'></div><div style='float:left;color:green;font-size:0.8em' id='matchedCntId'></div><div style='clear:both'></div><div id='sli-values-div' style='width:1200px;'>" ; + valuesHtml+=buildValuesHtml(valuesObj); + valuesHtml+="</div>"; + global_added_obj={}; + + + var title = "SLI Values for Module " + moduleName; + if(displayingRpcs){ + title = "RPCs for Module " + moduleName; + } + $('#sli-values-dialog').dialog({ + modal: false, + title: title, + width: 1200, + height: 500, + dialogClass: 'color-dialog', + open: function () { + $("#sli-values-dialog").dialog("widget").find(".ui-dialog-buttonpane").css({'background': 'aliceblue'}); + $(this).html(valuesHtml); + }, + buttons: { + Close: function () { + displayingRpcs = false; + //$(this).dialog("close"); + $(this).dialog("destroy"); + } + }, + close: function(ev,ui){ + displayingRpcs = false; + $(this).dialog("destroy"); + } + }); // end dialog div +} + +function showCommentsBox(){ + var comments = $("#node-input-comments").val(); + var commentsBoxHtml="<div><textarea style='font-size:18px;height:150px;width:390px;' id='taCommentId'>" + comments + "</textarea></div>" ; + + var nodeName=$("#node-input-name").val(); + $('#comments-dialog').dialog({ + modal: true, + title: "Add comments for Node " + nodeName, + width: 450, + height: 300, + /* + open: function () { + $(this).html(commentsBoxHtml); + }, + */ + buttons: { + "Save Comments": function () { + var v=$("#taCommentId").val(); + if(v != null){ + v = v.trim(); + if(v != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + }else{ + $("#node-input-btnComments").html("<b>Add Comments</b>"); + } + } + //console.log("value from text area" + v); + $("#node-input-comments").val(v); + $(this).dialog("close"); + //$(this).dialog("destroy"); + }, + Cancel: function () { + var v=$("#taCommentId").val(); + if(v != null){ + v = v.trim(); + if(v != ''){ + $("#node-input-btnComments").html("<span style='color:blue;'><b>View Comments</b></span>"); + }else{ + $("#node-input-btnComments").html("<b>Add Comments</b>"); + } + } + $(this).dialog("close"); + //$(this).dialog("destroy"); + } + }, + close: function(ev,ui){ + //console.log("closing.."); + $(this).dialog("destroy"); + } + }).html(commentsBoxHtml); + + //console.log("done"); +/* + function functionDialogResize(ev,ui) { + console.log("ui.size.height:" + ui.size.height); + $(this).css("height",(ui.size.height-275)+"px"); + }; + + $( this ).on("dialogresize", functionDialogResize); + + + $( this ).one("dialogopen", function(ev) { + var size = $( "#sliValDiv" ).dialog('option','sizeCache-function'); + if (size) { + functionDialogResize(null,{size:size}); + } + }); +*/ + +} + +function selectText(objId,groupVal){ + //console.log(objId + groupVal); + //console.log(objId + groupVal); + $(document).ready(function(){ + //console.log("doc ready"); + //console.dir($('#valAddDiv' + objId)); + if ($('#valAddDiv' + objId).is(":visible")) { + $("#variableBoxDiv" + objId ).hide("slow"); + //$("#a" + objId ).css({"background": "rgb(223, 191, 191)", + // "color": "rgb(32, 45, 87)"}); + $("#a" + objId ).css({"background": "aliceblue", + "color": "rgb(32, 45, 87)"}); + /*"color": "rgb(32, 45, 87)"});*/ + $("#valAddDiv" + objId ).hide("slow"); + $("#valueBoxDiv" +objId).css({"border-color": "aliceblue", + "border-width":"1px", + "background-color":"aliceblue", + "border-style":"solid"}); + //$("#valAddDiv" + objId ).fadeOut("slow"); + } else{ + $("#variableBoxDiv" + objId ).show("slow"); + $("#valAddDiv" + objId).show("slow"); + /*$("#valueBoxDiv" +objId).css({"border-color": "rgb(75, 111, 147)", + "border-width":"5px", + "background-color": "rgb(223, 191, 191)", + "border-style":"solid", + "border-bottom": "5px solid rgb(75, 111, 147)"}); + */ + $("#valueBoxDiv" +objId).css({"border-color": "rgb(75, 111, 147)", + "border-width":"3px", + "background-color": "aliceblue", + "border-style":"solid", + "border-bottom": "3px solid rgb(75, 111, 147)"}); + /*$("#a" + objId ).css({"background": "rgb(223, 191, 191)", + "color": "rgb(75, 111, 147)"}); + */ + $("#a" + objId ).css({"background": "aliceblue", + "color": "rgb(75, 111, 147)"}); + } + $("#a" + objId).select(); + }); + //console.log("group-heading" + objId); +// var obj= document.getElementById("group-heading" + objId); +// obj.innerText = groupVal; +// obj.style.color = "blue"; +// console.dir(obj); +} + +function hidePrevGroup(objId){ +// console.log("mouseout" ); +// var obj= document.getElementById("group-heading" + objId); +// obj.innerText = ""; +} +/* +function fixDiv() { + var $cache = $('#getFixed'); + if ($(window).scrollTop() > 100) + $cache.css({ + 'position': 'fixed', + 'top': '10px' + }); + else + $cache.css({ + 'position': 'relative', + 'top': 'auto' + }); + } + +$(window).scroll(fixDiv); + +function isScrolledIntoView(elem) +{ + var $elem = $(elem); + var $window = $(window); + + var docViewTop = $window.scrollTop(); + var docViewBottom = docViewTop + $window.height(); + + var elemTop = $elem.offset().top; + var elemBottom = elemTop + $elem.height(); + + return ((elemBottom <= docViewBottom) && (elemTop >= docViewTop)); +} +*/ + +function getCommits(filePath){ +var urlPath="/getCommitsInfo"; +$.get(urlPath,{"filePath" : filePath }) + .done(function( data ) { + if(data != undefined && data != null){ + //console.log(data.stdout); + var jsonObj = JSON.parse(data.stdout); + var codeCloudFilesHtmlStr = $( "#codecloud-browser-dialog" ).html(); + var htmlStr = getCCFileHtmlStr(filePath,jsonObj,codeCloudFilesHtmlStr); + $( "#codecloud-browser-dialog" ).html(htmlStr); + /* + for(var i=0;i<jsonObj.length;i++){ + console.log("commit:" + jsonObj[i].commit); + console.log("date:" + jsonObj[i].date); + console.log("author:" + jsonObj[i].author); + console.log("comment:" + jsonObj[i].comment); + } + */ + } + }) + .fail(function(err) { + }) + .always(function() { + }); +} + + +function getCCFileHtmlStr(filePath,rows,codeCloudFilesHtmlStr){ + var styleStr = "<style> " + + "table#cct01 { width:100%; } \n" + + "table#cct01 th,table#cct01 td { border: 1px solid black; border-collapse: collapse; } \n" + + "table#cct01 th,table#cct01 td { padding: 5px; text-align: left; } \n" + + "table#cct01 tr:nth-child(even) { background-color: #eee; }\n" + + "table#cct01 tr:nth-child(odd) { background-color:#fff; }\n" + + "table#cct01 th { background-color: #65a9d7; color: white; }\n" + + "table#cct01 a { color: #337ab7; }\n" + + "table#cct01 a:link { color: #65a9d7; }\n" + + "table#cct01 a:visited { color: #636; }\n" + + "table#cct01 a:hover { color: #3366CC; cursor: pointer }\n" + + "table#cct01 a:active { color: #65a9d7 }\n" + + "table#cct01 caption { display: table-caption; text-align: center; background: #eee; font-weight: bold; font-size: 1.1em; border: 1px solid black; }\n" + + "</style>"; + var htmlStr=""; + //console.dir(rows); + if(rows != null && rows.length >0){ + var alertDialog = '<div id="ccAlertdialog"></div>'; + htmlStr= alertDialog + "<div style='width:1050;height:650'>" + styleStr; + htmlStr += "<table id='cct01' >"; + htmlStr += "<caption id='ccCaptionId'>" + filePath + "</caption>"; + htmlStr += "<tr>"; + htmlStr += "<th>Commit ID</th>" ; + htmlStr += "<th>Date</th>" ; + htmlStr += "<th>Author</th>" ; + htmlStr += "<th>Comment</th>" ; + htmlStr += "</tr>"; + if(rows != null && rows.length == 0){ + htmlStr += "<tr>"; + htmlStr += "<td><b>No rows found</b></td>"; + htmlStr += "</tr></table></div>"; + return htmlStr; + } + for(var i=0;i<rows.length;i++){ + var row = rows[i]; + var _commitId = row.commit; + var dt = row.date; + var author = row.author; + var comment = row.comment; + htmlStr += "<tr>"; + htmlStr += "<td><a onclick=\"javascript:importCCFlow('" + _commitId + "','" + filePath + "')\">" + _commitId + "</a></td>"; + htmlStr += "<td>" + dt + "</td>"; + htmlStr += "<td>" + author + "</td>"; + htmlStr += "<td>" + comment + "</td>"; + htmlStr += "</tr>"; + } + htmlStr += "</table>"; + htmlStr += "</div>"; + } + //console.log(htmlStr); + return htmlStr; +} + + +var gitLocalFlowFiles=[]; +function filterGitLocalFlows(filterVal){ + + var matchedCnt =0; + var valuesObj = gitLocalFlowFiles; + //console.dir(codeCloudFlowFiles); + var updatedValuesObj =[]; + var searchValues =[]; + if(filterVal != null && filterVal != undefined){ + filterVal=filterVal.trim(); + } + searchValues = filterVal.split(/ /); + //console.log("filterVal:" + filterVal); + //console.dir(searchValues); + if(searchValues != null && searchValues != undefined){ + var foundCount = 0; + for(var k=0;k<searchValues.length;k++){ + if(foundCount >0){ + valuesObj=updatedValuesObj; + } + updatedValuesObj=[]; + for(var i=0;i<valuesObj.length;i++){ + var patt = new RegExp(searchValues[k],"gi"); + if(patt.test(valuesObj[i])){ + foundCount++; + updatedValuesObj.push(valuesObj[i]); + } + } + } + }else{ + updatedValuesObj = valuesObj; + } + //console.dir(updatedValuesObj); + var html="<ul>"; + if(updatedValuesObj != null){ + var files=updatedValuesObj; + //console.dir(files); + files.sort(function (a,b){ + if(a > b){ + return 1; + }else if(a < b){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;files != null && i<files.length;i++){ + html+="<li><a href=\"#\" onclick=\"importGitLocalFlow('" + files[i] + "')\">" + files[i] + "</a></li>"; + } + } + html+="</ul>"; + html+="</div>"; + $( "#gitlocal-data-container" ).html(html); +} + +var codeCloudFlowFiles=[]; +function filterFlows(filterVal){ + + var matchedCnt =0; + var valuesObj = codeCloudFlowFiles; + //console.dir(codeCloudFlowFiles); + var updatedValuesObj =[]; + var searchValues =[]; + if(filterVal != null && filterVal != undefined){ + filterVal=filterVal.trim(); + } + searchValues = filterVal.split(/ /); + //console.log("filterVal:" + filterVal); + //console.dir(searchValues); + if(searchValues != null && searchValues != undefined){ + var foundCount = 0; + for(var k=0;k<searchValues.length;k++){ + for(var i=0;i<valuesObj.length;i++){ + var patt = new RegExp(searchValues[k],"gi"); + if(patt.test(valuesObj[i])){ + foundCount++; + updatedValuesObj.push(valuesObj[i]); + } + } + } + }else{ + updatedValuesObj = valuesObj; + } + //console.dir(updatedValuesObj); + var html="<ul>"; + if(updatedValuesObj != null){ + var files=updatedValuesObj; + //console.dir(files); + files.sort(function (a,b){ + if(a > b){ + return 1; + }else if(a < b){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;files != null && i<files.length;i++){ + html+="<li><a href=\"#\" onclick=\"getCommits('" + files[i] + "')\">" + files[i] + "</a></li>"; + } + } + html+="</ul>"; + html+="</div>"; + $( "#codecloud-data-container" ).html(html); +} + +var yangFilesList=[]; +/* +function filterYangFiles(filterVal){ + + var matchedCnt =0; + var valuesObj = yangFilesList; + var updatedValuesObj =[]; + var searchValues =[]; + if(filterVal != null && filterVal != undefined){ + filterVal=filterVal.trim(); + } + searchValues = filterVal.split(/ /); + if(searchValues != null && searchValues != undefined){ + var foundCount = 0; + for(var k=0;k<searchValues.length;k++){ + for(var i=0;i<valuesObj.length;i++){ + var patt = new RegExp(searchValues[k],"gi"); + if(patt.test(valuesObj[i])){ + foundCount++; + updatedValuesObj.push(valuesObj[i]); + } + } + } + }else{ + updatedValuesObj = valuesObj; + } + //console.dir(updatedValuesObj); + var html="<ul>"; + if(updatedValuesObj != null){ + var files=updatedValuesObj; + //console.dir(files); + files.sort(function (a,b){ + if(a > b){ + return 1; + }else if(a < b){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;files != null && i<files.length;i++){ + html+="<li><a href=\"#\" onclick=\"getYangFile('" + files[i] + "')\">" + files[i] + "</a></li>"; + } + } + html+="</ul>"; + html+="</div>"; + $( "#list-yang-data-container" ).html(html); +} +*/ + +function filterYangFiles(filterVal){ + var matchedCnt =0; + var valuesObj = yangFilesList; + var updatedValuesObj =[]; + var searchValues =[]; + if(filterVal != null && filterVal != undefined){ + filterVal=filterVal.trim(); + } + searchValues = filterVal.split(/ /); + if(searchValues != null && searchValues != undefined){ + var foundCount = 0; + for(var k=0;k<searchValues.length;k++){ + for(var i=0;i<valuesObj.length;i++){ + var patt = new RegExp(searchValues[k],"gi"); + if(patt.test(valuesObj[i])){ + foundCount++; + updatedValuesObj.push(valuesObj[i]); + } + } + } + }else{ + updatedValuesObj = valuesObj; + } + //console.dir(updatedValuesObj); + var html="<table id='yang-file-list-table' border=1>"; + html+="<tr>"; + html+="<th>File</th>"; + html+="<th>Delete</th>"; + html+="</tr>"; + + if(updatedValuesObj != null){ + var files=updatedValuesObj; + //console.dir(files); + files.sort(function (a,b){ + if(a > b){ + return 1; + }else if(a < b){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;files != null && i<files.length;i++){ + html+="<tr><td><a href=\"#\" onclick=\"getYangFile('" + files[i] + "')\">" + files[i] + "</a></td><td>" + "<input type='button' onclick='deleteYangFile(\"" + files[i] + "\")' value='Delete'></td></td></td></tr>"; + } + } + html+="</table>"; + html+="</div>"; + + $( "#yang-files-data-container" ).html(html); +} + +function getYangFile(fileName){ + $("#dwnldYangFormId").remove(); + //using form to submit + var form = $('<form id="dwnldYangFormId" method="POST" action="/downloadYang"></form>'); + form.append('<input type="hidden" name="fileName" value="' + fileName + '"/>'); + form.appendTo('body'); + $("#dwnldYangFormId").submit(); + +} +function deleteYangFile(fileName){ + var reqData= {"fileName":fileName}; + $.post( "/deleteYangFile",reqData ) + .done(function( data ) { + }) + .fail(function(err) { + console.log( "error" + err ); + }) + .always(function() { + $("#list-yang-browser-dialog").dialog("close"); + $("#btn-list-yang-files").trigger("click"); + }); +} + +function importCCFlow(commitId,filePath){ +var urlPath="/importCodeCloudFlow"; +$.get(urlPath,{"commitId" : commitId,"filePath" : filePath }) + .done(function( data ) { + if(data != undefined && data != null){ + //console.log(data.stdout); + var jsonObj = JSON.parse(data.stdout); + $( "#codecloud-browser-dialog" ).dialog("close"); + RED.view.importNodes(JSON.stringify(jsonObj)); + } + }) + .fail(function(err) { + RED.notify("Could not import flow from code cloud."); + $( "#codecloud-browser-dialog").dialog("close"); + console.log( "error occured importing flow."); + }) + .always(function() { + }); +} + +function importGitLocalFlow(filePath){ +var urlPath="/importGitLocalFlow"; +$.get(urlPath,{"filePath" : filePath }) + .done(function( data ) { + if(data != undefined && data != null){ + //console.log(data.stdout); + var jsonObj; + try{ + jsonObj = JSON.parse(data.stdout); + $( "#gitlocal-browser-dialog" ).dialog("close"); + RED.view.importNodes(JSON.stringify(jsonObj)); + }catch(err){ + RED.notify("Could not import flow from Local Git Repository."); + $( "#gitlocal-browser-dialog").dialog("close"); + console.log( "error occured importing flow." + err); + } + }else{ + RED.notify("Could not import flow from Local Git Repository."); + $( "#gitlocal-browser-dialog").dialog("close"); + console.log( "error occured importing flow." + err); + } + }) + .fail(function(err) { + RED.notify("Could not import flow from Local Git Repository."); + $( "#gitlocal-browser-dialog").dialog("close"); + console.log( "error occured importing flow."); + }) + .always(function() { + }); +} + +var availableYangModules=[]; +function filterYangModules(filterVal){ + + var matchedCnt =0; + var valuesObj = availableYangModules ; + //console.dir(codeCloudFlowFiles); + var updatedValuesObj =[]; + var searchValues =[]; + if(filterVal != null && filterVal != undefined){ + filterVal=filterVal.trim(); + } + searchValues = filterVal.split(/ /); + //console.log("filterVal:" + filterVal); + //console.dir(searchValues); + if(searchValues != null && searchValues != undefined){ + var foundCount = 0; + for(var k=0;k<searchValues.length;k++){ + if(foundCount >0){ + valuesObj=updatedValuesObj; + } + updatedValuesObj=[]; + for(var i=0;i<valuesObj.length;i++){ + var patt = new RegExp(searchValues[k],"gi"); + if(patt.test(valuesObj[i])){ + foundCount++; + updatedValuesObj.push(valuesObj[i]); + } + } + } + }else{ + updatedValuesObj = valuesObj; + } + //console.dir(updatedValuesObj); + var html=""; + html+="<table border=1>"; + html+="<tr>"; + html+="<th>#</th>"; + html+="<th>Load</th>"; + html+="<th>Module</th>"; + html+="</tr>"; + + if(updatedValuesObj != null){ + var files=updatedValuesObj; + //console.dir(files); + files.sort(function (a,b){ + if(a > b){ + return 1; + }else if(a < b){ + return -1; + }else{ + return 0; + } + }); + var count=1; + for(var i=0;files != null && i<files.length;i++){ + var val = files[i].replace(/:.*/,""); + if(files[i].indexOf(":checked") != -1){ + html+="<tr><td>" + count + "</td><td><input type='checkbox' checked value='" + val + "'></td><td>" + val + "</td></tr>"; + }else{ + html+="<tr><td>" + count + "</td><td><input type='checkbox' value='" + val + "'></td><td>" + val + "</td></tr>"; + } + count++; + } + } + html+="</table>"; + html+="</div>"; + $( "#yang-modules-data-container" ).html(html); +} diff --git a/dgbuilder/public/util/js/validateNodeXml.js b/dgbuilder/public/util/js/validateNodeXml.js new file mode 100644 index 00000000..2291d865 --- /dev/null +++ b/dgbuilder/public/util/js/validateNodeXml.js @@ -0,0 +1,325 @@ +function resetStatus(){ + showMsg("","green"); +} + +function showMsg(msg,color){ + $("#node-validate-result").html(msg); + $("#node-validate-result") + .css('color', '') + .css('color', color); +} + +function getAttributeValue(xmlStr,attribute){ + + var attrVal=null; + try{ + if(xmlStr != null){ + var myRe = new RegExp(attribute + "[\s+]?=[\s+]?['\"]([^'\"]+)['\"]","m"); + var myArray = myRe.exec(xmlStr); + if(myArray != null && myArray[1] != null){ + attrVal=myArray[1]; + } + } + }catch(err){ + console.log(err); + } + return attrVal; +} + + +var resp = true; +var processedNode = ""; +var errList=[]; +var elementCount=0; +function processNode(xmlNode){ + if(xmlNode == null) return; + if(xmlNode.nodeName != "parsererror" && xmlNode.nodeName != "#text"){ + processedNode = xmlNode.nodeName; + } + //console.log("processedNode:" + processedNode); + switch(xmlNode.nodeType){ + case 1: + elementCount++; + //ELEMENT_NODE + //console.log(xmlNode.nodeName); + //console.dir(xmlNode.nodeName); + if(xmlNode.nodeName == "parsererror"){ + //var nearNode = xmlNode.previousSibling != null ?xmlNode.previousSibling.nodeName : xmlNode.parentNode.nodeName; + console.log("Error parsing xml after node " + processedNode); + var msg = "error parsing XML after element <" + processedNode + "> Element#" + elementCount; + errList.push(msg); + resp = false; + return; + } + processedNode = xmlNode.nodeName; + var attrs = xmlNode.attributes; + for(var i=0;i<attrs.length;i++){ + //console.log("Attribute:" + attrs[i].nodeName); + //console.log("Value:" + attrs[i].value); + if(attrs[i].nodeName != "value" && attrs[i].value == ""){ + var msg=""; + /* + var prevSibling = xmlNode.previousSibling; + if(prevSibling != null && prevSibling != undefined){ + msg = "element <" + xmlNode.nodeName + "> attribute '" + attrs[i].nodeName + "' is not set. Element#" + elementCount; + }else{ + msg = "element <" + xmlNode.nodeName + "> attribute '" + attrs[i].nodeName + "' is not set. Element#" + elementCount; + } + */ + msg = "element <" + xmlNode.nodeName + "> attribute '" + attrs[i].nodeName + "' is not set. Element#" + elementCount; + errList.push(msg); + //console.log("element <" + xmlNode.nodeName + "> attribute '" + attrs[i].nodeName + "' is not set.Element#" + elementCount); + resp = false; + } + } + var childNodes = xmlNode.childNodes; + for(var k=0;k<childNodes.length;k++){ + processNode(childNodes[k]); + } + break; + case 2: + //ATTRIBUTE_NODE + //console.log(xmlNode.nodeName); + break; + case 3: + //TEXT_NODE + //console.log(xmlNode.nodeValue); + break; + case 4: + //CDATA_SECTION_NODE + console.log("CDATA_SECTION_NODE"); + break; + case 5: + //ENTITY_REFERENCE_NODE + console.log("ENTITY_REFERENCE_NODE"); + break; + case 6: + //ENTITY_NODE + console.log("ENTITY_NODE"); + break; + case 7: + //PROCESSING_INSTRUCTION_NODE + console.log("PROCESSING_INSTRUCTION_NODE"); + break; + case 8: + //COMMENT_NODE + console.log("COMMENT_NODE"); + break; + case 9: + //DOCUMENT_NODE + console.log("DOCUMENT_NODE"); + break; + case 10: + //DOCUMENT_TYPE_NODE + console.log("DOCUMENT_TYPE_NODE"); + break; + case 11: + //DOCUMENT_TYPE_NODE + console.log("DOCUMENT_FRAGMENT_NODE"); + break; + case 12: + //NOTATION_NODE + console.log("DOCUMENT_FRAGMENT_NODE"); + break; + } +} + +function validateFinalXML(xmlStr){ + + //console.dir(RED); + processedNode=""; + resp=true; + errList=[]; + elementCount=0; + //console.log("In validateXML xmlStr:" + xmlStr); + if(xmlStr == null || xmlStr == "") return true; + xmlStr = xmlStr.trim(); + try{ + var xmlDoc; + if (window.DOMParser){ + try{ + var parser=new DOMParser(); + xmlDoc=parser.parseFromString(xmlStr,'text/xml'); + //console.log("Not IE"); + var n = xmlDoc.documentElement.nodeName; + if(n == "html"){ + resp=false; + console.log("Error parsing"); + return resp; + } + }catch(e){ + console.log("Error parsing" +e); + return false; + } + }else{ + try{ + //console.log("IE"); + // code for IE + xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async=false; + xmlDoc.loadXMLString(xmlStr); + }catch(e){ + console.log("Error parsing" +e); + return false; + } + } + + //console.dir(xmlDoc); + processNode(xmlDoc.documentElement); + + if(resp){ + console.log("Validation Successful"); + RED.notify("<strong>XML validation</strong>: SUCCESS","success"); + }else{ + console.log("Errors found. "); + RED.notify("<strong>XML validation</strong>: FAILED","error"); + } + }catch(e){ + console.log("error:" +e); + RED.notify("<strong>XML validation</strong>: FAILED","error"); + resp=false; + return resp; + } + return resp; +} + +function validateXML(xmlStr){ + + //console.dir(RED); + processedNode=""; + resp=true; + errList=[]; + elementCount=0; + //console.log("In validateXML xmlStr:" + xmlStr); + //var xmlStr = $("#node-input-xml-editor").text(); + if(xmlStr == null || xmlStr == undefined){ + xmlStr = $("#node-input-xml-editor").text(); + } + if(xmlStr == undefined) return false; + //console.dir($("#node-input-xml-editor")); + //console.log("xmlStr:" + xmlStr); + xmlStr = xmlStr.trim(); + var startTag ; + var endTag ; + try{ + var re = /^[0-9]+/; + xmlStr = xmlStr.replace(re,''); + var regex = /(<)([\w-]+)(.*)?/; + var match = regex.exec(xmlStr); + if(match != null){ + if(match[1] != undefined && match[2] != undefined){ + startTag = match[2]; + } + }else{ + resp=false; + showMsg("startTag not found.","red"); + return resp; + } + }catch(e){ + console.log(e); + return false; + } + //console.log(xmlStr); + if(xmlStr == ""){ + resp=false; + showMsg("XML not found","red"); + return resp; + } + endTag = "</" + startTag + ">"; + + if(xmlStr.indexOf(endTag) != -1){ + resp=false; + showMsg("Error: End tag </" + startTag + "> must not be included.","red"); + console.log("End tag " + endTag + " must not be included."); + return resp; + } + try{ + //var xmlTopStr = "<?xml version='1.0' encoding='UTF-8'?>\n" ; + //xmlStr = xmlTopStr + xmlStr; + //xmlStr = xmlStr.replace(/'/g,"\""); + xmlStr+= "\n" + endTag; + xmlStr = xmlStr.trim(); + //console.log("xmlStr:" + xmlStr); + var xmlDoc; + if (window.DOMParser){ + try{ + var parser=new DOMParser(); + xmlDoc=parser.parseFromString(xmlStr,'text/xml'); + //console.log("Not IE"); + var n = xmlDoc.documentElement.nodeName; + if(n == "html"){ + resp=false; + showMsg("Error parsing","red"); + console.log("Error parsing"); + return resp; + } + }catch(e){ + console.log("Error parsing" +e); + return false; + } + }else{ + try{ + //console.log("IE"); + // code for IE + xmlDoc=new ActiveXObject("Microsoft.XMLDOM"); + xmlDoc.async=false; + xmlDoc.loadXMLString(xmlStr); + }catch(e){ + console.log("Error parsing" +e); + return false; + } + } + + //console.dir(xmlDoc); + processNode(xmlDoc.documentElement); + if(resp){ + showMsg("Validation Successful","green"); + }else{ + showMsg("Errors found. <a onclick='javascript:showErrors()'>show errors</a>","red"); + console.log("Errors found. "); + } + }catch(e){ + console.log("error:" +e); + showMsg(e,"red"); + resp=false; + return resp; + } + return resp; +} + +function showErrors() { + //var sourceField = event != null ?event.srcElement:event.target; + //console.dir(sourceField); + //sourceField.style.backgroundColor="skyblue"; + //var leftVal = event.target.offsetLeft ; + //alert(topVal + ":" + leftVal); + /*left:leftVal,*/ + //var pos = event.target; + //var topVal = event.target.offsetTop + topPosition ; + //var topVal = event.target.offsetTop +75; + var htmlStr="<div id='error-list-div'><table id='errTable' border='1'><tr><th>Error List</th></tr>"; + for(var i=0;errList != null && i<errList.length;i++){ + var errSeq = i+1; + htmlStr += "<tr><td>" + errSeq + ")" + errList[i] + "</td></tr>"; + } + htmlStr += "</table></div>"; + //var prevHtml = $("#tab-info").html(); + //htmlStr += "<input type='button' value='Hide Errors' onclick=\"closeShowErrors('" + prevHtml + "')\" >"; + //$('#show-errors-div').html(htmlStr); + //$("#tab-info").html(prevHtml + htmlStr); + + //$('<div></div>').dialog({ + $('#show-errors-dialog').dialog({ + modal: true, + title: "XML Error List ", + width: 500, + open: function () { + $(this).html(htmlStr); + }, + buttons: { + Close: function () { + $(this).dialog("close"); + } + } + }); // end dialog div +} diff --git a/dgbuilder/public/util/js/vkbeautify.0.99.00.beta.js b/dgbuilder/public/util/js/vkbeautify.0.99.00.beta.js new file mode 100644 index 00000000..13cee3a5 --- /dev/null +++ b/dgbuilder/public/util/js/vkbeautify.0.99.00.beta.js @@ -0,0 +1,358 @@ +/** +* vkBeautify - javascript plugin to pretty-print or minify text in XML, JSON, CSS and SQL formats. +* +* Version - 0.99.00.beta +* Copyright (c) 2012 Vadim Kiryukhin +* vkiryukhin @ gmail.com +* http://www.eslinstructor.net/vkbeautify/ +* +* Dual licensed under the MIT and GPL licenses: +* http://www.opensource.org/licenses/mit-license.php +* http://www.gnu.org/licenses/gpl.html +* +* Pretty print +* +* vkbeautify.xml(text [,indent_pattern]); +* vkbeautify.json(text [,indent_pattern]); +* vkbeautify.css(text [,indent_pattern]); +* vkbeautify.sql(text [,indent_pattern]); +* +* @text - String; text to beatufy; +* @indent_pattern - Integer | String; +* Integer: number of white spaces; +* String: character string to visualize indentation ( can also be a set of white spaces ) +* Minify +* +* vkbeautify.xmlmin(text [,preserve_comments]); +* vkbeautify.jsonmin(text); +* vkbeautify.cssmin(text [,preserve_comments]); +* vkbeautify.sqlmin(text); +* +* @text - String; text to minify; +* @preserve_comments - Bool; [optional]; +* Set this flag to true to prevent removing comments from @text ( minxml and mincss functions only. ) +* +* Examples: +* vkbeautify.xml(text); // pretty print XML +* vkbeautify.json(text, 4 ); // pretty print JSON +* vkbeautify.css(text, '. . . .'); // pretty print CSS +* vkbeautify.sql(text, '----'); // pretty print SQL +* +* vkbeautify.xmlmin(text, true);// minify XML, preserve comments +* vkbeautify.jsonmin(text);// minify JSON +* vkbeautify.cssmin(text);// minify CSS, remove comments ( default ) +* vkbeautify.sqlmin(text);// minify SQL +* +*/ + +(function() { + +function createShiftArr(step) { + + var space = ' '; + + if ( isNaN(parseInt(step)) ) { // argument is string + space = step; + } else { // argument is integer + switch(step) { + case 1: space = ' '; break; + case 2: space = ' '; break; + case 3: space = ' '; break; + case 4: space = ' '; break; + case 5: space = ' '; break; + case 6: space = ' '; break; + case 7: space = ' '; break; + case 8: space = ' '; break; + case 9: space = ' '; break; + case 10: space = ' '; break; + case 11: space = ' '; break; + case 12: space = ' '; break; + } + } + + var shift = ['\n']; // array of shifts + for(ix=0;ix<100;ix++){ + shift.push(shift[ix]+space); + } + return shift; +} + +function vkbeautify(){ + this.step = ' '; // 4 spaces + this.shift = createShiftArr(this.step); +}; + +vkbeautify.prototype.xml = function(text,step) { + + var ar = text.replace(/>\s{0,}</g,"><") + .replace(/</g,"~::~<") + .replace(/\s*xmlns\:/g,"~::~xmlns:") + .replace(/\s*xmlns\=/g,"~::~xmlns=") + .split('~::~'), + len = ar.length, + inComment = false, + deep = 0, + str = '', + ix = 0, + shift = step ? createShiftArr(step) : this.shift; + + for(ix=0;ix<len;ix++) { + // start comment or <![CDATA[...]]> or <!DOCTYPE // + if(ar[ix].search(/<!/) > -1) { + str += shift[deep]+ar[ix]; + inComment = true; + // end comment or <![CDATA[...]]> // + if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1 || ar[ix].search(/!DOCTYPE/) > -1 ) { + inComment = false; + } + } else + // end comment or <![CDATA[...]]> // + if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1) { + str += ar[ix]; + inComment = false; + } else + // <elm></elm> // + if( /^<\w/.exec(ar[ix-1]) && /^<\/\w/.exec(ar[ix]) && + /^<[\w:\-\.\,]+/.exec(ar[ix-1]) == /^<\/[\w:\-\.\,]+/.exec(ar[ix])[0].replace('/','')) { + str += ar[ix]; + if(!inComment) deep--; + } else + // <elm> // + if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) == -1 && ar[ix].search(/\/>/) == -1 ) { + str = !inComment ? str += shift[deep++]+ar[ix] : str += ar[ix]; + } else + // <elm>...</elm> // + if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) > -1) { + str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix]; + } else + // </elm> // + if(ar[ix].search(/<\//) > -1) { + str = !inComment ? str += shift[--deep]+ar[ix] : str += ar[ix]; + } else + // <elm/> // + if(ar[ix].search(/\/>/) > -1 ) { + str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix]; + } else + // <? xml ... ?> // + if(ar[ix].search(/<\?/) > -1) { + str += shift[deep]+ar[ix]; + } else + // xmlns // + if( ar[ix].search(/xmlns\:/) > -1 || ar[ix].search(/xmlns\=/) > -1) { + str += shift[deep]+ar[ix]; + } + + else { + str += ar[ix]; + } + } + + return (str[0] == '\n') ? str.slice(1) : str; +} + +vkbeautify.prototype.json = function(text,step) { + + var step = step ? step : this.step; + + if (typeof JSON === 'undefined' ) return text; + + if ( typeof text === "string" ) return JSON.stringify(JSON.parse(text), null, step); + if ( typeof text === "object" ) return JSON.stringify(text, null, step); + + return text; // text is not string nor object +} + +vkbeautify.prototype.css = function(text, step) { + + var ar = text.replace(/\s{1,}/g,' ') + .replace(/\{/g,"{~::~") + .replace(/\}/g,"~::~}~::~") + .replace(/\;/g,";~::~") + .replace(/\/\*/g,"~::~/*") + .replace(/\*\//g,"*/~::~") + .replace(/~::~\s{0,}~::~/g,"~::~") + .split('~::~'), + len = ar.length, + deep = 0, + str = '', + ix = 0, + shift = step ? createShiftArr(step) : this.shift; + + for(ix=0;ix<len;ix++) { + + if( /\{/.exec(ar[ix])) { + str += shift[deep++]+ar[ix]; + } else + if( /\}/.exec(ar[ix])) { + str += shift[--deep]+ar[ix]; + } else + if( /\*\\/.exec(ar[ix])) { + str += shift[deep]+ar[ix]; + } + else { + str += shift[deep]+ar[ix]; + } + } + return str.replace(/^\n{1,}/,''); +} + +//---------------------------------------------------------------------------- + +function isSubquery(str, parenthesisLevel) { + return parenthesisLevel - (str.replace(/\(/g,'').length - str.replace(/\)/g,'').length ) +} + +function split_sql(str, tab) { + + return str.replace(/\s{1,}/g," ") + + .replace(/ AND /ig,"~::~"+tab+tab+"AND ") + .replace(/ BETWEEN /ig,"~::~"+tab+"BETWEEN ") + .replace(/ CASE /ig,"~::~"+tab+"CASE ") + .replace(/ ELSE /ig,"~::~"+tab+"ELSE ") + .replace(/ END /ig,"~::~"+tab+"END ") + .replace(/ FROM /ig,"~::~FROM ") + .replace(/ GROUP\s{1,}BY/ig,"~::~GROUP BY ") + .replace(/ HAVING /ig,"~::~HAVING ") + //.replace(/ SET /ig," SET~::~") + .replace(/ IN /ig," IN ") + + .replace(/ JOIN /ig,"~::~JOIN ") + .replace(/ CROSS~::~{1,}JOIN /ig,"~::~CROSS JOIN ") + .replace(/ INNER~::~{1,}JOIN /ig,"~::~INNER JOIN ") + .replace(/ LEFT~::~{1,}JOIN /ig,"~::~LEFT JOIN ") + .replace(/ RIGHT~::~{1,}JOIN /ig,"~::~RIGHT JOIN ") + + .replace(/ ON /ig,"~::~"+tab+"ON ") + .replace(/ OR /ig,"~::~"+tab+tab+"OR ") + .replace(/ ORDER\s{1,}BY/ig,"~::~ORDER BY ") + .replace(/ OVER /ig,"~::~"+tab+"OVER ") + + .replace(/\(\s{0,}SELECT /ig,"~::~(SELECT ") + .replace(/\)\s{0,}SELECT /ig,")~::~SELECT ") + + .replace(/ THEN /ig," THEN~::~"+tab+"") + .replace(/ UNION /ig,"~::~UNION~::~") + .replace(/ USING /ig,"~::~USING ") + .replace(/ WHEN /ig,"~::~"+tab+"WHEN ") + .replace(/ WHERE /ig,"~::~WHERE ") + .replace(/ WITH /ig,"~::~WITH ") + + //.replace(/\,\s{0,}\(/ig,",~::~( ") + //.replace(/\,/ig,",~::~"+tab+tab+"") + + .replace(/ ALL /ig," ALL ") + .replace(/ AS /ig," AS ") + .replace(/ ASC /ig," ASC ") + .replace(/ DESC /ig," DESC ") + .replace(/ DISTINCT /ig," DISTINCT ") + .replace(/ EXISTS /ig," EXISTS ") + .replace(/ NOT /ig," NOT ") + .replace(/ NULL /ig," NULL ") + .replace(/ LIKE /ig," LIKE ") + .replace(/\s{0,}SELECT /ig,"SELECT ") + .replace(/\s{0,}UPDATE /ig,"UPDATE ") + .replace(/ SET /ig," SET ") + + .replace(/~::~{1,}/g,"~::~") + .split('~::~'); +} + +vkbeautify.prototype.sql = function(text,step) { + + var ar_by_quote = text.replace(/\s{1,}/g," ") + .replace(/\'/ig,"~::~\'") + .split('~::~'), + len = ar_by_quote.length, + ar = [], + deep = 0, + tab = this.step,//+this.step, + inComment = true, + inQuote = false, + parenthesisLevel = 0, + str = '', + ix = 0, + shift = step ? createShiftArr(step) : this.shift;; + + for(ix=0;ix<len;ix++) { + if(ix%2) { + ar = ar.concat(ar_by_quote[ix]); + } else { + ar = ar.concat(split_sql(ar_by_quote[ix], tab) ); + } + } + + len = ar.length; + for(ix=0;ix<len;ix++) { + + parenthesisLevel = isSubquery(ar[ix], parenthesisLevel); + + if( /\s{0,}\s{0,}SELECT\s{0,}/.exec(ar[ix])) { + ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"") + } + + if( /\s{0,}\s{0,}SET\s{0,}/.exec(ar[ix])) { + ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"") + } + + if( /\s{0,}\(\s{0,}SELECT\s{0,}/.exec(ar[ix])) { + deep++; + str += shift[deep]+ar[ix]; + } else + if( /\'/.exec(ar[ix]) ) { + if(parenthesisLevel<1 && deep) { + deep--; + } + str += ar[ix]; + } + else { + str += shift[deep]+ar[ix]; + if(parenthesisLevel<1 && deep) { + deep--; + } + } + var junk = 0; + } + + str = str.replace(/^\n{1,}/,'').replace(/\n{1,}/g,"\n"); + return str; +} + + +vkbeautify.prototype.xmlmin = function(text, preserveComments) { + + var str = preserveComments ? text + : text.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g,"") + .replace(/[ \r\n\t]{1,}xmlns/g, ' xmlns'); + return str.replace(/>\s{0,}</g,"><"); +} + +vkbeautify.prototype.jsonmin = function(text) { + + if (typeof JSON === 'undefined' ) return text; + + return JSON.stringify(JSON.parse(text), null, 0); + +} + +vkbeautify.prototype.cssmin = function(text, preserveComments) { + + var str = preserveComments ? text + : text.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\//g,"") ; + + return str.replace(/\s{1,}/g,' ') + .replace(/\{\s{1,}/g,"{") + .replace(/\}\s{1,}/g,"}") + .replace(/\;\s{1,}/g,";") + .replace(/\/\*\s{1,}/g,"/*") + .replace(/\*\/\s{1,}/g,"*/"); +} + +vkbeautify.prototype.sqlmin = function(text) { + return text.replace(/\s{1,}/g," ").replace(/\s{1,}\(/,"(").replace(/\s{1,}\)/,")"); +} + +window.vkbeautify = new vkbeautify(); + +})(); + diff --git a/dgbuilder/red.js b/dgbuilder/red.js new file mode 100644 index 00000000..14f6d38c --- /dev/null +++ b/dgbuilder/red.js @@ -0,0 +1,224 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var http = require('http'); +var https = require('https'); +var util = require("util"); +var express = require("express"); +var crypto = require("crypto"); +var nopt = require("nopt"); +var path = require("path"); +var RED = require("./red/red.js"); + +var server; +var app = express(); + +var settingsFile = "./settings"; +var flowFile; + +var knownOpts = { + "settings":[path], + "v": Boolean, + "help": Boolean +}; +var shortHands = { + "s":["--settings"], + "?":["--help"] +}; +nopt.invalidHandler = function(k,v,t) { + // TODO: console.log(k,v,t); +} + +var parsedArgs = nopt(knownOpts,shortHands,process.argv,2) + +if (parsedArgs.help) { + console.log("Node-RED v"+RED.version()); + console.log("Usage: node red.js [-v] [-?] [--settings settings.js] [flows.json]"); + console.log(""); + console.log("Options:"); + console.log(" -s, --settings FILE use specified settings file"); + console.log(" -v enable verbose output"); + console.log(" -?, --help show usage"); + console.log(""); + console.log("Documentation can be found at http://nodered.org"); + process.exit(); +} +if (parsedArgs.argv.remain.length > 0) { + flowFile = parsedArgs.argv.remain[0]; +} + +if (parsedArgs.settings) { + settingsFile = parsedArgs.settings; +} +try { + var settings = require(settingsFile); +} catch(err) { + if (err.code == 'MODULE_NOT_FOUND') { + console.log("Unable to load settings file "+settingsFile); + } else { + console.log(err); + } + process.exit(); +} + +if (parsedArgs.v) { + settings.verbose = true; +} + +if (settings.https) { + server = https.createServer(settings.https,function(req,res){app(req,res);}); +} else { + server = http.createServer(function(req,res){app(req,res);}); +} +server.setMaxListeners(0); + +function formatRoot(root) { + if (root[0] != "/") { + root = "/" + root; + } + if (root.slice(-1) != "/") { + root = root + "/"; + } + return root; +} + +if (settings.httpRoot === false) { + settings.httpAdminRoot = false; + settings.httpNodeRoot = false; +} else { + settings.httpRoot = settings.httpRoot||"/"; + settings.disableEditor = settings.disableEditor||false; +} + +if (settings.httpAdminRoot !== false) { + settings.httpAdminRoot = formatRoot(settings.httpAdminRoot || settings.httpRoot || "/"); + settings.httpAdminAuth = settings.httpAdminAuth || settings.httpAuth; +} else { + settings.disableEditor = true; +} + +if (settings.httpNodeRoot !== false) { + settings.httpNodeRoot = formatRoot(settings.httpNodeRoot || settings.httpRoot || "/"); + settings.httpNodeAuth = settings.httpNodeAuth || settings.httpAuth; +} + +settings.uiPort = settings.uiPort||1880; +settings.uiHost = settings.uiHost||"0.0.0.0"; +var appDir = path.dirname(require.main.filename); +if (settings.flowFile != null && settings.flowFile.indexOf(appDir) != -1){ + settings.flowFile = flowFile || settings.flowFile; +}else{ + settings.flowFile = flowFile || appDir + "/" + settings.flowFile; +} + +RED.init(server,settings); + +if (settings.httpAdminRoot !== false && settings.httpAdminAuth) { + app.use(settings.httpAdminRoot, + express.basicAuth(function(user, pass) { + return user === settings.httpAdminAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAdminAuth.pass; + }) + ); +} +if (settings.httpNodeRoot !== false && settings.httpNodeAuth) { + app.use(settings.httpNodeRoot, + express.basicAuth(function(user, pass) { + return user === settings.httpNodeAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpNodeAuth.pass; + }) + ); +} +if (settings.httpAdminRoot !== false) { + app.use(settings.httpAdminRoot,RED.httpAdmin); +} +if (settings.httpNodeRoot !== false) { + app.use(settings.httpNodeRoot,RED.httpNode); +} + +if (settings.httpStatic) { + settings.httpStaticAuth = settings.httpStaticAuth || settings.httpAuth; + if (settings.httpStaticAuth) { + app.use("/", + express.basicAuth(function(user, pass) { + return user === settings.httpStaticAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpStaticAuth.pass; + }) + ); + } + app.use("/",express.static(settings.httpStatic)); +} + +function getListenPath() { + var listenPath = 'http'+(settings.https?'s':'')+'://'+ + (settings.uiHost == '0.0.0.0'?'127.0.0.1':settings.uiHost)+ + ':'+settings.uiPort; + if (settings.httpAdminRoot !== false) { + listenPath += settings.httpAdminRoot; + } else if (settings.httpStatic) { + listenPath += "/"; + } + return listenPath; +} + +RED.start().then(function() { + if (settings.httpAdminRoot !== false || settings.httpNodeRoot !== false || settings.httpStatic) { + server.on('error', function(err) { + if (err.errno === "EADDRINUSE") { + util.log('[red] Unable to listen on '+getListenPath()); + util.log('[red] Error: port in use'); + } else { + util.log('[red] Uncaught Exception:'); + if (err.stack) { + util.log(err.stack); + } else { + util.log(err); + } + } + process.exit(1); + }); + server.listen(settings.uiPort,settings.uiHost,function() { + if (settings.httpAdminRoot === false) { + util.log('[red] Admin UI disabled'); + } + process.title = 'node-red'; + util.log('[red] Server now running at '+getListenPath()); + }); + } else { + util.log('[red] Running in headless mode'); + } +}).otherwise(function(err) { + util.log("[red] Failed to start server:"); + if (err.stack) { + util.log(err.stack); + } else { + util.log(err); + } +}); + + +process.on('uncaughtException',function(err) { + util.log('[red] Uncaught Exception:'); + if (err.stack) { + util.log(err.stack); + } else { + util.log(err); + } + process.exit(1); +}); + +process.on('SIGINT', function () { + RED.stop(); + // TODO: need to allow nodes to close asynchronously before terminating the + // process - ie, promises + process.exit(); +}); diff --git a/dgbuilder/red/cli/lib/config.js b/dgbuilder/red/cli/lib/config.js new file mode 100644 index 00000000..3cd5244d --- /dev/null +++ b/dgbuilder/red/cli/lib/config.js @@ -0,0 +1,53 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var path = require("path"); +var fs = require("fs"); + +var userHome = process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE; + +var configDir = path.join(userHome,".nodered"); +var configFile = path.join(configDir,"config.json"); + +var config; + +function load() { + if (config == null) { + try { + config = JSON.parse(fs.readFileSync(configFile)); + } catch(err) { + config = {}; + } + } +} + +function save() { + try { + fs.mkdirSync(configDir); + } catch(err) { + if (err.code != "EEXIST") { + throw err; + } + } + fs.writeFileSync(configFile,JSON.stringify(config,null,4)); +} +module.exports = { + unload: function() { + config = null; + } +}; +module.exports.__defineGetter__('target',function() { load(); return config.target|| "http://localhost:1880" }); +module.exports.__defineSetter__('target',function(v) { load(); config.target = v; save();}); diff --git a/dgbuilder/red/cli/lib/request.js b/dgbuilder/red/cli/lib/request.js new file mode 100644 index 00000000..fbbe3dc6 --- /dev/null +++ b/dgbuilder/red/cli/lib/request.js @@ -0,0 +1,51 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var when = require("when"); +var request = require("request"); +var config = require("./config"); + +module.exports = function(path, options) { + var basePath = config.target; + return when.promise(function(resolve,reject) { + options.headers = options.headers||{}; + options.headers['Accept'] = 'application/json'; + if (options.method == 'PUT' || options.method == "POST") { + options.headers['content-type'] = 'application/json'; + } + options.url = basePath+path; + + // Pull out the request function so we can stub it in the tests + var requestFunc = request.get; + + if (options.method == 'PUT') { + requestFunc = request.put; + } else if (options.method == 'POST') { + requestFunc = request.post; + } else if (options.method == 'DELETE') { + requestFunc = request.del; + } + requestFunc(options, function(error,response,body) { + if (!error && response.statusCode == 200) { + resolve(JSON.parse(body)); + } else if (error) { + reject(error.toString()); + } else { + reject(response.statusCode+": "+body) + } + }); + }); +} diff --git a/dgbuilder/red/cli/nr-cli.js b/dgbuilder/red/cli/nr-cli.js new file mode 100755 index 00000000..6d62f05f --- /dev/null +++ b/dgbuilder/red/cli/nr-cli.js @@ -0,0 +1,151 @@ +#!/usr/bin/env node +;(function() { +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var request = require("request"); +var colors = require('colors'); +var apiRequest = require("./lib/request"); +var config = require("./lib/config"); + +var commands = { + "target": function() { + var target = process.argv[3]; + if (target) { + if (!/^https?:\/\/.+/.test(target)) { + console.warn("Invalid target url"); + return; + } + if (target.slice(-1) == "/") { + target = target.slice(0,target.length-1); + } + var oldTarget = config.target; + config.target = target; + } else { + console.log("Target: ".yellow+config.target); + } + + }, + "nodes": function() { + apiRequest('/nodes',{}).then(logNodeList).otherwise(logFailure); + }, + "node": function() { + apiRequest('/nodes/'+process.argv[3],{}).then(logNodeList).otherwise(logFailure); + }, + "enable-node": function() { + apiRequest('/nodes/'+process.argv[3],{ + method: "PUT", + body: JSON.stringify({enabled:true}) + }).then(logNodeList).otherwise(logFailure); + }, + "disable-node": function() { + apiRequest('/nodes/'+process.argv[3],{ + method: "PUT", + body: JSON.stringify({enabled:false}) + }).then(logNodeList).otherwise(logFailure); + }, + "install": function() { + apiRequest('/nodes',{ + method: "POST", + body: JSON.stringify({module:process.argv[3]}) + }).then(logNodeList).otherwise(logFailure); + }, + "remove": function() { + apiRequest('/nodes/'+process.argv[3],{ + method: "DELETE" + }).then(logNodeList).otherwise(logFailure); + }, + "search": function() { + var options = { + method: "GET", + url: 'https://registry.npmjs.org/-/_view/byKeyword?startkey=["node-red"]&endkey=["node-red",{}]&group_level=3' , + headers: { + 'Accept': 'application/json', + } + }; + request(options, function (error, response, body) { + if (!error && response.statusCode == 200) { + var info = (JSON.parse(body)).rows; + var filter = null; + if (process.argv[3]) { + filter = new RegExp(process.argv[3]); + } + for (var i=0;i<info.length;i++) { + var n = info[i]; + if (!filter || filter.test(n.key[1]) || filter.test(n.key[2])) { + console.log(n.key[1] + (" - "+ n.key[2]).grey); + } + } + } else if (error) { + console.log(error.toString().red); + } else { + console.log((response.statusCode+": "+body).red); + } + }); + } +} + +function logNodeList(nodes) { + if (!util.isArray(nodes)) { + nodes = [nodes]; + } + for (var i=0;i<nodes.length;i++) { + var n = nodes[i]; + console.log(formatNodeInfo(n)) + } +} + +function logFailure(msg) { + console.log(msg.red); +} + +function formatBoolean(v,c) { + if (v) { + return ("["+c+"]"); + } else { + return ("[ ]"); + } +} + +function formatNodeInfo(n) { + var inError = n.hasOwnProperty("err"); + + var str = formatBoolean(n.enabled,"X")+formatBoolean(n.loaded,"L")+" "; + str += n.id; + if (n.enabled && n.loaded) { + str = str.green; + } else if (n.enabled && n.err) { + str = str.red; + } else { + str = str.yellow; + } + if (n.module) { + str += " ["+n.module+"]"; + } + str += " "+n.types.join(", "); + if (n.err) { + str+=" "+n.err.red; + } + return str; +} + +if (commands[process.argv[2]]) { + commands[process.argv[2]].call(); +} + + +})(); diff --git a/dgbuilder/red/comms.js b/dgbuilder/red/comms.js new file mode 100644 index 00000000..5828c996 --- /dev/null +++ b/dgbuilder/red/comms.js @@ -0,0 +1,132 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var ws = require("ws"); +var util = require("util"); + +var server; +var settings; + +var wsServer; +var activeConnections = []; + +var retained = {}; + +var heartbeatTimer; +var lastSentTime; + + +function init(_server,_settings) { + server = _server; + settings = _settings; +} + +function start() { + + if (!settings.disableEditor) { + var webSocketKeepAliveTime = settings.webSocketKeepAliveTime || 15000; + var path = settings.httpAdminRoot || "/"; + path = path + (path.slice(-1) == "/" ? "":"/") + "comms"; + wsServer = new ws.Server({server:server,path:path}); + + wsServer.on('connection',function(ws) { + activeConnections.push(ws); + ws.on('close',function() { + for (var i=0;i<activeConnections.length;i++) { + if (activeConnections[i] === ws) { + activeConnections.splice(i,1); + break; + } + } + }); + ws.on('message', function(data,flags) { + var msg = null; + try { + msg = JSON.parse(data); + } catch(err) { + util.log("[red:comms] received malformed message : "+err.toString()); + return; + } + if (msg.subscribe) { + handleRemoteSubscription(ws,msg.subscribe); + } + }); + ws.on('error', function(err) { + util.log("[red:comms] error : "+err.toString()); + }); + }); + + wsServer.on('error', function(err) { + util.log("[red:comms] server error : "+err.toString()); + }); + + lastSentTime = Date.now(); + + heartbeatTimer = setInterval(function() { + var now = Date.now(); + if (now-lastSentTime > webSocketKeepAliveTime) { + publish("hb",lastSentTime); + } + }, webSocketKeepAliveTime); + } +} + +function stop() { + if (heartbeatTimer) { + clearInterval(heartbeatTimer); + } + if (wsServer) { + wsServer.close(); + } +} + +function publish(topic,data,retain) { + if (retain) { + retained[topic] = data; + } else { + delete retained[topic]; + } + lastSentTime = Date.now(); + activeConnections.forEach(function(conn) { + publishTo(conn,topic,data); + }); +} + +function publishTo(ws,topic,data) { + var msg = JSON.stringify({topic:topic,data:data}); + try { + ws.send(msg); + } catch(err) { + util.log("[red:comms] send error : "+err.toString()); + } +} + +function handleRemoteSubscription(ws,topic) { + var re = new RegExp("^"+topic.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$"); + for (var t in retained) { + if (re.test(t)) { + publishTo(ws,t,retained[t]); + } + } +} + + +module.exports = { + init:init, + start:start, + stop:stop, + publish:publish, +} diff --git a/dgbuilder/red/events.js b/dgbuilder/red/events.js new file mode 100644 index 00000000..89590494 --- /dev/null +++ b/dgbuilder/red/events.js @@ -0,0 +1,19 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var events = require("events"); + +module.exports = new events.EventEmitter(); diff --git a/dgbuilder/red/library.js b/dgbuilder/red/library.js new file mode 100644 index 00000000..cc4199f2 --- /dev/null +++ b/dgbuilder/red/library.js @@ -0,0 +1,117 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); + +var redApp = null; +var storage = null; + +function init() { + redApp = require("./server").app; + storage = require("./storage"); + + // -------- Flow Library -------- + redApp.post(new RegExp("/library/flows\/(.*)"), function(req,res) { + var fullBody = ''; + req.on('data', function(chunk) { + fullBody += chunk.toString(); + }); + req.on('end', function() { + storage.saveFlow(req.params[0],fullBody).then(function() { + res.send(204); + }).otherwise(function(err) { + util.log("[red] Error loading flow '"+req.params[0]+"' : "+err); + if (err.message.indexOf('forbidden') === 0) { + res.send(403); + return; + } + res.send(500); + }); + }); + }); + + redApp.get("/library/flows",function(req,res) { + storage.getAllFlows().then(function(flows) { + res.json(flows); + }); + }); + + redApp.get(new RegExp("/library/flows\/(.*)"), function(req,res) { + storage.getFlow(req.params[0]).then(function(data) { + res.set('Content-Type', 'application/json'); + res.send(data); + }).otherwise(function(err) { + if (err) { + util.log("[red] Error loading flow '"+req.params[0]+"' : "+err); + if (err.message.indexOf('forbidden') === 0) { + res.send(403); + return; + } + } + res.send(404); + }); + }); + + // ------------------------------ +} + +function createLibrary(type) { + + redApp.get(new RegExp("/library/"+type+"($|\/(.*))"),function(req,res) { + var path = req.params[1]||""; + storage.getLibraryEntry(type,path).then(function(result) { + if (typeof result === "string") { + res.writeHead(200, {'Content-Type': 'text/plain'}); + res.write(result); + res.end(); + } else { + res.json(result); + } + }).otherwise(function(err) { + if (err) { + util.log("[red] Error loading library entry '"+path+"' : "+err); + if (err.message.indexOf('forbidden') === 0) { + res.send(403); + return; + } + } + res.send(404); + }); + }); + + redApp.post(new RegExp("/library/"+type+"\/(.*)"),function(req,res) { + var path = req.params[0]; + var fullBody = ''; + req.on('data', function(chunk) { + fullBody += chunk.toString(); + }); + req.on('end', function() { + storage.saveLibraryEntry(type,path,req.query,fullBody).then(function() { + res.send(204); + }).otherwise(function(err) { + util.log("[red] Error saving library entry '"+path+"' : "+err); + if (err.message.indexOf('forbidden') === 0) { + res.send(403); + return; + } + res.send(500); + }); + }); + }); +} + +module.exports.init = init; +module.exports.register = createLibrary; diff --git a/dgbuilder/red/log.js b/dgbuilder/red/log.js new file mode 100644 index 00000000..236e6df0 --- /dev/null +++ b/dgbuilder/red/log.js @@ -0,0 +1,39 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var EventEmitter = require("events").EventEmitter; + +var logHandlers = []; + +var ConsoleLogHandler = new EventEmitter(); +ConsoleLogHandler.on("log",function(msg) { + util.log("["+msg.level+"] ["+msg.type+":"+(msg.name||msg.id)+"] "+msg.msg); +}); + +var log = module.exports = { + addHandler: function(func) { + logHandlers.push(func); + }, + + log: function(msg) { + logHandlers.forEach(function(handler) { + handler.emit("log",msg); + }); + } +} + +log.addHandler(ConsoleLogHandler); diff --git a/dgbuilder/red/nodes/Node.js b/dgbuilder/red/nodes/Node.js new file mode 100644 index 00000000..0e6fc525 --- /dev/null +++ b/dgbuilder/red/nodes/Node.js @@ -0,0 +1,147 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var EventEmitter = require("events").EventEmitter; +var clone = require("clone"); +var when = require("when"); + +var flows = require("./flows"); +var comms = require("../comms"); + +function Node(n) { + this.id = n.id; + flows.add(this); + this.type = n.type; + if (n.name) { + this.name = n.name; + } + this.wires = n.wires||[]; +} + +util.inherits(Node,EventEmitter); + +Node.prototype._on = Node.prototype.on; + +Node.prototype.on = function(event,callback) { + var node = this; + if (event == "close") { + if (callback.length == 1) { + this.close = function() { + return when.promise(function(resolve) { + callback.call(node,function() { + resolve(); + }); + }); + } + } else { + this.close = callback; + } + } else { + this._on(event,callback); + } +} + +Node.prototype.close = function() { +} + +Node.prototype.send = function(msg) { + // instanceof doesn't work for some reason here + if (msg == null) { + return; + } else if (!util.isArray(msg)) { + msg = [msg]; + } + for (var i=0;i<this.wires.length;i++) { + var wires = this.wires[i]; + if (i < msg.length) { + if (msg[i] != null) { + var msgs = msg[i]; + if (!util.isArray(msg[i])) { + msgs = [msg[i]]; + } + //if (wires.length == 1) { + // // Single recipient, don't need to clone the message + // var node = flows.get(wires[0]); + // if (node) { + // for (var k in msgs) { + // var mm = msgs[k]; + // node.receive(mm); + // } + // } + //} else { + // Multiple recipients, must send message copies + for (var j=0;j<wires.length;j++) { + var node = flows.get(wires[j]); + if (node) { + for (var k=0;k<msgs.length;k++) { + var mm = msgs[k]; + // Temporary fix for #97 + // TODO: remove this http-node-specific fix somehow + var req = mm.req; + var res = mm.res; + delete mm.req; + delete mm.res; + var m = clone(mm); + if (req) { + m.req = req; + mm.req = req; + } + if (res) { + m.res = res; + mm.res = res; + } + node.receive(m); + } + } + } + //} + } + } + } +} + +Node.prototype.receive = function(msg) { + this.emit("input",msg); +} + +function log_helper(self, level, msg) { + var o = {level:level, id:self.id, type:self.type, msg:msg}; + if (self.name) { + o.name = self.name; + } + self.emit("log",o); +} + +Node.prototype.log = function(msg) { + log_helper(this, 'log', msg); +} + +Node.prototype.warn = function(msg) { + log_helper(this, 'warn', msg); +} + +Node.prototype.error = function(msg) { + log_helper(this, 'error', msg); +} + +/** + * status: { fill:"red|green", shape:"dot|ring", text:"blah" } + */ +Node.prototype.status = function(status) { + comms.publish("status/"+this.id,status,true); +} +module.exports = Node; diff --git a/dgbuilder/red/nodes/credentials.js b/dgbuilder/red/nodes/credentials.js new file mode 100644 index 00000000..22e78d81 --- /dev/null +++ b/dgbuilder/red/nodes/credentials.js @@ -0,0 +1,208 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var when = require("when"); + +var credentialCache = {}; +var storage = null; +var credentialsDef = {}; +var redApp = null; + +/** + * Adds an HTTP endpoint to allow look up of credentials for a given node id. + */ +function registerEndpoint(type) { + redApp.get('/credentials/' + type + '/:id', function (req, res) { + // TODO: This could be a generic endpoint with the type value + // parameterised. + // + // TODO: It should verify the given node id is of the type specified - + // but that would add a dependency from this module to the + // registry module that knows about node types. + var nodeType = type; + var nodeID = req.params.id; + + var credentials = credentialCache[nodeID]; + if (credentials === undefined) { + res.json({}); + return; + } + var definition = credentialsDef[nodeType]; + + var sendCredentials = {}; + for (var cred in definition) { + if (definition.hasOwnProperty(cred)) { + if (definition[cred].type == "password") { + var key = 'has_' + cred; + sendCredentials[key] = credentials[cred] != null && credentials[cred] !== ''; + continue; + } + sendCredentials[cred] = credentials[cred] || ''; + } + } + res.json(sendCredentials); + + }); +} + + +module.exports = { + init: function (_storage) { + storage = _storage; + // TODO: this should get passed in init function call rather than + // required directly. + redApp = require("../server").app; + }, + + /** + * Loads the credentials from storage. + */ + load: function () { + return storage.getCredentials().then(function (creds) { + credentialCache = creds; + }).otherwise(function (err) { + util.log("[red] Error loading credentials : " + err); + }); + }, + + /** + * Adds a set of credentials for the given node id. + * @param id the node id for the credentials + * @param creds an object of credential key/value pairs + * @return a promise for the saving of credentials to storage + */ + add: function (id, creds) { + credentialCache[id] = creds; + return storage.saveCredentials(credentialCache); + }, + + /** + * Gets the credentials for the given node id. + * @param id the node id for the credentials + * @return the credentials + */ + get: function (id) { + return credentialCache[id]; + }, + + /** + * Deletes the credentials for the given node id. + * @param id the node id for the credentials + * @return a promise for the saving of credentials to storage + */ + delete: function (id) { + delete credentialCache[id]; + storage.saveCredentials(credentialCache); + }, + + /** + * Deletes any credentials for nodes that no longer exist + * @param getNode a function that can return a node for a given id + * @return a promise for the saving of credentials to storage + */ + clean: function (getNode) { + var deletedCredentials = false; + for (var c in credentialCache) { + if (credentialCache.hasOwnProperty(c)) { + var n = getNode(c); + if (!n) { + deletedCredentials = true; + delete credentialCache[c]; + } + } + } + if (deletedCredentials) { + return storage.saveCredentials(credentialCache); + } else { + return when.resolve(); + } + }, + + /** + * Registers a node credential definition. + * @param type the node type + * @param definition the credential definition + */ + register: function (type, definition) { + var dashedType = type.replace(/\s+/g, '-'); + credentialsDef[dashedType] = definition; + registerEndpoint(dashedType); + }, + + /** + * Extracts and stores any credential updates in the provided node. + * The provided node may have a .credentials property that contains + * new credentials for the node. + * This function loops through the credentials in the definition for + * the node-type and applies any of the updates provided in the node. + * + * This function does not save the credentials to disk as it is expected + * to be called multiple times when a new flow is deployed. + * + * @param node the node to extract credentials from + */ + extract: function(node) { + var nodeID = node.id; + var nodeType = node.type; + var newCreds = node.credentials; + if (newCreds) { + var savedCredentials = credentialCache[nodeID] || {}; + + var dashedType = nodeType.replace(/\s+/g, '-'); + var definition = credentialsDef[dashedType]; + + if (!definition) { + util.log('Credential Type ' + nodeType + ' is not registered.'); + return; + } + + for (var cred in definition) { + if (definition.hasOwnProperty(cred)) { + if (newCreds[cred] === undefined) { + continue; + } + if (definition[cred].type == "password" && newCreds[cred] == '__PWRD__') { + continue; + } + if (0 === newCreds[cred].length || /^\s*$/.test(newCreds[cred])) { + delete savedCredentials[cred]; + continue; + } + savedCredentials[cred] = newCreds[cred]; + } + } + credentialCache[nodeID] = savedCredentials; + } + }, + + /** + * Saves the credentials to storage + * @return a promise for the saving of credentials to storage + */ + save: function () { + return storage.saveCredentials(credentialCache); + }, + + /** + * Gets the credential definition for the given node type + * @param type the node type + * @return the credential definition + */ + getDefinition: function (type) { + return credentialsDef[type]; + } +} diff --git a/dgbuilder/red/nodes/flows.js b/dgbuilder/red/nodes/flows.js new file mode 100644 index 00000000..b0b5d514 --- /dev/null +++ b/dgbuilder/red/nodes/flows.js @@ -0,0 +1,220 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var when = require("when"); + +var typeRegistry = require("./registry"); +var credentials = require("./credentials"); +var log = require("../log"); +var events = require("../events"); + +var storage = null; + +var nodes = {}; +var activeConfig = []; +var missingTypes = []; + +events.on('type-registered',function(type) { + if (missingTypes.length > 0) { + var i = missingTypes.indexOf(type); + if (i != -1) { + missingTypes.splice(i,1); + util.log("[red] Missing type registered: "+type); + if (missingTypes.length === 0) { + parseConfig(); + } + } + } +}); + +/** + * Parses the current activeConfig and creates the required node instances + */ +function parseConfig() { + var i; + var nt; + missingTypes = []; + + // Scan the configuration for any unknown node types + for (i=0;i<activeConfig.length;i++) { + var type = activeConfig[i].type; + // TODO: remove workspace in next release+1 + if (type != "workspace" && type != "tab") { + nt = typeRegistry.get(type); + if (!nt && missingTypes.indexOf(type) == -1) { + missingTypes.push(type); + } + } + } + // Abort if there are any missing types + if (missingTypes.length > 0) { + util.log("[red] Waiting for missing types to be registered:"); + for (i=0;i<missingTypes.length;i++) { + util.log("[red] - "+missingTypes[i]); + } + return; + } + + util.log("[red] Starting flows"); + events.emit("nodes-starting"); + + // Instantiate each node in the flow + for (i=0;i<activeConfig.length;i++) { + var nn = null; + // TODO: remove workspace in next release+1 + if (activeConfig[i].type != "workspace" && activeConfig[i].type != "tab") { + nt = typeRegistry.get(activeConfig[i].type); + if (nt) { + try { + nn = new nt(activeConfig[i]); + } + catch (err) { + util.log("[red] "+activeConfig[i].type+" : "+err); + } + } + // console.log(nn); + if (nn === null) { + util.log("[red] unknown type: "+activeConfig[i].type); + } + } + } + // Clean up any orphaned credentials + credentials.clean(flowNodes.get); + events.emit("nodes-started"); +} + +/** + * Stops the current activeConfig + */ +function stopFlows() { + if (activeConfig&&activeConfig.length > 0) { + util.log("[red] Stopping flows"); + } + return flowNodes.clear(); +} + +var flowNodes = module.exports = { + init: function(_storage) { + storage = _storage; + }, + + /** + * Load the current activeConfig from storage and start it running + * @return a promise for the loading of the config + */ + load: function() { + return storage.getFlows().then(function(flows) { + return credentials.load().then(function() { + activeConfig = flows; + if (activeConfig && activeConfig.length > 0) { + parseConfig(); + } + }); + }).otherwise(function(err) { + util.log("[red] Error loading flows : "+err); + }); + }, + + /** + * Add a node to the current active set + * @param n the node to add + */ + add: function(n) { + nodes[n.id] = n; + n.on("log",log.log); + }, + + /** + * Get a node + * @param i the node id + * @return the node + */ + get: function(i) { + return nodes[i]; + }, + + /** + * Stops all active nodes and clears the active set + * @return a promise for the stopping of all active nodes + */ + clear: function() { + return when.promise(function(resolve) { + events.emit("nodes-stopping"); + var promises = []; + for (var n in nodes) { + if (nodes.hasOwnProperty(n)) { + try { + var p = nodes[n].close(); + if (p) { + promises.push(p); + } + } catch(err) { + nodes[n].error(err); + } + } + } + when.settle(promises).then(function() { + events.emit("nodes-stopped"); + nodes = {}; + resolve(); + }); + }); + }, + + /** + * Provides an iterator over the active set of nodes + * @param cb a function to be called for each node in the active set + */ + each: function(cb) { + for (var n in nodes) { + if (nodes.hasOwnProperty(n)) { + cb(nodes[n]); + } + } + }, + + /** + * @return the active configuration + */ + getFlows: function() { + return activeConfig; + }, + + /** + * Sets the current active config. + * @param config the configuration to enable + * @return a promise for the starting of the new flow + */ + setFlows: function (config) { + // Extract any credential updates + for (var i=0; i<config.length; i++) { + var node = config[i]; + if (node.credentials) { + credentials.extract(node); + delete node.credentials; + } + } + return credentials.save() + .then(function() { return storage.saveFlows(config);}) + .then(function() { return stopFlows();}) + .then(function () { + activeConfig = config; + parseConfig(); + }); + }, + stopFlows: stopFlows +}; diff --git a/dgbuilder/red/nodes/index.js b/dgbuilder/red/nodes/index.js new file mode 100644 index 00000000..3d5ad719 --- /dev/null +++ b/dgbuilder/red/nodes/index.js @@ -0,0 +1,134 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var registry = require("./registry"); +var credentials = require("./credentials"); +var flows = require("./flows"); +var Node = require("./Node"); + +/** + * Registers a node constructor + * @param type - the string type name + * @param constructor - the constructor function for this node type + * @param opts - optional additional options for the node + */ +function registerType(type,constructor,opts) { + if (opts && opts.credentials) { + credentials.register(type,opts.credentials); + } + registry.registerType(type,constructor); +} + +/** + * Called from a Node's constructor function, invokes the super-class + * constructor and attaches any credentials to the node. + * @param node the node object being created + * @param def the instance definition for the node + */ +function createNode(node,def) { + Node.call(node,def); + var creds = credentials.get(node.id); + if (creds) { + node.credentials = creds; + } +} + +function init(_settings,storage) { + credentials.init(storage); + flows.init(storage); + registry.init(_settings); +} + +function checkTypeInUse(id) { + var nodeInfo = registry.getNodeInfo(id); + if (!nodeInfo) { + throw new Error("Unrecognised id: "+info); + } + var inUse = {}; + flows.each(function(n) { + inUse[n.type] = (inUse[n.type]||0)+1; + }); + var nodesInUse = []; + nodeInfo.types.forEach(function(t) { + if (inUse[t]) { + nodesInUse.push(t); + } + }); + if (nodesInUse.length > 0) { + var msg = nodesInUse.join(", "); + throw new Error("Type in use: "+msg); + } +} + +function removeNode(id) { + checkTypeInUse(id); + return registry.removeNode(id); +} + +function removeModule(module) { + var info = registry.getNodeModuleInfo(module); + for (var i=0;i<info.nodes.length;i++) { + checkTypeInUse(info.nodes[i]); + } + return registry.removeModule(module); +} + + +function disableNode(id) { + checkTypeInUse(id); + return registry.disableNode(id); +} + +module.exports = { + // Lifecycle + init: init, + load: registry.load, + + // Node registry + createNode: createNode, + getNode: flows.get, + + addNode: registry.addNode, + removeNode: removeNode, + + addModule: registry.addModule, + removeModule: removeModule, + + enableNode: registry.enableNode, + disableNode: disableNode, + + // Node type registry + registerType: registerType, + getType: registry.get, + getNodeInfo: registry.getNodeInfo, + getNodeModuleInfo: registry.getNodeModuleInfo, + getNodeList: registry.getNodeList, + getNodeConfigs: registry.getNodeConfigs, + getNodeConfig: registry.getNodeConfig, + clearRegistry: registry.clear, + cleanNodeList: registry.cleanNodeList, + + // Flow handling + loadFlows: flows.load, + stopFlows: flows.stopFlows, + setFlows: flows.setFlows, + getFlows: flows.getFlows, + + // Credentials + addCredentials: credentials.add, + getCredentials: credentials.get, + deleteCredentials: credentials.delete +} + diff --git a/dgbuilder/red/nodes/registry.js b/dgbuilder/red/nodes/registry.js new file mode 100644 index 00000000..f2073aff --- /dev/null +++ b/dgbuilder/red/nodes/registry.js @@ -0,0 +1,693 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var util = require("util"); +var when = require("when"); +var whenNode = require('when/node'); +var fs = require("fs"); +var path = require("path"); +var crypto = require("crypto"); +var UglifyJS = require("uglify-js"); + +var events = require("../events"); + +var Node; +var settings; + +function filterNodeInfo(n) { + var r = { + id: n.id, + name: n.name, + types: n.types, + enabled: n.enabled + } + if (n.hasOwnProperty("loaded")) { + r.loaded = n.loaded; + } + if (n.hasOwnProperty("module")) { + r.module = n.module; + } + if (n.hasOwnProperty("err")) { + r.err = n.err.toString(); + } + return r; +} + +var registry = (function() { + var nodeConfigCache = null; + var nodeConfigs = {}; + var nodeList = []; + var nodeConstructors = {}; + var nodeTypeToId = {}; + var nodeModules = {}; + + function saveNodeList() { + var nodeList = {}; + + for (var i in nodeConfigs) { + if (nodeConfigs.hasOwnProperty(i)) { + var nodeConfig = nodeConfigs[i]; + var n = filterNodeInfo(nodeConfig); + n.file = nodeConfig.file; + delete n.loaded; + delete n.err; + delete n.file; + delete n.id; + nodeList[i] = n; + } + } + if (settings.available()) { + return settings.set("nodes",nodeList); + } else { + return when.reject("Settings unavailable"); + } + } + + return { + init: function() { + if (settings.available()) { + nodeConfigs = settings.get("nodes")||{}; + // Restore the node id property to individual entries + for (var id in nodeConfigs) { + if (nodeConfigs.hasOwnProperty(id)) { + nodeConfigs[id].id = id; + } + } + } else { + nodeConfigs = {}; + } + nodeModules = {}; + nodeTypeToId = {}; + nodeConstructors = {}; + nodeList = []; + nodeConfigCache = null; + }, + + addNodeSet: function(id,set) { + if (!set.err) { + set.types.forEach(function(t) { + nodeTypeToId[t] = id; + }); + } + + if (set.module) { + nodeModules[set.module] = nodeModules[set.module]||{nodes:[]}; + nodeModules[set.module].nodes.push(id); + } + + nodeConfigs[id] = set; + nodeList.push(id); + nodeConfigCache = null; + }, + removeNode: function(id) { + var config = nodeConfigs[id]; + if (!config) { + throw new Error("Unrecognised id: "+id); + } + delete nodeConfigs[id]; + var i = nodeList.indexOf(id); + if (i > -1) { + nodeList.splice(i,1); + } + config.types.forEach(function(t) { + delete nodeConstructors[t]; + delete nodeTypeToId[t]; + }); + config.enabled = false; + config.loaded = false; + nodeConfigCache = null; + return filterNodeInfo(config); + }, + removeModule: function(module) { + if (!settings.available()) { + throw new Error("Settings unavailable"); + } + var nodes = nodeModules[module]; + if (!nodes) { + throw new Error("Unrecognised module: "+module); + } + var infoList = []; + for (var i=0;i<nodes.nodes.length;i++) { + infoList.push(registry.removeNode(nodes.nodes[i])); + } + delete nodeModules[module]; + saveNodeList(); + return infoList; + }, + getNodeInfo: function(typeOrId) { + if (nodeTypeToId[typeOrId]) { + return filterNodeInfo(nodeConfigs[nodeTypeToId[typeOrId]]); + } else if (nodeConfigs[typeOrId]) { + return filterNodeInfo(nodeConfigs[typeOrId]); + } + return null; + }, + getNodeList: function() { + var list = []; + for (var id in nodeConfigs) { + if (nodeConfigs.hasOwnProperty(id)) { + list.push(filterNodeInfo(nodeConfigs[id])) + } + } + return list; + }, + registerNodeConstructor: function(type,constructor) { + if (nodeConstructors[type]) { + throw new Error(type+" already registered"); + } + //TODO: Ensure type is known - but doing so will break some tests + // that don't have a way to register a node template ahead + // of registering the constructor + util.inherits(constructor,Node); + nodeConstructors[type] = constructor; + events.emit("type-registered",type); + }, + + + /** + * Gets all of the node template configs + * @return all of the node templates in a single string + */ + getAllNodeConfigs: function() { + if (!nodeConfigCache) { + var result = ""; + var script = ""; + for (var i=0;i<nodeList.length;i++) { + var config = nodeConfigs[nodeList[i]]; + if (config.enabled && !config.err) { + result += config.config; + script += config.script; + } + } + if (script.length > 0) { + result += '<script type="text/javascript">'; + result += UglifyJS.minify(script, {fromString: true}).code; + result += '</script>'; + } + nodeConfigCache = result; + } + return nodeConfigCache; + }, + + getNodeConfig: function(id) { + var config = nodeConfigs[id]; + if (config) { + var result = config.config; + if (config.script) { + result += '<script type="text/javascript">'+config.script+'</script>'; + } + return result; + } else { + return null; + } + }, + + getNodeConstructor: function(type) { + var config = nodeConfigs[nodeTypeToId[type]]; + if (!config || (config.enabled && !config.err)) { + return nodeConstructors[type]; + } + return null; + }, + + clear: function() { + nodeConfigCache = null; + nodeConfigs = {}; + nodeList = []; + nodeConstructors = {}; + nodeTypeToId = {}; + }, + + getTypeId: function(type) { + return nodeTypeToId[type]; + }, + + getModuleInfo: function(type) { + return nodeModules[type]; + }, + + enableNodeSet: function(id) { + if (!settings.available()) { + throw new Error("Settings unavailable"); + } + var config = nodeConfigs[id]; + if (config) { + delete config.err; + config.enabled = true; + if (!config.loaded) { + // TODO: honour the promise this returns + loadNodeModule(config); + } + nodeConfigCache = null; + saveNodeList(); + } else { + throw new Error("Unrecognised id: "+id); + } + return filterNodeInfo(config); + }, + + disableNodeSet: function(id) { + if (!settings.available()) { + throw new Error("Settings unavailable"); + } + var config = nodeConfigs[id]; + if (config) { + // TODO: persist setting + config.enabled = false; + nodeConfigCache = null; + saveNodeList(); + } else { + throw new Error("Unrecognised id: "+id); + } + return filterNodeInfo(config); + }, + + saveNodeList: saveNodeList, + + cleanNodeList: function() { + var removed = false; + for (var id in nodeConfigs) { + if (nodeConfigs.hasOwnProperty(id)) { + if (nodeConfigs[id].module && !nodeModules[nodeConfigs[id].module]) { + registry.removeNode(id); + removed = true; + } + } + } + if (removed) { + saveNodeList(); + } + } + } +})(); + + + +function init(_settings) { + Node = require("./Node"); + settings = _settings; + registry.init(); +} + +/** + * Synchronously walks the directory looking for node files. + * Emits 'node-icon-dir' events for an icon dirs found + * @param dir the directory to search + * @return an array of fully-qualified paths to .js files + */ +function getNodeFiles(dir) { + var result = []; + var files = []; + try { + files = fs.readdirSync(dir); + } catch(err) { + return result; + } + files.sort(); + files.forEach(function(fn) { + var stats = fs.statSync(path.join(dir,fn)); + if (stats.isFile()) { + if (/\.js$/.test(fn)) { + var valid = true; + if (settings.nodesExcludes) { + for (var i=0;i<settings.nodesExcludes.length;i++) { + if (settings.nodesExcludes[i] == fn) { + valid = false; + break; + } + } + } + valid = valid && fs.existsSync(path.join(dir,fn.replace(/\.js$/,".html"))) + + if (valid) { + result.push(path.join(dir,fn)); + } + } + } else if (stats.isDirectory()) { + // Ignore /.dirs/, /lib/ /node_modules/ + if (!/^(\..*|lib|icons|node_modules|test)$/.test(fn)) { + result = result.concat(getNodeFiles(path.join(dir,fn))); + } else if (fn === "icons") { + events.emit("node-icon-dir",path.join(dir,fn)); + } + } + }); + return result; +} + +/** + * Scans the node_modules path for nodes + * @param moduleName the name of the module to be found + * @return a list of node modules: {dir,package} + */ +function scanTreeForNodesModules(moduleName) { + var dir = __dirname+"/../../nodes"; + var results = []; + var up = path.resolve(path.join(dir,"..")); + while (up !== dir) { + var pm = path.join(dir,"node_modules"); + try { + var files = fs.readdirSync(pm); + for (var i=0;i<files.length;i++) { + var fn = files[i]; + if (!registry.getModuleInfo(fn)) { + if (!moduleName || fn == moduleName) { + var pkgfn = path.join(pm,fn,"package.json"); + try { + var pkg = require(pkgfn); + if (pkg['node-red']) { + var moduleDir = path.join(pm,fn); + results.push({dir:moduleDir,package:pkg}); + } + } catch(err) { + if (err.code != "MODULE_NOT_FOUND") { + // TODO: handle unexpected error + } + } + if (fn == moduleName) { + break; + } + } + } + } + } catch(err) { + } + + dir = up; + up = path.resolve(path.join(dir,"..")); + } + return results; +} + +/** + * Loads the nodes provided in an npm package. + * @param moduleDir the root directory of the package + * @param pkg the module's package.json object + */ +function loadNodesFromModule(moduleDir,pkg) { + var nodes = pkg['node-red'].nodes||{}; + var results = []; + var iconDirs = []; + for (var n in nodes) { + if (nodes.hasOwnProperty(n)) { + var file = path.join(moduleDir,nodes[n]); + try { + results.push(loadNodeConfig(file,pkg.name,n)); + } catch(err) { + } + var iconDir = path.join(moduleDir,path.dirname(nodes[n]),"icons"); + if (iconDirs.indexOf(iconDir) == -1) { + if (fs.existsSync(iconDir)) { + events.emit("node-icon-dir",iconDir); + iconDirs.push(iconDir); + } + } + } + } + return results; +} + + +/** + * Loads a node's configuration + * @param file the fully qualified path of the node's .js file + * @param name the name of the node + * @return the node object + * { + * id: a unqiue id for the node file + * name: the name of the node file, or label from the npm module + * file: the fully qualified path to the node's .js file + * template: the fully qualified path to the node's .html file + * config: the non-script parts of the node's .html file + * script: the script part of the node's .html file + * types: an array of node type names in this file + * } + */ +function loadNodeConfig(file,module,name) { + var id = crypto.createHash('sha1').update(file).digest("hex"); + if (module && name) { + var newid = crypto.createHash('sha1').update(module+":"+name).digest("hex"); + var existingInfo = registry.getNodeInfo(id); + if (existingInfo) { + // For a brief period, id for modules were calculated incorrectly. + // To prevent false-duplicates, this removes the old id entry + registry.removeNode(id); + registry.saveNodeList(); + } + id = newid; + + } + var info = registry.getNodeInfo(id); + + var isEnabled = true; + + if (info) { + if (info.hasOwnProperty("loaded")) { + throw new Error(file+" already loaded"); + } + isEnabled = info.enabled; + } + + var node = { + id: id, + file: file, + template: file.replace(/\.js$/,".html"), + enabled: isEnabled, + loaded:false + } + + if (module) { + node.name = module+":"+name; + node.module = module; + } else { + node.name = path.basename(file) + } + try { + var content = fs.readFileSync(node.template,'utf8'); + + var types = []; + + var regExp = /<script ([^>]*)data-template-name=['"]([^'"]*)['"]/gi; + var match = null; + + while((match = regExp.exec(content)) !== null) { + types.push(match[2]); + } + node.types = types; + node.config = content; + + // TODO: parse out the javascript portion of the template + node.script = ""; + + for (var i=0;i<node.types.length;i++) { + if (registry.getTypeId(node.types[i])) { + node.err = node.types[i]+" already registered"; + break; + } + } + } catch(err) { + node.types = []; + if (err.code === 'ENOENT') { + node.err = "Error: "+file+" does not exist"; + } else { + node.err = err.toString(); + } + } + registry.addNodeSet(id,node); + return node; +} + +/** + * Loads all palette nodes + * @param defaultNodesDir optional parameter, when set, it overrides the default + * location of nodeFiles - used by the tests + * @return a promise that resolves on completion of loading + */ +function load(defaultNodesDir,disableNodePathScan) { + return when.promise(function(resolve,reject) { + // Find all of the nodes to load + var nodeFiles; + if(defaultNodesDir) { + nodeFiles = getNodeFiles(path.resolve(defaultNodesDir)); + } else { + nodeFiles = getNodeFiles(__dirname+"/../../nodes"); + } + + if (settings.nodesDir) { + var dir = settings.nodesDir; + if (typeof settings.nodesDir == "string") { + dir = [dir]; + } + for (var i=0;i<dir.length;i++) { + nodeFiles = nodeFiles.concat(getNodeFiles(dir[i])); + } + } + var nodes = []; + nodeFiles.forEach(function(file) { + try { + nodes.push(loadNodeConfig(file)); + } catch(err) { + // + } + }); + + // TODO: disabling npm module loading if defaultNodesDir set + // This indicates a test is being run - don't want to pick up + // unexpected nodes. + // Urgh. + if (!disableNodePathScan) { + // Find all of the modules containing nodes + var moduleFiles = scanTreeForNodesModules(); + moduleFiles.forEach(function(moduleFile) { + nodes = nodes.concat(loadNodesFromModule(moduleFile.dir,moduleFile.package)); + }); + } + var promises = []; + nodes.forEach(function(node) { + if (!node.err) { + promises.push(loadNodeModule(node)); + } + }); + + //resolve([]); + when.settle(promises).then(function(results) { + // Trigger a load of the configs to get it precached + registry.getAllNodeConfigs(); + + if (settings.available()) { + resolve(registry.saveNodeList()); + } else { + resolve(); + } + }); + }); +} + +/** + * Loads the specified node into the runtime + * @param node a node info object - see loadNodeConfig + * @return a promise that resolves to an update node info object. The object + * has the following properties added: + * err: any error encountered whilst loading the node + * + */ +function loadNodeModule(node) { + var nodeDir = path.dirname(node.file); + var nodeFn = path.basename(node.file); + if (!node.enabled) { + return when.resolve(node); + } + try { + var loadPromise = null; + var r = require(node.file); + if (typeof r === "function") { + var promise = r(require('../red')); + if (promise != null && typeof promise.then === "function") { + loadPromise = promise.then(function() { + node.enabled = true; + node.loaded = true; + return node; + }).otherwise(function(err) { + node.err = err; + return node; + }); + } + } + if (loadPromise == null) { + node.enabled = true; + node.loaded = true; + loadPromise = when.resolve(node); + } + return loadPromise; + } catch(err) { + node.err = err; + return when.resolve(node); + } +} + +function loadNodeList(nodes) { + var promises = []; + nodes.forEach(function(node) { + if (!node.err) { + promises.push(loadNodeModule(node)); + } else { + promises.push(node); + } + }); + + return when.settle(promises).then(function(results) { + return registry.saveNodeList().then(function() { + var list = results.map(function(r) { + return filterNodeInfo(r.value); + }); + return list; + }); + }); +} + +function addNode(file) { + if (!settings.available()) { + throw new Error("Settings unavailable"); + } + var nodes = []; + try { + nodes.push(loadNodeConfig(file)); + } catch(err) { + return when.reject(err); + } + return loadNodeList(nodes); +} + +function addModule(module) { + if (!settings.available()) { + throw new Error("Settings unavailable"); + } + var nodes = []; + if (registry.getModuleInfo(module)) { + return when.reject(new Error("Module already loaded")); + } + var moduleFiles = scanTreeForNodesModules(module); + if (moduleFiles.length === 0) { + var err = new Error("Cannot find module '" + module + "'"); + err.code = 'MODULE_NOT_FOUND'; + return when.reject(err); + } + moduleFiles.forEach(function(moduleFile) { + nodes = nodes.concat(loadNodesFromModule(moduleFile.dir,moduleFile.package)); + }); + return loadNodeList(nodes); +} + +module.exports = { + init:init, + load:load, + clear: registry.clear, + registerType: registry.registerNodeConstructor, + get: registry.getNodeConstructor, + getNodeInfo: registry.getNodeInfo, + getNodeModuleInfo: registry.getModuleInfo, + getNodeList: registry.getNodeList, + getNodeConfigs: registry.getAllNodeConfigs, + getNodeConfig: registry.getNodeConfig, + addNode: addNode, + removeNode: registry.removeNode, + enableNode: registry.enableNodeSet, + disableNode: registry.disableNodeSet, + + addModule: addModule, + removeModule: registry.removeModule, + cleanNodeList: registry.cleanNodeList +} diff --git a/dgbuilder/red/red.js b/dgbuilder/red/red.js new file mode 100644 index 00000000..2735e0da --- /dev/null +++ b/dgbuilder/red/red.js @@ -0,0 +1,68 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var server = require("./server"); +var nodes = require("./nodes"); +var library = require("./library"); +var comms = require("./comms"); +var log = require("./log"); +var util = require("./util"); +var fs = require("fs"); +var settings = require("./settings"); +var credentials = require("./nodes/credentials"); + +var path = require('path'); + +process.env.NODE_RED_HOME = process.env.NODE_RED_HOME || path.resolve(__dirname+"/.."); + +var events = require("events"); + +var RED = { + + init: function(httpServer,userSettings) { + userSettings.version = this.version(); + settings.init(userSettings); + server.init(httpServer,settings); + library.init(); + return server.app; + }, + + start: server.start, + stop: server.stop, + nodes: nodes, + library: library, + credentials: credentials, + events: events, + log: log, + comms: comms, + settings:settings, + util: util, + version: function () { + var p = require(path.join(process.env.NODE_RED_HOME,"package.json")); + if (fs.existsSync(path.join(process.env.NODE_RED_HOME,".git"))) { + return p.version+".git"; + } else { + return p.version; + } + } +}; + +RED.__defineGetter__("app", function() { console.log("Deprecated use of RED.app - use RED.httpAdmin instead"); return server.app }); +RED.__defineGetter__("httpAdmin", function() { return server.app }); +RED.__defineGetter__("httpNode", function() { return server.nodeApp }); +RED.__defineGetter__("server", function() { return server.server }); + +module.exports = RED; diff --git a/dgbuilder/red/server.js b/dgbuilder/red/server.js new file mode 100644 index 00000000..91bee453 --- /dev/null +++ b/dgbuilder/red/server.js @@ -0,0 +1,1318 @@ +/** + * Copyright 2013 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var express = require('express'); +var util = require('util'); +var multer = require('multer'); +var when = require('when'); +var exec = require('child_process').exec; + +var createUI = require("./ui"); +var redNodes = require("./nodes"); +var comms = require("./comms"); +var storage = require("./storage"); +var fs=require('fs'); +var path = require("path"); +var app = null; +var nodeApp = null; +var server = null; +var settings = null; + +var flowShareUsers = require("../flowShareUsers"); + +//console.dir(flowShareUsers); + +function createServer(_server,_settings) { + server = _server; + settings = _settings; + + comms.init(_server,_settings); + + nodeApp = express(); + app = express(); + + if (settings.httpAdminRoot !== false) { + + + if (!settings.disableEditor) { + createUI(settings,app); + } + + var slaActions = require("./sla"); + + app.get("/flows",function(req,res) { + res.json(redNodes.getFlows()); + }); + + app.get("/loadJSFiles",function(req,res) { + var appDir = path.dirname(require.main.filename); + var generatedJSDir=appDir + "/generatedJS"; + var glob = require("glob") + glob(generatedJSDir + "/**/*.js", null, function (er, files) { + // files is an array of filenames. + // If the `nonull` option is set, and nothing + // was found, then files is ["**/*.js"] + // er is an error object or null. + //console.dir(files); + var sliValuesObj =[]; + for(var i=0;files!= null && i<files.length;i++){ + var f = files[i].replace( new RegExp(generatedJSDir + "/", "g" ), "" ); + console.log("loading file " + f); + try{ + sliValuesObj.push(require(files[i])); + //console.dir(sliValuesObj); + }catch(err){ + console.log("Error:Could not load file " + files[i]); + } + } + res.json({"sliValuesObj" : sliValuesObj}); + }); + }); + + app.get("/loadSelectedModules",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + var generatedJSDir=appDir + "/generatedJS"; + //console.dir(req); + var selectedModulesStr = req.query.selectedModules; + var selectedModules = []; + if(selectedModulesStr != undefined && selectedModulesStr != null){ + selectedModules = selectedModulesStr.split(","); + } + console.log(selectedModules); + var loaded_modules = {"selected_modules" :selectedModules}; + var file = userDir + "/selected_modules"; + var content = "module.exports=\n" + JSON.stringify(loaded_modules); + try{ + fs.writeFileSync(file, content, 'utf8'); + }catch(err){ + console.log("could not write to file " + file); + } + var sliValuesObj =[]; + for(var i=0;selectedModules!= null && i<selectedModules.length;i++){ + var f = generatedJSDir + "/" + selectedModules[i] + "_inputs.js"; + try{ + delete require.cache[require.resolve(f)] + require.resolve(); + }catch(err){ + console.log("error deleting loaded module " + f + " from cache"); + } + //console.log("loading file " + f); + try{ + sliValuesObj.push(require(f)); + }catch(err){ + console.log("Error:Could not load file " + f); + } + } + //console.dir(sliValuesObj); + res.json({"sliValuesObj" : sliValuesObj}); + }); + + app.get("/initialLoadSelectedModules",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + var generatedJSDir=appDir + "/generatedJS"; + var file = userDir + "/selected_modules"; + var sliValuesObj =[]; + var selected_modules = []; + var selectedModules; + try{ + selectedModules = require(file); + selected_modules=selectedModules["selected_modules"]; + //console.log("selected_modules are "); + //console.dir(selected_modules); + }catch(err){ + console.log("Could not load the file " + file); + } + for(var i=0;selected_modules!= null && i<selected_modules.length;i++){ + var f = generatedJSDir + "/" + selected_modules[i] + "_inputs.js"; + console.log("loading file " + f); + try{ + sliValuesObj.push(require(f)); + }catch(err){ + console.log("Error:Could not load file " + f); + } + } + res.json({"sliValuesObj" : sliValuesObj}); + }); + + app.get("/listAvailableModules",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + var generatedJSDir=appDir + "/generatedJS"; + var glob = require("glob") + var file = userDir + "/selected_modules"; + var selected_modules = []; + var selectedModules; + try{ + delete require.cache[require.resolve(file)] + require.resolve(); + }catch(err){ + console.log("error deleting loaded module " + file + " from cache"); + } + try{ + selectedModules = require(file); + selected_modules=selectedModules["selected_modules"]; + console.log("selected_modules are "); + //console.dir(selected_modules); + }catch(err){ + console.log("Could not load the file " + file); + } + glob(generatedJSDir + "/**/*.js", null, function (er, files) { + var filesList =[]; + for(var i=0;files!= null && i<files.length;i++){ + var f = files[i].replace( new RegExp(generatedJSDir + "/", "g" ), "" ); + f = f.replace("_inputs.js",""); + if(selected_modules != undefined && selected_modules != null && selected_modules.indexOf(f) != -1){ + filesList.push(f + ":checked"); + }else{ + filesList.push(f + ":unchecked"); + } + } + res.json({"files" : filesList}); + }); + }); + + app.get("/listSLA",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + var settingsFile = userDir + "/customSettings.js"; + var jsonObj = require(settingsFile); + slaActions.listSLA(jsonObj,req,res); + }); + + app.get("/listCurrentDGs",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + var settingsFile = userDir + "/customSettings.js"; + var jsonObj = require(settingsFile); + slaActions.listCurrentDGs(jsonObj,req,res); + }); + + app.get("/activateDG",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + var settingsFile = userDir + "/customSettings.js"; + var jsonObj = require(settingsFile); + slaActions.activateDG(jsonObj,req,res); + }); + + app.get("/deActivateDG",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + var settingsFile = userDir + "/customSettings.js"; + var jsonObj = require(settingsFile); + slaActions.deActivateDG(jsonObj,req,res); + }); + + app.get("/deleteDG",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + var settingsFile = userDir + "/customSettings.js"; + var jsonObj = require(settingsFile); + slaActions.deleteDG(jsonObj,req,res); + }); + + app.get("/getCurrentSettings",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + //console.log("userDir:" + userDir); + var settingsFile = userDir + "/customSettings.js"; + var jsonObj = require(settingsFile); + res.json(jsonObj); + }); + + app.get("/getCommitsInfo", function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + //console.dir(req); + var filePath = req.query.filePath; + var fullFilePath = userDir + "/codecloud/" + filePath ; + //console.log("fullFilePath:" + fullFilePath); + var exec = require('child_process').exec; + var commandToExec = appDir + "/git_scripts/gitlog " + fullFilePath ; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + //console.log("stderr:" + stderr); + res.send(500,{'error':error,'stderr':stderr}); + }else{ + res.send(500,{'error':error}); + } + //console.log("stdout :" + stdout); + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + //console.log("output:" + stdout); + res.send(200,{'stdout':stdout,'stderr':stderr}); + } + } + }); + }); + + app.get("/importCodeCloudFlow", + function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + //console.dir(req); + var commitId = req.query.commitId; + var filePath = req.query.filePath; + var fullFilePath = userDir + "/codecloud/" + filePath ; + //console.log("fullFilePath:" + fullFilePath); + var exec = require('child_process').exec; + var commandToExec = appDir + "/git_scripts/gitckout " + commitId + " " + fullFilePath ; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,{maxBuffer: 1024 * 1024 * 16}, function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + //console.log("stderr:" + stderr); + res.send(500,{'error':error,'stderr':stderr}); + }else{ + res.send(500,{'error':error}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + //console.log("output:" + stdout); + res.send(200,{'stdout':stdout,'stderr':stderr}); + } + } + }); + }); + + app.get("/importGitLocalFlow", + function(req,res) { + var appDir = path.dirname(require.main.filename); + var gitLocalRepository = settings.gitLocalRepository; + //console.dir(req); + var filePath = req.query.filePath; + var fullFilePath = gitLocalRepository +"/" + filePath ; + //console.log("fullFilePath:" + fullFilePath); + var exec = require('child_process').exec; + var commandToExec = "cat " + fullFilePath ; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,{maxBuffer: 1024 * 1024 * 16}, function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + //console.log("stderr:" + stderr); + res.send(500,{'error':error,'stderr':stderr}); + }else{ + res.send(500,{'error':error}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + //console.log("output:" + stdout); + res.send(200,{'stdout':stdout,'stderr':stderr}); + } + } + }); + }); + + + app.get("/gitcheckout", function(req,res) { + var appDir = path.dirname(require.main.filename); + var gitLocalRepository = settings.gitLocalRepository; + //console.dir(req); + var branch = req.query.branch; + //console.log("fullFilePath:" + fullFilePath); + var exec = require('child_process').exec; + var commandToExec = appDir + "/git_scripts/gitcheckout " + gitLocalRepository + " " + branch ; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + console.log("stderr:" + stderr); + res.json({"output":stderr}); + }else{ + res.json({"output":error}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + res.json({"output": stderr + " " + stdout}); + } + } + }); + }); + + app.get("/gitpull", function(req,res) { + var appDir = path.dirname(require.main.filename); + var gitLocalRepository = settings.gitLocalRepository; + //console.dir(req); + var branch = req.query.branch; + //console.log("fullFilePath:" + fullFilePath); + var exec = require('child_process').exec; + var commandToExec = appDir + "/git_scripts/gitpull " + gitLocalRepository ; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + console.log("stderr:" + stderr); + res.json({"output":stderr}); + }else{ + res.json({"output":error}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + res.json({"output": stderr + " " + stdout}); + } + } + }); + }); + + app.get("/gitstatus", function(req,res) { + var appDir = path.dirname(require.main.filename); + var gitLocalRepository = settings.gitLocalRepository; + //console.dir(req); + var branch = req.query.branch; + //console.log("fullFilePath:" + fullFilePath); + var exec = require('child_process').exec; + var commandToExec = appDir + "/git_scripts/gitstatus " + gitLocalRepository ; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + console.log("stderr:" + stderr); + res.json({"output":stderr}); + }else{ + res.json({"output":error}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + res.json({"output": stderr + " " + stdout}); + } + } + }); + }); + + app.post("/getSharedFlow", + express.json(), + function(req,res) { + var qs = require('querystring'); + var body = ''; + req.on('data', function (data) { + body += data; + }); + req.on('end', function () { + var post = qs.parse(body); + //console.log("body:" + body); + fs.readFile(post.filePath, 'utf8', function (err,data) { + if (err) { + return console.log(err); + } + res.json(data); + //console.log(data); + }); + //res.sendFile(body.filePath); + }); + }); + + app.post("/downloadYang", + express.json(), + function(req,res) { + var qs = require('querystring'); + var body = ''; + req.on('data', function (data) { + body += data; + }); + req.on('end', function () { + var post = qs.parse(body); + var fileName = post.fileName; + var appDir = path.dirname(require.main.filename); + var yangDir = appDir + "/yangFiles" ; + var fullPathToFile = yangDir + "/" + fileName; + res.setHeader('Content-disposition', 'attachment; filename=' + fileName); + res.setHeader('Content-type', 'application/yang'); + res.download(fullPathToFile); + }); + }); + + function writeToFile(fullPathToFileName,str){ + try{ + fs.writeFileSync(fullPathToFileName,str); + }catch(e){ + console.log("Error:" + e); + } + } + function getCurrentDate(){ + var d = new Date(); + var mm = d.getMonth() + 1; + var dd = d.getDate(); + var yyyy = d.getYear() + 1900; + var hr = d.getHours(); + var min = d.getMinutes(); + var sec = d.getSeconds(); + if(mm<10) mm = "0" + mm; + if(dd<10) dd = "0" + dd; + if(hr<10) hr = "0" + hr; + if(min<10) min = "0" + min; + if(sec<10) sec = "0" + sec; + var formatedValue = mm + "-" + dd + "-" + yyyy + "_" + hr + "" + min + "" + sec; + return formatedValue; + } + + + app.post("/downloadXml", + express.json({'limit':'16mb'}), + function(req,res) { + //console.log("Received request and processing:" + new Date()); + var qs = require('querystring'); + var body = ''; + //var msecs1= Date.now(); + req.on('data', function (data) { + body += data; + }); + req.on('end', function () { + var appDir = path.dirname(require.main.filename); + var xmlDir = appDir + "/" + settings.xmlPath; + //var msecs2= Date.now(); + //console.log("Time taken to get request body:" + (msecs2 - msecs1)); + var msecs3= Date.now(); + var post = qs.parse(body); + var msecs4= Date.now(); + //console.log("Time taken to parse body:" + (msecs4 - msecs3)); + var xml = post['flowXml']; + //var pd = require('pretty-data').pd; + //var formatted_xml = pd.xml(xml); + var moduleName = post['moduleName']; + var methodName = post['methodName']; + if(moduleName == "" || methodName == ""){ + res.send({"ERROR":"ServiceLogic Module Name and method name are required."}); + }else{ + //var formatted_date = getCurrentDate(); + //var fileNameForServer=moduleName + "_" +methodName+ "_" + formatted_date + ".xml"; + //var fileName=moduleName + "_method_" +methodName+ ".xml"; + var fileName=moduleName + "_" +methodName+ ".xml"; + var file = xmlDir + "/" + fileName; + + //var msecs2= Date.now(); + writeToFile(file,xml); + //var msecs3= Date.now(); + //console.log("Time taken to write File:" + (msecs3 - msecs2)); + res.setHeader('Content-disposition', 'attachment; filename=' + fileName); + res.setHeader('Content-type', 'text/xml'); + res.end(xml); + //console.log("Response sent:" + new Date()); + } + }); + }); + + app.post("/downloadJson", + express.json({'limit':'16mb'}), + function(req,res) { + var appDir = path.dirname(require.main.filename); + var sharedDir = appDir + "/" + settings.sharedDir; + var qs = require('querystring'); + var body = ''; + req.on('data', function (data) { + body += data; + }); + req.on('end', function () { + var post = qs.parse(body); + var jsonStr = post['flowJson']; + var moduleName = post['moduleName']; + var methodName = post['methodName']; + //console.log("jsonStr:" + jsonStr); + if(moduleName == "" || methodName == ""){ + res.send({"ERROR":"ServiceLogic Module Name and method name are required."}); + }else{ + var formatted_date = getCurrentDate(); + //console.log("moduleName:" + moduleName); + //console.log("methodName:" + methodName); + + //var fileName=moduleName + "_method_" +methodName + ".json"; + //var renameOldfileTo=moduleName + "_method_" +methodName+ "_" + formatted_date + ".json"; + var fileName=moduleName + "_" +methodName + ".json"; + var renameOldfileTo=moduleName + "_" +methodName+ "_" + formatted_date + ".json"; + var file = sharedDir + "/" + fileName; + //console.log("fileName:" + fileName); + var renameFilePath = sharedDir + "/backups/" + renameOldfileTo; + //console.log("localfile:" + localfile); + fs.rename(file,renameFilePath, function (err) { + if(err){ + console.log('Error :' + err); + } + //write the newer version + writeToFile(file,jsonStr); + res.setHeader('Content-disposition', 'attachment; filename=' + fileName); + res.setHeader('Content-type', 'application/json'); + //res.download(file); + res.end(jsonStr); + }); + } + }); + }); + + app.post("/flows", + express.json({'limit':'16mb'}), + function(req,res) { + //console.log("Processing Request"); + var flows = req.body; + redNodes.setFlows(flows).then(function() { + res.send(204); + }).otherwise(function(err) { + util.log("[red] Error saving flows : "+err); + res.send(500,err.message); + }); + }, + function(error,req,res,next) { + res.send(400,"Invalid Flow. Error " + error); + } + ); + + app.get("/nodes",function(req,res) { + if (req.get("accept") == "application/json") { + res.json(redNodes.getNodeList()); + } else { + res.send(redNodes.getNodeConfigs()); + } + }); + + app.post("/nodes", + express.json(), + function(req,res) { + if (!settings.available()) { + res.send(400,new Error("Settings unavailable").toString()); + return; + } + var node = req.body; + var promise; + if (node.file) { + promise = redNodes.addNode(node.file).then(reportAddedModules); + } else if (node.module) { + var module = redNodes.getNodeModuleInfo(node.module); + if (module) { + res.send(400,"Module already loaded"); + return; + } + promise = installModule(node.module); + } else { + res.send(400,"Invalid request"); + return; + } + promise.then(function(info) { + res.json(info); + }).otherwise(function(err) { + if (err.code === 404) { + res.send(404); + } else { + res.send(400,err.toString()); + } + }); + }, + function(err,req,res,next) { + console.log(err.toString()); + res.send(400,err); + } + ); + + app.delete("/nodes/:id", + function(req,res) { + if (!settings.available()) { + res.send(400,new Error("Settings unavailable").toString()); + return; + } + var id = req.params.id; + var removedNodes = []; + try { + var node = redNodes.getNodeInfo(id); + var promise = null; + if (!node) { + var module = redNodes.getNodeModuleInfo(id); + if (!module) { + res.send(404); + return; + } else { + promise = uninstallModule(id); + } + } else { + promise = when.resolve([redNodes.removeNode(id)]).then(reportRemovedModules); + } + + promise.then(function(removedNodes) { + res.json(removedNodes); + }).otherwise(function(err) { + console.log(err.stack); + res.send(400,err.toString()); + }); + } catch(err) { + res.send(400,err.toString()); + } + }, + function(err,req,res,next) { + res.send(400,err); + } + ); + + app.get("/nodes/:id", function(req,res) { + var id = req.params.id; + var result = null; + if (req.get("accept") == "application/json") { + result = redNodes.getNodeInfo(id); + } else { + result = redNodes.getNodeConfig(id); + } + if (result) { + res.send(result); + } else { + res.send(404); + } + }); + + app.put("/nodes/:id", + express.json(), + function(req,res) { + if (!settings.available()) { + res.send(400,new Error("Settings unavailable").toString()); + return; + } + var body = req.body; + if (!body.hasOwnProperty("enabled")) { + res.send(400,"Invalid request"); + return; + } + try { + var info; + var id = req.params.id; + var node = redNodes.getNodeInfo(id); + if (!node) { + res.send(404); + } else if (!node.err && node.enabled === body.enabled) { + res.json(node); + } else { + if (body.enabled) { + info = redNodes.enableNode(id); + } else { + info = redNodes.disableNode(id); + } + if (info.enabled == body.enabled && !info.err) { + comms.publish("node/"+(body.enabled?"enabled":"disabled"),info,false); + util.log("[red] "+(body.enabled?"Enabled":"Disabled")+" node types:"); + for (var i=0;i<info.types.length;i++) { + util.log("[red] - "+info.types[i]); + } + } else if (body.enabled && info.err) { + util.log("[red] Failed to enable node:"); + util.log("[red] - "+info.name+" : "+info.err); + } + res.json(info); + } + } catch(err) { + res.send(400,err.toString()); + } + } + ); + app.get("/getCodeCloudFlows",function(req,res) { + var userDir=settings.userDir; + var codeCloudDir=userDir + "/codecloud"; + var glob = require("glob") + glob(codeCloudDir + "/**/*.json", null, function (er, files) { + // files is an array of filenames. + // If the `nonull` option is set, and nothing + // was found, then files is ["**/*.js"] + // er is an error object or null. + //console.dir(files); + var filesList =[]; + for(var i=0;files!= null && i<files.length;i++){ + var f = files[i].replace( new RegExp(codeCloudDir + "/", "g" ), "" ); + filesList.push(f); + + } + res.json({"files" : filesList}); + }); + }); + + app.get("/getCurrentGitBranch",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir=settings.userDir; + var settingsFile = appDir + "/" + userDir + "/customSettings.js"; + //console.log("settingsFile:" + settingsFile); + var jsonObj = require(settingsFile); + var gitLocalRepository=jsonObj.gitLocalRepository; + if(gitLocalRepository == undefined || gitLocalRepository == null || gitLocalRepository == ''){ + res.json({"output" : "GIT_LOCAL_REPOSITORY_NOT_SET"}); + return; + } + var exec = require('child_process').exec; + var commandToExec = appDir + "/git_scripts/gitcurbranch " + gitLocalRepository ; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + console.log("stderr:" + stderr); + res.json({"output":stderr}); + }else{ + res.json({"output":error}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + res.json({"output":stdout}); + } + } + }); + + }); + + app.get("/getGitLocalFlows",function(req,res) { + var appDir = path.dirname(require.main.filename); + var userDir=settings.userDir; + var settingsFile = appDir + "/" + userDir + "/customSettings.js"; + //console.log("settingsFile:" + settingsFile); + var jsonObj = require(settingsFile); + var performGitPull = jsonObj.performGitPull; + if(performGitPull == undefined || performGitPull == null) { + performGitPull="N"; + } + var gitLocalRepository=jsonObj.gitLocalRepository; + if(gitLocalRepository == undefined || gitLocalRepository == null || gitLocalRepository == ''){ + res.json({"files" : ["GIT_LOCAL_REPOSITORY_NOT_SET"]}); + return; + + } + + if(performGitPull == "Y"){ + var exec = require('child_process').exec; + var commandToExec = appDir + "/git_scripts/gitpull " + gitLocalRepository ; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + if(stderr){ + console.log("stderr:" + stderr); + res.json({"files":[]}); + }else{ + res.json({"files":[]}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + var glob = require("glob") + glob(gitLocalRepository + "/**/*.json", null, function (er, files) { + // files is an array of filenames. + // If the `nonull` option is set, and nothing + // was found, then files is ["**/*.js"] + // er is an error object or null. + //console.dir(files); + var filesList =[]; + for(var i=0;files!= null && i<files.length;i++){ + var f = files[i].replace( new RegExp(gitLocalRepository + "/", "g" ), "" ); + filesList.push(f); + + } + res.json({"files" : filesList}); + }); + } + } + }); + }else{//git pull not requested + var glob = require("glob") + glob(gitLocalRepository + "/**/*.json", null, function (er, files) { + // files is an array of filenames. + // If the `nonull` option is set, and nothing + // was found, then files is ["**/*.js"] + // er is an error object or null. + //console.dir(files); + var filesList =[]; + for(var i=0;files!= null && i<files.length;i++){ + var f = files[i].replace( new RegExp(gitLocalRepository + "/", "g" ), "" ); + filesList.push(f); + + } + res.json({"files" : filesList}); + }); + } + + }); + + app.get("/flowShareUsers",function(req,res) { + res.json(flowShareUsers); + }); + app.get("/getRelease",function(req,res) { + var userDir = settings.userDir; + //var release = userDir.replace(/releases/g,"release"); + res.json({"release" : userDir}); + }); + app.post("/getFiles/:id",function(req,res) { + var id = req.params.id; + //console.log("id:" + id); + var userDir=settings.userDir; + var flowDir= userDir + "/../" + id + "/flows/shared"; + //console.log("flowDir:" + flowDir); + fs.readdir(flowDir,function(err, files){ + if(err){ + res.json({"files": []}); + }else{ + var onlyFilesArr =[]; + if(files != null && files.length>0){ + files.sort(function(a,b){ + //console.log("file1:" + a); + //console.log("file2:" + b); + var fileStat1=fs.statSync(flowDir+ "/" + a); + var fileStat2=fs.statSync(flowDir+ "/" + b); + if(fileStat1.mtime > fileStat2.mtime){ + return 1; + }else if(fileStat1.mtime < fileStat2.mtime){ + return -1; + }else{ + return 0; + } + }); + for(var i=0;i<files.length;i++){ + var fileStat=fs.statSync(flowDir+ "/" + files[i]); + if(fileStat.isFile()){ + onlyFilesArr.push({"filePath":flowDir+ "/" + files[i],"name":files[i]}); + } + } + res.json(onlyFilesArr); + }else{ + res.json({"files": []}); + } + } + }); + }); + + app.post("/updateConfiguration", + express.json(), + function(req,res) { + var qs = require('querystring'); + //console.log("Received the request:"); + var body =""; + req.on('data', function (data) { + body += data; + }); + req.on('end',function(){ + var post = qs.parse(body); + var dbHost = post["dbHost"]; + var dbPort = post["dbPort"]; + var dbName = post["dbName"]; + var dbUser = post["dbUser"]; + var dbPassword = post["dbPassword"]; + var gitLocalRepository = post["gitLocalRepository"]; + var performGitPull = post["performGitPull"]; + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + console.log("userDir:" + userDir); + try{ + var settingsFile = userDir + "/customSettings.js"; + var jsonObj = require(settingsFile); + jsonObj.flowFile = jsonObj.flowFile.replace(appDir + "/",''); + jsonObj.dbHost = dbHost; + jsonObj.dbPort = dbPort; + jsonObj.dbName = dbName; + jsonObj.dbUser = dbUser; + jsonObj.dbPassword = dbPassword; + jsonObj.gitLocalRepository = gitLocalRepository; + jsonObj.performGitPull = performGitPull; + var updatedSettings = jsonObj; + + var settingsStr= "module.exports=" + JSON.stringify(updatedSettings,null,4); + //console.log("settingsStr:" + settingsStr); + fs.writeFileSync(settingsFile,settingsStr); + var svcLogicPropStr = "" ; + svcLogicPropStr += "org.onap.ccsdk.sli.dbtype=jdbc" + "\n"; + svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.url=jdbc:mysql://" + dbHost + ":" + dbPort + "/" + dbName + "\n"; + svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.database=" + dbName + "\n"; + svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.user=" + dbUser + "\n"; + svcLogicPropStr += "org.onap.ccsdk.sli.jdbc.password=" + dbPassword; + + //create svclogic.properties file in the conf dir + var svcPropFile = userDir + "/conf/svclogic.properties"; + fs.writeFileSync(svcPropFile,svcLogicPropStr); + + res.send({"status": "success"}); + }catch(e){ + console.log("Error:" + e); + res.send({"status": "error"}); + } + }); + } + ); + + app.post("/deleteYangFile", + express.json(), + function(req,res) { + var qs = require('querystring'); + //console.log("Received the request:"); + var body =""; + req.on('data', function (data) { + body += data; + }); + req.on('end',function(){ + var post = qs.parse(body); + //console.dir(body); + var fileName = post["fileName"]; + var appDir = path.dirname(require.main.filename); + var yangFilePath = appDir + "/yangFiles/" + fileName; + try{ + fs.unlinkSync(yangFilePath); + res.send({"status" :"SUCCESS"}); + }catch(err){ + console.log("error" + err); + res.send({"status" :"ERROR"}); + } + //console.log("prevPassword:" + settings.httpAuth.pass ); + }); + } + ); + + app.post("/updatePassword", + express.json(), + function(req,res) { + var qs = require('querystring'); + //console.log("Received the request:"); + var body =""; + req.on('data', function (data) { + body += data; + }); + req.on('end',function(){ + var post = qs.parse(body); + //console.dir(body); + var password = post["password"]; + //console.log("prevPassword:" + settings.httpAuth.pass ); + //console.log("New password:" + password); + var crypto = require("crypto"); + var cryptPasswd = crypto.createHash('md5').update(password,'utf8').digest('hex') + var appDir = path.dirname(require.main.filename); + var userDir = appDir + "/" + settings.userDir; + //console.log("userDir:" + userDir); + /*var newSettings = settings; + newSettings.httpAuth.pass = cryptPasswd; + var updatedSettings = JSON.stringify(settings,null,4); + var settingsStr = "module.exports=" + updatedSettings; + console.log(updatedSettings); + */ + try{ + var settingsFile = userDir + "/customSettings.js"; + //console.log("settingsFile:" + settingsFile); + //var buf = fs.readFileSync(settingsFile, "utf8"); + var jsonObj = require(settingsFile); + //console.log("jsonObj:" + JSON.stringify(jsonObj)); + jsonObj.httpAuth.pass = cryptPasswd; + jsonObj.httpAdminAuth.pass = cryptPasswd; + jsonObj.httpNodeAuth.pass = cryptPasswd; + jsonObj.flowFile = jsonObj.flowFile.replace(appDir + "/",''); + var updatedSettings = jsonObj; + /* + delete updatedSettings.httpRoot; + delete updatedSettings.disableEditor; + delete updatedSettings.httpAdminRoot; + delete updatedSettings.httpAdminAuth; + delete updatedSettings.httpNodeRoot; + delete updatedSettings.httpNodeAuth; + delete updatedSettings.uiHost; + delete updatedSettings.version; + */ + var settingsStr= "module.exports=" + JSON.stringify(updatedSettings,null,4); + //console.log("settingsStr:" + settingsStr); + fs.writeFileSync(settingsFile,settingsStr); + settings.httpAuth.pass = cryptPasswd; + res.send({"status": "success"}); + }catch(e){ + console.log("Error:" + e); + res.send({"status": "error"}); + } + }); + } + ); + + var appDir = path.dirname(require.main.filename); + var yangDir = appDir + "/yangFiles" ; + var diskStorage = multer.diskStorage({ + destination: function (req, file, callback) { + callback(null, yangDir); + }, + filename: function (req, file, callback) { + //callback(null, file.fieldname + '-' + Date.now()); + callback(null, file.originalname); + } + }); + var upload = multer({ storage : diskStorage}).single('yangFile'); + + app.post('/api/uploadyang',function(req,res){ + upload(req,res,function(err) { + if(err) { + console.log(err); + return res.end("Error uploading file." + err); + } + //console.dir(req); + var fileName = req.file.originalname; + var yangFileFullPath = appDir + "/yangFiles/" + fileName; + console.log("yangFileFullPath:" + yangFileFullPath); + var commandToExec =""; + if(fileName != null){ + var matchedArr = fileName.match(/.zip$/); + if(matchedArr != null && matchedArr.length >0){ + console.log("uploaded zip file" + fileName); + //commandToExec = appDir + "/tools/generate_props_from_yangs_zip.sh " + yangFileFullPath ; + commandToExec = appDir + "/tools/generate_props_from_yang.sh " + yangFileFullPath ; + }else{ + commandToExec = appDir + "/tools/generate_props_from_yang.sh " + yangFileFullPath ; + console.log("uploaded file" + fileName); + } + } + var exec = require('child_process').exec; + console.log("commandToExec:" + commandToExec); + var child = exec(commandToExec ,function (error,stdout,stderr){ + if(error){ + console.log("Error occured:" + error); + var msg = "File " + fileName + " could not be processed successfully."; + if(stderr){ + console.log("stderr:" + stderr); + res.json({"sliValuesObj" : [],"message":msg}); + }else{ + res.json({"sliValuesObj" : [],"message":msg}); + } + }else{ + if(stderr){ + console.log("stderr:" + stderr); + } + if(stdout){ + console.log("stdout:" + stdout); + } + var msg = "File " + fileName + " processed successfully."; + var generatedJSDir=appDir + "/generatedJS"; + var sliValuesObj =[]; + //var glob = require("glob"); + //glob(generatedJSDir + "/**/*.js", null, function (er, files) { + /* + var sliValuesObj =[]; + for(var i=0;files!= null && i<files.length;i++){ + var f = files[i].replace( new RegExp(generatedJSDir + "/", "g" ), "" ); + console.log("loading file " + f); + try{ + sliValuesObj.push(require(files[i])); + //console.dir(sliValuesObj); + }catch(err){ + console.log("Error:Could not load file " + files[i]); + } + } + res.json({"sliValuesObj" : sliValuesObj,"message":msg}); + }); + */ + res.json({"sliValuesObj" : sliValuesObj,"message":msg}); + } + }); + }); + }); + app.get("/getYangFiles",function(req,res) { + var appDir = path.dirname(require.main.filename); + var yangFilesDir=appDir + "/yangFiles"; + var glob = require("glob") + glob(yangFilesDir + "/**/*.yang", null, function (er, files) { + var filesList =[]; + for(var i=0;files!= null && i<files.length;i++){ + var f = files[i].replace( new RegExp(yangFilesDir + "/", "g" ), "" ); + filesList.push(f); + + } + res.json({"files" : filesList}); + }); + }); + } +} + +function reportAddedModules(info) { + comms.publish("node/added",info,false); + if (info.length > 0) { + util.log("[red] Added node types:"); + for (var i=0;i<info.length;i++) { + for (var j=0;j<info[i].types.length;j++) { + util.log("[red] - "+ + (info[i].module?info[i].module+":":"")+ + info[i].types[j]+ + (info[i].err?" : "+info[i].err:"") + ); + } + } + } + return info; +} + +function reportRemovedModules(removedNodes) { + comms.publish("node/removed",removedNodes,false); + util.log("[red] Removed node types:"); + for (var j=0;j<removedNodes.length;j++) { + for (var i=0;i<removedNodes[j].types.length;i++) { + util.log("[red] - "+(removedNodes[i].module?removedNodes[i].module+":":"")+removedNodes[j].types[i]); + } + } + return removedNodes; +} + +function installModule(module) { + //TODO: ensure module is 'safe' + return when.promise(function(resolve,reject) { + if (/[\s;]/.test(module)) { + reject(new Error("Invalid module name")); + return; + } + util.log("[red] Installing module: "+module); + var child = exec('npm install --production '+module, function(err, stdin, stdout) { + if (err) { + var lookFor404 = new RegExp(" 404 .*"+module+"$","m"); + if (lookFor404.test(stdout)) { + util.log("[red] Installation of module "+module+" failed: module not found"); + var e = new Error(); + e.code = 404; + reject(e); + } else { + util.log("[red] Installation of module "+module+" failed:"); + util.log("------------------------------------------"); + console.log(err.toString()); + util.log("------------------------------------------"); + reject(new Error("Install failed")); + } + } else { + util.log("[red] Installed module: "+module); + resolve(redNodes.addModule(module).then(reportAddedModules)); + } + }); + }); +} + +function uninstallModule(module) { + var list = redNodes.removeModule(module); + return when.promise(function(resolve,reject) { + if (/[\s;]/.test(module)) { + reject(new Error("Invalid module name")); + return; + } + util.log("[red] Removing module: "+module); + var child = exec('npm remove '+module, function(err, stdin, stdout) { + if (err) { + util.log("[red] Removal of module "+module+" failed:"); + util.log("------------------------------------------"); + console.log(err.toString()); + util.log("------------------------------------------"); + reject(new Error("Removal failed")); + } else { + util.log("[red] Removed module: "+module); + reportRemovedModules(list); + resolve(list); + } + }); + }); +} + +function start() { + var defer = when.defer(); + + storage.init(settings).then(function() { + settings.load(storage).then(function() { + console.log("\nWelcome to Node-RED\n===================\n"); + if (settings.version) { + util.log("[red] Version: "+settings.version); + } + util.log("[red] Loading palette nodes"); + redNodes.init(settings,storage); + redNodes.load().then(function() { + var i; + var nodes = redNodes.getNodeList(); + var nodeErrors = nodes.filter(function(n) { return n.err!=null;}); + var nodeMissing = nodes.filter(function(n) { return n.module && n.enabled && !n.loaded && !n.err;}); + if (nodeErrors.length > 0) { + util.log("------------------------------------------"); + if (settings.verbose) { + for (i=0;i<nodeErrors.length;i+=1) { + util.log("["+nodeErrors[i].name+"] "+nodeErrors[i].err); + } + } else { + util.log("[red] Failed to register "+nodeErrors.length+" node type"+(nodeErrors.length==1?"":"s")); + util.log("[red] Run with -v for details"); + } + util.log("------------------------------------------"); + } + if (nodeMissing.length > 0) { + util.log("[red] Missing node modules:"); + var missingModules = {}; + for (i=0;i<nodeMissing.length;i++) { + var missing = nodeMissing[i]; + missingModules[missing.module] = (missingModules[missing.module]||[]).concat(missing.types); + } + var promises = []; + for (i in missingModules) { + if (missingModules.hasOwnProperty(i)) { + util.log("[red] - "+i+": "+missingModules[i].join(", ")); + if (settings.autoInstallModules) { + installModule(i).otherwise(function(err) { + // Error already reported. Need the otherwise handler + // to stop the error propagating any further + }); + } + } + } + if (!settings.autoInstallModules) { + util.log("[red] Removing modules from config"); + redNodes.cleanNodeList(); + } + } + defer.resolve(); + + redNodes.loadFlows(); + }).otherwise(function(err) { + console.log(err); + }); + comms.start(); + }); + }).otherwise(function(err) { + defer.reject(err); + }); + + return defer.promise; +} + +function stop() { + redNodes.stopFlows(); + comms.stop(); +} + +module.exports = { + init: createServer, + start: start, + stop: stop +} + +module.exports.__defineGetter__("app", function() { return app }); +module.exports.__defineGetter__("nodeApp", function() { return nodeApp }); +module.exports.__defineGetter__("server", function() { return server }); diff --git a/dgbuilder/red/settings.js b/dgbuilder/red/settings.js new file mode 100644 index 00000000..4994953f --- /dev/null +++ b/dgbuilder/red/settings.js @@ -0,0 +1,84 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var when = require("when"); + +var assert = require("assert"); + +var userSettings = null; +var globalSettings = null; +var storage = null; + +var persistentSettings = { + init: function(settings) { + userSettings = settings; + + for (var i in settings) { + if (settings.hasOwnProperty(i)) { + (function() { + var j = i; + persistentSettings.__defineGetter__(j,function() { return userSettings[j]; }); + persistentSettings.__defineSetter__(j,function() { throw new Error("Property '"+i+"' is read-only"); }); + })(); + } + } + globalSettings = null; + }, + load: function(_storage) { + storage = _storage; + return storage.getSettings().then(function(_settings) { + globalSettings = _settings; + }); + }, + get: function(prop) { + if (userSettings.hasOwnProperty(prop)) { + return userSettings[prop]; + } + if (globalSettings === null) { + throw new Error("Settings not available"); + } + return globalSettings[prop]; + }, + + set: function(prop,value) { + if (userSettings.hasOwnProperty(prop)) { + throw new Error("Property '"+prop+"' is read-only"); + } + if (globalSettings === null) { + throw new Error("Settings not available"); + } + var current = globalSettings[prop]; + globalSettings[prop] = value; + try { + assert.deepEqual(current,value); + return when.resolve(); + } catch(err) { + return storage.saveSettings(globalSettings); + } + }, + + available: function() { + return (globalSettings !== null); + }, + + reset: function() { + userSettings = null; + globalSettings = null; + storage = null; + } +} + +module.exports = persistentSettings; diff --git a/dgbuilder/red/sla.js b/dgbuilder/red/sla.js new file mode 100644 index 00000000..1729ecbb --- /dev/null +++ b/dgbuilder/red/sla.js @@ -0,0 +1,249 @@ +exports.listSLA = function(settings,req,res) { +try{ + var mysql = require('mysql'); + + //console.dir(settings); + + var connection = mysql.createConnection( + { + host : settings.dbHost, + port : settings.dbPort, + user : settings.dbUser, + password : settings.dbPassword, + database : settings.dbName + }); + + var rows=[]; + + var sqlQuery = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC"; + //console.log("sqlQuery:" + sqlQuery); + connection.query(sqlQuery, function(err, rows) { + if(!err) { + if ( rows.length > 0 ) + { + res.send({ 'rows': rows,'dbHost':settings.dbHost } ); + }else{ + res.send({'rows': [],'dbHost':settings.dbHost}); + } + } else { + console.log("error:" + err); + res.send({error: "Connection to DB failed.",'dbHost':settings.dbHost}); + } + //console.dir(rows); + connection.end(); + }); //end query +}catch(error){ + console.log(error); + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); +} +} + +exports.listCurrentDGs = function(settings,req,res) { + var _module = req.query.module; + var rpc = req.query.rpc; + console.log("_module:" + _module); + console.log("rpc:" + rpc); +try{ + var mysql = require('mysql'); + + //console.dir(settings); + + var connection = mysql.createConnection( + { + host : settings.dbHost, + port : settings.dbPort, + user : settings.dbUser, + password : settings.dbPassword, + database : settings.dbName + }); + + var rows=[]; + + var sqlQuery = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC where module ='" + _module + "' and rpc ='" + rpc + "'"; + console.log("sqlQuery:" + sqlQuery); + connection.query(sqlQuery, function(err, rows) { + if(!err) { + if ( rows.length > 0 ) + { + res.send({ 'rows': rows,'dbHost':settings.dbHost } ); + }else{ + res.send({'rows': [],'dbHost':settings.dbHost}); + } + } else { + console.log("error:" + err); + res.send({error: "Connection to DB failed.",'dbHost':settings.dbHost}); + } + //console.dir(rows); + connection.end(); + }); //end query +}catch(error){ + console.log(error); + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); +} +} + +exports.activateDG = function(settings,req,res){ + var _module = req.query.module; + var rpc = req.query.rpc; + var version = req.query.version; + var mode = req.query.mode; + var displayOnlyCurrent = req.query.displayOnlyCurrent; + +try{ + var mysql = require('mysql'); + + var connection = mysql.createConnection( + { + host : settings.dbHost, + port : settings.dbPort, + user : settings.dbUser, + password : settings.dbPassword, + database : settings.dbName + }); + + var rows=[]; + + var updateStmt = "UPDATE SVC_LOGIC SET active=\'Y\' WHERE module=\'" + + _module + "' AND rpc=\'" + + rpc + "' AND version=\'" + + version + "' AND mode=\'" + + mode + "'"; + + connection.query(updateStmt, function(err, result) { + var nextUpdateStmt = "UPDATE SVC_LOGIC SET active=\'N\' WHERE module=\'" + + _module + "' AND rpc=\'" + + rpc + "' AND version !=\'" + + version + "'"; + connection.query(nextUpdateStmt, function(err, result) { + var query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC"; + if(displayOnlyCurrent == 'true'){ + query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC WHERE module=\'" + + _module + "' and rpc=\'" + rpc + "'"; + } + connection.query(query, function(err, rows) { + if(!err) { + if ( rows.length > 0 ) + { + res.send({ 'rows': rows,'dbHost':settings.dbHost } ); + }else{ + res.send({'rows': [],'dbHost':settings.dbHost}); + } + } else { + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); + } + connection.end(); + }); //end query + }); //end query + }); //end query +}catch(error){ + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); +} +} + + +exports.deActivateDG = function(settings,req,res){ + + var _module = req.query.module; + var rpc = req.query.rpc; + var version = req.query.version; + var mode = req.query.mode; + var displayOnlyCurrent = req.query.displayOnlyCurrent; + +try{ + var mysql = require('mysql'); + + var connection = mysql.createConnection( + { + host : settings.dbHost, + port : settings.dbPort, + user : settings.dbUser, + password : settings.dbPassword, + database : settings.dbName + }); + + var rows=[]; + + var updateStmt = "UPDATE SVC_LOGIC SET active=\'N\' WHERE module=\'" + + _module + "' AND rpc=\'" + + rpc + "' AND version=\'" + + version + "' AND mode=\'" + + mode + "'"; + + connection.query(updateStmt, function(err, result) { + var query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC"; + if(displayOnlyCurrent == 'true'){ + query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC WHERE module=\'" + + _module + "' and rpc=\'" + rpc + "'"; + } + connection.query(query, function(err, rows) { + if(!err) { + if ( rows.length > 0 ) + { + res.send({ 'rows': rows,'dbHost':settings.dbHost } ); + }else{ + res.send({'rows': [],'dbHost':settings.dbHost}); + } + } else { + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); + } + connection.end(); + }); //end query + }); //end query +}catch(error){ + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); +} +} + +exports.deleteDG = function(settings,req,res){ + + var _module = req.query.module; + var rpc = req.query.rpc; + var version = req.query.version; + var mode = req.query.mode; + var displayOnlyCurrent = req.query.displayOnlyCurrent; + +try{ + var mysql = require('mysql'); + + var connection = mysql.createConnection( + { + host : settings.dbHost, + port : settings.dbPort, + user : settings.dbUser, + password : settings.dbPassword, + database : settings.dbName + }); + + var rows=[]; + + var deleteStmt = "DELETE FROM SVC_LOGIC WHERE module=\'" + + _module + "' AND rpc=\'" + + rpc + "' AND version=\'" + + version + "' AND mode=\'" + + mode + "'"; + console.log(deleteStmt); + + connection.query(deleteStmt, function(err, result) { + var query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC"; + if(displayOnlyCurrent == 'true'){ + query = "SELECT module,rpc,version,mode,active FROM SVC_LOGIC WHERE module=\'" + + _module + "' and rpc=\'" + rpc + "'"; + } + connection.query(query, function(err, rows) { + if(!err) { + if ( rows.length > 0 ) + { + res.send({ 'rows': rows,'dbHost':settings.dbHost } ); + }else{ + res.send({'rows': [],'dbHost':settings.dbHost}); + } + } else { + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); + } + connection.end(); + }); //end query + }); //end query +}catch(error){ + res.send({'error': "Connection to DB failed.",'dbHost':settings.dbHost}); +} +} diff --git a/dgbuilder/red/storage/index.js b/dgbuilder/red/storage/index.js new file mode 100644 index 00000000..ba939627 --- /dev/null +++ b/dgbuilder/red/storage/index.js @@ -0,0 +1,107 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var when = require('when'); + +var storageModule; +var settingsAvailable; + +function moduleSelector(aSettings) { + var toReturn; + if (aSettings.storageModule) { + if (typeof aSettings.storageModule === "string") { + // TODO: allow storage modules to be specified by absolute path + toReturn = require("./"+aSettings.storageModule); + } else { + toReturn = aSettings.storageModule; + } + } else { + toReturn = require("./localfilesystem"); + } + return toReturn; +} + +function is_malicious(path) { + return path.indexOf('../') != -1 || path.indexOf('..\\') != -1; +} + +var storageModuleInterface = { + init: function(settings) { + try { + storageModule = moduleSelector(settings); + settingsAvailable = storageModule.hasOwnProperty("getSettings") && storageModule.hasOwnProperty("saveSettings"); + } catch (e) { + return when.reject(e); + } + return storageModule.init(settings); + }, + getFlows: function() { + return storageModule.getFlows(); + }, + saveFlows: function(flows) { + return storageModule.saveFlows(flows); + }, + getCredentials: function() { + return storageModule.getCredentials(); + }, + saveCredentials: function(credentials) { + return storageModule.saveCredentials(credentials); + }, + getSettings: function() { + if (settingsAvailable) { + return storageModule.getSettings(); + } else { + return when.resolve(null); + } + }, + saveSettings: function(settings) { + if (settingsAvailable) { + return storageModule.saveSettings(settings); + } else { + return when.resolve(); + } + }, + /* Library Functions */ + getAllFlows: function() { + return storageModule.getAllFlows(); + }, + getFlow: function(fn) { + if (is_malicious(fn)) { + return when.reject(new Error('forbidden flow name')); + } + return storageModule.getFlow(fn); + }, + saveFlow: function(fn, data) { + if (is_malicious(fn)) { + return when.reject(new Error('forbidden flow name')); + } + return storageModule.saveFlow(fn, data); + }, + getLibraryEntry: function(type, path) { + if (is_malicious(path)) { + return when.reject(new Error('forbidden flow name')); + } + return storageModule.getLibraryEntry(type, path); + }, + saveLibraryEntry: function(type, path, meta, body) { + if (is_malicious(path)) { + return when.reject(new Error('forbidden flow name')); + } + return storageModule.saveLibraryEntry(type, path, meta, body); + } +} + +module.exports = storageModuleInterface; diff --git a/dgbuilder/red/storage/localfilesystem.js b/dgbuilder/red/storage/localfilesystem.js new file mode 100644 index 00000000..48255332 --- /dev/null +++ b/dgbuilder/red/storage/localfilesystem.js @@ -0,0 +1,309 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var fs = require('fs'); +var when = require('when'); +var nodeFn = require('when/node/function'); +var keys = require('when/keys'); +var util = require('util'); +var fspath = require("path"); +var mkdirp = require("mkdirp"); + +var promiseDir = nodeFn.lift(mkdirp); + +var settings; +var flowsFile; +var flowsFullPath; +var flowsPrev; +var credentialsFile; +var oldCredentialsFile; +var userDir; +var libDir; +var libFlowsDir; +var globalSettingsFile; + +function listFiles(dir) { + var dirs = {}; + var files = []; + var dirCount = 0; + return nodeFn.call(fs.readdir, dir).then(function (contents) { + contents.sort().forEach(function(fn) { + var stats = fs.lstatSync(dir+"/"+fn); + if (stats.isDirectory()) { + dirCount += 1; + dirs[fn] = listFiles(dir+"/"+fn) + } else { + files.push(fn.split(".")[0]); + } + }) + var result = {}; + if (dirCount > 0) { result.d = keys.all(dirs); } + if (files.length > 0) { result.f = when.resolve(files); } + return keys.all(result); + }) +} + +function getFileMeta(root,path) { + var fn = fspath.join(root,path); + var fd = fs.openSync(fn,"r"); + var size = fs.fstatSync(fd).size; + var meta = {}; + var read = 0; + var length = 10; + var remaining = ""; + var buffer = Buffer(length); + while(read < size) { + read+=fs.readSync(fd,buffer,0,length); + var data = remaining+buffer.toString(); + var parts = data.split("\n"); + remaining = parts.splice(-1); + for (var i=0;i<parts.length;i+=1) { + var match = /^\/\/ (\w+): (.*)/.exec(parts[i]); + if (match) { + meta[match[1]] = match[2]; + } else { + read = size; + break; + } + } + } + fs.closeSync(fd); + return meta; +} + +function getFileBody(root,path) { + var body = ""; + var fn = fspath.join(root,path); + var fd = fs.openSync(fn,"r"); + var size = fs.fstatSync(fd).size; + var scanning = true; + var read = 0; + var length = 50; + var remaining = ""; + var buffer = Buffer(length); + while(read < size) { + var thisRead = fs.readSync(fd,buffer,0,length); + read += thisRead; + if (scanning) { + var data = remaining+buffer.slice(0,thisRead).toString(); + var parts = data.split("\n"); + remaining = parts.splice(-1)[0]; + for (var i=0;i<parts.length;i+=1) { + if (! /^\/\/ \w+: /.test(parts[i])) { + scanning = false; + body += parts[i]+"\n"; + } + } + if (! /^\/\/ \w+: /.test(remaining)) { + scanning = false; + } + if (!scanning) { + body += remaining; + } + } else { + body += buffer.slice(0,thisRead).toString(); + } + } + fs.closeSync(fd); + return body; +} + +var localfilesystem = { + init: function(_settings) { + settings = _settings; + userDir = settings.userDir || process.env.NODE_RED_HOME; + + if (settings.flowFile) { + flowsFile = settings.flowFile; + flowsFullPath = flowsFile; + } else { + flowsFile = 'flows_'+require('os').hostname()+'.json'; + flowsFullPath = fspath.join(userDir,flowsFile); + } + var fsext = fspath.extname(flowsFile); + credentialsFile = fspath.join(userDir,fspath.basename(flowsFile,fsext)+"_cred"+fsext); + oldCredentialsFile = fspath.join(userDir,"credentials.json"); + flowsPrev = fspath.join(userDir,"flows.backup"); + + libDir = fspath.join(userDir,"lib"); + libFlowsDir = fspath.join(libDir,"flows"); + + + globalSettingsFile = fspath.join(userDir,".config.json"); + + return promiseDir(libFlowsDir); + }, + + getFlows: function() { + var defer = when.defer(); + fs.exists(flowsFullPath, function(exists) { + if (exists) { + util.log("[red] Loading flows : "+flowsFile); + defer.resolve(nodeFn.call(fs.readFile,flowsFullPath,'utf8').then(function(data) { + return JSON.parse(data); + })); + } else { + util.log("[red] Flows file not found : "+flowsFile ); + defer.resolve([]); + } + }); + return defer.promise; + }, + + saveFlows: function(flows) { + if (fs.existsSync(flowsFullPath)) { + fs.renameSync(flowsFullPath,flowsPrev); + } + + var flowData; + + if (settings.flowFilePretty) { + flowData = JSON.stringify(flows,null,4); + } else { + flowData = JSON.stringify(flows); + } + console.log("Writing to file:" + flowsFullPath); + return nodeFn.call(fs.writeFile, flowsFullPath, flowData); + }, + + getCredentials: function() { + var defer = when.defer(); + fs.exists(credentialsFile, function(exists) { + if (exists) { + defer.resolve(nodeFn.call(fs.readFile, credentialsFile, 'utf8').then(function(data) { + return JSON.parse(data) + })); + } else { + fs.exists(oldCredentialsFile, function(exists) { + if (exists) { + defer.resolve(nodeFn.call(fs.readFile, oldCredentialsFile, 'utf8').then(function(data) { + return JSON.parse(data) + })); + } else { + defer.resolve({}); + } + }); + } + }); + return defer.promise; + }, + + saveCredentials: function(credentials) { + var credentialData; + if (settings.flowFilePretty) { + credentialData = JSON.stringify(credentials,null,4); + } else { + credentialData = JSON.stringify(credentials); + } + + return nodeFn.call(fs.writeFile, credentialsFile, credentialData) + }, + + getSettings: function() { + if (fs.existsSync(globalSettingsFile)) { + return nodeFn.call(fs.readFile,globalSettingsFile,'utf8').then(function(data) { + if (data) { + try { + return JSON.parse(data); + } catch(err) { + util.log("[red] Corrupted config detected - resetting"); + return {}; + } + } else { + return {}; + } + }); + } + return when.resolve({}); + }, + saveSettings: function(settings) { + return nodeFn.call(fs.writeFile,globalSettingsFile,JSON.stringify(settings,null,1),'utf8'); + }, + + + getAllFlows: function() { + return listFiles(libFlowsDir); + }, + + getFlow: function(fn) { + var defer = when.defer(); + var file = fspath.join(libFlowsDir,fn+".json"); + fs.exists(file, function(exists) { + if (exists) { + defer.resolve(nodeFn.call(fs.readFile,file,'utf8')); + } else { + defer.reject(); + } + }); + return defer.promise; + }, + + saveFlow: function(fn,data) { + var file = fspath.join(libFlowsDir,fn+".json"); + return promiseDir(fspath.dirname(file)).then(function () { + return nodeFn.call(fs.writeFile, file, data); + }); + }, + + getLibraryEntry: function(type,path) { + var root = fspath.join(libDir,type); + var rootPath = fspath.join(libDir,type,path); + return promiseDir(root).then(function () { + return nodeFn.call(fs.lstat, rootPath).then(function(stats) { + if (stats.isFile()) { + return getFileBody(root,path); + } + if (path.substr(-1) == '/') { + path = path.substr(0,path.length-1); + } + return nodeFn.call(fs.readdir, rootPath).then(function(fns) { + var dirs = []; + var files = []; + fns.sort().filter(function(fn) { + var fullPath = fspath.join(path,fn); + var absoluteFullPath = fspath.join(root,fullPath); + if (fn[0] != ".") { + var stats = fs.lstatSync(absoluteFullPath); + if (stats.isDirectory()) { + dirs.push(fn); + } else { + var meta = getFileMeta(root,fullPath); + meta.fn = fn; + files.push(meta); + } + } + }); + return dirs.concat(files); + }); + }); + }); + }, + + saveLibraryEntry: function(type,path,meta,body) { + var fn = fspath.join(libDir, type, path); + var headers = ""; + for (var i in meta) { + if (meta.hasOwnProperty(i)) { + headers += "// "+i+": "+meta[i]+"\n"; + } + } + return promiseDir(fspath.dirname(fn)).then(function () { + nodeFn.call(fs.writeFile, fn, headers+body); + }); + } +}; + +module.exports = localfilesystem; diff --git a/dgbuilder/red/ui.js b/dgbuilder/red/ui.js new file mode 100644 index 00000000..16580bf1 --- /dev/null +++ b/dgbuilder/red/ui.js @@ -0,0 +1,77 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var express = require('express'); +var fs = require("fs"); +var events = require("./events"); +var path = require("path"); + +var icon_paths = [path.resolve(__dirname + '/../public/icons')]; + +var settings; // settings has to be global, otherwise variable not in scope for express + +events.on("node-icon-dir",function(dir) { + icon_paths.push(path.resolve(dir)); +}); + + +function setupUI(_settings,app) { + + settings = _settings; + + // Need to ensure the url ends with a '/' so the static serving works + // with relative paths + app.get("/",function(req,res) { + if (req.originalUrl.slice(-1) != "/") { + res.redirect(req.originalUrl+"/"); + } else { + req.next(); + } + }); + + var iconCache = {}; + //TODO: create a default icon + var defaultIcon = path.resolve(__dirname + '/../public/icons/arrow-in.png'); + + app.get("/icons/:icon",function(req,res) { + if (iconCache[req.params.icon]) { + res.sendfile(iconCache[req.params.icon]); // if not found, express prints this to the console and serves 404 + } else { + for (var p=0;p<icon_paths.length;p++) { + var iconPath = path.join(icon_paths[p],req.params.icon); + if (fs.existsSync(iconPath)) { + res.sendfile(iconPath); + iconCache[req.params.icon] = iconPath; + return; + } + } + res.sendfile(defaultIcon); + } + }); + + app.get("/settings", function(req,res) { + var safeSettings = { + httpNodeRoot: settings.httpNodeRoot, + version: settings.version + }; + res.json(safeSettings); + }); + + app.use("/",express.static(__dirname + '/../public')); + + return app; +} + +module.exports = setupUI; diff --git a/dgbuilder/red/util.js b/dgbuilder/red/util.js new file mode 100644 index 00000000..7ca72b0e --- /dev/null +++ b/dgbuilder/red/util.js @@ -0,0 +1,43 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +function ensureString(o) { + if (Buffer.isBuffer(o)) { + return o.toString(); + } else if (typeof o === "object") { + return JSON.stringify(o); + } else if (typeof o === "string") { + return o; + } + return ""+o; +} + +function ensureBuffer(o) { + if (Buffer.isBuffer(o)) { + return o; + } else if (typeof o === "object") { + o = JSON.stringify(o); + } else if (typeof o !== "string") { + o = ""+o; + } + return new Buffer(o); +} + +module.exports = { + ensureString: ensureString, + ensureBuffer: ensureBuffer, +}; + diff --git a/dgbuilder/releases/sdnc1.0/.config.json b/dgbuilder/releases/sdnc1.0/.config.json new file mode 100644 index 00000000..d5f86c25 --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/.config.json @@ -0,0 +1,228 @@ +{ + "nodes": { + "f01e121fdcca44f4f1d1135f3e68095e1376b7eb": { + "name": "block.js", + "types": [ + "block" + ], + "enabled": true + }, + "717b8f34cf67474d1af03fdd6822bc9ef2e67bc2": { + "name": "call.js", + "types": [ + "call" + ], + "enabled": true + }, + "206bda0ae2599ad0cc8ce121fe7b70b84bf8a366": { + "name": "configure.js", + "types": [ + "configure" + ], + "enabled": true + }, + "4698a1beb7105851d2867245198c6b14f67f3e84": { + "name": "delete.js", + "types": [ + "delete" + ], + "enabled": true + }, + "dea017092a5d56efb769026110177045d8ea3430": { + "name": "execute.js", + "types": [ + "execute" + ], + "enabled": true + }, + "2e1ff0459a9f2572f6d441ee4ffc966835a36e04": { + "name": "exists.js", + "types": [ + "exists" + ], + "enabled": true + }, + "6ecaadc772558adea9aad9d440ee272a92b432f4": { + "name": "forNode.js", + "types": [ + "for" + ], + "enabled": true + }, + "a08ac375f31fb15f59a0df05c496ddd740aa6472": { + "name": "get-resource.js", + "types": [ + "get-resource" + ], + "enabled": true + }, + "39cc8c5b404aa076e5456d62de989bcdd2731f9a": { + "name": "is-available.js", + "types": [ + "is-available" + ], + "enabled": true + }, + "9bea307fd340b01a62086abf3a3940ac77730568": { + "name": "notify.js", + "types": [ + "notify" + ], + "enabled": true + }, + "276c320cd57c858be6dac2c636877648a35aa04c": { + "name": "record.js", + "types": [ + "record" + ], + "enabled": true + }, + "b36c73e0a1c43560d7b29a8959198fe431020ad9": { + "name": "release.js", + "types": [ + "release" + ], + "enabled": true + }, + "dfc45ebbf76658d3e8e73dbfb8bf962057ca2a57": { + "name": "reserve.js", + "types": [ + "reserve" + ], + "enabled": true + }, + "06a4ee60c18fddc68d290826daa18a9991b92919": { + "name": "save.js", + "types": [ + "save" + ], + "enabled": true + }, + "f99370311d57128b2bd1f408365e982c0dbafc46": { + "name": "set.js", + "types": [ + "set" + ], + "enabled": true + }, + "ab2b190a8e0c91eb36aed4f7fe25aef0c1019e9d": { + "name": "switchNode.js", + "types": [ + "switchNode" + ], + "enabled": true + }, + "d14d57596f9c543889e37fd44b83ae179224ec28": { + "name": "update.js", + "types": [ + "update" + ], + "enabled": true + }, + "28591694ec8869525734ef3e60ea13603d3a61f2": { + "name": "GenericXML.js", + "types": [ + "GenericXML" + ], + "enabled": true + }, + "055a038d5bf33e3aaeff6d83be1d0e0f9feaacb5": { + "name": "comment.js", + "types": [ + "comment" + ], + "enabled": true + }, + "2f1e87ae27d50973e857fa71e67eb717e65f2019": { + "name": "dgstart.js", + "types": [ + "dgstart" + ], + "enabled": true + }, + "c10b21de58bf98f978d17a2d0c16e8038d339fc3": { + "name": "method.js", + "types": [ + "method" + ], + "enabled": true + }, + "3b5f11ac0d6283221bc08ebf11d64fa17c15d4cb": { + "name": "serviceLogic.js", + "types": [ + "service-logic" + ], + "enabled": true + }, + "91e5dfbc8a58ff4f4c75c88f68209fe74172a79a": { + "name": "already-active.js", + "types": [ + "already-active" + ], + "enabled": true + }, + "2356e6f2b50eefaf1def0d8dd86f95227f5f3142": { + "name": "failure.js", + "types": [ + "failure" + ], + "enabled": true + }, + "d43be73f359a928c57a7cffcd5f37a7b9740d921": { + "name": "not-found.js", + "types": [ + "not-found" + ], + "enabled": true + }, + "bbc41e923705ff934c652daa85ea6599000e317b": { + "name": "other.js", + "types": [ + "other" + ], + "enabled": true + }, + "5490a91f90dcf4d1857910debbad5dfbfdc015f3": { + "name": "outcome.js", + "types": [ + "outcome" + ], + "enabled": true + }, + "608774ad827770597de4c27f9da3d202ad510409": { + "name": "outcomeFalse.js", + "types": [ + "outcomeFalse" + ], + "enabled": true + }, + "f8eb7854fe489265a7d484611791e750e96e0f4a": { + "name": "outcomeTrue.js", + "types": [ + "outcomeTrue" + ], + "enabled": true + }, + "cfb4ea42aa90d421129ff3275427599a438d3e61": { + "name": "success.js", + "types": [ + "success" + ], + "enabled": true + }, + "cdf3ac03ebc8419da64f2f3dc792c72660cdf41b": { + "name": "returnFailure.js", + "types": [ + "returnFailure" + ], + "enabled": true + }, + "8656992c3f5ffa48e7ea12a14fa33cfa87e0be4f": { + "name": "returnSuccess.js", + "types": [ + "returnSuccess" + ], + "enabled": true + } + } +}
\ No newline at end of file diff --git a/dgbuilder/releases/sdnc1.0/codecloud/.gitignore b/dgbuilder/releases/sdnc1.0/codecloud/.gitignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/codecloud/.gitignore diff --git a/dgbuilder/releases/sdnc1.0/conf/svclogic.properties b/dgbuilder/releases/sdnc1.0/conf/svclogic.properties new file mode 100644 index 00000000..92d997f1 --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/conf/svclogic.properties @@ -0,0 +1,5 @@ +org.onap.ccsdk.sli.dbtype=jdbc +org.onap.ccsdk.sli.jdbc.url=jdbc:mysql://dbhost:3306/sdnctl +org.onap.ccsdk.sli.jdbc.database=sdnctl +org.onap.ccsdk.sli.jdbc.user=sdnctl +org.onap.ccsdk.sli.jdbc.password=gamma diff --git a/dgbuilder/releases/sdnc1.0/customSettings.js b/dgbuilder/releases/sdnc1.0/customSettings.js new file mode 100644 index 00000000..dc85fa59 --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/customSettings.js @@ -0,0 +1,38 @@ +module.exports={ + "name": "Release sdnc1.0", + "emailAddress": "dguser@onap.org", + "uiPort": 3100, + "mqttReconnectTime": 15000, + "serialReconnectTime": 15000, + "debugMaxLength": 1000, + "htmlPath": "releases/sdnc1.0/html/", + "xmlPath": "releases/sdnc1.0/xml/", + "flowFile": "releases/sdnc1.0/flows/flows.json", + "sharedDir": "releases/sdnc1.0/flows/shared", + "userDir": "releases/sdnc1.0", + "httpAuth": { + "user": "dguser", + "pass": "cc03e747a6afbbcbf8be7668acfebee5" + }, + "dbHost": "dbhost", + "dbPort": "3306", + "dbName": "sdnctl", + "dbUser": "sdnctl", + "dbPassword": "gamma", + "gitLocalRepository": "", + "httpRoot": "/", + "disableEditor": false, + "httpAdminRoot": "/", + "httpAdminAuth": { + "user": "dguser", + "pass": "cc03e747a6afbbcbf8be7668acfebee5" + }, + "httpNodeRoot": "/", + "httpNodeAuth": { + "user": "dguser", + "pass": "cc03e747a6afbbcbf8be7668acfebee5" + }, + "uiHost": "0.0.0.0", + "version": "0.9.1", + "performGitPull": "N" +} diff --git a/dgbuilder/releases/sdnc1.0/flows/shared/.gitignore b/dgbuilder/releases/sdnc1.0/flows/shared/.gitignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/flows/shared/.gitignore diff --git a/dgbuilder/releases/sdnc1.0/flows/shared/backups/.gitignore b/dgbuilder/releases/sdnc1.0/flows/shared/backups/.gitignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/flows/shared/backups/.gitignore diff --git a/dgbuilder/releases/sdnc1.0/html/.gitignore b/dgbuilder/releases/sdnc1.0/html/.gitignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/html/.gitignore diff --git a/dgbuilder/releases/sdnc1.0/lib/flows/.gitignore b/dgbuilder/releases/sdnc1.0/lib/flows/.gitignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/lib/flows/.gitignore diff --git a/dgbuilder/releases/sdnc1.0/logs/.gitignore b/dgbuilder/releases/sdnc1.0/logs/.gitignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/logs/.gitignore diff --git a/dgbuilder/releases/sdnc1.0/logs/process_pid b/dgbuilder/releases/sdnc1.0/logs/process_pid new file mode 100644 index 00000000..8b137891 --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/logs/process_pid @@ -0,0 +1 @@ + diff --git a/dgbuilder/releases/sdnc1.0/xml/.gitignore b/dgbuilder/releases/sdnc1.0/xml/.gitignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/dgbuilder/releases/sdnc1.0/xml/.gitignore diff --git a/dgbuilder/show_status.sh b/dgbuilder/show_status.sh new file mode 100755 index 00000000..21197515 --- /dev/null +++ b/dgbuilder/show_status.sh @@ -0,0 +1,54 @@ +#!/bin/bash +tbold=$(tput setf 3) +bold=$(tput setf 2) +bold1=$(tput setf 2) +offbold=$(tput rmso;tput sgr0) + +function pad { + #echo "1 is $1 2 is $2" + if [ "$1" == "" ] + then + $1 = ""; + fi + let count=0 + curr_len=`expr length "$1"` + let space_length=$2-$curr_len + spaces="" + while [ $count -lt $space_length ] + do + spaces="$spaces " + let count=$count+1 + done + echo "$1$spaces" +} + +function isRunning { + echo $(curl -I "$1" 2>/dev/null|head -1|tail -1|awk '{print $2}') +} +dirName=$(pwd) +options=($(ls -l $dirName/releases|grep ^d|awk '{print $NF}'|sort)) + echo "$(pad RELEASE 15)$(pad URL 30)$(pad Status 10)" + echo "$(pad '----' 15)$(pad '---' 30)$(pad '------' 10)" + for opt in "${options[@]}" + do + + releaseDir="$opt" + if [ -e "./releases/${opt}/customSettings.js" ] + then + pid=$(cat ./releases/$releaseDir/logs/process_pid 2>/dev/null) + port=$(cat ./releases/$releaseDir/customSettings.js 2>/dev/null|grep uiPort|sed -e 's/[, ]//g'|cut -d: -f2) + resp1=$(isRunning "http://localhost:$port") + if [ "$resp1" == "401" ] + then + echo "$(pad $releaseDir 15)$(pad http://localhost:$port 30)${bold}$(pad running 10)${offbold}" + else + processId=$(netstat -upltn 2>/dev/null|grep $port|awk '{print $NF}'|sed -e 's%/node-red%%g') + if [ "$processId" == "" ] + then + echo "$(pad $releaseDir 15)$(pad http://localhost:$port 30)${bold}$(pad stopped 10)${offbold}" + else + echo "$(pad $releaseDir 15)$(pad http://localhost:$port 30)${bold}$(pad running 10)${offbold}" + fi + fi + fi + done diff --git a/dgbuilder/src/assembly/assemble_zip.xml b/dgbuilder/src/assembly/assemble_zip.xml new file mode 100644 index 00000000..f13efa01 --- /dev/null +++ b/dgbuilder/src/assembly/assemble_zip.xml @@ -0,0 +1,101 @@ +<!-- + ============LICENSE_START======================================================= + openECOMP : SDN-C + ================================================================================ + Copyright (C) 2017 AT&T Intellectual Property. All rights + reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<!-- Defines how we build the .zip file which is our distribution. --> + +<assembly + xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> + <id>bin</id> + <formats> + <format>zip</format> + </formats> + + <includeBaseDirectory>false</includeBaseDirectory> + + <fileSets> + <fileSet> + <directory>core_nodes</directory> + <outputDirectory>dgbuilder/core_nodes</outputDirectory> + </fileSet> + <fileSet> + <directory>generatedJS</directory> + <outputDirectory>dgbuilder/generatedJS</outputDirectory> + </fileSet> + <fileSet> + <directory>git_scripts</directory> + <outputDirectory>dgbuilder/git_scripts</outputDirectory> + </fileSet> + <fileSet> + <directory>nodes</directory> + <outputDirectory>dgbuilder/nodes</outputDirectory> + </fileSet> + <fileSet> + <directory>public</directory> + <outputDirectory>dgbuilder/public</outputDirectory> + </fileSet> + <fileSet> + <directory>red</directory> + <outputDirectory>dgbuilder/red</outputDirectory> + </fileSet> + <fileSet> + <directory>releases</directory> + <outputDirectory>dgbuilder/releases</outputDirectory> + </fileSet> + <fileSet> + <directory>svclogic</directory> + <outputDirectory>dgbuilder/svclogic</outputDirectory> + </fileSet> + <fileSet> + <directory>test</directory> + <outputDirectory>dgbuilder/test</outputDirectory> + </fileSet> + <fileSet> + <directory>tools</directory> + <outputDirectory>dgbuilder/tools</outputDirectory> + </fileSet> + <fileSet> + <directory>yangFiles</directory> + <outputDirectory>dgbuilder/yangFiles</outputDirectory> + </fileSet> + <fileSet> + <directory>.</directory> + <outputDirectory>dgbuilder/</outputDirectory> + <includes> + <include>*.json</include> + <include>*.js</include> + <include>*.md</include> + <include>*.sh</include> + <include>LICENSE</include> + </includes> + </fileSet> + <fileSet> + <directory>target/svclogic/lib</directory> + <outputDirectory>dgbuilder/svclogic/lib</outputDirectory> + <includes> + <include>*.jar</include> + </includes> + </fileSet> + </fileSets> + + +</assembly> diff --git a/dgbuilder/start.sh b/dgbuilder/start.sh new file mode 100755 index 00000000..38f11582 --- /dev/null +++ b/dgbuilder/start.sh @@ -0,0 +1,74 @@ +#!/bin/bash +releaseDir="$1" +if [ "$#" != "1" ] +then + echo "Usage: $0 releaseDirName" + exit +fi +echo "ReleaseDir:$releaseDir" +export PROJECT_HOME=`pwd` +tbold=$(tput setf 3) +bold=$(tput setf 2) +bold1=$(tput setf 2) +offbold=$(tput rmso;tput sgr0) + +function pad { + #echo "1 is $1 2 is $2" + if [ "$1" == "" ] + then + $1 = ""; + fi + let count=0 + curr_len=`expr length "$1"` + let space_length=$2-$curr_len + spaces="" + while [ $count -lt $space_length ] + do + spaces="$spaces " + let count=$count+1 + done + echo "$1$spaces" +} + +function isRunning { + echo $(curl -I "$1" 2>/dev/null|head -1|tail -1|awk '{print $2}') +} + +npm install + +if [ -e "releases/${releaseDir}/customSettings.js" ] +then + pid=$(cat releases/$releaseDir/logs/process_pid 2>/dev/null) + port=$(cat releases/$releaseDir/customSettings.js|grep uiPort|sed -e 's/[, ]//g'|cut -d: -f2 ) + count=$(ps -p$pid 2>/dev/null|grep -v PID|wc -l) + if [ "$count" != "0" ] + then + echo "For Release \"$releaseDir\" - http://localhost:$port" + echo "********ALREADY RUNNING PID:$pid *******" + else + pid_listening_on_port=$(netstat -upltn 2>/dev/null|grep -w $port|awk '{print $NF}'|cut -d'/' -f1) + if [ "$pid_listening_on_port" != "" ] + then + if [ "$pid_listening_on_port" != "$pid" ] + then + echo "port $port is already in use by other process" + ps -p $pid_listening_on_port + else + echo "Process is already running."; + fi + exit; + fi + node red.js --settings releases/${releaseDir}/customSettings.js + process_pid="$!" + echo $process_pid >releases/$releaseDir/logs/process_pid + port=$(cat releases/${releaseDir}/customSettings.js|grep uiPort|sed -e 's/[, ]//g'|cut -d: -f2) + echo "For Release \"$releaseDir\" ${urlIp}:$port --- STARTED PID:$process_pid" + if [ "${releaseDir}" != "" ] + then + sleep 3 + ./show_status.sh|grep -w ${releaseDir} + fi + fi +else + echo "Directory ${releaseDir} is not setup. Use the createReleaseDir.sh script to setup the directory." +fi diff --git a/dgbuilder/stop.sh b/dgbuilder/stop.sh new file mode 100755 index 00000000..b67babc0 --- /dev/null +++ b/dgbuilder/stop.sh @@ -0,0 +1,52 @@ +#!/bin/bash +tbold=$(tput setf 3) +bold=$(tput setf 2) +bold1=$(tput setf 2) +offbold=$(tput rmso;tput sgr0) + +function pad { + #echo "1 is $1 2 is $2" + if [ "$1" == "" ] + then + $1 = ""; + fi + let count=0 + curr_len=`expr length "$1"` + let space_length=$2-$curr_len + spaces="" + while [ $count -lt $space_length ] + do + spaces="$spaces " + let count=$count+1 + done + echo "$1$spaces" +} +releaseDir="" +if [ "$#" == "1" ] +then + releaseDir="$1" +fi + +if [ -e "releases/${releaseDir}/customSettings.js" ] +then + port=$(cat releases/${releaseDir}/customSettings.js|grep uiPort|sed -e 's/[, ]//g'|cut -d: -f2) + kill $(cat releases/${releaseDir}/logs/process_pid 2>/dev/null) >/dev/null 2>&1 + if [ "$?" != "0" ] + then + #kill only if its a node-red process + processPid=$(netstat -upltn 2>/dev/null|grep -w $port|awk '{print $NF}'|sed -e 's%/node-red%%g') + kill $processPid 2>/dev/null + echo "http://localhost:$port ---- STOPPED" + ./show_status.sh|grep -w "${releaseDir}" + else + echo "http://localhost:$port ---- STOPPED" + ./show_status.sh|grep -w "${releaseDir}" + fi +else + if [ "$releaseDir" != "" ] + then + echo "Release Directory ${releaseDir} not setup."; + else + echo "Usage:$0 releaseDirName" + fi +fi diff --git a/dgbuilder/svclogic/copy_xml.sh b/dgbuilder/svclogic/copy_xml.sh new file mode 100755 index 00000000..8b2cc4ee --- /dev/null +++ b/dgbuilder/svclogic/copy_xml.sh @@ -0,0 +1,4 @@ +dt=$(date +'%m%d%Y_%H%M%S') +mv ~/dg_xml/dg.xml ~/dg_xml/dg_${dt}.xml +cp $(ls -ltr /home/users/schinthakayala/nodered/production/flowDesigner/users/sheshi/xml/*.xml|tail -1|awk '{print $NF}') ~/dg_xml/dg.xml +echo "copied the latest DG" diff --git a/dgbuilder/svclogic/dg.xml b/dgbuilder/svclogic/dg.xml new file mode 100644 index 00000000..069a0269 --- /dev/null +++ b/dgbuilder/svclogic/dg.xml @@ -0,0 +1,2 @@ +<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='ModuleName' version='1.0.0'><method rpc='rpcName' mode='sync'> +</method></service-logic> diff --git a/dgbuilder/svclogic/lib/.gitignore b/dgbuilder/svclogic/lib/.gitignore new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/dgbuilder/svclogic/lib/.gitignore diff --git a/dgbuilder/svclogic/load_dg b/dgbuilder/svclogic/load_dg new file mode 100755 index 00000000..e13745b2 --- /dev/null +++ b/dgbuilder/svclogic/load_dg @@ -0,0 +1 @@ +/home/users/schinthakayala/dg_xml/svclogic.sh load /home/users/schinthakayala/dg_xml/dg.xml /home/users/schinthakayala/dg_xml/svclogic.properties diff --git a/dgbuilder/svclogic/svclogic.properties b/dgbuilder/svclogic/svclogic.properties new file mode 100644 index 00000000..b34ee25e --- /dev/null +++ b/dgbuilder/svclogic/svclogic.properties @@ -0,0 +1,5 @@ +org.onap.ccsdk.sli.dbtype = jdbc
+org.onap.ccsdk.sli.jdbc.url = jdbc:mysql://dbhost:3306/sdnctl
+org.onap.ccsdk.sli.jdbc.database = sdnctl
+org.onap.ccsdk.sli.jdbc.user = sdnctl
+org.onap.ccsdk.sli.jdbc.password = gamma
diff --git a/dgbuilder/svclogic/svclogic.sh b/dgbuilder/svclogic/svclogic.sh new file mode 100755 index 00000000..4c0d2da2 --- /dev/null +++ b/dgbuilder/svclogic/svclogic.sh @@ -0,0 +1,14 @@ +#!/bin/bash +#echo "PROJECT_HOME:$PROJECT_HOME" + +MYSQL_JDBC_DRIVER=${MYSQL_JDBC_DRIVER:-$PROJECT_HOME/svclogic/lib/mysql-connector-java-5.1.31.jar} +JARDIR="$PROJECT_HOME/svclogic/lib" +#JARDIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + +CLASSPATH=$CLASSPATH:$MYSQL_JDBC_DRIVER +for jar in $JARDIR/*.jar +do + CLASSPATH=$CLASSPATH:${jar} +done +#echo "CLASSPATH is ${CLASSPATH}" +java -cp ${CLASSPATH}:${MYSQL_JDBC_DRIVER}:${SLI_COMMON_JAR} org.onap.ccsdk.sli.core.sli.SvcLogicParser $* diff --git a/dgbuilder/test/_spec.js b/dgbuilder/test/_spec.js new file mode 100644 index 00000000..9eb7e07f --- /dev/null +++ b/dgbuilder/test/_spec.js @@ -0,0 +1,93 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +/** + * This test simply checks that for every .js file there exists + * a *_spec.js file under ./test correspondingly. + */ + +/** + * Currently we're only checking the core components under ./red + * TODO: Increase the scope of this check + */ + +var fs = require("fs"); +var should = require("should"); +var path = require('path'); + +// Directories to check with .js files and _spec.js files respectively +var jsdir = path.resolve(__dirname, "../red"); +var testdir = path.resolve(__dirname, "red"); + +var fs = require('fs'); +var walkDirectory = function(dir, topdir, done) { + fs.readdir(dir, function(err, list) { + var error; + var errReturned = false; + if (err) { + return done(err); + } + + var i = 0; + (function next() { + var file = list[i++]; + + // return error if there are no more files to check and error has not been previously returned to avoid multiple calls to done() + if (!file) { + if (!errReturned) { + errReturned = true; + return done(error); + } + } else { + file = path.resolve(dir, file); + fs.stat(file, function(err, stat) { + if (stat && stat.isDirectory()) { + walkDirectory(file, false, function(err) { + if (!error) { + error = err; + } + next(); + }); + } else { + if (path.extname(file) === ".js") { + var testFile = file.replace(jsdir, testdir).replace(".js", "_spec.js"); + fs.exists(testFile, function (exists) { + try { + exists.should.equal(true, testFile + " does not exist"); + } catch (err) { + if (!topdir) { + return done(err); + } else { + error = err; + return; + } + } + }); + } + next(); + } + }); + } + })(); + }); +}; + +describe('_spec.js', function() { + this.timeout(50000); // we might not finish within the Mocha default timeout limit, project will also grow + it('is checking if all .js files have a corresponding _spec.js test file.', function(done) { + walkDirectory(jsdir, true, done); + }); +}); diff --git a/dgbuilder/test/nodes/core/core/20-inject_spec.js b/dgbuilder/test/nodes/core/core/20-inject_spec.js new file mode 100644 index 00000000..aeeac9dd --- /dev/null +++ b/dgbuilder/test/nodes/core/core/20-inject_spec.js @@ -0,0 +1,118 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var injectNode = require("../../../../nodes/core/core/20-inject.js"); +var helper = require("../../helper.js"); + +describe('inject node', function() { + + before(function(done) { + helper.startServer(done); + }); + + afterEach(function() { + helper.unload(); + }); + + it('should inject once', function(done) { + + helper.load(injectNode, [{id:"n1", type:"inject", + payload:"payload", topic: "t1", + once: true, wires:[["n2"]] }, + {id:"n2", type:"helper"}], + function() { + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 't1'); + msg.should.have.property('payload', 'payload'); + done(); + }); + }); + }); + + it('should inject repeatedly', function(done) { + + helper.load(injectNode, [{id:"n1", type:"inject", + payload:"payload", topic: "t2", + repeat: 0.2, wires:[["n2"]] }, + {id:"n2", type:"helper"}], + function() { + var n2 = helper.getNode("n2"); + var count = 0; + n2.on("input", function(msg) { + msg.should.have.property('topic', 't2'); + msg.should.have.property('payload', 'payload'); + count += 1; + if (count > 2) { + helper.clearFlows().then(function() { + done(); + }); + } + }); + }); + }); + + it('should inject with cron', function(done) { + helper.load(injectNode, [{id:"n1", type:"inject", + payloadType:"date", topic: "t3", + crontab: "* * * * * *", wires:[["n3"]] }, + {id:"n3", type:"helper"}], + function() { + var n3 = helper.getNode("n3"); + n3.on("input", function(msg) { + msg.should.have.property('topic', 't3'); + msg.should.have.property('payload').be.a.Number; + helper.clearFlows().then(function() { + done(); + }); + }); + }); + }); + + describe('post', function() { + it('should inject message', function(done) { + helper.load(injectNode, + [{id:"n1", type:"inject", + payloadType:"some type", topic: "t4", + wires:[["n4"]] }, + { id:"n4", type:"helper"}], function() { + var n4 = helper.getNode("n4"); + n4.on("input", function(msg) { + msg.should.have.property('topic', 't4'); + msg.should.have.property('payload', ''); + helper.clearFlows().then(function() { + done(); + }); + }); + helper.request() + .post('/inject/n1') + .expect(200).end(function(err) { + if (err) { + return helper.clearFlows() + .then(function () { + done(err); + }); + } + }); + }); + }); + + it('should fail for invalid node', function(done) { + helper.request().post('/inject/invalid').expect(404).end(done); + }); + }); +}); diff --git a/dgbuilder/test/nodes/core/core/58-debug_spec.js b/dgbuilder/test/nodes/core/core/58-debug_spec.js new file mode 100644 index 00000000..f83fc2ca --- /dev/null +++ b/dgbuilder/test/nodes/core/core/58-debug_spec.js @@ -0,0 +1,298 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var debugNode = require("../../../../nodes/core/core/58-debug.js"); +var helper = require("../../helper.js"); +var WebSocket = require('ws'); + +describe('debug node', function() { + + before(function(done) { + helper.startServer(done); + }); + + afterEach(function() { + helper.unload(); + }); + + + it('should be loaded', function(done) { + var flow = [{id:"n1", type:"debug", name: "Debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + n1.should.have.property('name', 'Debug'); + done(); + }); + }); + + it('should publish on input', function(done) { + var flow = [{id:"n1", type:"debug", name: "Debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {payload:"test"}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",name:"Debug",msg:"test"} + }); + }, done); + }); + }); + + it('should publish to console', function(done) { + var flow = [{id:"n1", type:"debug", console: "true" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + var count = 0; + n1.on('log', function(msg) { + msg.should.eql({level:'log',id:'n1',type:'debug',msg:'test'}); + count++; + if (count == 2) { + done(); + } + }); + websocket_test(function() { + n1.emit("input", {payload:"test"}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",msg:"test"} + }); + count++; + }, function() { + if (count == 2) { + done(); + } + }); + }); + }); + + it('should publish complete message', function(done) { + var flow = [{id:"n1", type:"debug", complete: "true" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {payload:"test"}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{id:"n1",msg:'(Object) {\n "payload": "test"\n}'} + }); + }, done); + }); + }); + + it('should publish an Error', function(done) { + var flow = [{id:"n1", type:"debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {payload: new Error("oops")}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",msg:"Error: oops"} + }); + }, done); + }); + }); + + it('should publish a boolean', function(done) { + var flow = [{id:"n1", type:"debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {payload: true}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",msg: '(boolean) true'} + }); + }, done); + }); + }); + + it('should publish with no payload', function(done) { + var flow = [{id:"n1", type:"debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",msg: '(undefined)'} + }); + }, done); + }); + }); + + it('should publish an object', function(done) { + var flow = [{id:"n1", type:"debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {payload: {type:'foo'}}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{id:"n1",msg:'(Object) {\n "type": "foo"\n}'} + }); + }, done); + }); + }); + + it('should publish an array', function(done) { + var flow = [{id:"n1", type:"debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {payload: [0,1,2,3]}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{id:"n1",msg: '(Array) [\n 0,\n 1,\n 2,\n 3\n]'} + }); + }, done); + }); + }); + + it('should publish an object with circular references', function(done) { + var flow = [{id:"n1", type:"debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + var o = { name: 'bar' }; + o.o = o; + n1.emit("input", {payload: o}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{ + id:"n1", + msg:'(Object) {\n "name": "bar",\n "o": "[circular]"\n}' + } + }); + }, done); + }); + }); + + it('should truncated a long message', function(done) { + var flow = [{id:"n1", type:"debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {payload: Array(1002).join("X")}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{ + id:"n1", + msg: Array(1001).join("X")+' ....' + } + }); + }, done); + }); + }); + + it('should convert Buffer to hex', function(done) { + var flow = [{id:"n1", type:"debug" }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {payload: new Buffer('HELLO', 'utf8')}); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug", + data:{ + id:"n1", + msg: '(Buffer) 48454c4c4f', + } + }); + }, done); + }); + }); + + it('should publish when active', function(done) { + var flow = [{id:"n1", type:"debug", active: false }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function() { + n1.emit("input", {payload:"message 1"}); + helper.request() + .post('/debug/n1/enable') + .expect(200).end(function(err) { + if (err) { return done(err); } + n1.emit("input", {payload:"message 2"}); + }); + }, function(msg) { + JSON.parse(msg).should.eql({ + topic:"debug",data:{id:"n1",msg:"message 2"} + }); + }, done); + }); + }); + + it('should not publish when inactive', function(done) { + var flow = [{id:"n1", type:"debug", active: true }]; + helper.load(debugNode, flow, function() { + var n1 = helper.getNode("n1"); + websocket_test(function(close) { + helper.request() + .post('/debug/n1/disable') + .expect(201).end(function(err) { + if (err) { + close(); + return done(err); + } + n1.emit("input", {payload:"message"}); + setTimeout(function() { + close(); + done(); + }, 200); + }); + }, function(msg) { + should.fail(null,null,"unexpected message"); + }, function() {}); + }); + }); + + describe('post', function() { + it('should return 404 on invalid state', function(done) { + var flow = [{id:"n1", type:"debug", active: true }]; + helper.load(debugNode, flow, function() { + helper.request() + .post('/debug/n1/foobar') + .expect(404).end(done); + }); + }); + + it('should return 404 on invalid node', function(done) { + helper.request() + .post('/debug/n99/enable') + .expect(404).end(done); + }); + }); + +}); + +function websocket_test(open_callback, message_callback, done_callback) { + var ws = new WebSocket(helper.url() + "/comms"); + var close_callback = function() { ws.close(); }; + ws.on('open', function() { open_callback(close_callback); }); + ws.on('message', function(msg) { + message_callback(msg, close_callback); + ws.close(); + done_callback(); + }); +} diff --git a/dgbuilder/test/nodes/core/core/80-function_spec.js b/dgbuilder/test/nodes/core/core/80-function_spec.js new file mode 100644 index 00000000..9efd93aa --- /dev/null +++ b/dgbuilder/test/nodes/core/core/80-function_spec.js @@ -0,0 +1,149 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var functionNode = require("../../../../nodes/core/core/80-function.js"); +var helper = require("../../helper.js"); + +describe('function node', function() { + + before(function(done) { + helper.startServer(done); + }); + + afterEach(function() { + helper.unload(); + }); + + it('should be loaded', function(done) { + var flow = [{id:"n1", type:"function", name: "function" }]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + n1.should.have.property('name', 'function'); + done(); + }); + }); + + it('should send returned message', function(done) { + var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"return msg;"}, + {id:"n2", type:"helper"}]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + msg.should.have.property('payload', 'foo'); + done(); + }); + n1.receive({payload:"foo",topic: "bar"}); + }); + }); + + it('should pass through _topic', function(done) { + var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"return msg;"}, + {id:"n2", type:"helper"}]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + msg.should.have.property('payload', 'foo'); + msg.should.have.property('_topic', 'baz'); + done(); + }); + n1.receive({payload:"foo",topic: "bar", _topic: "baz"}); + }); + }); + + it('should send to multiple outputs', function(done) { + var flow = [{id:"n1",type:"function",wires:[["n2"],["n3"]], + func:"return [{payload: '1'},{payload: '2'}];"}, + {id:"n2", type:"helper"}, {id:"n3", type:"helper"} ]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + var n3 = helper.getNode("n3"); + var count = 0; + n2.on("input", function(msg) { + should(msg).have.property('payload', '1'); + count++; + if (count == 2) { + done(); + } + }); + n3.on("input", function(msg) { + should(msg).have.property('payload', '2'); + count++; + if (count == 2) { + done(); + } + }); + n1.receive({payload:"foo",topic: "bar"}); + }); + }); + + it('should send to multiple messages', function(done) { + var flow = [{id:"n1",type:"function",wires:[["n2"]], + func:"return [[{payload: 1},{payload: 2}]];"}, + {id:"n2", type:"helper"} ]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + var count = 0; + n2.on("input", function(msg) { + count++; + should(msg).have.property('payload', count); + should(msg).have.property('_topic', 'baz'); + if (count == 2) { + done(); + } + }); + n1.receive({payload:"foo", topic: "bar", _topic:"baz"}); + }); + }); + + it('should allow input to be discarded by returning null', function(done) { + var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"return null"}, + {id:"n2", type:"helper"}]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + setTimeout(function() { + done(); + }, 200); + n2.on("input", function(msg) { + should.fail(null,null,"unexpected message"); + }); + n1.receive({payload:"foo",topic: "bar"}); + }); + }); + + it('should handle and log script error', function(done) { + var flow = [{id:"n1",type:"function",wires:[["n2"]],func:"retunr"}]; + helper.load(functionNode, flow, function() { + var n1 = helper.getNode("n1"); + n1.on("log", function(msg) { + msg.should.have.property('level', 'error'); + msg.should.have.property('id', 'n1'); + msg.should.have.property('type', 'function'); + msg.should.have.property('msg', 'ReferenceError: retunr is not defined'); + done(); + }); + n1.receive({payload:"foo",topic: "bar"}); + }); + }); + +}); diff --git a/dgbuilder/test/nodes/core/core/80-template_spec.js b/dgbuilder/test/nodes/core/core/80-template_spec.js new file mode 100644 index 00000000..a89afa37 --- /dev/null +++ b/dgbuilder/test/nodes/core/core/80-template_spec.js @@ -0,0 +1,46 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var templateNode = require("../../../../nodes/core/core/80-template.js"); +var helper = require("../../helper.js"); + +describe('template node', function() { + + before(function(done) { + helper.startServer(done); + }); + + afterEach(function() { + helper.unload(); + }); + + + it('should modify payload', function(done) { + var flow = [{id:"n1", type:"template", field: "payload", template: "payload={{payload}}",wires:[["n2"]]},{id:"n2",type:"helper"}]; + helper.load(templateNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + msg.should.have.property('payload', 'payload=foo'); + done(); + }); + n1.receive({payload:"foo",topic: "bar"}); + }); + }); + +}); diff --git a/dgbuilder/test/nodes/core/core/89-delay_spec.js b/dgbuilder/test/nodes/core/core/89-delay_spec.js new file mode 100644 index 00000000..22c3173a --- /dev/null +++ b/dgbuilder/test/nodes/core/core/89-delay_spec.js @@ -0,0 +1,420 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); + +var delayNode = require("../../../../nodes/core/core/89-delay.js"); +var helper = require("../../helper.js"); + +var GRACE_PERCENTAGE=10; + +var nanosToSeconds = 1000000000; +var millisToSeconds = 1000; + +var secondsToMinutes = 60; +var secondsToHours = 3600; +var secondsToDays = 86400; + + +describe('delayNode', function() { + + beforeEach(function(done) { + helper.startServer(done); + }); + + afterEach(function(done) { + helper.unload(); + helper.stopServer(done); + }); + + it('should be loaded', function(done) { + var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[[]]}]; + helper.load(delayNode, flow, function() { + var delayNode1 = helper.getNode("delayNode1"); + delayNode1.should.have.property('name', 'delayNode'); + done(); + }); + }); + + var TimeUnitEnum = { + MILLIS : "milliseconds", + SECONDS : "seconds", + MINUTES : "minutes", + HOURS : "hours", + DAYS : "days" + } + + /** + * Tells whether two numeric values are close enough to each other + * @param actualValue - the value we're testing + * @param expectedValue - the value we're matching the test value against + * @param tolerancePercent - the percentage of tolerated deviation (0 means equals) + */ + function closeEnough(actualValue, expectedValue, tolerancePercent) { + var toReturn; + var toleranceFraction = expectedValue * (tolerancePercent/100); + var minExpected = expectedValue - toleranceFraction; + var maxExpected = expectedValue + toleranceFraction; + + if(actualValue >= minExpected && actualValue <= maxExpected) { + toReturn = true; + } else { + toReturn = false; + } + return toReturn; + } + + /** + * Runs a delay test + * @param aTimeout - the timeout quantity + * @param aTimeoutUnit - the unit of the timeout: milliseconds, seconds, minutes, hours, days + */ + function genericDelayTest(aTimeout, aTimeoutUnit, done) { + var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"delay","timeout":aTimeout,"timeoutUnits":aTimeoutUnit,"rate":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(delayNode, flow, function() { + var delayNode1 = helper.getNode("delayNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + var endTime = process.hrtime(startTime); + var runtimeNanos = ( (endTime[0] * nanosToSeconds) + endTime[1] ); + var runtimeSeconds = runtimeNanos / nanosToSeconds; + var aTimeoutUnifiedToSeconds; + + // calculating the timeout in seconds + if(aTimeoutUnit == TimeUnitEnum.MILLIS) { + aTimeoutUnifiedToSeconds = aTimeout / millisToSeconds; + } else if(aTimeoutUnit == TimeUnitEnum.SECONDS) { + aTimeoutUnifiedToSeconds = aTimeout; + } else if(aTimeoutUnit == TimeUnitEnum.MINUTES) { + aTimeoutUnifiedToSeconds = aTimeout * secondsToMinutes; + } else if(aTimeoutUnit == TimeUnitEnum.HOURS) { + aTimeoutUnifiedToSeconds = aTimeout * secondsToHours; + } else if(aTimeoutUnit == TimeUnitEnum.DAYS) { + aTimeoutUnifiedToSeconds = aTimeout * secondsToDays; + } + + if(closeEnough(runtimeSeconds, aTimeoutUnifiedToSeconds, GRACE_PERCENTAGE)) { + done(); + } else { + try { + should.fail(null, null, "Delayed runtime seconds " + runtimeSeconds + " was not close enough to exlected timeout seconds: " + aTimeoutUnifiedToSeconds); + } catch (err) { + done(err); + } + } + } catch(err) { + done(err); + } + }); + var startTime = process.hrtime(); + delayNode1.receive({payload:"delayMe"}); + }); + } + + /** + * We send a message, take a timestamp then when the message is received by the helper node, we take another timestamp. + * Then check if the message has been delayed by the expected amount. + */ + it('delays the message in seconds', function(done) { + genericDelayTest(0.5, "seconds", done); + }); + + it('delays the message in milliseconds', function(done) { + genericDelayTest(500, "milliseconds", done); + }); + + it('delays the message in minutes', function(done) { // this is also 0.5 seconds + genericDelayTest(0.00833, "minutes", done); + }); + + it('delays the message in hours', function(done) { // this is also 0.5 seconds + genericDelayTest(0.0001388, "hours", done); + }); + + it('delays the message in days', function(done) { // this is also 0.5 seconds + genericDelayTest(0.000005787, "days", done); + }); + + /** + * Runs a rate limit test - only testing seconds! + * @param aLimit - the message limit count + * @param runtimeInMillis - when to terminate run and count messages received + */ + function genericRateLimitSECONDSTest(aLimit, runtimeInMillis, done) { + var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(delayNode, flow, function() { + var delayNode1 = helper.getNode("delayNode1"); + var helperNode1 = helper.getNode("helperNode1"); + var receivedMessagesStack = []; + var rate = 1000/aLimit; + + var receiveTimestamp; + + helperNode1.on("input", function(msg) { + if(receiveTimestamp) { + var elapse = process.hrtime(receiveTimestamp); + var receiveInterval = (elapse[0] * 1000) + ((elapse[1] / nanosToSeconds) * 1000); + receiveInterval.should.be.above(rate * 0.9); + } + receiveTimestamp = process.hrtime(); + receivedMessagesStack.push(msg); + }); + + var possibleMaxMessageCount = Math.ceil(aLimit * (runtimeInMillis / 1000) + aLimit); // +aLimit as at the start of the 2nd period, we're allowing the 3rd burst + + var i = 0; + for(; i < possibleMaxMessageCount + 1; i++) { + delayNode1.receive({payload:i}); + } + + setTimeout(function() { + try { + receivedMessagesStack.length.should.be.lessThan(possibleMaxMessageCount); + for(var j = 0; j < receivedMessagesStack.length; j++) { + if(receivedMessagesStack[j].payload === j) { + if(j === (receivedMessagesStack.length -1)) { // last message, all matched so far + done(); + } + } else { + should.fail(null, null, "Received messages were not received in order. Message was " + receivedMessagesStack[i].payload + " on count " + i); + } + } + } catch (err) { + done(err); + } + }, runtimeInMillis); + }); + } + + it('limits the message rate to 1 per second', function(done) { + genericRateLimitSECONDSTest(1, 1500, done); + }); + + it('limits the message rate to 2 per second, 2 seconds', function(done) { + this.timeout(6000); + genericRateLimitSECONDSTest(2, 2100, done); + }); + + /** + * Runs a rate limit test with drop support - only testing seconds! + * @param aLimit - the message limit count + * @param runtimeInMillis - when to terminate run and count messages received + */ + function dropRateLimitSECONDSTest(aLimit, runtimeInMillis, done) { + var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":aLimit,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":true,"wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(delayNode, flow, function() { + var delayNode1 = helper.getNode("delayNode1"); + var helperNode1 = helper.getNode("helperNode1"); + var receivedMessagesStack = []; + + var rate = 1000/aLimit; + + var receiveTimestamp; + + helperNode1.on("input", function(msg) { + if(receiveTimestamp) { + var elapse = process.hrtime(receiveTimestamp); + var receiveInterval = (elapse[0] * 1000) + ((elapse[1] / nanosToSeconds) * 1000); + receiveInterval.should.be.above(rate * 0.9); + } + receiveTimestamp = process.hrtime(); + receivedMessagesStack.push(msg); + }); + + var possibleMaxMessageCount = Math.ceil(aLimit * (runtimeInMillis / 1000) + aLimit); // +aLimit as at the start of the 2nd period, we're allowing the 3rd burst + + var i = 0; + delayNode1.receive({payload:i}); + i++; + for(; i < possibleMaxMessageCount + 1; i++) { + setTimeout(function() { + delayNode1.receive({payload:i}); + }, 2 * ((rate * i) / possibleMaxMessageCount) ); + } + + //we need to send a message delayed so that it doesn't get dropped + setTimeout(function() { + delayNode1.receive({payload:++i}); + }, runtimeInMillis - 300); // should give enough time to squeeze another message in + + setTimeout(function() { + try { + receivedMessagesStack.length.should.be.lessThan(possibleMaxMessageCount + 1); + receivedMessagesStack.length.should.be.greaterThan(2); // ensure that we receive more than 1st and last message + receivedMessagesStack[0].payload.should.be.exactly(0); // means we received the last message injected just before test termination + var foundAtLeastOneDrop = false; + for(var i = 0; i < receivedMessagesStack.length; i++) { + if(i > 0) { + if(receivedMessagesStack[i].payload - receivedMessagesStack[i - 1].payload > 1) { + foundAtLeastOneDrop = true; + } + } + } + foundAtLeastOneDrop.should.be.true; + done(); + } catch (err) { + done(err); + } + }, runtimeInMillis); + }); + } + + it('limits the message rate to 1 per second, 4 seconds, with drop', function(done) { + this.timeout(6000); + dropRateLimitSECONDSTest(1, 4000, done); + }); + + it('limits the message rate to 2 per second, 5 seconds, with drop', function(done) { + this.timeout(6000); + dropRateLimitSECONDSTest(2, 5000, done); + }); + + /** + * Returns true if the actualTimeout is gracefully in between the timeoutFrom and timeoutTo + * values. Gracefully means that inBetween could actually mean smaller/greater values + * than the timeout range so long as it's within an actual grace percentage. + * @param timeoutFrom - The expected timeout range (low number) + * @param timeoutTo - The expected timeout range (high number) + * @param actualTimeout - The actual measured timeout value of test + * @param allowedGracePercent - The percentage of grace allowed + */ + function inBetweenDelays(timeoutFrom, timeoutTo, actualTimeout, allowedGracePercent) { + if(closeEnough(actualTimeout, timeoutFrom, allowedGracePercent)) { + return true; + } else if(closeEnough(actualTimeout, timeoutTo, allowedGracePercent)) { + return true; + } else if(timeoutFrom < actualTimeout && timeoutTo > actualTimeout) { + return true; + } else { + return false; + } + } + + /** + * Runs a RANDOM DELAY test, checks if the delay is in between the given timeout values + * @param aTimeoutFrom - the timeout quantity which is the minimal acceptable wait period + * @param aTimeoutTo - the timeout quantity which is the maximum acceptable wait period + * @param aTimeoutUnit - the unit of the timeout: milliseconds, seconds, minutes, hours, days + */ + function randomDelayTest(aTimeoutFrom, aTimeoutTo, aTimeoutUnit, done) { + var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"random","timeout":5,"timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":aTimeoutFrom,"randomLast":aTimeoutTo,"randomUnits":aTimeoutUnit,"drop":false,"wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(delayNode, flow, function() { + var delayNode1 = helper.getNode("delayNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + var endTime = process.hrtime(startTime); + var runtimeNanos = ( (endTime[0] * nanosToSeconds) + endTime[1] ); + var runtimeSeconds = runtimeNanos / nanosToSeconds; + var aTimeoutFromUnifiedToSeconds; + var aTimeoutToUnifiedToSeconds; + + // calculating the timeout in seconds + if(aTimeoutUnit == TimeUnitEnum.MILLIS) { + aTimeoutFromUnifiedToSeconds = aTimeoutFrom / millisToSeconds; + aTimeoutToUnifiedToSeconds = aTimeoutTo / millisToSeconds; + } else if(aTimeoutUnit == TimeUnitEnum.SECONDS) { + aTimeoutFromUnifiedToSeconds = aTimeoutFrom; + aTimeoutToUnifiedToSeconds = aTimeoutTo; + } else if(aTimeoutUnit == TimeUnitEnum.MINUTES) { + aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToMinutes; + aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToMinutes; + } else if(aTimeoutUnit == TimeUnitEnum.HOURS) { + aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToHours; + aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToHours; + } else if(aTimeoutUnit == TimeUnitEnum.DAYS) { + aTimeoutFromUnifiedToSeconds = aTimeoutFrom * secondsToDays; + aTimeoutToUnifiedToSeconds = aTimeoutTo * secondsToDays; + } + + if(inBetweenDelays(aTimeoutFromUnifiedToSeconds, aTimeoutToUnifiedToSeconds, runtimeSeconds, GRACE_PERCENTAGE)) { + done(); + } else { + try { + should.fail(null, null, "Delayed runtime seconds " + runtimeSeconds + " was not \"in between enough\" enough to expected values of: " + aTimeoutFromUnifiedToSeconds + " and " + aTimeoutToUnifiedToSeconds); + } catch (err) { + done(err); + } + } + } catch(err) { + done(err); + } + }); + var startTime = process.hrtime(); + delayNode1.receive({payload:"delayMe"}); + }); + } + + it('randomly delays the message in seconds', function(done) { + randomDelayTest(0.4, 0.8, "seconds", done); + }); + + it(' randomly delays the message in milliseconds', function(done) { + randomDelayTest(400, 800, "milliseconds", done); + }); + + it('randomly delays the message in minutes', function(done) { + randomDelayTest(0.0066, 0.0133, "minutes", done); + }); + + it('delays the message in hours', function(done) { + randomDelayTest(0.000111111, 0.000222222, "hours", done); + }); + + it('delays the message in days', function(done) { + randomDelayTest(0.0000046296, 0.0000092593, "days", done); + }); + + it('handles bursts using a buffer', function(done) { + this.timeout(6000); + + var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":5,"timeoutUnits":"seconds","rate":1000,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(delayNode, flow, function() { + var delayNode1 = helper.getNode("delayNode1"); + var helperNode1 = helper.getNode("helperNode1"); + + var sinon = require('sinon'); + + var receivedWarning = false; + var messageBurstSize = 1500; + + // we ensure that we note that a warning is received for buffer growth + sinon.stub(delayNode1, 'warn', function(warning){ + if(warning.indexOf("buffer exceeded 1000 messages" > -1)) { + receivedWarning = true; + } + }); + + // we ensure that the warning is received for buffer size and that we get the last message + helperNode1.on("input", function(msg) { + if(msg.payload === (messageBurstSize - 1) && receivedWarning === true) { + done(); // it will timeout if we don't receive the last message + } + }); + // send 1500 messages as quickly as possible + for(var i = 0; i < messageBurstSize; i++) { + delayNode1.receive({payload:i}); + } + }); + }); + +}); diff --git a/dgbuilder/test/nodes/core/core/90-comment_spec.js b/dgbuilder/test/nodes/core/core/90-comment_spec.js new file mode 100644 index 00000000..54563e9e --- /dev/null +++ b/dgbuilder/test/nodes/core/core/90-comment_spec.js @@ -0,0 +1,36 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var commentNode = require("../../../../nodes/core/core/90-comment.js"); +var helper = require("../../helper.js"); + +describe('comment node', function() { + + afterEach(function() { + helper.unload(); + }); + + it('should be loaded', function(done) { + var flow = [{id:"n1", type:"comment", name: "comment" }]; + helper.load(commentNode, flow, function() { + var n1 = helper.getNode("n1"); + n1.should.have.property('name', 'comment'); + done(); + }); + }); + +}); diff --git a/dgbuilder/test/nodes/core/logic/10-switch_spec.js b/dgbuilder/test/nodes/core/logic/10-switch_spec.js new file mode 100644 index 00000000..d5a42805 --- /dev/null +++ b/dgbuilder/test/nodes/core/logic/10-switch_spec.js @@ -0,0 +1,367 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); + +var switchNode = require("../../../../nodes/core/logic/10-switch.js"); +var helper = require("../../helper.js"); + +describe('SwitchNode', function() { + + beforeEach(function(done) { + helper.startServer(done); + }); + + afterEach(function(done) { + helper.unload(); + helper.stopServer(done); + }); + + it('should be loaded', function(done) { + var flow = [{"id":"switchNode1","type":"switch","name":"switchNode","property":"payload","rules":[{"t":"eq","v":""}],"checkall":"true","outputs":1,"wires":[[]]}]; + helper.load(switchNode, flow, function() { + var switchNode1 = helper.getNode("switchNode1"); + switchNode1.should.have.property('name', 'switchNode'); + done(); + }); + }); + + /** + * Test a switch node where one argument is consumed by the rule (such as greater than). + * @param rule - the switch rule (see 10-switc.js) string we're using + * @param ruleWith - whatever the rule should be executed with (say greater than 5) + * @param aCheckall - whether the switch flow should have the checkall flag set to true/false + * @param shouldReceive - whether the helper node should receive a payload + * @param sendPayload - the payload message we're sending + * @param done - callback when done + */ + function genericSwitchTest(rule, ruleWith, aCheckall, shouldReceive, sendPayload, done) { + var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":rule,"v":ruleWith}],checkall:aCheckall,outputs:1,wires:[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + customFlowSwitchTest(flow, shouldReceive, sendPayload, done); + } + + /** + * Test a switch node where NO arguments are consumed by the rule (such as TRUE/FALSE) + * @param rule - the switch rule (see 10-switc.js) string we're using + * @param aCheckall - whether the switch flow should have the checkall flag set to true/false + * @param shouldReceive - whether the helper node should receive a payload + * @param sendPayload - the payload message we're sending + * @param done - callback when done + */ + function singularSwitchTest(rule, aCheckall, shouldReceive, sendPayload, done) { + var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":rule}],checkall:aCheckall,outputs:1,wires:[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + customFlowSwitchTest(flow, shouldReceive, sendPayload, done); + } + + /** + * Test a switch node where two arguments are consumed by the rule (such as between). + * @param rule - the switch rule (see 10-switc.js) string we're using + * @param ruleWith - whatever the rule should be executed with (say between 5...) + * @param ruleWith2 - whatever the rule should be executed with (say ...and 5) + * @param aCheckall - whether the switch flow should have the checkall flag set to true/false + * @param shouldReceive - whether the helper node should receive a payload + * @param sendPayload - the payload message we're sending + * @param done - callback when done + */ + function twoFieldSwitchTest(rule, ruleWith, ruleWith2, aCheckall, shouldReceive, sendPayload, done) { + var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":rule,"v":ruleWith,"v2":ruleWith2}],checkall:aCheckall,outputs:1,wires:[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + customFlowSwitchTest(flow, shouldReceive, sendPayload, done); + } + + /** + * Execute a switch test. Can specify whether the should node is expected to send a payload onwards to the helper node. + * The flow and the payload can be customised + * @param flow - the custom flow to be tested => must contain a switch node (switchNode1) wiring a helper node (helperNode1) + * @param shouldReceive - whether the helper node should receive a payload + * @param sendPayload - the payload message we're sending + * @param done - callback when done + */ + function customFlowSwitchTest(flow, shouldReceive, sendPayload, done) { + helper.load(switchNode, flow, function() { + var switchNode1 = helper.getNode("switchNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + if(shouldReceive === true) { + msg.payload.should.equal(sendPayload); + done(); + } else { + should.fail(null, null, "We should never get an input!"); + } + } catch(err) { + done(err); + } + }); + switchNode1.receive({payload:sendPayload}); + if(shouldReceive === false) { + setTimeout(function() { + done(); + }, 200); + } + }); + } + + it('should check if payload equals given value', function(done) { + genericSwitchTest("eq", "Hello", true, true, "Hello", done); + }); + + it('should return nothing when the payload doesn\'t equal to desired string', function(done) { + genericSwitchTest("eq", "Hello", true, false, "Hello!", done); + }); + + it('should check if payload NOT equals given value', function(done) { + genericSwitchTest("neq", "Hello", true, true, "HEllO", done); + }); + + it('should return nothing when the payload does equal to desired string', function(done) { + genericSwitchTest("neq", "Hello", true, false, "Hello", done); + }); + + it('should check if payload equals given numeric value', function(done) { + genericSwitchTest("eq", 3, true, true, 3, done); + }); + + it('should return nothing when the payload doesn\'t equal to desired numeric value', function(done) { + genericSwitchTest("eq", 2, true, false, 4, done); + }); + + it('should check if payload NOT equals given numeric value', function(done) { + genericSwitchTest("neq", 55667744, true, true, -1234, done); + }); + + it('should return nothing when the payload does equal to desired numeric value', function(done) { + genericSwitchTest("neq", 10, true, false, 10, done); + }); + + it('should check if payload is less than given value', function(done) { + genericSwitchTest("lt", 3, true, true, 2, done); + }); + + it('should return nothing when the payload is not less than desired string', function(done) { + genericSwitchTest("lt", 3, true, false, 4, done); + }); + + it('should check if payload less than equals given value', function(done) { + genericSwitchTest("lte", 3, true, true, 3, done); + }); + + it('should check if payload is greater than given value', function(done) { + genericSwitchTest("gt", 3, true, true, 6, done); + }); + + it('should return nothing when the payload is not greater than desired string', function(done) { + genericSwitchTest("gt", 3, true, false, -1, done); + }); + + it('should check if payload is greater than/equals given value', function(done) { + genericSwitchTest("gte", 3, true, true, 3, done); + }); + + it('should return nothing when the payload is not greater than desired string', function(done) { + genericSwitchTest("gt", 3, true, false, -1, done); + }); + + it('should check if payload is greater than/equals given value', function(done) { + genericSwitchTest("gte", 3, true, true, 3, done); + }); + + it('should check if payload is between given values', function(done) { + twoFieldSwitchTest("btwn", 3, 5, true, true, 4, done); + }); + + it('should check if payload is not between given values', function(done) { + twoFieldSwitchTest("btwn", 3, 5, true, false, 12, done); + }); + + it('should check if payload contains given value', function(done) { + genericSwitchTest("cont", "Hello", true, true, "Hello World!", done); + }); + + it('should return nothing when the payload doesn\'t contain desired string', function(done) { + genericSwitchTest("cont", "Hello", true, false, "This is not a greeting!", done); + }); + + it('should match regex', function(done) { + genericSwitchTest("regex", "[abc]+", true, true, "abbabac", done); + }); + + it('should return nothing when the payload doesn\'t match regex', function(done) { + genericSwitchTest("regex", "\\d+", true, false, "This is not a digit", done); + }); + + it('should return nothing when the payload doesn\'t contain desired string', function(done) { + genericSwitchTest("cont", "Hello", true, false, "This is not a greeting!", done); + }); + + it('should check if input is true', function(done) { + singularSwitchTest(true, true, true, true, done); + }); + + it('sends nothing when input is false and checking for true', function(done) { + singularSwitchTest(true, true, false, false, done); + }); + + it('should check if input is indeed false', function(done) { + singularSwitchTest(false, true, true, false, done); + }); + + it('sends nothing when input is false and checking for true', function(done) { + singularSwitchTest(false, true, false, true, done); + }); + + it('should check if input is indeed null', function(done) { + var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"null"}],checkall:true,outputs:1,wires:[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + + + helper.load(switchNode, flow, function() { + var switchNode1 = helper.getNode("switchNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + if(msg.payload) { + try { + should.fail(null, null, "msg.payload should be undefined!"); + } catch (err) { + done(err); + } + } else { + done(); + } + }); + switchNode1.receive({payload:undefined}); + }); + }); + + it('should check if input is indeed not null', function(done) { + var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"nnull"}],checkall:false,outputs:1,wires:[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + + + helper.load(switchNode, flow, function() { + var switchNode1 = helper.getNode("switchNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + if(msg.payload) { + done(); + } else { + try { + msg.payload.should.equal("Anything here"); + } catch (err) { + done(err); + } + } + }); + switchNode1.receive({payload:"Anything here"}); + }); + }); + + it('sends a message when the "else/otherwise" statement is selected' , function(done) { + singularSwitchTest("else", true, true, 123456, done); + }); + + it('handles more than one switch statement' , function(done) { + var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"eq","v":"Hello"},{"t":"cont","v":"ello"}, {"t":"else"}],checkall:true,outputs:3,wires:[["helperNode1"], ["helperNode2"], ["helperNode3"]]}, + {id:"helperNode1", type:"helper", wires:[]}, + {id:"helperNode2", type:"helper", wires:[]}, + {id:"helperNode3", type:"helper", wires:[]}]; + + + helper.load(switchNode, flow, function() { + var switchNode1 = helper.getNode("switchNode1"); + var helperNode1 = helper.getNode("helperNode1"); + var helperNode2 = helper.getNode("helperNode2"); + var helperNode3 = helper.getNode("helperNode3"); + + var nodeHitCount = 0; + helperNode1.on("input", function(msg) { + try { + msg.payload.should.equal("Hello"); + nodeHitCount++; + } catch (err) { + done(err); + } + }); + helperNode2.on("input", function(msg) { + try { + msg.payload.should.equal("Hello"); + nodeHitCount++; + if(nodeHitCount == 2) { + done(); + } else { + try { + should.fail(null, null, "Both statements should be triggered!"); + } catch (err) { + done(err); + } + } + } catch (err) { + done(err); + } + }); + helperNode3.on("input", function(msg) { + try { + should.fail(null, null, "The otherwise/else statement should not be triggered here!"); + } catch (err) { + done(err); + } + }); + switchNode1.receive({payload:"Hello"}); + }); + }); + + it('stops after first statement' , function(done) { + var flow = [{id:"switchNode1",type:"switch",name:"switchNode",property:"payload",rules:[{"t":"eq","v":"Hello"},{"t":"cont","v":"ello"}, {"t":"else"}],checkall:"false",outputs:3,wires:[["helperNode1"], ["helperNode2"], ["helperNode3"]]}, + {id:"helperNode1", type:"helper", wires:[]}, + {id:"helperNode2", type:"helper", wires:[]}, + {id:"helperNode3", type:"helper", wires:[]}]; + + + helper.load(switchNode, flow, function() { + var switchNode1 = helper.getNode("switchNode1"); + var helperNode1 = helper.getNode("helperNode1"); + var helperNode2 = helper.getNode("helperNode2"); + var helperNode3 = helper.getNode("helperNode3"); + + helperNode1.on("input", function(msg) { + try { + msg.payload.should.equal("Hello"); + done(); + } catch (err) { + done(err); + } + }); + helperNode2.on("input", function(msg) { + try { + should.fail(null, null, "The otherwise/else statement should not be triggered here!"); + } catch (err) { + done(err); + } + }); + helperNode3.on("input", function(msg) { + try { + should.fail(null, null, "The otherwise/else statement should not be triggered here!"); + } catch (err) { + done(err); + } + }); + switchNode1.receive({payload:"Hello"}); + }); + }); + +}); diff --git a/dgbuilder/test/nodes/core/logic/15-change_spec.js b/dgbuilder/test/nodes/core/logic/15-change_spec.js new file mode 100644 index 00000000..5072dfce --- /dev/null +++ b/dgbuilder/test/nodes/core/logic/15-change_spec.js @@ -0,0 +1,194 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); + +var changeNode = require("../../../../nodes/core/logic/15-change.js"); +var helper = require("../../helper.js"); + +describe('ChangeNode', function() { + + beforeEach(function(done) { + helper.startServer(done); + }); + + afterEach(function(done) { + helper.unload(); + helper.stopServer(done); + }); + + it('should be loaded', function(done) { + var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"payload","from":"","to":"","reg":false,"name":"changeNode","wires":[[]]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + changeNode1.should.have.property('name', 'changeNode'); + done(); + }); + }); + + it('sets the value of the message property', function(done) { + var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"payload","from":"","to":"changed","reg":false,"name":"changeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + msg.payload.should.equal("changed"); + done(); + } catch(err) { + done(err); + } + }); + changeNode1.receive({payload:"changeMe"}); + }); + }); + + it('changes the value of the message property', function(done) { + var flow = [{"id":"changeNode1","type":"change","action":"change","property":"payload","from":"Hello","to":"Goodbye","reg":false,"name":"changeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + msg.payload.should.equal("Goodbye World!"); + done(); + } catch(err) { + done(err); + } + }); + changeNode1.receive({payload:"Hello World!"}); + }); + }); + + it('changes the value of the message property based on a regex', function(done) { + var flow = [{"id":"changeNode1","type":"change","action":"change","property":"payload","from":"\\d+","to":"NUMBER","reg":true,"name":"changeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + msg.payload.should.equal("Replace all numbers NUMBER and NUMBER"); + done(); + } catch(err) { + done(err); + } + }); + changeNode1.receive({payload:"Replace all numbers 12 and 14"}); + }); + }); + + it('supports regex groups', function(done) { + var flow = [{"id":"changeNode1","type":"change","action":"change","property":"payload","from":"(Hello)","to":"$1-$1-$1","reg":true,"name":"changeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + msg.payload.should.equal("Hello-Hello-Hello World"); + done(); + } catch(err) { + done(err); + } + }); + changeNode1.receive({payload:"Hello World"}); + }); + }); + + it('Reports invalid regex', function(done) { + + var sinon = require('sinon'); + + var flow = [{"id":"changeNode1","type":"change","action":"change","property":"payload","from":"\\+**+","to":"NUMBER","reg":true,"name":"changeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + + sinon.stub(changeNode1, 'error', function(error) { + if(error.indexOf("regular expression" > -1)) { + done(); + } else { + try { + should.fail(null, null, "An error should be reported for an invalid regex"); + } catch (err) { + done(err); + } + } + }); + changeNode1.receive({payload:"This is irrelevant"}); + }); + }); + + it('deletes the value of the message property', function(done) { + var flow = [{"id":"changeNode1","type":"change","action":"delete","property":"payload","from":"","to":"","reg":false,"name":"changeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + msg.should.not.have.property('payload'); + done(); + } catch(err) { + done(err); + } + }); + changeNode1.receive({payload:"This won't get through!"}); + }); + }); + +// TODO confirm the behaviour of the change node later,apparently calling eval such that makeNew( msg, node.property.split("."), eval(node.to) ); is incorrect +// it('changes the property name of the message object', function(done) { +// var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"payload","from":"","to":"msg.otherProp=10","reg":false,"name":"changeNode","wires":[["helperNode1"]]}, +// {id:"helperNode1", type:"helper", wires:[]}]; +// helper.load(changeNode, flow, function() { +// var changeNode1 = helper.getNode("changeNode1"); +// var helperNode1 = helper.getNode("helperNode1"); +// helperNode1.on("input", function(msg) { +// try { +// msg.otherProp.should.equal(10); +// done(); +// } catch(err) { +// done(err); +// } +// }); +// changeNode1.receive({payload:"changeMe"}); +// }); +// }); + + it('splits dot delimited properties into objects', function(done) { + var flow = [{"id":"changeNode1","type":"change","action":"replace","property":"pay.load","from":"","to":"10","reg":false,"name":"changeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(changeNode, flow, function() { + var changeNode1 = helper.getNode("changeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + msg.pay.load.should.equal("10"); + done(); + } catch(err) { + done(err); + } + }); + changeNode1.receive({"pay.load":"changeMe"}); + }); + }); +}); + diff --git a/dgbuilder/test/nodes/core/logic/16-range_spec.js b/dgbuilder/test/nodes/core/logic/16-range_spec.js new file mode 100644 index 00000000..abb6c646 --- /dev/null +++ b/dgbuilder/test/nodes/core/logic/16-range_spec.js @@ -0,0 +1,131 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); + +var rangeNode = require("../../../../nodes/core/logic/16-range.js"); +var helper = require("../../helper.js"); + +describe('RangeNode', function() { + + beforeEach(function(done) { + helper.startServer(done); + }); + + afterEach(function(done) { + helper.unload(); + helper.stopServer(done); + }); + + it('should be loaded', function(done) { + var flow = [{"id":"rangeNode1","type":"range","minin":"0","maxin":"99","minout":"100","maxout":"199","action":"range","round":true,"name":"rangeNode","wires":[[]]}]; + helper.load(rangeNode, flow, function() { + var rangeNode1 = helper.getNode("rangeNode1"); + rangeNode1.should.have.property('name', 'rangeNode'); + done(); + }); + }); + + /** + * Run a generic range test + * @param action - scale/clamp (range limit)/roll (modulo): what action to choose + * @param minin - map from minimum value + * @param maxin - map from maximum value + * @param minout - map to minimum value + * @param maxout - map to maximum value + * @param round - whether to round the result to the nearest integer + * @param aPayload - what payload to send to the range node + * @param expectedResult - what result we're expecting + * @param done - the callback to call when test done + */ + function genericRangeTest(action, minin, maxin, minout, maxout, round, aPayload, expectedResult, done) { + var flow = [{"id":"rangeNode1","type":"range","minin":minin,"maxin":maxin,"minout":minout,"maxout":maxout,"action":action,"round":round,"name":"rangeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(rangeNode, flow, function() { + var rangeNode1 = helper.getNode("rangeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + try { + msg.payload.should.equal(expectedResult); + done(); + } catch(err) { + done(err); + } + }); + rangeNode1.receive({payload:aPayload}); + }); + } + + it('ranges numbers up tenfold', function(done) { + genericRangeTest("scale", 0, 100, 0, 1000, false, 50, 500, done); + }); + + it('ranges numbers down such as centimetres to metres', function(done) { + genericRangeTest("scale", 0, 100, 0, 1, false, 55, 0.55, done); + }); + + it('wraps numbers down say for degree/rotation reading 1/2', function(done) { + genericRangeTest("roll", 0, 10, 0, 360, true, 15, 180, done); // 1/2 around wrap => "one and a half turns" + }); + + it('wraps numbers around say for degree/rotation reading 1/3', function(done) { + genericRangeTest("roll", 0, 10, 0, 360, true, 13.3333, 120, done); // 1/3 around wrap => "one and a third turns" + }); + + it('wraps numbers around say for degree/rotation reading 1/4', function(done) { + genericRangeTest("roll", 0, 10, 0, 360, true, 12.5, 90, done); // 1/4 around wrap => "one and a quarter turns" + }); + + it('wraps numbers around say for degree/rotation reading 1/4', function(done) { + genericRangeTest("roll", 0, 10, 0, 360, true, 12.5, 90, done); // 1/4 around wrap => "one and a quarter turns" + }); + + it('wraps numbers down say for degree/rotation reading 1/4', function(done) { + genericRangeTest("roll", 0, 10, 0, 360, true, -12.5, 270, done); // 1/4 backwards wrap => "one and a quarter turns backwards" + }); + + it('clamps numbers within a range - over max', function(done) { + genericRangeTest("clamp", 0, 10, 0, 1000, false, 111, 1000, done); + }); + + it('clamps numbers within a range - below min', function(done) { + genericRangeTest("clamp", 0, 10, 0, 1000, false, -1, 0, done); + }); + + it('reports if input is not a number', function(done) { + var flow = [{"id":"rangeNode1","type":"range","minin":0,"maxin":0,"minout":0,"maxout":0,"action":"scale","round":true,"name":"rangeNode","wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(rangeNode, flow, function() { + var rangeNode1 = helper.getNode("rangeNode1"); + var helperNode1 = helper.getNode("helperNode1"); + + var sinon = require('sinon'); + sinon.stub(rangeNode1, 'log', function(log) { + if(log.indexOf("Not a number") > -1) { + done(); + } else { + try { + should.fail(null, null, "Non-number inputs should be reported!"); + } catch (err) { + done(err); + } + } + }); + + rangeNode1.receive({payload:"NOT A NUMBER"}); + }); + }); +}); diff --git a/dgbuilder/test/nodes/core/parsers/70-HTML_spec.js b/dgbuilder/test/nodes/core/parsers/70-HTML_spec.js new file mode 100644 index 00000000..e7e4cbb5 --- /dev/null +++ b/dgbuilder/test/nodes/core/parsers/70-HTML_spec.js @@ -0,0 +1,211 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var sinon = require("sinon"); +var path = require("path"); +var fs = require('fs-extra'); + +var htmlNode = require("../../../../nodes/core/parsers/70-HTML.js"); +var helper = require("../../helper.js"); + +describe('html node', function() { + + var resourcesDir = __dirname+ path.sep + ".." + path.sep + ".." + path.sep + ".." + path.sep + "resources" + path.sep; + var file = path.join(resourcesDir, "70-HTML-test-file.html"); + + before(function(done) { + helper.startServer(done); + }); + + beforeEach(function() { + fs.existsSync(file).should.be.true; + }); + + afterEach(function() { + helper.unload(); + }); + + it('should be loaded', function(done) { + var flow = [{id:"htmlNode1", type:"html", name: "htmlNode" }]; + helper.load(htmlNode, flow, function() { + var htmlNode1 = helper.getNode("htmlNode1"); + htmlNode1.should.have.property('name', 'htmlNode'); + done(); + }); + }); + + it('should retrieve header contents as default', function(done) { + fs.readFile(file, 'utf8', function(err, data) { + var flow = [{id:"n1",type:"html",wires:[["n2"]],func:"return msg;"}, + {id:"n2", type:"helper"}]; + + helper.load(htmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + should.equal(msg.payload, 'This is a test page for node 70-HTML'); + done(); + }); + n1.receive({payload:data,topic: "bar"}); + }); + }); + }); + + it('should retrieve paragraph contents when specified', function(done) { + fs.readFile(file, 'utf8', function(err, data) { + var flow = [{id:"n1",type:"html",wires:[["n2"]],ret:"text",tag:"p"}, + {id:"n2", type:"helper"}]; + + helper.load(htmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + should.equal(msg.payload, 'There\'s nothing to read here.'); + done(); + }); + n1.receive({payload:data,topic: "bar"}); + }); + }); + }); + + it('should retrieve list contents as an array of html as default', function(done) { + fs.readFile(file, 'utf8', function(err, data) { + var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"ol"}, + {id:"n2", type:"helper"}]; + + helper.load(htmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + msg.payload[0].indexOf("<li>Blue</li>").should.be.above(-1); + msg.payload[0].indexOf("<li>Red</li>").should.be.above(-1); + done(); + }); + n1.receive({payload:data,topic: "bar"}); + }); + }); + }); + + it('should retrieve list contents as an array of text', function(done) { + fs.readFile(file, 'utf8', function(err, data) { + var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"ol",ret:"text"}, + {id:"n2", type:"helper"}]; + + helper.load(htmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + msg.payload.should.be.instanceof(Array).and.have.lengthOf(1); + msg.payload[0].indexOf("Blue").should.be.above(-1); + msg.payload[0].indexOf("Red").should.be.above(-1); + done(); + }); + n1.receive({payload:data,topic: "bar"}); + }); + }); + }); + + it('should log on error', function(done) { + fs.readFile(file,function(err, data) { + var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"p"}, + {id:"n2", type:"helper"}]; + + helper.load(htmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n1.on("log", function(msg) { + msg.should.have.property('msg'); + msg.msg.indexOf("Error:").should.be.above(-1); + msg.msg.should.startWith("Error:"); + done(); + }); + n1.receive({payload:null,topic: "bar"}); + }); + }); + }); + + describe('multiple messages', function(){ + var cnt = 0; + + afterEach(function() { + cnt.should.be.exactly(2); + cnt = 0; + }); + + it('should retrieve list contents as html as default with output as multiple msgs ', function(done) { + fs.readFile(file, 'utf8', function(err, data) { + var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"ul",as:"multi"}, + {id:"n2", type:"helper"}]; + + helper.load(htmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + cnt++; + msg.should.have.property('topic', 'bar'); + if (cnt !== 1 && cnt !== 2) { + return false; + } + if (cnt === 1) { + msg.payload.indexOf("<li>Apple</li>").should.be.above(-1); + msg.payload.indexOf("<li>Pear</li>").should.be.above(-1); + } else if (cnt === 2) { + msg.payload.indexOf("<li>Potato</li>").should.be.above(-1); + msg.payload.indexOf("<li>Parsnip</li>").should.be.above(-1); + done(); + } + }); + n1.receive({payload:data,topic: "bar"}); + }); + }); + }); + + it('should retrieve list contents as text with output as multiple msgs ', function(done) { + fs.readFile(file, 'utf8', function(err, data) { + var flow = [{id:"n1",type:"html",wires:[["n2"]],tag:"ul",ret:"text",as:"multi"}, + {id:"n2", type:"helper"}]; + + helper.load(htmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + cnt++; + msg.should.have.property('topic', 'bar'); + if (cnt !== 1 && cnt !== 2) { + return false; + } + if (cnt === 1) { + msg.payload.indexOf("Apple").should.be.above(-1); + msg.payload.indexOf("Pear").should.be.above(-1); + } else if (cnt === 2) { + msg.payload.indexOf("Potato").should.be.above(-1); + msg.payload.indexOf("Parsnip").should.be.above(-1); + done(); + } + }); + n1.receive({payload:data,topic: "bar"}); + }); + }); + }); + + }); + +}); diff --git a/dgbuilder/test/nodes/core/parsers/70-JSON_spec.js b/dgbuilder/test/nodes/core/parsers/70-JSON_spec.js new file mode 100644 index 00000000..b2ebe719 --- /dev/null +++ b/dgbuilder/test/nodes/core/parsers/70-JSON_spec.js @@ -0,0 +1,104 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var jsonNode = require("../../../../nodes/core/parsers/70-JSON.js"); +var helper = require("../../helper.js"); + +describe('JSON node', function() { + + before(function(done) { + helper.startServer(done); + }); + + afterEach(function() { + helper.unload(); + }); + + it('should be loaded', function(done) { + var flow = [{id:"jsonNode1", type:"json", name: "jsonNode" }]; + helper.load(jsonNode, flow, function() { + var jsonNode1 = helper.getNode("jsonNode1"); + jsonNode1.should.have.property('name', 'jsonNode'); + done(); + }); + }); + + it('should convert a valid json string to a javascript object', function(done) { + var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"}, + {id:"jn2", type:"helper"}]; + helper.load(jsonNode, flow, function() { + var jn1 = helper.getNode("jn1"); + var jn2 = helper.getNode("jn2"); + jn2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + msg.payload.should.have.property('employees'); + msg.payload.employees[0].should.have.property('firstName', 'John'); + msg.payload.employees[0].should.have.property('lastName', 'Smith'); + done(); + }); + var jsonString = '{"employees":[{"firstName":"John", "lastName":"Smith"}]}'; + jn1.receive({payload:jsonString,topic: "bar"}); + }); + }); + + it('should convert a javascript object to a json string', function(done) { + var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"}, + {id:"jn2", type:"helper"}]; + helper.load(jsonNode, flow, function() { + var jn1 = helper.getNode("jn1"); + var jn2 = helper.getNode("jn2"); + jn2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + should.equal(msg.payload, '{"employees":[{"firstName":"John","lastName":"Smith"}]}'); + done(); + }); + var obj = {employees:[{firstName:"John", lastName:"Smith"}]}; + jn1.receive({payload:obj,topic: "bar"}); + }); + }); + + it('should log an error if asked to parse an invalid json string', function(done) { + var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"}, + {id:"jn2", type:"helper"}]; + helper.load(jsonNode, flow, function() { + var jn1 = helper.getNode("jn1"); + var jn2 = helper.getNode("jn2"); + jn1.on("log", function(msg) { + msg.should.have.property('msg'); + should.deepEqual("SyntaxError: Unexpected token o"+ "\nfoo", msg.msg); + done(); + }); + jn1.receive({payload:'foo',topic: "bar"}); + }); + }); + + it('should log an error if asked to parse something thats not json or js', function(done) { + var flow = [{id:"jn1",type:"json",wires:[["jn2"]],func:"return msg;"}, + {id:"jn2", type:"helper"}]; + helper.load(jsonNode, flow, function() { + var jn1 = helper.getNode("jn1"); + var jn2 = helper.getNode("jn2"); + jn1.on("log", function(msg) { + msg.should.have.property('msg'); + should.deepEqual("dropped: 1", msg.msg); + done(); + }); + jn1.receive({payload:1,topic: "bar"}); + }); + }); + +}); diff --git a/dgbuilder/test/nodes/core/parsers/70-XML_spec.js b/dgbuilder/test/nodes/core/parsers/70-XML_spec.js new file mode 100644 index 00000000..8bf269d1 --- /dev/null +++ b/dgbuilder/test/nodes/core/parsers/70-XML_spec.js @@ -0,0 +1,107 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var xmlNode = require("../../../../nodes/core/parsers/70-XML.js"); +var helper = require("../../helper.js"); + +describe('XML node', function() { + + before(function(done) { + helper.startServer(done); + }); + + afterEach(function() { + helper.unload(); + }); + + it('should be loaded', function(done) { + var flow = [{id:"xmlNode1", type:"xml", name: "xmlNode" }]; + helper.load(xmlNode, flow, function() { + var xmlNode1 = helper.getNode("xmlNode1"); + xmlNode1.should.have.property('name', 'xmlNode'); + done(); + }); + }); + + it('should convert a valid xml string to a javascript object', function(done) { + var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"}, + {id:"n2", type:"helper"}]; + helper.load(xmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + msg.payload.should.have.property('employees'); + msg.payload.employees.should.have.property('firstName'); + should.equal(msg.payload.employees.firstName[0], 'John'); + msg.payload.employees.should.have.property('lastName'); + should.equal(msg.payload.employees.lastName[0], 'Smith'); + done(); + }); + var string = '<employees><firstName>John</firstName><lastName>Smith</lastName></employees>'; + n1.receive({payload:string,topic: "bar"}); + }); + }); + + it('should convert a javascript object to an xml string', function(done) { + var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"}, + {id:"n2", type:"helper"}]; + helper.load(xmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n2.on("input", function(msg) { + msg.should.have.property('topic', 'bar'); + console.log(msg.payload); + var index = msg.payload.indexOf('<employees><firstName>John</firstName><lastName>Smith</lastName></employees>'); + index.should.be.above(-1); + done(); + }); + var obj = {"employees":{"firstName":["John"],"lastName":["Smith"] }}; + n1.receive({payload:obj,topic: "bar"}); + }); + }); + + it('should log an error if asked to parse an invalid xml string', function(done) { + var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"}, + {id:"n2", type:"helper"}]; + helper.load(xmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n1.on("log", function(msg) { + should.deepEqual("error", msg.level); + done(); + }); + n1.receive({payload:'<not valid xml>',topic: "bar"}); + }); + }); + + it('should log an error if asked to parse something thats not xml or js', function(done) { + var flow = [{id:"n1",type:"xml",wires:[["n2"]],func:"return msg;"}, + {id:"n2", type:"helper"}]; + helper.load(xmlNode, flow, function() { + var n1 = helper.getNode("n1"); + var n2 = helper.getNode("n2"); + n1.on("log", function(msg) { + msg.should.have.property('msg'); + should.deepEqual("This node only handles xml strings or js objects.", msg.msg); + done(); + }); + n1.receive({payload:1,topic: "bar"}); + }); + }); + +}); diff --git a/dgbuilder/test/nodes/core/storage/28-tail_spec.js b/dgbuilder/test/nodes/core/storage/28-tail_spec.js new file mode 100644 index 00000000..06124576 --- /dev/null +++ b/dgbuilder/test/nodes/core/storage/28-tail_spec.js @@ -0,0 +1,165 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var path = require('path'); +var fs = require('fs-extra'); +var mkdirp = require('mkdirp'); + +var tailNode = require("../../../../nodes/core/storage/28-tail.js"); +var helper = require("../../helper.js"); + +describe('TailNode', function() { + + var resourcesDir = path.join(__dirname,"..","..","..","resources"); + var fileToTail = path.join(resourcesDir,"28-tail-test-file.txt"); + + beforeEach(function(done) { + fs.writeFileSync(fileToTail, "Tail message line 1\nTail message line 2\n"); + helper.startServer(done); + }); + + afterEach(function(done) { + helper.unload().then(function() { + fs.unlinkSync(fileToTail); + helper.stopServer(done); + }); + }); + + it('should be loaded', function(done) { + var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "split":true, "filename":fileToTail}]; + helper.load(tailNode, flow, function() { + var tailNode1 = helper.getNode("tailNode1"); + tailNode1.should.have.property('name', 'tailNode'); + done(); + }); + }); + + it('tail should tail a file', function(done) { + var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "split":true, "filename":fileToTail, "wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(tailNode, flow, function() { + var tailNode1 = helper.getNode("tailNode1"); + var helperNode1 = helper.getNode("helperNode1"); + var inputCounter = 0; + helperNode1.on("input", function(msg) { + //console.log(msg); + msg.should.have.property('topic', fileToTail); + msg.payload.should.equal("Tail message line " + (++inputCounter + 2)); + if (inputCounter === 2) { + done(); + } + }); + setTimeout( function() { + fs.appendFileSync(fileToTail, "Tail message line 3\n"); + fs.appendFileSync(fileToTail, "Tail message line 4\n"); + },100); + }); + }); + + it('tail should work in non-split mode', function(done) { + var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "split":false, "filename":fileToTail, "wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(tailNode, flow, function() { + var tailNode1 = helper.getNode("tailNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + //console.log(msg); + msg.should.have.property('topic', fileToTail); + msg.payload.should.equal("Tail message line 5\nTail message line 6\n"); + done(); + }); + setTimeout( function() { + fs.appendFileSync(fileToTail, "Tail message line 5\nTail message line 6\n"); + },150); + }); + }); + + it('tail should handle a non-existent file', function(done) { + fs.unlinkSync(fileToTail); + var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "split":true, "filename":fileToTail, "wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(tailNode, flow, function() { + var tailNode1 = helper.getNode("tailNode1"); + var helperNode1 = helper.getNode("helperNode1"); + helperNode1.on("input", function(msg) { + msg.should.have.property('topic', fileToTail); + msg.payload.should.equal("Tail message line"); + done(); + }); + setTimeout( function() { + fs.writeFileSync(fileToTail, "Tail message line\n"); + },150); + }); + }); + /* + it('tail should handle file truncation', function(done) { + var flow = [{id:"tailNode1", type:"tail", name: "tailNode", "split":true, "filename":fileToTail, "wires":[["helperNode1"]]}, + {id:"helperNode1", type:"helper", wires:[]}]; + helper.load(tailNode, flow, function() { + var tailNode1 = helper.getNode("tailNode1"); + var helperNode1 = helper.getNode("helperNode1"); + var inputCounter = 0; + var warned = false; + tailNode1.on("log", function(msg) { + if (msg.level == "warn") { warned = true; } + }); + helperNode1.on("input", function(msg) { + console.log("inputCounter =",inputCounter); + console.log(msg); + msg.should.have.property('topic', fileToTail); + inputCounter++; + if (inputCounter === 1) { + warned.should.be.false; + msg.payload.should.equal("Tail message line append"); + } else if (inputCounter === 2) { + msg.payload.should.equal("Tail message line truncate"); + } else { + msg.payload.should.equal("Tail message line append "+inputCounter); + } + + if (inputCounter === 5) { + setTimeout(function() { + warned.should.be.true; + done(); + },100); + } + }); + var actions = [ + function() { fs.appendFileSync(fileToTail, "Tail message line append\n");}, + function() { fs.writeFileSync(fileToTail, "Tail message line truncate\n");}, + function() { fs.appendFileSync(fileToTail, "Tail message line append 3\n");}, + function() { fs.appendFileSync(fileToTail, "Tail message line append 4\n");}, + function() { fs.appendFileSync(fileToTail, "Tail message line append 5\n");} + ]; + + function processAction() { + var action = actions.shift(); + action(); + if (actions.length > 0) { + setTimeout(function() { + processAction(); + },250); + } + } + setTimeout( function() { + processAction(); + },150); + }); + }); + */ + +}); diff --git a/dgbuilder/test/nodes/helper.js b/dgbuilder/test/nodes/helper.js new file mode 100644 index 00000000..9b371ca4 --- /dev/null +++ b/dgbuilder/test/nodes/helper.js @@ -0,0 +1,128 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var when = require("when"); +var request = require('supertest'); +var nock; +if (!process.version.match(/^v0\.[0-9]\./)) { + // only set nock for node >= 0.10 + try { + nock = require('nock'); + } catch (err) { + // nevermind, will skip nock tests + nock = null; + } +} +var RED = require("../../red/red.js"); +var redNodes = require("../../red/nodes"); +var flows = require("../../red/nodes/flows"); +var credentials = require("../../red/nodes/credentials"); +var comms = require("../../red/comms.js"); + +var http = require('http'); +var express = require('express'); +var app = express(); + +var address = '127.0.0.1'; +var listenPort = 0; // use ephemeral port +var port; +var url; + +var server; + +function helperNode(n) { + RED.nodes.createNode(this, n); +} + +module.exports = { + load: function(testNode, testFlows, testCredentials, cb) { + if (typeof testCredentials === 'function') { + cb = testCredentials; + testCredentials = {}; + } + + var storage = { + getFlows: function() { + var defer = when.defer(); + defer.resolve(testFlows); + return defer.promise; + }, + getCredentials: function() { + var defer = when.defer(); + defer.resolve(testCredentials); + return defer.promise; + }, + saveCredentials: function() { + // do nothing + }, + }; + var settings = { + available: function() { return false; } + }; + + redNodes.init(settings, storage); + credentials.init(storage); + RED.nodes.registerType("helper", helperNode); + testNode(RED); + flows.load().then(function() { + should.deepEqual(testFlows, flows.getFlows()); + cb(); + }); + }, + unload: function() { + // TODO: any other state to remove between tests? + redNodes.clearRegistry(); + return flows.stopFlows(); + }, + + getNode: function(id) { + return flows.get(id); + }, + + credentials: credentials, + + clearFlows: function() { + return flows.clear(); + }, + + request: function() { + return request(RED.httpAdmin); + }, + + startServer: function(done) { + server = http.createServer(function(req,res){app(req,res);}); + RED.init(server, {}); + server.listen(listenPort, address); + server.on('listening', function() { + port = server.address().port; + url = 'http://' + address + ':' + port; + comms.start(); + done(); + }); + }, + //TODO consider saving TCP handshake/server reinit on start/stop/start sequences + stopServer: function(done) { + if(server) { + server.close(done); + } + }, + + url: function() { return url; }, + + nock: nock, + +}; diff --git a/dgbuilder/test/red/cli/lib/config_spec.js b/dgbuilder/test/red/cli/lib/config_spec.js new file mode 100644 index 00000000..68e960af --- /dev/null +++ b/dgbuilder/test/red/cli/lib/config_spec.js @@ -0,0 +1,53 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var sinon = require("sinon"); +var fs = require("fs"); + +var config = require("../../../../red/cli/lib/config"); + +describe("cli config", function() { + afterEach(function() { + config.unload(); + }); + it('loads preferences when target referenced', sinon.test(function() { + this.stub(fs,"readFileSync",function() { + return '{"target":"http://example.com:1880"}' + }); + config.target.should.eql("http://example.com:1880"); + })); + it('provide default value for target', sinon.test(function() { + this.stub(fs,"readFileSync",function() { + return '{}' + }); + config.target.should.eql("http://localhost:1880"); + })); + it('saves preferences when target set', sinon.test(function() { + this.stub(fs,"readFileSync",function() { + return '{"target":"http://another.example.com:1880"}' + }); + this.stub(fs,"writeFileSync",function() {}); + + config.target.should.eql("http://another.example.com:1880"); + config.target = "http://final.example.com:1880"; + + fs.readFileSync.calledOnce.should.be.true; + fs.writeFileSync.calledOnce.should.be.true; + + })); + +});
\ No newline at end of file diff --git a/dgbuilder/test/red/cli/lib/request_spec.js b/dgbuilder/test/red/cli/lib/request_spec.js new file mode 100644 index 00000000..7d2b5ac7 --- /dev/null +++ b/dgbuilder/test/red/cli/lib/request_spec.js @@ -0,0 +1,46 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var sinon = require("sinon"); +var fs = require("fs"); +var request = require("request"); + +var apiRequest = require("../../../../red/cli/lib/request"); +var config = require("../../../../red/cli/lib/config"); + +describe("cli request", function() { + var sandbox = sinon.sandbox.create(); + before(function() { + sandbox.stub(fs,"readFileSync",function() { + return '{"target":"http://example.com:1880"}' + }); + }); + after(function() { + sandbox.restore(); + }); + + it('returns the json response to a get', sinon.test(function(done) { + this.stub(request, 'get').yields(null, {statusCode:200}, JSON.stringify({a: "b"})); + + apiRequest("/foo",{}).then(function(res) { + res.should.eql({a:"b"}); + done(); + }).otherwise(function(err) { + done(err); + }); + })); +});
\ No newline at end of file diff --git a/dgbuilder/test/red/cli/nr-cli_spec.js b/dgbuilder/test/red/cli/nr-cli_spec.js new file mode 100644 index 00000000..59a5c641 --- /dev/null +++ b/dgbuilder/test/red/cli/nr-cli_spec.js @@ -0,0 +1,15 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/
\ No newline at end of file diff --git a/dgbuilder/test/red/comms_spec.js b/dgbuilder/test/red/comms_spec.js new file mode 100644 index 00000000..dce4d83a --- /dev/null +++ b/dgbuilder/test/red/comms_spec.js @@ -0,0 +1,189 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var http = require('http'); +var express = require('express'); +var app = express(); +var WebSocket = require('ws'); + +var comms = require("../../red/comms.js"); +var address = '127.0.0.1'; +var listenPort = 0; // use ephemeral port + +describe("comms", function() { + describe("with default keepalive", function() { + var server; + var url; + var port; + before(function(done) { + server = http.createServer(function(req,res){app(req,res)}); + comms.init(server, {}); + server.listen(listenPort, address); + server.on('listening', function() { + port = server.address().port; + url = 'http://' + address + ':' + port + '/comms'; + comms.start(); + done(); + }); + }); + + after(function() { + comms.stop(); + }); + + it('accepts connection', function(done) { + var ws = new WebSocket(url); + ws.on('open', function() { + ws.close(); + done(); + }); + }); + + it('publishes message after subscription', function(done) { + var ws = new WebSocket(url); + ws.on('open', function() { + ws.send('{"subscribe":"topic1"}'); + comms.publish('topic1', 'foo'); + }); + ws.on('message', function(msg) { + msg.should.equal('{"topic":"topic1","data":"foo"}'); + ws.close(); + done(); + }); + }); + + it('publishes retained message for subscription', function(done) { + comms.publish('topic2', 'bar', true); + var ws = new WebSocket(url); + ws.on('open', function() { + ws.send('{"subscribe":"topic2"}'); + }); + ws.on('message', function(msg) { + msg.should.equal('{"topic":"topic2","data":"bar"}'); + ws.close(); + done(); + }); + }); + + it('retained message is deleted by non-retained message', function(done) { + comms.publish('topic3', 'retained', true); + comms.publish('topic3', 'non-retained'); + var ws = new WebSocket(url); + ws.on('open', function() { + ws.send('{"subscribe":"topic3"}'); + comms.publish('topic3', 'new'); + }); + ws.on('message', function(msg) { + msg.should.equal('{"topic":"topic3","data":"new"}'); + ws.close(); + done(); + }); + }); + + it('malformed messages are ignored',function(done) { + var ws = new WebSocket(url); + ws.on('open', function() { + ws.send('not json'); + ws.send('[]'); + ws.send('{"subscribe":"topic3"}'); + comms.publish('topic3', 'correct'); + }); + ws.on('message', function(msg) { + msg.should.equal('{"topic":"topic3","data":"correct"}'); + ws.close(); + done(); + }); + }); + + // The following test currently fails due to minimum viable + // implementation. More test should be written to test topic + // matching once this one is passing + + if (0) { + it('receives message on correct topic', function(done) { + var ws = new WebSocket(url); + ws.on('open', function() { + ws.send('{"subscribe":"topic4"}'); + comms.publish('topic5', 'foo'); + comms.publish('topic4', 'bar'); + }); + ws.on('message', function(msg) { + msg.should.equal('{"topic":"topic4","data":"bar"}'); + ws.close(); + done(); + }); + }); + } + }); + + describe("keep alives", function() { + var server; + var url; + var port; + before(function(done) { + server = http.createServer(function(req,res){app(req,res)}); + comms.init(server, {webSocketKeepAliveTime: 100}); + server.listen(listenPort, address); + server.on('listening', function() { + port = server.address().port; + url = 'http://' + address + ':' + port + '/comms'; + comms.start(); + done(); + }); + }); + after(function() { + comms.stop(); + }); + it('are sent', function(done) { + var ws = new WebSocket(url); + var count = 0; + ws.on('message', function(data) { + var msg = JSON.parse(data); + msg.should.have.property('topic','hb'); + msg.should.have.property('data').be.a.Number; + count++; + if (count == 3) { + ws.close(); + done(); + } + }); + }); + it('are not sent if other messages are sent', function(done) { + var ws = new WebSocket(url); + var count = 0; + var interval; + ws.on('open', function() { + ws.send('{"subscribe":"foo"}'); + interval = setInterval(function() { + comms.publish('foo', 'bar'); + }, 50); + }); + ws.on('message', function(data) { + var msg = JSON.parse(data); + msg.should.have.property('topic', 'foo'); + msg.should.have.property('data', 'bar'); + count++; + if (count == 5) { + clearInterval(interval); + ws.close(); + done(); + } + }); + }); + }); + +}); diff --git a/dgbuilder/test/red/events_spec.js b/dgbuilder/test/red/events_spec.js new file mode 100644 index 00000000..24759262 --- /dev/null +++ b/dgbuilder/test/red/events_spec.js @@ -0,0 +1,22 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var should = require("should"); + +describe("red/events", function() { + it('can be required without errors', function() { + require("../../red/events"); + }); +}); diff --git a/dgbuilder/test/red/library_spec.js b/dgbuilder/test/red/library_spec.js new file mode 100644 index 00000000..52255287 --- /dev/null +++ b/dgbuilder/test/red/library_spec.js @@ -0,0 +1,237 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var sinon = require('sinon'); +var request = require('supertest'); +var http = require('http'); +var express = require('express'); + +var fs = require('fs-extra'); +var path = require('path'); +var when = require('when'); + +var app = express(); +var RED = require("../../red/red.js"); +var server = require("../../red/server.js"); +var nodes = require("../../red/nodes"); + +describe("library", function() { + var userDir = path.join(__dirname,".testUserHome"); + before(function(done) { + fs.remove(userDir,function(err) { + fs.mkdir(userDir,function() { + sinon.stub(nodes, 'load', function() { + return when.promise(function(resolve,reject){ + resolve([]); + }); + }); + RED.init(http.createServer(function(req,res){app(req,res)}), + {userDir: userDir}); + server.start().then(function () { done(); }); + }); + }); + }); + + after(function(done) { + fs.remove(userDir,done); + server.stop(); + nodes.load.restore(); + }); + + afterEach(function(done) { + fs.remove(userDir,function(err) { + fs.mkdir(userDir,done); + }); + }); + + describe("flows", function() { + it('returns empty result', function(done) { + request(RED.httpAdmin) + .get('/library/flows') + .expect(200) + .end(function(err,res) { + if (err) { + throw err; + } + res.body.should.not.have.property('f'); + done(); + }); + }); + + it('returns 404 for non-existent entry', function(done) { + request(RED.httpAdmin) + .get('/library/flows/foo') + .expect(404) + .end(done); + }); + + it('can store and retrieve item', function(done) { + var flow = '[]'; + request(RED.httpAdmin) + .post('/library/flows/foo') + .set('Content-Type', 'text/plain') + .send(flow) + .expect(204).end(function (err, res) { + if (err) { + throw err; + } + request(RED.httpAdmin) + .get('/library/flows/foo') + .expect(200) + .end(function(err,res) { + if (err) { + throw err; + } + res.text.should.equal(flow); + done(); + }); + }); + }); + + it('lists a stored item', function(done) { + request(RED.httpAdmin) + .post('/library/flows/bar') + .expect(204) + .end(function () { + request(RED.httpAdmin) + .get('/library/flows') + .expect(200) + .end(function(err,res) { + if (err) { + throw err; + } + res.body.should.have.property('f'); + should.deepEqual(res.body.f,['bar']); + done(); + }); + }); + }); + + it('returns 403 for malicious access attempt', function(done) { + // without the userDir override the malicious url would be + // http://127.0.0.1:1880/library/flows/../../package to + // obtain package.json from the node-red root. + request(RED.httpAdmin) + .get('/library/flows/../../../../../package') + .expect(403) + .end(done); + }); + + it('returns 403 for malicious access attempt', function(done) { + // without the userDir override the malicious url would be + // http://127.0.0.1:1880/library/flows/../../package to + // obtain package.json from the node-red root. + request(RED.httpAdmin) + .post('/library/flows/../../../../../package') + .expect(403) + .end(done); + }); + + }); + + describe("type", function() { + before(function() { + RED.library.register('test'); + }); + + it('returns empty result', function(done) { + request(RED.httpAdmin) + .get('/library/test') + .expect(200) + .end(function(err,res) { + if (err) { + throw err; + } + res.body.should.not.have.property('f'); + done(); + }); + }); + + it('returns 404 for non-existent entry', function(done) { + request(RED.httpAdmin) + .get('/library/test/foo') + .expect(404) + .end(done); + }); + + it('can store and retrieve item', function(done) { + var flow = '[]'; + request(RED.httpAdmin) + .post('/library/test/foo') + .set('Content-Type', 'text/plain') + .send(flow) + .expect(204).end(function (err, res) { + if (err) { + throw err; + } + request(RED.httpAdmin) + .get('/library/test/foo') + .expect(200) + .end(function(err,res) { + if (err) { + throw err; + } + res.text.should.equal(flow); + done(); + }); + }); + }); + + it('lists a stored item', function(done) { + request(RED.httpAdmin) + .post('/library/test/bar') + .expect(204) + .end(function () { + request(RED.httpAdmin) + .get('/library/test') + .expect(200) + .end(function(err,res) { + if (err) { + throw err; + } + should.deepEqual(res.body,[{ fn: 'bar'}]); + done(); + }); + }); + }); + + + it('returns 403 for malicious access attempt', function(done) { + request(RED.httpAdmin) + .get('/library/test/../../../../../../../../../../etc/passwd') + .expect(403) + .end(done); + }); + + it('returns 403 for malicious access attempt', function(done) { + request(RED.httpAdmin) + .get('/library/test/..\\..\\..\\..\\..\\..\\..\\..\\..\\..\\etc\\passwd') + .expect(403) + .end(done); + }); + + it('returns 403 for malicious access attempt', function(done) { + request(RED.httpAdmin) + .post('/library/test/../../../../../../../../../../etc/passwd') + .set('Content-Type', 'text/plain') + .send('root:x:0:0:root:/root:/usr/bin/tclsh') + .expect(403) + .end(done); + }); + + }); +}); diff --git a/dgbuilder/test/red/log_spec.js b/dgbuilder/test/red/log_spec.js new file mode 100644 index 00000000..0fb0aafd --- /dev/null +++ b/dgbuilder/test/red/log_spec.js @@ -0,0 +1,22 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var should = require("should"); + +describe("red/log", function() { + it('can be required without errors', function() { + require("../../red/log"); + }); +}); diff --git a/dgbuilder/test/red/nodes/Node_spec.js b/dgbuilder/test/red/nodes/Node_spec.js new file mode 100644 index 00000000..6ac54bd2 --- /dev/null +++ b/dgbuilder/test/red/nodes/Node_spec.js @@ -0,0 +1,297 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var sinon = require('sinon'); +var RedNode = require("../../../red/nodes/Node"); +var comms = require('../../../red/comms'); + +describe('Node', function() { + describe('#constructor',function() { + it('is called with an id and a type',function() { + var n = new RedNode({id:'123',type:'abc'}); + n.should.have.property('id','123'); + n.should.have.property('type','abc'); + n.should.not.have.property('name'); + n.wires.should.be.empty; + }); + + it('is called with an id, a type and a name',function() { + var n = new RedNode({id:'123',type:'abc',name:'barney'}); + n.should.have.property('id','123'); + n.should.have.property('type','abc'); + n.should.have.property('name','barney'); + n.wires.should.be.empty; + }); + + it('is called with an id, a type and some wires',function() { + var n = new RedNode({id:'123',type:'abc',wires:['123','456']}); + n.should.have.property('id','123'); + n.should.have.property('type','abc'); + n.should.not.have.property('name'); + n.wires.should.have.length(2); + }); + + }); + + describe('#close', function() { + it('emits close event when closed',function(done) { + var n = new RedNode({id:'123',type:'abc'}); + n.on('close',function() { + done(); + }); + var p = n.close(); + should.not.exist(p); + }); + + it('returns a promise when provided a callback with a done parameter',function(testdone) { + var n = new RedNode({id:'123',type:'abc'}); + n.on('close',function(done) { + setTimeout(function() { + done(); + },200); + }); + var p = n.close(); + should.exist(p); + p.then(function() { + testdone(); + }); + }); + }); + + + describe('#receive', function() { + it('emits input event when called', function(done) { + var n = new RedNode({id:'123',type:'abc'}); + var message = {payload:"hello world"}; + n.on('input',function(msg) { + should.deepEqual(msg,message); + done(); + }); + n.receive(message); + }); + }); + + describe('#send', function() { + + it('emits a single message', function(done) { + var n1 = new RedNode({id:'n1',type:'abc',wires:[['n2']]}); + var n2 = new RedNode({id:'n2',type:'abc'}); + var message = {payload:"hello world"}; + + n2.on('input',function(msg) { + // msg equals message, but is a new copy + should.deepEqual(msg,message); + should.notStrictEqual(msg,message); + done(); + }); + + n1.send(message); + }); + + it('emits multiple messages on a single output', function(done) { + var n1 = new RedNode({id:'n1',type:'abc',wires:[['n2']]}); + var n2 = new RedNode({id:'n2',type:'abc'}); + + var messages = [ + {payload:"hello world"}, + {payload:"hello world again"} + ]; + + var rcvdCount = 0; + + n2.on('input',function(msg) { + should.deepEqual(msg,messages[rcvdCount]); + should.notStrictEqual(msg,messages[rcvdCount]); + rcvdCount += 1; + if (rcvdCount == 2) { + done(); + } + }); + n1.send([messages]); + }); + + it('emits messages to multiple outputs', function(done) { + var n1 = new RedNode({id:'n1',type:'abc',wires:[['n2'],['n3'],['n4','n5']]}); + var n2 = new RedNode({id:'n2',type:'abc'}); + var n3 = new RedNode({id:'n3',type:'abc'}); + var n4 = new RedNode({id:'n4',type:'abc'}); + var n5 = new RedNode({id:'n5',type:'abc'}); + + var messages = [ + {payload:"hello world"}, + null, + {payload:"hello world again"} + ]; + + var rcvdCount = 0; + + n2.on('input',function(msg) { + should.deepEqual(msg,messages[0]); + should.notStrictEqual(msg,messages[0]); + rcvdCount += 1; + if (rcvdCount == 3) { + done(); + } + }); + + n3.on('input',function(msg) { + should.fail(null,null,"unexpected message"); + }); + + n4.on('input',function(msg) { + should.deepEqual(msg,messages[2]); + should.notStrictEqual(msg,messages[2]); + rcvdCount += 1; + if (rcvdCount == 3) { + done(); + } + }); + + n5.on('input',function(msg) { + should.deepEqual(msg,messages[2]); + should.notStrictEqual(msg,messages[2]); + rcvdCount += 1; + if (rcvdCount == 3) { + done(); + } + }); + + n1.send(messages); + }); + + it('emits no messages', function(done) { + var n1 = new RedNode({id:'n1',type:'abc',wires:[['n2']]}); + var n2 = new RedNode({id:'n2',type:'abc'}); + + n2.on('input',function(msg) { + should.fail(null,null,"unexpected message"); + }); + + setTimeout(function() { + done(); + }, 200); + + n1.send(); + }); + + it('emits messages ignoring non-existent nodes', function(done) { + var n1 = new RedNode({id:'n1',type:'abc',wires:[['n9'],['n2']]}); + var n2 = new RedNode({id:'n2',type:'abc'}); + + var messages = [ + {payload:"hello world"}, + {payload:"hello world again"} + ]; + + n2.on('input',function(msg) { + should.deepEqual(msg,messages[1]); + should.notStrictEqual(msg,messages[1]); + done(); + }); + + n1.send(messages); + }); + + it('emits messages without cloning req or res', function(done) { + var n1 = new RedNode({id:'n1',type:'abc',wires:[['n2']]}); + var n2 = new RedNode({id:'n2',type:'abc'}); + + var req = {}; + var res = {}; + var cloned = {}; + var message = {payload: "foo", cloned: cloned, req: req, res: res}; + + n2.on('input',function(msg) { + should.deepEqual(msg, message); + msg.cloned.should.not.be.exactly(message.cloned); + msg.req.should.be.exactly(message.req); + msg.res.should.be.exactly(message.res); + done(); + }); + + n1.send(message); + }); + + }); + + describe('#log', function() { + it('emits a log message', function(done) { + var n = new RedNode({id:'123',type:'abc'}); + n.on('log',function(obj) { + should.deepEqual({level:"log", id:n.id, + type:n.type, msg:"a log message"}, obj); + done(); + }); + n.log("a log message"); + }); + }); + + describe('#log', function() { + it('emits a log message with a name', function(done) { + var n = new RedNode({id:'123', type:'abc', name:"barney"}); + n.on('log',function(obj) { + should.deepEqual({level:"log", id:n.id, name: "barney", + type:n.type, msg:"a log message"}, obj); + done(); + }); + n.log("a log message"); + }); + }); + + describe('#warn', function() { + it('emits a warning', function(done) { + var n = new RedNode({id:'123',type:'abc'}); + n.on('log',function(obj) { + should.deepEqual({level:"warn", id:n.id, + type:n.type, msg:"a warning"}, obj); + done(); + }); + n.warn("a warning"); + }); + }); + + describe('#error', function() { + it('emits an error message', function(done) { + var n = new RedNode({id:'123',type:'abc'}); + n.on('log',function(obj) { + should.deepEqual({level:"error", id:n.id, + type:n.type, msg:"an error message"}, obj); + done(); + }); + n.error("an error message"); + }); + }); + + describe('#status', function() { + after(function() { + comms.publish.restore(); + }); + it('publishes status', function(done) { + var n = new RedNode({id:'123',type:'abc'}); + var status = {fill:"green",shape:"dot",text:"connected"}; + sinon.stub(comms, 'publish', function(topic, message, retain) { + topic.should.equal('status/123'); + message.should.equal(status); + retain.should.be.true; + done(); + }); + + n.status(status); + }); + }); + +}); diff --git a/dgbuilder/test/red/nodes/credentials_spec.js b/dgbuilder/test/red/nodes/credentials_spec.js new file mode 100644 index 00000000..3d10461f --- /dev/null +++ b/dgbuilder/test/red/nodes/credentials_spec.js @@ -0,0 +1,497 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var sinon = require("sinon"); +var when = require("when"); +var util = require("util"); + +var index = require("../../../red/nodes/index"); +var credentials = require("../../../red/nodes/credentials"); + +describe('Credentials', function() { + + afterEach(function() { + index.clearRegistry(); + }); + + it('loads from storage',function(done) { + + var storage = { + getCredentials: function() { + return when.promise(function(resolve,reject) { + resolve({"a":{"b":1,"c":2}}); + }); + } + }; + + credentials.init(storage); + + credentials.load().then(function() { + + credentials.get("a").should.have.property('b',1); + credentials.get("a").should.have.property('c',2); + + done(); + }); + }); + + + it('saves to storage', function(done) { + var storage = { + getCredentials: function() { + return when.promise(function(resolve,reject) { + resolve({"a":{"b":1,"c":2}}); + }); + }, + saveCredentials: function(creds) { + return when(true); + } + }; + sinon.spy(storage,"saveCredentials"); + credentials.init(storage); + credentials.load().then(function() { + should.not.exist(credentials.get("b")) + credentials.add('b',{"d":3}); + storage.saveCredentials.callCount.should.be.exactly(1); + credentials.get("b").should.have.property('d',3); + storage.saveCredentials.restore(); + done(); + }); + }); + + it('deletes from storage', function(done) { + var storage = { + getCredentials: function() { + return when.promise(function(resolve,reject) { + resolve({"a":{"b":1,"c":2}}); + }); + }, + saveCredentials: function(creds) { + return when(true); + } + }; + sinon.spy(storage,"saveCredentials"); + credentials.init(storage); + credentials.load().then(function() { + should.exist(credentials.get("a")) + credentials.delete('a'); + storage.saveCredentials.callCount.should.be.exactly(1); + should.not.exist(credentials.get("a")); + storage.saveCredentials.restore(); + done(); + }); + + }); + + it('clean up from storage', function(done) { + var storage = { + getCredentials: function() { + return when.promise(function(resolve,reject) { + resolve({"a":{"b":1,"c":2}}); + }); + }, + saveCredentials: function(creds) { + return when(true); + } + }; + sinon.spy(storage,"saveCredentials"); + credentials.init(storage); + credentials.load().then(function() { + should.exist(credentials.get("a")); + credentials.clean(function() { + return false; + }); + storage.saveCredentials.callCount.should.be.exactly(1); + should.not.exist(credentials.get("a")); + storage.saveCredentials.restore(); + done(); + }); + }); + + it('handle error loading from storage', function(done) { + var storage = { + getCredentials: function() { + return when.promise(function(resolve,reject) { + reject("test forcing failure"); + }); + }, + saveCredentials: function(creds) { + return when(true); + } + }; + var logmsg = 'no errors yet'; + sinon.stub(util, 'log', function(msg) { + logmsg = msg; + }); + + credentials.init(storage); + credentials.load().then(function() { + should.equal('[red] Error loading credentials : test forcing failure', logmsg); + util.log.restore(); + done(); + }).otherwise(function(err){ + util.log.restore(); + done(err); + }); + }); + + it('credential type is not registered when extract', function(done) { + var testFlows = [{"type":"test","id":"tab1","label":"Sheet 1"}]; + var storage = { + getFlows: function() { + var defer = when.defer(); + defer.resolve(testFlows); + return defer.promise; + }, + getCredentials: function() { + return when.promise(function(resolve,reject) { + resolve({"tab1":{"b":1,"c":2}}); + }); + }, + saveFlows: function(conf) { + var defer = when.defer(); + defer.resolve(); + should.deepEqual(testFlows, conf); + return defer.promise; + }, + saveCredentials: function(creds) { + return when(true); + }, + getSettings: function() { + return when({}); + }, + saveSettings: function(s) { + return when(); + } + }; + function TestNode(n) { + index.createNode(this, n); + + this.id = 'tab1'; + this.type = 'test'; + this.name = 'barney'; + var node = this; + + this.on("log", function() { + // do nothing + }); + } + var logmsg = 'nothing logged yet'; + sinon.stub(util, 'log', function(msg) { + logmsg = msg; + }); + var settings = { + available: function() { return false;} + } + index.init(settings, storage); + index.registerType('test', TestNode); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'test',name:'barney'}); + credentials.extract(testnode); + should.equal(logmsg, 'Credential Type test is not registered.'); + util.log.restore(); + done(); + }).otherwise(function(err){ + util.log.restore(); + done(err); + }); + }); + + describe('extract and store credential updates in the provided node', function() { + var path = require('path'); + var fs = require('fs-extra'); + var http = require('http'); + var express = require('express'); + var server = require("../../../red/server"); + var localfilesystem = require("../../../red/storage/localfilesystem"); + var app = express(); + var RED = require("../../../red/red.js"); + + var userDir = path.join(__dirname,".testUserHome"); + before(function(done) { + fs.remove(userDir,function(err) { + fs.mkdir(userDir,function() { + sinon.stub(index, 'load', function() { + return when.promise(function(resolve,reject){ + resolve([]); + }); + }); + sinon.stub(localfilesystem, 'getCredentials', function() { + return when.promise(function(resolve,reject) { + resolve({"tab1":{"foo": 2, "pswd":'sticks'}}); + }); + }) ; + RED.init(http.createServer(function(req,res){app(req,res)}), + {userDir: userDir}); + server.start().then(function () { + done(); + }); + }); + }); + }); + + after(function(done) { + fs.remove(userDir,done); + server.stop(); + index.load.restore(); + localfilesystem.getCredentials.restore(); + }); + + function TestNode(n) { + index.createNode(this, n); + var node = this; + this.on("log", function() { + // do nothing + }); + } + + it(': credential updated with good value', function(done) { + index.registerType('test', TestNode, { + credentials: { + foo: {type:"test"} + } + }); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'test',name:'barney'}); + credentials.extract(testnode); + should.exist(credentials.get('tab1')); + credentials.get('tab1').should.have.property('foo',2); + + // set credentials to be an updated value and checking this is extracted properly + testnode.credentials = {"foo": 3}; + credentials.extract(testnode); + should.exist(credentials.get('tab1')); + credentials.get('tab1').should.not.have.property('foo',2); + credentials.get('tab1').should.have.property('foo',3); + done(); + }).otherwise(function(err){ + done(err); + }); + }); + + it(': credential updated with empty value', function(done) { + index.registerType('test', TestNode, { + credentials: { + foo: {type:"test"} + } + }); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'test',name:'barney'}); + // setting value of "foo" credential to be empty removes foo as a property + testnode.credentials = {"foo": ''}; + credentials.extract(testnode); + should.exist(credentials.get('tab1')); + credentials.get('tab1').should.not.have.property('foo',2); + credentials.get('tab1').should.not.have.property('foo'); + done(); + }).otherwise(function(err){ + done(err); + }); + }); + + it(': undefined credential updated', function(done) { + index.registerType('test', TestNode, { + credentials: { + foo: {type:"test"} + } + }); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'test',name:'barney'}); + // setting value of an undefined credential should not change anything + testnode.credentials = {"bar": 4}; + credentials.extract(testnode); + should.exist(credentials.get('tab1')); + credentials.get('tab1').should.have.property('foo',2); + credentials.get('tab1').should.not.have.property('bar'); + done(); + }).otherwise(function(err){ + done(err); + }); + }); + + it(': password credential updated', function(done) { + index.registerType('password', TestNode, { + credentials: { + pswd: {type:"password"} + } + }); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'password',name:'barney'}); + // setting value of password credential should update password + testnode.credentials = {"pswd": 'fiddle'}; + credentials.extract(testnode); + should.exist(credentials.get('tab1')); + credentials.get('tab1').should.have.property('pswd','fiddle'); + credentials.get('tab1').should.not.have.property('pswd','sticks'); + done(); + }).otherwise(function(err){ + done(err); + }); + }); + + it(': password credential not updated', function(done) { + index.registerType('password', TestNode, { + credentials: { + pswd: {type:"password"} + } + }); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'password',name:'barney'}); + // setting value of password credential should update password + testnode.credentials = {"pswd": '__PWRD__'}; + credentials.extract(testnode); + should.exist(credentials.get('tab1')); + credentials.get('tab1').should.have.property('pswd','sticks'); + credentials.get('tab1').should.not.have.property('pswd','__PWRD__'); + done(); + }).otherwise(function(err){ + done(err); + }); + }); + + }) + + describe('registerEndpoint', function() { + var path = require('path'); + var fs = require('fs-extra'); + var http = require('http'); + var express = require('express'); + var request = require('supertest'); + + var server = require("../../../red/server"); + var localfilesystem = require("../../../red/storage/localfilesystem"); + var app = express(); + var RED = require("../../../red/red.js"); + + var userDir = path.join(__dirname,".testUserHome"); + before(function(done) { + fs.remove(userDir,function(err) { + fs.mkdir(userDir,function() { + sinon.stub(index, 'load', function() { + return when.promise(function(resolve,reject){ + resolve([]); + }); + }); + sinon.stub(localfilesystem, 'getCredentials', function() { + return when.promise(function(resolve,reject) { + resolve({"tab1":{"foo": 2, "pswd":'sticks'}}); + }); + }) ; + RED.init(http.createServer(function(req,res){app(req,res)}), + {userDir: userDir}); + server.start().then(function () { + done(); + }); + }); + }); + }); + + after(function(done) { + fs.remove(userDir,done); + server.stop(); + index.load.restore(); + localfilesystem.getCredentials.restore(); + }); + + function TestNode(n) { + index.createNode(this, n); + var node = this; + this.on("log", function() { + // do nothing + }); + } + + it(': valid credential type', function(done) { + index.registerType('test', TestNode, { + credentials: { + foo: {type:"test"} + } + }); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'foo',name:'barney'}); + request(RED.httpAdmin).get('/credentials/test/tab1').expect(200).end(function(err,res) { + if (err) { + done(err); + } + res.body.should.have.property('foo', 2); + done(); + }); + }).otherwise(function(err){ + done(err); + }); + }); + + it(': password credential type', function(done) { + index.registerType('password', TestNode, { + credentials: { + pswd: {type:"password"} + } + }); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'pswd',name:'barney'}); + request(RED.httpAdmin).get('/credentials/password/tab1').expect(200).end(function(err,res) { + if (err) { + done(err); + } + res.body.should.have.property('has_pswd', true); + res.body.should.not.have.property('pswd'); + done(); + }); + }).otherwise(function(err){ + done(err); + }); + }); + + it(': returns 404 for undefined credential type', function(done) { + index.registerType('test', TestNode, { + credentials: { + foo: {type:"test"} + } + }); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'foo',name:'barney'}); + request(RED.httpAdmin).get('/credentials/unknownType/tab1').expect(404).end(done); + }).otherwise(function(err){ + done(err); + }); + }); + + it(': undefined nodeID', function(done) { + index.registerType('test', TestNode, { + credentials: { + foo: {type:"test"} + } + }); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'foo',name:'barney'}); + request(RED.httpAdmin).get('/credentials/test/unknownNode').expect(200).end(function(err,res) { + if (err) { + done(err); + } + var b = res.body; + res.body.should.not.have.property('foo'); + done(); + }); + }).otherwise(function(err){ + done(err); + }); + }); + + }) + +}) + diff --git a/dgbuilder/test/red/nodes/flows_spec.js b/dgbuilder/test/red/nodes/flows_spec.js new file mode 100644 index 00000000..091bf409 --- /dev/null +++ b/dgbuilder/test/red/nodes/flows_spec.js @@ -0,0 +1,134 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var sinon = require("sinon"); +var when = require("when"); +var flows = require("../../../red/nodes/flows"); +var RedNode = require("../../../red/nodes/Node"); +var RED = require("../../../red/nodes"); +var events = require("../../../red/events"); +var typeRegistry = require("../../../red/nodes/registry"); + + +var settings = { + available: function() { return false; } +} + +function loadFlows(testFlows, cb) { + var storage = { + getFlows: function() { + return when.resolve(testFlows); + }, + getCredentials: function() { + return when.resolve({}); + } + }; + RED.init(settings, storage); + flows.load().then(function() { + should.deepEqual(testFlows, flows.getFlows()); + cb(); + }); +} + +describe('flows', function() { + + describe('#add',function() { + it('should be called by node constructor',function(done) { + var n = new RedNode({id:'123',type:'abc'}); + should.deepEqual(n, flows.get("123")); + flows.clear().then(function() { + done(); + }); + }); + }); + + describe('#each',function() { + it('should "visit" all nodes',function(done) { + var nodes = [ + new RedNode({id:'n0'}), + new RedNode({id:'n1'}) + ]; + var count = 0; + flows.each(function(node) { + should.deepEqual(nodes[count], node); + count += 1; + if (count == 2) { + done(); + } + }); + }); + }); + + describe('#load',function() { + it('should load nothing when storage is empty',function(done) { + loadFlows([], done); + }); + + it('should load and start an empty tab flow',function(done) { + loadFlows([{"type":"tab","id":"tab1","label":"Sheet 1"}], function() {}); + events.once('nodes-started', function() { done(); }); + }); + + it('should load and start a registered node type', function(done) { + RED.registerType('debug', function() {}); + var typeRegistryGet = sinon.stub(typeRegistry,"get",function(nt) { + return function() {}; + }); + loadFlows([{"id":"n1","type":"debug"}], function() { }); + events.once('nodes-started', function() { + typeRegistryGet.restore(); + done(); + }); + }); + + it('should load and start when node type is registered', function(done) { + var typeRegistryGet = sinon.stub(typeRegistry,"get"); + typeRegistryGet.onCall(0).returns(null); + typeRegistryGet.returns(function(){}); + + loadFlows([{"id":"n2","type":"inject"}], function() { + events.emit('type-registered','inject'); + }); + events.once('nodes-started', function() { + typeRegistryGet.restore(); + done(); + }); + }); + }); + + describe('#setFlows',function() { + it('should save and start an empty tab flow',function(done) { + var saved = 0; + var testFlows = [{"type":"tab","id":"tab1","label":"Sheet 1"}]; + var storage = { + saveFlows: function(conf) { + var defer = when.defer(); + defer.resolve(); + should.deepEqual(testFlows, conf); + return defer.promise; + }, + saveCredentials: function (creds) { + return when(true); + } + }; + RED.init(settings, storage); + flows.setFlows(testFlows); + events.once('nodes-started', function() { done(); }); + }); + }); + +}); diff --git a/dgbuilder/test/red/nodes/index_spec.js b/dgbuilder/test/red/nodes/index_spec.js new file mode 100644 index 00000000..dcb866e9 --- /dev/null +++ b/dgbuilder/test/red/nodes/index_spec.js @@ -0,0 +1,255 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var fs = require('fs-extra'); +var path = require('path'); +var when = require("when"); +var sinon = require('sinon'); + +var index = require("../../../red/nodes/index"); + +describe("red/nodes/index", function() { + + afterEach(function() { + index.clearRegistry(); + }); + + var testFlows = [{"type":"test","id":"tab1","label":"Sheet 1"}]; + var storage = { + getFlows: function() { + return when(testFlows); + }, + getCredentials: function() { + return when({"tab1":{"b":1,"c":2}}); + }, + saveFlows: function(conf) { + should.deepEqual(testFlows, conf); + return when(); + }, + saveCredentials: function(creds) { + return when(true); + } + }; + + var settings = { + available: function() { return false } + }; + + function TestNode(n) { + index.createNode(this, n); + var node = this; + this.on("log", function() { + // do nothing + }); + } + + it('nodes are initialised with credentials',function(done) { + + index.init(settings, storage); + index.registerType('test', TestNode); + index.loadFlows().then(function() { + var testnode = new TestNode({id:'tab1',type:'test',name:'barney'}); + testnode.credentials.should.have.property('b',1); + testnode.credentials.should.have.property('c',2); + done(); + }).otherwise(function(err) { + done(err); + }); + + }); + + it('flows should be initialised',function(done) { + index.init(settings, storage); + index.loadFlows().then(function() { + should.deepEqual(testFlows, index.getFlows()); + done(); + }).otherwise(function(err) { + done(err); + }); + + }); + + describe("registerType should register credentials definition", function() { + var http = require('http'); + var express = require('express'); + var app = express(); + var server = require("../../../red/server"); + var credentials = require("../../../red/nodes/credentials"); + var localfilesystem = require("../../../red/storage/localfilesystem"); + var RED = require("../../../red/red.js"); + + var userDir = path.join(__dirname,".testUserHome"); + before(function(done) { + fs.remove(userDir,function(err) { + fs.mkdir(userDir,function() { + sinon.stub(index, 'load', function() { + return when.promise(function(resolve,reject){ + resolve([]); + }); + }); + sinon.stub(localfilesystem, 'getCredentials', function() { + return when.promise(function(resolve,reject) { + resolve({"tab1":{"b":1,"c":2}}); + }); + }) ; + RED.init(http.createServer(function(req,res){app(req,res)}), + {userDir: userDir}); + server.start().then(function () { + done(); + }); + }); + }); + }); + + after(function(done) { + fs.remove(userDir,done); + server.stop(); + index.load.restore(); + localfilesystem.getCredentials.restore(); + }); + + it(': definition defined',function(done) { + index.registerType('test', TestNode, { + credentials: { + foo: {type:"test"} + } + }); + var testnode = new TestNode({id:'tab1',type:'test',name:'barney'}); + credentials.getDefinition("test").should.have.property('foo'); + done(); + }); + + }); + + describe('allows nodes to be added/remove/enabled/disabled from the registry', function() { + var registry = require("../../../red/nodes/registry"); + var randomNodeInfo = {id:"5678",types:["random"]}; + + before(function() { + sinon.stub(registry,"getNodeInfo",function(id) { + if (id == "test") { + return {id:"1234",types:["test"]}; + } else if (id == "doesnotexist") { + return null; + } else { + return randomNodeInfo; + } + }); + sinon.stub(registry,"removeNode",function(id) { + return randomNodeInfo; + }); + sinon.stub(registry,"disableNode",function(id) { + return randomNodeInfo; + }); + }); + after(function() { + registry.getNodeInfo.restore(); + registry.removeNode.restore(); + registry.disableNode.restore(); + }); + + it(': allows an unused node type to be removed',function(done) { + index.init(settings, storage); + index.registerType('test', TestNode); + index.loadFlows().then(function() { + var info = index.removeNode("5678"); + registry.removeNode.calledOnce.should.be.true; + registry.removeNode.calledWith("5678").should.be.true; + info.should.eql(randomNodeInfo); + done(); + }).otherwise(function(err) { + done(err); + }); + }); + + it(': allows an unused node type to be disabled',function(done) { + index.init(settings, storage); + index.registerType('test', TestNode); + index.loadFlows().then(function() { + var info = index.disableNode("5678"); + registry.disableNode.calledOnce.should.be.true; + registry.disableNode.calledWith("5678").should.be.true; + info.should.eql(randomNodeInfo); + done(); + }).otherwise(function(err) { + done(err); + }); + }); + + it(': prevents removing a node type that is in use',function(done) { + index.init(settings, storage); + index.registerType('test', TestNode); + index.loadFlows().then(function() { + /*jshint immed: false */ + (function() { + index.removeNode("test"); + }).should.throw(); + + done(); + }).otherwise(function(err) { + done(err); + }); + }); + + it(': prevents disabling a node type that is in use',function(done) { + index.init(settings, storage); + index.registerType('test', TestNode); + index.loadFlows().then(function() { + /*jshint immed: false */ + (function() { + index.disabledNode("test"); + }).should.throw(); + + done(); + }).otherwise(function(err) { + done(err); + }); + }); + + it(': prevents removing a node type that is unknown',function(done) { + index.init(settings, storage); + index.registerType('test', TestNode); + index.loadFlows().then(function() { + /*jshint immed: false */ + (function() { + index.removeNode("doesnotexist"); + }).should.throw(); + + done(); + }).otherwise(function(err) { + done(err); + }); + }); + it(': prevents disabling a node type that is unknown',function(done) { + index.init(settings, storage); + index.registerType('test', TestNode); + index.loadFlows().then(function() { + /*jshint immed: false */ + (function() { + index.disableNode("doesnotexist"); + }).should.throw(); + + done(); + }).otherwise(function(err) { + done(err); + }); + }); + + }); + + +}); diff --git a/dgbuilder/test/red/nodes/registry_spec.js b/dgbuilder/test/red/nodes/registry_spec.js new file mode 100644 index 00000000..81c1a2ce --- /dev/null +++ b/dgbuilder/test/red/nodes/registry_spec.js @@ -0,0 +1,808 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var sinon = require("sinon"); +var path = require("path"); +var when = require("when"); + +var RedNodes = require("../../../red/nodes"); +var RedNode = require("../../../red/nodes/Node"); +var typeRegistry = require("../../../red/nodes/registry"); +var events = require("../../../red/events"); + +afterEach(function() { + typeRegistry.clear(); +}); + +describe('NodeRegistry', function() { + + var resourcesDir = __dirname+ path.sep + "resources" + path.sep; + + function stubSettings(s,available) { + s.available = function() {return available;} + s.set = function(s,v) { return when.resolve()}, + s.get = function(s) { return null;} + return s + } + var settings = stubSettings({},false); + var settingsWithStorage = stubSettings({},true); + + it('automatically registers new nodes',function() { + var testNode = RedNodes.getNode('123'); + should.not.exist(n); + var n = new RedNode({id:'123',type:'abc'}); + + var newNode = RedNodes.getNode('123'); + + should.strictEqual(n,newNode); + }); + + it('handles nodes that export a function', function(done) { + typeRegistry.init(settings); + typeRegistry.load(resourcesDir + "TestNode1",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + list[0].should.have.property("id"); + list[0].should.have.property("name","TestNode1.js"); + list[0].should.have.property("types",["test-node-1"]); + list[0].should.have.property("enabled",true); + list[0].should.not.have.property("err"); + + var nodeConstructor = typeRegistry.get("test-node-1"); + nodeConstructor.should.be.type("function"); + + done(); + }).catch(function(e) { + done(e); + }); + + }); + + + it('handles nodes that export a function returning a resolving promise', function(done) { + typeRegistry.init(settings); + typeRegistry.load(resourcesDir + "TestNode2",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + list[0].should.have.property("id"); + list[0].should.have.property("name","TestNode2.js"); + list[0].should.have.property("types",["test-node-2"]); + list[0].should.have.property("enabled",true); + list[0].should.not.have.property("err"); + var nodeConstructor = typeRegistry.get("test-node-2"); + nodeConstructor.should.be.type("function"); + + done(); + }).catch(function(e) { + done(e); + }); + + }); + + it('handles nodes that export a function returning a rejecting promise', function(done) { + typeRegistry.init(settings); + typeRegistry.load(resourcesDir + "TestNode3",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + list[0].should.have.property("id"); + list[0].should.have.property("name","TestNode3.js"); + list[0].should.have.property("types",["test-node-3"]); + list[0].should.have.property("enabled",true); + list[0].should.have.property("err","fail"); + + var nodeConstructor = typeRegistry.get("test-node-3"); + (nodeConstructor === null).should.be.true; + + done(); + }).catch(function(e) { + done(e); + }); + + }); + + it('handles files containing multiple nodes', function(done) { + typeRegistry.init(settings); + typeRegistry.load(resourcesDir + "MultipleNodes1",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + list[0].should.have.property("id"); + list[0].should.have.property("name","MultipleNodes1.js"); + list[0].should.have.property("types",["test-node-multiple-1a","test-node-multiple-1b"]); + list[0].should.have.property("enabled",true); + list[0].should.not.have.property("err"); + + var nodeConstructor = typeRegistry.get("test-node-multiple-1a"); + nodeConstructor.should.be.type("function"); + + nodeConstructor = typeRegistry.get("test-node-multiple-1b"); + nodeConstructor.should.be.type("function"); + + done(); + }).catch(function(e) { + done(e); + }); + }); + + it('handles nested directories', function(done) { + typeRegistry.init(settings); + typeRegistry.load(resourcesDir + "NestedDirectoryNode",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + list[0].should.have.property("id"); + list[0].should.have.property("name","NestedNode.js"); + list[0].should.have.property("types",["nested-node-1"]); + list[0].should.have.property("enabled",true); + list[0].should.not.have.property("err"); + done(); + }).catch(function(e) { + done(e); + }); + }); + + it('emits type-registered and node-icon-dir events', function(done) { + var eventEmitSpy = sinon.spy(events,"emit"); + typeRegistry.init(settings); + typeRegistry.load(resourcesDir + "NestedDirectoryNode",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + list[0].should.have.property("name","NestedNode.js"); + list[0].should.have.property("types",["nested-node-1"]); + list[0].should.have.property("enabled",true); + list[0].should.not.have.property("err"); + + eventEmitSpy.callCount.should.equal(2); + + eventEmitSpy.firstCall.args[0].should.be.equal("node-icon-dir"); + eventEmitSpy.firstCall.args[1].should.be.equal( + resourcesDir + "NestedDirectoryNode" + path.sep + "NestedNode" + path.sep + "icons"); + + eventEmitSpy.secondCall.args[0].should.be.equal("type-registered"); + eventEmitSpy.secondCall.args[1].should.be.equal("nested-node-1"); + + done(); + }).catch(function(e) { + done(e); + }).finally(function() { + eventEmitSpy.restore(); + }); + }); + + it('rejects a duplicate node type registration', function(done) { + + typeRegistry.init(stubSettings({ + nodesDir:[resourcesDir + "TestNode1",resourcesDir + "DuplicateTestNode"] + },false)); + typeRegistry.load("wontexist",true).then(function() { + var list = typeRegistry.getNodeList(); + + list.should.be.an.Array.and.have.lengthOf(2); + list[0].should.have.property("id"); + list[0].should.have.property("name","TestNode1.js"); + list[0].should.have.property("types",["test-node-1"]); + list[0].should.have.property("enabled",true); + list[0].should.not.have.property("err"); + + list[1].should.have.property("id"); + list[1].id.should.not.equal(list[0].id); + + list[1].should.have.property("name","TestNode1.js"); + list[1].should.have.property("types",["test-node-1"]); + list[1].should.have.property("enabled",true); + list[1].should.have.property("err"); + /already registered/.test(list[1].err).should.be.true; + + var nodeConstructor = typeRegistry.get("test-node-1"); + // Verify the duplicate node hasn't replaced the original one + nodeConstructor.name.should.be.equal("TestNode"); + + done(); + }).catch(function(e) { + done(e); + }); + }); + + it('handles nodesDir as a string', function(done) { + + typeRegistry.init(stubSettings({ + nodesDir :resourcesDir + "TestNode1" + },false)); + typeRegistry.load("wontexist",true).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + list[0].should.have.property("types",["test-node-1"]); + done(); + }).catch(function(e) { + done("Loading of non-existing nodesDir should succeed"); + }); + + }); + + it('handles invalid nodesDir',function(done) { + + typeRegistry.init(stubSettings({ + nodesDir : "wontexist" + },false)); + typeRegistry.load("wontexist",true).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.be.empty; + done(); + }).catch(function(e) { + done("Loading of non-existing nodesDir should succeed"); + }); + }); + + it('returns nothing for an unregistered type config', function() { + typeRegistry.init(settings); + typeRegistry.load("wontexist",true).then(function(){ + var config = typeRegistry.getNodeConfig("imaginary-shark"); + (config === null).should.be.true; + }).catch(function(e) { + done(e); + }); + }); + + it('excludes node files listed in nodesExcludes',function(done) { + typeRegistry.init(stubSettings({ + nodesExcludes: [ "TestNode1.js" ], + nodesDir:[resourcesDir + "TestNode1",resourcesDir + "TestNode2"] + },false)); + typeRegistry.load("wontexist",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + list[0].should.have.property("types",["test-node-2"]); + done(); + }).catch(function(e) { + done(e); + }); + }); + + it('returns the node configurations', function(done) { + typeRegistry.init(stubSettings({ + nodesDir:[resourcesDir + "TestNode1",resourcesDir + "TestNode2"] + },false)); + typeRegistry.load("wontexist",true).then(function() { + var list = typeRegistry.getNodeList(); + + var nodeConfigs = typeRegistry.getNodeConfigs(); + + // TODO: this is brittle... + nodeConfigs.should.equal("<script type=\"text/x-red\" data-template-name=\"test-node-1\"></script>\n<script type=\"text/x-red\" data-help-name=\"test-node-1\"></script>\n<script type=\"text/javascript\">RED.nodes.registerType('test-node-1',{});</script>\n<style></style>\n<p>this should be filtered out</p>\n<script type=\"text/x-red\" data-template-name=\"test-node-2\"></script>\n<script type=\"text/x-red\" data-help-name=\"test-node-2\"></script>\n<script type=\"text/javascript\">RED.nodes.registerType('test-node-2',{});</script>\n<style></style>\n"); + + var nodeId = list[0].id; + var nodeConfig = typeRegistry.getNodeConfig(nodeId); + nodeConfig.should.equal("<script type=\"text/x-red\" data-template-name=\"test-node-1\"></script>\n<script type=\"text/x-red\" data-help-name=\"test-node-1\"></script>\n<script type=\"text/javascript\">RED.nodes.registerType('test-node-1',{});</script>\n<style></style>\n<p>this should be filtered out</p>\n"); + done(); + }).catch(function(e) { + done(e); + }); + }); + + it('stores the node list', function(done) { + var settings = { + nodesDir:[resourcesDir + "TestNode1",resourcesDir + "TestNode2",resourcesDir + "TestNode3"], + available: function() { return true; }, + set: function(s,v) {return when.resolve();}, + get: function(s) { return null;} + } + var settingsSave = sinon.spy(settings,"set"); + typeRegistry.init(settings); + typeRegistry.load("wontexist",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.Array.and.have.length(3); + + settingsSave.callCount.should.equal(1); + settingsSave.firstCall.args[0].should.be.equal("nodes"); + var savedList = settingsSave.firstCall.args[1]; + + savedList[list[0].id].name == list[0].name; + savedList[list[1].id].name == list[1].name; + savedList[list[2].id].name == list[2].name; + + savedList[list[0].id].should.not.have.property("err"); + savedList[list[1].id].should.not.have.property("err"); + savedList[list[2].id].should.not.have.property("err"); + + done(); + }).catch(function(e) { + done(e); + }).finally(function() { + settingsSave.restore(); + }); + + }); + + it('allows nodes to be added by filename', function(done) { + var settings = { + available: function() { return true; }, + set: function(s,v) {return when.resolve();}, + get: function(s) { return null;} + } + typeRegistry.init(settings); + typeRegistry.load("wontexist",true).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.be.empty; + + typeRegistry.addNode(resourcesDir + "TestNode1/TestNode1.js").then(function(node) { + list = typeRegistry.getNodeList(); + list[0].should.have.property("id"); + list[0].should.have.property("name","TestNode1.js"); + list[0].should.have.property("types",["test-node-1"]); + list[0].should.have.property("enabled",true); + list[0].should.not.have.property("err"); + + node.should.be.an.Array.and.have.lengthOf(1); + node.should.eql(list); + + done(); + }).catch(function(e) { + done(e); + }); + + }).catch(function(e) { + done(e); + }); + }); + + it('fails to add non-existent filename', function(done) { + typeRegistry.init(settingsWithStorage); + typeRegistry.load("wontexist",true).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.be.empty; + typeRegistry.addNode(resourcesDir + "DoesNotExist/DoesNotExist.js").then(function(nodes) { + nodes.should.be.an.Array.and.have.lengthOf(1); + nodes[0].should.have.property("id"); + nodes[0].should.have.property("types",[]); + nodes[0].should.have.property("err"); + done(); + }).otherwise(function(e) { + done(e); + }); + + }).catch(function(e) { + done(e); + }); + }); + + it('returns node info by type or id', function(done) { + typeRegistry.init(settings); + typeRegistry.load(resourcesDir + "TestNode1",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + + var id = list[0].id; + var type = list[0].types[0]; + + list[0].should.have.property("id"); + list[0].should.have.property("name","TestNode1.js"); + list[0].should.have.property("types",["test-node-1"]); + list[0].should.have.property("enabled",true); + list[0].should.not.have.property("err"); + + var info = typeRegistry.getNodeInfo(id); + list[0].should.eql(info); + + var info2 = typeRegistry.getNodeInfo(type); + list[0].should.eql(info2); + + done(); + }).catch(function(e) { + done(e); + }); + + }); + + + it('rejects adding duplicate nodes', function(done) { + typeRegistry.init(settingsWithStorage); + typeRegistry.load(resourcesDir + "TestNode1",true).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + + typeRegistry.addNode({file:resourcesDir + "TestNode1" + path.sep + "TestNode1.js"}).then(function(node) { + done(new Error("duplicate node loaded")); + }).otherwise(function(e) { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + done(); + }); + + }).catch(function(e) { + done(e); + }); + }); + + it('removes nodes from the registry', function(done) { + typeRegistry.init(settingsWithStorage); + typeRegistry.load(resourcesDir + "TestNode1",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + list[0].should.have.property("id"); + list[0].should.have.property("name","TestNode1.js"); + list[0].should.have.property("types",["test-node-1"]); + list[0].should.have.property("enabled",true); + list[0].should.have.property("loaded",true); + + typeRegistry.getNodeConfigs().length.should.be.greaterThan(0); + + var info = typeRegistry.removeNode(list[0].id); + + info.should.have.property("id",list[0].id); + info.should.have.property("enabled",false); + info.should.have.property("loaded",false); + + typeRegistry.getNodeList().should.be.an.Array.and.be.empty; + typeRegistry.getNodeConfigs().length.should.equal(0); + + var nodeConstructor = typeRegistry.get("test-node-1"); + (typeof nodeConstructor).should.be.equal("undefined"); + + + done(); + }).catch(function(e) { + done(e); + }); + }); + + it('rejects removing unknown nodes from the registry', function(done) { + typeRegistry.init(settings); + typeRegistry.load("wontexist",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.be.empty; + + + /*jshint immed: false */ + (function() { + typeRegistry.removeNode("1234"); + }).should.throw(); + + done(); + }).catch(function(e) { + done(e); + }); + }); + + it('scans the node_modules path for node files', function(done) { + var fs = require("fs"); + var path = require("path"); + + var eventEmitSpy = sinon.spy(events,"emit"); + var pathJoin = (function() { + var _join = path.join; + return sinon.stub(path,"join",function() { + if (arguments.length == 3 && arguments[2] == "package.json") { + return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1],arguments[2]); + } + if (arguments.length == 2 && arguments[1] == "TestNodeModule") { + return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1]); + } + return _join.apply(this,arguments); + }); + })(); + + var readdirSync = (function() { + var originalReaddirSync = fs.readdirSync; + var callCount = 0; + return sinon.stub(fs,"readdirSync",function(dir) { + var result = []; + if (callCount == 1) { + result = originalReaddirSync(resourcesDir + "TestNodeModule" + path.sep + "node_modules"); + } + callCount++; + return result; + }); + })(); + + typeRegistry.init(settings); + typeRegistry.load("wontexist",false).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(2); + list[0].should.have.property("id"); + list[0].should.have.property("name","TestNodeModule:TestNodeMod1"); + list[0].should.have.property("types",["test-node-mod-1"]); + list[0].should.have.property("enabled",true); + list[0].should.not.have.property("err"); + + list[1].should.have.property("id"); + list[1].should.have.property("name","TestNodeModule:TestNodeMod2"); + list[1].should.have.property("types",["test-node-mod-2"]); + list[1].should.have.property("enabled",true); + list[1].should.have.property("err"); + + + eventEmitSpy.callCount.should.equal(2); + + eventEmitSpy.firstCall.args[0].should.be.equal("node-icon-dir"); + eventEmitSpy.firstCall.args[1].should.be.equal( + resourcesDir + "TestNodeModule" + path.sep+ "node_modules" + path.sep + "TestNodeModule" + path.sep + "icons"); + + eventEmitSpy.secondCall.args[0].should.be.equal("type-registered"); + eventEmitSpy.secondCall.args[1].should.be.equal("test-node-mod-1"); + + done(); + }).catch(function(e) { + done(e); + }).finally(function() { + readdirSync.restore(); + pathJoin.restore(); + eventEmitSpy.restore(); + }); + }); + + it('allows nodes to be added by module name', function(done) { + var fs = require("fs"); + var path = require("path"); + + var pathJoin = (function() { + var _join = path.join; + return sinon.stub(path,"join",function() { + if (arguments.length == 3 && arguments[2] == "package.json") { + return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1],arguments[2]); + } + if (arguments.length == 2 && arguments[1] == "TestNodeModule") { + return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1]); + } + return _join.apply(this,arguments); + }); + })(); + + var readdirSync = (function() { + var originalReaddirSync = fs.readdirSync; + var callCount = 0; + return sinon.stub(fs,"readdirSync",function(dir) { + var result = []; + if (callCount == 1) { + result = originalReaddirSync(resourcesDir + "TestNodeModule" + path.sep + "node_modules"); + } + callCount++; + return result; + }); + })(); + typeRegistry.init(settingsWithStorage); + typeRegistry.load("wontexist",true).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.be.empty; + + typeRegistry.addModule("TestNodeModule").then(function(node) { + list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(2); + list[0].should.have.property("id"); + list[0].should.have.property("name","TestNodeModule:TestNodeMod1"); + list[0].should.have.property("types",["test-node-mod-1"]); + list[0].should.have.property("enabled",true); + list[0].should.not.have.property("err"); + + list[1].should.have.property("id"); + list[1].should.have.property("name","TestNodeModule:TestNodeMod2"); + list[1].should.have.property("types",["test-node-mod-2"]); + list[1].should.have.property("enabled",true); + list[1].should.have.property("err"); + + node.should.eql(list); + + done(); + }).catch(function(e) { + done(e); + }); + + }).catch(function(e) { + done(e); + }).finally(function() { + readdirSync.restore(); + pathJoin.restore(); + }); + }); + + + it('rejects adding duplicate node modules', function(done) { + var fs = require("fs"); + var path = require("path"); + + var pathJoin = (function() { + var _join = path.join; + return sinon.stub(path,"join",function() { + if (arguments.length == 3 && arguments[2] == "package.json") { + return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1],arguments[2]); + } + if (arguments.length == 2 && arguments[1] == "TestNodeModule") { + return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1]); + } + return _join.apply(this,arguments); + }); + })(); + + var readdirSync = (function() { + var originalReaddirSync = fs.readdirSync; + var callCount = 0; + return sinon.stub(fs,"readdirSync",function(dir) { + var result = []; + if (callCount == 1) { + result = originalReaddirSync(resourcesDir + "TestNodeModule" + path.sep + "node_modules"); + } + callCount++; + return result; + }); + })(); + + typeRegistry.init(settingsWithStorage); + typeRegistry.load('wontexist',false).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(2); + typeRegistry.addModule("TestNodeModule").then(function(node) { + done(new Error("addModule resolved")); + }).otherwise(function(err) { + done(); + }); + }).catch(function(e) { + done(e); + }).finally(function() { + readdirSync.restore(); + pathJoin.restore(); + }); + }); + + + it('fails to add non-existent module name', function(done) { + typeRegistry.init(settingsWithStorage); + typeRegistry.load("wontexist",true).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.be.empty; + + typeRegistry.addModule("DoesNotExistModule").then(function(node) { + done(new Error("ENOENT not thrown")); + }).otherwise(function(e) { + e.code.should.eql("MODULE_NOT_FOUND"); + done(); + }); + + }).catch(function(e) { + done(e); + }); + }); + + it('removes nodes from the registry by module', function(done) { + var fs = require("fs"); + var path = require("path"); + + var pathJoin = (function() { + var _join = path.join; + return sinon.stub(path,"join",function() { + if (arguments.length == 3 && arguments[2] == "package.json") { + return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1],arguments[2]); + } + if (arguments.length == 2 && arguments[1] == "TestNodeModule") { + return _join(resourcesDir,"TestNodeModule" + path.sep + "node_modules" + path.sep,arguments[1]); + } + return _join.apply(this,arguments); + }); + })(); + + var readdirSync = (function() { + var originalReaddirSync = fs.readdirSync; + var callCount = 0; + return sinon.stub(fs,"readdirSync",function(dir) { + var result = []; + if (callCount == 1) { + result = originalReaddirSync(resourcesDir + "TestNodeModule" + path.sep + "node_modules"); + } + callCount++; + return result; + }); + })(); + + typeRegistry.init(settingsWithStorage); + typeRegistry.load('wontexist',false).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(2); + var res = typeRegistry.removeModule("TestNodeModule"); + + res.should.be.an.Array.and.have.lengthOf(2); + res[0].should.have.a.property("id",list[0].id); + res[1].should.have.a.property("id",list[1].id); + + list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.be.empty; + + done(); + }).catch(function(e) { + done(e); + }).finally(function() { + readdirSync.restore(); + pathJoin.restore(); + }); + + }); + + it('fails to remove non-existent module name', function(done) { + typeRegistry.init(settings); + typeRegistry.load("wontexist",true).then(function(){ + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.be.empty; + + /*jshint immed: false */ + (function() { + typeRegistry.removeModule("DoesNotExistModule"); + }).should.throw(); + + done(); + + }).catch(function(e) { + done(e); + }); + }); + + + it('allows nodes to be enabled and disabled', function(done) { + typeRegistry.init(settingsWithStorage); + typeRegistry.load(resourcesDir+path.sep+"TestNode1",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.have.lengthOf(1); + list[0].should.have.property("id"); + list[0].should.have.property("name","TestNode1.js"); + list[0].should.have.property("enabled",true); + + var nodeConfig = typeRegistry.getNodeConfigs(); + nodeConfig.length.should.be.greaterThan(0); + + var info = typeRegistry.disableNode(list[0].id); + info.should.have.property("id",list[0].id); + info.should.have.property("enabled",false); + + var list2 = typeRegistry.getNodeList(); + list2.should.be.an.Array.and.have.lengthOf(1); + list2[0].should.have.property("enabled",false); + + typeRegistry.getNodeConfigs().length.should.equal(0); + + var info2 = typeRegistry.enableNode(list[0].id); + info2.should.have.property("id",list[0].id); + info2.should.have.property("enabled",true); + + var list3 = typeRegistry.getNodeList(); + list3.should.be.an.Array.and.have.lengthOf(1); + list3[0].should.have.property("enabled",true); + + var nodeConfig2 = typeRegistry.getNodeConfigs(); + nodeConfig2.should.eql(nodeConfig); + + done(); + }).catch(function(e) { + done(e); + }); + }); + + it('fails to enable/disable non-existent nodes', function(done) { + typeRegistry.init(settings); + typeRegistry.load("wontexist",true).then(function() { + var list = typeRegistry.getNodeList(); + list.should.be.an.Array.and.be.empty; + + /*jshint immed: false */ + (function() { + typeRegistry.disableNode("123"); + }).should.throw(); + + /*jshint immed: false */ + (function() { + typeRegistry.enableNode("123"); + }).should.throw(); + + done(); + }).catch(function(e) { + done(e); + }); + }); +}); diff --git a/dgbuilder/test/red/nodes/resources/DuplicateTestNode/TestNode1.html b/dgbuilder/test/red/nodes/resources/DuplicateTestNode/TestNode1.html new file mode 100644 index 00000000..b637ede2 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/DuplicateTestNode/TestNode1.html @@ -0,0 +1,3 @@ +<script type="text/x-red" data-template-name="test-node-1"></script> +<script type="text/x-red" data-help-name="test-node-1"></script> +<script type="text/javascript">RED.nodes.registerType('test-node-1',{});</script> diff --git a/dgbuilder/test/red/nodes/resources/DuplicateTestNode/TestNode1.js b/dgbuilder/test/red/nodes/resources/DuplicateTestNode/TestNode1.js new file mode 100644 index 00000000..e8121416 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/DuplicateTestNode/TestNode1.js @@ -0,0 +1,5 @@ +// A test node that exports a function +module.exports = function(RED) { + function DuplicateTestNode(n) {} + RED.nodes.registerType("test-node-1",DuplicateTestNode); +} diff --git a/dgbuilder/test/red/nodes/resources/MultipleNodes1/MultipleNodes1.html b/dgbuilder/test/red/nodes/resources/MultipleNodes1/MultipleNodes1.html new file mode 100644 index 00000000..5359644e --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/MultipleNodes1/MultipleNodes1.html @@ -0,0 +1,6 @@ +<script type="text/x-red" data-template-name="test-node-multiple-1a"></script> +<script type="text/x-red" data-help-name="test-node-multiple-1a"></script> +<script type="text/javascript">RED.nodes.registerType('test-node-multiple-1a',{});</script> +<script type="text/x-red" data-template-name="test-node-multiple-1b"></script> +<script type="text/x-red" data-help-name="test-node-multiple-1b"></script> +<script type="text/javascript">RED.nodes.registerType('test-node-multiple-1b',{});</script> diff --git a/dgbuilder/test/red/nodes/resources/MultipleNodes1/MultipleNodes1.js b/dgbuilder/test/red/nodes/resources/MultipleNodes1/MultipleNodes1.js new file mode 100644 index 00000000..55747c0b --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/MultipleNodes1/MultipleNodes1.js @@ -0,0 +1,7 @@ +// A test node that exports a function +module.exports = function(RED) { + function TestNode1(n) {} + RED.nodes.registerType("test-node-multiple-1a",TestNode1); + function TestNode2(n) {} + RED.nodes.registerType("test-node-multiple-1b",TestNode2); +} diff --git a/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/NestedNode.html b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/NestedNode.html new file mode 100644 index 00000000..abc823e8 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/NestedNode.html @@ -0,0 +1,4 @@ +<script type="text/x-red" data-template-name="nested-node-1"></script> +<script type="text/x-red" data-help-name="nested-node-1"></script> +<script type="text/javascript">RED.nodes.registerType('nested-node-1',{});</script> +<style></style> diff --git a/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/NestedNode.js b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/NestedNode.js new file mode 100644 index 00000000..cd3148a5 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/NestedNode.js @@ -0,0 +1,5 @@ +// A test node that exports a function +module.exports = function(RED) { + function TestNode(n) {} + RED.nodes.registerType("nested-node-1",TestNode); +} diff --git a/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/icons/file.txt b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/icons/file.txt new file mode 100644 index 00000000..59a29af1 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/icons/file.txt @@ -0,0 +1,3 @@ +This file exists just to ensure the 'icons' directory is in the repository. +TODO: a future test needs to ensure the right icon files are loaded - this + directory can be used for that diff --git a/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html new file mode 100644 index 00000000..ac9235d2 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html @@ -0,0 +1,4 @@ +<script type="text/x-red" data-template-name="should-not-load-1"></script> +<script type="text/x-red" data-help-name="should-not-load-1"></script> +<script type="text/javascript">RED.nodes.registerType('should-not-load-1',{});</script> +<style></style> diff --git a/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js new file mode 100644 index 00000000..8af249b1 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js @@ -0,0 +1,5 @@ +// A test node that exports a function +module.exports = function(RED) { + function TestNode(n) {} + RED.nodes.registerType("should-not-load-1",TestNode); +} diff --git a/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html new file mode 100644 index 00000000..4212fd58 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html @@ -0,0 +1,4 @@ +<script type="text/x-red" data-template-name="should-not-load-3"></script> +<script type="text/x-red" data-help-name="should-not-load-3"></script> +<script type="text/javascript">RED.nodes.registerType('should-not-load-3',{});</script> +<style></style> diff --git a/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js new file mode 100644 index 00000000..5856adad --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js @@ -0,0 +1,5 @@ +// A test node that exports a function +module.exports = function(RED) { + function TestNode(n) {} + RED.nodes.registerType("should-not-load-3",TestNode); +} diff --git a/dgbuilder/test/red/nodes/resources/TestNode1/TestNode1.html b/dgbuilder/test/red/nodes/resources/TestNode1/TestNode1.html new file mode 100644 index 00000000..97dbf171 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/TestNode1/TestNode1.html @@ -0,0 +1,5 @@ +<script type="text/x-red" data-template-name="test-node-1"></script> +<script type="text/x-red" data-help-name="test-node-1"></script> +<script type="text/javascript">RED.nodes.registerType('test-node-1',{});</script> +<style></style> +<p>this should be filtered out</p> diff --git a/dgbuilder/test/red/nodes/resources/TestNode1/TestNode1.js b/dgbuilder/test/red/nodes/resources/TestNode1/TestNode1.js new file mode 100644 index 00000000..bfa3b65b --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/TestNode1/TestNode1.js @@ -0,0 +1,5 @@ +// A test node that exports a function +module.exports = function(RED) { + function TestNode(n) {} + RED.nodes.registerType("test-node-1",TestNode); +} diff --git a/dgbuilder/test/red/nodes/resources/TestNode2/TestNode2.html b/dgbuilder/test/red/nodes/resources/TestNode2/TestNode2.html new file mode 100644 index 00000000..66b65909 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/TestNode2/TestNode2.html @@ -0,0 +1,4 @@ +<script type="text/x-red" data-template-name="test-node-2"></script> +<script type="text/x-red" data-help-name="test-node-2"></script> +<script type="text/javascript">RED.nodes.registerType('test-node-2',{});</script> +<style></style> diff --git a/dgbuilder/test/red/nodes/resources/TestNode2/TestNode2.js b/dgbuilder/test/red/nodes/resources/TestNode2/TestNode2.js new file mode 100644 index 00000000..faf61a8f --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/TestNode2/TestNode2.js @@ -0,0 +1,10 @@ +// A test node that exports a function which returns a resolving promise + +var when = require("when"); +module.exports = function(RED) { + return when.promise(function(resolve,reject) { + function TestNode(n) {} + RED.nodes.registerType("test-node-2",TestNode); + resolve(); + }); +} diff --git a/dgbuilder/test/red/nodes/resources/TestNode3/TestNode3.html b/dgbuilder/test/red/nodes/resources/TestNode3/TestNode3.html new file mode 100644 index 00000000..9a0f6f7e --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/TestNode3/TestNode3.html @@ -0,0 +1,3 @@ +<script type="text/x-red" data-template-name="test-node-3"></script> +<script type="text/x-red" data-help-name="test-node-3"></script> +<script type="text/javascript">RED.nodes.registerType('test-node-3',{});</script> diff --git a/dgbuilder/test/red/nodes/resources/TestNode3/TestNode3.js b/dgbuilder/test/red/nodes/resources/TestNode3/TestNode3.js new file mode 100644 index 00000000..756dc139 --- /dev/null +++ b/dgbuilder/test/red/nodes/resources/TestNode3/TestNode3.js @@ -0,0 +1,8 @@ +// A test node that exports a function which returns a rejecting promise + +var when = require("when"); +module.exports = function(RED) { + return when.promise(function(resolve,reject) { + reject("fail"); + }); +} diff --git a/dgbuilder/test/red/red_spec.js b/dgbuilder/test/red/red_spec.js new file mode 100644 index 00000000..f61fd55b --- /dev/null +++ b/dgbuilder/test/red/red_spec.js @@ -0,0 +1,22 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var should = require("should"); + +describe("red/red", function() { + it('can be required without errors', function() { + require("../../red/red"); + }); +}); diff --git a/dgbuilder/test/red/server_spec.js b/dgbuilder/test/red/server_spec.js new file mode 100644 index 00000000..b20249ca --- /dev/null +++ b/dgbuilder/test/red/server_spec.js @@ -0,0 +1,22 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var should = require("should"); + +describe("red/server", function() { + it('can be required without errors', function() { + require("../../red/server"); + }); +}); diff --git a/dgbuilder/test/red/settings_spec.js b/dgbuilder/test/red/settings_spec.js new file mode 100644 index 00000000..fb4cbade --- /dev/null +++ b/dgbuilder/test/red/settings_spec.js @@ -0,0 +1,114 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var should = require("should"); +var when = require("when"); + +var settings = require("../../red/settings"); + + +describe("red/settings", function() { + + afterEach(function() { + settings.reset(); + }); + + it('wraps the user settings as read-only properties', function() { + var userSettings = { + a: 123, + b: "test", + c: [1,2,3] + } + settings.init(userSettings); + + settings.available().should.be.false; + + settings.a.should.equal(123); + settings.b.should.equal("test"); + settings.c.should.be.an.Array.with.lengthOf(3); + + settings.get("a").should.equal(123); + settings.get("b").should.equal("test"); + settings.get("c").should.be.an.Array.with.lengthOf(3); + + /*jshint immed: false */ + (function() { + settings.a = 456; + }).should.throw(); + + settings.c.push(5); + settings.c.should.be.an.Array.with.lengthOf(4); + + /*jshint immed: false */ + (function() { + settings.set("a",456); + }).should.throw(); + + /*jshint immed: false */ + (function() { + settings.set("a",456); + }).should.throw(); + + /*jshint immed: false */ + (function() { + settings.get("unknown"); + }).should.throw(); + + /*jshint immed: false */ + (function() { + settings.set("unknown",456); + }).should.throw(); + + }); + + it('loads global settings from storage', function(done) { + var userSettings = { + a: 123, + b: "test", + c: [1,2,3] + } + var savedSettings = null; + var storage = { + getSettings: function() { + return when.resolve({globalA:789}); + }, + saveSettings: function(settings) { + savedSettings = settings; + return when.resolve(); + } + } + settings.init(userSettings); + + settings.available().should.be.false; + + /*jshint immed: false */ + (function() { + settings.get("unknown"); + }).should.throw(); + + settings.load(storage).then(function() { + settings.available().should.be.true; + settings.get("globalA").should.equal(789); + settings.set("globalA","abc").then(function() { + savedSettings.globalA.should.equal("abc"); + done(); + }); + }).otherwise(function(err) { + done(err); + }); + + + }); +}); diff --git a/dgbuilder/test/red/storage/index_spec.js b/dgbuilder/test/red/storage/index_spec.js new file mode 100644 index 00000000..4b60ba83 --- /dev/null +++ b/dgbuilder/test/red/storage/index_spec.js @@ -0,0 +1,128 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var should = require("should"); + +describe("red/storage/index", function() { + + it('rejects the promise when settings suggest loading a bad module', function(done) { + + var wrongModule = { + storageModule : "thisaintloading" + }; + + var storage = require("../../../red/storage/index"); + storage.init(wrongModule).then( function() { + var one = 1; + var zero = 0; + try { + zero.should.equal(one, "The initialization promise should never get resolved"); + } catch(err) { + done(err); + } + }).catch(function(e) { + done(); //successfully rejected promise + }); + }); + + it('non-string storage module', function(done) { + var initSetsMeToTrue = false; + + var moduleWithBooleanSettingInit = { + init : function() { + initSetsMeToTrue = true; + } + }; + + var setsBooleanModule = { + storageModule : moduleWithBooleanSettingInit + }; + + var storage = require("../../../red/storage/index"); + storage.init(setsBooleanModule); + initSetsMeToTrue.should.be.true; + done(); + }); + + it('respects storage interface', function(done) { + var calledFlagGetFlows = false; + var calledFlagGetCredentials = false; + var calledFlagGetAllFlows = false; + var calledInit = false; + + var interfaceCheckerModule = { + init : function (settings) { + settings.should.be.an.Object; + calledInit = true; + }, + getFlows : function() { + calledFlagGetFlows = true; + }, + saveFlows : function (flows) { + flows.should.be.true; + }, + getCredentials : function() { + calledFlagGetCredentials = true; + }, + saveCredentials : function(credentials) { + credentials.should.be.true; + }, + getAllFlows : function() { + calledFlagGetAllFlows = true; + }, + getFlow : function(fn) { + fn.should.equal("name"); + }, + saveFlow : function(fn, data) { + fn.should.equal("name"); + data.should.be.true; + }, + getLibraryEntry : function(type, path) { + type.should.be.true; + path.should.equal("name"); + }, + saveLibraryEntry : function(type, path, meta, body) { + type.should.be.true; + path.should.equal("name"); + meta.should.be.true; + body.should.be.true; + } + }; + + var moduleToLoad = { + storageModule : interfaceCheckerModule + }; + var storage = require("../../../red/storage/index"); + + storage.init(moduleToLoad); + storage.getFlows(); + storage.saveFlows(true); + storage.getCredentials(); + storage.saveCredentials(true); + storage.getAllFlows(); + storage.getFlow("name"); + storage.saveFlow("name", true); + storage.getLibraryEntry(true, "name"); + storage.saveLibraryEntry(true, "name", true, true); + + calledInit.should.be.true; + calledFlagGetFlows.should.be.true; + calledFlagGetCredentials.should.be.true; + calledFlagGetAllFlows.should.be.true; + + done(); + }); + +}); diff --git a/dgbuilder/test/red/storage/localfilesystem_spec.js b/dgbuilder/test/red/storage/localfilesystem_spec.js new file mode 100644 index 00000000..a1311709 --- /dev/null +++ b/dgbuilder/test/red/storage/localfilesystem_spec.js @@ -0,0 +1,367 @@ +/** + * Copyright 2013, 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +var should = require("should"); +var fs = require('fs-extra'); +var path = require('path'); + +var localfilesystem = require("../../../red/storage/localfilesystem"); + +describe('LocalFileSystem', function() { + var userDir = path.join(__dirname,".testUserHome"); + var testFlow = [{"type":"tab","id":"d8be2a6d.2741d8","label":"Sheet 1"}]; + beforeEach(function(done) { + fs.remove(userDir,function(err) { + fs.mkdir(userDir,done); + }); + }); + afterEach(function(done) { + fs.remove(userDir,done); + }); + + it('should initialise the user directory',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + fs.existsSync(path.join(userDir,"lib")).should.be.true; + fs.existsSync(path.join(userDir,"lib",'flows')).should.be.true; + done(); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should handle missing flow file',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + var flowFile = 'flows_'+require('os').hostname()+'.json'; + var flowFilePath = path.join(userDir,flowFile); + fs.existsSync(flowFilePath).should.be.false; + localfilesystem.getFlows().then(function(flows) { + flows.should.eql([]); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should save flows to the default file',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + var flowFile = 'flows_'+require('os').hostname()+'.json'; + var flowFilePath = path.join(userDir,flowFile); + var flowFileBackupPath = path.join(userDir,"flows.backup"); + fs.existsSync(flowFilePath).should.be.false; + fs.existsSync(flowFileBackupPath).should.be.false; + localfilesystem.saveFlows(testFlow).then(function() { + fs.existsSync(flowFilePath).should.be.true; + fs.existsSync(flowFileBackupPath).should.be.false; + localfilesystem.getFlows().then(function(flows) { + flows.should.eql(testFlow); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should save flows to the specified file',function(done) { + var defaultFlowFile = 'flows_'+require('os').hostname()+'.json'; + var defaultFlowFilePath = path.join(userDir,defaultFlowFile); + var flowFile = 'test.json'; + var flowFilePath = path.join(userDir,flowFile); + + localfilesystem.init({userDir:userDir, flowFile:flowFilePath}).then(function() { + fs.existsSync(defaultFlowFilePath).should.be.false; + fs.existsSync(flowFilePath).should.be.false; + + localfilesystem.saveFlows(testFlow).then(function() { + fs.existsSync(defaultFlowFilePath).should.be.false; + fs.existsSync(flowFilePath).should.be.true; + localfilesystem.getFlows().then(function(flows) { + flows.should.eql(testFlow); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should backup the flows file', function(done) { + var defaultFlowFile = 'flows_'+require('os').hostname()+'.json'; + var defaultFlowFilePath = path.join(userDir,defaultFlowFile); + var flowFile = 'test.json'; + var flowFilePath = path.join(userDir,flowFile); + var flowFileBackupPath = path.join(userDir,"flows.backup"); + + localfilesystem.init({userDir:userDir, flowFile:flowFilePath}).then(function() { + fs.existsSync(defaultFlowFilePath).should.be.false; + fs.existsSync(flowFilePath).should.be.false; + fs.existsSync(flowFileBackupPath).should.be.false; + + localfilesystem.saveFlows(testFlow).then(function() { + fs.existsSync(flowFileBackupPath).should.be.false; + fs.existsSync(defaultFlowFilePath).should.be.false; + fs.existsSync(flowFilePath).should.be.true; + var content = fs.readFileSync(flowFilePath,'utf8'); + var testFlow2 = [{"type":"tab","id":"bc5672ad.2741d8","label":"Sheet 2"}]; + + localfilesystem.saveFlows(testFlow2).then(function() { + fs.existsSync(flowFileBackupPath).should.be.true; + fs.existsSync(defaultFlowFilePath).should.be.false; + fs.existsSync(flowFilePath).should.be.true; + var backupContent = fs.readFileSync(flowFileBackupPath,'utf8'); + content.should.equal(backupContent); + var content2 = fs.readFileSync(flowFilePath,'utf8'); + content2.should.not.equal(backupContent); + done(); + + }).otherwise(function(err) { + done(err); + }); + + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + + + }); + + it('should handle missing credentials', function(done) { + var flowFile = 'test.json'; + var flowFilePath = path.join(userDir,flowFile); + var credFile = path.join(userDir,"test_cred.json"); + localfilesystem.init({userDir:userDir, flowFile:flowFilePath}).then(function() { + fs.existsSync(credFile).should.be.false; + + localfilesystem.getCredentials().then(function(creds) { + creds.should.eql({}); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should handle credentials', function(done) { + var flowFile = 'test.json'; + var flowFilePath = path.join(userDir,flowFile); + var credFile = path.join(userDir,"test_cred.json"); + + localfilesystem.init({userDir:userDir, flowFile:flowFilePath}).then(function() { + + fs.existsSync(credFile).should.be.false; + + var credentials = {"abc":{"type":"creds"}}; + + localfilesystem.saveCredentials(credentials).then(function() { + fs.existsSync(credFile).should.be.true; + localfilesystem.getCredentials().then(function(creds) { + creds.should.eql(credentials); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should return an empty list of library flows',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + localfilesystem.getAllFlows().then(function(flows) { + flows.should.eql({}); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should return a valid list of library flows',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + var flowLib = path.join(userDir,"lib","flows"); + fs.closeSync(fs.openSync(path.join(flowLib,"A.json"),"w")); + fs.closeSync(fs.openSync(path.join(flowLib,"B.json"),"w")); + fs.mkdirSync(path.join(flowLib,"C")); + fs.closeSync(fs.openSync(path.join(flowLib,"C","D.json"),"w")); + var testFlowsList = {"d":{"C":{"f":["D"]}},"f":["A","B"]}; + + localfilesystem.getAllFlows().then(function(flows) { + flows.should.eql(testFlowsList); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should fail a non-existent flow', function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + localfilesystem.getFlow("a/b/c.json").then(function(flow) { + should.fail(flow,"No flow","Flow found"); + }).otherwise(function(err) { + // err should be null, so this will pass + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should return a flow',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + var testflowString = JSON.stringify(testFlow); + localfilesystem.saveFlow("a/b/c/d.json",testflowString).then(function() { + localfilesystem.getFlow("a/b/c/d.json").then(function(flow) { + flow.should.eql(testflowString); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should return an empty list of library objects',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + localfilesystem.getLibraryEntry('object','').then(function(flows) { + flows.should.eql({}); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should return an error for a non-existent library object',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + localfilesystem.getLibraryEntry('object','A/B').then(function(flows) { + should.fail(null,null,"non-existent flow"); + }).otherwise(function(err) { + should.exist(err); + done(); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + function createObjectLibrary() { + var objLib = path.join(userDir,"lib","object"); + fs.mkdirSync(objLib); + fs.mkdirSync(path.join(objLib,"A")); + fs.mkdirSync(path.join(objLib,"B")); + fs.mkdirSync(path.join(objLib,"B","C")); + fs.writeFileSync(path.join(objLib,"file1.js"),"// abc: def\n// not a metaline \n\n Hi",'utf8'); + fs.writeFileSync(path.join(objLib,"B","file2.js"),"// ghi: jkl\n// not a metaline \n\n Hi",'utf8'); + } + + it('should return a directory listing of library objects',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + createObjectLibrary(); + + localfilesystem.getLibraryEntry('object','').then(function(flows) { + flows.should.eql([ 'A', 'B', { abc: 'def', fn: 'file1.js' } ]); + localfilesystem.getLibraryEntry('object','B').then(function(flows) { + flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' } ]); + localfilesystem.getLibraryEntry('object','B/C').then(function(flows) { + flows.should.eql([]); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should return a library object',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + createObjectLibrary(); + localfilesystem.getLibraryEntry('object','B/file2.js').then(function(body) { + body.should.eql("// not a metaline \n\n Hi"); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + + it('should return a newly saved library object',function(done) { + localfilesystem.init({userDir:userDir}).then(function() { + createObjectLibrary(); + localfilesystem.getLibraryEntry('object','B').then(function(flows) { + flows.should.eql([ 'C', { ghi: 'jkl', fn: 'file2.js' } ]); + localfilesystem.saveLibraryEntry('object','B/D/file3.js',{mno:'pqr'},"// another non meta line\n\n Hi There").then(function() { + localfilesystem.getLibraryEntry('object','B/D').then(function(flows) { + flows.should.eql([ { mno: 'pqr', fn: 'file3.js' } ]); + localfilesystem.getLibraryEntry('object','B/D/file3.js').then(function(body) { + body.should.eql("// another non meta line\n\n Hi There"); + done(); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }).otherwise(function(err) { + done(err); + }); + }); + +}); diff --git a/dgbuilder/test/red/ui_spec.js b/dgbuilder/test/red/ui_spec.js new file mode 100644 index 00000000..b9de7bff --- /dev/null +++ b/dgbuilder/test/red/ui_spec.js @@ -0,0 +1,177 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var request = require("supertest"); +var express = require("express"); +var redUI = require("../../red/ui"); + + +describe("red/ui icon handler", function() { + it('returns the default icon when getting an unknown icon', function(done) { + var app = express(); + redUI({},app); + request(app) + .get("/icons/youwonthaveme.png") + .expect('Content-Type', /image\/png/) + .expect(200) + .end(function(err, res){ + if (err){ + return done(err); + } + done(); + }); + }); + + it('returns an icon from disk', function(done) { + var app = express(); + redUI({},app); + request(app) + .get("/icons/arduino.png") + .expect('Content-Type', /image\/png/) + .expect(200) + .end(function(err, res){ + if (err){ + return done(err); + } + done(); + }); + }); +}); + +describe("icon cache handler", function() { + var fs = require('fs-extra'); + var path = require('path'); + var events = require("../../red/events"); + + var tempDir = path.join(__dirname,".tmp/"); + var cachedFakePNG = tempDir + "cacheMe.png"; + + + beforeEach(function(done) { + fs.remove(tempDir,function(err) { + fs.mkdirSync(tempDir); + fs.writeFileSync(cachedFakePNG, "Hello PNG\n"); + done(); + }); + }); + afterEach(function(done) { + fs.exists(cachedFakePNG, function(exists) { + if(exists) { + fs.unlinkSync(cachedFakePNG); + } + fs.remove(tempDir,done); + }) + }); + + /* + * This test case test that: + * 1) any directory can be added to the path lookup (such as /tmp) by + * calling the right event + * 2) that a file we know exists gets cached so that the lookup/verification + * of actual existence doesn't occur again when a subsequent request comes in + * + * The second point verifies that the cache works. If the cache wouldn't work + * the default PNG would be served + */ + it('returns an icon using icon cache', function(done) { + var app = express(); + redUI({},app); + events.emit("node-icon-dir", tempDir); + request(app) + .get("/icons/cacheMe.png") + .expect('Content-Type', /image\/png/) + .expect(200) + .end(function(err, res){ + if (err){ + return done(err); + } + fs.unlink(cachedFakePNG, function(err) { + if(err) { + return done(err); + } + request(app) + .get("/icons/cacheMe.png") + .expect('Content-Type', /text\/html/) + .expect(404) + .end(function(err, res){ + if (err){ + return done(err); + } + done(); + }); + }); + }); + }); +}); + +describe("red/ui settings handler", function() { + it('returns the provided settings', function(done) { + var settings = { + httpNodeRoot: "testHttpNodeRoot", + version: "testVersion", + }; + var app = express(); + redUI(settings,app); + request(app) + .get("/settings") + .expect('Content-Type', /application\/json/) + .expect(200, "{\n \"httpNodeRoot\": \"testHttpNodeRoot\",\n \"version\": \"testVersion\"\n}") + .end(function(err, res){ + if (err){ + return done(err); + } + done(); + }); + + }); +}); + +describe("red/ui root handler", function() { + it('server up the main page', function(done) { + var app = express(); + redUI({},app); + + request(app) + .get("/") + .expect('Content-Type', /text\/html/) + .expect(200) + .end(function(err, res){ + if (err){ + return done(err); + } + done(); + }); + + }); + + it('redirects to path ending with /', function(done) { + var rapp = express(); + redUI({},rapp); + + var app = express().use('/root', rapp); + + request(app) + .get("/root") + .expect('Content-Type', /text\/plain/) + .expect(302) + .end(function(err, res){ + if (err){ + return done(err); + } + done(); + }); + + }); +}); diff --git a/dgbuilder/test/red/util_spec.js b/dgbuilder/test/red/util_spec.js new file mode 100644 index 00000000..5200ef12 --- /dev/null +++ b/dgbuilder/test/red/util_spec.js @@ -0,0 +1,70 @@ +/** + * Copyright 2014 IBM Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +var should = require("should"); +var util = require("../../red/util"); + +describe("red/util", function() { + describe('ensureString', function() { + it('strings are preserved', function() { + util.ensureString('string').should.equal('string'); + }); + it('Buffer is converted', function() { + var s = util.ensureString(new Buffer('foo')); + s.should.equal('foo'); + (typeof s).should.equal('string'); + }); + it('Object is converted to JSON', function() { + var s = util.ensureString({foo: "bar"}); + (typeof s).should.equal('string'); + should.deepEqual(JSON.parse(s), {foo:"bar"}); + }); + it('stringifies other things', function() { + var s = util.ensureString(123); + (typeof s).should.equal('string'); + s.should.equal('123'); + }); + }); + + describe('ensureBuffer', function() { + it('Buffers are preserved', function() { + var b = new Buffer(''); + util.ensureBuffer(b).should.equal(b); + }); + it('string is converted', function() { + var b = util.ensureBuffer('foo'); + var expected = new Buffer('foo'); + for (var i = 0; i < expected.length; i++) { + b[i].should.equal(expected[i]); + } + Buffer.isBuffer(b).should.equal(true); + }); + it('Object is converted to JSON', function() { + var obj = {foo: "bar"} + var b = util.ensureBuffer(obj); + Buffer.isBuffer(b).should.equal(true); + should.deepEqual(JSON.parse(b), obj); + }); + it('stringifies other things', function() { + var b = util.ensureBuffer(123); + Buffer.isBuffer(b).should.equal(true); + var expected = new Buffer('123'); + for (var i = 0; i < expected.length; i++) { + b[i].should.equal(expected[i]); + } + }); + }); +}); + diff --git a/dgbuilder/test/resources/70-HTML-test-file.html b/dgbuilder/test/resources/70-HTML-test-file.html new file mode 100644 index 00000000..a0932e15 --- /dev/null +++ b/dgbuilder/test/resources/70-HTML-test-file.html @@ -0,0 +1,25 @@ +<!DOCTYPE html> +<html> +<body> + +<h1>This is a test page for node 70-HTML</h1> + +<p>There's nothing to read here.</p> + +<ol id="colours"> + <li>Blue</li> + <li>Red</li> +</ol> + +<ul id="fruits"> + <li>Apple</li> + <li>Pear</li> +</ul> + +<ul id="vegetables"> + <li>Potato</li> + <li>Parsnip</li> +</ul> + +</body> +</html>
\ No newline at end of file diff --git a/dgbuilder/tools/FormatXml.java b/dgbuilder/tools/FormatXml.java new file mode 100644 index 00000000..7c6915f7 --- /dev/null +++ b/dgbuilder/tools/FormatXml.java @@ -0,0 +1,49 @@ +import javax.xml.transform.*; +import javax.xml.transform.stream.*; +import java.io.*; +import java.util.*; +import java.nio.file.Paths; +import java.nio.file.Files; +import java.nio.charset.StandardCharsets; +import java.nio.charset.Charset; +public class FormatXml{ +public static String formatXml(String input, int indent) { + try { + Source xmlInput = new StreamSource(new StringReader(input)); + StringWriter stringWriter = new StringWriter(); + StreamResult xmlOutput = new StreamResult(stringWriter); + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + transformerFactory.setAttribute("indent-number", indent); + Transformer transformer = transformerFactory.newTransformer(); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.transform(xmlInput, xmlOutput); + return xmlOutput.getWriter().toString(); + } catch (Exception e) { + throw new RuntimeException(e); // simple exception handling, please review it + } +} + +public static String prettyFormat(String input) { + return formatXml(input, 2); +} + +public static String readFile(String path, Charset encoding) + throws IOException +{ + byte[] encoded = Files.readAllBytes(Paths.get(path)); + return new String(encoded, encoding); +} + +public static void main(String[] args){ +try{ + if (args != null && args.length != 1){ + System.out.println("Usage:java FormatXml xmlStr"); + System.exit(-1); + } + String xmlStr = readFile(args[0], StandardCharsets.UTF_8); + System.out.println(prettyFormat(xmlStr)); +}catch(Exception e){ + e.printStackTrace(); +} +} +} diff --git a/dgbuilder/tools/PrintYangToProp.java b/dgbuilder/tools/PrintYangToProp.java new file mode 100644 index 00000000..93aaac79 --- /dev/null +++ b/dgbuilder/tools/PrintYangToProp.java @@ -0,0 +1,1424 @@ + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.io.FileDescriptor; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.LinkedList; +import java.util.List; +import java.util.Properties; +import java.util.Arrays; +import java.util.ArrayList; +import java.io.*; +import javax.json.*; +import org.opendaylight.yangtools.yang.binding.Identifier; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddress; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.IpAddressBuilder; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv4Address; +import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Ipv6Address; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.common.base.CaseFormat; + +public class PrintYangToProp { + + private static final Logger LOG = LoggerFactory.getLogger(PrintYangToProp.class); + public static final String PROPERTIES_FILE="/opt/bvc/controller/configuration/flowred.properties"; + private static Properties properties; + + static { + + // Trick class loader into loading builders. Some of + // these will be needed later by Reflection classes, but need + // to explicitly "new" them here to get class loader to load them. +/* + ServiceInformationBuilder b2 = new ServiceInformationBuilder(); + ServiceDataBuilder b3 = new ServiceDataBuilder(); + SdncRequestHeaderBuilder b4 = new SdncRequestHeaderBuilder(); + RequestInformationBuilder b6 = new RequestInformationBuilder(); + + FlowredGroupInformationDataBuilder b29 = new FlowredGroupInformationDataBuilder(); + FlowredInformationDataBuilder b48 = new FlowredInformationDataBuilder(); + + OperStatusBuilder b41 = new OperStatusBuilder(); +*/ + + + } + + public static void loadProperties() { + /* + + File file = new File(PROPERTIES_FILE); + properties = new Properties(); + InputStream input = null; + if (file.isFile() && file.canRead()) { + try { + input = new FileInputStream(file); + properties.load(input); + LOG.info("Loaded properties from " + PROPERTIES_FILE ); + } catch (Exception e) { + LOG.error("Failed to load properties " + PROPERTIES_FILE +"\n",e); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + LOG.error("Failed to close properties file " + PROPERTIES_FILE +"\n",e); + } + } + } + } + */ + } + + public static Properties toProperties(Properties props, Object fromObj) { + Class fromClass = null; + + if (fromObj != null) + { + fromClass = fromObj.getClass(); + } + return (toProperties(props, "", fromObj, fromClass)); + } + + public static Properties toProperties(Properties props, String pfx, Object fromObj) + { + Class fromClass = null; + + if (fromObj != null) + { + fromClass = fromObj.getClass(); + } + + return(toProperties(props, pfx, fromObj, fromClass)); + } + + public static Properties toProperties(Properties props, String pfx, + Object fromObj, Class fromClass) { + + if (fromObj == null) { + return (props); + } + + + String simpleName = fromClass.getSimpleName(); + + //LOG.debug("Extracting properties from " + fromClass.getName() + // + " class"); + if (fromObj instanceof List) { + + // Class is a List. List should contain yang-generated classes. + //LOG.debug(fromClass.getName() + " is a List"); + + List fromList = (List) fromObj; + + for (int i = 0; i < fromList.size(); i++) { + toProperties(props, pfx + "[" + i + "]", fromList.get(i), fromClass); + } + props.setProperty(pfx + "_length", "" + fromList.size()); + + } else if (isYangGenerated(fromClass)) { + // Class is yang generated. + //LOG.debug(fromClass.getName() + " is a Yang-generated class"); + + String propNamePfx = null; + + // If called from a list (so prefix ends in ']'), don't + // add class name again + if (pfx.endsWith("]")) { + propNamePfx = pfx; + } else { + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx ; + } else { + propNamePfx = toLowerHyphen(fromClass.getSimpleName()); + } + + if (propNamePfx.endsWith("-builder")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - "-builder".length()); + } + + if (propNamePfx.endsWith("-impl")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - "-impl".length()); + } + } + + // Iterate through getter methods to figure out values we need to + // save from + + for (Method m : fromClass.getMethods()) { + // LOG.debug("Checking " + m.getName() + " method"); + if (isGetter(m)) { + // LOG.debug(m.getName() + " is a getter"); + Class returnType = m.getReturnType(); + String fieldName = toLowerHyphen(m.getName().substring(3)); + if(m != null && m.getName().matches("^is[A-Z].*")){ + fieldName = toLowerHyphen(m.getName().substring(2)); + } + + fieldName = fieldName.substring(0, 1).toLowerCase() + + fieldName.substring(1); + + // Is the return type a yang generated class? + if (isYangGenerated(returnType)) { + // Is it an enum? + if (returnType.isEnum()) { + // Return type is a typedef. Save its value. + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + Object retValue = m.invoke(fromObj); + + if (!isAccessible) { + m.setAccessible(isAccessible); + } + if (retValue != null) { + String propName = propNamePfx + "." + + fieldName; + String propVal = retValue.toString(); + String yangProp = "yang." + fieldName + "." + propVal; + if ( properties.containsKey(yangProp)) { + propVal = properties.getProperty(yangProp); + //LOG.debug("Adjusting property " + yangProp + " " + propVal); + } + //LOG.debug("Setting property " + propName + // + " to " + propVal); + props.setProperty(propName, propVal); + } + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert Yang-generated enum returned by " + + fromClass.getName() + "." + + m.getName() + + "() to Properties entry", e); + } + } else if (isIpv4Address(returnType)) { + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Ipv4Address retValue = (Ipv4Address) m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (retValue != null) { + String propVal = retValue.getValue().toString(); + //LOG.debug("Setting property " + propName + // + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert value returned by " + + fromClass.getName() + "." + + m.getName() + + "() to Properties entry", e); + } + } else if (isIpv6Address(returnType)) { + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Ipv6Address retValue = (Ipv6Address) m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (retValue != null) { + String propVal = retValue.getValue().toString(); + //LOG.debug("Setting property " + propName + // + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert value returned by " + + fromClass.getName() + "." + + m.getName() + + "() to Properties entry", e); + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object retValue = m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + if (retValue != null) { + toProperties(props, propNamePfx + "." + fieldName, retValue, returnType); + } + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert Yang-generated class returned by" + + fromClass.getName() + "." + + m.getName() + + "() to Properties entry", e); + } + } + } else if (returnType.equals(Class.class)) { + + //LOG.debug(m.getName() + // + " returns a Class object - not interested"); + + } else if (List.class.isAssignableFrom(returnType)) { + + // This getter method returns a list. + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object retList = m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + // Figure out what type of elements are stored in this array. + Type paramType = m.getGenericReturnType(); + Type elementType = ((ParameterizedType) paramType) + .getActualTypeArguments()[0]; + toProperties(props, propNamePfx + "." + fieldName, + retList, (Class)elementType); + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert List returned by " + + fromClass.getName() + "." + + m.getName() + + "() to Properties entry", e); + } + + } else { + + // Method returns something that is not a List and not + // yang-generated. + // Save its value + try { + String propName = propNamePfx + "." + fieldName; + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + Object propValObj = m.invoke(fromObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + + if (propValObj != null) { + String propVal = propValObj.toString(); + //LOG.debug("Setting property " + propName + // + " to " + propVal); + props.setProperty(propName, propVal); + + } + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert value returned by " + + fromClass.getName() + "." + + m.getName() + + "() to Properties entry", e); + } + } + + } + } + + } else { + // Class is not yang generated and not a list + // Do nothing. + + } + + return (props); + } + + public static Object toBuilder(Properties props, Object toObj) { + + return (toBuilder(props, "", toObj)); + } + + public static List toList(Properties props, String pfx, List toObj, + Class elemType) { + + int maxIdx = -1; + boolean foundValue = false; + + //LOG.debug("Saving properties to List<" + elemType.getName() + // + "> from " + pfx); + + // Figure out array size + for (Object pNameObj : props.keySet()) { + String key = (String) pNameObj; + + if (key.startsWith(pfx + "[")) { + String idxStr = key.substring(pfx.length() + 1); + int endloc = idxStr.indexOf("]"); + if (endloc != -1) { + idxStr = idxStr.substring(0, endloc); + } + + try { + int curIdx = Integer.parseInt(idxStr); + if (curIdx > maxIdx) { + maxIdx = curIdx; + } + } catch (Exception e) { + LOG.error("Illegal subscript in property " + key); + } + + } + } + + //LOG.debug(pfx + " has max index of " + maxIdx); + for (int i = 0; i <= maxIdx; i++) { + + String curBase = pfx + "[" + i + "]"; + + if (isYangGenerated(elemType)) { + String builderName = elemType.getName() + "Builder"; + try { + Class builderClass = Class.forName(builderName); + Object builderObj = builderClass.newInstance(); + Method buildMethod = builderClass.getMethod("build"); + builderObj = toBuilder(props, curBase, builderObj, true); + if (builderObj != null) { + //LOG.debug("Calling " + builderObj.getClass().getName() + // + "." + buildMethod.getName() + "()"); + Object builtObj = buildMethod.invoke(builderObj); + toObj.add(builtObj); + foundValue = true; + } + + } catch (ClassNotFoundException e) { + LOG.warn("Could not find builder class " + builderName, e); + } catch (Exception e) { + LOG.error("Caught exception trying to populate list from " + + pfx); + } + } + + } + + if (foundValue) { + return (toObj); + } else { + return (null); + } + + } + + public static Object toBuilder(Properties props, String pfx, Object toObj) { + return(toBuilder(props, pfx, toObj, false)); + } + + public static Object toBuilder(Properties props, String pfx, Object toObj, boolean preservePfx) { + Class toClass = toObj.getClass(); + boolean foundValue = false; + + //LOG.debug("Saving properties to " + toClass.getName() + " class from " + // + pfx); + + Ipv4Address addr; + + if (isYangGenerated(toClass)) { + // Class is yang generated. + //LOG.debug(toClass.getName() + " is a Yang-generated class"); + + String propNamePfx = null; + if (preservePfx) { + propNamePfx = pfx; + } else { + + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx + "." + + toLowerHyphen(toClass.getSimpleName()); + } else { + propNamePfx = toLowerHyphen(toClass.getSimpleName()); + } + + if (propNamePfx.endsWith("-builder")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - "-builder".length()); + } + + if (propNamePfx.endsWith("-impl")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - "-impl".length()); + } + } + + if (toObj instanceof Identifier) { + //LOG.debug(toClass.getName() + " is a Key - skipping"); + return (toObj); + } + + // Iterate through getter methods to figure out values we need to + // set + + for (Method m : toClass.getMethods()) { + // LOG.debug("Is " + m.getName() + " method a setter?"); + if (isSetter(m)) { + // LOG.debug(m.getName() + " is a setter"); + Class paramTypes[] = m.getParameterTypes(); + Class paramClass = paramTypes[0]; + + String fieldName = toLowerHyphen(m.getName().substring(3)); + fieldName = fieldName.substring(0, 1).toLowerCase() + + fieldName.substring(1); + + String propName = propNamePfx + "." + fieldName; + + String paramValue = props.getProperty(propName); + if (paramValue == null) { + //LOG.debug(propName + " is unset"); + } else { + //LOG.debug(propName + " = " + paramValue); + } + + // Is the return type a yang generated class? + if (isYangGenerated(paramClass)) { + // Is it an enum? + if (paramClass.isEnum()) { + + //LOG.debug(m.getName() + " expects an Enum"); + // Param type is a typedef. + if (paramValue != null) { + Object paramObj = null; + + try { + paramObj = Enum.valueOf(paramClass, + toUpperCamelCase(paramValue)); + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert field " + + propName + " to enum " + + paramClass.getName(), e); + } + + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + //LOG.debug("Calling " + // + toObj.getClass().getName() + "." + // + m.getName() + "(" + paramValue + // + ")"); + m.invoke(toObj, paramObj); + + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error( + "Caught exception trying to create Yang-generated enum expected by" + + toClass.getName() + + "." + + m.getName() + + "() from Properties entry", + e); + } + } + } else { + + String simpleName = paramClass.getSimpleName(); + + if ("Ipv4Address".equals(simpleName) + || "Ipv6Address".equals(simpleName)) { + + if (paramValue != null) { + try { + IpAddress ipAddr = IpAddressBuilder + .getDefaultInstance(paramValue); + + + if ("Ipv4Address".equals(simpleName)) + { + m.invoke(toObj, ipAddr.getIpv4Address()); + } + else + { + m.invoke(toObj, ipAddr.getIpv6Address()); + + } + foundValue = true; + } catch (Exception e) { + LOG.error( + "Caught exception calling " + + toClass.getName() + "." + + m.getName() + "(" + + paramValue + ")", e); + + } + } + + } else { + // setter expects a yang-generated class. Need + // to + // create a builder to set it. + + String builderName = paramClass.getName() + + "Builder"; + Class builderClass = null; + Object builderObj = null; + Object paramObj = null; + + //LOG.debug(m.getName() + // + " expects a yang-generated class - looking for builder " + // + builderName); + try { + builderClass = Class.forName(builderName); + builderObj = builderClass.newInstance(); + paramObj = toBuilder(props, propNamePfx, + builderObj); + } catch (ClassNotFoundException e) { + Object constObj = null; + try { + // See if I can find a constructor I can + // use + Constructor[] constructors = paramClass + .getConstructors(); + // Is there a String constructor? + for (Constructor c : constructors) { + Class[] cParms = c + .getParameterTypes(); + if ((cParms != null) + && (cParms.length == 1)) { + if (String.class + .isAssignableFrom(cParms[0])) { + constObj = c + .newInstance(paramValue); + } + } + } + + if (constObj == null) { + // Is there a Long constructor? + for (Constructor c : constructors) { + Class[] cParms = c + .getParameterTypes(); + if ((cParms != null) + && (cParms.length == 1)) { + if (Long.class + .isAssignableFrom(cParms[0])) { + constObj = c + .newInstance(Long + .parseLong(paramValue)); + } + } + } + + } + + if (constObj != null) { + try { + m.invoke(toObj, constObj); + foundValue = true; + } catch (Exception e2) { + LOG.error( + "Caught exception trying to call " + + m.getName(), + e2); + } + } + } catch (Exception e1) { + LOG.warn( + "Could not find a suitable constructor for " + + paramClass.getName(), + e1); + } + + if (paramObj == null) { + LOG.warn("Could not find builder class " + + builderName + + " and could not find a String or Long constructor - trying just to set passing paramValue"); + + } + + } catch (Exception e) { + LOG.error( + "Caught exception trying to create builder " + + builderName, e); + } + + if (paramObj != null) { + + try { + + Method buildMethod = builderClass + .getMethod("build"); + //LOG.debug("Calling " + // + paramObj.getClass().getName() + // + "." + buildMethod.getName() + // + "()"); + Object builtObj = buildMethod + .invoke(paramObj); + + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + + //LOG.debug("Calling " + // + toObj.getClass().getName() + // + "." + m.getName() + "()"); + m.invoke(toObj, builtObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error( + "Caught exception trying to set Yang-generated class expected by" + + toClass.getName() + + "." + + m.getName() + + "() from Properties entry", + e); + } + } else { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + //LOG.debug("Calling " + // + toObj.getClass().getName() + // + "." + m.getName() + "(" + // + paramValue + ")"); + m.invoke(toObj, paramValue); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert value returned by" + + toClass.getName() + + "." + + m.getName() + + "() to Properties entry", + e); + } + } + } + } + } else { + + // Setter's argument is not a yang-generated class. See + // if it is a List. + + if (List.class.isAssignableFrom(paramClass)) { + + //LOG.debug("Parameter class " + paramClass.getName() + // + " is a List"); + + // Figure out what type of args are in List and pass + // that to toList(). + + Type paramType = m.getGenericParameterTypes()[0]; + Type elementType = ((ParameterizedType) paramType) + .getActualTypeArguments()[0]; + Object paramObj = new LinkedList(); + try { + paramObj = toList(props, propName, + (List) paramObj, (Class) elementType); + } catch (Exception e) { + LOG.error("Caught exception trying to create list expected as argument to " + + toClass.getName() + "." + m.getName()); + } + + if (paramObj != null) { + try { + boolean isAccessible = m.isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + //LOG.debug("Calling " + // + toObj.getClass().getName() + "." + // + m.getName() + "(" + paramValue + // + ")"); + m.invoke(toObj, paramObj); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert List returned by" + + toClass.getName() + "." + + m.getName() + + "() to Properties entry", + e); + } + } + } else { + + // Setter expects something that is not a List and + // not yang-generated. Just pass the parameter value + + //LOG.debug("Parameter class " + // + paramClass.getName() + // + " is not a yang-generated class or a List"); + + if (paramValue != null) { + + Object constObj = null; + + try { + // See if I can find a constructor I can use + Constructor[] constructors = paramClass + .getConstructors(); + // Is there a String constructor? + for (Constructor c : constructors) { + Class[] cParms = c.getParameterTypes(); + if ((cParms != null) + && (cParms.length == 1)) { + if (String.class + .isAssignableFrom(cParms[0])) { + constObj = c + .newInstance(paramValue); + } + } + } + + if (constObj == null) { + // Is there a Long constructor? + for (Constructor c : constructors) { + Class[] cParms = c + .getParameterTypes(); + if ((cParms != null) + && (cParms.length == 1)) { + if (Long.class + .isAssignableFrom(cParms[0])) { + constObj = c + .newInstance(Long + .parseLong(paramValue)); + } + } + } + + } + + if (constObj != null) { + try { + //LOG.debug("Calling " + // + toObj.getClass() + // .getName() + "." + // + m.getName() + "(" + // + constObj + ")"); + m.invoke(toObj, constObj); + foundValue = true; + } catch (Exception e2) { + LOG.error( + "Caught exception trying to call " + + m.getName(), e2); + } + } else { + try { + boolean isAccessible = m + .isAccessible(); + if (!isAccessible) { + m.setAccessible(true); + } + //LOG.debug("Calling " + // + toObj.getClass() + // .getName() + "." + // + m.getName() + "(" + // + paramValue + ")"); + m.invoke(toObj, paramValue); + if (!isAccessible) { + m.setAccessible(isAccessible); + } + foundValue = true; + + } catch (Exception e) { + LOG.error( + "Caught exception trying to convert value returned by" + + toClass.getName() + + "." + + m.getName() + + "() to Properties entry", + e); + } + } + } catch (Exception e1) { + LOG.warn( + "Could not find a suitable constructor for " + + paramClass.getName(), e1); + } + + /* + * try { boolean isAccessible = + * m.isAccessible(); if (!isAccessible) { + * m.setAccessible(true); } LOG.debug("Calling " + * + toObj.getClass().getName() + "." + + * m.getName() + "(" + paramValue + ")"); + * m.invoke(toObj, paramValue); if + * (!isAccessible) { + * m.setAccessible(isAccessible); } foundValue = + * true; + * + * } catch (Exception e) { LOG.error( + * "Caught exception trying to convert value returned by" + * + toClass.getName() + "." + m.getName() + + * "() to Properties entry", e); } + */ + } + } + } + } // End of section handling "setter" method + } // End of loop through Methods + } // End of section handling yang-generated class + + if (foundValue) { + return (toObj); + } else { + return (null); + } + } + +/* + public static void printPropertyList(PrintStream pstr, String pfx, + Class toClass) { + boolean foundValue = false; + + //LOG.debug("Analyzing " + toClass.getName() + " class : pfx " + pfx); + + if (isYangGenerated(toClass) + && (!Identifier.class.isAssignableFrom(toClass))) { + // Class is yang generated. + //LOG.debug(toClass.getName() + " is a Yang-generated class"); + + if (toClass.getName().endsWith("Key")) { + if (Identifier.class.isAssignableFrom(toClass)) { + //LOG.debug(Identifier.class.getName() + // + " is assignable from " + toClass.getName()); + } else { + + //LOG.debug(Identifier.class.getName() + // + " is NOT assignable from " + toClass.getName()); + } + } + + String propNamePfx = null; + if (pfx.endsWith("]")) { + propNamePfx = pfx; + } else { + + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx + "." + + toLowerHyphen(toClass.getSimpleName()); + } else { + propNamePfx = toLowerHyphen(toClass.getSimpleName()); + } + + if (propNamePfx.endsWith("-builder")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - "-builder".length()); + } + + if (propNamePfx.endsWith("-impl")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - "-impl".length()); + } + } + + // Iterate through getter methods to figure out values we need to + // set + + for (Method m : toClass.getMethods()) { + //LOG.debug("Is " + m.getName() + " method a getter?"); + if (isGetter(m)) { + //LOG.debug(m.getName() + " is a getter"); + Class returnClass = m.getReturnType(); + + String fieldName = toLowerHyphen(m.getName().substring(3)); + fieldName = fieldName.substring(0, 1).toLowerCase() + + fieldName.substring(1); + + String propName = propNamePfx + "." + fieldName; + + // Is the return type a yang generated class? + if (isYangGenerated(returnClass)) { + // Is it an enum? + if (returnClass.isEnum()) { + //System.out.println(returnClass.getSimpleName()); + //System.out.println(Arrays.asList(returnClass.getEnumConstants())); + + //LOG.debug(m.getName() + " is an Enum"); + pstr.print("\n" + propName + ":Enum:" + Arrays.asList(returnClass.getEnumConstants()) + "\n"); + + } else { + + String simpleName = returnClass.getSimpleName(); + + if ("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName)) { + //LOG.debug(m.getName()+" is an "+simpleName); + pstr.print("\n" + propName + ":" + simpleName + "\n"); + } else { + printPropertyList(pstr, propNamePfx, returnClass); + } + + } + } else { + + // Setter's argument is not a yang-generated class. See + // if it is a List. + + if (List.class.isAssignableFrom(returnClass)) { + + //LOG.debug("Parameter class " + //+ returnClass.getName() + " is a List"); + + // Figure out what type of args are in List and pass + // that to toList(). + + Type returnType = m.getGenericReturnType(); + Type elementType = ((ParameterizedType) returnType) + .getActualTypeArguments()[0]; + Class elementClass = (Class) elementType; + //LOG.debug("Calling printPropertyList on list type (" + //+ elementClass.getName() + //+ "), pfx is (" + // + pfx + // + "), toClass is (" + // + toClass.getName() + ")"); + printPropertyList( + pstr, + propNamePfx + + "." + + toLowerHyphen(elementClass + .getSimpleName()) + "[]", + elementClass); + + } else if (!returnClass.equals(Class.class)) { + + // Setter expects something that is not a List and + // not yang-generated. Just pass the parameter value + + //LOG.debug("Parameter class " + // + returnClass.getName() + // + " is not a yang-generated class or a List"); + String className=returnClass.getName(); + + //"org.opendaylight.yangtools.yang.binding.Identifier" + int nClassNameIndex = className.lastIndexOf('.'); + String nClassName = className; + if(nClassNameIndex != -1){ + nClassName=className.substring(nClassNameIndex+1); + } + pstr.print("\n" + propName +":" + nClassName +"\n"); + + } + } + } // End of section handling "setter" method + } // End of loop through Methods + } // End of section handling yang-generated class + + } +*/ + + public static Properties prop = new Properties(); + public static ArrayList<String> propList = new ArrayList<String>(); + public static Properties getProperties(PrintStream pstr, String pfx, + Class toClass) { + boolean foundValue = false; + + //LOG.debug("Analyzing " + toClass.getName() + " class : pfx " + pfx); + + if (isYangGenerated(toClass) + && (!Identifier.class.isAssignableFrom(toClass))) { + // Class is yang generated. + //LOG.debug(toClass.getName() + " is a Yang-generated class"); + + if (toClass.getName().endsWith("Key")) { + if (Identifier.class.isAssignableFrom(toClass)) { + //LOG.debug(Identifier.class.getName() + // + " is assignable from " + toClass.getName()); + } else { + + //LOG.debug(Identifier.class.getName() + // + " is NOT assignable from " + toClass.getName()); + } + } + + String propNamePfx = null; + if (pfx.endsWith("]")) { + propNamePfx = pfx; + }else if(pfx.indexOf(".CLASS_FOUND") != -1){ + pfx = pfx.replace(".CLASS_FOUND",""); + propNamePfx = pfx + "." + + toLowerHyphen(toClass.getSimpleName()); + } else { + + if ((pfx != null) && (pfx.length() > 0)) { + propNamePfx = pfx + "." + + toLowerHyphen(toClass.getSimpleName()); + } else { + propNamePfx = toLowerHyphen(toClass.getSimpleName()); + } + + if (propNamePfx.endsWith("-builder")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - "-builder".length()); + } + + if (propNamePfx.endsWith("-impl")) { + propNamePfx = propNamePfx.substring(0, propNamePfx.length() + - "-impl".length()); + } + } + + // Iterate through getter methods to figure out values we need to + // set + + for (Method m : toClass.getMethods()) { + //LOG.debug("Is " + m.getName() + " method a getter?"); + if (isGetter(m)) { + // LOG.debug(m.getName() + " is a getter"); + Class returnClass = m.getReturnType(); + + String fieldName = toLowerHyphen(m.getName().substring(3)); + if(m != null && m.getName().matches("^is[A-Z].*")){ + fieldName = toLowerHyphen(m.getName().substring(2)); + } + fieldName = fieldName.substring(0, 1).toLowerCase() + + fieldName.substring(1); + + String propName = propNamePfx + "." + fieldName; + //System.out.println("****" + propName); + + // Is the return type a yang generated class? + if (isYangGenerated(returnClass)) { + // Is it an enum? + if (returnClass.isEnum()) { + + //LOG.debug(m.getName() + " is an Enum"); + //pstr.print("\n" + propName); + //pstr.print("\n" + propName + ":Enum:" + Arrays.asList(returnClass.getEnumConstants()) + "\n"); + pstr.print("\"" + propName + ":Enum:" + Arrays.asList(returnClass.getEnumConstants()) + "\","); + prop.setProperty(propName,""); + propList.add(propName); + + } else { + + String simpleName = returnClass.getSimpleName(); + //System.out.println("simpleName:" + simpleName); + + if ("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName) || "IpAddress".equals(simpleName)) { + //LOG.debug(m.getName()+" is an "+simpleName); + //pstr.print("\n" + propName); + //pstr.print("\n" + propName + ":" + simpleName + "\n"); + pstr.print("\"" + propName + ":" + simpleName + "\","); + prop.setProperty(propName,""); + propList.add(propName); + } else { + boolean isString = false; + boolean isNumber = false; + boolean isBoolean = false; + boolean isIdentifier = false; + //System.out.println("simpleName:" + simpleName); + //System.out.println("propName:" + propName); + for(Method mthd : returnClass.getMethods()){ + String methodName = mthd.getName(); + //System.out.println("methodName:" + methodName); + if(methodName.equals("getValue")){ + Class retType = mthd.getReturnType(); + //System.out.println("retType:" + retType); + isString = String.class.isAssignableFrom(retType); + isNumber = Number.class.isAssignableFrom(retType); + isBoolean = Boolean.class.isAssignableFrom(retType); + isIdentifier = Identifier.class.isAssignableFrom(retType); + //System.out.println("isString:" + isString); + //System.out.println("isNumber:" + isNumber); + //System.out.println("isNumber:" + isNumber); + break; + } + } + + if(isString){ + pstr.print("\"" + propName + ":String\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(isNumber){ + pstr.print("\"" + propName + ":Number\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(isBoolean){ + pstr.print("\"" + propName + ":Boolean\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(isIdentifier){ + //System.out.println("isIdentifier"); + //isIdentifer so skipping + continue; + }else{ + /* + System.out.println("fieldName:" + fieldName); + System.out.println("simpleName:" + simpleName); + System.out.println("returnClass:" + returnClass); + System.out.println("pstr:" + pstr); + System.out.println("propNamePfx:" + propNamePfx); + */ + getProperties(pstr, propNamePfx + ".CLASS_FOUND", returnClass); + } + } + + } + } else { + + // Setter's argument is not a yang-generated class. See + // if it is a List. + + if (List.class.isAssignableFrom(returnClass)) { + + //LOG.debug("Parameter class " + // + returnClass.getName() + " is a List"); + + // Figure out what type of args are in List and pass + // that to toList(). + + Type returnType = m.getGenericReturnType(); + Type elementType = ((ParameterizedType) returnType) + .getActualTypeArguments()[0]; + Class elementClass = (Class) elementType; + //LOG.debug("Calling printPropertyList on list type (" + //+ elementClass.getName() + // + "), pfx is (" + // + pfx + // + "), toClass is (" + // + toClass.getName() + ")"); + //System.out.println("List propNamePfx:" + propNamePfx+ "." + toLowerHyphen(elementClass.getSimpleName()) + "[]"); + if(String.class.isAssignableFrom(elementClass)){ + pstr.print("\"" + propName + ":[String,String,...]\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(Number.class.isAssignableFrom(elementClass)){ + pstr.print("\"" + propName + ":[Number,Number,...]\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(Boolean.class.isAssignableFrom(elementClass)){ + pstr.print("\"" + propName + ":[Boolean,Boolean,...]\","); + prop.setProperty(propName,""); + propList.add(propName); + }else if(Identifier.class.isAssignableFrom(elementClass)){ + continue; + }else{ + getProperties( + pstr, + propNamePfx + + "." + + toLowerHyphen(elementClass + .getSimpleName()) + "[]", + elementClass); + } + + } else if (!returnClass.equals(Class.class)) { + + // Setter expects something that is not a List and + // not yang-generated. Just pass the parameter value + + //LOG.debug("Parameter class " + // + returnClass.getName() + // + " is not a yang-generated class or a List"); + + //pstr.print("\n" + propName); + String className=returnClass.getName(); + int nClassNameIndex = className.lastIndexOf('.'); + String nClassName = className; + if(nClassNameIndex != -1){ + nClassName=className.substring(nClassNameIndex+1); + } + boolean isString = String.class.isAssignableFrom(returnClass); + boolean isNumber = Number.class.isAssignableFrom(returnClass); + boolean isBoolean = Boolean.class.isAssignableFrom(returnClass); + //pstr.print("\n" + propName +":" + nClassName +"\n"); + boolean isIdentifier = Identifier.class.isAssignableFrom(returnClass); + if(!isIdentifier && !nClassName.equals("[C")){ + if(isNumber){ + pstr.print("\"" + propName +":Number\","); + }else if(isBoolean){ + pstr.print("\"" + propName +":Boolean\","); + }else{ + if(nClassName.equals("[B")){ + pstr.print("\"" + propName +":Binary\","); + }else{ + pstr.print("\"" + propName +":" + nClassName +"\","); + } + } + prop.setProperty(propName,""); + propList.add(propName); + } + + } + } + } // End of section handling "setter" method + } // End of loop through Methods + } // End of section handling yang-generated class + + return prop; + } + + public static boolean isYangGenerated(Class c) { + if (c == null) { + return (false); + } else { + //System.out.println(c.getName()); + return (c.getName().startsWith("org.opendaylight.yang.gen.")); + } + } + + public static boolean isIpv4Address(Class c) { + + if (c == null ) { + return (false); + } + String simpleName = c.getSimpleName(); + return ("Ipv4Address".equals(simpleName)) ; + } + + public static boolean isIpv6Address(Class c) { + + if (c == null ) { + return (false); + } + String simpleName = c.getSimpleName(); + return ("Ipv6Address".equals(simpleName)) ; + } + + public static String toLowerHyphen(String inStr) { + if (inStr == null) { + return (null); + } + + String str = inStr.substring(0, 1).toLowerCase(); + if (inStr.length() > 1) { + str = str + inStr.substring(1); + } + + String regex = "(([a-z0-9])([A-Z]))"; + String replacement = "$2-$3"; + + String retval = str.replaceAll(regex, replacement).toLowerCase(); + + //LOG.debug("Converting " + inStr + " => " + str + " => " + retval); + return (retval); + } + + public static String toUpperCamelCase(String inStr) { + if (inStr == null) { + return (null); + } + + String[] terms = inStr.split("-"); + StringBuffer sbuff = new StringBuffer(); + // Check if string begins with a digit + if (Character.isDigit(inStr.charAt(0))) { + sbuff.append('_'); + } + for (String term : terms) { + sbuff.append(term.substring(0, 1).toUpperCase()); + if (term.length() > 1) { + sbuff.append(term.substring(1)); + } + } + return (sbuff.toString()); + + } + + public static boolean isGetter(Method m) { + //System.out.println(m); + if (m == null) { + return (false); + } + + if (Modifier.isPublic(m.getModifiers()) + && (m.getParameterTypes().length == 0)) { + if ((m.getName().matches("^is[A-Z].*") || m.getName().matches("^get[A-Z].*")) + && m.getReturnType().equals(Boolean.class)) { + return (true); + } + if (m.getName().matches("^get[A-Z].*") + && !m.getReturnType().equals(void.class)) { + return (true); + } + + } + + return (false); + } + + public static boolean isSetter(Method m) { + if (m == null) { + return (false); + } + + if (Modifier.isPublic(m.getModifiers()) + && (m.getParameterTypes().length == 1)) { + if (m.getName().matches("^set[A-Z].*")) { + Class[] paramTypes = m.getParameterTypes(); + if (paramTypes[0].isAssignableFrom(Identifier.class) + || Identifier.class.isAssignableFrom(paramTypes[0])) { + return (false); + } else { + return (true); + } + } + + } + + return (false); + } + + public static void main(String[] args){ + try{ + PrintStream ps = new PrintStream(new FileOutputStream(FileDescriptor.out)); + PrintYangToProp printYangToProp = new PrintYangToProp(); + String className = args[0]; + //ClassLoader classLoader = PrintYangToProp.class.getClassLoader(); + //Class aClass = classLoader.loadClass(className); + Class cl = Class.forName(className); + //printPropertyList(ps,"",cl); + //JsonObject jsonObj = Json.createObjectBuilder().build(); + Properties p = getProperties(ps,"",cl); + //System.out.println(p); + + }catch(Exception e){ + e.printStackTrace(); + } + } + + +} diff --git a/dgbuilder/tools/dot_to_json.js b/dgbuilder/tools/dot_to_json.js new file mode 100644 index 00000000..7ff80e8b --- /dev/null +++ b/dgbuilder/tools/dot_to_json.js @@ -0,0 +1,138 @@ +var obj={}; +function dotToJson(str,value,obj){ + //var objArr = path.split("."), part; + var objArr = str.split("."); + var prevStr; + var currObj; + var prevObj; + //console.log(str); + var isArray = false; + var prevObjIsArray = false; + for(var i=0;i<objArr.length -1;i++){ + var subStr= objArr[i] ; + if(isArray){ + prevObjIsArray = true; + } + isArray = false; + if(subStr.indexOf(']') == subStr.length -1){ + subStr = subStr.substring(0,subStr.length -2); + isArray = true; + } + //console.log("subStr:" + subStr + isArray); + //console.dir(prevObj); + if(isArray){ + if(i==0 && obj[subStr] == undefined ){ + //console.log("i==0 && obj[subStr] "); + obj[subStr]=[]; + }else if(i==0 && obj[subStr][0] == undefined ){ + obj[subStr][0]={}; + }else if(i==0 && obj[subStr][0] != undefined ){ + currObj= obj[subStr][0]; + }else{ + if(i == 1){ + //console.log("i==1 && obj[prevStr] "); + prevObj=obj[prevStr]; + if(prevObj[subStr] != undefined && prevObj[subStr][0] == undefined){ + prevObj[subStr] = []; + prevObj[subStr][0] = {}; + currObj = prevObj[subStr][0]; + }else if(prevObj[subStr] != undefined && prevObj[subStr][0] != undefined){ + currObj = prevObj[subStr][0]; + }else if(prevObj[subStr] == undefined){ + prevObj[subStr] = []; + prevObj[subStr][0] = {}; + currObj = prevObj[subStr][0]; + } + }else{ + if(prevObj[subStr] == undefined){ + prevObj[subStr]=[]; + prevObj[subStr][0]={}; + currObj = prevObj[subStr][0]; + }else{ + currObj = prevObj[subStr][0]; + } + } + } + }else{ + if(i==0 && obj[subStr] == undefined ){ + obj[subStr] = {}; + currObj= obj[subStr]; + }else if(i==0 && obj[subStr] != undefined ){ + currObj=obj[subStr]; + //console.log("in gkjgjkg"); + }else{ + if(i == 1){ + prevObj=obj[prevStr]; + if(prevObj[subStr] == undefined){ + prevObj[subStr] = {}; + currObj = prevObj[subStr]; + }else{ + currObj = prevObj[subStr]; + } + }else{ + if(prevObj[subStr] == undefined){ + prevObj[subStr] = {}; + currObj = prevObj[subStr]; + }else{ + currObj = prevObj[subStr]; + } + } + } + } + prevStr=subStr; + if(i <objArr.length-2){ + //console.dir(currObj); + prevObj=currObj; + } + } + var lastStr = objArr[objArr.length-1]; + if(isArray){ + currObj[lastStr] = value; + }else{ + currObj[lastStr] = value; + } + //prevObj[lastStr] = value; + //console.dir(currObj); + return obj; +} +function printObj(obj){ +for( j in obj){ + console.log(j + ":" + obj[j]); + if(typeof obj[j] == "object" ){ + printObj(obj[j]); + } + +} +} + +/* +var nObj={}; +for(var i=0;i<a.length;i++){ + dotToJson(a[i],'',nObj); +} +*/ +var sliValuesObj = require(process.argv[2]); +var moduleName = process.argv[3]; +//console.dir(sliValuesObj); +var a= sliValuesObj[moduleName + "_VALUES"]; +var rpcs= sliValuesObj[moduleName + "_RPCS"]; +var nObj={}; +nObj['moduleName'] = moduleName; +console.log("module.exports = "); +for(var i=0;i<a.length;i++){ + var key =a[i].substring(0,a[i].indexOf(':')); + //console.log(key); + var value =a[i].substring(a[i].indexOf(':') +1); + if(value == undefined) value =""; + dotToJson(key,value,nObj); +} + +nObj[moduleName + "_PROPS"] =[]; +for(var i=0;i<a.length;i++){ + var key =a[i].substring(0,a[i].indexOf(':')); + nObj[moduleName + "_PROPS"].push(key); +} + +nObj[moduleName + "_RPCS"] = rpcs; + +console.log(JSON.stringify(nObj,null,4)); diff --git a/dgbuilder/tools/formatXml.py b/dgbuilder/tools/formatXml.py new file mode 100644 index 00000000..913456a1 --- /dev/null +++ b/dgbuilder/tools/formatXml.py @@ -0,0 +1,11 @@ +import xml.dom.minidom +import lxml.etree as etree +import sys + +xml_fname=sys.argv[1] +#xml = xml.dom.minidom.parse(xml_fname) # or xml.dom.minidom.parseString(xml_string) +#pretty_xml_as_string = xml.toprettyxml() +#print pretty_xml_as_string + +x = etree.parse(xml_fname) +print etree.tostring(x, pretty_print = True) diff --git a/dgbuilder/tools/format_json.sh b/dgbuilder/tools/format_json.sh new file mode 100755 index 00000000..f86ad3cf --- /dev/null +++ b/dgbuilder/tools/format_json.sh @@ -0,0 +1,6 @@ +if [ "$#" != "1" ] +then + echo "Usage: $0 jsonFileFullPath" + exit +fi +cat $1|python -m json.tool diff --git a/dgbuilder/tools/format_xml.sh b/dgbuilder/tools/format_xml.sh new file mode 100755 index 00000000..c66153ed --- /dev/null +++ b/dgbuilder/tools/format_xml.sh @@ -0,0 +1,16 @@ +if [ "$#" != "1" ] +then + echo "Usage: $0 xmlFileFullPath" + exit +fi + +if [ -z "$PROJECT_HOME" ] +then + export PROJECT_HOME=$(pwd)/.. +fi +if [ -e "$1" ] +then + python $PROJECT_HOME/tools/formatXml.py $1 +else + echo "File $1 does not exist" +fi diff --git a/dgbuilder/tools/generate_props_from_yang.sh b/dgbuilder/tools/generate_props_from_yang.sh new file mode 100755 index 00000000..70162c6f --- /dev/null +++ b/dgbuilder/tools/generate_props_from_yang.sh @@ -0,0 +1,96 @@ +if [ -z "$PROJECT_HOME" ] +then + export PROJECT_HOME=$(pwd)/.. +fi + +toolsDir=$PROJECT_HOME/tools +rm -rf ${toolsDir}/tmpws +mkdir ${toolsDir}/tmpws +mkdir ${toolsDir}/tmpws/logs +mkdir ${toolsDir}/tmpws/jars +mkdir ${toolsDir}/tmpws/tmp +if [ "$#" != "1" ] +then + echo "Command line:$0 $*" >${toolsDir}/tmpws/logs/err.log + echo "Usage: $0 yangFile" >>${toolsDir}/tmpws/logs/err.log + exit +fi + +isZipFile="N" +echo "$1" | grep "\.zip$" >/dev/null 2>&1 +if [ "$?" -eq "0" ] +then + isZipFile="Y" +fi + +if [ "$isZipFile" = "Y" ] +then + #zip file of yangs provided + zipFile=$(basename $1) + unzip -o -d $PROJECT_HOME/tools/tmpws/tmp $1 >/dev/null 2>&1 + rm $1 >/dev/null 2>&1 + cd $PROJECT_HOME/tools/tmpws/tmp + fName="${zipFile}" + extension="${fName##*.}" + moduleName="${fName%.*}" + #echo "ModuleName is :$moduleName" + rm -rf $PROJECT_HOME/yangFiles/$moduleName + mkdir $PROJECT_HOME/yangFiles/$moduleName + mv *.yang $PROJECT_HOME/yangFiles/$moduleName + cd $PROJECT_HOME/tools + yangFilesFullPath=${PROJECT_HOME}/yangFiles/$moduleName + cd ${toolsDir}/tmpws + mkdir -p yangApp/model/src/main/yang + mkdir -p yangApp/model/src/main/yang-gen-sal + cp -r ${yangFilesFullPath}/* yangApp/model/src/main/yang + cp ${toolsDir}/pom.xml_base yangApp/model/pom.xml + cd ${toolsDir}/tmpws/yangApp/model + + #Maven Compile + mvn clean install >${toolsDir}/tmpws/logs/mvn_install.log 2>${toolsDir}/tmpws/logs/err.log + yangApp_model_jar="yangApp-model-1.0.0-SNAPSHOT.jar" + + #Copy the built jar to jars directory + cp ${toolsDir}/tmpws/yangApp/model/target/${yangApp_model_jar} ${toolsDir}/tmpws/jars + . ${toolsDir}/setClasspath + + mv ${toolsDir}/output_js/${moduleName}_inputs.js ${toolsDir}/output_js/${moduleName}_inputs_prev.js >/dev/null 2>&1 + + ${toolsDir}/getRpcsClassFromYang.sh ${yangFilesFullPath}/${moduleName}.yang ${toolsDir}/tmpws/yangApp/model/target/${yangApp_model_jar} > ${toolsDir}/output_js/${moduleName}.js + + node ${toolsDir}/dot_to_json.js ${toolsDir}/output_js/${moduleName}.js $moduleName >${toolsDir}/output_js/${moduleName}_inputs.js + + cp ${toolsDir}/output_js/${moduleName}_inputs.js $PROJECT_HOME/generatedJS +else + #Single yang provided + yangFileFullPath=$1 + cd ${toolsDir}/tmpws + mkdir -p yangApp/model/src/main/yang + mkdir -p yangApp/model/src/main/yang-gen-sal + cp ${yangFileFullPath} yangApp/model/src/main/yang + cp ${toolsDir}/pom.xml_base yangApp/model/pom.xml + cd ${toolsDir}/tmpws/yangApp/model + + #Maven Compile + mvn clean install >${toolsDir}/tmpws/logs/mvn_install.log 2>${toolsDir}/tmpws/logs/err.log + yangApp_model_jar="yangApp-model-1.0.0-SNAPSHOT.jar" + + #Copy the built jar to jars directory + cp ${toolsDir}/tmpws/yangApp/model/target/${yangApp_model_jar} ${toolsDir}/tmpws/jars + . ${toolsDir}/setClasspath + + moduleName=$(cat $yangFileFullPath|egrep "module .*{"|cut -d' ' -f2|cut -d'{' -f1) + + mv ${toolsDir}/output_js/${moduleName}_inputs.js ${toolsDir}/output_js/${moduleName}_inputs_prev.js >/dev/null 2>&1 + + ${toolsDir}/getRpcsClassFromYang.sh ${yangFileFullPath} ${toolsDir}/tmpws/yangApp/model/target/${yangApp_model_jar} > ${toolsDir}/output_js/${moduleName}.js + + node ${toolsDir}/dot_to_json.js ${toolsDir}/output_js/${moduleName}.js $moduleName >${toolsDir}/output_js/${moduleName}_inputs.js + + cp ${toolsDir}/output_js/${moduleName}_inputs.js $PROJECT_HOME/generatedJS + + +fi + +echo "Done..." + diff --git a/dgbuilder/tools/getModuleName.sh b/dgbuilder/tools/getModuleName.sh new file mode 100755 index 00000000..cf0db193 --- /dev/null +++ b/dgbuilder/tools/getModuleName.sh @@ -0,0 +1,2 @@ +module=$(cat $1|egrep "module .*{"|awk '{print $2}'|sed -e 's/{//g') +echo $module diff --git a/dgbuilder/tools/getRpcsClassFromYang.sh b/dgbuilder/tools/getRpcsClassFromYang.sh new file mode 100755 index 00000000..b0703152 --- /dev/null +++ b/dgbuilder/tools/getRpcsClassFromYang.sh @@ -0,0 +1,85 @@ +toolsDir=$PROJECT_HOME/tools +. ${toolsDir}/setClasspath +if [ "$#" != "2" ] +then + echo "Usage $0 yang_file generated_jar_file" + echo "example $0 /home/users/sdnc/src/sample.yang /home/users/sdnc/target/sample.model-1.0.0.jar" + exit +fi +yangFile="$1" +jarFile="$2" +module=$(cat $yangFile|egrep "module .*{"|awk '{print $2}'|sed -e 's/{//g') +#echo " \"$module\" : [" +rpcs=$(grep rpc $yangFile|grep -v leaf|sed -e 's/^\s\+rpc//g'|awk '{print $1}') +#echo ${rpcs} +for i in `find ${PROJECT_HOME}/svclogic/lib -name "*.jar" -print` +do +#echo $i +export CLASSPATH=$CLASSPATH:$i +done +export CLASSPATH=$CLASSPATH:${toolsDir}/printYangToProp.jar:. +allProps="" +for rpc in $rpcs +do +rpcVal=$(echo $rpc|sed -e "s/\b\(.\)/\u\1/g"|sed s/\-//g) +className=$(jar -tvf ${jarFile}|grep "org/opendaylight/yang/gen/"|grep -w "${rpcVal}Input.class"|grep -v grep|awk '{print $NF}'|sed -e 's/\//./g'|sed -e 's/.class$//g') +inputProps="" +if [ "$className" != "" ] +then + #java -cp $CLASSPATH PrintYangToProp $className 2>/dev/null|grep '*' |cut -d'*' -f2|sed -e "s/^[ \t]*//g"|sed -e "s/^/\t\t\"/g"|sed -e "s/$/\",/g" + inputProps=$(java -cp $CLASSPATH PrintYangToProp $className 2>${toolsDir}/tmpws/logs/err.log) +fi +className=$(jar -tvf ${jarFile}|grep "org/opendaylight/yang/gen/"|grep -w "${rpcVal}Output"|grep -v grep|awk '{print $NF}'|sed -e 's/\//./g'|sed -e 's/.class$//g') +#echo $inputProps +#echo $className +outputProps="" +if [ "$className" != "" ] +then + #java -cp $CLASSPATH PrintYangToProp $className 2>/dev/null|grep '*' |cut -d'*' -f2|sed -e "s/^[ \t]*//g"|sed -e "s/^/\t\t\"/g"|sed -e "s/$/\",/g" + outputProps=$(java -cp $CLASSPATH PrintYangToProp $className 2>${toolsDir}/tmpws/logs/err.log) +fi +if [ -z "$allProps" ] +then + allProps=$(echo ${inputProps}${outputProps}|sed -e s/,$//g) +else + allProps=$(echo ${allProps},${inputProps}${outputProps}|sed -e s/,$//g) +fi +done +#allProps=$(echo ${inputProps}${outputProps}|sed -e s/,$//g) +#echo $allProps +#OIFS=$IFS +#IFS=',' +#arr2=$allProps +#for x in $arr2 +#do +# echo "$x" +#done +#IFS=$OIFS +#echo " ]" +echo "module.exports = {" +echo "\"moduleName\" : \"${module}\"," +echo "'${module}_VALUES' : " +echo "[ $allProps ]"|python -m json.tool +echo "," +echo "'${module}_RPCS' : [" + +cnt=0 +#numOfRpcs=${#rpcs[@]} +numOfRpcs=0; +for rpc in $rpcs +do + numOfRpcs=$((numOfRpcs+1)) +done + +for rpc in $rpcs +do + cnt=$((cnt+1)) + if [ $cnt -eq $numOfRpcs ] + then + echo " \"$rpc\"" + else + echo " \"$rpc\"," + fi +done +echo " ]" +echo "}" diff --git a/dgbuilder/tools/jsonTool.js b/dgbuilder/tools/jsonTool.js new file mode 100644 index 00000000..d95ae10d --- /dev/null +++ b/dgbuilder/tools/jsonTool.js @@ -0,0 +1,119 @@ +var obj={}; +function dotToJson(str,value,obj){ + //var objArr = path.split("."), part; + var objArr = str.split("."); + var prevStr; + var currObj; + var prevObj; + //console.log(str); + var isArray = false; + var prevObjIsArray = false; + for(var i=0;i<objArr.length -1;i++){ + var subStr= objArr[i] ; + if(isArray){ + prevObjIsArray = true; + } + isArray = false; + if(subStr.indexOf(']') == subStr.length -1){ + subStr = subStr.substring(0,subStr.length -2); + isArray = true; + } + //console.log("subStr:" + subStr + isArray); + //console.dir(prevObj); + if(isArray){ + if(i==0 && obj[subStr] == undefined ){ + //console.log("i==0 && obj[subStr] "); + obj[subStr]=[]; + }else if(i==0 && obj[subStr][0] == undefined ){ + obj[subStr][0]={}; + }else if(i==0 && obj[subStr][0] != undefined ){ + currObj= obj[subStr][0]; + }else{ + if(i == 1){ + //console.log("i==1 && obj[prevStr] "); + prevObj=obj[prevStr]; + if(prevObj[subStr][0] == undefined){ + prevObj[subStr] = []; + prevObj[subStr][0] = {}; + currObj = prevObj[subStr][0]; + }else{ + currObj = prevObj[subStr][0]; + } + }else{ + if(prevObj[subStr] == undefined){ + prevObj[subStr]=[]; + prevObj[subStr][0]={}; + currObj = prevObj[subStr][0]; + }else{ + currObj = prevObj[subStr][0]; + } + } + } + }else{ + if(i==0 && obj[subStr] == undefined ){ + obj[subStr] = {}; + currObj= obj[subStr]; + }else if(i==0 && obj[subStr] != undefined ){ + currObj=obj[subStr]; + //console.log("in gkjgjkg"); + }else{ + if(i == 1){ + prevObj=obj[prevStr]; + if(prevObj[subStr] == undefined){ + prevObj[subStr] = {}; + currObj = prevObj[subStr]; + }else{ + currObj = prevObj[subStr]; + } + }else{ + if(prevObj[subStr] == undefined){ + prevObj[subStr] = {}; + currObj = prevObj[subStr]; + }else{ + currObj = prevObj[subStr]; + } + } + } + } + prevStr=subStr; + if(i <objArr.length-2){ + //console.dir(currObj); + prevObj=currObj; + } + } + var lastStr = objArr[objArr.length-1]; + if(isArray){ + currObj[lastStr] = value; + }else{ + currObj[lastStr] = value; + } + //prevObj[lastStr] = value; + //console.dir(currObj); + return obj; +} +function printObj(obj){ +for( j in obj){ + console.log(j + ":" + obj[j]); + if(typeof obj[j] == "object" ){ + printObj(obj[j]); + } + +} +} + +var a=[]; +var nObj={}; +for(var i=0;i<a.length;i++){ + dotToJson(a[i],'',nObj); +} + +var nObj={}; +for(var i=0;i<a.length;i++){ + var key =a[i].substring(0,a[i].indexOf(':')); + console.log(key); + var value =a[i].substring(a[i].indexOf(':') +1); + if(value == undefined) value =""; + dotToJson(key,value,nObj); +} +console.log(JSON.stringify(nObj,null,4)); +//console.log (stringToObj('abc.ebg.h',"",{})); diff --git a/dgbuilder/tools/json_to_html b/dgbuilder/tools/json_to_html new file mode 100644 index 00000000..51afe452 --- /dev/null +++ b/dgbuilder/tools/json_to_html @@ -0,0 +1,139 @@ +try{ +var jsonStr='{}'; +jsonObj=JSON.parse(jsonStr); +var objectId =0; +var level=0; +var htmlStr="" +htmlStr += "<html>"; +htmlStr += "<head>"; +htmlStr += "<script>"; +htmlStr += "function show(idVal){"; +htmlStr += " var val = \"<table border='1'>\" + document.getElementById(idVal).value + \"</table>\";"; +htmlStr += " document.getElementById('displayId').innerHTML = val;"; +htmlStr += "document.getElementById('displayId').style.display = \"block\";"; +//htmlStr += "alert(idVal);"; +//htmlStr += "alert(val);"; +htmlStr += "}"; +htmlStr += "</script>"; +htmlStr += "</head>"; +htmlStr += "<div id='displayId' style='display:none'></div>"; +htmlStr += "<div>\n<table border='1'>\n"; +printObjectValues(jsonObj,level); +htmlStr += "\n</table>\n</div>"; +//var pattern = new RegExp("\\n","g"); +//htmlstr =htmlStr.replace(pattern,''); +htmlStr += "</html>"; +console.log(htmlStr); + +function tabs(level){ +return ''; +} +function tabsOrig(level){ + var tabs=""; + for(var i=0;i<level;i++){ + tabs += "\t"; + } + return tabs; +} + +function printObjectValues(jsonObj,level){ +var output=""; +var objectHtmlStr=""; +try{ +for (var key in jsonObj) { +//console.log(key +":" + jsonObj.hasOwnProperty(key)); + if (jsonObj.hasOwnProperty(key)) { + var v = jsonObj[key]; + if(typeof v === 'object' && Array.isArray(v) === false){ + var idVal = objectId++; + level++; + objectHtmlStr += tabs(level) + "<div>\n" ; + objectHtmlStr += tabs(level+1 ) +"<table border='1'>\n" ; + + var str=printObjectValues(v,level+2); + if(str != null && str != ''){ + htmlStr += tabs(level+2) + objectHtmlStr + "<tr><td style='background-color:green'><a href=\"javascript:show('obj_" + idVal + "')\">" + key + "</a>\n"; + htmlStr +="<input id='obj_" + idVal + "' type='hidden' value='" + str.trim() + "'>\n"; + } + + htmlStr += tabs(level+1) + "</table>\n" ; + htmlStr += tabs(level) + "</div>\n"; + }else if(typeof v === 'object' && Array.isArray(v) === true){ + var idVal = objectId++; + level++; + objectHtmlStr += tabs(level) + "<div>\n"; + objectHtmlStr += tabs(level+1) + "<table border='1'>\n"; + + var str = printArrayValues(v,key,level+2); + if(str != null && str != ''){ + htmlStr += tabs(level+2) + objectHtmlStr + "<tr><td style='background-color:blue'><a href=\"javascript:show('obj_" + idVal + "')\">" + key + "</a>\n"; + htmlStr+="<input id='obj_" + objectId + "' type='hidden' value='" + str.trim() + "'>\n"; + } + + htmlStr += tabs(level+1) + "</table>\n" ; + htmlStr += tabs(level) + "</div>\n"; + }else{ + output += tabs(level) +"<tr><td>" + key + "</td><td>" + printValue(v) + "</td></tr>\n"; + } + } +} +}catch(err){ + console.log(err); +} +return output; +} + +}catch(err){ +console.log( err ); +} + +function printArrayValues(arrObj,key,level){ +var output =""; +var arrayHtmlStr =""; +try{ + for(var i=0;arrObj != null && i<arrObj.length;i++){ + var o=arrObj[i]; + if(typeof o === 'object' && Array.isArray(o) === false){ + var idVal = objectId++; + level++; + arrayHtmlStr += tabs(level) + "<div>\n" ; + arrayHtmlStr += tabs(level+1 ) +"<table border='1'>\n" ; + + var str = printObjectValues(o,level+2); + if(str != null && str != ''){ + htmlStr += tabs(level+2 ) + arrayHtmlStr + "<tr><td><a href=\"javascript:show('obj_" + idVal + "')\">" +key + "[" + i + "]" + "</a>\n"; + htmlStr+="<input id='obj_" + idVal + "' type='hidden' value='" +str.trim() + "'>\n"; + } + htmlStr += tabs(level+1) + "</table>\n"; + htmlStr += tabs(level) + "</div>\n"; + }else if(typeof o === 'object' && Array.isArray(v) === true){ + var idVal = objectId++; + level++; + arrayHtmlStr += tabs(level) + "<div>\n" ; + arrayHtmlStr += tabs(level+1 ) +"<table border='1'>\n" ; + + var str = printArrayValues(o,key,level); + if(str != null && str != ''){ + htmlStr += tabs(level+2 ) + arrayHtmlStr + "<tr><td><a href=\"javascript:show('obj_" + idVal + "')\">Array</a>\n"; + htmlStr+="<input id='obj_" + idVal + "' type='hidden' value='" +str.trim() + "'>\n"; + } + + htmlStr += tabs(level+1) + "</table>\n"; + htmlStr += tabs(level) + "</div>\n"; + }else{ + output += tabs(level) + "<tr><td>" + printValue(o) + "</td></tr>\n"; + } + } +}catch(err){ + console.log(err); +} +return output; +} + +function printValue(obj){ + if(obj != undefined){ + return obj; + }else{ + return ""; + } +} diff --git a/dgbuilder/tools/json_to_html_table b/dgbuilder/tools/json_to_html_table new file mode 100755 index 00000000..20c9cfeb --- /dev/null +++ b/dgbuilder/tools/json_to_html_table @@ -0,0 +1,144 @@ +try{ +var jsonStr='{}'; +jsonObj=JSON.parse(jsonStr); +var htmlObj ={}; +var objectId =0; +var level=0; +var htmlStr="" +htmlStr += "<html>"; +htmlStr += "<head>"; +htmlStr += "<script>"; +htmlStr += "function show(idVal){"; +htmlStr += " var val = \"<table border='1'>\" + document.getElementById(idVal).value + \"</table>\";"; +htmlStr += " document.getElementById('displayId').innerHTML = val;"; +htmlStr += "document.getElementById('displayId').style.display = \"block\";"; +//htmlStr += "alert(idVal);"; +//htmlStr += "alert(val);"; +htmlStr += "}"; +htmlStr += "</script>"; +htmlStr += "</head>"; +htmlStr += "<div id='displayId' style='display:none'></div>"; +htmlStr += "<div>\n<table border='1'>\n"; +console.log("<html><table border='1'>"); +printObjectValues(jsonObj,null,level); +console.log("</table></html>"); +htmlStr += "\n</table>\n</div>"; +//var pattern = new RegExp("\\n","g"); +//htmlstr =htmlStr.replace(pattern,''); +htmlStr += "</html>"; +//console.log(htmlStr); + +//console.dir(htmlObj); +var keyObj={}; +for (var key in htmlObj) { + var idx = key.lastIndexOf("."); + if(idx != -1){ + var str = key.substr(0,idx); + keyObj[str] =''; + }else{ + keyObj[key] =''; + } + //console.log(str); +} + +console.dir(keyObj); +console.log("<ul>"); +for (var key in keyObj) { + console.log("<li>" + key + "</li>"); +} +console.log("</ul>"); + +function tabs(level){ +return ''; +} +function tabsOrig(level){ + var tabs=""; + for(var i=0;i<level;i++){ + tabs += "\t"; + } + return tabs; +} + +function printObjectValues(jsonObj,pkey,level){ +var output=""; +var objectHtmlStr=""; +try{ +for (var key in jsonObj) { + if (jsonObj.hasOwnProperty(key)) { + var v = jsonObj[key]; + if(typeof v === 'object' && Array.isArray(v) === false){ + var nkey=""; + if(pkey != null){ + nkey = pkey + "." + key; + }else{ + nkey = key; + } + var str=printObjectValues(v,nkey,level+2); + }else if(typeof v === 'object' && Array.isArray(v) === true){ + var nkey=""; + if(pkey != null){ + nkey = pkey + "." + key; + }else{ + nkey = key; + } + var str = printArrayValues(v,nkey,level+2); + }else{ + if(pkey != null){ + //console.log(pkey + "." + key + ":" +printValue(v) ); + console.log("<tr><td>" + pkey + "." + key + "</td><td>" +printValue(v) + "</td></tr>" ); + htmlObj[pkey + "." + key ] = printValue(v); + }else{ + //console.log( key + ":" +printValue(v) ); + console.log("<tr><td>" + key + "</td><td>" +printValue(v) + "</td></tr>" ); + htmlObj[key ] = printValue(v); + } + //printValue(v); + } + } +} +}catch(err){ + console.log(err); +} +return output; +} + +}catch(err){ +console.log( err ); +} + +function printArrayValues(arrObj,pkey,level){ +var output =""; +var arrayHtmlStr =""; +try{ + for(var i=0;arrObj != null && i<arrObj.length;i++){ + var o=arrObj[i]; + if(typeof o === 'object' && Array.isArray(o) === false){ + var nkey = pkey +"[" + i + "]" ; + var str = printObjectValues(o,nkey,level+2); + }else if(typeof o === 'object' && Array.isArray(v) === true){ + var nkey = pkey +"[" + i + "]" ; + var str = printArrayValues(o,nkey,level); + }else{ + console.log("<tr><td>" + pkey + "." + key + "</td><td>" +printValue(o) + "</td></tr>" ); + htmlObj[pkey + "." + key ] = printValue(o); + //console.log(pkey + ":" +printValue(o) ); + //output += tabs(level) + "<tr><td>" + printValue(o) + "</td></tr>\n"; + } + } +}catch(err){ + console.log(err); +} +return output; +} + +function printValue(obj){ + if(obj != undefined){ + if(typeof obj == 'string'){ + return "'" + obj + "'"; + }else{ + return obj; + } + }else{ + return ""; + } +} diff --git a/dgbuilder/tools/json_to_prop b/dgbuilder/tools/json_to_prop new file mode 100755 index 00000000..f8830f38 --- /dev/null +++ b/dgbuilder/tools/json_to_prop @@ -0,0 +1,116 @@ +try{ +var jsonStr='{}'; +jsonObj=JSON.parse(jsonStr); +var htmlObj ={}; +var objectId =0; +var level=0; +var htmlStr="" +htmlStr += "<html>"; +htmlStr += "<head>"; +htmlStr += "<script>"; +htmlStr += "function show(idVal){"; +htmlStr += " var val = \"<table border='1'>\" + document.getElementById(idVal).value + \"</table>\";"; +htmlStr += " document.getElementById('displayId').innerHTML = val;"; +htmlStr += "document.getElementById('displayId').style.display = \"block\";"; +//htmlStr += "alert(idVal);"; +//htmlStr += "alert(val);"; +htmlStr += "}"; +htmlStr += "</script>"; +htmlStr += "</head>"; +htmlStr += "<div id='displayId' style='display:none'></div>"; +htmlStr += "<div>\n<table border='1'>\n"; +printObjectValues(jsonObj,null,level); +htmlStr += "\n</table>\n</div>"; +//var pattern = new RegExp("\\n","g"); +//htmlstr =htmlStr.replace(pattern,''); +htmlStr += "</html>"; +//console.log(htmlStr); + +function tabs(level){ +return ''; +} +function tabsOrig(level){ + var tabs=""; + for(var i=0;i<level;i++){ + tabs += "\t"; + } + return tabs; +} + +function printObjectValues(jsonObj,pkey,level){ +var output=""; +var objectHtmlStr=""; +try{ +for (var key in jsonObj) { + if (jsonObj.hasOwnProperty(key)) { + var v = jsonObj[key]; + if(typeof v === 'object' && Array.isArray(v) === false){ + var nkey=""; + if(pkey != null){ + nkey = pkey + "." + key; + }else{ + nkey = key; + } + var str=printObjectValues(v,nkey,level+2); + }else if(typeof v === 'object' && Array.isArray(v) === true){ + var nkey=""; + if(pkey != null){ + nkey = pkey + "." + key; + }else{ + nkey = key; + } + var str = printArrayValues(v,nkey,level+2); + }else{ + if(pkey != null){ + console.log(pkey + "." + key + ":" +printValue(v) ); + }else{ + console.log(key + ":" +printValue(v) ); + } + //printValue(v); + } + } +} +}catch(err){ + console.log(err); +} +return output; +} + +}catch(err){ +console.log( err ); +} + +function printArrayValues(arrObj,pkey,level){ +var output =""; +var arrayHtmlStr =""; +try{ + for(var i=0;arrObj != null && i<arrObj.length;i++){ + var o=arrObj[i]; + if(typeof o === 'object' && Array.isArray(o) === false){ + var nkey = pkey +"[" + i + "]" ; + var str = printObjectValues(o,nkey,level+2); + }else if(typeof o === 'object' && Array.isArray(v) === true){ + var nkey = pkey +"[" + i + "]" ; + var str = printArrayValues(o,nkey,level); + }else{ + console.log(pkey + ":" +printValue(o) ); + //output += tabs(level) + "<tr><td>" + printValue(o) + "</td></tr>\n"; + } + } +}catch(err){ + console.log(err); +} +return output; +} + +function printValue(obj){ + if(obj != undefined){ + if(typeof obj == 'string'){ + return "'" + obj + "'"; + }else{ + return obj; + } + }else{ + return ""; + } +} diff --git a/dgbuilder/tools/output_js/.gitignore b/dgbuilder/tools/output_js/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/dgbuilder/tools/output_js/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/dgbuilder/tools/pom.xml_base b/dgbuilder/tools/pom.xml_base new file mode 100644 index 00000000..b54c27f6 --- /dev/null +++ b/dgbuilder/tools/pom.xml_base @@ -0,0 +1,79 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.onap.ccsdk.distribution</groupId> + <artifactId>distribution-root</artifactId> + <version>0.1.0-SNAPSHOT</version> + </parent> + <artifactId>yangApp-model</artifactId> + <packaging>bundle</packaging> + <version>1.0.0-SNAPSHOT</version> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <extensions>true</extensions> + <configuration> + <instructions> + <Import-Package>*</Import-Package> + </instructions> + </configuration> + </plugin> + <plugin> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>yang-maven-plugin</artifactId> + <version>${odl.yangtools.yang.maven.plugin.version}</version> + <dependencies> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>maven-sal-api-gen-plugin</artifactId> + <version>${odl.sal.api.gen.plugin.version}</version> + <type>jar</type> + </dependency> + </dependencies> + <executions> + <execution> + <goals> + <goal>generate-sources</goal> + </goals> + <configuration> + <yangFilesRootDir>${yang.file.directory}</yangFilesRootDir> + <codeGenerators> + <generator> + <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass> + <outputBaseDir>${salGeneratorPath}</outputBaseDir> + </generator> + </codeGenerators> + <inspectDependencies>true</inspectDependencies> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + <dependencies> + <dependency> + <groupId>org.opendaylight.mdsal</groupId> + <artifactId>yang-binding</artifactId> + <version>${odl.mdsal.yang.binding.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.yangtools</groupId> + <artifactId>yang-common</artifactId> + <version>${odl.yangtools.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.model</groupId> + <artifactId>ietf-inet-types</artifactId> + <version>${odl.ietf-inet-types.version}</version> + </dependency> + <dependency> + <groupId>org.opendaylight.mdsal.model</groupId> + <artifactId>ietf-yang-types</artifactId> + <version>${odl.ietf-yang-types.version}</version> + </dependency> + </dependencies> +</project> diff --git a/dgbuilder/tools/printYangProps.sh b/dgbuilder/tools/printYangProps.sh new file mode 100755 index 00000000..7d1d0faf --- /dev/null +++ b/dgbuilder/tools/printYangProps.sh @@ -0,0 +1,8 @@ +toolsDir=$PROJECT_HOME/tools +. ${toolsDir}/setClasspath +if [ "$#" != "1" ] +then + echo "Usage $0 className_without_the_dot_class_ext" + exit +fi + java PrintYangToProp $1 diff --git a/dgbuilder/tools/printYangToProp.jar b/dgbuilder/tools/printYangToProp.jar Binary files differnew file mode 100644 index 00000000..01b73107 --- /dev/null +++ b/dgbuilder/tools/printYangToProp.jar diff --git a/dgbuilder/tools/rs b/dgbuilder/tools/rs new file mode 100755 index 00000000..3d92b627 --- /dev/null +++ b/dgbuilder/tools/rs @@ -0,0 +1,2 @@ +#replaces / with a . +echo $1|sed -e s%/%.%g diff --git a/dgbuilder/tools/setClasspath b/dgbuilder/tools/setClasspath new file mode 100755 index 00000000..898ef350 --- /dev/null +++ b/dgbuilder/tools/setClasspath @@ -0,0 +1,13 @@ +toolsDir=${PROJECT_HOME}/tools +svcLogicLib=${PROJECT_HOME}/svclogic/lib + +export CLASSPATH= +for i in `find ${svcLogicLib} -name "*.jar" -print` +do +export CLASSPATH=$CLASSPATH:$i +done + +for i in `find ${toolsDir}/tmpws/jars -name "*.jar" -print` +do +export CLASSPATH=$CLASSPATH:$i +done diff --git a/dgbuilder/yangFiles/.gitignore b/dgbuilder/yangFiles/.gitignore new file mode 100644 index 00000000..d6b7ef32 --- /dev/null +++ b/dgbuilder/yangFiles/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore |