diff --git a/.gitignore b/.gitignore index 123ae94..aee1f9c 100644 --- a/.gitignore +++ b/.gitignore @@ -10,18 +10,24 @@ pids # Directory for instrumented libs generated by jscoverage/JSCover lib-cov -# Coverage directory used by tools like istanbul -coverage - # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) .grunt # node-waf configuration .lock-wscript +# idea editing tools +.idea + +# osx directory files +.DS_Store + +# ignore personal objects in the object folder. +# objects/* + # Compiled binary addons (http://nodejs.org/api/addons.html) build/Release # Dependency directory # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git -node_modules +node_modules \ No newline at end of file diff --git a/README.md b/README.md index 118a84f..085ca83 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,299 @@ -# object -Hybrid Object code +Overview +======== + +This page of notes outlines how to use a Mac OS X system to prepare an Arduino Yún linux image that turns +the Arduino into a HybridObject. + + +How to install on an Arduino Yún +================================ + +1. Plug the SD card into the Arduino Yún and power it on + +2. On your computer, connect to the Arduino's WiFi network, named similar to "Arduino Yun-XXXXXXXX." +Using a web browser, navigate to *http://arduino.local* and enter password *arduino* when prompted. + +3. Give the board a name and enter the WiFi settings for your network. + +4. Expand the Yún's available space by moving the root filesystem to the SD card. +See [How to expand the Yún disk space](https://www.arduino.cc/en/Tutorial/ExpandingYunDiskSpace). +When using a 4 GB SD card, choose 1000 MB for the size of the data partition. + +After expansion is complete: + +5. Upload any other sketch to remove the update sketch. + +6. On your Mac OS X computer install [osxfuse](https://osxfuse.github.io/). This provides `sshfs` +capability which we'll use later to conveniently mount a folder on the Yún to your computer. + +7. Connect to the Yún via: `ssh root@objectname.local` + + Example for getting to the right folder: + +```` + root@so1:~# cd .. + root@so1:/# cd mnt/sda1/ +```` + + +8. Update the software on the Yún and install the sftp server and node packages: + +```` + opkg update + opkg install openssh-sftp-server node node-socket.io node-socket.io-client node-serialport +```` + +9. Create a folder with the name "mountpoint" + +```` + mkdir ~/mountpoint +```` + +10. Mount the arduino's filesystem to your local mountpoint: + +```` + sshfs root@objectname.local:/mnt/sda1/arduino ~/mountpoint +```` + + (To unmount: `umount ~/mountpoint`) + +11. Work in the mounted folder and run your programms via the terminal. + +12. To allow logins over the serial port on the Hybrid Object, uncomment in `/etc/inittab`: + +```` + #ttyATH0::askfirst:/bin/ash --login +```` + +13. Setup a swap file as described below in section **SWAP**. + +14. copy the arduino code to the sda1 SD card. + +15. Install the dependences: + +```` + npm install +```` + + +reboot + + +Rename Host +=========== + +```` + uci set system.@system[0].hostname=obj + uci commit system +```` + + +Clone Yún to SD card +==================== + +```` + umount /overlay + dd if=/dev/mtd7ro of=/mnt/sda1/hybrid-squashfs-sysupgrade.bin +```` + +If you plan to disconnect power and remove the SD card, run these additional commands: + +```` + sync + halt +```` + + +Setup a TFTP server on your Mac +=============================== + +Start the TFTP service on your Mac: + +```` + sudo launchctl load -F /System/Library/LaunchDaemons/tftp.plist + sudo launchctl start com.apple.tftpd +```` + +Download the [Arduino Yún base images zip file from Arduino.cc](http://arduino.cc/download_handler.php?f=/openwrtyun/1/YunImage_v1.5.3.zip) +and extract the three files (uboot, kernel, rootfs) from the archive. + +Move the unpacked base images files into the `/private/tftpboot/` folder. + + +Reflashing U-Boot +----------------- + +```` + setenv serverip 192.168.1.1; + setenv ipaddr 192.168.1.146; + + tftp 0x80060000 openwrt-ar71xx-generic-linino-u-boot.bin; + erase 0x9f000000 +0x40000; + cp.b $fileaddr 0x9f000000 $filesize; + + tftp 0x80060000 openwrt-ar71xx-generic-yun-16M-kernel.bin; + erase 0x9fEa0000 +0x140000; + cp.b $fileaddr 0x9fea0000 $filesize; + + tftp 0x80060000 openwrt-ar71xx-generic-yun-16M-rootfs-squashfs.bin; + erase 0x9f050000 +0xE50000; + cp.b $fileaddr 0x9f050000 $filesize; + + bootm 0x9fea0000 +```` + +For more information refer to [Reflashing the OpenWrt-Yún image on the Yún](https://www.arduino.cc/en/Tutorial/YunUBootReflash). + + +Make node app run on startup +----------------------------- + +TODO: +Evaluate https://github.com/chovy/node-startup + + +SWAP +==== + +A swap file is a special kind of file that can be used as *virtual memory* by a computer's operating system. +This allows the computer's operating system to push infrequently used items from RAM to the hard disk +so that new items can use the newly freed space in the actual RAM. + +#### Verifying Free Memory + +Connect to Yún using ssh (i.e. by running "ssh root@youryun.local” from terminal). Then run `free -m`. +This shows your current memory memory usage in **m**egabytes, including free memory. For example: + +```` + total used free shared buffers +Mem: 61116 43556 17560 0 9612 +-/+ buffers: 33944 27172 +Swap: 0 0 0 +```` + +Note that the swap space shows **0**, indicating that there is no swap configured and available. +After confirming the lack of swap, you can setup a file to use for swap space. + +#### Step 1: Create an empty file to act as a swap file + +While connected to the Yún through the ssh terminal, run the following command to create a +512 MB swap file named yunswapfile in folder "/swap" filled with zeroes: + + dd if=/dev/zero of=/swap/yunswapfile bs=1M count=512 + +This should run for a bit and provide output like this: + +```` +512+0 records in +512+0 records out +```` + +#### Step 2: Designate the file as a swap file + +The step above just created an empty file. To make sure it can be used as a swap file, run this from the shell: + + mkswap /swap/yunswapfile + +You should get output like this: + +```` +Setting up swapspace version 1, size = 524284 KiB +no label, UUID=e3e63fad-e6f7-4d4e-a32a-a326bbe48e8c +```` + +#### Step 3: Load the swap file for verifying + +To verify that the swap file is good, try to load it by running this: + + swapon /swap/yunswapfile + +This will not provide any output if everything is cool. So verify by checking free memory. + + free -m + +This shows: + +```` + total used free shared buffers +Mem: 61116 28644 32472 0 4888 +-/+ buffers: 23756 37360 +Swap: 524284 0 524284 +```` + +Viola!!! Notice that swap space is now available for use by the RAM. We're not done yet, we must instruct +the system to use this file for swap on boot, as show in step 4. + +#### Step 4: Load the swap file as part of boot sequence + +If you stop with Step 3, next time when you restart your Yún (linux part... either through power off/on or +the Linux reset button near the LEDs) the swap file will not have been loaded. So to make sure that it gets +loaded every time, you need to set the swap file as part of boot sequence. + +**Warning:** The steps are fairly simple, but if the steps are not executed fully you might leave an inconsistent +boot config and the Linux part of the Yún may not load properly. Don't worry, since this is Arduino you can reset +the whole thing easily and try again. So please execute the following cleanly after understanding them. + +These commands are meant to be run as **root** on your Yún. Lines beginning with `#` are interpreted as comments +by the shell and are not interpreted, so they won't hurt anything if included via copy/paste: + +```` +#1. Add swap config entry to fstab +uci add fstab swap + +#2. Set device config entry to swap. Make sure you provide your full swap file name +uci set fstab.@swap[0].device=/swap/yunswapfile + +#3. Enable swap +uci set fstab.@swap[0].enabled=1 + +#4. Set file system type as "swap" +uci set fstab.@swap[0].fstype=swap + +#5. set swap options to default +uci set fstab.@swap[0].options=default + +#6. set fsck to 0 +uci set fstab.@swap[0].enabled_fsck=0 + +#7. Commit the config changes. If you don't run commit, the config changes will not be saved. +uci commit +```` + +That's it. Restart the Linux part of Yún (reset button near LEDs). After reboot, if you run +`free -m` you should see the swap file loaded. You have successfully expanded the RAM on your +Arduino Yún's Linux side. + + +How to install on a Raspberry Pi +================================ + +1. Use [NOOBS](https://www.raspberrypi.org/downloads/noobs/) to install the base Raspian image. + +2. Update the system software. + ```` + sudo apt-get update + sudo apt-get upgrade -y + ```` + +3. Remove the default nodejs instance and replace it with v0.12 or higher. + ```` + sudo apt-get remove nodejs + curl -sLS https://apt.adafruit.com/add | sudo bash + sudo apt-get install -y node + ```` + +4. Get the latest OpenHybrid Object code and download dependencies. + ```` + git clone https://github.com/openhybrid/object.git + cd object + npm install + ```` + +5. Run the OpenHybrid Object code. + ```` + node server.js + ```` + +A this point, you should be able to navigate to port 8080 on your device and find the Object dashboard. + + diff --git a/hardwareInterfaces/AdvertismentExample/index.js b/hardwareInterfaces/AdvertismentExample/index.js new file mode 100755 index 0000000..ac4ca71 --- /dev/null +++ b/hardwareInterfaces/AdvertismentExample/index.js @@ -0,0 +1,182 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * Modified by Carsten on 12/06/15. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * Set to true to enable the hardware interface + **/ +exports.enabled = false; + +if (exports.enabled) { + + var server = require(__dirname + '/../../libraries/hardwareInterfaces'); + + server.enableDeveloperUI(true); + + server.addNode("obj47", "light1", "node"); + server.addNode("obj47", "light2", "node"); + + server.addNode("obj47", "light3", "node"); + server.addNode("obj47", "switch", "node"); + + + server.addNode("obj45", "one", "node"); + server.addNode("obj45", "two", "node"); + + var _serialport = require("serialport"); + + const serialBaudRate = 9600; // baud rate for connection to arudino + const serialSource = "/dev/cu.usbmodem1411"; // this is pointing to the arduino + + //initialisation of the socket connection + var SerialP = _serialport.SerialPort; // localize object constructor + var serialPort = new SerialP(serialSource, { + parser: _serialport.parsers.readline("\r\n"), + baudrate: serialBaudRate + }, false); + + serialPort.on('error', function (err) { + console.error("Serial port error", err); + }); + + serialPort.open(); + serialPort.on("open", function () { + + serialPort.on('data', function (data) { + + if(data === "on"){ + server.write("obj47", "switch", 1, "f"); + } + else if(data === "off"){ + server.write("obj47", "switch", 0, "f"); + } + else if(data === "2") { + server.advertiseConnection("obj47","light1"); + console.log("advertise light1"); + } + else if(data === "1") { + server.advertiseConnection("obj47","light2"); + console.log("advertise light2"); + } + else if(data === "0") { + server.advertiseConnection("obj47","light3"); + console.log("advertise light3"); + } + else if(data === "3") { + server.advertiseConnection("obj47", "switch"); + console.log("advertise switch"); + } + + + console.log("this: "+data); + + }); + }); + + +/* + setInterval(function () { + + serialPort.write("0\n"); + setTimeout(function() { + serialPort.write("1\n"); + }, 1000); + + + }, 3000); +*/ + + + + server.addReadListener("obj47", "light1", function (data) { + if(data.value >0){ + serialPort.write("1\n"); + } else { + serialPort.write("0\n"); + } + }); + server.addReadListener("obj47", "light2", function (data) { + if(data.value >0){ + serialPort.write("3\n"); + } else { + serialPort.write("2\n"); + } + }); + server.addReadListener("obj47", "light3", function (data) { + if(data.value >0){ + serialPort.write("5\n"); + } else { + serialPort.write("4\n"); + } + }); + + + + server.addEventListener("reset", function () { + + }); + + server.addEventListener("shutdown", function () { + + }); + + setInterval(function () { + + server.write("obj45", "one", Math.random(), "f"); + + }, 300); + + /* + setInterval(function () { + + server.advertiseConnection("obj45","one"); + + setTimeout(function() { + server.advertiseConnection("obj47", "hans"); + }, 4000); + + }, 8000);*/ + +} diff --git a/hardwareInterfaces/EV3/index.js b/hardwareInterfaces/EV3/index.js new file mode 100755 index 0000000..157a5b4 --- /dev/null +++ b/hardwareInterfaces/EV3/index.js @@ -0,0 +1,643 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * Modified by Carsten on 12/06/15. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * Set to true to enable the hardware interface + **/ +exports.enabled = false; + +if (exports.enabled) { + + + var speed =0; // global variable for the speed of the robot. + var server = require(__dirname + '/../../libraries/hardwareInterfaces'); + server.enableDeveloperUI(true); + var stop_command_tilt = false; + var stop_command_grip=false; + + + + var Ev3 = require ("./module/Ev3.js"); + var Ev3_base = Ev3.base; + + var bot_brick = new Ev3_base("/dev/tty.WhiteLOW-SerialPort"); + var top_brick = new Ev3_base("/dev/tty.EV3-SerialPort"); // put your bluetooth socket. + var motor_output_top = {"a": 0, "b":0,"c":0, "d":0}; + var motor_output_bot = {"a": 0, "b":0,"c":0, "d":0}; + var top_ready = false; // boolean to check if top EV3 Brick has been connected to the computer + var bot_ready = false; // boolean to check if bot EV3 Brick has been connected to the computer + var bot_target = undefined; // bot and top targets are the brick objects used to control the robot arm + var top_target = undefined; + /* ----------------------------------------------------------------------------------------------------------------- */ + //all global variables used for calibrating top brick + var prev_f_twist = 100; // default to white (not moving) + var f_twist= 100; // default to white (not moving) + var u_tilt = ""; // default to white (not moving) + var tilt_calibrated = false; // boolean check for if grip rotation and tilt have been calibrated + var grip_calibrated = false; // boolean check for if grip rotation and tilt have been calibrated + var forearm_touch_sensor = false; + var first_pass = true; + /* ----------------------------------------------------------------------------------------------------------------- */ + // all global variables used for calibrating bottom brick + var shoulder_calibrated = false; + var base_color = ""; + var shoulder_color = ""; + /* ----------------------------------------------------------------------------------------------------------------- */ + // below are completion checks for every element of calibration + var grip_ready = true; + var shoulder_ready = true; + var forearm_twist_ready = true; + var upper_tilt_ready = true; + /* ----------------------------------------------------------------------------------------------------------------- */ + // below are boolean checks for boundry movement using reality editor + var shoulder_forwards = true; + var shoulder_backwards = true; + var arm_upwards = true; + var arm_downwards = true; + var arm_twist_cw = true; // arm twist in clockwise directoin + var arm_twist_ccw = true; // arm twist in counter clock wise direciton + /* ----------------------------------------------------------------------------------------------------------------- */ + // below are the rotation angles set by the user for the robot to calibrate with + + var base_angle_correction = 0; // used by all interfaces to set the base angle of rotation. + var shoulder_angle_correction = Math.PI/2; // used for right and left base interfaces to control shoulder rotation angle. + var upper_tilt_angle_correction =0; // used by top upper tilt interface to control upper tilt angle + var shoulder_stop_point =400; // the interface is 800 pixels wide, the halfway point is 400. Used for right and left shoulder interfaces. + var grip_stop_point =300; // the interface is 600 pixels long, the halfway point is 300. Used for gripper interface. + + var forearm_angle_correction = 0; + var grip_angle_correction = 0; + + var forearm_starting_height = 0; + var gripper_open = true; + var grabbing = false; + /* ----------------------------------------------------------------------------------------------------------------- */ + // below are booleans used for markers that have both touch movement and movement based off of the phones rotation. Both should not be possible at once, or oscilations happen. + var shoulder_tilting = false; + var forearm_tilting = false; + + var joint_grip_active = false; + var grip_tilting = false; + var forearm_locked = false; // used by Gripper + /* ----------------------------------------------------------------------------------------------------------------- */ + // below are booleans used for certain stops which require kicking the motor in the opposite direction + var forearm_stopping = false; + var shoulder_stopping = false; + + var test = 0; + var grip_val = 0; + + bot_brick.connect(function(){ // this function connects the bottom brick to the computer via bluetooth. It initializes all the sensors as well. + bot_brick.start_program(function(target){ + bot_ready=true; + bot_target=target; + target.registerSensor(2, target.S_TYPE_COLOR, target.SM_COL_RINTENSITY); + target.registerSensorListener(2, function (result) { + base_color = result; + }); + target.registerSensor(1, target.S_TYPE_COLOR, target.SM_COL_COLOR); + target.registerSensorListener(1, function (result) { // registers sensor in the base which looks up at the main arm + // in this callback which is performed on every reading the sensor checks if it is at one of the boundaries and if it is sets a boolean representing movement in that direction to be false + shoulder_color = result; + if(result == Ev3.COL_RED) + shoulder_forwards=false; + else if(result == Ev3.COL_BLACK) + shoulder_backwards=false; + else{ + shoulder_forwards=true; + shoulder_backwards=true; + } + + }); + target.registerSensor(3,target.S_TYPE_TOUCH,0); + target.registerSensorListener(3,function(result){ // the red button to reset the system and cause calibration to begin + if(result){ + grip_ready=false; + shoulder_ready=false; + forearm_twist_ready=false; + upper_tilt_ready=false; + tilt_calibrated=false; + first_pass=true; + grip_calibrated=false; + shoulder_calibrated=false; + motor_output_top = {"a": 0, "b":0,"c":0, "d":0}; + motor_output_bot = {"a": 0, "b":0,"c":0, "d":0}; + } + }); + + }) + }); + // + top_brick.connect(function(){ // connects top brick to ev3 + top_brick.start_program(function(target){ + top_ready=true; + top_target = target; // target is what is used to send commands to the robot + target.registerSensor(1,target.S_TYPE_TOUCH,0); + target.registerSensorListener(1,function(result){ + forearm_touch_sensor = result; + }); + + target.registerSensor(3, target.S_TYPE_COLOR, target.SM_COL_COLOR); + target.registerSensorListener(3, function (result) { + //console.log("Result has value:" + result + "and prev value was " + f_twist_res); + prev_f_twist = f_twist; + f_twist = result; + if(result == Ev3.COL_RED){ + arm_twist_ccw=false; + } + else if(result == Ev3.COL_BROWN){ + arm_twist_cw=false; + } + else{ + arm_twist_cw=true; + arm_twist_ccw=true; + } + }); + target.registerSensor(2, target.S_TYPE_COLOR, target.SM_COL_COLOR); + target.registerSensorListener(2, function (result) { + u_tilt = result; + if(result == Ev3.COL_NULL || result==Ev3.COL_BLACK || result==Ev3.COL_BROWN || result == Ev3.COL_GREEN){ + arm_downwards=false; + //stopForearm(); + } + else if(result == Ev3.COL_WHITE) + arm_upwards=false; + else{ + arm_upwards=true; + arm_downwards=true; + } + //console.log(result); + }); + }) + }); + + var main_loop = setInterval(function(){ // main loop of the entire system. Runs 10 times/second. First checks if bot/top are connected, then pulls readings from them, and then check if the robot needs to be calibrated. If all aspects of the robot arm are ready, then it takes whatever is stored in the database for motor speeds and sets it to the robot arm. + if(bot_ready && top_ready){ + bot_target.pullReadings(); + top_target.pullReadings(); + if(shoulder_ready && upper_tilt_ready && forearm_twist_ready && grip_ready){ + var top_output = top_target.getOutputSequence(motor_output_top["a"], motor_output_top["b"], motor_output_top["c"], motor_output_top["d"]); + if (top_output) { + top_target.sp.write(top_output, function (err, len) { + if (err) { + + console.log(motor_output_top); + console.log(top_output); + console.log(JSON.stringify([].slice.call(arguments))); + } + }); + } + + var bot_output = bot_target.getOutputSequence(motor_output_bot["a"], motor_output_bot["b"], motor_output_bot["c"], motor_output_bot["d"]); + if (bot_output) { + bot_target.sp.write(bot_output, function (err, len) { + if (err) { + console.log(motor_output_bot); + console.log(bot_output); + console.log(JSON.stringify([].slice.call(arguments))); + } + }); + } + } + else { // means that the robot needs to be calibrated and calibration routine begins. + if (!first_pass) { + resetForearmTwist(f_twist); + } + else { + motor_output_top['d'] = 5; + first_pass = false; + } + if (!tilt_calibrated) + tilt_calibrated = resetUpperTilt(u_tilt); + if (!grip_calibrated) + grip_calibrated = resetGrip(forearm_touch_sensor); + else{ + // console.log("The motor speed is: " + motor_output_top['b']); + } + if (!shoulder_calibrated) + shoulder_calibrated = resetShoulder(shoulder_color); + // console.log("Im writing a command with values" + motor_output_top["a"], motor_output_top["b"], motor_output_top["c"], motor_output_top["d"]); + var top_output = top_target.getOutputSequence(motor_output_top["a"], motor_output_top["b"], motor_output_top["c"], motor_output_top["d"]); + top_target.sp.write(top_output, function () {}); + var bot_output = bot_target.getOutputSequence(motor_output_bot["a"], motor_output_bot["b"], motor_output_bot["c"], motor_output_bot["d"]); + bot_target.sp.write(bot_output, function () {}); + } + + } + },100); + + + + function map(x, in_min, in_max, out_min,out_max) { + if (x > in_max) x = in_max; + if (x < in_min) x = in_min; + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; + } + function stopForearm(){ // function to kick back the motor in the opposite directino to stop arm moving from inertia + if(motor_output_top['a'] >5){ + if(motor_output_top['a']>40) + motor_output_top['a']=-20; + else if(motor_output_top['a']>15) + motor_output_top['a']=-5; + else + motor_output_top['a']=-3; + setTimeout(function(){ + motor_output_top['a']=0; + forearm_stopping=false; + },100); + } + else{ + motor_output_top['a']=0; + forearm_stopping=false; + } + motor_output_top['d']=0; + } + + function stopShoulder(){ //function to kick back the motor in the opposite directino to stop arm moving from inertia + if(Math.abs(motor_output_bot.c) >15){ + if(motor_output_bot.c>40){ + motor_output_bot.c=-20; + motor_output_bot.b=-20; + } + else if(motor_output_bot.c>15){ + motor_output_bot.c=-5; + motor_output_bot.b=-5; + } + else if(motor_output_bot.b<-40){ + motor_output_bot.c=20; + motor_output_bot.b=20; + } + else{ + motor_output_bot.c=5; + motor_output_bot.b=5; + } + setTimeout(function(){ + motor_output_bot.b=0; + motor_output_bot.c=0; + shoulder_stopping=false; + },100); + } + else{ + motor_output_bot.b=0; + motor_output_bot.c=0; + shoulder_stopping=false; + } + } + + + + function resetForearmTwist(value){ // used by calibration + if(value == Ev3.COL_BLACK) { // sees black and at middle point + motor_output_top['d'] = 0; + forearm_twist_ready=true; // forearm will be fully calibrated and rotate perfectly to be middle. + } + else if(value == Ev3.COL_BROWN) + motor_output_top['d']= 10; + else if(value == Ev3.COL_RED) + motor_output_top['d']= -8; + } + + function resetUpperTilt(value){ // used by calibration + if(value != Ev3.COL_WHITE){ + motor_output_top['a'] = -35; + return false; + } + else{ + motor_output_top['a']=35; + setTimeout(function(){ + motor_output_top['a']=0; + upper_tilt_ready=true; + },2550); + return true; // shoulder will be perfectly vertical and fully calibrated + } + } + + function resetGrip(value){// used by calibration + if(!value){ + motor_output_top['c'] = 13; + return false; + } + else{ + motor_output_top['c'] = -30; + motor_output_bot.d=-10; + //motor_output_top['b'] = -30; + // console.log("he's going up sir"); + setTimeout(function(){ + motor_output_top['c'] = 0; + motor_output_top['b'] = 0; + motor_output_bot.d=0; + gripper_open=true; + grip_ready=true; + // console.log("command has been sent"); + },2800); + return true; // grip has hit the touch sensor and is fully calibrated + } + } + + function resetShoulder(value){// used by calibration + if(value != Ev3.COL_RED){ + motor_output_bot['c'] = -12; + motor_output_bot['b'] = -12; + return false; + } + else{ + motor_output_bot['c'] = 30; + motor_output_bot['b'] = 30; + setTimeout(function(){ + motor_output_bot['c'] = 0; + motor_output_bot['b'] = 0; + shoulder_ready=true; + },2000); + return true; // shoulder will be perfectly vertical and fully calibrated + } + } + + function resetBase(value){ // used by calibration + if(value >= 98){ + motor_output_bot['a']= 0; + } + else + motor_output_bot['a']= 20; + } + + + + + + + server.addNode("Gripper6AxisEV3", "Vertical Touch", "default"); + server.addNode("Gripper6AxisEV3", "Horizontal Touch", "default"); + server.addNode("Gripper6AxisEV3", "pitch", "default"); + server.addNode("Gripper6AxisEV3", "Height Tracking", "default"); + server.addNode("Gripper6AxisEV3", "roll", "default"); + server.addNode("Gripper6AxisEV3", "Upper Tilt + Top Joint", "default"); + server.addNode("Gripper6AxisEV3", "Grip Rotation", "default"); + server.addNode("Gripper6AxisEV3", "Grip Tilt", "default"); + server.addNode("Gripper6AxisEV3", "grab", "default"); + server.addNode("Gripper6AxisEV3", "kickback joint tilt", "default"); + + server.addNode("TopForearm6AxisEV3", "Vertical Touch_ft", "default"); + server.addNode("TopForearm6AxisEV3", "Horizontal Touch_ft", "default"); + server.addNode("TopForearm6AxisEV3", "pitch_ft", "default"); + server.addNode("TopForearm6AxisEV3", "Height Tracking_ft", "default"); + server.addNode("TopForearm6AxisEV3", "Forearm Rotation", "default"); + + server.addNode("TopUpperTilt6AxisEV3", "yaw_ut", "default"); + server.addNode("TopUpperTilt6AxisEV3", "Vertical Touch_ut", "default"); + server.addNode("TopUpperTilt6AxisEV3", "roll_ut", "default"); + + server.addNode("RightUpperTilt6AxisEV3", "yaw_ur", "default"); + server.addNode("RightUpperTilt6AxisEV3", "Horizontal Touch_ur", "default"); + server.addNode("RightUpperTilt6AxisEV3", "pitch_ur", "default"); + server.addNode("RightUpperTilt6AxisEV3", "Upper Tilt", "default"); + server.addNode("RightUpperTilt6AxisEV3", "Arm + Shoulder", "default"); + server.addNode("RightUpperTilt6AxisEV3", "kickback arm", "default"); + server.addNode("RightUpperTilt6AxisEV3", "kickback arm + shoulder", "default"); + + server.addNode("RightShoulder6AxisEV3", "Horizontal Touch_sr", "default"); + server.addNode("RightShoulder6AxisEV3", "pitch_sr", "default"); + + server.addNode("RightBase6AxisEV3", "pitch_br", "default"); + server.addNode("RightBase6AxisEV3", "yaw_br", "default"); + server.addNode("RightBase6AxisEV3", "kickback_br", "default"); + server.addNode("RightBase6AxisEV3", "Base Rotation", "default"); + server.addNode("RightBase6AxisEV3", "Base Joint", "default"); + /** + * ******************************* + */ + + server.addReadListener("RightUpperTilt6AxisEV3", "Upper Tilt", function (item) { + if(bot_ready && top_ready) { + if (shoulder_ready && upper_tilt_ready && forearm_twist_ready && grip_ready) { // makes sure that calibration is not running + var value = Math.floor(map(item.number,0,1,-100,100)); + + // code + forearm_tilting=true; + speed = value; + test = value; + + } + } + }); + + + server.addReadListener("Gripper6AxisEV3", "Upper Tilt + Top Joint", function (item) { + if(bot_ready && top_ready) { + if (shoulder_ready && upper_tilt_ready && forearm_twist_ready && grip_ready) { // makes sure that calibration is not running + var value = Math.floor(map(item.number,0,1,-100,100)); + + // code + speed = value; + if(!arm_downwards && speed >0 && !forearm_stopping){ + forearm_stopping=true; + stopForearm(); + speed =0; + } + else { + speed = value; + if (!arm_downwards && speed > 0 && !forearm_stopping) { + forearm_stopping = true; + stopForearm(); + } + else if (!arm_upwards && speed < 0 && !forearm_stopping) { + forearm_stopping = true; + stopForearm(); + } + else { + motor_output_top['a'] = speed; + } + // console.log("gripval: " + grip_val); + speed = Math.floor(grip_val); + motor_output_top['c'] = speed; + } + + } + } + }); + server.addReadListener("Gripper6AxisEV3", "Grip Rotation", function (item) { + if(bot_ready && top_ready) { + if (shoulder_ready && upper_tilt_ready && forearm_twist_ready && grip_ready) { // makes sure that calibration is not running + var value = Math.floor(map(item.number,0,1,-100,100)); + + // code + speed = value; + motor_output_top.b = speed; + + } + } + }); + server.addReadListener("Gripper6AxisEV3", "Grip Tilt", function (item) { + if(bot_ready && top_ready) { + if (shoulder_ready && upper_tilt_ready && forearm_twist_ready && grip_ready) { // makes sure that calibration is not running + var value = Math.floor(map(item.number,0,1,-100,100)); + + // code + grip_val=value; + + } + } + }); + server.addReadListener("Gripper6AxisEV3", "grab", function (item) { + if(bot_ready && top_ready) { + if (shoulder_ready && upper_tilt_ready && forearm_twist_ready && grip_ready) { // makes sure that calibration is not running + var value = Math.floor(map(item.number,0,1,-100,100)); + + // code + if(!grabbing){ + grabbing=true; + if(gripper_open){ + motor_output_bot.d=15; + gripper_open=false; + } + else{ + motor_output_bot.d=-15; + gripper_open=true; + } + setTimeout(function(){ + motor_output_bot.d=0; + grabbing=false; + },1500); + } + + } + } + }); + server.addReadListener("TopForearm6AxisEV3", "Forearm Rotation", function (item) { + if(bot_ready && top_ready) { + if (shoulder_ready && upper_tilt_ready && forearm_twist_ready && grip_ready) { // makes sure that calibration is not running + var value = Math.floor(map(item.number,0,1,-100,100)); + + // code + speed = value; + if(speed < 0 && !arm_twist_cw){ + motor_output_top['d']=0; + } + if(speed > 0 && !arm_twist_ccw){ + motor_output_top['d']=0; + } + motor_output_top.d = speed; + + } + } + }); + server.addReadListener("RightUpperTilt6AxisEV3","Arm + Shoulder" , function (item) { + if(bot_ready && top_ready) { + if (shoulder_ready && upper_tilt_ready && forearm_twist_ready && grip_ready) { // makes sure that calibration is not running + var value = Math.floor(map(item.number,0,1,-100,100)); + + // code + speed = -value; + shoulder_tilting = true; + if (!shoulder_forwards && speed < 0) + speed = 0; + else if (!shoulder_backwards && speed > 0) + speed = 0; + motor_output_bot.b = speed; + motor_output_bot.c = speed; + speed = Math.floor(-5 / 7 * value + test); + if (!arm_downwards && speed > 0 && !forearm_stopping) { + forearm_stopping = true; + stopForearm(); + speed = 0; + } + else if (!arm_upwards && speed < 0 && !forearm_stopping) { + forearm_stopping = true; + stopForearm(); + speed = 0; + } + else + motor_output_top.a = speed; + + } + } + }); + server.addReadListener("RightBase6AxisEV3","Base Rotation" , function (item) { + if(bot_ready && top_ready) { + if (shoulder_ready && upper_tilt_ready && forearm_twist_ready && grip_ready) { // makes sure that calibration is not running + var value = Math.floor(map(item.number,0,1,-100,100)); + + // code + speed = value; + motor_output_bot.a = value; + + } + } + }); + server.addReadListener("RightBase6AxisEV3","Base Joint" , function (item) { + if(bot_ready && top_ready) { + if (shoulder_ready && upper_tilt_ready && forearm_twist_ready && grip_ready) { // makes sure that calibration is not running + var value = Math.floor(map(item.number,0,1,-100,100)); + + // code + //console.log("base joint " + value); + speed = value; + + if(!shoulder_forwards && speed <0) + speed=0; + else if(!shoulder_backwards && speed >0) + speed =0; + // console.log("I recieved a value of " + value + " and speed: " + speed + " and i should go down " + shoulder_forwards); + motor_output_bot['b'] = speed; + motor_output_bot['c'] = speed; + + } + } + }); + + server.addEventListener("reset", function () { + + }); + + server.addEventListener("shutdown", function () { + console.log("shutting down from exports.shutdown!"); + if(top_target!==undefined) + top_target.disconnect(); + if(bot_target!==undefined) + bot_target.disconnect(); + return; + }); + server.enableDeveloperUI(true); +} diff --git a/hardwareInterfaces/EV3/module/Ev3.js b/hardwareInterfaces/EV3/module/Ev3.js new file mode 100644 index 0000000..0ca467c --- /dev/null +++ b/hardwareInterfaces/EV3/module/Ev3.js @@ -0,0 +1,306 @@ +var SP = require("serialport"); +var SerialPort = SP.SerialPort; +var util = require('util'); + +var Sensor = function(port,type,mode){ + var port = port; + var type = type; + this.mode = mode; + this.callbacks = []; + var pull_command = null; + this.request_counter = -1; + + this.pushCallback = function(callback){ + this.callbacks.push(callback); + }; + + this.pullReading = function(counter,sp){ + this.request_counter = counter; + //construct buffer + pull_command = new Buffer("0B00"+counter+"0001009A000"+ (port-1) + type +"0"+ mode +"60","hex"); + //console.log(pull_command.toString("hex")); + sp.write(pull_command); + } + +} + + + +Sensor.prototype.processData = function(counter){ + if(counter != this.request_counter){ + return + } +} + + +//inherited sensors +var ColorSensor = function(port,type,mode){ + //paratistic inheritance + //http://www.crockford.com/javascript/inheritance.html + var sensor = new Sensor(port,type,mode); + sensor.processData =function(counter,value){ + if(counter != this.request_counter){ + return + } + var payload = value.substr(10,2); + + //if mode is light intensity, change the result to numeric value + if(this.mode == 0 || this.mode ==1 ){ + payload = parseInt(payload,16); + } + + for(var i=0; i < this.callbacks.length ; i++){ + this.callbacks[i](payload); + } + } + + return sensor; +} + +var TouchSensor = function(port,type,mode){ + //paratistic inheritance + //http://www.crockford.com/javascript/inheritance.html + var sensor = new Sensor(port,type,mode); + sensor.processData = function(counter,value){ + if(counter != this.request_counter){ + return + } + + var payload = value.substr(10,2); + var result = false; + if(payload == "00") { result = false; } else if(payload == "64") { result=true; } + for(var i=0; i < this.callbacks.length ; i++){ + this.callbacks[i](result); + } + } + + return sensor; +} + +module.exports.COL_NULL = "00"; +module.exports.COL_BLACK = "0c"; +module.exports.COL_BLUE = "19"; +module.exports.COL_GREEN = "25"; +module.exports.COL_YELLOW = "32"; +module.exports.COL_RED = "3e"; +module.exports.COL_WHITE = "4b"; +module.exports.COL_BROWN = "57"; + +//---------------base class----------------- +var Ev3_base = function(btport){ + + //All sequence read from reverse engineering + this.INIT_SEQ =new Buffer([0x07,0x00,0x00,0x00,0x80,0x00,0x00,0x02,0x01]); + this.INIT_DOWNLOAD_SEQ = new Buffer("2500010001920F0100002F6D6E742F72616D6469736B2F70726A732F6D6F62696C652E72626600", "hex"); + + + this.PROGRAM_SEQ = new Buffer("B10002000193004C45474FAC0000006500020002000000280000000000000008000000AB0000000000000000000000841200841300820000820000841C01820000820000842E2E2F617070732F427269636B2050726F6772616D2F4F6E427269636B496D6167653132008400821B08300060858332000000403482020046646046821300348202004768604782080031604430006005444161820B00A5000161A6000140820400A300010086404082C1FF0A0A", "hex"); + this.STOP_DOWNLOAD_SEQ = new Buffer("0600030001980000", "hex"); + + //single motor + //this.RUN_PROGRAM_SEQ = new Buffer("2D000400800020C00801842F6D6E742F72616D6469736B2F70726A732F6D6F62696C652E7262660040440301404440", "hex" ); + //this.PROGRAM_SEQ = new Buffer("B10002000193004C45474FAC0000006500020002000000280000000000000008000000AB0000000000000000000000841200841300820000820000841C01820000820000842E2E2F617070732F427269636B2050726F6772616D2F4F6E427269636B496D6167653132008400821B08300060858332000000403482020046646046821300348202004768604782080031604430006005444161820B00A5000161A6000140820400A300010086404082C1FF0A0A", "hex"); + + //multi - motor + //this.RUN_PROGRAM_SEQ = new Buffer("2D000400800020C00801842F6D6E742F72616D6469736B2F70726A732F6D6F62696C652E7262660040440301404440", "hex" ); + //this.PROGRAM_SEQ = new Buffer("140102000193004C45474F0F01000065000500050000004C00000000000000080000000B01000000000000000000000C01000000000000000000000D01000000000000000000000E0100000000000000000000841200841300820000820000841C01820000820000842E2E2F617070732F427269636B2050726F6772616D2F4F6E427269636B496D6167653132008400821B08300060858332000000403482020046646046821300348205004768604782080031604430006005444161820B00A5000161A6000140820400A30001004162820B00A5000262A6000240820400A30002004163820B00A5000463A6000440820400A30004004164820B00A5000864A6000840820400A30008008640408285FF0A0A0A0A0A", "hex"); + + //multi - motor - single touch sensor + this.RUN_PROGRAM_SEQ = new Buffer("2D000400800020C00801842F6D6E742F72616D6469736B2F70726A732F6D6F62696C652E7262660040440301404440", "hex" ); + this.PROGRAM_SEQ = new Buffer("140102000193004C45474F0F01000065000500050000004C00000000000000080000000B01000000000000000000000C01000000000000000000000D01000000000000000000000E0100000000000000000000841200841300820000820000841C01820000820000842E2E2F617070732F427269636B2050726F6772616D2F4F6E427269636B496D6167653132008400821B08300060858332000000403482020046646046821300348205004768604782080031604430006005444161820B00A5000161A6000140820400A30001004162820B00A5000262A6000240820400A30002004163820B00A5000463A6000440820400A30004004164820B00A5000864A6000840820400A30008008640408285FF0A0A0A0A0A", "hex"); + + this.sensors = []; + + this.OUTPUT_HEADER_SEQ = "000004"; + this.OUTPUT_DELIMITER_SEQ = "30"; + this.OUTPUT_BODY_SEQ = "407E018200008"; + this.TERMINATE_SEQ = new Buffer("070055008000000201","hex"); + + this.sp = new SerialPort(btport, { + parser: SP.parsers.raw + }, false); + + this.getOutputSequence = function(a,b,c,d){ + //modify header + var header = this.OUTPUT_HEADER_SEQ; + + var body_a = ""; + if(a !== null) body_a = this.OUTPUT_DELIMITER_SEQ + this.getHexOutput(a) + this.OUTPUT_BODY_SEQ + "301000000830100000040"; + + var body_b = ""; + if(b !== null) body_b = this.OUTPUT_DELIMITER_SEQ + this.getHexOutput(b) + this.OUTPUT_BODY_SEQ + "302000000830200000040"; + + var body_c = ""; + if(c !== null) body_c = this.OUTPUT_DELIMITER_SEQ + this.getHexOutput(c) + this.OUTPUT_BODY_SEQ + "303000000830300000040"; + + var body_d = ""; + if(d !== null) body_d = this.OUTPUT_DELIMITER_SEQ + this.getHexOutput(d) + this.OUTPUT_BODY_SEQ + "304000000830400000040"; + + //get counter + // console.log(this.getCounter()); + var size = ((this.getCounter()+header+body_a+body_b+body_c+body_d).length/2).toString(16); //check this + var prefix = size + "00" + this.getCounter() + header ; + var body = prefix + body_a + body_b + body_c + body_d; + try { + return new Buffer( body.toUpperCase(), "hex"); + } catch(e) { + console.log(body.toUpperCase()); + debugger; + } + }; + var counter = 0; + this.getCounter = function(){ + var cstring = counter.toString(16); + if(cstring.length == 1){ + cstring = "000"+ cstring ; + //console.log(cstring); + } else if (cstring.length == 2){ + cstring = "00" + cstring; + } else if (cstring.length == 3){ + cstring = "0" + cstring; + } + counter++; + if (counter > 0xffff) { + console.log('fixed everything Kappa'); + counter = 0; + } + return cstring; + } + + this.getHexOutput = function(output){ + var res = ""; + if(output < 0 && output >= -32) { + output = 256 + output; + res = output.toString(16); + + } + else if ( output < -32 ){ + output = 256 + output; + res = output.toString(16); + res = "81" + res; + } + + if (output >= 0 && output < 32) { + res = output.toString(16); + } + else if ( output >= 32 ) { + res = output.toString(16); + res = "81" + res; + } + + //one digit + if (res.length == 1){ + res = "0" +res; + } + + return res; + } + + this.loadProgram = function(callback){ + var connection = this.sp; + var main = this; + connection.write(main.INIT_DOWNLOAD_SEQ,function(){ + connection.write(main.PROGRAM_SEQ,function(){ + connection.write(main.STOP_DOWNLOAD_SEQ,function(){ + if(callback != null) callback(); + //setupSensor(); + }); + }); + }); + }; +}; + +//-------------- Sensor --------------------- +Ev3_base.prototype.S_TYPE_IR = 0; +Ev3_base.prototype.S_TYPE_TOUCH = "10"; +Ev3_base.prototype.S_TYPE_COLOR = "1d"; +Ev3_base.prototype.S_TYPE_USONIC = 0; +Ev3_base.prototype.S_TYPE_GYRO = 0; + + +//color sensor modes +Ev3_base.prototype.SM_COL_RINTENSITY = 0; +Ev3_base.prototype.SM_COL_AINTENSITY = 1; +Ev3_base.prototype.SM_COL_COLOR = 2; + +Ev3_base.prototype.sensorResponse = function(counter,value){ + for (var i =0 ; i4 || port<1) {return; }//should return error + if(type == this.S_TYPE_COLOR){ + this.sensors[port-1] = new ColorSensor(port,type,mode); + } + + if(type == this.S_TYPE_TOUCH){ + this.sensors[port-1] = new TouchSensor(port,type,mode); + } +} + +Ev3_base.prototype.registerSensorListener = function(port,callback){ + this.sensors[port-1].pushCallback(callback); +} + +Ev3_base.prototype.pullReadings = function(){ + //console.log("There are this many sensors: " + this.sensors.length); + for (var i =0 ; i (http://wenchaojames.wordpress.com/)", + "license": "MIT", + "bugs": { + "url": "https://github.com/wenchaojiang/Ev3NodeJsBtAPI/issues" + } +} diff --git a/hardwareInterfaces/arduinoUno/index.js b/hardwareInterfaces/arduinoUno/index.js new file mode 100644 index 0000000..1506b0c --- /dev/null +++ b/hardwareInterfaces/arduinoUno/index.js @@ -0,0 +1,268 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +exports.enabled = false; + +if (exports.enabled) { + var _ = require('lodash'); + var serialport = require("serialport"); + var server = require(__dirname + '/../../libraries/hardwareInterfaces'); + + + const serialBaudRate = 115200; // baud rate for connection to arudino + + // change this to what ever is your Arudino Serial Port + + const serialSource = "/dev/cu.usbmodem1411"; // this is pointing to the arduino + + function ArduinoIndex() { + this.objName = null; + this.ioName = null; + this.index = null; + } + + var ArduinoLookup = {}; + var ArduinoLookupByIndex = {}; + var FullLookup = {}; + var serialPortOpen = false; + + //initialisation of the socket connection + var SerialP = serialport.SerialPort; // localize object constructor + var serialPort = new SerialP(serialSource, { + parser: serialport.parsers.readline("\n"), + baudrate: serialBaudRate + }, false); + + serialPort.on('error', function (err) { + console.error("Serial port error", err); + }); + + serialServer(serialPort); + + function serialServer(serialPort) { + if (server.getDebug()) console.log("opneserial"); + serialPort.open(); + serialPort.on("open", function () { + + if (server.getDebug()) console.log('Serial port opened'); + serialPortOpen = true; + var dataSwitch = 0; + var pos = null; + var objID = null; + var obj = null; + var object = null; + var arrayID = null; + var valueMode = ""; + var value = null; + var thisName = ""; + var thisPlugin = "default"; + var amount = 0; + //var okCounter = 0; + + serialPort.on('data', function (data) { + // console.log(data); + switch (dataSwitch) { + case 0: + if (data === "f") { + //if (server.getClear()) { + valueMode = "f"; + dataSwitch = 1; + //} + } + else if (data === "d") { + //if (server.getClear()) { + valueMode = "d"; + dataSwitch = 1; + //} + } + else if (data === "p") { // positive step value + //if (server.getClear()) { + valueMode = "p"; + dataSwitch = 1; + //} + } + else if (data === "n") {// negative step value + //if (server.getClear()) { + valueMode = "n"; + dataSwitch = 1; + //} + } + else if (data === "a") { + dataSwitch = 20; + } + else if (data === "okbird") { + + serialPort.write(" \n"); + serialPort.write("okbird\n"); + if (server.getDebug()) console.log("ok as respond"); + dataSwitch = 0; + } + else if (data === "def") { + if (server.getDebug()) console.log("developer"); + dataSwitch = 40; + } + else if (data === "c") { + if (server.getDebug()) console.log("clear"); + dataSwitch = 50; + + } + break; + case 1: + arrayID = parseInt(data, 10); + dataSwitch = 2; + break; + case 2: + value = parseFloat(data); + + if (ArduinoLookupByIndex.hasOwnProperty(arrayID)) + server.write(ArduinoLookupByIndex[arrayID].objName, ArduinoLookupByIndex[arrayID].ioName, value, valueMode); + + + dataSwitch = 0; + break; + case 20: + object = data.split("\t"); + dataSwitch = 21; + break; + case 21: + arrayID = parseInt(data, 10); + dataSwitch = 23; + break; + case 23: + thisPlugin = data; + obj = object[1]; + pos = object[0]; + + if (server.getDebug()) console.log("Add Arduino Yun"); + + ArduinoLookup[obj + pos] = new ArduinoIndex(); + ArduinoLookup[obj + pos].objName = obj; + ArduinoLookup[obj + pos].ioName = pos; + ArduinoLookup[obj + pos].index = arrayID; + + ArduinoLookupByIndex[arrayID] = new ArduinoIndex(); + ArduinoLookupByIndex[arrayID].objName = obj; + ArduinoLookupByIndex[arrayID].ioName = pos; + ArduinoLookupByIndex[arrayID].index = arrayID; + + var thisObjectID = server.getObjectIdFromObjectName(obj); + + + if (!FullLookup.hasOwnProperty(thisObjectID)) { + FullLookup[thisObjectID] = {}; + } + server.addNode(obj, pos, "node"); + + if(thisObjectID) { + FullLookup[thisObjectID][thisObjectID+pos] = arrayID; + + // console.log("dddddsasdasdasdasdasdasdasdasdasdsd ",obj, pos); + server.addReadListener(obj, pos, function (obj,pos,node,data) { + // console.log(obj,pos,data); + serialSender(serialPort, obj, pos, data.value, "f"); + }.bind(data,thisObjectID,thisObjectID+pos,"node")); + + } + + + + + + dataSwitch = 0; + break; + case 40: + if (parseInt(data, 10) === 1) { + // server.developerOn(); + server.enableDeveloperUI(true); + } + dataSwitch = 0; + break; + case 50: + amount = parseInt(data, 10); + //server.clearIO("arduinoYun"); + dataSwitch = 0; + break; + } + + }); + + // this is for when the server is started... + serialPort.write(" \n"); + serialPort.write("okbird\n"); + + }); + if (server.getDebug()) console.log("no problem"); + } + + + function serialSender(serialPort, objName, ioName, value, mode) { + // console.log("check index: ", objName); + + // console.log(FullLookup); + if (FullLookup.hasOwnProperty(objName)) { + + if (FullLookup[objName].hasOwnProperty(ioName)) { + + var index = FullLookup[objName][ioName]; + + // console.log("check index: ", index); + var yunModes = ["f", "d", "p", "n"]; + if (_.includes(yunModes, mode)) { + serialPort.write(mode + "\n"); + } else { + serialPort.write("f\n"); + } + serialPort.write(index + "\n"); + serialPort.write(value + "\n"); + } + } + } + + server.addEventListener("reset", function () { + if (serialPortOpen) { + serialPort.write(" \n"); + serialPort.write("okbird\n"); + } + }); +} \ No newline at end of file diff --git a/hardwareInterfaces/arduinoUno/package.json b/hardwareInterfaces/arduinoUno/package.json new file mode 100644 index 0000000..94e233f --- /dev/null +++ b/hardwareInterfaces/arduinoUno/package.json @@ -0,0 +1,10 @@ +{ + "name": "arduinoYun", + "version": "0.0.1", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "Valentin Heun (http://valentinheun.com/)", + "license": "MIT" +} diff --git a/hardwareInterfaces/camera/index.js b/hardwareInterfaces/camera/index.js new file mode 100644 index 0000000..2370869 --- /dev/null +++ b/hardwareInterfaces/camera/index.js @@ -0,0 +1,180 @@ +exports.enabled = false; + +if (exports.enabled) { + var http = require('http'); + + var server = require('../../libraries/hardwareInterfaces'); + server.enableDeveloperUI(true); + + var SMTPServer = require('smtp-server').SMTPServer; + var smtpServer = new SMTPServer({ + onAuth: onSMTPAuth, + onData: onSMTPData, + disabledCommands: ['STARTTLS'], + allowInsecureAuth: true + }); + smtpServer.listen(27183); + + var objectName = 'camera'; + + var motionDetectionDuration = 5000; + var lastSMTPData = 0; + + + function onSMTPAuth(auth, session, callback) { + if (auth.username !== 'camera' || auth.password !== 'fluidnsa') { + return callback(new Error('Invalid username or password')); + } + callback(null, {user: 'camera'}); + } + + function onSMTPData(stream, session, callback) { + lastSMTPData = Date.now(); + stream.resume(); + stream.on('end', function() { + callback(null, 'OK'); + }); + } + + var deadzone = 0.01; + var pan = 0; + var tilt = 0; + var requestInFlight = false; + var updateTimeout = null; + var motion = 0; + + var options = { + hostname: '192.168.1.138', + path: '/pantiltcontrol.cgi', + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + 'Referer': 'http://192.168.1.138' + }, + auth: 'admin:fluidnsa' + }; + + function postToServer(path, body, callback) { + options.path = path; + options.headers['Content-Length'] = Buffer.byteLength(body); + var req = http.request(options, function() { + if (callback) { + callback(); + } + }); + req.on('error', function(e) { + console.log('Problem with request:', e.message); + if (callback) { + callback(); + } + }); + + req.write(body); + req.end(); + } + + function sendPreset(preset) { + postToServer('/setControlPanTilt', 'PanTiltPresetPositionMove=' + preset); + } + + function writeMotion(newMotion) { + motion = newMotion; + server.write(objectName, 'motion', motion, 'f'); + } + + function update() { + if (lastSMTPData + motionDetectionDuration > Date.now()) { + if (motion < 0.5) { + writeMotion(1); + } + } else if (motion > 0.5) { + writeMotion(0); + } + // Map pan and tilt to index + // 0 is NW, 1 is N, etc. + var index = -1; + var panning = Math.abs(pan) > deadzone; + var tilting = Math.abs(tilt) > deadzone; + if (panning && tilting) { + if (panning < 0) { + if (tilting < 0) { + index = 4; + } else { + index = 2; + } + } else { + if (tilting > 0) { + index = 0; + } else { + index = 6; + } + } + } else if (panning) { + if (pan < 0) { + index = 3; + } else { + index = 5; + } + } else if (tilting) { + if (tilt < 0) { + index = 7; + } else { + index = 1; + } + } + + if (index !== -1) { + sendMovement(index); + } + updateTimeout = setTimeout(update, 33); + } + + function sendMovement(index) { + // Note that this must balance overwhelming the camera with requests + // (causing lag at end time) and sending requests too infrequently + // (causing jitter) + if (requestInFlight) { + return; + } + requestInFlight = true; + var body = 'PanSingleMoveDegree=1&TiltSingleMoveDegree=1&PanTiltSingleMove=' + index; + postToServer('/pantiltcontrol.cgi', body, function() { + requestInFlight = false; + }); + } + + server.addNode(objectName, 'pan', 'default'); + server.addNode(objectName, 'tilt', 'default'); + server.addNode(objectName, 'motion', 'default'); + + server.activate(objectName); + + server.addReadListener(objectName, 'pan', function(data) { + pan = (data.value - 0.5) * 2; + }); + + server.addReadListener(objectName, 'tilt', function(data) { + tilt = (data.value - 0.5) * 2; + }); + + update(); + + + server.addEventListener('shutdown', function() { + if (updateTimeout) { + clearTimeout(updateTimeout); + } + }); + + var express = require('express'); + var app = express(); + var cors = require('cors'); + app.use(cors()); + app.use('/preset/:presetId', function(req, res) { + sendPreset(req.params.presetId); + res.send('complete'); + }); + app.listen(42448, function() { + console.log('listening on 42448'); + }); +} diff --git a/hardwareInterfaces/philipsHue/config.json b/hardwareInterfaces/philipsHue/config.json new file mode 100644 index 0000000..93ba20c --- /dev/null +++ b/hardwareInterfaces/philipsHue/config.json @@ -0,0 +1,14 @@ +{ + "Light1": { + "host": "192.168.1.12", + "url": "/api/Hw2QChjzsx82qtAnOEbSwt7-P8aztrWIEXzaPrOg/lights/1", + "id": "Light1", + "port": "80" + }, + "Light2": { + "host": "192.168.1.12", + "url": "/api/Hw2QChjzsx82qtAnOEbSwt7-P8aztrWIEXzaPrOg/lights/2", + "id": "Light2", + "port": "80" + } +} diff --git a/hardwareInterfaces/philipsHue/index.js b/hardwareInterfaces/philipsHue/index.js new file mode 100644 index 0000000..bdcf4c8 --- /dev/null +++ b/hardwareInterfaces/philipsHue/index.js @@ -0,0 +1,298 @@ +/** + * Created by Carsten on 12/06/15. + * Modified by Peter Som de Cerff (PCS) on 12/21/15 + * + * Copyright (c) 2015 Carsten Strunk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + * PHILIPS HUE CONNECTOR + * + * This hardware interface can communicate with philips Hue lights. The config.json file specifies the connection information + * for the lamps in your setup. A light in this config file has the following attributes: + * { + * "host":"localhost", // ip or hostname of the philips Hue bridge + * "url":"/api/newdeveloper/lights/1", // base path of the light on the bridge, replace newdeveloper with a valid username (see http://www.developers.meethue.com/documentation/getting-started) + * "id":"Light1", // the name of the HybridObject + * "port":"80" // port the hue bridge is listening on (80 on all bridges by default) + * + * } + * + * Some helpful resources on the Philips Hue API: + * http://www.developers.meethue.com/documentation/getting-started + * http://www.developers.meethue.com/documentation/lights-api + * + * TODO: Add some more functionality, i.e. change color or whatever the philips Hue API offers + */ +//Enable this hardware interface +exports.enabled = false; + +if (exports.enabled) { + + + var fs = require('fs'); + var http = require('http'); + var _ = require('lodash'); + var server = require('../../libraries/hardwareInterfaces'); + server.enableDeveloperUI(true); + + + + var lights = JSON.parse(fs.readFileSync(__dirname + "/config.json", "utf8")); + + //function Light() { + // this.id; + // this.host; + // this.url; + // this.port; + //} + + /** + * @desc setup() runs once, adds and clears the IO points + **/ + function setup() { + //load the config file + //lights = JSON.parse(fs.readFileSync(__dirname + "/config.json", "utf8")); + + if (server.getDebug()) console.log("setup philipsHue"); + for (var key in lights) { + lights[key].switch = undefined; + lights[key].bri = undefined; + if (lights[key].colorful) { + lights[key].hue = undefined; + lights[key].sat = undefined; + } + } + } + + + /** + * @desc getLightState() communicates with the philipsHue bridge and checks the state of the light + * @param {Object} light the light to check + * @param {function} callback function to run when the response has arrived + **/ + function getLightState(light, callback) { + var state; + + var options = { + host: light.host, + path: light.url, + port: light.port, + method: 'GET', + }; + + callbackHttp = function (response) { + var str = ''; + + response.on('data', function (chunk) { + str += chunk; + }); + + response.on('end', function () { + //TODO add some error handling + state = JSON.parse(str).state; + if (!state) { + console.error('Philips Hue Error', str); + return; + } + if (state.on != light.switch) { + light.switch = state.on; + if (state.on) { + callback(light.id, "switch", 1, "d"); + } else { + callback(light.id, "switch", 0, "d"); + } + + } + + if (state.bri != light.bri) { + light.bri = state.bri; // brightness is a value between 1 and 254 + callback(light.id, "brightness", (state.bri - 1) / 253, "f"); + } + + if (light.colorful) { + if (state.hue != light.hue) { + light.hue = state.hue; // hue is a value between 0 and 65535 + callback(light.id, "hue", state.hue / 65535, "f"); // map hue to [0,1] + } + + if (state.sat != light.sat) { + light.sat = state.sat; + callback(light.id, "saturation", state.sat / 254, "f"); + } + } + + }); + } + + + + var req = http.request(options, callbackHttp); + req.on('error', function (e) { + console.log('GetLightState HTTP error: ' + e.message); + }); + req.end(); + + } + + + /** + * @desc writeSwitchState() turns the specified light on or off + * @param {float} state turns the light on if > 0.5, turns it off otherwise + **/ + function writeSwitchState(light, state) { + var options = { + host: light.host, + path: light.url + "/state", + port: light.port, + method: 'PUT', + }; + + + var req = http.request(options, function () { }); + req.on('error', function (e) { + console.log('writeSwitchState HTTP error: ' + e.message); + }); + + if (state < 0.5) { + req.write('{"on":false}'); + } else { + req.write('{"on":true}'); + } + + + + req.end(); + + //TODO check for success message from the bridge + } + + + /** + * @desc writeBrightness() Sets the brightness of the specified light + * @param {float} bri is the brightness in the range [0,1] + **/ + + function writeBrightness(light, bri) { + if (writeBrightness.requestInFlight) { + return; + } + + var options = { + hostname: light.host, + path: light.url + "/state", + port: light.port, + method: 'PUT', + }; + + writeBrightness.requestInFlight = true; + var req = http.request(options, function() { + setTimeout(function() { + writeBrightness.requestInFlight = false; + }, 100); + }); + req.on('error', function (e) { + console.log('writeBrightness HTTP error: ' + e.message); + setTimeout(function() { + writeBrightness.requestInFlight = false; + }, 100); + }); + + req.write('{"bri":' + _.floor(bri * 253 + 1) + '}'); + + req.end(); + } + + + /** + * @desc writeSaturation() sets the saturation for the specified light + * @param {float} sat is the saturatin in the range [0,1] + **/ + function writeSaturation(light, sat) { + var options = { + hostname: light.host, + path: light.url + "/state", + port: light.port, + method: 'PUT', + }; + + var req = http.request(options, function () { }); + req.on('error', function (e) { + console.log('writeSaturation HTTP error: ' + e.message); + }); + req.write('{"sat":' + _.floor(sat * 254) + '}'); + req.end(); + } + + + /** + * @desc writeHue() sets the hue for the specified light + * @param {integer} hue is the hue in the range [0,1] + **/ + function writeHue(light, hue) { + var options = { + hostname: light.host, + path: light.url + "/state", + port: light.port, + method: 'PUT', + }; + + var req = http.request(options, function () { }); + req.on('error', function (e) { + console.log('writeHue HTTP error: ' + e.message); + }); + req.write('{"hue":' + _.floor(hue * 65535) + '}'); + req.end(); + } + + /** + * @desc philipsHueServer() The main function, runs the setup and then periodically checks whether the lights are on. + **/ + function philipsHueServer() { + console.log("philipsHue starting philipsHue"); + setup(); + + + if (server.getDebug()) console.log("philipsHue setup read by poll"); + //TODO poll more often in productive environment + for (var key in lights) { + setInterval(function (light) { + getLightState(light, server.write); + }, 700 + _.random(-100, 100), lights[key]); + } + + } + + function onRead(lightId, writeFn) { + return function(data) { + writeFn(lights[lightId], data.value); + }; + } + + for (var lightId in lights) { + server.addNode(lightId, "switch", "node"); + server.addNode(lightId, "brightness", "node"); + if (lights[lightId].colorful) { + server.addNode(lightId, "hue", "node"); + server.addNode(lightId, "saturation", "node"); + } + server.activate(lightId); + + server.addReadListener(lightId, 'switch', onRead(lightId, writeSwitchState)); + server.addReadListener(lightId, 'brightness', onRead(lightId, writeBrightness)); + + if (lights[lightId].colorful) { + server.addReadListener(lightId, 'hue', onRead(lightId, writeHue)); + server.addReadListener(lightId, 'saturation', onRead(lightId, writeSaturation)); + } + } + + philipsHueServer(); +} + + + diff --git a/hardwareInterfaces/referenceExample/index.js b/hardwareInterfaces/referenceExample/index.js new file mode 100755 index 0000000..72894e4 --- /dev/null +++ b/hardwareInterfaces/referenceExample/index.js @@ -0,0 +1,87 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * Modified by Carsten on 12/06/15. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * Set to true to enable the hardware interface + **/ +exports.enabled = false; + +if (exports.enabled) { + + var server = require(__dirname + '/../../libraries/hardwareInterfaces'); + + server.enableDeveloperUI(true); + + server.addNode("demoTest", "distance", "node"); + server.addNode("demoTest", "motor", "node"); + +/* + server.addNode("obj45", "one", "node"); + server.addNode("obj45", "two", "node"); + server.addNode("obj45", "three", "node"); + server.addNode("obj45", "four", "node"); + */ + + server.addEventListener("reset", function () { + + }); + + server.addEventListener("shutdown", function () { + + }); + + /* + setInterval(function () { + + server.advertiseConnection("obj45","one"); + + setTimeout(function() { + server.advertiseConnection("obj47", "hans"); + }, 4000); + + }, 8000);*/ + +} diff --git a/hardwareInterfaces/testExample/index.js b/hardwareInterfaces/testExample/index.js new file mode 100755 index 0000000..34eb0e0 --- /dev/null +++ b/hardwareInterfaces/testExample/index.js @@ -0,0 +1,62 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * Modified by Carsten on 12/06/15. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * Set to true to enable the hardware interface + **/ +exports.enabled = false; + + +if (exports.enabled) { + var server = require(__dirname + '/../../libraries/hardwareInterfaces'); + + server.enableDeveloperUI(true); + server.addNode("lego1", "light1", "node"); + server.addNode("lego2", "light2", "node"); + server.addNode("lego3", "light1", "node"); + server.addNode("lego4", "light2", "node"); + server.addNode("lego5", "light1", "node"); +} \ No newline at end of file diff --git a/hardwareInterfaces/timer/index.html b/hardwareInterfaces/timer/index.html new file mode 100644 index 0000000..aae2d9d --- /dev/null +++ b/hardwareInterfaces/timer/index.html @@ -0,0 +1,47 @@ + + + + + Timer + + +
0
+





+
+ + + + diff --git a/hardwareInterfaces/timer/index.js b/hardwareInterfaces/timer/index.js new file mode 100755 index 0000000..9ab1ed5 --- /dev/null +++ b/hardwareInterfaces/timer/index.js @@ -0,0 +1,119 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * Modified by Carsten on 12/06/15. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * Set to true to enable the hardware interface + **/ +exports.enabled = false; + +if (exports.enabled) { + + var server = require(__dirname + '/../../libraries/hardwareInterfaces'); + + var app = require('express')(); + var http = require('http').Server(app); + var io = require('socket.io')(http); + + + app.get('/', function(req, res){ + res.sendFile(__dirname + '/index.html'); + }); + app.get('/marker.jpg', function(req, res){ + res.sendFile(__dirname + '/marker.jpg'); + }); + + + http.listen(3000, function(){ + console.log('listening on *:3000'); + }); + + var counter = 0; + var timer = false; + server.enableDeveloperUI(true); + + server.addNode("timer", "start", "node"); + server.addNode("timer", "stop", "node"); + server.addNode("timer", "reset", "node"); + server.addNode("timer", "running", "node"); + + server.addReadListener("timer", "start", function (data) { + if (data.value > 0.5) { + if (!timer) { + io.emit('timer', {timer: "start"}); + timer = true; + server.write('timer', 'running', 1.0, 'f'); + } + } + }); + + server.addReadListener("timer", "reset", function (data) { + if (data.value > 0.5) { + io.emit('timer', {timer: "reset"}); + } + }); + + server.addReadListener("timer", "stop", function (data) { + console.log(data.value); + if (data.value > 0.5) { + if (timer) { + io.emit('timer', {timer: "stop"}); + timer = false; + server.write('timer', 'running', 0.0, 'f'); + } + } + }); + + server.addEventListener("reset", function () { + }); + + server.addEventListener("shutdown", function () { + }); + + io.on('connection', function(socket){ + timer = false; + }); +} + diff --git a/hardwareInterfaces/timer/marker.jpg b/hardwareInterfaces/timer/marker.jpg new file mode 100644 index 0000000..5046bfa Binary files /dev/null and b/hardwareInterfaces/timer/marker.jpg differ diff --git a/hardwareInterfaces/wedo2/index.js b/hardwareInterfaces/wedo2/index.js new file mode 100755 index 0000000..6e79721 --- /dev/null +++ b/hardwareInterfaces/wedo2/index.js @@ -0,0 +1,240 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * Modified by Carsten on 12/06/15. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * Set to true to enable the hardware interface + **/ +exports.enabled = false; + +if (exports.enabled) { + + var names = {}; + var Wedo = require('WeDo2'); + var wedo = new Wedo("lego"); + + var server = require(__dirname + '/../../libraries/hardwareInterfaces'); + + server.enableDeveloperUI(true); + + wedo.on('connected', function (uuid) { + + + // todo If both wedos have the same name, give numbers + // todo make nodes invisible on command + + if (wedo.wedo[uuid]) { + names[uuid] = {px1 : "port 1", px2 : "port 2"}; + names[uuid].name = wedo.wedo[uuid].name; + if(wedo.wedo[uuid].name) { + var thisWedo = wedo.wedo[uuid].name; + + server.addNode(thisWedo, "port 1", "node"); + // server.addNode(thisWedo, "none 1", "node"); + + server.addNode(thisWedo, "port 2", "node"); + // server.addNode(thisWedo, "none 2", "node"); + + server.addNode(thisWedo, "button", "node"); + + server.addNode(thisWedo, "light", "node"); + + server.renameNode(names[uuid].name, "port 1", "port 1"); + // server.renameNode(names[uuid].name, "none 1", "y1"); + server.renameNode(names[uuid].name, "port 2", "port 2"); + // server.renameNode(names[uuid].name, "none 2", "y2"); + + server.activate(thisWedo); + + server.addReadListener(names[uuid].name, "port 1", function (names, wedo, uuid, data) { + // console.log(names[uuid].name,data); + if (names[uuid].px1 === "motor 1") { + wedo.setMotor(server.map(data.value, -1, 1, -100, 100), 1, uuid); + } + }.bind(this, names, wedo, uuid)); + + server.addReadListener(names[uuid].name, "port 2", function (names, wedo, uuid, data) { + // console.log(names[uuid].name,data); + if (names[uuid].px2 === "motor 2") { + // console.log(server.map(data.value,0,1,-100,100)); + wedo.setMotor(server.map(data.value, -1, 1, -100, 100), 2, uuid); + } + }.bind(this, names, wedo, uuid)); + + + server.addReadListener(names[uuid].name, "light", function (names, wedo, uuid, data) { + var color = parseInt(data.value*255); + wedo.setLedColor(color,color,color, uuid); + }.bind(this, names, wedo, uuid)); + + /* server.addReadListener(names[uuid].name, "port2", function (names,wedo,uuid, data){ + + if(names[uuid].p1 === "motor") { + wedo.setMotor(server.map(data.value,0,1,-100,100), 2, uuid); + } + }.bind(this, names,wedo,uuid)) + */ + + wedo.on('button', function (button, uuid) { + if (uuid in names) { + server.write(names[uuid].name, "button", button, "f"); + } + + }); + + } + } + }.bind(this)); + + + + wedo.on('disconnected', function (uuid) { + + // remove all listeners when disconnected + + if (names[uuid].name) { + server.deactivate( names[uuid].name); + + server.renameNode(names[uuid].name, "port 1", " "); + names[uuid].px1 = "port 1"; + server.renameNode(names[uuid].name, "port 2", " "); + names[uuid].px2 = "port 2"; + + // server.renameNode(names[uuid].name, "none 1", " "); + //names[uuid].py1 = "none 1"; + //server.renameNode(names[uuid].name, "none 2", " "); + //names[uuid].py2 = "none 2"; + + server.removeReadListeners(names[uuid].name); + + resetNode(uuid,1); + resetNode(uuid,2); + } + + }); + + + wedo.on('distanceSensor', function (distance, port, uuid) { + if(uuid in names) { + server.write(names[uuid].name, "port "+port, server.map(10-distance,0,10,0,1), "f"); + } + }); + + wedo.on('tiltSensor', function (x,y, port, uuid) { + if(uuid in names) { + Math.round( 20.49); + server.write(names[uuid].name, "port "+port, Math.round(server.map(x,-45,45,0,1)*100)/100, "f"); + // server.write(names[uuid].name, "none "+port, Math.round(server.map(y,-45,45,0,1)*100)/100, "f"); + } + }); + + + wedo.on('port', function (port, connected, type, uuid) { + + if (wedo.wedo[uuid]) { + names[uuid] = names[uuid] || {}; + + var x = "port", y = " "; + + if(type==="distanceSensor"){ + x = "distance"; + } + if(type==="motor"){ + x = "motor"; + } + if(type==="tiltSensor"){ + x = "motion"; + // y = "y"; + } + + var thisWedo = wedo.wedo[uuid].name; + if (port === 1 && connected) { + server.renameNode(thisWedo, "port 1", x); + names[uuid].px1 = x + " 1"; + /* if(y === " "){ + server.renameNode(thisWedo, "none 1"," "); + } else { + server.renameNode(thisWedo, "none 1", y); + } + names[uuid].py1 = y + " 1"; + */ + } + if (port === 2 && connected) { + server.renameNode(thisWedo, "port 2", x); + names[uuid].px2 = x + " 2"; + /* if(y === " ") { + server.renameNode(thisWedo, "none 2"," "); + } else { + server.renameNode(thisWedo, "none 2", y); + } + names[uuid].py2 = y + " 2"; + */ + } + + if (port === 1 && !connected) { + server.renameNode(thisWedo, "port 1", " "); + names[uuid].px1 = "port 1"; + // server.renameNode(thisWedo, "none 1", " "); + // names[uuid].py1 = "none 1"; + resetNode(uuid,1); + } + if (port === 2 && !connected) { + server.renameNode(thisWedo, "port 2", " "); + names[uuid].px2 = "port 2"; + // server.renameNode(thisWedo, "none 2", " "); + // names[uuid].py2 = "none 2"; + resetNode(uuid,2); + } + + } + }); +} + + +function resetNode (uuid, port){ + server.write(names[uuid].name, "port "+port, 0, "f"); + // server.write(names[uuid].name, "none "+port, 0, "f"); + +} \ No newline at end of file diff --git a/libraries/blockIconTemplates.pdf b/libraries/blockIconTemplates.pdf new file mode 100644 index 0000000..a124c06 Binary files /dev/null and b/libraries/blockIconTemplates.pdf differ diff --git a/libraries/hardwareInterfaces.js b/libraries/hardwareInterfaces.js new file mode 100644 index 0000000..46c5a3e --- /dev/null +++ b/libraries/hardwareInterfaces.js @@ -0,0 +1,353 @@ +/** + * Created by Carsten on 12/06/2015. + * Modified by Valentin Heun on 16/08/16. + ** + * Copyright (c) 2015 Carsten Strunk + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * Hybrid Objecst Hardware Interface API + * + * This API is intended for users who want to create their own hardware interfaces. + * To create a new hardware interface create a folder under hardwareInterfaces and create the file index.js. + * You should take a look at /hardwareInterfaces/emptyExample/index.js to get started. + */ + +var http = require('http'); +var utilities = require(__dirname + '/utilities'); +var _ = require('lodash'); + +//global variables, passed through from server.js +var objects = {}; +var objectLookup; +var globalVariables; +var dirnameO; +var nodeTypeModules; +var blockModules; +var callback; +var Node; +var actionCallback; +var hardwareObjects = {}; +var callBacks = new Objects(); +var _this = this; +//data structures to manage the IO points generated by the API user +function Objects() { + this.resetCallBacks = []; + this.shutdownCallBacks = []; +} + +function Object(objectName) { + this.name = objectName; + this.nodes = {}; + +} + +function EmptyNode(nodeName, type) { + this.name = nodeName; + this.type = type; + this.callBack = {}; +} + +/* + ********** API FUNCTIONS ********* + */ + +/** + * @desc This function writes the values passed from the hardware interface to the HybridObjects server. + * @param {string} objectName The name of the HybridObject + * @param {string} nodeName The name of the IO point + * @param {value} value The value to be passed on + * @param {string} mode specifies the datatype of value, you can define it to be whatever you want. For example 'f' could mean value is a floating point variable. + **/ +exports.write = function (objectName, nodeName, value, mode, unit, unitMin, unitMax) { + if (typeof mode === 'undefined') mode = "f"; + if (typeof unit === 'undefined') unit = false; + if (typeof unitMin === 'undefined') unitMin = 0; + if (typeof unitMax === 'undefined') unitMax = 1; + + var objectKey = utilities.readObject(objectLookup, objectName); //get globally unique object id + // var valueKey = nodeName + objKey2; + + var nodeUuid = objectKey+nodeName; + //console.log(objectLookup); +// console.log("writeIOToServer obj: "+objectName + " name: "+nodeName+ " value: "+value+ " mode: "+mode); + if (objects.hasOwnProperty(objectKey)) { + if (objects[objectKey].nodes.hasOwnProperty(nodeUuid)) { + var thisData = objects[objectKey].nodes[nodeUuid].data; + thisData.value = value; + thisData.mode = mode; + thisData.unit = unit; + thisData.unitMin = unitMin; + thisData.unitMax = unitMax; + //callback is objectEngine in server.js. Notify data has changed. + callback(objectKey, nodeUuid, thisData, objects, nodeTypeModules); + } + } +}; + +/** + * @desc clearIO() removes IO points which are no longer needed. It should be called in your hardware interface after all addIO() calls have finished. + * @param {string} type The name of your hardware interface (i.e. what you put in the type parameter of addIO()) + **/ +exports.clearObject = function (objectId) { + var objectID = utilities.getObjectIdFromTarget(objectId, dirnameO); + if (!_.isUndefined(objectID) && !_.isNull(objectID)) { + for (var key in objects[objectID].nodes) { + if (!hardwareObjects[objectId].nodes.hasOwnProperty(key)) { + cout("Deleting: " + objectID + " " + key); + delete objects[objectID].nodes[key]; + } + } + + } + //TODO: clear links too + cout("object is all cleared"); +}; + +/** + * @desc addIO() a new IO point to the specified HybridObject + * @param {string} objectName The name of the HybridObject + * @param {string} nodeName The name of the nodeName + * @param {string} type The name of the data conversion type. If you don't have your own put in "default". + **/ +exports.addNode = function (objectName, nodeName, type) { + + + + utilities.createFolder(objectName, dirnameO, globalVariables.debug); + + var objectID = utilities.getObjectIdFromTarget(objectName, dirnameO); + cout("AddIO objectID: " + objectID); + + var nodeUuid = objectID+nodeName; + + //objID = nodeName + objectID; + + if (!_.isUndefined(objectID) && !_.isNull(objectID)) { + + cout("I will save: " + objectName + " and: " + nodeName); + + if (objects.hasOwnProperty(objectID)) { + objects[objectID].developer = globalVariables.developer; + objects[objectID].name = objectName; + + if (!objects[objectID].nodes.hasOwnProperty(nodeUuid)) { + var thisObject = objects[objectID].nodes[nodeUuid] = new Node(); + thisObject.x = utilities.randomIntInc(0, 200) - 100; + thisObject.y = utilities.randomIntInc(0, 200) - 100; + thisObject.frameSizeX = 100; + thisObject.frameSizeY = 100; + } + + var thisObj = objects[objectID].nodes[nodeUuid]; + thisObj.name = nodeName; + thisObj.text = undefined; + thisObj.type = type; + + if (!hardwareObjects.hasOwnProperty(objectName)) { + hardwareObjects[objectName] = new Object(objectName); + } + + if (!hardwareObjects[objectName].nodes.hasOwnProperty(nodeUuid)) { + hardwareObjects[objectName].nodes[nodeUuid] = new EmptyNode(nodeName); + hardwareObjects[objectName].nodes[nodeUuid].type = type; + } + } + } + objectID = undefined; +}; + +exports.renameNode = function (objectName,oldNodeName, newNodeName) { + var objectID = utilities.getObjectIdFromTarget(objectName, dirnameO); + if (!_.isUndefined(objectID) && !_.isNull(objectID)) { + if (objects.hasOwnProperty(objectID)) { + var thisNode = objectID+oldNodeName; + + if(thisNode in objects[objectID].nodes){ + objects[objectID].nodes[thisNode].text = newNodeName; + // return + } /*else { + for (var key in objects[objectID].nodes) { + if (objects[objectID].nodes[key].name === oldNodeName) { + objects[objectID].nodes[key].name = newNodeName; + return; + } + } + }*/ + } + } + actionCallback({reloadObject: {object: objectID}}); + objectID = undefined; +}; + +exports.activate = function (objectName) { + var objectID = utilities.getObjectIdFromTarget(objectName, dirnameO); + if (!_.isUndefined(objectID) && !_.isNull(objectID)) { + if (objects.hasOwnProperty(objectID)) { + objects[objectID].deactivated = false; + } + } +}; + +exports.deactivate = function (objectName) { + var objectID = utilities.getObjectIdFromTarget(objectName, dirnameO); + console.log("--------- deactive---------") + if (!_.isUndefined(objectID) && !_.isNull(objectID)) { + if (objects.hasOwnProperty(objectID)) { + objects[objectID].deactivated = true; + + } + } +}; + + + + +exports.getObjectIdFromObjectName = function (objectName) { + return utilities.getObjectIdFromTarget(objectName, dirnameO); +}; + +/** + * @desc developerOn() Enables the developer mode for all HybridObjects and enables the developer web interface + **/ +exports.enableDeveloperUI = function (developer) { + globalVariables.developer = developer; + for (var objectID in objects) { + objects[objectID].developer = developer; + } +}; + +/** + * @desc getDebug() checks if debug mode is turned on + * @return {boolean} true if debug mode is on, false otherwise + **/ +exports.getDebug = function () { + return globalVariables.debug; +}; + +/* + ********** END API FUNCTIONS ********* + */ + +/** + * @desc setup() DO NOT call this in your hardware interface. setup() is only called from server.js to pass through some global variables. + **/ +exports.setup = function (objExp, objLookup, glblVars, dir, types, blocks, cb, objValue, actionCallBack) { + objects = objExp; + objectLookup = objLookup; + globalVariables = glblVars; + dirnameO = dir; + nodeTypeModules = types; + blockModules = blocks; + callback = cb; + Node = objValue; + actionCallback = actionCallBack; +}; + +exports.reset = function (){ + for (var objectKey in objects) { + var object = objects[objectKey]; + for (var nodeKey in object.nodes) { + var node = object.nodes[nodeKey] + if (node.type === "logic" || node.frame) { + continue; + } + // addNode requires that nodeKey === object.name + node.name + _this.addNode(object.name, node.name, node.type); + } + _this.clearObject(objectKey); + } + + cout("sendReset"); + for (var i = 0; i < callBacks.resetCallBacks.length; i++) { + callBacks.resetCallBacks[i](); + } +}; + +exports.readCall = function (objectName, nodeName, data) { + if (callBacks.hasOwnProperty(objectName)) { + if (callBacks[objectName].nodes.hasOwnProperty(nodeName)) { + callBacks[objectName].nodes[nodeName].callBack(data); + } + } +}; + +exports.addReadListener = function (objectName, nodeName, callBack) { + var objectID = utilities.readObject(objectLookup, objectName); + var nodeID = objectID+nodeName; + + cout("Add read listener for objectID: " + objectID); + + if (!_.isUndefined(objectID) && !_.isNull(objectID)) { + + if (objects.hasOwnProperty(objectID)) { + if (!callBacks.hasOwnProperty(objectID)) { + callBacks[objectID] = new Object(objectID); + } + + if (!callBacks[objectID].nodes.hasOwnProperty(nodeID)) { + callBacks[objectID].nodes[nodeID] = new EmptyNode(nodeName); + callBacks[objectID].nodes[nodeID].callBack = callBack; + } else { + callBacks[objectID].nodes[nodeID].callBack = callBack; + } + } + } +}; + +exports.removeReadListeners = function (objectName){ + var objectID = utilities.readObject(objectLookup, objectName); + if(callBacks[objectID]) + delete callBacks[objectID]; +}; + +exports.map = function (x, in_min, in_max, out_min, out_max) { + if (x > in_max) x = in_max; + if (x < in_min) x = in_min; + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +}; + + +exports.addEventListener = function (option, callBack){ + if(option === "reset") { + cout("Add reset listener"); + callBacks.resetCallBacks.push(callBack); + } + if(option === "shutdown") { + cout("Add reset listener"); + callBacks.shutdownCallBacks.push(callBack); + } + +}; + +exports.advertiseConnection = function (object, node, logic){ + if(typeof logic === "undefined") { + logic = false; + } + var objectID = utilities.readObject(objectLookup, object); + var nodeID = objectID+node; + + var message = {advertiseConnection:{ + object: objectID, + node: nodeID, + logic: logic, + names: [object, node], + }}; + actionCallback(message); +}; + +exports.shutdown = function (){ + + cout("call shutdowns"); + for (var i = 0; i < callBacks.shutdownCallBacks.length; i++) { + callBacks.shutdownCallBacks[i](); + } +}; + +function cout(msg) { + if (globalVariables.debug) console.log(msg); +} \ No newline at end of file diff --git a/libraries/inactiveLogicBlocks/motor/gui/icon.svg b/libraries/inactiveLogicBlocks/motor/gui/icon.svg new file mode 100644 index 0000000..9b99790 --- /dev/null +++ b/libraries/inactiveLogicBlocks/motor/gui/icon.svg @@ -0,0 +1 @@ +icon \ No newline at end of file diff --git a/libraries/inactiveLogicBlocks/motor/gui/index.html b/libraries/inactiveLogicBlocks/motor/gui/index.html new file mode 100644 index 0000000..d169a20 --- /dev/null +++ b/libraries/inactiveLogicBlocks/motor/gui/index.html @@ -0,0 +1,58 @@ + + + + + Setup Slider + + + + +
+ + + +
+ + + diff --git a/libraries/inactiveLogicBlocks/motor/gui/label.svg b/libraries/inactiveLogicBlocks/motor/gui/label.svg new file mode 100644 index 0000000..0088ed3 --- /dev/null +++ b/libraries/inactiveLogicBlocks/motor/gui/label.svg @@ -0,0 +1 @@ +label \ No newline at end of file diff --git a/libraries/inactiveLogicBlocks/motor/gui/style.css b/libraries/inactiveLogicBlocks/motor/gui/style.css new file mode 100644 index 0000000..f9dcf3b --- /dev/null +++ b/libraries/inactiveLogicBlocks/motor/gui/style.css @@ -0,0 +1,88 @@ +body { + background-color: dimgray; +} +input[type=range] { + background-color: transparent; + -webkit-appearance: none; + +} + +input[type=range]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 68px; /* Must add six because this width includes the border */ + background-color: rgba(255, 255, 255, 0); + -webkit-backdrop-filter: blur(4px); + border: solid 4px #00edff; + border-radius: 8px; + padding: 5px; +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 50px; + width: 50px; + border-radius: 2px; + background: #00edff; +} + +.range-slider input[type="range"]:after { + height: 2px; + background: #fff; + content: ' '; + width: 5px; + top: 50%; + margin-top: -1px; + left: -5px; + z-index: 1; + position: absolute; +} + +input[type=range]:focus { + outline: none; +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: xx-large; + font-weight: 700; + color: #00ffff; + align: center; + text-align: center; + position: relative; + top:50px; +} + +/* HTML5 Boilerplate radio-one hidden styles */ +[type="radio"] { + border: 0; + height: 1px; margin: -1px; + padding: 0; + position: absolute; + width: 1px; + display: none; +} + +/* One radio button per line */ +label { + display: block; + cursor: pointer; /*hand view when on hover*/ + line-height: 2.5; + font-size: 1.5em; +} + +/* the basic, unchecked style */ +[type="radio"] + span:before { + content: ''; + display: inline-block; + width: 1em; + height: 1em; + vertical-align: -0.25em; + border-radius: 1em; /*hard border*/ + border: 0.125em solid #00ffff; + margin-right: 0.75em; +} + +/* the checked style using the :checked pseudo class */ +[type="radio"]:checked + span:before { + background: #00ffff; +} diff --git a/libraries/inactiveLogicBlocks/motor/index.js b/libraries/inactiveLogicBlocks/motor/index.js new file mode 100755 index 0000000..df818b4 --- /dev/null +++ b/libraries/inactiveLogicBlocks/motor/index.js @@ -0,0 +1,98 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "motor", + blockSize : 2, + privateData : {}, + publicData : {}, + activeInputs : [true, true, false, false], + activeOutputs : [true, true, false, false], + iconImage : "icon.png", + nameInput : ["in", "stream in", "", ""], + nameOutput : ["out", "stream out", "", ""], + type : "switch" +}; + +var switchValue = 0; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + for (var key in thisBlock.data[index]) { + if(key === "value"){ + if(index === 0){ + thisBlock.processedData[0].value = Math.round(((1-thisBlock.data[index].value)/2)*1000)/1000; + } + + if(index === 1){ + thisBlock.processedData[0].value = Math.round((((thisBlock.data[index].value)/2)+0.5)*1000)/1000; + } + + } else { + thisBlock.processedData[index][key] = thisBlock.data[index][key]; + } + } + + callback(object, node, block, index, thisBlock); +}; \ No newline at end of file diff --git a/libraries/logicBlocks/add/gui/icon.svg b/libraries/logicBlocks/add/gui/icon.svg new file mode 100644 index 0000000..479010b --- /dev/null +++ b/libraries/logicBlocks/add/gui/icon.svg @@ -0,0 +1,10 @@ + + + + + + icon + + A B + + + \ No newline at end of file diff --git a/libraries/logicBlocks/add/gui/index.html b/libraries/logicBlocks/add/gui/index.html new file mode 100644 index 0000000..f00e318 --- /dev/null +++ b/libraries/logicBlocks/add/gui/index.html @@ -0,0 +1,12 @@ + + + + + Setup Slider + + + + + + + diff --git a/libraries/logicBlocks/add/gui/label.svg b/libraries/logicBlocks/add/gui/label.svg new file mode 100644 index 0000000..8300515 --- /dev/null +++ b/libraries/logicBlocks/add/gui/label.svg @@ -0,0 +1,21 @@ + + + + label + + + + + + + + + + + + A + B + \ No newline at end of file diff --git a/libraries/logicBlocks/add/gui/style.css b/libraries/logicBlocks/add/gui/style.css new file mode 100644 index 0000000..e69de29 diff --git a/libraries/logicBlocks/add/index.js b/libraries/logicBlocks/add/index.js new file mode 100755 index 0000000..ddbb8d1 --- /dev/null +++ b/libraries/logicBlocks/add/index.js @@ -0,0 +1,100 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "add", + blockSize : 2, + privateData : {}, + publicData : {}, + activeInputs : [true, true, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["A", "B", "", ""], + nameOutput : ["A + B", "", "", ""], + type : "add" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + var sum = 0; + // add value from A + if (thisBlock.data[0].value) { + sum += thisBlock.data[0].value; + } + // add value from B + if (thisBlock.data[1].value) { + sum += thisBlock.data[1].value; + } + // constrain sum to 0-1 range + sum = Math.max(0, Math.min(1, sum)); + + for (var key in thisBlock.data[0]) { + thisBlock.processedData[0][key] = thisBlock.data[0][key]; + } + + console.log(sum); + + thisBlock.processedData[0].value = sum; + + callback(object, node, block, index, thisBlock); +}; \ No newline at end of file diff --git a/libraries/logicBlocks/add3/gui/icon.svg b/libraries/logicBlocks/add3/gui/icon.svg new file mode 100644 index 0000000..998c48f --- /dev/null +++ b/libraries/logicBlocks/add3/gui/icon.svg @@ -0,0 +1,10 @@ + + + + + + icon + + A B C + + + + \ No newline at end of file diff --git a/libraries/logicBlocks/add3/gui/index.html b/libraries/logicBlocks/add3/gui/index.html new file mode 100644 index 0000000..f00e318 --- /dev/null +++ b/libraries/logicBlocks/add3/gui/index.html @@ -0,0 +1,12 @@ + + + + + Setup Slider + + + + + + + diff --git a/libraries/logicBlocks/add3/gui/label.svg b/libraries/logicBlocks/add3/gui/label.svg new file mode 100644 index 0000000..f74b23c --- /dev/null +++ b/libraries/logicBlocks/add3/gui/label.svg @@ -0,0 +1,23 @@ + + + + label + + + + + + + + + + + + + + A + B + C + \ No newline at end of file diff --git a/libraries/logicBlocks/add3/gui/style.css b/libraries/logicBlocks/add3/gui/style.css new file mode 100644 index 0000000..e69de29 diff --git a/libraries/logicBlocks/add3/index.js b/libraries/logicBlocks/add3/index.js new file mode 100755 index 0000000..00de8a9 --- /dev/null +++ b/libraries/logicBlocks/add3/index.js @@ -0,0 +1,102 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "add3", + blockSize : 3, + privateData : {}, + publicData : {}, + activeInputs : [true, true, true, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["A", "B", "C", ""], + nameOutput : ["A + B + C", "", "", ""], + type : "add3" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + var sum = 0; + // add value from A + if (thisBlock.data[0].value) { + sum += thisBlock.data[0].value; + } + // add value from B + if (thisBlock.data[1].value) { + sum += thisBlock.data[1].value; + } + // add value from C + if (thisBlock.data[2].value) { + sum += thisBlock.data[2].value; + } + // constrain sum to 0-1 range + sum = Math.max(0, Math.min(1, sum)); + + for (var key in thisBlock.data[0]) { + thisBlock.processedData[0][key] = thisBlock.data[0][key]; + } + + thisBlock.processedData[0].value = sum; + + callback(object, node, block, index, thisBlock); +}; \ No newline at end of file diff --git a/libraries/logicBlocks/add4/gui/icon.svg b/libraries/logicBlocks/add4/gui/icon.svg new file mode 100644 index 0000000..19cccd7 --- /dev/null +++ b/libraries/logicBlocks/add4/gui/icon.svg @@ -0,0 +1,10 @@ + + + + + + icon + + A B C D + + + + + \ No newline at end of file diff --git a/libraries/logicBlocks/add4/gui/index.html b/libraries/logicBlocks/add4/gui/index.html new file mode 100644 index 0000000..f00e318 --- /dev/null +++ b/libraries/logicBlocks/add4/gui/index.html @@ -0,0 +1,12 @@ + + + + + Setup Slider + + + + + + + diff --git a/libraries/logicBlocks/add4/gui/label.svg b/libraries/logicBlocks/add4/gui/label.svg new file mode 100644 index 0000000..dd0cd58 --- /dev/null +++ b/libraries/logicBlocks/add4/gui/label.svg @@ -0,0 +1,25 @@ + + + + label + + + + + + + + + + + + + + + + A + B + C + D + \ No newline at end of file diff --git a/libraries/logicBlocks/add4/gui/style.css b/libraries/logicBlocks/add4/gui/style.css new file mode 100644 index 0000000..e69de29 diff --git a/libraries/logicBlocks/add4/index.js b/libraries/logicBlocks/add4/index.js new file mode 100755 index 0000000..66872ba --- /dev/null +++ b/libraries/logicBlocks/add4/index.js @@ -0,0 +1,106 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "add4", + blockSize : 4, + privateData : {}, + publicData : {}, + activeInputs : [true, true, true, true], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["A", "B", "C", "D"], + nameOutput : ["A + B + C + D", "", "", ""], + type : "add4" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + var sum = 0; + // add value from A + if (thisBlock.data[0].value) { + sum += thisBlock.data[0].value; + } + // add value from B + if (thisBlock.data[1].value) { + sum += thisBlock.data[1].value; + } + // add value from C + if (thisBlock.data[2].value) { + sum += thisBlock.data[2].value; + } + // add value from D + if (thisBlock.data[3].value) { + sum += thisBlock.data[3].value; + } + // constrain sum to 0-1 range + sum = Math.max(0, Math.min(1, sum)); + + for (var key in thisBlock.data[0]) { + thisBlock.processedData[0][key] = thisBlock.data[0][key]; + } + + thisBlock.processedData[0].value = sum; + + callback(object, node, block, index, thisBlock); +}; \ No newline at end of file diff --git a/libraries/logicBlocks/default/gui/icon.svg b/libraries/logicBlocks/default/gui/icon.svg new file mode 100644 index 0000000..49b4cb9 --- /dev/null +++ b/libraries/logicBlocks/default/gui/icon.svg @@ -0,0 +1 @@ +icon \ No newline at end of file diff --git a/libraries/logicBlocks/default/gui/index.html b/libraries/logicBlocks/default/gui/index.html new file mode 100644 index 0000000..f00e318 --- /dev/null +++ b/libraries/logicBlocks/default/gui/index.html @@ -0,0 +1,12 @@ + + + + + Setup Slider + + + + + + + diff --git a/libraries/logicBlocks/default/gui/label.svg b/libraries/logicBlocks/default/gui/label.svg new file mode 100644 index 0000000..f16df75 --- /dev/null +++ b/libraries/logicBlocks/default/gui/label.svg @@ -0,0 +1,16 @@ + + + + +label + + + + + + diff --git a/libraries/logicBlocks/default/gui/style.css b/libraries/logicBlocks/default/gui/style.css new file mode 100644 index 0000000..e69de29 diff --git a/libraries/logicBlocks/default/index.js b/libraries/logicBlocks/default/index.js new file mode 100755 index 0000000..280839f --- /dev/null +++ b/libraries/logicBlocks/default/index.js @@ -0,0 +1,83 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "default", + blockSize : 1, + privateData : {}, + publicData : {}, + activeInputs : [true, false, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["in", "", "", ""], + nameOutput : ["out", "", "", ""], + type : "default" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + for (var key in thisBlock.data[index]) { + thisBlock.processedData[index][key] = thisBlock.data[index][key]; + } + callback(object, node, block, index, thisBlock); +}; \ No newline at end of file diff --git a/libraries/logicBlocks/delay/gui/icon.svg b/libraries/logicBlocks/delay/gui/icon.svg new file mode 100644 index 0000000..a956762 --- /dev/null +++ b/libraries/logicBlocks/delay/gui/icon.svg @@ -0,0 +1 @@ +icon \ No newline at end of file diff --git a/libraries/logicBlocks/delay/gui/index.html b/libraries/logicBlocks/delay/gui/index.html new file mode 100644 index 0000000..d619b7d --- /dev/null +++ b/libraries/logicBlocks/delay/gui/index.html @@ -0,0 +1,53 @@ + + + + + Setup Slider + + + + +
+ + + + diff --git a/libraries/logicBlocks/delay/gui/label.svg b/libraries/logicBlocks/delay/gui/label.svg new file mode 100644 index 0000000..b132319 --- /dev/null +++ b/libraries/logicBlocks/delay/gui/label.svg @@ -0,0 +1 @@ +label \ No newline at end of file diff --git a/libraries/logicBlocks/delay/gui/style.css b/libraries/logicBlocks/delay/gui/style.css new file mode 100644 index 0000000..497202c --- /dev/null +++ b/libraries/logicBlocks/delay/gui/style.css @@ -0,0 +1,53 @@ +body { + background-color: dimgray; +} +input[type=range] { + background-color: transparent; + -webkit-appearance: none; + +} + +input[type=range]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 68px; /* Must add six because this width includes the border */ + background-color: rgba(255, 255, 255, 0); + -webkit-backdrop-filter: blur(4px); + border: solid 4px #00edff; + border-radius: 8px; + padding: 5px; +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 50px; + width: 50px; + border-radius: 2px; + background: #00edff; +} + +.range-slider input[type="range"]:after { + height: 2px; + background: #fff; + content: ' '; + width: 5px; + top: 50%; + margin-top: -1px; + left: -5px; + z-index: 1; + position: absolute; +} + +input[type=range]:focus { + outline: none; +} +.number { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: xx-large; + font-weight: 700; + color: #00ffff; + align: center; + text-align: center; + position: relative; + top:50px; +} \ No newline at end of file diff --git a/libraries/logicBlocks/delay/index.js b/libraries/logicBlocks/delay/index.js new file mode 100755 index 0000000..ca36cc3 --- /dev/null +++ b/libraries/logicBlocks/delay/index.js @@ -0,0 +1,86 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "delay", + blockSize : 1, + privateData : {}, + publicData : {delayTime : 1000}, + activeInputs : [true, false, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["in", "", "", ""], + nameOutput : ["out", "", "", ""], + type : "delay" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + var delayedValue = thisBlock.data[index].value; + + setTimeout(function() { + thisBlock.processedData[index].value = delayedValue; + callback(object, node, block, index, thisBlock); + }, thisBlock.publicData.delayTime); + +}; diff --git a/libraries/logicBlocks/duplex/gui/icon.png b/libraries/logicBlocks/duplex/gui/icon.png new file mode 100644 index 0000000..9f7e15d Binary files /dev/null and b/libraries/logicBlocks/duplex/gui/icon.png differ diff --git a/libraries/logicBlocks/duplex/gui/icon.svg b/libraries/logicBlocks/duplex/gui/icon.svg new file mode 100644 index 0000000..bc08193 --- /dev/null +++ b/libraries/logicBlocks/duplex/gui/icon.svg @@ -0,0 +1 @@ +blockIconTemplates \ No newline at end of file diff --git a/libraries/logicBlocks/duplex/gui/index.html b/libraries/logicBlocks/duplex/gui/index.html new file mode 100644 index 0000000..0dd88c9 --- /dev/null +++ b/libraries/logicBlocks/duplex/gui/index.html @@ -0,0 +1,51 @@ + + + + + Setup Slider + + + + + A duplex switch switches from its two inputs based on whether its switch + input is lower or higher than 0.5. + + + diff --git a/libraries/logicBlocks/duplex/gui/label.png b/libraries/logicBlocks/duplex/gui/label.png new file mode 100644 index 0000000..4a79efd Binary files /dev/null and b/libraries/logicBlocks/duplex/gui/label.png differ diff --git a/libraries/logicBlocks/duplex/gui/label.svg b/libraries/logicBlocks/duplex/gui/label.svg new file mode 100644 index 0000000..18bd272 --- /dev/null +++ b/libraries/logicBlocks/duplex/gui/label.svg @@ -0,0 +1 @@ +blockIconTemplates \ No newline at end of file diff --git a/libraries/logicBlocks/duplex/gui/style.css b/libraries/logicBlocks/duplex/gui/style.css new file mode 100644 index 0000000..f9dcf3b --- /dev/null +++ b/libraries/logicBlocks/duplex/gui/style.css @@ -0,0 +1,88 @@ +body { + background-color: dimgray; +} +input[type=range] { + background-color: transparent; + -webkit-appearance: none; + +} + +input[type=range]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 68px; /* Must add six because this width includes the border */ + background-color: rgba(255, 255, 255, 0); + -webkit-backdrop-filter: blur(4px); + border: solid 4px #00edff; + border-radius: 8px; + padding: 5px; +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 50px; + width: 50px; + border-radius: 2px; + background: #00edff; +} + +.range-slider input[type="range"]:after { + height: 2px; + background: #fff; + content: ' '; + width: 5px; + top: 50%; + margin-top: -1px; + left: -5px; + z-index: 1; + position: absolute; +} + +input[type=range]:focus { + outline: none; +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: xx-large; + font-weight: 700; + color: #00ffff; + align: center; + text-align: center; + position: relative; + top:50px; +} + +/* HTML5 Boilerplate radio-one hidden styles */ +[type="radio"] { + border: 0; + height: 1px; margin: -1px; + padding: 0; + position: absolute; + width: 1px; + display: none; +} + +/* One radio button per line */ +label { + display: block; + cursor: pointer; /*hand view when on hover*/ + line-height: 2.5; + font-size: 1.5em; +} + +/* the basic, unchecked style */ +[type="radio"] + span:before { + content: ''; + display: inline-block; + width: 1em; + height: 1em; + vertical-align: -0.25em; + border-radius: 1em; /*hard border*/ + border: 0.125em solid #00ffff; + margin-right: 0.75em; +} + +/* the checked style using the :checked pseudo class */ +[type="radio"]:checked + span:before { + background: #00ffff; +} diff --git a/libraries/logicBlocks/duplex/index.js b/libraries/logicBlocks/duplex/index.js new file mode 100755 index 0000000..a880904 --- /dev/null +++ b/libraries/logicBlocks/duplex/index.js @@ -0,0 +1,94 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "duplex", + blockSize : 3, + privateData : {}, + publicData : {}, + activeInputs : [true, true, true, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["in", "low in", "high in", ""], + nameOutput : ["out", "", "", ""], + type : "duplex" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +function copyValuesToOutput(thisBlock, index) { + for (var key in thisBlock.data[index]) { + thisBlock.processedData[0][key] = thisBlock.data[index][key]; + } +} +exports.render = function (object, node, block, index, thisBlock, callback) { + + if(thisBlock.data[0].value > 0.5 ) { + // Copy values from high input to out + copyValuesToOutput(thisBlock, 2); + } else { + // Copy values from low input to out + copyValuesToOutput(thisBlock, 1); + } + + callback(object, node, block, index, thisBlock); +}; diff --git a/libraries/logicBlocks/fullRange/gui/icon.svg b/libraries/logicBlocks/fullRange/gui/icon.svg new file mode 100644 index 0000000..6f5f9d4 --- /dev/null +++ b/libraries/logicBlocks/fullRange/gui/icon.svg @@ -0,0 +1 @@ +_ \ No newline at end of file diff --git a/libraries/logicBlocks/fullRange/gui/index.html b/libraries/logicBlocks/fullRange/gui/index.html new file mode 100644 index 0000000..1110bd2 --- /dev/null +++ b/libraries/logicBlocks/fullRange/gui/index.html @@ -0,0 +1,15 @@ + + + + + Setup Slider + + + + + + + + diff --git a/libraries/logicBlocks/fullRange/gui/label.svg b/libraries/logicBlocks/fullRange/gui/label.svg new file mode 100644 index 0000000..e4dfbb1 --- /dev/null +++ b/libraries/logicBlocks/fullRange/gui/label.svg @@ -0,0 +1 @@ +_ \ No newline at end of file diff --git a/libraries/logicBlocks/fullRange/gui/style.css b/libraries/logicBlocks/fullRange/gui/style.css new file mode 100644 index 0000000..f9dcf3b --- /dev/null +++ b/libraries/logicBlocks/fullRange/gui/style.css @@ -0,0 +1,88 @@ +body { + background-color: dimgray; +} +input[type=range] { + background-color: transparent; + -webkit-appearance: none; + +} + +input[type=range]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 68px; /* Must add six because this width includes the border */ + background-color: rgba(255, 255, 255, 0); + -webkit-backdrop-filter: blur(4px); + border: solid 4px #00edff; + border-radius: 8px; + padding: 5px; +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 50px; + width: 50px; + border-radius: 2px; + background: #00edff; +} + +.range-slider input[type="range"]:after { + height: 2px; + background: #fff; + content: ' '; + width: 5px; + top: 50%; + margin-top: -1px; + left: -5px; + z-index: 1; + position: absolute; +} + +input[type=range]:focus { + outline: none; +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: xx-large; + font-weight: 700; + color: #00ffff; + align: center; + text-align: center; + position: relative; + top:50px; +} + +/* HTML5 Boilerplate radio-one hidden styles */ +[type="radio"] { + border: 0; + height: 1px; margin: -1px; + padding: 0; + position: absolute; + width: 1px; + display: none; +} + +/* One radio button per line */ +label { + display: block; + cursor: pointer; /*hand view when on hover*/ + line-height: 2.5; + font-size: 1.5em; +} + +/* the basic, unchecked style */ +[type="radio"] + span:before { + content: ''; + display: inline-block; + width: 1em; + height: 1em; + vertical-align: -0.25em; + border-radius: 1em; /*hard border*/ + border: 0.125em solid #00ffff; + margin-right: 0.75em; +} + +/* the checked style using the :checked pseudo class */ +[type="radio"]:checked + span:before { + background: #00ffff; +} diff --git a/libraries/logicBlocks/fullRange/index.js b/libraries/logicBlocks/fullRange/index.js new file mode 100755 index 0000000..6209fa2 --- /dev/null +++ b/libraries/logicBlocks/fullRange/index.js @@ -0,0 +1,86 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "full Range", + blockSize : 1, + privateData : {}, + publicData : {}, + activeInputs : [true, false, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["in", "", "", ""], + nameOutput : ["out", "", "", ""], + type : "fullRange" +}; + +var switchValue = 0; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +exports.render = function (object, node, block, index, thisBlock, callback) { + + for (var key in thisBlock.data[0]) { + if (key === "value") { + thisBlock.processedData[0].value = (thisBlock.data[0].value -0.5)*2; + } + } + callback(object, node, block, index, thisBlock); +}; \ No newline at end of file diff --git a/libraries/logicBlocks/ifttt/gui/icon.svg b/libraries/logicBlocks/ifttt/gui/icon.svg new file mode 100644 index 0000000..8438ba7 --- /dev/null +++ b/libraries/logicBlocks/ifttt/gui/icon.svg @@ -0,0 +1,13 @@ + + + + + + icon + IFTTT + + + + + + \ No newline at end of file diff --git a/libraries/logicBlocks/ifttt/gui/index.html b/libraries/logicBlocks/ifttt/gui/index.html new file mode 100644 index 0000000..9107e9b --- /dev/null +++ b/libraries/logicBlocks/ifttt/gui/index.html @@ -0,0 +1,81 @@ + + + + + + Setup Slider + + + + + +
+ This will make trigger an IFTTT event + + +
+ +
+ Current event name:
+
+ +
+ Current IFTTT Key:
+
+ +
+ + + + diff --git a/libraries/logicBlocks/ifttt/gui/label.svg b/libraries/logicBlocks/ifttt/gui/label.svg new file mode 100644 index 0000000..08c5aac --- /dev/null +++ b/libraries/logicBlocks/ifttt/gui/label.svg @@ -0,0 +1,18 @@ + + + + + + + label + + + + + + IFTTT + \ No newline at end of file diff --git a/libraries/logicBlocks/ifttt/gui/style.css b/libraries/logicBlocks/ifttt/gui/style.css new file mode 100644 index 0000000..1d60ee9 --- /dev/null +++ b/libraries/logicBlocks/ifttt/gui/style.css @@ -0,0 +1,37 @@ +body { + background-color: dimgray; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #00ffff; + text-align: center; + width: 506px; + word-wrap: break-word; +} + +#description { + margin: 30px 40px 30px 40px; +} + +#interaction { + margin: 0 40px 0 40px; +} + +#eventNameTextField, #iftttTextField { + width: 70%; + text-align: center; + font-size: 16px; + height: 30px; +} + +.code { + font-family: monospace; +} + +.placeholder { + font-style: italic; +} + +#updateButton { + width: 100px; + height: 30px; + margin: 10px; +} \ No newline at end of file diff --git a/libraries/logicBlocks/ifttt/index.js b/libraries/logicBlocks/ifttt/index.js new file mode 100755 index 0000000..006baf7 --- /dev/null +++ b/libraries/logicBlocks/ifttt/index.js @@ -0,0 +1,141 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var request = require('request'); + +var generalProperties = { + name : "IFTTT", + blockSize : 1, + privateData : {}, + publicData : { + eventName: "reality_editor_43bb26f9", + ifttt_key: "cjizq-2cjLs9dasYKceqOB" //"d7KguEO4Vn2Xhut0sR0_JI" + }, + activeInputs : [true, false, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["in", "", "", ""], + nameOutput : ["out", "", "", ""], + type : "IFTTT" +}; + +//endpointUrl : "http://192.168.1.12:8082/test", +//https://maker.ifttt.com/trigger/{event}/with/key/d7KguEO4Vn2Xhut0sR0_JI + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + // data flows through it like normal + for (var key in thisBlock.data[index]) { + thisBlock.processedData[index][key] = thisBlock.data[index][key]; + } + + // BUT ALSO: makes a post request to the server endpoint configured in publicData + console.log("making ifttt request to " + JSON.stringify(thisBlock.publicData)); + + if (index === 0) { + + var endpointUrl = "https://maker.ifttt.com/trigger/" + thisBlock.publicData.eventName + "/with/key/" + thisBlock.publicData.ifttt_key; + //var jsonBody = {value1: thisBlock.processedData[0].value}; + + var requestBody = {value1: thisBlock.processedData[0].value}; + //var requestBody = {"value1":"1"}; + //var requestBody = { json: {value1: thisBlock.processedData[0].value} }; + + //request.post( + // endpointUrl, + // requestBody, + // function (error, response, body) { + // if (!error && response.statusCode == 200) { + // console.log(body); + // } + // } + //); + + var options = { + method: 'post', + //body: {}, + body: requestBody, + json: true, + url: endpointUrl + }; + + request(options, function (err, res, body) { + if (err) { + console.error('error posting json: ', err); + throw err + } + var headers = res.headers; + var statusCode = res.statusCode; + console.log('headers: ', headers); + console.log('statusCode: ', statusCode); + console.log('body: ', body); + }); + + + } + + //console.log(endpointUrl, requestBody); + + callback(object, node, block, index, thisBlock); +}; diff --git a/libraries/logicBlocks/invert/gui/icon.svg b/libraries/logicBlocks/invert/gui/icon.svg new file mode 100644 index 0000000..e8a7b59 --- /dev/null +++ b/libraries/logicBlocks/invert/gui/icon.svg @@ -0,0 +1 @@ +icon \ No newline at end of file diff --git a/libraries/logicBlocks/invert/gui/index.html b/libraries/logicBlocks/invert/gui/index.html new file mode 100644 index 0000000..f00e318 --- /dev/null +++ b/libraries/logicBlocks/invert/gui/index.html @@ -0,0 +1,12 @@ + + + + + Setup Slider + + + + + + + diff --git a/libraries/logicBlocks/invert/gui/label.svg b/libraries/logicBlocks/invert/gui/label.svg new file mode 100644 index 0000000..3c83249 --- /dev/null +++ b/libraries/logicBlocks/invert/gui/label.svg @@ -0,0 +1,19 @@ + + + + +label + + + + + + + + diff --git a/libraries/logicBlocks/invert/gui/style.css b/libraries/logicBlocks/invert/gui/style.css new file mode 100644 index 0000000..e69de29 diff --git a/libraries/logicBlocks/invert/index.js b/libraries/logicBlocks/invert/index.js new file mode 100755 index 0000000..a7b033f --- /dev/null +++ b/libraries/logicBlocks/invert/index.js @@ -0,0 +1,87 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "invert", + blockSize : 1, + privateData : {}, + publicData : {}, + activeInputs : [true, false, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["in", "", "", ""], + nameOutput : ["out", "", "", ""], + type : "default" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + for (var key in thisBlock.data[index]) { + if(key === "value"){ + thisBlock.processedData[index].value = 1-thisBlock.data[index].value; + } else { + thisBlock.processedData[index][key] = thisBlock.data[index][key]; + } + } + callback(object, node, block, index, thisBlock); +}; \ No newline at end of file diff --git a/libraries/logicBlocks/invertMotor/gui/icon.svg b/libraries/logicBlocks/invertMotor/gui/icon.svg new file mode 100644 index 0000000..9d183c2 --- /dev/null +++ b/libraries/logicBlocks/invertMotor/gui/icon.svg @@ -0,0 +1 @@ +_ \ No newline at end of file diff --git a/libraries/logicBlocks/invertMotor/gui/index.html b/libraries/logicBlocks/invertMotor/gui/index.html new file mode 100644 index 0000000..d2872be --- /dev/null +++ b/libraries/logicBlocks/invertMotor/gui/index.html @@ -0,0 +1,11 @@ + + + + + Setup Slider + + + +HI + + diff --git a/libraries/logicBlocks/invertMotor/gui/label.svg b/libraries/logicBlocks/invertMotor/gui/label.svg new file mode 100644 index 0000000..a63c915 --- /dev/null +++ b/libraries/logicBlocks/invertMotor/gui/label.svg @@ -0,0 +1 @@ +_ \ No newline at end of file diff --git a/libraries/logicBlocks/invertMotor/gui/style.css b/libraries/logicBlocks/invertMotor/gui/style.css new file mode 100644 index 0000000..f9dcf3b --- /dev/null +++ b/libraries/logicBlocks/invertMotor/gui/style.css @@ -0,0 +1,88 @@ +body { + background-color: dimgray; +} +input[type=range] { + background-color: transparent; + -webkit-appearance: none; + +} + +input[type=range]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 68px; /* Must add six because this width includes the border */ + background-color: rgba(255, 255, 255, 0); + -webkit-backdrop-filter: blur(4px); + border: solid 4px #00edff; + border-radius: 8px; + padding: 5px; +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 50px; + width: 50px; + border-radius: 2px; + background: #00edff; +} + +.range-slider input[type="range"]:after { + height: 2px; + background: #fff; + content: ' '; + width: 5px; + top: 50%; + margin-top: -1px; + left: -5px; + z-index: 1; + position: absolute; +} + +input[type=range]:focus { + outline: none; +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: xx-large; + font-weight: 700; + color: #00ffff; + align: center; + text-align: center; + position: relative; + top:50px; +} + +/* HTML5 Boilerplate radio-one hidden styles */ +[type="radio"] { + border: 0; + height: 1px; margin: -1px; + padding: 0; + position: absolute; + width: 1px; + display: none; +} + +/* One radio button per line */ +label { + display: block; + cursor: pointer; /*hand view when on hover*/ + line-height: 2.5; + font-size: 1.5em; +} + +/* the basic, unchecked style */ +[type="radio"] + span:before { + content: ''; + display: inline-block; + width: 1em; + height: 1em; + vertical-align: -0.25em; + border-radius: 1em; /*hard border*/ + border: 0.125em solid #00ffff; + margin-right: 0.75em; +} + +/* the checked style using the :checked pseudo class */ +[type="radio"]:checked + span:before { + background: #00ffff; +} diff --git a/libraries/logicBlocks/invertMotor/index.js b/libraries/logicBlocks/invertMotor/index.js new file mode 100755 index 0000000..ba1cf41 --- /dev/null +++ b/libraries/logicBlocks/invertMotor/index.js @@ -0,0 +1,86 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "invert Motor", + blockSize : 1, + privateData : {}, + publicData : {}, + activeInputs : [true, false, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["in", "", "", ""], + nameOutput : ["out", "", "", ""], + type : "invertMotor" +}; + +var switchValue = 0; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +exports.render = function (object, node, block, index, thisBlock, callback) { + + for (var key in thisBlock.data[0]) { + if (key === "value") { + thisBlock.processedData[0].value = thisBlock.data[0].value * -1; + } + } + callback(object, node, block, index, thisBlock); +}; \ No newline at end of file diff --git a/libraries/logicBlocks/multiply/gui/icon.svg b/libraries/logicBlocks/multiply/gui/icon.svg new file mode 100644 index 0000000..306ead6 --- /dev/null +++ b/libraries/logicBlocks/multiply/gui/icon.svg @@ -0,0 +1,10 @@ + + + + + + icon + + A B + + \ No newline at end of file diff --git a/libraries/logicBlocks/multiply/gui/index.html b/libraries/logicBlocks/multiply/gui/index.html new file mode 100644 index 0000000..f00e318 --- /dev/null +++ b/libraries/logicBlocks/multiply/gui/index.html @@ -0,0 +1,12 @@ + + + + + Setup Slider + + + + + + + diff --git a/libraries/logicBlocks/multiply/gui/label.svg b/libraries/logicBlocks/multiply/gui/label.svg new file mode 100644 index 0000000..0a1e6a5 --- /dev/null +++ b/libraries/logicBlocks/multiply/gui/label.svg @@ -0,0 +1,25 @@ + + + + + + + label + + + + + + + + + + + + A B + + \ No newline at end of file diff --git a/libraries/logicBlocks/multiply/gui/style.css b/libraries/logicBlocks/multiply/gui/style.css new file mode 100644 index 0000000..e69de29 diff --git a/libraries/logicBlocks/multiply/index.js b/libraries/logicBlocks/multiply/index.js new file mode 100755 index 0000000..343922d --- /dev/null +++ b/libraries/logicBlocks/multiply/index.js @@ -0,0 +1,96 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "multiply", + blockSize : 2, + privateData : {}, + publicData : {}, + activeInputs : [true, true, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["A", "B", "", ""], + nameOutput : ["A * B", "", "", ""], + type : "multiply" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + var product = 0; + // add value from A + if (thisBlock.data[0].value && thisBlock.data[1].value) { + product = thisBlock.data[0].value * thisBlock.data[1].value; + } + // constrain sum to 0-1 range + product = Math.max(0, Math.min(1, product)); + + for (var key in thisBlock.data[0]) { + thisBlock.processedData[0][key] = thisBlock.data[0][key]; + } + + console.log(product); + + thisBlock.processedData[0].value = product; + + callback(object, node, block, index, thisBlock); +}; \ No newline at end of file diff --git a/libraries/logicBlocks/scale/gui/icon.svg b/libraries/logicBlocks/scale/gui/icon.svg new file mode 100644 index 0000000..03d9cff --- /dev/null +++ b/libraries/logicBlocks/scale/gui/icon.svg @@ -0,0 +1 @@ +_ \ No newline at end of file diff --git a/libraries/logicBlocks/scale/gui/index.html b/libraries/logicBlocks/scale/gui/index.html new file mode 100644 index 0000000..6147819 --- /dev/null +++ b/libraries/logicBlocks/scale/gui/index.html @@ -0,0 +1,49 @@ + + + + + Setup Slider + + + + +
+ + + + diff --git a/libraries/logicBlocks/scale/gui/label.svg b/libraries/logicBlocks/scale/gui/label.svg new file mode 100644 index 0000000..ee4e120 --- /dev/null +++ b/libraries/logicBlocks/scale/gui/label.svg @@ -0,0 +1 @@ +_ \ No newline at end of file diff --git a/libraries/logicBlocks/scale/gui/style.css b/libraries/logicBlocks/scale/gui/style.css new file mode 100644 index 0000000..497202c --- /dev/null +++ b/libraries/logicBlocks/scale/gui/style.css @@ -0,0 +1,53 @@ +body { + background-color: dimgray; +} +input[type=range] { + background-color: transparent; + -webkit-appearance: none; + +} + +input[type=range]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 68px; /* Must add six because this width includes the border */ + background-color: rgba(255, 255, 255, 0); + -webkit-backdrop-filter: blur(4px); + border: solid 4px #00edff; + border-radius: 8px; + padding: 5px; +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 50px; + width: 50px; + border-radius: 2px; + background: #00edff; +} + +.range-slider input[type="range"]:after { + height: 2px; + background: #fff; + content: ' '; + width: 5px; + top: 50%; + margin-top: -1px; + left: -5px; + z-index: 1; + position: absolute; +} + +input[type=range]:focus { + outline: none; +} +.number { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: xx-large; + font-weight: 700; + color: #00ffff; + align: center; + text-align: center; + position: relative; + top:50px; +} \ No newline at end of file diff --git a/libraries/logicBlocks/scale/index.js b/libraries/logicBlocks/scale/index.js new file mode 100755 index 0000000..894ff14 --- /dev/null +++ b/libraries/logicBlocks/scale/index.js @@ -0,0 +1,91 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "scale", + blockSize : 1, + privateData : {}, + publicData : {scale : 1}, + activeInputs : [true, false, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["in", "", "", ""], + nameOutput : ["out", "", "", ""], + type : "scale" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + for (var key in thisBlock.data[0]) { + if(key === "value"){ + console.log(thisBlock.data[0][key]); + thisBlock.processedData[0][key] = thisBlock.data[0][key] * thisBlock.publicData.scale; + } else { + thisBlock.processedData[0][key] = thisBlock.data[0][key]; + } + } + + callback(object, node, block, index, thisBlock); + +}; diff --git a/libraries/logicBlocks/seesaw/gui/icon.svg b/libraries/logicBlocks/seesaw/gui/icon.svg new file mode 100644 index 0000000..c3e33f1 --- /dev/null +++ b/libraries/logicBlocks/seesaw/gui/icon.svg @@ -0,0 +1 @@ +_ \ No newline at end of file diff --git a/libraries/logicBlocks/seesaw/gui/index.html b/libraries/logicBlocks/seesaw/gui/index.html new file mode 100644 index 0000000..38fe671 --- /dev/null +++ b/libraries/logicBlocks/seesaw/gui/index.html @@ -0,0 +1,11 @@ + + + + + Setup Slider + + + + + + diff --git a/libraries/logicBlocks/seesaw/gui/label.svg b/libraries/logicBlocks/seesaw/gui/label.svg new file mode 100644 index 0000000..880e60b --- /dev/null +++ b/libraries/logicBlocks/seesaw/gui/label.svg @@ -0,0 +1,51 @@ + + + + +_ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/libraries/logicBlocks/seesaw/gui/style.css b/libraries/logicBlocks/seesaw/gui/style.css new file mode 100644 index 0000000..f9dcf3b --- /dev/null +++ b/libraries/logicBlocks/seesaw/gui/style.css @@ -0,0 +1,88 @@ +body { + background-color: dimgray; +} +input[type=range] { + background-color: transparent; + -webkit-appearance: none; + +} + +input[type=range]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 68px; /* Must add six because this width includes the border */ + background-color: rgba(255, 255, 255, 0); + -webkit-backdrop-filter: blur(4px); + border: solid 4px #00edff; + border-radius: 8px; + padding: 5px; +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 50px; + width: 50px; + border-radius: 2px; + background: #00edff; +} + +.range-slider input[type="range"]:after { + height: 2px; + background: #fff; + content: ' '; + width: 5px; + top: 50%; + margin-top: -1px; + left: -5px; + z-index: 1; + position: absolute; +} + +input[type=range]:focus { + outline: none; +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: xx-large; + font-weight: 700; + color: #00ffff; + align: center; + text-align: center; + position: relative; + top:50px; +} + +/* HTML5 Boilerplate radio-one hidden styles */ +[type="radio"] { + border: 0; + height: 1px; margin: -1px; + padding: 0; + position: absolute; + width: 1px; + display: none; +} + +/* One radio button per line */ +label { + display: block; + cursor: pointer; /*hand view when on hover*/ + line-height: 2.5; + font-size: 1.5em; +} + +/* the basic, unchecked style */ +[type="radio"] + span:before { + content: ''; + display: inline-block; + width: 1em; + height: 1em; + vertical-align: -0.25em; + border-radius: 1em; /*hard border*/ + border: 0.125em solid #00ffff; + margin-right: 0.75em; +} + +/* the checked style using the :checked pseudo class */ +[type="radio"]:checked + span:before { + background: #00ffff; +} diff --git a/libraries/logicBlocks/seesaw/index.js b/libraries/logicBlocks/seesaw/index.js new file mode 100755 index 0000000..e613f45 --- /dev/null +++ b/libraries/logicBlocks/seesaw/index.js @@ -0,0 +1,112 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "seesaw", + blockSize : 3, + privateData : {}, + publicData : {toggle: true}, + activeInputs : [true, true, true, false], + activeOutputs : [true, true, true, false], + iconImage : "icon.png", + nameInput : ["in", "in", "in", ""], + nameOutput : ["digital out", "digital out", "out", ""], + type : "seesaw" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + if (index === 0) { + if(thisBlock.data[0].value > 0.5 ){ + if(thisBlock.publicData.toggle !== false) { + + thisBlock.publicData.toggle = false; + thisBlock.processedData[0].value = 1; + thisBlock.processedData[1].value = 0; + return callback(object, node, block, index, thisBlock); + + } + } + } + + else if (index === 1) { + if(thisBlock.data[1].value > 0.5 ){ + if(thisBlock.publicData.toggle !== true) { + + thisBlock.publicData.toggle = true; + thisBlock.processedData[0].value = 0; + thisBlock.processedData[1].value = 1; + return callback(object, node, block, index, thisBlock); + } + } + + } else if (index === 2) { + + if (thisBlock.publicData.toggle === true) { + thisBlock.processedData[2] = thisBlock.data[2]; + return callback(object, node, block, index, thisBlock); + } + } + +}; \ No newline at end of file diff --git a/libraries/logicBlocks/switch/gui/icon.svg b/libraries/logicBlocks/switch/gui/icon.svg new file mode 100644 index 0000000..d319e5b --- /dev/null +++ b/libraries/logicBlocks/switch/gui/icon.svg @@ -0,0 +1 @@ +icon \ No newline at end of file diff --git a/libraries/logicBlocks/switch/gui/index.html b/libraries/logicBlocks/switch/gui/index.html new file mode 100644 index 0000000..d169a20 --- /dev/null +++ b/libraries/logicBlocks/switch/gui/index.html @@ -0,0 +1,58 @@ + + + + + Setup Slider + + + + +
+ + + +
+ + + diff --git a/libraries/logicBlocks/switch/gui/label.svg b/libraries/logicBlocks/switch/gui/label.svg new file mode 100644 index 0000000..2ee6b6f --- /dev/null +++ b/libraries/logicBlocks/switch/gui/label.svg @@ -0,0 +1 @@ +label \ No newline at end of file diff --git a/libraries/logicBlocks/switch/gui/style.css b/libraries/logicBlocks/switch/gui/style.css new file mode 100644 index 0000000..f9dcf3b --- /dev/null +++ b/libraries/logicBlocks/switch/gui/style.css @@ -0,0 +1,88 @@ +body { + background-color: dimgray; +} +input[type=range] { + background-color: transparent; + -webkit-appearance: none; + +} + +input[type=range]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 68px; /* Must add six because this width includes the border */ + background-color: rgba(255, 255, 255, 0); + -webkit-backdrop-filter: blur(4px); + border: solid 4px #00edff; + border-radius: 8px; + padding: 5px; +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 50px; + width: 50px; + border-radius: 2px; + background: #00edff; +} + +.range-slider input[type="range"]:after { + height: 2px; + background: #fff; + content: ' '; + width: 5px; + top: 50%; + margin-top: -1px; + left: -5px; + z-index: 1; + position: absolute; +} + +input[type=range]:focus { + outline: none; +} +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: xx-large; + font-weight: 700; + color: #00ffff; + align: center; + text-align: center; + position: relative; + top:50px; +} + +/* HTML5 Boilerplate radio-one hidden styles */ +[type="radio"] { + border: 0; + height: 1px; margin: -1px; + padding: 0; + position: absolute; + width: 1px; + display: none; +} + +/* One radio button per line */ +label { + display: block; + cursor: pointer; /*hand view when on hover*/ + line-height: 2.5; + font-size: 1.5em; +} + +/* the basic, unchecked style */ +[type="radio"] + span:before { + content: ''; + display: inline-block; + width: 1em; + height: 1em; + vertical-align: -0.25em; + border-radius: 1em; /*hard border*/ + border: 0.125em solid #00ffff; + margin-right: 0.75em; +} + +/* the checked style using the :checked pseudo class */ +[type="radio"]:checked + span:before { + background: #00ffff; +} diff --git a/libraries/logicBlocks/switch/index.js b/libraries/logicBlocks/switch/index.js new file mode 100755 index 0000000..b605bd2 --- /dev/null +++ b/libraries/logicBlocks/switch/index.js @@ -0,0 +1,115 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "switch", + blockSize : 2, + privateData : {}, + publicData : {switchType : "toggle", switch: false, toggle: false}, + activeInputs : [true, true, false, false], + activeOutputs : [true, true, false, false], + iconImage : "icon.png", + nameInput : ["in", "stream in", "", ""], + nameOutput : ["out", "stream out", "", ""], + type : "switch" +}; + +var switchValue = 0; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + if(thisBlock.publicData.switchType === "toggle"){ + + if(thisBlock.data[0].value > 0.5 ){ + if(thisBlock.publicData.toggle !== true) { + thisBlock.publicData.toggle = true; + + thisBlock.publicData.switch = !thisBlock.publicData.switch; + + } + } else { + thisBlock.publicData.toggle = false; + } + + } else { + if(thisBlock.data[0].value > 0.5){ + thisBlock.publicData.switch = true; + } else { + thisBlock.publicData.switch = false; + } + } + + if(thisBlock.publicData.switch) { + for (var key in thisBlock.data[index]) { + thisBlock.processedData[index][key] = thisBlock.data[index][key]; + } + + if (index === 0) thisBlock.processedData[index].value = 1; + } + else { + thisBlock.processedData[index].value = 0; + } + + callback(object, node, block, index, thisBlock); +}; diff --git a/libraries/logicBlocks/threshold/gui/icon.svg b/libraries/logicBlocks/threshold/gui/icon.svg new file mode 100644 index 0000000..f2fb274 --- /dev/null +++ b/libraries/logicBlocks/threshold/gui/icon.svg @@ -0,0 +1 @@ +icon \ No newline at end of file diff --git a/libraries/logicBlocks/threshold/gui/index.html b/libraries/logicBlocks/threshold/gui/index.html new file mode 100644 index 0000000..11557df --- /dev/null +++ b/libraries/logicBlocks/threshold/gui/index.html @@ -0,0 +1,99 @@ + + + + + Setup Slider + + + + +
0 ms
+
+ + +
+ + + +
+ +
+ + + +
+ + + + diff --git a/libraries/logicBlocks/threshold/gui/label.svg b/libraries/logicBlocks/threshold/gui/label.svg new file mode 100644 index 0000000..ca20e1d --- /dev/null +++ b/libraries/logicBlocks/threshold/gui/label.svg @@ -0,0 +1 @@ +label \ No newline at end of file diff --git a/libraries/logicBlocks/threshold/gui/style.css b/libraries/logicBlocks/threshold/gui/style.css new file mode 100644 index 0000000..ef59383 --- /dev/null +++ b/libraries/logicBlocks/threshold/gui/style.css @@ -0,0 +1,100 @@ +body { + background-color: dimgray; +} +input[type=range] { + background-color: transparent; + -webkit-appearance: none; + +} + +input[type=range]::-webkit-slider-runnable-track { + -webkit-appearance: none; + height: 68px; /* Must add six because this width includes the border */ + background-color: rgba(255, 255, 255, 0); + -webkit-backdrop-filter: blur(4px); + border: solid 4px #00edff; + border-radius: 8px; + padding: 5px; +} + +input[type=range]::-webkit-slider-thumb { + -webkit-appearance: none; + border: none; + height: 50px; + width: 50px; + border-radius: 2px; + background: #00edff; +} + +.range-slider input[type="range"]:after { + height: 2px; + background: #fff; + content: ' '; + width: 5px; + top: 50%; + margin-top: -1px; + left: -5px; + z-index: 1; + position: absolute; +} + +input[type=range]:focus { + outline: none; +} +#number { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: xx-large; + font-weight: 700; + color: #00ffff; + align: center; + text-align: center; + position: relative; + top:0px; +} + + +body { + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: xx-large; + font-weight: 700; + color: #00ffff; + align: center; + text-align: center; + position: relative; + top:10px; +} + +/* HTML5 Boilerplate radio-one hidden styles */ +[type="radio"] { + border: 0; + height: 1px; margin: -1px; + padding: 0; + position: absolute; + width: 1px; + display: none; +} + +/* One radio button per line */ +label { + display: block; + cursor: pointer; /*hand view when on hover*/ + line-height: 1; + font-size: xx-large; +} + +/* the basic, unchecked style */ +[type="radio"] + span:before { + content: ''; + display: inline-block; + width: 0.5em; + height: 0.5em; + vertical-align: -0.25em; + border-radius: 1em; /*hard border*/ + border: 0.125em solid #00ffff; + margin-right: 0.75em; +} + +/* the checked style using the :checked pseudo class */ +[type="radio"]:checked + span:before { + background: #00ffff; +} diff --git a/libraries/logicBlocks/threshold/index.js b/libraries/logicBlocks/threshold/index.js new file mode 100755 index 0000000..71227e1 --- /dev/null +++ b/libraries/logicBlocks/threshold/index.js @@ -0,0 +1,115 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var generalProperties = { + name : "threshold", + blockSize : 1, + privateData : {}, + publicData : {threshold : 0.5, direction:">", digital:true}, + activeInputs : [true, false, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["stream in", "", "", ""], + nameOutput : ["stream out", "", "", ""], + type : "threshold" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + + +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + // check orientations and calculate if threshold is meet. + var pass = false; + if(thisBlock.publicData.direction === ">") + { + if(thisBlock.data[0].value > thisBlock.publicData.threshold){ + pass = true; + } + } else if(thisBlock.publicData.direction === "<") + { + if(thisBlock.data[0].value < thisBlock.publicData.threshold){ + pass = true; + } + } + + for ( var key in thisBlock.data[0]) { + thisBlock.processedData[0][key] = thisBlock.data[0][key]; + } + + // calculate final output + if(pass){ + if(thisBlock.publicData.digital){ + thisBlock.processedData[0].value = 1; + callback(object, node, block, index, thisBlock); + + } + } else { + thisBlock.processedData[0].value = 0; + callback(object, node, block, index, thisBlock); + + } + + if(!thisBlock.publicData.digital){ + + callback(object, node, block, index, thisBlock); + } +}; \ No newline at end of file diff --git a/libraries/logicBlocks/webPost/gui/icon.svg b/libraries/logicBlocks/webPost/gui/icon.svg new file mode 100644 index 0000000..52c84ce --- /dev/null +++ b/libraries/logicBlocks/webPost/gui/icon.svg @@ -0,0 +1,13 @@ + + + + + + icon + POST + + + + + + \ No newline at end of file diff --git a/libraries/logicBlocks/webPost/gui/index.html b/libraries/logicBlocks/webPost/gui/index.html new file mode 100644 index 0000000..990dca7 --- /dev/null +++ b/libraries/logicBlocks/webPost/gui/index.html @@ -0,0 +1,54 @@ + + + + + + Setup Slider + + + + + +
+ This will make a post request to the specified URL
+ with the body: { blockData: _array_with_one_value_ } +
+ +
+ Current Endpoint:
+
+ +
+ + + + diff --git a/libraries/logicBlocks/webPost/gui/label.svg b/libraries/logicBlocks/webPost/gui/label.svg new file mode 100644 index 0000000..b1d3df9 --- /dev/null +++ b/libraries/logicBlocks/webPost/gui/label.svg @@ -0,0 +1,18 @@ + + + + + + + label + + + + + + POST + \ No newline at end of file diff --git a/libraries/logicBlocks/webPost/gui/style.css b/libraries/logicBlocks/webPost/gui/style.css new file mode 100644 index 0000000..ce72d50 --- /dev/null +++ b/libraries/logicBlocks/webPost/gui/style.css @@ -0,0 +1,37 @@ +body { + background-color: dimgray; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #00ffff; + text-align: center; + width: 506px; + word-wrap: break-word; +} + +#description { + margin: 30px 40px 30px 40px; +} + +#interaction { + margin: 0 40px 0 40px; +} + +#endpointTextField { + width: 70%; + text-align: center; + font-size: 16px; + height: 30px; +} + +.code { + font-family: monospace; +} + +.placeholder { + font-style: italic; +} + +#updateButton { + width: 100px; + height: 30px; + margin: 10px; +} \ No newline at end of file diff --git a/libraries/logicBlocks/webPost/index.js b/libraries/logicBlocks/webPost/index.js new file mode 100755 index 0000000..fa5a428 --- /dev/null +++ b/libraries/logicBlocks/webPost/index.js @@ -0,0 +1,105 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var request = require('request'); + +var generalProperties = { + name : "webPost", + blockSize : 1, + privateData : {}, + publicData : {endpointUrl : "http://192.168.1.12:8082/test"}, + activeInputs : [true, false, false, false], + activeOutputs : [true, false, false, false], + iconImage : "icon.png", + nameInput : ["in", "", "", ""], + nameOutput : ["out", "", "", ""], + type : "webPost" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + // data flows through it like normal + for (var key in thisBlock.data[index]) { + thisBlock.processedData[index][key] = thisBlock.data[index][key]; + } + + // BUT ALSO: makes a post request to the server endpoint configured in publicData + if (index === 0) { + + console.log("making post request to " + JSON.stringify(thisBlock.publicData)); + + request.post( + thisBlock.publicData.endpointUrl, + { json: {blockData: thisBlock.processedData} }, + function (error, response, body) { + if (!error && response.statusCode == 200) { + console.log(body); + } + } + ); + + } + + callback(object, node, block, index, thisBlock); +}; diff --git a/libraries/logicBlocks/webPost2/gui/icon.svg b/libraries/logicBlocks/webPost2/gui/icon.svg new file mode 100644 index 0000000..f25db6e --- /dev/null +++ b/libraries/logicBlocks/webPost2/gui/icon.svg @@ -0,0 +1,18 @@ + + + + + + icon + POST + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/logicBlocks/webPost2/gui/index.html b/libraries/logicBlocks/webPost2/gui/index.html new file mode 100644 index 0000000..cc84c9f --- /dev/null +++ b/libraries/logicBlocks/webPost2/gui/index.html @@ -0,0 +1,54 @@ + + + + + + Setup Slider + + + + + +
+ This will make a post request to the specified URL
+ with the body: { blockData: _array_with_two_values_ } +
+ +
+ Current Endpoint:
+
+ +
+ + + + diff --git a/libraries/logicBlocks/webPost2/gui/label.svg b/libraries/logicBlocks/webPost2/gui/label.svg new file mode 100644 index 0000000..fef6f45 --- /dev/null +++ b/libraries/logicBlocks/webPost2/gui/label.svg @@ -0,0 +1,23 @@ + + + + + + + label + + + + + + POST + + + + + + \ No newline at end of file diff --git a/libraries/logicBlocks/webPost2/gui/style.css b/libraries/logicBlocks/webPost2/gui/style.css new file mode 100644 index 0000000..ce72d50 --- /dev/null +++ b/libraries/logicBlocks/webPost2/gui/style.css @@ -0,0 +1,37 @@ +body { + background-color: dimgray; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + color: #00ffff; + text-align: center; + width: 506px; + word-wrap: break-word; +} + +#description { + margin: 30px 40px 30px 40px; +} + +#interaction { + margin: 0 40px 0 40px; +} + +#endpointTextField { + width: 70%; + text-align: center; + font-size: 16px; + height: 30px; +} + +.code { + font-family: monospace; +} + +.placeholder { + font-style: italic; +} + +#updateButton { + width: 100px; + height: 30px; + margin: 10px; +} \ No newline at end of file diff --git a/libraries/logicBlocks/webPost2/index.js b/libraries/logicBlocks/webPost2/index.js new file mode 100755 index 0000000..5420843 --- /dev/null +++ b/libraries/logicBlocks/webPost2/index.js @@ -0,0 +1,106 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var request = require('request'); + +var generalProperties = { + name : "webPost2", + blockSize : 2, + privateData : {}, + publicData : {endpointUrl : "http://192.168.1.12:8082/test2"}, + activeInputs : [true, true, false, false], + activeOutputs : [true, true, false, false], + iconImage : "icon.png", + nameInput : ["in", "in", "", ""], + nameOutput : ["out", "out", "", ""], + type : "webPost2" +}; + +exports.properties = generalProperties; + +exports.setup = function (object,logic, block, activeBlockProperties){ +// add code here that should be executed once. + +}; + +//var logicAPI = require(__dirname + '/../../libraries/logicInterfaces'); + +exports.render = function (object, node, block, index, thisBlock, callback) { + + // data flows through it like normal + for (var key in thisBlock.data[index]) { + thisBlock.processedData[index][key] = thisBlock.data[index][key]; + } + + // BUT ALSO: makes a post request to the server endpoint configured in publicData + if (index === 1) { + + console.log("making post request to " + JSON.stringify(thisBlock.publicData)); + + request.post( + thisBlock.publicData.endpointUrl, + { json: {blockData: thisBlock.processedData} }, + function (error, response, body) { + if (!error && response.statusCode == 200) { + console.log(body); + } + } + ); + + } + + + callback(object, node, block, index, thisBlock); +}; diff --git a/libraries/logicInterfaces.js b/libraries/logicInterfaces.js new file mode 100644 index 0000000..11f5cb3 --- /dev/null +++ b/libraries/logicInterfaces.js @@ -0,0 +1,48 @@ + + +// Todo this are just some thoughts about the API + +exports.writePublicData = function () { }; +exports.writePrivateData = function () { }; + +exports.readPublicData = function () { }; +exports.readPrivateData = function () { }; + +exports.shape = function () { }; + +exports.activeInputs = function () { }; +exports.activeInputs = function () { }; + + + +this.name = ""; + +this.x = null; +this.y = null; +// amount of elements the IO point is created of. Single IO nodes have the size 1. +this.blockSize = 1; +// the global / world wide id of the actual reference block design. +this.globalId = null; +// the checksum should be identical with the checksum for the persistent package files of the reference block design. +this.checksum = null; // checksum of the files for the program +// data for logic blocks. depending on the blockSize which one is used. +this.item = [new Data(), new Data(), new Data(), new Data()]; +// experimental. This are objects for data storage. Maybe it makes sense to store data in the general object +// this would allow the the packages to be persistent. // todo discuss usability with Ben. +this.privateData = {}; +this.publicData = {}; + +// IO for logic +// define how many inputs are active. +this.activeInputs = [true, false, false, false]; +// define how many outputs are active. +this.activeOutputs = [true, false, false, false]; +// define the names of each active IO +this.nameInput = ["", "", "", ""]; +this.nameOutput = ["", "", "", ""]; +// A specific icon for the node, png or jpg. +this.iconImage = null; +// Text within the node, if no icon is available. +this.text = ""; +// indicates how much calls per second is happening on this block +this.stress = 0; \ No newline at end of file diff --git a/libraries/nodes/default_temp_disabled/gui/index.html b/libraries/nodes/default_temp_disabled/gui/index.html new file mode 100755 index 0000000..8c940aa --- /dev/null +++ b/libraries/nodes/default_temp_disabled/gui/index.html @@ -0,0 +1,88 @@ + + + + + + IO + + + +
+ +
+
+ + + + \ No newline at end of file diff --git a/libraries/nodes/default_temp_disabled/index.js b/libraries/nodes/default_temp_disabled/index.js new file mode 100755 index 0000000..0f93ede --- /dev/null +++ b/libraries/nodes/default_temp_disabled/index.js @@ -0,0 +1,78 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ +var outputData = {}; +exports.render = function (objectID, linkID, inputData, callback) { + var outputData = outputData; + var key; + for (var key in inputData) { + outputData[key] = inputData[key]; + } + + callback(objectID, linkID, outputData); +}; + +/* // example for delay + exports.render = function (objectID, linkID, inputData, callback) { + var outputData = {}; + for(key in inputData) + { + outputData[key] = inputData[key]; + } + + setTimeout(function() { + callback(objectID, linkPositionID, outputData); + }, 1000); + }; + */ diff --git a/libraries/nodes/invisible/gui/index.html b/libraries/nodes/invisible/gui/index.html new file mode 100755 index 0000000..06dcfa7 --- /dev/null +++ b/libraries/nodes/invisible/gui/index.html @@ -0,0 +1,81 @@ + + + + + + IO + + + +
+ +
+ + + \ No newline at end of file diff --git a/libraries/nodes/invisible/index.js b/libraries/nodes/invisible/index.js new file mode 100755 index 0000000..d024fed --- /dev/null +++ b/libraries/nodes/invisible/index.js @@ -0,0 +1,77 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {number} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +exports.render = function (objectID, linkID, inputData, callback) { + var outputData = {}; + var key; + for (key in inputData) { + outputData[key] = inputData[key]; + } + callback(objectID, linkID, outputData); +}; + +/* // example for delay + exports.render = function (objectID, linkID, inputData, callback) { + var outputData = {}; + for(key in inputData) + { + outputData[key] = inputData[key]; + } + + setTimeout(function() { + callback(objectID, linkPositionID, outputData); + }, 1000); + }; + */ diff --git a/libraries/nodes/logic/gui/index.html b/libraries/nodes/logic/gui/index.html new file mode 100755 index 0000000..8c940aa --- /dev/null +++ b/libraries/nodes/logic/gui/index.html @@ -0,0 +1,88 @@ + + + + + + IO + + + +
+ +
+
+ + + + \ No newline at end of file diff --git a/libraries/nodes/logic/index.js b/libraries/nodes/logic/index.js new file mode 100755 index 0000000..a88800a --- /dev/null +++ b/libraries/nodes/logic/index.js @@ -0,0 +1,82 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {number} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +/** + + [callbacks] + + */ + +exports.render = function (objectID, linkID, inputData, callback) { + var outputData = {}; + var key; + for (key in inputData) { + outputData[key] = inputData[key]; + } + callback(objectID, linkID, outputData); +}; +/* // example for delay + exports.render = function (objectID, linkID, inputData, callback) { + var outputData = {}; + for(key in inputData) + { + outputData[key] = inputData[key]; + } + + setTimeout(function() { + callback(objectID, linkPositionID, outputData); + }, 1000); + }; + */ diff --git a/libraries/nodes/node/gui/index.html b/libraries/nodes/node/gui/index.html new file mode 100755 index 0000000..8c940aa --- /dev/null +++ b/libraries/nodes/node/gui/index.html @@ -0,0 +1,88 @@ + + + + + + IO + + + +
+ +
+
+ + + + \ No newline at end of file diff --git a/libraries/nodes/node/index.js b/libraries/nodes/node/index.js new file mode 100755 index 0000000..b22c264 --- /dev/null +++ b/libraries/nodes/node/index.js @@ -0,0 +1,77 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/** + * @desc prototype for a plugin. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkID the id of the link that is related to the call + * @param {object} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +exports.render = function (object, node, thisNode, callback) { + + for (var key in thisNode.data) { + thisNode.processedData[key] = thisNode.data[key]; + } + + callback(object, node, thisNode); +}; + +/* // example for delay + exports.render = function (objectID, linkID, inputData, callback) { + var outputData = {}; + for(key in inputData) + { + outputData[key] = inputData[key]; + } + + setTimeout(function() { + callback(objectID, linkPositionID, outputData); + }, 1000); + }; + */ diff --git a/libraries/objectDefaultFiles/bird.png b/libraries/objectDefaultFiles/bird.png new file mode 100755 index 0000000..9a5a9be Binary files /dev/null and b/libraries/objectDefaultFiles/bird.png differ diff --git a/libraries/objectDefaultFiles/index.html b/libraries/objectDefaultFiles/index.html new file mode 100755 index 0000000..b581f8f --- /dev/null +++ b/libraries/objectDefaultFiles/index.html @@ -0,0 +1,12 @@ + + + + +Default UI + + + + + + + diff --git a/libraries/objectDefaultFiles/object.css b/libraries/objectDefaultFiles/object.css new file mode 100755 index 0000000..525224b --- /dev/null +++ b/libraries/objectDefaultFiles/object.css @@ -0,0 +1,6 @@ +body, html{ + height: 100%; margin:0; padding:0; +} +img{ + display: block; +} \ No newline at end of file diff --git a/libraries/objectDefaultFiles/object.js b/libraries/objectDefaultFiles/object.js new file mode 100644 index 0000000..4be1755 --- /dev/null +++ b/libraries/objectDefaultFiles/object.js @@ -0,0 +1,768 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var realityObject = { + node: "", + object: "", + logic: "", + block: "", + publicData: {}, + modelViewMatrix: [], + projectionMatrix: [], + visibility: "visible", + sendMatrix: false, + sendAcceleration: false, + sendFullScreen: false, + height: "100%", + width: "100%", + socketIoScript: {}, + socketIoRequest: {}, + style: document.createElement('style'), + messageCallBacks: {}, + interface : "gui", + version: 200 +}; + +// adding css styles nessasary for acurate 3D transformations. +realityObject.style.type = 'text/css'; +realityObject.style.innerHTML = 'body, html{ height: 100%; margin:0; padding:0;}'; +document.getElementsByTagName('head')[0].appendChild(realityObject.style); + +// Load socket.io.js synchronous so that it is available by the time the rest of the code is executed. +realityObject.socketIoRequest = new XMLHttpRequest(); +realityObject.socketIoRequest.open('GET', "/socket.io/socket.io.js", false); +realityObject.socketIoRequest.send(); + +//Only add script if fetch was successful +if (realityObject.socketIoRequest.status == 200) { + realityObject.socketIoScript = document.createElement('script'); + realityObject.socketIoScript.type = "text/javascript"; + realityObject.socketIoScript.text = realityObject.socketIoRequest.responseText; + document.getElementsByTagName('head')[0].appendChild(realityObject.socketIoScript); +} else { + console.log("Error XMLHttpRequest HTTP status: " + realityObject.socketIoRequest.status); +} + +/** + ************************************************************ + */ + +// function for resizing the windows. + +window.addEventListener("message", function (MSG) { + + var msgContent = JSON.parse(MSG.data); + for (var key in realityObject.messageCallBacks) { + realityObject.messageCallBacks[key](msgContent); + } +}, false); + +realityObject.messageCallBacks.mainCall = function (msgContent) { + + console.log("------------------------------"); + console.log(msgContent); + + if (typeof msgContent.node !== "undefined") { + + if (realityObject.sendFullScreen === false) { + realityObject.height = document.body.scrollHeight; + realityObject.width = document.body.scrollWidth; + } + + parent.postMessage(JSON.stringify( + { + version: realityObject.version, + node: msgContent.node, + object: msgContent.object, + height: realityObject.height, + width: realityObject.width, + sendMatrix: realityObject.sendMatrix, + sendAcceleration: realityObject.sendAcceleration, + fullScreen: realityObject.sendFullScreen + } + ) + // this needs to contain the final interface source + , "*"); + + realityObject.node = msgContent.node; + realityObject.object = msgContent.object; + } + else if (typeof msgContent.logic !== "undefined") { + + + parent.postMessage(JSON.stringify( + { + version: realityObject.version, + block: msgContent.block, + logic: msgContent.logic, + object: msgContent.object, + publicData: msgContent.publicData + } + ) + // this needs to contain the final interface source + , "*"); + + realityObject.block = msgContent.block; + realityObject.logic = msgContent.logic; + realityObject.object = msgContent.object; + realityObject.publicData = msgContent.publicData; + } + + if (typeof msgContent.modelViewMatrix !== "undefined") { + realityObject.modelViewMatrix = msgContent.modelViewMatrix; + } + + if (typeof msgContent.projectionMatrix !== "undefined") { + realityObject.projectionMatrix = msgContent.projectionMatrix; + } + + if (typeof msgContent.visibility !== "undefined") { + realityObject.visibility = msgContent.visibility; + } + + if (typeof msgContent.interface !== "undefined") { + realityObject.interface = msgContent.interface + } +}; + +/** + ************************************************************ + */ + +function HybridObject() { + + /** + ************************************************************ + */ + + this.sendGlobalMessage = function (ohMSG) { + if (typeof realityObject.node !== "undefined") { + var msgg = JSON.stringify( + { + version: realityObject.version, + node: realityObject.node, + object: realityObject.object, + globalMessage: ohMSG + }); + window.parent.postMessage(msgg + , "*"); + } + }; + + /** + ************************************************************ + */ + + this.addGlobalMessageListener = function (callback) { + + realityObject.messageCallBacks.gloablMessageCall = function (msgContent) { + if (typeof msgContent.globalMessage !== "undefined") { + callback(msgContent.globalMessage); + } + }; + }; + + /** + ************************************************************ + */ + + this.addMatrixListener = function (callback) { + realityObject.messageCallBacks.matrixCall = function (msgContent) { + if (typeof msgContent.modelViewMatrix !== "undefined") { + callback(msgContent.modelViewMatrix, realityObject.projectionMatrix); + } + } + }; + + this.addAccelerationListener = function (callback) { + console.log("got this"); + realityObject.messageCallBacks.AccelerationCall = function (msgContent) { + if (typeof msgContent.acceleration !== "undefined") { + callback(msgContent.acceleration); + } + } + }; + + + /** + ************************************************************ + */ + // subscriptions + this.subscribeToMatrix = function () { + realityObject.sendMatrix = true; + if (typeof realityObject.node !== "undefined") { + + if (realityObject.sendFullScreen === false) { + realityObject.height = document.body.scrollHeight; + realityObject.width = document.body.scrollWidth; + } + + parent.postMessage(JSON.stringify( + { + version: realityObject.version, + node: realityObject.node, + object: realityObject.object, + height: realityObject.height, + width: realityObject.width, + sendMatrix: realityObject.sendMatrix, + sendAcceleration: realityObject.sendAcceleration, + fullScreen: realityObject.sendFullScreen + }), "*"); + } + }; + + // subscriptions + this.subscribeToAcceleration = function () { + realityObject.sendAcceleration = true; + if (typeof realityObject.node !== "undefined") { + parent.postMessage(JSON.stringify( + { + version: realityObject.version, + node: realityObject.node, + object: realityObject.object, + height: realityObject.height, + width: realityObject.width, + sendMatrix: realityObject.sendMatrix, + sendAcceleration: realityObject.sendAcceleration, + fullScreen: realityObject.sendFullScreen + }), "*"); + } + }; + + + + /** + ************************************************************ + */ + + this.setFullScreenOn = function () { + realityObject.sendFullScreen = true; + console.log("fullscreen is loaded"); + if (typeof realityObject.node !== "undefined") { + + realityObject.height = "100%"; + realityObject.width = "100%"; + + parent.postMessage(JSON.stringify( + { + version: realityObject.version, + node: realityObject.node, + object: realityObject.object, + height: realityObject.height, + width: realityObject.width, + sendMatrix: realityObject.sendMatrix, + sendAcceleration: realityObject.sendAcceleration, + fullScreen: realityObject.sendFullScreen + }), "*"); + } + }; + + /** + ************************************************************ + */ + + this.setFullScreenOff = function () { + realityObject.sendFullScreen = false; + if (typeof realityObject.node !== "undefined") { + + realityObject.height = document.body.scrollHeight; + realityObject.width = document.body.scrollWidth; + + parent.postMessage(JSON.stringify( + { + version: realityObject.version, + node: realityObject.node, + object: realityObject.object, + height: realityObject.height, + width: realityObject.width, + sendMatrix: realityObject.sendMatrix, + sendAcceleration: realityObject.sendAcceleration, + fullScreen: realityObject.sendFullScreen + }), "*"); + } + }; + + /** + ************************************************************ + */ + + this.getVisibility = function () { + return realityObject.visibility; + }; + + /** + ************************************************************ + */ + + this.addVisibilityListener = function (callback) { + realityObject.messageCallBacks.visibilityCall = function (msgContent) { + if (typeof msgContent.visibility !== "undefined") { + callback(msgContent.visibility); + } + }; + }; + + + /** + ************************************************************ + */ + + this.getInterface= function () { + return realityObject.interface; + }; + + /** + ************************************************************ + */ + + this.addInterfaceListener = function (callback) { + realityObject.messageCallBacks.interfaceCall = function (msgContent) { + if (typeof msgContent.interface !== "undefined" && typeof msgContent.search === "undefined") { + callback(msgContent.interface, null); + } else if (typeof msgContent.interface !== "undefined" && typeof msgContent.search !== "undefined") { + callback(msgContent.interface, msgContent.search); + } + }; + }; + + /** + ************************************************************ + */ + + this.search = function (ingredients, userList) { + for (var key in userList) { + + if (userList[key].state === false) { + if(typeof ingredients[key] !== "undefined"){ + if(ingredients[key].state === true){ + return false; + } + } + } + + if (userList[key].state === true) { + if(typeof ingredients[key] !== "undefined"){ + if(ingredients[key].state === false){ + return false; + } + } else return false; + } + } + return true; + } + + this.getPossitionX = function () { + if (typeof realityObject.modelViewMatrix[12] !== "undefined") { + return realityObject.modelViewMatrix[12]; + } else return undefined; + }; + + /** + ************************************************************ + */ + + this.getPossitionY = function () { + if (typeof realityObject.modelViewMatrix[13] !== "undefined") { + return realityObject.modelViewMatrix[13]; + } else return undefined; + }; + + /** + ************************************************************ + */ + + this.getPossitionZ = function () { + if (typeof realityObject.modelViewMatrix[14] !== "undefined") { + return realityObject.modelViewMatrix[14]; + } else return undefined; + }; + + /** + ************************************************************ + */ + + this.getProjectionMatrix = function () { + if (typeof realityObject.projectionMatrix !== "undefined") { + return realityObject.projectionMatrix; + } else return undefined; + }; + + /** + ************************************************************ + */ + + this.getModelViewMatrix = function () { + if (typeof realityObject.modelViewMatrix !== "undefined") { + return realityObject.modelViewMatrix; + } else return undefined; + }; + + if (typeof io !== "undefined") { + var _this = this; + + this.ioObject = io.connect(); + this.oldValueList = {}; + + this.sendEealityEditorSubscribe = setInterval(function () { + if (realityObject.object) { + _this.ioObject.emit('/subscribe/realityEditor', JSON.stringify({object: realityObject.object, protocol: realityObject.protocol})); + clearInterval(_this.sendEealityEditorSubscribe); + } + }, 10); + + /** + ************************************************************ + */ + + + this.write = function (node, value, mode, unit, unitMin, unitMax) { + if (!mode) mode = "f"; + if (!unit) unit = false; + if (!unitMin) unitMin = 0; + if (!unitMax) unitMax = 1; + + var thisData = {value: value, mode: mode, unit: unit, unitMin: unitMin, unitMax: unitMax}; + if (!node in _this.oldValueList) { + _this.oldValueList[node] = null; + } + + if (_this.oldValueList[node] !== value) { + this.ioObject.emit('object', JSON.stringify({ + object: realityObject.object, + node: realityObject.object+node, + data: thisData + })); + } + _this.oldValueList[node] = value; + }; + + /** + ************************************************************ + */ + + this.readRequest = function (node) { + this.ioObject.emit('/object/readRequest', JSON.stringify({object: realityObject.object, node: realityObject.object+node})); + }; + + /** + ************************************************************ + */ + + this.read = function (node, msg) { + if (msg.node === realityObject.object+node) { + return msg.data.value; + } else { + return undefined; + } + }; + + /** + ************************************************************ + */ + + this.addReadListener = function (node, callback) { + _this.ioObject.on("object", function (msg) { + var thisMsg = JSON.parse(msg); + if (typeof thisMsg.node !== "undefined") { + if (thisMsg.node === realityObject.object+node) { + if (typeof thisMsg.data !== "undefined") + callback(thisMsg.data.value); + } + } + }); + }; + + console.log("socket.io is loaded"); + } + else { + + /** + ************************************************************ + */ + this.ioObject = { + on: function (x, cb) { + } + }; + + /** + ************************************************************ + */ + this.write = function (node, value, mode) { + }; + + /** + ************************************************************ + */ + this.read = function (node, data) { + return undefined; + }; + + /** + ************************************************************ + */ + this.readRequest = function (node) { + }; + + /** + ************************************************************ + */ + this.addReadListener = function (node, callback) { + + }; + + console.log("socket.io is not working. This is normal when you work offline."); + } +} + +// these are functions used for the setup of logic blocks + +function HybridLogic() { + this.publicData = realityObject.publicData; + + + + this.readPublicData = function (valueName, value) { + if (!value) value = 0; + + if (typeof realityObject.publicData[valueName] === "undefined") { + realityObject.publicData[valueName] = value; + return value; + } else { + return realityObject.publicData[valueName]; + } + }; + + if (typeof io !== "undefined") { + var _this = this; + + this.ioObject = io.connect(); + this.oldValueList = {}; + + this.addReadPublicDataListener = function (valueName, callback) { + + _this.ioObject.on("block", function (msg) { + var thisMsg = JSON.parse(msg); + if (typeof thisMsg.publicData !== "undefined") { + if (typeof thisMsg.publicData[valueName] !== "undefined") { + callback(thisMsg.publicData[valueName]); + } + } + }); + }; + + + + this.sendEealityEditorSubscribe = setInterval(function () { + if (realityObject.object) { + _this.ioObject.emit('/subscribe/realityEditorBlock', JSON.stringify( + { + object: realityObject.object, + logic:realityObject.logic, + block: realityObject.block + })); + clearInterval(_this.sendEealityEditorSubscribe); + } + }, 10); + + /** + ************************************************************ + */ + + this.writePublicData = function (valueName, value) { + + realityObject.publicData[valueName] = value; + + this.ioObject.emit('block/publicData', JSON.stringify({ + object: realityObject.object, + logic: realityObject.logic, + block: realityObject.block, + publicData: realityObject.publicData + })); + + parent.postMessage(JSON.stringify( + { + version: realityObject.version, + block: realityObject.block, + logic: realityObject.logic, + object: realityObject.object, + publicData: realityObject.publicData + } + ), "*"); + }; + + this.writePrivateData = function (valueName, value) { + + var thisItem = {}; + thisItem[valueName] = value; + + this.ioObject.emit('block/privateData', JSON.stringify({ + object: realityObject.object, + logic: realityObject.logic, + block: realityObject.block, + privateData: thisItem + })); + }; + + console.log("socket.io is loaded"); + } + else { + + this.addReadPublicDataListener = function (valueName, callback) { + + realityObject.messageCallBacks.updateLogicGUI = function (msgContent) { + if (typeof msgContent.publicData !== "undefined") { + if (typeof msgContent.publicData[valueName] !== "undefined") { + callback(msgContent.publicData[valueName]); + } + } + }; + }; + + /** + ************************************************************ + */ + this.ioObject = { + on: function (x, cb) { + } + }; + + /** + ************************************************************ + */ + this.writePrivateData = function (valueName, value) { + }; + + /** + ************************************************************ + */ + this.writePublicData = function (valueName, value) { + }; + + console.log("socket.io is not working. This is normal when you work offline."); + } + +} + +document.addEventListener('DOMContentLoaded', function() { + var touchTimer = null; + var sendTouchEvents = false; + var startCoords = { + x: 0, + y: 0 + }; + var touchMoveTolerance = 100; + + function getTouchX(event) { + return event.changedTouches[0].screenX; + } + + function getTouchY(event) { + return event.changedTouches[0].screenY; + } + + function sendTouchEvent(event) { + parent.postMessage(JSON.stringify({ + version: realityObject.version, + node: realityObject.node, + object: realityObject.object, + touchEvent: { + type: event.type, + x: getTouchX(event), + y: getTouchY(event) + } + }), '*'); + } + + document.body.addEventListener('touchstart', function() { + if (!realityObject.width) { + return; + } + + if (touchTimer) { + return; + } + + startCoords.x = getTouchX(event); + startCoords.y = getTouchY(event); + + touchTimer = setTimeout(function() { + parent.postMessage(JSON.stringify({ + version: realityObject.version, + node: realityObject.node, + object: realityObject.object, + beginTouchEditing: true + }), '*'); + sendTouchEvents = true; + touchTimer = null; + }, 400); + }); + + document.body.addEventListener('touchmove', function(event) { + if (sendTouchEvents) { + sendTouchEvent(event); + } else if (touchTimer) { + var dx = getTouchX(event) - startCoords.x; + var dy = getTouchY(event) - startCoords.y; + if (dx * dx + dy * dy > touchMoveTolerance) { + clearTimeout(touchTimer); + touchTimer = null; + } + } + }); + + document.body.addEventListener('touchend', function(event) { + if (sendTouchEvents) { + sendTouchEvent(event); + } + clearTimeout(touchTimer); + touchTimer = null; + }); + + window.addEventListener('message', function (msg) { + var msgContent = JSON.parse(msg.data); + if (msgContent.stopTouchEditing) { + sendTouchEvents = false; + } + }); +}, false); diff --git a/libraries/utilities.js b/libraries/utilities.js new file mode 100644 index 0000000..36d844d --- /dev/null +++ b/libraries/utilities.js @@ -0,0 +1,284 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + + + +/** + * @desc prototype for a source. This prototype is called when a value should be changed. + * It defines how this value should be transformed before sending it to the destination. + * @param {object} objectID Origin object in which the related link is saved. + * @param {string} linkPositionID the id of the link that is related to the call + * @param {value} inputData the data that needs to be processed + * @param {function} callback the function that is called for when the process is rendered. + * @note the callback has the same structure then the initial prototype, however inputData has changed to outputData + **/ + +var debug = false; +var xml2js = require('xml2js'); +var fs = require('fs'); + +exports.writeObject = function (objectLookup, folder, id) { + objectLookup[folder] = {id: id}; +}; + +exports.readObject = function (objectLookup, folder) { + if (objectLookup.hasOwnProperty(folder)) { + return objectLookup[folder].id; + } else { + return null; + } +}; + +exports.createFolder = function (folderVar, dirnameO, debug) { + + var folder = dirnameO + '/objects/' + folderVar + '/'; + if (debug) console.log("Creating folder: " + folder); + + if (!fs.existsSync(folder)) { + fs.mkdirSync(folder, "0766", function (err) { + if (err) { + console.log(err); + res.send("ERROR! Can't make the directory! \n"); // echo the result back + } + }); + + try { + // fs.createReadStream(__dirname + "/objects/object.css").pipe(fs.createWriteStream(__dirname + "/objects/" + folderVar + "/object.css")); + // fs.createReadStream(dirnameO + "/libraries/objectDefaultFiles/object.js").pipe(fs.createWriteStream(dirnameO + "/objects/" + folderVar + "/object.js")); + fs.createReadStream(dirnameO + "/libraries/objectDefaultFiles/index.html").pipe(fs.createWriteStream(dirnameO + "/objects/" + folderVar + "/index.html")); + fs.createReadStream(dirnameO + "/libraries/objectDefaultFiles/bird.png").pipe(fs.createWriteStream(dirnameO + "/objects/" + folderVar + "/bird.png")); + + } catch (e) { + if (debug) console.log("Could not copy source files", e); + } + + // writeObjectToFile(tempFolderName); + } +}; + +/** + * Generates a random number between the two inputs, inclusive. + * @param {number} min - The minimum possible value. + * @param {number} max - The maximum possible value. + */ +exports.randomIntInc = function (min, max) { + return Math.floor(Math.random() * (max - min + 1) + min); +}; + +/** + * Generates a 12-digit unique identifier string, much of which is based on the current time. + */ +exports.uuidTime = function () { + var dateUuidTime = new Date(); + var abcUuidTime = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + var stampUuidTime = parseInt(Math.floor((Math.random() * 199) + 1) + "" + dateUuidTime.getTime()).toString(36); + while (stampUuidTime.length < 12) stampUuidTime = abcUuidTime.charAt(Math.floor(Math.random() * abcUuidTime.length)) + stampUuidTime; + return stampUuidTime; +}; + +exports.getObjectIdFromTarget = function (folderName, dirnameO) { + + var xmlFile = dirnameO + '/objects/' + folderName + '/target/target.xml'; + + if (fs.existsSync(xmlFile)) { + var resultXML = ""; + xml2js. + Parser(). + parseString(fs.readFileSync(xmlFile, "utf8"), + function (err, result) { + for (var first in result) { + resultXML = result[first].Tracking[0].ImageTarget[0].$.name; + break; + } + }); + + return resultXML; + } else { + return null; + } +}; + +/** + * Saves the HybridObject as "object.json" + * + * @param {object} objects - The array of objects + * @param {string} object - The key used to look up the object in the objects array + * @param {string} dirnameO - The base directory name in which an "objects" directory resides. + **/ +exports.writeObjectToFile = function (objects, object, dirnameO) { +console.log("start saving"); + var outputFilename = dirnameO + '/objects/' + objects[object].name + '/object.json'; + fs.writeFile(outputFilename, JSON.stringify(objects[object], null, '\t'), function (err) { + if (err) { + console.log(err); + } else { + console.log("JSON saved to " + outputFilename); + } + }); +}; + +var crcTable = [0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]; + + +var crc = 0xffffffff; + +function crc32(data) { + for(var i=0, l=data.length; i>> 8 ^ crcTable[ crc & 255 ^ data[i] ]; + } + return (crc ^ -1) >>> 0; +} + + +function crc16reset(){ + crc = 0xffffffff; +} + +function itob62(i) { + var u = i; + var b32 = ""; + do + { + var d = Math.floor(u % 62); + if (d < 10) { + + b32 = String.fromCharCode('0'.charCodeAt(0) + d) + b32; + } + else if (d < 36) { + b32 = String.fromCharCode('a'.charCodeAt(0) + d - 10) + b32; + } else { + b32 = String.fromCharCode('A'.charCodeAt(0) + d - 36) + b32; + } + + u = Math.floor(u / 62); + + } while (u > 0); + + return b32; +} + +/** + * @desc Generates a checksum of all files hand over with fileArray + * @param objects hand over the overall object list + * @param fileArray The array that represents all files that should be checksumed + * @return + **/ + +exports.genereateChecksums = function (objects,fileArray) { + crc16reset(); + var checksumText; + for(i = 0; i< fileArray.length; i++) + { + if(fs.existsSync(fileArray[i])) { + checksumText = itob62(crc32(fs.readFileSync(fileArray[i]))); + } + } + console.log("created Checksum: " + checksumText); +return checksumText; +}; \ No newline at end of file diff --git a/libraries/webFrontend.js b/libraries/webFrontend.js new file mode 100644 index 0000000..b328d7b --- /dev/null +++ b/libraries/webFrontend.js @@ -0,0 +1,979 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + + +var utilities = require(__dirname+'/utilities'); +var fs = require('fs'); +var changeCase = require('change-case'); +var debug = false; +var pathUtilities = require('path'); + + + +exports.printFolder = function (objects, dirnameO, debug, objectInterfaceName, objectLookup, version) { + var resText = "" + + "" + + "" + + "" + + "" + + ' \n' + + ' \n' + + // ""+ + "" + + '' +// background:repeating-linear-gradient(-45deg, #e4f6ff, #e4f6ff 5px, white 5px, white 10px);" >\n'+ + "
" + + + "
" + + "
" + + "

Hybrid Object - Administration                Version: "+version+"

" + + "
" + + + + "
" + + "
    "; + + + var tempFiles = ""; + var objectPath = dirnameO + "/objects"; + var tempFiles = fs.readdirSync(objectPath).filter(function (file) { + return fs.statSync(objectPath + '/' + file).isDirectory(); + }); + + if (debug) { + console.log("----------------------- objects"); + for (var keykey in objects) { + console.log(keykey); + } + + console.log("----------------------- objects"); + for (var keykey in objects) { + console.log(keykey); + } + + console.log("----------------------- object lookup"); + + for (var keykey in objectLookup) { + console.log(keykey + " = " + JSON.stringify(objectLookup[keykey])); + } + console.log("----------------------- end" + Math.random()); + } + // remove hidden directories + if (typeof tempFiles[0] !== "undefined") { + while (tempFiles[0][0] === ".") { + tempFiles.splice(0, 1); + } + + for (var i = 0; i < tempFiles.length; i++) { + resText += "
  • " + + "
    " + + "
    " + + "" + tempFiles[i] + "" + + "
    " + + "
    "; + + if (objects.hasOwnProperty(utilities.readObject(objectLookup, tempFiles[i])) && fs.existsSync(objectPath + "/" + tempFiles[i] + "/target/target.xml")) { + resText += + " "; + } else { + resText += + " "; + } + + + resText += " " + + " "; + + var thisObject = utilities.readObject(objectLookup, tempFiles[i]); + + if (objects.hasOwnProperty(thisObject)) { + if(objects[thisObject].deactivated !== true) { + resText += " "; + } + else{ + resText += " "; + } + + } else { + resText += " "; + } + + resText += + + // "
    "+ + // "
    "+ + + // "
    " + + ' ' + + "
    " + + "" + + "" + + " " + + "
    "; + + resText += + //"
    "+ + "
    " + + "
  • "; + + + } + + } + + resText += + "
" + + "
" + + "
" + + "" + + "" + + "
" + + "
" + + " " + + "
" + + "
" + + "
" + + ' ' + + ' ' + + + 'Upload Object' + + + '' + + ' ' + + + '

' + + '
' + + '
' + + '
' + + '
' + + "
" + + + + ' ' + + "
" + + + // "upload default files"+ + + + ' '; + + resText += ""; + return resText; + +} + +exports.uploadInfoText = function (parm, objectLookup, objects, knownObjects, socketsInfo) { + var objectName = utilities.readObject(objectLookup, parm); //parm + thisMacAddress; + + var ArduinoINstance = 0; + + for (subKey in objects) { + if (subKey === objectName) { + break; + } + ArduinoINstance++; + } + var text = '\n' + + '\n' + + ''+ + ' \n' + + ' \n' + + '\n' + + '\n' + + '
\n' + + '
\n' + + '
\n' + + '

Hybrid Object - ' + parm + ' - Info    back

\n' + + '
\n' + + '
\n' + +'
'+ + +''+ + '
\n' + + '\n' + + '\n' + + ''; + + + return text; + + + // var tempFolderName = tempFiles[i] + macAddress.replace(/:/gi, ''); + + // fill objects with objects named by the folders in objects + // objects[tempFolderName] = new ObjectExp(); + // objects[tempFolderName].name = tempFiles[i]; +} + + +exports.uploadInfoContent = function (parm, objectLookup, objects, knownObjects, socketsInfo) { + var objectName = utilities.readObject(objectLookup, parm); //parm + thisMacAddress; + + + var uploadInfoTexttempArray = objects[objectName].links; + var uploadInfoTexttempArrayValue = objects[objectName].nodes; + + var ArduinoINstance = 0; + + // objects[objectName] + + for (subKey in objects) { + if (subKey === objectName) { + break; + } + ArduinoINstance++; + } + var text = + '
\n' + + '
\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n'; + + var protocolText = ""; + if(objects[objectName].protocol === "R0") protocolText = "R0 over WebSocket"; + if(objects[objectName].protocol === "R1") protocolText = "R1 over WebSocket"; + + var infoCount = 0; + for (var subKey in uploadInfoTexttempArrayValue) { + + var thisHtmlNode = uploadInfoTexttempArrayValue[subKey]; + + + if(thisHtmlNode.name === "") thisHtmlNode.name = "LOGIC"; + + if(typeof thisHtmlNode.routeBuffer !== "undefined" && thisHtmlNode.routeBuffer !== null && thisHtmlNode.type === "logic") { + + text += ""; + } else { + if(!thisHtmlNode.text) { + text += ""; + } else { + text += ""; + } + + } + + + + infoCount++; + + + + + } + + if (infoCount === 0) { + text += ""; + } + + text += + ' \n' + + '
IndexI/O NameValue
" + infoCount + "" + thisHtmlNode.name + "" + thisHtmlNode.routeBuffer[0] + "
" + + "" + thisHtmlNode.routeBuffer[1] + "
" + + "" + thisHtmlNode.routeBuffer[2] + "
" + + "" + thisHtmlNode.routeBuffer[3] + "
" + infoCount + "" + thisHtmlNode.name + "" + thisHtmlNode.data.value + "
" + infoCount + "" + thisHtmlNode.text + "" + thisHtmlNode.data.value + "
- -
\n' + + '
\n' + + '
\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + /* '\n'+ + ' \n'+ + ' \n'+ + ' \n'+*/ + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '
Object Information
Arduino Instance'+ArduinoINstance+'
Ip' + objects[objectName].ip + '
Version' + objects[objectName].version + '
Protocol' + protocolText+ '
Amount of Sockets' + socketsInfo.sockets + '
Connected' + socketsInfo.connected + '
Disconnected' + socketsInfo.notConnected + '
\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n'; + + + infoCount = 0; + for (subKey in knownObjects) { + text += '' + + ''; + infoCount++; + } + + if (infoCount === 0) { + text += ""; + } + + text += + ' \n' + + '
Known ObjectsVersion        IP        Protocol
' + subKey + '' + knownObjects[subKey].version+ '     ' +knownObjects[subKey].ip+ '     ' +knownObjects[subKey].protocol+ '
no Object found
\n' + + '
\n' + + '
\n' + + + '
\n' + + '
\n' + + + '
\n' + + '
\n' + + + '
\n' + + '
\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n'; + + + infoCount = 0; + for (subKey in uploadInfoTexttempArray) { + if(uploadInfoTexttempArray[subKey].hasOwnProperty("namesA")) + text += '\n'; + else + text += '\n'; + + infoCount++; + } + + if (infoCount === 0) { + text += ""; + } + + text += + ' \n' + + '
Active Link IDOrigin ObjectOrigin NodeDestination Object\n' + + ' Destination Node
' + subKey + '' + uploadInfoTexttempArray[subKey].namesA[0] + '' + uploadInfoTexttempArray[subKey].namesA[1] + '' + uploadInfoTexttempArray[subKey].namesB[0] + '' + uploadInfoTexttempArray[subKey].namesB[1] + '
' + subKey + '' + uploadInfoTexttempArray[subKey].objectA + '' + uploadInfoTexttempArray[subKey].nodeA + '' + uploadInfoTexttempArray[subKey].objectB + '' + uploadInfoTexttempArray[subKey].nodeB + '
no Link found
\n' + + '
\n' + + '
\n' + + ''; + + + return text; + + + // var tempFolderName = tempFiles[i] + macAddress.replace(/:/gi, ''); + + // fill objects with objects named by the folders in objects + // objects[tempFolderName] = new ObjectExp(); + // objects[tempFolderName].name = tempFiles[i]; +}; + + + +exports.uploadTargetText = function (parm, objectLookup, objects) { + if(debug) console.log("target content"); + var objectName = ""; + if (objects.hasOwnProperty(utilities.readObject(objectLookup, parm))) { + + objectName = utilities.readObject(objectLookup, parm); + } else { + objectName = parm + utilities.uuidTime(); + } + + var text = '\n' + + '\n' + + '\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '\n' + + '\n' + + '
\n' + + '
\n' + + '
\n' + + '

Hybrid Object - ' + parm + ' - Target    back

\n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' 1. Upload your target source image (jpg only, < 0.5 MB)
' + + ' 2. Login to the Vuforia Target Manager.
' + + ' 3. Create a new or open a Device Databases.
' + + ' 4. Create a target for your Object and name it exactly:
    ' + objectName + '
' + + ' 5. Make sure that only this one Target is Activated.
' + + ' 6. Download the database and then upload it here:
' + + ' (You can just drag and drop the files anywhere in the striped area)' + + '
' + + '
' + + ' ' + + ' ' + + ' ' + + ' ' + + '

' + + '
' + + '
' + + '
' + + '
' + + ' ' + + '  Upload Target zip and jpg Files ' + + ' ' + + '
' + + '
' + + ' ' + + ' ' + + '
' + + '' + + '' + + '' + + + + ''; + + return text; + +} + + + + +exports.uploadTargetContent = function (parm, dirname0, objectInterfaceName) { + if(debug) console.log("interface content"); + var text = + + ''; + + var objectPath = dirname0 + "/objects/"; + + var objectPath2 = dirname0 + "/objects/" + parm; + + var tempFiles = fs.readdirSync(objectPath).filter(function (file) { + return fs.statSync(objectPath + '/' + file).isDirectory(); + }); + + + var fileList; + // List all files in a directory in Node.js recursively in a synchronous fashion + /* var walkSync = function(dir, filelist) { + var fs = fs || require('fs'), + files = fs.readdirSync(dir); + filelist = filelist || []; + files.forEach(function(file) { + if (fs.statSync(dir + '/' + file).isDirectory()) { + filelist = walkSync(dir +'/'+ file + '/', filelist); + folderDepth++; + filelist.push("<"); + filelist.push(file); + } + else { + if(file[0] !== "." ) + filelist.push(file); + } + } + ); + if(folderDepth !==0){ + filelist.push(">");} + + return filelist; + };*/ + + var walk = function (dir) { + var results = []; + var list = fs.readdirSync(dir); + list.forEach(function (file) { + file = dir + '/' + file; + var stat = fs.statSync(file); + if (stat && stat.isDirectory()) results = results.concat(walk(file)); + else results.push(file) + }); + return results + }; + + var listeliste = walk(objectPath2); + + // var folderContent = walkSync(objectPath,fileList); + var nameSpace = ""; + + + var nameOrigin = "/obj/"; + + var llist; + + var nameOld = ""; + + text += + '\n' + + '\n' + + '\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + '\n' + + '\n' + + '
\n' + + '
\n' + + '
\n' + + '

Hybrid Object - ' + parm + ' - File    back

\n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n' + + ' \n'; + + + for (var i = 0; i < listeliste.length; i++) { + + var content = listeliste[i].replace(objectPath2 + '/', '').split("/"); + + if (content[1] !== undefined) { + if (content[0] !== nameOld) { + + // console.log("---" + content[0]); + + text += ''; + + } + // console.log("-"+content[0]); + // console.log(content[0]+" / "+content[1]); + + if (content[1][0] !== "." && content[1][0] !== "_") { + if (debug)console.log(content[1]); + var fileTypeF = changeCase.lowerCase(content[1].split(".")[1]); + + text += '' + content[1] + ''; + } + + + nameOld = content[0]; + } else { + if (content[0][0] !== "." && content[0][0] !== "_") { + var fileTypeF2 = changeCase.lowerCase(content[0].split(".")[1]);//.toLowerCase(); + text += '' + content[0] + ''; + + } else { + text += 'delete'; + } + } + + } + + } + + text += + + '' + + '' + + ' \n' + + '
Object Folder
  ' + content[0] + ''; + + var dateiTobeRemoved = parm + '/' + content[0]; + text += "
" + + "" + + ""; + + text += 'delete
'; + + var dateiTobeRemoved = parm + '/' + content[0] + '/' + content[1]; + text += "
" + + "" + + ""; + if (debug) console.log(dateiTobeRemoved); + text += 'delete
'; + + var dateiTobeRemoved = parm + '/' + content[0]; + text += "
" + + "" + + ""; + + + if (content[0] === "object.json" || content[0] === "object.css" || content[0] === "object.js") { + text += 'delete
\n' + + '
\n' + + 'Drag and Drop your interface files anywhere on this window. Make sure that index.html is your startpoint.' + + ' You can drop all your files at the same time.

' + + 'object.json holds all relevant information about your object.
' + + + '

' + + '
' + + '
' + + '
' + + '
' + + ' ' + + "                " + + "Add Interface Files" + + "                " + + ' ' + + ' ' + + + ' ' + + ' ' + + '\n' + + '\n'; + + return text; + +}; + +exports.editContent = function(req, res) { + console.log(req.params); + var path = req.params[0]; + // TODO sanitize path for security + var file = pathUtilities.basename(path); + var context = {id: req.params.id, file: file, backUrl: '/content/' + req.params.id, path: path}; + res.render('edit', context); +}; diff --git a/libraries/webInterface/LICENSE_BOOTSTRAP b/libraries/webInterface/LICENSE_BOOTSTRAP new file mode 100644 index 0000000..9858866 --- /dev/null +++ b/libraries/webInterface/LICENSE_BOOTSTRAP @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2011-2015 Twitter, Inc + +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. \ No newline at end of file diff --git a/libraries/webInterface/LICENSE_DROPZONE b/libraries/webInterface/LICENSE_DROPZONE new file mode 100644 index 0000000..ea0b20a --- /dev/null +++ b/libraries/webInterface/LICENSE_DROPZONE @@ -0,0 +1,20 @@ +The MIT License (MIT) + +Copyright (c) 2013 lev-kuznetsov + +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. \ No newline at end of file diff --git a/libraries/webInterface/LICENSE_ZEROCLIPBOARD b/libraries/webInterface/LICENSE_ZEROCLIPBOARD new file mode 100644 index 0000000..cfd4a0d --- /dev/null +++ b/libraries/webInterface/LICENSE_ZEROCLIPBOARD @@ -0,0 +1,8 @@ +MIT License +Copyright (c) 2009-2014 Jon Rohan, James M. Greene + +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. \ No newline at end of file diff --git a/libraries/webInterface/css/bootstrap-theme.min.css b/libraries/webInterface/css/bootstrap-theme.min.css new file mode 100644 index 0000000..cff38df --- /dev/null +++ b/libraries/webInterface/css/bootstrap-theme.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.1.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} \ No newline at end of file diff --git a/libraries/webInterface/css/bootstrap.min.css b/libraries/webInterface/css/bootstrap.min.css new file mode 100644 index 0000000..976dada --- /dev/null +++ b/libraries/webInterface/css/bootstrap.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.1.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none!important;color:#000!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) ")"}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}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}.list-inline>li:first-child{padding-left:0}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.428571429;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.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>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.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 col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=date]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.428571429;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:400;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.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;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.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;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top: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;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px;height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.428571429;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.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;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:gray}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;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{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group .list-group-item:first-child{border-top:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel>.list-group:first-child .list-group-item:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tfoot>tr:first-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tfoot>tr:first-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:first-child>td{border-top:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;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:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.428571429px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;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-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.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{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top .arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right .arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom .arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left .arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto;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:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none!important}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none!important}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none!important}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}@media print{.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none!important}} \ No newline at end of file diff --git a/libraries/webInterface/fonts/glyphicons-halflings-regular.eot b/libraries/webInterface/fonts/glyphicons-halflings-regular.eot new file mode 100644 index 0000000..b93a495 Binary files /dev/null and b/libraries/webInterface/fonts/glyphicons-halflings-regular.eot differ diff --git a/libraries/webInterface/fonts/glyphicons-halflings-regular.svg b/libraries/webInterface/fonts/glyphicons-halflings-regular.svg new file mode 100644 index 0000000..94fb549 --- /dev/null +++ b/libraries/webInterface/fonts/glyphicons-halflings-regular.svg @@ -0,0 +1,288 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/webInterface/fonts/glyphicons-halflings-regular.ttf b/libraries/webInterface/fonts/glyphicons-halflings-regular.ttf new file mode 100644 index 0000000..1413fc6 Binary files /dev/null and b/libraries/webInterface/fonts/glyphicons-halflings-regular.ttf differ diff --git a/libraries/webInterface/fonts/glyphicons-halflings-regular.woff b/libraries/webInterface/fonts/glyphicons-halflings-regular.woff new file mode 100644 index 0000000..9e61285 Binary files /dev/null and b/libraries/webInterface/fonts/glyphicons-halflings-regular.woff differ diff --git a/libraries/webInterface/fonts/glyphicons-halflings-regular.woff2 b/libraries/webInterface/fonts/glyphicons-halflings-regular.woff2 new file mode 100644 index 0000000..64539b5 Binary files /dev/null and b/libraries/webInterface/fonts/glyphicons-halflings-regular.woff2 differ diff --git a/libraries/webInterface/js/ZeroClipboard.js b/libraries/webInterface/js/ZeroClipboard.js new file mode 100755 index 0000000..136e4a9 --- /dev/null +++ b/libraries/webInterface/js/ZeroClipboard.js @@ -0,0 +1,1031 @@ +/*! +* ZeroClipboard +* The ZeroClipboard library provides an easy way to copy text to the clipboard using an invisible Adobe Flash movie and a JavaScript interface. +* Copyright (c) 2014 Jon Rohan, James M. Greene +* Licensed MIT +* http://zeroclipboard.org/ +* v1.3.5 +*/ +(function(window) { + "use strict"; + var currentElement; + var flashState = { + bridge: null, + version: "0.0.0", + disabled: null, + outdated: null, + ready: null + }; + var _clipData = {}; + var clientIdCounter = 0; + var _clientMeta = {}; + var elementIdCounter = 0; + var _elementMeta = {}; + var _amdModuleId = null; + var _cjsModuleId = null; + var _swfPath = function() { + var i, jsDir, tmpJsPath, jsPath, swfPath = "ZeroClipboard.swf"; + if (document.currentScript && (jsPath = document.currentScript.src)) {} else { + var scripts = document.getElementsByTagName("script"); + if ("readyState" in scripts[0]) { + for (i = scripts.length; i--; ) { + if (scripts[i].readyState === "interactive" && (jsPath = scripts[i].src)) { + break; + } + } + } else if (document.readyState === "loading") { + jsPath = scripts[scripts.length - 1].src; + } else { + for (i = scripts.length; i--; ) { + tmpJsPath = scripts[i].src; + if (!tmpJsPath) { + jsDir = null; + break; + } + tmpJsPath = tmpJsPath.split("#")[0].split("?")[0]; + tmpJsPath = tmpJsPath.slice(0, tmpJsPath.lastIndexOf("/") + 1); + if (jsDir == null) { + jsDir = tmpJsPath; + } else if (jsDir !== tmpJsPath) { + jsDir = null; + break; + } + } + if (jsDir !== null) { + jsPath = jsDir; + } + } + } + if (jsPath) { + jsPath = jsPath.split("#")[0].split("?")[0]; + swfPath = jsPath.slice(0, jsPath.lastIndexOf("/") + 1) + swfPath; + } + return swfPath; + }(); + var _camelizeCssPropName = function() { + var matcherRegex = /\-([a-z])/g, replacerFn = function(match, group) { + return group.toUpperCase(); + }; + return function(prop) { + return prop.replace(matcherRegex, replacerFn); + }; + }(); + var _getStyle = function(el, prop) { + var value, camelProp, tagName, possiblePointers, i, len; + if (window.getComputedStyle) { + value = window.getComputedStyle(el, null).getPropertyValue(prop); + } else { + camelProp = _camelizeCssPropName(prop); + if (el.currentStyle) { + value = el.currentStyle[camelProp]; + } else { + value = el.style[camelProp]; + } + } + if (prop === "cursor") { + if (!value || value === "auto") { + tagName = el.tagName.toLowerCase(); + if (tagName === "a") { + return "pointer"; + } + } + } + return value; + }; + var _elementMouseOver = function(event) { + if (!event) { + event = window.event; + } + var target; + if (this !== window) { + target = this; + } else if (event.target) { + target = event.target; + } else if (event.srcElement) { + target = event.srcElement; + } + ZeroClipboard.activate(target); + }; + var _addEventHandler = function(element, method, func) { + if (!element || element.nodeType !== 1) { + return; + } + if (element.addEventListener) { + element.addEventListener(method, func, false); + } else if (element.attachEvent) { + element.attachEvent("on" + method, func); + } + }; + var _removeEventHandler = function(element, method, func) { + if (!element || element.nodeType !== 1) { + return; + } + if (element.removeEventListener) { + element.removeEventListener(method, func, false); + } else if (element.detachEvent) { + element.detachEvent("on" + method, func); + } + }; + var _addClass = function(element, value) { + if (!element || element.nodeType !== 1) { + return element; + } + if (element.classList) { + if (!element.classList.contains(value)) { + element.classList.add(value); + } + return element; + } + if (value && typeof value === "string") { + var classNames = (value || "").split(/\s+/); + if (element.nodeType === 1) { + if (!element.className) { + element.className = value; + } else { + var className = " " + element.className + " ", setClass = element.className; + for (var c = 0, cl = classNames.length; c < cl; c++) { + if (className.indexOf(" " + classNames[c] + " ") < 0) { + setClass += " " + classNames[c]; + } + } + element.className = setClass.replace(/^\s+|\s+$/g, ""); + } + } + } + return element; + }; + var _removeClass = function(element, value) { + if (!element || element.nodeType !== 1) { + return element; + } + if (element.classList) { + if (element.classList.contains(value)) { + element.classList.remove(value); + } + return element; + } + if (value && typeof value === "string" || value === undefined) { + var classNames = (value || "").split(/\s+/); + if (element.nodeType === 1 && element.className) { + if (value) { + var className = (" " + element.className + " ").replace(/[\n\t]/g, " "); + for (var c = 0, cl = classNames.length; c < cl; c++) { + className = className.replace(" " + classNames[c] + " ", " "); + } + element.className = className.replace(/^\s+|\s+$/g, ""); + } else { + element.className = ""; + } + } + } + return element; + }; + var _getZoomFactor = function() { + var rect, physicalWidth, logicalWidth, zoomFactor = 1; + if (typeof document.body.getBoundingClientRect === "function") { + rect = document.body.getBoundingClientRect(); + physicalWidth = rect.right - rect.left; + logicalWidth = document.body.offsetWidth; + zoomFactor = Math.round(physicalWidth / logicalWidth * 100) / 100; + } + return zoomFactor; + }; + var _getDOMObjectPosition = function(obj, defaultZIndex) { + var info = { + left: 0, + top: 0, + width: 0, + height: 0, + zIndex: _getSafeZIndex(defaultZIndex) - 1 + }; + if (obj.getBoundingClientRect) { + var rect = obj.getBoundingClientRect(); + var pageXOffset, pageYOffset, zoomFactor; + if ("pageXOffset" in window && "pageYOffset" in window) { + pageXOffset = window.pageXOffset; + pageYOffset = window.pageYOffset; + } else { + zoomFactor = _getZoomFactor(); + pageXOffset = Math.round(document.documentElement.scrollLeft / zoomFactor); + pageYOffset = Math.round(document.documentElement.scrollTop / zoomFactor); + } + var leftBorderWidth = document.documentElement.clientLeft || 0; + var topBorderWidth = document.documentElement.clientTop || 0; + info.left = rect.left + pageXOffset - leftBorderWidth; + info.top = rect.top + pageYOffset - topBorderWidth; + info.width = "width" in rect ? rect.width : rect.right - rect.left; + info.height = "height" in rect ? rect.height : rect.bottom - rect.top; + } + return info; + }; + var _cacheBust = function(path, options) { + var cacheBust = options == null || options && options.cacheBust === true && options.useNoCache === true; + if (cacheBust) { + return (path.indexOf("?") === -1 ? "?" : "&") + "noCache=" + new Date().getTime(); + } else { + return ""; + } + }; + var _vars = function(options) { + var i, len, domain, str = [], domains = [], trustedOriginsExpanded = []; + if (options.trustedOrigins) { + if (typeof options.trustedOrigins === "string") { + domains.push(options.trustedOrigins); + } else if (typeof options.trustedOrigins === "object" && "length" in options.trustedOrigins) { + domains = domains.concat(options.trustedOrigins); + } + } + if (options.trustedDomains) { + if (typeof options.trustedDomains === "string") { + domains.push(options.trustedDomains); + } else if (typeof options.trustedDomains === "object" && "length" in options.trustedDomains) { + domains = domains.concat(options.trustedDomains); + } + } + if (domains.length) { + for (i = 0, len = domains.length; i < len; i++) { + if (domains.hasOwnProperty(i) && domains[i] && typeof domains[i] === "string") { + domain = _extractDomain(domains[i]); + if (!domain) { + continue; + } + if (domain === "*") { + trustedOriginsExpanded = [ domain ]; + break; + } + trustedOriginsExpanded.push.apply(trustedOriginsExpanded, [ domain, "//" + domain, window.location.protocol + "//" + domain ]); + } + } + } + if (trustedOriginsExpanded.length) { + str.push("trustedOrigins=" + encodeURIComponent(trustedOriginsExpanded.join(","))); + } + if (typeof options.jsModuleId === "string" && options.jsModuleId) { + str.push("jsModuleId=" + encodeURIComponent(options.jsModuleId)); + } + return str.join("&"); + }; + var _inArray = function(elem, array, fromIndex) { + if (typeof array.indexOf === "function") { + return array.indexOf(elem, fromIndex); + } + var i, len = array.length; + if (typeof fromIndex === "undefined") { + fromIndex = 0; + } else if (fromIndex < 0) { + fromIndex = len + fromIndex; + } + for (i = fromIndex; i < len; i++) { + if (array.hasOwnProperty(i) && array[i] === elem) { + return i; + } + } + return -1; + }; + var _prepClip = function(elements) { + if (typeof elements === "string") throw new TypeError("ZeroClipboard doesn't accept query strings."); + if (!elements.length) return [ elements ]; + return elements; + }; + var _dispatchCallback = function(func, context, args, async) { + if (async) { + window.setTimeout(function() { + func.apply(context, args); + }, 0); + } else { + func.apply(context, args); + } + }; + var _getSafeZIndex = function(val) { + var zIndex, tmp; + if (val) { + if (typeof val === "number" && val > 0) { + zIndex = val; + } else if (typeof val === "string" && (tmp = parseInt(val, 10)) && !isNaN(tmp) && tmp > 0) { + zIndex = tmp; + } + } + if (!zIndex) { + if (typeof _globalConfig.zIndex === "number" && _globalConfig.zIndex > 0) { + zIndex = _globalConfig.zIndex; + } else if (typeof _globalConfig.zIndex === "string" && (tmp = parseInt(_globalConfig.zIndex, 10)) && !isNaN(tmp) && tmp > 0) { + zIndex = tmp; + } + } + return zIndex || 0; + }; + var _deprecationWarning = function(deprecatedApiName, debugEnabled) { + if (deprecatedApiName && debugEnabled !== false && typeof console !== "undefined" && console && (console.warn || console.log)) { + var deprecationWarning = "`" + deprecatedApiName + "` is deprecated. See docs for more info:\n" + " https://github.com/zeroclipboard/zeroclipboard/blob/master/docs/instructions.md#deprecations"; + if (console.warn) { + console.warn(deprecationWarning); + } else { + console.log(deprecationWarning); + } + } + }; + var _extend = function() { + var i, len, arg, prop, src, copy, target = arguments[0] || {}; + for (i = 1, len = arguments.length; i < len; i++) { + if ((arg = arguments[i]) != null) { + for (prop in arg) { + if (arg.hasOwnProperty(prop)) { + src = target[prop]; + copy = arg[prop]; + if (target === copy) { + continue; + } + if (copy !== undefined) { + target[prop] = copy; + } + } + } + } + } + return target; + }; + var _extractDomain = function(originOrUrl) { + if (originOrUrl == null || originOrUrl === "") { + return null; + } + originOrUrl = originOrUrl.replace(/^\s+|\s+$/g, ""); + if (originOrUrl === "") { + return null; + } + var protocolIndex = originOrUrl.indexOf("//"); + originOrUrl = protocolIndex === -1 ? originOrUrl : originOrUrl.slice(protocolIndex + 2); + var pathIndex = originOrUrl.indexOf("/"); + originOrUrl = pathIndex === -1 ? originOrUrl : protocolIndex === -1 || pathIndex === 0 ? null : originOrUrl.slice(0, pathIndex); + if (originOrUrl && originOrUrl.slice(-4).toLowerCase() === ".swf") { + return null; + } + return originOrUrl || null; + }; + var _determineScriptAccess = function() { + var _extractAllDomains = function(origins, resultsArray) { + var i, len, tmp; + if (origins != null && resultsArray[0] !== "*") { + if (typeof origins === "string") { + origins = [ origins ]; + } + if (typeof origins === "object" && "length" in origins) { + for (i = 0, len = origins.length; i < len; i++) { + if (origins.hasOwnProperty(i)) { + tmp = _extractDomain(origins[i]); + if (tmp) { + if (tmp === "*") { + resultsArray.length = 0; + resultsArray.push("*"); + break; + } + if (_inArray(tmp, resultsArray) === -1) { + resultsArray.push(tmp); + } + } + } + } + } + } + }; + var _accessLevelLookup = { + always: "always", + samedomain: "sameDomain", + never: "never" + }; + return function(currentDomain, configOptions) { + var asaLower, allowScriptAccess = configOptions.allowScriptAccess; + if (typeof allowScriptAccess === "string" && (asaLower = allowScriptAccess.toLowerCase()) && /^always|samedomain|never$/.test(asaLower)) { + return _accessLevelLookup[asaLower]; + } + var swfDomain = _extractDomain(configOptions.moviePath); + if (swfDomain === null) { + swfDomain = currentDomain; + } + var trustedDomains = []; + _extractAllDomains(configOptions.trustedOrigins, trustedDomains); + _extractAllDomains(configOptions.trustedDomains, trustedDomains); + var len = trustedDomains.length; + if (len > 0) { + if (len === 1 && trustedDomains[0] === "*") { + return "always"; + } + if (_inArray(currentDomain, trustedDomains) !== -1) { + if (len === 1 && currentDomain === swfDomain) { + return "sameDomain"; + } + return "always"; + } + } + return "never"; + }; + }(); + var _objectKeys = function(obj) { + if (obj == null) { + return []; + } + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + keys.push(prop); + } + } + return keys; + }; + var _deleteOwnProperties = function(obj) { + if (obj) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + delete obj[prop]; + } + } + } + return obj; + }; + var _safeActiveElement = function() { + try { + return document.activeElement; + } catch (err) {} + return null; + }; + var _detectFlashSupport = function() { + var hasFlash = false; + if (typeof flashState.disabled === "boolean") { + hasFlash = flashState.disabled === false; + } else { + if (typeof ActiveXObject === "function") { + try { + if (new ActiveXObject("ShockwaveFlash.ShockwaveFlash")) { + hasFlash = true; + } + } catch (error) {} + } + if (!hasFlash && navigator.mimeTypes["application/x-shockwave-flash"]) { + hasFlash = true; + } + } + return hasFlash; + }; + function _parseFlashVersion(flashVersion) { + return flashVersion.replace(/,/g, ".").replace(/[^0-9\.]/g, ""); + } + function _isFlashVersionSupported(flashVersion) { + return parseFloat(_parseFlashVersion(flashVersion)) >= 10; + } + var ZeroClipboard = function(elements, options) { + if (!(this instanceof ZeroClipboard)) { + return new ZeroClipboard(elements, options); + } + this.id = "" + clientIdCounter++; + _clientMeta[this.id] = { + instance: this, + elements: [], + handlers: {} + }; + if (elements) { + this.clip(elements); + } + if (typeof options !== "undefined") { + _deprecationWarning("new ZeroClipboard(elements, options)", _globalConfig.debug); + ZeroClipboard.config(options); + } + this.options = ZeroClipboard.config(); + if (typeof flashState.disabled !== "boolean") { + flashState.disabled = !_detectFlashSupport(); + } + if (flashState.disabled === false && flashState.outdated !== true) { + if (flashState.bridge === null) { + flashState.outdated = false; + flashState.ready = false; + _bridge(); + } + } + }; + ZeroClipboard.prototype.setText = function(newText) { + if (newText && newText !== "") { + _clipData["text/plain"] = newText; + if (flashState.ready === true && flashState.bridge && typeof flashState.bridge.setText === "function") { + flashState.bridge.setText(newText); + } else { + flashState.ready = false; + } + } + return this; + }; + ZeroClipboard.prototype.setSize = function(width, height) { + if (flashState.ready === true && flashState.bridge && typeof flashState.bridge.setSize === "function") { + flashState.bridge.setSize(width, height); + } else { + flashState.ready = false; + } + return this; + }; + var _setHandCursor = function(enabled) { + if (flashState.ready === true && flashState.bridge && typeof flashState.bridge.setHandCursor === "function") { + flashState.bridge.setHandCursor(enabled); + } else { + flashState.ready = false; + } + }; + ZeroClipboard.prototype.destroy = function() { + this.unclip(); + this.off(); + delete _clientMeta[this.id]; + }; + var _getAllClients = function() { + var i, len, client, clients = [], clientIds = _objectKeys(_clientMeta); + for (i = 0, len = clientIds.length; i < len; i++) { + client = _clientMeta[clientIds[i]].instance; + if (client && client instanceof ZeroClipboard) { + clients.push(client); + } + } + return clients; + }; + ZeroClipboard.version = "1.3.5"; + var _globalConfig = { + swfPath: _swfPath, + trustedDomains: window.location.host ? [ window.location.host ] : [], + cacheBust: true, + forceHandCursor: false, + zIndex: 999999999, + debug: true, + title: null, + autoActivate: true + }; + ZeroClipboard.config = function(options) { + if (typeof options === "object" && options !== null) { + _extend(_globalConfig, options); + } + if (typeof options === "string" && options) { + if (_globalConfig.hasOwnProperty(options)) { + return _globalConfig[options]; + } + return; + } + var copy = {}; + for (var prop in _globalConfig) { + if (_globalConfig.hasOwnProperty(prop)) { + if (typeof _globalConfig[prop] === "object" && _globalConfig[prop] !== null) { + if ("length" in _globalConfig[prop]) { + copy[prop] = _globalConfig[prop].slice(0); + } else { + copy[prop] = _extend({}, _globalConfig[prop]); + } + } else { + copy[prop] = _globalConfig[prop]; + } + } + } + return copy; + }; + ZeroClipboard.destroy = function() { + ZeroClipboard.deactivate(); + for (var clientId in _clientMeta) { + if (_clientMeta.hasOwnProperty(clientId) && _clientMeta[clientId]) { + var client = _clientMeta[clientId].instance; + if (client && typeof client.destroy === "function") { + client.destroy(); + } + } + } + var htmlBridge = _getHtmlBridge(flashState.bridge); + if (htmlBridge && htmlBridge.parentNode) { + htmlBridge.parentNode.removeChild(htmlBridge); + flashState.ready = null; + flashState.bridge = null; + } + }; + ZeroClipboard.activate = function(element) { + if (currentElement) { + _removeClass(currentElement, _globalConfig.hoverClass); + _removeClass(currentElement, _globalConfig.activeClass); + } + currentElement = element; + _addClass(element, _globalConfig.hoverClass); + _reposition(); + var newTitle = _globalConfig.title || element.getAttribute("title"); + if (newTitle) { + var htmlBridge = _getHtmlBridge(flashState.bridge); + if (htmlBridge) { + htmlBridge.setAttribute("title", newTitle); + } + } + var useHandCursor = _globalConfig.forceHandCursor === true || _getStyle(element, "cursor") === "pointer"; + _setHandCursor(useHandCursor); + }; + ZeroClipboard.deactivate = function() { + var htmlBridge = _getHtmlBridge(flashState.bridge); + if (htmlBridge) { + htmlBridge.style.left = "0px"; + htmlBridge.style.top = "-9999px"; + htmlBridge.removeAttribute("title"); + } + if (currentElement) { + _removeClass(currentElement, _globalConfig.hoverClass); + _removeClass(currentElement, _globalConfig.activeClass); + currentElement = null; + } + }; + var _bridge = function() { + var flashBridge, len; + var container = document.getElementById("global-zeroclipboard-html-bridge"); + if (!container) { + var opts = ZeroClipboard.config(); + opts.jsModuleId = typeof _amdModuleId === "string" && _amdModuleId || typeof _cjsModuleId === "string" && _cjsModuleId || null; + var allowScriptAccess = _determineScriptAccess(window.location.host, _globalConfig); + var flashvars = _vars(opts); + var swfUrl = _globalConfig.moviePath + _cacheBust(_globalConfig.moviePath, _globalConfig); + var html = ' '; + container = document.createElement("div"); + container.id = "global-zeroclipboard-html-bridge"; + container.setAttribute("class", "global-zeroclipboard-container"); + container.style.position = "absolute"; + container.style.left = "0px"; + container.style.top = "-9999px"; + container.style.width = "15px"; + container.style.height = "15px"; + container.style.zIndex = "" + _getSafeZIndex(_globalConfig.zIndex); + document.body.appendChild(container); + container.innerHTML = html; + } + flashBridge = document["global-zeroclipboard-flash-bridge"]; + if (flashBridge && (len = flashBridge.length)) { + flashBridge = flashBridge[len - 1]; + } + flashState.bridge = flashBridge || container.children[0].lastElementChild; + }; + var _getHtmlBridge = function(flashBridge) { + var isFlashElement = /^OBJECT|EMBED$/; + var htmlBridge = flashBridge && flashBridge.parentNode; + while (htmlBridge && isFlashElement.test(htmlBridge.nodeName) && htmlBridge.parentNode) { + htmlBridge = htmlBridge.parentNode; + } + return htmlBridge || null; + }; + var _reposition = function() { + if (currentElement) { + var pos = _getDOMObjectPosition(currentElement, _globalConfig.zIndex); + var htmlBridge = _getHtmlBridge(flashState.bridge); + if (htmlBridge) { + htmlBridge.style.top = pos.top + "px"; + htmlBridge.style.left = pos.left + "px"; + htmlBridge.style.width = pos.width + "px"; + htmlBridge.style.height = pos.height + "px"; + htmlBridge.style.zIndex = pos.zIndex + 1; + } + if (flashState.ready === true && flashState.bridge && typeof flashState.bridge.setSize === "function") { + flashState.bridge.setSize(pos.width, pos.height); + } else { + flashState.ready = false; + } + } + return this; + }; + ZeroClipboard.prototype.on = function(eventName, func) { + var i, len, events, added = {}, handlers = _clientMeta[this.id] && _clientMeta[this.id].handlers; + if (typeof eventName === "string" && eventName) { + events = eventName.toLowerCase().split(/\s+/); + } else if (typeof eventName === "object" && eventName && typeof func === "undefined") { + for (i in eventName) { + if (eventName.hasOwnProperty(i) && typeof i === "string" && i && typeof eventName[i] === "function") { + this.on(i, eventName[i]); + } + } + } + if (events && events.length) { + for (i = 0, len = events.length; i < len; i++) { + eventName = events[i].replace(/^on/, ""); + added[eventName] = true; + if (!handlers[eventName]) { + handlers[eventName] = []; + } + handlers[eventName].push(func); + } + if (added.noflash && flashState.disabled) { + _receiveEvent.call(this, "noflash", {}); + } + if (added.wrongflash && flashState.outdated) { + _receiveEvent.call(this, "wrongflash", { + flashVersion: flashState.version + }); + } + if (added.load && flashState.ready) { + _receiveEvent.call(this, "load", { + flashVersion: flashState.version + }); + } + } + return this; + }; + ZeroClipboard.prototype.off = function(eventName, func) { + var i, len, foundIndex, events, perEventHandlers, handlers = _clientMeta[this.id] && _clientMeta[this.id].handlers; + if (arguments.length === 0) { + events = _objectKeys(handlers); + } else if (typeof eventName === "string" && eventName) { + events = eventName.split(/\s+/); + } else if (typeof eventName === "object" && eventName && typeof func === "undefined") { + for (i in eventName) { + if (eventName.hasOwnProperty(i) && typeof i === "string" && i && typeof eventName[i] === "function") { + this.off(i, eventName[i]); + } + } + } + if (events && events.length) { + for (i = 0, len = events.length; i < len; i++) { + eventName = events[i].toLowerCase().replace(/^on/, ""); + perEventHandlers = handlers[eventName]; + if (perEventHandlers && perEventHandlers.length) { + if (func) { + foundIndex = _inArray(func, perEventHandlers); + while (foundIndex !== -1) { + perEventHandlers.splice(foundIndex, 1); + foundIndex = _inArray(func, perEventHandlers, foundIndex); + } + } else { + handlers[eventName].length = 0; + } + } + } + } + return this; + }; + ZeroClipboard.prototype.handlers = function(eventName) { + var prop, copy = null, handlers = _clientMeta[this.id] && _clientMeta[this.id].handlers; + if (handlers) { + if (typeof eventName === "string" && eventName) { + return handlers[eventName] ? handlers[eventName].slice(0) : null; + } + copy = {}; + for (prop in handlers) { + if (handlers.hasOwnProperty(prop) && handlers[prop]) { + copy[prop] = handlers[prop].slice(0); + } + } + } + return copy; + }; + var _dispatchClientCallbacks = function(eventName, context, args, async) { + var handlers = _clientMeta[this.id] && _clientMeta[this.id].handlers[eventName]; + if (handlers && handlers.length) { + var i, len, func, originalContext = context || this; + for (i = 0, len = handlers.length; i < len; i++) { + func = handlers[i]; + context = originalContext; + if (typeof func === "string" && typeof window[func] === "function") { + func = window[func]; + } + if (typeof func === "object" && func && typeof func.handleEvent === "function") { + context = func; + func = func.handleEvent; + } + if (typeof func === "function") { + _dispatchCallback(func, context, args, async); + } + } + } + return this; + }; + ZeroClipboard.prototype.clip = function(elements) { + elements = _prepClip(elements); + for (var i = 0; i < elements.length; i++) { + if (elements.hasOwnProperty(i) && elements[i] && elements[i].nodeType === 1) { + if (!elements[i].zcClippingId) { + elements[i].zcClippingId = "zcClippingId_" + elementIdCounter++; + _elementMeta[elements[i].zcClippingId] = [ this.id ]; + if (_globalConfig.autoActivate === true) { + _addEventHandler(elements[i], "mouseover", _elementMouseOver); + } + } else if (_inArray(this.id, _elementMeta[elements[i].zcClippingId]) === -1) { + _elementMeta[elements[i].zcClippingId].push(this.id); + } + var clippedElements = _clientMeta[this.id].elements; + if (_inArray(elements[i], clippedElements) === -1) { + clippedElements.push(elements[i]); + } + } + } + return this; + }; + ZeroClipboard.prototype.unclip = function(elements) { + var meta = _clientMeta[this.id]; + if (meta) { + var clippedElements = meta.elements; + var arrayIndex; + if (typeof elements === "undefined") { + elements = clippedElements.slice(0); + } else { + elements = _prepClip(elements); + } + for (var i = elements.length; i--; ) { + if (elements.hasOwnProperty(i) && elements[i] && elements[i].nodeType === 1) { + arrayIndex = 0; + while ((arrayIndex = _inArray(elements[i], clippedElements, arrayIndex)) !== -1) { + clippedElements.splice(arrayIndex, 1); + } + var clientIds = _elementMeta[elements[i].zcClippingId]; + if (clientIds) { + arrayIndex = 0; + while ((arrayIndex = _inArray(this.id, clientIds, arrayIndex)) !== -1) { + clientIds.splice(arrayIndex, 1); + } + if (clientIds.length === 0) { + if (_globalConfig.autoActivate === true) { + _removeEventHandler(elements[i], "mouseover", _elementMouseOver); + } + delete elements[i].zcClippingId; + } + } + } + } + } + return this; + }; + ZeroClipboard.prototype.elements = function() { + var meta = _clientMeta[this.id]; + return meta && meta.elements ? meta.elements.slice(0) : []; + }; + var _getAllClientsClippedToElement = function(element) { + var elementMetaId, clientIds, i, len, client, clients = []; + if (element && element.nodeType === 1 && (elementMetaId = element.zcClippingId) && _elementMeta.hasOwnProperty(elementMetaId)) { + clientIds = _elementMeta[elementMetaId]; + if (clientIds && clientIds.length) { + for (i = 0, len = clientIds.length; i < len; i++) { + client = _clientMeta[clientIds[i]].instance; + if (client && client instanceof ZeroClipboard) { + clients.push(client); + } + } + } + } + return clients; + }; + _globalConfig.hoverClass = "zeroclipboard-is-hover"; + _globalConfig.activeClass = "zeroclipboard-is-active"; + _globalConfig.trustedOrigins = null; + _globalConfig.allowScriptAccess = null; + _globalConfig.useNoCache = true; + _globalConfig.moviePath = "ZeroClipboard.swf"; + ZeroClipboard.detectFlashSupport = function() { + _deprecationWarning("ZeroClipboard.detectFlashSupport", _globalConfig.debug); + return _detectFlashSupport(); + }; + ZeroClipboard.dispatch = function(eventName, args) { + if (typeof eventName === "string" && eventName) { + var cleanEventName = eventName.toLowerCase().replace(/^on/, ""); + if (cleanEventName) { + var clients = currentElement && _globalConfig.autoActivate === true ? _getAllClientsClippedToElement(currentElement) : _getAllClients(); + for (var i = 0, len = clients.length; i < len; i++) { + _receiveEvent.call(clients[i], cleanEventName, args); + } + } + } + }; + ZeroClipboard.prototype.setHandCursor = function(enabled) { + _deprecationWarning("ZeroClipboard.prototype.setHandCursor", _globalConfig.debug); + enabled = typeof enabled === "boolean" ? enabled : !!enabled; + _setHandCursor(enabled); + _globalConfig.forceHandCursor = enabled; + return this; + }; + ZeroClipboard.prototype.reposition = function() { + _deprecationWarning("ZeroClipboard.prototype.reposition", _globalConfig.debug); + return _reposition(); + }; + ZeroClipboard.prototype.receiveEvent = function(eventName, args) { + _deprecationWarning("ZeroClipboard.prototype.receiveEvent", _globalConfig.debug); + if (typeof eventName === "string" && eventName) { + var cleanEventName = eventName.toLowerCase().replace(/^on/, ""); + if (cleanEventName) { + _receiveEvent.call(this, cleanEventName, args); + } + } + }; + ZeroClipboard.prototype.setCurrent = function(element) { + _deprecationWarning("ZeroClipboard.prototype.setCurrent", _globalConfig.debug); + ZeroClipboard.activate(element); + return this; + }; + ZeroClipboard.prototype.resetBridge = function() { + _deprecationWarning("ZeroClipboard.prototype.resetBridge", _globalConfig.debug); + ZeroClipboard.deactivate(); + return this; + }; + ZeroClipboard.prototype.setTitle = function(newTitle) { + _deprecationWarning("ZeroClipboard.prototype.setTitle", _globalConfig.debug); + newTitle = newTitle || _globalConfig.title || currentElement && currentElement.getAttribute("title"); + if (newTitle) { + var htmlBridge = _getHtmlBridge(flashState.bridge); + if (htmlBridge) { + htmlBridge.setAttribute("title", newTitle); + } + } + return this; + }; + ZeroClipboard.setDefaults = function(options) { + _deprecationWarning("ZeroClipboard.setDefaults", _globalConfig.debug); + ZeroClipboard.config(options); + }; + ZeroClipboard.prototype.addEventListener = function(eventName, func) { + _deprecationWarning("ZeroClipboard.prototype.addEventListener", _globalConfig.debug); + return this.on(eventName, func); + }; + ZeroClipboard.prototype.removeEventListener = function(eventName, func) { + _deprecationWarning("ZeroClipboard.prototype.removeEventListener", _globalConfig.debug); + return this.off(eventName, func); + }; + ZeroClipboard.prototype.ready = function() { + _deprecationWarning("ZeroClipboard.prototype.ready", _globalConfig.debug); + return flashState.ready === true; + }; + var _receiveEvent = function(eventName, args) { + eventName = eventName.toLowerCase().replace(/^on/, ""); + var cleanVersion = args && args.flashVersion && _parseFlashVersion(args.flashVersion) || null; + var element = currentElement; + var performCallbackAsync = true; + switch (eventName) { + case "load": + if (cleanVersion) { + if (!_isFlashVersionSupported(cleanVersion)) { + _receiveEvent.call(this, "onWrongFlash", { + flashVersion: cleanVersion + }); + return; + } + flashState.outdated = false; + flashState.ready = true; + flashState.version = cleanVersion; + } + break; + + case "wrongflash": + if (cleanVersion && !_isFlashVersionSupported(cleanVersion)) { + flashState.outdated = true; + flashState.ready = false; + flashState.version = cleanVersion; + } + break; + + case "mouseover": + _addClass(element, _globalConfig.hoverClass); + break; + + case "mouseout": + if (_globalConfig.autoActivate === true) { + ZeroClipboard.deactivate(); + } + break; + + case "mousedown": + _addClass(element, _globalConfig.activeClass); + break; + + case "mouseup": + _removeClass(element, _globalConfig.activeClass); + break; + + case "datarequested": + if (element) { + var targetId = element.getAttribute("data-clipboard-target"), targetEl = !targetId ? null : document.getElementById(targetId); + if (targetEl) { + var textContent = targetEl.value || targetEl.textContent || targetEl.innerText; + if (textContent) { + this.setText(textContent); + } + } else { + var defaultText = element.getAttribute("data-clipboard-text"); + if (defaultText) { + this.setText(defaultText); + } + } + } + performCallbackAsync = false; + break; + + case "complete": + _deleteOwnProperties(_clipData); + if (element && element !== _safeActiveElement() && element.focus) { + element.focus(); + } + break; + } + var context = element; + var eventArgs = [ this, args ]; + return _dispatchClientCallbacks.call(this, eventName, context, eventArgs, performCallbackAsync); + }; + if (typeof define === "function" && define.amd) { + define([ "require", "exports", "module" ], function(require, exports, module) { + _amdModuleId = module && module.id || null; + return ZeroClipboard; + }); + } else if (typeof module === "object" && module && typeof module.exports === "object" && module.exports && typeof window.require === "function") { + _cjsModuleId = module.id || null; + module.exports = ZeroClipboard; + } else { + window.ZeroClipboard = ZeroClipboard; + } +})(function() { + return this; +}()); \ No newline at end of file diff --git a/libraries/webInterface/js/ZeroClipboard.swf b/libraries/webInterface/js/ZeroClipboard.swf new file mode 100755 index 0000000..55ccf96 Binary files /dev/null and b/libraries/webInterface/js/ZeroClipboard.swf differ diff --git a/libraries/webInterface/js/bootstrap-theme.min.css b/libraries/webInterface/js/bootstrap-theme.min.css new file mode 100644 index 0000000..cff38df --- /dev/null +++ b/libraries/webInterface/js/bootstrap-theme.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.1.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +.btn-default,.btn-primary,.btn-success,.btn-info,.btn-warning,.btn-danger{text-shadow:0 -1px 0 rgba(0,0,0,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 1px rgba(0,0,0,.075)}.btn-default:active,.btn-primary:active,.btn-success:active,.btn-info:active,.btn-warning:active,.btn-danger:active,.btn-default.active,.btn-primary.active,.btn-success.active,.btn-info.active,.btn-warning.active,.btn-danger.active{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn:active,.btn.active{background-image:none}.btn-default{background-image:-webkit-linear-gradient(top,#fff 0,#e0e0e0 100%);background-image:linear-gradient(to bottom,#fff 0,#e0e0e0 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#dbdbdb;text-shadow:0 1px 0 #fff;border-color:#ccc}.btn-default:hover,.btn-default:focus{background-color:#e0e0e0;background-position:0 -15px}.btn-default:active,.btn-default.active{background-color:#e0e0e0;border-color:#dbdbdb}.btn-primary{background-image:-webkit-linear-gradient(top,#428bca 0,#2d6ca2 100%);background-image:linear-gradient(to bottom,#428bca 0,#2d6ca2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#2b669a}.btn-primary:hover,.btn-primary:focus{background-color:#2d6ca2;background-position:0 -15px}.btn-primary:active,.btn-primary.active{background-color:#2d6ca2;border-color:#2b669a}.btn-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#419641 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#419641 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#3e8f3e}.btn-success:hover,.btn-success:focus{background-color:#419641;background-position:0 -15px}.btn-success:active,.btn-success.active{background-color:#419641;border-color:#3e8f3e}.btn-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#2aabd2 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#2aabd2 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#28a4c9}.btn-info:hover,.btn-info:focus{background-color:#2aabd2;background-position:0 -15px}.btn-info:active,.btn-info.active{background-color:#2aabd2;border-color:#28a4c9}.btn-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#eb9316 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#eb9316 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#e38d13}.btn-warning:hover,.btn-warning:focus{background-color:#eb9316;background-position:0 -15px}.btn-warning:active,.btn-warning.active{background-color:#eb9316;border-color:#e38d13}.btn-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c12e2a 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c12e2a 100%);filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);background-repeat:repeat-x;border-color:#b92c28}.btn-danger:hover,.btn-danger:focus{background-color:#c12e2a;background-position:0 -15px}.btn-danger:active,.btn-danger.active{background-color:#c12e2a;border-color:#b92c28}.thumbnail,.img-thumbnail{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);background-color:#e8e8e8}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);background-color:#357ebd}.navbar-default{background-image:-webkit-linear-gradient(top,#fff 0,#f8f8f8 100%);background-image:linear-gradient(to bottom,#fff 0,#f8f8f8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);border-radius:4px;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075);box-shadow:inset 0 1px 0 rgba(255,255,255,.15),0 1px 5px rgba(0,0,0,.075)}.navbar-default .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f3f3f3 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f3f3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.075);box-shadow:inset 0 3px 9px rgba(0,0,0,.075)}.navbar-brand,.navbar-nav>li>a{text-shadow:0 1px 0 rgba(255,255,255,.25)}.navbar-inverse{background-image:-webkit-linear-gradient(top,#3c3c3c 0,#222 100%);background-image:linear-gradient(to bottom,#3c3c3c 0,#222 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);filter:progid:DXImageTransform.Microsoft.gradient(enabled=false)}.navbar-inverse .navbar-nav>.active>a{background-image:-webkit-linear-gradient(top,#222 0,#282828 100%);background-image:linear-gradient(to bottom,#222 0,#282828 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);-webkit-box-shadow:inset 0 3px 9px rgba(0,0,0,.25);box-shadow:inset 0 3px 9px rgba(0,0,0,.25)}.navbar-inverse .navbar-brand,.navbar-inverse .navbar-nav>li>a{text-shadow:0 -1px 0 rgba(0,0,0,.25)}.navbar-static-top,.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}.alert{text-shadow:0 1px 0 rgba(255,255,255,.2);-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05);box-shadow:inset 0 1px 0 rgba(255,255,255,.25),0 1px 2px rgba(0,0,0,.05)}.alert-success{background-image:-webkit-linear-gradient(top,#dff0d8 0,#c8e5bc 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#c8e5bc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);border-color:#b2dba1}.alert-info{background-image:-webkit-linear-gradient(top,#d9edf7 0,#b9def0 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#b9def0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);border-color:#9acfea}.alert-warning{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#f8efc0 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#f8efc0 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);border-color:#f5e79e}.alert-danger{background-image:-webkit-linear-gradient(top,#f2dede 0,#e7c3c3 100%);background-image:linear-gradient(to bottom,#f2dede 0,#e7c3c3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);border-color:#dca7a7}.progress{background-image:-webkit-linear-gradient(top,#ebebeb 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#ebebeb 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0)}.progress-bar{background-image:-webkit-linear-gradient(top,#428bca 0,#3071a9 100%);background-image:linear-gradient(to bottom,#428bca 0,#3071a9 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0)}.progress-bar-success{background-image:-webkit-linear-gradient(top,#5cb85c 0,#449d44 100%);background-image:linear-gradient(to bottom,#5cb85c 0,#449d44 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0)}.progress-bar-info{background-image:-webkit-linear-gradient(top,#5bc0de 0,#31b0d5 100%);background-image:linear-gradient(to bottom,#5bc0de 0,#31b0d5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0)}.progress-bar-warning{background-image:-webkit-linear-gradient(top,#f0ad4e 0,#ec971f 100%);background-image:linear-gradient(to bottom,#f0ad4e 0,#ec971f 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0)}.progress-bar-danger{background-image:-webkit-linear-gradient(top,#d9534f 0,#c9302c 100%);background-image:linear-gradient(to bottom,#d9534f 0,#c9302c 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0)}.list-group{border-radius:4px;-webkit-box-shadow:0 1px 2px rgba(0,0,0,.075);box-shadow:0 1px 2px rgba(0,0,0,.075)}.list-group-item.active,.list-group-item.active:hover,.list-group-item.active:focus{text-shadow:0 -1px 0 #3071a9;background-image:-webkit-linear-gradient(top,#428bca 0,#3278b3 100%);background-image:linear-gradient(to bottom,#428bca 0,#3278b3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);border-color:#3278b3}.panel{-webkit-box-shadow:0 1px 2px rgba(0,0,0,.05);box-shadow:0 1px 2px rgba(0,0,0,.05)}.panel-default>.panel-heading{background-image:-webkit-linear-gradient(top,#f5f5f5 0,#e8e8e8 100%);background-image:linear-gradient(to bottom,#f5f5f5 0,#e8e8e8 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0)}.panel-primary>.panel-heading{background-image:-webkit-linear-gradient(top,#428bca 0,#357ebd 100%);background-image:linear-gradient(to bottom,#428bca 0,#357ebd 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0)}.panel-success>.panel-heading{background-image:-webkit-linear-gradient(top,#dff0d8 0,#d0e9c6 100%);background-image:linear-gradient(to bottom,#dff0d8 0,#d0e9c6 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0)}.panel-info>.panel-heading{background-image:-webkit-linear-gradient(top,#d9edf7 0,#c4e3f3 100%);background-image:linear-gradient(to bottom,#d9edf7 0,#c4e3f3 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0)}.panel-warning>.panel-heading{background-image:-webkit-linear-gradient(top,#fcf8e3 0,#faf2cc 100%);background-image:linear-gradient(to bottom,#fcf8e3 0,#faf2cc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0)}.panel-danger>.panel-heading{background-image:-webkit-linear-gradient(top,#f2dede 0,#ebcccc 100%);background-image:linear-gradient(to bottom,#f2dede 0,#ebcccc 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0)}.well{background-image:-webkit-linear-gradient(top,#e8e8e8 0,#f5f5f5 100%);background-image:linear-gradient(to bottom,#e8e8e8 0,#f5f5f5 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);border-color:#dcdcdc;-webkit-box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 3px rgba(0,0,0,.05),0 1px 0 rgba(255,255,255,.1)} \ No newline at end of file diff --git a/libraries/webInterface/js/bootstrap.min.css b/libraries/webInterface/js/bootstrap.min.css new file mode 100644 index 0000000..976dada --- /dev/null +++ b/libraries/webInterface/js/bootstrap.min.css @@ -0,0 +1,7 @@ +/*! + * Bootstrap v3.1.0 (http://getbootstrap.com) + * Copyright 2011-2014 Twitter, Inc. + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ + +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:0 0}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:700}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}@media print{*{text-shadow:none!important;color:#000!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) ")"}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}p,h2,h3{orphans:3;widows:3}h2,h3{page-break-after:avoid}select{background:#fff!important}.navbar{display:none}.table td,.table th{background-color:#fff!important}.btn>.caret,.dropup>.btn>.caret{border-top-color:#000!important}.label{border:1px solid #000}.table{border-collapse:collapse!important}.table-bordered th,.table-bordered td{border:1px solid #ddd!important}}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}:before,:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0,0,0,0)}body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333;background-color:#fff}input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit}a{color:#428bca;text-decoration:none}a:hover,a:focus{color:#2a6496;text-decoration:underline}a:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}figure{margin:0}img{vertical-align:middle}.img-responsive{display:block;max-width:100%;height:auto}.img-rounded{border-radius:6px}.img-thumbnail{padding:4px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out;display:inline-block;max-width:100%;height:auto}.img-circle{border-radius:50%}hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eee}.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0,0,0,0);border:0}h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:inherit;font-weight:500;line-height:1.1;color:inherit}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small,h1 .small,h2 .small,h3 .small,h4 .small,h5 .small,h6 .small,.h1 .small,.h2 .small,.h3 .small,.h4 .small,.h5 .small,.h6 .small{font-weight:400;line-height:1;color:#999}h1,.h1,h2,.h2,h3,.h3{margin-top:20px;margin-bottom:10px}h1 small,.h1 small,h2 small,.h2 small,h3 small,.h3 small,h1 .small,.h1 .small,h2 .small,.h2 .small,h3 .small,.h3 .small{font-size:65%}h4,.h4,h5,.h5,h6,.h6{margin-top:10px;margin-bottom:10px}h4 small,.h4 small,h5 small,.h5 small,h6 small,.h6 small,h4 .small,.h4 .small,h5 .small,.h5 .small,h6 .small,.h6 .small{font-size:75%}h1,.h1{font-size:36px}h2,.h2{font-size:30px}h3,.h3{font-size:24px}h4,.h4{font-size:18px}h5,.h5{font-size:14px}h6,.h6{font-size:12px}p{margin:0 0 10px}.lead{margin-bottom:20px;font-size:16px;font-weight:200;line-height:1.4}@media (min-width:768px){.lead{font-size:21px}}small,.small{font-size:85%}cite{font-style:normal}.text-left{text-align:left}.text-right{text-align:right}.text-center{text-align:center}.text-justify{text-align:justify}.text-muted{color:#999}.text-primary{color:#428bca}a.text-primary:hover{color:#3071a9}.text-success{color:#3c763d}a.text-success:hover{color:#2b542c}.text-info{color:#31708f}a.text-info:hover{color:#245269}.text-warning{color:#8a6d3b}a.text-warning:hover{color:#66512c}.text-danger{color:#a94442}a.text-danger:hover{color:#843534}.bg-primary{color:#fff;background-color:#428bca}a.bg-primary:hover{background-color:#3071a9}.bg-success{background-color:#dff0d8}a.bg-success:hover{background-color:#c1e2b3}.bg-info{background-color:#d9edf7}a.bg-info:hover{background-color:#afd9ee}.bg-warning{background-color:#fcf8e3}a.bg-warning:hover{background-color:#f7ecb5}.bg-danger{background-color:#f2dede}a.bg-danger:hover{background-color:#e4b9b9}.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eee}ul,ol{margin-top:0;margin-bottom:10px}ul ul,ol ul,ul ol,ol ol{margin-bottom:0}.list-unstyled{padding-left:0;list-style:none}.list-inline{padding-left:0;list-style:none}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px}.list-inline>li:first-child{padding-left:0}dl{margin-top:0;margin-bottom:20px}dt,dd{line-height:1.428571429}dt{font-weight:700}dd{margin-left:0}@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dl-horizontal dd{margin-left:180px}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999}.initialism{font-size:90%;text-transform:uppercase}blockquote{padding:10px 20px;margin:0 0 20px;font-size:17.5px;border-left:5px solid #eee}blockquote p:last-child,blockquote ul:last-child,blockquote ol:last-child{margin-bottom:0}blockquote footer,blockquote small,blockquote .small{display:block;font-size:80%;line-height:1.428571429;color:#999}blockquote footer:before,blockquote small:before,blockquote .small:before{content:'\2014 \00A0'}.blockquote-reverse,blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eee;border-left:0;text-align:right}.blockquote-reverse footer:before,blockquote.pull-right footer:before,.blockquote-reverse small:before,blockquote.pull-right small:before,.blockquote-reverse .small:before,blockquote.pull-right .small:before{content:''}.blockquote-reverse footer:after,blockquote.pull-right footer:after,.blockquote-reverse small:after,blockquote.pull-right small:after,.blockquote-reverse .small:after,blockquote.pull-right .small:after{content:'\00A0 \2014'}blockquote:before,blockquote:after{content:""}address{margin-bottom:20px;font-style:normal;line-height:1.428571429}code,kbd,pre,samp{font-family:Menlo,Monaco,Consolas,"Courier New",monospace}code{padding:2px 4px;font-size:90%;color:#c7254e;background-color:#f9f2f4;white-space:nowrap;border-radius:4px}kbd{padding:2px 4px;font-size:90%;color:#fff;background-color:#333;border-radius:3px;box-shadow:inset 0 -1px 0 rgba(0,0,0,.25)}pre{display:block;padding:9.5px;margin:0 0 10px;font-size:13px;line-height:1.428571429;word-break:break-all;word-wrap:break-word;color:#333;background-color:#f5f5f5;border:1px solid #ccc;border-radius:4px}pre code{padding:0;font-size:inherit;color:inherit;white-space:pre-wrap;background-color:transparent;border-radius:0}.pre-scrollable{max-height:340px;overflow-y:scroll}.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}@media (min-width:768px){.container{width:750px}}@media (min-width:992px){.container{width:970px}}@media (min-width:1200px){.container{width:1170px}}.container-fluid{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px}.row{margin-left:-15px;margin-right:-15px}.col-xs-1,.col-sm-1,.col-md-1,.col-lg-1,.col-xs-2,.col-sm-2,.col-md-2,.col-lg-2,.col-xs-3,.col-sm-3,.col-md-3,.col-lg-3,.col-xs-4,.col-sm-4,.col-md-4,.col-lg-4,.col-xs-5,.col-sm-5,.col-md-5,.col-lg-5,.col-xs-6,.col-sm-6,.col-md-6,.col-lg-6,.col-xs-7,.col-sm-7,.col-md-7,.col-lg-7,.col-xs-8,.col-sm-8,.col-md-8,.col-lg-8,.col-xs-9,.col-sm-9,.col-md-9,.col-lg-9,.col-xs-10,.col-sm-10,.col-md-10,.col-lg-10,.col-xs-11,.col-sm-11,.col-md-11,.col-lg-11,.col-xs-12,.col-sm-12,.col-md-12,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px}.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12{float:left}.col-xs-12{width:100%}.col-xs-11{width:91.66666666666666%}.col-xs-10{width:83.33333333333334%}.col-xs-9{width:75%}.col-xs-8{width:66.66666666666666%}.col-xs-7{width:58.333333333333336%}.col-xs-6{width:50%}.col-xs-5{width:41.66666666666667%}.col-xs-4{width:33.33333333333333%}.col-xs-3{width:25%}.col-xs-2{width:16.666666666666664%}.col-xs-1{width:8.333333333333332%}.col-xs-pull-12{right:100%}.col-xs-pull-11{right:91.66666666666666%}.col-xs-pull-10{right:83.33333333333334%}.col-xs-pull-9{right:75%}.col-xs-pull-8{right:66.66666666666666%}.col-xs-pull-7{right:58.333333333333336%}.col-xs-pull-6{right:50%}.col-xs-pull-5{right:41.66666666666667%}.col-xs-pull-4{right:33.33333333333333%}.col-xs-pull-3{right:25%}.col-xs-pull-2{right:16.666666666666664%}.col-xs-pull-1{right:8.333333333333332%}.col-xs-pull-0{right:0}.col-xs-push-12{left:100%}.col-xs-push-11{left:91.66666666666666%}.col-xs-push-10{left:83.33333333333334%}.col-xs-push-9{left:75%}.col-xs-push-8{left:66.66666666666666%}.col-xs-push-7{left:58.333333333333336%}.col-xs-push-6{left:50%}.col-xs-push-5{left:41.66666666666667%}.col-xs-push-4{left:33.33333333333333%}.col-xs-push-3{left:25%}.col-xs-push-2{left:16.666666666666664%}.col-xs-push-1{left:8.333333333333332%}.col-xs-push-0{left:0}.col-xs-offset-12{margin-left:100%}.col-xs-offset-11{margin-left:91.66666666666666%}.col-xs-offset-10{margin-left:83.33333333333334%}.col-xs-offset-9{margin-left:75%}.col-xs-offset-8{margin-left:66.66666666666666%}.col-xs-offset-7{margin-left:58.333333333333336%}.col-xs-offset-6{margin-left:50%}.col-xs-offset-5{margin-left:41.66666666666667%}.col-xs-offset-4{margin-left:33.33333333333333%}.col-xs-offset-3{margin-left:25%}.col-xs-offset-2{margin-left:16.666666666666664%}.col-xs-offset-1{margin-left:8.333333333333332%}.col-xs-offset-0{margin-left:0}@media (min-width:768px){.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12{float:left}.col-sm-12{width:100%}.col-sm-11{width:91.66666666666666%}.col-sm-10{width:83.33333333333334%}.col-sm-9{width:75%}.col-sm-8{width:66.66666666666666%}.col-sm-7{width:58.333333333333336%}.col-sm-6{width:50%}.col-sm-5{width:41.66666666666667%}.col-sm-4{width:33.33333333333333%}.col-sm-3{width:25%}.col-sm-2{width:16.666666666666664%}.col-sm-1{width:8.333333333333332%}.col-sm-pull-12{right:100%}.col-sm-pull-11{right:91.66666666666666%}.col-sm-pull-10{right:83.33333333333334%}.col-sm-pull-9{right:75%}.col-sm-pull-8{right:66.66666666666666%}.col-sm-pull-7{right:58.333333333333336%}.col-sm-pull-6{right:50%}.col-sm-pull-5{right:41.66666666666667%}.col-sm-pull-4{right:33.33333333333333%}.col-sm-pull-3{right:25%}.col-sm-pull-2{right:16.666666666666664%}.col-sm-pull-1{right:8.333333333333332%}.col-sm-pull-0{right:0}.col-sm-push-12{left:100%}.col-sm-push-11{left:91.66666666666666%}.col-sm-push-10{left:83.33333333333334%}.col-sm-push-9{left:75%}.col-sm-push-8{left:66.66666666666666%}.col-sm-push-7{left:58.333333333333336%}.col-sm-push-6{left:50%}.col-sm-push-5{left:41.66666666666667%}.col-sm-push-4{left:33.33333333333333%}.col-sm-push-3{left:25%}.col-sm-push-2{left:16.666666666666664%}.col-sm-push-1{left:8.333333333333332%}.col-sm-push-0{left:0}.col-sm-offset-12{margin-left:100%}.col-sm-offset-11{margin-left:91.66666666666666%}.col-sm-offset-10{margin-left:83.33333333333334%}.col-sm-offset-9{margin-left:75%}.col-sm-offset-8{margin-left:66.66666666666666%}.col-sm-offset-7{margin-left:58.333333333333336%}.col-sm-offset-6{margin-left:50%}.col-sm-offset-5{margin-left:41.66666666666667%}.col-sm-offset-4{margin-left:33.33333333333333%}.col-sm-offset-3{margin-left:25%}.col-sm-offset-2{margin-left:16.666666666666664%}.col-sm-offset-1{margin-left:8.333333333333332%}.col-sm-offset-0{margin-left:0}}@media (min-width:992px){.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12{float:left}.col-md-12{width:100%}.col-md-11{width:91.66666666666666%}.col-md-10{width:83.33333333333334%}.col-md-9{width:75%}.col-md-8{width:66.66666666666666%}.col-md-7{width:58.333333333333336%}.col-md-6{width:50%}.col-md-5{width:41.66666666666667%}.col-md-4{width:33.33333333333333%}.col-md-3{width:25%}.col-md-2{width:16.666666666666664%}.col-md-1{width:8.333333333333332%}.col-md-pull-12{right:100%}.col-md-pull-11{right:91.66666666666666%}.col-md-pull-10{right:83.33333333333334%}.col-md-pull-9{right:75%}.col-md-pull-8{right:66.66666666666666%}.col-md-pull-7{right:58.333333333333336%}.col-md-pull-6{right:50%}.col-md-pull-5{right:41.66666666666667%}.col-md-pull-4{right:33.33333333333333%}.col-md-pull-3{right:25%}.col-md-pull-2{right:16.666666666666664%}.col-md-pull-1{right:8.333333333333332%}.col-md-pull-0{right:0}.col-md-push-12{left:100%}.col-md-push-11{left:91.66666666666666%}.col-md-push-10{left:83.33333333333334%}.col-md-push-9{left:75%}.col-md-push-8{left:66.66666666666666%}.col-md-push-7{left:58.333333333333336%}.col-md-push-6{left:50%}.col-md-push-5{left:41.66666666666667%}.col-md-push-4{left:33.33333333333333%}.col-md-push-3{left:25%}.col-md-push-2{left:16.666666666666664%}.col-md-push-1{left:8.333333333333332%}.col-md-push-0{left:0}.col-md-offset-12{margin-left:100%}.col-md-offset-11{margin-left:91.66666666666666%}.col-md-offset-10{margin-left:83.33333333333334%}.col-md-offset-9{margin-left:75%}.col-md-offset-8{margin-left:66.66666666666666%}.col-md-offset-7{margin-left:58.333333333333336%}.col-md-offset-6{margin-left:50%}.col-md-offset-5{margin-left:41.66666666666667%}.col-md-offset-4{margin-left:33.33333333333333%}.col-md-offset-3{margin-left:25%}.col-md-offset-2{margin-left:16.666666666666664%}.col-md-offset-1{margin-left:8.333333333333332%}.col-md-offset-0{margin-left:0}}@media (min-width:1200px){.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{float:left}.col-lg-12{width:100%}.col-lg-11{width:91.66666666666666%}.col-lg-10{width:83.33333333333334%}.col-lg-9{width:75%}.col-lg-8{width:66.66666666666666%}.col-lg-7{width:58.333333333333336%}.col-lg-6{width:50%}.col-lg-5{width:41.66666666666667%}.col-lg-4{width:33.33333333333333%}.col-lg-3{width:25%}.col-lg-2{width:16.666666666666664%}.col-lg-1{width:8.333333333333332%}.col-lg-pull-12{right:100%}.col-lg-pull-11{right:91.66666666666666%}.col-lg-pull-10{right:83.33333333333334%}.col-lg-pull-9{right:75%}.col-lg-pull-8{right:66.66666666666666%}.col-lg-pull-7{right:58.333333333333336%}.col-lg-pull-6{right:50%}.col-lg-pull-5{right:41.66666666666667%}.col-lg-pull-4{right:33.33333333333333%}.col-lg-pull-3{right:25%}.col-lg-pull-2{right:16.666666666666664%}.col-lg-pull-1{right:8.333333333333332%}.col-lg-pull-0{right:0}.col-lg-push-12{left:100%}.col-lg-push-11{left:91.66666666666666%}.col-lg-push-10{left:83.33333333333334%}.col-lg-push-9{left:75%}.col-lg-push-8{left:66.66666666666666%}.col-lg-push-7{left:58.333333333333336%}.col-lg-push-6{left:50%}.col-lg-push-5{left:41.66666666666667%}.col-lg-push-4{left:33.33333333333333%}.col-lg-push-3{left:25%}.col-lg-push-2{left:16.666666666666664%}.col-lg-push-1{left:8.333333333333332%}.col-lg-push-0{left:0}.col-lg-offset-12{margin-left:100%}.col-lg-offset-11{margin-left:91.66666666666666%}.col-lg-offset-10{margin-left:83.33333333333334%}.col-lg-offset-9{margin-left:75%}.col-lg-offset-8{margin-left:66.66666666666666%}.col-lg-offset-7{margin-left:58.333333333333336%}.col-lg-offset-6{margin-left:50%}.col-lg-offset-5{margin-left:41.66666666666667%}.col-lg-offset-4{margin-left:33.33333333333333%}.col-lg-offset-3{margin-left:25%}.col-lg-offset-2{margin-left:16.666666666666664%}.col-lg-offset-1{margin-left:8.333333333333332%}.col-lg-offset-0{margin-left:0}}table{max-width:100%;background-color:transparent}th{text-align:left}.table{width:100%;margin-bottom:20px}.table>thead>tr>th,.table>tbody>tr>th,.table>tfoot>tr>th,.table>thead>tr>td,.table>tbody>tr>td,.table>tfoot>tr>td{padding:8px;line-height:1.428571429;vertical-align:top;border-top:1px solid #ddd}.table>thead>tr>th{vertical-align:bottom;border-bottom:2px solid #ddd}.table>caption+thead>tr:first-child>th,.table>colgroup+thead>tr:first-child>th,.table>thead:first-child>tr:first-child>th,.table>caption+thead>tr:first-child>td,.table>colgroup+thead>tr:first-child>td,.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>thead>tr>th,.table-condensed>tbody>tr>th,.table-condensed>tfoot>tr>th,.table-condensed>thead>tr>td,.table-condensed>tbody>tr>td,.table-condensed>tfoot>tr>td{padding:5px}.table-bordered{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>tbody>tr>th,.table-bordered>tfoot>tr>th,.table-bordered>thead>tr>td,.table-bordered>tbody>tr>td,.table-bordered>tfoot>tr>td{border:1px solid #ddd}.table-bordered>thead>tr>th,.table-bordered>thead>tr>td{border-bottom-width:2px}.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 col[class*=col-]{position:static;float:none;display:table-column}table td[class*=col-],table th[class*=col-]{position:static;float:none;display:table-cell}.table>thead>tr>td.active,.table>tbody>tr>td.active,.table>tfoot>tr>td.active,.table>thead>tr>th.active,.table>tbody>tr>th.active,.table>tfoot>tr>th.active,.table>thead>tr.active>td,.table>tbody>tr.active>td,.table>tfoot>tr.active>td,.table>thead>tr.active>th,.table>tbody>tr.active>th,.table>tfoot>tr.active>th{background-color:#f5f5f5}.table-hover>tbody>tr>td.active:hover,.table-hover>tbody>tr>th.active:hover,.table-hover>tbody>tr.active:hover>td,.table-hover>tbody>tr.active:hover>th{background-color:#e8e8e8}.table>thead>tr>td.success,.table>tbody>tr>td.success,.table>tfoot>tr>td.success,.table>thead>tr>th.success,.table>tbody>tr>th.success,.table>tfoot>tr>th.success,.table>thead>tr.success>td,.table>tbody>tr.success>td,.table>tfoot>tr.success>td,.table>thead>tr.success>th,.table>tbody>tr.success>th,.table>tfoot>tr.success>th{background-color:#dff0d8}.table-hover>tbody>tr>td.success:hover,.table-hover>tbody>tr>th.success:hover,.table-hover>tbody>tr.success:hover>td,.table-hover>tbody>tr.success:hover>th{background-color:#d0e9c6}.table>thead>tr>td.info,.table>tbody>tr>td.info,.table>tfoot>tr>td.info,.table>thead>tr>th.info,.table>tbody>tr>th.info,.table>tfoot>tr>th.info,.table>thead>tr.info>td,.table>tbody>tr.info>td,.table>tfoot>tr.info>td,.table>thead>tr.info>th,.table>tbody>tr.info>th,.table>tfoot>tr.info>th{background-color:#d9edf7}.table-hover>tbody>tr>td.info:hover,.table-hover>tbody>tr>th.info:hover,.table-hover>tbody>tr.info:hover>td,.table-hover>tbody>tr.info:hover>th{background-color:#c4e3f3}.table>thead>tr>td.warning,.table>tbody>tr>td.warning,.table>tfoot>tr>td.warning,.table>thead>tr>th.warning,.table>tbody>tr>th.warning,.table>tfoot>tr>th.warning,.table>thead>tr.warning>td,.table>tbody>tr.warning>td,.table>tfoot>tr.warning>td,.table>thead>tr.warning>th,.table>tbody>tr.warning>th,.table>tfoot>tr.warning>th{background-color:#fcf8e3}.table-hover>tbody>tr>td.warning:hover,.table-hover>tbody>tr>th.warning:hover,.table-hover>tbody>tr.warning:hover>td,.table-hover>tbody>tr.warning:hover>th{background-color:#faf2cc}.table>thead>tr>td.danger,.table>tbody>tr>td.danger,.table>tfoot>tr>td.danger,.table>thead>tr>th.danger,.table>tbody>tr>th.danger,.table>tfoot>tr>th.danger,.table>thead>tr.danger>td,.table>tbody>tr.danger>td,.table>tfoot>tr.danger>td,.table>thead>tr.danger>th,.table>tbody>tr.danger>th,.table>tfoot>tr.danger>th{background-color:#f2dede}.table-hover>tbody>tr>td.danger:hover,.table-hover>tbody>tr>th.danger:hover,.table-hover>tbody>tr.danger:hover>td,.table-hover>tbody>tr.danger:hover>th{background-color:#ebcccc}@media (max-width:767px){.table-responsive{width:100%;margin-bottom:15px;overflow-y:hidden;overflow-x:scroll;-ms-overflow-style:-ms-autohiding-scrollbar;border:1px solid #ddd;-webkit-overflow-scrolling:touch}.table-responsive>.table{margin-bottom:0}.table-responsive>.table>thead>tr>th,.table-responsive>.table>tbody>tr>th,.table-responsive>.table>tfoot>tr>th,.table-responsive>.table>thead>tr>td,.table-responsive>.table>tbody>tr>td,.table-responsive>.table>tfoot>tr>td{white-space:nowrap}.table-responsive>.table-bordered{border:0}.table-responsive>.table-bordered>thead>tr>th:first-child,.table-responsive>.table-bordered>tbody>tr>th:first-child,.table-responsive>.table-bordered>tfoot>tr>th:first-child,.table-responsive>.table-bordered>thead>tr>td:first-child,.table-responsive>.table-bordered>tbody>tr>td:first-child,.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.table-responsive>.table-bordered>thead>tr>th:last-child,.table-responsive>.table-bordered>tbody>tr>th:last-child,.table-responsive>.table-bordered>tfoot>tr>th:last-child,.table-responsive>.table-bordered>thead>tr>td:last-child,.table-responsive>.table-bordered>tbody>tr>td:last-child,.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.table-responsive>.table-bordered>tbody>tr:last-child>th,.table-responsive>.table-bordered>tfoot>tr:last-child>th,.table-responsive>.table-bordered>tbody>tr:last-child>td,.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}}fieldset{padding:0;margin:0;border:0;min-width:0}legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333;border:0;border-bottom:1px solid #e5e5e5}label{display:inline-block;margin-bottom:5px;font-weight:700}input[type=search]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}input[type=radio],input[type=checkbox]{margin:4px 0 0;margin-top:1px \9;line-height:normal}input[type=file]{display:block}input[type=range]{display:block;width:100%}select[multiple],select[size]{height:auto}input[type=file]:focus,input[type=radio]:focus,input[type=checkbox]:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}output{display:block;padding-top:7px;font-size:14px;line-height:1.428571429;color:#555}.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555;background-color:#fff;background-image:none;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075);-webkit-transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s,box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.form-control:-moz-placeholder{color:#999}.form-control::-moz-placeholder{color:#999;opacity:1}.form-control:-ms-input-placeholder{color:#999}.form-control::-webkit-input-placeholder{color:#999}.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee;opacity:1}textarea.form-control{height:auto}input[type=date]{line-height:34px}.form-group{margin-bottom:15px}.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px}.radio label,.checkbox label{display:inline;font-weight:400;cursor:pointer}.radio input[type=radio],.radio-inline input[type=radio],.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox]{float:left;margin-left:-20px}.radio+.radio,.checkbox+.checkbox{margin-top:-5px}.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:400;cursor:pointer}.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px}input[type=radio][disabled],input[type=checkbox][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type=radio],fieldset[disabled] input[type=checkbox],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed}.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-sm{height:30px;line-height:30px}textarea.input-sm,select[multiple].input-sm{height:auto}.input-lg{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-lg{height:46px;line-height:46px}textarea.input-lg,select[multiple].input-lg{height:auto}.has-feedback{position:relative}.has-feedback .form-control{padding-right:42.5px}.has-feedback .form-control-feedback{position:absolute;top:25px;right:0;display:block;width:34px;height:34px;line-height:34px;text-align:center}.has-success .help-block,.has-success .control-label,.has-success .radio,.has-success .checkbox,.has-success .radio-inline,.has-success .checkbox-inline{color:#3c763d}.has-success .form-control{border-color:#3c763d;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-success .form-control:focus{border-color:#2b542c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #67b168}.has-success .input-group-addon{color:#3c763d;border-color:#3c763d;background-color:#dff0d8}.has-success .form-control-feedback{color:#3c763d}.has-warning .help-block,.has-warning .control-label,.has-warning .radio,.has-warning .checkbox,.has-warning .radio-inline,.has-warning .checkbox-inline{color:#8a6d3b}.has-warning .form-control{border-color:#8a6d3b;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-warning .form-control:focus{border-color:#66512c;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #c0a16b}.has-warning .input-group-addon{color:#8a6d3b;border-color:#8a6d3b;background-color:#fcf8e3}.has-warning .form-control-feedback{color:#8a6d3b}.has-error .help-block,.has-error .control-label,.has-error .radio,.has-error .checkbox,.has-error .radio-inline,.has-error .checkbox-inline{color:#a94442}.has-error .form-control{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075);box-shadow:inset 0 1px 1px rgba(0,0,0,.075)}.has-error .form-control:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 6px #ce8483}.has-error .input-group-addon{color:#a94442;border-color:#a94442;background-color:#f2dede}.has-error .form-control-feedback{color:#a94442}.form-control-static{margin-bottom:0}.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373}@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.form-inline .form-control{display:inline-block;width:auto;vertical-align:middle}.form-inline .control-label{margin-bottom:0;vertical-align:middle}.form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.form-inline .radio input[type=radio],.form-inline .checkbox input[type=checkbox]{float:none;margin-left:0}.form-inline .has-feedback .form-control-feedback{top:0}}.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px}.form-horizontal .radio,.form-horizontal .checkbox{min-height:27px}.form-horizontal .form-group{margin-left:-15px;margin-right:-15px}.form-horizontal .form-control-static{padding-top:7px}@media (min-width:768px){.form-horizontal .control-label{text-align:right}}.form-horizontal .has-feedback .form-control-feedback{top:0;right:15px}.btn{display:inline-block;margin-bottom:0;font-weight:400;text-align:center;vertical-align:middle;cursor:pointer;background-image:none;border:1px solid transparent;white-space:nowrap;padding:6px 12px;font-size:14px;line-height:1.428571429;border-radius:4px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.btn:focus{outline:thin dotted;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px}.btn:hover,.btn:focus{color:#333;text-decoration:none}.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none}.btn-default{color:#333;background-color:#fff;border-color:#ccc}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333;background-color:#ebebeb;border-color:#adadad}.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none}.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#fff;border-color:#ccc}.btn-default .badge{color:#fff;background-color:#333}.btn-primary{color:#fff;background-color:#428bca;border-color:#357ebd}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#fff;background-color:#3276b1;border-color:#285e8e}.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none}.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd}.btn-primary .badge{color:#428bca;background-color:#fff}.btn-success{color:#fff;background-color:#5cb85c;border-color:#4cae4c}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#fff;background-color:#47a447;border-color:#398439}.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none}.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c}.btn-success .badge{color:#5cb85c;background-color:#fff}.btn-info{color:#fff;background-color:#5bc0de;border-color:#46b8da}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#fff;background-color:#39b3d7;border-color:#269abc}.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none}.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da}.btn-info .badge{color:#5bc0de;background-color:#fff}.btn-warning{color:#fff;background-color:#f0ad4e;border-color:#eea236}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#fff;background-color:#ed9c28;border-color:#d58512}.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none}.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236}.btn-warning .badge{color:#f0ad4e;background-color:#fff}.btn-danger{color:#fff;background-color:#d9534f;border-color:#d43f3a}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#fff;background-color:#d2322d;border-color:#ac2925}.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none}.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a}.btn-danger .badge{color:#d9534f;background-color:#fff}.btn-link{color:#428bca;font-weight:400;cursor:pointer;border-radius:0}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none}.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent}.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent}.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999;text-decoration:none}.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-sm{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-xs{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-block{display:block;width:100%;padding-left:0;padding-right:0}.btn-block+.btn-block{margin-top:5px}input[type=submit].btn-block,input[type=reset].btn-block,input[type=button].btn-block{width:100%}.fade{opacity:0;-webkit-transition:opacity .15s linear;transition:opacity .15s linear}.fade.in{opacity:1}.collapse{display:none}.collapse.in{display:block}.collapsing{position:relative;height:0;overflow:hidden;-webkit-transition:height .35s ease;transition:height .35s ease}@font-face{font-family:'Glyphicons Halflings';src:url(../fonts/glyphicons-halflings-regular.eot);src:url(../fonts/glyphicons-halflings-regular.eot?#iefix) format('embedded-opentype'),url(../fonts/glyphicons-halflings-regular.woff) format('woff'),url(../fonts/glyphicons-halflings-regular.ttf) format('truetype'),url(../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular) format('svg')}.glyphicon{position:relative;top:1px;display:inline-block;font-family:'Glyphicons Halflings';font-style:normal;font-weight:400;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.glyphicon-asterisk:before{content:"\2a"}.glyphicon-plus:before{content:"\2b"}.glyphicon-euro:before{content:"\20ac"}.glyphicon-minus:before{content:"\2212"}.glyphicon-cloud:before{content:"\2601"}.glyphicon-envelope:before{content:"\2709"}.glyphicon-pencil:before{content:"\270f"}.glyphicon-glass:before{content:"\e001"}.glyphicon-music:before{content:"\e002"}.glyphicon-search:before{content:"\e003"}.glyphicon-heart:before{content:"\e005"}.glyphicon-star:before{content:"\e006"}.glyphicon-star-empty:before{content:"\e007"}.glyphicon-user:before{content:"\e008"}.glyphicon-film:before{content:"\e009"}.glyphicon-th-large:before{content:"\e010"}.glyphicon-th:before{content:"\e011"}.glyphicon-th-list:before{content:"\e012"}.glyphicon-ok:before{content:"\e013"}.glyphicon-remove:before{content:"\e014"}.glyphicon-zoom-in:before{content:"\e015"}.glyphicon-zoom-out:before{content:"\e016"}.glyphicon-off:before{content:"\e017"}.glyphicon-signal:before{content:"\e018"}.glyphicon-cog:before{content:"\e019"}.glyphicon-trash:before{content:"\e020"}.glyphicon-home:before{content:"\e021"}.glyphicon-file:before{content:"\e022"}.glyphicon-time:before{content:"\e023"}.glyphicon-road:before{content:"\e024"}.glyphicon-download-alt:before{content:"\e025"}.glyphicon-download:before{content:"\e026"}.glyphicon-upload:before{content:"\e027"}.glyphicon-inbox:before{content:"\e028"}.glyphicon-play-circle:before{content:"\e029"}.glyphicon-repeat:before{content:"\e030"}.glyphicon-refresh:before{content:"\e031"}.glyphicon-list-alt:before{content:"\e032"}.glyphicon-lock:before{content:"\e033"}.glyphicon-flag:before{content:"\e034"}.glyphicon-headphones:before{content:"\e035"}.glyphicon-volume-off:before{content:"\e036"}.glyphicon-volume-down:before{content:"\e037"}.glyphicon-volume-up:before{content:"\e038"}.glyphicon-qrcode:before{content:"\e039"}.glyphicon-barcode:before{content:"\e040"}.glyphicon-tag:before{content:"\e041"}.glyphicon-tags:before{content:"\e042"}.glyphicon-book:before{content:"\e043"}.glyphicon-bookmark:before{content:"\e044"}.glyphicon-print:before{content:"\e045"}.glyphicon-camera:before{content:"\e046"}.glyphicon-font:before{content:"\e047"}.glyphicon-bold:before{content:"\e048"}.glyphicon-italic:before{content:"\e049"}.glyphicon-text-height:before{content:"\e050"}.glyphicon-text-width:before{content:"\e051"}.glyphicon-align-left:before{content:"\e052"}.glyphicon-align-center:before{content:"\e053"}.glyphicon-align-right:before{content:"\e054"}.glyphicon-align-justify:before{content:"\e055"}.glyphicon-list:before{content:"\e056"}.glyphicon-indent-left:before{content:"\e057"}.glyphicon-indent-right:before{content:"\e058"}.glyphicon-facetime-video:before{content:"\e059"}.glyphicon-picture:before{content:"\e060"}.glyphicon-map-marker:before{content:"\e062"}.glyphicon-adjust:before{content:"\e063"}.glyphicon-tint:before{content:"\e064"}.glyphicon-edit:before{content:"\e065"}.glyphicon-share:before{content:"\e066"}.glyphicon-check:before{content:"\e067"}.glyphicon-move:before{content:"\e068"}.glyphicon-step-backward:before{content:"\e069"}.glyphicon-fast-backward:before{content:"\e070"}.glyphicon-backward:before{content:"\e071"}.glyphicon-play:before{content:"\e072"}.glyphicon-pause:before{content:"\e073"}.glyphicon-stop:before{content:"\e074"}.glyphicon-forward:before{content:"\e075"}.glyphicon-fast-forward:before{content:"\e076"}.glyphicon-step-forward:before{content:"\e077"}.glyphicon-eject:before{content:"\e078"}.glyphicon-chevron-left:before{content:"\e079"}.glyphicon-chevron-right:before{content:"\e080"}.glyphicon-plus-sign:before{content:"\e081"}.glyphicon-minus-sign:before{content:"\e082"}.glyphicon-remove-sign:before{content:"\e083"}.glyphicon-ok-sign:before{content:"\e084"}.glyphicon-question-sign:before{content:"\e085"}.glyphicon-info-sign:before{content:"\e086"}.glyphicon-screenshot:before{content:"\e087"}.glyphicon-remove-circle:before{content:"\e088"}.glyphicon-ok-circle:before{content:"\e089"}.glyphicon-ban-circle:before{content:"\e090"}.glyphicon-arrow-left:before{content:"\e091"}.glyphicon-arrow-right:before{content:"\e092"}.glyphicon-arrow-up:before{content:"\e093"}.glyphicon-arrow-down:before{content:"\e094"}.glyphicon-share-alt:before{content:"\e095"}.glyphicon-resize-full:before{content:"\e096"}.glyphicon-resize-small:before{content:"\e097"}.glyphicon-exclamation-sign:before{content:"\e101"}.glyphicon-gift:before{content:"\e102"}.glyphicon-leaf:before{content:"\e103"}.glyphicon-fire:before{content:"\e104"}.glyphicon-eye-open:before{content:"\e105"}.glyphicon-eye-close:before{content:"\e106"}.glyphicon-warning-sign:before{content:"\e107"}.glyphicon-plane:before{content:"\e108"}.glyphicon-calendar:before{content:"\e109"}.glyphicon-random:before{content:"\e110"}.glyphicon-comment:before{content:"\e111"}.glyphicon-magnet:before{content:"\e112"}.glyphicon-chevron-up:before{content:"\e113"}.glyphicon-chevron-down:before{content:"\e114"}.glyphicon-retweet:before{content:"\e115"}.glyphicon-shopping-cart:before{content:"\e116"}.glyphicon-folder-close:before{content:"\e117"}.glyphicon-folder-open:before{content:"\e118"}.glyphicon-resize-vertical:before{content:"\e119"}.glyphicon-resize-horizontal:before{content:"\e120"}.glyphicon-hdd:before{content:"\e121"}.glyphicon-bullhorn:before{content:"\e122"}.glyphicon-bell:before{content:"\e123"}.glyphicon-certificate:before{content:"\e124"}.glyphicon-thumbs-up:before{content:"\e125"}.glyphicon-thumbs-down:before{content:"\e126"}.glyphicon-hand-right:before{content:"\e127"}.glyphicon-hand-left:before{content:"\e128"}.glyphicon-hand-up:before{content:"\e129"}.glyphicon-hand-down:before{content:"\e130"}.glyphicon-circle-arrow-right:before{content:"\e131"}.glyphicon-circle-arrow-left:before{content:"\e132"}.glyphicon-circle-arrow-up:before{content:"\e133"}.glyphicon-circle-arrow-down:before{content:"\e134"}.glyphicon-globe:before{content:"\e135"}.glyphicon-wrench:before{content:"\e136"}.glyphicon-tasks:before{content:"\e137"}.glyphicon-filter:before{content:"\e138"}.glyphicon-briefcase:before{content:"\e139"}.glyphicon-fullscreen:before{content:"\e140"}.glyphicon-dashboard:before{content:"\e141"}.glyphicon-paperclip:before{content:"\e142"}.glyphicon-heart-empty:before{content:"\e143"}.glyphicon-link:before{content:"\e144"}.glyphicon-phone:before{content:"\e145"}.glyphicon-pushpin:before{content:"\e146"}.glyphicon-usd:before{content:"\e148"}.glyphicon-gbp:before{content:"\e149"}.glyphicon-sort:before{content:"\e150"}.glyphicon-sort-by-alphabet:before{content:"\e151"}.glyphicon-sort-by-alphabet-alt:before{content:"\e152"}.glyphicon-sort-by-order:before{content:"\e153"}.glyphicon-sort-by-order-alt:before{content:"\e154"}.glyphicon-sort-by-attributes:before{content:"\e155"}.glyphicon-sort-by-attributes-alt:before{content:"\e156"}.glyphicon-unchecked:before{content:"\e157"}.glyphicon-expand:before{content:"\e158"}.glyphicon-collapse-down:before{content:"\e159"}.glyphicon-collapse-up:before{content:"\e160"}.glyphicon-log-in:before{content:"\e161"}.glyphicon-flash:before{content:"\e162"}.glyphicon-log-out:before{content:"\e163"}.glyphicon-new-window:before{content:"\e164"}.glyphicon-record:before{content:"\e165"}.glyphicon-save:before{content:"\e166"}.glyphicon-open:before{content:"\e167"}.glyphicon-saved:before{content:"\e168"}.glyphicon-import:before{content:"\e169"}.glyphicon-export:before{content:"\e170"}.glyphicon-send:before{content:"\e171"}.glyphicon-floppy-disk:before{content:"\e172"}.glyphicon-floppy-saved:before{content:"\e173"}.glyphicon-floppy-remove:before{content:"\e174"}.glyphicon-floppy-save:before{content:"\e175"}.glyphicon-floppy-open:before{content:"\e176"}.glyphicon-credit-card:before{content:"\e177"}.glyphicon-transfer:before{content:"\e178"}.glyphicon-cutlery:before{content:"\e179"}.glyphicon-header:before{content:"\e180"}.glyphicon-compressed:before{content:"\e181"}.glyphicon-earphone:before{content:"\e182"}.glyphicon-phone-alt:before{content:"\e183"}.glyphicon-tower:before{content:"\e184"}.glyphicon-stats:before{content:"\e185"}.glyphicon-sd-video:before{content:"\e186"}.glyphicon-hd-video:before{content:"\e187"}.glyphicon-subtitles:before{content:"\e188"}.glyphicon-sound-stereo:before{content:"\e189"}.glyphicon-sound-dolby:before{content:"\e190"}.glyphicon-sound-5-1:before{content:"\e191"}.glyphicon-sound-6-1:before{content:"\e192"}.glyphicon-sound-7-1:before{content:"\e193"}.glyphicon-copyright-mark:before{content:"\e194"}.glyphicon-registration-mark:before{content:"\e195"}.glyphicon-cloud-download:before{content:"\e197"}.glyphicon-cloud-upload:before{content:"\e198"}.glyphicon-tree-conifer:before{content:"\e199"}.glyphicon-tree-deciduous:before{content:"\e200"}.caret{display:inline-block;width:0;height:0;margin-left:2px;vertical-align:middle;border-top:4px solid;border-right:4px solid transparent;border-left:4px solid transparent}.dropdown{position:relative}.dropdown-toggle:focus{outline:0}.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;font-size:14px;background-color:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,.15);border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175);background-clip:padding-box}.dropdown-menu.pull-right{right:0;left:auto}.dropdown-menu .divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.dropdown-menu>li>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.428571429;color:#333;white-space:nowrap}.dropdown-menu>li>a:hover,.dropdown-menu>li>a:focus{text-decoration:none;color:#262626;background-color:#f5f5f5}.dropdown-menu>.active>a,.dropdown-menu>.active>a:hover,.dropdown-menu>.active>a:focus{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.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;background-color:transparent;background-image:none;filter:progid:DXImageTransform.Microsoft.gradient(enabled=false);cursor:not-allowed}.open>.dropdown-menu{display:block}.open>a{outline:0}.dropdown-menu-right{left:auto;right:0}.dropdown-menu-left{left:0;right:auto}.dropdown-header{display:block;padding:3px 20px;font-size:12px;line-height:1.428571429;color:#999}.dropdown-backdrop{position:fixed;left:0;right:0;bottom:0;top: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;content:""}.dropup .dropdown-menu,.navbar-fixed-bottom .dropdown .dropdown-menu{top:auto;bottom:100%;margin-bottom:1px}@media (min-width:768px){.navbar-right .dropdown-menu{left:auto;right:0}.navbar-right .dropdown-menu-left{left:0;right:auto}}.btn-group,.btn-group-vertical{position:relative;display:inline-block;vertical-align:middle}.btn-group>.btn,.btn-group-vertical>.btn{position:relative;float:left}.btn-group>.btn:hover,.btn-group-vertical>.btn:hover,.btn-group>.btn:focus,.btn-group-vertical>.btn:focus,.btn-group>.btn:active,.btn-group-vertical>.btn:active,.btn-group>.btn.active,.btn-group-vertical>.btn.active{z-index:2}.btn-group>.btn:focus,.btn-group-vertical>.btn:focus{outline:0}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-toolbar{margin-left:-5px}.btn-toolbar .btn-group,.btn-toolbar .input-group{float:left}.btn-toolbar>.btn,.btn-toolbar>.btn-group,.btn-toolbar>.input-group{margin-left:5px}.btn-group>.btn:not(:first-child):not(:last-child):not(.dropdown-toggle){border-radius:0}.btn-group>.btn:first-child{margin-left:0}.btn-group>.btn:first-child:not(:last-child):not(.dropdown-toggle){border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn:last-child:not(:first-child),.btn-group>.dropdown-toggle:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.btn-group>.btn-group{float:left}.btn-group>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group>.btn-group:first-child>.btn:last-child,.btn-group>.btn-group:first-child>.dropdown-toggle{border-bottom-right-radius:0;border-top-right-radius:0}.btn-group>.btn-group:last-child>.btn:first-child{border-bottom-left-radius:0;border-top-left-radius:0}.btn-group .dropdown-toggle:active,.btn-group.open .dropdown-toggle{outline:0}.btn-group-xs>.btn{padding:1px 5px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-sm>.btn{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}.btn-group-lg>.btn{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}.btn-group>.btn+.dropdown-toggle{padding-left:8px;padding-right:8px}.btn-group>.btn-lg+.dropdown-toggle{padding-left:12px;padding-right:12px}.btn-group.open .dropdown-toggle{-webkit-box-shadow:inset 0 3px 5px rgba(0,0,0,.125);box-shadow:inset 0 3px 5px rgba(0,0,0,.125)}.btn-group.open .dropdown-toggle.btn-link{-webkit-box-shadow:none;box-shadow:none}.btn .caret{margin-left:0}.btn-lg .caret{border-width:5px 5px 0;border-bottom-width:0}.dropup .btn-lg .caret{border-width:0 5px 5px}.btn-group-vertical>.btn,.btn-group-vertical>.btn-group,.btn-group-vertical>.btn-group>.btn{display:block;float:none;width:100%;max-width:100%}.btn-group-vertical>.btn-group>.btn{float:none}.btn-group-vertical>.btn+.btn,.btn-group-vertical>.btn+.btn-group,.btn-group-vertical>.btn-group+.btn,.btn-group-vertical>.btn-group+.btn-group{margin-top:-1px;margin-left:0}.btn-group-vertical>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group-vertical>.btn:first-child:not(:last-child){border-top-right-radius:4px;border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn:last-child:not(:first-child){border-bottom-left-radius:4px;border-top-right-radius:0;border-top-left-radius:0}.btn-group-vertical>.btn-group:not(:first-child):not(:last-child)>.btn{border-radius:0}.btn-group-vertical>.btn-group:first-child:not(:last-child)>.btn:last-child,.btn-group-vertical>.btn-group:first-child:not(:last-child)>.dropdown-toggle{border-bottom-right-radius:0;border-bottom-left-radius:0}.btn-group-vertical>.btn-group:last-child:not(:first-child)>.btn:first-child{border-top-right-radius:0;border-top-left-radius:0}.btn-group-justified{display:table;width:100%;table-layout:fixed;border-collapse:separate}.btn-group-justified>.btn,.btn-group-justified>.btn-group{float:none;display:table-cell;width:1%}.btn-group-justified>.btn-group .btn{width:100%}[data-toggle=buttons]>.btn>input[type=radio],[data-toggle=buttons]>.btn>input[type=checkbox]{display:none}.input-group{position:relative;display:table;border-collapse:separate}.input-group[class*=col-]{float:none;padding-left:0;padding-right:0}.input-group .form-control{float:left;width:100%;margin-bottom:0}.input-group-lg>.form-control,.input-group-lg>.input-group-addon,.input-group-lg>.input-group-btn>.btn{height:46px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px}select.input-group-lg>.form-control,select.input-group-lg>.input-group-addon,select.input-group-lg>.input-group-btn>.btn{height:46px;line-height:46px}textarea.input-group-lg>.form-control,textarea.input-group-lg>.input-group-addon,textarea.input-group-lg>.input-group-btn>.btn,select[multiple].input-group-lg>.form-control,select[multiple].input-group-lg>.input-group-addon,select[multiple].input-group-lg>.input-group-btn>.btn{height:auto}.input-group-sm>.form-control,.input-group-sm>.input-group-addon,.input-group-sm>.input-group-btn>.btn{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px}select.input-group-sm>.form-control,select.input-group-sm>.input-group-addon,select.input-group-sm>.input-group-btn>.btn{height:30px;line-height:30px}textarea.input-group-sm>.form-control,textarea.input-group-sm>.input-group-addon,textarea.input-group-sm>.input-group-btn>.btn,select[multiple].input-group-sm>.form-control,select[multiple].input-group-sm>.input-group-addon,select[multiple].input-group-sm>.input-group-btn>.btn{height:auto}.input-group-addon,.input-group-btn,.input-group .form-control{display:table-cell}.input-group-addon:not(:first-child):not(:last-child),.input-group-btn:not(:first-child):not(:last-child),.input-group .form-control:not(:first-child):not(:last-child){border-radius:0}.input-group-addon,.input-group-btn{width:1%;white-space:nowrap;vertical-align:middle}.input-group-addon{padding:6px 12px;font-size:14px;font-weight:400;line-height:1;color:#555;text-align:center;background-color:#eee;border:1px solid #ccc;border-radius:4px}.input-group-addon.input-sm{padding:5px 10px;font-size:12px;border-radius:3px}.input-group-addon.input-lg{padding:10px 16px;font-size:18px;border-radius:6px}.input-group-addon input[type=radio],.input-group-addon input[type=checkbox]{margin-top:0}.input-group .form-control:first-child,.input-group-addon:first-child,.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group>.btn,.input-group-btn:first-child>.dropdown-toggle,.input-group-btn:last-child>.btn:not(:last-child):not(.dropdown-toggle),.input-group-btn:last-child>.btn-group:not(:last-child)>.btn{border-bottom-right-radius:0;border-top-right-radius:0}.input-group-addon:first-child{border-right:0}.input-group .form-control:last-child,.input-group-addon:last-child,.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group>.btn,.input-group-btn:last-child>.dropdown-toggle,.input-group-btn:first-child>.btn:not(:first-child),.input-group-btn:first-child>.btn-group:not(:first-child)>.btn{border-bottom-left-radius:0;border-top-left-radius:0}.input-group-addon:last-child{border-left:0}.input-group-btn{position:relative;font-size:0;white-space:nowrap}.input-group-btn>.btn{position:relative}.input-group-btn>.btn+.btn{margin-left:-1px}.input-group-btn>.btn:hover,.input-group-btn>.btn:focus,.input-group-btn>.btn:active{z-index:2}.input-group-btn:first-child>.btn,.input-group-btn:first-child>.btn-group{margin-right:-1px}.input-group-btn:last-child>.btn,.input-group-btn:last-child>.btn-group{margin-left:-1px}.nav{margin-bottom:0;padding-left:0;list-style:none}.nav>li{position:relative;display:block}.nav>li>a{position:relative;display:block;padding:10px 15px}.nav>li>a:hover,.nav>li>a:focus{text-decoration:none;background-color:#eee}.nav>li.disabled>a{color:#999}.nav>li.disabled>a:hover,.nav>li.disabled>a:focus{color:#999;text-decoration:none;background-color:transparent;cursor:not-allowed}.nav .open>a,.nav .open>a:hover,.nav .open>a:focus{background-color:#eee;border-color:#428bca}.nav .nav-divider{height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5}.nav>li>a>img{max-width:none}.nav-tabs{border-bottom:1px solid #ddd}.nav-tabs>li{float:left;margin-bottom:-1px}.nav-tabs>li>a{margin-right:2px;line-height:1.428571429;border:1px solid transparent;border-radius:4px 4px 0 0}.nav-tabs>li>a:hover{border-color:#eee #eee #ddd}.nav-tabs>li.active>a,.nav-tabs>li.active>a:hover,.nav-tabs>li.active>a:focus{color:#555;background-color:#fff;border:1px solid #ddd;border-bottom-color:transparent;cursor:default}.nav-tabs.nav-justified{width:100%;border-bottom:0}.nav-tabs.nav-justified>li{float:none}.nav-tabs.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-tabs.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-tabs.nav-justified>li{display:table-cell;width:1%}.nav-tabs.nav-justified>li>a{margin-bottom:0}}.nav-tabs.nav-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs.nav-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs.nav-justified>.active>a,.nav-tabs.nav-justified>.active>a:hover,.nav-tabs.nav-justified>.active>a:focus{border-bottom-color:#fff}}.nav-pills>li{float:left}.nav-pills>li>a{border-radius:4px}.nav-pills>li+li{margin-left:2px}.nav-pills>li.active>a,.nav-pills>li.active>a:hover,.nav-pills>li.active>a:focus{color:#fff;background-color:#428bca}.nav-stacked>li{float:none}.nav-stacked>li+li{margin-top:2px;margin-left:0}.nav-justified{width:100%}.nav-justified>li{float:none}.nav-justified>li>a{text-align:center;margin-bottom:5px}.nav-justified>.dropdown .dropdown-menu{top:auto;left:auto}@media (min-width:768px){.nav-justified>li{display:table-cell;width:1%}.nav-justified>li>a{margin-bottom:0}}.nav-tabs-justified{border-bottom:0}.nav-tabs-justified>li>a{margin-right:0;border-radius:4px}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border:1px solid #ddd}@media (min-width:768px){.nav-tabs-justified>li>a{border-bottom:1px solid #ddd;border-radius:4px 4px 0 0}.nav-tabs-justified>.active>a,.nav-tabs-justified>.active>a:hover,.nav-tabs-justified>.active>a:focus{border-bottom-color:#fff}}.tab-content>.tab-pane{display:none}.tab-content>.active{display:block}.nav-tabs .dropdown-menu{margin-top:-1px;border-top-right-radius:0;border-top-left-radius:0}.navbar{position:relative;min-height:50px;margin-bottom:20px;border:1px solid transparent}@media (min-width:768px){.navbar{border-radius:4px}}@media (min-width:768px){.navbar-header{float:left}}.navbar-collapse{max-height:340px;overflow-x:visible;padding-right:15px;padding-left:15px;border-top:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.1);-webkit-overflow-scrolling:touch}.navbar-collapse.in{overflow-y:auto}@media (min-width:768px){.navbar-collapse{width:auto;border-top:0;box-shadow:none}.navbar-collapse.collapse{display:block!important;height:auto!important;padding-bottom:0;overflow:visible!important}.navbar-collapse.in{overflow-y:visible}.navbar-fixed-top .navbar-collapse,.navbar-static-top .navbar-collapse,.navbar-fixed-bottom .navbar-collapse{padding-left:0;padding-right:0}}.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:-15px;margin-left:-15px}@media (min-width:768px){.container>.navbar-header,.container-fluid>.navbar-header,.container>.navbar-collapse,.container-fluid>.navbar-collapse{margin-right:0;margin-left:0}}.navbar-static-top{z-index:1000;border-width:0 0 1px}@media (min-width:768px){.navbar-static-top{border-radius:0}}.navbar-fixed-top,.navbar-fixed-bottom{position:fixed;right:0;left:0;z-index:1030}@media (min-width:768px){.navbar-fixed-top,.navbar-fixed-bottom{border-radius:0}}.navbar-fixed-top{top:0;border-width:0 0 1px}.navbar-fixed-bottom{bottom:0;margin-bottom:0;border-width:1px 0 0}.navbar-brand{float:left;padding:15px;font-size:18px;line-height:20px;height:20px}.navbar-brand:hover,.navbar-brand:focus{text-decoration:none}@media (min-width:768px){.navbar>.container .navbar-brand,.navbar>.container-fluid .navbar-brand{margin-left:-15px}}.navbar-toggle{position:relative;float:right;margin-right:15px;padding:9px 10px;margin-top:8px;margin-bottom:8px;background-color:transparent;background-image:none;border:1px solid transparent;border-radius:4px}.navbar-toggle:focus{outline:0}.navbar-toggle .icon-bar{display:block;width:22px;height:2px;border-radius:1px}.navbar-toggle .icon-bar+.icon-bar{margin-top:4px}@media (min-width:768px){.navbar-toggle{display:none}}.navbar-nav{margin:7.5px -15px}.navbar-nav>li>a{padding-top:10px;padding-bottom:10px;line-height:20px}@media (max-width:767px){.navbar-nav .open .dropdown-menu{position:static;float:none;width:auto;margin-top:0;background-color:transparent;border:0;box-shadow:none}.navbar-nav .open .dropdown-menu>li>a,.navbar-nav .open .dropdown-menu .dropdown-header{padding:5px 15px 5px 25px}.navbar-nav .open .dropdown-menu>li>a{line-height:20px}.navbar-nav .open .dropdown-menu>li>a:hover,.navbar-nav .open .dropdown-menu>li>a:focus{background-image:none}}@media (min-width:768px){.navbar-nav{float:left;margin:0}.navbar-nav>li{float:left}.navbar-nav>li>a{padding-top:15px;padding-bottom:15px}.navbar-nav.navbar-right:last-child{margin-right:-15px}}@media (min-width:768px){.navbar-left{float:left!important}.navbar-right{float:right!important}}.navbar-form{margin-left:-15px;margin-right:-15px;padding:10px 15px;border-top:1px solid transparent;border-bottom:1px solid transparent;-webkit-box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);box-shadow:inset 0 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1);margin-top:8px;margin-bottom:8px}@media (min-width:768px){.navbar-form .form-group{display:inline-block;margin-bottom:0;vertical-align:middle}.navbar-form .form-control{display:inline-block;width:auto;vertical-align:middle}.navbar-form .control-label{margin-bottom:0;vertical-align:middle}.navbar-form .radio,.navbar-form .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;vertical-align:middle}.navbar-form .radio input[type=radio],.navbar-form .checkbox input[type=checkbox]{float:none;margin-left:0}.navbar-form .has-feedback .form-control-feedback{top:0}}@media (max-width:767px){.navbar-form .form-group{margin-bottom:5px}}@media (min-width:768px){.navbar-form{width:auto;border:0;margin-left:0;margin-right:0;padding-top:0;padding-bottom:0;-webkit-box-shadow:none;box-shadow:none}.navbar-form.navbar-right:last-child{margin-right:-15px}}.navbar-nav>li>.dropdown-menu{margin-top:0;border-top-right-radius:0;border-top-left-radius:0}.navbar-fixed-bottom .navbar-nav>li>.dropdown-menu{border-bottom-right-radius:0;border-bottom-left-radius:0}.navbar-btn{margin-top:8px;margin-bottom:8px}.navbar-btn.btn-sm{margin-top:10px;margin-bottom:10px}.navbar-btn.btn-xs{margin-top:14px;margin-bottom:14px}.navbar-text{margin-top:15px;margin-bottom:15px}@media (min-width:768px){.navbar-text{float:left;margin-left:15px;margin-right:15px}.navbar-text.navbar-right:last-child{margin-right:0}}.navbar-default{background-color:#f8f8f8;border-color:#e7e7e7}.navbar-default .navbar-brand{color:#777}.navbar-default .navbar-brand:hover,.navbar-default .navbar-brand:focus{color:#5e5e5e;background-color:transparent}.navbar-default .navbar-text{color:#777}.navbar-default .navbar-nav>li>a{color:#777}.navbar-default .navbar-nav>li>a:hover,.navbar-default .navbar-nav>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav>.active>a,.navbar-default .navbar-nav>.active>a:hover,.navbar-default .navbar-nav>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav>.disabled>a,.navbar-default .navbar-nav>.disabled>a:hover,.navbar-default .navbar-nav>.disabled>a:focus{color:#ccc;background-color:transparent}.navbar-default .navbar-toggle{border-color:#ddd}.navbar-default .navbar-toggle:hover,.navbar-default .navbar-toggle:focus{background-color:#ddd}.navbar-default .navbar-toggle .icon-bar{background-color:#888}.navbar-default .navbar-collapse,.navbar-default .navbar-form{border-color:#e7e7e7}.navbar-default .navbar-nav>.open>a,.navbar-default .navbar-nav>.open>a:hover,.navbar-default .navbar-nav>.open>a:focus{background-color:#e7e7e7;color:#555}@media (max-width:767px){.navbar-default .navbar-nav .open .dropdown-menu>li>a{color:#777}.navbar-default .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>li>a:focus{color:#333;background-color:transparent}.navbar-default .navbar-nav .open .dropdown-menu>.active>a,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.active>a:focus{color:#555;background-color:#e7e7e7}.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-default .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#ccc;background-color:transparent}}.navbar-default .navbar-link{color:#777}.navbar-default .navbar-link:hover{color:#333}.navbar-inverse{background-color:#222;border-color:#080808}.navbar-inverse .navbar-brand{color:#999}.navbar-inverse .navbar-brand:hover,.navbar-inverse .navbar-brand:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-text{color:#999}.navbar-inverse .navbar-nav>li>a{color:#999}.navbar-inverse .navbar-nav>li>a:hover,.navbar-inverse .navbar-nav>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav>.active>a,.navbar-inverse .navbar-nav>.active>a:hover,.navbar-inverse .navbar-nav>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav>.disabled>a,.navbar-inverse .navbar-nav>.disabled>a:hover,.navbar-inverse .navbar-nav>.disabled>a:focus{color:#444;background-color:transparent}.navbar-inverse .navbar-toggle{border-color:#333}.navbar-inverse .navbar-toggle:hover,.navbar-inverse .navbar-toggle:focus{background-color:#333}.navbar-inverse .navbar-toggle .icon-bar{background-color:#fff}.navbar-inverse .navbar-collapse,.navbar-inverse .navbar-form{border-color:#101010}.navbar-inverse .navbar-nav>.open>a,.navbar-inverse .navbar-nav>.open>a:hover,.navbar-inverse .navbar-nav>.open>a:focus{background-color:#080808;color:#fff}@media (max-width:767px){.navbar-inverse .navbar-nav .open .dropdown-menu>.dropdown-header{border-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu .divider{background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a{color:#999}.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>li>a:focus{color:#fff;background-color:transparent}.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.active>a:focus{color:#fff;background-color:#080808}.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:hover,.navbar-inverse .navbar-nav .open .dropdown-menu>.disabled>a:focus{color:#444;background-color:transparent}}.navbar-inverse .navbar-link{color:#999}.navbar-inverse .navbar-link:hover{color:#fff}.breadcrumb{padding:8px 15px;margin-bottom:20px;list-style:none;background-color:#f5f5f5;border-radius:4px}.breadcrumb>li{display:inline-block}.breadcrumb>li+li:before{content:"/\00a0";padding:0 5px;color:#ccc}.breadcrumb>.active{color:#999}.pagination{display:inline-block;padding-left:0;margin:20px 0;border-radius:4px}.pagination>li{display:inline}.pagination>li>a,.pagination>li>span{position:relative;float:left;padding:6px 12px;line-height:1.428571429;text-decoration:none;color:#428bca;background-color:#fff;border:1px solid #ddd;margin-left:-1px}.pagination>li:first-child>a,.pagination>li:first-child>span{margin-left:0;border-bottom-left-radius:4px;border-top-left-radius:4px}.pagination>li:last-child>a,.pagination>li:last-child>span{border-bottom-right-radius:4px;border-top-right-radius:4px}.pagination>li>a:hover,.pagination>li>span:hover,.pagination>li>a:focus,.pagination>li>span:focus{color:#2a6496;background-color:#eee;border-color:#ddd}.pagination>.active>a,.pagination>.active>span,.pagination>.active>a:hover,.pagination>.active>span:hover,.pagination>.active>a:focus,.pagination>.active>span:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca;cursor:default}.pagination>.disabled>span,.pagination>.disabled>span:hover,.pagination>.disabled>span:focus,.pagination>.disabled>a,.pagination>.disabled>a:hover,.pagination>.disabled>a:focus{color:#999;background-color:#fff;border-color:#ddd;cursor:not-allowed}.pagination-lg>li>a,.pagination-lg>li>span{padding:10px 16px;font-size:18px}.pagination-lg>li:first-child>a,.pagination-lg>li:first-child>span{border-bottom-left-radius:6px;border-top-left-radius:6px}.pagination-lg>li:last-child>a,.pagination-lg>li:last-child>span{border-bottom-right-radius:6px;border-top-right-radius:6px}.pagination-sm>li>a,.pagination-sm>li>span{padding:5px 10px;font-size:12px}.pagination-sm>li:first-child>a,.pagination-sm>li:first-child>span{border-bottom-left-radius:3px;border-top-left-radius:3px}.pagination-sm>li:last-child>a,.pagination-sm>li:last-child>span{border-bottom-right-radius:3px;border-top-right-radius:3px}.pager{padding-left:0;margin:20px 0;list-style:none;text-align:center}.pager li{display:inline}.pager li>a,.pager li>span{display:inline-block;padding:5px 14px;background-color:#fff;border:1px solid #ddd;border-radius:15px}.pager li>a:hover,.pager li>a:focus{text-decoration:none;background-color:#eee}.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;background-color:#fff;cursor:not-allowed}.label{display:inline;padding:.2em .6em .3em;font-size:75%;font-weight:700;line-height:1;color:#fff;text-align:center;white-space:nowrap;vertical-align:baseline;border-radius:.25em}.label[href]:hover,.label[href]:focus{color:#fff;text-decoration:none;cursor:pointer}.label:empty{display:none}.btn .label{position:relative;top:-1px}.label-default{background-color:#999}.label-default[href]:hover,.label-default[href]:focus{background-color:gray}.label-primary{background-color:#428bca}.label-primary[href]:hover,.label-primary[href]:focus{background-color:#3071a9}.label-success{background-color:#5cb85c}.label-success[href]:hover,.label-success[href]:focus{background-color:#449d44}.label-info{background-color:#5bc0de}.label-info[href]:hover,.label-info[href]:focus{background-color:#31b0d5}.label-warning{background-color:#f0ad4e}.label-warning[href]:hover,.label-warning[href]:focus{background-color:#ec971f}.label-danger{background-color:#d9534f}.label-danger[href]:hover,.label-danger[href]:focus{background-color:#c9302c}.badge{display:inline-block;min-width:10px;padding:3px 7px;font-size:12px;font-weight:700;color:#fff;line-height:1;vertical-align:baseline;white-space:nowrap;text-align:center;background-color:#999;border-radius:10px}.badge:empty{display:none}.btn .badge{position:relative;top:-1px}.btn-xs .badge{top:0;padding:1px 5px}a.badge:hover,a.badge:focus{color:#fff;text-decoration:none;cursor:pointer}a.list-group-item.active>.badge,.nav-pills>.active>a>.badge{color:#428bca;background-color:#fff}.nav-pills>li>a>.badge{margin-left:3px}.jumbotron{padding:30px;margin-bottom:30px;color:inherit;background-color:#eee}.jumbotron h1,.jumbotron .h1{color:inherit}.jumbotron p{margin-bottom:15px;font-size:21px;font-weight:200}.container .jumbotron{border-radius:6px}.jumbotron .container{max-width:100%}@media screen and (min-width:768px){.jumbotron{padding-top:48px;padding-bottom:48px}.container .jumbotron{padding-left:60px;padding-right:60px}.jumbotron h1,.jumbotron .h1{font-size:63px}}.thumbnail{display:block;padding:4px;margin-bottom:20px;line-height:1.428571429;background-color:#fff;border:1px solid #ddd;border-radius:4px;-webkit-transition:all .2s ease-in-out;transition:all .2s ease-in-out}.thumbnail>img,.thumbnail a>img{display:block;max-width:100%;height:auto;margin-left:auto;margin-right:auto}a.thumbnail:hover,a.thumbnail:focus,a.thumbnail.active{border-color:#428bca}.thumbnail .caption{padding:9px;color:#333}.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px}.alert h4{margin-top:0;color:inherit}.alert .alert-link{font-weight:700}.alert>p,.alert>ul{margin-bottom:0}.alert>p+p{margin-top:5px}.alert-dismissable{padding-right:35px}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit}.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#3c763d}.alert-success hr{border-top-color:#c9e2b3}.alert-success .alert-link{color:#2b542c}.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#31708f}.alert-info hr{border-top-color:#a6e1ec}.alert-info .alert-link{color:#245269}.alert-warning{background-color:#fcf8e3;border-color:#faebcc;color:#8a6d3b}.alert-warning hr{border-top-color:#f7e1b5}.alert-warning .alert-link{color:#66512c}.alert-danger{background-color:#f2dede;border-color:#ebccd1;color:#a94442}.alert-danger hr{border-top-color:#e4b9c0}.alert-danger .alert-link{color:#843534}@-webkit-keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}@keyframes progress-bar-stripes{from{background-position:40px 0}to{background-position:0 0}}.progress{overflow:hidden;height:20px;margin-bottom:20px;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#428bca;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.progress-striped .progress-bar{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-size:40px 40px}.progress.active .progress-bar{-webkit-animation:progress-bar-stripes 2s linear infinite;animation:progress-bar-stripes 2s linear infinite}.progress-bar-success{background-color:#5cb85c}.progress-striped .progress-bar-success{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-info{background-color:#5bc0de}.progress-striped .progress-bar-info{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-warning{background-color:#f0ad4e}.progress-striped .progress-bar-warning{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.progress-bar-danger{background-color:#d9534f}.progress-striped .progress-bar-danger{background-image:-webkit-linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent);background-image:linear-gradient(45deg,rgba(255,255,255,.15) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.15) 50%,rgba(255,255,255,.15) 75%,transparent 75%,transparent)}.media,.media-body{overflow:hidden;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{padding-left:0;list-style:none}.list-group{margin-bottom:20px;padding-left:0}.list-group-item{position:relative;display:block;padding:10px 15px;margin-bottom:-1px;background-color:#fff;border:1px solid #ddd}.list-group-item:first-child{border-top-right-radius:4px;border-top-left-radius:4px}.list-group-item:last-child{margin-bottom:0;border-bottom-right-radius:4px;border-bottom-left-radius:4px}.list-group-item>.badge{float:right}.list-group-item>.badge+.badge{margin-right:5px}a.list-group-item{color:#555}a.list-group-item .list-group-item-heading{color:#333}a.list-group-item:hover,a.list-group-item:focus{text-decoration:none;background-color:#f5f5f5}a.list-group-item.active,a.list-group-item.active:hover,a.list-group-item.active:focus{z-index:2;color:#fff;background-color:#428bca;border-color:#428bca}a.list-group-item.active .list-group-item-heading,a.list-group-item.active:hover .list-group-item-heading,a.list-group-item.active:focus .list-group-item-heading{color:inherit}a.list-group-item.active .list-group-item-text,a.list-group-item.active:hover .list-group-item-text,a.list-group-item.active:focus .list-group-item-text{color:#e1edf7}.list-group-item-success{color:#3c763d;background-color:#dff0d8}a.list-group-item-success{color:#3c763d}a.list-group-item-success .list-group-item-heading{color:inherit}a.list-group-item-success:hover,a.list-group-item-success:focus{color:#3c763d;background-color:#d0e9c6}a.list-group-item-success.active,a.list-group-item-success.active:hover,a.list-group-item-success.active:focus{color:#fff;background-color:#3c763d;border-color:#3c763d}.list-group-item-info{color:#31708f;background-color:#d9edf7}a.list-group-item-info{color:#31708f}a.list-group-item-info .list-group-item-heading{color:inherit}a.list-group-item-info:hover,a.list-group-item-info:focus{color:#31708f;background-color:#c4e3f3}a.list-group-item-info.active,a.list-group-item-info.active:hover,a.list-group-item-info.active:focus{color:#fff;background-color:#31708f;border-color:#31708f}.list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3}a.list-group-item-warning{color:#8a6d3b}a.list-group-item-warning .list-group-item-heading{color:inherit}a.list-group-item-warning:hover,a.list-group-item-warning:focus{color:#8a6d3b;background-color:#faf2cc}a.list-group-item-warning.active,a.list-group-item-warning.active:hover,a.list-group-item-warning.active:focus{color:#fff;background-color:#8a6d3b;border-color:#8a6d3b}.list-group-item-danger{color:#a94442;background-color:#f2dede}a.list-group-item-danger{color:#a94442}a.list-group-item-danger .list-group-item-heading{color:inherit}a.list-group-item-danger:hover,a.list-group-item-danger:focus{color:#a94442;background-color:#ebcccc}a.list-group-item-danger.active,a.list-group-item-danger.active:hover,a.list-group-item-danger.active:focus{color:#fff;background-color:#a94442;border-color:#a94442}.list-group-item-heading{margin-top:0;margin-bottom:5px}.list-group-item-text{margin-bottom:0;line-height:1.3}.panel{margin-bottom:20px;background-color:#fff;border:1px solid transparent;border-radius:4px;-webkit-box-shadow:0 1px 1px rgba(0,0,0,.05);box-shadow:0 1px 1px rgba(0,0,0,.05)}.panel-body{padding:15px}.panel>.list-group{margin-bottom:0}.panel>.list-group .list-group-item{border-width:1px 0;border-radius:0}.panel>.list-group .list-group-item:first-child{border-top:0}.panel>.list-group .list-group-item:last-child{border-bottom:0}.panel>.list-group:first-child .list-group-item:first-child{border-top-right-radius:3px;border-top-left-radius:3px}.panel>.list-group:last-child .list-group-item:last-child{border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-heading+.list-group .list-group-item:first-child{border-top-width:0}.panel>.table,.panel>.table-responsive>.table{margin-bottom:0}.panel>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:first-child,.panel>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:first-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:first-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:first-child{border-top-left-radius:3px}.panel>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child td:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child td:last-child,.panel>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>thead:first-child>tr:first-child th:last-child,.panel>.table:first-child>tbody:first-child>tr:first-child th:last-child,.panel>.table-responsive:first-child>.table:first-child>tbody:first-child>tr:first-child th:last-child{border-top-right-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:first-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:first-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:first-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:first-child{border-bottom-left-radius:3px}.panel>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child td:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child td:last-child,.panel>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tbody:last-child>tr:last-child th:last-child,.panel>.table:last-child>tfoot:last-child>tr:last-child th:last-child,.panel>.table-responsive:last-child>.table:last-child>tfoot:last-child>tr:last-child th:last-child{border-bottom-right-radius:3px}.panel>.panel-body+.table,.panel>.panel-body+.table-responsive{border-top:1px solid #ddd}.panel>.table>tbody:first-child>tr:first-child th,.panel>.table>tbody:first-child>tr:first-child td{border-top:0}.panel>.table-bordered,.panel>.table-responsive>.table-bordered{border:0}.panel>.table-bordered>thead>tr>th:first-child,.panel>.table-responsive>.table-bordered>thead>tr>th:first-child,.panel>.table-bordered>tbody>tr>th:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:first-child,.panel>.table-bordered>tfoot>tr>th:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:first-child,.panel>.table-bordered>thead>tr>td:first-child,.panel>.table-responsive>.table-bordered>thead>tr>td:first-child,.panel>.table-bordered>tbody>tr>td:first-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:first-child,.panel>.table-bordered>tfoot>tr>td:first-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:first-child{border-left:0}.panel>.table-bordered>thead>tr>th:last-child,.panel>.table-responsive>.table-bordered>thead>tr>th:last-child,.panel>.table-bordered>tbody>tr>th:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>th:last-child,.panel>.table-bordered>tfoot>tr>th:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>th:last-child,.panel>.table-bordered>thead>tr>td:last-child,.panel>.table-responsive>.table-bordered>thead>tr>td:last-child,.panel>.table-bordered>tbody>tr>td:last-child,.panel>.table-responsive>.table-bordered>tbody>tr>td:last-child,.panel>.table-bordered>tfoot>tr>td:last-child,.panel>.table-responsive>.table-bordered>tfoot>tr>td:last-child{border-right:0}.panel>.table-bordered>thead>tr:first-child>th,.panel>.table-responsive>.table-bordered>thead>tr:first-child>th,.panel>.table-bordered>tbody>tr:first-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>th,.panel>.table-bordered>tfoot>tr:first-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:first-child>th,.panel>.table-bordered>thead>tr:first-child>td,.panel>.table-responsive>.table-bordered>thead>tr:first-child>td,.panel>.table-bordered>tbody>tr:first-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:first-child>td,.panel>.table-bordered>tfoot>tr:first-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:first-child>td{border-top:0}.panel>.table-bordered>thead>tr:last-child>th,.panel>.table-responsive>.table-bordered>thead>tr:last-child>th,.panel>.table-bordered>tbody>tr:last-child>th,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>th,.panel>.table-bordered>tfoot>tr:last-child>th,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>th,.panel>.table-bordered>thead>tr:last-child>td,.panel>.table-responsive>.table-bordered>thead>tr:last-child>td,.panel>.table-bordered>tbody>tr:last-child>td,.panel>.table-responsive>.table-bordered>tbody>tr:last-child>td,.panel>.table-bordered>tfoot>tr:last-child>td,.panel>.table-responsive>.table-bordered>tfoot>tr:last-child>td{border-bottom:0}.panel>.table-responsive{border:0;margin-bottom:0}.panel-heading{padding:10px 15px;border-bottom:1px solid transparent;border-top-right-radius:3px;border-top-left-radius:3px}.panel-heading>.dropdown .dropdown-toggle{color:inherit}.panel-title{margin-top:0;margin-bottom:0;font-size:16px;color:inherit}.panel-title>a{color:inherit}.panel-footer{padding:10px 15px;background-color:#f5f5f5;border-top:1px solid #ddd;border-bottom-right-radius:3px;border-bottom-left-radius:3px}.panel-group{margin-bottom:20px}.panel-group .panel{margin-bottom:0;border-radius:4px;overflow:hidden}.panel-group .panel+.panel{margin-top:5px}.panel-group .panel-heading{border-bottom:0}.panel-group .panel-heading+.panel-collapse .panel-body{border-top:1px solid #ddd}.panel-group .panel-footer{border-top:0}.panel-group .panel-footer+.panel-collapse .panel-body{border-bottom:1px solid #ddd}.panel-default{border-color:#ddd}.panel-default>.panel-heading{color:#333;background-color:#f5f5f5;border-color:#ddd}.panel-default>.panel-heading+.panel-collapse .panel-body{border-top-color:#ddd}.panel-default>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ddd}.panel-primary{border-color:#428bca}.panel-primary>.panel-heading{color:#fff;background-color:#428bca;border-color:#428bca}.panel-primary>.panel-heading+.panel-collapse .panel-body{border-top-color:#428bca}.panel-primary>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#428bca}.panel-success{border-color:#d6e9c6}.panel-success>.panel-heading{color:#3c763d;background-color:#dff0d8;border-color:#d6e9c6}.panel-success>.panel-heading+.panel-collapse .panel-body{border-top-color:#d6e9c6}.panel-success>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#d6e9c6}.panel-info{border-color:#bce8f1}.panel-info>.panel-heading{color:#31708f;background-color:#d9edf7;border-color:#bce8f1}.panel-info>.panel-heading+.panel-collapse .panel-body{border-top-color:#bce8f1}.panel-info>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#bce8f1}.panel-warning{border-color:#faebcc}.panel-warning>.panel-heading{color:#8a6d3b;background-color:#fcf8e3;border-color:#faebcc}.panel-warning>.panel-heading+.panel-collapse .panel-body{border-top-color:#faebcc}.panel-warning>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#faebcc}.panel-danger{border-color:#ebccd1}.panel-danger>.panel-heading{color:#a94442;background-color:#f2dede;border-color:#ebccd1}.panel-danger>.panel-heading+.panel-collapse .panel-body{border-top-color:#ebccd1}.panel-danger>.panel-footer+.panel-collapse .panel-body{border-bottom-color:#ebccd1}.well{min-height:20px;padding:19px;margin-bottom:20px;background-color:#f5f5f5;border:1px solid #e3e3e3;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.05);box-shadow:inset 0 1px 1px rgba(0,0,0,.05)}.well blockquote{border-color:#ddd;border-color:rgba(0,0,0,.15)}.well-lg{padding:24px;border-radius:6px}.well-sm{padding:9px;border-radius:3px}.close{float:right;font-size:21px;font-weight:700;line-height:1;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:.5;filter:alpha(opacity=50)}button.close{padding:0;cursor:pointer;background:0 0;border:0;-webkit-appearance:none}.modal-open{overflow:hidden}.modal{display:none;overflow:auto;overflow-y:scroll;position:fixed;top:0;right:0;bottom:0;left:0;z-index:1050;-webkit-overflow-scrolling:touch;outline:0}.modal.fade .modal-dialog{-webkit-transform:translate(0,-25%);-ms-transform:translate(0,-25%);transform:translate(0,-25%);-webkit-transition:-webkit-transform .3s ease-out;-moz-transition:-moz-transform .3s ease-out;-o-transition:-o-transform .3s ease-out;transition:transform .3s ease-out}.modal.in .modal-dialog{-webkit-transform:translate(0,0);-ms-transform:translate(0,0);transform:translate(0,0)}.modal-dialog{position:relative;width:auto;margin:10px}.modal-content{position:relative;background-color:#fff;border:1px solid #999;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);background-clip:padding-box;outline:0}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:1040;background-color:#000}.modal-backdrop.fade{opacity:0;filter:alpha(opacity=0)}.modal-backdrop.in{opacity:.5;filter:alpha(opacity=50)}.modal-header{padding:15px;border-bottom:1px solid #e5e5e5;min-height:16.428571429px}.modal-header .close{margin-top:-2px}.modal-title{margin:0;line-height:1.428571429}.modal-body{position:relative;padding:20px}.modal-footer{margin-top:15px;padding:19px 20px 20px;text-align:right;border-top:1px solid #e5e5e5}.modal-footer .btn+.btn{margin-left:5px;margin-bottom:0}.modal-footer .btn-group .btn+.btn{margin-left:-1px}.modal-footer .btn-block+.btn-block{margin-left:0}@media (min-width:768px){.modal-dialog{width:600px;margin:30px auto}.modal-content{-webkit-box-shadow:0 5px 15px rgba(0,0,0,.5);box-shadow:0 5px 15px rgba(0,0,0,.5)}.modal-sm{width:300px}.modal-lg{width:900px}}.tooltip{position:absolute;z-index:1030;display:block;visibility:visible;font-size:12px;line-height:1.4;opacity:0;filter:alpha(opacity=0)}.tooltip.in{opacity:.9;filter:alpha(opacity=90)}.tooltip.top{margin-top:-3px;padding:5px 0}.tooltip.right{margin-left:3px;padding:0 5px}.tooltip.bottom{margin-top:3px;padding:5px 0}.tooltip.left{margin-left:-3px;padding:0 5px}.tooltip-inner{max-width:200px;padding:3px 8px;color:#fff;text-align:center;text-decoration:none;background-color:#000;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-width:5px 5px 0;border-top-color:#000}.tooltip.top-left .tooltip-arrow{bottom:0;left:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.top-right .tooltip-arrow{bottom:0;right:5px;border-width:5px 5px 0;border-top-color:#000}.tooltip.right .tooltip-arrow{top:50%;left:0;margin-top:-5px;border-width:5px 5px 5px 0;border-right-color:#000}.tooltip.left .tooltip-arrow{top:50%;right:0;margin-top:-5px;border-width:5px 0 5px 5px;border-left-color:#000}.tooltip.bottom .tooltip-arrow{top:0;left:50%;margin-left:-5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-left .tooltip-arrow{top:0;left:5px;border-width:0 5px 5px;border-bottom-color:#000}.tooltip.bottom-right .tooltip-arrow{top:0;right:5px;border-width:0 5px 5px;border-bottom-color:#000}.popover{position:absolute;top:0;left:0;z-index:1010;display:none;padding:1px;text-align:left;background-color:#fff;background-clip:padding-box;border:1px solid #ccc;border:1px solid rgba(0,0,0,.2);border-radius:6px;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);white-space:normal}.popover.top{margin-top:-10px}.popover.right{margin-left:10px}.popover.bottom{margin-top:10px}.popover.left{margin-left:-10px}.popover-title{margin:0;padding:8px 14px;font-size:14px;font-weight:400;line-height:18px;background-color:#f7f7f7;border-bottom:1px solid #ebebeb;border-radius:5px 5px 0 0}.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{left:50%;margin-left:-11px;border-bottom-width:0;border-top-color:#999;border-top-color:rgba(0,0,0,.25);bottom:-11px}.popover.top .arrow:after{content:" ";bottom:1px;margin-left:-10px;border-bottom-width:0;border-top-color:#fff}.popover.right .arrow{top:50%;left:-11px;margin-top:-11px;border-left-width:0;border-right-color:#999;border-right-color:rgba(0,0,0,.25)}.popover.right .arrow:after{content:" ";left:1px;bottom:-10px;border-left-width:0;border-right-color:#fff}.popover.bottom .arrow{left:50%;margin-left:-11px;border-top-width:0;border-bottom-color:#999;border-bottom-color:rgba(0,0,0,.25);top:-11px}.popover.bottom .arrow:after{content:" ";top:1px;margin-left:-10px;border-top-width:0;border-bottom-color:#fff}.popover.left .arrow{top:50%;right:-11px;margin-top:-11px;border-right-width:0;border-left-color:#999;border-left-color:rgba(0,0,0,.25)}.popover.left .arrow:after{content:" ";right:1px;border-right-width:0;border-left-color:#fff;bottom:-10px}.carousel{position:relative}.carousel-inner{position:relative;overflow:hidden;width:100%}.carousel-inner>.item{display:none;position:relative;-webkit-transition:.6s ease-in-out left;transition:.6s ease-in-out left}.carousel-inner>.item>img,.carousel-inner>.item>a>img{display:block;max-width:100%;height:auto;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:0;left:0;bottom:0;width:15%;opacity:.5;filter:alpha(opacity=50);font-size:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-control.left{background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.5) 0),color-stop(rgba(0,0,0,.0001) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.5) 0,rgba(0,0,0,.0001) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1)}.carousel-control.right{left:auto;right:0;background-image:-webkit-linear-gradient(left,color-stop(rgba(0,0,0,.0001) 0),color-stop(rgba(0,0,0,.5) 100%));background-image:linear-gradient(to right,rgba(0,0,0,.0001) 0,rgba(0,0,0,.5) 100%);background-repeat:repeat-x;filter:progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1)}.carousel-control:hover,.carousel-control:focus{outline:0;color:#fff;text-decoration:none;opacity:.9;filter:alpha(opacity=90)}.carousel-control .icon-prev,.carousel-control .icon-next,.carousel-control .glyphicon-chevron-left,.carousel-control .glyphicon-chevron-right{position:absolute;top:50%;z-index:5;display:inline-block}.carousel-control .icon-prev,.carousel-control .glyphicon-chevron-left{left:50%}.carousel-control .icon-next,.carousel-control .glyphicon-chevron-right{right:50%}.carousel-control .icon-prev,.carousel-control .icon-next{width:20px;height:20px;margin-top:-10px;margin-left:-10px;font-family:serif}.carousel-control .icon-prev:before{content:'\2039'}.carousel-control .icon-next:before{content:'\203a'}.carousel-indicators{position:absolute;bottom:10px;left:50%;z-index:15;width:60%;margin-left:-30%;padding-left:0;list-style:none;text-align:center}.carousel-indicators li{display:inline-block;width:10px;height:10px;margin:1px;text-indent:-999px;border:1px solid #fff;border-radius:10px;cursor:pointer;background-color:#000 \9;background-color:rgba(0,0,0,0)}.carousel-indicators .active{margin:0;width:12px;height:12px;background-color:#fff}.carousel-caption{position:absolute;left:15%;right:15%;bottom:20px;z-index:10;padding-top:20px;padding-bottom:20px;color:#fff;text-align:center;text-shadow:0 1px 2px rgba(0,0,0,.6)}.carousel-caption .btn{text-shadow:none}@media screen and (min-width:768px){.carousel-control .glyphicons-chevron-left,.carousel-control .glyphicons-chevron-right,.carousel-control .icon-prev,.carousel-control .icon-next{width:30px;height:30px;margin-top:-15px;margin-left:-15px;font-size:30px}.carousel-caption{left:20%;right:20%;padding-bottom:30px}.carousel-indicators{bottom:20px}}.clearfix:before,.clearfix:after,.container:before,.container:after,.container-fluid:before,.container-fluid:after,.row:before,.row:after,.form-horizontal .form-group:before,.form-horizontal .form-group:after,.btn-toolbar:before,.btn-toolbar:after,.btn-group-vertical>.btn-group:before,.btn-group-vertical>.btn-group:after,.nav:before,.nav:after,.navbar:before,.navbar:after,.navbar-header:before,.navbar-header:after,.navbar-collapse:before,.navbar-collapse:after,.pager:before,.pager:after,.panel-body:before,.panel-body:after,.modal-footer:before,.modal-footer:after{content:" ";display:table}.clearfix:after,.container:after,.container-fluid:after,.row:after,.form-horizontal .form-group:after,.btn-toolbar:after,.btn-group-vertical>.btn-group:after,.nav:after,.navbar:after,.navbar-header:after,.navbar-collapse:after,.pager:after,.panel-body:after,.modal-footer:after{clear:both}.center-block{display:block;margin-left:auto;margin-right:auto}.pull-right{float:right!important}.pull-left{float:left!important}.hide{display:none!important}.show{display:block!important}.invisible{visibility:hidden}.text-hide{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}.hidden{display:none!important;visibility:hidden!important}.affix{position:fixed}@-ms-viewport{width:device-width}.visible-xs,tr.visible-xs,th.visible-xs,td.visible-xs{display:none!important}@media (max-width:767px){.visible-xs{display:block!important}table.visible-xs{display:table}tr.visible-xs{display:table-row!important}th.visible-xs,td.visible-xs{display:table-cell!important}}.visible-sm,tr.visible-sm,th.visible-sm,td.visible-sm{display:none!important}@media (min-width:768px) and (max-width:991px){.visible-sm{display:block!important}table.visible-sm{display:table}tr.visible-sm{display:table-row!important}th.visible-sm,td.visible-sm{display:table-cell!important}}.visible-md,tr.visible-md,th.visible-md,td.visible-md{display:none!important}@media (min-width:992px) and (max-width:1199px){.visible-md{display:block!important}table.visible-md{display:table}tr.visible-md{display:table-row!important}th.visible-md,td.visible-md{display:table-cell!important}}.visible-lg,tr.visible-lg,th.visible-lg,td.visible-lg{display:none!important}@media (min-width:1200px){.visible-lg{display:block!important}table.visible-lg{display:table}tr.visible-lg{display:table-row!important}th.visible-lg,td.visible-lg{display:table-cell!important}}@media (max-width:767px){.hidden-xs,tr.hidden-xs,th.hidden-xs,td.hidden-xs{display:none!important}}@media (min-width:768px) and (max-width:991px){.hidden-sm,tr.hidden-sm,th.hidden-sm,td.hidden-sm{display:none!important}}@media (min-width:992px) and (max-width:1199px){.hidden-md,tr.hidden-md,th.hidden-md,td.hidden-md{display:none!important}}@media (min-width:1200px){.hidden-lg,tr.hidden-lg,th.hidden-lg,td.hidden-lg{display:none!important}}.visible-print,tr.visible-print,th.visible-print,td.visible-print{display:none!important}@media print{.visible-print{display:block!important}table.visible-print{display:table}tr.visible-print{display:table-row!important}th.visible-print,td.visible-print{display:table-cell!important}}@media print{.hidden-print,tr.hidden-print,th.hidden-print,td.hidden-print{display:none!important}} \ No newline at end of file diff --git a/libraries/webInterface/js/build.js b/libraries/webInterface/js/build.js new file mode 100644 index 0000000..e973ae2 --- /dev/null +++ b/libraries/webInterface/js/build.js @@ -0,0 +1,13476 @@ + +/** + * Require the given path. + * + * @param {String} path + * @return {Object} exports + * @api public + */ + +function require(path, parent, orig) { + var resolved = require.resolve(path); + + // lookup failed + if (null == resolved) { + orig = orig || path; + parent = parent || 'root'; + var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); + err.path = orig; + err.parent = parent; + err.require = true; + throw err; + } + + var module = require.modules[resolved]; + + // perform real require() + // by invoking the module's + // registered function + if (!module._resolving && !module.exports) { + var mod = {}; + mod.exports = {}; + mod.client = mod.component = true; + module._resolving = true; + module.call(this, mod.exports, require.relative(resolved), mod); + delete module._resolving; + module.exports = mod.exports; + } + + return module.exports; +} + +/** + * Registered modules. + */ + +require.modules = {}; + +/** + * Registered aliases. + */ + +require.aliases = {}; + +/** + * Resolve `path`. + * + * Lookup: + * + * - PATH/index.js + * - PATH.js + * - PATH + * + * @param {String} path + * @return {String} path or null + * @api private + */ + +require.resolve = function(path) { + if (path.charAt(0) === '/') + path = path.slice(1); + + var paths = [ + path, + path + '.js', + path + '.json', + path + '/index.js', + path + '/index.json' + ]; + + for (var i = 0; i < paths.length; i++) { + var path = paths[i]; + if (require.modules.hasOwnProperty(path)) + return path; + if (require.aliases.hasOwnProperty(path)) + return require.aliases[path]; + } +}; + +/** + * Normalize `path` relative to the current path. + * + * @param {String} curr + * @param {String} path + * @return {String} + * @api private + */ + +require.normalize = function(curr, path) { + var segs = []; + + if ('.' != path.charAt(0)) + return path; + + curr = curr.split('/'); + path = path.split('/'); + + for (var i = 0; i < path.length; ++i) { + if ('..' == path[i]) { + curr.pop(); + } else if ('.' != path[i] && '' != path[i]) { + segs.push(path[i]); + } + } + + return curr.concat(segs).join('/'); +}; + +/** + * Register module at `path` with callback `definition`. + * + * @param {String} path + * @param {Function} definition + * @api private + */ + +require.register = function(path, definition) { + require.modules[path] = definition; +}; + +/** + * Alias a module definition. + * + * @param {String} from + * @param {String} to + * @api private + */ + +require.alias = function(from, to) { + if (!require.modules.hasOwnProperty(from)) { + throw new Error('Failed to alias "' + from + '", it does not exist'); + } + require.aliases[to] = from; +}; + +/** + * Return a require function relative to the `parent` path. + * + * @param {String} parent + * @return {Function} + * @api private + */ + +require.relative = function(parent) { + var p = require.normalize(parent, '..'); + + /** + * lastIndexOf helper. + */ + + function lastIndexOf(arr, obj) { + var i = arr.length; + while (i--) { + if (arr[i] === obj) + return i; + } + return - 1; + } + + /** + * The relative require() itself. + */ + + function localRequire(path) { + var resolved = localRequire.resolve(path); + return require(resolved, parent, path); + } + + /** + * Resolve relative to the parent. + */ + + localRequire.resolve = function(path) { + var c = path.charAt(0); + if ('/' == c) + return path.slice(1); + if ('.' == c) + return require.normalize(p, path); + + // resolve deps by returning + // the dep in the nearest "deps" + // directory + var segs = parent.split('/'); + var i = lastIndexOf(segs, 'deps') + 1; + if (!i) + i = 0; + path = segs.slice(0, i + 1).join('/') + '/deps/' + path; + return path; + }; + + /** + * Check if module is defined at `path`. + */ + + localRequire.exists = function(path) { + return require.modules.hasOwnProperty(localRequire.resolve(path)); + }; + + return localRequire; +}; +require.register("component-emitter/index.js", function(exports, require, module) { + + /** + * Expose `Emitter`. + */ + + module.exports = Emitter; + + /** + * Initialize a new `Emitter`. + * + * @api public + */ + + function Emitter(obj) { + if (obj) + return mixin(obj); + }; + + /** + * Mixin the emitter properties. + * + * @param {Object} obj + * @return {Object} + * @api private + */ + + function mixin(obj) { + for (var key in Emitter.prototype) { + obj[key] = Emitter.prototype[key]; + } + return obj; + } + + /** + * Listen on the given `event` with `fn`. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.on = + Emitter.prototype.addEventListener = function(event, fn) { + this._callbacks = this._callbacks || {}; + (this._callbacks[event] = this._callbacks[event] || []) + .push(fn); + return this; + }; + + /** + * Adds an `event` listener that will be invoked a single + * time then automatically removed. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.once = function(event, fn) { + var self = this; + this._callbacks = this._callbacks || {}; + + function on() { + self.off(event, on); + fn.apply(this, arguments); + } + + on.fn = fn; + this.on(event, on); + return this; + }; + + /** + * Remove the given callback for `event` or all + * registered callbacks. + * + * @param {String} event + * @param {Function} fn + * @return {Emitter} + * @api public + */ + + Emitter.prototype.off = + Emitter.prototype.removeListener = + Emitter.prototype.removeAllListeners = + Emitter.prototype.removeEventListener = function(event, fn) { + this._callbacks = this._callbacks || {}; + + // all + if (0 == arguments.length) { + this._callbacks = {}; + return this; + } + + // specific event + var callbacks = this._callbacks[event]; + if (!callbacks) + return this; + + // remove all handlers + if (1 == arguments.length) { + delete this._callbacks[event]; + return this; + } + + // remove specific handler + var cb; + for (var i = 0; i < callbacks.length; i++) { + cb = callbacks[i]; + if (cb === fn || cb.fn === fn) { + callbacks.splice(i, 1); + break; + } + } + return this; + }; + + /** + * Emit `event` with the given args. + * + * @param {String} event + * @param {Mixed} ... + * @return {Emitter} + */ + + Emitter.prototype.emit = function(event) { + this._callbacks = this._callbacks || {}; + var args = [].slice.call(arguments, 1) + , callbacks = this._callbacks[event]; + + if (callbacks) { + callbacks = callbacks.slice(0); + for (var i = 0, len = callbacks.length; i < len; ++i) { + callbacks[i].apply(this, args); + } + } + + return this; + }; + + /** + * Return array of callbacks for `event`. + * + * @param {String} event + * @return {Array} + * @api public + */ + + Emitter.prototype.listeners = function(event) { + this._callbacks = this._callbacks || {}; + return this._callbacks[event] || []; + }; + + /** + * Check if this emitter has `event` handlers. + * + * @param {String} event + * @return {Boolean} + * @api public + */ + + Emitter.prototype.hasListeners = function(event) { + return !! this.listeners(event).length; + }; + +}); +require.register("enyo-dropzone/index.js", function(exports, require, module) { + + + /** + * Exposing dropzone + */ + module.exports = require("./lib/dropzone.js"); + +}); +require.register("enyo-dropzone/lib/dropzone.js", function(exports, require, module) { + /* + # + # More info at [www.dropzonejs.com](http://www.dropzonejs.com) + # + # Copyright (c) 2012, Matias Meno + # + # 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. + # + */ + + + (function() { + var Dropzone, Em, camelize, contentLoaded, detectVerticalSquash, drawImageIOSFix, noop, without, + __hasProp = {}.hasOwnProperty, + __extends = function(child, parent) { + for (var key in parent) { + if (__hasProp.call(parent, key)) + child[key] = parent[key]; + } + function ctor() { + this.constructor = child; + } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + child.__super__ = parent.prototype; + return child; + }, + __slice = [].slice; + + Em = typeof Emitter !== "undefined" && Emitter !== null ? Emitter : require("emitter"); + + noop = function() {}; + + Dropzone = (function(_super) { + var extend; + + __extends(Dropzone, _super); + + /* + This is a list of all available events you can register on a dropzone object. + + You can register an event handler like this: + + dropzone.on("dragEnter", function() { }); + */ + + + Dropzone.prototype.events = ["drop", "dragstart", "dragend", "dragenter", "dragover", "dragleave", "addedfile", "removedfile", "thumbnail", "error", "errormultiple", "processing", "processingmultiple", "uploadprogress", "totaluploadprogress", "sending", "sendingmultiple", "success", "successmultiple", "canceled", "canceledmultiple", "complete", "completemultiple", "reset", "maxfilesexceeded", "maxfilesreached"]; + + Dropzone.prototype.defaultOptions = { + url: null, + method: "post", + withCredentials: false, + parallelUploads: 2, + uploadMultiple: false, + maxFilesize: 256, + paramName: "file", + createImageThumbnails: true, + maxThumbnailFilesize: 10, + thumbnailWidth: 100, + thumbnailHeight: 100, + maxFiles: null, + params: {}, + clickable: true, + ignoreHiddenFiles: true, + acceptedFiles: null, + acceptedMimeTypes: null, + autoProcessQueue: true, + autoQueue: true, + addRemoveLinks: false, + previewsContainer: null, + dictDefaultMessage: "Drop files here to upload", + dictFallbackMessage: "Your browser does not support drag'n'drop file uploads.", + dictFallbackText: "Please use the fallback form below to upload your files like in the olden days.", + dictFileTooBig: "File is too big ({{filesize}}MiB). Max filesize: {{maxFilesize}}MiB.", + dictInvalidFileType: "You can't upload files of this type.", + dictResponseError: "Server responded with {{statusCode}} code.", + dictCancelUpload: "Cancel upload", + dictCancelUploadConfirmation: "Are you sure you want to cancel this upload?", + dictRemoveFile: "Remove file", + dictRemoveFileConfirmation: null, + dictMaxFilesExceeded: "You can not upload any more files.", + accept: function(file, done) { + return done(); + }, + init: function() { + return noop; + }, + forceFallback: false, + fallback: function() { + var child, messageElement, span, _i, _len, _ref; + this.element.className = "" + this.element.className + " dz-browser-not-supported"; + _ref = this.element.getElementsByTagName("div"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + child = _ref[_i]; + if (/(^| )dz-message($| )/.test(child.className)) { + messageElement = child; + child.className = "dz-message"; + continue; + } + } + if (!messageElement) { + messageElement = Dropzone.createElement("
"); + this.element.appendChild(messageElement); + } + span = messageElement.getElementsByTagName("span")[0]; + if (span) { + span.textContent = this.options.dictFallbackMessage; + } + return this.element.appendChild(this.getFallbackForm()); + }, + resize: function(file) { + var info, srcRatio, trgRatio; + info = { + srcX: 0, + srcY: 0, + srcWidth: file.width, + srcHeight: file.height + }; + srcRatio = file.width / file.height; + trgRatio = this.options.thumbnailWidth / this.options.thumbnailHeight; + if (file.height < this.options.thumbnailHeight || file.width < this.options.thumbnailWidth) { + info.trgHeight = info.srcHeight; + info.trgWidth = info.srcWidth; + } else { + if (srcRatio > trgRatio) { + info.srcHeight = file.height; + info.srcWidth = info.srcHeight * trgRatio; + } else { + info.srcWidth = file.width; + info.srcHeight = info.srcWidth / trgRatio; + } + } + info.srcX = (file.width - info.srcWidth) / 2; + info.srcY = (file.height - info.srcHeight) / 2; + return info; + }, + /* + Those functions register themselves to the events on init and handle all + the user interface specific stuff. Overwriting them won't break the upload + but can break the way it's displayed. + You can overwrite them if you don't like the default behavior. If you just + want to add an additional event handler, register it on the dropzone object + and don't overwrite those options. + */ + + drop: function(e) { + return this.element.classList.remove("dz-drag-hover"); + }, + dragstart: noop, + dragend: function(e) { + return this.element.classList.remove("dz-drag-hover"); + }, + dragenter: function(e) { + return this.element.classList.add("dz-drag-hover"); + }, + dragover: function(e) { + return this.element.classList.add("dz-drag-hover"); + }, + dragleave: function(e) { + return this.element.classList.remove("dz-drag-hover"); + }, + paste: noop, + reset: function() { + return this.element.classList.remove("dz-started"); + }, + addedfile: function(file) { + var node, removeFileEvent, removeLink, _i, _j, _k, _len, _len1, _len2, _ref, _ref1, _ref2, _results, + _this = this; + if (this.element === this.previewsContainer) { + this.element.classList.add("dz-started"); + } + file.previewElement = Dropzone.createElement(this.options.previewTemplate.trim()); + file.previewTemplate = file.previewElement; + this.previewsContainer.appendChild(file.previewElement); + _ref = file.previewElement.querySelectorAll("[data-dz-name]"); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + node.textContent = file.name; + } + _ref1 = file.previewElement.querySelectorAll("[data-dz-size]"); + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + node = _ref1[_j]; + node.innerHTML = this.filesize(file.size); + } + if (this.options.addRemoveLinks) { + file._removeLink = Dropzone.createElement("" + this.options.dictRemoveFile + ""); + file.previewElement.appendChild(file._removeLink); + } + removeFileEvent = function(e) { + e.preventDefault(); + e.stopPropagation(); + if (file.status === Dropzone.UPLOADING) { + return Dropzone.confirm(_this.options.dictCancelUploadConfirmation, function() { + return _this.removeFile(file); + }); + } else { + if (_this.options.dictRemoveFileConfirmation) { + return Dropzone.confirm(_this.options.dictRemoveFileConfirmation, function() { + return _this.removeFile(file); + }); + } else { + return _this.removeFile(file); + } + } + }; + _ref2 = file.previewElement.querySelectorAll("[data-dz-remove]"); + _results = []; + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + removeLink = _ref2[_k]; + _results.push(removeLink.addEventListener("click", removeFileEvent)); + } + return _results; + }, + removedfile: function(file) { + var _ref; + if ((_ref = file.previewElement) != null) { + _ref.parentNode.removeChild(file.previewElement); + } + return this._updateMaxFilesReachedClass(); + }, + thumbnail: function(file, dataUrl) { + var thumbnailElement, _i, _len, _ref, _results; + file.previewElement.classList.remove("dz-file-preview"); + file.previewElement.classList.add("dz-image-preview"); + _ref = file.previewElement.querySelectorAll("[data-dz-thumbnail]"); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + thumbnailElement = _ref[_i]; + thumbnailElement.alt = file.name; + _results.push(thumbnailElement.src = dataUrl); + } + return _results; + }, + error: function(file, message) { + var node, _i, _len, _ref, _results; + file.previewElement.classList.add("dz-error"); + if (typeof message !== "String" && message.error) { + message = message.error; + } + _ref = file.previewElement.querySelectorAll("[data-dz-errormessage]"); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + _results.push(node.textContent = message); + } + return _results; + }, + errormultiple: noop, + processing: function(file) { + file.previewElement.classList.add("dz-processing"); + if (file._removeLink) { + return file._removeLink.textContent = this.options.dictCancelUpload; + } + }, + processingmultiple: noop, + uploadprogress: function(file, progress, bytesSent) { + var node, _i, _len, _ref, _results; + _ref = file.previewElement.querySelectorAll("[data-dz-uploadprogress]"); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + node = _ref[_i]; + _results.push(node.style.width = "" + progress + "%"); + } + return _results; + }, + totaluploadprogress: noop, + sending: noop, + sendingmultiple: noop, + success: function(file) { + return file.previewElement.classList.add("dz-success"); + }, + successmultiple: noop, + canceled: function(file) { + return this.emit("error", file, "Upload canceled."); + }, + canceledmultiple: noop, + complete: function(file) { + if (file._removeLink) { + return file._removeLink.textContent = this.options.dictRemoveFile; + } + }, + completemultiple: noop, + maxfilesexceeded: noop, + maxfilesreached: noop, + previewTemplate: "
\n
\n
\n
\n \n
\n
\n
\n
\n
\n
" + }; + + extend = function() { + var key, object, objects, target, val, _i, _len; + target = arguments[0], objects = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + for (_i = 0, _len = objects.length; _i < _len; _i++) { + object = objects[_i]; + for (key in object) { + val = object[key]; + target[key] = val; + } + } + return target; + }; + + function Dropzone(element, options) { + var elementOptions, fallback, _ref; + this.element = element; + this.version = Dropzone.version; + this.defaultOptions.previewTemplate = this.defaultOptions.previewTemplate.replace(/\n*/g, ""); + this.clickableElements = []; + this.listeners = []; + this.files = []; + if (typeof this.element === "string") { + this.element = document.querySelector(this.element); + } + if (!(this.element && (this.element.nodeType != null))) { + throw new Error("Invalid dropzone element."); + } + if (this.element.dropzone) { + throw new Error("Dropzone already attached."); + } + Dropzone.instances.push(this); + this.element.dropzone = this; + elementOptions = (_ref = Dropzone.optionsForElement(this.element)) != null ? _ref : {}; + this.options = extend({}, this.defaultOptions, elementOptions, options != null ? options : {}); + if (this.options.forceFallback || !Dropzone.isBrowserSupported()) { + return this.options.fallback.call(this); + } + if (this.options.url == null) { + this.options.url = this.element.getAttribute("action"); + } + if (!this.options.url) { + throw new Error("No URL provided."); + } + if (this.options.acceptedFiles && this.options.acceptedMimeTypes) { + throw new Error("You can't provide both 'acceptedFiles' and 'acceptedMimeTypes'. 'acceptedMimeTypes' is deprecated."); + } + if (this.options.acceptedMimeTypes) { + this.options.acceptedFiles = this.options.acceptedMimeTypes; + delete this.options.acceptedMimeTypes; + } + this.options.method = this.options.method.toUpperCase(); + if ((fallback = this.getExistingFallback()) && fallback.parentNode) { + fallback.parentNode.removeChild(fallback); + } + if (this.options.previewsContainer) { + this.previewsContainer = Dropzone.getElement(this.options.previewsContainer, "previewsContainer"); + } else { + this.previewsContainer = this.element; + } + if (this.options.clickable) { + if (this.options.clickable === true) { + this.clickableElements = [this.element]; + } else { + this.clickableElements = Dropzone.getElements(this.options.clickable, "clickable"); + } + } + this.init(); + } + + Dropzone.prototype.getAcceptedFiles = function() { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.accepted) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.getRejectedFiles = function() { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (!file.accepted) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.getFilesWithStatus = function(status) { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.status === status) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.getQueuedFiles = function() { + return this.getFilesWithStatus(Dropzone.QUEUED); + }; + + Dropzone.prototype.getUploadingFiles = function() { + return this.getFilesWithStatus(Dropzone.UPLOADING); + }; + + Dropzone.prototype.getActiveFiles = function() { + var file, _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.status === Dropzone.UPLOADING || file.status === Dropzone.QUEUED) { + _results.push(file); + } + } + return _results; + }; + + Dropzone.prototype.init = function() { + var eventName, noPropagation, setupHiddenFileInput, _i, _len, _ref, _ref1, + _this = this; + if (this.element.tagName === "form") { + this.element.setAttribute("enctype", "multipart/form-data"); + } + if (this.element.classList.contains("dropzone") && !this.element.querySelector(".dz-message")) { + this.element.appendChild(Dropzone.createElement("
" + this.options.dictDefaultMessage + "
")); + } + if (this.clickableElements.length) { + setupHiddenFileInput = function() { + if (_this.hiddenFileInput) { + document.body.removeChild(_this.hiddenFileInput); + } + _this.hiddenFileInput = document.createElement("input"); + _this.hiddenFileInput.setAttribute("type", "file"); + if ((_this.options.maxFiles == null) || _this.options.maxFiles > 1) { + _this.hiddenFileInput.setAttribute("multiple", "multiple"); + } + _this.hiddenFileInput.className = "dz-hidden-input"; + if (_this.options.acceptedFiles != null) { + _this.hiddenFileInput.setAttribute("accept", _this.options.acceptedFiles); + } + _this.hiddenFileInput.style.visibility = "hidden"; + _this.hiddenFileInput.style.position = "absolute"; + _this.hiddenFileInput.style.top = "0"; + _this.hiddenFileInput.style.left = "0"; + _this.hiddenFileInput.style.height = "0"; + _this.hiddenFileInput.style.width = "0"; + document.body.appendChild(_this.hiddenFileInput); + return _this.hiddenFileInput.addEventListener("change", function() { + var file, files, _i, _len; + files = _this.hiddenFileInput.files; + if (files.length) { + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + _this.addFile(file); + } + } + return setupHiddenFileInput(); + }); + }; + setupHiddenFileInput(); + } + this.URL = (_ref = window.URL) != null ? _ref : window.webkitURL; + _ref1 = this.events; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + eventName = _ref1[_i]; + this.on(eventName, this.options[eventName]); + } + this.on("uploadprogress", function() { + return _this.updateTotalUploadProgress(); + }); + this.on("removedfile", function() { + return _this.updateTotalUploadProgress(); + }); + this.on("canceled", function(file) { + return _this.emit("complete", file); + }); + this.on("complete", function(file) { + if (_this.getUploadingFiles().length === 0 && _this.getQueuedFiles().length === 0) { + return setTimeout((function() { + return _this.emit("queuecomplete"); + }), 0); + } + }); + noPropagation = function(e) { + e.stopPropagation(); + if (e.preventDefault) { + return e.preventDefault(); + } else { + return e.returnValue = false; + } + }; + this.listeners = [ + { + element: this.element, + events: { + "dragstart": function(e) { + return _this.emit("dragstart", e); + }, + "dragenter": function(e) { + noPropagation(e); + return _this.emit("dragenter", e); + }, + "dragover": function(e) { + var efct; + try { + efct = e.dataTransfer.effectAllowed; + } catch (_error) {} + e.dataTransfer.dropEffect = 'move' === efct || 'linkMove' === efct ? 'move' : 'copy'; + noPropagation(e); + return _this.emit("dragover", e); + }, + "dragleave": function(e) { + return _this.emit("dragleave", e); + }, + "drop": function(e) { + noPropagation(e); + return _this.drop(e); + }, + "dragend": function(e) { + return _this.emit("dragend", e); + } + } + } + ]; + this.clickableElements.forEach(function(clickableElement) { + return _this.listeners.push({ + element: clickableElement, + events: { + "click": function(evt) { + if ((clickableElement !== _this.element) || (evt.target === _this.element || Dropzone.elementInside(evt.target, _this.element.querySelector(".dz-message")))) { + return _this.hiddenFileInput.click(); + } + } + } + }); + }); + this.enable(); + return this.options.init.call(this); + }; + + Dropzone.prototype.destroy = function() { + var _ref; + this.disable(); + this.removeAllFiles(true); + if ((_ref = this.hiddenFileInput) != null ? _ref.parentNode : void 0) { + this.hiddenFileInput.parentNode.removeChild(this.hiddenFileInput); + this.hiddenFileInput = null; + } + delete this.element.dropzone; + return Dropzone.instances.splice(Dropzone.instances.indexOf(this), 1); + }; + + Dropzone.prototype.updateTotalUploadProgress = function() { + var activeFiles, file, totalBytes, totalBytesSent, totalUploadProgress, _i, _len, _ref; + totalBytesSent = 0; + totalBytes = 0; + activeFiles = this.getActiveFiles(); + if (activeFiles.length) { + _ref = this.getActiveFiles(); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + totalBytesSent += file.upload.bytesSent; + totalBytes += file.upload.total; + } + totalUploadProgress = 100 * totalBytesSent / totalBytes; + } else { + totalUploadProgress = 100; + } + return this.emit("totaluploadprogress", totalUploadProgress, totalBytes, totalBytesSent); + }; + + Dropzone.prototype.getFallbackForm = function() { + var existingFallback, fields, fieldsString, form; + if (existingFallback = this.getExistingFallback()) { + return existingFallback; + } + fieldsString = "
"; + if (this.options.dictFallbackText) { + fieldsString += "

" + this.options.dictFallbackText + "

"; + } + fieldsString += "
"; + fields = Dropzone.createElement(fieldsString); + if (this.element.tagName !== "FORM") { + form = Dropzone.createElement("
"); + form.appendChild(fields); + } else { + this.element.setAttribute("enctype", "multipart/form-data"); + this.element.setAttribute("method", this.options.method); + } + return form != null ? form : fields; + }; + + Dropzone.prototype.getExistingFallback = function() { + var fallback, getFallback, tagName, _i, _len, _ref; + getFallback = function(elements) { + var el, _i, _len; + for (_i = 0, _len = elements.length; _i < _len; _i++) { + el = elements[_i]; + if (/(^| )fallback($| )/.test(el.className)) { + return el; + } + } + }; + _ref = ["div", "form"]; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + tagName = _ref[_i]; + if (fallback = getFallback(this.element.getElementsByTagName(tagName))) { + return fallback; + } + } + }; + + Dropzone.prototype.setupEventListeners = function() { + var elementListeners, event, listener, _i, _len, _ref, _results; + _ref = this.listeners; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + elementListeners = _ref[_i]; + _results.push((function() { + var _ref1, _results1; + _ref1 = elementListeners.events; + _results1 = []; + for (event in _ref1) { + listener = _ref1[event]; + _results1.push(elementListeners.element.addEventListener(event, listener, false)); + } + return _results1; + })()); + } + return _results; + }; + + Dropzone.prototype.removeEventListeners = function() { + var elementListeners, event, listener, _i, _len, _ref, _results; + _ref = this.listeners; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + elementListeners = _ref[_i]; + _results.push((function() { + var _ref1, _results1; + _ref1 = elementListeners.events; + _results1 = []; + for (event in _ref1) { + listener = _ref1[event]; + _results1.push(elementListeners.element.removeEventListener(event, listener, false)); + } + return _results1; + })()); + } + return _results; + }; + + Dropzone.prototype.disable = function() { + var file, _i, _len, _ref, _results; + this.clickableElements.forEach(function(element) { + return element.classList.remove("dz-clickable"); + }); + this.removeEventListeners(); + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + _results.push(this.cancelUpload(file)); + } + return _results; + }; + + Dropzone.prototype.enable = function() { + this.clickableElements.forEach(function(element) { + return element.classList.add("dz-clickable"); + }); + return this.setupEventListeners(); + }; + + Dropzone.prototype.filesize = function(size) { + var string; + if (size >= 1024 * 1024 * 1024 * 1024 / 10) { + size = size / (1024 * 1024 * 1024 * 1024 / 10); + string = "TiB"; + } else if (size >= 1024 * 1024 * 1024 / 10) { + size = size / (1024 * 1024 * 1024 / 10); + string = "GiB"; + } else if (size >= 1024 * 1024 / 10) { + size = size / (1024 * 1024 / 10); + string = "MiB"; + } else if (size >= 1024 / 10) { + size = size / (1024 / 10); + string = "KiB"; + } else { + size = size * 10; + string = "b"; + } + return "" + (Math.round(size) / 10) + " " + string; + }; + + Dropzone.prototype._updateMaxFilesReachedClass = function() { + if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) { + if (this.getAcceptedFiles().length === this.options.maxFiles) { + this.emit('maxfilesreached', this.files); + } + return this.element.classList.add("dz-max-files-reached"); + } else { + return this.element.classList.remove("dz-max-files-reached"); + } + }; + + Dropzone.prototype.drop = function(e) { + var files, items; + if (!e.dataTransfer) { + return; + } + this.emit("drop", e); + files = e.dataTransfer.files; + if (files.length) { + items = e.dataTransfer.items; + if (items && items.length && (items[0].webkitGetAsEntry != null)) { + this._addFilesFromItems(items); + } else { + this.handleFiles(files); + } + } + }; + + Dropzone.prototype.paste = function(e) { + var items, _ref; + if ((e != null ? (_ref = e.clipboardData) != null ? _ref.items : void 0 : void 0) == null) { + return; + } + this.emit("paste", e); + items = e.clipboardData.items; + if (items.length) { + return this._addFilesFromItems(items); + } + }; + + Dropzone.prototype.handleFiles = function(files) { + var file, _i, _len, _results; + _results = []; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + _results.push(this.addFile(file)); + } + return _results; + }; + + Dropzone.prototype._addFilesFromItems = function(items) { + var entry, item, _i, _len, _results; + _results = []; + for (_i = 0, _len = items.length; _i < _len; _i++) { + item = items[_i]; + if ((item.webkitGetAsEntry != null) && (entry = item.webkitGetAsEntry())) { + if (entry.isFile) { + _results.push(this.addFile(item.getAsFile())); + } else if (entry.isDirectory) { + _results.push(this._addFilesFromDirectory(entry, entry.name)); + } else { + _results.push(void 0); + } + } else if (item.getAsFile != null) { + if ((item.kind == null) || item.kind === "file") { + _results.push(this.addFile(item.getAsFile())); + } else { + _results.push(void 0); + } + } else { + _results.push(void 0); + } + } + return _results; + }; + + Dropzone.prototype._addFilesFromDirectory = function(directory, path) { + var dirReader, entriesReader, + _this = this; + dirReader = directory.createReader(); + entriesReader = function(entries) { + var entry, _i, _len; + for (_i = 0, _len = entries.length; _i < _len; _i++) { + entry = entries[_i]; + if (entry.isFile) { + entry.file(function(file) { + if (_this.options.ignoreHiddenFiles && file.name.substring(0, 1) === '.') { + return; + } + file.fullPath = "" + path + "/" + file.name; + return _this.addFile(file); + }); + } else if (entry.isDirectory) { + _this._addFilesFromDirectory(entry, "" + path + "/" + entry.name); + } + } + }; + return dirReader.readEntries(entriesReader, function(error) { + return typeof console !== "undefined" && console !== null ? typeof console.log === "function" ? console.log(error) : void 0 : void 0; + }); + }; + + Dropzone.prototype.accept = function(file, done) { + if (file.size > this.options.maxFilesize * 1024 * 1024) { + return done(this.options.dictFileTooBig.replace("{{filesize}}", Math.round(file.size / 1024 / 10.24) / 100).replace("{{maxFilesize}}", this.options.maxFilesize)); + } else if (!Dropzone.isValidFile(file, this.options.acceptedFiles)) { + return done(this.options.dictInvalidFileType); + } else if ((this.options.maxFiles != null) && this.getAcceptedFiles().length >= this.options.maxFiles) { + done(this.options.dictMaxFilesExceeded.replace("{{maxFiles}}", this.options.maxFiles)); + return this.emit("maxfilesexceeded", file); + } else { + return this.options.accept.call(this, file, done); + } + }; + + Dropzone.prototype.addFile = function(file) { + var _this = this; + file.upload = { + progress: 0, + total: file.size, + bytesSent: 0 + }; + this.files.push(file); + file.status = Dropzone.ADDED; + this.emit("addedfile", file); + this._enqueueThumbnail(file); + return this.accept(file, function(error) { + if (error) { + file.accepted = false; + _this._errorProcessing([file], error); + } else { + file.accepted = true; + if (_this.options.autoQueue) { + _this.enqueueFile(file); + } + } + return _this._updateMaxFilesReachedClass(); + }); + }; + + Dropzone.prototype.enqueueFiles = function(files) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + this.enqueueFile(file); + } + return null; + }; + + Dropzone.prototype.enqueueFile = function(file) { + var _this = this; + if (file.status === Dropzone.ADDED && file.accepted === true) { + file.status = Dropzone.QUEUED; + if (this.options.autoProcessQueue) { + return setTimeout((function() { + return _this.processQueue(); + }), 0); + } + } else { + throw new Error("This file can't be queued because it has already been processed or was rejected."); + } + }; + + Dropzone.prototype._thumbnailQueue = []; + + Dropzone.prototype._processingThumbnail = false; + + Dropzone.prototype._enqueueThumbnail = function(file) { + var _this = this; + if (this.options.createImageThumbnails && file.type.match(/image.*/) && file.size <= this.options.maxThumbnailFilesize * 1024 * 1024) { + this._thumbnailQueue.push(file); + return setTimeout((function() { + return _this._processThumbnailQueue(); + }), 0); + } + }; + + Dropzone.prototype._processThumbnailQueue = function() { + var _this = this; + if (this._processingThumbnail || this._thumbnailQueue.length === 0) { + return; + } + this._processingThumbnail = true; + return this.createThumbnail(this._thumbnailQueue.shift(), function() { + _this._processingThumbnail = false; + return _this._processThumbnailQueue(); + }); + }; + + Dropzone.prototype.removeFile = function(file) { + if (file.status === Dropzone.UPLOADING) { + this.cancelUpload(file); + } + this.files = without(this.files, file); + this.emit("removedfile", file); + if (this.files.length === 0) { + return this.emit("reset"); + } + }; + + Dropzone.prototype.removeAllFiles = function(cancelIfNecessary) { + var file, _i, _len, _ref; + if (cancelIfNecessary == null) { + cancelIfNecessary = false; + } + _ref = this.files.slice(); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.status !== Dropzone.UPLOADING || cancelIfNecessary) { + this.removeFile(file); + } + } + return null; + }; + + Dropzone.prototype.createThumbnail = function(file, callback) { + var fileReader, + _this = this; + fileReader = new FileReader; + fileReader.onload = function() { + var img; + img = document.createElement("img"); + img.onload = function() { + var canvas, ctx, resizeInfo, thumbnail, _ref, _ref1, _ref2, _ref3; + file.width = img.width; + file.height = img.height; + resizeInfo = _this.options.resize.call(_this, file); + if (resizeInfo.trgWidth == null) { + resizeInfo.trgWidth = _this.options.thumbnailWidth; + } + if (resizeInfo.trgHeight == null) { + resizeInfo.trgHeight = _this.options.thumbnailHeight; + } + canvas = document.createElement("canvas"); + ctx = canvas.getContext("2d"); + canvas.width = resizeInfo.trgWidth; + canvas.height = resizeInfo.trgHeight; + drawImageIOSFix(ctx, img, (_ref = resizeInfo.srcX) != null ? _ref : 0, (_ref1 = resizeInfo.srcY) != null ? _ref1 : 0, resizeInfo.srcWidth, resizeInfo.srcHeight, (_ref2 = resizeInfo.trgX) != null ? _ref2 : 0, (_ref3 = resizeInfo.trgY) != null ? _ref3 : 0, resizeInfo.trgWidth, resizeInfo.trgHeight); + thumbnail = canvas.toDataURL("image/png"); + _this.emit("thumbnail", file, thumbnail); + if (callback != null) { + return callback(); + } + }; + return img.src = fileReader.result; + }; + return fileReader.readAsDataURL(file); + }; + + Dropzone.prototype.processQueue = function() { + var i, parallelUploads, processingLength, queuedFiles; + parallelUploads = this.options.parallelUploads; + processingLength = this.getUploadingFiles().length; + i = processingLength; + if (processingLength >= parallelUploads) { + return; + } + queuedFiles = this.getQueuedFiles(); + if (!(queuedFiles.length > 0)) { + return; + } + if (this.options.uploadMultiple) { + return this.processFiles(queuedFiles.slice(0, parallelUploads - processingLength)); + } else { + while (i < parallelUploads) { + if (!queuedFiles.length) { + return; + } + this.processFile(queuedFiles.shift()); + i++; + } + } + }; + + Dropzone.prototype.processFile = function(file) { + return this.processFiles([file]); + }; + + Dropzone.prototype.processFiles = function(files) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + file.processing = true; + file.status = Dropzone.UPLOADING; + this.emit("processing", file); + } + if (this.options.uploadMultiple) { + this.emit("processingmultiple", files); + } + return this.uploadFiles(files); + }; + + Dropzone.prototype._getFilesWithXhr = function(xhr) { + var file, files; + return files = (function() { + var _i, _len, _ref, _results; + _ref = this.files; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + file = _ref[_i]; + if (file.xhr === xhr) { + _results.push(file); + } + } + return _results; + }).call(this); + }; + + Dropzone.prototype.cancelUpload = function(file) { + var groupedFile, groupedFiles, _i, _j, _len, _len1, _ref; + if (file.status === Dropzone.UPLOADING) { + groupedFiles = this._getFilesWithXhr(file.xhr); + for (_i = 0, _len = groupedFiles.length; _i < _len; _i++) { + groupedFile = groupedFiles[_i]; + groupedFile.status = Dropzone.CANCELED; + } + file.xhr.abort(); + for (_j = 0, _len1 = groupedFiles.length; _j < _len1; _j++) { + groupedFile = groupedFiles[_j]; + this.emit("canceled", groupedFile); + } + if (this.options.uploadMultiple) { + this.emit("canceledmultiple", groupedFiles); + } + } else if ((_ref = file.status) === Dropzone.ADDED || _ref === Dropzone.QUEUED) { + file.status = Dropzone.CANCELED; + this.emit("canceled", file); + if (this.options.uploadMultiple) { + this.emit("canceledmultiple", [file]); + } + } + if (this.options.autoProcessQueue) { + return this.processQueue(); + } + }; + + Dropzone.prototype.uploadFile = function(file) { + return this.uploadFiles([file]); + }; + + Dropzone.prototype.uploadFiles = function(files) { + var file, formData, handleError, headerName, headerValue, headers, input, inputName, inputType, key, option, progressObj, response, updateProgress, value, xhr, _i, _j, _k, _l, _len, _len1, _len2, _len3, _len4, _m, _ref, _ref1, _ref2, _ref3, _ref4, + _this = this; + xhr = new XMLHttpRequest(); + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + file.xhr = xhr; + } + xhr.open(this.options.method, this.options.url, true); + xhr.withCredentials = !!this.options.withCredentials; + response = null; + handleError = function() { + var _j, _len1, _results; + _results = []; + for (_j = 0, _len1 = files.length; _j < _len1; _j++) { + file = files[_j]; + _results.push(_this._errorProcessing(files, response || _this.options.dictResponseError.replace("{{statusCode}}", xhr.status), xhr)); + } + return _results; + }; + updateProgress = function(e) { + var allFilesFinished, progress, _j, _k, _l, _len1, _len2, _len3, _results; + if (e != null) { + progress = 100 * e.loaded / e.total; + for (_j = 0, _len1 = files.length; _j < _len1; _j++) { + file = files[_j]; + file.upload = { + progress: progress, + total: e.total, + bytesSent: e.loaded + }; + } + } else { + allFilesFinished = true; + progress = 100; + for (_k = 0, _len2 = files.length; _k < _len2; _k++) { + file = files[_k]; + if (!(file.upload.progress === 100 && file.upload.bytesSent === file.upload.total)) { + allFilesFinished = false; + } + file.upload.progress = progress; + file.upload.bytesSent = file.upload.total; + } + if (allFilesFinished) { + return; + } + } + _results = []; + for (_l = 0, _len3 = files.length; _l < _len3; _l++) { + file = files[_l]; + _results.push(_this.emit("uploadprogress", file, progress, file.upload.bytesSent)); + } + return _results; + }; + xhr.onload = function(e) { + var _ref; + if (files[0].status === Dropzone.CANCELED) { + return; + } + if (xhr.readyState !== 4) { + return; + } + response = xhr.responseText; + if (xhr.getResponseHeader("content-type") && ~xhr.getResponseHeader("content-type").indexOf("application/json")) { + try { + response = JSON.parse(response); + } catch (_error) { + e = _error; + response = "Invalid JSON response from server."; + } + } + updateProgress(); + if (!((200 <= (_ref = xhr.status) && _ref < 300))) { + return handleError(); + } else { + return _this._finished(files, response, e); + } + }; + xhr.onerror = function() { + if (files[0].status === Dropzone.CANCELED) { + return; + } + return handleError(); + }; + progressObj = (_ref = xhr.upload) != null ? _ref : xhr; + progressObj.onprogress = updateProgress; + headers = { + "Accept": "application/json", + "Cache-Control": "no-cache", + "X-Requested-With": "XMLHttpRequest" + }; + if (this.options.headers) { + extend(headers, this.options.headers); + } + for (headerName in headers) { + headerValue = headers[headerName]; + xhr.setRequestHeader(headerName, headerValue); + } + formData = new FormData(); + if (this.options.params) { + _ref1 = this.options.params; + for (key in _ref1) { + value = _ref1[key]; + formData.append(key, value); + } + } + for (_j = 0, _len1 = files.length; _j < _len1; _j++) { + file = files[_j]; + this.emit("sending", file, xhr, formData); + } + if (this.options.uploadMultiple) { + this.emit("sendingmultiple", files, xhr, formData); + } + if (this.element.tagName === "FORM") { + _ref2 = this.element.querySelectorAll("input, textarea, select, button"); + for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) { + input = _ref2[_k]; + inputName = input.getAttribute("name"); + inputType = input.getAttribute("type"); + if (input.tagName === "SELECT" && input.hasAttribute("multiple")) { + _ref3 = input.options; + for (_l = 0, _len3 = _ref3.length; _l < _len3; _l++) { + option = _ref3[_l]; + if (option.selected) { + formData.append(inputName, option.value); + } + } + } else if (!inputType || ((_ref4 = inputType.toLowerCase()) !== "checkbox" && _ref4 !== "radio") || input.checked) { + formData.append(inputName, input.value); + } + } + } + for (_m = 0, _len4 = files.length; _m < _len4; _m++) { + file = files[_m]; + formData.append("" + this.options.paramName + (this.options.uploadMultiple ? "[]" : ""), file, file.name); + } + return xhr.send(formData); + }; + + Dropzone.prototype._finished = function(files, responseText, e) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + file.status = Dropzone.SUCCESS; + this.emit("success", file, responseText, e); + this.emit("complete", file); + } + if (this.options.uploadMultiple) { + this.emit("successmultiple", files, responseText, e); + this.emit("completemultiple", files); + } + if (this.options.autoProcessQueue) { + return this.processQueue(); + } + }; + + Dropzone.prototype._errorProcessing = function(files, message, xhr) { + var file, _i, _len; + for (_i = 0, _len = files.length; _i < _len; _i++) { + file = files[_i]; + file.status = Dropzone.ERROR; + this.emit("error", file, message, xhr); + this.emit("complete", file); + } + if (this.options.uploadMultiple) { + this.emit("errormultiple", files, message, xhr); + this.emit("completemultiple", files); + } + if (this.options.autoProcessQueue) { + return this.processQueue(); + } + }; + + return Dropzone; + + })(Em); + + Dropzone.version = "3.8.6"; + + Dropzone.options = {}; + + Dropzone.optionsForElement = function(element) { + if (element.getAttribute("id")) { + return Dropzone.options[camelize(element.getAttribute("id"))]; + } else { + return void 0; + } + }; + + Dropzone.instances = []; + + Dropzone.forElement = function(element) { + if (typeof element === "string") { + element = document.querySelector(element); + } + if ((element != null ? element.dropzone : void 0) == null) { + throw new Error("No Dropzone found for given element. This is probably because you're trying to access it before Dropzone had the time to initialize. Use the `init` option to setup any additional observers on your Dropzone."); + } + return element.dropzone; + }; + + Dropzone.autoDiscover = true; + + Dropzone.discover = function() { + var checkElements, dropzone, dropzones, _i, _len, _results; + if (document.querySelectorAll) { + dropzones = document.querySelectorAll(".dropzone"); + } else { + dropzones = []; + checkElements = function(elements) { + var el, _i, _len, _results; + _results = []; + for (_i = 0, _len = elements.length; _i < _len; _i++) { + el = elements[_i]; + if (/(^| )dropzone($| )/.test(el.className)) { + _results.push(dropzones.push(el)); + } else { + _results.push(void 0); + } + } + return _results; + }; + checkElements(document.getElementsByTagName("div")); + checkElements(document.getElementsByTagName("form")); + } + _results = []; + for (_i = 0, _len = dropzones.length; _i < _len; _i++) { + dropzone = dropzones[_i]; + if (Dropzone.optionsForElement(dropzone) !== false) { + _results.push(new Dropzone(dropzone)); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Dropzone.blacklistedBrowsers = [/opera.*Macintosh.*version\/12/i]; + + Dropzone.isBrowserSupported = function() { + var capableBrowser, regex, _i, _len, _ref; + capableBrowser = true; + if (window.File && window.FileReader && window.FileList && window.Blob && window.FormData && document.querySelector) { + if (!("classList" in document.createElement("a"))) { + capableBrowser = false; + } else { + _ref = Dropzone.blacklistedBrowsers; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + regex = _ref[_i]; + if (regex.test(navigator.userAgent)) { + capableBrowser = false; + continue; + } + } + } + } else { + capableBrowser = false; + } + return capableBrowser; + }; + + without = function(list, rejectedItem) { + var item, _i, _len, _results; + _results = []; + for (_i = 0, _len = list.length; _i < _len; _i++) { + item = list[_i]; + if (item !== rejectedItem) { + _results.push(item); + } + } + return _results; + }; + + camelize = function(str) { + return str.replace(/[\-_](\w)/g, function(match) { + return match.charAt(1).toUpperCase(); + }); + }; + + Dropzone.createElement = function(string) { + var div; + div = document.createElement("div"); + div.innerHTML = string; + return div.childNodes[0]; + }; + + Dropzone.elementInside = function(element, container) { + if (element === container) { + return true; + } + while (element = element.parentNode) { + if (element === container) { + return true; + } + } + return false; + }; + + Dropzone.getElement = function(el, name) { + var element; + if (typeof el === "string") { + element = document.querySelector(el); + } else if (el.nodeType != null) { + element = el; + } + if (element == null) { + throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector or a plain HTML element."); + } + return element; + }; + + Dropzone.getElements = function(els, name) { + var e, el, elements, _i, _j, _len, _len1, _ref; + if (els instanceof Array) { + elements = []; + try { + for (_i = 0, _len = els.length; _i < _len; _i++) { + el = els[_i]; + elements.push(this.getElement(el, name)); + } + } catch (_error) { + e = _error; + elements = null; + } + } else if (typeof els === "string") { + elements = []; + _ref = document.querySelectorAll(els); + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + el = _ref[_j]; + elements.push(el); + } + } else if (els.nodeType != null) { + elements = [els]; + } + if (!((elements != null) && elements.length)) { + throw new Error("Invalid `" + name + "` option provided. Please provide a CSS selector, a plain HTML element or a list of those."); + } + return elements; + }; + + Dropzone.confirm = function(question, accepted, rejected) { + if (window.confirm(question)) { + return accepted(); + } else if (rejected != null) { + return rejected(); + } + }; + + Dropzone.isValidFile = function(file, acceptedFiles) { + var baseMimeType, mimeType, validType, _i, _len; + if (!acceptedFiles) { + return true; + } + acceptedFiles = acceptedFiles.split(","); + mimeType = file.type; + baseMimeType = mimeType.replace(/\/.*$/, ""); + for (_i = 0, _len = acceptedFiles.length; _i < _len; _i++) { + validType = acceptedFiles[_i]; + validType = validType.trim(); + if (validType.charAt(0) === ".") { + if (file.name.toLowerCase().indexOf(validType.toLowerCase(), file.name.length - validType.length) !== - 1) { + return true; + } + } else if (/\/\*$/.test(validType)) { + if (baseMimeType === validType.replace(/\/.*$/, "")) { + return true; + } + } else { + if (mimeType === validType) { + return true; + } + } + } + return false; + }; + + if (typeof jQuery !== "undefined" && jQuery !== null) { + jQuery.fn.dropzone = function(options) { + return this.each(function() { + return new Dropzone(this, options); + }); + }; + } + + if (typeof module !== "undefined" && module !== null) { + module.exports = Dropzone; + } else { + window.Dropzone = Dropzone; + } + + Dropzone.ADDED = "added"; + + Dropzone.QUEUED = "queued"; + + Dropzone.ACCEPTED = Dropzone.QUEUED; + + Dropzone.UPLOADING = "uploading"; + + Dropzone.PROCESSING = Dropzone.UPLOADING; + + Dropzone.CANCELED = "canceled"; + + Dropzone.ERROR = "error"; + + Dropzone.SUCCESS = "success"; + + /* + + Bugfix for iOS 6 and 7 + Source: http://stackoverflow.com/questions/11929099/html5-canvas-drawimage-ratio-bug-ios + based on the work of https://github.com/stomita/ios-imagefile-megapixel + */ + + + detectVerticalSquash = function(img) { + var alpha, canvas, ctx, data, ey, ih, iw, py, ratio, sy; + iw = img.naturalWidth; + ih = img.naturalHeight; + canvas = document.createElement("canvas"); + canvas.width = 1; + canvas.height = ih; + ctx = canvas.getContext("2d"); + ctx.drawImage(img, 0, 0); + data = ctx.getImageData(0, 0, 1, ih).data; + sy = 0; + ey = ih; + py = ih; + while (py > sy) { + alpha = data[(py - 1) * 4 + 3]; + if (alpha === 0) { + ey = py; + } else { + sy = py; + } + py = (ey + sy) >> 1; + } + ratio = py / ih; + if (ratio === 0) { + return 1; + } else { + return ratio; + } + }; + + drawImageIOSFix = function(ctx, img, sx, sy, sw, sh, dx, dy, dw, dh) { + var vertSquashRatio; + vertSquashRatio = detectVerticalSquash(img); + return ctx.drawImage(img, sx, sy, sw, sh, dx, dy, dw, dh / vertSquashRatio); + }; + + /* + # contentloaded.js + # + # Author: Diego Perini (diego.perini at gmail.com) + # Summary: cross-browser wrapper for DOMContentLoaded + # Updated: 20101020 + # License: MIT + # Version: 1.2 + # + # URL: + # http://javascript.nwbox.com/ContentLoaded/ + # http://javascript.nwbox.com/ContentLoaded/MIT-LICENSE + */ + + + contentLoaded = function(win, fn) { + var add, doc, done, init, poll, pre, rem, root, top; + done = false; + top = true; + doc = win.document; + root = doc.documentElement; + add = (doc.addEventListener ? "addEventListener" : "attachEvent"); + rem = (doc.addEventListener ? "removeEventListener" : "detachEvent"); + pre = (doc.addEventListener ? "" : "on"); + init = function(e) { + if (e.type === "readystatechange" && doc.readyState !== "complete") { + return; + }(e.type === "load" ? win : doc)[rem](pre + e.type, init, false); + if (!done && (done = true)) { + return fn.call(win, e.type || e); + } + }; + poll = function() { + var e; + try { + root.doScroll("left"); + } catch (_error) { + e = _error; + setTimeout(poll, 50); + return; + } + return init("poll"); + }; + if (doc.readyState !== "complete") { + if (doc.createEventObject && root.doScroll) { + try { + top = !win.frameElement; + } catch (_error) {} + if (top) { + poll(); + } + } + doc[add](pre + "DOMContentLoaded", init, false); + doc[add](pre + "readystatechange", init, false); + return win[add](pre + "load", init, false); + } + }; + + Dropzone._autoDiscoverFunction = function() { + if (Dropzone.autoDiscover) { + return Dropzone.discover(); + } + }; + + contentLoaded(window, Dropzone._autoDiscoverFunction); + + }).call(this); + +}); +require.register("enyo-opentip/index.js", function(exports, require, module) { + // Copyright (c) 2012 Matias Meno + + + // The index.js file for component + var Opentip = require("./lib/opentip.js"); + + + var Adapter = require("./lib/adapter-component.js"); + + // Add the adapter to the list + Opentip.addAdapter(new Adapter()); + + + // Exposing the Opentip class + module.exports = Opentip; +}); +require.register("enyo-opentip/lib/opentip.js", function(exports, require, module) { + /* + # + # Opentip v2.4.6 + # + # More info at [www.opentip.org](http://www.opentip.org) + # + # Copyright (c) 2012, Matias Meno + # Graphics by Tjandra Mayerhold + # + # 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. + # + */ + + var Opentip, firstAdapter, i, mouseMoved, mousePosition, mousePositionObservers, position, vendors, _i, _len, _ref, + __slice = [].slice, + __indexOf = [].indexOf || function(item) { + for (var i = 0, l = this.length; i < l; i++) { + if (i in this && this[i] === item) + return i; + } + return - 1; + }, + __hasProp = {}.hasOwnProperty; + + Opentip = (function() { + Opentip.prototype.STICKS_OUT_TOP = 1; + + Opentip.prototype.STICKS_OUT_BOTTOM = 2; + + Opentip.prototype.STICKS_OUT_LEFT = 1; + + Opentip.prototype.STICKS_OUT_RIGHT = 2; + + Opentip.prototype["class"] = { + container: "opentip-container", + opentip: "opentip", + header: "ot-header", + content: "ot-content", + loadingIndicator: "ot-loading-indicator", + close: "ot-close", + goingToHide: "ot-going-to-hide", + hidden: "ot-hidden", + hiding: "ot-hiding", + goingToShow: "ot-going-to-show", + showing: "ot-showing", + visible: "ot-visible", + loading: "ot-loading", + ajaxError: "ot-ajax-error", + fixed: "ot-fixed", + showEffectPrefix: "ot-show-effect-", + hideEffectPrefix: "ot-hide-effect-", + stylePrefix: "style-" + }; + + function Opentip(element, content, title, options) { + var elementsOpentips, hideTrigger, methodToBind, optionSources, prop, styleName, _i, _j, _len, _len1, _ref, _ref1, _ref2, _tmpStyle, + _this = this; + + this.id = ++Opentip.lastId; + this.debug("Creating Opentip."); + Opentip.tips.push(this); + this.adapter = Opentip.adapter; + elementsOpentips = this.adapter.data(element, "opentips") || []; + elementsOpentips.push(this); + this.adapter.data(element, "opentips", elementsOpentips); + this.triggerElement = this.adapter.wrap(element); + if (this.triggerElement.length > 1) { + throw new Error("You can't call Opentip on multiple elements."); + } + if (this.triggerElement.length < 1) { + throw new Error("Invalid element."); + } + this.loaded = false; + this.loading = false; + this.visible = false; + this.waitingToShow = false; + this.waitingToHide = false; + this.currentPosition = { + left: 0, + top: 0 + }; + this.dimensions = { + width: 100, + height: 50 + }; + this.content = ""; + this.redraw = true; + this.currentObservers = { + showing: false, + visible: false, + hiding: false, + hidden: false + }; + options = this.adapter.clone(options); + if (typeof content === "object") { + options = content; + content = title = void 0; + } else if (typeof title === "object") { + options = title; + title = void 0; + } + if (title != null) { + options.title = title; + } + if (content != null) { + this.setContent(content); + } + if (options["extends"] == null) { + if (options.style != null) { + options["extends"] = options.style; + } else { + options["extends"] = Opentip.defaultStyle; + } + } + optionSources = [options]; + _tmpStyle = options; + while (_tmpStyle["extends"]) { + styleName = _tmpStyle["extends"]; + _tmpStyle = Opentip.styles[styleName]; + if (_tmpStyle == null) { + throw new Error("Invalid style: " + styleName); + } + optionSources.unshift(_tmpStyle); + if (!((_tmpStyle["extends"] != null) || styleName === "standard")) { + _tmpStyle["extends"] = "standard"; + } + } + options = (_ref = this.adapter).extend.apply(_ref, [{} + ].concat(__slice.call(optionSources))); + options.hideTriggers = (function() { + var _i, _len, _ref1, _results; + + _ref1 = options.hideTriggers; + _results = []; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + hideTrigger = _ref1[_i]; + _results.push(hideTrigger); + } + return _results; + })(); + if (options.hideTrigger && options.hideTriggers.length === 0) { + options.hideTriggers.push(options.hideTrigger); + } + _ref1 = ["tipJoint", "targetJoint", "stem"]; + for (_i = 0, _len = _ref1.length; _i < _len; _i++) { + prop = _ref1[_i]; + if (options[prop] && typeof options[prop] === "string") { + options[prop] = new Opentip.Joint(options[prop]); + } + } + if (options.ajax && (options.ajax === true || !options.ajax)) { + if (this.adapter.tagName(this.triggerElement) === "A") { + options.ajax = this.adapter.attr(this.triggerElement, "href"); + } else { + options.ajax = false; + } + } + if (options.showOn === "click" && this.adapter.tagName(this.triggerElement) === "A") { + this.adapter.observe(this.triggerElement, "click", function(e) { + e.preventDefault(); + e.stopPropagation(); + return e.stopped = true; + }); + } + if (options.target) { + options.fixed = true; + } + if (options.stem === true) { + options.stem = new Opentip.Joint(options.tipJoint); + } + if (options.target === true) { + options.target = this.triggerElement; + } else if (options.target) { + options.target = this.adapter.wrap(options.target); + } + this.currentStem = options.stem; + if (options.delay == null) { + options.delay = options.showOn === "mouseover" ? 0.2 : 0; + } + if (options.targetJoint == null) { + options.targetJoint = new Opentip.Joint(options.tipJoint).flip(); + } + this.showTriggers = []; + this.showTriggersWhenVisible = []; + this.hideTriggers = []; + if (options.showOn && options.showOn !== "creation") { + this.showTriggers.push({ + element: this.triggerElement, + event: options.showOn + }); + } + if (options.ajaxCache != null) { + options.cache = options.ajaxCache; + delete options.ajaxCache; + } + this.options = options; + this.bound = {}; + _ref2 = ["prepareToShow", "prepareToHide", "show", "hide", "reposition"]; + for (_j = 0, _len1 = _ref2.length; _j < _len1; _j++) { + methodToBind = _ref2[_j]; + this.bound[methodToBind] = (function(methodToBind) { + return function() { + return _this[methodToBind].apply(_this, arguments); + }; + })(methodToBind); + } + this.adapter.domReady(function() { + _this.activate(); + if (_this.options.showOn === "creation") { + return _this.prepareToShow(); + } + }); + } + + Opentip.prototype._setup = function() { + var hideOn, hideTrigger, hideTriggerElement, i, _i, _j, _len, _len1, _ref, _ref1, _results; + + this.debug("Setting up the tooltip."); + this._buildContainer(); + this.hideTriggers = []; + _ref = this.options.hideTriggers; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + hideTrigger = _ref[i]; + hideTriggerElement = null; + hideOn = this.options.hideOn instanceof Array ? this.options.hideOn[i] : this.options.hideOn; + if (typeof hideTrigger === "string") { + switch (hideTrigger) { + case "trigger": + hideOn = hideOn || "mouseout"; + hideTriggerElement = this.triggerElement; + break; + case "tip": + hideOn = hideOn || "mouseover"; + hideTriggerElement = this.container; + break; + case "target": + hideOn = hideOn || "mouseover"; + hideTriggerElement = this.options.target; + break; + case "closeButton": + break; + default: + throw new Error("Unknown hide trigger: " + hideTrigger + "."); + } + } else { + hideOn = hideOn || "mouseover"; + hideTriggerElement = this.adapter.wrap(hideTrigger); + } + if (hideTriggerElement) { + this.hideTriggers.push({ + element: hideTriggerElement, + event: hideOn, + original: hideTrigger + }); + } + } + _ref1 = this.hideTriggers; + _results = []; + for (_j = 0, _len1 = _ref1.length; _j < _len1; _j++) { + hideTrigger = _ref1[_j]; + _results.push(this.showTriggersWhenVisible.push({ + element: hideTrigger.element, + event: "mouseover" + })); + } + return _results; + }; + + Opentip.prototype._buildContainer = function() { + this.container = this.adapter.create("
"); + this.adapter.css(this.container, { + position: "absolute" + }); + if (this.options.ajax) { + this.adapter.addClass(this.container, this["class"].loading); + } + if (this.options.fixed) { + this.adapter.addClass(this.container, this["class"].fixed); + } + if (this.options.showEffect) { + this.adapter.addClass(this.container, "" + this["class"].showEffectPrefix + this.options.showEffect); + } + if (this.options.hideEffect) { + return this.adapter.addClass(this.container, "" + this["class"].hideEffectPrefix + this.options.hideEffect); + } + }; + + Opentip.prototype._buildElements = function() { + var headerElement, titleElement; + + this.tooltipElement = this.adapter.create("
"); + this.backgroundCanvas = this.adapter.wrap(document.createElement("canvas")); + this.adapter.css(this.backgroundCanvas, { + position: "absolute" + }); + if (typeof G_vmlCanvasManager !== "undefined" && G_vmlCanvasManager !== null) { + G_vmlCanvasManager.initElement(this.adapter.unwrap(this.backgroundCanvas)); + } + headerElement = this.adapter.find(this.tooltipElement, "." + this["class"].header); + if (this.options.title) { + titleElement = this.adapter.create("

"); + this.adapter.update(titleElement, this.options.title, this.options.escapeTitle); + this.adapter.append(headerElement, titleElement); + } + if (this.options.ajax && !this.loaded) { + this.adapter.append(this.tooltipElement, this.adapter.create("
")); + } + if (__indexOf.call(this.options.hideTriggers, "closeButton") >= 0) { + this.closeButtonElement = this.adapter.create("Close"); + this.adapter.append(headerElement, this.closeButtonElement); + } + this.adapter.append(this.container, this.backgroundCanvas); + this.adapter.append(this.container, this.tooltipElement); + this.adapter.append(document.body, this.container); + this._newContent = true; + return this.redraw = true; + }; + + Opentip.prototype.setContent = function(content) { + this.content = content; + this._newContent = true; + if (typeof this.content === "function") { + this._contentFunction = this.content; + this.content = ""; + } else { + this._contentFunction = null; + } + if (this.visible) { + return this._updateElementContent(); + } + }; + + Opentip.prototype._updateElementContent = function() { + var contentDiv; + + if (this._newContent || (!this.options.cache && this._contentFunction)) { + contentDiv = this.adapter.find(this.container, "." + this["class"].content); + if (contentDiv != null) { + if (this._contentFunction) { + this.debug("Executing content function."); + this.content = this._contentFunction(this); + } + this.adapter.update(contentDiv, this.content, this.options.escapeContent); + } + this._newContent = false; + } + this._storeAndLockDimensions(); + return this.reposition(); + }; + + Opentip.prototype._storeAndLockDimensions = function() { + var prevDimension; + + if (!this.container) { + return; + } + prevDimension = this.dimensions; + this.adapter.css(this.container, { + width: "auto", + left: "0px", + top: "0px" + }); + this.dimensions = this.adapter.dimensions(this.container); + this.dimensions.width += 1; + this.adapter.css(this.container, { + width: "" + this.dimensions.width + "px", + top: "" + this.currentPosition.top + "px", + left: "" + this.currentPosition.left + "px" + }); + if (!this._dimensionsEqual(this.dimensions, prevDimension)) { + this.redraw = true; + return this._draw(); + } + }; + + Opentip.prototype.activate = function() { + return this._setupObservers("hidden", "hiding"); + }; + + Opentip.prototype.deactivate = function() { + this.debug("Deactivating tooltip."); + this.hide(); + return this._setupObservers("-showing", "-visible", "-hidden", "-hiding"); + }; + + Opentip.prototype._setupObservers = function() { + var observeOrStop, removeObserver, state, states, trigger, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref, _ref1, _ref2, + _this = this; + + states = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + for (_i = 0, _len = states.length; _i < _len; _i++) { + state = states[_i]; + removeObserver = false; + if (state.charAt(0) === "-") { + removeObserver = true; + state = state.substr(1); + } + if (this.currentObservers[state] === !removeObserver) { + continue; + } + this.currentObservers[state] = !removeObserver; + observeOrStop = function() { + var args, _ref, _ref1; + + args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + if (removeObserver) { + return (_ref = _this.adapter).stopObserving.apply(_ref, args); + } else { + return (_ref1 = _this.adapter).observe.apply(_ref1, args); + } + }; + switch (state) { + case "showing": + _ref = this.hideTriggers; + for (_j = 0, _len1 = _ref.length; _j < _len1; _j++) { + trigger = _ref[_j]; + observeOrStop(trigger.element, trigger.event, this.bound.prepareToHide); + } + observeOrStop((document.onresize != null ? document : window), "resize", this.bound.reposition); + observeOrStop(window, "scroll", this.bound.reposition); + break; + case "visible": + _ref1 = this.showTriggersWhenVisible; + for (_k = 0, _len2 = _ref1.length; _k < _len2; _k++) { + trigger = _ref1[_k]; + observeOrStop(trigger.element, trigger.event, this.bound.prepareToShow); + } + break; + case "hiding": + _ref2 = this.showTriggers; + for (_l = 0, _len3 = _ref2.length; _l < _len3; _l++) { + trigger = _ref2[_l]; + observeOrStop(trigger.element, trigger.event, this.bound.prepareToShow); + } + break; + case "hidden": + break; + default: + throw new Error("Unknown state: " + state); + } + } + return null; + }; + + Opentip.prototype.prepareToShow = function() { + this._abortHiding(); + this._abortShowing(); + if (this.visible) { + return; + } + this.debug("Showing in " + this.options.delay + "s."); + if (this.container == null) { + this._setup(); + } + if (this.options.group) { + Opentip._abortShowingGroup(this.options.group, this); + } + this.preparingToShow = true; + this._setupObservers("-hidden", "-hiding", "showing"); + this._followMousePosition(); + if (this.options.fixed && !this.options.target) { + this.initialMousePosition = mousePosition; + } + this.reposition(); + return this._showTimeoutId = this.setTimeout(this.bound.show, this.options.delay || 0); + }; + + Opentip.prototype.show = function() { + var _this = this; + + this._abortHiding(); + if (this.visible) { + return; + } + this._clearTimeouts(); + if (!this._triggerElementExists()) { + return this.deactivate(); + } + this.debug("Showing now."); + if (this.container == null) { + this._setup(); + } + if (this.options.group) { + Opentip._hideGroup(this.options.group, this); + } + this.visible = true; + this.preparingToShow = false; + if (this.tooltipElement == null) { + this._buildElements(); + } + this._updateElementContent(); + if (this.options.ajax && (!this.loaded || !this.options.cache)) { + this._loadAjax(); + } + this._searchAndActivateCloseButtons(); + this._startEnsureTriggerElement(); + this.adapter.css(this.container, { + zIndex: Opentip.lastZIndex++ + }); + this._setupObservers("-hidden", "-hiding", "-showing", "-visible", "showing", "visible"); + if (this.options.fixed && !this.options.target) { + this.initialMousePosition = mousePosition; + } + this.reposition(); + this.adapter.removeClass(this.container, this["class"].hiding); + this.adapter.removeClass(this.container, this["class"].hidden); + this.adapter.addClass(this.container, this["class"].goingToShow); + this.setCss3Style(this.container, { + transitionDuration: "0s" + }); + this.defer(function() { + var delay; + + if (!_this.visible || _this.preparingToHide) { + return; + } + _this.adapter.removeClass(_this.container, _this["class"].goingToShow); + _this.adapter.addClass(_this.container, _this["class"].showing); + delay = 0; + if (_this.options.showEffect && _this.options.showEffectDuration) { + delay = _this.options.showEffectDuration; + } + _this.setCss3Style(_this.container, { + transitionDuration: "" + delay + "s" + }); + _this._visibilityStateTimeoutId = _this.setTimeout(function() { + _this.adapter.removeClass(_this.container, _this["class"].showing); + return _this.adapter.addClass(_this.container, _this["class"].visible); + }, delay); + return _this._activateFirstInput(); + }); + return this._draw(); + }; + + Opentip.prototype._abortShowing = function() { + if (this.preparingToShow) { + this.debug("Aborting showing."); + this._clearTimeouts(); + this._stopFollowingMousePosition(); + this.preparingToShow = false; + return this._setupObservers("-showing", "-visible", "hiding", "hidden"); + } + }; + + Opentip.prototype.prepareToHide = function() { + this._abortShowing(); + this._abortHiding(); + if (!this.visible) { + return; + } + this.debug("Hiding in " + this.options.hideDelay + "s"); + this.preparingToHide = true; + this._setupObservers("-showing", "visible", "-hidden", "hiding"); + return this._hideTimeoutId = this.setTimeout(this.bound.hide, this.options.hideDelay); + }; + + Opentip.prototype.hide = function() { + var _this = this; + + this._abortShowing(); + if (!this.visible) { + return; + } + this._clearTimeouts(); + this.debug("Hiding!"); + this.visible = false; + this.preparingToHide = false; + this._stopEnsureTriggerElement(); + this._setupObservers("-showing", "-visible", "-hiding", "-hidden", "hiding", "hidden"); + if (!this.options.fixed) { + this._stopFollowingMousePosition(); + } + if (!this.container) { + return; + } + this.adapter.removeClass(this.container, this["class"].visible); + this.adapter.removeClass(this.container, this["class"].showing); + this.adapter.addClass(this.container, this["class"].goingToHide); + this.setCss3Style(this.container, { + transitionDuration: "0s" + }); + return this.defer(function() { + var hideDelay; + + _this.adapter.removeClass(_this.container, _this["class"].goingToHide); + _this.adapter.addClass(_this.container, _this["class"].hiding); + hideDelay = 0; + if (_this.options.hideEffect && _this.options.hideEffectDuration) { + hideDelay = _this.options.hideEffectDuration; + } + _this.setCss3Style(_this.container, { + transitionDuration: "" + hideDelay + "s" + }); + return _this._visibilityStateTimeoutId = _this.setTimeout(function() { + _this.adapter.removeClass(_this.container, _this["class"].hiding); + _this.adapter.addClass(_this.container, _this["class"].hidden); + _this.setCss3Style(_this.container, { + transitionDuration: "0s" + }); + if (_this.options.removeElementsOnHide) { + _this.debug("Removing HTML elements."); + _this.adapter.remove(_this.container); + delete _this.container; + return delete _this.tooltipElement; + } + }, hideDelay); + }); + }; + + Opentip.prototype._abortHiding = function() { + if (this.preparingToHide) { + this.debug("Aborting hiding."); + this._clearTimeouts(); + this.preparingToHide = false; + return this._setupObservers("-hiding", "showing", "visible"); + } + }; + + Opentip.prototype.reposition = function() { + var position, stem, _ref, + _this = this; + + position = this.getPosition(); + if (position == null) { + return; + } + stem = this.options.stem; + if (this.options.containInViewport) { + _ref = this._ensureViewportContainment(position), position = _ref.position, stem = _ref.stem; + } + if (this._positionsEqual(position, this.currentPosition)) { + return; + } + if (!(!this.options.stem || stem.eql(this.currentStem))) { + this.redraw = true; + } + this.currentPosition = position; + this.currentStem = stem; + this._draw(); + this.adapter.css(this.container, { + left: "" + position.left + "px", + top: "" + position.top + "px" + }); + return this.defer(function() { + var rawContainer, redrawFix; + + rawContainer = _this.adapter.unwrap(_this.container); + rawContainer.style.visibility = "hidden"; + redrawFix = rawContainer.offsetHeight; + return rawContainer.style.visibility = "visible"; + }); + }; + + Opentip.prototype.getPosition = function(tipJoint, targetJoint, stem) { + var additionalHorizontal, additionalVertical, offsetDistance, position, stemLength, targetDimensions, targetPosition, unwrappedTarget, _ref; + + if (!this.container) { + return; + } + if (tipJoint == null) { + tipJoint = this.options.tipJoint; + } + if (targetJoint == null) { + targetJoint = this.options.targetJoint; + } + position = {}; + if (this.options.target) { + targetPosition = this.adapter.offset(this.options.target); + targetDimensions = this.adapter.dimensions(this.options.target); + position = targetPosition; + if (targetJoint.right) { + unwrappedTarget = this.adapter.unwrap(this.options.target); + if (unwrappedTarget.getBoundingClientRect != null) { + position.left = unwrappedTarget.getBoundingClientRect().right + ((_ref = window.pageXOffset) != null ? _ref : document.body.scrollLeft); + } else { + position.left += targetDimensions.width; + } + } else if (targetJoint.center) { + position.left += Math.round(targetDimensions.width / 2); + } + if (targetJoint.bottom) { + position.top += targetDimensions.height; + } else if (targetJoint.middle) { + position.top += Math.round(targetDimensions.height / 2); + } + if (this.options.borderWidth) { + if (this.options.tipJoint.left) { + position.left += this.options.borderWidth; + } + if (this.options.tipJoint.right) { + position.left -= this.options.borderWidth; + } + if (this.options.tipJoint.top) { + position.top += this.options.borderWidth; + } else if (this.options.tipJoint.bottom) { + position.top -= this.options.borderWidth; + } + } + } else { + if (this.initialMousePosition) { + position = { + top: this.initialMousePosition.y, + left: this.initialMousePosition.x + }; + } else { + position = { + top: mousePosition.y, + left: mousePosition.x + }; + } + } + if (this.options.autoOffset) { + stemLength = this.options.stem ? this.options.stemLength : 0; + offsetDistance = stemLength && this.options.fixed ? 2 : 10; + additionalHorizontal = tipJoint.middle && !this.options.fixed ? 15 : 0; + additionalVertical = tipJoint.center && !this.options.fixed ? 15 : 0; + if (tipJoint.right) { + position.left -= offsetDistance + additionalHorizontal; + } else if (tipJoint.left) { + position.left += offsetDistance + additionalHorizontal; + } + if (tipJoint.bottom) { + position.top -= offsetDistance + additionalVertical; + } else if (tipJoint.top) { + position.top += offsetDistance + additionalVertical; + } + if (stemLength) { + if (stem == null) { + stem = this.options.stem; + } + if (stem.right) { + position.left -= stemLength; + } else if (stem.left) { + position.left += stemLength; + } + if (stem.bottom) { + position.top -= stemLength; + } else if (stem.top) { + position.top += stemLength; + } + } + } + position.left += this.options.offset[0]; + position.top += this.options.offset[1]; + if (tipJoint.right) { + position.left -= this.dimensions.width; + } else if (tipJoint.center) { + position.left -= Math.round(this.dimensions.width / 2); + } + if (tipJoint.bottom) { + position.top -= this.dimensions.height; + } else if (tipJoint.middle) { + position.top -= Math.round(this.dimensions.height / 2); + } + return position; + }; + + Opentip.prototype._ensureViewportContainment = function(position) { + var needsRepositioning, newSticksOut, originals, revertedX, revertedY, scrollOffset, stem, sticksOut, targetJoint, tipJoint, viewportDimensions, viewportPosition; + + stem = this.options.stem; + originals = { + position: position, + stem: stem + }; + if (!(this.visible && position)) { + return originals; + } + sticksOut = this._sticksOut(position); + if (!(sticksOut[0] || sticksOut[1])) { + return originals; + } + tipJoint = new Opentip.Joint(this.options.tipJoint); + if (this.options.targetJoint) { + targetJoint = new Opentip.Joint(this.options.targetJoint); + } + scrollOffset = this.adapter.scrollOffset(); + viewportDimensions = this.adapter.viewportDimensions(); + viewportPosition = [position.left - scrollOffset[0], position.top - scrollOffset[1]]; + needsRepositioning = false; + if (viewportDimensions.width >= this.dimensions.width) { + if (sticksOut[0]) { + needsRepositioning = true; + switch (sticksOut[0]) { + case this.STICKS_OUT_LEFT: + tipJoint.setHorizontal("left"); + if (this.options.targetJoint) { + targetJoint.setHorizontal("right"); + } + break; + case this.STICKS_OUT_RIGHT: + tipJoint.setHorizontal("right"); + if (this.options.targetJoint) { + targetJoint.setHorizontal("left"); + } + } + } + } + if (viewportDimensions.height >= this.dimensions.height) { + if (sticksOut[1]) { + needsRepositioning = true; + switch (sticksOut[1]) { + case this.STICKS_OUT_TOP: + tipJoint.setVertical("top"); + if (this.options.targetJoint) { + targetJoint.setVertical("bottom"); + } + break; + case this.STICKS_OUT_BOTTOM: + tipJoint.setVertical("bottom"); + if (this.options.targetJoint) { + targetJoint.setVertical("top"); + } + } + } + } + if (!needsRepositioning) { + return originals; + } + if (this.options.stem) { + stem = tipJoint; + } + position = this.getPosition(tipJoint, targetJoint, stem); + newSticksOut = this._sticksOut(position); + revertedX = false; + revertedY = false; + if (newSticksOut[0] && (newSticksOut[0] !== sticksOut[0])) { + revertedX = true; + tipJoint.setHorizontal(this.options.tipJoint.horizontal); + if (this.options.targetJoint) { + targetJoint.setHorizontal(this.options.targetJoint.horizontal); + } + } + if (newSticksOut[1] && (newSticksOut[1] !== sticksOut[1])) { + revertedY = true; + tipJoint.setVertical(this.options.tipJoint.vertical); + if (this.options.targetJoint) { + targetJoint.setVertical(this.options.targetJoint.vertical); + } + } + if (revertedX && revertedY) { + return originals; + } + if (revertedX || revertedY) { + if (this.options.stem) { + stem = tipJoint; + } + position = this.getPosition(tipJoint, targetJoint, stem); + } + return { + position: position, + stem: stem + }; + }; + + Opentip.prototype._sticksOut = function(position) { + var positionOffset, scrollOffset, sticksOut, viewportDimensions; + + scrollOffset = this.adapter.scrollOffset(); + viewportDimensions = this.adapter.viewportDimensions(); + positionOffset = [position.left - scrollOffset[0], position.top - scrollOffset[1]]; + sticksOut = [false, false]; + if (positionOffset[0] < 0) { + sticksOut[0] = this.STICKS_OUT_LEFT; + } else if (positionOffset[0] + this.dimensions.width > viewportDimensions.width) { + sticksOut[0] = this.STICKS_OUT_RIGHT; + } + if (positionOffset[1] < 0) { + sticksOut[1] = this.STICKS_OUT_TOP; + } else if (positionOffset[1] + this.dimensions.height > viewportDimensions.height) { + sticksOut[1] = this.STICKS_OUT_BOTTOM; + } + return sticksOut; + }; + + Opentip.prototype._draw = function() { + var backgroundCanvas, bulge, canvasDimensions, canvasPosition, closeButton, closeButtonInner, closeButtonOuter, ctx, drawCorner, drawLine, hb, position, stemBase, stemLength, _i, _len, _ref, _ref1, _ref2, + _this = this; + + if (!(this.backgroundCanvas && this.redraw)) { + return; + } + this.debug("Drawing background."); + this.redraw = false; + if (this.currentStem) { + _ref = ["top", "right", "bottom", "left"]; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + position = _ref[_i]; + this.adapter.removeClass(this.container, "stem-" + position); + } + this.adapter.addClass(this.container, "stem-" + this.currentStem.horizontal); + this.adapter.addClass(this.container, "stem-" + this.currentStem.vertical); + } + closeButtonInner = [0, 0]; + closeButtonOuter = [0, 0]; + if (__indexOf.call(this.options.hideTriggers, "closeButton") >= 0) { + closeButton = new Opentip.Joint(((_ref1 = this.currentStem) != null ? _ref1.toString() : void 0) === "top right" ? "top left" : "top right"); + closeButtonInner = [this.options.closeButtonRadius + this.options.closeButtonOffset[0], this.options.closeButtonRadius + this.options.closeButtonOffset[1]]; + closeButtonOuter = [this.options.closeButtonRadius - this.options.closeButtonOffset[0], this.options.closeButtonRadius - this.options.closeButtonOffset[1]]; + } + canvasDimensions = this.adapter.clone(this.dimensions); + canvasPosition = [0, 0]; + if (this.options.borderWidth) { + canvasDimensions.width += this.options.borderWidth * 2; + canvasDimensions.height += this.options.borderWidth * 2; + canvasPosition[0] -= this.options.borderWidth; + canvasPosition[1] -= this.options.borderWidth; + } + if (this.options.shadow) { + canvasDimensions.width += this.options.shadowBlur * 2; + canvasDimensions.width += Math.max(0, this.options.shadowOffset[0] - this.options.shadowBlur * 2); + canvasDimensions.height += this.options.shadowBlur * 2; + canvasDimensions.height += Math.max(0, this.options.shadowOffset[1] - this.options.shadowBlur * 2); + canvasPosition[0] -= Math.max(0, this.options.shadowBlur - this.options.shadowOffset[0]); + canvasPosition[1] -= Math.max(0, this.options.shadowBlur - this.options.shadowOffset[1]); + } + bulge = { + left: 0, + right: 0, + top: 0, + bottom: 0 + }; + if (this.currentStem) { + if (this.currentStem.left) { + bulge.left = this.options.stemLength; + } else if (this.currentStem.right) { + bulge.right = this.options.stemLength; + } + if (this.currentStem.top) { + bulge.top = this.options.stemLength; + } else if (this.currentStem.bottom) { + bulge.bottom = this.options.stemLength; + } + } + if (closeButton) { + if (closeButton.left) { + bulge.left = Math.max(bulge.left, closeButtonOuter[0]); + } else if (closeButton.right) { + bulge.right = Math.max(bulge.right, closeButtonOuter[0]); + } + if (closeButton.top) { + bulge.top = Math.max(bulge.top, closeButtonOuter[1]); + } else if (closeButton.bottom) { + bulge.bottom = Math.max(bulge.bottom, closeButtonOuter[1]); + } + } + canvasDimensions.width += bulge.left + bulge.right; + canvasDimensions.height += bulge.top + bulge.bottom; + canvasPosition[0] -= bulge.left; + canvasPosition[1] -= bulge.top; + if (this.currentStem && this.options.borderWidth) { + _ref2 = this._getPathStemMeasures(this.options.stemBase, this.options.stemLength, this.options.borderWidth), stemLength = _ref2.stemLength, stemBase = _ref2.stemBase; + } + backgroundCanvas = this.adapter.unwrap(this.backgroundCanvas); + backgroundCanvas.width = canvasDimensions.width; + backgroundCanvas.height = canvasDimensions.height; + this.adapter.css(this.backgroundCanvas, { + width: "" + backgroundCanvas.width + "px", + height: "" + backgroundCanvas.height + "px", + left: "" + canvasPosition[0] + "px", + top: "" + canvasPosition[1] + "px" + }); + ctx = backgroundCanvas.getContext("2d"); + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.clearRect(0, 0, backgroundCanvas.width, backgroundCanvas.height); + ctx.beginPath(); + ctx.fillStyle = this._getColor(ctx, this.dimensions, this.options.background, this.options.backgroundGradientHorizontal); + ctx.lineJoin = "miter"; + ctx.miterLimit = 500; + hb = this.options.borderWidth / 2; + if (this.options.borderWidth) { + ctx.strokeStyle = this.options.borderColor; + ctx.lineWidth = this.options.borderWidth; + } else { + stemLength = this.options.stemLength; + stemBase = this.options.stemBase; + } + if (stemBase == null) { + stemBase = 0; + } + drawLine = function(length, stem, first) { + if (first) { + ctx.moveTo(Math.max(stemBase, _this.options.borderRadius, closeButtonInner[0]) + 1 - hb, - hb); + } + if (stem) { + ctx.lineTo(length / 2 - stemBase / 2, - hb); + ctx.lineTo(length / 2, - stemLength - hb); + return ctx.lineTo(length / 2 + stemBase / 2, - hb); + } + }; + drawCorner = function(stem, closeButton, i) { + var angle1, angle2, innerWidth, offset; + + if (stem) { + ctx.lineTo( - stemBase + hb, 0 - hb); + ctx.lineTo(stemLength + hb, - stemLength - hb); + return ctx.lineTo(hb, stemBase - hb); + } else if (closeButton) { + offset = _this.options.closeButtonOffset; + innerWidth = closeButtonInner[0]; + if (i % 2 !== 0) { + offset = [offset[1], offset[0]]; + innerWidth = closeButtonInner[1]; + } + angle1 = Math.acos(offset[1] / _this.options.closeButtonRadius); + angle2 = Math.acos(offset[0] / _this.options.closeButtonRadius); + ctx.lineTo( - innerWidth + hb, - hb); + return ctx.arc(hb - offset[0], - hb + offset[1], _this.options.closeButtonRadius, - (Math.PI / 2 + angle1), angle2, false); + } else { + ctx.lineTo( - _this.options.borderRadius + hb, - hb); + return ctx.quadraticCurveTo(hb, - hb, hb, _this.options.borderRadius - hb); + } + }; + ctx.translate( - canvasPosition[0], - canvasPosition[1]); + ctx.save(); + (function() { + var cornerStem, i, lineLength, lineStem, positionIdx, positionX, positionY, rotation, _j, _ref3, _results; + + _results = []; + for (i = _j = 0, _ref3 = Opentip.positions.length / 2; 0 <= _ref3 ? _j < _ref3 : _j > _ref3; i = 0 <= _ref3 ? ++_j : --_j) { + positionIdx = i * 2; + positionX = i === 0 || i === 3 ? 0 : _this.dimensions.width; + positionY = i < 2 ? 0 : _this.dimensions.height; + rotation = (Math.PI / 2) * i; + lineLength = i % 2 === 0 ? _this.dimensions.width : _this.dimensions.height; + lineStem = new Opentip.Joint(Opentip.positions[positionIdx]); + cornerStem = new Opentip.Joint(Opentip.positions[positionIdx + 1]); + ctx.save(); + ctx.translate(positionX, positionY); + ctx.rotate(rotation); + drawLine(lineLength, lineStem.eql(_this.currentStem), i === 0); + ctx.translate(lineLength, 0); + drawCorner(cornerStem.eql(_this.currentStem), cornerStem.eql(closeButton), i); + _results.push(ctx.restore()); + } + return _results; + })(); + ctx.closePath(); + ctx.save(); + if (this.options.shadow) { + ctx.shadowColor = this.options.shadowColor; + ctx.shadowBlur = this.options.shadowBlur; + ctx.shadowOffsetX = this.options.shadowOffset[0]; + ctx.shadowOffsetY = this.options.shadowOffset[1]; + } + ctx.fill(); + ctx.restore(); + if (this.options.borderWidth) { + ctx.stroke(); + } + ctx.restore(); + if (closeButton) { + return (function() { + var crossCenter, crossHeight, crossWidth, hcs, linkCenter; + + crossWidth = crossHeight = _this.options.closeButtonRadius * 2; + if (closeButton.toString() === "top right") { + linkCenter = [_this.dimensions.width - _this.options.closeButtonOffset[0], _this.options.closeButtonOffset[1]]; + crossCenter = [linkCenter[0] + hb, linkCenter[1] - hb]; + } else { + linkCenter = [_this.options.closeButtonOffset[0], _this.options.closeButtonOffset[1]]; + crossCenter = [linkCenter[0] - hb, linkCenter[1] - hb]; + } + ctx.translate(crossCenter[0], crossCenter[1]); + hcs = _this.options.closeButtonCrossSize / 2; + ctx.save(); + ctx.beginPath(); + ctx.strokeStyle = _this.options.closeButtonCrossColor; + ctx.lineWidth = _this.options.closeButtonCrossLineWidth; + ctx.lineCap = "round"; + ctx.moveTo( - hcs, - hcs); + ctx.lineTo(hcs, hcs); + ctx.stroke(); + ctx.beginPath(); + ctx.moveTo(hcs, - hcs); + ctx.lineTo( - hcs, hcs); + ctx.stroke(); + ctx.restore(); + return _this.adapter.css(_this.closeButtonElement, { + left: "" + (linkCenter[0] - hcs - _this.options.closeButtonLinkOverscan) + "px", + top: "" + (linkCenter[1] - hcs - _this.options.closeButtonLinkOverscan) + "px", + width: "" + (_this.options.closeButtonCrossSize + _this.options.closeButtonLinkOverscan * 2) + "px", + height: "" + (_this.options.closeButtonCrossSize + _this.options.closeButtonLinkOverscan * 2) + "px" + }); + })(); + } + }; + + Opentip.prototype._getPathStemMeasures = function(outerStemBase, outerStemLength, borderWidth) { + var angle, distanceBetweenTips, halfAngle, hb, rhombusSide, stemBase, stemLength; + + hb = borderWidth / 2; + halfAngle = Math.atan((outerStemBase / 2) / outerStemLength); + angle = halfAngle * 2; + rhombusSide = hb / Math.sin(angle); + distanceBetweenTips = 2 * rhombusSide * Math.cos(halfAngle); + stemLength = hb + outerStemLength - distanceBetweenTips; + if (stemLength < 0) { + throw new Error("Sorry but your stemLength / stemBase ratio is strange."); + } + stemBase = (Math.tan(halfAngle) * stemLength) * 2; + return { + stemLength: stemLength, + stemBase: stemBase + }; + }; + + Opentip.prototype._getColor = function(ctx, dimensions, color, horizontal) { + var colorStop, gradient, i, _i, _len; + + if (horizontal == null) { + horizontal = false; + } + if (typeof color === "string") { + return color; + } + if (horizontal) { + gradient = ctx.createLinearGradient(0, 0, dimensions.width, 0); + } else { + gradient = ctx.createLinearGradient(0, 0, 0, dimensions.height); + } + for (i = _i = 0, _len = color.length; _i < _len; i = ++_i) { + colorStop = color[i]; + gradient.addColorStop(colorStop[0], colorStop[1]); + } + return gradient; + }; + + Opentip.prototype._searchAndActivateCloseButtons = function() { + var element, _i, _len, _ref; + + _ref = this.adapter.findAll(this.container, "." + this["class"].close); + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + element = _ref[_i]; + this.hideTriggers.push({ + element: this.adapter.wrap(element), + event: "click" + }); + } + if (this.currentObservers.showing) { + this._setupObservers("-showing", "showing"); + } + if (this.currentObservers.visible) { + return this._setupObservers("-visible", "visible"); + } + }; + + Opentip.prototype._activateFirstInput = function() { + var input; + + input = this.adapter.unwrap(this.adapter.find(this.container, "input, textarea")); + return input != null ? typeof input.focus === "function" ? input.focus() : void 0 : void 0; + }; + + Opentip.prototype._followMousePosition = function() { + if (!this.options.fixed) { + return Opentip._observeMousePosition(this.bound.reposition); + } + }; + + Opentip.prototype._stopFollowingMousePosition = function() { + if (!this.options.fixed) { + return Opentip._stopObservingMousePosition(this.bound.reposition); + } + }; + + Opentip.prototype._clearShowTimeout = function() { + return clearTimeout(this._showTimeoutId); + }; + + Opentip.prototype._clearHideTimeout = function() { + return clearTimeout(this._hideTimeoutId); + }; + + Opentip.prototype._clearTimeouts = function() { + clearTimeout(this._visibilityStateTimeoutId); + this._clearShowTimeout(); + return this._clearHideTimeout(); + }; + + Opentip.prototype._triggerElementExists = function() { + var el; + + el = this.adapter.unwrap(this.triggerElement); + while (el.parentNode) { + if (el.parentNode.tagName === "BODY") { + return true; + } + el = el.parentNode; + } + return false; + }; + + Opentip.prototype._loadAjax = function() { + var _this = this; + + if (this.loading) { + return; + } + this.loaded = false; + this.loading = true; + this.adapter.addClass(this.container, this["class"].loading); + this.setContent(""); + this.debug("Loading content from " + this.options.ajax); + return this.adapter.ajax({ + url: this.options.ajax, + method: this.options.ajaxMethod, + onSuccess: function(responseText) { + _this.debug("Loading successful."); + _this.adapter.removeClass(_this.container, _this["class"].loading); + return _this.setContent(responseText); + }, + onError: function(error) { + var message; + + message = _this.options.ajaxErrorMessage; + _this.debug(message, error); + _this.setContent(message); + return _this.adapter.addClass(_this.container, _this["class"].ajaxError); + }, + onComplete: function() { + _this.adapter.removeClass(_this.container, _this["class"].loading); + _this.loading = false; + _this.loaded = true; + _this._searchAndActivateCloseButtons(); + _this._activateFirstInput(); + return _this.reposition(); + } + }); + }; + + Opentip.prototype._ensureTriggerElement = function() { + if (!this._triggerElementExists()) { + this.deactivate(); + return this._stopEnsureTriggerElement(); + } + }; + + Opentip.prototype._ensureTriggerElementInterval = 1000; + + Opentip.prototype._startEnsureTriggerElement = function() { + var _this = this; + + return this._ensureTriggerElementTimeoutId = setInterval((function() { + return _this._ensureTriggerElement(); + }), this._ensureTriggerElementInterval); + }; + + Opentip.prototype._stopEnsureTriggerElement = function() { + return clearInterval(this._ensureTriggerElementTimeoutId); + }; + + return Opentip; + + })(); + + vendors = ["khtml", "ms", "o", "moz", "webkit"]; + + Opentip.prototype.setCss3Style = function(element, styles) { + var prop, value, vendor, vendorProp, _results; + + element = this.adapter.unwrap(element); + _results = []; + for (prop in styles) { + if (!__hasProp.call(styles, prop)) + continue; + value = styles[prop]; + if (element.style[prop] != null) { + _results.push(element.style[prop] = value); + } else { + _results.push((function() { + var _i, _len, _results1; + + _results1 = []; + for (_i = 0, _len = vendors.length; _i < _len; _i++) { + vendor = vendors[_i]; + vendorProp = "" + (this.ucfirst(vendor)) + (this.ucfirst(prop)); + if (element.style[vendorProp] != null) { + _results1.push(element.style[vendorProp] = value); + } else { + _results1.push(void 0); + } + } + return _results1; + }).call(this)); + } + } + return _results; + }; + + Opentip.prototype.defer = function(func) { + return setTimeout(func, 0); + }; + + Opentip.prototype.setTimeout = function(func, seconds) { + return setTimeout(func, seconds ? seconds * 1000 : 0); + }; + + Opentip.prototype.ucfirst = function(string) { + if (string == null) { + return ""; + } + return string.charAt(0).toUpperCase() + string.slice(1); + }; + + Opentip.prototype.dasherize = function(string) { + return string.replace(/([A-Z])/g, function(_, character) { + return "-" + (character.toLowerCase()); + }); + }; + + mousePositionObservers = []; + + mousePosition = { + x: 0, + y: 0 + }; + + mouseMoved = function(e) { + var observer, _i, _len, _results; + + mousePosition = Opentip.adapter.mousePosition(e); + _results = []; + for (_i = 0, _len = mousePositionObservers.length; _i < _len; _i++) { + observer = mousePositionObservers[_i]; + _results.push(observer()); + } + return _results; + }; + + Opentip.followMousePosition = function() { + return Opentip.adapter.observe(document.body, "mousemove", mouseMoved); + }; + + Opentip._observeMousePosition = function(observer) { + return mousePositionObservers.push(observer); + }; + + Opentip._stopObservingMousePosition = function(removeObserver) { + var observer; + + return mousePositionObservers = (function() { + var _i, _len, _results; + + _results = []; + for (_i = 0, _len = mousePositionObservers.length; _i < _len; _i++) { + observer = mousePositionObservers[_i]; + if (observer !== removeObserver) { + _results.push(observer); + } + } + return _results; + })(); + }; + + Opentip.Joint = (function() { + function Joint(pointerString) { + if (pointerString == null) { + return; + } + if (pointerString instanceof Opentip.Joint) { + pointerString = pointerString.toString(); + } + this.set(pointerString); + this; + } + + Joint.prototype.set = function(string) { + string = string.toLowerCase(); + this.setHorizontal(string); + this.setVertical(string); + return this; + }; + + Joint.prototype.setHorizontal = function(string) { + var i, valid, _i, _j, _len, _len1, _results; + + valid = ["left", "center", "right"]; + for (_i = 0, _len = valid.length; _i < _len; _i++) { + i = valid[_i]; + if (~string.indexOf(i)) { + this.horizontal = i.toLowerCase(); + } + } + if (this.horizontal == null) { + this.horizontal = "center"; + } + _results = []; + for (_j = 0, _len1 = valid.length; _j < _len1; _j++) { + i = valid[_j]; + _results.push(this[i] = this.horizontal === i ? i : void 0); + } + return _results; + }; + + Joint.prototype.setVertical = function(string) { + var i, valid, _i, _j, _len, _len1, _results; + + valid = ["top", "middle", "bottom"]; + for (_i = 0, _len = valid.length; _i < _len; _i++) { + i = valid[_i]; + if (~string.indexOf(i)) { + this.vertical = i.toLowerCase(); + } + } + if (this.vertical == null) { + this.vertical = "middle"; + } + _results = []; + for (_j = 0, _len1 = valid.length; _j < _len1; _j++) { + i = valid[_j]; + _results.push(this[i] = this.vertical === i ? i : void 0); + } + return _results; + }; + + Joint.prototype.eql = function(pointer) { + return (pointer != null) && this.horizontal === pointer.horizontal && this.vertical === pointer.vertical; + }; + + Joint.prototype.flip = function() { + var flippedIndex, positionIdx; + + positionIdx = Opentip.position[this.toString(true)]; + flippedIndex = (positionIdx + 4) % 8; + this.set(Opentip.positions[flippedIndex]); + return this; + }; + + Joint.prototype.toString = function(camelized) { + var horizontal, vertical; + + if (camelized == null) { + camelized = false; + } + vertical = this.vertical === "middle" ? "" : this.vertical; + horizontal = this.horizontal === "center" ? "" : this.horizontal; + if (vertical && horizontal) { + if (camelized) { + horizontal = Opentip.prototype.ucfirst(horizontal); + } else { + horizontal = " " + horizontal; + } + } + return "" + vertical + horizontal; + }; + + return Joint; + + })(); + + Opentip.prototype._positionsEqual = function(posA, posB) { + return (posA != null) && (posB != null) && posA.left === posB.left && posA.top === posB.top; + }; + + Opentip.prototype._dimensionsEqual = function(dimA, dimB) { + return (dimA != null) && (dimB != null) && dimA.width === dimB.width && dimA.height === dimB.height; + }; + + Opentip.prototype.debug = function() { + var args; + + args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + if (Opentip.debug && ((typeof console !== "undefined" && console !== null ? console.debug : void 0) != null)) { + args.unshift("#" + this.id + " |"); + return console.debug.apply(console, args); + } + }; + + Opentip.findElements = function() { + var adapter, content, element, optionName, optionValue, options, _i, _len, _ref, _results; + + adapter = Opentip.adapter; + _ref = adapter.findAll(document.body, "[data-ot]"); + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + element = _ref[_i]; + options = {}; + content = adapter.data(element, "ot"); + if (content === "" || content === "true" || content === "yes") { + content = adapter.attr(element, "title"); + adapter.attr(element, "title", ""); + } + content = content || ""; + for (optionName in Opentip.styles.standard) { + optionValue = adapter.data(element, "ot" + (Opentip.prototype.ucfirst(optionName))); + if (optionValue != null) { + if (optionValue === "yes" || optionValue === "true" || optionValue === "on") { + optionValue = true; + } else if (optionValue === "no" || optionValue === "false" || optionValue === "off") { + optionValue = false; + } + options[optionName] = optionValue; + } + } + _results.push(new Opentip(element, content, options)); + } + return _results; + }; + + Opentip.version = "2.4.6"; + + Opentip.debug = false; + + Opentip.lastId = 0; + + Opentip.lastZIndex = 100; + + Opentip.tips = []; + + Opentip._abortShowingGroup = function(group, originatingOpentip) { + var opentip, _i, _len, _ref, _results; + + _ref = Opentip.tips; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + opentip = _ref[_i]; + if (opentip !== originatingOpentip && opentip.options.group === group) { + _results.push(opentip._abortShowing()); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Opentip._hideGroup = function(group, originatingOpentip) { + var opentip, _i, _len, _ref, _results; + + _ref = Opentip.tips; + _results = []; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + opentip = _ref[_i]; + if (opentip !== originatingOpentip && opentip.options.group === group) { + _results.push(opentip.hide()); + } else { + _results.push(void 0); + } + } + return _results; + }; + + Opentip.adapters = {}; + + Opentip.adapter = null; + + firstAdapter = true; + + Opentip.addAdapter = function(adapter) { + Opentip.adapters[adapter.name] = adapter; + if (firstAdapter) { + Opentip.adapter = adapter; + adapter.domReady(Opentip.findElements); + adapter.domReady(Opentip.followMousePosition); + return firstAdapter = false; + } + }; + + Opentip.positions = ["top", "topRight", "right", "bottomRight", "bottom", "bottomLeft", "left", "topLeft"]; + + Opentip.position = {}; + + _ref = Opentip.positions; + for (i = _i = 0, _len = _ref.length; _i < _len; i = ++_i) { + position = _ref[i]; + Opentip.position[position] = i; + } + + Opentip.styles = { + standard: { + "extends": null, + title: void 0, + escapeTitle: true, + escapeContent: false, + className: "standard", + stem: true, + delay: null, + hideDelay: 0.1, + fixed: false, + showOn: "mouseover", + hideTrigger: "trigger", + hideTriggers: [], + hideOn: null, + removeElementsOnHide: false, + offset: [0, + 0], + containInViewport: true, + autoOffset: true, + showEffect: "appear", + hideEffect: "fade", + showEffectDuration: 0.3, + hideEffectDuration: 0.2, + stemLength: 5, + stemBase: 8, + tipJoint: "top left", + target: null, + targetJoint: null, + cache: true, + ajax: false, + ajaxMethod: "GET", + ajaxErrorMessage: "There was a problem downloading the content.", + group: null, + style: null, + background: "#fff18f", + backgroundGradientHorizontal: false, + closeButtonOffset: [5, + 5], + closeButtonRadius: 7, + closeButtonCrossSize: 4, + closeButtonCrossColor: "#d2c35b", + closeButtonCrossLineWidth: 1.5, + closeButtonLinkOverscan: 6, + borderRadius: 5, + borderWidth: 1, + borderColor: "#f2e37b", + shadow: true, + shadowBlur: 10, + shadowOffset: [3, + 3], + shadowColor: "rgba(0, 0, 0, 0.1)" + }, + glass: { + "extends": "standard", + className: "glass", + background: [[0, "rgba(252, 252, 252, 0.8)"], [0.5, "rgba(255, 255, 255, 0.8)"], [0.5, "rgba(250, 250, 250, 0.9)"], [1, "rgba(245, 245, 245, 0.9)"]], + borderColor: "#eee", + closeButtonCrossColor: "rgba(0, 0, 0, 0.2)", + borderRadius: 15, + closeButtonRadius: 10, + closeButtonOffset: [8, 8] + }, + dark: { + "extends": "standard", + className: "dark", + borderRadius: 13, + borderColor: "#444", + closeButtonCrossColor: "rgba(240, 240, 240, 1)", + shadowColor: "rgba(0, 0, 0, 0.3)", + shadowOffset: [2, 2], + background: [[0, "rgba(30, 30, 30, 0.7)"], [0.5, "rgba(30, 30, 30, 0.8)"], [0.5, "rgba(10, 10, 10, 0.8)"], [1, "rgba(10, 10, 10, 0.9)"]] + }, + alert: { + "extends": "standard", + className: "alert", + borderRadius: 1, + borderColor: "#AE0D11", + closeButtonCrossColor: "rgba(255, 255, 255, 1)", + shadowColor: "rgba(0, 0, 0, 0.3)", + shadowOffset: [2, 2], + background: [[0, "rgba(203, 15, 19, 0.7)"], [0.5, "rgba(203, 15, 19, 0.8)"], [0.5, "rgba(189, 14, 18, 0.8)"], [1, "rgba(179, 14, 17, 0.9)"]] + } + }; + + Opentip.defaultStyle = "standard"; + + if (typeof module !== "undefined" && module !== null) { + module.exports = Opentip; + } else { + window.Opentip = Opentip; + } + +}); +require.register("enyo-opentip/lib/adapter-component.js", function(exports, require, module) { + var $, Adapter, _ref, + __slice = [].slice; + + $ = (_ref = window.jQuery) != null ? _ref : require("jquery"); + + module.exports = Adapter = (function() { + function Adapter() {} + + Adapter.prototype.name = "component"; + + Adapter.prototype.domReady = function(callback) { + return $(callback); + }; + + Adapter.prototype.create = function(html) { + return $(html); + }; + + Adapter.prototype.wrap = function(element) { + element = $(element); + if (element.length > 1) { + throw new Error("Multiple elements provided."); + } + return element; + }; + + Adapter.prototype.unwrap = function(element) { + return $(element)[0]; + }; + + Adapter.prototype.tagName = function(element) { + return this.unwrap(element).tagName; + }; + + Adapter.prototype.attr = function() { + var args, element, _ref1; + + element = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + return (_ref1 = $(element)).attr.apply(_ref1, args); + }; + + Adapter.prototype.data = function() { + var args, element, _ref1; + + element = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + return (_ref1 = $(element)).data.apply(_ref1, args); + }; + + Adapter.prototype.find = function(element, selector) { + return $(element).find(selector)[0]; + }; + + Adapter.prototype.findAll = function(element, selector) { + return $(element).find(selector); + }; + + Adapter.prototype.update = function(element, content, escape) { + element = $(element); + if (escape) { + return element.text(content); + } else { + return element.html(content); + } + }; + + Adapter.prototype.append = function(element, child) { + return $(element).append(child); + }; + + Adapter.prototype.remove = function(element) { + return $(element).remove(); + }; + + Adapter.prototype.addClass = function(element, className) { + return $(element).addClass(className); + }; + + Adapter.prototype.removeClass = function(element, className) { + return $(element).removeClass(className); + }; + + Adapter.prototype.css = function(element, properties) { + return $(element).css(properties); + }; + + Adapter.prototype.dimensions = function(element) { + return { + width: $(element).outerWidth(), + height: $(element).outerHeight() + }; + }; + + Adapter.prototype.scrollOffset = function() { + return [window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft, window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop]; + }; + + Adapter.prototype.viewportDimensions = function() { + return { + width: document.documentElement.clientWidth, + height: document.documentElement.clientHeight + }; + }; + + Adapter.prototype.mousePosition = function(e) { + if (e == null) { + return null; + } + return { + x: e.pageX, + y: e.pageY + }; + }; + + Adapter.prototype.offset = function(element) { + var offset; + + offset = $(element).offset(); + return { + left: offset.left, + top: offset.top + }; + }; + + Adapter.prototype.observe = function(element, eventName, observer) { + return $(element).bind(eventName, observer); + }; + + Adapter.prototype.stopObserving = function(element, eventName, observer) { + return $(element).unbind(eventName, observer); + }; + + Adapter.prototype.ajax = function(options) { + var _ref1, _ref2; + + if (options.url == null) { + throw new Error("No url provided"); + } + return $.ajax({ + url: options.url, + type: (_ref1 = (_ref2 = options.method) != null ? _ref2.toUpperCase() : void 0) != null ? _ref1 : "GET" + }).done(function(content) { + return typeof options.onSuccess === "function" ? options.onSuccess(content) : void 0; + }).fail(function(request) { + return typeof options.onError === "function" ? options.onError("Server responded with status " + request.status) : void 0; + }).always(function() { + return typeof options.onComplete === "function" ? options.onComplete() : void 0; + }); + }; + + Adapter.prototype.clone = function(object) { + return $.extend({}, object); + }; + + Adapter.prototype.extend = function() { + var sources, target; + + target = arguments[0], sources = 2 <= arguments.length ? __slice.call(arguments, 1) : []; + return $.extend.apply($, [target].concat(__slice.call(sources))); + }; + + return Adapter; + + })(); + +}); +require.register("component-jquery/index.js", function(exports, require, module) { + /*! + * jQuery JavaScript Library v1.9.1 + * http://jquery.com/ + * + * Includes Sizzle.js + * http://sizzlejs.com/ + * + * Copyright 2005, 2012 jQuery Foundation, Inc. and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2013-2-4 + */ + (function( window, undefined ) { + + // Can't do this because several apps including ASP.NET trace + // the stack via arguments.caller.callee and Firefox dies if + // you try to trace through "use strict" call chains. (#13335) + // Support: Firefox 18+ + //"use strict"; + var + // The deferred used on DOM ready + readyList, + // A central reference to the root jQuery(document) + rootjQuery, + // Support: IE<9 + // For `typeof node.method` instead of `node.method !== undefined` + core_strundefined = typeof undefined, + // Use the correct document accordingly with window argument (sandbox) + document = window.document, + location = window.location, + // Map over jQuery in case of overwrite + _jQuery = window.jQuery, + // Map over the $ in case of overwrite + _$ = window.$, + // [[Class]] -> type pairs + class2type = {}, + // List of deleted data cache ids, so we can reuse them + core_deletedIds = [], + core_version = "1.9.1", + // Save a reference to some core methods + core_concat = core_deletedIds.concat, + core_push = core_deletedIds.push, + core_slice = core_deletedIds.slice, + core_indexOf = core_deletedIds.indexOf, + core_toString = class2type.toString, + core_hasOwn = class2type.hasOwnProperty, + core_trim = core_version.trim, + // Define a local copy of jQuery + jQuery = function( selector, context ) { + // The jQuery object is actually just the init constructor 'enhanced' + return new jQuery.fn.init( selector, context, rootjQuery ); + }, + // Used for matching numbers + core_pnum = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source, + // Used for splitting on whitespace + core_rnotwhite = /\S+/g, + // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + // A simple way to check for HTML strings + // Prioritize #id over to avoid XSS via location.hash (#9521) + // Strict HTML recognition (#11290: must start with <) + rquickExpr = /^(?:(<[\w\W]+>)[^>]*|#([\w-]*))$/, + // Match a standalone tag + rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, + // JSON RegExp + rvalidchars = /^[\],:{}\s]*$/, + rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, + rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, + rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d+\.|)\d+(?:[eE][+-]?\d+|)/g, + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([\da-z])/gi, + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }, + // The ready event handler + completed = function( event ) { + + // readyState === "complete" is good enough for us to call the dom ready in oldIE + if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) { + detach(); + jQuery.ready(); + } + }, + // Clean-up method for dom ready events + detach = function() { + if ( document.addEventListener ) { + document.removeEventListener( "DOMContentLoaded", completed, false ); + window.removeEventListener( "load", completed, false ); + + } else { + document.detachEvent( "onreadystatechange", completed ); + window.detachEvent( "onload", completed ); + } + }; + + jQuery.fn = jQuery.prototype = { + // The current version of jQuery being used + jquery: core_version, + + constructor: jQuery, + init: function( selector, context, rootjQuery ) { + var match, elem; + + // HANDLE: $(""), $(null), $(undefined), $(false) + if ( !selector ) { + return this; + } + + // Handle HTML strings + if ( typeof selector === "string" ) { + if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { + // Assume that strings that start and end with <> are HTML and skip the regex check + match = [ null, selector, null ]; + + } else { + match = rquickExpr.exec( selector ); + } + + // Match html or make sure no context is specified for #id + if ( match && (match[1] || !context) ) { + + // HANDLE: $(html) -> $(array) + if ( match[1] ) { + context = context instanceof jQuery ? context[0] : context; + + // scripts is true for back-compat + jQuery.merge( this, jQuery.parseHTML( + match[1], + context && context.nodeType ? context.ownerDocument || context : document, + true + ) ); + + // HANDLE: $(html, props) + if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { + for ( match in context ) { + // Properties of context are called as methods if possible + if ( jQuery.isFunction( this[ match ] ) ) { + this[ match ]( context[ match ] ); + + // ...and otherwise set as attributes + } else { + this.attr( match, context[ match ] ); + } + } + } + + return this; + + // HANDLE: $(#id) + } else { + elem = document.getElementById( match[2] ); + + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE and Opera return items + // by name instead of ID + if ( elem.id !== match[2] ) { + return rootjQuery.find( selector ); + } + + // Otherwise, we inject the element directly into the jQuery object + this.length = 1; + this[0] = elem; + } + + this.context = document; + this.selector = selector; + return this; + } + + // HANDLE: $(expr, $(...)) + } else if ( !context || context.jquery ) { + return ( context || rootjQuery ).find( selector ); + + // HANDLE: $(expr, context) + // (which is just equivalent to: $(context).find(expr) + } else { + return this.constructor( context ).find( selector ); + } + + // HANDLE: $(DOMElement) + } else if ( selector.nodeType ) { + this.context = this[0] = selector; + this.length = 1; + return this; + + // HANDLE: $(function) + // Shortcut for document ready + } else if ( jQuery.isFunction( selector ) ) { + return rootjQuery.ready( selector ); + } + + if ( selector.selector !== undefined ) { + this.selector = selector.selector; + this.context = selector.context; + } + + return jQuery.makeArray( selector, this ); + }, + + // Start with an empty selector + selector: "", + + // The default length of a jQuery object is 0 + length: 0, + + // The number of elements contained in the matched element set + size: function() { + return this.length; + }, + + toArray: function() { + return core_slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num == null ? + // Return a 'clean' array + this.toArray() : + // Return just the object + ( num < 0 ? this[ this.length + num ] : this[ num ] ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + ret.context = this.context; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + // (You can seed the arguments with an array of args, but this is + // only used internally.) + each: function( callback, args ) { + return jQuery.each( this, callback, args ); + }, + + ready: function( fn ) { + // Add the callback + jQuery.ready.promise().done( fn ); + + return this; + }, + + slice: function() { + return this.pushStack( core_slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( - 1 ); + }, + + eq: function( i ) { + var len = this.length, + j = + i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map(this, function( elem, i ) { + return callback.call( elem, i, elem ); + })); + }, + + end: function() { + return this.prevObject || this.constructor(null); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: core_push, + sort: [].sort, + splice: [].splice + }; + + // Give the init function the jQuery prototype for later instantiation + jQuery.fn.init.prototype = jQuery.fn; + + jQuery.extend = jQuery.fn.extend = function() { + var src, copyIsArray, copy, name, options, clone, + target = arguments[0] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + target = arguments[1] || {}; + // skip the boolean and the target + i = 2; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction(target) ) { + target = {}; + } + + // extend jQuery itself if only one argument is passed + if ( length === i ) { + target = this; + --i; + } + + for ( ; i < length; i++ ) { + // Only deal with non-null/undefined values + if ( (options = arguments[ i ]) != null ) { + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray(src) ? src : []; + + } else { + clone = src && jQuery.isPlainObject(src) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; + }; + + jQuery.extend({ + noConflict: function( deep ) { + if ( window.$ === jQuery ) { + window.$ = _$; + } + + if ( deep && window.jQuery === jQuery ) { + window.jQuery = _jQuery; + } + + return jQuery; + }, + + // Is the DOM ready to be used? Set to true once it occurs. + isReady: false, + + // A counter to track how many items to wait for before + // the ready event fires. See #6781 + readyWait: 1, + + // Hold (or release) the ready event + holdReady: function( hold ) { + if ( hold ) { + jQuery.readyWait++; + } else { + jQuery.ready( true ); + } + }, + + // Handle when the DOM is ready + ready: function( wait ) { + + // Abort if there are pending holds or we're already ready + if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { + return; + } + + // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). + if ( !document.body ) { + return setTimeout( jQuery.ready ); + } + + // Remember that the DOM is ready + jQuery.isReady = true; + + // If a normal DOM Ready event fired, decrement, and wait if need be + if ( wait !== true && --jQuery.readyWait > 0 ) { + return; + } + + // If there are functions bound, to execute + readyList.resolveWith( document, [ jQuery ] ); + + // Trigger any bound ready events + if ( jQuery.fn.trigger ) { + jQuery( document ).trigger("ready").off("ready"); + } + }, + + // See test/unit/core.js for details concerning isFunction. + // Since version 1.3, DOM methods and functions like alert + // aren't supported. They return false on IE (#2968). + isFunction: function( obj ) { + return jQuery.type(obj) === "function"; + }, + + isArray: Array.isArray || function( obj ) { + return jQuery.type(obj) === "array"; + }, + + isWindow: function( obj ) { + return obj != null && obj == obj.window; + }, + + isNumeric: function( obj ) { + return !isNaN( parseFloat(obj) ) && isFinite( obj ); + }, + + type: function( obj ) { + if ( obj == null ) { + return String( obj ); + } + return typeof obj === "object" || typeof obj === "function" ? + class2type[ core_toString.call(obj) ] || "object" : + typeof obj; + }, + + isPlainObject: function( obj ) { + // Must be an Object. + // Because of IE, we also have to check the presence of the constructor property. + // Make sure that DOM nodes and window objects don't pass through, as well + if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { + return false; + } + + try { + // Not own constructor property must be Object + if ( obj.constructor && + !core_hasOwn.call(obj, "constructor") && + !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { + return false; + } + } catch ( e ) { + // IE8,9 Will throw exceptions on certain host objects #9897 + return false; + } + + // Own properties are enumerated firstly, so to speed up, + // if last one is own, then all properties are own. + + var key; + for ( key in obj ) {} + + return key === undefined || core_hasOwn.call( obj, key ); + }, + + isEmptyObject: function( obj ) { + var name; + for ( name in obj ) { + return false; + } + return true; + }, + + error: function( msg ) { + throw new Error( msg ); + }, + + // data: string of html + // context (optional): If specified, the fragment will be created in this context, defaults to document + // keepScripts (optional): If true, will include scripts passed in the html string + parseHTML: function( data, context, keepScripts ) { + if ( !data || typeof data !== "string" ) { + return null; + } + if ( typeof context === "boolean" ) { + keepScripts = context; + context = false; + } + context = context || document; + + var parsed = rsingleTag.exec( data ), + scripts = !keepScripts && []; + + // Single tag + if ( parsed ) { + return [ context.createElement( parsed[1] ) ]; + } + + parsed = jQuery.buildFragment( [ data ], context, scripts ); + if ( scripts ) { + jQuery( scripts ).remove(); + } + return jQuery.merge( [], parsed.childNodes ); + }, + + parseJSON: function( data ) { + // Attempt to parse using the native JSON parser first + if ( window.JSON && window.JSON.parse ) { + return window.JSON.parse( data ); + } + + if ( data === null ) { + return data; + } + + if ( typeof data === "string" ) { + + // Make sure leading/trailing whitespace is removed (IE can't handle it) + data = jQuery.trim( data ); + + if ( data ) { + // Make sure the incoming data is actual JSON + // Logic borrowed from http://json.org/json2.js + if ( rvalidchars.test( data.replace( rvalidescape, "@" ) + .replace( rvalidtokens, "]" ) + .replace( rvalidbraces, "")) ) { + + return ( new Function( "return " + data ) )(); + } + } + } + + jQuery.error( "Invalid JSON: " + data ); + }, + + // Cross-browser xml parsing + parseXML: function( data ) { + var xml, tmp; + if ( !data || typeof data !== "string" ) { + return null; + } + try { + if ( window.DOMParser ) { + // Standard + tmp = new DOMParser(); + xml = tmp.parseFromString( data , "text/xml" ); + } else { + // IE + xml = new ActiveXObject( "Microsoft.XMLDOM" ); + xml.async = "false"; + xml.loadXML( data ); + } + } catch ( e ) { + xml = undefined; + } + if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { + jQuery.error( "Invalid XML: " + data ); + } + return xml; + }, + + noop: function() {}, + + // Evaluates a script in a global context + // Workarounds based on findings by Jim Driscoll + // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context + globalEval: function( data ) { + if ( data && jQuery.trim( data ) ) { + // We use execScript on Internet Explorer + // We use an anonymous function so that context is window + // rather than jQuery in Firefox + ( window.execScript || function( data ) { + window[ "eval" ].call( window, data ); + })( data ); + } + }, + + // Convert dashed to camelCase; used by the css and data modules + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + // args is for internal usage only + each: function( obj, callback, args ) { + var value, + i = 0, + length = obj.length, + isArray = isArraylike( obj ); + + if ( args ) { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.apply( obj[ i ], args ); + + if ( value === false ) { + break; + } + } + } + + // A special, fast, case for the most common use of each + } else { + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } else { + for ( i in obj ) { + value = callback.call( obj[ i ], i, obj[ i ] ); + + if ( value === false ) { + break; + } + } + } + } + + return obj; + }, + + // Use native String.trim function wherever possible + trim: core_trim && !core_trim.call("\uFEFF\xA0") ? + function( text ) { + return text == null ? + "" : + core_trim.call( text ); + } + : + // Otherwise use our own trimming functionality + function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArraylike( Object(arr) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + core_push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + var len; + + if ( arr ) { + if ( core_indexOf ) { + return core_indexOf.call( arr, elem, i ); + } + + len = arr.length; + i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; + + for ( ; i < len; i++ ) { + // Skip accessing in sparse arrays + if ( i in arr && arr[ i ] === elem ) { + return i; + } + } + } + + return - 1; + }, + + merge: function( first, second ) { + var l = second.length, + i = first.length, + j = 0; + + if ( typeof l === "number" ) { + for ( ; j < l; j++ ) { + first[ i++ ] = second[ j ]; + } + } else { + while ( second[j] !== undefined ) { + first[ i++ ] = second[ j++ ]; + } + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, inv ) { + var retVal, + ret = [], + i = 0, + length = elems.length; + inv = !!inv; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + retVal = !!callback( elems[ i ], i ); + if ( inv !== retVal ) { + ret.push( elems[ i ] ); + } + } + + return ret; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var value, + i = 0, + length = elems.length, + isArray = isArraylike( elems ), + ret = []; + + // Go through the array, translating each of the items to their + if ( isArray ) { + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret[ ret.length ] = value; + } + } + } + + // Flatten any nested arrays + return core_concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var args, proxy, tmp; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = core_slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( core_slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + // Multifunctional method to get and set values of a collection + // The value/s can optionally be executed if it's a function + access: function( elems, fn, key, value, chainable, emptyGet, raw ) { + var i = 0, + length = elems.length, + bulk = key == null; + + // Sets many values + if ( jQuery.type( key ) === "object" ) { + chainable = true; + for ( i in key ) { + jQuery.access( elems, fn, i, key[i], true, emptyGet, raw ); + } + + // Sets one value + } else if ( value !== undefined ) { + chainable = true; + + if ( !jQuery.isFunction( value ) ) { + raw = true; + } + + if ( bulk ) { + // Bulk operations run against the entire set + if ( raw ) { + fn.call( elems, value ); + fn = null; + + // ...except when executing function values + } else { + bulk = fn; + fn = function( elem, key, value ) { + return bulk.call( jQuery( elem ), value ); + }; + } + } + + if ( fn ) { + for ( ; i < length; i++ ) { + fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) ); + } + } + } + + return chainable ? + elems : + // Gets + bulk ? + fn.call( elems ) : + length ? fn( elems[0], key ) : emptyGet; + }, + + now: function() { + return ( new Date() ).getTime(); + } + }); + + jQuery.ready.promise = function( obj ) { + if ( !readyList ) { + + readyList = jQuery.Deferred(); + + // Catch cases where $(document).ready() is called after the browser event has already occurred. + // we once tried to use readyState "interactive" here, but it caused issues like the one + // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 + if ( document.readyState === "complete" ) { + // Handle it asynchronously to allow scripts the opportunity to delay ready + setTimeout( jQuery.ready ); + + // Standards-based browsers support DOMContentLoaded + } else if ( document.addEventListener ) { + // Use the handy event callback + document.addEventListener( "DOMContentLoaded", completed, false ); + + // A fallback to window.onload, that will always work + window.addEventListener( "load", completed, false ); + + // If IE event model is used + } else { + // Ensure firing before onload, maybe late but safe also for iframes + document.attachEvent( "onreadystatechange", completed ); + + // A fallback to window.onload, that will always work + window.attachEvent( "onload", completed ); + + // If IE and not a frame + // continually check to see if the document is ready + var top = false; + + try { + top = window.frameElement == null && document.documentElement; + } catch (e) {} + + if ( top && top.doScroll ) { + (function doScrollCheck() { + if ( !jQuery.isReady ) { + + try { + // Use the trick by Diego Perini + // http://javascript.nwbox.com/IEContentLoaded/ + top.doScroll("left"); + } catch (e) { + return setTimeout( doScrollCheck, 50 ); + } + + // detach all dom ready events + detach(); + + // and execute any waiting functions + jQuery.ready(); + } + })(); + } + } + } + return readyList.promise( obj ); + }; + + // Populate the class2type map + jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + }); + + function isArraylike( obj ) { + var length = obj.length, + type = jQuery.type( obj ); + + if ( jQuery.isWindow( obj ) ) { + return false; + } + + if ( obj.nodeType === 1 && length ) { + return true; + } + + return type === "array" || type !== "function" && + ( length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj ); + } + + // All jQuery objects should point back to these + rootjQuery = jQuery(document); + // String to Object options format cache + var optionsCache = {}; + + // Convert String-formatted options into Object-formatted ones and store in cache + function createOptions( options ) { + var object = optionsCache[ options ] = {}; + jQuery.each( options.match( core_rnotwhite ) || [], function( _, flag ) { + object[ flag ] = true; + }); + return object; + } + + /* + * Create a callback list using the following parameters: + * + * options: an optional list of space-separated options that will change how + * the callback list behaves or a more traditional option object + * + * By default a callback list will act like an event callback list and can be + * "fired" multiple times. + * + * Possible options: + * + * once: will ensure the callback list can only be fired once (like a Deferred) + * + * memory: will keep track of previous values and will call any callback added + * after the list has been fired right away with the latest "memorized" + * values (like a Deferred) + * + * unique: will ensure a callback can only be added once (no duplicate in the list) + * + * stopOnFalse: interrupt callings when a callback returns false + * + */ + jQuery.Callbacks = function( options ) { + + // Convert options from String-formatted to Object-formatted if needed + // (we check in cache first) + options = typeof options === "string" ? + ( optionsCache[ options ] || createOptions( options ) ) : + jQuery.extend( {}, options ); + + var // Flag to know if list is currently firing + firing, + // Last fire value (for non-forgettable lists) + memory, + // Flag to know if list was already fired + fired, + // End of the loop when firing + firingLength, + // Index of currently firing callback (modified by remove if needed) + firingIndex, + // First callback to fire (used internally by add and fireWith) + firingStart, + // Actual callback list + list = [], + // Stack of fire calls for repeatable lists + stack = !options.once && [], + // Fire callbacks + fire = function( data ) { + memory = options.memory && data; + fired = true; + firingIndex = firingStart || 0; + firingStart = 0; + firingLength = list.length; + firing = true; + for ( ; list && firingIndex < firingLength; firingIndex++ ) { + if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { + memory = false; // To prevent further calls using add + break; + } + } + firing = false; + if ( list ) { + if ( stack ) { + if ( stack.length ) { + fire( stack.shift() ); + } + } else if ( memory ) { + list = []; + } else { + self.disable(); + } + } + }, + // Actual Callbacks object + self = { + // Add a callback or a collection of callbacks to the list + add: function() { + if ( list ) { + // First, we save the current length + var start = list.length; + (function add( args ) { + jQuery.each( args, function( _, arg ) { + var type = jQuery.type( arg ); + if ( type === "function" ) { + if ( !options.unique || !self.has( arg ) ) { + list.push( arg ); + } + } else if ( arg && arg.length && type !== "string" ) { + // Inspect recursively + add( arg ); + } + }); + })( arguments ); + // Do we need to add the callbacks to the + // current firing batch? + if ( firing ) { + firingLength = list.length; + // With memory, if we're not firing then + // we should call right away + } else if ( memory ) { + firingStart = start; + fire( memory ); + } + } + return this; + }, + // Remove a callback from the list + remove: function() { + if ( list ) { + jQuery.each( arguments, function( _, arg ) { + var index; + while ( ( index = jQuery.inArray( arg, list, index ) ) > - 1 ) { + list.splice( index, 1 ); + // Handle firing indexes + if ( firing ) { + if ( index <= firingLength ) { + firingLength--; + } + if ( index <= firingIndex ) { + firingIndex--; + } + } + } + }); + } + return this; + }, + // Check if a given callback is in the list. + // If no argument is given, return whether or not list has callbacks attached. + has: function( fn ) { + return fn ? jQuery.inArray( fn, list ) > - 1 : !!( list && list.length ); + }, + // Remove all callbacks from the list + empty: function() { + list = []; + return this; + }, + // Have the list do nothing anymore + disable: function() { + list = stack = memory = undefined; + return this; + }, + // Is it disabled? + disabled: function() { + return !list; + }, + // Lock the list in its current state + lock: function() { + stack = undefined; + if ( !memory ) { + self.disable(); + } + return this; + }, + // Is it locked? + locked: function() { + return !stack; + }, + // Call all callbacks with the given context and arguments + fireWith: function( context, args ) { + args = args || []; + args = [ context, args.slice ? args.slice() : args ]; + if ( list && ( !fired || stack ) ) { + if ( firing ) { + stack.push( args ); + } else { + fire( args ); + } + } + return this; + }, + // Call all the callbacks with the given arguments + fire: function() { + self.fireWith( this, arguments ); + return this; + }, + // To know if the callbacks have already been called at least once + fired: function() { + return !!fired; + } + }; + + return self; + }; + jQuery.extend({ + + Deferred: function( func ) { + var tuples = [ + // action, add listener, listener list, final state + [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], + [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], + [ "notify", "progress", jQuery.Callbacks("memory") ] + ], + state = "pending", + promise = { + state: function() { + return state; + }, + always: function() { + deferred.done( arguments ).fail( arguments ); + return this; + }, + then: function( /* fnDone, fnFail, fnProgress */ + ) { + var fns = arguments; + return jQuery.Deferred(function( newDefer ) { + jQuery.each( tuples, function( i, tuple ) { + var action = tuple[ 0 ], + fn = jQuery.isFunction( fns[ i ] ) && fns[ i ]; + // deferred[ done | fail | progress ] for forwarding actions to newDefer + deferred[ tuple[1] ](function() { + var returned = fn && fn.apply( this, arguments ); + if ( returned && jQuery.isFunction( returned.promise ) ) { + returned.promise() + .done( newDefer.resolve ) + .fail( newDefer.reject ) + .progress( newDefer.notify ); + } else { + newDefer[ action + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments ); + } + }); + }); + fns = null; + }).promise(); + }, + // Get a promise for this deferred + // If obj is provided, the promise aspect is added to the object + promise: function( obj ) { + return obj != null ? jQuery.extend( obj, promise ) : promise; + } + }, + deferred = {}; + + // Keep pipe for back-compat + promise.pipe = promise.then; + + // Add list-specific methods + jQuery.each( tuples, function( i, tuple ) { + var list = tuple[ 2 ], + stateString = tuple[ 3 ]; + + // promise[ done | fail | progress ] = list.add + promise[ tuple[1] ] = list.add; + + // Handle state + if ( stateString ) { + list.add(function() { + // state = [ resolved | rejected ] + state = stateString; + + // [ reject_list | resolve_list ].disable; progress_list.lock + }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); + } + + // deferred[ resolve | reject | notify ] + deferred[ tuple[0] ] = function() { + deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments ); + return this; + }; + deferred[ tuple[0] + "With" ] = list.fireWith; + }); + + // Make the deferred a promise + promise.promise( deferred ); + + // Call given func if any + if ( func ) { + func.call( deferred, deferred ); + } + + // All done! + return deferred; + }, + + // Deferred helper + when: function( subordinate /* , ..., subordinateN */ + ) { + var i = 0, + resolveValues = core_slice.call( arguments ), + length = resolveValues.length, + // the count of uncompleted subordinates + remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, + // the master Deferred. If resolveValues consist of only a single Deferred, just use that. + deferred = remaining === 1 ? subordinate : jQuery.Deferred(), + // Update function for both resolve and progress values + updateFunc = function( i, contexts, values ) { + return function( value ) { + contexts[ i ] = this; + values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; + if ( values === progressValues ) { + deferred.notifyWith( contexts, values ); + } else if ( !( --remaining ) ) { + deferred.resolveWith( contexts, values ); + } + }; + }, + progressValues, progressContexts, resolveContexts; + + // add listeners to Deferred subordinates; treat others as resolved + if ( length > 1 ) { + progressValues = new Array( length ); + progressContexts = new Array( length ); + resolveContexts = new Array( length ); + for ( ; i < length; i++ ) { + if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { + resolveValues[ i ].promise() + .done( updateFunc( i, resolveContexts, resolveValues ) ) + .fail( deferred.reject ) + .progress( updateFunc( i, progressContexts, progressValues ) ); + } else { + --remaining; + } + } + } + + // if we're not waiting on anything, resolve the master + if ( !remaining ) { + deferred.resolveWith( resolveContexts, resolveValues ); + } + + return deferred.promise(); + } + }); + jQuery.support = (function() { + + var support, all, a, + input, select, fragment, + opt, eventName, isSupported, i, + div = document.createElement("div"); + + // Setup + div.setAttribute( "className", "t" ); + div.innerHTML = "
a"; + + // Support tests won't run in some limited or non-browser environments + all = div.getElementsByTagName("*"); + a = div.getElementsByTagName("a")[ 0 ]; + if ( !all || !a || !all.length ) { + return {}; + } + + // First batch of tests + select = document.createElement("select"); + opt = select.appendChild( document.createElement("option") ); + input = div.getElementsByTagName("input")[ 0 ]; + + a.style.cssText = "top:1px;float:left;opacity:.5"; + support = { + // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) + getSetAttribute: div.className !== "t", + + // IE strips leading whitespace when .innerHTML is used + leadingWhitespace: div.firstChild.nodeType === 3, + + // Make sure that tbody elements aren't automatically inserted + // IE will insert them into empty tables + tbody: !div.getElementsByTagName("tbody").length, + + // Make sure that link elements get serialized correctly by innerHTML + // This requires a wrapper element in IE + htmlSerialize: !!div.getElementsByTagName("link").length, + + // Get the style information from getAttribute + // (IE uses .cssText instead) + style: /top/.test( a.getAttribute("style") ), + + // Make sure that URLs aren't manipulated + // (IE normalizes it by default) + hrefNormalized: a.getAttribute("href") === "/a", + + // Make sure that element opacity exists + // (IE uses filter instead) + // Use a regex to work around a WebKit issue. See #5145 + opacity: /^0.5/.test( a.style.opacity ), + + // Verify style float existence + // (IE uses styleFloat instead of cssFloat) + cssFloat: !!a.style.cssFloat, + + // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere) + checkOn: !!input.value, + + // Make sure that a selected-by-default option has a working selected property. + // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) + optSelected: opt.selected, + + // Tests for enctype support on a form (#6743) + enctype: !!document.createElement("form").enctype, + + // Makes sure cloning an html5 element does not cause problems + // Where outerHTML is undefined, this still works + html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", + + // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode + boxModel: document.compatMode === "CSS1Compat", + + // Will be defined later + deleteExpando: true, + noCloneEvent: true, + inlineBlockNeedsLayout: false, + shrinkWrapBlocks: false, + reliableMarginRight: true, + boxSizingReliable: true, + pixelPosition: false + }; + + // Make sure checked status is properly cloned + input.checked = true; + support.noCloneChecked = input.cloneNode( true ).checked; + + // Make sure that the options inside disabled selects aren't marked as disabled + // (WebKit marks them as disabled) + select.disabled = true; + support.optDisabled = !opt.disabled; + + // Support: IE<9 + try { + delete div.test; + } catch ( e ) { + support.deleteExpando = false; + } + + // Check if we can trust getAttribute("value") + input = document.createElement("input"); + input.setAttribute( "value", "" ); + support.input = input.getAttribute( "value" ) === ""; + + // Check if an input maintains its value after becoming a radio + input.value = "t"; + input.setAttribute( "type", "radio" ); + support.radioValue = input.value === "t"; + + // #11217 - WebKit loses check when the name is after the checked attribute + input.setAttribute( "checked", "t" ); + input.setAttribute( "name", "t" ); + + fragment = document.createDocumentFragment(); + fragment.appendChild( input ); + + // Check if a disconnected checkbox will retain its checked + // value of true after appended to the DOM (IE6/7) + support.appendChecked = input.checked; + + // WebKit doesn't clone checked state correctly in fragments + support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; + + // Support: IE<9 + // Opera does not clone events (and typeof div.attachEvent === undefined). + // IE9-10 clones events bound via attachEvent, but they don't trigger with .click() + if ( div.attachEvent ) { + div.attachEvent( "onclick", function() { + support.noCloneEvent = false; + }); + + div.cloneNode( true ).click(); + } + + // Support: IE<9 (lack submit/change bubble), Firefox 17+ (lack focusin event) + // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP), test/csp.php + for ( i in { + submit: true, + change: true, + focusin: true + }) { + div.setAttribute( eventName = "on" + i, "t" ); + + support[ i + "Bubbles" ] = eventName in window || div.attributes[ eventName ].expando === false; + } + + div.style.backgroundClip = "content-box"; + div.cloneNode( true ).style.backgroundClip = ""; + support.clearCloneStyle = div.style.backgroundClip === "content-box"; + + // Run tests that need a body at doc ready + jQuery(function() { + var container, marginDiv, tds, + divReset = "padding:0;margin:0;border:0;display:block;box-sizing:content-box;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;", + body = document.getElementsByTagName("body")[0]; + + if ( !body ) { + // Return for frameset docs that don't have a body + return; + } + + container = document.createElement("div"); + container.style.cssText = "border:0;width:0;height:0;position:absolute;top:0;left:-9999px;margin-top:1px"; + + body.appendChild( container ).appendChild( div ); + + // Support: IE8 + // Check if table cells still have offsetWidth/Height when they are set + // to display:none and there are still other visible table cells in a + // table row; if so, offsetWidth/Height are not reliable for use when + // determining if an element has been hidden directly using + // display:none (it is still safe to use offsets if a parent element is + // hidden; don safety goggles and see bug #4512 for more information). + div.innerHTML = "
t
"; + tds = div.getElementsByTagName("td"); + tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; + isSupported = ( tds[ 0 ].offsetHeight === 0 ); + + tds[ 0 ].style.display = ""; + tds[ 1 ].style.display = "none"; + + // Support: IE8 + // Check if empty table cells still have offsetWidth/Height + support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); + + // Check box-sizing and margin behavior + div.innerHTML = ""; + div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; + support.boxSizing = ( div.offsetWidth === 4 ); + support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 ); + + // Use window.getComputedStyle because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + support.pixelPosition = ( window.getComputedStyle( div, null ) || {}).top !== "1%"; + support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { + width: "4px" + }).width === "4px"; + + // Check if div with explicit width and no margin-right incorrectly + // gets computed margin-right based on width of container. (#3333) + // Fails in WebKit before Feb 2011 nightlies + // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right + marginDiv = div.appendChild( document.createElement("div") ); + marginDiv.style.cssText = div.style.cssText = divReset; + marginDiv.style.marginRight = marginDiv.style.width = "0"; + div.style.width = "1px"; + + support.reliableMarginRight = + !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {}).marginRight ); + } + + if ( typeof div.style.zoom !== core_strundefined ) { + // Support: IE<8 + // Check if natively block-level elements act like inline-block + // elements when setting their display to 'inline' and giving + // them layout + div.innerHTML = ""; + div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; + support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); + + // Support: IE6 + // Check if elements with layout shrink-wrap their children + div.style.display = "block"; + div.innerHTML = "
"; + div.firstChild.style.width = "5px"; + support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); + + if ( support.inlineBlockNeedsLayout ) { + // Prevent IE 6 from affecting layout for positioned elements #11048 + // Prevent IE from shrinking the body in IE 7 mode #12869 + // Support: IE<8 + body.style.zoom = 1; + } + } + + body.removeChild( container ); + + // Null elements to avoid leaks in IE + container = div = tds = marginDiv = null; + }); + + // Null elements to avoid leaks in IE + all = select = fragment = opt = a = input = null; + + return support; + })(); + + var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, + rmultiDash = /([A-Z])/g; + + function internalData( elem, name, data, pvt /* Internal Use Only */ + ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var thisCache, ret, + internalKey = jQuery.expando, + getByName = typeof name === "string", + // We have to handle DOM nodes and JS objects differently because IE6-7 + // can't GC object references properly across the DOM-JS boundary + isNode = elem.nodeType, + // Only DOM nodes need the global jQuery cache; JS object data is + // attached directly to the object so GC can occur automatically + cache = isNode ? jQuery.cache : elem, + // Only defining an ID for JS objects if its cache already exists allows + // the code to shortcut on the same path as a DOM node with no cache + id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; + + // Avoid doing any more work than we need to when trying to get data on an + // object that has no data at all + if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) { + return; + } + + if ( !id ) { + // Only DOM nodes need a new unique ID for each element since their data + // ends up in the global cache + if ( isNode ) { + elem[ internalKey ] = id = core_deletedIds.pop() || jQuery.guid++; + } else { + id = internalKey; + } + } + + if ( !cache[ id ] ) { + cache[ id ] = {}; + + // Avoids exposing jQuery metadata on plain JS objects when the object + // is serialized using JSON.stringify + if ( !isNode ) { + cache[ id ].toJSON = jQuery.noop; + } + } + + // An object can be passed to jQuery.data instead of a key/value pair; this gets + // shallow copied over onto the existing cache + if ( typeof name === "object" || typeof name === "function" ) { + if ( pvt ) { + cache[ id ] = jQuery.extend( cache[ id ], name ); + } else { + cache[ id ].data = jQuery.extend( cache[ id ].data, name ); + } + } + + thisCache = cache[ id ]; + + // jQuery data() is stored in a separate object inside the object's internal data + // cache in order to avoid key collisions between internal data and user-defined + // data. + if ( !pvt ) { + if ( !thisCache.data ) { + thisCache.data = {}; + } + + thisCache = thisCache.data; + } + + if ( data !== undefined ) { + thisCache[ jQuery.camelCase( name ) ] = data; + } + + // Check for both converted-to-camel and non-converted data property names + // If a data property was specified + if ( getByName ) { + + // First Try to find as-is property data + ret = thisCache[ name ]; + + // Test for null|undefined property data + if ( ret == null ) { + + // Try to find the camelCased property + ret = thisCache[ jQuery.camelCase( name ) ]; + } + } else { + ret = thisCache; + } + + return ret; + } + + function internalRemoveData( elem, name, pvt ) { + if ( !jQuery.acceptData( elem ) ) { + return; + } + + var i, l, thisCache, + isNode = elem.nodeType, + // See jQuery.data for more information + cache = isNode ? jQuery.cache : elem, + id = isNode ? elem[ jQuery.expando ] : jQuery.expando; + + // If there is already no cache entry for this object, there is no + // purpose in continuing + if ( !cache[ id ] ) { + return; + } + + if ( name ) { + + thisCache = pvt ? cache[ id ] : cache[ id ].data; + + if ( thisCache ) { + + // Support array or space separated string names for data keys + if ( !jQuery.isArray( name ) ) { + + // try the string as a key before any manipulation + if ( name in thisCache ) { + name = [ name ]; + } else { + + // split the camel cased version by spaces unless a key with the spaces exists + name = jQuery.camelCase( name ); + if ( name in thisCache ) { + name = [ name ]; + } else { + name = name.split(" "); + } + } + } else { + // If "name" is an array of keys... + // When data is initially created, via ("key", "val") signature, + // keys will be converted to camelCase. + // Since there is no way to tell _how_ a key was added, remove + // both plain key and camelCase key. #12786 + // This will only penalize the array argument path. + name = name.concat( jQuery.map( name, jQuery.camelCase ) ); + } + + for ( i = 0, l = name.length; i < l; i++ ) { + delete thisCache[ name[i] ]; + } + + // If there is no data left in the cache, we want to continue + // and let the cache object itself get destroyed + if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { + return; + } + } + } + + // See jQuery.data for more information + if ( !pvt ) { + delete cache[ id ].data; + + // Don't destroy the parent cache unless the internal data object + // had been the only thing left in it + if ( !isEmptyDataObject( cache[ id ] ) ) { + return; + } + } + + // Destroy the cache + if ( isNode ) { + jQuery.cleanData( [ elem ], true ); + + // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) + } else if ( jQuery.support.deleteExpando || cache != cache.window ) { + delete cache[ id ]; + + // When all else fails, null + } else { + cache[ id ] = null; + } + } + + jQuery.extend({ + cache: {}, + + // Unique for each copy of jQuery on the page + // Non-digits removed to match rinlinejQuery + expando: "jQuery" + ( core_version + Math.random() ).replace( /\D/g, "" ), + + // The following elements throw uncatchable exceptions if you + // attempt to add expando properties to them. + noData: { + "embed": true, + // Ban all objects except for Flash (which handle expandos) + "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", + "applet": true + }, + + hasData: function( elem ) { + elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; + return !!elem && !isEmptyDataObject( elem ); + }, + + data: function( elem, name, data ) { + return internalData( elem, name, data ); + }, + + removeData: function( elem, name ) { + return internalRemoveData( elem, name ); + }, + + // For internal use only. + _data: function( elem, name, data ) { + return internalData( elem, name, data, true ); + }, + + _removeData: function( elem, name ) { + return internalRemoveData( elem, name, true ); + }, + + // A method for determining if a DOM node can handle the data expando + acceptData: function( elem ) { + // Do not set data on non-element because it will not be cleared (#8335). + if ( elem.nodeType && elem.nodeType !== 1 && elem.nodeType !== 9 ) { + return false; + } + + var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; + + // nodes accept data unless otherwise specified; rejection can be conditional + return !noData || noData !== true && elem.getAttribute("classid") === noData; + } + }); + + jQuery.fn.extend({ + data: function( key, value ) { + var attrs, name, + elem = this[0], + i = 0, + data = null; + + // Gets all values + if ( key === undefined ) { + if ( this.length ) { + data = jQuery.data( elem ); + + if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { + attrs = elem.attributes; + for ( ; i < attrs.length; i++ ) { + name = attrs[i].name; + + if ( !name.indexOf( "data-" ) ) { + name = jQuery.camelCase( name.slice(5) ); + + dataAttr( elem, name, data[ name ] ); + } + } + jQuery._data( elem, "parsedAttrs", true ); + } + } + + return data; + } + + // Sets multiple values + if ( typeof key === "object" ) { + return this.each(function() { + jQuery.data( this, key ); + }); + } + + return jQuery.access( this, function( value ) { + + if ( value === undefined ) { + // Try to fetch any internally stored data first + return elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : null; + } + + this.each(function() { + jQuery.data( this, key, value ); + }); + }, null, value, arguments.length > 1, null, true ); + }, + + removeData: function( key ) { + return this.each(function() { + jQuery.removeData( this, key ); + }); + } + }); + + function dataAttr( elem, key, data ) { + // If nothing was found internally, try to fetch any + // data from the HTML5 data-* attribute + if ( data === undefined && elem.nodeType === 1 ) { + + var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); + + data = elem.getAttribute( name ); + + if ( typeof data === "string" ) { + try { + data = data === "true" ? true : + data === "false" ? false : + data === "null" ? null : + // Only convert to a number if it doesn't change the string + + data + "" === data ? + data : + rbrace.test( data ) ? jQuery.parseJSON( data ) : + data; + } catch ( e ) {} + + // Make sure we set the data so it isn't changed later + jQuery.data( elem, key, data ); + + } else { + data = undefined; + } + } + + return data; + } + + // checks a cache object for emptiness + function isEmptyDataObject( obj ) { + var name; + for ( name in obj ) { + + // if the public data object is empty, the private is still empty + if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { + continue; + } + if ( name !== "toJSON" ) { + return false; + } + } + + return true; + } + jQuery.extend({ + queue: function( elem, type, data ) { + var queue; + + if ( elem ) { + type = ( type || "fx" ) + "queue"; + queue = jQuery._data( elem, type ); + + // Speed up dequeue by getting out quickly if this is just a lookup + if ( data ) { + if ( !queue || jQuery.isArray(data) ) { + queue = jQuery._data( elem, type, jQuery.makeArray(data) ); + } else { + queue.push( data ); + } + } + return queue || []; + } + }, + + dequeue: function( elem, type ) { + type = type || "fx"; + + var queue = jQuery.queue( elem, type ), + startLength = queue.length, + fn = queue.shift(), + hooks = jQuery._queueHooks( elem, type ), + next = function() { + jQuery.dequeue( elem, type ); + }; + + // If the fx queue is dequeued, always remove the progress sentinel + if ( fn === "inprogress" ) { + fn = queue.shift(); + startLength--; + } + + hooks.cur = fn; + if ( fn ) { + + // Add a progress sentinel to prevent the fx queue from being + // automatically dequeued + if ( type === "fx" ) { + queue.unshift( "inprogress" ); + } + + // clear up the last queue stop function + delete hooks.stop; + fn.call( elem, next, hooks ); + } + + if ( !startLength && hooks ) { + hooks.empty.fire(); + } + }, + + // not intended for public consumption - generates a queueHooks object, or returns the current one + _queueHooks: function( elem, type ) { + var key = type + "queueHooks"; + return jQuery._data( elem, key ) || jQuery._data( elem, key, { + empty: jQuery.Callbacks("once memory").add(function() { + jQuery._removeData( elem, type + "queue" ); + jQuery._removeData( elem, key ); + }) + }); + } + }); + + jQuery.fn.extend({ + queue: function( type, data ) { + var setter = 2; + + if ( typeof type !== "string" ) { + data = type; + type = "fx"; + setter--; + } + + if ( arguments.length < setter ) { + return jQuery.queue( this[0], type ); + } + + return data === undefined ? + this : + this.each(function() { + var queue = jQuery.queue( this, type, data ); + + // ensure a hooks for this queue + jQuery._queueHooks( this, type ); + + if ( type === "fx" && queue[0] !== "inprogress" ) { + jQuery.dequeue( this, type ); + } + }); + }, + dequeue: function( type ) { + return this.each(function() { + jQuery.dequeue( this, type ); + }); + }, + // Based off of the plugin by Clint Helfers, with permission. + // http://blindsignals.com/index.php/2009/07/jquery-delay/ + delay: function( time, type ) { + time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; + type = type || "fx"; + + return this.queue( type, function( next, hooks ) { + var timeout = setTimeout( next, time ); + hooks.stop = function() { + clearTimeout( timeout ); + }; + }); + }, + clearQueue: function( type ) { + return this.queue( type || "fx", [] ); + }, + // Get a promise resolved when queues of a certain type + // are emptied (fx is the type by default) + promise: function( type, obj ) { + var tmp, + count = 1, + defer = jQuery.Deferred(), + elements = this, + i = this.length, + resolve = function() { + if ( !( --count ) ) { + defer.resolveWith( elements, [ elements ] ); + } + }; + + if ( typeof type !== "string" ) { + obj = type; + type = undefined; + } + type = type || "fx"; + + while ( i-- ) { + tmp = jQuery._data( elements[ i ], type + "queueHooks" ); + if ( tmp && tmp.empty ) { + count++; + tmp.empty.add( resolve ); + } + } + resolve(); + return defer.promise( obj ); + } + }); + var nodeHook, boolHook, + rclass = /[\t\r\n]/g, + rreturn = /\r/g, + rfocusable = /^(?:input|select|textarea|button|object)$/i, + rclickable = /^(?:a|area)$/i, + rboolean = /^(?:checked|selected|autofocus|autoplay|async|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped)$/i, + ruseDefault = /^(?:checked|selected)$/i, + getSetAttribute = jQuery.support.getSetAttribute, + getSetInput = jQuery.support.input; + + jQuery.fn.extend({ + attr: function( name, value ) { + return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); + }, + + removeAttr: function( name ) { + return this.each(function() { + jQuery.removeAttr( this, name ); + }); + }, + + prop: function( name, value ) { + return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); + }, + + removeProp: function( name ) { + name = jQuery.propFix[ name ] || name; + return this.each(function() { + // try/catch handles cases where IE balks (such as removing a property on window) + try { + this[ name ] = undefined; + delete this[ name ]; + } catch ( e ) {} + }); + }, + + addClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).addClass( value.call( this, j, this.className ) ); + }); + } + + if ( proceed ) { + // The disjunction here is for better compressibility (see removeClass) + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + " " + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + if ( cur.indexOf( " " + clazz + " " ) < 0 ) { + cur += clazz + " "; + } + } + elem.className = jQuery.trim( cur ); + + } + } + } + + return this; + }, + + removeClass: function( value ) { + var classes, elem, cur, clazz, j, + i = 0, + len = this.length, + proceed = arguments.length === 0 || typeof value === "string" && value; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( j ) { + jQuery( this ).removeClass( value.call( this, j, this.className ) ); + }); + } + if ( proceed ) { + classes = ( value || "" ).match( core_rnotwhite ) || []; + + for ( ; i < len; i++ ) { + elem = this[ i ]; + // This expression is here for better compressibility (see addClass) + cur = elem.nodeType === 1 && ( elem.className ? + ( " " + elem.className + " " ).replace( rclass, " " ) : + "" + ); + + if ( cur ) { + j = 0; + while ( (clazz = classes[j++]) ) { + // Remove *all* instances + while ( cur.indexOf( " " + clazz + " " ) >= 0 ) { + cur = cur.replace( " " + clazz + " ", " " ); + } + } + elem.className = value ? jQuery.trim( cur ) : ""; + } + } + } + + return this; + }, + + toggleClass: function( value, stateVal ) { + var type = typeof value, + isBool = typeof stateVal === "boolean"; + + if ( jQuery.isFunction( value ) ) { + return this.each(function( i ) { + jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); + }); + } + + return this.each(function() { + if ( type === "string" ) { + // toggle individual class names + var className, + i = 0, + self = jQuery( this ), + state = stateVal, + classNames = value.match( core_rnotwhite ) || []; + + while ( (className = classNames[ i++ ]) ) { + // check each className given, space separated list + state = isBool ? state : !self.hasClass( className ); + self[ state ? "addClass" : "removeClass" ]( className ); + } + + // Toggle whole class name + } else if ( type === core_strundefined || type === "boolean" ) { + if ( this.className ) { + // store className if set + jQuery._data( this, "__className__", this.className ); + } + + // If the element has a class name or if we're passed "false", + // then remove the whole classname (if there was one, the above saved it). + // Otherwise bring back whatever was previously saved (if anything), + // falling back to the empty string if nothing was stored. + this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; + } + }); + }, + + hasClass: function( selector ) { + var className = " " + selector + " ", + i = 0, + l = this.length; + for ( ; i < l; i++ ) { + if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { + return true; + } + } + + return false; + }, + + val: function( value ) { + var ret, hooks, isFunction, + elem = this[0]; + + if ( !arguments.length ) { + if ( elem ) { + hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; + + if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { + return ret; + } + + ret = elem.value; + + return typeof ret === "string" ? + // handle most common string cases + ret.replace(rreturn, "") : + // handle cases where value is null/undef or number + ret == null ? "" : ret; + } + + return; + } + + isFunction = jQuery.isFunction( value ); + + return this.each(function( i ) { + var val, + self = jQuery(this); + + if ( this.nodeType !== 1 ) { + return; + } + + if ( isFunction ) { + val = value.call( this, i, self.val() ); + } else { + val = value; + } + + // Treat null/undefined as ""; convert numbers to string + if ( val == null ) { + val = ""; + } else if ( typeof val === "number" ) { + val += ""; + } else if ( jQuery.isArray( val ) ) { + val = jQuery.map(val, function ( value ) { + return value == null ? "" : value + ""; + }); + } + + hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; + + // If set returns undefined, fall back to normal setting + if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { + this.value = val; + } + }); + } + }); + + jQuery.extend({ + valHooks: { + option: { + get: function( elem ) { + // attributes.value is undefined in Blackberry 4.7 but + // uses .value. See #6932 + var val = elem.attributes.value; + return !val || val.specified ? elem.value : elem.text; + } + }, + select: { + get: function( elem ) { + var value, option, + options = elem.options, + index = elem.selectedIndex, + one = elem.type === "select-one" || index < 0, + values = one ? null : [], + max = one ? index + 1 : options.length, + i = index < 0 ? + max : + one ? index : 0; + + // Loop through all the selected options + for ( ; i < max; i++ ) { + option = options[ i ]; + + // oldIE doesn't update selected after form reset (#2551) + if ( ( option.selected || i === index ) && + // Don't return options that are disabled or in a disabled optgroup + ( jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) && + ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) { + + // Get the specific value for the option + value = jQuery( option ).val(); + + // We don't need an array for one selects + if ( one ) { + return value; + } + + // Multi-Selects return an array + values.push( value ); + } + } + + return values; + }, + + set: function( elem, value ) { + var values = jQuery.makeArray( value ); + + jQuery(elem).find("option").each(function() { + this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; + }); + + if ( !values.length ) { + elem.selectedIndex = - 1; + } + return values; + } + } + }, + + attr: function( elem, name, value ) { + var hooks, notxml, ret, + nType = elem.nodeType; + + // don't get/set attributes on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + // Fallback to prop when attributes are not supported + if ( typeof elem.getAttribute === core_strundefined ) { + return jQuery.prop( elem, name, value ); + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + // All attributes are lowercase + // Grab necessary hook if one is defined + if ( notxml ) { + name = name.toLowerCase(); + hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); + } + + if ( value !== undefined ) { + + if ( value === null ) { + jQuery.removeAttr( elem, name ); + + } else if ( hooks && notxml && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + elem.setAttribute( name, value + "" ); + return value; + } + + } else if ( hooks && notxml && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + + // In IE9+, Flash objects don't have .getAttribute (#12945) + // Support: IE9+ + if ( typeof elem.getAttribute !== core_strundefined ) { + ret = elem.getAttribute( name ); + } + + // Non-existent attributes return null, we normalize to undefined + return ret == null ? + undefined : + ret; + } + }, + + removeAttr: function( elem, value ) { + var name, propName, + i = 0, + attrNames = value && value.match( core_rnotwhite ); + + if ( attrNames && elem.nodeType === 1 ) { + while ( (name = attrNames[i++]) ) { + propName = jQuery.propFix[ name ] || name; + + // Boolean attributes get special treatment (#10870) + if ( rboolean.test( name ) ) { + // Set corresponding property to false for boolean attributes + // Also clear defaultChecked/defaultSelected (if appropriate) for IE<8 + if ( !getSetAttribute && ruseDefault.test( name ) ) { + elem[ jQuery.camelCase( "default-" + name ) ] = + elem[ propName ] = false; + } else { + elem[ propName ] = false; + } + + // See #9699 for explanation of this approach (setting first, then removal) + } else { + jQuery.attr( elem, name, "" ); + } + + elem.removeAttribute( getSetAttribute ? name : propName ); + } + } + }, + + attrHooks: { + type: { + set: function( elem, value ) { + if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { + // Setting the type on a radio button after the value resets the value in IE6-9 + // Reset value to default in case type is set after value during creation + var val = elem.value; + elem.setAttribute( "type", value ); + if ( val ) { + elem.value = val; + } + return value; + } + } + } + }, + + propFix: { + tabindex: "tabIndex", + readonly: "readOnly", + "for": "htmlFor", + "class": "className", + maxlength: "maxLength", + cellspacing: "cellSpacing", + cellpadding: "cellPadding", + rowspan: "rowSpan", + colspan: "colSpan", + usemap: "useMap", + frameborder: "frameBorder", + contenteditable: "contentEditable" + }, + + prop: function( elem, name, value ) { + var ret, hooks, notxml, + nType = elem.nodeType; + + // don't get/set properties on text, comment and attribute nodes + if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { + return; + } + + notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); + + if ( notxml ) { + // Fix name and attach hooks + name = jQuery.propFix[ name ] || name; + hooks = jQuery.propHooks[ name ]; + } + + if ( value !== undefined ) { + if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { + return ret; + + } else { + return ( elem[ name ] = value ); + } + + } else { + if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { + return ret; + + } else { + return elem[ name ]; + } + } + }, + + propHooks: { + tabIndex: { + get: function( elem ) { + // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set + // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ + var attributeNode = elem.getAttributeNode("tabindex"); + + return attributeNode && attributeNode.specified ? + parseInt( attributeNode.value, 10 ) : + rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? + 0 : + undefined; + } + } + } + }); + + // Hook for boolean attributes + boolHook = { + get: function( elem, name ) { + var + // Use .prop to determine if this attribute is understood as boolean + prop = jQuery.prop( elem, name ), + // Fetch it accordingly + attr = typeof prop === "boolean" && elem.getAttribute( name ), + detail = typeof prop === "boolean" ? + getSetInput && getSetAttribute ? + attr != null : + // oldIE fabricates an empty string for missing boolean attributes + // and conflates checked/selected into attroperties + ruseDefault.test( name ) ? + elem[ jQuery.camelCase( "default-" + name ) ] : + !!attr : + // fetch an attribute node for properties not recognized as boolean + elem.getAttributeNode( name ); + + return detail && detail.value !== false ? + name.toLowerCase() : + undefined; + }, + set: function( elem, value, name ) { + if ( value === false ) { + // Remove boolean attributes when set to false + jQuery.removeAttr( elem, name ); + } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) { + // IE<8 needs the *property* name + elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name ); + + // Use defaultChecked and defaultSelected for oldIE + } else { + elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true; + } + + return name; + } + }; + + // fix oldIE value attroperty + if ( !getSetInput || !getSetAttribute ) { + jQuery.attrHooks.value = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return jQuery.nodeName( elem, "input" ) ? + // Ignore the value *property* by using defaultValue + elem.defaultValue : + ret && ret.specified ? ret.value : undefined; + }, + set: function( elem, value, name ) { + if ( jQuery.nodeName( elem, "input" ) ) { + // Does not return so that setAttribute is also used + elem.defaultValue = value; + } else { + // Use nodeHook if defined (#1954); otherwise setAttribute is fine + return nodeHook && nodeHook.set( elem, value, name ); + } + } + }; + } + + // IE6/7 do not support getting/setting some attributes with get/setAttribute + if ( !getSetAttribute ) { + + // Use this for any attribute in IE6/7 + // This fixes almost every IE6/7 issue + nodeHook = jQuery.valHooks.button = { + get: function( elem, name ) { + var ret = elem.getAttributeNode( name ); + return ret && ( name === "id" || name === "name" || name === "coords" ? ret.value !== "" : ret.specified ) ? + ret.value : + undefined; + }, + set: function( elem, value, name ) { + // Set the existing or create a new attribute node + var ret = elem.getAttributeNode( name ); + if ( !ret ) { + elem.setAttributeNode( + (ret = elem.ownerDocument.createAttribute( name )) + ); + } + + ret.value = value += ""; + + // Break association with cloned elements by also using setAttribute (#9646) + return name === "value" || value === elem.getAttribute( name ) ? + value : + undefined; + } + }; + + // Set contenteditable to false on removals(#10429) + // Setting to empty string throws an error as an invalid value + jQuery.attrHooks.contenteditable = { + get: nodeHook.get, + set: function( elem, value, name ) { + nodeHook.set( elem, value === "" ? false : value, name ); + } + }; + + // Set width and height to auto instead of 0 on empty string( Bug #8150 ) + // This is for removals + jQuery.each([ "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + set: function( elem, value ) { + if ( value === "" ) { + elem.setAttribute( name, "auto" ); + return value; + } + } + }); + }); + } + + + // Some attributes require a special call on IE + // http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx + if ( !jQuery.support.hrefNormalized ) { + jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { + jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { + get: function( elem ) { + var ret = elem.getAttribute( name, 2 ); + return ret == null ? undefined : ret; + } + }); + }); + + // href/src property should get the full normalized URL (#10299/#12915) + jQuery.each([ "href", "src" ], function( i, name ) { + jQuery.propHooks[ name ] = { + get: function( elem ) { + return elem.getAttribute( name, 4 ); + } + }; + }); + } + + if ( !jQuery.support.style ) { + jQuery.attrHooks.style = { + get: function( elem ) { + // Return undefined in the case of empty string + // Note: IE uppercases css property names, but if we were to .toLowerCase() + // .cssText, that would destroy case senstitivity in URL's, like in "background" + return elem.style.cssText || undefined; + }, + set: function( elem, value ) { + return ( elem.style.cssText = value + "" ); + } + }; + } + + // Safari mis-reports the default selected property of an option + // Accessing the parent's selectedIndex property fixes it + if ( !jQuery.support.optSelected ) { + jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { + get: function( elem ) { + var parent = elem.parentNode; + + if ( parent ) { + parent.selectedIndex; + + // Make sure that it also works with optgroups, see #5701 + if ( parent.parentNode ) { + parent.parentNode.selectedIndex; + } + } + return null; + } + }); + } + + // IE6/7 call enctype encoding + if ( !jQuery.support.enctype ) { + jQuery.propFix.enctype = "encoding"; + } + + // Radios and checkboxes getter/setter + if ( !jQuery.support.checkOn ) { + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = { + get: function( elem ) { + // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified + return elem.getAttribute("value") === null ? "on" : elem.value; + } + }; + }); + } + jQuery.each([ "radio", "checkbox" ], function() { + jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { + set: function( elem, value ) { + if ( jQuery.isArray( value ) ) { + return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); + } + } + }); + }); + var rformElems = /^(?:input|select|textarea)$/i, + rkeyEvent = /^key/, + rmouseEvent = /^(?:mouse|contextmenu)|click/, + rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, + rtypenamespace = /^([^.]*)(?:\.(.+)|)$/; + + function returnTrue() { + return true; + } + + function returnFalse() { + return false; + } + + /* + * Helper functions for managing events -- not part of the public interface. + * Props to Dean Edwards' addEvent library for many of the ideas. + */ + jQuery.event = { + + global: {}, + + add: function( elem, types, handler, data, selector ) { + var tmp, events, t, handleObjIn, + special, eventHandle, handleObj, + handlers, type, namespaces, origType, + elemData = jQuery._data( elem ); + + // Don't attach events to noData or text/comment nodes (but allow plain objects) + if ( !elemData ) { + return; + } + + // Caller can pass in an object of custom data in lieu of the handler + if ( handler.handler ) { + handleObjIn = handler; + handler = handleObjIn.handler; + selector = handleObjIn.selector; + } + + // Make sure that the handler has a unique ID, used to find/remove it later + if ( !handler.guid ) { + handler.guid = jQuery.guid++; + } + + // Init the element's event structure and main handler, if this is the first + if ( !(events = elemData.events) ) { + events = elemData.events = {}; + } + if ( !(eventHandle = elemData.handle) ) { + eventHandle = elemData.handle = function( e ) { + // Discard the second event of a jQuery.event.trigger() and + // when an event is called after a page has unloaded + return typeof jQuery !== core_strundefined && (!e || jQuery.event.triggered !== e.type) ? + jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : + undefined; + }; + // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events + eventHandle.elem = elem; + } + + // Handle multiple events separated by a space + // jQuery(...).bind("mouseover mouseout", fn); + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // If event changes its type, use the special event handlers for the changed type + special = jQuery.event.special[ type ] || {}; + + // If selector defined, determine special event api type, otherwise given type + type = ( selector ? special.delegateType : special.bindType ) || type; + + // Update special based on newly reset type + special = jQuery.event.special[ type ] || {}; + + // handleObj is passed to all event handlers + handleObj = jQuery.extend({ + type: type, + origType: origType, + data: data, + handler: handler, + guid: handler.guid, + selector: selector, + needsContext: selector && jQuery.expr.match.needsContext.test( selector ), + namespace: namespaces.join(".") + }, handleObjIn ); + + // Init the event handler queue if we're the first + if ( !(handlers = events[ type ]) ) { + handlers = events[ type ] = []; + handlers.delegateCount = 0; + + // Only use addEventListener/attachEvent if the special events handler returns false + if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { + // Bind the global event handler to the element + if ( elem.addEventListener ) { + elem.addEventListener( type, eventHandle, false ); + + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, eventHandle ); + } + } + } + + if ( special.add ) { + special.add.call( elem, handleObj ); + + if ( !handleObj.handler.guid ) { + handleObj.handler.guid = handler.guid; + } + } + + // Add to the element's handler list, delegates in front + if ( selector ) { + handlers.splice( handlers.delegateCount++, 0, handleObj ); + } else { + handlers.push( handleObj ); + } + + // Keep track of which events have ever been used, for event optimization + jQuery.event.global[ type ] = true; + } + + // Nullify elem to prevent memory leaks in IE + elem = null; + }, + + // Detach an event or set of events from an element + remove: function( elem, types, handler, selector, mappedTypes ) { + var j, handleObj, tmp, + origCount, t, events, + special, handlers, type, + namespaces, origType, + elemData = jQuery.hasData( elem ) && jQuery._data( elem ); + + if ( !elemData || !(events = elemData.events) ) { + return; + } + + // Once for each type.namespace in types; type may be omitted + types = ( types || "" ).match( core_rnotwhite ) || [""]; + t = types.length; + while ( t-- ) { + tmp = rtypenamespace.exec( types[t] ) || []; + type = origType = tmp[1]; + namespaces = ( tmp[2] || "" ).split( "." ).sort(); + + // Unbind all events (on this namespace, if provided) for the element + if ( !type ) { + for ( type in events ) { + jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); + } + continue; + } + + special = jQuery.event.special[ type ] || {}; + type = ( selector ? special.delegateType : special.bindType ) || type; + handlers = events[ type ] || []; + tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ); + + // Remove matching events + origCount = j = handlers.length; + while ( j-- ) { + handleObj = handlers[ j ]; + + if ( ( mappedTypes || origType === handleObj.origType ) && + ( !handler || handler.guid === handleObj.guid ) && + ( !tmp || tmp.test( handleObj.namespace ) ) && + ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { + handlers.splice( j, 1 ); + + if ( handleObj.selector ) { + handlers.delegateCount--; + } + if ( special.remove ) { + special.remove.call( elem, handleObj ); + } + } + } + + // Remove generic event handler if we removed something and no more handlers exist + // (avoids potential for endless recursion during removal of special event handlers) + if ( origCount && !handlers.length ) { + if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { + jQuery.removeEvent( elem, type, elemData.handle ); + } + + delete events[ type ]; + } + } + + // Remove the expando if it's no longer used + if ( jQuery.isEmptyObject( events ) ) { + delete elemData.handle; + + // removeData also checks for emptiness and clears the expando if empty + // so use it instead of delete + jQuery._removeData( elem, "events" ); + } + }, + + trigger: function( event, data, elem, onlyHandlers ) { + var handle, ontype, cur, + bubbleType, special, tmp, i, + eventPath = [ elem || document ], + type = core_hasOwn.call( event, "type" ) ? event.type : event, + namespaces = core_hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : []; + + cur = tmp = elem = elem || document; + + // Don't do events on text and comment nodes + if ( elem.nodeType === 3 || elem.nodeType === 8 ) { + return; + } + + // focus/blur morphs to focusin/out; ensure we're not firing them right now + if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { + return; + } + + if ( type.indexOf(".") >= 0 ) { + // Namespaced trigger; create a regexp to match event type in handle() + namespaces = type.split("."); + type = namespaces.shift(); + namespaces.sort(); + } + ontype = type.indexOf(":") < 0 && "on" + type; + + // Caller can pass in a jQuery.Event object, Object, or just an event type string + event = event[ jQuery.expando ] ? + event : + new jQuery.Event( type, typeof event === "object" && event ); + + event.isTrigger = true; + event.namespace = namespaces.join("."); + event.namespace_re = event.namespace ? + new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) : + null; + + // Clean up the event in case it is being reused + event.result = undefined; + if ( !event.target ) { + event.target = elem; + } + + // Clone any incoming data and prepend the event, creating the handler arg list + data = data == null ? + [ event ] : + jQuery.makeArray( data, [ event ] ); + + // Allow special events to draw outside the lines + special = jQuery.event.special[ type ] || {}; + if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) { + return; + } + + // Determine event propagation path in advance, per W3C events spec (#9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { + + bubbleType = special.delegateType || type; + if ( !rfocusMorph.test( bubbleType + type ) ) { + cur = cur.parentNode; + } + for ( ; cur; cur = cur.parentNode ) { + eventPath.push( cur ); + tmp = cur; + } + + // Only add window if we got to document (e.g., not plain obj or detached DOM) + if ( tmp === (elem.ownerDocument || document) ) { + eventPath.push( tmp.defaultView || tmp.parentWindow || window ); + } + } + + // Fire handlers on the event path + i = 0; + while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) { + + event.type = i > 1 ? + bubbleType : + special.bindType || type; + + // jQuery handler + handle = ( jQuery._data( cur, "events" ) || {})[ event.type ] && jQuery._data( cur, "handle" ); + if ( handle ) { + handle.apply( cur, data ); + } + + // Native handler + handle = ontype && cur[ ontype ]; + if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { + event.preventDefault(); + } + } + event.type = type; + + // If nobody prevented the default action, do it now + if ( !onlyHandlers && !event.isDefaultPrevented() ) { + + if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && + !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { + + // Call a native DOM method on the target with the same name name as the event. + // Can't use an .isFunction() check here because IE6/7 fails that test. + // Don't do default actions on window, that's where global variables be (#6170) + if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) { + + // Don't re-trigger an onFOO event when we call its FOO() method + tmp = elem[ ontype ]; + + if ( tmp ) { + elem[ ontype ] = null; + } + + // Prevent re-triggering of the same event, since we already bubbled it above + jQuery.event.triggered = type; + try { + elem[ type ](); + } catch ( e ) { + // IE<9 dies on focus/blur to hidden element (#1486,#12518) + // only reproducible on winXP IE8 native, not IE9 in IE8 mode + } + jQuery.event.triggered = undefined; + + if ( tmp ) { + elem[ ontype ] = tmp; + } + } + } + } + + return event.result; + }, + + dispatch: function( event ) { + + // Make a writable jQuery.Event from the native event object + event = jQuery.event.fix( event ); + + var i, ret, handleObj, matched, j, + handlerQueue = [], + args = core_slice.call( arguments ), + handlers = ( jQuery._data( this, "events" ) || {})[ event.type ] || [], + special = jQuery.event.special[ event.type ] || {}; + + // Use the fix-ed jQuery.Event rather than the (read-only) native event + args[0] = event; + event.delegateTarget = this; + + // Call the preDispatch hook for the mapped type, and let it bail if desired + if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { + return; + } + + // Determine handlers + handlerQueue = jQuery.event.handlers.call( this, event, handlers ); + + // Run delegates first; they may want to stop propagation beneath us + i = 0; + while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) { + event.currentTarget = matched.elem; + + j = 0; + while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) { + + // Triggered event must either 1) have no namespace, or + // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). + if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) { + + event.handleObj = handleObj; + event.data = handleObj.data; + + ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) + .apply( matched.elem, args ); + + if ( ret !== undefined ) { + if ( (event.result = ret) === false ) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } + } + + // Call the postDispatch hook for the mapped type + if ( special.postDispatch ) { + special.postDispatch.call( this, event ); + } + + return event.result; + }, + + handlers: function( event, handlers ) { + var sel, handleObj, matches, i, + handlerQueue = [], + delegateCount = handlers.delegateCount, + cur = event.target; + + // Find delegate handlers + // Black-hole SVG instance trees (#13180) + // Avoid non-left-click bubbling in Firefox (#3861) + if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) { + + for ( ; cur != this; cur = cur.parentNode || this ) { + + // Don't check non-elements (#13208) + // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) { + matches = []; + for ( i = 0; i < delegateCount; i++ ) { + handleObj = handlers[ i ]; + + // Don't conflict with Object.prototype properties (#13203) + sel = handleObj.selector + " "; + + if ( matches[ sel ] === undefined ) { + matches[ sel ] = handleObj.needsContext ? + jQuery( sel, this ).index( cur ) >= 0 : + jQuery.find( sel, this, null, [ cur ] ).length; + } + if ( matches[ sel ] ) { + matches.push( handleObj ); + } + } + if ( matches.length ) { + handlerQueue.push({ + elem: cur, + handlers: matches + }); + } + } + } + } + + // Add the remaining (directly-bound) handlers + if ( delegateCount < handlers.length ) { + handlerQueue.push({ + elem: this, + handlers: handlers.slice( delegateCount ) + }); + } + + return handlerQueue; + }, + + fix: function( event ) { + if ( event[ jQuery.expando ] ) { + return event; + } + + // Create a writable copy of the event object and normalize some properties + var i, prop, copy, + type = event.type, + originalEvent = event, + fixHook = this.fixHooks[ type ]; + + if ( !fixHook ) { + this.fixHooks[ type ] = fixHook = + rmouseEvent.test( type ) ? this.mouseHooks : + rkeyEvent.test( type ) ? this.keyHooks : + {}; + } + copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; + + event = new jQuery.Event( originalEvent ); + + i = copy.length; + while ( i-- ) { + prop = copy[ i ]; + event[ prop ] = originalEvent[ prop ]; + } + + // Support: IE<9 + // Fix target property (#1925) + if ( !event.target ) { + event.target = originalEvent.srcElement || document; + } + + // Support: Chrome 23+, Safari? + // Target should not be a text node (#504, #13143) + if ( event.target.nodeType === 3 ) { + event.target = event.target.parentNode; + } + + // Support: IE<9 + // For mouse/key events, metaKey==false if it's undefined (#3368, #11328) + event.metaKey = !!event.metaKey; + + return fixHook.filter ? fixHook.filter( event, originalEvent ) : event; + }, + + // Includes some event props shared by KeyEvent and MouseEvent + 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( event, original ) { + + // Add which for key events + if ( event.which == null ) { + event.which = original.charCode != null ? original.charCode : original.keyCode; + } + + return event; + } + }, + + mouseHooks: { + props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), + filter: function( event, original ) { + var body, eventDoc, doc, + button = original.button, + fromElement = original.fromElement; + + // Calculate pageX/Y if missing and clientX/Y available + if ( event.pageX == null && original.clientX != null ) { + eventDoc = event.target.ownerDocument || document; + doc = eventDoc.documentElement; + body = eventDoc.body; + + event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); + event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); + } + + // Add relatedTarget, if necessary + if ( !event.relatedTarget && fromElement ) { + event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; + } + + // Add which for click: 1 === left; 2 === middle; 3 === right + // Note: button is not normalized, so don't use it + if ( !event.which && button !== undefined ) { + event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); + } + + return event; + } + }, + + special: { + load: { + // Prevent triggered image.load events from bubbling to window.load + noBubble: true + }, + click: { + // For checkbox, fire native event so checked state will be right + trigger: function() { + if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) { + this.click(); + return false; + } + } + }, + focus: { + // Fire native event if possible so blur/focus sequence is correct + trigger: function() { + if ( this !== document.activeElement && this.focus ) { + try { + this.focus(); + return false; + } catch ( e ) { + // Support: IE<9 + // If we error on focus to hidden element (#1486, #12518), + // let .trigger() run the handlers + } + } + }, + delegateType: "focusin" + }, + blur: { + trigger: function() { + if ( this === document.activeElement && this.blur ) { + this.blur(); + return false; + } + }, + delegateType: "focusout" + }, + + beforeunload: { + postDispatch: function( event ) { + + // Even when returnValue equals to undefined Firefox will still show alert + if ( event.result !== undefined ) { + event.originalEvent.returnValue = event.result; + } + } + } + }, + + simulate: function( type, elem, event, bubble ) { + // Piggyback on a donor event to simulate a different one. + // Fake originalEvent to avoid donor's stopPropagation, but if the + // simulated event prevents default then we do the same on the donor. + var e = jQuery.extend( + new jQuery.Event(), + event, + { + type: type, + isSimulated: true, + originalEvent: {} + }); + if ( bubble ) { + jQuery.event.trigger( e, null, elem ); + } else { + jQuery.event.dispatch.call( elem, e ); + } + if ( e.isDefaultPrevented() ) { + event.preventDefault(); + } + } + }; + + jQuery.removeEvent = document.removeEventListener ? + function( elem, type, handle ) { + if ( elem.removeEventListener ) { + elem.removeEventListener( type, handle, false ); + } + } : + function( elem, type, handle ) { + var name = "on" + type; + + if ( elem.detachEvent ) { + + // #8545, #7054, preventing memory leaks for custom events in IE6-8 + // detachEvent needed property on element, by name of that event, to properly expose it to GC + if ( typeof elem[ name ] === core_strundefined ) { + elem[ name ] = null; + } + + elem.detachEvent( name, handle ); + } + }; + + jQuery.Event = function( src, props ) { + // Allow instantiation without the 'new' keyword + if ( !(this instanceof jQuery.Event) ) { + return new jQuery.Event( src, props ); + } + + // Event object + if ( src && src.type ) { + this.originalEvent = src; + this.type = src.type; + + // Events bubbling up the document may have been marked as prevented + // by a handler lower down the tree; reflect the correct value. + this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || + src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; + + // Event type + } else { + this.type = src; + } + + // Put explicitly provided properties onto the event object + if ( props ) { + jQuery.extend( this, props ); + } + + // Create a timestamp if incoming event doesn't have one + this.timeStamp = src && src.timeStamp || jQuery.now(); + + // Mark it as fixed + this[ jQuery.expando ] = true; + }; + + // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding + // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html + jQuery.Event.prototype = { + isDefaultPrevented: returnFalse, + isPropagationStopped: returnFalse, + isImmediatePropagationStopped: returnFalse, + + preventDefault: function() { + var e = this.originalEvent; + + this.isDefaultPrevented = returnTrue; + if ( !e ) { + return; + } + + // If preventDefault exists, run it on the original event + if ( e.preventDefault ) { + e.preventDefault(); + + // Support: IE + // Otherwise set the returnValue property of the original event to false + } else { + e.returnValue = false; + } + }, + stopPropagation: function() { + var e = this.originalEvent; + + this.isPropagationStopped = returnTrue; + if ( !e ) { + return; + } + // If stopPropagation exists, run it on the original event + if ( e.stopPropagation ) { + e.stopPropagation(); + } + + // Support: IE + // Set the cancelBubble property of the original event to true + e.cancelBubble = true; + }, + stopImmediatePropagation: function() { + this.isImmediatePropagationStopped = returnTrue; + this.stopPropagation(); + } + }; + + // Create mouseenter/leave events using mouseover/out and event-time checks + jQuery.each({ + mouseenter: "mouseover", + mouseleave: "mouseout" + }, function( orig, fix ) { + jQuery.event.special[ orig ] = { + delegateType: fix, + bindType: fix, + + handle: function( event ) { + var ret, + target = this, + related = event.relatedTarget, + handleObj = event.handleObj; + + // For mousenter/leave call the handler if related is outside the target. + // NB: No relatedTarget if the mouse left/entered the browser window + if ( !related || (related !== target && !jQuery.contains( target, related )) ) { + event.type = handleObj.origType; + ret = handleObj.handler.apply( this, arguments ); + event.type = fix; + } + return ret; + } + }; + }); + + // IE submit delegation + if ( !jQuery.support.submitBubbles ) { + + jQuery.event.special.submit = { + setup: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Lazy-add a submit handler when a descendant form may potentially be submitted + jQuery.event.add( this, "click._submit keypress._submit", function( e ) { + // Node name check avoids a VML-related crash in IE (#9807) + var elem = e.target, + form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; + if ( form && !jQuery._data( form, "submitBubbles" ) ) { + jQuery.event.add( form, "submit._submit", function( event ) { + event._submit_bubble = true; + }); + jQuery._data( form, "submitBubbles", true ); + } + }); + // return undefined since we don't need an event listener + }, + + postDispatch: function( event ) { + // If form was submitted by the user, bubble the event up the tree + if ( event._submit_bubble ) { + delete event._submit_bubble; + if ( this.parentNode && !event.isTrigger ) { + jQuery.event.simulate( "submit", this.parentNode, event, true ); + } + } + }, + + teardown: function() { + // Only need this for delegated form submit events + if ( jQuery.nodeName( this, "form" ) ) { + return false; + } + + // Remove delegated handlers; cleanData eventually reaps submit handlers attached above + jQuery.event.remove( this, "._submit" ); + } + }; + } + + // IE change delegation and checkbox/radio fix + if ( !jQuery.support.changeBubbles ) { + + jQuery.event.special.change = { + + setup: function() { + + if ( rformElems.test( this.nodeName ) ) { + // IE doesn't fire change on a check/radio until blur; trigger it on click + // after a propertychange. Eat the blur-change in special.change.handle. + // This still fires onchange a second time for check/radio after blur. + if ( this.type === "checkbox" || this.type === "radio" ) { + jQuery.event.add( this, "propertychange._change", function( event ) { + if ( event.originalEvent.propertyName === "checked" ) { + this._just_changed = true; + } + }); + jQuery.event.add( this, "click._change", function( event ) { + if ( this._just_changed && !event.isTrigger ) { + this._just_changed = false; + } + // Allow triggered, simulated change events (#11500) + jQuery.event.simulate( "change", this, event, true ); + }); + } + return false; + } + // Delegated event; lazy-add a change handler on descendant inputs + jQuery.event.add( this, "beforeactivate._change", function( e ) { + var elem = e.target; + + if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) { + jQuery.event.add( elem, "change._change", function( event ) { + if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { + jQuery.event.simulate( "change", this.parentNode, event, true ); + } + }); + jQuery._data( elem, "changeBubbles", true ); + } + }); + }, + + handle: function( event ) { + var elem = event.target; + + // Swallow native change events from checkbox/radio, we already triggered them above + if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { + return event.handleObj.handler.apply( this, arguments ); + } + }, + + teardown: function() { + jQuery.event.remove( this, "._change" ); + + return !rformElems.test( this.nodeName ); + } + }; + } + + // Create "bubbling" focus and blur events + if ( !jQuery.support.focusinBubbles ) { + jQuery.each({ + focus: "focusin", + blur: "focusout" + }, function( orig, fix ) { + + // Attach a single capturing handler while someone wants focusin/focusout + var attaches = 0, + handler = function( event ) { + jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); + }; + + jQuery.event.special[ fix ] = { + setup: function() { + if ( attaches++ === 0 ) { + document.addEventListener( orig, handler, true ); + } + }, + teardown: function() { + if ( --attaches === 0 ) { + document.removeEventListener( orig, handler, true ); + } + } + }; + }); + } + + jQuery.fn.extend({ + + on: function( types, selector, data, fn, /*INTERNAL*/ + one ) { + var type, origFn; + + // Types can be a map of types/handlers + if ( typeof types === "object" ) { + // ( types-Object, selector, data ) + if ( typeof selector !== "string" ) { + // ( types-Object, data ) + data = data || selector; + selector = undefined; + } + for ( type in types ) { + this.on( type, selector, data, types[ type ], one ); + } + return this; + } + + if ( data == null && fn == null ) { + // ( types, fn ) + fn = selector; + data = selector = undefined; + } else if ( fn == null ) { + if ( typeof selector === "string" ) { + // ( types, selector, fn ) + fn = data; + data = undefined; + } else { + // ( types, data, fn ) + fn = data; + data = selector; + selector = undefined; + } + } + if ( fn === false ) { + fn = returnFalse; + } else if ( !fn ) { + return this; + } + + if ( one === 1 ) { + origFn = fn; + fn = function( event ) { + // Can use an empty set, since event contains the info + jQuery().off( event ); + return origFn.apply( this, arguments ); + }; + // Use same guid so caller can remove using origFn + fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); + } + return this.each( function() { + jQuery.event.add( this, types, fn, data, selector ); + }); + }, + one: function( types, selector, data, fn ) { + return this.on( types, selector, data, fn, 1 ); + }, + off: function( types, selector, fn ) { + var handleObj, type; + if ( types && types.preventDefault && types.handleObj ) { + // ( event ) dispatched jQuery.Event + handleObj = types.handleObj; + jQuery( types.delegateTarget ).off( + handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, + handleObj.selector, + handleObj.handler + ); + return this; + } + if ( typeof types === "object" ) { + // ( types-object [, selector] ) + for ( type in types ) { + this.off( type, selector, types[ type ] ); + } + return this; + } + if ( selector === false || typeof selector === "function" ) { + // ( types [, fn] ) + fn = selector; + selector = undefined; + } + if ( fn === false ) { + fn = returnFalse; + } + return this.each(function() { + jQuery.event.remove( this, types, fn, selector ); + }); + }, + + bind: function( types, data, fn ) { + return this.on( types, null, data, fn ); + }, + unbind: function( types, fn ) { + return this.off( types, null, fn ); + }, + + delegate: function( selector, types, data, fn ) { + return this.on( types, selector, data, fn ); + }, + undelegate: function( selector, types, fn ) { + // ( namespace ) or ( selector, types [, fn] ) + return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); + }, + + trigger: function( type, data ) { + return this.each(function() { + jQuery.event.trigger( type, data, this ); + }); + }, + triggerHandler: function( type, data ) { + var elem = this[0]; + if ( elem ) { + return jQuery.event.trigger( type, data, elem, true ); + } + } + }); + /*! + * Sizzle CSS Selector Engine + * Copyright 2012 jQuery Foundation and other contributors + * Released under the MIT license + * http://sizzlejs.com/ + */ + (function( window, undefined ) { + + var i, + cachedruns, + Expr, + getText, + isXML, + compile, + hasDuplicate, + outermostContext, + // Local document vars + setDocument, + document, + docElem, + documentIsXML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + sortOrder, + // Instance-specific data + expando = "sizzle" + - (new Date()), + preferredDoc = window.document, + support = {}, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + // General-purpose constants + strundefined = typeof undefined, + MAX_NEGATIVE = 1 << 31, + // Array methods + arr = [], + pop = arr.pop, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf if we can't use a native one + indexOf = arr.indexOf || function( elem ) { + var i = 0, + len = this.length; + for ( ; i < len; i++ ) { + if ( this[i] === elem ) { + return i; + } + } + return - 1; + }, + + // Regular expressions + + // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + // http://www.w3.org/TR/css3-syntax/#characters + characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+", + // Loosely modeled on CSS identifier characters + // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors + // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = characterEncoding.replace( "w", "w#" ), + // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors + operators = "([*^$|!~]?=)", + attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + + "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", + // Prefer arguments quoted, + // then not containing pseudos/brackets, + // then attribute selectors/non-parenthetical expressions, + // then anything else + // These preferences are here to reduce the number of selectors + // needing tokenize in the PSEUDO preFilter + pseudos = ":(" + characterEncoding + ")(?:\\(((['\"])((?:\\\\.|[^\\\\])*?)\\3|((?:\\\\.|[^\\\\()[\\]]|" + attributes.replace( 3, 8 ) + ")*)|.*)\\)|)", + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + matchExpr = { + "ID": new RegExp( "^#(" + characterEncoding + ")" ), + "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), + "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), + "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + rsibling = /[\x20\t\r\n\f]*[+~]/, + rnative = /^[^{]+\{\s*\[native code/, + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + rescape = /'|\\/g, + rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, + // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = /\\([\da-fA-F]{1,6}[\x20\t\r\n\f]?|.)/g, + funescape = function( _, escaped ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + return high !== high ? + escaped : + // BMP codepoint + high < 0 ? + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }; + + // Use a stripped-down slice if we can't use a native one + try { + slice.call( preferredDoc.documentElement.childNodes, 0 )[0].nodeType; + } catch ( e ) { + slice = function( i ) { + var elem, + results = []; + while ( (elem = this[i++]) ) { + results.push( elem ); + } + return results; + }; + } + + /** + * For feature detection + * @param {Function} fn The function to test for native support + */ + function isNative( fn ) { + return rnative.test( fn + "" ); + } + + /** + * Create key-value caches of limited size + * @returns {Function(string, Object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ + function createCache() { + var cache, + keys = []; + + return (cache = function( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key += " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key ] = value); + }); + } + + /** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ + function markFunction( fn ) { + fn[ expando ] = true; + return fn; + } + + /** + * Support testing using an element + * @param {Function} fn Passed the created div and expects a boolean result + */ + function assert( fn ) { + var div = document.createElement("div"); + + try { + return fn( div ); + } catch (e) { + return false; + } finally { + // release memory in IE + div = null; + } + } + + function Sizzle( selector, context, results, seed ) { + var match, elem, m, nodeType, + // QSA vars + i, groups, old, nid, newContext, newSelector; + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + + context = context || document; + results = results || []; + + if ( !selector || typeof selector !== "string" ) { + return results; + } + + if ( (nodeType = context.nodeType) !== 1 && nodeType !== 9 ) { + return []; + } + + if ( !documentIsXML && !seed ) { + + // Shortcuts + if ( (match = rquickExpr.exec( selector )) ) { + // Speed-up: Sizzle("#ID") + if ( (m = match[1]) ) { + if ( nodeType === 9 ) { + elem = context.getElementById( m ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + if ( elem && elem.parentNode ) { + // Handle the case where IE, Opera, and Webkit return items + // by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + } else { + // Context is not a document + if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && + contains( context, elem ) && elem.id === m ) { + results.push( elem ); + return results; + } + } + + // Speed-up: Sizzle("TAG") + } else if ( match[2] ) { + push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); + return results; + + // Speed-up: Sizzle(".CLASS") + } else if ( (m = match[3]) && support.getByClassName && context.getElementsByClassName ) { + push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); + return results; + } + } + + // QSA path + if ( support.qsa && !rbuggyQSA.test(selector) ) { + old = true; + nid = expando; + newContext = context; + newSelector = nodeType === 9 && selector; + + // qSA works strangely on Element-rooted queries + // We can work around this by specifying an extra ID on the root + // and working up from there (Thanks to Andrew Dupont for the technique) + // IE 8 doesn't work on object elements + if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { + groups = tokenize( selector ); + + if ( (old = context.getAttribute("id")) ) { + nid = old.replace( rescape, "\\$&" ); + } else { + context.setAttribute( "id", nid ); + } + nid = "[id='" + nid + "'] "; + + i = groups.length; + while ( i-- ) { + groups[i] = nid + toSelector( groups[i] ); + } + newContext = rsibling.test( selector ) && context.parentNode || context; + newSelector = groups.join(","); + } + + if ( newSelector ) { + try { + push.apply( results, slice.call( newContext.querySelectorAll( + newSelector + ), 0 ) ); + return results; + } catch (qsaError) {} finally { + if ( !old ) { + context.removeAttribute("id"); + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); + } + + /** + * Detect xml + * @param {Element|Object} elem An element or a document + */ + isXML = Sizzle.isXML = function( elem ) { + // documentElement is verified for cases where it doesn't yet exist + // (such as loading iframes in IE - #4833) + var documentElement = elem && (elem.ownerDocument || elem).documentElement; + return documentElement ? documentElement.nodeName !== "HTML" : false; + }; + + /** + * Sets document-related variables once based on the current document + * @param {Element|Object} [doc] An element or document object to use to set the document + * @returns {Object} Returns the current document + */ + setDocument = Sizzle.setDocument = function( node ) { + var doc = node ? node.ownerDocument || node : preferredDoc; + + // If no document and documentElement is available, return + if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) { + return document; + } + + // Set our document + document = doc; + docElem = doc.documentElement; + + // Support tests + documentIsXML = isXML( doc ); + + // Check if getElementsByTagName("*") returns only elements + support.tagNameNoComments = assert(function( div ) { + div.appendChild( doc.createComment("") ); + return !div.getElementsByTagName("*").length; + }); + + // Check if attributes should be retrieved by attribute nodes + support.attributes = assert(function( div ) { + div.innerHTML = ""; + var type = typeof div.lastChild.getAttribute("multiple"); + // IE8 returns a string for some attributes even when not present + return type !== "boolean" && type !== "string"; + }); + + // Check if getElementsByClassName can be trusted + support.getByClassName = assert(function( div ) { + // Opera can't find a second classname (in 9.6) + div.innerHTML = ""; + if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { + return false; + } + + // Safari 3.2 caches class attributes and doesn't catch changes + div.lastChild.className = "e"; + return div.getElementsByClassName("e").length === 2; + }); + + // Check if getElementById returns elements by name + // Check if getElementsByName privileges form controls or returns elements by ID + support.getByName = assert(function( div ) { + // Inject content + div.id = expando + 0; + div.innerHTML = "
"; + docElem.insertBefore( div, docElem.firstChild ); + + // Test + var pass = doc.getElementsByName && + // buggy browsers will return fewer than the correct 2 + doc.getElementsByName( expando ).length === 2 + + // buggy browsers will return more than the correct 0 + doc.getElementsByName( expando + 0 ).length; + support.getIdNotName = !doc.getElementById( expando ); + + // Cleanup + docElem.removeChild( div ); + + return pass; + }); + + // IE6/7 return modified attributes + Expr.attrHandle = assert(function( div ) { + div.innerHTML = ""; + return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && + div.firstChild.getAttribute("href") === "#"; + }) ? + {} : + { + "href": function( elem ) { + return elem.getAttribute( "href", 2 ); + }, + "type": function( elem ) { + return elem.getAttribute("type"); + } + }; + + // ID find and filter + if ( support.getIdNotName ) { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && !documentIsXML ) { + var m = context.getElementById( id ); + // Check parentNode to catch when Blackberry 4.6 returns + // nodes that are no longer in the document #6963 + return m && m.parentNode ? [m] : []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + return elem.getAttribute("id") === attrId; + }; + }; + } else { + Expr.find["ID"] = function( id, context ) { + if ( typeof context.getElementById !== strundefined && !documentIsXML ) { + var m = context.getElementById( id ); + + return m ? + m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? + [m] : + undefined : + []; + } + }; + Expr.filter["ID"] = function( id ) { + var attrId = id.replace( runescape, funescape ); + return function( elem ) { + var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); + return node && node.value === attrId; + }; + }; + } + + // Tag + Expr.find["TAG"] = support.tagNameNoComments ? + function( tag, context ) { + if ( typeof context.getElementsByTagName !== strundefined ) { + return context.getElementsByTagName( tag ); + } + } : + function( tag, context ) { + var elem, + tmp = [], + i = 0, + results = context.getElementsByTagName( tag ); + + // Filter out possible comments + if ( tag === "*" ) { + while ( (elem = results[i++]) ) { + if ( elem.nodeType === 1 ) { + tmp.push( elem ); + } + } + + return tmp; + } + return results; + }; + + // Name + Expr.find["NAME"] = support.getByName && function( tag, context ) { + if ( typeof context.getElementsByName !== strundefined ) { + return context.getElementsByName( name ); + } + }; + + // Class + Expr.find["CLASS"] = support.getByClassName && function( className, context ) { + if ( typeof context.getElementsByClassName !== strundefined && !documentIsXML ) { + return context.getElementsByClassName( className ); + } + }; + + // QSA and matchesSelector support + + // matchesSelector(:active) reports false when true (IE9/Opera 11.5) + rbuggyMatches = []; + + // qSa(:focus) reports false when true (Chrome 21), + // no need to also add to buggyMatches since matches checks buggyQSA + // A support test would require too much code (would include document ready) + rbuggyQSA = [ ":focus" ]; + + if ( (support.qsa = isNative(doc.querySelectorAll)) ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert(function( div ) { + // Select is set to empty string on purpose + // This is to test IE's treatment of not explictly + // setting a boolean content attribute, + // since its presence should be enough + // http://bugs.jquery.com/ticket/12359 + div.innerHTML = ""; + + // IE8 - Some boolean attributes are not treated correctly + if ( !div.querySelectorAll("[selected]").length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); + } + + // Webkit/Opera - :checked should return selected option elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":checked").length ) { + rbuggyQSA.push(":checked"); + } + }); + + assert(function( div ) { + + // Opera 10-12/IE8 - ^= $= *= and empty values + // Should not select anything + div.innerHTML = ""; + if ( div.querySelectorAll("[i^='']").length ) { + rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); + } + + // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) + // IE8 throws error here and will not see later tests + if ( !div.querySelectorAll(":enabled").length ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Opera 10-11 does not throw on post-comma invalid pseudos + div.querySelectorAll("*,:x"); + rbuggyQSA.push(",.*:"); + }); + } + + if ( (support.matchesSelector = isNative( (matches = docElem.matchesSelector || + docElem.mozMatchesSelector || + docElem.webkitMatchesSelector || + docElem.oMatchesSelector || + docElem.msMatchesSelector) )) ) { + + assert(function( div ) { + // Check to see if it's possible to do matchesSelector + // on a disconnected node (IE 9) + support.disconnectedMatch = matches.call( div, "div" ); + + // This should fail with an exception + // Gecko does not error, returns false instead + matches.call( div, "[s!='']:x" ); + rbuggyMatches.push( "!=", pseudos ); + }); + } + + rbuggyQSA = new RegExp( rbuggyQSA.join("|") ); + rbuggyMatches = new RegExp( rbuggyMatches.join("|") ); + + // Element contains another + // Purposefully does not implement inclusive descendent + // As in, an element does not contain itself + contains = isNative(docElem.contains) || docElem.compareDocumentPosition ? + function( a, b ) { + var adown = a.nodeType === 9 ? a.documentElement : a, + bup = b && b.parentNode; + return a === bup || !!( bup && bup.nodeType === 1 && ( + adown.contains ? + adown.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + )); + } : + function( a, b ) { + if ( b ) { + while ( (b = b.parentNode) ) { + if ( b === a ) { + return true; + } + } + } + return false; + }; + + // Document order sorting + sortOrder = docElem.compareDocumentPosition ? + function( a, b ) { + var compare; + + if ( a === b ) { + hasDuplicate = true; + return 0; + } + + if ( (compare = b.compareDocumentPosition && a.compareDocumentPosition && a.compareDocumentPosition( b )) ) { + if ( compare & 1 || a.parentNode && a.parentNode.nodeType === 11 ) { + if ( a === doc || contains( preferredDoc, a ) ) { + return - 1; + } + if ( b === doc || contains( preferredDoc, b ) ) { + return 1; + } + return 0; + } + return compare & 4 ? - 1 : 1; + } + + return a.compareDocumentPosition ? - 1 : 1; + } : + function( a, b ) { + var cur, + i = 0, + aup = a.parentNode, + bup = b.parentNode, + ap = [ a ], + bp = [ b ]; + + // Exit early if the nodes are identical + if ( a === b ) { + hasDuplicate = true; + return 0; + + // Parentless nodes are either documents or disconnected + } else if ( !aup || !bup ) { + return a === doc ? - 1 : + b === doc ? 1 : + aup ? - 1 : + bup ? 1 : + 0; + + // If the nodes are siblings, we can do a quick check + } else if ( aup === bup ) { + return siblingCheck( a, b ); + } + + // Otherwise we need full lists of their ancestors for comparison + cur = a; + while ( (cur = cur.parentNode) ) { + ap.unshift( cur ); + } + cur = b; + while ( (cur = cur.parentNode) ) { + bp.unshift( cur ); + } + + // Walk down the tree looking for a discrepancy + while ( ap[i] === bp[i] ) { + i++; + } + + return i ? + // Do a sibling check if the nodes have a common ancestor + siblingCheck( ap[i], bp[i] ) : + // Otherwise nodes in our document sort first + ap[i] === preferredDoc ? - 1 : + bp[i] === preferredDoc ? 1 : + 0; + }; + + // Always assume the presence of duplicates if sort doesn't + // pass them to our comparison function (as in Google Chrome). + hasDuplicate = false; + [0, 0].sort( sortOrder ); + support.detectDuplicates = hasDuplicate; + + return document; + }; + + Sizzle.matches = function( expr, elements ) { + return Sizzle( expr, null, null, elements ); + }; + + Sizzle.matchesSelector = function( elem, expr ) { + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + // Make sure that attribute selectors are quoted + expr = expr.replace( rattributeQuotes, "='$1']" ); + + // rbuggyQSA always contains :focus, so no need for an existence check + if ( support.matchesSelector && !documentIsXML && (!rbuggyMatches || !rbuggyMatches.test(expr)) && !rbuggyQSA.test(expr) ) { + try { + var ret = matches.call( elem, expr ); + + // IE 9's matchesSelector returns false on disconnected nodes + if ( ret || support.disconnectedMatch || + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { + return ret; + } + } catch (e) {} + } + + return Sizzle( expr, document, null, [elem] ).length > 0; + }; + + Sizzle.contains = function( context, elem ) { + // Set document vars if needed + if ( ( context.ownerDocument || context ) !== document ) { + setDocument( context ); + } + return contains( context, elem ); + }; + + Sizzle.attr = function( elem, name ) { + var val; + + // Set document vars if needed + if ( ( elem.ownerDocument || elem ) !== document ) { + setDocument( elem ); + } + + if ( !documentIsXML ) { + name = name.toLowerCase(); + } + if ( (val = Expr.attrHandle[ name ]) ) { + return val( elem ); + } + if ( documentIsXML || support.attributes ) { + return elem.getAttribute( name ); + } + return ( (val = elem.getAttributeNode( name )) || elem.getAttribute( name ) ) && elem[ name ] === true ? + name : + val && val.specified ? val.value : null; + }; + + Sizzle.error = function( msg ) { + throw new Error( "Syntax error, unrecognized expression: " + msg ); + }; + + // Document sorting and removing duplicates + Sizzle.uniqueSort = function( results ) { + var elem, + duplicates = [], + i = 1, + j = 0; + + // Unless we *know* we can detect duplicates, assume their presence + hasDuplicate = !support.detectDuplicates; + results.sort( sortOrder ); + + if ( hasDuplicate ) { + for ( ; (elem = results[i]); i++ ) { + if ( elem === results[ i - 1 ] ) { + j = duplicates.push( i ); + } + } + while ( j-- ) { + results.splice( duplicates[ j ], 1 ); + } + } + + return results; + }; + + function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && ( ~b.sourceIndex || MAX_NEGATIVE ) - ( ~a.sourceIndex || MAX_NEGATIVE ); + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return - 1; + } + } + } + + return a ? 1 : - 1; + } + + // Returns a function to use in pseudos for input types + function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; + } + + // Returns a function to use in pseudos for buttons + function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; + } + + // Returns a function to use in pseudos for positionals + function createPositionalPseudo( fn ) { + return markFunction(function( argument ) { + argument = + argument; + return markFunction(function( seed, matches ) { + var j, + matchIndexes = fn( [], seed.length, argument ), + i = matchIndexes.length; + + // Match elements found at the specified indexes + while ( i-- ) { + if ( seed[ (j = matchIndexes[i]) ] ) { + seed[j] = !(matches[j] = seed[j]); + } + } + }); + }); + } + + /** + * Utility function for retrieving the text value of an array of DOM nodes + * @param {Array|Element} elem + */ + getText = Sizzle.getText = function( elem ) { + var node, + ret = "", + i = 0, + nodeType = elem.nodeType; + + if ( !nodeType ) { + // If no nodeType, this is expected to be an array + for ( ; (node = elem[i]); i++ ) { + // Do not traverse comment nodes + ret += getText( node ); + } + } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { + // Use textContent for elements + // innerText usage removed for consistency of new lines (see #11153) + if ( typeof elem.textContent === "string" ) { + return elem.textContent; + } else { + // Traverse its children + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + ret += getText( elem ); + } + } + } else if ( nodeType === 3 || nodeType === 4 ) { + return elem.nodeValue; + } + // Do not include comment or processing instruction nodes + + return ret; + }; + + Expr = Sizzle.selectors = { + + // Can be adjusted by the user + cacheLength: 50, + + createPseudo: markFunction, + + match: matchExpr, + + find: {}, + + relative: { + ">": { + dir: "parentNode", + first: true + }, + " ": { + dir: "parentNode" + }, + "+": { + dir: "previousSibling", + first: true + }, + "~": { + dir: "previousSibling" + } + }, + + preFilter: { + "ATTR": function( match ) { + match[1] = match[1].replace( runescape, funescape ); + + // Move the given value to match[3] whether quoted or unquoted + match[3] = ( match[4] || match[5] || "" ).replace( runescape, funescape ); + + if ( match[2] === "~=" ) { + match[3] = " " + match[3] + " "; + } + + return match.slice( 0, 4 ); + }, + + "CHILD": function( match ) { + /* matches from matchExpr["CHILD"] + 1 type (only|nth|...) + 2 what (child|of-type) + 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...) + 4 xn-component of xn+y argument ([+-]?\d*n|) + 5 sign of xn-component + 6 x of xn-component + 7 sign of y-component + 8 y of y-component + */ + match[1] = match[1].toLowerCase(); + + if ( match[1].slice( 0, 3 ) === "nth" ) { + // nth-* requires argument + if ( !match[3] ) { + Sizzle.error( match[0] ); + } + + // numeric x and y parameters for Expr.filter.CHILD + // remember that false/true cast respectively to 0/1 + match[4] = + ( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) ); + match[5] = + ( ( match[7] + match[8] ) || match[3] === "odd" ); + + // other types prohibit arguments + } else if ( match[3] ) { + Sizzle.error( match[0] ); + } + + return match; + }, + + "PSEUDO": function( match ) { + var excess, + unquoted = !match[5] && match[2]; + + if ( matchExpr["CHILD"].test( match[0] ) ) { + return null; + } + + // Accept quoted arguments as-is + if ( match[4] ) { + match[2] = match[4]; + + // Strip excess characters from unquoted arguments + } else if ( unquoted && rpseudo.test( unquoted ) && + // Get excess from tokenize (recursively) + (excess = tokenize( unquoted, true )) && + // advance to the next closing parenthesis + (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { + + // excess is a negative index + match[0] = match[0].slice( 0, excess ); + match[2] = unquoted.slice( 0, excess ); + } + + // Return only captures needed by the pseudo filter method (type and argument) + return match.slice( 0, 3 ); + } + }, + + filter: { + + "TAG": function( nodeName ) { + if ( nodeName === "*" ) { + return function() { + return true; + }; + } + + nodeName = nodeName.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + }; + }, + + "CLASS": function( className ) { + var pattern = classCache[ className + " " ]; + + return pattern || + (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) && + classCache( className, function( elem ) { + return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); + }); + }, + + "ATTR": function( name, operator, check ) { + return function( elem ) { + var result = Sizzle.attr( elem, name ); + + if ( result == null ) { + return operator === "!="; + } + if ( !operator ) { + return true; + } + + result += ""; + + return operator === "=" ? result === check : + operator === "!=" ? result !== check : + operator === "^=" ? check && result.indexOf( check ) === 0 : + operator === "*=" ? check && result.indexOf( check ) > - 1 : + operator === "$=" ? check && result.slice( - check.length ) === check : + operator === "~=" ? ( " " + result + " " ).indexOf( check ) > - 1 : + operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : + false; + }; + }, + + "CHILD": function( type, what, argument, first, last ) { + var simple = type.slice( 0, 3 ) !== "nth", + forward = type.slice( - 4 ) !== "last", + ofType = what === "of-type"; + + return first === 1 && last === 0 ? + // Shortcut for :nth-*(n) + function( elem ) { + return !!elem.parentNode; + } : + function( elem, context, xml ) { + var cache, outerCache, node, diff, nodeIndex, start, + dir = simple !== forward ? "nextSibling" : "previousSibling", + parent = elem.parentNode, + name = ofType && elem.nodeName.toLowerCase(), + useCache = !xml && !ofType; + + if ( parent ) { + + // :(first|last|only)-(child|of-type) + if ( simple ) { + while ( dir ) { + node = elem; + while ( (node = node[ dir ]) ) { + if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) { + return false; + } + } + // Reverse direction for :only-* (if we haven't yet done so) + start = dir = type === "only" && !start && "nextSibling"; + } + return true; + } + + start = [ forward ? parent.firstChild : parent.lastChild ]; + + // non-xml :nth-child(...) stores cache data on `parent` + if ( forward && useCache ) { + // Seek `elem` from a previously-cached index + outerCache = parent[ expando ] || (parent[ expando ] = {}); + cache = outerCache[ type ] || []; + nodeIndex = cache[0] === dirruns && cache[1]; + diff = cache[0] === dirruns && cache[2]; + node = nodeIndex && parent.childNodes[ nodeIndex ]; + + while ( (node = ++nodeIndex && node && node[ dir ] || + // Fallback to seeking `elem` from the start + (diff = nodeIndex = 0) || start.pop()) ) { + + // When found, cache indexes on `parent` and break + if ( node.nodeType === 1 && ++diff && node === elem ) { + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; + break; + } + } + + // Use previously-cached element index if available + } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) { + diff = cache[1]; + + // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...) + } else { + // Use the same loop as above to seek `elem` from the start + while ( (node = ++nodeIndex && node && node[ dir ] || + (diff = nodeIndex = 0) || start.pop()) ) { + + if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) { + // Cache the index of each encountered element + if ( useCache ) { + (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ]; + } + + if ( node === elem ) { + break; + } + } + } + } + + // Incorporate the offset, then check against cycle size + diff -= last; + return diff === first || ( diff % first === 0 && diff / first >= 0 ); + } + }; + }, + + "PSEUDO": function( pseudo, argument ) { + // pseudo-class names are case-insensitive + // http://www.w3.org/TR/selectors/#pseudo-classes + // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters + // Remember that setFilters inherits from pseudos + var args, + fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || + Sizzle.error( "unsupported pseudo: " + pseudo ); + + // The user may use createPseudo to indicate that + // arguments are needed to create the filter function + // just as Sizzle does + if ( fn[ expando ] ) { + return fn( argument ); + } + + // But maintain support for old signatures + if ( fn.length > 1 ) { + args = [ pseudo, pseudo, "", argument ]; + return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? + markFunction(function( seed, matches ) { + var idx, + matched = fn( seed, argument ), + i = matched.length; + while ( i-- ) { + idx = indexOf.call( seed, matched[i] ); + seed[ idx ] = !( matches[ idx ] = matched[i] ); + } + }) : + function( elem ) { + return fn( elem, 0, args ); + }; + } + + return fn; + } + }, + + pseudos: { + // Potentially complex pseudos + "not": markFunction(function( selector ) { + // Trim the selector passed to compile + // to avoid treating leading and trailing + // spaces as combinators + var input = [], + results = [], + matcher = compile( selector.replace( rtrim, "$1" ) ); + + return matcher[ expando ] ? + markFunction(function( seed, matches, context, xml ) { + var elem, + unmatched = matcher( seed, null, xml, [] ), + i = seed.length; + + // Match elements unmatched by `matcher` + while ( i-- ) { + if ( (elem = unmatched[i]) ) { + seed[i] = !(matches[i] = elem); + } + } + }) : + function( elem, context, xml ) { + input[0] = elem; + matcher( input, null, xml, results ); + return !results.pop(); + }; + }), + + "has": markFunction(function( selector ) { + return function( elem ) { + return Sizzle( selector, elem ).length > 0; + }; + }), + + "contains": markFunction(function( text ) { + return function( elem ) { + return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > - 1; + }; + }), + + // "Whether an element is represented by a :lang() selector + // is based solely on the element's language value + // being equal to the identifier C, + // or beginning with the identifier C immediately followed by "-". + // The matching of C against the element's language value is performed case-insensitively. + // The identifier C does not have to be a valid language name." + // http://www.w3.org/TR/selectors/#lang-pseudo + "lang": markFunction( function( lang ) { + // lang value must be a valid identifider + if ( !ridentifier.test(lang || "") ) { + Sizzle.error( "unsupported lang: " + lang ); + } + lang = lang.replace( runescape, funescape ).toLowerCase(); + return function( elem ) { + var elemLang; + do { + if ( (elemLang = documentIsXML ? + elem.getAttribute("xml:lang") || elem.getAttribute("lang") : + elem.lang) ) { + + elemLang = elemLang.toLowerCase(); + return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0; + } + } + while ( (elem = elem.parentNode) && elem.nodeType === 1 ); + return false; + }; + }), + + // Miscellaneous + "target": function( elem ) { + var hash = window.location && window.location.hash; + return hash && hash.slice( 1 ) === elem.id; + }, + + "root": function( elem ) { + return elem === docElem; + }, + + "focus": function( elem ) { + return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); + }, + + // Boolean properties + "enabled": function( elem ) { + return elem.disabled === false; + }, + + "disabled": function( elem ) { + return elem.disabled === true; + }, + + "checked": function( elem ) { + // In CSS3, :checked should return both checked and selected elements + // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + var nodeName = elem.nodeName.toLowerCase(); + return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); + }, + + "selected": function( elem ) { + // Accessing this property makes selected-by-default + // options in Safari work properly + if ( elem.parentNode ) { + elem.parentNode.selectedIndex; + } + + return elem.selected === true; + }, + + // Contents + "empty": function( elem ) { + // http://www.w3.org/TR/selectors/#empty-pseudo + // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), + // not comment, processing instructions, or others + // Thanks to Diego Perini for the nodeName shortcut + // Greater than "@" means alpha characters (specifically not starting with "#" or "?") + for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { + if ( elem.nodeName > "@" || elem.nodeType === 3 || elem.nodeType === 4 ) { + return false; + } + } + return true; + }, + + "parent": function( elem ) { + return !Expr.pseudos["empty"]( elem ); + }, + + // Element/input types + "header": function( elem ) { + return rheader.test( elem.nodeName ); + }, + + "input": function( elem ) { + return rinputs.test( elem.nodeName ); + }, + + "button": function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === "button" || name === "button"; + }, + + "text": function( elem ) { + var attr; + // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) + // use getAttribute instead to test this case + return elem.nodeName.toLowerCase() === "input" && + elem.type === "text" && + ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === elem.type ); + }, + + // Position-in-collection + "first": createPositionalPseudo(function() { + return [ 0 ]; + }), + + "last": createPositionalPseudo(function( matchIndexes, length ) { + return [ length - 1 ]; + }), + + "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { + return [ argument < 0 ? argument + length : argument ]; + }), + + "even": createPositionalPseudo(function( matchIndexes, length ) { + var i = 0; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "odd": createPositionalPseudo(function( matchIndexes, length ) { + var i = 1; + for ( ; i < length; i += 2 ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; --i >= 0; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }), + + "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { + var i = argument < 0 ? argument + length : argument; + for ( ; ++i < length; ) { + matchIndexes.push( i ); + } + return matchIndexes; + }) + } + }; + + // Add button/input type pseudos + for ( i in { + radio: true, + checkbox: true, + file: true, + password: true, + image: true + }) { + Expr.pseudos[ i ] = createInputPseudo( i ); + } + for ( i in { + submit: true, + reset: true + }) { + Expr.pseudos[ i ] = createButtonPseudo( i ); + } + + function tokenize( selector, parseOnly ) { + var matched, match, tokens, type, + soFar, groups, preFilters, + cached = tokenCache[ selector + " " ]; + + if ( cached ) { + return parseOnly ? 0 : cached.slice( 0 ); + } + + soFar = selector; + groups = []; + preFilters = Expr.preFilter; + + while ( soFar ) { + + // Comma and first run + if ( !matched || (match = rcomma.exec( soFar )) ) { + if ( match ) { + // Don't consume trailing commas as valid + soFar = soFar.slice( match[0].length ) || soFar; + } + groups.push( tokens = [] ); + } + + matched = false; + + // Combinators + if ( (match = rcombinators.exec( soFar )) ) { + matched = match.shift(); + tokens.push( { + value: matched, + // Cast descendant combinators to space + type: match[0].replace( rtrim, " " ) + }); + soFar = soFar.slice( matched.length ); + } + + // Filters + for ( type in Expr.filter ) { + if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || + (match = preFilters[ type ]( match ))) ) { + matched = match.shift(); + tokens.push( { + value: matched, + type: type, + matches: match + }); + soFar = soFar.slice( matched.length ); + } + } + + if ( !matched ) { + break; + } + } + + // Return the length of the invalid excess + // if we're just parsing + // Otherwise, throw an error or return tokens + return parseOnly ? + soFar.length : + soFar ? + Sizzle.error( selector ) : + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); + } + + function toSelector( tokens ) { + var i = 0, + len = tokens.length, + selector = ""; + for ( ; i < len; i++ ) { + selector += tokens[i].value; + } + return selector; + } + + function addCombinator( matcher, combinator, base ) { + var dir = combinator.dir, + checkNonElements = base && dir === "parentNode", + doneName = done++; + + return combinator.first ? + // Check against closest ancestor/preceding element + function( elem, context, xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + return matcher( elem, context, xml ); + } + } + } : + // Check against all ancestor/preceding elements + function( elem, context, xml ) { + var data, cache, outerCache, + dirkey = dirruns + " " + doneName; + + // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching + if ( xml ) { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + if ( matcher( elem, context, xml ) ) { + return true; + } + } + } + } else { + while ( (elem = elem[ dir ]) ) { + if ( elem.nodeType === 1 || checkNonElements ) { + outerCache = elem[ expando ] || (elem[ expando ] = {}); + if ( (cache = outerCache[ dir ]) && cache[0] === dirkey ) { + if ( (data = cache[1]) === true || data === cachedruns ) { + return data === true; + } + } else { + cache = outerCache[ dir ] = [ dirkey ]; + cache[1] = matcher( elem, context, xml ) || cachedruns; + if ( cache[1] === true ) { + return true; + } + } + } + } + } + }; + } + + function elementMatcher( matchers ) { + return matchers.length > 1 ? + function( elem, context, xml ) { + var i = matchers.length; + while ( i-- ) { + if ( !matchers[i]( elem, context, xml ) ) { + return false; + } + } + return true; + } : + matchers[0]; + } + + function condense( unmatched, map, filter, context, xml ) { + var elem, + newUnmatched = [], + i = 0, + len = unmatched.length, + mapped = map != null; + + for ( ; i < len; i++ ) { + if ( (elem = unmatched[i]) ) { + if ( !filter || filter( elem, context, xml ) ) { + newUnmatched.push( elem ); + if ( mapped ) { + map.push( i ); + } + } + } + } + + return newUnmatched; + } + + function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { + if ( postFilter && !postFilter[ expando ] ) { + postFilter = setMatcher( postFilter ); + } + if ( postFinder && !postFinder[ expando ] ) { + postFinder = setMatcher( postFinder, postSelector ); + } + return markFunction(function( seed, results, context, xml ) { + var temp, i, elem, + preMap = [], + postMap = [], + preexisting = results.length, + // Get initial elements from seed or context + elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ), + // Prefilter to get matcher input, preserving a map for seed-results synchronization + matcherIn = preFilter && ( seed || !selector ) ? + condense( elems, preMap, preFilter, context, xml ) : + elems, + matcherOut = matcher ? + // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, + postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + // ...intermediate processing is necessary + [] : + // ...otherwise use results directly + results : + matcherIn; + + // Find primary matches + if ( matcher ) { + matcher( matcherIn, matcherOut, context, xml ); + } + + // Apply postFilter + if ( postFilter ) { + temp = condense( matcherOut, postMap ); + postFilter( temp, [], context, xml ); + + // Un-match failing elements by moving them back to matcherIn + i = temp.length; + while ( i-- ) { + if ( (elem = temp[i]) ) { + matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); + } + } + } + + if ( seed ) { + if ( postFinder || preFilter ) { + if ( postFinder ) { + // Get the final matcherOut by condensing this intermediate into postFinder contexts + temp = []; + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) ) { + // Restore matcherIn since elem is not yet a final match + temp.push( (matcherIn[i] = elem) ); + } + } + postFinder( null, (matcherOut = []), temp, xml ); + } + + // Move matched elements from seed to results to keep them synchronized + i = matcherOut.length; + while ( i-- ) { + if ( (elem = matcherOut[i]) && + (temp = postFinder ? indexOf.call( seed, elem ) : preMap[i]) > - 1 ) { + + seed[temp] = !(results[temp] = elem); + } + } + } + + // Add elements to results, through postFinder if defined + } else { + matcherOut = condense( + matcherOut === results ? + matcherOut.splice( preexisting, matcherOut.length ) : + matcherOut + ); + if ( postFinder ) { + postFinder( null, results, matcherOut, xml ); + } else { + push.apply( results, matcherOut ); + } + } + }); + } + + function matcherFromTokens( tokens ) { + var checkContext, matcher, j, + len = tokens.length, + leadingRelative = Expr.relative[ tokens[0].type ], + implicitRelative = leadingRelative || Expr.relative[" "], + i = leadingRelative ? 1 : 0, + // The foundational matcher ensures that elements are reachable from top-level context(s) + matchContext = addCombinator( function( elem ) { + return elem === checkContext; + }, implicitRelative, true ), + matchAnyContext = addCombinator( function( elem ) { + return indexOf.call( checkContext, elem ) > - 1; + }, implicitRelative, true ), + matchers = [ function( elem, context, xml ) { + return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + (checkContext = context).nodeType ? + matchContext( elem, context, xml ) : + matchAnyContext( elem, context, xml ) ); + } + ]; + + for ( ; i < len; i++ ) { + if ( (matcher = Expr.relative[ tokens[i].type ]) ) { + matchers = [ addCombinator(elementMatcher( matchers ), matcher) ]; + } else { + matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); + + // Return special upon seeing a positional matcher + if ( matcher[ expando ] ) { + // Find the next relative operator (if any) for proper handling + j = ++i; + for ( ; j < len; j++ ) { + if ( Expr.relative[ tokens[j].type ] ) { + break; + } + } + return setMatcher( + i > 1 && elementMatcher( matchers ), + i > 1 && toSelector( tokens.slice( 0, i - 1 ) ).replace( rtrim, "$1" ), + matcher, + i < j && matcherFromTokens( tokens.slice( i, j ) ), + j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), + j < len && toSelector( tokens ) + ); + } + matchers.push( matcher ); + } + } + + return elementMatcher( matchers ); + } + + function matcherFromGroupMatchers( elementMatchers, setMatchers ) { + // A counter to specify which element is currently being matched + var matcherCachedRuns = 0, + bySet = setMatchers.length > 0, + byElement = elementMatchers.length > 0, + superMatcher = function( seed, context, xml, results, expandContext ) { + var elem, j, matcher, + setMatched = [], + matchedCount = 0, + i = "0", + unmatched = seed && [], + outermost = expandContext != null, + contextBackup = outermostContext, + // We must always have either seed elements or context + elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), + // Use integer dirruns iff this is the outermost matcher + dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1); + + if ( outermost ) { + outermostContext = context !== document && context; + cachedruns = matcherCachedRuns; + } + + // Add elements passing elementMatchers directly to results + // Keep `i` a string if there are no elements so `matchedCount` will be "00" below + for ( ; (elem = elems[i]) != null; i++ ) { + if ( byElement && elem ) { + j = 0; + while ( (matcher = elementMatchers[j++]) ) { + if ( matcher( elem, context, xml ) ) { + results.push( elem ); + break; + } + } + if ( outermost ) { + dirruns = dirrunsUnique; + cachedruns = ++matcherCachedRuns; + } + } + + // Track unmatched elements for set filters + if ( bySet ) { + // They will have gone through all possible matchers + if ( (elem = !matcher && elem) ) { + matchedCount--; + } + + // Lengthen the array for every element, matched or not + if ( seed ) { + unmatched.push( elem ); + } + } + } + + // Apply set filters to unmatched elements + matchedCount += i; + if ( bySet && i !== matchedCount ) { + j = 0; + while ( (matcher = setMatchers[j++]) ) { + matcher( unmatched, setMatched, context, xml ); + } + + if ( seed ) { + // Reintegrate element matches to eliminate the need for sorting + if ( matchedCount > 0 ) { + while ( i-- ) { + if ( !(unmatched[i] || setMatched[i]) ) { + setMatched[i] = pop.call( results ); + } + } + } + + // Discard index placeholder values to get only actual matches + setMatched = condense( setMatched ); + } + + // Add matches to results + push.apply( results, setMatched ); + + // Seedless set matches succeeding multiple successful matchers stipulate sorting + if ( outermost && !seed && setMatched.length > 0 && + ( matchedCount + setMatchers.length ) > 1 ) { + + Sizzle.uniqueSort( results ); + } + } + + // Override manipulation of globals by nested matchers + if ( outermost ) { + dirruns = dirrunsUnique; + outermostContext = contextBackup; + } + + return unmatched; + }; + + return bySet ? + markFunction( superMatcher ) : + superMatcher; + } + + compile = Sizzle.compile = function( selector, group /* Internal Use Only */ + ) { + var i, + setMatchers = [], + elementMatchers = [], + cached = compilerCache[ selector + " " ]; + + if ( !cached ) { + // Generate a function of recursive functions that can be used to check each element + if ( !group ) { + group = tokenize( selector ); + } + i = group.length; + while ( i-- ) { + cached = matcherFromTokens( group[i] ); + if ( cached[ expando ] ) { + setMatchers.push( cached ); + } else { + elementMatchers.push( cached ); + } + } + + // Cache the compiled function + cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); + } + return cached; + }; + + function multipleContexts( selector, contexts, results ) { + var i = 0, + len = contexts.length; + for ( ; i < len; i++ ) { + Sizzle( selector, contexts[i], results ); + } + return results; + } + + function select( selector, context, results, seed ) { + var i, tokens, token, type, find, + match = tokenize( selector ); + + if ( !seed ) { + // Try to minimize operations if there is only one group + if ( match.length === 1 ) { + + // Take a shortcut and set the context if the root selector is an ID + tokens = match[0] = match[0].slice( 0 ); + if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && + context.nodeType === 9 && !documentIsXML && + Expr.relative[ tokens[1].type ] ) { + + context = Expr.find["ID"]( token.matches[0].replace( runescape, funescape ), context )[0]; + if ( !context ) { + return results; + } + + selector = selector.slice( tokens.shift().value.length ); + } + + // Fetch a seed set for right-to-left matching + i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length; + while ( i-- ) { + token = tokens[i]; + + // Abort if we hit a combinator + if ( Expr.relative[ (type = token.type) ] ) { + break; + } + if ( (find = Expr.find[ type ]) ) { + // Search, expanding context for leading sibling combinators + if ( (seed = find( + token.matches[0].replace( runescape, funescape ), + rsibling.test( tokens[0].type ) && context.parentNode || context + )) ) { + + // If seed is empty or no tokens remain, we can return early + tokens.splice( i, 1 ); + selector = seed.length && toSelector( tokens ); + if ( !selector ) { + push.apply( results, slice.call( seed, 0 ) ); + return results; + } + + break; + } + } + } + } + } + + // Compile and execute a filtering function + // Provide `match` to avoid retokenization if we modified the selector above + compile( selector, match )( + seed, + context, + documentIsXML, + results, + rsibling.test( selector ) + ); + return results; + } + + // Deprecated + Expr.pseudos["nth"] = Expr.pseudos["eq"]; + + // Easy API for creating new setFilters + function setFilters() {} + Expr.filters = setFilters.prototype = Expr.pseudos; + Expr.setFilters = new setFilters(); + + // Initialize with the default document + setDocument(); + + // Override sizzle attribute retrieval + Sizzle.attr = jQuery.attr; + jQuery.find = Sizzle; + jQuery.expr = Sizzle.selectors; + jQuery.expr[":"] = jQuery.expr.pseudos; + jQuery.unique = Sizzle.uniqueSort; + jQuery.text = Sizzle.getText; + jQuery.isXMLDoc = Sizzle.isXML; + jQuery.contains = Sizzle.contains; + + + })( window ); + var runtil = /Until$/, + rparentsprev = /^(?:parents|prev(?:Until|All))/, + isSimple = /^.[^:#\[\.,]*$/, + rneedsContext = jQuery.expr.match.needsContext, + // methods guaranteed to produce a unique set when starting from a unique set + guaranteedUnique = { + children: true, + contents: true, + next: true, + prev: true + }; + + jQuery.fn.extend({ + find: function( selector ) { + var i, ret, self, + len = this.length; + + if ( typeof selector !== "string" ) { + self = this; + return this.pushStack( jQuery( selector ).filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( self[ i ], this ) ) { + return true; + } + } + }) ); + } + + ret = []; + for ( i = 0; i < len; i++ ) { + jQuery.find( selector, this[ i ], ret ); + } + + // Needed because $( selector, context ) becomes $( context ).find( selector ) + ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret ); + ret.selector = ( this.selector ? this.selector + " " : "" ) + selector; + return ret; + }, + + has: function( target ) { + var i, + targets = jQuery( target, this ), + len = targets.length; + + return this.filter(function() { + for ( i = 0; i < len; i++ ) { + if ( jQuery.contains( this, targets[i] ) ) { + return true; + } + } + }); + }, + + not: function( selector ) { + return this.pushStack( winnow(this, selector, false) ); + }, + + filter: function( selector ) { + return this.pushStack( winnow(this, selector, true) ); + }, + + is: function( selector ) { + return !!selector && ( + typeof selector === "string" ? + // If this is a positional/relative selector, check membership in the returned set + // so $("p:first").is("p:last") won't return true for a doc with two "p". + rneedsContext.test( selector ) ? + jQuery( selector, this.context ).index( this[0] ) >= 0 : + jQuery.filter( selector, this ).length > 0 : + this.filter( selector ).length > 0 ); + }, + + closest: function( selectors, context ) { + var cur, + i = 0, + l = this.length, + ret = [], + pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? + jQuery( selectors, context || this.context ) : + 0; + + for ( ; i < l; i++ ) { + cur = this[i]; + + while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { + if ( pos ? pos.index(cur) > - 1 : jQuery.find.matchesSelector(cur, selectors) ) { + ret.push( cur ); + break; + } + cur = cur.parentNode; + } + } + + return this.pushStack( ret.length > 1 ? jQuery.unique( ret ) : ret ); + }, + + // Determine the position of an element within + // the matched set of elements + index: function( elem ) { + + // No argument, return index in parent + if ( !elem ) { + return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : - 1; + } + + // index in selector + if ( typeof elem === "string" ) { + return jQuery.inArray( this[0], jQuery( elem ) ); + } + + // Locate the position of the desired element + return jQuery.inArray( + // If it receives a jQuery object, the first element is used + elem.jquery ? elem[0] : elem, this ); + }, + + add: function( selector, context ) { + var set = typeof selector === "string" ? + jQuery( selector, context ) : + jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), + all = jQuery.merge( this.get(), set ); + + return this.pushStack( jQuery.unique(all) ); + }, + + addBack: function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter(selector) + ); + } + }); + + jQuery.fn.andSelf = jQuery.fn.addBack; + + function sibling( cur, dir ) { + do { + cur = cur[ dir ]; + } + while ( cur && cur.nodeType !== 1 ); + + return cur; + } + + jQuery.each({ + parent: function( elem ) { + var parent = elem.parentNode; + return parent && parent.nodeType !== 11 ? parent : null; + }, + parents: function( elem ) { + return jQuery.dir( elem, "parentNode" ); + }, + parentsUntil: function( elem, i, until ) { + return jQuery.dir( elem, "parentNode", until ); + }, + next: function( elem ) { + return sibling( elem, "nextSibling" ); + }, + prev: function( elem ) { + return sibling( elem, "previousSibling" ); + }, + nextAll: function( elem ) { + return jQuery.dir( elem, "nextSibling" ); + }, + prevAll: function( elem ) { + return jQuery.dir( elem, "previousSibling" ); + }, + nextUntil: function( elem, i, until ) { + return jQuery.dir( elem, "nextSibling", until ); + }, + prevUntil: function( elem, i, until ) { + return jQuery.dir( elem, "previousSibling", until ); + }, + siblings: function( elem ) { + return jQuery.sibling( ( elem.parentNode || {}).firstChild, elem ); + }, + children: function( elem ) { + return jQuery.sibling( elem.firstChild ); + }, + contents: function( elem ) { + return jQuery.nodeName( elem, "iframe" ) ? + elem.contentDocument || elem.contentWindow.document : + jQuery.merge( [], elem.childNodes ); + } + }, function( name, fn ) { + jQuery.fn[ name ] = function( until, selector ) { + var ret = jQuery.map( this, fn, until ); + + if ( !runtil.test( name ) ) { + selector = until; + } + + if ( selector && typeof selector === "string" ) { + ret = jQuery.filter( selector, ret ); + } + + ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; + + if ( this.length > 1 && rparentsprev.test( name ) ) { + ret = ret.reverse(); + } + + return this.pushStack( ret ); + }; + }); + + jQuery.extend({ + filter: function( expr, elems, not ) { + if ( not ) { + expr = ":not(" + expr + ")"; + } + + return elems.length === 1 ? + jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : + jQuery.find.matches(expr, elems); + }, + + dir: function( elem, dir, until ) { + var matched = [], + cur = elem[ dir ]; + + while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { + if ( cur.nodeType === 1 ) { + matched.push( cur ); + } + cur = cur[dir]; + } + return matched; + }, + + sibling: function( n, elem ) { + var r = []; + + for ( ; n; n = n.nextSibling ) { + if ( n.nodeType === 1 && n !== elem ) { + r.push( n ); + } + } + + return r; + } + }); + + // Implement the identical functionality for filter and not + function winnow( elements, qualifier, keep ) { + + // Can't pass null or undefined to indexOf in Firefox 4 + // Set to 0 to skip string check + qualifier = qualifier || 0; + + if ( jQuery.isFunction( qualifier ) ) { + return jQuery.grep(elements, function( elem, i ) { + var retVal = !!qualifier.call( elem, i, elem ); + return retVal === keep; + }); + + } else if ( qualifier.nodeType ) { + return jQuery.grep(elements, function( elem ) { + return ( elem === qualifier ) === keep; + }); + + } else if ( typeof qualifier === "string" ) { + var filtered = jQuery.grep(elements, function( elem ) { + return elem.nodeType === 1; + }); + + if ( isSimple.test( qualifier ) ) { + return jQuery.filter(qualifier, filtered, !keep); + } else { + qualifier = jQuery.filter( qualifier, filtered ); + } + } + + return jQuery.grep(elements, function( elem ) { + return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; + }); + } + function createSafeFragment( document ) { + var list = nodeNames.split( "|" ), + safeFrag = document.createDocumentFragment(); + + if ( safeFrag.createElement ) { + while ( list.length ) { + safeFrag.createElement( + list.pop() + ); + } + } + return safeFrag; + } + + var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + + "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", + rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, + rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"), + rleadingWhitespace = /^\s+/, + rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, + rtagName = /<([\w:]+)/, + rtbody = /\s*$/g, + // We have to close these tags to support XHTML (#13200) + wrapMap = { + option: [ 1, "" ], + legend: [ 1, "
", "
" ], + area: [ 1, "", "" ], + param: [ 1, "", "" ], + thead: [ 1, "", "
" ], + tr: [ 2, "", "
" ], + col: [ 2, "", "
" ], + td: [ 3, "", "
" ], + + // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, + // unless wrapped in a div with non-breaking characters in front of it. + _default: jQuery.support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X
", "
" ] + }, + safeFragment = createSafeFragment( document ), + fragmentDiv = safeFragment.appendChild( document.createElement("div") ); + + wrapMap.optgroup = wrapMap.option; + wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; + wrapMap.th = wrapMap.td; + + jQuery.fn.extend({ + text: function( value ) { + return jQuery.access( this, function( value ) { + return value === undefined ? + jQuery.text( this ) : + this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); + }, null, value, arguments.length ); + }, + + wrapAll: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapAll( html.call(this, i) ); + }); + } + + if ( this[0] ) { + // The elements to wrap the target around + var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); + + if ( this[0].parentNode ) { + wrap.insertBefore( this[0] ); + } + + wrap.map(function() { + var elem = this; + + while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { + elem = elem.firstChild; + } + + return elem; + }).append( this ); + } + + return this; + }, + + wrapInner: function( html ) { + if ( jQuery.isFunction( html ) ) { + return this.each(function(i) { + jQuery(this).wrapInner( html.call(this, i) ); + }); + } + + return this.each(function() { + var self = jQuery( this ), + contents = self.contents(); + + if ( contents.length ) { + contents.wrapAll( html ); + + } else { + self.append( html ); + } + }); + }, + + wrap: function( html ) { + var isFunction = jQuery.isFunction( html ); + + return this.each(function(i) { + jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); + }); + }, + + unwrap: function() { + return this.parent().each(function() { + if ( !jQuery.nodeName( this, "body" ) ) { + jQuery( this ).replaceWith( this.childNodes ); + } + }).end(); + }, + + append: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.appendChild( elem ); + } + }); + }, + + prepend: function() { + return this.domManip(arguments, true, function( elem ) { + if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) { + this.insertBefore( elem, this.firstChild ); + } + }); + }, + + before: function() { + return this.domManip( arguments, false, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this ); + } + }); + }, + + after: function() { + return this.domManip( arguments, false, function( elem ) { + if ( this.parentNode ) { + this.parentNode.insertBefore( elem, this.nextSibling ); + } + }); + }, + + // keepData is for internal use only--do not document + remove: function( selector, keepData ) { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + if ( !selector || jQuery.filter( selector, [ elem ] ).length > 0 ) { + if ( !keepData && elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem ) ); + } + + if ( elem.parentNode ) { + if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) { + setGlobalEval( getAll( elem, "script" ) ); + } + elem.parentNode.removeChild( elem ); + } + } + } + + return this; + }, + + empty: function() { + var elem, + i = 0; + + for ( ; (elem = this[i]) != null; i++ ) { + // Remove element nodes and prevent memory leaks + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + } + + // Remove any remaining nodes + while ( elem.firstChild ) { + elem.removeChild( elem.firstChild ); + } + + // If this is a select, ensure that it displays empty (#12336) + // Support: IE<9 + if ( elem.options && jQuery.nodeName( elem, "select" ) ) { + elem.options.length = 0; + } + } + + return this; + }, + + clone: function( dataAndEvents, deepDataAndEvents ) { + dataAndEvents = dataAndEvents == null ? false : dataAndEvents; + deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; + + return this.map( function () { + return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); + }); + }, + + html: function( value ) { + return jQuery.access( this, function( value ) { + var elem = this[0] || {}, + i = 0, + l = this.length; + + if ( value === undefined ) { + return elem.nodeType === 1 ? + elem.innerHTML.replace( rinlinejQuery, "" ) : + undefined; + } + + // See if we can take a shortcut and just use innerHTML + if ( typeof value === "string" && !rnoInnerhtml.test( value ) && + ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && + ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && + !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { + + value = value.replace( rxhtmlTag, "<$1>" ); + + try { + for (; i < l; i++ ) { + // Remove element nodes and prevent memory leaks + elem = this[i] || {}; + if ( elem.nodeType === 1 ) { + jQuery.cleanData( getAll( elem, false ) ); + elem.innerHTML = value; + } + } + + elem = 0; + + // If using innerHTML throws an exception, use the fallback method + } catch (e) {} + } + + if ( elem ) { + this.empty().append( value ); + } + }, null, value, arguments.length ); + }, + + replaceWith: function( value ) { + var isFunc = jQuery.isFunction( value ); + + // Make sure that the elements are removed from the DOM before they are inserted + // this can help fix replacing a parent with child elements + if ( !isFunc && typeof value !== "string" ) { + value = jQuery( value ).not( this ).detach(); + } + + return this.domManip( [ value ], true, function( elem ) { + var next = this.nextSibling, + parent = this.parentNode; + + if ( parent ) { + jQuery( this ).remove(); + parent.insertBefore( elem, next ); + } + }); + }, + + detach: function( selector ) { + return this.remove( selector, true ); + }, + + domManip: function( args, table, callback ) { + + // Flatten any nested arrays + args = core_concat.apply( [], args ); + + var first, node, hasScripts, + scripts, doc, fragment, + i = 0, + l = this.length, + set = this, + iNoClone = l - 1, + value = args[0], + isFunction = jQuery.isFunction( value ); + + // We can't cloneNode fragments that contain checked, in WebKit + if ( isFunction || !( l <= 1 || typeof value !== "string" || jQuery.support.checkClone || !rchecked.test( value ) ) ) { + return this.each(function( index ) { + var self = set.eq( index ); + if ( isFunction ) { + args[0] = value.call( this, index, table ? self.html() : undefined ); + } + self.domManip( args, table, callback ); + }); + } + + if ( l ) { + fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this ); + first = fragment.firstChild; + + if ( fragment.childNodes.length === 1 ) { + fragment = first; + } + + if ( first ) { + table = table && jQuery.nodeName( first, "tr" ); + scripts = jQuery.map( getAll( fragment, "script" ), disableScript ); + hasScripts = scripts.length; + + // Use the original fragment for the last item instead of the first because it can end up + // being emptied incorrectly in certain situations (#8070). + for ( ; i < l; i++ ) { + node = fragment; + + if ( i !== iNoClone ) { + node = jQuery.clone( node, true, true ); + + // Keep references to cloned scripts for later restoration + if ( hasScripts ) { + jQuery.merge( scripts, getAll( node, "script" ) ); + } + } + + callback.call( + table && jQuery.nodeName( this[i], "table" ) ? + findOrAppend( this[i], "tbody" ) : + this[i], + node, + i + ); + } + + if ( hasScripts ) { + doc = scripts[ scripts.length - 1 ].ownerDocument; + + // Reenable scripts + jQuery.map( scripts, restoreScript ); + + // Evaluate executable scripts on first document insertion + for ( i = 0; i < hasScripts; i++ ) { + node = scripts[ i ]; + if ( rscriptType.test( node.type || "" ) && + !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) { + + if ( node.src ) { + // Hope ajax is available... + jQuery.ajax({ + url: node.src, + type: "GET", + dataType: "script", + async: false, + global: false, + "throws": true + }); + } else { + jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) ); + } + } + } + } + + // Fix #11809: Avoid leaking memory + fragment = first = null; + } + } + + return this; + } + }); + + function findOrAppend( elem, tag ) { + return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) ); + } + + // Replace/restore the type attribute of script elements for safe DOM manipulation + function disableScript( elem ) { + var attr = elem.getAttributeNode("type"); + elem.type = ( attr && attr.specified ) + "/" + elem.type; + return elem; + } + function restoreScript( elem ) { + var match = rscriptTypeMasked.exec( elem.type ); + if ( match ) { + elem.type = match[1]; + } else { + elem.removeAttribute("type"); + } + return elem; + } + + // Mark scripts as having already been evaluated + function setGlobalEval( elems, refElements ) { + var elem, + i = 0; + for ( ; (elem = elems[i]) != null; i++ ) { + jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) ); + } + } + + function cloneCopyEvent( src, dest ) { + + if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { + return; + } + + var type, i, l, + oldData = jQuery._data( src ), + curData = jQuery._data( dest, oldData ), + events = oldData.events; + + if ( events ) { + delete curData.handle; + curData.events = {}; + + for ( type in events ) { + for ( i = 0, l = events[ type ].length; i < l; i++ ) { + jQuery.event.add( dest, type, events[ type ][ i ] ); + } + } + } + + // make the cloned public data object a copy from the original + if ( curData.data ) { + curData.data = jQuery.extend( {}, curData.data ); + } + } + + function fixCloneNodeIssues( src, dest ) { + var nodeName, e, data; + + // We do not need to do anything for non-Elements + if ( dest.nodeType !== 1 ) { + return; + } + + nodeName = dest.nodeName.toLowerCase(); + + // IE6-8 copies events bound via attachEvent when using cloneNode. + if ( !jQuery.support.noCloneEvent && dest[ jQuery.expando ] ) { + data = jQuery._data( dest ); + + for ( e in data.events ) { + jQuery.removeEvent( dest, e, data.handle ); + } + + // Event data gets referenced instead of copied if the expando gets copied too + dest.removeAttribute( jQuery.expando ); + } + + // IE blanks contents when cloning scripts, and tries to evaluate newly-set text + if ( nodeName === "script" && dest.text !== src.text ) { + disableScript( dest ).text = src.text; + restoreScript( dest ); + + // IE6-10 improperly clones children of object elements using classid. + // IE10 throws NoModificationAllowedError if parent is null, #12132. + } else if ( nodeName === "object" ) { + if ( dest.parentNode ) { + dest.outerHTML = src.outerHTML; + } + + // This path appears unavoidable for IE9. When cloning an object + // element in IE9, the outerHTML strategy above is not sufficient. + // If the src has innerHTML and the destination does not, + // copy the src.innerHTML into the dest.innerHTML. #10324 + if ( jQuery.support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) { + dest.innerHTML = src.innerHTML; + } + + } else if ( nodeName === "input" && manipulation_rcheckableType.test( src.type ) ) { + // IE6-8 fails to persist the checked state of a cloned checkbox + // or radio button. Worse, IE6-7 fail to give the cloned element + // a checked appearance if the defaultChecked value isn't also set + + dest.defaultChecked = dest.checked = src.checked; + + // IE6-7 get confused and end up setting the value of a cloned + // checkbox/radio button to an empty string instead of "on" + if ( dest.value !== src.value ) { + dest.value = src.value; + } + + // IE6-8 fails to return the selected option to the default selected + // state when cloning options + } else if ( nodeName === "option" ) { + dest.defaultSelected = dest.selected = src.defaultSelected; + + // IE6-8 fails to set the defaultValue to the correct value when + // cloning other types of input fields + } else if ( nodeName === "input" || nodeName === "textarea" ) { + dest.defaultValue = src.defaultValue; + } + } + + jQuery.each({ + appendTo: "append", + prependTo: "prepend", + insertBefore: "before", + insertAfter: "after", + replaceAll: "replaceWith" + }, function( name, original ) { + jQuery.fn[ name ] = function( selector ) { + var elems, + i = 0, + ret = [], + insert = jQuery( selector ), + last = insert.length - 1; + + for ( ; i <= last; i++ ) { + elems = i === last ? this : this.clone(true); + jQuery( insert[i] )[ original ]( elems ); + + // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get() + core_push.apply( ret, elems.get() ); + } + + return this.pushStack( ret ); + }; + }); + + function getAll( context, tag ) { + var elems, elem, + i = 0, + found = typeof context.getElementsByTagName !== core_strundefined ? context.getElementsByTagName( tag || "*" ) : + typeof context.querySelectorAll !== core_strundefined ? context.querySelectorAll( tag || "*" ) : + undefined; + + if ( !found ) { + for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) { + if ( !tag || jQuery.nodeName( elem, tag ) ) { + found.push( elem ); + } else { + jQuery.merge( found, getAll( elem, tag ) ); + } + } + } + + return tag === undefined || tag && jQuery.nodeName( context, tag ) ? + jQuery.merge( [ context ], found ) : + found; + } + + // Used in buildFragment, fixes the defaultChecked property + function fixDefaultChecked( elem ) { + if ( manipulation_rcheckableType.test( elem.type ) ) { + elem.defaultChecked = elem.checked; + } + } + + jQuery.extend({ + clone: function( elem, dataAndEvents, deepDataAndEvents ) { + var destElements, node, clone, i, srcElements, + inPage = jQuery.contains( elem.ownerDocument, elem ); + + if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { + clone = elem.cloneNode( true ); + + // IE<=8 does not properly clone detached, unknown element nodes + } else { + fragmentDiv.innerHTML = elem.outerHTML; + fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); + } + + if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && + (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { + + // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2 + destElements = getAll( clone ); + srcElements = getAll( elem ); + + // Fix all IE cloning issues + for ( i = 0; (node = srcElements[i]) != null; ++i ) { + // Ensure that the destination node is not null; Fixes #9587 + if ( destElements[i] ) { + fixCloneNodeIssues( node, destElements[i] ); + } + } + } + + // Copy the events from the original to the clone + if ( dataAndEvents ) { + if ( deepDataAndEvents ) { + srcElements = srcElements || getAll( elem ); + destElements = destElements || getAll( clone ); + + for ( i = 0; (node = srcElements[i]) != null; i++ ) { + cloneCopyEvent( node, destElements[i] ); + } + } else { + cloneCopyEvent( elem, clone ); + } + } + + // Preserve script evaluation history + destElements = getAll( clone, "script" ); + if ( destElements.length > 0 ) { + setGlobalEval( destElements, !inPage && getAll( elem, "script" ) ); + } + + destElements = srcElements = node = null; + + // Return the cloned set + return clone; + }, + + buildFragment: function( elems, context, scripts, selection ) { + var j, elem, contains, + tmp, tag, tbody, wrap, + l = elems.length, + // Ensure a safe fragment + safe = createSafeFragment( context ), + nodes = [], + i = 0; + + for ( ; i < l; i++ ) { + elem = elems[ i ]; + + if ( elem || elem === 0 ) { + + // Add nodes directly + if ( jQuery.type( elem ) === "object" ) { + jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); + + // Convert non-html into a text node + } else if ( !rhtml.test( elem ) ) { + nodes.push( context.createTextNode( elem ) ); + + // Convert html into DOM nodes + } else { + tmp = tmp || safe.appendChild( context.createElement("div") ); + + // Deserialize a standard representation + tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); + wrap = wrapMap[ tag ] || wrapMap._default; + + tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1>" ) + wrap[2]; + + // Descend through wrappers to the right content + j = wrap[0]; + while ( j-- ) { + tmp = tmp.lastChild; + } + + // Manually add leading whitespace removed by IE + if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { + nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) ); + } + + // Remove IE's autoinserted from table fragments + if ( !jQuery.support.tbody ) { + + // String was a , *may* have spurious + elem = tag === "table" && !rtbody.test( elem ) ? + tmp.firstChild : + // String was a bare or + wrap[1] === "
" && !rtbody.test( elem ) ? + tmp : + 0; + + j = elem && elem.childNodes.length; + while ( j-- ) { + if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) { + elem.removeChild( tbody ); + } + } + } + + jQuery.merge( nodes, tmp.childNodes ); + + // Fix #12392 for WebKit and IE > 9 + tmp.textContent = ""; + + // Fix #12392 for oldIE + while ( tmp.firstChild ) { + tmp.removeChild( tmp.firstChild ); + } + + // Remember the top-level container for proper cleanup + tmp = safe.lastChild; + } + } + } + + // Fix #11356: Clear elements from fragment + if ( tmp ) { + safe.removeChild( tmp ); + } + + // Reset defaultChecked for any radios and checkboxes + // about to be appended to the DOM in IE 6/7 (#8060) + if ( !jQuery.support.appendChecked ) { + jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked ); + } + + i = 0; + while ( (elem = nodes[ i++ ]) ) { + + // #4087 - If origin and destination elements are the same, and this is + // that element, do not do anything + if ( selection && jQuery.inArray( elem, selection ) !== - 1 ) { + continue; + } + + contains = jQuery.contains( elem.ownerDocument, elem ); + + // Append to fragment + tmp = getAll( safe.appendChild( elem ), "script" ); + + // Preserve script evaluation history + if ( contains ) { + setGlobalEval( tmp ); + } + + // Capture executables + if ( scripts ) { + j = 0; + while ( (elem = tmp[ j++ ]) ) { + if ( rscriptType.test( elem.type || "" ) ) { + scripts.push( elem ); + } + } + } + } + + tmp = null; + + return safe; + }, + + cleanData: function( elems, /* internal */ + acceptData ) { + var elem, type, id, data, + i = 0, + internalKey = jQuery.expando, + cache = jQuery.cache, + deleteExpando = jQuery.support.deleteExpando, + special = jQuery.event.special; + + for ( ; (elem = elems[i]) != null; i++ ) { + + if ( acceptData || jQuery.acceptData( elem ) ) { + + id = elem[ internalKey ]; + data = id && cache[ id ]; + + if ( data ) { + if ( data.events ) { + for ( type in data.events ) { + if ( special[ type ] ) { + jQuery.event.remove( elem, type ); + + // This is a shortcut to avoid jQuery.event.remove's overhead + } else { + jQuery.removeEvent( elem, type, data.handle ); + } + } + } + + // Remove cache only if it was not already removed by jQuery.event.remove + if ( cache[ id ] ) { + + delete cache[ id ]; + + // IE does not allow us to delete expando properties from nodes, + // nor does it have a removeAttribute function on Document nodes; + // we must handle all of these cases + if ( deleteExpando ) { + delete elem[ internalKey ]; + + } else if ( typeof elem.removeAttribute !== core_strundefined ) { + elem.removeAttribute( internalKey ); + + } else { + elem[ internalKey ] = null; + } + + core_deletedIds.push( id ); + } + } + } + } + } + }); + var iframe, getStyles, curCSS, + ralpha = /alpha\([^)]*\)/i, + ropacity = /opacity\s*=\s*([^)]*)/, + rposition = /^(top|right|bottom|left)$/, + // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" + // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display + rdisplayswap = /^(none|table(?!-c[ea]).+)/, + rmargin = /^margin/, + rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), + rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), + rrelNum = new RegExp( "^([+-])=(" + core_pnum + ")", "i" ), + elemdisplay = { + BODY: "block" + }, + cssShow = { + position: "absolute", + visibility: "hidden", + display: "block" + }, + cssNormalTransform = { + letterSpacing: 0, + fontWeight: 400 + }, + cssExpand = [ "Top", "Right", "Bottom", "Left" ], + cssPrefixes = [ "Webkit", "O", "Moz", "ms" ]; + + // return a css property mapped to a potentially vendor prefixed property + function vendorPropName( style, name ) { + + // shortcut for names that are not vendor prefixed + if ( name in style ) { + return name; + } + + // check for vendor prefixed names + var capName = name.charAt(0).toUpperCase() + name.slice(1), + origName = name, + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in style ) { + return name; + } + } + + return origName; + } + + function isHidden( elem, el ) { + // isHidden might be called from jQuery#filter function; + // in that case, element will be second argument + elem = el || elem; + return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); + } + + function showHide( elements, show ) { + var display, elem, hidden, + values = [], + index = 0, + length = elements.length; + + for ( ; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + + values[ index ] = jQuery._data( elem, "olddisplay" ); + display = elem.style.display; + if ( show ) { + // Reset the inline display of this element to learn if it is + // being hidden by cascaded rules or not + if ( !values[ index ] && display === "none" ) { + elem.style.display = ""; + } + + // Set elements which have been overridden with display: none + // in a stylesheet to whatever the default browser style is + // for such an element + if ( elem.style.display === "" && isHidden( elem ) ) { + values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); + } + } else { + + if ( !values[ index ] ) { + hidden = isHidden( elem ); + + if ( display && display !== "none" || !hidden ) { + jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) ); + } + } + } + } + + // Set the display of most of the elements in a second loop + // to avoid the constant reflow + for ( index = 0; index < length; index++ ) { + elem = elements[ index ]; + if ( !elem.style ) { + continue; + } + if ( !show || elem.style.display === "none" || elem.style.display === "" ) { + elem.style.display = show ? values[ index ] || "" : "none"; + } + } + + return elements; + } + + jQuery.fn.extend({ + css: function( name, value ) { + return jQuery.access( this, function( elem, name, value ) { + var len, styles, + map = {}, + i = 0; + + if ( jQuery.isArray( name ) ) { + styles = getStyles( elem ); + len = name.length; + + for ( ; i < len; i++ ) { + map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles ); + } + + return map; + } + + return value !== undefined ? + jQuery.style( elem, name, value ) : + jQuery.css( elem, name ); + }, name, value, arguments.length > 1 ); + }, + show: function() { + return showHide( this, true ); + }, + hide: function() { + return showHide( this ); + }, + toggle: function( state ) { + var bool = typeof state === "boolean"; + + return this.each(function() { + if ( bool ? state : isHidden( this ) ) { + jQuery( this ).show(); + } else { + jQuery( this ).hide(); + } + }); + } + }); + + jQuery.extend({ + // Add in style property hooks for overriding the default + // behavior of getting and setting a style property + cssHooks: { + opacity: { + get: function( elem, computed ) { + if ( computed ) { + // We should always get a number back from opacity + var ret = curCSS( elem, "opacity" ); + return ret === "" ? "1" : ret; + } + } + } + }, + + // Exclude the following css properties to add px + cssNumber: { + "columnCount": true, + "fillOpacity": true, + "fontWeight": true, + "lineHeight": true, + "opacity": true, + "orphans": true, + "widows": true, + "zIndex": true, + "zoom": true + }, + + // Add in properties whose names you wish to fix before + // setting or getting the value + cssProps: { + // normalize float css property + "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" + }, + + // Get and set the style property on a DOM Node + style: function( elem, name, value, extra ) { + // Don't set styles on text and comment nodes + if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { + return; + } + + // Make sure that we're working with the right name + var ret, type, hooks, + origName = jQuery.camelCase( name ), + style = elem.style; + + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // Check if we're setting a value + if ( value !== undefined ) { + type = typeof value; + + // convert relative number strings (+= or -=) to relative numbers. #7345 + if ( type === "string" && (ret = rrelNum.exec( value )) ) { + value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); + // Fixes bug #9237 + type = "number"; + } + + // Make sure that NaN and null values aren't set. See: #7116 + if ( value == null || type === "number" && isNaN( value ) ) { + return; + } + + // If a number was passed in, add 'px' to the (except for certain CSS properties) + if ( type === "number" && !jQuery.cssNumber[ origName ] ) { + value += "px"; + } + + // Fixes #8908, it can be done more correctly by specifing setters in cssHooks, + // but it would mean to define eight (for every problematic property) identical functions + if ( !jQuery.support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) { + style[ name ] = "inherit"; + } + + // If a hook was provided, use that value, otherwise just set the specified value + if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { + + // Wrapped to prevent IE from throwing errors when 'invalid' values are provided + // Fixes bug #5509 + try { + style[ name ] = value; + } catch (e) {} + } + + } else { + // If a hook was provided get the non-computed value from there + if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { + return ret; + } + + // Otherwise just get the value from the style object + return style[ name ]; + } + }, + + css: function( elem, name, extra, styles ) { + var num, val, hooks, + origName = jQuery.camelCase( name ); + + // Make sure that we're working with the right name + name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); + + // gets hook for the prefixed version + // followed by the unprefixed version + hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; + + // If a hook was provided get the computed value from there + if ( hooks && "get" in hooks ) { + val = hooks.get( elem, true, extra ); + } + + // Otherwise, if a way to get the computed value exists, use that + if ( val === undefined ) { + val = curCSS( elem, name, styles ); + } + + //convert "normal" to computed value + if ( val === "normal" && name in cssNormalTransform ) { + val = cssNormalTransform[ name ]; + } + + // Return, converting to number if forced or a qualifier was provided and val looks numeric + if ( extra === "" || extra ) { + num = parseFloat( val ); + return extra === true || jQuery.isNumeric( num ) ? num || 0 : val; + } + return val; + }, + + // A method for quickly swapping in/out CSS properties to get correct calculations + swap: function( elem, options, callback, args ) { + var ret, name, + old = {}; + + // Remember the old values, and insert the new ones + for ( name in options ) { + old[ name ] = elem.style[ name ]; + elem.style[ name ] = options[ name ]; + } + + ret = callback.apply( elem, args || [] ); + + // Revert the old values + for ( name in options ) { + elem.style[ name ] = old[ name ]; + } + + return ret; + } + }); + + // NOTE: we've included the "window" in window.getComputedStyle + // because jsdom on node.js will break without it. + if ( window.getComputedStyle ) { + getStyles = function( elem ) { + return window.getComputedStyle( elem, null ); + }; + + curCSS = function( elem, name, _computed ) { + var width, minWidth, maxWidth, + computed = _computed || getStyles( elem ), + // getPropertyValue is only needed for .css('filter') in IE9, see #12537 + ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined, + style = elem.style; + + if ( computed ) { + + if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + ret = jQuery.style( elem, name ); + } + + // A tribute to the "awesome hack by Dean Edwards" + // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right + // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels + // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values + if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { + + // Remember the original values + width = style.width; + minWidth = style.minWidth; + maxWidth = style.maxWidth; + + // Put in the new values to get a computed value out + style.minWidth = style.maxWidth = style.width = ret; + ret = computed.width; + + // Revert the changed values + style.width = width; + style.minWidth = minWidth; + style.maxWidth = maxWidth; + } + } + + return ret; + }; + } else if ( document.documentElement.currentStyle ) { + getStyles = function( elem ) { + return elem.currentStyle; + }; + + curCSS = function( elem, name, _computed ) { + var left, rs, rsLeft, + computed = _computed || getStyles( elem ), + ret = computed ? computed[ name ] : undefined, + style = elem.style; + + // Avoid setting ret to empty string here + // so we don't default to auto + if ( ret == null && style && style[ name ] ) { + ret = style[ name ]; + } + + // From the awesome hack by Dean Edwards + // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 + + // If we're not dealing with a regular pixel number + // but a number that has a weird ending, we need to convert it to pixels + // but not position css attributes, as those are proportional to the parent element instead + // and we can't measure the parent instead because it might trigger a "stacking dolls" problem + if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { + + // Remember the original values + left = style.left; + rs = elem.runtimeStyle; + rsLeft = rs && rs.left; + + // Put in the new values to get a computed value out + if ( rsLeft ) { + rs.left = elem.currentStyle.left; + } + style.left = name === "fontSize" ? "1em" : ret; + ret = style.pixelLeft + "px"; + + // Revert the changed values + style.left = left; + if ( rsLeft ) { + rs.left = rsLeft; + } + } + + return ret === "" ? "auto" : ret; + }; + } + + function setPositiveNumber( elem, value, subtract ) { + var matches = rnumsplit.exec( value ); + return matches ? + // Guard against undefined "subtract", e.g., when used as in cssHooks + Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : + value; + } + + function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) { + var i = extra === ( isBorderBox ? "border" : "content" ) ? + // If we already have the right measurement, avoid augmentation + 4 : + // Otherwise initialize for horizontal or vertical properties + name === "width" ? 1 : 0, + val = 0; + + for ( ; i < 4; i += 2 ) { + // both box models exclude margin, so add it if we want it + if ( extra === "margin" ) { + val += jQuery.css( elem, extra + cssExpand[ i ], true, styles ); + } + + if ( isBorderBox ) { + // border-box includes padding, so remove it if we want content + if ( extra === "content" ) { + val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + } + + // at this point, extra isn't border nor margin, so remove border + if ( extra !== "margin" ) { + val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } else { + // at this point, extra isn't content, so add padding + val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles ); + + // at this point, extra isn't content nor padding, so add border + if ( extra !== "padding" ) { + val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles ); + } + } + } + + return val; + } + + function getWidthOrHeight( elem, name, extra ) { + + // Start with offset property, which is equivalent to the border-box value + var valueIsBorderBox = true, + val = name === "width" ? elem.offsetWidth : elem.offsetHeight, + styles = getStyles( elem ), + isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; + + // some non-html elements return undefined for offsetWidth, so check for null/undefined + // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 + // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 + if ( val <= 0 || val == null ) { + // Fall back to computed then uncomputed css if necessary + val = curCSS( elem, name, styles ); + if ( val < 0 || val == null ) { + val = elem.style[ name ]; + } + + // Computed unit is not pixels. Stop here and return. + if ( rnumnonpx.test(val) ) { + return val; + } + + // we need the check for style in case a browser which returns unreliable values + // for getComputedStyle silently falls back to the reliable elem.style + valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); + + // Normalize "", auto, and prepare for extra + val = parseFloat( val ) || 0; + } + + // use the active box-sizing model to add/subtract irrelevant styles + return ( val + + augmentWidthOrHeight( + elem, + name, + extra || ( isBorderBox ? "border" : "content" ), + valueIsBorderBox, + styles + ) + ) + "px"; + } + + // Try to determine the default display value of an element + function css_defaultDisplay( nodeName ) { + var doc = document, + display = elemdisplay[ nodeName ]; + + if ( !display ) { + display = actualDisplay( nodeName, doc ); + + // If the simple way fails, read from inside an iframe + if ( display === "none" || !display ) { + // Use the already-created iframe if possible + iframe = ( iframe || + jQuery(" + + + + + + + diff --git a/libraries/webInterface/views/layouts/main.handlebars b/libraries/webInterface/views/layouts/main.handlebars new file mode 100644 index 0000000..4390384 --- /dev/null +++ b/libraries/webInterface/views/layouts/main.handlebars @@ -0,0 +1,19 @@ + + + + + Reality + + + + + + + {{{body}}} + + diff --git a/logicDefinition.md b/logicDefinition.md new file mode 100644 index 0000000..058603f --- /dev/null +++ b/logicDefinition.md @@ -0,0 +1,100 @@ +### Behaviour + +Links can connect to the logic block at a specific color.
+Within the logic node blocks can be moved around. + + +Therefore, logic nodes are a special kind of nodes. + + + + // defines if IO-Point is a logic block + this.isBlock = false; + + ``` +var testA = ""; +var testB = false; +var result = false; +var counter = 0; +var time = new Date().getTime(); + +while(counter < 100000000){ + if(testA===null){ + result = true; + }else { + result = false; + } + counter++; +} +console.log("long null: " + parseInt(new Date().getTime()-time)); + +var testA = true; +var testB = false; +var result = false; +var counter = 0; +var time = new Date().getTime(); + +while(counter < 100000000){ + if(testA===true){ + result = true; + }else { + result = false; + } + counter++; +} +console.log("long bool: "+ parseInt(new Date().getTime()-time)); + + +var testA = true; +var testA = "2312123"; +var result = false; +var counter = 0; +var time = new Date().getTime(); + +while(counter < 100000000){ + if(testA===""){ + result = true; + }else { + result = false; + } + counter++; +} +console.log("string: "+ parseInt(new Date().getTime()-time)); + +var testA = true; +var testA = 231223213; +var result = 23231; +var counter = 0; +var time = new Date().getTime(); + +while(counter < 100000000){ + if(testA===11){ + result = true; + }else { + result = false; + } + counter++; +} +console.log("short int: "+ parseInt(new Date().getTime()-time)); + + +var testA = true; +var testA = 231223213213213123123123223; +var result = 23231; +var counter = 0; +var time = new Date().getTime(); + +while(counter < 100000000){ + if(testA===11){ + result = true; + }else { + result = false; + } + counter++; +} +console.log("long int: "+ parseInt(new Date().getTime()-time)); + + + + +``` \ No newline at end of file diff --git a/objects/6AxisScripts/6AxisScripts.js b/objects/6AxisScripts/6AxisScripts.js new file mode 100644 index 0000000..f411f0a --- /dev/null +++ b/objects/6AxisScripts/6AxisScripts.js @@ -0,0 +1,107 @@ +function scaleData(data){ + //data is a JSON object that dependent on the interface might contain: pitch,yaw,roll,height,touchX,touchY + // its job is to take this data and scale it between 0 and 1 + var scaledData = {}; + if(data.pitch) + scaledData.pitch = map(data.pitch.value-data.pitch.init,-1,1,0,1); + if(data.yaw){ + var yaw = data.yaw.value; + yaw = scaleYaw(yaw); + var init_yaw = scaleYaw(data.yaw.init); + scaledData.yaw=map(yaw-init_yaw+.5,0,1,0,1); + } + if(data.roll){ + var roll = scaleRoll(data.roll.value); + var init_roll = scaleRoll(data.roll.init); + scaledData.roll=map(roll-init_roll+.5,0,1,0,1); + } + if(data.height){ + var height = (((10001-(20000/data.height.value))/9999)+1)/2; + height = map(height,.9971,1,0,1); + var init_height = (((10001-(20000/data.height.init))/9999)+1)/2; + init_height = map(init_height,.9971,1,0,1); + scaledData.height=map(height-init_height+.5,0,1,0,1); + } + if(data.touchX){ + scaledData.touchX = map(data.touchX.value-data.touchX.init,-350,350,0,1); + } + if(data.touchY){ + scaledData.touchY = map(data.touchY.value-data.touchY.init,-350,350,0,1); + } + return scaledData; +} + +function scaleYaw(value){ + if(value>0 && value 1 || sharpness < 0) + sharpness = .5; + if(max_value > 1 || max_value < 0) + max_value = .5; + value = (value-1/2)*2; + if(negate) + value *= -1; + if(Math.abs(value)>error){ + if(mapping_type == "exponential") + speed = mapExponential(Math.abs(value),sharpness,max_value); + else if(mapping_type == "linear") + speed = mapLinear(Math.abs(value),sharpness,max_value); + else + speed = mapLogistic(Math.abs(value),sharpness,max_value); + } + speed *= value/Math.abs(value); + + hybridObj.write(ioPoint,map(speed,-1,1,0,1)); +} + +function mapExponential(value,sharpness,max_value){ + var scale = 5+(sharpness-.5)*7; + return max_value*(1-Math.pow(Math.E,-scale*value)); +} +function mapLinear(value,sharpness,max_value){ + var value = (1+2*(sharpness-.5))*value; + if(value > max_value) + value = max_value; + return value; +} +function mapLogistic(value,sharpness,max_value){ + var scale = 10+(sharpness-.5)*10; + return max_value/(1+Math.pow(Math.E,-scale*(value-.5))); +} +function map(x, in_min, in_max, out_min,out_max) { + if (x > in_max) x = in_max; + if (x < in_min) x = in_min; + return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; +} \ No newline at end of file diff --git a/objects/6AxisScripts/bird.png b/objects/6AxisScripts/bird.png new file mode 100755 index 0000000..9a5a9be Binary files /dev/null and b/objects/6AxisScripts/bird.png differ diff --git a/objects/Gripper6AxisEV3/bird.png b/objects/Gripper6AxisEV3/bird.png new file mode 100755 index 0000000..9a5a9be Binary files /dev/null and b/objects/Gripper6AxisEV3/bird.png differ diff --git a/objects/Gripper6AxisEV3/index.html b/objects/Gripper6AxisEV3/index.html new file mode 100644 index 0000000..e0a4617 --- /dev/null +++ b/objects/Gripper6AxisEV3/index.html @@ -0,0 +1,233 @@ + + + + +EV3 + + + + + +
+
+ +
+
+ + + \ No newline at end of file diff --git a/objects/Gripper6AxisEV3/object.json b/objects/Gripper6AxisEV3/object.json new file mode 100644 index 0000000..78ebe90 --- /dev/null +++ b/objects/Gripper6AxisEV3/object.json @@ -0,0 +1,315 @@ +{ + "objectId": "Gripper6AxisEV3a1a22x6p9s3m", + "name": "Gripper6AxisEV3", + "ip": "192.168.1.7", + "version": "1.7.0", + "protocol": "R1", + "tcs": "1Y82mv", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": {}, + "links": { + "ya1gnxzr": { + "objectA": "Gripper6AxisEV3a1a22x6p9s3m", + "objectB": "Gripper6AxisEV3a1a22x6p9s3m", + "nodeA": "Gripper6AxisEV3a1a22x6p9s3mroll", + "nodeB": "Gripper6AxisEV3a1a22x6p9s3mGrip Tilt", + "logicA": false, + "logicB": false, + "namesA": [ + "Gripper6AxisEV3", + "roll" + ], + "namesB": [ + "Gripper6AxisEV3", + "Grip Tilt" + ], + "loop": false + }, + "Oi0ztecf": { + "objectA": "Gripper6AxisEV3a1a22x6p9s3m", + "objectB": "Gripper6AxisEV3a1a22x6p9s3m", + "nodeA": "Gripper6AxisEV3a1a22x6p9s3mpitch", + "nodeB": "Gripper6AxisEV3a1a22x6p9s3mGrip Rotation", + "logicA": false, + "logicB": false, + "namesA": [ + "Gripper6AxisEV3", + "pitch" + ], + "namesB": [ + "Gripper6AxisEV3", + "Grip Rotation" + ], + "loop": false + }, + "q6w47a4f": { + "objectA": "Gripper6AxisEV3a1a22x6p9s3m", + "objectB": "Gripper6AxisEV3a1a22x6p9s3m", + "nodeA": "Gripper6AxisEV3a1a22x6p9s3mHeight Tracking", + "nodeB": "Gripper6AxisEV3a1a22x6p9s3mkickback joint tilt", + "logicA": false, + "logicB": false, + "namesA": [ + "Gripper6AxisEV3", + "Height Tracking" + ], + "namesB": [ + "Gripper6AxisEV3", + "kickback joint tilt" + ], + "loop": false + }, + "jxqm8pr3": { + "objectA": "Gripper6AxisEV3a1a22x6p9s3m", + "objectB": "Gripper6AxisEV3a1a22x6p9s3m", + "nodeA": "Gripper6AxisEV3a1a22x6p9s3mkickback joint tilt", + "nodeB": "Gripper6AxisEV3a1a22x6p9s3mUpper Tilt + Top Joint", + "logicA": false, + "logicB": false, + "namesA": [ + "Gripper6AxisEV3", + "kickback joint tilt" + ], + "namesB": [ + "Gripper6AxisEV3", + "Upper Tilt + Top Joint" + ], + "loop": false + }, + "zrXkgfpj": { + "objectA": "Gripper6AxisEV3a1a22x6p9s3m", + "objectB": "RightBase6AxisEV3V78ogdk6csbe", + "nodeA": "Gripper6AxisEV3a1a22x6p9s3mHorizontal Touch", + "nodeB": "RightBase6AxisEV3V78ogdk6csbeBase Rotation", + "logicA": false, + "logicB": false, + "namesA": [ + "Gripper6AxisEV3", + "Horizontal Touch" + ], + "namesB": [ + "RightBase6AxisEV3", + "Base Rotation" + ], + "loop": false + }, + "0NF1tag9": { + "objectA": "Gripper6AxisEV3a1a22x6p9s3m", + "objectB": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "nodeA": "Gripper6AxisEV3a1a22x6p9s3mVertical Touch", + "nodeB": "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm + shoulder", + "logicA": false, + "logicB": false, + "namesA": [ + "Gripper6AxisEV3", + "Vertical Touch" + ], + "namesB": [ + "RightUpperTilt6AxisEV3", + "kickback arm + shoulder" + ], + "loop": false + } + }, + "nodes": { + "Gripper6AxisEV3a1a22x6p9s3mVertical Touch": { + "name": "Vertical Touch", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 206.33318058931354, + "y": -219.58932768143177, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "Gripper6AxisEV3a1a22x6p9s3mHorizontal Touch": { + "name": "Horizontal Touch", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 286.34371729911595, + "y": 234.17319305738692, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "Gripper6AxisEV3a1a22x6p9s3mpitch": { + "name": "pitch", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -326.09581366211023, + "y": 0.01635377259526649, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "Gripper6AxisEV3a1a22x6p9s3mHeight Tracking": { + "name": "Height Tracking", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 405.910473623587, + "y": 10.225202127854573, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "Gripper6AxisEV3a1a22x6p9s3mroll": { + "name": "roll", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -269.02284327182906, + "y": 230.94073829488525, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "Gripper6AxisEV3a1a22x6p9s3mUpper Tilt + Top Joint": { + "name": "Upper Tilt + Top Joint", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -30.702437297203232, + "y": -224.20098426852292, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "Gripper6AxisEV3a1a22x6p9s3mGrip Rotation": { + "name": "Grip Rotation", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -103.46392104317124, + "y": 3.552950305227114, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "Gripper6AxisEV3a1a22x6p9s3mGrip Tilt": { + "name": "Grip Tilt", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 154.76352955665993, + "y": -13.788654253356526, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "Gripper6AxisEV3a1a22x6p9s3mgrab": { + "name": "grab", + "data": + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": -6.5617496283020955, + "y": 233.9308623102952, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "Gripper6AxisEV3a1a22x6p9s3mkickback joint tilt": { + "name": "kickback joint tilt", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -274.72902860564864, + "y": -223.52884918892732, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + } + }, + "logic": {}, + "deactivated": true +} \ No newline at end of file diff --git a/objects/Gripper6AxisEV3/target/target.dat b/objects/Gripper6AxisEV3/target/target.dat new file mode 100644 index 0000000..8bb9806 Binary files /dev/null and b/objects/Gripper6AxisEV3/target/target.dat differ diff --git a/objects/Gripper6AxisEV3/target/target.jpg b/objects/Gripper6AxisEV3/target/target.jpg new file mode 100644 index 0000000..6bb60be Binary files /dev/null and b/objects/Gripper6AxisEV3/target/target.jpg differ diff --git a/objects/Gripper6AxisEV3/target/target.xml b/objects/Gripper6AxisEV3/target/target.xml new file mode 100644 index 0000000..21c792b --- /dev/null +++ b/objects/Gripper6AxisEV3/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/README.md b/objects/README.md new file mode 100644 index 0000000..e69de29 diff --git a/objects/RightBase6AxisEV3/bird.png b/objects/RightBase6AxisEV3/bird.png new file mode 100755 index 0000000..9a5a9be Binary files /dev/null and b/objects/RightBase6AxisEV3/bird.png differ diff --git a/objects/RightBase6AxisEV3/index.html b/objects/RightBase6AxisEV3/index.html new file mode 100644 index 0000000..6973357 --- /dev/null +++ b/objects/RightBase6AxisEV3/index.html @@ -0,0 +1,119 @@ + + + + +EV3 + + + + + + + + + \ No newline at end of file diff --git a/objects/RightBase6AxisEV3/object.json b/objects/RightBase6AxisEV3/object.json new file mode 100644 index 0000000..5437002 --- /dev/null +++ b/objects/RightBase6AxisEV3/object.json @@ -0,0 +1,169 @@ +{ + "objectId": "RightBase6AxisEV3V78ogdk6csbe", + "name": "RightBase6AxisEV3", + "ip": "192.168.1.7", + "version": "1.7.0", + "protocol": "R1", + "tcs": "37RBTH", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": {}, + "links": { + "pAy2ur6o": { + "objectA": "RightBase6AxisEV3V78ogdk6csbe", + "objectB": "RightBase6AxisEV3V78ogdk6csbe", + "nodeA": "RightBase6AxisEV3V78ogdk6csbeyaw_br", + "nodeB": "RightBase6AxisEV3V78ogdk6csbekickback_br", + "logicA": false, + "logicB": false, + "namesA": [ + "RightBase6AxisEV3", + "yaw_br" + ], + "namesB": [ + "RightBase6AxisEV3", + "kickback_br" + ], + "loop": false + }, + "DK237m5c": { + "objectA": "RightBase6AxisEV3V78ogdk6csbe", + "objectB": "RightBase6AxisEV3V78ogdk6csbe", + "nodeA": "RightBase6AxisEV3V78ogdk6csbekickback_br", + "nodeB": "RightBase6AxisEV3V78ogdk6csbeBase Joint", + "logicA": false, + "logicB": false, + "namesA": [ + "RightBase6AxisEV3", + "kickback_br" + ], + "namesB": [ + "RightBase6AxisEV3", + "Base Joint" + ], + "loop": false + }, + "CLE18o4w": { + "objectA": "RightBase6AxisEV3V78ogdk6csbe", + "objectB": "RightBase6AxisEV3V78ogdk6csbe", + "nodeA": "RightBase6AxisEV3V78ogdk6csbepitch_br", + "nodeB": "RightBase6AxisEV3V78ogdk6csbeBase Rotation", + "logicA": false, + "logicB": false, + "namesA": [ + "RightBase6AxisEV3", + "pitch_br" + ], + "namesB": [ + "RightBase6AxisEV3", + "Base Rotation" + ], + "loop": false + } + }, + "nodes": { + "RightBase6AxisEV3V78ogdk6csbepitch_br": { + "name": "pitch_br", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -34.562140854916606, + "y": 209.0208681513036, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightBase6AxisEV3V78ogdk6csbeyaw_br": { + "name": "yaw_br", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -225.25660222641795, + "y": -24.14846670326915, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightBase6AxisEV3V78ogdk6csbekickback_br": { + "name": "kickback_br", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -42.5185107637335, + "y": -246.0857776650264, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightBase6AxisEV3V78ogdk6csbeBase Rotation": { + "name": "Base Rotation", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 210.3759909620992, + "y": -27.577658586246343, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightBase6AxisEV3V78ogdk6csbeBase Joint": { + "name": "Base Joint", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -11.81385061100491, + "y": -23.402863490473464, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + } + }, + "logic": {}, + "deactivated": true +} \ No newline at end of file diff --git a/objects/RightBase6AxisEV3/style.css b/objects/RightBase6AxisEV3/style.css new file mode 100644 index 0000000..7687c5c --- /dev/null +++ b/objects/RightBase6AxisEV3/style.css @@ -0,0 +1,4 @@ +#interface{ + -webkit-touch-callout: none; + opacity: 1; +} \ No newline at end of file diff --git a/objects/RightBase6AxisEV3/target/target.dat b/objects/RightBase6AxisEV3/target/target.dat new file mode 100644 index 0000000..bc24336 Binary files /dev/null and b/objects/RightBase6AxisEV3/target/target.dat differ diff --git a/objects/RightBase6AxisEV3/target/target.jpg b/objects/RightBase6AxisEV3/target/target.jpg new file mode 100644 index 0000000..c372cf8 Binary files /dev/null and b/objects/RightBase6AxisEV3/target/target.jpg differ diff --git a/objects/RightBase6AxisEV3/target/target.xml b/objects/RightBase6AxisEV3/target/target.xml new file mode 100644 index 0000000..32e5ce4 --- /dev/null +++ b/objects/RightBase6AxisEV3/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/RightShoulder6AxisEV3/bird.png b/objects/RightShoulder6AxisEV3/bird.png new file mode 100755 index 0000000..9a5a9be Binary files /dev/null and b/objects/RightShoulder6AxisEV3/bird.png differ diff --git a/objects/RightShoulder6AxisEV3/index.html b/objects/RightShoulder6AxisEV3/index.html new file mode 100644 index 0000000..8c6238c --- /dev/null +++ b/objects/RightShoulder6AxisEV3/index.html @@ -0,0 +1,130 @@ + + + + + EV3 + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/objects/RightShoulder6AxisEV3/object.json b/objects/RightShoulder6AxisEV3/object.json new file mode 100644 index 0000000..a3d0625 --- /dev/null +++ b/objects/RightShoulder6AxisEV3/object.json @@ -0,0 +1,95 @@ +{ + "objectId": "RightShoulder6AxisEV35Z5j0vl9jkf1", + "name": "RightShoulder6AxisEV3", + "ip": "192.168.1.7", + "version": "1.7.0", + "protocol": "R1", + "tcs": "2uTHPQ", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": {}, + "links": { + "JpOZ15sv": { + "objectA": "RightShoulder6AxisEV35Z5j0vl9jkf1", + "objectB": "RightBase6AxisEV3V78ogdk6csbe", + "nodeA": "RightShoulder6AxisEV35Z5j0vl9jkf1pitch_sr", + "nodeB": "RightBase6AxisEV3V78ogdk6csbeBase Rotation", + "logicA": false, + "logicB": false, + "namesA": [ + "RightShoulder6AxisEV3", + "pitch_sr" + ], + "namesB": [ + "RightBase6AxisEV3", + "Base Rotation" + ], + "loop": false + }, + "Mzwzvgf3": { + "objectA": "RightShoulder6AxisEV35Z5j0vl9jkf1", + "objectB": "RightBase6AxisEV3V78ogdk6csbe", + "nodeA": "RightShoulder6AxisEV35Z5j0vl9jkf1Horizontal Touch_sr", + "nodeB": "RightBase6AxisEV3V78ogdk6csbekickback_br", + "logicA": false, + "logicB": false, + "namesA": [ + "RightShoulder6AxisEV3", + "Horizontal Touch_sr" + ], + "namesB": [ + "RightBase6AxisEV3", + "kickback_br" + ], + "loop": false + } + }, + "nodes": { + "RightShoulder6AxisEV35Z5j0vl9jkf1Horizontal Touch_sr": { + "name": "Horizontal Touch_sr", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 106.7825790514363, + "y": -5.291976945324677, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightShoulder6AxisEV35Z5j0vl9jkf1pitch_sr": { + "name": "pitch_sr", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -117.67724213327551, + "y": -3.7922077912494387, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + } + }, + "logic": {}, + "deactivated": true +} \ No newline at end of file diff --git a/objects/RightShoulder6AxisEV3/target/target.dat b/objects/RightShoulder6AxisEV3/target/target.dat new file mode 100644 index 0000000..28570fc Binary files /dev/null and b/objects/RightShoulder6AxisEV3/target/target.dat differ diff --git a/objects/RightShoulder6AxisEV3/target/target.jpg b/objects/RightShoulder6AxisEV3/target/target.jpg new file mode 100644 index 0000000..64c2b74 Binary files /dev/null and b/objects/RightShoulder6AxisEV3/target/target.jpg differ diff --git a/objects/RightShoulder6AxisEV3/target/target.xml b/objects/RightShoulder6AxisEV3/target/target.xml new file mode 100644 index 0000000..2d076ec --- /dev/null +++ b/objects/RightShoulder6AxisEV3/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/RightUpperTilt6AxisEV3/bird.png b/objects/RightUpperTilt6AxisEV3/bird.png new file mode 100755 index 0000000..9a5a9be Binary files /dev/null and b/objects/RightUpperTilt6AxisEV3/bird.png differ diff --git a/objects/RightUpperTilt6AxisEV3/index.html b/objects/RightUpperTilt6AxisEV3/index.html new file mode 100644 index 0000000..d6810d7 --- /dev/null +++ b/objects/RightUpperTilt6AxisEV3/index.html @@ -0,0 +1,138 @@ + + + + +EV3 + + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/objects/RightUpperTilt6AxisEV3/object.json b/objects/RightUpperTilt6AxisEV3/object.json new file mode 100644 index 0000000..e060f97 --- /dev/null +++ b/objects/RightUpperTilt6AxisEV3/object.json @@ -0,0 +1,241 @@ +{ + "objectId": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "name": "RightUpperTilt6AxisEV3", + "ip": "192.168.1.7", + "version": "1.7.0", + "protocol": "R1", + "tcs": "fvRhP", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": {}, + "links": { + "1N91vo3l": { + "objectA": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "objectB": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "nodeA": "RightUpperTilt6AxisEV3SEc0z3n53s8kyaw_ur", + "nodeB": "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm", + "logicA": false, + "logicB": false, + "namesA": [ + "RightUpperTilt6AxisEV3", + "yaw_ur" + ], + "namesB": [ + "RightUpperTilt6AxisEV3", + "kickback arm" + ], + "loop": false + }, + "HNV3ltr5": { + "objectA": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "objectB": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "nodeA": "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm", + "nodeB": "RightUpperTilt6AxisEV3SEc0z3n53s8kUpper Tilt", + "logicA": false, + "logicB": false, + "namesA": [ + "RightUpperTilt6AxisEV3", + "kickback arm" + ], + "namesB": [ + "RightUpperTilt6AxisEV3", + "Upper Tilt" + ], + "loop": false + }, + "G9Lhhq9d": { + "objectA": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "objectB": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "nodeA": "RightUpperTilt6AxisEV3SEc0z3n53s8kHorizontal Touch_ur", + "nodeB": "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm + shoulder", + "logicA": false, + "logicB": false, + "namesA": [ + "RightUpperTilt6AxisEV3", + "Horizontal Touch_ur" + ], + "namesB": [ + "RightUpperTilt6AxisEV3", + "kickback arm + shoulder" + ], + "loop": false + }, + "Pa8a3l01": { + "objectA": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "objectB": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "nodeA": "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm + shoulder", + "nodeB": "RightUpperTilt6AxisEV3SEc0z3n53s8kArm + Shoulder", + "logicA": false, + "logicB": false, + "namesA": [ + "RightUpperTilt6AxisEV3", + "kickback arm + shoulder" + ], + "namesB": [ + "RightUpperTilt6AxisEV3", + "Arm + Shoulder" + ], + "loop": false + }, + "dLNLe3ux": { + "objectA": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "objectB": "RightBase6AxisEV3V78ogdk6csbe", + "nodeA": "RightUpperTilt6AxisEV3SEc0z3n53s8kpitch_ur", + "nodeB": "RightBase6AxisEV3V78ogdk6csbeBase Rotation", + "logicA": false, + "logicB": false, + "namesA": [ + "RightUpperTilt6AxisEV3", + "pitch_ur" + ], + "namesB": [ + "RightBase6AxisEV3", + "Base Rotation" + ], + "loop": false + } + }, + "nodes": { + "RightUpperTilt6AxisEV3SEc0z3n53s8kyaw_ur": { + "name": "yaw_ur", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -215.9151544441786, + "y": -238.5340853047328, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightUpperTilt6AxisEV3SEc0z3n53s8kHorizontal Touch_ur": { + "name": "Horizontal Touch_ur", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 0.9060758220641674, + "y": 228.96103898169895, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightUpperTilt6AxisEV3SEc0z3n53s8kpitch_ur": { + "name": "pitch_ur", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 237.03606980428071, + "y": -248.83487882365807, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightUpperTilt6AxisEV3SEc0z3n53s8kUpper Tilt": { + "name": "Upper Tilt", + "data": + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 10.968422144942451, + "y": -242.12576298051863, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightUpperTilt6AxisEV3SEc0z3n53s8kArm + Shoulder": { + "name": "Arm + Shoulder", + "data": + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 3.8800656703056795, + "y": -5.857709178559162, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm": { + "name": "kickback arm", + "data": + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 234.66231564725035, + "y": -13.753471714702755, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm + shoulder": { + "name": "kickback arm + shoulder", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 225.7385301214997, + "y": 238.7631017196327, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + } + }, + "logic": {}, + "deactivated": true +} \ No newline at end of file diff --git a/objects/RightUpperTilt6AxisEV3/target/target.dat b/objects/RightUpperTilt6AxisEV3/target/target.dat new file mode 100644 index 0000000..867499f Binary files /dev/null and b/objects/RightUpperTilt6AxisEV3/target/target.dat differ diff --git a/objects/RightUpperTilt6AxisEV3/target/target.jpg b/objects/RightUpperTilt6AxisEV3/target/target.jpg new file mode 100644 index 0000000..0756b32 Binary files /dev/null and b/objects/RightUpperTilt6AxisEV3/target/target.jpg differ diff --git a/objects/RightUpperTilt6AxisEV3/target/target.xml b/objects/RightUpperTilt6AxisEV3/target/target.xml new file mode 100644 index 0000000..e2ade55 --- /dev/null +++ b/objects/RightUpperTilt6AxisEV3/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/TopForearm6AxisEV3/bird.png b/objects/TopForearm6AxisEV3/bird.png new file mode 100755 index 0000000..9a5a9be Binary files /dev/null and b/objects/TopForearm6AxisEV3/bird.png differ diff --git a/objects/TopForearm6AxisEV3/index.html b/objects/TopForearm6AxisEV3/index.html new file mode 100644 index 0000000..8db9649 --- /dev/null +++ b/objects/TopForearm6AxisEV3/index.html @@ -0,0 +1,174 @@ + + + + +EV3 + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/objects/TopForearm6AxisEV3/object.json b/objects/TopForearm6AxisEV3/object.json new file mode 100644 index 0000000..044aabc --- /dev/null +++ b/objects/TopForearm6AxisEV3/object.json @@ -0,0 +1,186 @@ +{ + "objectId": "TopForearm6AxisEV3Zg1zey40sedb", + "name": "TopForearm6AxisEV3", + "ip": "192.168.1.7", + "version": "1.7.0", + "protocol": "R1", + "tcs": "2eegD3", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": {}, + "links": { + "cwW2lhvt": { + "objectA": "TopForearm6AxisEV3Zg1zey40sedb", + "objectB": "TopForearm6AxisEV3Zg1zey40sedb", + "nodeA": "TopForearm6AxisEV3Zg1zey40sedbpitch_ft", + "nodeB": "TopForearm6AxisEV3Zg1zey40sedbForearm Rotation", + "logicA": false, + "logicB": false, + "namesA": [ + "TopForearm6AxisEV3", + "pitch_ft" + ], + "namesB": [ + "TopForearm6AxisEV3", + "Forearm Rotation" + ], + "loop": false + }, + "6tg4mdc9": { + "objectA": "TopForearm6AxisEV3Zg1zey40sedb", + "objectB": "RightBase6AxisEV3V78ogdk6csbe", + "nodeA": "TopForearm6AxisEV3Zg1zey40sedbHorizontal Touch_ft", + "nodeB": "RightBase6AxisEV3V78ogdk6csbeBase Rotation", + "logicA": false, + "logicB": false, + "namesA": [ + "TopForearm6AxisEV3", + "Horizontal Touch_ft" + ], + "namesB": [ + "RightBase6AxisEV3", + "Base Rotation" + ], + "loop": false + }, + "Z8E2q7mx": { + "objectA": "TopForearm6AxisEV3Zg1zey40sedb", + "objectB": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "nodeA": "TopForearm6AxisEV3Zg1zey40sedbHeight Tracking_ft", + "nodeB": "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm + shoulder", + "logicA": false, + "logicB": false, + "namesA": [ + "TopForearm6AxisEV3", + "Height Tracking_ft" + ], + "namesB": [ + "RightUpperTilt6AxisEV3", + "kickback arm + shoulder" + ], + "loop": false + }, + "qqekjkm9": { + "objectA": "TopForearm6AxisEV3Zg1zey40sedb", + "objectB": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "nodeA": "TopForearm6AxisEV3Zg1zey40sedbVertical Touch_ft", + "nodeB": "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm", + "logicA": false, + "logicB": false, + "namesA": [ + "TopForearm6AxisEV3", + "Vertical Touch_ft" + ], + "namesB": [ + "RightUpperTilt6AxisEV3", + "kickback arm" + ], + "loop": false + } + }, + "nodes": { + "TopForearm6AxisEV3Zg1zey40sedbVertical Touch_ft": { + "name": "Vertical Touch_ft", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 214.08931154948823, + "y": -222.48640425469776, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "TopForearm6AxisEV3Zg1zey40sedbHorizontal Touch_ft": { + "name": "Horizontal Touch_ft", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 217.2911131724809, + "y": 7.051890307712743, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "TopForearm6AxisEV3Zg1zey40sedbpitch_ft": { + "name": "pitch_ft", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -267.15985765170717, + "y": -36.419472009315285, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "TopForearm6AxisEV3Zg1zey40sedbHeight Tracking_ft": { + "name": "Height Tracking_ft", + "data": + { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -267.8587811071443, + "y": -258.374723705767, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "TopForearm6AxisEV3Zg1zey40sedbForearm Rotation": { + "name": "Forearm Rotation", + "data": + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": -10.489539590570075, + "y": -5.555897214325782, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + } + }, + "logic": {}, + "deactivated": true +} \ No newline at end of file diff --git a/objects/TopForearm6AxisEV3/target/target.dat b/objects/TopForearm6AxisEV3/target/target.dat new file mode 100644 index 0000000..8851cab Binary files /dev/null and b/objects/TopForearm6AxisEV3/target/target.dat differ diff --git a/objects/TopForearm6AxisEV3/target/target.jpg b/objects/TopForearm6AxisEV3/target/target.jpg new file mode 100644 index 0000000..06ea631 Binary files /dev/null and b/objects/TopForearm6AxisEV3/target/target.jpg differ diff --git a/objects/TopForearm6AxisEV3/target/target.xml b/objects/TopForearm6AxisEV3/target/target.xml new file mode 100644 index 0000000..a61c086 --- /dev/null +++ b/objects/TopForearm6AxisEV3/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/TopUpperTilt6AxisEV3/bird.png b/objects/TopUpperTilt6AxisEV3/bird.png new file mode 100755 index 0000000..9a5a9be Binary files /dev/null and b/objects/TopUpperTilt6AxisEV3/bird.png differ diff --git a/objects/TopUpperTilt6AxisEV3/index.html b/objects/TopUpperTilt6AxisEV3/index.html new file mode 100644 index 0000000..d2d7c7f --- /dev/null +++ b/objects/TopUpperTilt6AxisEV3/index.html @@ -0,0 +1,140 @@ + + + + +EV3 + + + + + + +
+ +
+ + + \ No newline at end of file diff --git a/objects/TopUpperTilt6AxisEV3/object.json b/objects/TopUpperTilt6AxisEV3/object.json new file mode 100644 index 0000000..17d8193 --- /dev/null +++ b/objects/TopUpperTilt6AxisEV3/object.json @@ -0,0 +1,131 @@ +{ + "objectId": "TopUpperTilt6AxisEV36pb1j09z64s3", + "name": "TopUpperTilt6AxisEV3", + "ip": "192.168.1.7", + "version": "1.7.0", + "protocol": "R1", + "tcs": "3TaL1s", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": {}, + "links": { + "qZD3eh3d": { + "objectA": "TopUpperTilt6AxisEV36pb1j09z64s3", + "objectB": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "nodeA": "TopUpperTilt6AxisEV36pb1j09z64s3Vertical Touch_ut", + "nodeB": "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm + shoulder", + "logicA": false, + "logicB": false, + "namesA": [ + "TopUpperTilt6AxisEV3", + "Vertical Touch_ut" + ], + "namesB": [ + "RightUpperTilt6AxisEV3", + "kickback arm + shoulder" + ], + "loop": false + }, + "bxP1zwvl": { + "objectA": "TopUpperTilt6AxisEV36pb1j09z64s3", + "objectB": "RightUpperTilt6AxisEV3SEc0z3n53s8k", + "nodeA": "TopUpperTilt6AxisEV36pb1j09z64s3roll_ut", + "nodeB": "RightUpperTilt6AxisEV3SEc0z3n53s8kkickback arm", + "logicA": false, + "logicB": false, + "namesA": [ + "TopUpperTilt6AxisEV3", + "roll_ut" + ], + "namesB": [ + "RightUpperTilt6AxisEV3", + "kickback arm" + ], + "loop": false + }, + "1sa3ehv5": { + "objectA": "TopUpperTilt6AxisEV36pb1j09z64s3", + "objectB": "RightBase6AxisEV3V78ogdk6csbe", + "nodeA": "TopUpperTilt6AxisEV36pb1j09z64s3yaw_ut", + "nodeB": "RightBase6AxisEV3V78ogdk6csbeBase Rotation", + "logicA": false, + "logicB": false, + "namesA": [ + "TopUpperTilt6AxisEV3", + "yaw_ut" + ], + "namesB": [ + "RightBase6AxisEV3", + "Base Rotation" + ], + "loop": false + } + }, + "nodes": { + "TopUpperTilt6AxisEV36pb1j09z64s3yaw_ut": { + "name": "yaw_ut", + "data": + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": -121.45466428718055, + "y": -108.99713154912843, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "TopUpperTilt6AxisEV36pb1j09z64s3Vertical Touch_ut": { + "name": "Vertical Touch_ut", + "data": + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": -9.831676944647825, + "y": 120.20207819455754, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "TopUpperTilt6AxisEV36pb1j09z64s3roll_ut": { + "name": "roll_ut", + "data": + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 109.603623873566, + "y": -112.51306105483991, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + } + }, + "logic": {}, + "deactivated": true +} \ No newline at end of file diff --git a/objects/TopUpperTilt6AxisEV3/target/target.dat b/objects/TopUpperTilt6AxisEV3/target/target.dat new file mode 100644 index 0000000..9e8a443 Binary files /dev/null and b/objects/TopUpperTilt6AxisEV3/target/target.dat differ diff --git a/objects/TopUpperTilt6AxisEV3/target/target.jpg b/objects/TopUpperTilt6AxisEV3/target/target.jpg new file mode 100644 index 0000000..f3f6089 Binary files /dev/null and b/objects/TopUpperTilt6AxisEV3/target/target.jpg differ diff --git a/objects/TopUpperTilt6AxisEV3/target/target.xml b/objects/TopUpperTilt6AxisEV3/target/target.xml new file mode 100644 index 0000000..3a50fda --- /dev/null +++ b/objects/TopUpperTilt6AxisEV3/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/demoTest/bird.png b/objects/demoTest/bird.png new file mode 100644 index 0000000..9a5a9be Binary files /dev/null and b/objects/demoTest/bird.png differ diff --git a/objects/demoTest/index.html b/objects/demoTest/index.html new file mode 100644 index 0000000..d37ce1f --- /dev/null +++ b/objects/demoTest/index.html @@ -0,0 +1,12 @@ + + + + +Default UI + + + + + + + diff --git a/objects/demoTest/memory/memory.jpg b/objects/demoTest/memory/memory.jpg new file mode 100644 index 0000000..72e0a00 Binary files /dev/null and b/objects/demoTest/memory/memory.jpg differ diff --git a/objects/demoTest/memory/memoryThumbnail.jpg b/objects/demoTest/memory/memoryThumbnail.jpg new file mode 100644 index 0000000..56d6b05 Binary files /dev/null and b/objects/demoTest/memory/memoryThumbnail.jpg differ diff --git a/objects/demoTest/object.json b/objects/demoTest/object.json new file mode 100644 index 0000000..7764ce0 --- /dev/null +++ b/objects/demoTest/object.json @@ -0,0 +1,107 @@ +{ + "objectId": "demoTestvs8z3en96db0", + "name": "demoTest", + "ip": "192.168.1.8", + "version": "1.7.0", + "deactivated": false, + "protocol": "R1", + "tcs": null, + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": { + "matrix": [ + -1.000336289405823, + 0.007616966497153044, + -0.04017903655767441, + 0, + 0.004037053789943457, + 0.9960631728172302, + 0.08855444937944412, + 0, + 0.040743138641119, + 0.0883183553814888, + -0.9952607154846191, + 0, + 48.25081253051758, + -146.3660125732422, + 928.7445068359375, + 1 + ] + }, + "links": {}, + "nodes": { + "demoTestvs8z3en96db0distance": { + "name": "distance", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": -184.90116615947773, + "y": 0.7548205706443696, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "demoTestvs8z3en96db0motor": { + "name": "motor", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 193.0976027403667, + "y": -5.664771564354851, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + } + }, + "frames": { + "framess3k4w4xt8bj": { + "src": "bower_components/reality-control-slider-kinetic/index.html", + "x": 538.7165634155099, + "y": -149.7197439333795, + "scale": 1, + "matrix": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "developer": true, + "width": "206", + "height": "526", + "lastEditor": "kK1f5njg", + "loaded": false + } + } +} \ No newline at end of file diff --git a/objects/demoTest/target/target.dat b/objects/demoTest/target/target.dat new file mode 100644 index 0000000..f00fc44 Binary files /dev/null and b/objects/demoTest/target/target.dat differ diff --git a/objects/demoTest/target/target.jpg b/objects/demoTest/target/target.jpg new file mode 100644 index 0000000..b26a6d8 Binary files /dev/null and b/objects/demoTest/target/target.jpg differ diff --git a/objects/demoTest/target/target.xml b/objects/demoTest/target/target.xml new file mode 100644 index 0000000..b581cb9 --- /dev/null +++ b/objects/demoTest/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/knop1/bird.png b/objects/knop1/bird.png new file mode 100644 index 0000000..9a5a9be Binary files /dev/null and b/objects/knop1/bird.png differ diff --git a/objects/knop1/index.html b/objects/knop1/index.html new file mode 100644 index 0000000..b581f8f --- /dev/null +++ b/objects/knop1/index.html @@ -0,0 +1,12 @@ + + + + +Default UI + + + + + + + diff --git a/objects/knop1/object.json b/objects/knop1/object.json new file mode 100644 index 0000000..8998e2a --- /dev/null +++ b/objects/knop1/object.json @@ -0,0 +1,58 @@ +{ + "objectId": "knop1xe35ycj6l5xy", + "name": "knop1", + "ip": "192.168.1.6", + "version": "1.7.0", + "protocol": "R1", + "tcs": "Eq9rz", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": {}, + "links": { + "gmpqxw13": { + "objectA": "knop1xe35ycj6l5xy", + "objectB": "lamp2CH73qpztykp3", + "nodeA": "knop1xe35ycj6l5xyscale", + "nodeB": "lamp2CH73qpztykp3button", + "logicA": false, + "logicB": false, + "namesA": [ + "knop1", + "scale" + ], + "namesB": [ + "lamp2", + "button" + ], + "loop": false + } + }, + "nodes": { + "knop1xe35ycj6l5xyscale": { + "name": "scale", + "data": { + "value": 0.7875, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 93, + "y": -69, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + } + }, + "logic": {}, + "deactivated": true +} \ No newline at end of file diff --git a/objects/knop1/target/target.dat b/objects/knop1/target/target.dat new file mode 100644 index 0000000..233d4c4 Binary files /dev/null and b/objects/knop1/target/target.dat differ diff --git a/objects/knop1/target/target.jpg b/objects/knop1/target/target.jpg new file mode 100644 index 0000000..20c8a73 Binary files /dev/null and b/objects/knop1/target/target.jpg differ diff --git a/objects/knop1/target/target.xml b/objects/knop1/target/target.xml new file mode 100644 index 0000000..1dff198 --- /dev/null +++ b/objects/knop1/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/lamp1/bird.png b/objects/lamp1/bird.png new file mode 100644 index 0000000..9a5a9be Binary files /dev/null and b/objects/lamp1/bird.png differ diff --git a/objects/lamp1/icon_off.svg b/objects/lamp1/icon_off.svg new file mode 100755 index 0000000..22473c5 --- /dev/null +++ b/objects/lamp1/icon_off.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/objects/lamp1/icon_on.svg b/objects/lamp1/icon_on.svg new file mode 100755 index 0000000..bb3df5c --- /dev/null +++ b/objects/lamp1/icon_on.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + diff --git a/objects/lamp1/index.html b/objects/lamp1/index.html new file mode 100755 index 0000000..948f104 --- /dev/null +++ b/objects/lamp1/index.html @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + +
+

50

+ + +
+ + + + + diff --git a/objects/lamp1/knob-min.js b/objects/lamp1/knob-min.js new file mode 100755 index 0000000..b86518b --- /dev/null +++ b/objects/lamp1/knob-min.js @@ -0,0 +1,490 @@ +var Knob; +Knob = function(input, ui) { + var container = document.createElement('div'); + container.setAttribute('tabindex', 0); + input.parentNode.replaceChild(container, input); + input.style.cssText = 'position: absolute; top: -10000px'; + input.setAttribute('tabindex', -1); + container.appendChild(input); + + var settings = this.settings = this._getSettings(input); + + + this.value = input.value = settings.min + settings.range / 2; + this.input = input; + this.min = settings.min; + + this.ui = ui; + input.addEventListener('change', this.changed.bind(this), false); + + var events = { + keydown: this._handleKeyEvents.bind(this), + mousewheel: this._handleWheelEvents.bind(this), + DOMMouseScroll: this._handleWheelEvents.bind(this), + touchstart: this._handleMove.bind(this, 'touchmove', 'touchend'), + mousedown: this._handleMove.bind(this, 'mousemove', 'mouseup') + }; + + for (var event in events) { + container.addEventListener(event, events[event], false); + } + + container.style.cssText = 'position: relative; width:' + settings.width + 'px;' + 'height:' + settings.height + 'px;'; + + ui.init(container, settings); + this.container = container; + this.changed(0); + +}; + +Knob.prototype = { + _handleKeyEvents: function(e) { + var keycode = e.keyCode; + if (keycode >= 37 && keycode <= 40) { + e.preventDefault(); + var f = 1 + e.shiftKey * 9; + this.changed({37: -1, 38: 1, 39: 1, 40: -1}[keycode] * f); + } + }, + + _handleWheelEvents: function(e) { + e.preventDefault(); + var deltaX = -e.detail || e.wheelDeltaX; + var deltaY = -e.detail || e.wheelDeltaY; + var val = deltaX > 0 || deltaY > 0 ? 1 : deltaX < 0 || deltaY < 0 ? -1 : 0; + this.changed(val); + }, + + _handleMove: function(onMove, onEnd) { + this.centerX = Math.floor(this.container.getBoundingClientRect().left)+ document.body.scrollLeft + this.settings.width / 2; + this.centerY = Math.floor(this.container.getBoundingClientRect().top)+ document.body.scrollTop + this.settings.height / 2; + + var fnc = this._updateWhileMoving.bind(this); + var body = document.body; + body.addEventListener(onMove, fnc, false); + body.addEventListener(onEnd, function() { + body.removeEventListener(onMove, fnc, false); + }, false); + }, + + _updateWhileMoving: function(event) { + event.preventDefault(); + var e = event.changedTouches ? event.changedTouches[0] : event; + var x = this.centerX - e.pageX; + var y = this.centerY - e.pageY; + var deg = Math.atan2(-y, -x) * 180 / Math.PI + 90 - this.settings.angleoffset; + var percent; + + if (deg < 0) { + deg += 360; + } + deg = deg % 360; + if (deg <= this.settings.anglerange) { + percent = Math.max(Math.min(1, deg / this.settings.anglerange), 0); + } else { + percent = +(deg - this.settings.anglerange < (360 - this.settings.anglerange) / 2); + } + var range = this.settings.range; + var value = this.min + range * percent; + + var step = (this.settings.max - this.min) / range; + this.value = this.input.value = Math.round(value / step) * step; + this.ui.update(percent, this.value); + }, + + changed: function(direction) { + this.input.value = this.limit(parseFloat(this.input.value) + direction * (this.input.step || 1)); + this.value = this.input.value; + this.ui.update(this._valueToPercent(), this.value); + }, + + + update: function(percent) { + var range = this.settings.range; + var value = this.min + range * percent; + + var step = (this.settings.max - this.min) / range; + this.value = this.input.value = Math.round(value / step) * step; + + + this.ui.update(percent, this.value); + }, + + _valueToPercent: function() { + return this.value != null ? 100 / this.settings.range * (this.value - this.min) / 100 : this.min; + }, + + limit: function(value) { + return Math.min(Math.max(this.settings.min, value), this.settings.max); + }, + + _getSettings: function(input) { + var labels; + + if(input.dataset.labels){ + labels = input.dataset.labels.split(','); + } + var settings = { + max: labels ? labels.length-1 : parseFloat(input.max), + min: labels ? 0 : parseFloat(input.min), + step: parseFloat(input.step) || 1, + angleoffset: 0, + anglerange: 360, + labels: labels + }; + settings.range = settings.max - settings.min; + var data = input.dataset; + for (var i in data) { + if (data.hasOwnProperty(i) && i!=='labels') { + var value = +data[i]; + settings[i] = isNaN(value) ? data[i] : value; + } + } + return settings; + } +}; + + + +var Ui = function() { +}; + +Ui.prototype = { + init: function(parentEl, options) { + this.options || (this.options = {}); + this.merge(this.options, options); + this.width = options.width; + this.height = options.height; + this.createElement(parentEl); + if (!this.components) { + return; + } + this.components.forEach(function(component) { + component.init(this.el.node, options); + }.bind(this)); + }, + + merge: function(dest, src) { + for (var i in src) { + if (src.hasOwnProperty(i)) { + dest[i] = src[i]; + } + } + return dest; + }, + + addComponent: function(component) { + this.components || (this.components = []); + this.components.push(component); + }, + + update: function(percent, value) { + + if (!this.components) { + return; + } + this.components.forEach(function(component) { + component.update(percent, value); + }); + }, + + createElement: function(parentEl) { + this.el = new Ui.El(this.width, this.height); + this.el.create("svg", { + version: "1.2", + baseProfile: "tiny", + width: this.width, + height: this.height + }); + this.appendTo(parentEl); + }, + appendTo: function(parent) { + parent.appendChild(this.el.node); + } + +}; + +Ui.Pointer = function(options) { + this.options = options || {}; + this.options.type && Ui.El[this.options.type] || (this.options.type = 'Triangle'); +}; + +Ui.Pointer.prototype = Object.create(Ui.prototype); + +Ui.Pointer.prototype.update = function(percent) { + this.el.rotate(this.options.angleoffset + percent * this.options.anglerange, this.width / 2, + this.height / 2); +}; + +Ui.Pointer.prototype.createElement = function(parentEl) { + this.options.pointerHeight || (this.options.pointerHeight = this.height / 2); + if (this.options.type == 'Arc') { + this.el = new Ui.El.Arc(this.options); + this.el.setAngle(this.options.size); + } else { + this.el = new Ui.El[this.options.type](this.options.pointerWidth, + this.options.pointerHeight, this.width / 2, + this.options.pointerHeight / 2 + this.options.offset); + } + this.el.addClassName('pointer'); + this.appendTo(parentEl); + +}; + +Ui.Arc = function(options) { + this.options = options || {}; +}; + +Ui.Arc.prototype = Object.create(Ui.prototype); + +Ui.Arc.prototype.createElement = function(parentEl) { + this.el = new Ui.El.Arc(this.options); + this.appendTo(parentEl); +}; + +Ui.Arc.prototype.update = function(percent) { + this.el.setAngle(percent * this.options.anglerange); +}; + +Ui.Scale = function(options) { + this.options = this.merge({ + steps: options.range / options.step, + radius: this.width / 2, + tickWidth: 1, + tickHeight: 3 + }, options); + this.options.type = Ui.El[this.options.type || 'Rect']; +}; + +Ui.Scale.prototype = Object.create(Ui.prototype); + +Ui.Scale.prototype.createElement = function(parentEl) { + this.el = new Ui.El(this.width, this.height); + this.startAngle = this.options.angleoffset || 0; + this.options.radius || (this.options.radius = this.height / 2.5); + this.el.create("g"); + this.el.addClassName('scale'); + if (this.options.drawScale) { + if(!this.options.labels){ + var step = this.options.anglerange / this.options.steps; + var end = this.options.steps + (this.options.anglerange == 360 ? 0 : 1); + this.ticks = []; + var Shape = this.options.type; + for (var i = 0; i < end; i++) { + var rect = new Shape(this.options.tickWidth, this.options.tickHeight, this.width / 2, + this.options.tickHeight / 2); + rect.rotate(this.startAngle + i * step, this.width / 2, this.height / 2); + this.el.append(rect); + this.ticks.push(rect); + } + } + } + this.appendTo(parentEl); + if (this.options.drawDial) { + this.dial(); + } +}; + +Ui.Scale.prototype.dial = function() { + var step = this.options.anglerange / this.options.steps; + var min = this.options.min; + var dialStep = (this.options.max - min) / this.options.steps; + var end = this.options.steps + (this.options.anglerange == 360 ? 0 : 1); + this.dials = []; + if(!this.options.labels){ + for (var i = 0; i < end; i++) { + var text = new Ui.El.Text(Math.abs(min + dialStep * i), this.width / 2 - 2.5, + this.height / 2 - this.options.radius, 5, 5); + this.el.append(text); + text.rotate(this.startAngle + i * step, this.width / 2, this.height / 2); + this.dials.push(text); + } + } else { + step = this.options.anglerange / (this.options.labels.length-1); + for(var i=0; i + + + + + diff --git a/objects/lamp2/bird.png b/objects/lamp2/bird.png new file mode 100644 index 0000000..9a5a9be Binary files /dev/null and b/objects/lamp2/bird.png differ diff --git a/objects/lamp2/icon_off.svg b/objects/lamp2/icon_off.svg new file mode 100755 index 0000000..22473c5 --- /dev/null +++ b/objects/lamp2/icon_off.svg @@ -0,0 +1,19 @@ + + + + + + + + + diff --git a/objects/lamp2/icon_on.svg b/objects/lamp2/icon_on.svg new file mode 100755 index 0000000..bb3df5c --- /dev/null +++ b/objects/lamp2/icon_on.svg @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + diff --git a/objects/lamp2/index.html b/objects/lamp2/index.html new file mode 100644 index 0000000..948f104 --- /dev/null +++ b/objects/lamp2/index.html @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + +
+

50

+ + +
+ + + + + diff --git a/objects/lamp2/knob-min.js b/objects/lamp2/knob-min.js new file mode 100755 index 0000000..b86518b --- /dev/null +++ b/objects/lamp2/knob-min.js @@ -0,0 +1,490 @@ +var Knob; +Knob = function(input, ui) { + var container = document.createElement('div'); + container.setAttribute('tabindex', 0); + input.parentNode.replaceChild(container, input); + input.style.cssText = 'position: absolute; top: -10000px'; + input.setAttribute('tabindex', -1); + container.appendChild(input); + + var settings = this.settings = this._getSettings(input); + + + this.value = input.value = settings.min + settings.range / 2; + this.input = input; + this.min = settings.min; + + this.ui = ui; + input.addEventListener('change', this.changed.bind(this), false); + + var events = { + keydown: this._handleKeyEvents.bind(this), + mousewheel: this._handleWheelEvents.bind(this), + DOMMouseScroll: this._handleWheelEvents.bind(this), + touchstart: this._handleMove.bind(this, 'touchmove', 'touchend'), + mousedown: this._handleMove.bind(this, 'mousemove', 'mouseup') + }; + + for (var event in events) { + container.addEventListener(event, events[event], false); + } + + container.style.cssText = 'position: relative; width:' + settings.width + 'px;' + 'height:' + settings.height + 'px;'; + + ui.init(container, settings); + this.container = container; + this.changed(0); + +}; + +Knob.prototype = { + _handleKeyEvents: function(e) { + var keycode = e.keyCode; + if (keycode >= 37 && keycode <= 40) { + e.preventDefault(); + var f = 1 + e.shiftKey * 9; + this.changed({37: -1, 38: 1, 39: 1, 40: -1}[keycode] * f); + } + }, + + _handleWheelEvents: function(e) { + e.preventDefault(); + var deltaX = -e.detail || e.wheelDeltaX; + var deltaY = -e.detail || e.wheelDeltaY; + var val = deltaX > 0 || deltaY > 0 ? 1 : deltaX < 0 || deltaY < 0 ? -1 : 0; + this.changed(val); + }, + + _handleMove: function(onMove, onEnd) { + this.centerX = Math.floor(this.container.getBoundingClientRect().left)+ document.body.scrollLeft + this.settings.width / 2; + this.centerY = Math.floor(this.container.getBoundingClientRect().top)+ document.body.scrollTop + this.settings.height / 2; + + var fnc = this._updateWhileMoving.bind(this); + var body = document.body; + body.addEventListener(onMove, fnc, false); + body.addEventListener(onEnd, function() { + body.removeEventListener(onMove, fnc, false); + }, false); + }, + + _updateWhileMoving: function(event) { + event.preventDefault(); + var e = event.changedTouches ? event.changedTouches[0] : event; + var x = this.centerX - e.pageX; + var y = this.centerY - e.pageY; + var deg = Math.atan2(-y, -x) * 180 / Math.PI + 90 - this.settings.angleoffset; + var percent; + + if (deg < 0) { + deg += 360; + } + deg = deg % 360; + if (deg <= this.settings.anglerange) { + percent = Math.max(Math.min(1, deg / this.settings.anglerange), 0); + } else { + percent = +(deg - this.settings.anglerange < (360 - this.settings.anglerange) / 2); + } + var range = this.settings.range; + var value = this.min + range * percent; + + var step = (this.settings.max - this.min) / range; + this.value = this.input.value = Math.round(value / step) * step; + this.ui.update(percent, this.value); + }, + + changed: function(direction) { + this.input.value = this.limit(parseFloat(this.input.value) + direction * (this.input.step || 1)); + this.value = this.input.value; + this.ui.update(this._valueToPercent(), this.value); + }, + + + update: function(percent) { + var range = this.settings.range; + var value = this.min + range * percent; + + var step = (this.settings.max - this.min) / range; + this.value = this.input.value = Math.round(value / step) * step; + + + this.ui.update(percent, this.value); + }, + + _valueToPercent: function() { + return this.value != null ? 100 / this.settings.range * (this.value - this.min) / 100 : this.min; + }, + + limit: function(value) { + return Math.min(Math.max(this.settings.min, value), this.settings.max); + }, + + _getSettings: function(input) { + var labels; + + if(input.dataset.labels){ + labels = input.dataset.labels.split(','); + } + var settings = { + max: labels ? labels.length-1 : parseFloat(input.max), + min: labels ? 0 : parseFloat(input.min), + step: parseFloat(input.step) || 1, + angleoffset: 0, + anglerange: 360, + labels: labels + }; + settings.range = settings.max - settings.min; + var data = input.dataset; + for (var i in data) { + if (data.hasOwnProperty(i) && i!=='labels') { + var value = +data[i]; + settings[i] = isNaN(value) ? data[i] : value; + } + } + return settings; + } +}; + + + +var Ui = function() { +}; + +Ui.prototype = { + init: function(parentEl, options) { + this.options || (this.options = {}); + this.merge(this.options, options); + this.width = options.width; + this.height = options.height; + this.createElement(parentEl); + if (!this.components) { + return; + } + this.components.forEach(function(component) { + component.init(this.el.node, options); + }.bind(this)); + }, + + merge: function(dest, src) { + for (var i in src) { + if (src.hasOwnProperty(i)) { + dest[i] = src[i]; + } + } + return dest; + }, + + addComponent: function(component) { + this.components || (this.components = []); + this.components.push(component); + }, + + update: function(percent, value) { + + if (!this.components) { + return; + } + this.components.forEach(function(component) { + component.update(percent, value); + }); + }, + + createElement: function(parentEl) { + this.el = new Ui.El(this.width, this.height); + this.el.create("svg", { + version: "1.2", + baseProfile: "tiny", + width: this.width, + height: this.height + }); + this.appendTo(parentEl); + }, + appendTo: function(parent) { + parent.appendChild(this.el.node); + } + +}; + +Ui.Pointer = function(options) { + this.options = options || {}; + this.options.type && Ui.El[this.options.type] || (this.options.type = 'Triangle'); +}; + +Ui.Pointer.prototype = Object.create(Ui.prototype); + +Ui.Pointer.prototype.update = function(percent) { + this.el.rotate(this.options.angleoffset + percent * this.options.anglerange, this.width / 2, + this.height / 2); +}; + +Ui.Pointer.prototype.createElement = function(parentEl) { + this.options.pointerHeight || (this.options.pointerHeight = this.height / 2); + if (this.options.type == 'Arc') { + this.el = new Ui.El.Arc(this.options); + this.el.setAngle(this.options.size); + } else { + this.el = new Ui.El[this.options.type](this.options.pointerWidth, + this.options.pointerHeight, this.width / 2, + this.options.pointerHeight / 2 + this.options.offset); + } + this.el.addClassName('pointer'); + this.appendTo(parentEl); + +}; + +Ui.Arc = function(options) { + this.options = options || {}; +}; + +Ui.Arc.prototype = Object.create(Ui.prototype); + +Ui.Arc.prototype.createElement = function(parentEl) { + this.el = new Ui.El.Arc(this.options); + this.appendTo(parentEl); +}; + +Ui.Arc.prototype.update = function(percent) { + this.el.setAngle(percent * this.options.anglerange); +}; + +Ui.Scale = function(options) { + this.options = this.merge({ + steps: options.range / options.step, + radius: this.width / 2, + tickWidth: 1, + tickHeight: 3 + }, options); + this.options.type = Ui.El[this.options.type || 'Rect']; +}; + +Ui.Scale.prototype = Object.create(Ui.prototype); + +Ui.Scale.prototype.createElement = function(parentEl) { + this.el = new Ui.El(this.width, this.height); + this.startAngle = this.options.angleoffset || 0; + this.options.radius || (this.options.radius = this.height / 2.5); + this.el.create("g"); + this.el.addClassName('scale'); + if (this.options.drawScale) { + if(!this.options.labels){ + var step = this.options.anglerange / this.options.steps; + var end = this.options.steps + (this.options.anglerange == 360 ? 0 : 1); + this.ticks = []; + var Shape = this.options.type; + for (var i = 0; i < end; i++) { + var rect = new Shape(this.options.tickWidth, this.options.tickHeight, this.width / 2, + this.options.tickHeight / 2); + rect.rotate(this.startAngle + i * step, this.width / 2, this.height / 2); + this.el.append(rect); + this.ticks.push(rect); + } + } + } + this.appendTo(parentEl); + if (this.options.drawDial) { + this.dial(); + } +}; + +Ui.Scale.prototype.dial = function() { + var step = this.options.anglerange / this.options.steps; + var min = this.options.min; + var dialStep = (this.options.max - min) / this.options.steps; + var end = this.options.steps + (this.options.anglerange == 360 ? 0 : 1); + this.dials = []; + if(!this.options.labels){ + for (var i = 0; i < end; i++) { + var text = new Ui.El.Text(Math.abs(min + dialStep * i), this.width / 2 - 2.5, + this.height / 2 - this.options.radius, 5, 5); + this.el.append(text); + text.rotate(this.startAngle + i * step, this.width / 2, this.height / 2); + this.dials.push(text); + } + } else { + step = this.options.anglerange / (this.options.labels.length-1); + for(var i=0; i + + + + + diff --git a/objects/lego1/bird.png b/objects/lego1/bird.png new file mode 100644 index 0000000..9a5a9be Binary files /dev/null and b/objects/lego1/bird.png differ diff --git a/objects/lego1/index.html b/objects/lego1/index.html new file mode 100644 index 0000000..b581f8f --- /dev/null +++ b/objects/lego1/index.html @@ -0,0 +1,12 @@ + + + + +Default UI + + + + + + + diff --git a/objects/lego1/memory/memory.jpg b/objects/lego1/memory/memory.jpg new file mode 100644 index 0000000..43d94ff Binary files /dev/null and b/objects/lego1/memory/memory.jpg differ diff --git a/objects/lego1/memory/memoryThumbnail.jpg b/objects/lego1/memory/memoryThumbnail.jpg new file mode 100644 index 0000000..d6c189d Binary files /dev/null and b/objects/lego1/memory/memoryThumbnail.jpg differ diff --git a/objects/lego1/object.json b/objects/lego1/object.json new file mode 100644 index 0000000..4153b0f --- /dev/null +++ b/objects/lego1/object.json @@ -0,0 +1,159 @@ +{ + "objectId": "lego1Mih8ul6sqsow", + "name": "lego1", + "ip": "192.168.1.8", + "version": "1.7.0", + "deactivated": true, + "protocol": "R1", + "tcs": "41SIxV", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": { + "matrix": [ + -0.9944484233856201, + -0.0680159255862236, + -0.09198922663927078, + 0, + -0.08941574394702911, + 1.15974497795105, + 0.4827709794044495, + 0, + 0.05547261238098145, + 0.6500707864761353, + -0.8709020018577576, + 0, + 217.40771484375, + -23.5766544342041, + 1346.669921875, + 1 + ] + }, + "links": { + "Hrkyhk4o": { + "objectA": "lego1Mih8ul6sqsow", + "objectB": "lego1Mih8ul6sqsow", + "nodeA": "lego1Mih8ul6sqsowbutton", + "nodeB": "lego1Mih8ul6sqsowlight", + "logicA": false, + "logicB": false, + "namesA": [ + "lego1", + "button" + ], + "namesB": [ + "lego1", + "light" + ], + "lastEditor": "W3ubqra0", + "loop": false + } + }, + "nodes": { + "lego1Mih8ul6sqsowport 1": { + "name": "port 1", + "data": { + "value": 0.2, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 131.69264806859064, + "y": 143.73935275443364, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0.2, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego1Mih8ul6sqsowport 2": { + "name": "port 2", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -121.99635393283825, + "y": 146.77284211906954, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego1Mih8ul6sqsowbutton": { + "name": "button", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -1.5721425158644706, + "y": -279.68752849282464, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego1Mih8ul6sqsowlight": { + "name": "light", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -1.0741697439761992, + "y": -505.98239159127115, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + } + } +} \ No newline at end of file diff --git a/objects/lego1/target/target.dat b/objects/lego1/target/target.dat new file mode 100644 index 0000000..7b08ce6 Binary files /dev/null and b/objects/lego1/target/target.dat differ diff --git a/objects/lego1/target/target.jpg b/objects/lego1/target/target.jpg new file mode 100644 index 0000000..15befa1 Binary files /dev/null and b/objects/lego1/target/target.jpg differ diff --git a/objects/lego1/target/target.xml b/objects/lego1/target/target.xml new file mode 100644 index 0000000..a7d7c22 --- /dev/null +++ b/objects/lego1/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/lego2/bird.png b/objects/lego2/bird.png new file mode 100644 index 0000000..9a5a9be Binary files /dev/null and b/objects/lego2/bird.png differ diff --git a/objects/lego2/index.html b/objects/lego2/index.html new file mode 100644 index 0000000..b581f8f --- /dev/null +++ b/objects/lego2/index.html @@ -0,0 +1,12 @@ + + + + +Default UI + + + + + + + diff --git a/objects/lego2/memory/memory.jpg b/objects/lego2/memory/memory.jpg new file mode 100644 index 0000000..e3b54fc Binary files /dev/null and b/objects/lego2/memory/memory.jpg differ diff --git a/objects/lego2/memory/memoryThumbnail.jpg b/objects/lego2/memory/memoryThumbnail.jpg new file mode 100644 index 0000000..ead43a1 Binary files /dev/null and b/objects/lego2/memory/memoryThumbnail.jpg differ diff --git a/objects/lego2/object.json b/objects/lego2/object.json new file mode 100644 index 0000000..275f7c7 --- /dev/null +++ b/objects/lego2/object.json @@ -0,0 +1,133 @@ +{ + "objectId": "lego2PM1e5heefta7", + "name": "lego2", + "ip": "192.168.1.8", + "version": "1.7.0", + "deactivated": true, + "protocol": "R1", + "tcs": "26FIr3", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": { + "matrix": [ + -0.9980140924453735, + -0.03710634633898735, + -0.05648976564407349, + 0, + -0.05164576321840286, + 1.16551673412323, + 0.4804401397705078, + 0, + 0.03606565296649933, + 0.6421995759010315, + -0.8752063512802124, + 0, + 121.7186050415039, + 0.5918760895729065, + 1256.4931640625, + 1 + ] + }, + "links": {}, + "nodes": { + "lego2PM1e5heefta7port 1": { + "name": "port 1", + "data": { + "value": 0.7, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 101.10054514719377, + "y": 149.31751178239938, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0.7, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego2PM1e5heefta7port 2": { + "name": "port 2", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": -128.5718305909977, + "y": 152.4075902471086, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "lego2PM1e5heefta7button": { + "name": "button", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -8.104134675719251, + "y": -260.5845571607206, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego2PM1e5heefta7light": { + "name": "light", + "data": { + "value": 1, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -3.3579621620374382, + "y": -497.98571401124354, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 1, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + } + } +} \ No newline at end of file diff --git a/objects/lego2/target/target.dat b/objects/lego2/target/target.dat new file mode 100644 index 0000000..189b6d3 Binary files /dev/null and b/objects/lego2/target/target.dat differ diff --git a/objects/lego2/target/target.jpg b/objects/lego2/target/target.jpg new file mode 100644 index 0000000..5b9b968 Binary files /dev/null and b/objects/lego2/target/target.jpg differ diff --git a/objects/lego2/target/target.xml b/objects/lego2/target/target.xml new file mode 100644 index 0000000..669afbc --- /dev/null +++ b/objects/lego2/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/lego3/bird.png b/objects/lego3/bird.png new file mode 100644 index 0000000..9a5a9be Binary files /dev/null and b/objects/lego3/bird.png differ diff --git a/objects/lego3/index.html b/objects/lego3/index.html new file mode 100644 index 0000000..b581f8f --- /dev/null +++ b/objects/lego3/index.html @@ -0,0 +1,12 @@ + + + + +Default UI + + + + + + + diff --git a/objects/lego3/memory/memory.jpg b/objects/lego3/memory/memory.jpg new file mode 100644 index 0000000..78ca9de Binary files /dev/null and b/objects/lego3/memory/memory.jpg differ diff --git a/objects/lego3/memory/memoryThumbnail.jpg b/objects/lego3/memory/memoryThumbnail.jpg new file mode 100644 index 0000000..f491f4a Binary files /dev/null and b/objects/lego3/memory/memoryThumbnail.jpg differ diff --git a/objects/lego3/object.json b/objects/lego3/object.json new file mode 100644 index 0000000..d78e917 --- /dev/null +++ b/objects/lego3/object.json @@ -0,0 +1,159 @@ +{ + "objectId": "lego3Rc8s06n61f7o", + "name": "lego3", + "ip": "192.168.1.8", + "version": "1.7.0", + "deactivated": true, + "protocol": "R1", + "tcs": "1Djycp", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": { + "matrix": [ + -0.9998239278793335, + 0.02333233132958412, + 0.00670170970261097, + 0, + 0.0186723954975605, + 1.19016706943512, + 0.4476333558559418, + 0, + 0.001854028319939971, + 0.595973551273346, + -0.894192099571228, + 0, + 108.7134323120117, + 64.0157241821289, + 1151.2373046875, + 1 + ] + }, + "links": { + "gl1ib914": { + "objectA": "lego3Rc8s06n61f7o", + "objectB": "lego3Rc8s06n61f7o", + "nodeA": "lego3Rc8s06n61f7obutton", + "nodeB": "lego3Rc8s06n61f7olight", + "logicA": false, + "logicB": false, + "namesA": [ + "lego3", + "button" + ], + "namesB": [ + "lego3", + "light" + ], + "lastEditor": "rkIz2y6w", + "loop": false + } + }, + "nodes": { + "lego3Rc8s06n61f7oport 1": { + "name": "port 1", + "data": { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 113.75972987433488, + "y": 135.34563449848793, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego3Rc8s06n61f7oport 2": { + "name": "port 2", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -124.56552908084632, + "y": 130.97820963679987, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego3Rc8s06n61f7obutton": { + "name": "button", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 4.048499554824957, + "y": -275.90034089263645, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego3Rc8s06n61f7olight": { + "name": "light", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 9.530190729718015, + "y": -506.7114613811136, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + } + } +} \ No newline at end of file diff --git a/objects/lego3/target/target.dat b/objects/lego3/target/target.dat new file mode 100644 index 0000000..b7fa69d Binary files /dev/null and b/objects/lego3/target/target.dat differ diff --git a/objects/lego3/target/target.jpg b/objects/lego3/target/target.jpg new file mode 100644 index 0000000..c7cd951 Binary files /dev/null and b/objects/lego3/target/target.jpg differ diff --git a/objects/lego3/target/target.xml b/objects/lego3/target/target.xml new file mode 100644 index 0000000..f52d6e4 --- /dev/null +++ b/objects/lego3/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/lego4/bird.png b/objects/lego4/bird.png new file mode 100644 index 0000000..9a5a9be Binary files /dev/null and b/objects/lego4/bird.png differ diff --git a/objects/lego4/index.html b/objects/lego4/index.html new file mode 100644 index 0000000..b581f8f --- /dev/null +++ b/objects/lego4/index.html @@ -0,0 +1,12 @@ + + + + +Default UI + + + + + + + diff --git a/objects/lego4/memory/memory.jpg b/objects/lego4/memory/memory.jpg new file mode 100644 index 0000000..e388f1d Binary files /dev/null and b/objects/lego4/memory/memory.jpg differ diff --git a/objects/lego4/memory/memoryThumbnail.jpg b/objects/lego4/memory/memoryThumbnail.jpg new file mode 100644 index 0000000..6127400 Binary files /dev/null and b/objects/lego4/memory/memoryThumbnail.jpg differ diff --git a/objects/lego4/object.json b/objects/lego4/object.json new file mode 100644 index 0000000..a64dd4b --- /dev/null +++ b/objects/lego4/object.json @@ -0,0 +1,152 @@ +{ + "objectId": "lego40i73qtpzc80n", + "name": "lego4", + "ip": "192.168.1.8", + "version": "1.7.0", + "deactivated": true, + "protocol": "R1", + "tcs": "CuT7b", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": { + "matrix": [ + -0.9949462413787842, + -0.09977176785469055, + -0.06682159751653671, + 0, + -0.09851891547441483, + 1.14111602306366, + 0.5055122971534729, + 0, + 0.01939180307090282, + 0.6783261895179749, + -0.8602280020713806, + 0, + 217.8303680419922, + -90.42867279052734, + 1378.0703125, + 1 + ] + }, + "links": { + "edDqmleg": { + "objectA": "lego40i73qtpzc80n", + "objectB": "lego40i73qtpzc80n", + "nodeA": "lego40i73qtpzc80nbutton", + "nodeB": "lego40i73qtpzc80nlight", + "logicA": false, + "logicB": false, + "namesA": [ + "lego4", + "button" + ], + "namesB": [ + "lego4", + "light" + ], + "lastEditor": "rkIz2y6w", + "loop": false + } + }, + "nodes": { + "lego40i73qtpzc80nport 1": { + "name": "port 1", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 125.97762987286478, + "y": 138.28180726410937, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "lego40i73qtpzc80nport 2": { + "name": "port 2", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -112.55501993498183, + "y": 142.32293332810514, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego40i73qtpzc80nbutton": { + "name": "button", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -6.842036685975472, + "y": -252.51751060799143, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego40i73qtpzc80nlight": { + "name": "light", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -2.759803212972656, + "y": -489.3391485055836, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + } + } +} \ No newline at end of file diff --git a/objects/lego4/target/target.dat b/objects/lego4/target/target.dat new file mode 100644 index 0000000..e8e9f02 Binary files /dev/null and b/objects/lego4/target/target.dat differ diff --git a/objects/lego4/target/target.jpg b/objects/lego4/target/target.jpg new file mode 100644 index 0000000..a40e81d Binary files /dev/null and b/objects/lego4/target/target.jpg differ diff --git a/objects/lego4/target/target.xml b/objects/lego4/target/target.xml new file mode 100644 index 0000000..57c7dd3 --- /dev/null +++ b/objects/lego4/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/lego5/bird.png b/objects/lego5/bird.png new file mode 100644 index 0000000..9a5a9be Binary files /dev/null and b/objects/lego5/bird.png differ diff --git a/objects/lego5/index.html b/objects/lego5/index.html new file mode 100644 index 0000000..b581f8f --- /dev/null +++ b/objects/lego5/index.html @@ -0,0 +1,12 @@ + + + + +Default UI + + + + + + + diff --git a/objects/lego5/memory/memory.jpg b/objects/lego5/memory/memory.jpg new file mode 100644 index 0000000..197d0ee Binary files /dev/null and b/objects/lego5/memory/memory.jpg differ diff --git a/objects/lego5/memory/memoryThumbnail.jpg b/objects/lego5/memory/memoryThumbnail.jpg new file mode 100644 index 0000000..31efaf0 Binary files /dev/null and b/objects/lego5/memory/memoryThumbnail.jpg differ diff --git a/objects/lego5/object.json b/objects/lego5/object.json new file mode 100644 index 0000000..efe1b96 --- /dev/null +++ b/objects/lego5/object.json @@ -0,0 +1,159 @@ +{ + "objectId": "lego51Ci4r2m9thih", + "name": "lego5", + "ip": "192.168.1.8", + "version": "1.7.0", + "deactivated": true, + "protocol": "R1", + "tcs": "1o7d6e", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": { + "matrix": [ + 0.9714251756668091, + 0.235308438539505, + 0.05634212493896484, + 0, + 0.2322360128164291, + -0.8383921384811401, + -0.4932458996772766, + 0, + -0.06890890747308731, + 0.4916590452194214, + -0.8680634498596191, + 0, + 188.9325561523438, + 87.59776306152344, + 1572.089721679688, + 1 + ] + }, + "links": { + "3Uk9yh8g": { + "objectA": "lego51Ci4r2m9thih", + "objectB": "lego51Ci4r2m9thih", + "nodeA": "lego51Ci4r2m9thihbutton", + "nodeB": "lego51Ci4r2m9thihlight", + "logicA": false, + "logicB": false, + "namesA": [ + "lego5", + "button" + ], + "namesB": [ + "lego5", + "light" + ], + "lastEditor": "W3ubqra0", + "loop": false + } + }, + "nodes": { + "lego51Ci4r2m9thihport 1": { + "name": "port 1", + "data": { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 111.02018970843346, + "y": 153.91573404584778, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0.5, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego51Ci4r2m9thihport 2": { + "name": "port 2", + "data": { + "value": 1, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -126.3548935323197, + "y": 157.14264060294954, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 1, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego51Ci4r2m9thihbutton": { + "name": "button", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 2.8203385045198957, + "y": -246.39623701467644, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "lego51Ci4r2m9thihlight": { + "name": "light", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 3.3077468703413615, + "y": -476.14530245013884, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + } + } +} \ No newline at end of file diff --git a/objects/lego5/target/target.dat b/objects/lego5/target/target.dat new file mode 100644 index 0000000..c0c1735 Binary files /dev/null and b/objects/lego5/target/target.dat differ diff --git a/objects/lego5/target/target.jpg b/objects/lego5/target/target.jpg new file mode 100644 index 0000000..2d498b6 Binary files /dev/null and b/objects/lego5/target/target.jpg differ diff --git a/objects/lego5/target/target.xml b/objects/lego5/target/target.xml new file mode 100644 index 0000000..2f3baf0 --- /dev/null +++ b/objects/lego5/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/obj45/bird.png b/objects/obj45/bird.png new file mode 100755 index 0000000..9a5a9be Binary files /dev/null and b/objects/obj45/bird.png differ diff --git a/objects/obj45/index.html b/objects/obj45/index.html new file mode 100644 index 0000000..2b4e5fb --- /dev/null +++ b/objects/obj45/index.html @@ -0,0 +1,82 @@ + + + + + Slider + + + + + + + diff --git a/objects/obj45/object.json b/objects/obj45/object.json new file mode 100644 index 0000000..935cb1f --- /dev/null +++ b/objects/obj45/object.json @@ -0,0 +1,1787 @@ +{ + "objectId": "obj45y4gk159d097q", + "name": "obj45", + "ip": "192.168.1.5", + "version": "1.7.0", + "protocol": "R1", + "tcs": "bsyBi", + "x": 59.86856807983639, + "y": -81.53133283114366, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": {}, + "links": { + "jPr2cnxf": { + "objectA": "obj45y4gk159d097q", + "objectB": "obj45y4gk159d097q", + "nodeA": "obj45y4gk159d097qone", + "nodeB": "obj45y4gk159d097qtwo", + "logicA": false, + "logicB": false, + "namesA": [ + "obj45", + "one" + ], + "namesB": [ + "obj45", + "two" + ], + "loop": false + }, + "Cedzbzrr": { + "objectA": "obj45y4gk159d097q", + "objectB": "obj45y4gk159d097q", + "nodeA": "obj45y4gk159d097qtwo", + "nodeB": "ON6pkcgqaraz", + "logicA": false, + "logicB": 0, + "namesA": [ + "obj45", + "two" + ], + "namesB": [ + "obj45", + "LOGIC1:BLUE" + ], + "loop": false + } + }, + "nodes": { + "obj45y4gk159d097qone": { + "name": "one", + "data": { + "value": 0.7794148311950266, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -91, + "y": -90, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0.7794148311950266, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "obj45y4gk159d097qtwo": { + "name": "two", + "data": { + "value": 0.7794148311950266, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 59, + "y": -38, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0.7794148311950266, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "5Gc82guh3rpz": { + "name": "LOGIC0", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": -81.6832774763343, + "y": 117.76170840986947, + "scale": 0.5, + "matrix": [], + "visible": false, + "visibleEditing": false, + "lastSetting": false, + "lastSettingBlock": "", + "iconImage": null, + "nameInput": [ + "", + "", + "", + "" + ], + "nameOutput": [ + "", + "", + "", + "" + ], + "type": "logic", + "links": { + "blockLink-in0-0-blockHf4chpzoipnh-0": { + "nodeA": "in0", + "logicA": 0, + "nodeB": "blockHf4chpzoipnh", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + }, + "blockLink-blockHf4chpzoipnh-0-out1-0": { + "nodeA": "blockHf4chpzoipnh", + "logicA": 0, + "nodeB": "out1", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + }, + "blockLink-in0-0-blockHf4chpzoipnh-1": { + "nodeA": "in0", + "logicA": 0, + "nodeB": "blockHf4chpzoipnh", + "logicB": 1, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + }, + "blockLink-blockHf4chpzoipnh-1-out2-0": { + "nodeA": "blockHf4chpzoipnh", + "logicA": 1, + "nodeB": "out2", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + } + }, + "loaded": false, + "animationScale": 0, + "begin": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "temp": [ + -887.243381024304, + -387.95861521824, + 0.337719508464, + 0.331032, + 413.16009765704007, + -726.9703267728, + 1.08150593818, + 1.06009, + 80.829008610256, + -542.51442858624, + -1.6969203502360002, + -1.663318, + -18962.749442237888, + 9727.32052334592, + 1094.8204133300883, + 1271.160644 + ], + "fullScreen": false, + "screenX": 348.6811803672696, + "screenY": 116.73625417114295, + "screenZ": 1186.689785280809, + "screenLinearZ": 10.098742472911972, + "blocks": { + "in0": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in1": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in2": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in3": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out0": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out1": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out2": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out3": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "blockBMfh1ktos077": { + "type": "delay", + "x": 0, + "y": 1, + "blockSize": 1, + "globalId": "blockBMfh1ktos077", + "checksum": null, + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "privateData": {}, + "publicData": { + "delayTime": 1000 + }, + "activeInputs": [ + true, + false, + false, + false + ], + "activeOutputs": [ + true, + false, + false, + false + ], + "nameInput": [ + "in", + "", + "", + "" + ], + "nameOutput": [ + "out", + "", + "", + "" + ], + "iconImage": null, + "name": "delay", + "stress": 0, + "isTempBlock": false, + "isPortBlock": false + }, + "blockHf4chpzoipnh": { + "type": "switch", + "x": 1, + "y": 2, + "blockSize": 2, + "globalId": "blockHf4chpzoipnh", + "checksum": null, + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "privateData": {}, + "publicData": { + "switchType": "toggle", + "switch": false, + "toggle": false + }, + "activeInputs": [ + true, + true, + false, + false + ], + "activeOutputs": [ + true, + true, + false, + false + ], + "nameInput": [ + "in", + "stream in", + "", + "" + ], + "nameOutput": [ + "out", + "stream out", + "", + "" + ], + "iconImage": null, + "name": "switch", + "stress": 0, + "isTempBlock": false, + "isPortBlock": false + } + } + }, + "ON6pkcgqaraz": { + "name": "LOGIC1", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 161.97662459301011, + "y": 76.1906662276916, + "scale": 0.5, + "matrix": [], + "visible": false, + "visibleEditing": false, + "lastSetting": false, + "lastSettingBlock": "", + "iconImage": null, + "nameInput": [ + "", + "", + "", + "" + ], + "nameOutput": [ + "", + "", + "", + "" + ], + "type": "logic", + "links": { + "blockLink4x2vbl2g5gyh": { + "nodeA": "blockAz6t3yj4gejv", + "logicA": 0, + "nodeB": "block8e92mz2lxu3d", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + }, + "blockLinkA8gr4i4j175v": { + "nodeA": "blockAz6t3yj4gejv", + "logicA": 1, + "nodeB": "blocklPjbach5xtxb", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + }, + "blockLink-in1-0-blockAz6t3yj4gejv-0": { + "nodeA": "in1", + "logicA": 0, + "nodeB": "blockAz6t3yj4gejv", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + }, + "blockLink-block8e92mz2lxu3d-0-out1-0": { + "nodeA": "block8e92mz2lxu3d", + "logicA": 0, + "nodeB": "out1", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + }, + "blockLink-blocklPjbach5xtxb-0-out3-0": { + "nodeA": "blocklPjbach5xtxb", + "logicA": 0, + "nodeB": "out3", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + } + }, + "loaded": false, + "animationScale": 0, + "begin": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "temp": [ + 975.865697124432, + 62.11392297791999, + -0.17889854191200003, + -0.175356, + -57.3587176332, + 983.6026856304001, + 0.10669272516000002, + 0.10458, + -93.969833135136, + 44.57209092864, + -2.029744929504, + -1.989552, + -73468.34470945418, + -11417.67421028256, + 1439.117790492116, + 1608.640258 + ], + "screenX": 337.6060035800397, + "screenY": 193.13236375240226, + "screenZ": 899.7557129984721, + "screenLinearZ": 13.391045682653136, + "fullScreen": false, + "blocks": { + "in0": { + "name": "", + "data": [ + { + "value": 0.7794148311950266, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default", + "processedData": [ + { + "value": 0.7794148311950266, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + {}, + {}, + {} + ] + }, + "in1": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in2": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in3": { + "name": "", + "data": [ + { + "value": 0.42700667888857424, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default", + "processedData": [ + {}, + {}, + {}, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ] + }, + "out0": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out1": { + "name": "", + "data": [ + { + "value": 0.15780732384882867, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default", + "processedData": [ + { + "value": 0.15780732384882867, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + {}, + {}, + {} + ] + }, + "out2": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out3": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "block8e92mz2lxu3d": { + "type": "delay", + "x": 1, + "y": 2, + "blockSize": 1, + "globalId": "block8e92mz2lxu3d", + "checksum": null, + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "privateData": {}, + "publicData": { + "delayTime": 1000 + }, + "activeInputs": [ + true, + false, + false, + false + ], + "activeOutputs": [ + true, + false, + false, + false + ], + "nameInput": [ + "in", + "", + "", + "" + ], + "nameOutput": [ + "out", + "", + "", + "" + ], + "iconImage": null, + "name": "delay", + "stress": 0, + "isTempBlock": false, + "isPortBlock": false + }, + "blocklPjbach5xtxb": { + "type": "delay", + "x": 3, + "y": 1, + "blockSize": 1, + "globalId": "blocklPjbach5xtxb", + "checksum": null, + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "privateData": {}, + "publicData": { + "delayTime": 1000 + }, + "activeInputs": [ + true, + false, + false, + false + ], + "activeOutputs": [ + true, + false, + false, + false + ], + "nameInput": [ + "in", + "", + "", + "" + ], + "nameOutput": [ + "out", + "", + "", + "" + ], + "iconImage": null, + "name": "delay", + "stress": 0, + "isTempBlock": false, + "isPortBlock": false + }, + "blockAz6t3yj4gejv": { + "type": "switch", + "x": 1, + "y": 1, + "blockSize": 2, + "globalId": "blockAz6t3yj4gejv", + "checksum": null, + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "privateData": {}, + "publicData": { + "switchType": "toggle", + "switch": false, + "toggle": false + }, + "activeInputs": [ + true, + true, + false, + false + ], + "activeOutputs": [ + true, + true, + false, + false + ], + "nameInput": [ + "in", + "stream in", + "", + "" + ], + "nameOutput": [ + "out", + "stream out", + "", + "" + ], + "iconImage": null, + "name": "switch", + "stress": 0, + "isTempBlock": false, + "isPortBlock": false + } + }, + "routeBuffer": [ + 0.7794148311950266, + 0, + 0, + 0.42700667888857424 + ] + }, + "ps1zf3mudl9w": { + "name": "LOGIC2", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 40.48191171732344, + "y": 211.12180241594137, + "scale": 0.5, + "matrix": [], + "visible": false, + "visibleEditing": false, + "lastSetting": false, + "lastSettingBlock": "", + "iconImage": null, + "nameInput": [ + "", + "", + "", + "" + ], + "nameOutput": [ + "", + "", + "", + "" + ], + "type": "logic", + "links": { + "blockLink-in0-0-blockxQ7pc6giw2kt-0": { + "nodeA": "in0", + "logicA": 0, + "nodeB": "blockxQ7pc6giw2kt", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + }, + "blockLink-in2-0-blockxQ7pc6giw2kt-1": { + "nodeA": "in2", + "logicA": 0, + "nodeB": "blockxQ7pc6giw2kt", + "logicB": 1, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + }, + "blockLink-blockxQ7pc6giw2kt-0-out1-0": { + "nodeA": "blockxQ7pc6giw2kt", + "logicA": 0, + "nodeB": "out1", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + }, + "blockLink-blockxQ7pc6giw2kt-1-out2-0": { + "nodeA": "blockxQ7pc6giw2kt", + "logicA": 1, + "nodeB": "out2", + "logicB": 0, + "loop": false, + "health": 0, + "ballAnimationCount": 0, + "route": null + } + }, + "loaded": false, + "animationScale": 0, + "begin": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "temp": [ + 979.360833752704, + -8.24755864416, + 0.16026149177600002, + 0.157088, + 11.635916929008, + 985.4101772908799, + -0.09236296786800001, + -0.090534, + 71.773543033408, + -47.09571020352, + -2.0320016163280004, + -1.991764, + -156973.64195344198, + -152928.3614751869, + 1424.044281457268, + 1593.865234 + ], + "screenX": 203.39904107615985, + "screenY": 201.7531834449167, + "screenZ": 1393.3536449490437, + "screenLinearZ": 8.567494614723607, + "fullScreen": false, + "blocks": { + "in0": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in1": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in2": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in3": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out0": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out1": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out2": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out3": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "blockxQ7pc6giw2kt": { + "type": "switch", + "x": 1, + "y": 1, + "blockSize": 2, + "globalId": "blockxQ7pc6giw2kt", + "checksum": null, + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "privateData": {}, + "publicData": { + "switchType": "toggle", + "switch": false, + "toggle": false + }, + "activeInputs": [ + true, + true, + false, + false + ], + "activeOutputs": [ + true, + true, + false, + false + ], + "nameInput": [ + "in", + "stream in", + "", + "" + ], + "nameOutput": [ + "out", + "stream out", + "", + "" + ], + "iconImage": null, + "name": "switch", + "stress": 0, + "isTempBlock": false, + "isPortBlock": false + } + } + } + }, + "deactivated": true +} \ No newline at end of file diff --git a/objects/obj45/target/target.dat b/objects/obj45/target/target.dat new file mode 100644 index 0000000..0c508c7 Binary files /dev/null and b/objects/obj45/target/target.dat differ diff --git a/objects/obj45/target/target.jpg b/objects/obj45/target/target.jpg new file mode 100644 index 0000000..4e366c6 Binary files /dev/null and b/objects/obj45/target/target.jpg differ diff --git a/objects/obj45/target/target.xml b/objects/obj45/target/target.xml new file mode 100644 index 0000000..398c41b --- /dev/null +++ b/objects/obj45/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/obj47/bird.png b/objects/obj47/bird.png new file mode 100755 index 0000000..9a5a9be Binary files /dev/null and b/objects/obj47/bird.png differ diff --git a/objects/obj47/index.html b/objects/obj47/index.html new file mode 100644 index 0000000..fe36edc --- /dev/null +++ b/objects/obj47/index.html @@ -0,0 +1,11 @@ + + + + +Default UI + + + + + + diff --git a/objects/obj47/object.json b/objects/obj47/object.json new file mode 100644 index 0000000..765c534 --- /dev/null +++ b/objects/obj47/object.json @@ -0,0 +1,928 @@ +{ + "objectId": "obj47n32vbg5gk3he", + "name": "obj47", + "ip": "192.168.1.8", + "version": "1.7.0", + "protocol": "R1", + "tcs": "4o9q5c", + "x": 37.558251699426734, + "y": -11.874119446479426, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": {}, + "links": { + "Rh269jpr": { + "objectA": "obj47n32vbg5gk3he", + "objectB": "obj47n32vbg5gk3he", + "nodeA": "obj47n32vbg5gk3heswitch", + "nodeB": "obj47n32vbg5gk3helight3", + "logicA": false, + "logicB": false, + "namesA": [ + "obj47", + "switch" + ], + "namesB": [ + "obj47", + "light3" + ], + "loop": false + } + }, + "nodes": { + "obj47n32vbg5gk3hehans": { + "name": "hans", + "data": { + "value": 0.0047300278674811125, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": 245.30615238491737, + "y": 230.77724921674235, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "obj47n32vbg5gk3hepeter": { + "name": "peter", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": -117.92000213538995, + "y": -216.0064614935036, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "obj47n32vbg5gk3helight1": { + "name": "light1", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -347.2689108199629, + "y": 208.1054391519574, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "obj47n32vbg5gk3helight2": { + "name": "light2", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -323.42933924104, + "y": 1.720590661640017, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "obj47n32vbg5gk3helight3": { + "name": "light3", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -347.173061093883, + "y": -188.78789735520695, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "obj47n32vbg5gk3heswitch": { + "name": "switch", + "data": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + }, + "x": -120.17964998885873, + "y": 185.42282736005654, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100, + "processedData": { + "value": 0, + "mode": "f", + "unit": false, + "unitMin": 0, + "unitMax": 1 + } + }, + "B16bdwue18rq": { + "name": "LOGIC0", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 227.25140484734425, + "y": 50.961520653269645, + "scale": 0.5, + "matrix": [], + "visible": false, + "visibleEditing": false, + "lastSetting": false, + "lastSettingBlock": "", + "iconImage": null, + "nameInput": [ + "", + "", + "", + "" + ], + "nameOutput": [ + "", + "", + "", + "" + ], + "type": "logic", + "links": {}, + "loaded": false, + "animationScale": 0, + "begin": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "temp": [ + 981.882754773712, + -18.54321113568, + 0.008951252348, + 0.008774, + 18.402255023280002, + 984.7248925536, + -0.11510939166, + -0.11283, + -1.6517176331680004, + -57.37298754528, + -2.0371352727920002, + -1.996796, + -152740.37991211773, + -62034.30139845311, + 1509.3786002927318, + 1677.509766 + ], + "screenX": 340.9041604287786, + "screenY": 151.37513518577046, + "screenZ": 1512.841481921116, + "screenLinearZ": 7.873032693643303, + "fullScreen": false, + "blocks": { + "in0": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in1": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in2": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in3": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out0": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out1": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out2": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out3": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + } + } + }, + "Q9gcy2dj13gu": { + "name": "LOGIC1", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 225.24923190782738, + "y": -101.90432386078322, + "scale": 0.5, + "matrix": [], + "visible": false, + "visibleEditing": false, + "lastSetting": false, + "lastSettingBlock": "", + "iconImage": null, + "nameInput": [ + "", + "", + "", + "" + ], + "nameOutput": [ + "", + "", + "", + "" + ], + "type": "logic", + "links": {}, + "loaded": false, + "animationScale": 0, + "begin": [ + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1, + 0, + 0, + 0, + 0, + 1 + ], + "temp": [ + 982.039477793872, + 5.47469537472, + 0.013725797708000002, + 0.013454, + -5.282850624768001, + 983.12851826112, + -0.16656429973200002, + -0.163266, + 2.1266228616800005, + -82.1428139664, + -2.03354824256, + -1.99328, + -156316.04548383452, + 4804.84599300288, + 1512.3382062947321, + 1680.410766 + ], + "screenX": 322.48406242322386, + "screenY": 104.62196041728768, + "screenZ": 1532.4035540293157, + "screenLinearZ": 7.769654770990748, + "fullScreen": false, + "blocks": { + "in0": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in1": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in2": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "in3": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out0": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out1": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out2": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + }, + "out3": { + "name": "", + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "stress": 0, + "type": "default" + } + } + }, + "obj47n32vbg5gk3hedistance": { + "name": "distance", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": -113.6345797601025, + "y": -50.445298123140674, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "obj47n32vbg5gk3hemotor": { + "name": "motor", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 461.62845528755133, + "y": 15.318016481502127, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + } + }, + "logic": {}, + "deactivated": false +} \ No newline at end of file diff --git a/objects/obj47/target/target.dat b/objects/obj47/target/target.dat new file mode 100644 index 0000000..8ca23a5 Binary files /dev/null and b/objects/obj47/target/target.dat differ diff --git a/objects/obj47/target/target.jpg b/objects/obj47/target/target.jpg new file mode 100644 index 0000000..9dc2541 Binary files /dev/null and b/objects/obj47/target/target.jpg differ diff --git a/objects/obj47/target/target.xml b/objects/obj47/target/target.xml new file mode 100644 index 0000000..4e8617c --- /dev/null +++ b/objects/obj47/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/objects/timer/bird.png b/objects/timer/bird.png new file mode 100644 index 0000000..9a5a9be Binary files /dev/null and b/objects/timer/bird.png differ diff --git a/objects/timer/index.html b/objects/timer/index.html new file mode 100644 index 0000000..80c1850 --- /dev/null +++ b/objects/timer/index.html @@ -0,0 +1,45 @@ + + + + +Default UI + + + + + + + + diff --git a/objects/timer/object.json b/objects/timer/object.json new file mode 100644 index 0000000..e52fd4a --- /dev/null +++ b/objects/timer/object.json @@ -0,0 +1,76 @@ +{ + "objectId": "timer1bfv827dfb7s", + "name": "timer", + "ip": "192.168.1.8", + "version": "1.7.0", + "deactivated": false, + "protocol": "R1", + "tcs": "1f968F", + "x": 0, + "y": 0, + "scale": 1, + "matrix": [], + "visible": false, + "visibleText": false, + "visibleEditing": false, + "developer": true, + "memory": {}, + "links": {}, + "nodes": { + "timer1bfv827dfb7sstart": { + "name": "start", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": -224.3252893662575, + "y": 188.42080127341615, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "timer1bfv827dfb7sstop": { + "name": "stop", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 1.6559879206324695, + "y": 192.27795204301947, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + }, + "timer1bfv827dfb7sreset": { + "name": "reset", + "data": { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + "x": 214.06152948633826, + "y": 216.25057089907932, + "scale": 1, + "matrix": [], + "type": "node", + "stress": 0, + "frameSizeX": 100, + "frameSizeY": 100 + } + }, + "frames": {} +} \ No newline at end of file diff --git a/objects/timer/target/target.dat b/objects/timer/target/target.dat new file mode 100644 index 0000000..b95709e Binary files /dev/null and b/objects/timer/target/target.dat differ diff --git a/objects/timer/target/target.jpg b/objects/timer/target/target.jpg new file mode 100644 index 0000000..5046bfa Binary files /dev/null and b/objects/timer/target/target.jpg differ diff --git a/objects/timer/target/target.xml b/objects/timer/target/target.xml new file mode 100644 index 0000000..b23755e --- /dev/null +++ b/objects/timer/target/target.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..55998ca --- /dev/null +++ b/package.json @@ -0,0 +1,84 @@ +{ + "name": "HybridObjects", + "version": "0.3.1", + "description": "", + "main": "server.js", + "dependencies": { + "archiver": "^0.14.2", + "body-parser": "^1.9.2", + "change-case": "^2.2.0", + "cheerio": "0.19.0", + "cors": "^2.5.0", + "decompress-zip": "^0.1.0", + "express": "^4.11.0", + "express-handlebars": "^3.0.0", + "formidable": "^1.0.16", + "fs-extra": "^0.12.0", + "fstream": "^1.0.4", + "getmac": "^1.0.6", + "ip": "^0.3.2", + "kodi-ws": "^2.3.0", + "lodash": "^3.10.1", + "monaco-editor": "^0.5.1", + "mpd": "^1.3.0", + "node-watch": "^0.3.4", + "onoff": "^1.0.3", + "serialport": "^3.0.1", + "smtp-server": "^1.16.1", + "socket.io": "^1.2.0", + "socket.io-client": "^1.2.0", + "unzip": "^0.1.11", + "watch": "^0.13.0", + "wedo2": "^1.5.*", + "xml2js": "^0.4.4", + "request": "^2.*" + }, + "repository": { + "type": "git", + "url": "https://github.com/openhybrid/object" + }, + "devDependencies": {}, + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node server.js" + }, + "author": { + "name": "Valentin Heun", + "email": "heun@media.mit.edu" + }, + "contributors": [ + { + "name": "Shunichi Kasahara", + "email": "" + }, + { + "name": "James Hobin", + "email": "" + }, + { + "name": "Kevin Wong", + "email": "" + }, + { + "name": "Kenny Friedman", + "email": "" + }, + { + "name": "Michelle Suh", + "email": "" + }, + { + "name": "Benjamin F Reynolds ", + "email": "" + }, + { + "name": "Eva Stern-Rodriguez", + "email": "" + }, + { + "name": "Carsten Strunk", + "email": "" + } + ], + "license": "MPL-2.0" +} diff --git a/server.js b/server.js new file mode 100644 index 0000000..6f36090 --- /dev/null +++ b/server.js @@ -0,0 +1,3068 @@ +/** + * @preserve + * + * .,,,;;,'''.. + * .'','... ..',,,. + * .,,,,,,',,',;;:;,. .,l, + * .,',. ... ,;, :l. + * ':;. .'.:do;;. .c ol;'. + * ';;' ;.; ', .dkl';, .c :; .'.',::,,'''. + * ',,;;;,. ; .,' .'''. .'. .d;''.''''. + * .oxddl;::,,. ', .'''. .... .'. ,:;.. + * .'cOX0OOkdoc. .,'. .. ..... 'lc. + * .:;,,::co0XOko' ....''..'.'''''''. + * .dxk0KKdc:cdOXKl............. .. ..,c.... + * .',lxOOxl:'':xkl,',......'.... ,'. + * .';:oo:... . + * .cd, ╔═╗┌─┐┬─┐┬ ┬┌─┐┬─┐ . + * .l; ╚═╗├┤ ├┬┘└┐┌┘├┤ ├┬┘ ' + * 'l. ╚═╝└─┘┴└─ └┘ └─┘┴└─ '. + * .o. ... + * .''''','.;:''......... + * .' .l + * .:. l' + * .:. .l. + * .x: :k;,. + * cxlc; cdc,,;;. + * 'l :.. .c , + * o. + * ., + * + * ╦ ╦┬ ┬┌┐ ┬─┐┬┌┬┐ ╔═╗┌┐ ┬┌─┐┌─┐┌┬┐┌─┐ + * ╠═╣└┬┘├┴┐├┬┘│ ││ ║ ║├┴┐ │├┤ │ │ └─┐ + * ╩ ╩ ┴ └─┘┴└─┴─┴┘ ╚═╝└─┘└┘└─┘└─┘ ┴ └─┘ + * + * Created by Valentin on 10/22/14. + * Modified by Carsten on 12/06/15. + * Modified by Psomdecerff (PCS) on 12/21/15. + * + * Copyright (c) 2015 Valentin Heun + * + * All ascii characters above must be included in any redistribution. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/********************************************************************************************************************* + ******************************************** TODOS ******************************************************************* + ********************************************************************************************************************** + + ** + + * TODO - Only allow upload backups and not any other data.... + * + * TODO - check any collision with knownObjects -> Show collision with other object.... + * TODO - Check if Targets are double somehwere. And iff Target has more than one target in the file... + * + * TODO - Check the socket connections + * TODO - check if links are pointing to values that actually exist. - (happens in browser at the moment) + * TODO - Test self linking from internal to internal value (endless loop) - (happens in browser at the moment) + * + * TODO - Checksum for marker needs to be verified on the server side as well. + ** + + ********************************************************************************************************************** + ******************************************** constant settings ******************************************************* + **********************************************************************************************************************/ + +// These variables are used for global status, such as if the server sends debugging messages and if the developer +// user interfaces should be accesable + +var globalVariables = { + developer: true, // show developer web GUI + debug: false // debug messages to console +}; + +// ports used to define the server behaviour +/* + The server uses port 8080 to communicate with other servers and with the Reality Editor. + As such the Server reacts to http and web sockets on this port. + + The beat port is used to send UDP broadcasting messages in a local network. The Reality Editor and other Objects + pick up these messages to identify the object. + + */ + +const serverPort = 8080; +const socketPort = serverPort; // server and socket port are always identical +const beatPort = 52316; // this is the port for UDP broadcasting so that the objects find each other. +const timeToLive = 2; // the amount of routers a UDP broadcast can jump. For a local network 2 is enough. +const beatInterval = 5000; // how often is the heartbeat sent +const socketUpdateInterval = 2000; // how often the system checks if the socket connections are still up and running. +const version = "1.7.0"; // the version of this server +const protocol = "R1"; // the version of this server +const netmask = "255.255.0.0"; // define the network scope from which this server is accessable. +// for a local network 255.255.0.0 allows a 16 bit block of local network addresses to reach the object. +// basically all your local devices can see the object, however the internet is unable to reach the object. + +console.log(parseInt(version.replace(/\./g, ""))); + +// All objects are stored in this folder: +const objectPath = __dirname + "/objects"; +// All visual UI representations for IO Points are stored in this folder: +const nodePath = __dirname + "/libraries/nodes"; +// All visual UI representations for IO Points are stored in this folder: +const blockPath = __dirname + "/libraries/logicBlocks"; +// All interfaces for different hardware such as Arduino Yun, PI, Philips Hue are stored in this folder. +const hardwarePath = __dirname + "/hardwareInterfaces"; +// The web service level on which objects are accessable. http://:8080 +const objectInterfaceFolder = "/"; + +/********************************************************************************************************************** + ******************************************** Requirements ************************************************************ + **********************************************************************************************************************/ + +var _ = require('lodash'); // JavaScript utility library +var fs = require('fs'); // Filesystem library +var dgram = require('dgram'); // UDP Broadcasting library +var ip = require("ip"); // get the device IP address library +var bodyParser = require('body-parser'); // body parsing middleware +var express = require('express'); // Web Sever library +var exphbs = require('express-handlebars'); // View Template library + + +// constrution for the werbserver using express combined with socket.io +var webServer = express(); +webServer.set('views', 'libraries/webInterface/views'); + +webServer.engine('handlebars', exphbs({ + defaultLayout: 'main', + layoutsDir: 'libraries/webInterface/views/layouts', + partialsDir: 'libraries/webInterface/views/partials' +})); +webServer.set('view engine', 'handlebars'); + +var http = require('http').createServer(webServer).listen(serverPort, function () { + cout('webserver + socket.io is listening on port: ' + serverPort); +}); +var io = require('socket.io')(http); // Websocket library +var socket = require('socket.io-client'); // websocket client source +var cors = require('cors'); // Library for HTTP Cross-Origin-Resource-Sharing +var formidable = require('formidable'); // Multiple file upload library +var cheerio = require('cheerio'); + +// additional files containing project code + +// This file hosts all kinds of utilities programmed for the server +var utilities = require(__dirname + '/libraries/utilities'); +// The web frontend a developer is able to see when creating new user interfaces. +var webFrontend = require(__dirname + '/libraries/webFrontend'); +// Definition for a simple API for hardware interfaces talking to the server. +// This is used for the interfaces defined in the hardwareAPI folder. +var hardwareAPI = require(__dirname + '/libraries/hardwareInterfaces'); + +var util = require("util"); // node.js utility functionality +var events = require("events"); // node.js events used for the socket events. + +// Set web frontend debug to inherit from global debug +webFrontend.debug = globalVariables.debug; + +/********************************************************************************************************************** + ******************************************** Constructors ************************************************************ + **********************************************************************************************************************/ + +/** + * @desc This is the default constructor for the Hybrid Object. + * It contains information about how to render the UI and how to process the internal data. + **/ + +function Objects() { + // The ID for the object will be broadcasted along with the IP. It consists of the name with a 12 letter UUID added. + this.objectId = null; + // The name for the object used for interfaces. + this.name = ""; + // The IP address for the object is relevant to point the Reality Editor to the right server. + // It will be used for the UDP broadcasts. + this.ip = ip.address(); + // The version number of the Object. + this.version = version; + + this.deactivated = false; + + this.protocol = protocol; + // The (t)arget (C)eck(S)um is a sum of the checksum values for the target files. + this.tcs = null; + // Reality Editor: This is used to possition the UI element within its x axis in 3D Space. Relative to Marker origin. + this.x = 0; + // Reality Editor: This is used to possition the UI element within its y axis in 3D Space. Relative to Marker origin. + this.y = 0; + // Reality Editor: This is used to scale the UI element in 3D Space. Default scale is 1. + this.scale = 1; + // Unconstrained positioning in 3D space + this.matrix = []; + // Used internally from the reality editor to indicate if an object should be rendered or not. + this.visible = false; + // Used internally from the reality editor to trigger the visibility of naming UI elements. + this.visibleText = false; + // Used internally from the reality editor to indicate the editing status. + this.visibleEditing = false; + // every object holds the developer mode variable. It indicates if an object is editable in the Reality Editor. + this.developer = true; + // Intended future use is to keep a memory of the last matrix transformation when interacted. + // This data can be used for interacting with objects for when they are not visible. + this.memory = {}; // TODO use this to store UI interface for image later. + // Stores all the links that emerge from within the object. If a IOPoint has new data, + // the server looks through the Links to find if the data has influence on other IOPoints or Objects. + this.links = {}; + // Stores all IOPoints. These points are used to keep the state of an object and process its data. + this.nodes = {}; + // Store the frames. These embed content positioned relative to the object + this.frames = {}; +} + +/** + * @desc The Link constructor is used every time a new link is stored in the links object. + * The link does not need to keep its own ID since it is created with the link ID as Obejct name. + **/ + +function Link() { + // The origin object from where the link is sending data from + this.objectA = null; + // The origin IOPoint from where the link is taking its data from + this.nodeA = null; + // if origin location is a Logic Node then set to Logic Node output location (which is a number between 0 and 3) otherwise null + this.logicA = null; + // Defines the type of the link origin. Currently this function is not in use. + this.namesA = ["",""]; + // The destination object to where the origin object is sending data to. + // At this point the destination object accepts all incoming data and routs the data according to the link data sent. + this.objectB = null; + // The destination IOPoint to where the link is sending data from the origin object. + // objectB and nodeB will be send with each data package. + this.nodeB = null; + // if destination location is a Logic Node then set to logic block input location (which is a number between 0 and 3) otherwise null + this.logicB = null; + // Defines the type of the link destination. Currently this function is not in use. + this.namesB = ["",""]; + // check that there is no endless loop in the system + this.loop = false; + // Will be used to test if a link is still able to find its destination. + // It needs to be discussed what to do if a link is not able to find the destination and for what time span. + this.health = 0; // todo use this to test if link is still valid. If not able to send for some while, kill link. +} + +/** + * @desc Constructor used to define every nodes generated in the Object. It does not need to contain its own ID + * since the object is created within the nodes with the ID as object name. + **/ + +function Node() { + // the name of each link. It is used in the Reality Editor to show the IO name. + this.name = ""; + // the actual data of the node + this.data = new Data(); + // Reality Editor: This is used to possition the UI element within its x axis in 3D Space. Relative to Marker origin. + this.x = 0; + // Reality Editor: This is used to possition the UI element within its y axis in 3D Space. Relative to Marker origin. + this.y = 0; + // Reality Editor: This is used to scale the UI element in 3D Space. Default scale is 1. + this.scale = 1; + // Unconstrained positioning in 3D space + this.matrix = []; + // defines the nodeInterface that is used to process data of this type. It also defines the visual representation + // in the Reality Editor. Such data points interfaces can be found in the nodeInterface folder. + this.type = "node"; + // defines the origin Hardware interface of the IO Point. For example if this is arduinoYun the Server associates + // this IO Point with the Arduino Yun hardware interface. + //this.type = "arduinoYun"; // todo "arduinoYun", "virtual", "edison", ... make sure to define yours in your internal_module file + // indicates how much calls per second is happening on this node + this.stress = 0; +} + +/** + * @desc Constructor used to define every logic node generated in the Object. It does not need to contain its own ID + * since the object is created within the nodes with the ID as object name. + **/ + +function Logic() { + this.name = ""; + // data for logic blocks. depending on the blockSize which one is used. + this.data = new Data(); + // Reality Editor: This is used to possition the UI element within its x axis in 3D Space. Relative to Marker origin. + this.x = 0; + // Reality Editor: This is used to possition the UI element within its y axis in 3D Space. Relative to Marker origin. + this.y = 0; + // Reality Editor: This is used to scale the UI element in 3D Space. Default scale is 1. + this.scale = 1; + // Unconstrained positioning in 3D space + this.matrix = []; + // if showLastSettingFirst is true then lastSetting is the name of the last block that was moved or set. + this.lastSetting = false; + + this.lastSettingBlock = ""; + // the iconImage is in png or jpg format and will be stored within the logicBlock folder. A reference is placed here. + this.iconImage = null; + // nameInput are the names given for each IO. + this.nameInput = ["", "", "", ""]; + // nameOutput are the names given for each IO + this.nameOutput = ["", "", "", ""]; + // the array of possible connections within the logicBlock. + // if a block is set, a new Node instance is coppied in to the spot. + this.type = "logic"; + this.links = {}; + this.blocks = {}; + + this.route = 0; + this.routeBuffer = [0,0,0,0]; +} + +/** + * @desc The Link constructor for Blocks is used every time a new logic Link is stored in the logic Node. + * The block link does not need to keep its own ID since it is created with the link ID as Object name. + **/ + +function BlockLink() { + // origin block UUID + this.nodeA = null; + // item in that block + this.logicA = 0; + // destination block UUID + this.nodeB = null; + // item in that block + this.logicB = 0; + // check if the links are looped. + this.loop = false; + // Will be used to test if a link is still able to find its destination. + // It needs to be discussed what to do if a link is not able to find the destination and for what time span. + this.health = 0; // todo use this to test if link is still valid. If not able to send for some while, kill link. +} + +/** + * @desc Constructor used to define every block within the logicNode. + * The block does not need to keep its own ID since it is created with the link ID as Object name. + **/ + + +function Block() { + // name of the block + this.name = ""; + // local ID given to a used block. + this.id = null; + + this.x = null; + this.y = null; + // amount of elements the IO point is created of. Single IO nodes have the size 1. + this.blockSize = 1; + // the category for the editor + this.category = 1; + // the global / world wide id of the actual reference block design. // checksum of the block?? + this.globalId = null; + // the checksum should be identical with the checksum for the persistent package files of the reference block design. + this.checksum = null; // checksum of the files for the program + // data for logic blocks. depending on the blockSize which one is used. + this.data = [new Data(), new Data(), new Data(), new Data()]; + // experimental. This are objects for data storage. Maybe it makes sense to store data in the general object + // this would allow the the packages to be persistent. // todo discuss usability with Ben. + this.privateData = {}; + this.publicData = {}; + + // IO for logic + // define how many inputs are active. + this.activeInputs = [true, false, false, false]; + // define how many outputs are active. + this.activeOutputs = [true, false, false, false]; + // define the names of each active IO + this.nameInput = ["", "", "", ""]; + this.nameOutput = ["", "", "", ""]; + // A specific icon for the node, png or jpg. + this.iconImage = null; + // Text within the node, if no icon is available. + // indicates how much calls per second is happening on this block + this.stress = 0; + // this is just a compatibility with the original engine. Maybe its here to stay + this.type = "default"; +} + +/** + * @desc Constructor used to define special blocks that are connecting the logic crafting with the outside system. + **/ + +function EdgeBlock() { + // name of the block + this.name = ""; + // data for logic blocks. depending on the blockSize which one is used. + this.data = [new Data(), new Data(), new Data(), new Data()]; + // indicates how much calls per second is happening on this block + this.stress = 0; + this.type = "default"; +} + + +/** + * @desc Definition for Values that are sent around. + **/ + +function Data() { + // storing the numerical content send between nodes. Range is between 0 and 1. + this.value = 0; + // Defines the kind of data send. At this point we have 3 active data modes and one future possibility. + // (f) defines floating point values between 0 and 1. This is the default value. + // (d) defines a digital value exactly 0 or 1. + // (+) defines a positive step with a floating point value for compatibility. + // (-) defines a negative step with a floating point value for compatibility. + this.mode = "f"; + // string of the name for the unit used (for Example "C", "F", "cm"). Default is set to no unit. + this.unit = ""; + // scale of the unit that is used. Usually the scale is between 0 and 1. + this.unitMin = 0; + this.unitMax = 1; +} + +/** + * Embedded content positioned relative to an object + * @constructor + * @param {String} src - path to content + */ +function ObjectFrame(src) { + this.src = src; + this.x = 0; + this.y = 0; + this.scale = 1; + this.matrix = [ + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ]; + this.developer = true; +} + +/** + * @desc This Constructor is used when a new socket connection is generated. + **/ + +function ObjectSockets(socketPort, ip) { + // keeps the own IP of an object + this.ip = ip; + // defines where to connect to + this.io = socket.connect('http://' + ip + ':' + socketPort, { + // defines the timeout for a connection between objects and the reality editor. + 'connect timeout': 5000, + // try to reconnect + 'reconnect': true, + // time between re-connections + 'reconnection delay': 500, + // the amount of reconnection attempts. Once the connection failed, the server kicks in and tries to reconnect + // infinitely. This behaviour can be changed once discussed what the best model would be. + // At this point the invinit reconnection attempt keeps the system optimal running at all time. + 'max reconnection attempts': 20, + // automatically connect a new conneciton. + 'auto connect': true, + // fallbacks connection models for socket.io + 'transports': [ + 'websocket' + , 'flashsocket' + , 'htmlfile' + , 'xhr-multipart' + , 'xhr-polling' + , 'jsonp-polling'] + }); +} + +function EditorSocket(socketID, object) { + // keeps the own IP of an object + this.id = socketID; + // defines where to connect to + this.obj = object; + +} + +function Protocols() { + + this.R1 = { + send: function (object, node, data) { + return JSON.stringify({object: object, node: node, data: data}) + }, + receive: function (message) { + if (!message) return null; + var msgContent = JSON.parse(message); + if (!msgContent.object) return null; + if (!msgContent.node) return null; + if (!msgContent.data) return null; + + if (msgContent.object in objects) { + if (msgContent.node in objects[msgContent.object].nodes) { + + var objectData = objects[msgContent.object].nodes[msgContent.node].data; + + for (var key in msgContent.data) { + objectData[key] = msgContent.data[key]; + } + return {object:msgContent.object, node:msgContent.node, data: objectData}; + } + + } + + return null + } + }; + this.R0 = { + send: function (object, node, data) { + return JSON.stringify({obj: object, pos: node, value: data.value, mode: data.mode})}, + receive: function (message) { + if (!message) return null; + var msgContent = JSON.parse(message); + if (!msgContent.obj) return null; + if (!msgContent.pos) return null; + if (!msgContent.value) msgContent.value = 0; + if (!msgContent.mode) return null; + + if (msgContent.obj in objects) { + if (msgContent.pos in objects[msgContent.obj].nodes) { + + var objectData = objects[msgContent.obj].nodes[msgContent.pos].data; + + objectData.value = msgContent.value; + objectData.mode = msgContent.mode; + + return {object:msgContent.obj, node:msgContent.pos, data: objectData}; + } + + } + return null + } + }; +} + +/********************************************************************************************************************** + ******************************************** Variables and Objects *************************************************** + **********************************************************************************************************************/ + +// This variable will hold the entire tree of all objects and their sub objects. +var objects = {}; +var nodeTypeModules = {}; // Will hold all available data point interfaces +var blockModules = {}; // Will hold all available data point interfaces +var hardwareInterfaceModules = {}; // Will hold all available hardware interfaces. +// A list of all objects known and their IPs in the network. The objects are found via the udp heart beat. +// If a new link is linking to another objects, this knownObjects list is used to establish the connection. +// This list is also used to keep track of the actual IP of an object. If the IP of an object in a network changes, +// It has no influance on the connectivity, as it is referenced by the object UUID through the entire time. +var protocols = new Protocols(); +var knownObjects = {}; +// A lookup table used to process faster through the objects. +var objectLookup = {}; +// This list holds all the socket connections that are kept alive. Socket connections are kept alive if a link is +// associated with this object. Once there is no more link the socket connection is deleted. +var socketArray = {}; // all socket connections that are kept alive + +var realityEditorSocketArray = {}; // all socket connections that are kept alive +var realityEditorBlockSocketArray = {}; // all socket connections that are kept alive + +// counter for the socket connections +// this counter is used for the Web Developer Interface to reflect the state of the server socket connections. +var sockets = { + sockets: 0, // amount of created socket connections + connected: 0, // amount of connected socket connections + notConnected: 0, // not connected + socketsOld: 0, // used internally to react only on updates + connectedOld: 0, // used internally to react only on updates + notConnectedOld: 0 // used internally to react only on updates +}; + +/********************************************************************************************************************** + ******************************************** Initialisations ********************************************************* + **********************************************************************************************************************/ + + +cout("Starting the Server"); + +// get a list with the names for all IO-Points, based on the folder names in the nodeInterfaces folder folder. +// Each folder represents on IO-Point. +var nodeFolderList = fs.readdirSync(nodePath).filter(function (file) { + return fs.statSync(nodePath + '/' + file).isDirectory(); +}); + +// Remove eventually hidden files from the Hybrid Object list. +while (nodeFolderList[0][0] === ".") { + nodeFolderList.splice(0, 1); +} + +// Create a objects list with all IO-Points code. +for (var i = 0; i < nodeFolderList.length; i++) { + nodeTypeModules[nodeFolderList[i]] = require(nodePath + '/' + nodeFolderList[i] + "/index.js"); +} + + +// get a list with the names for all IO-Points, based on the folder names in the nodeInterfaces folder folder. +// Each folder represents on IO-Point. +var blockFolderList = fs.readdirSync(blockPath).filter(function (file) { + return fs.statSync(blockPath + '/' + file).isDirectory(); +}); + +// Remove eventually hidden files from the Hybrid Object list. +while (blockFolderList[0][0] === ".") { + blockFolderList.splice(0, 1); +} + + + + + +// Create a objects list with all IO-Points code. +for (var i = 0; i < blockFolderList.length; i++) { + blockModules[blockFolderList[i]] = require(blockPath + '/' + blockFolderList[i] + "/index.js"); +} + + +cout("Initialize System: "); +cout("Loading Hardware interfaces"); +// set all the initial states for the Hardware Interfaces in order to run with the Server. +hardwareAPI.setup(objects, objectLookup, globalVariables, __dirname, nodeTypeModules, blockModules, function (objectKey, nodeKey, data, objects, nodeTypeModules) { + + //these are the calls that come from the objects before they get processed by the object engine. + // send the saved value before it is processed + + sendMessagetoEditors({ + object: objectKey, + node: nodeKey, + data: data + }); + engine.trigger(objectKey, nodeKey, objects[objectKey].nodes[nodeKey]); + + +}, Node, function(thisAction){ + actionSender(thisAction); +}); +cout("Done"); + +cout("Loading Objects"); +// This function will load all the Objects +loadObjects(); +cout("Done"); + +startSystem(); +cout("started"); + +// get the directory names of all available soutyperces for the 3D-UI +var hardwareAPIFolderList = fs.readdirSync(hardwarePath).filter(function (file) { + return fs.statSync(hardwarePath + '/' + file).isDirectory(); +}); +// remove hidden directories +while (hardwareAPIFolderList[0][0] === ".") { + hardwareAPIFolderList.splice(0, 1); +} + +// add all types to the nodeTypeModules object. Iterate backwards because splice works inplace +for (var i = hardwareAPIFolderList.length - 1; i >= 0; i--) { + //check if hardwareInterface is enabled, if it is, add it to the hardwareInterfaceModules + if (require(hardwarePath + "/" + hardwareAPIFolderList[i] + "/index.js").enabled) { + hardwareInterfaceModules[hardwareAPIFolderList[i]] = require(hardwarePath + "/" + hardwareAPIFolderList[i] + "/index.js"); + } else { + hardwareAPIFolderList.splice(i, 1); + } +} + +cout("ready to start internal servers"); + +hardwareAPI.reset(); + +cout("found " + hardwareAPIFolderList.length + " internal server"); +cout("starting internal Server."); + +/** + * Returns the file extension (portion after the last dot) of the given filename. + * If a file name starts with a dot, returns an empty string. + * + * @author VisioN @ StackOverflow + * @param {string} fileName - The name of the file, such as foo.zip + * @return {string} The lowercase extension of the file, such has "zip" + */ +function getFileExtension(fileName) { + return fileName.substr((~-fileName.lastIndexOf(".") >>> 0) + 2).toLowerCase(); +} + +/** + * @desc Add objects from the objects folder to the system + **/ +function loadObjects() { + cout("Enter loadObjects"); + // check for objects in the objects folder by reading the objects directory content. + // get all directory names within the objects directory + var objectFolderList = fs.readdirSync(objectPath).filter(function (file) { + return fs.statSync(objectPath + '/' + file).isDirectory(); + }); + + // remove hidden directories + try { + while (objectFolderList[0][0] === ".") { + objectFolderList.splice(0, 1); + } + } catch (e) { + cout("no hidden files"); + } + + for (var i = 0; i < objectFolderList.length; i++) { + var tempFolderName = utilities.getObjectIdFromTarget(objectFolderList[i], __dirname); + cout("TempFolderName: " + tempFolderName); + + if (tempFolderName !== null) { + // fill objects with objects named by the folders in objects + objects[tempFolderName] = new Objects(); + objects[tempFolderName].name = objectFolderList[i]; + + // add object to object lookup table + utilities.writeObject(objectLookup, objectFolderList[i], tempFolderName); + + // try to read a saved previous state of the object + try { + objects[tempFolderName] = JSON.parse(fs.readFileSync(__dirname + "/objects/" + objectFolderList[i] + "/object.json", "utf8")); + objects[tempFolderName].ip = ip.address(); + + // this is for transforming old lists to new lists + + if(typeof objects[tempFolderName].objectValues !== "undefined") + { + objects[tempFolderName].nodes = objects[tempFolderName].objectValues; + delete objects[tempFolderName].objectValues; + } + if(typeof objects[tempFolderName].objectLinks !== "undefined") + { + objects[tempFolderName].links = objects[tempFolderName].objectLinks; + delete objects[tempFolderName].objectLinks; + } + + + + for (var nodeKey in objects[tempFolderName].nodes) { + + if(typeof objects[tempFolderName].nodes[nodeKey].item !== "undefined"){ + var tempItem = objects[tempFolderName].nodes[nodeKey].item; + objects[tempFolderName].nodes[nodeKey].data = tempItem[0]; + } + } + + cout("I found objects that I want to add"); + + + } catch (e) { + objects[tempFolderName].ip = ip.address(); + objects[tempFolderName].objectId = tempFolderName; + cout("No saved data for: " + tempFolderName); + } + + } else { + cout(" object " + objectFolderList[i] + " has no marker yet"); + } + } + + hardwareAPI.reset(); +} + +/********************************************************************************************************************** + ******************************************** Starting the System ****************************************************** + **********************************************************************************************************************/ + +/** + * @desc starting the system + **/ + +function startSystem() { + + // generating a udp heartbeat signal for every object that is hosted in this device + for (var key in objects) { + if(!objects[key].deactivated) { + objectBeatSender(beatPort, key, objects[key].ip); + } + } + + // receiving heartbeat messages and adding new objects to the knownObjects Array + objectBeatServer(); + + // serving the visual frontend with web content as well serving the REST API for add/remove links and changing + // object sizes and positions + objectWebServer(); + + // receives all socket connections and processes the data + socketServer(); + + // initializes the first sockets to be opened to other objects + socketUpdater(); + + // keeps sockets to other objects alive based on the links found in the local objects + // removes socket connections to objects that are no longer linked. + socketUpdaterInterval(); + +} + +/********************************************************************************************************************** + ******************************************** Stopping the System ***************************************************** + **********************************************************************************************************************/ + +function exit() { + var mod; + + hardwareAPI.shutdown(); + + process.exit(); +} + +process.on('SIGINT', exit); + +/********************************************************************************************************************** + ******************************************** Emitter/Client/Sender *************************************************** + **********************************************************************************************************************/ + +/** + * @desc Sends out a Heartbeat broadcast via UDP in the local network. + * @param {Number} PORT The port where to start the Beat + * @param {string} thisId The name of the Object + * @param {string} thisIp The IP of the Object + * @param {string} thisVersion The version of the Object + * @param {string} thisTcs The target checksum of the Object. + * @param {boolean} oneTimeOnly if true the beat will only be sent once. + **/ + +function objectBeatSender(PORT, thisId, thisIp, oneTimeOnly) { + if (typeof oneTimeOnly === "undefined") { + oneTimeOnly = false; + } + + var HOST = '255.255.255.255'; + + cout("creating beat for object: " + thisId); + objects[thisId].version = version; + objects[thisId].protocol = protocol; + + var thisVersionNumber = parseInt(objects[thisId].version.replace(/\./g, "")); + + if (typeof objects[thisId].tcs === "undefined") { + objects[thisId].tcs = 0; + } + + // Objects + cout("with version number: " + thisVersionNumber); + + // json string to be send + var message = new Buffer(JSON.stringify({ + id: thisId, + ip: thisIp, + vn: thisVersionNumber, + pr: protocol, + tcs: objects[thisId].tcs + })); + + if (globalVariables.debug) console.log("UDP broadcasting on port: " + PORT); + if (globalVariables.debug) console.log("Sending beats... Content: " + JSON.stringify({ + id: thisId, + ip: thisIp, + vn: thisVersionNumber, + pr: protocol, + tcs: objects[thisId].tcs + })); + cout("UDP broadcasting on port: " + PORT); + cout("Sending beats... Content: " + JSON.stringify({ + id: thisId, + ip: thisIp, + vn: thisVersionNumber, + pr: protocol, + tcs: objects[thisId].tcs + })); + + // creating the datagram + var client = dgram.createSocket('udp4'); + client.bind(function () { + client.setBroadcast(true); + client.setTTL(timeToLive); + client.setMulticastTTL(timeToLive); + }); + + if (!oneTimeOnly) { + setInterval(function () { + // send the beat# + if (thisId in objects && !objects[thisId].deactivated) { + // cout("Sending beats... Content: " + JSON.stringify({ id: thisId, ip: thisIp, vn:thisVersionNumber, tcs: objects[thisId].tcs})); + + var message = new Buffer(JSON.stringify({ + id: thisId, + ip: thisIp, + vn: thisVersionNumber, + pr: protocol, + tcs: objects[thisId].tcs + })); + +// this is an uglly trick to sync each object with being a developer object + if (globalVariables.developer) { + objects[thisId].developer = true; + } else { + objects[thisId].developer = false; + } + //console.log(globalVariables.developer); + + client.send(message, 0, message.length, PORT, HOST, function (err) { + if (err) { + cout("error in beatSender"); + throw err; + } + // client is not being closed, as the beat is send ongoing + }); + } + }, beatInterval + _.random(-250, 250)); + } + else { + // Single-shot, one-time heartbeat + // delay the signal with timeout so that not all objects send the beat in the same time. + setTimeout(function () { + // send the beat + if (thisId in objects && !objects[thisId].deactivated) { + + var message = new Buffer(JSON.stringify({ + id: thisId, + ip: thisIp, + vn: thisVersionNumber, + pr: protocol, + tcs: objects[thisId].tcs + })); + + client.send(message, 0, message.length, PORT, HOST, function (err) { + if (err) throw err; + // close the socket as the function is only called once. + client.close(); + }); + } + }, _.random(1, 250)); + } +} + +/** + * @desc sends out an action json object via udp. Actions are used to cause actions in all objects and devices within the network. + * @param {Object} action string of the action to be send to the system. this can be a jason object + **/ + +function actionSender(action) { + console.log(action); + + var HOST = '255.255.255.255'; + var message; + + message = new Buffer(JSON.stringify({action: action})); + + // creating the datagram + var client = dgram.createSocket('udp4'); + client.bind(function () { + client.setBroadcast(true); + client.setTTL(timeToLive); + client.setMulticastTTL(timeToLive); + }); + // send the datagram + client.send(message, 0, message.length, beatPort, HOST, function (err) { + if (err) { + throw err; + } + client.close(); + }); +} + +/********************************************************************************************************************** + ******************************************** Server Objects ********************************************************** + **********************************************************************************************************************/ + +/** + * @desc Receives a Heartbeat broadcast via UDP in the local network and updates the knownObjects Array in case of a + * new object + * @note if action "ping" is received, the object calls a heartbeat that is send one time. + **/ + +var thisIP = ip.address(); +function objectBeatServer() { + + // creating the udp server + var udpServer = dgram.createSocket("udp4"); + udpServer.on("error", function (err) { + cout("server error:\n" + err); + udpServer.close(); + }); + + udpServer.on("message", function (msg) { + + var msgContent; + // check if object ping + msgContent = JSON.parse(msg); + + if (msgContent.id && msgContent.ip && !checkObjectActivation(msgContent.id) && !(msgContent.id in knownObjects)) { + + if(!knownObjects[msgContent.id]){ + knownObjects[msgContent.id] = {}; + } + + if(msgContent.vn) + knownObjects[msgContent.id].version = msgContent.vn; + + if(msgContent.pr) + knownObjects[msgContent.id].protocol = msgContent.pr; + else + { + knownObjects[msgContent.id].protocol = "R0"; + } + + if(msgContent.ip) + knownObjects[msgContent.id].ip = msgContent.ip; + + cout("I found new Objects: " + JSON.stringify(knownObjects[msgContent.id])); + } + // check if action 'ping' + if (msgContent.action === "ping") { + cout(msgContent.action); + for (var key in objects) { + objectBeatSender(beatPort, key, objects[key].ip, true); + } + } + }); + + udpServer.on("listening", function () { + var address = udpServer.address(); + cout("UDP listening on port: " + address.port); + }); + + // bind the udp server to the udp beatPort + + udpServer.bind(beatPort); +} + +/** + * @desc A static Server that serves the user, handles the links and + * additional provides active modification for objectDefinition. + **/ + +function existsSync(filename) { + try { + fs.accessSync(filename); + return true; + } catch (ex) { + return false; + } +} + +// REGEX to break an ip address into parts +var ip_regex = /(\d+)\.(\d+)\.(\d+)\.(\d+)(?:\.(\d+))?(?::(\d+))?/ig; +var ip_regex2 = /(\d+)\.(\d+)\.(\d+)\.(\d+)/; + +// Parse the ip string into an object containing it's parts +var parseIpSpace = function(ip_string){ + + // Use Regex to get the parts of the ip address + var ip_parts = ip_regex.exec(ip_string); + var ip_parts2 = ip_regex2.exec(ip_string); + // Set ip address if the regex executed successfully + var thisresult = ""; + + if( ip_parts && ip_parts.length > 6 ){ + thisresult = [parseInt(ip_parts[1]),parseInt(ip_parts[2]),parseInt(ip_parts[3]),parseInt(ip_parts[4])]; + } else if( ip_parts2 && ip_parts2.length > 3){ + thisresult = [parseInt(ip_parts2[1]),parseInt(ip_parts2[2]),parseInt(ip_parts2[3]),parseInt(ip_parts2[4])]; + } + else if(ip_string === "::1"){ + thisresult = [127,0,0,1]; + } + // Return object + return thisresult; +}; + +function objectWebServer() { + thisIP = ip.address(); + // security implemented + + // check all sever requests for being inside the netmask parameters. + // the netmask is set to local networks only. + + webServer.use("*", function (req, res, next) { + + + + var remoteIP = parseIpSpace(req.ip); + var localIP = parseIpSpace(thisIP); + var thisNetmask = parseIpSpace(netmask); + + var checkThisNetwork = true; + + if (!(remoteIP[0] === localIP[0] || remoteIP[0] <= (255- thisNetmask[0]))){ + checkThisNetwork = false; + } + + if (!(remoteIP[1] === localIP[1] || remoteIP[1] <= (255- thisNetmask[1]))){ + checkThisNetwork = false; + } + + if (!(remoteIP[2] === localIP[2] || remoteIP[2] <= (255- thisNetmask[2]))){ + checkThisNetwork = false; + } + + if (!(remoteIP[3] === localIP[3] || remoteIP[3] <= (255- thisNetmask[3]))){ + checkThisNetwork = false; + } + + if(!checkThisNetwork) + if (remoteIP[0] === 127 && remoteIP[1] === 0 && remoteIP[2] === 0 && remoteIP[3] === 1){ + checkThisNetwork = true; + } + + if(checkThisNetwork) + { + next(); + } else { + res.status(403).send('Error 400: Forbidden. The requested page may be only available in a local network.'); + } + }); + // define the body parser + webServer.use(bodyParser.urlencoded({ + extended: true + })); + webServer.use(bodyParser.json()); + // define a couple of static directory routs + + webServer.use('/objectDefaultFiles', express.static(__dirname + '/libraries/objectDefaultFiles/')); + + webServer.use("/obj", function (req, res, next) { + + var urlArray = req.originalUrl.split("/"); + + // console.log(urlArray); + if ((req.method === "GET" && urlArray[2] !== "nodes") && (req.url.slice(-1) === "/" || urlArray[3].match(/\.html?$/))) { + + var fileName = __dirname + "/objects" + req.url; + + if (urlArray[3] !== "index.html" && urlArray[3] !== "index.htm") { + + if (fs.existsSync(fileName + "index.html")) { + fileName = fileName + "index.html"; + } else if (fs.existsSync(fileName + "index.htm")) { + fileName = fileName + "index.htm"; + } + } + + if (!fs.existsSync(fileName)) { + next(); + return; + } + + var html = fs.readFileSync(fileName, 'utf8'); + + html = html.replace('', ''); + html = html.replace('', ''); + html = html.replace('', ''); + + var loadedHtml = cheerio.load(html); + var scriptNode = ''; + loadedHtml('head').prepend(scriptNode); + res.send(loadedHtml.html()); + } + else if ((req.method === "GET" && urlArray[2] !== "nodes") && (req.url.slice(-1) === "/" || urlArray[3].match(/\.json?$/))) { + + var fileName = __dirname + "/objects" + req.url + "object.json"; + + if (!fs.existsSync(fileName)) { + next(); + return; + } + + var json = JSON.parse(fs.readFileSync(fileName, "utf8")); + + for(var thisKey in json.logic) { + for (var thisKey2 in json.nodes[thisKey].blocks) { + delete json.nodes[thisKey].blocks[thisKey2].privateData; + } + } + res.json(json); + } + else + next(); + }, express.static(__dirname + '/objects/')); + + if (globalVariables.developer === true) { + webServer.use("/libraries", express.static(__dirname + '/libraries/webInterface/')); + webServer.use("/libraries/monaco-editor/", express.static(__dirname + '/node_modules/monaco-editor/')); + } + + // use the cors cross origin REST model + webServer.use(cors()); + // allow requests from all origins with '*'. TODO make it dependent on the local network. this is important for security + webServer.options('*', cors()); + + + /// logic node handling + + + /** + * Logic Links + **/ + + // delete a logic link. *1 is the object *2 is the logic *3 is the link id + // **************************************************************************************************************** + webServer.delete('/logic/*/*/link/*/lastEditor/*/', function (req, res) { + + var thisLinkId = req.params[2]; + var fullEntry = objects[req.params[0]].nodes[req.params[1]].links[thisLinkId]; + var destinationIp = knownObjects[fullEntry.objectB]; + + delete objects[req.params[0]].nodes[req.params[1]].links[thisLinkId]; + cout("deleted link: " + thisLinkId); + // cout(objects[req.params[0]].links); + actionSender({reloadNode: {object: req.params[0], node: req.params[1]}, lastEditor: req.params[3]}); + utilities.writeObjectToFile(objects, req.params[0], __dirname); + res.send("deleted: " + thisLinkId + " in logic "+ req.params[1] +" for object: " + req.params[0]); + + }); + + // adding a new logic link to an object. *1 is the object *2 is the logic *3 is the link id + // **************************************************************************************************************** + webServer.post('/logic/*/*/link/*/', function (req, res) { + + var updateStatus = "nothing happened"; + + if (objects.hasOwnProperty(req.params[0])) { + + objects[req.params[0]].nodes[req.params[1]].links[req.params[2]] = req.body; + + var thisObject = objects[req.params[0]].nodes[req.params[1]].links[req.params[2]]; + + thisObject.loop = false; + + // todo the first link in a chain should carry a UUID that propagates through the entire chain each time a change is done to the chain. + // todo endless loops should be checked by the time of creation of a new loop and not in the Engine + if (thisObject.nodeA === thisObject.nodeB && thisObject.logicA === thisObject.logicB) { + thisObject.loop = true; + } + + if (!thisObject.loop) { + // call an action that asks all devices to reload their links, once the links are changed. + actionSender({reloadNode: {object: req.params[0], node: req.params[1]}, lastEditor: req.body.lastEditor}); + updateStatus = "added"; + cout("added link: " + req.params[2]); + // check if there are new connections associated with the new link. + // write the object state to the permanent storage. + utilities.writeObjectToFile(objects, req.params[0], __dirname); + } else { + updateStatus = "found endless Loop"; + } + + res.send(updateStatus); + } + }); + + /** + * Logic Blocks + **/ + + // adding a new block to an object. *1 is the object *2 is the logic *3 is the link id + // **************************************************************************************************************** + webServer.post('/logic/*/*/block/*/', function (req, res) { + + console.log("where is this object"); + + var updateStatus = "nothing happened"; + + if (objects.hasOwnProperty(req.params[0])) { + + var thisBlocks = objects[req.params[0]].nodes[req.params[1]].blocks; + + thisBlocks[req.params[2]] = new Block(); + + + + // todo activate when system is working to increase security + /* var thisMessage = req.body; + + var thisModule = {}; + + var breakPoint = false; + + if (thisMessage.type in blockFolderList) { + thisModule = blockModules[thisMessage.type]; + + for (var thisKey in thisMessage.publicData) { + if (typeof thisMessage.publicData[thisKey] !== typeof thisModule.publicData[thisKey]) { + breakPoint = true; + } + } + + for (var thisKey in thisMessage.privateData) { + if (typeof thisMessage.privateData[thisKey] !== typeof thisModule.privateData[thisKey]) { + breakPoint = true; + } + } + } + else { + breakPoint = true; + } + + if (!breakPoint)*/ + + thisBlocks[req.params[2]] = req.body; + + // todo this can be removed once the system runs smoothly + if(typeof thisBlocks[req.params[2]].type === "undefined"){ + thisBlocks[req.params[2]].type = thisBlocks[req.params[2]].name; + } + + for( var k in objects[req.params[0]].nodes[req.params[1]].blocks){ + console.log(k); + } + + // call an action that asks all devices to reload their links, once the links are changed. + actionSender({reloadNode: {object: req.params[0], node: req.params[1]}, lastEditor: req.body.lastEditor}); + updateStatus = "added"; + cout("added block: " + req.params[2]); + utilities.writeObjectToFile(objects, req.params[0], __dirname); + res.send(updateStatus); + } + }); + + // delete a block from the logic. *1 is the object *2 is the logic *3 is the link id + // **************************************************************************************************************** + webServer.delete('/logic/*/*/block/*/lastEditor/*/', function (req, res) { + + var thisLinkId = req.params[2]; + var fullEntry = objects[req.params[0]].nodes[req.params[1]].blocks[thisLinkId]; + var destinationIp = knownObjects[fullEntry.objectB]; + + delete objects[req.params[0]].nodes[req.params[1]].blocks[thisLinkId]; + cout("deleted block: " + thisLinkId); + + var thisLinks = objects[req.params[0]].nodes[req.params[1]].links; + // Make sure that no links are connected to deleted objects + for (var subCheckerKey in thisLinks) { + if (thisLinks[subCheckerKey].nodeA === thisLinkId || thisLinks[subCheckerKey].nodeB === thisLinkId) { + delete objects[req.params[0]].nodes[req.params[1]].links[subCheckerKey]; + } + } + + actionSender({reloadNode: {object: req.params[0], node: req.params[1]}, lastEditor: req.params[3]}); + utilities.writeObjectToFile(objects, req.params[0], __dirname); + res.send("deleted: " + thisLinkId + " in blocks for object: " + req.params[0]); + }); + + + webServer.post('/logic/*/*/blockPosition/*/', function (req, res) { + + // cout("post 2"); + var updateStatus = "nothing happened"; + var thisObject = req.params[0]; + var thisNode = req.params[1]; + var thisBlock = req.params[2]; + + cout("changing Possition for :" + thisObject + " : " + thisNode+ " : " + thisBlock); + + var tempObject = objects[thisObject].nodes[thisNode].blocks[thisBlock]; + + + // check that the numbers are valid numbers.. + if (typeof req.body.x === "number" && typeof req.body.y === "number") { + + tempObject.x = req.body.x; + tempObject.y = req.body.y; + + utilities.writeObjectToFile(objects, req.params[0], __dirname); + actionSender({reloadNode: {object: req.params[0], node: req.params[1]}, lastEditor: req.body.lastEditor}); + updateStatus = "ok"; + res.send(updateStatus); + } else + res.send(updateStatus); + }); + + + /** + * Logic Nodes + **/ + + // adding a new logic node block to an object. *1 is the object *2 is the logic *3 is the link id + // **************************************************************************************************************** + webServer.post('/logic/*/*/node/', function (req, res) { + + var updateStatus = "nothing happened"; + + if (objects.hasOwnProperty(req.params[0])) { + + objects[req.params[0]].nodes[req.params[1]] = req.body; + + objects[req.params[0]].nodes[req.params[1]].blocks["in0"] = new EdgeBlock(); + objects[req.params[0]].nodes[req.params[1]].blocks["in1"] = new EdgeBlock(); + objects[req.params[0]].nodes[req.params[1]].blocks["in2"] = new EdgeBlock(); + objects[req.params[0]].nodes[req.params[1]].blocks["in3"] = new EdgeBlock(); + + objects[req.params[0]].nodes[req.params[1]].blocks["out0"] = new EdgeBlock(); + objects[req.params[0]].nodes[req.params[1]].blocks["out1"] = new EdgeBlock(); + objects[req.params[0]].nodes[req.params[1]].blocks["out2"] = new EdgeBlock(); + objects[req.params[0]].nodes[req.params[1]].blocks["out3"] = new EdgeBlock(); + console.log("added tons of nodes ----------"); + + objects[req.params[0]].nodes[req.params[1]].type = "logic"; + + // call an action that asks all devices to reload their links, once the links are changed. + updateStatus = "added"; + cout("added logic node: " + req.params[1]); + utilities.writeObjectToFile(objects, req.params[0], __dirname); + + // console.log(objects[req.params[0]].nodes[req.params[1]]); + actionSender({reloadNode: {object: req.params[0], node: req.params[1]}, lastEditor: req.body.lastEditor}); + + res.send(updateStatus); + } + }); + + // delete a logic node from the logic. *1 is the object *2 is the logic *3 is the link id + // **************************************************************************************************************** + webServer.delete('/logic/*/*/node/lastEditor/*/', function (req, res) { + + var fullEntry = objects[req.params[0]].nodes[req.params[1]]; + + delete objects[req.params[0]].nodes[req.params[1]]; + cout("deleted node: " + req.params[1]); + + + //todo check all links as well in object + + // Make sure that no links are connected to deleted objects + /* for (var subCheckerKey in objects[req.params[0]].links) { + + if (objects[req.params[0]].links[subCheckerKey].nodeA === req.params[1] && objects[req.params[0]].links[subCheckerKey].objectA === req.params[0]) { + delete objects[req.params[0]].links[subCheckerKey]; + } + if (objects[req.params[0]].links[subCheckerKey].nodeB === req.params[1] && objects[req.params[0]].links[subCheckerKey].objectB === req.params[0]) { + delete objects[req.params[0]].links[subCheckerKey]; + } + }*/ + + console.log("deleted Object"); + utilities.writeObjectToFile(objects, req.params[0], __dirname); + actionSender({reloadNode: {object: req.params[0], node: req.params[1]}, lastEditor: req.params[2]}); + res.send("deleted: " + req.params[1] + " in object: " + req.params[0]); + + }); + + + webServer.post('/logic/*/*/nodeSize/', function (req, res) { + + // cout("post 2"); + var updateStatus = "nothing happened"; + var thisObject = req.params[0]; + var thisValue = req.params[1]; + + cout("changing Size for :" + thisObject + " : " + thisValue); + + var tempObject = objects[thisObject].nodes[thisValue]; + + + // check that the numbers are valid numbers.. + if (typeof req.body.x === "number" && typeof req.body.y === "number" && typeof req.body.scale === "number") { + + // if the object is equal the datapoint id, the item is actually the object it self. + + tempObject.x = req.body.x; + tempObject.y = req.body.y; + tempObject.scale = req.body.scale; + // console.log(req.body); + // ask the devices to reload the objects + } + + if (typeof req.body.matrix === "object") { + + tempObject.matrix = req.body.matrix; + } + + if ((typeof req.body.x === "number" && typeof req.body.y === "number" && typeof req.body.scale === "number") || (typeof req.body.matrix === "object" )) { + utilities.writeObjectToFile(objects, req.params[0], __dirname); + + // actionSender({reloadObject: {object: thisObject}}); + actionSender({reloadObject: {object: req.params[0], node: req.params[1]}, lastEditor: req.body.lastEditor}); + updateStatus = "ok"; + } + + res.send(updateStatus); + }); + + + + // sends json object for a specific hybrid object. * is the object name + // ths is the most relevant for + // **************************************************************************************************************** + webServer.get('/availableLogicBlocks/', function (req, res) { + // cout("get 7"); + var blockList = {} + // Create a objects list with all IO-Points code. + for (var i = 0; i < blockFolderList.length; i++) { + + // make sure that each block contains always all keys. + blockList[blockFolderList[i]] = new Block(); + + var thisBlock = blockModules[blockFolderList[i]].properties; + + for (var key in thisBlock) { + blockList[blockFolderList[i]][key] = thisBlock[key]; + } + // this makes sure that the type of the block is set. + blockList[blockFolderList[i]].type = blockFolderList[i]; + + } + res.json(blockList); + }); + + webServer.get('/api/items/objects', function (req, res) { + var ret = []; + for (var v in objects) { + if (!objects[v].deactivated) + ret.push({id: objects[v].objectId, ip: objects[v].ip, vn: objects[v].version, pr: objects[v].protocol, tcs: objects[v].tcs}) + } + res.json(ret); + + }); + + /** + * Normal Links + **/ + + // delete a link. *1 is the object *2 is the link id + // **************************************************************************************************************** + webServer.delete('/object/*/link/*/lastEditor/*/', function (req, res) { + + var thisLinkId = req.params[1]; + var fullEntry = objects[req.params[0]].links[thisLinkId]; + var destinationIp = knownObjects[fullEntry.objectB]; + + delete objects[req.params[0]].links[thisLinkId]; + cout("deleted link: " + thisLinkId); + // cout(objects[req.params[0]].links); + utilities.writeObjectToFile(objects, req.params[0], __dirname); + actionSender({reloadLink: {object: req.params[0]}, lastEditor: req.params[2]}); + res.send("deleted: " + thisLinkId + " in object: " + req.params[0]); + + var checkIfIpIsUsed = false; + var checkerKey, subCheckerKey; + for (checkerKey in objects) { + for (subCheckerKey in objects[checkerKey].links) { + if (objects[checkerKey].links[subCheckerKey].objectB === fullEntry.objectB) { + checkIfIpIsUsed = true; + } + } + } + + if (fullEntry.objectB !== fullEntry.objectA && !checkIfIpIsUsed) { + // socketArray.splice(destinationIp, 1); + delete socketArray[destinationIp]; + } + }); + + // todo links for programms as well + // adding a new link to an object. *1 is the object *2 is the link id + // **************************************************************************************************************** + webServer.post('/object/*/link/*/', function (req, res) { + + console.log("new link"); + var updateStatus = "nothing happened"; + + if (objects.hasOwnProperty(req.params[0])) { + + objects[req.params[0]].links[req.params[1]] = req.body; + + var thisObject = objects[req.params[0]].links[req.params[1]]; + + thisObject.loop = false; + + // todo the first link in a chain should carry a UUID that propagates through the entire chain each time a change is done to the chain. + // todo endless loops should be checked by the time of creation of a new loop and not in the Engine + if (thisObject.objectA === thisObject.objectB && thisObject.nodeA === thisObject.nodeB) { + thisObject.loop = true; + } + + if (!thisObject.loop) { + updateStatus = "added"; + cout("added link: " + req.params[1]); + // check if there are new connections associated with the new link. + utilities.writeObjectToFile(objects, req.params[0], __dirname); + // write the object state to the permanent storage. + socketUpdater(); + // call an action that asks all devices to reload their links, once the links are changed. + actionSender({reloadLink: {object: req.params[0]}, lastEditor: req.body.lastEditor}); + } else { + updateStatus = "found endless Loop"; + } + + res.send(updateStatus); + } + }); + + // Add a new node to an object linked to a frame + webServer.post('/object/:objectKey/node/:nodeKey/', function (req, res) { + var objectKey = req.params.objectKey; + var nodeKey = req.params.nodeKey; + var node = req.body; + + if (!objects.hasOwnProperty(objectKey)) { + res.status(404); + res.json({failure: true, error: 'Object ' + objectKey + ' not found'}).end(); + return; + } + + var obj = objects[objectKey]; + obj.nodes[nodeKey] = node; + utilities.writeObjectToFile(objects, objectKey, __dirname); + actionSender({reloadObject: {object: objectKey}, lastEditor: req.body.lastEditor}); + + res.json({success: 'true'}).end(); + }); + + // adding a new lock to an object. *1 is the object *2 is the datapoint id + // **************************************************************************************************************** + webServer.post('/object/*/nodeLock/*/', function (req, res) { + + var updateStatus = "nothing happened"; + + if (objects.hasOwnProperty(req.params[0])) { + + var previousLockPassword = objects[req.params[0]].nodes[req.params[1]].lockPassword; + var newLockPassword = req.body['lockPassword']; + var previousLockType = objects[req.params[0]].nodes[req.params[1]].lockType; + var newLockType = req.body['lockType']; + + var isLockActionAllowed = (!previousLockPassword && !!newLockPassword) || + (!!newLockPassword && previousLockPassword === newLockPassword && newLockType !== previousLockType); + + if (isLockActionAllowed) { + objects[req.params[0]].nodes[req.params[1]].lockPassword = newLockPassword; + objects[req.params[0]].nodes[req.params[1]].lockType = newLockType; + + utilities.writeObjectToFile(objects, req.params[0], __dirname); + + actionSender({reloadNode: {object: req.params[0], node: req.params[1]}}); + + updateStatus = "added"; + + } else { + if (previousLockPassword === newLockPassword) { + updateStatus = "already locked by this user"; + } else { + updateStatus = "not authorized to add"; + } + } + } + + res.send(updateStatus); + }); + + // delete a lock. *1 is the object *2 is the datapoint id *3 is the encrypted user id + // **************************************************************************************************************** + webServer.delete('/object/*/nodeLock/*/password/*/', function (req, res) { + + var updateStatus = "nothing happened"; + + if (objects.hasOwnProperty(req.params[0])) { + + var previousLockPassword = objects[req.params[0]].nodes[req.params[1]].lockPassword; + var newLockPassword = req.params[2]; + + if (newLockPassword === previousLockPassword || newLockPassword === "DEBUG") { // TODO: remove DEBUG mode + objects[req.params[0]].nodes[req.params[1]].lockPassword = null; + objects[req.params[0]].nodes[req.params[1]].lockType = null; + utilities.writeObjectToFile(objects, req.params[0], __dirname); + + actionSender({reloadNode: {object: req.params[0], node: req.params[1]}}); + + updateStatus = "deleted"; + } else { + updateStatus = "not authorized to delete" + } + } + + res.send(updateStatus); + }); + + // adding a new lock to an object link. *1 is the object *2 is the link id + // **************************************************************************************************************** + webServer.post('/object/*/linkLock/*/', function (req, res) { + + var updateStatus = "nothing happened"; + + if (objects.hasOwnProperty(req.params[0])) { + + var previousLockPassword = objects[req.params[0]].links[req.params[1]].lockPassword; + var newLockPassword = req.body['lockPassword']; + var previousLockType = objects[req.params[0]].links[req.params[1]].lockType; + var newLockType = req.body['lockType']; + + var isLockActionAllowed = (!previousLockPassword && !!newLockPassword) || + (!!newLockPassword && previousLockPassword === newLockPassword && newLockType !== previousLockType); + + if (isLockActionAllowed) { + objects[req.params[0]].links[req.params[1]].lockPassword = newLockPassword; + objects[req.params[0]].links[req.params[1]].lockType = newLockType; + utilities.writeObjectToFile(objects, req.params[0], __dirname); + + actionSender({reloadLink: {object: req.params[0]}}); + + updateStatus = "added"; + + } else { + if (previousLockPassword === newLockPassword) { + updateStatus = "already locked by this user"; + } else { + updateStatus = "not authorized to add"; + } + } + } + + res.send(updateStatus); + }); + + // delete a lock from a link. *1 is the object *2 is the link id *3 is the encrypted user id + // **************************************************************************************************************** + webServer.delete('/object/*/linkLock/*/password/*/', function (req, res) { + + var updateStatus = "nothing happened"; + + if (objects.hasOwnProperty(req.params[0])) { + + var previousLockPassword = objects[req.params[0]].links[req.params[1]].lockPassword; + var newLockPassword = req.params[2]; + + if (newLockPassword === previousLockPassword || newLockPassword === "DEBUG") { // TODO: remove DEBUG mode + objects[req.params[0]].links[req.params[1]].lockPassword = null; + objects[req.params[0]].links[req.params[1]].lockType = null; + utilities.writeObjectToFile(objects, req.params[0], __dirname); + + actionSender({reloadLink: {object: req.params[0]}}); + + updateStatus = "deleted"; + } else { + updateStatus = "not authorized to delete" + } + } + + res.send(updateStatus); + }); + + + // Handler of new memory uploads + webServer.post('/object/:id/memory', function (req, res) { + var objId = req.params.id; + if (!objects.hasOwnProperty(objId)) { + res.status(404); + res.json({failure: true, error: 'Object ' + objId + ' not found'}).end(); + return; + } + + var obj = objects[objId]; + + var memoryDir = __dirname + '/objects/' + obj.name + '/memory/'; + if (!fs.existsSync(memoryDir)) { + fs.mkdirSync(memoryDir); + } + + var form = new formidable.IncomingForm({ + uploadDir: memoryDir, + keepExtensions: true, + accept: 'image/jpeg' + }); + + form.on('error', function(err) { + res.status(500); + res.send(err); + throw err; + }); + + form.on('fileBegin', function(name, file) { + if (name === 'memoryThumbnailImage') { + file.path = form.uploadDir + '/memoryThumbnail.jpg'; + } else { + file.path = form.uploadDir + '/memory.jpg'; + } + }); + + form.parse(req, function(err, fields) { + if (obj) { + obj.memory = JSON.parse(fields.memoryInfo); + utilities.writeObjectToFile(objects, objId, __dirname); + actionSender({loadMemory:{object: objId, ip: obj.ip}}); + } + + res.status(200); + res.json({success: true}).end(); + }); + }); + + // Create a frame for an object + webServer.post('/object/*/frames/', function (req, res) { + var objectId = req.params[0]; + + if (!objects.hasOwnProperty(objectId)) { + res.status(404).json({failure: true, error: 'Object ' + objectId + ' not found'}).end(); + return; + } + + var object = objects[objectId]; + var frameId = 'frame' + utilities.uuidTime(); + var frame = req.body; + + if (!frame.src) { + res.status(500).json({failure: true, error: 'frame must have src'}).end(); + return; + } + + if (!object.frames) { + object.frames = {}; + } + + if (!object.frames[frameId]) { + object.frames[frameId] = new ObjectFrame(frame.src); + } + + // Copy over all properties of frame + Object.assign(object.frames[frameId], frame); + + utilities.writeObjectToFile(objects, objectId, __dirname); + + actionSender({reloadObject: {object: objectId}, lastEditor: req.body.lastEditor}); + + res.json({success: true, frameId: frameId}).end(); + }); + + // Update an object's frame + webServer.post('/object/*/frames/*/', function (req, res) { + var objectId = req.params[0]; + var frameId = req.params[1]; + + if (!objects.hasOwnProperty(objectId)) { + res.status(404).json({failure: true, error: 'Object ' + objectId + ' not found'}).end(); + return; + } + + var object = objects[objectId]; + var frame = req.body; + + if (!frame.src) { + res.status(500).json({failure: true, error: 'frame must have src'}).end(); + return; + } + + if (!object.frames) { + object.frames = {}; + } + + if (!object.frames[frameId]) { + object.frames[frameId] = new ObjectFrame(frame.src); + } + + frame.loaded = false; + // Copy over all properties of frame + Object.assign(object.frames[frameId], frame); + + utilities.writeObjectToFile(objects, objectId, __dirname); + + actionSender({reloadObject: {object: objectId}, lastEditor: req.body.lastEditor}); + + res.json({success: true}).end(); + }); + + webServer.delete('/object/:objectId/frames/:frameId/', function(req, res) { + var objectId = req.params.objectId; + var frameId = req.params.frameId; + // Delete frame + var object = objects[objectId]; + if (!object) { + res.status(404).json({failure: true, error: 'object ' + objectId + ' not found'}).end(); + return; + } + + var frame = object.frames[frameId]; + if (!frame) { + res.status(404).json({failure: true, error: 'frame ' + frameId + ' not found'}).end(); + return; + } + + delete object.frames[frameId]; + + // Delete frame's nodes + var deletedNodes = {}; + for (var nodeId in object.nodes) { + var node = object.nodes[nodeId]; + if (node.frame === frameId) { + deletedNodes[nodeId] = true; + delete object.nodes[nodeId]; + } + } + + // Delete links involving frame's nodes + for (var linkObjectId in objects) { + var linkObject = objects[linkObjectId]; + var linkObjectHasChanged = false; + + for (var linkId in linkObject.links) { + var link = linkObject.links[linkId]; + if (link.objectA === objectId || link.objectB === objectId) { + if (deletedNodes[link.nodeA] || deletedNodes[link.nodeB]) { + linkObjectHasChanged = true; + delete linkObject.links[linkId]; + } + } + } + + if (linkObjectHasChanged) { + utilities.writeObjectToFile(objects, linkObjectId, __dirname); + actionSender({reloadObject: {object: linkObjectId}, lastEditor: req.body.lastEditor}); + } + } + + utilities.writeObjectToFile(objects, objectId, __dirname); + actionSender({reloadObject: {object: objectId}, lastEditor: req.body.lastEditor}); + + res.json({success: true}).end(); + }); + + // changing the size and possition of an item. *1 is the object *2 is the datapoint id + + // **************************************************************************************************************** + + if (globalVariables.developer === true) { + webServer.post('/object/*/size/*/', function (req, res) { + + // cout("post 2"); + var updateStatus = "nothing happened"; + var thisObject = req.params[0]; + var thisValue = req.params[1]; + + cout("changing Size for :" + thisObject + " : " + thisValue); + + var tempObject; + if (thisObject === thisValue) { + tempObject = objects[thisObject]; + } else { + tempObject = objects[thisObject].nodes[thisValue]; + } + + // check that the numbers are valid numbers.. + if (typeof req.body.x === "number" && typeof req.body.y === "number" && typeof req.body.scale === "number") { + + // if the object is equal the datapoint id, the item is actually the object it self. + + tempObject.x = req.body.x; + tempObject.y = req.body.y; + tempObject.scale = req.body.scale; + // console.log(req.body); + // ask the devices to reload the objects + } + + if (typeof req.body.matrix === "object") { + + tempObject.matrix = req.body.matrix; + } + + if ((typeof req.body.x === "number" && typeof req.body.y === "number" && typeof req.body.scale === "number") || (typeof req.body.matrix === "object" )) { + utilities.writeObjectToFile(objects, req.params[0], __dirname); + + actionSender({reloadObject: {object: thisObject}, lastEditor: req.body.lastEditor}); + // actionSender({reloadNode: {object: req.params[0], node: req.params[1]}, lastEditor: req.body.lastEditor}); + updateStatus = "added object"; + } + + res.send(updateStatus); + }); + } + + /** + * Send the programming interface static web content [This is the older form. Consider it deprecated. + */ + + // Version 1 + webServer.get('/obj/dataPointInterfaces/*/*/', function (req, res) { // watch out that you need to make a "/" behind request. + res.sendFile(nodePath + "/" + req.params[0] + '/gui/' + req.params[1]); + }); + + // Version 2 + webServer.get('/dataPointInterfaces/*/*/', function (req, res) { // watch out that you need to make a "/" behind request. + res.sendFile(nodePath + "/" + req.params[0] + '/gui/' + req.params[1]); + }); + + // Version 3 #### Active Version + webServer.get('/nodes/*/*/', function (req, res) { // watch out that you need to make a "/" behind request. + res.sendFile(nodePath + "/" + req.params[0] + '/gui/' + req.params[1]); + }); + + // Version 3 #### Active Version *1 Block *2 file + webServer.get('/logicBlock/*/*/', function (req, res) { // watch out that you need to make a "/" behind request. + res.sendFile(blockPath + "/" + req.params[0] + '/gui/' + req.params[1]); + }); + + // **************************************************************************************************************** + // frontend interface + // **************************************************************************************************************** + + if (globalVariables.developer === true) { + + // sends the info page for the object :id + // **************************************************************************************************************** + webServer.get(objectInterfaceFolder + 'info/:id', function (req, res) { + // cout("get 12"); + res.send(webFrontend.uploadInfoText(req.params.id, objectLookup, objects, knownObjects, sockets)); + }); + + webServer.get(objectInterfaceFolder + 'infoLoadData/:id', function (req, res) { + // cout("get 12"); + res.send(webFrontend.uploadInfoContent(req.params.id, objectLookup, objects, knownObjects, sockets)); + }); + + // sends the content page for the object :id + // **************************************************************************************************************** + webServer.get(objectInterfaceFolder + 'content/:id', function (req, res) { + // cout("get 13"); + res.send(webFrontend.uploadTargetContent(req.params.id, __dirname, objectInterfaceFolder)); + }); + + webServer.get(objectInterfaceFolder + 'edit/:id/*', function (req, res) { + webFrontend.editContent(req, res); + }); + + webServer.put(objectInterfaceFolder + 'edit/:id/*', function (req, res) { + // TODO insecure, requires sanitization of path + console.log('PUT', req.path, req.body.content); + fs.writeFile(__dirname + '/' + req.path.replace('edit', 'objects'), req.body.content, function(err) { + if (err) { + throw err; + } + // Success! + res.end(''); + }); + }); + // sends the target page for the object :id + // **************************************************************************************************************** + webServer.get(objectInterfaceFolder + 'target/:id', function (req, res) { + // cout("get 14"); + res.send(webFrontend.uploadTargetText(req.params.id, objectLookup, objects, globalVariables.debug)); + // res.sendFile(__dirname + '/'+ "index2.html"); + }); + + webServer.get(objectInterfaceFolder + 'target/*/*/', function (req, res) { + res.sendFile(__dirname + '/' + req.params[0] + '/' + req.params[1]); + }); + + // Send the main starting page for the web user interface + // **************************************************************************************************************** + webServer.get(objectInterfaceFolder, function (req, res) { + // cout("get 16"); + res.send(webFrontend.printFolder(objects, __dirname, globalVariables.debug, objectInterfaceFolder, objectLookup, version)); + }); + + + + // deactivated + + webServer.get('/object/*/deactivate/', function (req, res) { + objects[req.params[0]].deactivated = true; + utilities.writeObjectToFile(objects, req.params[0], __dirname); + + res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'); + res.redirect(req.get('referer')); + }); + + webServer.get('/object/*/activate/', function (req, res) { + objects[req.params[0]].deactivated = false; + utilities.writeObjectToFile(objects, req.params[0], __dirname); + res.header('Cache-Control', 'no-cache, private, no-store, must-revalidate, max-stale=0, post-check=0, pre-check=0'); + res.redirect(req.get('referer')); + }); + + // request a zip-file with the object stored inside. *1 is the object + // **************************************************************************************************************** + webServer.get('/object/*/zipBackup/', function (req, res) { + console.log("++++++++++++++++++++++++++++++++++++++++++++++++"); + // cout("get 3"); + res.writeHead(200, { + 'Content-Type': 'application/zip', + 'Content-disposition': 'attachment; filename='+req.params[0]+'.zip' + }); + + var Archiver = require('archiver'); + + var zip = Archiver.create('zip', false); + zip.pipe(res); + zip.directory(__dirname + "/objects/" + req.params[0], req.params[0] + "/"); + zip.finalize(); + }); + + // sends json object for a specific hybrid object. * is the object name + // ths is the most relevant for + // **************************************************************************************************************** + webServer.get('/object/:object/node/:node/', function (req, res) { + // cout("get 7"); + res.json(objects[req.params.object].nodes[req.params.node] || {}); + }); + + // sends json object for a specific hybrid object. * is the object name + // ths is the most relevant for + // **************************************************************************************************************** + webServer.get('/object/*/', function (req, res) { + // cout("get 7"); + res.json(objects[req.params[0]]); + }); + + + + // **************************************************************************************************************** + // post interfaces + // **************************************************************************************************************** + + webServer.post(objectInterfaceFolder + "contentDelete/:id", function (req, res) { + if (req.body.action === "delete") { + var folderDel = __dirname + '/objects/' + req.body.name; + + if (fs.lstatSync(folderDel).isDirectory()) { + var deleteFolderRecursive = function (folderDel) { + if (fs.existsSync(folderDel)) { + fs.readdirSync(folderDel).forEach(function (file, index) { + var curPath = folderDel + "/" + file; + if (fs.lstatSync(curPath).isDirectory()) { // recurse + deleteFolderRecursive(curPath); + } else { // delete file + fs.unlinkSync(curPath); + } + }); + fs.rmdirSync(folderDel); + } + }; + + deleteFolderRecursive(folderDel); + } + else { + fs.unlinkSync(folderDel); + } + + res.send(webFrontend.uploadTargetContent(req.params.id, __dirname, objectInterfaceFolder)); + } + + }); + + //***************************************************************************************** + webServer.post(objectInterfaceFolder, function (req, res) { + // cout("post 22"); + if (req.body.action === "new") { + // cout(req.body); + if (req.body.name !== "") { + + utilities.createFolder(req.body.name, __dirname, globalVariables.debug); + + } + res.send(webFrontend.printFolder(objects, __dirname, globalVariables.debug, objectInterfaceFolder, objectLookup, version)); + } + if (req.body.action === "delete") { + var folderDel = __dirname + '/objects/' + req.body.name; + + var deleteFolderRecursive = function (folderDel) { + if (fs.existsSync(folderDel)) { + fs.readdirSync(folderDel).forEach(function (file, index) { + var curPath = folderDel + "/" + file; + if (fs.lstatSync(curPath).isDirectory()) { // recurse + deleteFolderRecursive(curPath); + } else { // delete file + fs.unlinkSync(curPath); + } + }); + fs.rmdirSync(folderDel); + } + }; + + deleteFolderRecursive(folderDel); + + var tempFolderName2 = utilities.readObject(objectLookup, req.body.name);// req.body.name + thisMacAddress; + + if (tempFolderName2 !== null) { + if (tempFolderName2 in objects) { + cout("ist noch da"); + } else { + cout("ist weg"); + } + if (tempFolderName2 in knownObjects) { + cout("ist noch da"); + } else { + cout("ist weg"); + } + + // remove object from tree + delete objects[tempFolderName2]; + delete knownObjects[tempFolderName2]; + delete objectLookup[req.body.name]; + + if (tempFolderName2 in objects) { + cout("ist noch da"); + } else { + cout("ist weg"); + } + if (tempFolderName2 in knownObjects) { + cout("ist noch da"); + } else { + cout("ist weg"); + } + } + + cout("i deleted: " + tempFolderName2); + + res.send(webFrontend.printFolder(objects, __dirname, globalVariables.debug, objectInterfaceFolder, objectLookup, version)); + } + + }); + + var tmpFolderFile = ""; + + // this is all used just for the backup folder + //************************************************************************************* + webServer.post(objectInterfaceFolder + 'backup/', + function (req, res) { + // cout("post 23"); + + cout("komm ich hier hin?"); + + var form = new formidable.IncomingForm({ + uploadDir: __dirname + '/objects', // don't forget the __dirname here + keepExtensions: true + }); + + var filename = ""; + + form.on('error', function (err) { + throw err; + }); + + form.on('fileBegin', function (name, file) { + filename = file.name; + //rename the incoming file to the file's name + file.path = form.uploadDir + "/" + file.name; + }); + + form.parse(req); + + form.on('end', function () { + var folderD = form.uploadDir; + // cout("------------" + form.uploadDir + " " + filename); + + if (getFileExtension(filename) === "zip") { + + cout("I found a zip file"); + + try { + var DecompressZip = require('decompress-zip'); + var unzipper = new DecompressZip(folderD + "/" + filename); + + unzipper.on('error', function (err) { + cout('Caught an error'); + }); + + unzipper.on('extract', function (log) { + cout('Finished extracting'); + cout("have created a new object"); + //createObjectFromTarget(filename.substr(0, filename.lastIndexOf('.'))); + createObjectFromTarget(Objects, objects, filename.substr(0, filename.lastIndexOf('.')), __dirname, objectLookup, hardwareInterfaceModules, objectBeatSender, beatPort, globalVariables.debug); + + //todo add object to the beatsender. + + cout("have created a new object"); + fs.unlinkSync(folderD + "/" + filename); + + res.status(200); + res.send("done"); + + }); + + unzipper.on('progress', function (fileIndex, fileCount) { + cout('Extracted file ' + (fileIndex + 1) + ' of ' + fileCount); + }); + + unzipper.extract({ + path: folderD + "/", + filter: function (file) { + return file.type !== "SymbolicLink"; + } + }); + + cout("extracting: " + filename + " " + folderD); + + } catch (err) { + cout("could not unzip file"); + } + } + }); + }); + + // this for all the upload to content + //*********************************************************************** + + webServer.post(objectInterfaceFolder + 'content/:id', + function (req, res) { + + cout("object is: " + req.params.id); + + tmpFolderFile = req.params.id; + + if (req.body.action === "delete") { + var folderDel = __dirname + '/objects/' + req.body.name; + + if (fs.existsSync(folderDel)) { + if (fs.lstatSync(folderDel).isDirectory()) { + var deleteFolderRecursive = function (folderDel) { + if (fs.existsSync(folderDel)) { + fs.readdirSync(folderDel).forEach(function (file, index) { + var curPath = folderDel + "/" + file; + if (fs.lstatSync(curPath).isDirectory()) { // recurse + deleteFolderRecursive(curPath); + } else { // delete file + fs.unlinkSync(curPath); + } + }); + fs.rmdirSync(folderDel); + } + }; + + deleteFolderRecursive(folderDel); + } + else { + fs.unlinkSync(folderDel); + } + } + + var tempFolderName2 = utilities.readObject(objectLookup, req.body.name);//req.body.name + thisMacAddress; + // remove object from tree + if (tempFolderName2 !== null) { + delete objects[tempFolderName2]; + delete knownObjects[tempFolderName2]; + } + + cout("i deleted: " + tempFolderName2); + + res.send(webFrontend.uploadTargetContent(req.params.id, __dirname, objectInterfaceFolder)); + } + + var form = new formidable.IncomingForm({ + uploadDir: __dirname + '/objects/' + req.params.id, // don't forget the __dirname here + keepExtensions: true + }); + + var filename = ""; + + form.on('error', function (err) { + throw err; + }); + + form.on('fileBegin', function (name, file) { + filename = file.name; + //rename the incoming file to the file's name + if (req.headers.type === "targetUpload") { + file.path = form.uploadDir + "/" + file.name; + } else { + file.path = form.uploadDir + "/" + file.name; + } + }); + + form.parse(req); + + form.on('end', function () { + var folderD = form.uploadDir; + cout("------------" + form.uploadDir + "/" + filename); + + if (req.headers.type === "targetUpload") { + var fileExtension = getFileExtension(filename); + + if (fileExtension === "jpg") { + if (!fs.existsSync(folderD + "/target/")) { + fs.mkdirSync(folderD + "/target/", "0766", function (err) { + if (err) { + cout(err); + res.send("ERROR! Can't make the directory! \n"); // echo the result back + } + }); + } + + fs.renameSync(folderD + "/" + filename, folderD + "/target/target.jpg"); + + var objectName = req.params.id + utilities.uuidTime(); + + var documentcreate = '\n' + + '\n' + + ' \n' + + ' \n' + + ' \n' + + ' '; + + var xmlOutFile = folderD + "/target/target.xml"; + if (!fs.existsSync(xmlOutFile)) { + fs.writeFile(xmlOutFile, documentcreate, function (err) { + if (err) { + cout(err); + } else { + cout("XML saved to " + xmlOutFile); + } + }); + } + + var fileList = [folderD + "/target/target.jpg", folderD + "/target/target.xml", folderD + "/target/target.dat"]; + + var thisObjectId = utilities.readObject(objectLookup, req.params.id); + + if (typeof objects[thisObjectId] !== "undefined") { + var thisObject = objects[thisObjectId]; + + thisObject.tcs = utilities.genereateChecksums(objects, fileList); + + utilities.writeObjectToFile(objects, thisObjectId, __dirname); + + objectBeatSender(beatPort, thisObjectId, objects[thisObjectId].ip, true); + + } + + res.status(200); + res.send("done"); + // fs.unlinkSync(folderD + "/" + filename); + } + + else if (fileExtension === "zip") { + + cout("I found a zip file"); + + try { + var DecompressZip = require('decompress-zip'); + var unzipper = new DecompressZip(folderD + "/" + filename); + + unzipper.on('error', function (err) { + cout('Caught an error in unzipper'); + }); + + unzipper.on('extract', function (log) { + var folderFile = fs.readdirSync(folderD + "/target"); + var folderFileType; + + for (var i = 0; i < folderFile.length; i++) { + cout(folderFile[i]); + folderFileType = folderFile[i].substr(folderFile[i].lastIndexOf('.') + 1); + if (folderFileType === "xml" || folderFileType === "dat") { + fs.renameSync(folderD + "/target/" + folderFile[i], folderD + "/target/target." + folderFileType); + } + } + fs.unlinkSync(folderD + "/" + filename); + + // evnetually create the object. + + if (fs.existsSync(folderD + "/target/target.dat") && fs.existsSync(folderD + "/target/target.xml")) { + + cout("creating object from target file " + tmpFolderFile); + // createObjectFromTarget(tmpFolderFile); + createObjectFromTarget(Objects, objects, tmpFolderFile, __dirname, objectLookup, hardwareInterfaceModules, objectBeatSender, beatPort, globalVariables.debug); + + //todo send init to internal modules + cout("have created a new object"); + + hardwareAPI.reset(); + cout("have initialized the modules"); + + var fileList = [folderD + "/target/target.jpg", folderD + "/target/target.xml", folderD + "/target/target.dat"]; + + var thisObjectId = utilities.readObject(objectLookup, req.params.id); + + if (typeof objects[thisObjectId] !== "undefined") { + var thisObject = objects[thisObjectId]; + + thisObject.tcs = utilities.genereateChecksums(objects, fileList); + + utilities.writeObjectToFile(objects, thisObjectId, __dirname); + + objectBeatSender(beatPort, thisObjectId, objects[thisObjectId].ip, true); + + } + + } + + res.status(200); + res.send("done"); + }); + + unzipper.on('progress', function (fileIndex, fileCount) { + cout('Extracted file ' + (fileIndex + 1) + ' of ' + fileCount); + }); + + unzipper.extract({ + path: folderD + "/target", + filter: function (file) { + return file.type !== "SymbolicLink"; + } + }); + } catch (err) { + cout("could not unzip file"); + } + } else { + res.status(200); + res.send("done"); + } + + } else { + res.status(200); + res.send("done"); + } + + }); + }); + } else { + webServer.get(objectInterfaceFolder, function (req, res) { + // cout("GET 21"); + res.send("Objects
Developer functions are off"); + }); + } +} + +// TODO this should move to the utilities section +//createObjectFromTarget(Objects, objects, tmpFolderFile, __dirname, objectLookup, hardwareInterfaceModules, objectBeatSender, beatPort, globalVariables.debug); + +function createObjectFromTarget(Objects, objects, folderVar, __dirname, objectLookup, hardwareInterfaceModules, objectBeatSender, beatPort, debug) { + cout("I can start"); + + var folder = __dirname + '/objects/' + folderVar + '/'; + cout(folder); + + if (fs.existsSync(folder)) { + cout("folder exists"); + var objectIDXML = utilities.getObjectIdFromTarget(folderVar, __dirname); + cout("got ID: objectIDXML"); + if (!_.isUndefined(objectIDXML) && !_.isNull(objectIDXML)) { + if (objectIDXML.length > 13) { + + objects[objectIDXML] = new Objects(); + objects[objectIDXML].name = folderVar; + objects[objectIDXML].objectId = objectIDXML; + + cout("this should be the IP" + objectIDXML); + + try { + objects[objectIDXML] = JSON.parse(fs.readFileSync(__dirname + "/objects/" + folderVar + "/object.json", "utf8")); + objects[objectIDXML].ip = ip.address(); + cout("testing: " + objects[objectIDXML].ip); + } catch (e) { + objects[objectIDXML].ip = ip.address(); + cout("testing: " + objects[objectIDXML].ip); + cout("No saved data for: " + objectIDXML); + } + + if (utilities.readObject(objectLookup, folderVar) !== objectIDXML) { + delete objects[utilities.readObject(objectLookup, folderVar)]; + } + utilities.writeObject(objectLookup, folderVar, objectIDXML); + // entering the obejct in to the lookup table + + // ask the object to reinitialize + //serialPort.write("ok\n"); + // todo send init to internal + + hardwareAPI.reset(); + + cout("weiter im text " + objectIDXML); + utilities.writeObjectToFile(objects, objectIDXML, __dirname); + + objectBeatSender(beatPort, objectIDXML, objects[objectIDXML].ip); + } + } + } +} + +/** + * @desc Check for incoming MSG from other objects or the User. Make changes to the objectValues if changes occur. + **/ + +function socketServer() { + + io.on('connection', function (socket) { + + socket.on('/subscribe/realityEditor', function (msg) { + + var msgContent = JSON.parse(msg); + var thisProtocol = "R1"; + + if (!msgContent.object) { + msgContent.object = msgContent.obj; + thisProtocol = "R0"; + } + + if (objects.hasOwnProperty(msgContent.object)) { + cout("reality editor subscription for object: " + msgContent.object); + cout("the latest socket has the ID: " + socket.id); + + realityEditorSocketArray[socket.id] = {object: msgContent.object, protocol: thisProtocol}; + cout(realityEditorSocketArray); + } + }); + + socket.on('/subscribe/realityEditorBlock', function (msg) { + var msgContent = JSON.parse(msg); + + if (objects.hasOwnProperty(msgContent.object)) { + cout("reality editor block: " + msgContent.object); + cout("the latest socket has the ID: " + socket.id); + + realityEditorBlockSocketArray[socket.id] = {object: msgContent.object}; + cout(realityEditorBlockSocketArray); + } + + io.sockets.connected[socket.id].emit('block', JSON.stringify({ + object: msgContent.object, + node: msgContent.node, + block: msgContent.block, + publicData: objects[msgContent.object].nodes[msgContent.logic].blocks[msgContent.block].publicData + }));// socket.emit('object', msgToSend); + }); + + + socket.on('object', function (msg) { + + var msgContent = protocols[protocol].receive(msg); + if (msgContent === null) { + msgContent = protocols["R0"].receive(msg); + } + + if (msgContent !== null) { + hardwareAPI.readCall(msgContent.object, msgContent.node, msgContent.data); + + sendMessagetoEditors({ + object: msgContent.object, + node: msgContent.node, + data: msgContent.data + }); + engine.trigger(msgContent.object, msgContent.node, objects[msgContent.object].nodes[msgContent.node]); + } + + }); +// todo do this stuff tomorrrow + + socket.on('block/setup', function (_msg) { + var msg = JSON.parse(_msg); + + if (typeof msg.object !== "undefined" && typeof msg.logic !== "undefined" && typeof msg.block !== "undefined") { + if (msg.object in objects) { + if (msg.logic in objects[msg.object].nodes) { + if (msg.block in objects[msg.object].nodes[msg.logic].blocks) { + if (typeof objects[msg.object].nodes[msg.logic].blocks[msg.block].publicData !== "undefined") { + + var thisPublicData = objects[msg.object].nodes[msg.logic].blocks[msg.block]; + blockModules[thisPublicData.type].setup(msg.object, msg.logic, msg.block, thisPublicData); + + } + + } + } + } + + } + }); + + + socket.on('block/publicData', function (_msg) { + var msg = JSON.parse(_msg); + // console.log(msg); + if (typeof msg.object !== "undefined" && typeof msg.logic !== "undefined" && typeof msg.block !== "undefined") { + if (msg.object in objects) { + if (msg.logic in objects[msg.object].nodes) { + if (msg.block in objects[msg.object].nodes[msg.logic].blocks) { + if(typeof objects[msg.object].nodes[msg.logic].blocks[msg.block].publicData !== "undefined"){ + + var thisPublicData = objects[msg.object].nodes[msg.logic].blocks[msg.block].publicData; + + for (var key in msg.publicData) { + thisPublicData[key] = msg.publicData[key]; + } + } + } + + } + } + } + }); + + + // this is only for down compatibility for when the UI would request a readRequest + socket.on('/object/readRequest', function (msg) { + var msgContent = JSON.parse(msg); + messagetoSend(msgContent, socket.id); + }); + + socket.on('disconnect', function () { + + + if(socket.id in realityEditorSocketArray) { + delete realityEditorSocketArray[socket.id]; + console.log("GUI for "+ socket.id + " has disconnected"); + } + + if(socket.id in realityEditorBlockSocketArray) { + utilities.writeObjectToFile(objects, realityEditorBlockSocketArray[socket.id].object, __dirname); + actionSender({reloadObject: {object: realityEditorBlockSocketArray[socket.id].object}}); + delete realityEditorBlockSocketArray[socket.id]; + console.log("Settings for "+ socket.id + " has disconnected"); + } + + //utilities.writeObjectToFile(objects, req.params[0], __dirname); + + }); + }); + this.io = io; + cout('socket.io started'); +} + +function sendMessagetoEditors(msgContent) { + + for (var thisEditor in realityEditorSocketArray) { + if (msgContent.object === realityEditorSocketArray[thisEditor].object) { + messagetoSend(msgContent, thisEditor); + } + } +} + +function messagetoSend(msgContent, socketID) { + + if (objects.hasOwnProperty(msgContent.object)) { + if (objects[msgContent.object].nodes.hasOwnProperty(msgContent.node)) { + + io.sockets.connected[socketID].emit('object', JSON.stringify({ + object: msgContent.object, + node: msgContent.node, + data: objects[msgContent.object].nodes[msgContent.node].data + }));// socket.emit('object', msgToSend); + } + } +} + +/********************************************************************************************************************** + ******************************************** Engine ****************************************************************** + **********************************************************************************************************************/ + +/** + * @desc Take the id of a value in objectValue and look through all links, if this id is used. + * All links that use the id will fire up the engine to process the link. + **/ + +var engine = { + link: undefined, + internalObjectDestination: undefined, + blockKey: undefined, + objects: objects, + router: undefined, + nodeTypeModules: nodeTypeModules, + blockModules: blockModules, + hardwareAPI: hardwareAPI, + nextLogic: undefined, + logic: undefined, + + // triggered by normal inputs from hardware or network + trigger: function (object, node, thisNode) { + if (!thisNode.processedData) + thisNode.processedData = {}; + + var _this = this; + if ((thisNode.type in this.nodeTypeModules)) { + this.nodeTypeModules[thisNode.type].render(object, node, thisNode, function (object, node, thisNode) { + _this.processLinks(object, node, thisNode); + }); + } + }, + // once data is processed it will determin where to send it. + processLinks: function (object, node, thisNode) { + + var linkKey; + + for (linkKey in this.objects[object].links) { + + this.link = this.objects[object].links[linkKey]; + + if (this.link.nodeA === node && this.link.objectA === object) { + if (!checkObjectActivation(this.link.objectB)) { + socketSender(object, linkKey, thisNode.processedData); + } + else { + + this.internalObjectDestination = this.objects[this.link.objectB].nodes[this.link.nodeB]; + + if (this.link.logicB !== 0 && this.link.logicB !== 1 && this.link.logicB !== 2 && this.link.logicB !== 3) { + this.computeProcessedData(thisNode, this.link, this.internalObjectDestination) + } + else { + this.blockKey = "in" + this.link.logicB; + + if (this.objects[this.link.objectB].nodes[this.link.nodeB] && this.blockKey) { + if (this.objects[this.link.objectB].nodes[this.link.nodeB].blocks) { + this.internalObjectDestination = this.objects[this.link.objectB].nodes[this.link.nodeB].blocks[this.blockKey]; + + for (var key in thisNode.processedData) { + this.internalObjectDestination.data[0][key] = thisNode.processedData[key]; + } + + this.nextLogic = this.objects[this.link.objectB].nodes[this.link.nodeB]; + // this needs to be at the beginning; + if (!this.nextLogic.routeBuffer) + this.nextLogic.routeBuffer = [0, 0, 0, 0]; + + this.nextLogic.routeBuffer[this.link.logicB] = thisNode.processedData.value; + this.blockTrigger(this.link.objectB, this.link.nodeB, this.blockKey, 0, this.internalObjectDestination); + } + } + } + + } + } + } + }, + // this is a helper for internal nodes. + computeProcessedData: function (thisNode, thisLink, internalObjectDestination) { + if (!internalObjectDestination) { + console.log('temporarily ignored undefined destination in computeProcessedData', thisLink); + return; + } + + // save data in local destination object; + var key; + for (key in thisNode.processedData) { + internalObjectDestination.data[key] = thisNode.processedData[key]; + } + + // trigger hardware API to push data to the objects + this.hardwareAPI.readCall(thisLink.objectB, thisLink.nodeB, internalObjectDestination.data); + + // push the data to the editor; + sendMessagetoEditors({ + object: thisLink.objectB, + node: thisLink.nodeB, + data: internalObjectDestination.data + }); + + // trigger the next round of the engine on the next object + this.trigger(thisLink.objectB, thisLink.nodeB, internalObjectDestination); + }, + // this is when a logic block is triggered. + blockTrigger: function (object, node, block, index, thisBlock) { + if (!thisBlock.processedData) + thisBlock.processedData = [{}, {}, {}, {}]; + + var _this = this; + + if ((thisBlock.type in this.blockModules)) { + this.blockModules[thisBlock.type].render(object, node, block, index, thisBlock, function (object, node, block, index, thisBlock) { + _this.processBlockLinks(object, node, block, index, thisBlock); + }); + } + }, +// this is for after a logic block is processed. + processBlockLinks: function (object, node, block, index, thisBlock) { + + for (var i = 0; i < 4; i++) { + + // check if there is data to be processed + if (typeof thisBlock.processedData[i].value === "number") { + + this.router = null; + + if (block === "out0") this.router = 0; + if (block === "out1") this.router = 1; + if (block === "out2") this.router = 2; + if (block === "out3") this.router = 3; + + var linkKey; + + if (this.router !== null) { + + for (linkKey in this.objects[object].links) { + this.link = this.objects[object].links[linkKey]; + + if (this.link.nodeA === node && + this.link.objectA === object && this.link.logicA === this.router) { + if (!(checkObjectActivation(this.link.objectB))) { + socketSender(object, linkKey, thisBlock.processedData[i]); + } + else { + this.internalObjectDestination = this.objects[this.link.objectB].nodes[this.link.nodeB]; + + if (this.link.logicB !== 0 && this.link.logicB !== 1 && this.link.logicB !== 2 && this.link.logicB !== 3) { + this.computeProcessedBlockData(thisBlock, this.link, i, this.internalObjectDestination) + } + } + } + } + } + else { + this.logic = this.objects[object].nodes[node]; + // process all links in the block + for (linkKey in this.logic.links) { + if(this.logic.links[linkKey]) + if (this.logic.links[linkKey].nodeA === block) { + if (this.logic.links[linkKey].logicA === i) { + + this.link = this.logic.links[linkKey]; + + this.internalObjectDestination = this.logic.blocks[this.link.nodeB]; + var key; + for (key in thisBlock.processedData[i]) { + this.internalObjectDestination.data[this.link.logicB][key] = thisBlock.processedData[i][key]; + } + this.blockTrigger(object, node, this.link.nodeB, this.link.logicB, this.internalObjectDestination); + } + } + } + } + } + } + }, + + computeProcessedBlockData: function (thisNode, thisLink, index, internalObjectDestination) { + // save data in local destination object; + var key1; + for (key1 in thisNode.processedData[index]) { + internalObjectDestination.data[key1] = thisNode.processedData[index][key1]; + } + + // trigger hardware API to push data to the objects + this.hardwareAPI.readCall(thisLink.objectB, thisLink.nodeB, internalObjectDestination.data); + + // push the data to the editor; + sendMessagetoEditors({ + object: thisLink.objectB, + node: thisLink.nodeB, + data: internalObjectDestination.data + }); + + // console.log( thisNode.processedData[index].value) + // trigger the next round of the engine on the next object + this.trigger(thisLink.objectB, thisLink.nodeB, internalObjectDestination); + } +}; + +/** + * @desc Sends processedValue to the responding Object using the data saved in the LinkArray located by IDinLinkArray + **/ + +function socketSender(object, link, data) { + var thisLink = objects[object].links[link]; + + var msg = ""; + + if(thisLink.objectB in knownObjects){ + if (knownObjects[thisLink.objectB].protocol){ + var thisProtocol = knownObjects[thisLink.objectB].protocol; + if(thisProtocol in protocols){ + msg = protocols[thisProtocol].send(thisLink.objectB, thisLink.nodeB, data); + } + else { + msg = protocols["R0"].send(thisLink.objectB, thisLink.nodeB, data); + } + } else { + msg = protocols["R0"].send(thisLink.objectB, thisLink.nodeB, data); + } + + try { + var thisIp = knownObjects[thisLink.objectB].ip; + var presentObjectConnection = socketArray[thisIp].io; + if (presentObjectConnection.connected) { + presentObjectConnection.emit("object", msg); + } + } + catch (e) { + cout("can not emit from link ID:" + link + "and object: " + object); + } + + } +} + +/********************************************************************************************************************** + ******************************************** Socket Utilities Section ************************************************ + **********************************************************************************************************************/ + +/** + * @desc Watches the connections to all objects that have stored links within the object. + * If an object is disconnected, the object tries to reconnect on a regular basis. + **/ + +function socketUpdater() { + // cout(knownObjects); + // delete unconnected connections + var sockKey, objectKey, nodeKey; + + for (sockKey in socketArray) { + var socketIsUsed = false; + + // check if the link is used somewhere. if it is not used delete it. + for (objectKey in objects) { + for (nodeKey in objects[objectKey].links) { + var thisSocket = knownObjects[objects[objectKey].links[nodeKey].objectB]; + + if (thisSocket === sockKey) { + socketIsUsed = true; + } + } + } + if (!socketArray[sockKey].io.connected || !socketIsUsed) { + // delete socketArray[sockKey]; + } + } + for (objectKey in objects) { + for (nodeKey in objects[objectKey].links) { + var thisLink = objects[objectKey].links[nodeKey]; + + if (!checkObjectActivation(thisLink.objectB) && (thisLink.objectB in knownObjects)) { + + var thisIp = knownObjects[thisLink.objectB].ip; + //cout("this ip: "+ip); + if (!(thisIp in socketArray)) { + // cout("shoudl not show up -----------"); + socketArray[thisIp] = new ObjectSockets(socketPort, thisIp); + } + } + } + } + + socketIndicator(); + + if (sockets.socketsOld !== sockets.sockets || sockets.notConnectedOld !== sockets.notConnected || sockets.connectedOld !== sockets.connected) { + for (var socketKey in socketArray) { + if (!socketArray[socketKey].io.connected) { + for (var objectKey in knownObjects) { + if (knownObjects[objectKey] === socketKey) { + cout("Looking for: " + objectKey + " with the ip: " + socketKey); + } + } + } + } + + cout(sockets.sockets + " connections; " + sockets.connected + " connected and " + sockets.notConnected + " not connected"); + + } + sockets.socketsOld = sockets.sockets; + sockets.connectedOld = sockets.connected; + sockets.notConnectedOld = sockets.notConnected; +} + +/** + * Updates the global saved sockets data + */ +function socketIndicator() { + sockets.sockets = 0; + sockets.connected = 0; + sockets.notConnected = 0; + + for (var sockKey2 in socketArray) { + if (socketArray[sockKey2].io.connected) { + sockets.connected++; + } else { + sockets.notConnected++; + } + sockets.sockets++; + } +} + +/** + * @desc + * @param + * @param + * @return + **/ + +function socketUpdaterInterval() { + setInterval(function () { + socketUpdater(); + }, socketUpdateInterval); +} + +function cout(msg) { + if (globalVariables.debug) console.log(msg); +} + +function checkObjectActivation(id){ + if(id in objects){ + return !objects[id].deactivated + } else return false; +} diff --git a/temp b/temp new file mode 100644 index 0000000..4e885c6 --- /dev/null +++ b/temp @@ -0,0 +1,41 @@ +function BlockLink() { + // origin block UUID + this.nodeA = null; + // item in that block + this.logicA = 0; + // destination block UUID + this.nodeB = null; + // item in that block + this.logicB = 0; + // check if the links are looped. + this.loop = false; + // Will be used to test if a link is still able to find its destination. + // It needs to be discussed what to do if a link is not able to find the destination and for what time span. + this.health = 0; // todo use this to test if link is still valid. If not able to send for some while, kill link. +} + +function Link() { + // The origin object from where the link is sending data from + this.objectA = null; + // The origin IOPoint from where the link is taking its data from + this.nodeA = null; + // if origin location is a Logic Node then set to Logic Node output location (which is a number between 0 and 3) otherwise null + this.logicA = null; + // Defines the type of the link origin. Currently this function is not in use. + this.namesA = ["",""]; + // The destination object to where the origin object is sending data to. + // At this point the destination object accepts all incoming data and routs the data according to the link data sent. + this.objectB = null; + // The destination IOPoint to where the link is sending data from the origin object. + // objectB and nodeB will be send with each data package. + this.nodeB = null; + // if destination location is a Logic Node then set to logic block input location (which is a number between 0 and 3) otherwise null + this.logicB = null; + // Defines the type of the link destination. Currently this function is not in use. + this.namesB = ["",""]; + // check that there is no endless loop in the system + this.loop = false; + // Will be used to test if a link is still able to find its destination. + // It needs to be discussed what to do if a link is not able to find the destination and for what time span. + this.health = 0; // todo use this to test if link is still valid. If not able to send for some while, kill link. +} \ No newline at end of file diff --git a/tempJson b/tempJson new file mode 100644 index 0000000..f4d5f02 --- /dev/null +++ b/tempJson @@ -0,0 +1,284 @@ +{ + "default": { + "name": "default", + "x": null, + "y": null, + "blockSize": 1, + "globalId": null, + "checksum": null, + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "privateData": {}, + "publicData": {}, + "activeInputs": [ + true, + false, + false, + false + ], + "activeOutputs": [ + true, + false, + false, + false + ], + "nameInput": [ + "in", + "", + "", + "" + ], + "nameOutput": [ + "out", + "", + "", + "" + ], + "iconImage": "icon.png", + "text": "default", + "stress": 0, + "appearance": "default" + }, + "delay": { + "name": "delay", + "x": null, + "y": null, + "blockSize": 1, + "globalId": null, + "checksum": null, + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "privateData": {}, + "publicData": { + "delayTime": 1000 + }, + "activeInputs": [ + true, + false, + false, + false + ], + "activeOutputs": [ + true, + false, + false, + false + ], + "nameInput": [ + "in", + "", + "", + "" + ], + "nameOutput": [ + "out", + "", + "", + "" + ], + "iconImage": "icon.png", + "text": "delay", + "stress": 0, + "appearance": "default" + }, + "switch": { + "name": "switch", + "x": null, + "y": null, + "blockSize": 1, + "globalId": null, + "checksum": null, + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "privateData": {}, + "publicData": { + "switchType": "toggle", + "switch": false, + "toggle": false + }, + "activeInputs": [ + true, + true, + false, + false + ], + "activeOutputs": [ + true, + true, + false, + false + ], + "nameInput": [ + "in", + "stream in", + "", + "" + ], + "nameOutput": [ + "out", + "stream out", + "", + "" + ], + "iconImage": "icon.png", + "text": "switch", + "stress": 0, + "appearance": "default" + }, + "threshold": { + "name": "threshold", + "x": null, + "y": null, + "blockSize": 1, + "globalId": null, + "checksum": null, + "data": [ + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + }, + { + "value": 0, + "mode": "f", + "unit": "", + "unitMin": 0, + "unitMax": 1 + } + ], + "privateData": {}, + "publicData": { + "threshold": 0.5, + "direction": ">", + "digital": true + }, + "activeInputs": [ + true, + false, + false, + false + ], + "activeOutputs": [ + true, + false, + false, + false + ], + "nameInput": [ + "stream in", + "", + "", + "" + ], + "nameOutput": [ + "stream out", + "", + "", + "" + ], + "iconImage": "icon.png", + "text": "threshold", + "stress": 0, + "appearance": "default" + } +} \ No newline at end of file diff --git a/test b/test new file mode 100644 index 0000000..e69de29 diff --git a/test.js b/test.js new file mode 100644 index 0000000..72c4418 --- /dev/null +++ b/test.js @@ -0,0 +1,39 @@ +var noble = require('noble'); + +noble.on('stateChange', function(state) { + if (state === 'poweredOn') { + noble.startScanning(); + } else { + noble.stopScanning(); + } +}); + +noble.on('discover', function(peripheral) { + console.log('peripheral discovered (' + peripheral.id + + ' with address <' + peripheral.address + ', ' + peripheral.addressType + '>,' + + ' connectable ' + peripheral.connectable + ',' + + ' RSSI ' + peripheral.rssi + ':'); + console.log('\thello my local name is:'); + console.log('\t\t' + peripheral.advertisement.localName); + console.log('\tcan I interest you in any of the following advertised services:'); + console.log('\t\t' + JSON.stringify(peripheral.advertisement.serviceUuids)); + + var serviceData = peripheral.advertisement.serviceData; + if (serviceData && serviceData.length) { + console.log('\there is my service data:'); + for (var i in serviceData) { + console.log('\t\t' + JSON.stringify(serviceData[i].uuid) + ': ' + JSON.stringify(serviceData[i].data.toString('hex'))); + } + } + if (peripheral.advertisement.manufacturerData) { + console.log('\there is my manufacturer data:'); + console.log('\t\t' + JSON.stringify(peripheral.advertisement.manufacturerData.toString('hex'))); + } + if (peripheral.advertisement.txPowerLevel !== undefined) { + console.log('\tmy TX power level is:'); + console.log('\t\t' + peripheral.advertisement.txPowerLevel); + } + + console.log(); +}); +